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)
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
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
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)
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()
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()))
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)))
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)
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
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)
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
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)
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
def run_output(): tf = tftest.TerraformTest('../') return tf.output()
def run_destroy(): tf = tftest.TerraformTest('../') return tf.destroy()
def plan(fixtures_dir): tf = tftest.TerraformTest('no_outputs', fixtures_dir) tf.setup(extra_files=['plan.auto.tfvars']) return tf.plan(output=True)
def output(fixtures_dir): tf = tftest.TerraformTest('apply', fixtures_dir) tf.setup() tf.apply() yield tf.output() tf.destroy()
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)
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!'
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)
def run_apply(): tf = tftest.TerraformTest('../') return tf.apply()
# # 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'
def plan(fixtures_dir): tf = tftest.TerraformTest('plan_no_variables', fixtures_dir) tf.setup() return tf.plan(output=True)
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})