Beispiel #1
0
def get_vertices_references(
        str_value: str, aliases: Dict[str, Dict[str, BlockType]],
        resources_types: List[str]) -> List[TerraformVertexReference]:
    vertices_references = []
    words_in_str_value = str_value.split()

    for word in words_in_str_value:
        if word.startswith(".") or word.startswith("/."):
            # check if word is a relative path
            continue

        interpolations = re.split(INTERPOLATION_EXPR, word)
        for interpolation_content in interpolations:
            for w in interpolation_content.split(","):
                word_sub_parts = w.split(".")
                if len(word_sub_parts) <= 1 or word_sub_parts[0].isnumeric():
                    # if the word doesn't contain a '.' char, or if the first part before the dot is a number
                    continue

                suspected_block_type = word_sub_parts[0]
                if suspected_block_type in BLOCK_TYPES_STRINGS:
                    # matching cases like 'var.x'
                    vertex_reference = TerraformVertexReference(
                        block_type=suspected_block_type,
                        sub_parts=word_sub_parts[1:],
                        origin_value=w)
                    if vertex_reference not in vertices_references:
                        vertices_references.append(vertex_reference)
                    continue

                vertex_reference_alias = get_vertex_reference_from_alias(
                    suspected_block_type, aliases, word_sub_parts)
                if vertex_reference_alias and vertex_reference_alias not in vertices_references:
                    vertex_reference_alias.origin_value = w
                    # matching cases where the word is referring an alias
                    vertices_references.append(vertex_reference_alias)
                    continue

                # matching cases like 'aws_vpc.main'
                if word_sub_parts[0] in resources_types:
                    block_name = word_sub_parts[0] + "." + word_sub_parts[1]
                    word_sub_parts = [block_name] + word_sub_parts[2:]
                    vertex_reference = TerraformVertexReference(
                        block_type=BlockType.RESOURCE,
                        sub_parts=word_sub_parts,
                        origin_value=w)
                    if vertex_reference not in vertices_references:
                        vertices_references.append(vertex_reference)

    return vertices_references
Beispiel #2
0
def get_vertex_reference_from_alias(
    block_type_str: str, aliases: Dict[str, Dict[str, BlockType]], val: List[str]
) -> Optional[TerraformVertexReference]:
    block_type = ""
    if block_type_str in aliases:
        block_type = aliases[block_type_str][CustomAttributes.BLOCK_TYPE]
    aliased_provider = ".".join(val)
    if aliased_provider in aliases:
        block_type = aliases[aliased_provider][CustomAttributes.BLOCK_TYPE]
    if block_type:
        return TerraformVertexReference(block_type=block_type, sub_parts=val, origin_value="")
    return None
