|
6 | 6 | from collections import defaultdict |
7 | 7 | from functools import partial |
8 | 8 | from pathlib import Path |
9 | | -from typing import List, Optional, Union, Any, Dict, overload, TypedDict, cast |
| 9 | +from typing import List, Optional, Union, Any, Dict, TypedDict, cast |
10 | 10 |
|
11 | 11 | import checkov.terraform.graph_builder.foreach.consts |
12 | 12 | from checkov.common.graph.graph_builder import Edge |
13 | 13 | from checkov.common.graph.graph_builder import reserved_attribute_names |
14 | 14 | from checkov.common.graph.graph_builder.graph_components.attribute_names import CustomAttributes |
15 | 15 | from checkov.common.graph.graph_builder.local_graph import LocalGraph |
16 | | -from checkov.common.graph.graph_builder.utils import calculate_hash, join_trimmed_strings, filter_sub_keys |
| 16 | +from checkov.common.graph.graph_builder.utils import calculate_hash, join_trimmed_strings, filter_sub_keys, \ |
| 17 | + update_dictionary_attribute |
17 | 18 | from checkov.common.runners.base_runner import strtobool |
18 | 19 | from checkov.common.typing import TFDefinitionKeyType |
19 | 20 | from checkov.common.util.data_structures_utils import pickle_deepcopy |
20 | | -from checkov.common.util.type_forcers import force_int |
21 | 21 | from checkov.terraform.graph_builder.foreach.builder import ForeachBuilder |
22 | 22 | from checkov.terraform.graph_builder.foreach.consts import VIRTUAL_RESOURCE |
23 | 23 | from checkov.terraform.graph_builder.variable_rendering.vertex_reference import TerraformVertexReference |
|
31 | 31 | get_attribute_is_leaf, |
32 | 32 | get_referenced_vertices_in_value, |
33 | 33 | attribute_has_nested_attributes, |
34 | | - remove_index_pattern_from_str, |
35 | | - join_double_quote_surrounded_dot_split, ) |
| 34 | + remove_index_pattern_from_str, ) |
36 | 35 | from checkov.terraform.graph_builder.foreach.utils import get_terraform_foreach_or_count_key, \ |
37 | 36 | get_sanitized_terraform_resource_id |
38 | 37 | from checkov.terraform.graph_builder.utils import is_local_path |
@@ -857,99 +856,6 @@ def _build_virtual_resources_edges(self, origin_node_index: int, vertex: Terrafo |
857 | 856 | self.create_edge(i, origin_node_index, VIRTUAL_RESOURCE) |
858 | 857 |
|
859 | 858 |
|
860 | | -def to_list(data: Any) -> list[Any] | dict[str, Any]: |
861 | | - if isinstance(data, list) and len(data) == 1 and (isinstance(data[0], str) or isinstance(data[0], int)): |
862 | | - return data |
863 | | - elif isinstance(data, list): |
864 | | - return [to_list(x) for x in data] |
865 | | - elif isinstance(data, dict): |
866 | | - return {key: to_list(val) for key, val in data.items()} |
867 | | - else: |
868 | | - return [data] |
869 | | - |
870 | | - |
871 | | -@overload |
872 | | -def update_dictionary_attribute( |
873 | | - config: dict[str, Any], key_to_update: str, new_value: Any, dynamic_blocks: bool = False |
874 | | -) -> dict[str, Any]: |
875 | | - ... |
876 | | - |
877 | | - |
878 | | -@overload |
879 | | -def update_dictionary_attribute( |
880 | | - config: list[Any], key_to_update: str, new_value: Any, dynamic_blocks: bool = False |
881 | | -) -> list[Any]: |
882 | | - ... |
883 | | - |
884 | | - |
885 | | -def update_dictionary_attribute( |
886 | | - config: Union[List[Any], Dict[str, Any]], key_to_update: str, new_value: Any, dynamic_blocks: bool = False |
887 | | -) -> Union[List[Any], Dict[str, Any]]: |
888 | | - key_parts = key_to_update.split(".") |
889 | | - if '"' in key_to_update: |
890 | | - key_parts = join_double_quote_surrounded_dot_split(str_parts=key_parts) |
891 | | - |
892 | | - if isinstance(config, dict) and isinstance(key_parts, list): |
893 | | - key = key_parts[0] |
894 | | - inner_config = config.get(key) |
895 | | - |
896 | | - if inner_config is not None: |
897 | | - if len(key_parts) == 1: |
898 | | - if isinstance(inner_config, list) and not isinstance(new_value, list): |
899 | | - new_value = [new_value] |
900 | | - config[key] = to_list(new_value) if dynamic_blocks else new_value |
901 | | - return config |
902 | | - else: |
903 | | - config[key] = update_dictionary_attribute( |
904 | | - inner_config, ".".join(key_parts[1:]), new_value, dynamic_blocks=dynamic_blocks |
905 | | - ) |
906 | | - else: |
907 | | - for key in config: |
908 | | - config[key] = update_dictionary_attribute( |
909 | | - config[key], key_to_update, new_value, dynamic_blocks=dynamic_blocks |
910 | | - ) |
911 | | - if isinstance(config, list): |
912 | | - return update_list_attribute( |
913 | | - config=config, |
914 | | - key_parts=key_parts, |
915 | | - key_to_update=key_to_update, |
916 | | - new_value=new_value, |
917 | | - dynamic_blocks=dynamic_blocks, |
918 | | - ) |
919 | | - return config |
920 | | - |
921 | | - |
922 | | -def update_list_attribute( |
923 | | - config: list[Any], key_parts: list[str], key_to_update: str, new_value: Any, dynamic_blocks: bool = False |
924 | | -) -> list[Any] | dict[str, Any]: |
925 | | - """Updates a list attribute in the given config""" |
926 | | - |
927 | | - if not config: |
928 | | - # happens when we can't correctly evaluate something, because of strange defaults or 'for_each' blocks |
929 | | - return config |
930 | | - |
931 | | - if len(key_parts) == 1 and len(config) == 1: |
932 | | - idx = force_int(key_parts[0]) |
933 | | - # Avoid changing the config and cause side effects |
934 | | - inner_config = pickle_deepcopy(config[0]) |
935 | | - |
936 | | - if idx is not None and isinstance(inner_config, list): |
937 | | - if not inner_config: |
938 | | - # happens when config = [[]] |
939 | | - return config |
940 | | - |
941 | | - inner_config[idx] = new_value |
942 | | - return [inner_config] |
943 | | - entry_to_update = int(key_parts[0]) if key_parts[0].isnumeric() else -1 |
944 | | - for i, config_value in enumerate(config): |
945 | | - if entry_to_update == -1: |
946 | | - config[i] = update_dictionary_attribute(config=config_value, key_to_update=key_to_update, new_value=new_value, dynamic_blocks=dynamic_blocks) |
947 | | - elif entry_to_update == i: |
948 | | - config[i] = update_dictionary_attribute(config=config_value, key_to_update=".".join(key_parts[1:]), new_value=new_value, dynamic_blocks=dynamic_blocks) |
949 | | - |
950 | | - return config |
951 | | - |
952 | | - |
953 | 859 | def get_vertex_as_tf_module(block: TerraformBlock) -> TFModule: |
954 | 860 | block_name = get_sanitized_terraform_resource_id(block.name) |
955 | 861 | return TFModule(path=block.path, name=block_name, nested_tf_module=block.source_module_object, foreach_idx=block.for_each_index) |
0 commit comments