Esempio n. 1
0
    def extract_value_from_vertex(self, key_path: List[str],
                                  attributes: Dict[str, Any]) -> Any:
        for i, _ in enumerate(key_path):
            key = join_trimmed_strings(char_to_join=".",
                                       str_lst=key_path,
                                       num_to_trim=i)
            value = attributes.get(key, None)
            if value is not None:
                return value

        reversed_key_path = key_path[::-1]
        for i, _ in enumerate(reversed_key_path):
            key = join_trimmed_strings(char_to_join=".",
                                       str_lst=reversed_key_path,
                                       num_to_trim=i)
            value = attributes.get(key, None)
            if value is not None:
                return value

        if attributes.get(CustomAttributes.BLOCK_TYPE) in [
                BlockType.VARIABLE, BlockType.TF_VARIABLE
        ]:
            var_type = attributes.get('type')
            default_val = attributes.get("default")
            if default_val is None:
                # this allows functions like merge(var.xyz, ...) to work even with no default value
                default_val = self.get_default_placeholder_value(var_type)
            value = None
            if isinstance(default_val, dict):
                value = self.extract_value_from_vertex(key_path, default_val)
            return default_val if not value else value
        if attributes.get(CustomAttributes.BLOCK_TYPE) == BlockType.OUTPUT:
            return attributes.get("value")
        return None
Esempio n. 2
0
    def update_attribute(self, attribute_key: str, attribute_value: Any,
                         change_origin_id: Optional[int],
                         previous_breadcrumbs: List[BreadcrumbMetadata],
                         attribute_at_dest: Optional[str]) -> None:
        if self._should_add_previous_breadcrumbs(change_origin_id,
                                                 previous_breadcrumbs,
                                                 attribute_at_dest):
            previous_breadcrumbs.append(
                BreadcrumbMetadata(change_origin_id, attribute_at_dest))

        attribute_key_parts = attribute_key.split(".")
        if len(attribute_key_parts) == 1:
            self.attributes[attribute_key] = attribute_value
            if self._should_set_changed_attributes(change_origin_id,
                                                   attribute_at_dest):
                self.changed_attributes[attribute_key] = previous_breadcrumbs
            return
        for i in range(len(attribute_key_parts)):
            key = join_trimmed_strings(char_to_join=".",
                                       str_lst=attribute_key_parts,
                                       num_to_trim=i)
            if key.find(".") > -1:
                self.attributes[key] = attribute_value
                attribute_value = {
                    attribute_key_parts[len(attribute_key_parts) - 1 - i]:
                    attribute_value
                }
                if self._should_set_changed_attributes(change_origin_id,
                                                       attribute_at_dest):
                    self.changed_attributes[key] = previous_breadcrumbs
Esempio n. 3
0
    def update_attribute(
        self,
        attribute_key: str,
        attribute_value: Any,
        change_origin_id: Optional[int],
        previous_breadcrumbs: List[BreadcrumbMetadata],
        attribute_at_dest: Optional[str],
        transform_step: bool = False,
    ) -> None:
        if self._should_add_previous_breadcrumbs(change_origin_id, previous_breadcrumbs, attribute_at_dest):
            previous_breadcrumbs.append(BreadcrumbMetadata(change_origin_id, attribute_at_dest))

        # update the numbered attributes, if the new value is a list
        if isinstance(attribute_value, list):
            for idx, value in enumerate(attribute_value):
                self.attributes[f"{attribute_key}.{idx}"] = value

        attribute_key_parts = attribute_key.split(".")
        if len(attribute_key_parts) == 1:
            self.attributes[attribute_key] = attribute_value
            if self._should_set_changed_attributes(change_origin_id, attribute_at_dest):
                self.changed_attributes[attribute_key] = previous_breadcrumbs
            return
        for i in range(len(attribute_key_parts)):
            key = join_trimmed_strings(char_to_join=".", str_lst=attribute_key_parts, num_to_trim=i)
            if key.find(".") > -1:
                self.attributes[key] = attribute_value
                end_key_part = attribute_key_parts[len(attribute_key_parts) - 1 - i]
                if transform_step and end_key_part in ("1", "2"):
                    # if condition logic during the transform step breaks the values
                    return
                attribute_value = {end_key_part: attribute_value}
                if self._should_set_changed_attributes(change_origin_id, attribute_at_dest):
                    self.changed_attributes[key] = previous_breadcrumbs
Esempio n. 4
0
    def _build_edges(self) -> None:
        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 enumerate(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,
                                vertex.module_dependency_num)
                            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,
                                    vertex.module_dependency_num)
                        else:
                            dest_node_index = self._find_vertex_index_relative_to_path(
                                vertex_reference.block_type, reference_name,
                                vertex.path, vertex.module_dependency,
                                vertex.module_dependency_num)
                        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 and vertex.attributes.get(
                    'source'):
                target_path = vertex.path
                if vertex.module_dependency != "":
                    target_path = unify_dependency_path(
                        [vertex.module_dependency, vertex.path])
                dest_module_path = self._get_dest_module_path(
                    curr_module_dir=self.get_dirname(vertex.path),
                    dest_module_source=vertex.attributes["source"][0],
                    dest_module_version=vertex.attributes.get(
                        "version", ["latest"])[0])
                target_variables = [
                    index for index in self.vertices_by_module_dependency.get((
                        target_path,
                        self.module.module_address_map.get((
                            vertex.path,
                            vertex.name))), {}).get(BlockType.VARIABLE, [])
                    if self.get_dirname(self.vertices[index].path) ==
                    dest_module_path
                ]
                for attribute, value in vertex.attributes.items():
                    if attribute in MODULE_RESERVED_ATTRIBUTES:
                        continue
                    target_variable = next(
                        (v for v in target_variables
                         if self.vertices[v].name == attribute), None)
                    if target_variable is not None:
                        self._create_edge(target_variable, origin_node_index,
                                          "default")
            elif vertex.block_type == BlockType.TF_VARIABLE:
                # Assuming the tfvars file is in the same directory as the variables file (best practice)
                target_variables = [
                    index for index in self.vertices_block_name_map.get(
                        BlockType.VARIABLE, {}).get(vertex.name, [])
                    if self.get_dirname(self.vertices[index].path) ==
                    self.get_dirname(vertex.path)
                ]
                if len(target_variables) == 1:
                    self._create_edge(target_variables[0], origin_node_index,
                                      "default")