Ejemplo n.º 1
0
def tf_output(config_path):
    """Return the output after applying the Terraform configuration.

    Note:  the scope for this pytest fixture is "module", so this will only
    run once for this file.
    """
    # Terraform requires that AWS_DEFAULT_REGION be set.  If this script is
    # invoked from the command line in a properly setup environment, that
    # environment variable is set, but not if invoked from a Makefile.
    os.environ["AWS_DEFAULT_REGION"] = AWS_DEFAULT_REGION

    tf_test = tftest.TerraformTest(config_path, basedir=None, env=None)

    # Use LocalStack to simulate the AWS stack.  "localstack.tf" contains
    # the endpoints and services information needed by LocalStack.
    tf_test.setup(
        extra_files=[str(Path(Path.cwd() / "tests" / "localstack.tf"))])

    tf_vars = {
        "cc_list": "foo.com,bar.com",
        "subject": "Add a new account for Acme",
        "communication_body": "Please add this account to Enterprise support",
        "localstack_host": LOCALSTACK_HOST,
    }

    try:
        tf_test.apply(tf_vars=tf_vars)
        yield tf_test.output(json_format=True)
    except tftest.TerraformTestError as exc:
        pytest.exit(msg=f"Catastropic error running Terraform 'apply':  {exc}",
                    returncode=1)
    finally:
        tf_test.destroy(tf_vars=tf_vars)
def tf_output(config_path, valid_trust_policy):
    """Return the output after applying the Terraform configuration.

    Note:  the scope for this pytest fixture is "module", so this will only
    run once for this file.
    """
    # Terraform requires that AWS_DEFAULT_REGION be set.  If this script is
    # invoked from the command line in a properly setup environment, that
    # environment variable is set, but not if invoked from a Makefile.
    os.environ["AWS_DEFAULT_REGION"] = AWS_DEFAULT_REGION

    tf_test = tftest.TerraformTest(config_path, basedir=None, env=None)

    # Use LocalStack to simulate the AWS stack.  "localstack.tf" contains
    # the endpoints and services information needed by LocalStack.
    tf_test.setup(
        extra_files=[str(Path(Path.cwd() / "tests" / "localstack.tf"))])

    tf_vars = {
        "assume_role_name": FAKE_ACCOUNT_ID,
        "role_name": NEW_ROLE_NAME,
        "role_permission_policy": MANAGED_POLICY,
        "trust_policy_json": valid_trust_policy,
        "localstack_host": LOCALSTACK_HOST,
    }

    try:
        tf_test.apply(tf_vars=tf_vars)
        yield tf_test.output(json_format=True)
    except tftest.TerraformTestError as exc:
        pytest.exit(msg=f"Catastropic error running Terraform 'apply':  {exc}",
                    returncode=1)
    finally:
        tf_test.destroy(tf_vars=tf_vars)
Ejemplo n.º 3
0
 def run_apply(fixture_path, **tf_vars):
     "Runs Terraform apply and returns parsed output"
     tf = tftest.TerraformTest(fixture_path, BASEDIR,
                               os.environ.get('TERRAFORM', 'terraform'))
     tf.setup()
     apply = tf.apply(tf_vars=tf_vars)
     output = tf.output(json_format=True)
     return apply, output
Ejemplo n.º 4
0
 def run_apply(fixture_path, tf_var_file=None, **tf_vars):
     "Runs Terraform apply and returns parsed output"
     tf = tftest.TerraformTest(fixture_path, BASEDIR,
                               os.environ.get('TERRAFORM', 'terraform'))
     tf.setup(cleanup_on_exit=False)
     apply = tf.apply(tf_vars=tf_vars, tf_var_file=tf_var_file)
     output = tf.output(json_format=True)
     return apply, output
