From 336c000846300d6e377193cbb1600ccaee865e66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kaan=20Kat=C4=B1rc=C4=B1o=C4=9Flu?= <32440802+Kudbettin@users.noreply.github.com> Date: Fri, 15 Jan 2021 13:50:11 +0300 Subject: [PATCH] Handling unresolvable references (#446) * partial fix * tests and Changelog --- CHANGELOG.md | 3 ++ terraform_compliance/extensions/terraform.py | 43 +++++++++++++++- tests/functional/test_issue-424/main.tf | 28 ++++++++++ .../test_issue-424/modules/ecr_module/main.tf | 51 +++++++++++++++++++ tests/functional/test_issue-424/plan.out.json | 1 + tests/functional/test_issue-424/test.feature | 8 +++ tests/functional/test_issue-424/variables.tf | 25 +++++++++ 7 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 tests/functional/test_issue-424/main.tf create mode 100644 tests/functional/test_issue-424/modules/ecr_module/main.tf create mode 100644 tests/functional/test_issue-424/plan.out.json create mode 100644 tests/functional/test_issue-424/test.feature create mode 100644 tests/functional/test_issue-424/variables.tf diff --git a/CHANGELOG.md b/CHANGELOG.md index 496b90a4..05328623 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # CHANGELOG +## Unreleased +* Fixed an issue where ambigious references were breaking during parsing. ([#446](https://github.com/terraform-compliance/cli/pull/446)) + ## 1.3.9 (2020-01-10) * Fixed an issue where incorrect `ref_type` format were breaking during parsing. ([#444](https://github.com/eerkunt/terraform-compliance/pull/444)) * Fixed an issue where \x08 character was breaking JUnit XML conversion during provider version_constraint checks. ([#432](https://github.com/eerkunt/terraform-compliance/pull/432)) diff --git a/terraform_compliance/extensions/terraform.py b/terraform_compliance/extensions/terraform.py index 8174cce1..c48bc147 100644 --- a/terraform_compliance/extensions/terraform.py +++ b/terraform_compliance/extensions/terraform.py @@ -2,6 +2,7 @@ from terraform_compliance.common.helper import seek_key_in_dict, flatten_list, Match, merge_dicts, remove_constant_values import sys from copy import deepcopy +from radish.utils import console_write from terraform_compliance.common.defaults import Defaults from terraform_compliance.extensions.cache import Cache from terraform_compliance.common.exceptions import TerraformComplianceInternalFailure @@ -357,7 +358,47 @@ def _mount_references(self): valid_references = [r for r in ref['references'] if not r.startswith(invalid_references)] for ref in valid_references: - if key not in ref_list: + # if ref is not in the correct format, handle it + if len(ref.split('.')) < 3 and ref.startswith('module'): + + # Using for_each and modules together may introduce an issue where the plan.out.json won't include the necessary third part of the reference + # It is partially resolved by mounting the reference to all instances belonging to the module + if 'for_each_expression' in self.configuration['resources'][resource]: + + # extract source resources + assumed_source_resources = [k for k in self.resources.keys() if k.startswith(resource)] + # extract for_each keys + assumed_for_each_keys = [k[len(resource):].split('.')[0] for k in assumed_source_resources] + # combine ref with for each keys + assumed_refs = ['{}{}'.format(ref, key) for key in assumed_for_each_keys] + # get all the resources that start with updated ref + ambigious_references = [] + for r in self.resources.keys(): + for assumed_ref in assumed_refs: + if r.startswith(assumed_ref): + if key in ref_list: + ref_list[key].append(r) + else: + ref_list[key] = [r] + + ambigious_references.append(r) + + # throw a warning + defaults = Defaults() + console_write('{} {}: {}'.format(defaults.warning_icon, + defaults.warning_colour('WARNING (Mounting)'), + defaults.info_colour('The reference "{}" in resource {} is ambigious.' + ' It will be mounted to the following resources:').format(ref, resource))) + for i, r in enumerate(ambigious_references, 1): + console_write(defaults.info_colour('{}. {}'.format(i, r))) + + # if the reference can not be resolved, warn the user and continue. + else: + console_write('{} {}: {}'.format(Defaults().warning_icon, + Defaults().warning_colour('WARNING (Mounting)'), + Defaults().info_colour('The reference "{}" in resource {} is ambigious. It will not be mounted.'.format(ref, resource)))) + continue + elif key not in ref_list: ref_list[key] = self._find_resource_from_name(ref) else: ref_list[key].extend(self._find_resource_from_name(ref)) diff --git a/tests/functional/test_issue-424/main.tf b/tests/functional/test_issue-424/main.tf new file mode 100644 index 00000000..c4b03dcd --- /dev/null +++ b/tests/functional/test_issue-424/main.tf @@ -0,0 +1,28 @@ +module "ecr_repository" { + source = "./modules/ecr_module" + for_each = var.ecr_repositories + + name = each.key + scan_on_push = each.value.scan_on_push +} + + +resource "aws_iam_role" "test_iam_role" { + for_each = var.ecr_repositories + name = module.ecr_repository[each.key].ecr_name + assume_role_policy = <