localstack-core 4.4.1.dev60__py3-none-any.whl → 4.4.1.dev65__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- localstack/aws/api/ec2/__init__.py +70 -2
- localstack/aws/api/s3/__init__.py +2 -0
- localstack/services/cloudformation/engine/v2/change_set_model.py +106 -144
- localstack/services/cloudformation/engine/v2/change_set_model_describer.py +9 -7
- localstack/services/cloudformation/engine/v2/change_set_model_executor.py +7 -6
- localstack/services/cloudformation/engine/v2/change_set_model_preproc.py +223 -114
- localstack/services/cloudformation/engine/v2/change_set_model_visitor.py +10 -0
- localstack/services/s3/provider.py +3 -2
- localstack/services/sns/provider.py +27 -9
- localstack/version.py +2 -2
- {localstack_core-4.4.1.dev60.dist-info → localstack_core-4.4.1.dev65.dist-info}/METADATA +3 -3
- {localstack_core-4.4.1.dev60.dist-info → localstack_core-4.4.1.dev65.dist-info}/RECORD +20 -20
- localstack_core-4.4.1.dev65.dist-info/plux.json +1 -0
- localstack_core-4.4.1.dev60.dist-info/plux.json +0 -1
- {localstack_core-4.4.1.dev60.data → localstack_core-4.4.1.dev65.data}/scripts/localstack +0 -0
- {localstack_core-4.4.1.dev60.data → localstack_core-4.4.1.dev65.data}/scripts/localstack-supervisor +0 -0
- {localstack_core-4.4.1.dev60.data → localstack_core-4.4.1.dev65.data}/scripts/localstack.bat +0 -0
- {localstack_core-4.4.1.dev60.dist-info → localstack_core-4.4.1.dev65.dist-info}/WHEEL +0 -0
- {localstack_core-4.4.1.dev60.dist-info → localstack_core-4.4.1.dev65.dist-info}/entry_points.txt +0 -0
- {localstack_core-4.4.1.dev60.dist-info → localstack_core-4.4.1.dev65.dist-info}/licenses/LICENSE.txt +0 -0
- {localstack_core-4.4.1.dev60.dist-info → localstack_core-4.4.1.dev65.dist-info}/top_level.txt +0 -0
@@ -23,6 +23,9 @@ class NothingType:
|
|
23
23
|
cls._singleton = super().__new__(cls)
|
24
24
|
return cls._singleton
|
25
25
|
|
26
|
+
def __eq__(self, other):
|
27
|
+
return is_nothing(other)
|
28
|
+
|
26
29
|
def __str__(self):
|
27
30
|
return repr(self)
|
28
31
|
|
@@ -35,11 +38,46 @@ class NothingType:
|
|
35
38
|
def __iter__(self):
|
36
39
|
return iter(())
|
37
40
|
|
41
|
+
def __contains__(self, item):
|
42
|
+
return False
|
43
|
+
|
38
44
|
|
39
45
|
Maybe = Union[T, NothingType]
|
40
46
|
Nothing = NothingType()
|
41
47
|
|
42
48
|
|
49
|
+
def is_nothing(value: Any) -> bool:
|
50
|
+
return isinstance(value, NothingType)
|
51
|
+
|
52
|
+
|
53
|
+
def is_created(before: Maybe[Any], after: Maybe[Any]) -> bool:
|
54
|
+
return is_nothing(before) and not is_nothing(after)
|
55
|
+
|
56
|
+
|
57
|
+
def is_removed(before: Maybe[Any], after: Maybe[Any]) -> bool:
|
58
|
+
return not is_nothing(before) and is_nothing(after)
|
59
|
+
|
60
|
+
|
61
|
+
def parent_change_type_of(children: list[Maybe[ChangeSetEntity]]):
|
62
|
+
change_types = [c.change_type for c in children if not is_nothing(c)]
|
63
|
+
if not change_types:
|
64
|
+
return ChangeType.UNCHANGED
|
65
|
+
first_type = change_types[0]
|
66
|
+
if all(ct == first_type for ct in change_types):
|
67
|
+
return first_type
|
68
|
+
return ChangeType.MODIFIED
|
69
|
+
|
70
|
+
|
71
|
+
def change_type_of(before: Maybe[Any], after: Maybe[Any], children: list[Maybe[ChangeSetEntity]]):
|
72
|
+
if is_created(before, after):
|
73
|
+
change_type = ChangeType.CREATED
|
74
|
+
elif is_removed(before, after):
|
75
|
+
change_type = ChangeType.REMOVED
|
76
|
+
else:
|
77
|
+
change_type = parent_change_type_of(children)
|
78
|
+
return change_type
|
79
|
+
|
80
|
+
|
43
81
|
class Scope(str):
|
44
82
|
_ROOT_SCOPE: Final[str] = str()
|
45
83
|
_SEPARATOR: Final[str] = "/"
|
@@ -66,14 +104,6 @@ class ChangeType(enum.Enum):
|
|
66
104
|
def __str__(self):
|
67
105
|
return self.value
|
68
106
|
|
69
|
-
def for_child(self, child_change_type: ChangeType) -> ChangeType:
|
70
|
-
if child_change_type == self:
|
71
|
-
return self
|
72
|
-
elif self == ChangeType.UNCHANGED:
|
73
|
-
return child_change_type
|
74
|
-
else:
|
75
|
-
return ChangeType.MODIFIED
|
76
|
-
|
77
107
|
|
78
108
|
class ChangeSetEntity(abc.ABC):
|
79
109
|
scope: Final[Scope]
|
@@ -122,13 +152,13 @@ class NodeTemplate(ChangeSetNode):
|
|
122
152
|
def __init__(
|
123
153
|
self,
|
124
154
|
scope: Scope,
|
125
|
-
change_type: ChangeType,
|
126
155
|
mappings: NodeMappings,
|
127
156
|
parameters: NodeParameters,
|
128
157
|
conditions: NodeConditions,
|
129
158
|
resources: NodeResources,
|
130
159
|
outputs: NodeOutputs,
|
131
160
|
):
|
161
|
+
change_type = parent_change_type_of([resources, outputs])
|
132
162
|
super().__init__(scope=scope, change_type=change_type)
|
133
163
|
self.mappings = mappings
|
134
164
|
self.parameters = parameters
|
@@ -151,17 +181,17 @@ class NodeParameter(ChangeSetNode):
|
|
151
181
|
name: Final[str]
|
152
182
|
type_: Final[ChangeSetEntity]
|
153
183
|
dynamic_value: Final[ChangeSetEntity]
|
154
|
-
default_value: Final[
|
184
|
+
default_value: Final[Maybe[ChangeSetEntity]]
|
155
185
|
|
156
186
|
def __init__(
|
157
187
|
self,
|
158
188
|
scope: Scope,
|
159
|
-
change_type: ChangeType,
|
160
189
|
name: str,
|
161
190
|
type_: ChangeSetEntity,
|
162
191
|
dynamic_value: ChangeSetEntity,
|
163
|
-
default_value:
|
192
|
+
default_value: Maybe[ChangeSetEntity],
|
164
193
|
):
|
194
|
+
change_type = parent_change_type_of([type_, default_value, dynamic_value])
|
165
195
|
super().__init__(scope=scope, change_type=change_type)
|
166
196
|
self.name = name
|
167
197
|
self.type_ = type_
|
@@ -172,7 +202,8 @@ class NodeParameter(ChangeSetNode):
|
|
172
202
|
class NodeParameters(ChangeSetNode):
|
173
203
|
parameters: Final[list[NodeParameter]]
|
174
204
|
|
175
|
-
def __init__(self, scope: Scope,
|
205
|
+
def __init__(self, scope: Scope, parameters: list[NodeParameter]):
|
206
|
+
change_type = parent_change_type_of(parameters)
|
176
207
|
super().__init__(scope=scope, change_type=change_type)
|
177
208
|
self.parameters = parameters
|
178
209
|
|
@@ -181,8 +212,8 @@ class NodeMapping(ChangeSetNode):
|
|
181
212
|
name: Final[str]
|
182
213
|
bindings: Final[NodeObject]
|
183
214
|
|
184
|
-
def __init__(self, scope: Scope,
|
185
|
-
super().__init__(scope=scope, change_type=change_type)
|
215
|
+
def __init__(self, scope: Scope, name: str, bindings: NodeObject):
|
216
|
+
super().__init__(scope=scope, change_type=bindings.change_type)
|
186
217
|
self.name = name
|
187
218
|
self.bindings = bindings
|
188
219
|
|
@@ -190,7 +221,8 @@ class NodeMapping(ChangeSetNode):
|
|
190
221
|
class NodeMappings(ChangeSetNode):
|
191
222
|
mappings: Final[list[NodeMapping]]
|
192
223
|
|
193
|
-
def __init__(self, scope: Scope,
|
224
|
+
def __init__(self, scope: Scope, mappings: list[NodeMapping]):
|
225
|
+
change_type = parent_change_type_of(mappings)
|
194
226
|
super().__init__(scope=scope, change_type=change_type)
|
195
227
|
self.mappings = mappings
|
196
228
|
|
@@ -198,18 +230,18 @@ class NodeMappings(ChangeSetNode):
|
|
198
230
|
class NodeOutput(ChangeSetNode):
|
199
231
|
name: Final[str]
|
200
232
|
value: Final[ChangeSetEntity]
|
201
|
-
export: Final[
|
202
|
-
condition_reference: Final[
|
233
|
+
export: Final[Maybe[ChangeSetEntity]]
|
234
|
+
condition_reference: Final[Maybe[TerminalValue]]
|
203
235
|
|
204
236
|
def __init__(
|
205
237
|
self,
|
206
238
|
scope: Scope,
|
207
|
-
change_type: ChangeType,
|
208
239
|
name: str,
|
209
240
|
value: ChangeSetEntity,
|
210
|
-
export:
|
211
|
-
conditional_reference:
|
241
|
+
export: Maybe[ChangeSetEntity],
|
242
|
+
conditional_reference: Maybe[TerminalValue],
|
212
243
|
):
|
244
|
+
change_type = parent_change_type_of([value, export, conditional_reference])
|
213
245
|
super().__init__(scope=scope, change_type=change_type)
|
214
246
|
self.name = name
|
215
247
|
self.value = value
|
@@ -220,7 +252,8 @@ class NodeOutput(ChangeSetNode):
|
|
220
252
|
class NodeOutputs(ChangeSetNode):
|
221
253
|
outputs: Final[list[NodeOutput]]
|
222
254
|
|
223
|
-
def __init__(self, scope: Scope,
|
255
|
+
def __init__(self, scope: Scope, outputs: list[NodeOutput]):
|
256
|
+
change_type = parent_change_type_of(outputs)
|
224
257
|
super().__init__(scope=scope, change_type=change_type)
|
225
258
|
self.outputs = outputs
|
226
259
|
|
@@ -229,8 +262,8 @@ class NodeCondition(ChangeSetNode):
|
|
229
262
|
name: Final[str]
|
230
263
|
body: Final[ChangeSetEntity]
|
231
264
|
|
232
|
-
def __init__(self, scope: Scope,
|
233
|
-
super().__init__(scope=scope, change_type=change_type)
|
265
|
+
def __init__(self, scope: Scope, name: str, body: ChangeSetEntity):
|
266
|
+
super().__init__(scope=scope, change_type=body.change_type)
|
234
267
|
self.name = name
|
235
268
|
self.body = body
|
236
269
|
|
@@ -238,7 +271,8 @@ class NodeCondition(ChangeSetNode):
|
|
238
271
|
class NodeConditions(ChangeSetNode):
|
239
272
|
conditions: Final[list[NodeCondition]]
|
240
273
|
|
241
|
-
def __init__(self, scope: Scope,
|
274
|
+
def __init__(self, scope: Scope, conditions: list[NodeCondition]):
|
275
|
+
change_type = parent_change_type_of(conditions)
|
242
276
|
super().__init__(scope=scope, change_type=change_type)
|
243
277
|
self.conditions = conditions
|
244
278
|
|
@@ -246,7 +280,8 @@ class NodeConditions(ChangeSetNode):
|
|
246
280
|
class NodeResources(ChangeSetNode):
|
247
281
|
resources: Final[list[NodeResource]]
|
248
282
|
|
249
|
-
def __init__(self, scope: Scope,
|
283
|
+
def __init__(self, scope: Scope, resources: list[NodeResource]):
|
284
|
+
change_type = parent_change_type_of(resources)
|
250
285
|
super().__init__(scope=scope, change_type=change_type)
|
251
286
|
self.resources = resources
|
252
287
|
|
@@ -254,9 +289,9 @@ class NodeResources(ChangeSetNode):
|
|
254
289
|
class NodeResource(ChangeSetNode):
|
255
290
|
name: Final[str]
|
256
291
|
type_: Final[ChangeSetTerminal]
|
257
|
-
condition_reference: Final[Optional[TerminalValue]]
|
258
292
|
properties: Final[NodeProperties]
|
259
|
-
|
293
|
+
condition_reference: Final[Maybe[TerminalValue]]
|
294
|
+
depends_on: Final[Maybe[NodeDependsOn]]
|
260
295
|
|
261
296
|
def __init__(
|
262
297
|
self,
|
@@ -265,8 +300,8 @@ class NodeResource(ChangeSetNode):
|
|
265
300
|
name: str,
|
266
301
|
type_: ChangeSetTerminal,
|
267
302
|
properties: NodeProperties,
|
268
|
-
condition_reference:
|
269
|
-
depends_on:
|
303
|
+
condition_reference: Maybe[TerminalValue],
|
304
|
+
depends_on: Maybe[NodeDependsOn],
|
270
305
|
):
|
271
306
|
super().__init__(scope=scope, change_type=change_type)
|
272
307
|
self.name = name
|
@@ -279,7 +314,8 @@ class NodeResource(ChangeSetNode):
|
|
279
314
|
class NodeProperties(ChangeSetNode):
|
280
315
|
properties: Final[list[NodeProperty]]
|
281
316
|
|
282
|
-
def __init__(self, scope: Scope,
|
317
|
+
def __init__(self, scope: Scope, properties: list[NodeProperty]):
|
318
|
+
change_type = parent_change_type_of(properties)
|
283
319
|
super().__init__(scope=scope, change_type=change_type)
|
284
320
|
self.properties = properties
|
285
321
|
|
@@ -287,8 +323,8 @@ class NodeProperties(ChangeSetNode):
|
|
287
323
|
class NodeDependsOn(ChangeSetNode):
|
288
324
|
depends_on: Final[NodeArray]
|
289
325
|
|
290
|
-
def __init__(self, scope: Scope,
|
291
|
-
super().__init__(scope=scope, change_type=change_type)
|
326
|
+
def __init__(self, scope: Scope, depends_on: NodeArray):
|
327
|
+
super().__init__(scope=scope, change_type=depends_on.change_type)
|
292
328
|
self.depends_on = depends_on
|
293
329
|
|
294
330
|
|
@@ -296,8 +332,8 @@ class NodeProperty(ChangeSetNode):
|
|
296
332
|
name: Final[str]
|
297
333
|
value: Final[ChangeSetEntity]
|
298
334
|
|
299
|
-
def __init__(self, scope: Scope,
|
300
|
-
super().__init__(scope=scope, change_type=change_type)
|
335
|
+
def __init__(self, scope: Scope, name: str, value: ChangeSetEntity):
|
336
|
+
super().__init__(scope=scope, change_type=value.change_type)
|
301
337
|
self.name = name
|
302
338
|
self.value = value
|
303
339
|
|
@@ -386,6 +422,8 @@ FnGetAttKey: Final[str] = "Fn::GetAtt"
|
|
386
422
|
FnEqualsKey: Final[str] = "Fn::Equals"
|
387
423
|
FnFindInMapKey: Final[str] = "Fn::FindInMap"
|
388
424
|
FnSubKey: Final[str] = "Fn::Sub"
|
425
|
+
FnTransform: Final[str] = "Fn::Transform"
|
426
|
+
FnSelect: Final[str] = "Fn::Select"
|
389
427
|
INTRINSIC_FUNCTIONS: Final[set[str]] = {
|
390
428
|
RefKey,
|
391
429
|
FnIfKey,
|
@@ -395,6 +433,8 @@ INTRINSIC_FUNCTIONS: Final[set[str]] = {
|
|
395
433
|
FnGetAttKey,
|
396
434
|
FnFindInMapKey,
|
397
435
|
FnSubKey,
|
436
|
+
FnTransform,
|
437
|
+
FnSelect,
|
398
438
|
}
|
399
439
|
|
400
440
|
|
@@ -440,9 +480,9 @@ class ChangeSetModel:
|
|
440
480
|
terminal_value = self._visited_scopes.get(scope)
|
441
481
|
if isinstance(terminal_value, TerminalValue):
|
442
482
|
return terminal_value
|
443
|
-
if
|
483
|
+
if is_created(before=before_value, after=after_value):
|
444
484
|
terminal_value = TerminalValueCreated(scope=scope, value=after_value)
|
445
|
-
elif
|
485
|
+
elif is_removed(before=before_value, after=after_value):
|
446
486
|
terminal_value = TerminalValueRemoved(scope=scope, value=before_value)
|
447
487
|
elif before_value == after_value:
|
448
488
|
terminal_value = TerminalValueUnchanged(scope=scope, value=before_value)
|
@@ -466,9 +506,9 @@ class ChangeSetModel:
|
|
466
506
|
arguments = self._visit_value(
|
467
507
|
scope=scope, before_value=before_arguments, after_value=after_arguments
|
468
508
|
)
|
469
|
-
if
|
509
|
+
if is_created(before=before_arguments, after=after_arguments):
|
470
510
|
change_type = ChangeType.CREATED
|
471
|
-
elif
|
511
|
+
elif is_removed(before=before_arguments, after=after_arguments):
|
472
512
|
change_type = ChangeType.REMOVED
|
473
513
|
else:
|
474
514
|
function_name = intrinsic_function.replace("::", "_")
|
@@ -586,8 +626,7 @@ class ChangeSetModel:
|
|
586
626
|
)
|
587
627
|
if not isinstance(node_condition, NodeCondition):
|
588
628
|
raise RuntimeError()
|
589
|
-
|
590
|
-
change_type = self._change_type_for_parent_of(change_types=change_types)
|
629
|
+
change_type = parent_change_type_of([node_condition, *arguments[1:]])
|
591
630
|
return change_type
|
592
631
|
|
593
632
|
def _visit_array(
|
@@ -602,12 +641,7 @@ class ChangeSetModel:
|
|
602
641
|
scope=value_scope, before_value=before_value, after_value=after_value
|
603
642
|
)
|
604
643
|
array.append(value)
|
605
|
-
|
606
|
-
change_type = ChangeType.CREATED
|
607
|
-
elif self._is_removed(before=before_array, after=after_array):
|
608
|
-
change_type = ChangeType.REMOVED
|
609
|
-
else:
|
610
|
-
change_type = self._change_type_for_parent_of([value.change_type for value in array])
|
644
|
+
change_type = change_type_of(before_array, after_array, array)
|
611
645
|
return NodeArray(scope=scope, change_type=change_type, array=array)
|
612
646
|
|
613
647
|
def _visit_object(
|
@@ -616,12 +650,6 @@ class ChangeSetModel:
|
|
616
650
|
node_object = self._visited_scopes.get(scope)
|
617
651
|
if isinstance(node_object, NodeObject):
|
618
652
|
return node_object
|
619
|
-
if self._is_created(before=before_object, after=after_object):
|
620
|
-
change_type = ChangeType.CREATED
|
621
|
-
elif self._is_removed(before=before_object, after=after_object):
|
622
|
-
change_type = ChangeType.REMOVED
|
623
|
-
else:
|
624
|
-
change_type = ChangeType.UNCHANGED
|
625
653
|
binding_names = self._safe_keys_of(before_object, after_object)
|
626
654
|
bindings: dict[str, ChangeSetEntity] = dict()
|
627
655
|
for binding_name in binding_names:
|
@@ -632,7 +660,7 @@ class ChangeSetModel:
|
|
632
660
|
scope=binding_scope, before_value=before_value, after_value=after_value
|
633
661
|
)
|
634
662
|
bindings[binding_name] = value
|
635
|
-
|
663
|
+
change_type = change_type_of(before_object, after_object, list(bindings.values()))
|
636
664
|
node_object = NodeObject(scope=scope, change_type=change_type, bindings=bindings)
|
637
665
|
self._visited_scopes[scope] = node_object
|
638
666
|
return node_object
|
@@ -660,9 +688,9 @@ class ChangeSetModel:
|
|
660
688
|
unset = object()
|
661
689
|
if before_type_name == after_type_name:
|
662
690
|
dominant_value = before_value
|
663
|
-
elif
|
691
|
+
elif is_created(before=before_value, after=after_value):
|
664
692
|
dominant_value = after_value
|
665
|
-
elif
|
693
|
+
elif is_removed(before=before_value, after=after_value):
|
666
694
|
dominant_value = before_value
|
667
695
|
else:
|
668
696
|
dominant_value = unset
|
@@ -713,9 +741,7 @@ class ChangeSetModel:
|
|
713
741
|
value = self._visit_value(
|
714
742
|
scope=scope, before_value=before_property, after_value=after_property
|
715
743
|
)
|
716
|
-
node_property = NodeProperty(
|
717
|
-
scope=scope, change_type=value.change_type, name=property_name, value=value
|
718
|
-
)
|
744
|
+
node_property = NodeProperty(scope=scope, name=property_name, value=value)
|
719
745
|
self._visited_scopes[scope] = node_property
|
720
746
|
return node_property
|
721
747
|
|
@@ -725,10 +751,8 @@ class ChangeSetModel:
|
|
725
751
|
node_properties = self._visited_scopes.get(scope)
|
726
752
|
if isinstance(node_properties, NodeProperties):
|
727
753
|
return node_properties
|
728
|
-
# TODO: double check we are sure not to have this be a NodeObject
|
729
754
|
property_names: list[str] = self._safe_keys_of(before_properties, after_properties)
|
730
755
|
properties: list[NodeProperty] = list()
|
731
|
-
change_type = ChangeType.UNCHANGED
|
732
756
|
for property_name in property_names:
|
733
757
|
property_scope, (before_property, after_property) = self._safe_access_in(
|
734
758
|
scope, property_name, before_properties, after_properties
|
@@ -740,10 +764,7 @@ class ChangeSetModel:
|
|
740
764
|
after_property=after_property,
|
741
765
|
)
|
742
766
|
properties.append(property_)
|
743
|
-
|
744
|
-
node_properties = NodeProperties(
|
745
|
-
scope=scope, change_type=change_type, properties=properties
|
746
|
-
)
|
767
|
+
node_properties = NodeProperties(scope=scope, properties=properties)
|
747
768
|
self._visited_scopes[scope] = node_properties
|
748
769
|
return node_properties
|
749
770
|
|
@@ -765,13 +786,6 @@ class ChangeSetModel:
|
|
765
786
|
if isinstance(node_resource, NodeResource):
|
766
787
|
return node_resource
|
767
788
|
|
768
|
-
if self._is_created(before=before_resource, after=after_resource):
|
769
|
-
change_type = ChangeType.CREATED
|
770
|
-
elif self._is_removed(before=before_resource, after=after_resource):
|
771
|
-
change_type = ChangeType.REMOVED
|
772
|
-
else:
|
773
|
-
change_type = ChangeType.UNCHANGED
|
774
|
-
|
775
789
|
scope_type, (before_type, after_type) = self._safe_access_in(
|
776
790
|
scope, TypeKey, before_resource, after_resource
|
777
791
|
)
|
@@ -779,7 +793,7 @@ class ChangeSetModel:
|
|
779
793
|
scope=scope_type, before_type=before_type, after_type=after_type
|
780
794
|
)
|
781
795
|
|
782
|
-
condition_reference =
|
796
|
+
condition_reference = Nothing
|
783
797
|
scope_condition, (before_condition, after_condition) = self._safe_access_in(
|
784
798
|
scope, ConditionKey, before_resource, after_resource
|
785
799
|
)
|
@@ -788,7 +802,7 @@ class ChangeSetModel:
|
|
788
802
|
scope_condition, before_condition, after_condition
|
789
803
|
)
|
790
804
|
|
791
|
-
depends_on =
|
805
|
+
depends_on = Nothing
|
792
806
|
scope_depends_on, (before_depends_on, after_depends_on) = self._safe_access_in(
|
793
807
|
scope, DependsOnKey, before_resource, after_resource
|
794
808
|
)
|
@@ -805,10 +819,10 @@ class ChangeSetModel:
|
|
805
819
|
before_properties=before_properties,
|
806
820
|
after_properties=after_properties,
|
807
821
|
)
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
822
|
+
|
823
|
+
change_type = change_type_of(
|
824
|
+
before_resource, after_resource, [properties, condition_reference, depends_on]
|
825
|
+
)
|
812
826
|
node_resource = NodeResource(
|
813
827
|
scope=scope,
|
814
828
|
change_type=change_type,
|
@@ -825,7 +839,6 @@ class ChangeSetModel:
|
|
825
839
|
self, scope: Scope, before_resources: Maybe[dict], after_resources: Maybe[dict]
|
826
840
|
) -> NodeResources:
|
827
841
|
# TODO: investigate type changes behavior.
|
828
|
-
change_type = ChangeType.UNCHANGED
|
829
842
|
resources: list[NodeResource] = list()
|
830
843
|
resource_names = self._safe_keys_of(before_resources, after_resources)
|
831
844
|
for resource_name in resource_names:
|
@@ -839,8 +852,7 @@ class ChangeSetModel:
|
|
839
852
|
after_resource=after_resource,
|
840
853
|
)
|
841
854
|
resources.append(resource)
|
842
|
-
|
843
|
-
return NodeResources(scope=scope, change_type=change_type, resources=resources)
|
855
|
+
return NodeResources(scope=scope, resources=resources)
|
844
856
|
|
845
857
|
def _visit_mapping(
|
846
858
|
self, scope: Scope, name: str, before_mapping: Maybe[dict], after_mapping: Maybe[dict]
|
@@ -848,14 +860,11 @@ class ChangeSetModel:
|
|
848
860
|
bindings = self._visit_object(
|
849
861
|
scope=scope, before_object=before_mapping, after_object=after_mapping
|
850
862
|
)
|
851
|
-
return NodeMapping(
|
852
|
-
scope=scope, change_type=bindings.change_type, name=name, bindings=bindings
|
853
|
-
)
|
863
|
+
return NodeMapping(scope=scope, name=name, bindings=bindings)
|
854
864
|
|
855
865
|
def _visit_mappings(
|
856
866
|
self, scope: Scope, before_mappings: Maybe[dict], after_mappings: Maybe[dict]
|
857
867
|
) -> NodeMappings:
|
858
|
-
change_type = ChangeType.UNCHANGED
|
859
868
|
mappings: list[NodeMapping] = list()
|
860
869
|
mapping_names = self._safe_keys_of(before_mappings, after_mappings)
|
861
870
|
for mapping_name in mapping_names:
|
@@ -869,8 +878,7 @@ class ChangeSetModel:
|
|
869
878
|
after_mapping=after_mapping,
|
870
879
|
)
|
871
880
|
mappings.append(mapping)
|
872
|
-
|
873
|
-
return NodeMappings(scope=scope, change_type=change_type, mappings=mappings)
|
881
|
+
return NodeMappings(scope=scope, mappings=mappings)
|
874
882
|
|
875
883
|
def _visit_dynamic_parameter(self, parameter_name: str) -> ChangeSetEntity:
|
876
884
|
scope = Scope("Dynamic").open_scope("Parameters")
|
@@ -905,13 +913,8 @@ class ChangeSetModel:
|
|
905
913
|
|
906
914
|
dynamic_value = self._visit_dynamic_parameter(parameter_name=parameter_name)
|
907
915
|
|
908
|
-
change_type = self._change_type_for_parent_of(
|
909
|
-
change_types=[type_.change_type, default_value.change_type, dynamic_value.change_type]
|
910
|
-
)
|
911
|
-
|
912
916
|
node_parameter = NodeParameter(
|
913
917
|
scope=scope,
|
914
|
-
change_type=change_type,
|
915
918
|
name=parameter_name,
|
916
919
|
type_=type_,
|
917
920
|
default_value=default_value,
|
@@ -928,7 +931,6 @@ class ChangeSetModel:
|
|
928
931
|
return node_parameters
|
929
932
|
parameter_names: list[str] = self._safe_keys_of(before_parameters, after_parameters)
|
930
933
|
parameters: list[NodeParameter] = list()
|
931
|
-
change_type = ChangeType.UNCHANGED
|
932
934
|
for parameter_name in parameter_names:
|
933
935
|
parameter_scope, (before_parameter, after_parameter) = self._safe_access_in(
|
934
936
|
scope, parameter_name, before_parameters, after_parameters
|
@@ -940,10 +942,7 @@ class ChangeSetModel:
|
|
940
942
|
after_parameter=after_parameter,
|
941
943
|
)
|
942
944
|
parameters.append(parameter)
|
943
|
-
|
944
|
-
node_parameters = NodeParameters(
|
945
|
-
scope=scope, change_type=change_type, parameters=parameters
|
946
|
-
)
|
945
|
+
node_parameters = NodeParameters(scope=scope, parameters=parameters)
|
947
946
|
self._visited_scopes[scope] = node_parameters
|
948
947
|
return node_parameters
|
949
948
|
|
@@ -974,9 +973,7 @@ class ChangeSetModel:
|
|
974
973
|
node_array = self._visit_array(
|
975
974
|
scope=scope, before_array=before_depends_on, after_array=after_depends_on
|
976
975
|
)
|
977
|
-
node_depends_on = NodeDependsOn(
|
978
|
-
scope=scope, change_type=node_array.change_type, depends_on=node_array
|
979
|
-
)
|
976
|
+
node_depends_on = NodeDependsOn(scope=scope, depends_on=node_array)
|
980
977
|
return node_depends_on
|
981
978
|
|
982
979
|
def _visit_condition(
|
@@ -992,9 +989,7 @@ class ChangeSetModel:
|
|
992
989
|
body = self._visit_value(
|
993
990
|
scope=scope, before_value=before_condition, after_value=after_condition
|
994
991
|
)
|
995
|
-
node_condition = NodeCondition(
|
996
|
-
scope=scope, change_type=body.change_type, name=condition_name, body=body
|
997
|
-
)
|
992
|
+
node_condition = NodeCondition(scope=scope, name=condition_name, body=body)
|
998
993
|
self._visited_scopes[scope] = node_condition
|
999
994
|
return node_condition
|
1000
995
|
|
@@ -1006,7 +1001,6 @@ class ChangeSetModel:
|
|
1006
1001
|
return node_conditions
|
1007
1002
|
condition_names: list[str] = self._safe_keys_of(before_conditions, after_conditions)
|
1008
1003
|
conditions: list[NodeCondition] = list()
|
1009
|
-
change_type = ChangeType.UNCHANGED
|
1010
1004
|
for condition_name in condition_names:
|
1011
1005
|
condition_scope, (before_condition, after_condition) = self._safe_access_in(
|
1012
1006
|
scope, condition_name, before_conditions, after_conditions
|
@@ -1018,33 +1012,27 @@ class ChangeSetModel:
|
|
1018
1012
|
after_condition=after_condition,
|
1019
1013
|
)
|
1020
1014
|
conditions.append(condition)
|
1021
|
-
|
1022
|
-
node_conditions = NodeConditions(
|
1023
|
-
scope=scope, change_type=change_type, conditions=conditions
|
1024
|
-
)
|
1015
|
+
node_conditions = NodeConditions(scope=scope, conditions=conditions)
|
1025
1016
|
self._visited_scopes[scope] = node_conditions
|
1026
1017
|
return node_conditions
|
1027
1018
|
|
1028
1019
|
def _visit_output(
|
1029
1020
|
self, scope: Scope, name: str, before_output: Maybe[dict], after_output: Maybe[dict]
|
1030
1021
|
) -> NodeOutput:
|
1031
|
-
change_type = ChangeType.UNCHANGED
|
1032
1022
|
scope_value, (before_value, after_value) = self._safe_access_in(
|
1033
1023
|
scope, ValueKey, before_output, after_output
|
1034
1024
|
)
|
1035
1025
|
value = self._visit_value(scope_value, before_value, after_value)
|
1036
|
-
change_type = change_type.for_child(value.change_type)
|
1037
1026
|
|
1038
|
-
export:
|
1027
|
+
export: Maybe[ChangeSetEntity] = Nothing
|
1039
1028
|
scope_export, (before_export, after_export) = self._safe_access_in(
|
1040
1029
|
scope, ExportKey, before_output, after_output
|
1041
1030
|
)
|
1042
1031
|
if before_export or after_export:
|
1043
1032
|
export = self._visit_value(scope_export, before_export, after_export)
|
1044
|
-
change_type = change_type.for_child(export.change_type)
|
1045
1033
|
|
1046
1034
|
# TODO: condition references should be resolved for the condition's change_type?
|
1047
|
-
condition_reference:
|
1035
|
+
condition_reference: Maybe[TerminalValue] = Nothing
|
1048
1036
|
scope_condition, (before_condition, after_condition) = self._safe_access_in(
|
1049
1037
|
scope, ConditionKey, before_output, after_output
|
1050
1038
|
)
|
@@ -1052,11 +1040,9 @@ class ChangeSetModel:
|
|
1052
1040
|
condition_reference = self._visit_terminal_value(
|
1053
1041
|
scope_condition, before_condition, after_condition
|
1054
1042
|
)
|
1055
|
-
change_type = change_type.for_child(condition_reference.change_type)
|
1056
1043
|
|
1057
1044
|
return NodeOutput(
|
1058
1045
|
scope=scope,
|
1059
|
-
change_type=change_type,
|
1060
1046
|
name=name,
|
1061
1047
|
value=value,
|
1062
1048
|
export=export,
|
@@ -1066,7 +1052,6 @@ class ChangeSetModel:
|
|
1066
1052
|
def _visit_outputs(
|
1067
1053
|
self, scope: Scope, before_outputs: Maybe[dict], after_outputs: Maybe[dict]
|
1068
1054
|
) -> NodeOutputs:
|
1069
|
-
change_type = ChangeType.UNCHANGED
|
1070
1055
|
outputs: list[NodeOutput] = list()
|
1071
1056
|
output_names: list[str] = self._safe_keys_of(before_outputs, after_outputs)
|
1072
1057
|
for output_name in output_names:
|
@@ -1080,8 +1065,7 @@ class ChangeSetModel:
|
|
1080
1065
|
after_output=after_output,
|
1081
1066
|
)
|
1082
1067
|
outputs.append(output)
|
1083
|
-
|
1084
|
-
return NodeOutputs(scope=scope, change_type=change_type, outputs=outputs)
|
1068
|
+
return NodeOutputs(scope=scope, outputs=outputs)
|
1085
1069
|
|
1086
1070
|
def _model(self, before_template: Maybe[dict], after_template: Maybe[dict]) -> NodeTemplate:
|
1087
1071
|
root_scope = Scope()
|
@@ -1131,7 +1115,6 @@ class ChangeSetModel:
|
|
1131
1115
|
# TODO: compute the change_type of the template properly.
|
1132
1116
|
return NodeTemplate(
|
1133
1117
|
scope=root_scope,
|
1134
|
-
change_type=resources.change_type,
|
1135
1118
|
mappings=mappings,
|
1136
1119
|
parameters=parameters,
|
1137
1120
|
conditions=conditions,
|
@@ -1139,7 +1122,7 @@ class ChangeSetModel:
|
|
1139
1122
|
outputs=outputs,
|
1140
1123
|
)
|
1141
1124
|
|
1142
|
-
def _retrieve_condition_if_exists(self, condition_name: str) ->
|
1125
|
+
def _retrieve_condition_if_exists(self, condition_name: str) -> Maybe[NodeCondition]:
|
1143
1126
|
conditions_scope, (before_conditions, after_conditions) = self._safe_access_in(
|
1144
1127
|
Scope(), ConditionsKey, self._before_template, self._after_template
|
1145
1128
|
)
|
@@ -1156,14 +1139,12 @@ class ChangeSetModel:
|
|
1156
1139
|
after_condition=after_condition,
|
1157
1140
|
)
|
1158
1141
|
return node_condition
|
1159
|
-
return
|
1142
|
+
return Nothing
|
1160
1143
|
|
1161
|
-
def _retrieve_parameter_if_exists(self, parameter_name: str) ->
|
1144
|
+
def _retrieve_parameter_if_exists(self, parameter_name: str) -> Maybe[NodeParameter]:
|
1162
1145
|
parameters_scope, (before_parameters, after_parameters) = self._safe_access_in(
|
1163
1146
|
Scope(), ParametersKey, self._before_template, self._after_template
|
1164
1147
|
)
|
1165
|
-
before_parameters = before_parameters or dict()
|
1166
|
-
after_parameters = after_parameters or dict()
|
1167
1148
|
if parameter_name in before_parameters or parameter_name in after_parameters:
|
1168
1149
|
parameter_scope, (before_parameter, after_parameter) = self._safe_access_in(
|
1169
1150
|
parameters_scope, parameter_name, before_parameters, after_parameters
|
@@ -1175,15 +1156,13 @@ class ChangeSetModel:
|
|
1175
1156
|
after_parameter=after_parameter,
|
1176
1157
|
)
|
1177
1158
|
return node_parameter
|
1178
|
-
return
|
1159
|
+
return Nothing
|
1179
1160
|
|
1180
1161
|
def _retrieve_mapping(self, mapping_name) -> NodeMapping:
|
1181
1162
|
# TODO: add caching mechanism, and raise appropriate error if missing.
|
1182
1163
|
scope_mappings, (before_mappings, after_mappings) = self._safe_access_in(
|
1183
1164
|
Scope(), MappingsKey, self._before_template, self._after_template
|
1184
1165
|
)
|
1185
|
-
before_mappings = before_mappings or dict()
|
1186
|
-
after_mappings = after_mappings or dict()
|
1187
1166
|
if mapping_name in before_mappings or mapping_name in after_mappings:
|
1188
1167
|
scope_mapping, (before_mapping, after_mapping) = self._safe_access_in(
|
1189
1168
|
scope_mappings, mapping_name, before_mappings, after_mappings
|
@@ -1240,15 +1219,6 @@ class ChangeSetModel:
|
|
1240
1219
|
keys = sorted(key_set)
|
1241
1220
|
return keys
|
1242
1221
|
|
1243
|
-
@staticmethod
|
1244
|
-
def _change_type_for_parent_of(change_types: list[ChangeType]) -> ChangeType:
|
1245
|
-
parent_change_type = ChangeType.UNCHANGED
|
1246
|
-
for child_change_type in change_types:
|
1247
|
-
parent_change_type = parent_change_type.for_child(child_change_type)
|
1248
|
-
if parent_change_type == ChangeType.MODIFIED:
|
1249
|
-
break
|
1250
|
-
return parent_change_type
|
1251
|
-
|
1252
1222
|
@staticmethod
|
1253
1223
|
def _name_if_intrinsic_function(value: Maybe[Any]) -> Optional[str]:
|
1254
1224
|
if isinstance(value, dict):
|
@@ -1277,11 +1247,3 @@ class ChangeSetModel:
|
|
1277
1247
|
@staticmethod
|
1278
1248
|
def _is_array(value: Any) -> bool:
|
1279
1249
|
return isinstance(value, list)
|
1280
|
-
|
1281
|
-
@staticmethod
|
1282
|
-
def _is_created(before: Maybe[Any], after: Maybe[Any]) -> bool:
|
1283
|
-
return isinstance(before, NothingType) and not isinstance(after, NothingType)
|
1284
|
-
|
1285
|
-
@staticmethod
|
1286
|
-
def _is_removed(before: Maybe[Any], after: Maybe[Any]) -> bool:
|
1287
|
-
return not isinstance(before, NothingType) and isinstance(after, NothingType)
|