Ejemplo n.º 5
0
 def run_plan(fixture_path, targets=None, refresh=True, **tf_vars):
     "Runs Terraform plan and returns parsed output."
     tf = tftest.TerraformTest(fixture_path, BASEDIR,
                               os.environ.get('TERRAFORM', 'terraform'))
     tf.setup()
     return tf.plan(output=True,
                    refresh=refresh,
                    tf_vars=tf_vars,
                    targets=targets)
Ejemplo n.º 6
0
def terraform_outputs(terraform_dir):
    tf = tftest.TerraformTest('alb_example', terraform_dir)
    tf.setup()
    tf.apply()
    # This is kind of hacky, but we need to give the alb targets
    # time to become healthy.
    time.sleep(30)
    yield tf.output()
    tf.destroy()
Ejemplo n.º 7
0
 def run_plan(fixture_path=None):
     "Runs Terraform plan and returns count of modules and resources."
     tf = tftest.TerraformTest(fixture_path, BASEDIR,
                               os.environ.get('TERRAFORM', 'terraform'))
     tf.setup(upgrade=True)
     plan = tf.plan(output=True, refresh=True)
     # the fixture is the example we are testing
     modules = plan.modules or {}
     return (len(modules), sum(len(m.resources) for m in modules.values()))
Ejemplo n.º 8
0
def test_setup_files():
  "Test that extra files are linked in on setup and removed on dereferencing."
  with tempfile.TemporaryDirectory() as tmpdir:
    with tempfile.NamedTemporaryFile() as tmpfile:
      tf = tftest.TerraformTest(tmpdir)
      tf.setup(extra_files=[tmpfile.name])
      assert os.path.exists(os.path.join(
          tmpdir, os.path.basename(tmpfile.name)))
      tf = None
      assert not os.path.exists(os.path.join(
          tmpdir, os.path.basename(tmpfile.name)))
Ejemplo n.º 9
0
 def run_plan(fixture_path, is_module=True, targets=None, **tf_vars):
     "Runs Terraform plan and returns parsed output"
     tf = tftest.TerraformTest(fixture_path, BASEDIR,
                               os.environ.get('TERRAFORM', 'terraform'))
     tf.setup()
     plan = tf.plan(output=True, tf_vars=tf_vars, targets=targets)
     root_module = plan.planned_values['root_module']['child_modules'][0]
     if is_module:
         return (plan, root_module['resources'])
     modules = dict((mod['address'], mod['resources'])
                    for mod in root_module['child_modules'])
     return plan, modules
def test_setup_files():
    with tempfile.TemporaryDirectory() as tmpdir:
        try:
            with tempfile.NamedTemporaryFile(delete=False) as tmpfile:
                tf = tftest.TerraformTest(tmpdir)
                tf.setup(extra_files=[tmpfile.name])
                assert os.path.exists(
                    os.path.join(tmpdir, os.path.basename(tmpfile.name)))
                tf = None
                assert not os.path.exists(
                    os.path.join(tmpdir, os.path.basename(tmpfile.name)))
        finally:
            os.unlink(tmpfile.name)
Ejemplo n.º 11
0
 def setUp(self):
     tags = "[\"test-tags\"]"
     source_ranges = "[\"0.0.0.0/0\"]"
     self.setup_variables = {
         "port_type": "tcp",
         "image_port": "80",
         "tags": tags,
         "network": "test-network",
         "project_id": "project-id",
         "source_ranges": source_ranges
     }
     tf = tftest.TerraformTest('./modules/firewall/allow')
     tf.init()
     self.plan = tf.plan(tf_vars=self.setup_variables, output=True)
     self.vars = self.plan.variables
