buildzr 0.0.17__tar.gz → 0.0.19__tar.gz
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-0.0.17 → buildzr-0.0.19}/PKG-INFO +1 -1
- buildzr-0.0.19/buildzr/__about__.py +1 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/buildzr/dsl/dsl.py +60 -3
- {buildzr-0.0.17 → buildzr-0.0.19}/tests/test_dsl.py +275 -1
- {buildzr-0.0.17 → buildzr-0.0.19}/tests/test_explorer.py +2 -2
- buildzr-0.0.17/buildzr/__about__.py +0 -1
- {buildzr-0.0.17 → buildzr-0.0.19}/.gitignore +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/CONTRIBUTING.md +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/LICENSE.md +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/README.md +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/buildzr/__init__.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/buildzr/dsl/__init__.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/buildzr/dsl/color.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/buildzr/dsl/explorer.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/buildzr/dsl/expression.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/buildzr/dsl/factory/__init__.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/buildzr/dsl/factory/gen_id.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/buildzr/dsl/interfaces/__init__.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/buildzr/dsl/interfaces/interfaces.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/buildzr/dsl/relations.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/buildzr/encoders/__init__.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/buildzr/encoders/encoder.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/buildzr/models/__init__.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/buildzr/models/generate.sh +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/buildzr/models/models.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/buildzr/sinks/__init__.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/buildzr/sinks/interfaces.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/buildzr/sinks/json_sink.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/pyproject.toml +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/tests/__init__.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/tests/abstract_builder.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/tests/samples/__init__.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/tests/samples/component_view.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/tests/samples/container_view.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/tests/samples/container_view_sugar.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/tests/samples/groups.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/tests/samples/implied_relationships.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/tests/samples/nested_groups.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/tests/samples/simple.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/tests/samples/simple_dsl.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/tests/samples/system_context_view.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/tests/samples/system_landscape_view.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/tests/test_expression.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/tests/test_typehints.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/tests/test_views.py +0 -0
- {buildzr-0.0.17 → buildzr-0.0.19}/tests/test_workspaces.py +0 -0
@@ -0,0 +1 @@
|
|
1
|
+
VERSION = "0.0.19"
|
@@ -129,16 +129,19 @@ class Workspace(DslWorkspaceElement):
|
|
129
129
|
|
130
130
|
_current_workspace.reset(self._token)
|
131
131
|
|
132
|
-
def _imply_relationships(
|
133
|
-
self,
|
132
|
+
def _imply_relationships( self,
|
134
133
|
) -> None:
|
135
134
|
|
136
135
|
"""
|
137
136
|
Process implied relationships:
|
138
137
|
If we have relationship s >> do >> a.b, then create s >> do >> a.
|
139
138
|
If we have relationship s.ss >> do >> a.b.c, then create s.ss >> do >> a.b and s.ss >> do >> a.
|
139
|
+
If we have relationship s.ss >> do >> a, then create s >> do >> a.
|
140
140
|
And so on...
|
141
141
|
|
142
|
+
Relationships of `SoftwareSystemInstance`s and `ContainerInstance`s are
|
143
|
+
skipped.
|
144
|
+
|
142
145
|
This process is idempotent, which means this can be called multiple times
|
143
146
|
without duplicating similar relationships.
|
144
147
|
"""
|
@@ -149,12 +152,22 @@ class Workspace(DslWorkspaceElement):
|
|
149
152
|
from buildzr.dsl.explorer import Explorer
|
150
153
|
|
151
154
|
explorer = Explorer(self)
|
155
|
+
# Take a snapshot of relationships to avoid processing newly created ones
|
152
156
|
relationships = list(explorer.walk_relationships())
|
153
157
|
for relationship in relationships:
|
154
158
|
source = relationship.source
|
155
159
|
destination = relationship.destination
|
156
160
|
destination_parent = destination.parent
|
157
161
|
|
162
|
+
if isinstance(source, (SoftwareSystemInstance, ContainerInstance)) or \
|
163
|
+
isinstance(destination, (SoftwareSystemInstance, ContainerInstance)):
|
164
|
+
continue
|
165
|
+
|
166
|
+
# Skip relationships that are already implied (have linkedRelationshipId)
|
167
|
+
if relationship.model.linkedRelationshipId is not None:
|
168
|
+
continue
|
169
|
+
|
170
|
+
# Handle case: s >> a.b => s >> a (destination is child)
|
158
171
|
while destination_parent is not None and \
|
159
172
|
isinstance(source, DslElement) and \
|
160
173
|
not isinstance(source.model, buildzr.models.Workspace) and \
|
@@ -179,7 +192,38 @@ class Workspace(DslWorkspaceElement):
|
|
179
192
|
technology=relationship.model.technology,
|
180
193
|
)
|
181
194
|
r.model.linkedRelationshipId = relationship.model.id
|
182
|
-
|
195
|
+
destination_parent = destination_parent.parent
|
196
|
+
|
197
|
+
# Handle inverse case: s.ss >> a => s >> a (source is child)
|
198
|
+
source_parent = source.parent
|
199
|
+
while source_parent is not None and \
|
200
|
+
isinstance(destination, DslElement) and \
|
201
|
+
not isinstance(destination.model, buildzr.models.Workspace) and \
|
202
|
+
not isinstance(source_parent.model, buildzr.models.Workspace) and \
|
203
|
+
not isinstance(source_parent, DslWorkspaceElement):
|
204
|
+
|
205
|
+
if source_parent is destination.parent:
|
206
|
+
break
|
207
|
+
|
208
|
+
rels = source_parent.model.relationships
|
209
|
+
|
210
|
+
# The parent source relationship might be empty
|
211
|
+
# (i.e., []).
|
212
|
+
if rels is not None:
|
213
|
+
already_exists = any(
|
214
|
+
r.destinationId == destination.model.id and
|
215
|
+
r.description == relationship.model.description and
|
216
|
+
r.technology == relationship.model.technology
|
217
|
+
for r in rels
|
218
|
+
)
|
219
|
+
if not already_exists:
|
220
|
+
r = source_parent.uses(
|
221
|
+
destination,
|
222
|
+
description=relationship.model.description,
|
223
|
+
technology=relationship.model.technology,
|
224
|
+
)
|
225
|
+
r.model.linkedRelationshipId = relationship.model.id
|
226
|
+
source_parent = source_parent.parent
|
183
227
|
|
184
228
|
def person(self) -> TypedDynamicAttribute['Person']:
|
185
229
|
return TypedDynamicAttribute['Person'](self._dynamic_attrs)
|
@@ -364,6 +408,7 @@ class SoftwareSystem(DslElementRelationOverrides[
|
|
364
408
|
self.model.id = GenerateId.for_element()
|
365
409
|
self.model.name = name
|
366
410
|
self.model.description = description
|
411
|
+
self.model.relationships = []
|
367
412
|
self.model.tags = ','.join(self._tags)
|
368
413
|
self.model.properties = properties
|
369
414
|
|
@@ -832,6 +877,12 @@ class DeploymentEnvironment(DslDeploymentEnvironment):
|
|
832
877
|
if not relationship.destinationId in other_softwares_ids:
|
833
878
|
continue
|
834
879
|
|
880
|
+
if software.model.id not in software_instance_map:
|
881
|
+
continue
|
882
|
+
|
883
|
+
if relationship.destinationId not in software_instance_map:
|
884
|
+
continue
|
885
|
+
|
835
886
|
this_software_instances = software_instance_map[software.model.id]
|
836
887
|
other_software_instances = software_instance_map[relationship.destinationId]
|
837
888
|
|
@@ -900,6 +951,12 @@ class DeploymentEnvironment(DslDeploymentEnvironment):
|
|
900
951
|
if not relationship.destinationId in other_containers_ids:
|
901
952
|
continue
|
902
953
|
|
954
|
+
if container.model.id not in container_instance_map:
|
955
|
+
continue
|
956
|
+
|
957
|
+
if relationship.destinationId not in container_instance_map:
|
958
|
+
continue
|
959
|
+
|
903
960
|
this_container_instances = container_instance_map[container.model.id]
|
904
961
|
other_container_instances = container_instance_map[relationship.destinationId]
|
905
962
|
|
@@ -15,6 +15,7 @@ from buildzr.dsl import (
|
|
15
15
|
SystemContextView,
|
16
16
|
DeploymentEnvironment,
|
17
17
|
DeploymentNode,
|
18
|
+
DeploymentView,
|
18
19
|
InfrastructureNode,
|
19
20
|
DeploymentGroup,
|
20
21
|
SoftwareSystemInstance,
|
@@ -394,6 +395,53 @@ def test_implied_relationship() -> Optional[None]:
|
|
394
395
|
assert w.u.model.relationships[1].id in system_context_view_relationships
|
395
396
|
assert w.u.model.relationships[1].linkedRelationshipId == w.u.model.relationships[0].id
|
396
397
|
|
398
|
+
import os
|
399
|
+
os.remove('workspace.test.json')
|
400
|
+
os.remove('workspace2.test.json')
|
401
|
+
|
402
|
+
def test_inverse_implied_relationship() -> Optional[None]:
|
403
|
+
"""
|
404
|
+
Test that inverse implied relationships work correctly.
|
405
|
+
When a.container >> b (child to parent), it should imply a >> b.
|
406
|
+
|
407
|
+
See: https://docs.structurizr.com/java/implied-relationships
|
408
|
+
"""
|
409
|
+
|
410
|
+
with Workspace("w", implied_relationships=True) as w:
|
411
|
+
u = Person('User')
|
412
|
+
s = SoftwareSystem('System')
|
413
|
+
with s:
|
414
|
+
api = Container('API')
|
415
|
+
db = Container('Database')
|
416
|
+
api >> "Uses" >> db
|
417
|
+
|
418
|
+
# Create relationship from child to parent: s.api >> u
|
419
|
+
# This should imply s >> u
|
420
|
+
s.api >> "Notifies" >> u
|
421
|
+
|
422
|
+
# Invoke implied relationships via view
|
423
|
+
SystemContextView(
|
424
|
+
software_system_selector=s,
|
425
|
+
key='s_context',
|
426
|
+
description="System context view",
|
427
|
+
)
|
428
|
+
|
429
|
+
w.to_json('workspace.inverse.test.json')
|
430
|
+
|
431
|
+
# Check that System has an implied relationship to User
|
432
|
+
assert len(s.model.relationships) == 1
|
433
|
+
assert s.model.relationships[0].description == "Notifies"
|
434
|
+
assert s.model.relationships[0].sourceId == s.model.id
|
435
|
+
assert s.model.relationships[0].destinationId == u.model.id
|
436
|
+
assert s.model.relationships[0].linkedRelationshipId == s.api.model.relationships[1].id
|
437
|
+
|
438
|
+
# The implied relationship should appear in system context view
|
439
|
+
system_context_view_relationships = [x.id for x in w._m.views.systemContextViews[0].relationships]
|
440
|
+
assert s.model.relationships[0].id in system_context_view_relationships
|
441
|
+
|
442
|
+
import os
|
443
|
+
os.remove('workspace.inverse.test.json')
|
444
|
+
|
397
445
|
def test_tags_on_elements() -> Optional[None]:
|
398
446
|
|
399
447
|
u = Person('My User', tags={'admin'})
|
@@ -1099,4 +1147,230 @@ def test_json_sink_empty_views() -> Optional[None]:
|
|
1099
1147
|
assert data
|
1100
1148
|
|
1101
1149
|
import os
|
1102
|
-
os.remove("test.json")
|
1150
|
+
os.remove("test.json")
|
1151
|
+
|
1152
|
+
def test_deployment_instance_relationships_with_implied_relationships() -> Optional[None]:
|
1153
|
+
"""
|
1154
|
+
Test that deployment instance relationships are created correctly when
|
1155
|
+
implied_relationships=True, without creating duplicates.
|
1156
|
+
|
1157
|
+
This test ensures:
|
1158
|
+
1. Container relationships automatically create ContainerInstance relationships
|
1159
|
+
2. No duplicate instance relationships are created when implied_relationships=True
|
1160
|
+
3. Instance relationships are only created once, even with multiple view/export calls
|
1161
|
+
"""
|
1162
|
+
|
1163
|
+
with Workspace('deployment-test', implied_relationships=True) as w:
|
1164
|
+
# Create containers with relationships
|
1165
|
+
ecommerce = SoftwareSystem('E-Commerce System')
|
1166
|
+
with ecommerce:
|
1167
|
+
api_gateway = Container('API Gateway', technology='Kong')
|
1168
|
+
order_svc = Container('Order Service', technology='Node.js')
|
1169
|
+
db = Container('Database', technology='MongoDB')
|
1170
|
+
|
1171
|
+
# Define container relationships
|
1172
|
+
api_gateway >> "Routes to" >> order_svc
|
1173
|
+
order_svc >> "Stores in" >> db
|
1174
|
+
|
1175
|
+
# Create deployment with container instances
|
1176
|
+
with DeploymentEnvironment('Production') as prod:
|
1177
|
+
with DeploymentNode('AWS', technology='Cloud Provider'):
|
1178
|
+
api_gw_instance = ContainerInstance(api_gateway)
|
1179
|
+
order_instance = ContainerInstance(order_svc)
|
1180
|
+
db_instance = ContainerInstance(db)
|
1181
|
+
|
1182
|
+
# Create views and export (triggers implied relationships multiple times)
|
1183
|
+
SystemContextView(
|
1184
|
+
software_system_selector=ecommerce,
|
1185
|
+
key='test-system-context',
|
1186
|
+
description="Test System Context",
|
1187
|
+
)
|
1188
|
+
|
1189
|
+
DeploymentView(
|
1190
|
+
environment=prod,
|
1191
|
+
key='test-deployment',
|
1192
|
+
)
|
1193
|
+
|
1194
|
+
# Export multiple times to ensure idempotency
|
1195
|
+
w.to_json('test_deployment1.json')
|
1196
|
+
w.to_json('test_deployment2.json')
|
1197
|
+
|
1198
|
+
# Verify instance relationships exist
|
1199
|
+
assert api_gw_instance.model.relationships is not None
|
1200
|
+
assert order_instance.model.relationships is not None
|
1201
|
+
|
1202
|
+
# Get all instance relationships
|
1203
|
+
api_gw_rels = api_gw_instance.model.relationships
|
1204
|
+
order_rels = order_instance.model.relationships
|
1205
|
+
|
1206
|
+
# Should have exactly 1 relationship from api_gw_instance to order_instance
|
1207
|
+
api_to_order_rels = [
|
1208
|
+
r for r in api_gw_rels
|
1209
|
+
if r.destinationId == order_instance.model.id
|
1210
|
+
]
|
1211
|
+
assert len(api_to_order_rels) == 1, f"Expected 1 relationship, found {len(api_to_order_rels)}"
|
1212
|
+
assert api_to_order_rels[0].description == "Routes to"
|
1213
|
+
|
1214
|
+
# Should have exactly 1 relationship from order_instance to db_instance
|
1215
|
+
order_to_db_rels = [
|
1216
|
+
r for r in order_rels
|
1217
|
+
if r.destinationId == db_instance.model.id
|
1218
|
+
]
|
1219
|
+
assert len(order_to_db_rels) == 1, f"Expected 1 relationship, found {len(order_to_db_rels)}"
|
1220
|
+
assert order_to_db_rels[0].description == "Stores in"
|
1221
|
+
|
1222
|
+
# Verify linkedRelationshipId is set correctly
|
1223
|
+
assert api_to_order_rels[0].linkedRelationshipId is not None
|
1224
|
+
assert order_to_db_rels[0].linkedRelationshipId is not None
|
1225
|
+
|
1226
|
+
# Clean up
|
1227
|
+
import os
|
1228
|
+
os.remove('test_deployment1.json')
|
1229
|
+
os.remove('test_deployment2.json')
|
1230
|
+
|
1231
|
+
def test_imply_relationships_before_deployment_environment_not_crashing() -> Optional[None]:
|
1232
|
+
|
1233
|
+
with Workspace('workspace') as w:
|
1234
|
+
|
1235
|
+
with SoftwareSystem("X") as x:
|
1236
|
+
|
1237
|
+
# Notice that we don't need to specify the tags "Application" and "Database"
|
1238
|
+
# for styling -- just pass the `wa` and `db` variables directly to the `StyleElements` class.
|
1239
|
+
wa = Container("Web Application", technology="Java and Spring boot")
|
1240
|
+
db = Container("Database Schema")
|
1241
|
+
|
1242
|
+
wa >> "Reads from and writes to" >> db
|
1243
|
+
|
1244
|
+
with DeploymentEnvironment("Live") as live:
|
1245
|
+
with DeploymentNode("Amazon Web Services") as aws:
|
1246
|
+
aws.add_tags("Amazon Web Services - Cloud")
|
1247
|
+
|
1248
|
+
with DeploymentNode("US-East-1") as region:
|
1249
|
+
region.add_tags("Amazon Web Services - Region")
|
1250
|
+
|
1251
|
+
dns = InfrastructureNode(
|
1252
|
+
"DNS Router",
|
1253
|
+
description="Routes incoming requests based upon domain name.",
|
1254
|
+
technology="Route 53",
|
1255
|
+
tags={"Amazon Web Services - Route 53"}
|
1256
|
+
)
|
1257
|
+
|
1258
|
+
lb = InfrastructureNode(
|
1259
|
+
"Load Balancer",
|
1260
|
+
description="Automatically distributes incoming application traffic.",
|
1261
|
+
technology="Elastic Load Balancer",
|
1262
|
+
tags={"Amazon Web Services - Elastic Load Balancer"}
|
1263
|
+
)
|
1264
|
+
|
1265
|
+
dns >> ("Fowards requests to", "HTTP") >> lb
|
1266
|
+
|
1267
|
+
with DeploymentNode("Amazon EC2", tags={"Amazon Web Services - EC2"}) as asg:
|
1268
|
+
with DeploymentNode("Amazon EC2 - Ubuntu Server", tags={"Amazon Web Services - EC2 Instance"}):
|
1269
|
+
lb >> "Forwards requests to" >> ContainerInstance(wa)
|
1270
|
+
|
1271
|
+
with DeploymentNode("Amazon RDS", tags={"Amazon Web Services - RDS Instance"}) as rds:
|
1272
|
+
with DeploymentNode("MySQL", tags={"Amazon Web Services - RDS MySQL instance"}):
|
1273
|
+
database_instance = ContainerInstance(db)
|
1274
|
+
|
1275
|
+
DeploymentView(
|
1276
|
+
environment=live,
|
1277
|
+
key='aws-deployment-view',
|
1278
|
+
software_system_selector=x,
|
1279
|
+
title="Amazon Web Services Deployment",
|
1280
|
+
description="Deployment view of the web application on AWS",
|
1281
|
+
auto_layout='lr',
|
1282
|
+
)
|
1283
|
+
|
1284
|
+
w.to_json('amazon_web_services.json', pretty=True)
|
1285
|
+
|
1286
|
+
def test_software_system_instance_relationships_with_missing_instances() -> Optional[None]:
|
1287
|
+
"""
|
1288
|
+
Test that _imply_software_system_instance_relationships doesn't crash when
|
1289
|
+
a software system has a relationship to another software system, but only
|
1290
|
+
one of them has instances deployed.
|
1291
|
+
|
1292
|
+
This reproduces the bug where:
|
1293
|
+
- E-Commerce System has instances deployed
|
1294
|
+
- Payment Provider has NO instances deployed
|
1295
|
+
- E-Commerce System -> Payment Provider relationship exists
|
1296
|
+
- Should not crash with KeyError when trying to look up Payment Provider instances
|
1297
|
+
"""
|
1298
|
+
|
1299
|
+
with Workspace('test-workspace') as w:
|
1300
|
+
# Create two software systems with a relationship
|
1301
|
+
ecommerce = SoftwareSystem('E-Commerce System')
|
1302
|
+
payment_provider = SoftwareSystem('Payment Provider')
|
1303
|
+
|
1304
|
+
ecommerce >> "Processes payments via" >> payment_provider
|
1305
|
+
|
1306
|
+
# Deploy only the E-Commerce System, NOT the Payment Provider
|
1307
|
+
with DeploymentEnvironment('Production') as prod:
|
1308
|
+
with DeploymentNode('AWS'):
|
1309
|
+
ecommerce_instance = SoftwareSystemInstance(ecommerce)
|
1310
|
+
|
1311
|
+
# This should not crash - the implication happens in DeploymentEnvironment.__exit__
|
1312
|
+
# Even though ecommerce has a relationship to payment_provider,
|
1313
|
+
# payment_provider has no instances deployed
|
1314
|
+
|
1315
|
+
# If we get here without a KeyError, the test passes
|
1316
|
+
assert ecommerce_instance.model.softwareSystemId == ecommerce.model.id
|
1317
|
+
|
1318
|
+
def test_container_instance_relationships_with_missing_instances() -> Optional[None]:
|
1319
|
+
"""
|
1320
|
+
Test that _imply_container_instance_relationships doesn't crash when
|
1321
|
+
a container has a relationship to another container, but only one of
|
1322
|
+
them has instances deployed.
|
1323
|
+
|
1324
|
+
This tests the same bug pattern but for containers instead of software systems.
|
1325
|
+
"""
|
1326
|
+
|
1327
|
+
with Workspace('test-workspace') as w:
|
1328
|
+
# Create software system with containers that have relationships
|
1329
|
+
with SoftwareSystem('E-Commerce System') as ecommerce:
|
1330
|
+
web_app = Container('Web Application')
|
1331
|
+
api = Container('API')
|
1332
|
+
database = Container('Database')
|
1333
|
+
external_service = Container('External Payment Service')
|
1334
|
+
|
1335
|
+
# Create relationships
|
1336
|
+
web_app >> "Calls" >> api
|
1337
|
+
api >> "Stores data in" >> database
|
1338
|
+
api >> "Processes payments via" >> external_service
|
1339
|
+
|
1340
|
+
# Deploy only some containers, NOT all of them
|
1341
|
+
with DeploymentEnvironment('Production') as prod:
|
1342
|
+
with DeploymentNode('AWS'):
|
1343
|
+
web_app_instance = ContainerInstance(web_app)
|
1344
|
+
api_instance = ContainerInstance(api)
|
1345
|
+
db_instance = ContainerInstance(database)
|
1346
|
+
# Note: external_service is NOT deployed
|
1347
|
+
|
1348
|
+
# This should not crash - even though api has a relationship to external_service,
|
1349
|
+
# external_service has no instances deployed
|
1350
|
+
|
1351
|
+
# If we get here without a KeyError, the test passes
|
1352
|
+
assert web_app_instance.model.containerId == web_app.model.id
|
1353
|
+
assert api_instance.model.containerId == api.model.id
|
1354
|
+
assert db_instance.model.containerId == database.model.id
|
1355
|
+
|
1356
|
+
# Verify that the deployed instances DO have implied relationships
|
1357
|
+
# web_app_instance should have relationship to api_instance
|
1358
|
+
web_to_api_rels = [
|
1359
|
+
r for r in (web_app_instance.model.relationships or [])
|
1360
|
+
if r.destinationId == api_instance.model.id
|
1361
|
+
]
|
1362
|
+
assert len(web_to_api_rels) == 1
|
1363
|
+
|
1364
|
+
# api_instance should have relationship to db_instance
|
1365
|
+
api_to_db_rels = [
|
1366
|
+
r for r in (api_instance.model.relationships or [])
|
1367
|
+
if r.destinationId == db_instance.model.id
|
1368
|
+
]
|
1369
|
+
assert len(api_to_db_rels) == 1
|
1370
|
+
|
1371
|
+
# But api_instance should NOT have a relationship to external_service
|
1372
|
+
# (because it wasn't deployed)
|
1373
|
+
all_api_destinations = [
|
1374
|
+
r.destinationId for r in (api_instance.model.relationships or [])
|
1375
|
+
]
|
1376
|
+
assert external_service.model.id not in all_api_destinations
|
@@ -90,7 +90,7 @@ def test_walk_relationships(workspace: Workspace) -> Optional[None]:
|
|
90
90
|
|
91
91
|
# 5 explicit relationships.
|
92
92
|
# Add one additional implied relationship.
|
93
|
-
# And four additional from container instances for each two container instance (2x2=4
|
93
|
+
# And four additional from container instances for each two container instance (2x2=4).
|
94
94
|
#
|
95
95
|
# Explanation: if we have containers A and B with relationship A >> "Uses" >> B,
|
96
96
|
# and container instances ci_A_1, ci_A_2, ci_B_1, ci_B_2, then we have the
|
@@ -99,7 +99,7 @@ def test_walk_relationships(workspace: Workspace) -> Optional[None]:
|
|
99
99
|
# ci_A_1 >> "Uses" >> ci_B_2
|
100
100
|
# ci_A_2 >> "Uses" >> ci_B_1
|
101
101
|
# ci_A_2 >> "Uses" >> ci_B_2
|
102
|
-
assert len(relationships) ==
|
102
|
+
assert len(relationships) == 10
|
103
103
|
|
104
104
|
for relationship in relationships:
|
105
105
|
relationship_set = (
|
@@ -1 +0,0 @@
|
|
1
|
-
VERSION = "0.0.17"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|