infrahub-server 1.2.11__py3-none-any.whl → 1.3.0b1__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.
- infrahub/actions/constants.py +86 -0
- infrahub/actions/gather.py +114 -0
- infrahub/actions/models.py +241 -0
- infrahub/actions/parsers.py +104 -0
- infrahub/actions/schema.py +382 -0
- infrahub/actions/tasks.py +126 -0
- infrahub/actions/triggers.py +21 -0
- infrahub/cli/db.py +1 -2
- infrahub/core/account.py +24 -47
- infrahub/core/attribute.py +13 -15
- infrahub/core/constants/__init__.py +5 -0
- infrahub/core/constants/infrahubkind.py +9 -0
- infrahub/core/convert_object_type/__init__.py +0 -0
- infrahub/core/convert_object_type/conversion.py +122 -0
- infrahub/core/convert_object_type/schema_mapping.py +56 -0
- infrahub/core/diff/query/all_conflicts.py +1 -5
- infrahub/core/diff/query/artifact.py +10 -20
- infrahub/core/diff/query/diff_get.py +3 -6
- infrahub/core/diff/query/field_summary.py +2 -4
- infrahub/core/diff/query/merge.py +70 -123
- infrahub/core/diff/query/save.py +20 -32
- infrahub/core/diff/query/summary_counts_enricher.py +34 -54
- infrahub/core/manager.py +14 -11
- infrahub/core/migrations/graph/m003_relationship_parent_optional.py +1 -2
- infrahub/core/migrations/graph/m013_convert_git_password_credential.py +2 -4
- infrahub/core/migrations/graph/m019_restore_rels_to_time.py +11 -22
- infrahub/core/migrations/graph/m020_duplicate_edges.py +3 -6
- infrahub/core/migrations/graph/m021_missing_hierarchy_merge.py +1 -2
- infrahub/core/migrations/graph/m024_missing_hierarchy_backfill.py +1 -2
- infrahub/core/migrations/query/attribute_add.py +1 -2
- infrahub/core/migrations/query/attribute_rename.py +5 -10
- infrahub/core/migrations/query/delete_element_in_schema.py +19 -17
- infrahub/core/migrations/query/node_duplicate.py +19 -21
- infrahub/core/migrations/query/relationship_duplicate.py +19 -17
- infrahub/core/migrations/schema/node_attribute_remove.py +4 -8
- infrahub/core/migrations/schema/node_remove.py +19 -19
- infrahub/core/models.py +29 -2
- infrahub/core/node/__init__.py +90 -18
- infrahub/core/node/create.py +211 -0
- infrahub/core/node/resource_manager/number_pool.py +31 -5
- infrahub/core/node/standard.py +6 -1
- infrahub/core/protocols.py +56 -0
- infrahub/core/protocols_base.py +3 -0
- infrahub/core/query/__init__.py +2 -2
- infrahub/core/query/diff.py +19 -32
- infrahub/core/query/ipam.py +10 -20
- infrahub/core/query/node.py +28 -46
- infrahub/core/query/relationship.py +53 -32
- infrahub/core/query/resource_manager.py +1 -2
- infrahub/core/query/subquery.py +2 -4
- infrahub/core/relationship/model.py +3 -0
- infrahub/core/schema/__init__.py +2 -1
- infrahub/core/schema/attribute_parameters.py +160 -0
- infrahub/core/schema/attribute_schema.py +111 -8
- infrahub/core/schema/basenode_schema.py +25 -1
- infrahub/core/schema/definitions/core/__init__.py +29 -1
- infrahub/core/schema/definitions/core/group.py +45 -0
- infrahub/core/schema/definitions/internal.py +27 -4
- infrahub/core/schema/generated/attribute_schema.py +16 -3
- infrahub/core/schema/manager.py +3 -0
- infrahub/core/schema/schema_branch.py +67 -7
- infrahub/core/validators/__init__.py +13 -1
- infrahub/core/validators/attribute/choices.py +1 -3
- infrahub/core/validators/attribute/enum.py +1 -3
- infrahub/core/validators/attribute/kind.py +1 -3
- infrahub/core/validators/attribute/length.py +13 -7
- infrahub/core/validators/attribute/min_max.py +118 -0
- infrahub/core/validators/attribute/number_pool.py +106 -0
- infrahub/core/validators/attribute/optional.py +1 -4
- infrahub/core/validators/attribute/regex.py +5 -6
- infrahub/core/validators/attribute/unique.py +1 -3
- infrahub/core/validators/determiner.py +18 -2
- infrahub/core/validators/enum.py +12 -0
- infrahub/core/validators/node/hierarchy.py +3 -6
- infrahub/core/validators/query.py +1 -3
- infrahub/core/validators/relationship/count.py +6 -12
- infrahub/core/validators/relationship/optional.py +2 -4
- infrahub/core/validators/relationship/peer.py +3 -8
- infrahub/core/validators/uniqueness/query.py +5 -9
- infrahub/database/__init__.py +11 -2
- infrahub/events/group_action.py +1 -0
- infrahub/git/base.py +5 -3
- infrahub/git/integrator.py +102 -3
- infrahub/graphql/analyzer.py +139 -18
- infrahub/graphql/manager.py +4 -0
- infrahub/graphql/mutations/action.py +164 -0
- infrahub/graphql/mutations/convert_object_type.py +62 -0
- infrahub/graphql/mutations/main.py +24 -175
- infrahub/graphql/mutations/proposed_change.py +20 -17
- infrahub/graphql/mutations/resource_manager.py +62 -6
- infrahub/graphql/queries/convert_object_type_mapping.py +36 -0
- infrahub/graphql/queries/resource_manager.py +7 -1
- infrahub/graphql/schema.py +6 -0
- infrahub/menu/menu.py +31 -0
- infrahub/message_bus/messages/__init__.py +0 -10
- infrahub/message_bus/operations/__init__.py +0 -8
- infrahub/patch/queries/consolidate_duplicated_nodes.py +3 -6
- infrahub/patch/queries/delete_duplicated_edges.py +5 -10
- infrahub/pools/number.py +5 -3
- infrahub/prefect_server/models.py +1 -19
- infrahub/proposed_change/models.py +68 -3
- infrahub/proposed_change/tasks.py +907 -30
- infrahub/task_manager/models.py +10 -6
- infrahub/trigger/catalogue.py +2 -0
- infrahub/trigger/models.py +18 -2
- infrahub/trigger/tasks.py +3 -1
- infrahub/types.py +6 -0
- infrahub/workflows/catalogue.py +76 -0
- infrahub_sdk/client.py +43 -10
- infrahub_sdk/node/__init__.py +39 -0
- infrahub_sdk/node/attribute.py +122 -0
- infrahub_sdk/node/constants.py +21 -0
- infrahub_sdk/{node.py → node/node.py} +50 -749
- infrahub_sdk/node/parsers.py +15 -0
- infrahub_sdk/node/property.py +24 -0
- infrahub_sdk/node/related_node.py +266 -0
- infrahub_sdk/node/relationship.py +302 -0
- infrahub_sdk/protocols.py +112 -0
- infrahub_sdk/protocols_base.py +34 -2
- infrahub_sdk/query_groups.py +13 -2
- infrahub_sdk/schema/main.py +1 -0
- infrahub_sdk/schema/repository.py +16 -0
- infrahub_sdk/spec/object.py +1 -1
- infrahub_sdk/store.py +1 -1
- infrahub_sdk/testing/schemas/car_person.py +1 -0
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/METADATA +4 -4
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/RECORD +134 -122
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/WHEEL +1 -1
- infrahub_testcontainers/container.py +0 -1
- infrahub_testcontainers/docker-compose.test.yml +1 -1
- infrahub_testcontainers/helpers.py +8 -2
- infrahub/message_bus/messages/check_generator_run.py +0 -26
- infrahub/message_bus/messages/finalize_validator_execution.py +0 -15
- infrahub/message_bus/messages/proposed_change/base_with_diff.py +0 -16
- infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +0 -11
- infrahub/message_bus/messages/request_generatordefinition_check.py +0 -20
- infrahub/message_bus/messages/request_proposedchange_pipeline.py +0 -23
- infrahub/message_bus/operations/check/__init__.py +0 -3
- infrahub/message_bus/operations/check/generator.py +0 -156
- infrahub/message_bus/operations/finalize/__init__.py +0 -3
- infrahub/message_bus/operations/finalize/validator.py +0 -133
- infrahub/message_bus/operations/requests/__init__.py +0 -9
- infrahub/message_bus/operations/requests/generator_definition.py +0 -140
- infrahub/message_bus/operations/requests/proposed_change.py +0 -629
- /infrahub/{message_bus/messages/proposed_change → actions}/__init__.py +0 -0
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/entry_points.txt +0 -0
infrahub/core/account.py
CHANGED
|
@@ -69,8 +69,7 @@ class AccountGlobalPermissionQuery(Query):
|
|
|
69
69
|
query = """
|
|
70
70
|
MATCH (account:%(generic_account_node)s)
|
|
71
71
|
WHERE account.uuid = $account_id
|
|
72
|
-
CALL {
|
|
73
|
-
WITH account
|
|
72
|
+
CALL (account) {
|
|
74
73
|
MATCH (account)-[r:IS_PART_OF]-(root:Root)
|
|
75
74
|
WHERE %(branch_filter)s
|
|
76
75
|
RETURN account as account1, r as r1
|
|
@@ -80,8 +79,7 @@ class AccountGlobalPermissionQuery(Query):
|
|
|
80
79
|
WITH account, r1 as r
|
|
81
80
|
WHERE r.status = "active"
|
|
82
81
|
WITH account
|
|
83
|
-
CALL {
|
|
84
|
-
WITH account
|
|
82
|
+
CALL (account) {
|
|
85
83
|
MATCH (account)-[r1:IS_RELATED]->(:Relationship {name: "group_member"})<-[r2:IS_RELATED]-(account_group:%(account_group_node)s)
|
|
86
84
|
WHERE all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
87
85
|
WITH account_group, r1, r2, (r1.status = "active" AND r2.status = "active") AS is_active
|
|
@@ -92,8 +90,7 @@ class AccountGlobalPermissionQuery(Query):
|
|
|
92
90
|
}
|
|
93
91
|
WITH account_group
|
|
94
92
|
|
|
95
|
-
CALL {
|
|
96
|
-
WITH account_group
|
|
93
|
+
CALL (account_group) {
|
|
97
94
|
MATCH (account_group)-[r1:IS_RELATED]->(:Relationship {name: "role__accountgroups"})<-[r2:IS_RELATED]-(account_role:%(account_role_node)s)
|
|
98
95
|
WHERE all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
99
96
|
WITH account_role, r1, r2, (r1.status = "active" AND r2.status = "active") AS is_active
|
|
@@ -104,8 +101,7 @@ class AccountGlobalPermissionQuery(Query):
|
|
|
104
101
|
}
|
|
105
102
|
WITH account_role
|
|
106
103
|
|
|
107
|
-
CALL {
|
|
108
|
-
WITH account_role
|
|
104
|
+
CALL (account_role) {
|
|
109
105
|
MATCH (account_role)-[r1:IS_RELATED]->(:Relationship {name: "role__permissions"})<-[r2:IS_RELATED]-(global_permission:%(global_permission_node)s)
|
|
110
106
|
WHERE all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
111
107
|
WITH global_permission, r1, r2, (r1.status = "active" AND r2.status = "active") AS is_active
|
|
@@ -116,7 +112,7 @@ class AccountGlobalPermissionQuery(Query):
|
|
|
116
112
|
}
|
|
117
113
|
WITH global_permission
|
|
118
114
|
|
|
119
|
-
CALL {
|
|
115
|
+
CALL (global_permission) {
|
|
120
116
|
WITH global_permission
|
|
121
117
|
MATCH (global_permission)-[r1:HAS_ATTRIBUTE]->(:Attribute {name: "action"})-[r2:HAS_VALUE]->(global_permission_action:AttributeValue)
|
|
122
118
|
WHERE all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
@@ -127,8 +123,7 @@ class AccountGlobalPermissionQuery(Query):
|
|
|
127
123
|
WITH global_permission, global_permission_action, is_active AS gpa_is_active
|
|
128
124
|
WHERE gpa_is_active = TRUE
|
|
129
125
|
|
|
130
|
-
CALL {
|
|
131
|
-
WITH global_permission
|
|
126
|
+
CALL (global_permission) {
|
|
132
127
|
MATCH (global_permission)-[r1:HAS_ATTRIBUTE]->(:Attribute {name: "decision"})-[r2:HAS_VALUE]->(global_permission_decision:AttributeValue)
|
|
133
128
|
WHERE all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
134
129
|
RETURN global_permission_decision, (r1.status = "active" AND r2.status = "active") AS is_active
|
|
@@ -183,8 +178,7 @@ class AccountObjectPermissionQuery(Query):
|
|
|
183
178
|
query = """
|
|
184
179
|
MATCH (account:%(generic_account_node)s)
|
|
185
180
|
WHERE account.uuid = $account_id
|
|
186
|
-
CALL {
|
|
187
|
-
WITH account
|
|
181
|
+
CALL (account) {
|
|
188
182
|
MATCH (account)-[r:IS_PART_OF]-(root:Root)
|
|
189
183
|
WHERE %(branch_filter)s
|
|
190
184
|
RETURN account as account1, r as r1
|
|
@@ -194,8 +188,7 @@ class AccountObjectPermissionQuery(Query):
|
|
|
194
188
|
WITH account, r1 as r
|
|
195
189
|
WHERE r.status = "active"
|
|
196
190
|
WITH account
|
|
197
|
-
CALL {
|
|
198
|
-
WITH account
|
|
191
|
+
CALL (account) {
|
|
199
192
|
MATCH (account)-[r1:IS_RELATED]->(:Relationship {name: "group_member"})<-[r2:IS_RELATED]-(account_group:%(account_group_node)s)
|
|
200
193
|
WHERE all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
201
194
|
WITH account_group, r1, r2, (r1.status = "active" AND r2.status = "active") AS is_active
|
|
@@ -206,8 +199,7 @@ class AccountObjectPermissionQuery(Query):
|
|
|
206
199
|
}
|
|
207
200
|
WITH account_group
|
|
208
201
|
|
|
209
|
-
CALL {
|
|
210
|
-
WITH account_group
|
|
202
|
+
CALL (account_group) {
|
|
211
203
|
MATCH (account_group)-[r1:IS_RELATED]->(:Relationship {name: "role__accountgroups"})<-[r2:IS_RELATED]-(account_role:%(account_role_node)s)
|
|
212
204
|
WHERE all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
213
205
|
WITH account_role, r1, r2, (r1.status = "active" AND r2.status = "active") AS is_active
|
|
@@ -218,8 +210,7 @@ class AccountObjectPermissionQuery(Query):
|
|
|
218
210
|
}
|
|
219
211
|
WITH account_role
|
|
220
212
|
|
|
221
|
-
CALL {
|
|
222
|
-
WITH account_role
|
|
213
|
+
CALL (account_role) {
|
|
223
214
|
MATCH (account_role)-[r1:IS_RELATED]->(:Relationship {name: "role__permissions"})<-[r2:IS_RELATED]-(object_permission:%(object_permission_node)s)
|
|
224
215
|
WHERE all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
225
216
|
WITH object_permission, r1, r2, (r1.status = "active" AND r2.status = "active") AS is_active
|
|
@@ -230,8 +221,7 @@ class AccountObjectPermissionQuery(Query):
|
|
|
230
221
|
}
|
|
231
222
|
WITH object_permission
|
|
232
223
|
|
|
233
|
-
CALL {
|
|
234
|
-
WITH object_permission
|
|
224
|
+
CALL (object_permission) {
|
|
235
225
|
MATCH (object_permission)-[r1:HAS_ATTRIBUTE]->(:Attribute {name: "namespace"})-[r2:HAS_VALUE]->(object_permission_namespace:AttributeValue)
|
|
236
226
|
WHERE all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
237
227
|
RETURN object_permission_namespace, (r1.status = "active" AND r2.status = "active") AS is_active
|
|
@@ -240,8 +230,7 @@ class AccountObjectPermissionQuery(Query):
|
|
|
240
230
|
}
|
|
241
231
|
WITH object_permission, object_permission_namespace, is_active AS opn_is_active
|
|
242
232
|
WHERE opn_is_active = TRUE
|
|
243
|
-
CALL {
|
|
244
|
-
WITH object_permission
|
|
233
|
+
CALL (object_permission) {
|
|
245
234
|
MATCH (object_permission)-[r1:HAS_ATTRIBUTE]->(:Attribute {name: "name"})-[r2:HAS_VALUE]->(object_permission_name:AttributeValue)
|
|
246
235
|
WHERE all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
247
236
|
RETURN object_permission_name, (r1.status = "active" AND r2.status = "active") AS is_active
|
|
@@ -250,8 +239,7 @@ class AccountObjectPermissionQuery(Query):
|
|
|
250
239
|
}
|
|
251
240
|
WITH object_permission, object_permission_namespace, object_permission_name, is_active AS opn_is_active
|
|
252
241
|
WHERE opn_is_active = TRUE
|
|
253
|
-
CALL {
|
|
254
|
-
WITH object_permission
|
|
242
|
+
CALL (object_permission) {
|
|
255
243
|
MATCH (object_permission)-[r1:HAS_ATTRIBUTE]->(:Attribute {name: "action"})-[r2:HAS_VALUE]->(object_permission_action:AttributeValue)
|
|
256
244
|
WHERE all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
257
245
|
RETURN object_permission_action, (r1.status = "active" AND r2.status = "active") AS is_active
|
|
@@ -260,8 +248,7 @@ class AccountObjectPermissionQuery(Query):
|
|
|
260
248
|
}
|
|
261
249
|
WITH object_permission, object_permission_namespace, object_permission_name, object_permission_action, is_active AS opa_is_active
|
|
262
250
|
WHERE opa_is_active = TRUE
|
|
263
|
-
CALL {
|
|
264
|
-
WITH object_permission
|
|
251
|
+
CALL (object_permission) {
|
|
265
252
|
MATCH (object_permission)-[r1:HAS_ATTRIBUTE]->(:Attribute {name: "decision"})-[r2:HAS_VALUE]->(object_permission_decision:AttributeValue)
|
|
266
253
|
WHERE all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
267
254
|
RETURN object_permission_decision, (r1.status = "active" AND r2.status = "active") AS is_active
|
|
@@ -336,8 +323,7 @@ class AccountRoleGlobalPermissionQuery(Query):
|
|
|
336
323
|
query = """
|
|
337
324
|
MATCH (account_role:%(account_role_node)s)
|
|
338
325
|
WHERE account_role.uuid = $role_id
|
|
339
|
-
CALL {
|
|
340
|
-
WITH account_role
|
|
326
|
+
CALL (account_role) {
|
|
341
327
|
MATCH (account_role)-[r:IS_PART_OF]-(root:Root)
|
|
342
328
|
WHERE %(branch_filter)s
|
|
343
329
|
RETURN account_role as account_role1, r as r1
|
|
@@ -348,8 +334,7 @@ class AccountRoleGlobalPermissionQuery(Query):
|
|
|
348
334
|
WHERE r.status = "active"
|
|
349
335
|
WITH account_role
|
|
350
336
|
|
|
351
|
-
CALL {
|
|
352
|
-
WITH account_role
|
|
337
|
+
CALL (account_role) {
|
|
353
338
|
MATCH (account_role)-[r1:IS_RELATED]->(:Relationship {name: "role__permissions"})<-[r2:IS_RELATED]-(global_permission:%(global_permission_node)s)
|
|
354
339
|
WHERE all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
355
340
|
WITH global_permission, r1, r2, (r1.status = "active" AND r2.status = "active") AS is_active
|
|
@@ -360,8 +345,7 @@ class AccountRoleGlobalPermissionQuery(Query):
|
|
|
360
345
|
}
|
|
361
346
|
WITH global_permission
|
|
362
347
|
|
|
363
|
-
CALL {
|
|
364
|
-
WITH global_permission
|
|
348
|
+
CALL (global_permission) {
|
|
365
349
|
MATCH (global_permission)-[r1:HAS_ATTRIBUTE]->(:Attribute {name: "action"})-[r2:HAS_VALUE]->(global_permission_action:AttributeValue)
|
|
366
350
|
WHERE all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
367
351
|
RETURN global_permission_action, (r1.status = "active" AND r2.status = "active") AS is_active
|
|
@@ -371,8 +355,7 @@ class AccountRoleGlobalPermissionQuery(Query):
|
|
|
371
355
|
WITH global_permission, global_permission_action, is_active AS gpa_is_active
|
|
372
356
|
WHERE gpa_is_active = TRUE
|
|
373
357
|
|
|
374
|
-
CALL {
|
|
375
|
-
WITH global_permission
|
|
358
|
+
CALL (global_permission) {
|
|
376
359
|
MATCH (global_permission)-[r1:HAS_ATTRIBUTE]->(:Attribute {name: "decision"})-[r2:HAS_VALUE]->(global_permission_decision:AttributeValue)
|
|
377
360
|
WHERE all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
378
361
|
RETURN global_permission_decision, (r1.status = "active" AND r2.status = "active") AS is_active
|
|
@@ -425,8 +408,7 @@ class AccountRoleObjectPermissionQuery(Query):
|
|
|
425
408
|
query = """
|
|
426
409
|
MATCH (account_role:%(account_role_node)s)
|
|
427
410
|
WHERE account_role.uuid = $role_id
|
|
428
|
-
CALL {
|
|
429
|
-
WITH account_role
|
|
411
|
+
CALL (account_role) {
|
|
430
412
|
MATCH (account_role)-[r:IS_PART_OF]-(root:Root)
|
|
431
413
|
WHERE %(branch_filter)s
|
|
432
414
|
RETURN account_role as account_role1, r as r1
|
|
@@ -437,8 +419,7 @@ class AccountRoleObjectPermissionQuery(Query):
|
|
|
437
419
|
WHERE r.status = "active"
|
|
438
420
|
WITH account_role
|
|
439
421
|
|
|
440
|
-
CALL {
|
|
441
|
-
WITH account_role
|
|
422
|
+
CALL (account_role) {
|
|
442
423
|
MATCH (account_role)-[r1:IS_RELATED]->(:Relationship {name: "role__permissions"})<-[r2:IS_RELATED]-(object_permission:%(object_permission_node)s)
|
|
443
424
|
WHERE all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
444
425
|
WITH object_permission, r1, r2, (r1.status = "active" AND r2.status = "active") AS is_active
|
|
@@ -449,8 +430,7 @@ class AccountRoleObjectPermissionQuery(Query):
|
|
|
449
430
|
}
|
|
450
431
|
WITH object_permission
|
|
451
432
|
|
|
452
|
-
CALL {
|
|
453
|
-
WITH object_permission
|
|
433
|
+
CALL (object_permission) {
|
|
454
434
|
MATCH (object_permission)-[r1:HAS_ATTRIBUTE]->(:Attribute {name: "namespace"})-[r2:HAS_VALUE]->(object_permission_namespace:AttributeValue)
|
|
455
435
|
WHERE all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
456
436
|
RETURN object_permission_namespace, (r1.status = "active" AND r2.status = "active") AS is_active
|
|
@@ -459,8 +439,7 @@ class AccountRoleObjectPermissionQuery(Query):
|
|
|
459
439
|
}
|
|
460
440
|
WITH object_permission, object_permission_namespace, is_active AS opn_is_active
|
|
461
441
|
WHERE opn_is_active = TRUE
|
|
462
|
-
CALL {
|
|
463
|
-
WITH object_permission
|
|
442
|
+
CALL (object_permission) {
|
|
464
443
|
MATCH (object_permission)-[r1:HAS_ATTRIBUTE]->(:Attribute {name: "name"})-[r2:HAS_VALUE]->(object_permission_name:AttributeValue)
|
|
465
444
|
WHERE all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
466
445
|
RETURN object_permission_name, (r1.status = "active" AND r2.status = "active") AS is_active
|
|
@@ -469,8 +448,7 @@ class AccountRoleObjectPermissionQuery(Query):
|
|
|
469
448
|
}
|
|
470
449
|
WITH object_permission, object_permission_namespace, object_permission_name, is_active AS opn_is_active
|
|
471
450
|
WHERE opn_is_active = TRUE
|
|
472
|
-
CALL {
|
|
473
|
-
WITH object_permission
|
|
451
|
+
CALL (object_permission) {
|
|
474
452
|
MATCH (object_permission)-[r1:HAS_ATTRIBUTE]->(:Attribute {name: "action"})-[r2:HAS_VALUE]->(object_permission_action:AttributeValue)
|
|
475
453
|
WHERE all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
476
454
|
RETURN object_permission_action, (r1.status = "active" AND r2.status = "active") AS is_active
|
|
@@ -479,8 +457,7 @@ class AccountRoleObjectPermissionQuery(Query):
|
|
|
479
457
|
}
|
|
480
458
|
WITH object_permission, object_permission_namespace, object_permission_name, object_permission_action, is_active AS opa_is_active
|
|
481
459
|
WHERE opa_is_active = TRUE
|
|
482
|
-
CALL {
|
|
483
|
-
WITH object_permission
|
|
460
|
+
CALL (object_permission) {
|
|
484
461
|
MATCH (object_permission)-[r1:HAS_ATTRIBUTE]->(:Attribute {name: "decision"})-[r2:HAS_VALUE]->(object_permission_decision:AttributeValue)
|
|
485
462
|
WHERE all(r IN [r1, r2] WHERE (%(branch_filter)s))
|
|
486
463
|
RETURN object_permission_decision, (r1.status = "active" AND r2.status = "active") AS is_active
|
infrahub/core/attribute.py
CHANGED
|
@@ -93,8 +93,8 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
93
93
|
updated_at: Timestamp | str | None = None,
|
|
94
94
|
is_default: bool = False,
|
|
95
95
|
is_from_profile: bool = False,
|
|
96
|
-
**kwargs,
|
|
97
|
-
):
|
|
96
|
+
**kwargs: dict[str, Any],
|
|
97
|
+
) -> None:
|
|
98
98
|
self.id = id
|
|
99
99
|
self.db_id = db_id
|
|
100
100
|
|
|
@@ -169,7 +169,7 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
169
169
|
return self.branch
|
|
170
170
|
|
|
171
171
|
@classmethod
|
|
172
|
-
def __init_subclass__(cls, **kwargs) -> None:
|
|
172
|
+
def __init_subclass__(cls, **kwargs: dict[str, Any]) -> None:
|
|
173
173
|
super().__init_subclass__(**kwargs)
|
|
174
174
|
registry.attribute[cls.__name__] = cls
|
|
175
175
|
|
|
@@ -232,7 +232,7 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
232
232
|
Raises:
|
|
233
233
|
ValidationError: Content of the attribute value is not valid
|
|
234
234
|
"""
|
|
235
|
-
if schema.
|
|
235
|
+
if regex := schema.get_regex():
|
|
236
236
|
if schema.kind == "List":
|
|
237
237
|
validation_values = [str(entry) for entry in value]
|
|
238
238
|
else:
|
|
@@ -240,22 +240,20 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
240
240
|
|
|
241
241
|
for validation_value in validation_values:
|
|
242
242
|
try:
|
|
243
|
-
is_valid = re.match(pattern=
|
|
243
|
+
is_valid = re.match(pattern=regex, string=str(validation_value))
|
|
244
244
|
except re.error as exc:
|
|
245
|
-
raise ValidationError(
|
|
246
|
-
{name: f"The regex defined in the schema is not valid ({schema.regex!r})"}
|
|
247
|
-
) from exc
|
|
245
|
+
raise ValidationError({name: f"The regex defined in the schema is not valid ({regex!r})"}) from exc
|
|
248
246
|
|
|
249
247
|
if not is_valid:
|
|
250
|
-
raise ValidationError({name: f"{validation_value} must conform with the regex: {
|
|
248
|
+
raise ValidationError({name: f"{validation_value} must conform with the regex: {regex!r}"})
|
|
251
249
|
|
|
252
|
-
if schema.
|
|
253
|
-
if len(value) <
|
|
254
|
-
raise ValidationError({name: f"{value} must have a minimum length of {
|
|
250
|
+
if min_length := schema.get_min_length():
|
|
251
|
+
if len(value) < min_length:
|
|
252
|
+
raise ValidationError({name: f"{value} must have a minimum length of {min_length!r}"})
|
|
255
253
|
|
|
256
|
-
if schema.
|
|
257
|
-
if len(value) >
|
|
258
|
-
raise ValidationError({name: f"{value} must have a maximum length of {
|
|
254
|
+
if max_length := schema.get_max_length():
|
|
255
|
+
if len(value) > max_length:
|
|
256
|
+
raise ValidationError({name: f"{value} must have a maximum length of {max_length!r}"})
|
|
259
257
|
|
|
260
258
|
if schema.enum:
|
|
261
259
|
try:
|
|
@@ -146,6 +146,11 @@ class AllowOverrideType(InfrahubStringEnum):
|
|
|
146
146
|
ANY = "any"
|
|
147
147
|
|
|
148
148
|
|
|
149
|
+
class RepositoryObjects(InfrahubStringEnum):
|
|
150
|
+
OBJECT = "object"
|
|
151
|
+
MENU = "menu"
|
|
152
|
+
|
|
153
|
+
|
|
149
154
|
class ContentType(InfrahubStringEnum):
|
|
150
155
|
APPLICATION_JSON = "application/json"
|
|
151
156
|
APPLICATION_YAML = "application/yaml"
|
|
@@ -2,6 +2,7 @@ ACCOUNT = "CoreAccount"
|
|
|
2
2
|
ACCOUNTGROUP = "CoreAccountGroup"
|
|
3
3
|
ACCOUNTROLE = "CoreAccountRole"
|
|
4
4
|
ACCOUNTTOKEN = "InternalAccountToken"
|
|
5
|
+
ACTION = "CoreAction"
|
|
5
6
|
ARTIFACT = "CoreArtifact"
|
|
6
7
|
ARTIFACTCHECK = "CoreArtifactCheck"
|
|
7
8
|
ARTIFACTDEFINITION = "CoreArtifactDefinition"
|
|
@@ -21,6 +22,7 @@ DATAVALIDATOR = "CoreDataValidator"
|
|
|
21
22
|
FILECHECK = "CoreFileCheck"
|
|
22
23
|
FILETHREAD = "CoreFileThread"
|
|
23
24
|
GENERICACCOUNT = "CoreGenericAccount"
|
|
25
|
+
GENERATORACTION = "CoreGeneratorAction"
|
|
24
26
|
GENERATORCHECK = "CoreGeneratorCheck"
|
|
25
27
|
GENERATORDEFINITION = "CoreGeneratorDefinition"
|
|
26
28
|
GENERATORINSTANCE = "CoreGeneratorInstance"
|
|
@@ -30,6 +32,8 @@ GENERICGROUP = "CoreGroup"
|
|
|
30
32
|
GLOBALPERMISSION = "CoreGlobalPermission"
|
|
31
33
|
GRAPHQLQUERY = "CoreGraphQLQuery"
|
|
32
34
|
GRAPHQLQUERYGROUP = "CoreGraphQLQueryGroup"
|
|
35
|
+
GROUPACTION = "CoreGroupAction"
|
|
36
|
+
GROUPTRIGGERRULE = "CoreGroupTriggerRule"
|
|
33
37
|
IPNAMESPACE = "BuiltinIPNamespace"
|
|
34
38
|
IPADDRESS = "BuiltinIPAddress"
|
|
35
39
|
IPADDRESSPOOL = "CoreIPAddressPool"
|
|
@@ -39,6 +43,9 @@ MENU = "CoreMenu"
|
|
|
39
43
|
MENUITEM = "CoreMenuItem"
|
|
40
44
|
NAMESPACE = "IpamNamespace"
|
|
41
45
|
NODE = "CoreNode"
|
|
46
|
+
NODETRIGGERRULE = "CoreNodeTriggerRule"
|
|
47
|
+
NODETRIGGERATTRIBUTEMATCH = "CoreNodeTriggerAttributeMatch"
|
|
48
|
+
NODETRIGGERRELATIONSHIPMATCH = "CoreNodeTriggerRelationshipMatch"
|
|
42
49
|
NUMBERPOOL = "CoreNumberPool"
|
|
43
50
|
LINEAGEOWNER = "LineageOwner"
|
|
44
51
|
LINEAGESOURCE = "LineageSource"
|
|
@@ -51,6 +58,7 @@ PROFILE = "CoreProfile"
|
|
|
51
58
|
PROPOSEDCHANGE = "CoreProposedChange"
|
|
52
59
|
REFRESHTOKEN = "InternalRefreshToken"
|
|
53
60
|
REPOSITORY = "CoreRepository"
|
|
61
|
+
REPOSITORYGROUP = "CoreRepositoryGroup"
|
|
54
62
|
RESOURCEPOOL = "CoreResourcePool"
|
|
55
63
|
GENERICREPOSITORY = "CoreGenericRepository"
|
|
56
64
|
READONLYREPOSITORY = "CoreReadOnlyRepository"
|
|
@@ -67,6 +75,7 @@ THREADCOMMENT = "CoreThreadComment"
|
|
|
67
75
|
TRANSFORM = "CoreTransformation"
|
|
68
76
|
TRANSFORMJINJA2 = "CoreTransformJinja2"
|
|
69
77
|
TRANSFORMPYTHON = "CoreTransformPython"
|
|
78
|
+
TRIGGERRULE = "CoreTriggerRule"
|
|
70
79
|
USERVALIDATOR = "CoreUserValidator"
|
|
71
80
|
VALIDATOR = "CoreValidator"
|
|
72
81
|
WEBHOOK = "CoreWebhook"
|
|
File without changes
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
|
|
5
|
+
from infrahub.core.attribute import BaseAttribute
|
|
6
|
+
from infrahub.core.branch import Branch
|
|
7
|
+
from infrahub.core.constants import RelationshipCardinality
|
|
8
|
+
from infrahub.core.manager import NodeManager
|
|
9
|
+
from infrahub.core.node import Node
|
|
10
|
+
from infrahub.core.node.create import create_node
|
|
11
|
+
from infrahub.core.query.relationship import GetAllPeersIds
|
|
12
|
+
from infrahub.core.relationship import RelationshipManager
|
|
13
|
+
from infrahub.core.schema import NodeSchema
|
|
14
|
+
from infrahub.database import InfrahubDatabase
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class InputDataForDestField(BaseModel): # Only one of these fields can be not None
|
|
18
|
+
attribute_value: Any | None = None
|
|
19
|
+
peer_id: str | None = None
|
|
20
|
+
peers_ids: list[str] | None = None
|
|
21
|
+
|
|
22
|
+
@property
|
|
23
|
+
def value(self) -> Any:
|
|
24
|
+
fields = [self.attribute_value, self.peer_id, self.peers_ids]
|
|
25
|
+
set_fields = [f for f in fields if f is not None]
|
|
26
|
+
if len(set_fields) != 1:
|
|
27
|
+
raise ValueError("Exactly one of attribute_value, peer_id, or peers_ids must be set")
|
|
28
|
+
return set_fields[0]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class InputForDestField(BaseModel): # Only one of these fields can be not None
|
|
32
|
+
source_field: str | None = None
|
|
33
|
+
data: InputDataForDestField | None = None
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def value(self) -> Any:
|
|
37
|
+
if self.source_field is not None and self.data is not None:
|
|
38
|
+
raise ValueError("Only one of source_field or data can be set")
|
|
39
|
+
if self.source_field is None and self.data is None:
|
|
40
|
+
raise ValueError("Either source_field or data must be set")
|
|
41
|
+
return self.source_field if self.source_field is not None else self.data
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
async def get_out_rels_peers_ids(node: Node, db: InfrahubDatabase) -> list[str]:
|
|
45
|
+
all_peers: list[Node] = []
|
|
46
|
+
for name in node._relationships:
|
|
47
|
+
relm: RelationshipManager = getattr(node, name)
|
|
48
|
+
peers = await relm.get_peers(db=db)
|
|
49
|
+
all_peers.extend(peers.values())
|
|
50
|
+
return [peer.id for peer in all_peers]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
async def build_data_new_node(db: InfrahubDatabase, mapping: dict[str, InputForDestField], node: Node) -> dict:
|
|
54
|
+
"""Value of a given field on the target kind to convert is either an input source attribute/relationship of the source node,
|
|
55
|
+
or a raw value."""
|
|
56
|
+
|
|
57
|
+
data = {}
|
|
58
|
+
for dest_field_name, input_for_dest_field in mapping.items():
|
|
59
|
+
value = input_for_dest_field.value
|
|
60
|
+
if isinstance(value, str): # source_field
|
|
61
|
+
item = getattr(node, value)
|
|
62
|
+
if isinstance(item, BaseAttribute):
|
|
63
|
+
data[dest_field_name] = item.value
|
|
64
|
+
elif isinstance(item, RelationshipManager):
|
|
65
|
+
if item.schema.cardinality == RelationshipCardinality.ONE:
|
|
66
|
+
peer = await item.get_peer(db=db)
|
|
67
|
+
if peer is not None:
|
|
68
|
+
data[dest_field_name] = {"id": peer.id}
|
|
69
|
+
# else, relationship is optional, and if the target relationship is mandatory an error will be raised during creation
|
|
70
|
+
elif item.schema.cardinality == RelationshipCardinality.MANY:
|
|
71
|
+
data[dest_field_name] = [{"id": peer.id} for _, peer in (await item.get_peers(db=db)).items()]
|
|
72
|
+
else:
|
|
73
|
+
raise ValueError(f"Unknown cardinality {item.schema.cardinality=}")
|
|
74
|
+
else: # user input data
|
|
75
|
+
data[dest_field_name] = value.value
|
|
76
|
+
return data
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
async def get_unidirectional_rels_peers_ids(node: Node, branch: Branch, db: InfrahubDatabase) -> list[str]:
|
|
80
|
+
"""
|
|
81
|
+
Returns peers ids of nodes connected to input `node` through an incoming unidirectional relationship.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
out_rels_identifier = [rel.identifier for rel in node.get_schema().relationships]
|
|
85
|
+
query = await GetAllPeersIds.init(db=db, node_id=node.id, branch=branch, exclude_identifiers=out_rels_identifier)
|
|
86
|
+
await query.execute(db=db)
|
|
87
|
+
return query.get_peers_uuids()
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
async def convert_object_type(
|
|
91
|
+
node: Node, target_schema: NodeSchema, mapping: dict[str, InputForDestField], branch: Branch, db: InfrahubDatabase
|
|
92
|
+
) -> Node:
|
|
93
|
+
"""Delete the node and return the new created one. If creation fails, the node is not deleted, and raise an error.
|
|
94
|
+
An extra check is performed on input node peers relationships to make sure they are still valid."""
|
|
95
|
+
|
|
96
|
+
node_schema = node.get_schema()
|
|
97
|
+
if not isinstance(node_schema, NodeSchema):
|
|
98
|
+
raise ValueError(f"Only a node with a NodeSchema can be converted, got {type(node_schema)}")
|
|
99
|
+
|
|
100
|
+
async with db.start_transaction() as dbt: # noqa: PLR1702
|
|
101
|
+
deleted_node_out_rels_peer_ids = await get_out_rels_peers_ids(node=node, db=dbt)
|
|
102
|
+
deleted_node_unidir_rels_peer_ids = await get_unidirectional_rels_peers_ids(node=node, db=dbt, branch=branch)
|
|
103
|
+
|
|
104
|
+
deleted_nodes = await NodeManager.delete(db=dbt, branch=branch, nodes=[node], cascade_delete=False)
|
|
105
|
+
if len(deleted_nodes) != 1:
|
|
106
|
+
raise ValueError(f"Deleted {len(deleted_nodes)} nodes instead of 1")
|
|
107
|
+
|
|
108
|
+
data_new_node = await build_data_new_node(dbt, mapping, node)
|
|
109
|
+
node_created = await create_node(
|
|
110
|
+
data=data_new_node,
|
|
111
|
+
db=dbt,
|
|
112
|
+
branch=branch,
|
|
113
|
+
schema=target_schema,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# Make sure relationships with constraints are not broken by retrieving them
|
|
117
|
+
peers_ids = deleted_node_out_rels_peer_ids + deleted_node_unidir_rels_peer_ids
|
|
118
|
+
peers = await NodeManager.get_many(ids=peers_ids, db=dbt, prefetch_relationships=True, branch=branch)
|
|
119
|
+
for peer in peers.values():
|
|
120
|
+
peer.validate_relationships()
|
|
121
|
+
|
|
122
|
+
return node_created
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from pydantic import BaseModel
|
|
2
|
+
|
|
3
|
+
from infrahub.core.constants import RelationshipCardinality
|
|
4
|
+
from infrahub.core.schema import NodeSchema
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class SchemaMappingValue(BaseModel):
|
|
8
|
+
is_mandatory: bool
|
|
9
|
+
source_field_name: str | None = None # None means there is no corresponding source field name
|
|
10
|
+
relationship_cardinality: RelationshipCardinality | None = None
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
SchemaMapping = dict[str, SchemaMappingValue]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def get_schema_mapping(source_schema: NodeSchema, target_schema: NodeSchema) -> SchemaMapping:
|
|
17
|
+
"""
|
|
18
|
+
Return fields mapping meant to be used for converting a node from `source_kind` to `target_kind`.
|
|
19
|
+
For any field of the target kind, field of the source kind will be matched if:
|
|
20
|
+
- It's an attribute with identical name and type.
|
|
21
|
+
- It's a relationship with identical peer kind and cardinality.
|
|
22
|
+
If there is no match, the mapping will only indicate whether the field is mandatory or not.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
target_field_to_source_field = {}
|
|
26
|
+
|
|
27
|
+
# Create lookup dictionaries for source attributes and relationships
|
|
28
|
+
source_attrs = {attr.name: attr for attr in source_schema.attributes}
|
|
29
|
+
source_rels = {rel.name: rel for rel in source_schema.relationships}
|
|
30
|
+
|
|
31
|
+
# Process attributes
|
|
32
|
+
for target_attr in target_schema.attributes:
|
|
33
|
+
source_attr = source_attrs.get(target_attr.name)
|
|
34
|
+
if source_attr and source_attr.kind == target_attr.kind:
|
|
35
|
+
target_field_to_source_field[target_attr.name] = SchemaMappingValue(
|
|
36
|
+
source_field_name=source_attr.name, is_mandatory=not target_attr.optional
|
|
37
|
+
)
|
|
38
|
+
else:
|
|
39
|
+
target_field_to_source_field[target_attr.name] = SchemaMappingValue(is_mandatory=not target_attr.optional)
|
|
40
|
+
|
|
41
|
+
# Process relationships
|
|
42
|
+
for target_rel in target_schema.relationships:
|
|
43
|
+
source_rel = source_rels.get(target_rel.name)
|
|
44
|
+
if source_rel and source_rel.peer == target_rel.peer and source_rel.cardinality == target_rel.cardinality:
|
|
45
|
+
target_field_to_source_field[target_rel.name] = SchemaMappingValue(
|
|
46
|
+
source_field_name=source_rel.name,
|
|
47
|
+
is_mandatory=not target_rel.optional,
|
|
48
|
+
relationship_cardinality=target_rel.cardinality,
|
|
49
|
+
)
|
|
50
|
+
else:
|
|
51
|
+
target_field_to_source_field[target_rel.name] = SchemaMappingValue(
|
|
52
|
+
is_mandatory=not target_rel.optional,
|
|
53
|
+
relationship_cardinality=target_rel.cardinality,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
return target_field_to_source_field
|
|
@@ -37,22 +37,18 @@ AND (
|
|
|
37
37
|
($diff_id IS NOT NULL AND root.uuid = $diff_id)
|
|
38
38
|
OR ($tracking_id IS NOT NULL AND root.tracking_id = $tracking_id AND root.diff_branch = $diff_branch_name)
|
|
39
39
|
)
|
|
40
|
-
CALL {
|
|
41
|
-
WITH root
|
|
40
|
+
CALL (root) {
|
|
42
41
|
MATCH (root)-[:DIFF_HAS_NODE]->(node:DiffNode)-[:DIFF_HAS_CONFLICT]->(node_conflict:DiffConflict)
|
|
43
42
|
RETURN node.path_identifier AS path_identifier, node_conflict AS conflict
|
|
44
43
|
UNION
|
|
45
|
-
WITH root
|
|
46
44
|
MATCH (root)-[:DIFF_HAS_NODE]->(node:DiffNode)-[:DIFF_HAS_ATTRIBUTE]->(:DiffAttribute)
|
|
47
45
|
-[:DIFF_HAS_PROPERTY]->(property:DiffProperty)-[:DIFF_HAS_CONFLICT]->(attr_property_conflict:DiffConflict)
|
|
48
46
|
RETURN property.path_identifier AS path_identifier, attr_property_conflict AS conflict
|
|
49
47
|
UNION
|
|
50
|
-
WITH root
|
|
51
48
|
MATCH (root)-[:DIFF_HAS_NODE]->(node:DiffNode)-[:DIFF_HAS_RELATIONSHIP]->(:DiffRelationship)
|
|
52
49
|
-[:DIFF_HAS_ELEMENT]->(element:DiffRelationshipElement)-[:DIFF_HAS_CONFLICT]->(rel_element_conflict:DiffConflict)
|
|
53
50
|
RETURN element.path_identifier AS path_identifier, rel_element_conflict AS conflict
|
|
54
51
|
UNION
|
|
55
|
-
WITH root
|
|
56
52
|
MATCH (root)-[:DIFF_HAS_NODE]->(node:DiffNode)-[:DIFF_HAS_RELATIONSHIP]->(:DiffRelationship)
|
|
57
53
|
-[:DIFF_HAS_ELEMENT]->(:DiffRelationshipElement)-[:DIFF_HAS_PROPERTY]->(property:DiffProperty)
|
|
58
54
|
-[:DIFF_HAS_CONFLICT]->(rel_property_conflict:DiffConflict)
|
|
@@ -40,8 +40,7 @@ class ArtifactDiffQuery(Query):
|
|
|
40
40
|
// -----------------------
|
|
41
41
|
MATCH (source_artifact:%(artifact_kind)s)-[r:IS_PART_OF]->(:Root)
|
|
42
42
|
WHERE r.branch IN [$source_branch_name, $target_branch_name]
|
|
43
|
-
CALL {
|
|
44
|
-
WITH source_artifact
|
|
43
|
+
CALL (source_artifact) {
|
|
45
44
|
MATCH (source_artifact)-[r:IS_PART_OF]->(:Root)
|
|
46
45
|
WHERE %(source_branch_filter)s
|
|
47
46
|
RETURN r AS root_rel
|
|
@@ -50,13 +49,11 @@ CALL {
|
|
|
50
49
|
}
|
|
51
50
|
WITH source_artifact, root_rel
|
|
52
51
|
WHERE root_rel.status = "active"
|
|
53
|
-
CALL {
|
|
54
|
-
WITH source_artifact
|
|
52
|
+
CALL (source_artifact) {
|
|
55
53
|
// -----------------------
|
|
56
54
|
// get the artifact's target node
|
|
57
55
|
// -----------------------
|
|
58
|
-
CALL {
|
|
59
|
-
WITH source_artifact
|
|
56
|
+
CALL (source_artifact) {
|
|
60
57
|
OPTIONAL MATCH (source_artifact)-[rrel1:IS_RELATED]-(rel_node:Relationship)-[rrel2:IS_RELATED]-(target_node:Node)
|
|
61
58
|
WHERE rel_node.name = $target_rel_identifier
|
|
62
59
|
AND all(r IN [rrel1, rrel2] WHERE ( %(source_branch_filter)s ))
|
|
@@ -70,8 +67,7 @@ CALL {
|
|
|
70
67
|
// -----------------------
|
|
71
68
|
// get the artifact's definition node
|
|
72
69
|
// -----------------------
|
|
73
|
-
CALL {
|
|
74
|
-
WITH source_artifact
|
|
70
|
+
CALL (source_artifact) {
|
|
75
71
|
OPTIONAL MATCH (source_artifact)-[rrel1:IS_RELATED]-(rel_node:Relationship)-[rrel2:IS_RELATED]-(definition_node:Node)
|
|
76
72
|
WHERE rel_node.name = $definition_rel_identifier
|
|
77
73
|
AND all(r IN [rrel1, rrel2] WHERE ( %(source_branch_filter)s ))
|
|
@@ -85,8 +81,7 @@ CALL {
|
|
|
85
81
|
// -----------------------
|
|
86
82
|
// get the artifact's checksum
|
|
87
83
|
// -----------------------
|
|
88
|
-
CALL {
|
|
89
|
-
WITH source_artifact
|
|
84
|
+
CALL (source_artifact) {
|
|
90
85
|
OPTIONAL MATCH (source_artifact)-[attr_rel:HAS_ATTRIBUTE]->(attr:Attribute)-[value_rel:HAS_VALUE]->(attr_val:AttributeValue)
|
|
91
86
|
WHERE attr.name = "checksum"
|
|
92
87
|
AND all(r IN [attr_rel, value_rel] WHERE ( %(source_branch_filter)s ))
|
|
@@ -100,8 +95,7 @@ CALL {
|
|
|
100
95
|
// -----------------------
|
|
101
96
|
// get the artifact's storage_id
|
|
102
97
|
// -----------------------
|
|
103
|
-
CALL {
|
|
104
|
-
WITH source_artifact
|
|
98
|
+
CALL (source_artifact) {
|
|
105
99
|
OPTIONAL MATCH (source_artifact)-[attr_rel:HAS_ATTRIBUTE]->(attr:Attribute)-[value_rel:HAS_VALUE]->(attr_val:AttributeValue)
|
|
106
100
|
WHERE attr.name = "storage_id"
|
|
107
101
|
AND all(r IN [attr_rel, value_rel] WHERE ( %(source_branch_filter)s ))
|
|
@@ -137,13 +131,11 @@ CALL {
|
|
|
137
131
|
ELSE NULL
|
|
138
132
|
END AS source_storage_id
|
|
139
133
|
}
|
|
140
|
-
CALL {
|
|
134
|
+
CALL (target_node, definition_node){
|
|
141
135
|
// -----------------------
|
|
142
136
|
// get the corresponding artifact on the target branch, if it exists
|
|
143
137
|
// -----------------------
|
|
144
|
-
|
|
145
|
-
CALL {
|
|
146
|
-
WITH target_node, definition_node
|
|
138
|
+
CALL (target_node, definition_node) {
|
|
147
139
|
OPTIONAL MATCH path = (target_node)-[trel1:IS_RELATED]-(trel_node:Relationship)-[trel2:IS_RELATED]-
|
|
148
140
|
(target_artifact:%(artifact_kind)s)-[drel1:IS_RELATED]-(drel_node:Relationship)-[drel2:IS_RELATED]-(definition_node)
|
|
149
141
|
WHERE trel_node.name = $target_rel_identifier
|
|
@@ -165,8 +157,7 @@ CALL {
|
|
|
165
157
|
// -----------------------
|
|
166
158
|
// get the artifact's checksum on target branch
|
|
167
159
|
// -----------------------
|
|
168
|
-
CALL {
|
|
169
|
-
WITH target_artifact
|
|
160
|
+
CALL (target_artifact) {
|
|
170
161
|
OPTIONAL MATCH (target_artifact)-[attr_rel:HAS_ATTRIBUTE]->(attr:Attribute)-[value_rel:HAS_VALUE]->(attr_val:AttributeValue)
|
|
171
162
|
WHERE attr.name = "checksum"
|
|
172
163
|
AND attr_rel.branch = $target_branch_name
|
|
@@ -178,8 +169,7 @@ CALL {
|
|
|
178
169
|
// -----------------------
|
|
179
170
|
// get the artifact's storage_id on target branch
|
|
180
171
|
// -----------------------
|
|
181
|
-
CALL {
|
|
182
|
-
WITH target_artifact
|
|
172
|
+
CALL (target_artifact) {
|
|
183
173
|
OPTIONAL MATCH (target_artifact)-[attr_rel:HAS_ATTRIBUTE]->(attr:Attribute)-[value_rel:HAS_VALUE]->(attr_val:AttributeValue)
|
|
184
174
|
WHERE attr.name = "storage_id"
|
|
185
175
|
AND attr_rel.branch = $target_branch_name
|