Ejemplo n.º 12
0
def test_autorun():
  "Test that autorun executes the right commands in setup and destroy"
  with unittest.mock.patch('tftest.os.environ.copy', return_value={}):
    with unittest.mock.patch('tftest.subprocess.Popen', autospec=True) as Popen:
      Popen.return_value.communicate.return_value = (
          b'{"a":{"value":1, "sensitive": 0}}', b'error')
      Popen.return_value.returncode = 0
      with tempfile.TemporaryDirectory() as tmpdir:
        tf = tftest.TerraformTest(tmpdir)
        tf.setup(command='output', destroy=True)
        tf.teardown()
      # popen instantiations
      kwargs = {'cwd': tmpdir, 'env': {}, 'stderr': -1, 'stdout': -1}
      call_args_list = Popen.call_args_list
      for i, call in enumerate(call_args_list):
        assert call == unittest.mock.call(_AUTORUN_CALLS[i], **kwargs)
Ejemplo n.º 13
0
    def make_tf_test(tf_module):
        """Return a TerraformTest object for given module."""
        tf_test = tftest.TerraformTest(tf_module,
                                       basedir=str(tf_dir),
                                       env=None)
        extra_files = []

        # Create an override file that contain endpoints for all the services in use
        if is_mock:
            current_dir = Path(__file__).resolve().parent

            # Get the terraform objects from the test module
            tf_objects = parse_tf_module(tf_dir / tf_module)

            mock_provider = copy.deepcopy(aws_provider_override)
            mock_aws_provider = mock_provider["provider"]["aws"][0]

            # Get the aws providers from the terraform objects
            aws_providers = []
            for tf_object in tf_objects:
                aws_providers.extend(tf_aws_providers(tf_object))

            # For all aws provider blocks that contain an "alias" attribute,
            # add a mock aws provider config with that alias
            for provider in aws_providers:
                if "alias" in provider:
                    mock_provider["provider"]["aws"].append({
                        **mock_aws_provider,
                        **{
                            "alias": provider["alias"]
                        },
                    })

            tf_provider_path = Path(current_dir /
                                    MOCKSTACK_TF_PROVIDER_OVERRIDE)
            extra_files.append(
                write_file(tf_provider_path, json.dumps(mock_provider,
                                                        indent=4)))
        tf_test.setup(extra_files=extra_files,
                      upgrade=True,
                      cleanup_on_exit=False)
        return tf_test
Ejemplo n.º 14
0
    def run_plan(fixture_path=None, targets=None, refresh=True, **tf_vars):
        "Runs Terraform plan and returns parsed output."
        if fixture_path is None:
            # find out the fixture directory from the caller's directory
            caller = inspect.stack()[2]
            fixture_path = os.path.join(os.path.dirname(caller.filename),
                                        "fixture")

        fixture_parent = os.path.dirname(fixture_path)
        fixture_prefix = os.path.basename(fixture_path) + "_"
        with tempfile.TemporaryDirectory(prefix=fixture_prefix,
                                         dir=fixture_parent) as tmp_path:
            # copy fixture to a temporary directory so we can execute
            # multiple tests in parallel
            shutil.copytree(fixture_path, tmp_path, dirs_exist_ok=True)
            tf = tftest.TerraformTest(tmp_path, BASEDIR,
                                      os.environ.get('TERRAFORM', 'terraform'))
            tf.setup(upgrade=True)
            return tf.plan(output=True,
                           refresh=refresh,
                           tf_vars=tf_vars,
                           targets=targets)
Ejemplo n.º 15
0
    def make_tf_test(tf_module):
        """Return a TerraformTest object for given module."""
        tf_test = tftest.TerraformTest(tf_module,
                                       basedir=str(tf_dir),
                                       env=None)

        # Create a list of provider files that contain endpoints for all
        # the services in use.  The endpoints will be represented by
        # Terraform variables.
        current_dir = Path(__file__).resolve().parent
        copy_files = [str(Path(current_dir / VARIABLES_TF_FILENAME))]

        if is_mock:
            tf_provider_path = Path(current_dir / MOCKSTACK_TF_FILENAME)
        else:
            tf_provider_path = Path(current_dir / AWS_TF_FILENAME)
        copy_files.append(str(tf_provider_path))

        if provider_alias:
            copy_files.append(create_provider_alias_file(tf_provider_path))

        tf_test.setup(extra_files=copy_files)
        return tf_test
