buildzr 0.0.12__py3-none-any.whl → 0.0.14__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.
- buildzr/__about__.py +1 -1
- buildzr/dsl/__init__.py +7 -0
- buildzr/dsl/dsl.py +845 -82
- buildzr/dsl/explorer.py +28 -2
- buildzr/dsl/expression.py +115 -25
- buildzr/dsl/interfaces/__init__.py +4 -0
- buildzr/dsl/interfaces/interfaces.py +77 -0
- buildzr/models/generate.sh +9 -0
- buildzr/models/models.py +3 -1
- {buildzr-0.0.12.dist-info → buildzr-0.0.14.dist-info}/METADATA +2 -4
- buildzr-0.0.14.dist-info/RECORD +24 -0
- buildzr-0.0.12.dist-info/RECORD +0 -24
- {buildzr-0.0.12.dist-info → buildzr-0.0.14.dist-info}/WHEEL +0 -0
- {buildzr-0.0.12.dist-info → buildzr-0.0.14.dist-info}/licenses/LICENSE.md +0 -0
buildzr/dsl/dsl.py
CHANGED
@@ -29,6 +29,10 @@ from buildzr.dsl.interfaces import (
|
|
29
29
|
DslWorkspaceElement,
|
30
30
|
DslElement,
|
31
31
|
DslViewElement,
|
32
|
+
DslDeploymentEnvironment,
|
33
|
+
DslInfrastructureNodeElement,
|
34
|
+
DslDeploymentNodeElement,
|
35
|
+
DslElementInstance,
|
32
36
|
)
|
33
37
|
from buildzr.dsl.relations import (
|
34
38
|
DslElementRelationOverrides,
|
@@ -53,6 +57,8 @@ _current_workspace: ContextVar[Optional['Workspace']] = ContextVar('current_work
|
|
53
57
|
_current_group_stack: ContextVar[List['Group']] = ContextVar('current_group', default=[])
|
54
58
|
_current_software_system: ContextVar[Optional['SoftwareSystem']] = ContextVar('current_software_system', default=None)
|
55
59
|
_current_container: ContextVar[Optional['Container']] = ContextVar('current_container', default=None)
|
60
|
+
_current_deployment_environment: ContextVar[Optional['DeploymentEnvironment']] = ContextVar('current_deployment_environment', default=None)
|
61
|
+
_current_deployment_node_stack: ContextVar[List['DeploymentNode']] = ContextVar('current_deployment_node', default=[])
|
56
62
|
|
57
63
|
class Workspace(DslWorkspaceElement):
|
58
64
|
"""
|
@@ -68,7 +74,7 @@ class Workspace(DslWorkspaceElement):
|
|
68
74
|
return None
|
69
75
|
|
70
76
|
@property
|
71
|
-
def children(self) -> Optional[List[Union['Person', 'SoftwareSystem']]]:
|
77
|
+
def children(self) -> Optional[List[Union['Person', 'SoftwareSystem', 'DeploymentNode']]]:
|
72
78
|
return self._children
|
73
79
|
|
74
80
|
def __init__(
|
@@ -82,7 +88,7 @@ class Workspace(DslWorkspaceElement):
|
|
82
88
|
|
83
89
|
self._m = buildzr.models.Workspace()
|
84
90
|
self._parent = None
|
85
|
-
self._children: Optional[List[Union['Person', 'SoftwareSystem']]] = []
|
91
|
+
self._children: Optional[List[Union['Person', 'SoftwareSystem', 'DeploymentNode']]] = []
|
86
92
|
self._dynamic_attrs: Dict[str, Union['Person', 'SoftwareSystem']] = {}
|
87
93
|
self._use_implied_relationships = implied_relationships
|
88
94
|
self._group_separator = group_separator
|
@@ -118,47 +124,53 @@ class Workspace(DslWorkspaceElement):
|
|
118
124
|
|
119
125
|
def __exit__(self, exc_type: Optional[Type[BaseException]], exc_value: Optional[BaseException], traceback: Optional[Any]) -> None:
|
120
126
|
|
127
|
+
if self._use_implied_relationships:
|
128
|
+
self._imply_relationships()
|
129
|
+
|
130
|
+
_current_workspace.reset(self._token)
|
131
|
+
|
132
|
+
def _imply_relationships(
|
133
|
+
self,
|
134
|
+
) -> None:
|
135
|
+
|
121
136
|
from buildzr.dsl.explorer import Explorer
|
122
137
|
|
123
138
|
# Process implied relationships:
|
124
139
|
# If we have relationship s >> do >> a.b, then create s >> do >> a.
|
125
140
|
# If we have relationship s.ss >> do >> a.b.c, then create s.ss >> do >> a.b and s.ss >> do >> a.
|
126
141
|
# And so on...
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
142
|
+
explorer = Explorer(self)
|
143
|
+
relationships = list(explorer.walk_relationships())
|
144
|
+
for relationship in relationships:
|
145
|
+
source = relationship.source
|
146
|
+
destination = relationship.destination
|
147
|
+
destination_parent = destination.parent
|
148
|
+
|
149
|
+
while destination_parent is not None and \
|
150
|
+
isinstance(source, DslElement) and \
|
151
|
+
not isinstance(source.model, buildzr.models.Workspace) and \
|
152
|
+
not isinstance(destination_parent, DslWorkspaceElement):
|
153
|
+
|
154
|
+
if destination_parent is source.parent:
|
155
|
+
break
|
156
|
+
|
157
|
+
rels = source.model.relationships
|
158
|
+
|
159
|
+
if rels:
|
160
|
+
already_exists = any(
|
161
|
+
r.destinationId == destination_parent.model.id and
|
162
|
+
r.description == relationship.model.description and
|
163
|
+
r.technology == relationship.model.technology
|
164
|
+
for r in rels
|
165
|
+
)
|
166
|
+
if not already_exists:
|
167
|
+
r = source.uses(
|
168
|
+
destination_parent,
|
169
|
+
description=relationship.model.description,
|
170
|
+
technology=relationship.model.technology,
|
151
171
|
)
|
152
|
-
|
153
|
-
|
154
|
-
destination_parent,
|
155
|
-
description=relationship.model.description,
|
156
|
-
technology=relationship.model.technology,
|
157
|
-
)
|
158
|
-
r.model.linkedRelationshipId = relationship.model.id
|
159
|
-
destination_parent = destination_parent.parent
|
160
|
-
|
161
|
-
_current_workspace.reset(self._token)
|
172
|
+
r.model.linkedRelationshipId = relationship.model.id
|
173
|
+
destination_parent = destination_parent.parent
|
162
174
|
|
163
175
|
def person(self) -> TypedDynamicAttribute['Person']:
|
164
176
|
return TypedDynamicAttribute['Person'](self._dynamic_attrs)
|
@@ -166,7 +178,12 @@ class Workspace(DslWorkspaceElement):
|
|
166
178
|
def software_system(self) -> TypedDynamicAttribute['SoftwareSystem']:
|
167
179
|
return TypedDynamicAttribute['SoftwareSystem'](self._dynamic_attrs)
|
168
180
|
|
169
|
-
def add_model(
|
181
|
+
def add_model(
|
182
|
+
self, model: Union[
|
183
|
+
'Person',
|
184
|
+
'SoftwareSystem',
|
185
|
+
'DeploymentNode',
|
186
|
+
]) -> None:
|
170
187
|
if isinstance(model, Person):
|
171
188
|
self._m.model.people.append(model._m)
|
172
189
|
model._parent = self
|
@@ -177,6 +194,10 @@ class Workspace(DslWorkspaceElement):
|
|
177
194
|
model._parent = self
|
178
195
|
self._add_dynamic_attr(model.model.name, model)
|
179
196
|
self._children.append(model)
|
197
|
+
elif isinstance(model, DeploymentNode):
|
198
|
+
self._m.model.deploymentNodes.append(model._m)
|
199
|
+
model._parent = self
|
200
|
+
self._children.append(model)
|
180
201
|
else:
|
181
202
|
raise ValueError('Invalid element type: Trying to add an element of type {} to a workspace.'.format(type(model)))
|
182
203
|
|
@@ -187,6 +208,7 @@ class Workspace(DslWorkspaceElement):
|
|
187
208
|
'SystemContextView',
|
188
209
|
'ContainerView',
|
189
210
|
'ComponentView',
|
211
|
+
'DeploymentView',
|
190
212
|
]
|
191
213
|
) -> None:
|
192
214
|
|
@@ -215,6 +237,11 @@ class Workspace(DslWorkspaceElement):
|
|
215
237
|
self.model.views.componentViews = [view.model]
|
216
238
|
else:
|
217
239
|
self.model.views.componentViews.append(view.model)
|
240
|
+
elif isinstance(view, DeploymentView):
|
241
|
+
if not self.model.views.deploymentViews:
|
242
|
+
self.model.views.deploymentViews = [view.model]
|
243
|
+
else:
|
244
|
+
self.model.views.deploymentViews.append(view.model)
|
218
245
|
else:
|
219
246
|
raise NotImplementedError("The view {0} is currently not supported", type(view))
|
220
247
|
|
@@ -708,6 +735,500 @@ _AutoLayout = Optional[
|
|
708
735
|
]
|
709
736
|
]
|
710
737
|
|
738
|
+
class DeploymentEnvironment(DslDeploymentEnvironment):
|
739
|
+
|
740
|
+
def __init__(self, name: str) -> None:
|
741
|
+
self._name = name
|
742
|
+
self._parent: Optional[Workspace] = None
|
743
|
+
self._children: Optional[List['DeploymentNode']] = []
|
744
|
+
|
745
|
+
workspace = _current_workspace.get()
|
746
|
+
if workspace is not None:
|
747
|
+
self._parent = workspace
|
748
|
+
|
749
|
+
@property
|
750
|
+
def name(self) -> str:
|
751
|
+
return self._name
|
752
|
+
|
753
|
+
@property
|
754
|
+
def parent(self) -> Optional[Workspace]:
|
755
|
+
return self._parent
|
756
|
+
|
757
|
+
@property
|
758
|
+
def children(self) -> Optional[List['DeploymentNode']]:
|
759
|
+
return self._children
|
760
|
+
|
761
|
+
def add_deployment_node(self, node: 'DeploymentNode') -> None:
|
762
|
+
node._m.environment = self._name
|
763
|
+
|
764
|
+
def __enter__(self) -> Self:
|
765
|
+
self._token = _current_deployment_environment.set(self)
|
766
|
+
return self
|
767
|
+
|
768
|
+
def __exit__(self, exc_type: Optional[Type[BaseException]], exc_value: Optional[BaseException], traceback: Optional[Any]) -> None:
|
769
|
+
_current_deployment_environment.reset(self._token)
|
770
|
+
|
771
|
+
if self._parent is not None:
|
772
|
+
self._imply_software_system_instance_relationships(self._parent)
|
773
|
+
self._imply_container_instance_relationships(self._parent)
|
774
|
+
|
775
|
+
def _imply_software_system_instance_relationships(self, workspace: Workspace) -> None:
|
776
|
+
|
777
|
+
from buildzr.dsl.expression import Expression
|
778
|
+
|
779
|
+
"""
|
780
|
+
Process implied instance relationships. For example, if we have a
|
781
|
+
relationship between two software systems, and the software system
|
782
|
+
instances of those software systems exists, then we need to create a
|
783
|
+
new relationship between those software system instances.
|
784
|
+
|
785
|
+
These implied relationships are used in `DeploymentView`.
|
786
|
+
"""
|
787
|
+
|
788
|
+
software_instances = [
|
789
|
+
cast('SoftwareSystemInstance', e) for e in Expression(include_elements=[
|
790
|
+
lambda w, e: e.type == SoftwareSystemInstance,
|
791
|
+
]).elements(workspace)
|
792
|
+
]
|
793
|
+
|
794
|
+
software_instance_map: Dict[str, List['SoftwareSystemInstance']] = {}
|
795
|
+
for software_instance in software_instances:
|
796
|
+
software_id = software_instance.model.softwareSystemId
|
797
|
+
if software_id not in software_instance_map:
|
798
|
+
software_instance_map[software_id] = []
|
799
|
+
software_instance_map[software_id].append(software_instance)
|
800
|
+
|
801
|
+
softwares = [
|
802
|
+
cast('SoftwareSystem', e) for e in Expression(include_elements=[
|
803
|
+
lambda w, e: e.type == SoftwareSystem,
|
804
|
+
]).elements(workspace)
|
805
|
+
]
|
806
|
+
|
807
|
+
for software in softwares:
|
808
|
+
|
809
|
+
other_softwares_ids = {
|
810
|
+
s.model.id for s in softwares
|
811
|
+
if s.model.id != software.model.id
|
812
|
+
}
|
813
|
+
|
814
|
+
if not software.model.relationships:
|
815
|
+
continue
|
816
|
+
|
817
|
+
for relationship in software.model.relationships:
|
818
|
+
if not relationship.destinationId in other_softwares_ids:
|
819
|
+
continue
|
820
|
+
|
821
|
+
this_software_instances = software_instance_map[software.model.id]
|
822
|
+
other_software_instances = software_instance_map[relationship.destinationId]
|
823
|
+
|
824
|
+
for this_software_instance in this_software_instances:
|
825
|
+
for other_software_instance in other_software_instances:
|
826
|
+
|
827
|
+
already_exists = this_software_instance.model.relationships is not None and any(
|
828
|
+
r.sourceId == this_software_instance.model.id and
|
829
|
+
r.destinationId == other_software_instance.model.id and
|
830
|
+
r.description == relationship.description and
|
831
|
+
r.technology == relationship.technology
|
832
|
+
for r in this_software_instance.model.relationships
|
833
|
+
)
|
834
|
+
|
835
|
+
if not already_exists:
|
836
|
+
# Note: tags aren't carried over.
|
837
|
+
r = this_software_instance.uses(
|
838
|
+
other_software_instance,
|
839
|
+
description=relationship.description,
|
840
|
+
technology=relationship.technology,
|
841
|
+
)
|
842
|
+
r.model.linkedRelationshipId = relationship.id
|
843
|
+
|
844
|
+
def _imply_container_instance_relationships(self, workspace: Workspace) -> None:
|
845
|
+
|
846
|
+
"""
|
847
|
+
Process implied instance relationships. For example, if we have a
|
848
|
+
relationship between two containers, and the container instances of
|
849
|
+
those containers exists, then we need to create a new relationship
|
850
|
+
between those container instances.
|
851
|
+
|
852
|
+
These implied relationships are used in `DeploymentView`.
|
853
|
+
"""
|
854
|
+
|
855
|
+
from buildzr.dsl.expression import Expression
|
856
|
+
|
857
|
+
container_instances = [
|
858
|
+
cast('ContainerInstance', e) for e in Expression(include_elements=[
|
859
|
+
lambda w, e: e.type == ContainerInstance,
|
860
|
+
]).elements(workspace)]
|
861
|
+
|
862
|
+
container_instance_map: Dict[str, List['ContainerInstance']] = {}
|
863
|
+
for container_instance in container_instances:
|
864
|
+
container_id = container_instance.model.containerId
|
865
|
+
if container_id not in container_instance_map:
|
866
|
+
container_instance_map[container_id] = []
|
867
|
+
container_instance_map[container_id].append(container_instance)
|
868
|
+
|
869
|
+
containers = [
|
870
|
+
cast('ContainerInstance', e) for e in Expression(include_elements=[
|
871
|
+
lambda w, e: e.type == Container,
|
872
|
+
]).elements(workspace)]
|
873
|
+
|
874
|
+
for container in containers:
|
875
|
+
|
876
|
+
other_containers_ids = {
|
877
|
+
c.model.id for c in containers
|
878
|
+
if c.model.id != container.model.id
|
879
|
+
}
|
880
|
+
|
881
|
+
if not container.model.relationships:
|
882
|
+
continue
|
883
|
+
|
884
|
+
for relationship in container.model.relationships:
|
885
|
+
|
886
|
+
if not relationship.destinationId in other_containers_ids:
|
887
|
+
continue
|
888
|
+
|
889
|
+
this_container_instances = container_instance_map[container.model.id]
|
890
|
+
other_container_instances = container_instance_map[relationship.destinationId]
|
891
|
+
|
892
|
+
for this_container_instance in this_container_instances:
|
893
|
+
for other_container_instance in other_container_instances:
|
894
|
+
|
895
|
+
already_exists = this_container_instance.model.relationships is not None and any(
|
896
|
+
r.sourceId == this_container_instance.model.id and
|
897
|
+
r.destinationId == other_container_instance.model.id and
|
898
|
+
r.description == relationship.description and
|
899
|
+
r.technology == relationship.technology
|
900
|
+
for r in this_container_instance.model.relationships
|
901
|
+
)
|
902
|
+
|
903
|
+
if not already_exists:
|
904
|
+
# Note: tags aren't carried over.
|
905
|
+
r = this_container_instance.uses(
|
906
|
+
other_container_instance,
|
907
|
+
description=relationship.description,
|
908
|
+
technology=relationship.technology,
|
909
|
+
)
|
910
|
+
r.model.linkedRelationshipId = relationship.id
|
911
|
+
|
912
|
+
|
913
|
+
class DeploymentNode(DslDeploymentNodeElement, DslElementRelationOverrides[
|
914
|
+
'DeploymentNode',
|
915
|
+
'DeploymentNode'
|
916
|
+
]):
|
917
|
+
|
918
|
+
def __init__(self, name: str, description: str="", technology: str="", tags: Set[str]=set(), instances: str="1") -> None:
|
919
|
+
self._m = buildzr.models.DeploymentNode()
|
920
|
+
self._m.instances = instances
|
921
|
+
self._m.id = GenerateId.for_element()
|
922
|
+
self._m.name = name
|
923
|
+
self._m.children = []
|
924
|
+
self._m.softwareSystemInstances = []
|
925
|
+
self._m.containerInstances = []
|
926
|
+
self._m.infrastructureNodes = []
|
927
|
+
self._m.description = description
|
928
|
+
self._m.technology = technology
|
929
|
+
self._parent: Optional[Workspace] = None
|
930
|
+
self._children: Optional[List[
|
931
|
+
Union[
|
932
|
+
'SoftwareSystemInstance',
|
933
|
+
'ContainerInstance',
|
934
|
+
'InfrastructureNode',
|
935
|
+
'DeploymentNode']]
|
936
|
+
] = []
|
937
|
+
self._tags = {'Element', 'Deployment Node'}.union(tags)
|
938
|
+
self._m.tags = ','.join(self._tags)
|
939
|
+
|
940
|
+
self._sources: List[DslElement] = []
|
941
|
+
self._destinations: List[DslElement] = []
|
942
|
+
self._relationships: Set[DslRelationship] = set()
|
943
|
+
|
944
|
+
# If the deployment stack is not empty, then we're inside the context of
|
945
|
+
# another deployment node. Otherwise, we're at the root of the
|
946
|
+
# workspace.
|
947
|
+
stack = _current_deployment_node_stack.get()
|
948
|
+
if stack:
|
949
|
+
stack[-1].add_deployment_node(self)
|
950
|
+
else:
|
951
|
+
workspace = _current_workspace.get()
|
952
|
+
if workspace:
|
953
|
+
self._parent = workspace
|
954
|
+
workspace.add_model(self)
|
955
|
+
|
956
|
+
deployment_environment = _current_deployment_environment.get()
|
957
|
+
if deployment_environment is not None:
|
958
|
+
self._m.environment = deployment_environment.name
|
959
|
+
deployment_environment.add_deployment_node(self)
|
960
|
+
|
961
|
+
@property
|
962
|
+
def model(self) -> buildzr.models.DeploymentNode:
|
963
|
+
return self._m
|
964
|
+
|
965
|
+
@property
|
966
|
+
def tags(self) -> Set[str]:
|
967
|
+
return self._tags
|
968
|
+
|
969
|
+
@property
|
970
|
+
def parent(self) -> Optional[Workspace]:
|
971
|
+
return self._parent
|
972
|
+
|
973
|
+
@property
|
974
|
+
def children(self) -> Optional[List[Union['SoftwareSystemInstance', 'ContainerInstance', 'InfrastructureNode', 'DeploymentNode']]]:
|
975
|
+
return self._children
|
976
|
+
|
977
|
+
@property
|
978
|
+
def destinations(self) -> List[DslElement]:
|
979
|
+
return self._destinations
|
980
|
+
|
981
|
+
@property
|
982
|
+
def sources(self) -> List[DslElement]:
|
983
|
+
return self._sources
|
984
|
+
|
985
|
+
@property
|
986
|
+
def relationships(self) -> Set[DslRelationship]:
|
987
|
+
return self._relationships
|
988
|
+
|
989
|
+
def __enter__(self) -> Self:
|
990
|
+
stack = _current_deployment_node_stack.get()
|
991
|
+
stack.extend([self])
|
992
|
+
self._token = _current_deployment_node_stack.set(stack)
|
993
|
+
return self
|
994
|
+
|
995
|
+
def __exit__(
|
996
|
+
self,
|
997
|
+
exc_type: Optional[Type[BaseException]],
|
998
|
+
exc_value: Optional[BaseException],
|
999
|
+
traceback: Optional[Any]
|
1000
|
+
) -> None:
|
1001
|
+
stack = _current_deployment_node_stack.get()
|
1002
|
+
stack.pop()
|
1003
|
+
_current_deployment_node_stack.reset(self._token)
|
1004
|
+
|
1005
|
+
def add_infrastructure_node(self, node: 'InfrastructureNode') -> None:
|
1006
|
+
self._m.infrastructureNodes.append(node.model)
|
1007
|
+
self._children.append(node)
|
1008
|
+
|
1009
|
+
def add_element_instance(self, instance: Union['SoftwareSystemInstance', 'ContainerInstance']) -> None:
|
1010
|
+
if isinstance(instance, SoftwareSystemInstance):
|
1011
|
+
self._m.softwareSystemInstances.append(instance.model)
|
1012
|
+
elif isinstance(instance, ContainerInstance):
|
1013
|
+
self._m.containerInstances.append(instance.model)
|
1014
|
+
self._children.append(instance)
|
1015
|
+
|
1016
|
+
def add_deployment_node(self, node: 'DeploymentNode') -> None:
|
1017
|
+
self._m.children.append(node.model)
|
1018
|
+
self._children.append(node)
|
1019
|
+
|
1020
|
+
class InfrastructureNode(DslInfrastructureNodeElement, DslElementRelationOverrides[
|
1021
|
+
'InfrastructureNode',
|
1022
|
+
Union[
|
1023
|
+
'DeploymentNode',
|
1024
|
+
'InfrastructureNode',
|
1025
|
+
'SoftwareSystemInstance',
|
1026
|
+
'ContainerInstance',
|
1027
|
+
]
|
1028
|
+
]):
|
1029
|
+
|
1030
|
+
def __init__(self, name: str, description: str="", technology: str="", tags: Set[str]=set(), properties: Dict[str, Any]=dict()) -> None:
|
1031
|
+
self._m = buildzr.models.InfrastructureNode()
|
1032
|
+
self._m.id = GenerateId.for_element()
|
1033
|
+
self._m.name = name
|
1034
|
+
self._m.description = description
|
1035
|
+
self._m.technology = technology
|
1036
|
+
self._m.properties = properties
|
1037
|
+
self._parent: Optional[DeploymentNode] = None
|
1038
|
+
self._tags = {'Element', 'Infrastructure Node'}.union(tags)
|
1039
|
+
self._m.tags = ','.join(self._tags)
|
1040
|
+
|
1041
|
+
self._sources: List[DslElement] = []
|
1042
|
+
self._destinations: List[DslElement] = []
|
1043
|
+
self._relationships: Set[DslRelationship] = set()
|
1044
|
+
|
1045
|
+
stack = _current_deployment_node_stack.get()
|
1046
|
+
if stack:
|
1047
|
+
stack[-1].add_infrastructure_node(self)
|
1048
|
+
|
1049
|
+
deployment_environment = _current_deployment_environment.get()
|
1050
|
+
if deployment_environment is not None:
|
1051
|
+
self._m.environment = deployment_environment.name
|
1052
|
+
|
1053
|
+
@property
|
1054
|
+
def model(self) -> buildzr.models.InfrastructureNode:
|
1055
|
+
return self._m
|
1056
|
+
|
1057
|
+
@property
|
1058
|
+
def tags(self) -> Set[str]:
|
1059
|
+
return self._tags
|
1060
|
+
|
1061
|
+
@property
|
1062
|
+
def parent(self) -> Optional[DeploymentNode]:
|
1063
|
+
return self._parent
|
1064
|
+
|
1065
|
+
@property
|
1066
|
+
def children(self) -> None:
|
1067
|
+
"""
|
1068
|
+
The `InfrastructureNode` element does not have any children, and will always return
|
1069
|
+
`None`.
|
1070
|
+
"""
|
1071
|
+
return None
|
1072
|
+
|
1073
|
+
@property
|
1074
|
+
def sources(self) -> List[DslElement]:
|
1075
|
+
return self._sources
|
1076
|
+
|
1077
|
+
@property
|
1078
|
+
def destinations(self) -> List[DslElement]:
|
1079
|
+
return self._destinations
|
1080
|
+
|
1081
|
+
@property
|
1082
|
+
def relationships(self) -> Set[DslRelationship]:
|
1083
|
+
return self._relationships
|
1084
|
+
|
1085
|
+
class SoftwareSystemInstance(DslElementInstance, DslElementRelationOverrides[
|
1086
|
+
'SoftwareSystemInstance',
|
1087
|
+
'InfrastructureNode',
|
1088
|
+
]):
|
1089
|
+
|
1090
|
+
def __init__(
|
1091
|
+
self,
|
1092
|
+
software_system: 'SoftwareSystem',
|
1093
|
+
deployment_groups: Optional[List['DeploymentGroup']]=None,
|
1094
|
+
tags: Set[str]=set(),
|
1095
|
+
) -> None:
|
1096
|
+
self._m = buildzr.models.SoftwareSystemInstance()
|
1097
|
+
self._m.id = GenerateId.for_element()
|
1098
|
+
self._m.softwareSystemId = software_system.model.id
|
1099
|
+
self._parent: Optional[DeploymentNode] = None
|
1100
|
+
self._element = software_system
|
1101
|
+
self._m.deploymentGroups = [g.name for g in deployment_groups] if deployment_groups else ["Default"]
|
1102
|
+
self._tags = {'Software System Instance'}.union(tags)
|
1103
|
+
self._m.tags = ','.join(self._tags)
|
1104
|
+
|
1105
|
+
self._sources: List[DslElement] = []
|
1106
|
+
self._destinations: List[DslElement] = []
|
1107
|
+
self._relationships: Set[DslRelationship] = set()
|
1108
|
+
|
1109
|
+
stack = _current_deployment_node_stack.get()
|
1110
|
+
if stack:
|
1111
|
+
self._parent = stack[-1]
|
1112
|
+
self._parent.add_element_instance(self)
|
1113
|
+
|
1114
|
+
deployment_environment = _current_deployment_environment.get()
|
1115
|
+
if deployment_environment is not None:
|
1116
|
+
self._m.environment = deployment_environment.name
|
1117
|
+
|
1118
|
+
@property
|
1119
|
+
def model(self) -> buildzr.models.SoftwareSystemInstance:
|
1120
|
+
return self._m
|
1121
|
+
|
1122
|
+
@property
|
1123
|
+
def tags(self) -> Set[str]:
|
1124
|
+
return self._tags
|
1125
|
+
|
1126
|
+
@property
|
1127
|
+
def parent(self) -> Optional[DeploymentNode]:
|
1128
|
+
return self._parent
|
1129
|
+
|
1130
|
+
@property
|
1131
|
+
def children(self) -> None:
|
1132
|
+
"""
|
1133
|
+
The `SoftwareSystemInstance` element does not have any children, and will always return
|
1134
|
+
`None`.
|
1135
|
+
"""
|
1136
|
+
return None
|
1137
|
+
|
1138
|
+
@property
|
1139
|
+
def destinations(self) -> List[DslElement]:
|
1140
|
+
return self._destinations
|
1141
|
+
|
1142
|
+
@property
|
1143
|
+
def sources(self) -> List[DslElement]:
|
1144
|
+
return self._sources
|
1145
|
+
|
1146
|
+
@property
|
1147
|
+
def relationships(self) -> Set[DslRelationship]:
|
1148
|
+
return self._relationships
|
1149
|
+
|
1150
|
+
@property
|
1151
|
+
def element(self) -> DslElement:
|
1152
|
+
return self._element
|
1153
|
+
|
1154
|
+
class ContainerInstance(DslElementInstance, DslElementRelationOverrides[
|
1155
|
+
'ContainerInstance',
|
1156
|
+
'InfrastructureNode',
|
1157
|
+
]):
|
1158
|
+
|
1159
|
+
def __init__(
|
1160
|
+
self,
|
1161
|
+
container: 'Container',
|
1162
|
+
deployment_groups: Optional[List['DeploymentGroup']]=None,
|
1163
|
+
tags: Set[str]=set(),
|
1164
|
+
) -> None:
|
1165
|
+
self._m = buildzr.models.ContainerInstance()
|
1166
|
+
self._m.id = GenerateId.for_element()
|
1167
|
+
self._m.containerId = container.model.id
|
1168
|
+
self._parent: Optional[DeploymentNode] = None
|
1169
|
+
self._element = container
|
1170
|
+
self._m.deploymentGroups = [g.name for g in deployment_groups] if deployment_groups else ["Default"]
|
1171
|
+
self._tags = {'Container Instance'}.union(tags)
|
1172
|
+
self._m.tags = ','.join(self._tags)
|
1173
|
+
|
1174
|
+
self._sources: List[DslElement] = []
|
1175
|
+
self._destinations: List[DslElement] = []
|
1176
|
+
self._relationships: Set[DslRelationship] = set()
|
1177
|
+
|
1178
|
+
stack = _current_deployment_node_stack.get()
|
1179
|
+
if stack:
|
1180
|
+
self._parent = stack[-1]
|
1181
|
+
self._parent.add_element_instance(self)
|
1182
|
+
|
1183
|
+
deployment_environment = _current_deployment_environment.get()
|
1184
|
+
if deployment_environment is not None:
|
1185
|
+
self._m.environment = deployment_environment.name
|
1186
|
+
|
1187
|
+
@property
|
1188
|
+
def model(self) -> buildzr.models.ContainerInstance:
|
1189
|
+
return self._m
|
1190
|
+
|
1191
|
+
@property
|
1192
|
+
def tags(self) -> Set[str]:
|
1193
|
+
return self._tags
|
1194
|
+
|
1195
|
+
@property
|
1196
|
+
def parent(self) -> Optional[DeploymentNode]:
|
1197
|
+
return self._parent
|
1198
|
+
|
1199
|
+
@property
|
1200
|
+
def children(self) -> None:
|
1201
|
+
"""
|
1202
|
+
The `ContainerInstance` element does not have any children, and will always return
|
1203
|
+
`None`.
|
1204
|
+
"""
|
1205
|
+
return None
|
1206
|
+
|
1207
|
+
@property
|
1208
|
+
def sources(self) -> List[DslElement]:
|
1209
|
+
return self._sources
|
1210
|
+
|
1211
|
+
@property
|
1212
|
+
def destinations(self) -> List[DslElement]:
|
1213
|
+
return self._destinations
|
1214
|
+
|
1215
|
+
@property
|
1216
|
+
def relationships(self) -> Set[DslRelationship]:
|
1217
|
+
return self._relationships
|
1218
|
+
|
1219
|
+
@property
|
1220
|
+
def element(self) -> DslElement:
|
1221
|
+
return self._element
|
1222
|
+
|
1223
|
+
class DeploymentGroup:
|
1224
|
+
|
1225
|
+
def __init__(self, name: str) -> None:
|
1226
|
+
self._name = name
|
1227
|
+
|
1228
|
+
@property
|
1229
|
+
def name(self) -> str:
|
1230
|
+
return self._name
|
1231
|
+
|
711
1232
|
def _auto_layout_to_model(auto_layout: _AutoLayout) -> buildzr.models.AutomaticLayout:
|
712
1233
|
"""
|
713
1234
|
See: https://docs.structurizr.com/dsl/language#autolayout
|
@@ -767,7 +1288,7 @@ def _auto_layout_to_model(auto_layout: _AutoLayout) -> buildzr.models.AutomaticL
|
|
767
1288
|
|
768
1289
|
class SystemLandscapeView(DslViewElement):
|
769
1290
|
|
770
|
-
from buildzr.dsl.expression import Expression,
|
1291
|
+
from buildzr.dsl.expression import Expression, WorkspaceExpression, ElementExpression, RelationshipExpression
|
771
1292
|
|
772
1293
|
@property
|
773
1294
|
def model(self) -> buildzr.models.SystemLandscapeView:
|
@@ -779,10 +1300,10 @@ class SystemLandscapeView(DslViewElement):
|
|
779
1300
|
description: str,
|
780
1301
|
auto_layout: _AutoLayout='tb',
|
781
1302
|
title: Optional[str]=None,
|
782
|
-
include_elements: List[Union[DslElement, Callable[[
|
783
|
-
exclude_elements: List[Union[DslElement, Callable[[
|
784
|
-
include_relationships: List[Union[DslElement, Callable[[
|
785
|
-
exclude_relationships: List[Union[DslElement, Callable[[
|
1303
|
+
include_elements: List[Union[DslElement, Callable[[WorkspaceExpression, ElementExpression], bool]]]=[],
|
1304
|
+
exclude_elements: List[Union[DslElement, Callable[[WorkspaceExpression, ElementExpression], bool]]]=[],
|
1305
|
+
include_relationships: List[Union[DslElement, Callable[[WorkspaceExpression, RelationshipExpression], bool]]]=[],
|
1306
|
+
exclude_relationships: List[Union[DslElement, Callable[[WorkspaceExpression, RelationshipExpression], bool]]]=[],
|
786
1307
|
properties: Optional[Dict[str, str]]=None,
|
787
1308
|
) -> None:
|
788
1309
|
self._m = buildzr.models.SystemLandscapeView()
|
@@ -805,7 +1326,7 @@ class SystemLandscapeView(DslViewElement):
|
|
805
1326
|
|
806
1327
|
def _on_added(self, workspace: Workspace) -> None:
|
807
1328
|
|
808
|
-
from buildzr.dsl.expression import Expression,
|
1329
|
+
from buildzr.dsl.expression import Expression, WorkspaceExpression, ElementExpression, RelationshipExpression
|
809
1330
|
from buildzr.models import ElementView, RelationshipView
|
810
1331
|
|
811
1332
|
expression = Expression(
|
@@ -815,17 +1336,17 @@ class SystemLandscapeView(DslViewElement):
|
|
815
1336
|
exclude_relationships=self._exclude_relationships,
|
816
1337
|
)
|
817
1338
|
|
818
|
-
include_view_elements_filter: List[Union[DslElement, Callable[[
|
1339
|
+
include_view_elements_filter: List[Union[DslElement, Callable[[WorkspaceExpression, ElementExpression], bool]]] = [
|
819
1340
|
lambda w, e: e.type == Person,
|
820
1341
|
lambda w, e: e.type == SoftwareSystem
|
821
1342
|
]
|
822
1343
|
|
823
|
-
exclude_view_elements_filter: List[Union[DslElement, Callable[[
|
1344
|
+
exclude_view_elements_filter: List[Union[DslElement, Callable[[WorkspaceExpression, ElementExpression], bool]]] = [
|
824
1345
|
lambda w, e: e.type == Container,
|
825
1346
|
lambda w, e: e.type == Component,
|
826
1347
|
]
|
827
1348
|
|
828
|
-
include_view_relationships_filter: List[Union[DslElement, Callable[[
|
1349
|
+
include_view_relationships_filter: List[Union[DslElement, Callable[[WorkspaceExpression, RelationshipExpression], bool]]] = [
|
829
1350
|
lambda w, r: r.source.type == Person,
|
830
1351
|
lambda w, r: r.source.type == SoftwareSystem,
|
831
1352
|
lambda w, r: r.destination.type == Person,
|
@@ -864,7 +1385,7 @@ class SystemContextView(DslViewElement):
|
|
864
1385
|
relationship with the selected `SoftwareSystem`.
|
865
1386
|
"""
|
866
1387
|
|
867
|
-
from buildzr.dsl.expression import Expression,
|
1388
|
+
from buildzr.dsl.expression import Expression, WorkspaceExpression, ElementExpression, RelationshipExpression
|
868
1389
|
|
869
1390
|
@property
|
870
1391
|
def model(self) -> buildzr.models.SystemContextView:
|
@@ -872,15 +1393,15 @@ class SystemContextView(DslViewElement):
|
|
872
1393
|
|
873
1394
|
def __init__(
|
874
1395
|
self,
|
875
|
-
software_system_selector: Union[SoftwareSystem, Callable[[
|
1396
|
+
software_system_selector: Union[SoftwareSystem, Callable[[WorkspaceExpression], SoftwareSystem]],
|
876
1397
|
key: str,
|
877
1398
|
description: str,
|
878
1399
|
auto_layout: _AutoLayout='tb',
|
879
1400
|
title: Optional[str]=None,
|
880
|
-
include_elements: List[Union[DslElement, Callable[[
|
881
|
-
exclude_elements: List[Union[DslElement, Callable[[
|
882
|
-
include_relationships: List[Union[DslElement, Callable[[
|
883
|
-
exclude_relationships: List[Union[DslElement, Callable[[
|
1401
|
+
include_elements: List[Union[DslElement, Callable[[WorkspaceExpression, ElementExpression], bool]]]=[],
|
1402
|
+
exclude_elements: List[Union[DslElement, Callable[[WorkspaceExpression, ElementExpression], bool]]]=[],
|
1403
|
+
include_relationships: List[Union[DslElement, Callable[[WorkspaceExpression, RelationshipExpression], bool]]]=[],
|
1404
|
+
exclude_relationships: List[Union[DslElement, Callable[[WorkspaceExpression, RelationshipExpression], bool]]]=[],
|
884
1405
|
properties: Optional[Dict[str, str]]=None,
|
885
1406
|
) -> None:
|
886
1407
|
self._m = buildzr.models.SystemContextView()
|
@@ -904,21 +1425,21 @@ class SystemContextView(DslViewElement):
|
|
904
1425
|
|
905
1426
|
def _on_added(self, workspace: Workspace) -> None:
|
906
1427
|
|
907
|
-
from buildzr.dsl.expression import Expression,
|
1428
|
+
from buildzr.dsl.expression import Expression, WorkspaceExpression, ElementExpression, RelationshipExpression
|
908
1429
|
from buildzr.models import ElementView, RelationshipView
|
909
1430
|
|
910
1431
|
if isinstance(self._selector, SoftwareSystem):
|
911
1432
|
software_system = self._selector
|
912
1433
|
else:
|
913
|
-
software_system = self._selector(workspace)
|
1434
|
+
software_system = self._selector(WorkspaceExpression(workspace))
|
914
1435
|
self._m.softwareSystemId = software_system.model.id
|
915
|
-
view_elements_filter: List[Union[DslElement, Callable[[
|
1436
|
+
view_elements_filter: List[Union[DslElement, Callable[[WorkspaceExpression, ElementExpression], bool]]] = [
|
916
1437
|
lambda w, e: e == software_system,
|
917
1438
|
lambda w, e: software_system.model.id in e.sources.ids,
|
918
1439
|
lambda w, e: software_system.model.id in e.destinations.ids,
|
919
1440
|
]
|
920
1441
|
|
921
|
-
view_relationships_filter: List[Union[DslElement, Callable[[
|
1442
|
+
view_relationships_filter: List[Union[DslElement, Callable[[WorkspaceExpression, RelationshipExpression], bool]]] = [
|
922
1443
|
lambda w, r: software_system == r.source,
|
923
1444
|
lambda w, r: software_system == r.destination,
|
924
1445
|
]
|
@@ -950,7 +1471,7 @@ class SystemContextView(DslViewElement):
|
|
950
1471
|
|
951
1472
|
class ContainerView(DslViewElement):
|
952
1473
|
|
953
|
-
from buildzr.dsl.expression import Expression,
|
1474
|
+
from buildzr.dsl.expression import Expression, WorkspaceExpression, ElementExpression, RelationshipExpression
|
954
1475
|
|
955
1476
|
@property
|
956
1477
|
def model(self) -> buildzr.models.ContainerView:
|
@@ -958,15 +1479,15 @@ class ContainerView(DslViewElement):
|
|
958
1479
|
|
959
1480
|
def __init__(
|
960
1481
|
self,
|
961
|
-
software_system_selector: Union[SoftwareSystem, Callable[[
|
1482
|
+
software_system_selector: Union[SoftwareSystem, Callable[[WorkspaceExpression], SoftwareSystem]],
|
962
1483
|
key: str,
|
963
1484
|
description: str,
|
964
1485
|
auto_layout: _AutoLayout='tb',
|
965
1486
|
title: Optional[str]=None,
|
966
|
-
include_elements: List[Union[DslElement, Callable[[
|
967
|
-
exclude_elements: List[Union[DslElement, Callable[[
|
968
|
-
include_relationships: List[Union[DslElement, Callable[[
|
969
|
-
exclude_relationships: List[Union[DslElement, Callable[[
|
1487
|
+
include_elements: List[Union[DslElement, Callable[[WorkspaceExpression, ElementExpression], bool]]]=[],
|
1488
|
+
exclude_elements: List[Union[DslElement, Callable[[WorkspaceExpression, ElementExpression], bool]]]=[],
|
1489
|
+
include_relationships: List[Union[DslElement, Callable[[WorkspaceExpression, RelationshipExpression], bool]]]=[],
|
1490
|
+
exclude_relationships: List[Union[DslElement, Callable[[WorkspaceExpression, RelationshipExpression], bool]]]=[],
|
970
1491
|
properties: Optional[Dict[str, str]]=None,
|
971
1492
|
) -> None:
|
972
1493
|
self._m = buildzr.models.ContainerView()
|
@@ -990,24 +1511,24 @@ class ContainerView(DslViewElement):
|
|
990
1511
|
|
991
1512
|
def _on_added(self, workspace: Workspace) -> None:
|
992
1513
|
|
993
|
-
from buildzr.dsl.expression import Expression,
|
1514
|
+
from buildzr.dsl.expression import Expression, WorkspaceExpression, ElementExpression, RelationshipExpression
|
994
1515
|
from buildzr.models import ElementView, RelationshipView
|
995
1516
|
|
996
1517
|
if isinstance(self._selector, SoftwareSystem):
|
997
1518
|
software_system = self._selector
|
998
1519
|
else:
|
999
|
-
software_system = self._selector(workspace)
|
1520
|
+
software_system = self._selector(WorkspaceExpression(workspace))
|
1000
1521
|
self._m.softwareSystemId = software_system.model.id
|
1001
1522
|
|
1002
1523
|
container_ids = { container.model.id for container in software_system.children}
|
1003
1524
|
|
1004
|
-
view_elements_filter: List[Union[DslElement, Callable[[
|
1525
|
+
view_elements_filter: List[Union[DslElement, Callable[[WorkspaceExpression, ElementExpression], bool]]] = [
|
1005
1526
|
lambda w, e: e.parent == software_system,
|
1006
1527
|
lambda w, e: any(container_ids.intersection({ id for id in e.sources.ids })),
|
1007
1528
|
lambda w, e: any(container_ids.intersection({ id for id in e.destinations.ids })),
|
1008
1529
|
]
|
1009
1530
|
|
1010
|
-
view_relationships_filter: List[Union[DslElement, Callable[[
|
1531
|
+
view_relationships_filter: List[Union[DslElement, Callable[[WorkspaceExpression, RelationshipExpression], bool]]] = [
|
1011
1532
|
lambda w, r: software_system == r.source.parent,
|
1012
1533
|
lambda w, r: software_system == r.destination.parent,
|
1013
1534
|
]
|
@@ -1039,7 +1560,7 @@ class ContainerView(DslViewElement):
|
|
1039
1560
|
|
1040
1561
|
class ComponentView(DslViewElement):
|
1041
1562
|
|
1042
|
-
from buildzr.dsl.expression import Expression,
|
1563
|
+
from buildzr.dsl.expression import Expression, WorkspaceExpression, ElementExpression, RelationshipExpression
|
1043
1564
|
|
1044
1565
|
@property
|
1045
1566
|
def model(self) -> buildzr.models.ComponentView:
|
@@ -1047,15 +1568,15 @@ class ComponentView(DslViewElement):
|
|
1047
1568
|
|
1048
1569
|
def __init__(
|
1049
1570
|
self,
|
1050
|
-
container_selector: Union[Container, Callable[[
|
1571
|
+
container_selector: Union[Container, Callable[[WorkspaceExpression], Container]],
|
1051
1572
|
key: str,
|
1052
1573
|
description: str,
|
1053
1574
|
auto_layout: _AutoLayout='tb',
|
1054
1575
|
title: Optional[str]=None,
|
1055
|
-
include_elements: List[Union[DslElement, Callable[[
|
1056
|
-
exclude_elements: List[Union[DslElement, Callable[[
|
1057
|
-
include_relationships: List[Union[DslElement, Callable[[
|
1058
|
-
exclude_relationships: List[Union[DslElement, Callable[[
|
1576
|
+
include_elements: List[Union[DslElement, Callable[[WorkspaceExpression, ElementExpression], bool]]]=[],
|
1577
|
+
exclude_elements: List[Union[DslElement, Callable[[WorkspaceExpression, ElementExpression], bool]]]=[],
|
1578
|
+
include_relationships: List[Union[DslElement, Callable[[WorkspaceExpression, RelationshipExpression], bool]]]=[],
|
1579
|
+
exclude_relationships: List[Union[DslElement, Callable[[WorkspaceExpression, RelationshipExpression], bool]]]=[],
|
1059
1580
|
properties: Optional[Dict[str, str]]=None,
|
1060
1581
|
) -> None:
|
1061
1582
|
self._m = buildzr.models.ComponentView()
|
@@ -1079,24 +1600,24 @@ class ComponentView(DslViewElement):
|
|
1079
1600
|
|
1080
1601
|
def _on_added(self, workspace: Workspace) -> None:
|
1081
1602
|
|
1082
|
-
from buildzr.dsl.expression import Expression,
|
1603
|
+
from buildzr.dsl.expression import Expression, WorkspaceExpression, ElementExpression, RelationshipExpression
|
1083
1604
|
from buildzr.models import ElementView, RelationshipView
|
1084
1605
|
|
1085
1606
|
if isinstance(self._selector, Container):
|
1086
1607
|
container = self._selector
|
1087
1608
|
else:
|
1088
|
-
container = self._selector(workspace)
|
1609
|
+
container = self._selector(WorkspaceExpression(workspace))
|
1089
1610
|
self._m.containerId = container.model.id
|
1090
1611
|
|
1091
1612
|
component_ids = { component.model.id for component in container.children }
|
1092
1613
|
|
1093
|
-
view_elements_filter: List[Union[DslElement, Callable[[
|
1614
|
+
view_elements_filter: List[Union[DslElement, Callable[[WorkspaceExpression, ElementExpression], bool]]] = [
|
1094
1615
|
lambda w, e: e.parent == container,
|
1095
1616
|
lambda w, e: any(component_ids.intersection({ id for id in e.sources.ids })),
|
1096
1617
|
lambda w, e: any(component_ids.intersection({ id for id in e.destinations.ids })),
|
1097
1618
|
]
|
1098
1619
|
|
1099
|
-
view_relationships_filter: List[Union[DslElement, Callable[[
|
1620
|
+
view_relationships_filter: List[Union[DslElement, Callable[[WorkspaceExpression, RelationshipExpression], bool]]] = [
|
1100
1621
|
lambda w, r: container == r.source.parent,
|
1101
1622
|
lambda w, r: container == r.destination.parent,
|
1102
1623
|
]
|
@@ -1126,9 +1647,251 @@ class ComponentView(DslViewElement):
|
|
1126
1647
|
for relationship_id in relationship_ids:
|
1127
1648
|
self._m.relationships.append(RelationshipView(id=relationship_id))
|
1128
1649
|
|
1650
|
+
class DeploymentView(DslViewElement):
|
1651
|
+
|
1652
|
+
from buildzr.dsl.expression import Expression, WorkspaceExpression, ElementExpression, RelationshipExpression
|
1653
|
+
|
1654
|
+
@property
|
1655
|
+
def model(self) -> buildzr.models.DeploymentView:
|
1656
|
+
return self._m
|
1657
|
+
|
1658
|
+
def __init__(
|
1659
|
+
self,
|
1660
|
+
environment: DeploymentEnvironment,
|
1661
|
+
key: str,
|
1662
|
+
software_system_selector: Optional[Union[SoftwareSystem, Callable[[WorkspaceExpression], SoftwareSystem]]]=None,
|
1663
|
+
description: str="",
|
1664
|
+
auto_layout: _AutoLayout='tb',
|
1665
|
+
title: Optional[str]=None,
|
1666
|
+
include_elements: List[Union[DslElement, Callable[[WorkspaceExpression, ElementExpression], bool]]]=[],
|
1667
|
+
exclude_elements: List[Union[DslElement, Callable[[WorkspaceExpression, ElementExpression], bool]]]=[],
|
1668
|
+
include_relationships: List[Union[DslElement, Callable[[WorkspaceExpression, RelationshipExpression], bool]]]=[],
|
1669
|
+
exclude_relationships: List[Union[DslElement, Callable[[WorkspaceExpression, RelationshipExpression], bool]]]=[],
|
1670
|
+
properties: Optional[Dict[str, str]]=None,
|
1671
|
+
) -> None:
|
1672
|
+
self._m = buildzr.models.DeploymentView()
|
1673
|
+
|
1674
|
+
self._selector = software_system_selector
|
1675
|
+
self._environment = environment
|
1676
|
+
|
1677
|
+
self._m.key = key
|
1678
|
+
self._m.description = description
|
1679
|
+
self._m.environment = environment.name
|
1680
|
+
|
1681
|
+
self._m.automaticLayout = _auto_layout_to_model(auto_layout)
|
1682
|
+
self._m.title = title
|
1683
|
+
self._m.properties = properties
|
1684
|
+
|
1685
|
+
self._include_elements = include_elements
|
1686
|
+
self._exclude_elements = exclude_elements
|
1687
|
+
self._include_relationships = include_relationships
|
1688
|
+
self._exclude_relationships = exclude_relationships
|
1689
|
+
|
1690
|
+
workspace = _current_workspace.get()
|
1691
|
+
if workspace is not None:
|
1692
|
+
workspace.apply_view(self)
|
1693
|
+
|
1694
|
+
def _on_added(self, workspace: Workspace) -> None:
|
1695
|
+
|
1696
|
+
from buildzr.dsl.expression import Expression, WorkspaceExpression, ElementExpression, RelationshipExpression
|
1697
|
+
from buildzr.dsl.explorer import Explorer
|
1698
|
+
from buildzr.models import ElementView, RelationshipView
|
1699
|
+
|
1700
|
+
software_system: Optional[SoftwareSystem] = None
|
1701
|
+
if self._selector is not None:
|
1702
|
+
if isinstance(self._selector, SoftwareSystem):
|
1703
|
+
software_system = self._selector
|
1704
|
+
self._m.softwareSystemId = software_system.model.id
|
1705
|
+
else:
|
1706
|
+
software_system = self._selector(WorkspaceExpression(workspace))
|
1707
|
+
self._m.softwareSystemId = software_system.model.id
|
1708
|
+
|
1709
|
+
view_elements_filter: List[Union[DslElement, Callable[[WorkspaceExpression, ElementExpression], bool]]] = []
|
1710
|
+
view_elements_filter_excludes: List[Union[DslElement, Callable[[WorkspaceExpression, ElementExpression], bool]]] = []
|
1711
|
+
view_relationships_filter_env: List[Union[DslElement, Callable[[WorkspaceExpression, RelationshipExpression], bool]]] = []
|
1712
|
+
view_relationships_filter_implied_instance_relationships: List[Union[DslElement, Callable[[WorkspaceExpression, RelationshipExpression], bool]]] = []
|
1713
|
+
|
1714
|
+
def is_software_system_contains_container(
|
1715
|
+
software_system_id: str,
|
1716
|
+
container_id: str,
|
1717
|
+
) -> bool:
|
1718
|
+
for software_system in workspace.model.model.softwareSystems:
|
1719
|
+
if software_system.id == software_system_id:
|
1720
|
+
for container in software_system.containers:
|
1721
|
+
if container.id == container_id:
|
1722
|
+
return True
|
1723
|
+
return False
|
1724
|
+
|
1725
|
+
def recursive_includes(
|
1726
|
+
deployment_node_ancestor_ids: List[str],
|
1727
|
+
deployment_node: buildzr.models.DeploymentNode,
|
1728
|
+
upstream_software_system_ids: Set[str],
|
1729
|
+
environment: str,
|
1730
|
+
include_ids: Set[str],
|
1731
|
+
selected_software_system: Optional[buildzr.models.SoftwareSystem] = None,
|
1732
|
+
) -> None:
|
1733
|
+
|
1734
|
+
"""
|
1735
|
+
Recursively includes the relevant deployment nodes, software system
|
1736
|
+
instances, container instances, and infrastructure nodes based on
|
1737
|
+
the provided environment and DeploymentView parameters.
|
1738
|
+
|
1739
|
+
@param deployment_node_ancestor_ids: List of ancestor deployment
|
1740
|
+
node IDs. Useful for tracing back the upstream deployment nodes that
|
1741
|
+
should be included in the view. For example, we may have deployment nodes
|
1742
|
+
`a` -> `b` -> `c`, and we want to include all of them if `c` is included,
|
1743
|
+
even if `b` has no software system instances, container instances,
|
1744
|
+
or infrastructure nodes.
|
1745
|
+
|
1746
|
+
@param upstream_software_system_ids: Set of software system IDs that
|
1747
|
+
whose instance exists in the upstream deployment nodes.
|
1748
|
+
"""
|
1749
|
+
|
1750
|
+
instance_ids: Set[str] = set()
|
1751
|
+
for child in deployment_node.children:
|
1752
|
+
if child.environment == environment:
|
1753
|
+
recursive_includes(
|
1754
|
+
deployment_node_ancestor_ids + [deployment_node.id],
|
1755
|
+
child,
|
1756
|
+
upstream_software_system_ids.union({
|
1757
|
+
software_system_instance.softwareSystemId
|
1758
|
+
for software_system_instance in deployment_node.softwareSystemInstances
|
1759
|
+
}),
|
1760
|
+
environment,
|
1761
|
+
include_ids,
|
1762
|
+
selected_software_system
|
1763
|
+
)
|
1764
|
+
|
1765
|
+
if selected_software_system is None:
|
1766
|
+
software_instance_ids = {
|
1767
|
+
instance.id for instance in deployment_node.softwareSystemInstances
|
1768
|
+
if instance.environment == environment
|
1769
|
+
}
|
1770
|
+
|
1771
|
+
sibling_software_system_ids = {
|
1772
|
+
instance.softwareSystemId for instance in deployment_node.softwareSystemInstances
|
1773
|
+
if instance.environment == environment
|
1774
|
+
}
|
1775
|
+
|
1776
|
+
container_instance_ids = {
|
1777
|
+
instance.id for instance in deployment_node.containerInstances
|
1778
|
+
if instance.environment == environment and \
|
1779
|
+
not any({
|
1780
|
+
is_software_system_contains_container(
|
1781
|
+
software_system_id,
|
1782
|
+
instance.containerId
|
1783
|
+
) for software_system_id in upstream_software_system_ids.union(sibling_software_system_ids)
|
1784
|
+
})
|
1785
|
+
}
|
1786
|
+
|
1787
|
+
instance_ids.update(software_instance_ids)
|
1788
|
+
instance_ids.update(container_instance_ids)
|
1789
|
+
|
1790
|
+
else:
|
1791
|
+
container_instance_ids = {
|
1792
|
+
instance.id for instance in deployment_node.containerInstances
|
1793
|
+
if instance.environment == environment and \
|
1794
|
+
is_software_system_contains_container(
|
1795
|
+
selected_software_system.id,
|
1796
|
+
instance.containerId
|
1797
|
+
)
|
1798
|
+
}
|
1799
|
+
|
1800
|
+
instance_ids.update(container_instance_ids)
|
1801
|
+
|
1802
|
+
software_instance_relation_ids: Set[str] = set()
|
1803
|
+
for software_system_instance in deployment_node.softwareSystemInstances:
|
1804
|
+
if software_system_instance.relationships and software_system_instance.environment == environment:
|
1805
|
+
for relationship in software_system_instance.relationships:
|
1806
|
+
software_instance_relation_ids.add(relationship.id)
|
1807
|
+
|
1808
|
+
container_instance_relation_ids: Set[str] = set()
|
1809
|
+
if selected_software_system is not None:
|
1810
|
+
# Note: These relations are created in the `__exit__` of each
|
1811
|
+
# `DeploymentEnvironment` -- the relationships are being implied
|
1812
|
+
# from the respective `SoftwareSystem`s and `Container`s.
|
1813
|
+
for container_instance in deployment_node.containerInstances:
|
1814
|
+
if container_instance.relationships and container_instance.environment == environment:
|
1815
|
+
for relationship in container_instance.relationships:
|
1816
|
+
container_instance_relation_ids.add(relationship.id)
|
1817
|
+
|
1818
|
+
infrastructure_node_relation_ids: Set[str] = set()
|
1819
|
+
for infrastructure_node in deployment_node.infrastructureNodes:
|
1820
|
+
if infrastructure_node.relationships and infrastructure_node.environment == environment:
|
1821
|
+
for relationship in infrastructure_node.relationships:
|
1822
|
+
infrastructure_node_relation_ids.add(relationship.id)
|
1823
|
+
|
1824
|
+
infrastructure_node_ids = {
|
1825
|
+
infrastructure_node.id for infrastructure_node in deployment_node.infrastructureNodes
|
1826
|
+
if infrastructure_node.environment == environment
|
1827
|
+
}
|
1828
|
+
|
1829
|
+
instance_ids.update(software_instance_relation_ids)
|
1830
|
+
instance_ids.update(container_instance_relation_ids)
|
1831
|
+
instance_ids.update(infrastructure_node_relation_ids)
|
1832
|
+
instance_ids.update(infrastructure_node_ids)
|
1833
|
+
|
1834
|
+
# Only include this deployment node
|
1835
|
+
# if there's anything to include at all.
|
1836
|
+
if len(instance_ids) > 0:
|
1837
|
+
for deployment_node_ancestor_id in deployment_node_ancestor_ids:
|
1838
|
+
include_ids.add(deployment_node_ancestor_id)
|
1839
|
+
include_ids.add(deployment_node.id)
|
1840
|
+
include_ids.update(instance_ids)
|
1841
|
+
|
1842
|
+
include_ids: Set[str] = set()
|
1843
|
+
upstream_software_system_ids: Set[str] = set()
|
1844
|
+
|
1845
|
+
for root_deployment_node in workspace.model.model.deploymentNodes:
|
1846
|
+
if root_deployment_node.environment == self._environment.name:
|
1847
|
+
recursive_includes(
|
1848
|
+
[],
|
1849
|
+
root_deployment_node,
|
1850
|
+
upstream_software_system_ids,
|
1851
|
+
self._environment.name,
|
1852
|
+
include_ids,
|
1853
|
+
software_system.model if software_system else None
|
1854
|
+
)
|
1855
|
+
|
1856
|
+
view_elements_filter = [
|
1857
|
+
lambda w, e: (
|
1858
|
+
e.id in include_ids
|
1859
|
+
),
|
1860
|
+
]
|
1861
|
+
|
1862
|
+
view_relationships_filter_env = [
|
1863
|
+
lambda w, r: r.source.environment == self._environment.name,
|
1864
|
+
lambda w, r: r.destination.environment == self._environment.name,
|
1865
|
+
]
|
1866
|
+
|
1867
|
+
view_relationships_filter_implied_instance_relationships = [
|
1868
|
+
lambda w, r: r.id in include_ids,
|
1869
|
+
]
|
1870
|
+
|
1871
|
+
expression = Expression(
|
1872
|
+
include_elements=self._include_elements + view_elements_filter,
|
1873
|
+
exclude_elements=self._exclude_elements,
|
1874
|
+
include_relationships=self._include_relationships +\
|
1875
|
+
view_relationships_filter_env +\
|
1876
|
+
view_relationships_filter_implied_instance_relationships,
|
1877
|
+
exclude_relationships=self._exclude_relationships,
|
1878
|
+
)
|
1879
|
+
|
1880
|
+
element_ids = [str(element.model.id) for element in expression.elements(workspace)]
|
1881
|
+
relationship_ids = [str(relationship.model.id) for relationship in expression.relationships(workspace)]
|
1882
|
+
|
1883
|
+
self._m.elements = []
|
1884
|
+
for element_id in element_ids:
|
1885
|
+
self._m.elements.append(ElementView(id=element_id))
|
1886
|
+
|
1887
|
+
self._m.relationships = []
|
1888
|
+
for relationship_id in relationship_ids:
|
1889
|
+
self._m.relationships.append(RelationshipView(id=relationship_id))
|
1890
|
+
|
1891
|
+
|
1129
1892
|
class StyleElements:
|
1130
1893
|
|
1131
|
-
from buildzr.dsl.expression import
|
1894
|
+
from buildzr.dsl.expression import WorkspaceExpression, ElementExpression
|
1132
1895
|
|
1133
1896
|
Shapes = Union[
|
1134
1897
|
Literal['Box'],
|
@@ -1161,7 +1924,7 @@ class StyleElements:
|
|
1161
1924
|
on: List[Union[
|
1162
1925
|
DslElement,
|
1163
1926
|
Group,
|
1164
|
-
Callable[[
|
1927
|
+
Callable[[WorkspaceExpression, ElementExpression], bool],
|
1165
1928
|
Type[Union['Person', 'SoftwareSystem', 'Container', 'Component']],
|
1166
1929
|
str
|
1167
1930
|
]],
|
@@ -1204,7 +1967,7 @@ class StyleElements:
|
|
1204
1967
|
# item, not for each of `StyleElements` instance. This makes the styling
|
1205
1968
|
# makes more concise and flexible.
|
1206
1969
|
|
1207
|
-
from buildzr.dsl.expression import
|
1970
|
+
from buildzr.dsl.expression import ElementExpression
|
1208
1971
|
from uuid import uuid4
|
1209
1972
|
|
1210
1973
|
if background:
|
@@ -1277,7 +2040,7 @@ class StyleElements:
|
|
1277
2040
|
elif isinstance(element, str):
|
1278
2041
|
element_style.tag = element
|
1279
2042
|
elif callable(element):
|
1280
|
-
from buildzr.dsl.expression import
|
2043
|
+
from buildzr.dsl.expression import ElementExpression, Expression
|
1281
2044
|
if self._parent:
|
1282
2045
|
matched_elems = Expression(include_elements=[element]).elements(self._parent)
|
1283
2046
|
for e in matched_elems:
|
@@ -1293,7 +2056,7 @@ class StyleElements:
|
|
1293
2056
|
|
1294
2057
|
class StyleRelationships:
|
1295
2058
|
|
1296
|
-
from buildzr.dsl.expression import
|
2059
|
+
from buildzr.dsl.expression import WorkspaceExpression, RelationshipExpression
|
1297
2060
|
|
1298
2061
|
@property
|
1299
2062
|
def model(self) -> List[buildzr.models.RelationshipStyle]:
|
@@ -1308,7 +2071,7 @@ class StyleRelationships:
|
|
1308
2071
|
on: Optional[List[Union[
|
1309
2072
|
DslRelationship,
|
1310
2073
|
Group,
|
1311
|
-
Callable[[
|
2074
|
+
Callable[[WorkspaceExpression, RelationshipExpression], bool],
|
1312
2075
|
str
|
1313
2076
|
]]]=None,
|
1314
2077
|
thickness: Optional[int]=None,
|