Beispiel #3
0
 def test_find_var_blocks(self):
     cases: List[Tuple[str, List[TerraformVertexReference]]] = [
         ("${local.one}", [
             TerraformVertexReference(BlockType.LOCALS,
                                      sub_parts=["one"],
                                      origin_value="local.one")
         ]),
         ("${local.NAME[foo]}-${local.TAIL}${var.gratuitous_var_default}", [
             TerraformVertexReference(BlockType.LOCALS,
                                      sub_parts=["NAME"],
                                      origin_value="local.NAME"),
             TerraformVertexReference(BlockType.LOCALS,
                                      sub_parts=["TAIL"],
                                      origin_value="local.TAIL"),
             TerraformVertexReference(
                 BlockType.VARIABLE,
                 sub_parts=["gratuitous_var_default"],
                 origin_value="var.gratuitous_var_default"),
         ]),
         # Ordered returning of sub-vars and then outer var.
         (
             "${merge(local.common_tags,local.common_data_tags,{'Name': 'my-thing-${var.ENVIRONMENT}-${var.REGION}'})}",
             [
                 TerraformVertexReference(BlockType.LOCALS,
                                          sub_parts=["common_tags"],
                                          origin_value="local.common_tags"),
                 TerraformVertexReference(
                     BlockType.LOCALS,
                     sub_parts=["common_data_tags"],
                     origin_value="local.common_data_tags"),
                 TerraformVertexReference(BlockType.VARIABLE,
                                          sub_parts=["ENVIRONMENT"],
                                          origin_value="var.ENVIRONMENT"),
                 TerraformVertexReference(BlockType.VARIABLE,
                                          sub_parts=["REGION"],
                                          origin_value="var.REGION"),
             ],
         ),
         (
             "${merge(${local.common_tags},${local.common_data_tags},{'Name': 'my-thing-${var.ENVIRONMENT}-${var.REGION}'})}",
             [
                 TerraformVertexReference(BlockType.LOCALS,
                                          sub_parts=["common_tags"],
                                          origin_value="local.common_tags"),
                 TerraformVertexReference(
                     BlockType.LOCALS,
                     sub_parts=["common_data_tags"],
                     origin_value="local.common_data_tags"),
                 TerraformVertexReference(BlockType.VARIABLE,
                                          sub_parts=["ENVIRONMENT"],
                                          origin_value="var.ENVIRONMENT"),
                 TerraformVertexReference(BlockType.VARIABLE,
                                          sub_parts=["REGION"],
                                          origin_value="var.REGION"),
             ],
         ),
         ('${merge(var.tags, map("Name", "${var.name}", "data_classification", "none"))}',
          [
              TerraformVertexReference(BlockType.VARIABLE,
                                       sub_parts=["tags"],
                                       origin_value="var.tags"),
              TerraformVertexReference(BlockType.VARIABLE,
                                       sub_parts=["name"],
                                       origin_value="var.name"),
          ]),
         ('${var.metadata_http_tokens_required ? "required" : "optional"}',
          [
              TerraformVertexReference(
                  BlockType.VARIABLE,
                  sub_parts=["metadata_http_tokens_required"],
                  origin_value="var.metadata_http_tokens_required"),
          ]),
         ('${local.NAME[${module.bucket.bucket_name}]}-${local.TAIL}${var.gratuitous_var_default}',
          [
              TerraformVertexReference(BlockType.LOCALS,
                                       sub_parts=["NAME"],
                                       origin_value="local.NAME"),
              TerraformVertexReference(
                  BlockType.MODULE,
                  sub_parts=["bucket", "bucket_name"],
                  origin_value="module.bucket.bucket_name"),
              TerraformVertexReference(BlockType.LOCALS,
                                       sub_parts=["TAIL"],
                                       origin_value="local.TAIL"),
              TerraformVertexReference(
                  BlockType.VARIABLE,
                  sub_parts=["gratuitous_var_default"],
                  origin_value="var.gratuitous_var_default"),
          ]),
     ]
     for case in cases:
         actual = get_referenced_vertices_in_value(value=case[0],
                                                   aliases={},
                                                   resources_types=[])
         assert actual == case[1], \
             f"Case \"{case[0]}\" failed ❌:\n" \
             f"  Expected: \n{pprint.pformat([str(c) for c in case[1]], indent=2)}\n\n" \
             f"  Actual: \n{pprint.pformat([str(c) for c in actual], indent=2)}"
         print(f"Case \"{case[0]}: ✅")
Beispiel #4
0
    def test_find_non_literal_values(self):
        aliases = {'aws': {CustomAttributes.BLOCK_TYPE: BlockType.PROVIDER}}
        str_value = 'aws.east1'
        expected = [
            TerraformVertexReference(BlockType.PROVIDER, ['aws', 'east1'],
                                     'aws.east1')
        ]
        self.assertEqual(
            expected, get_referenced_vertices_in_value(str_value, aliases, []))

        str_values = [
            'var.x',
            'format("-%s", var.x)',
            '../child',
            'aws_instance.example.id',
            'bc_c_${var.customer_name}',
            'aws iam delete-role --role-name ${local.role_name} --profile ${var.profile} --region ${var.region}',
            'length(aws_vpc.main) > 0 ? aws_vpc.main[0].cidr_block : ${var.x}',
        ]
        expected = [
            [TerraformVertexReference(BlockType.VARIABLE, ['x'], 'var.x')],
            [TerraformVertexReference(BlockType.VARIABLE, ['x'], 'var.x')],
            [],
            [
                TerraformVertexReference(BlockType.RESOURCE,
                                         ['aws_instance.example', 'id'],
                                         'aws_instance.example.id')
            ],
            [
                TerraformVertexReference(BlockType.VARIABLE, ['customer_name'],
                                         'var.customer_name')
            ],
            [
                TerraformVertexReference(BlockType.LOCALS, ['role_name'],
                                         'local.role_name'),
                TerraformVertexReference(BlockType.VARIABLE, ['profile'],
                                         'var.profile'),
                TerraformVertexReference(BlockType.VARIABLE, ['region'],
                                         'var.region')
            ],
            [
                TerraformVertexReference(BlockType.RESOURCE, ['aws_vpc.main'],
                                         'aws_vpc.main'),
                TerraformVertexReference(BlockType.RESOURCE,
                                         ['aws_vpc.main', 'cidr_block'],
                                         'aws_vpc.main.cidr_block'),
                TerraformVertexReference(BlockType.VARIABLE, ['x'], 'var.x')
            ],
        ]

        for i in range(0, len(str_values)):
            self.assertEqual(
                expected[i],
                get_referenced_vertices_in_value(str_values[i], aliases,
                                                 ['aws_vpc', 'aws_instance']))