Example #1
0
 def evaluate_non_rendered_values(self) -> None:
     for vertex in self.local_graph.vertices:
         changed_attributes = {}
         attributes: Dict[str, Any] = {}
         vertex.get_origin_attributes(attributes)
         for attribute in filter(
             lambda attr: attr not in reserved_attribute_names
             and not attribute_has_nested_attributes(attr, vertex.attributes),
             vertex.attributes,
         ):
             curr_val = vertex.attributes.get(attribute)
             lst_curr_val = curr_val
             if not isinstance(lst_curr_val, list):
                 lst_curr_val = [lst_curr_val]
             if len(lst_curr_val) > 0 and isinstance(lst_curr_val[0], Tree):
                 lst_curr_val[0] = str(lst_curr_val[0])
             evaluated_lst = []
             for inner_val in lst_curr_val:
                 if (
                     isinstance(inner_val, str)
                     and not any(c in inner_val for c in ["{", "}", "[", "]", "="])
                     or attribute in ATTRIBUTES_NO_EVAL
                 ):
                     evaluated_lst.append(inner_val)
                     continue
                 evaluated = self.evaluate_value(inner_val)
                 evaluated_lst.append(evaluated)
             evaluated = evaluated_lst
             if not isinstance(curr_val, list):
                 evaluated = evaluated_lst[0]
             if evaluated != curr_val:
                 vertex.update_inner_attribute(attribute, vertex.attributes, evaluated)
                 changed_attributes[attribute] = evaluated
         self.local_graph.update_vertex_config(vertex, changed_attributes)
Example #2
0
 def test__attribute_has_nested_attributes_list(self):
     attributes = {
         'most_recent': [True],
         'filter': [{
             'name': 'name',
             'values': ['amzn-ami-hvm-*-x86_64-gp2']
         }, {
             'name': 'owner-alias',
             'values': ['amazon']
         }],
         'filter.0': {
             'name': 'name',
             'values': ['amzn-ami-hvm-*-x86_64-gp2']
         },
         'filter.0.name':
         'name',
         'filter.0.values': ['amzn-ami-hvm-*-x86_64-gp2'],
         'filter.0.values.0':
         'amzn-ami-hvm-*-x86_64-gp2',
         'filter.1': {
             'name': 'owner-alias',
             'values': ['amazon']
         },
         'filter.1.name':
         'owner-alias',
         'filter.1.values': ['amazon'],
         'filter.1.values.0':
         'amazon'
     }
     self.assertTrue(
         attribute_has_nested_attributes(attribute_key='filter',
                                         attributes=attributes))
     self.assertTrue(
         attribute_has_nested_attributes(attribute_key='filter.1.values',
                                         attributes=attributes))
     self.assertFalse(
         attribute_has_nested_attributes(attribute_key='filter.1.values.0',
                                         attributes=attributes))
Example #3
0
 def test__attribute_has_nested_attributes_dictionary(self):
     attributes = {
         'name': ['${var.lb_name}'],
         'internal': [True],
         'security_groups': ['${var.lb_security_group_ids}'],
         'subnets': ['${var.subnet_id}'],
         'enable_deletion_protection': [True],
         'tags': {
             'Terraform': True,
             'Environment': 'sophi-staging'
         },
         'resource_type': ['aws_alb'],
         'tags.Terraform': True,
         'tags.Environment': 'sophi-staging'
     }
     self.assertTrue(
         attribute_has_nested_attributes(attribute_key='tags',
                                         attributes=attributes))
     self.assertFalse(
         attribute_has_nested_attributes(attribute_key='name',
                                         attributes=attributes))
     self.assertFalse(
         attribute_has_nested_attributes(attribute_key='tags.Environment',
                                         attributes=attributes))
Example #4
0
    def _build_edges(self):
        logging.info('Creating edges')
        self.get_module_vertices_mapping()
        aliases = self._get_aliases()
        for origin_node_index, vertex in enumerate(self.vertices):
            for attribute_key in vertex.attributes:
                if attribute_key in reserved_attribute_names or attribute_has_nested_attributes(
                        attribute_key, vertex.attributes):
                    continue
                referenced_vertices = get_referenced_vertices_in_value(
                    value=vertex.attributes[attribute_key],
                    aliases=aliases,
                    resources_types=self.get_resources_types_in_graph())
                for vertex_reference in referenced_vertices:
                    # for certain blocks such as data and resource, the block name is composed from several parts.
                    # the purpose of the loop is to avoid not finding the node if the name has several parts
                    sub_values = [
                        remove_index_pattern_from_str(sub_value)
                        for sub_value in vertex_reference.sub_parts
                    ]
                    for i in range(len(sub_values)):
                        reference_name = join_trimmed_strings(
                            char_to_join=".",
                            str_lst=sub_values,
                            num_to_trim=i)
                        if vertex.module_dependency:
                            dest_node_index = self._find_vertex_index_relative_to_path(
                                vertex_reference.block_type, reference_name,
                                vertex.path, vertex.module_dependency)
                            if dest_node_index == -1:
                                dest_node_index = self._find_vertex_index_relative_to_path(
                                    vertex_reference.block_type,
                                    reference_name, vertex.path, vertex.path)
                        else:
                            dest_node_index = self._find_vertex_index_relative_to_path(
                                vertex_reference.block_type, reference_name,
                                vertex.path, vertex.module_dependency)
                        if dest_node_index > -1 and origin_node_index > -1:
                            if vertex_reference.block_type == BlockType.MODULE:
                                try:
                                    self._connect_module(
                                        sub_values, attribute_key,
                                        self.vertices[dest_node_index],
                                        origin_node_index)
                                except Exception as e:
                                    logging.warning(
                                        f'Module {self.vertices[dest_node_index]} does not have source attribute, skipping'
                                    )
                                    logging.warning(e, stack_info=True)
                            else:
                                self._create_edge(origin_node_index,
                                                  dest_node_index,
                                                  attribute_key)
                            break

            if vertex.block_type == BlockType.MODULE:
                target_path = vertex.path
                if vertex.module_dependency != '':
                    target_path = unify_dependency_path(
                        [vertex.module_dependency, vertex.path])
                target_variables = list(
                    filter(
                        lambda v: self.vertices[v].module_dependency ==
                        target_path,
                        self.vertices_by_block_type.get(
                            BlockType.VARIABLE, {})))
                for attribute, value in vertex.attributes.items():
                    if attribute in MODULE_RESERVED_ATTRIBUTES:
                        continue
                    target_variable = None
                    for v in target_variables:
                        if self.vertices[v].name == attribute:
                            target_variable = v
                            break
                    if target_variable is not None:
                        self._create_edge(target_variable, origin_node_index,
                                          'default')
            elif vertex.block_type == BlockType.TF_VARIABLE:
                if vertex.module_dependency != '':
                    target_path = unify_dependency_path(
                        [vertex.module_dependency, vertex.path])
                # Assuming the tfvars file is in the same directory as the variables file (best practice)
                target_variables = list(
                    filter(
                        lambda v: os.path.dirname(self.vertices[v].path) == os.
                        path.dirname(vertex.path),
                        self.vertices_block_name_map.get(
                            BlockType.VARIABLE, {}).get(vertex.name, [])))
                if len(target_variables) == 1:
                    self._create_edge(target_variables[0], origin_node_index,
                                      'default')