Ejemplo n.º 16
0
def run_output():
    tf = tftest.TerraformTest('../')
    return tf.output()
Ejemplo n.º 17
0
def run_destroy():
    tf = tftest.TerraformTest('../')
    return tf.destroy()
Ejemplo n.º 18
0
def plan(fixtures_dir):
    tf = tftest.TerraformTest('no_outputs', fixtures_dir)
    tf.setup(extra_files=['plan.auto.tfvars'])
    return tf.plan(output=True)
Ejemplo n.º 19
0
def output(fixtures_dir):
  tf = tftest.TerraformTest('apply', fixtures_dir)
  tf.setup()
  tf.apply()
  yield tf.output()
  tf.destroy()
Ejemplo n.º 20
0
 def run_plan(testdir):
   tfdir = testdir.replace('_', '-')
   tf = tftest.TerraformTest(tfdir, _BASEDIR,
                             os.environ.get('TERRAFORM', 'terraform'))
   tf.setup(extra_files=['tests/{}/terraform.tfvars'.format(testdir)])
   return tf.plan(output=True)
Ejemplo n.º 21
0
def test_plan_with_no_resources_succeeds(fixtures_dir):
  tf = tftest.TerraformTest('plan_no_resource_changes', fixtures_dir)
  result = tf.plan(output=True)

  assert result.outputs['just_an_output'] == 'Hello, plan!'
Ejemplo n.º 22
0
def plan(terraform_dir):
    #import pdb; pdb.set_trace()
    tf = tftest.TerraformTest('vpc', terraform_dir)
    return tf.plan(output=True)
 def init_runner(**backend_config):
     tf = tftest.TerraformTest('apply', fixtures_dir)
     tf.setup(init_vars=backend_config)
Ejemplo n.º 24
0
def run_apply():
    tf = tftest.TerraformTest('../')
    return tf.apply()
Ejemplo n.º 25
0
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Example plan test with no injected files."""

import os
import re

import tftest

TF = tftest.TerraformTest(
    os.path.join(os.path.dirname(os.path.abspath(__file__)), 'foo'))


def setup():
    TF.setup(command='plan')


def test_resources():
    """Test that plan contains all expected resources."""
    values = re.findall(r'(?m)^\s*\+\s+(null_resource\S+)\s*^',
                        TF.setup_output)
    assert values == ['null_resource.foo_resource'], values


def test_attributes():
    """Test that resources have the correct attributes."""
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Example apply test with local state."""

import os
import re

import tftest

ROOT = os.path.dirname(os.path.abspath(__file__))
TF = tftest.TerraformTest(os.path.join(ROOT, 'foo'))


def setup():
    TF.setup(command='output', destroy=True)


def teardown():
    TF.teardown()


def test_output():
    """Test that apply creates the correct resources and outputs are correct."""
    assert TF.setup_output['foos'] == [{
        'foo': 'foo',
        'index': '0'
Ejemplo n.º 27
0
def plan(fixtures_dir):
    tf = tftest.TerraformTest('plan_no_variables', fixtures_dir)
    tf.setup()
    return tf.plan(output=True)
Ejemplo n.º 28
0
    def setUpClass(self):

        self.tf = tftest.TerraformTest(self.tf_dir)
        self.tf.setup(extra_files=['./test_plan.auto.tfvars'])
        self.tf_output = self.tf.plan(output=True)
def plan(fixtures_dir):
    tf = tftest.TerraformTest(tfdir=fixtures_dir,
                              terraform='/usr/local/bin/terraform',
                              env=envs)
    tf.init()
    return tf.plan(output=True)
def output(fixtures_dir):
    tf = tftest.TerraformTest('apply', fixtures_dir)
    tf.setup()
    tf.apply()
    yield tf.output()
    tf.destroy(**{"auto_approve": True})