Skip to content

Commit 323a4dd

Browse files
daFont-iriusriskPacoCid
authored andcommitted
Merged in feature/OPT-400 (pull request #149)
[OPT-400] to dev Approved-by: Paco Cid
2 parents 13906b7 + 63fa573 commit 323a4dd

File tree

43 files changed

+4008
-1051
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+4008
-1051
lines changed

slp_base/tests/util/otm.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
from typing import Union
2+
13
from deepdiff import DeepDiff
24

5+
from otm.otm.otm import OTM
36
from slp_base.slp_base.otm_file_loader import OtmFileLoader
47
from slp_base.slp_base.schema import Schema
58

@@ -13,15 +16,15 @@
1316
internet_name = 'Internet'
1417

1518

16-
def validate_and_diff_filename(actual_filename: str, expected_filename: str, excluded_regex):
17-
expected = OtmFileLoader().load(expected_filename)
18-
actual = OtmFileLoader().load(actual_filename)
19-
return validate_and_diff(actual, expected, excluded_regex)
19+
def __load_otm (otm: Union[dict, str, OTM]):
20+
if isinstance(otm, dict):
21+
return otm
2022

23+
if isinstance(otm, OTM):
24+
return otm.json()
2125

22-
def validate_and_diff_otm(actual: dict, expected_filename: str, excluded_regex):
23-
expected = OtmFileLoader().load(expected_filename)
24-
return validate_and_diff(actual, expected, excluded_regex)
26+
if isinstance(otm, str):
27+
return OtmFileLoader().load(otm)
2528

2629

2730
def __compare_otm_files(expected: dict,
@@ -36,15 +39,18 @@ def __validate_otm_schema(otm) -> Schema:
3639
return schema
3740

3841

39-
def validate_and_diff(actual: dict, expected: dict, excluded_regex):
42+
def validate_and_diff(actual: Union[dict, str, OTM], expected: Union[dict, str, OTM], excluded_regex):
4043
"""
4144
Utils for validating otm has a correct Schema
4245
and OTM contains expected data
4346
"""
44-
schema = __validate_otm_schema(actual)
47+
actual_otm = __load_otm(actual)
48+
expected_otm = __load_otm(expected)
49+
50+
schema = __validate_otm_schema(actual_otm)
4551
if not schema.valid:
4652
return {'schema_errors': schema.errors}
47-
diff = __compare_otm_files(expected, actual, excluded_regex)
53+
diff = __compare_otm_files(expected_otm, actual_otm, excluded_regex)
4854
if diff:
4955
return diff
5056
return {}

slp_cft/slp_cft/parse/cft_parser.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from slp_base.slp_base.errors import OtmBuildingError
66
from slp_base.slp_base.provider_parser import ProviderParser
77
from slp_base.slp_base.provider_type import IacType
8+
from slp_cft.slp_cft.parse.mapping.cft_path_ids_calculator import CloudformationPathIdsCalculator
89
from slp_cft.slp_cft.parse.mapping.cft_sourcemodel import CloudformationSourceModel
910
from slp_cft.slp_cft.parse.mapping.cft_transformer import CloudformationTransformer
1011

@@ -29,6 +30,7 @@ def __init__(self, project_id: str, project_name: str, source, mapping: [str]):
2930
def build_otm(self) -> OTM:
3031
try:
3132
self.transformer.run(self.mapping)
33+
self.__set_full_path_in_ids()
3234
except Exception as e:
3335
logger.error(f'{e}')
3436
detail = e.__class__.__name__
@@ -39,3 +41,23 @@ def build_otm(self) -> OTM:
3941

4042
def __initialize_otm(self):
4143
return OtmBuilder(self.project_id, self.project_name, IacType.CLOUDFORMATION).build()
44+
45+
def __set_full_path_in_ids(self):
46+
path_ids = CloudformationPathIdsCalculator(self.otm.components).calculate_path_ids()
47+
48+
self.__update_component_ids(path_ids)
49+
self.__update_dataflow_ids(path_ids)
50+
51+
def __update_component_ids(self, path_ids: {}):
52+
for component in self.otm.components:
53+
if component.id in path_ids:
54+
component.id = path_ids[component.id]
55+
if component.parent in path_ids:
56+
component.parent = path_ids[component.parent]
57+
58+
def __update_dataflow_ids(self, path_ids: {}):
59+
for dataflow in self.otm.dataflows:
60+
if dataflow.source_node in path_ids:
61+
dataflow.source_node = path_ids[dataflow.source_node]
62+
if dataflow.destination_node in path_ids:
63+
dataflow.destination_node = path_ids[dataflow.destination_node]
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import re
2+
3+
VALID_ID_REGEX = r"(\w+)"
4+
5+
6+
def normalize_name(name: str):
7+
return "_".join(re.findall(VALID_ID_REGEX, name.lower()))
8+
9+
10+
def is_altsource_resource(source: dict) -> bool:
11+
return 'altsource' in source and source['altsource']
12+
13+
14+
def build_path_id(id_elements: []):
15+
return ".".join(id_elements)
16+
17+
18+
class CloudformationComponentIdGenerator:
19+
20+
def __init__(self,
21+
name: str,
22+
parent_id: str,
23+
type: str = None,
24+
is_altsource: bool = False):
25+
self.name = normalize_name(name)
26+
self.parent_id = parent_id
27+
self.type = type
28+
self.is_altsource = is_altsource
29+
30+
@staticmethod
31+
def from_component(component_source: dict, parent_id: str):
32+
is_altsource = is_altsource_resource(component_source)
33+
34+
return CloudformationComponentIdGenerator(
35+
name=component_source['_key'],
36+
type=component_source['Type'],
37+
parent_id=parent_id,
38+
is_altsource=is_altsource
39+
)
40+
41+
def generate_id(self):
42+
if self.is_altsource:
43+
return self.__generate_altsource_component_id()
44+
else:
45+
return self.__generate_regular_component_id()
46+
47+
def __generate_regular_component_id(self):
48+
return build_path_id([self.parent_id, self.name])
49+
50+
def __generate_altsource_component_id(self):
51+
return self.__generate_regular_component_id() + '-altsource'
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from otm.otm.otm import Component
2+
from slp_cft.slp_cft.parse.mapping.cft_component_id_generator import CloudformationComponentIdGenerator
3+
4+
5+
class CloudformationPathIdsCalculator:
6+
7+
def __init__(self, components: [Component]):
8+
self.components = components
9+
10+
self.path_ids = {}
11+
12+
def calculate_path_ids(self) -> {}:
13+
for component in self.components:
14+
if component.id not in self.path_ids:
15+
self.__calculate_path_id(component)
16+
17+
return self.path_ids
18+
19+
def __calculate_path_id(self, component: {}) -> str:
20+
path_id = self.__build_component_id(component, self.__get_parent_path_id(component))
21+
22+
self.path_ids[component.id] = path_id
23+
24+
return path_id
25+
26+
def __get_parent_path_id(self, component: Component) -> str:
27+
if component.parent_type == 'trustZone':
28+
return component.parent
29+
30+
if component.parent in self.path_ids:
31+
return self.path_ids[component.parent]
32+
33+
return self.__calculate_path_id(self.__find_parent_component(component.parent))
34+
35+
def __find_parent_component(self, parent_id: str):
36+
return next(filter(lambda x: x.id == parent_id, self.components), None)
37+
38+
def __build_component_id(self, component: {}, parent_id: str):
39+
return CloudformationComponentIdGenerator.from_component(component.source, parent_id).generate_id()

slp_cft/slp_cft/parse/mapping/mappers/cft_component_mapper.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,19 @@ def __get_alt_source_components(self, source_model) -> []:
135135
component_tags, singleton_multiple_tags = self.__get_component_tags(source_model,
136136
alt_source_object,
137137
mapping_tags)
138-
component = {"id": str(uuid.uuid4()), "name": component_name,
139-
"type": mapping_lookup["type"], "parent": self.id_map[self.DEFAULT_TRUSTZONE]}
138+
139+
# if a new object is not created could be problems related with updating the same object with
140+
# the "altsource" property, as the jmespath search for altsource components returns the same
141+
# object as the original search of the component
142+
alt_source_object_copy = alt_source_object.copy()
143+
alt_source_object_copy["altsource"] = True
144+
145+
component = {"id": str(uuid.uuid4()),
146+
"name": component_name,
147+
"type": mapping_lookup["type"],
148+
"parent": self.id_map[self.DEFAULT_TRUSTZONE],
149+
"source": alt_source_object_copy
150+
}
140151

141152
component = self.set_optional_parameters_to_resource(component, mapping_tags,
142153
component_tags,

0 commit comments

Comments
 (0)