infrahub-server 1.4.12__py3-none-any.whl → 1.5.0__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/tasks.py +208 -16
- infrahub/api/artifact.py +3 -0
- infrahub/api/diff/diff.py +1 -1
- infrahub/api/internal.py +2 -0
- infrahub/api/query.py +2 -0
- infrahub/api/schema.py +27 -3
- infrahub/auth.py +5 -5
- infrahub/cli/__init__.py +2 -0
- infrahub/cli/db.py +160 -157
- infrahub/cli/dev.py +118 -0
- infrahub/cli/tasks.py +46 -0
- infrahub/cli/upgrade.py +56 -9
- infrahub/computed_attribute/tasks.py +19 -7
- infrahub/config.py +7 -2
- infrahub/core/attribute.py +35 -24
- infrahub/core/branch/enums.py +1 -1
- infrahub/core/branch/models.py +9 -5
- infrahub/core/branch/needs_rebase_status.py +11 -0
- infrahub/core/branch/tasks.py +72 -10
- infrahub/core/changelog/models.py +2 -10
- infrahub/core/constants/__init__.py +4 -0
- infrahub/core/constants/infrahubkind.py +1 -0
- infrahub/core/convert_object_type/object_conversion.py +201 -0
- infrahub/core/convert_object_type/repository_conversion.py +89 -0
- infrahub/core/convert_object_type/schema_mapping.py +27 -3
- infrahub/core/diff/calculator.py +2 -2
- infrahub/core/diff/model/path.py +4 -0
- infrahub/core/diff/payload_builder.py +1 -1
- infrahub/core/diff/query/artifact.py +1 -0
- infrahub/core/diff/query/delete_query.py +9 -5
- infrahub/core/diff/query/field_summary.py +1 -0
- infrahub/core/diff/query/merge.py +39 -23
- infrahub/core/graph/__init__.py +1 -1
- infrahub/core/initialization.py +7 -4
- infrahub/core/manager.py +3 -81
- infrahub/core/migrations/__init__.py +3 -0
- infrahub/core/migrations/exceptions.py +4 -0
- infrahub/core/migrations/graph/__init__.py +13 -10
- infrahub/core/migrations/graph/load_schema_branch.py +21 -0
- infrahub/core/migrations/graph/m013_convert_git_password_credential.py +1 -1
- infrahub/core/migrations/graph/m037_index_attr_vals.py +11 -30
- infrahub/core/migrations/graph/m039_ipam_reconcile.py +9 -7
- infrahub/core/migrations/graph/m041_deleted_dup_edges.py +149 -0
- infrahub/core/migrations/graph/m042_profile_attrs_in_db.py +147 -0
- infrahub/core/migrations/graph/m043_create_hfid_display_label_in_db.py +164 -0
- infrahub/core/migrations/graph/m044_backfill_hfid_display_label_in_db.py +864 -0
- infrahub/core/migrations/query/__init__.py +7 -8
- infrahub/core/migrations/query/attribute_add.py +8 -6
- infrahub/core/migrations/query/attribute_remove.py +134 -0
- infrahub/core/migrations/runner.py +54 -0
- infrahub/core/migrations/schema/attribute_kind_update.py +9 -3
- infrahub/core/migrations/schema/attribute_supports_profile.py +90 -0
- infrahub/core/migrations/schema/node_attribute_add.py +26 -5
- infrahub/core/migrations/schema/node_attribute_remove.py +13 -109
- infrahub/core/migrations/schema/node_kind_update.py +2 -1
- infrahub/core/migrations/schema/node_remove.py +2 -1
- infrahub/core/migrations/schema/placeholder_dummy.py +3 -2
- infrahub/core/migrations/shared.py +66 -19
- infrahub/core/models.py +2 -2
- infrahub/core/node/__init__.py +207 -54
- infrahub/core/node/create.py +53 -49
- infrahub/core/node/lock_utils.py +124 -0
- infrahub/core/node/node_property_attribute.py +230 -0
- infrahub/core/node/resource_manager/ip_address_pool.py +2 -1
- infrahub/core/node/resource_manager/ip_prefix_pool.py +2 -1
- infrahub/core/node/resource_manager/number_pool.py +2 -1
- infrahub/core/node/standard.py +1 -1
- infrahub/core/property.py +11 -0
- infrahub/core/protocols.py +8 -1
- infrahub/core/query/attribute.py +82 -15
- infrahub/core/query/diff.py +61 -16
- infrahub/core/query/ipam.py +16 -4
- infrahub/core/query/node.py +92 -212
- infrahub/core/query/relationship.py +44 -26
- infrahub/core/query/subquery.py +0 -8
- infrahub/core/relationship/model.py +69 -24
- infrahub/core/schema/__init__.py +56 -0
- infrahub/core/schema/attribute_schema.py +4 -2
- infrahub/core/schema/basenode_schema.py +42 -2
- infrahub/core/schema/definitions/core/__init__.py +2 -0
- infrahub/core/schema/definitions/core/check.py +1 -1
- infrahub/core/schema/definitions/core/generator.py +2 -0
- infrahub/core/schema/definitions/core/group.py +16 -2
- infrahub/core/schema/definitions/core/repository.py +7 -0
- infrahub/core/schema/definitions/core/transform.py +1 -1
- infrahub/core/schema/definitions/internal.py +12 -3
- infrahub/core/schema/generated/attribute_schema.py +2 -2
- infrahub/core/schema/generated/base_node_schema.py +6 -1
- infrahub/core/schema/manager.py +3 -0
- infrahub/core/schema/node_schema.py +1 -0
- infrahub/core/schema/relationship_schema.py +0 -1
- infrahub/core/schema/schema_branch.py +295 -10
- infrahub/core/schema/schema_branch_display.py +135 -0
- infrahub/core/schema/schema_branch_hfid.py +120 -0
- infrahub/core/validators/aggregated_checker.py +1 -1
- infrahub/database/graph.py +21 -0
- infrahub/display_labels/__init__.py +0 -0
- infrahub/display_labels/gather.py +48 -0
- infrahub/display_labels/models.py +240 -0
- infrahub/display_labels/tasks.py +192 -0
- infrahub/display_labels/triggers.py +22 -0
- infrahub/events/branch_action.py +27 -1
- infrahub/events/group_action.py +1 -1
- infrahub/events/node_action.py +1 -1
- infrahub/generators/constants.py +7 -0
- infrahub/generators/models.py +38 -12
- infrahub/generators/tasks.py +34 -16
- infrahub/git/base.py +42 -2
- infrahub/git/integrator.py +22 -14
- infrahub/git/tasks.py +52 -2
- infrahub/graphql/analyzer.py +9 -0
- infrahub/graphql/api/dependencies.py +2 -4
- infrahub/graphql/api/endpoints.py +16 -6
- infrahub/graphql/app.py +2 -4
- infrahub/graphql/initialization.py +2 -3
- infrahub/graphql/manager.py +213 -137
- infrahub/graphql/middleware.py +12 -0
- infrahub/graphql/mutations/branch.py +16 -0
- infrahub/graphql/mutations/computed_attribute.py +110 -3
- infrahub/graphql/mutations/convert_object_type.py +44 -13
- infrahub/graphql/mutations/display_label.py +118 -0
- infrahub/graphql/mutations/generator.py +25 -7
- infrahub/graphql/mutations/hfid.py +125 -0
- infrahub/graphql/mutations/ipam.py +73 -41
- infrahub/graphql/mutations/main.py +61 -178
- infrahub/graphql/mutations/profile.py +195 -0
- infrahub/graphql/mutations/proposed_change.py +8 -1
- infrahub/graphql/mutations/relationship.py +2 -2
- infrahub/graphql/mutations/repository.py +22 -83
- infrahub/graphql/mutations/resource_manager.py +2 -2
- infrahub/graphql/mutations/webhook.py +1 -1
- infrahub/graphql/queries/resource_manager.py +1 -1
- infrahub/graphql/registry.py +173 -0
- infrahub/graphql/resolvers/resolver.py +2 -0
- infrahub/graphql/schema.py +8 -1
- infrahub/graphql/schema_sort.py +170 -0
- infrahub/graphql/types/branch.py +4 -1
- infrahub/graphql/types/enums.py +3 -0
- infrahub/groups/tasks.py +1 -1
- infrahub/hfid/__init__.py +0 -0
- infrahub/hfid/gather.py +48 -0
- infrahub/hfid/models.py +240 -0
- infrahub/hfid/tasks.py +191 -0
- infrahub/hfid/triggers.py +22 -0
- infrahub/lock.py +119 -42
- infrahub/locks/__init__.py +0 -0
- infrahub/locks/tasks.py +37 -0
- infrahub/message_bus/types.py +1 -0
- infrahub/patch/plan_writer.py +2 -2
- infrahub/permissions/constants.py +2 -0
- infrahub/profiles/__init__.py +0 -0
- infrahub/profiles/node_applier.py +101 -0
- infrahub/profiles/queries/__init__.py +0 -0
- infrahub/profiles/queries/get_profile_data.py +98 -0
- infrahub/profiles/tasks.py +63 -0
- infrahub/proposed_change/tasks.py +67 -14
- infrahub/repositories/__init__.py +0 -0
- infrahub/repositories/create_repository.py +113 -0
- infrahub/server.py +9 -1
- infrahub/services/__init__.py +8 -5
- infrahub/services/adapters/http/__init__.py +5 -0
- infrahub/services/adapters/workflow/worker.py +14 -3
- infrahub/task_manager/event.py +5 -0
- infrahub/task_manager/models.py +7 -0
- infrahub/task_manager/task.py +73 -0
- infrahub/tasks/registry.py +6 -4
- infrahub/trigger/catalogue.py +4 -0
- infrahub/trigger/models.py +2 -0
- infrahub/trigger/setup.py +13 -4
- infrahub/trigger/tasks.py +6 -0
- infrahub/webhook/models.py +1 -1
- infrahub/workers/dependencies.py +3 -1
- infrahub/workers/infrahub_async.py +10 -2
- infrahub/workflows/catalogue.py +118 -3
- infrahub/workflows/initialization.py +21 -0
- infrahub/workflows/models.py +17 -2
- infrahub/workflows/utils.py +2 -1
- infrahub_sdk/branch.py +17 -8
- infrahub_sdk/checks.py +1 -1
- infrahub_sdk/client.py +376 -95
- infrahub_sdk/config.py +29 -2
- infrahub_sdk/convert_object_type.py +61 -0
- infrahub_sdk/ctl/branch.py +3 -0
- infrahub_sdk/ctl/check.py +2 -3
- infrahub_sdk/ctl/cli_commands.py +20 -12
- infrahub_sdk/ctl/config.py +8 -2
- infrahub_sdk/ctl/generator.py +6 -3
- infrahub_sdk/ctl/graphql.py +184 -0
- infrahub_sdk/ctl/repository.py +39 -1
- infrahub_sdk/ctl/schema.py +40 -10
- infrahub_sdk/ctl/task.py +110 -0
- infrahub_sdk/ctl/utils.py +4 -0
- infrahub_sdk/ctl/validate.py +5 -3
- infrahub_sdk/diff.py +4 -5
- infrahub_sdk/exceptions.py +2 -0
- infrahub_sdk/generator.py +7 -1
- infrahub_sdk/graphql/__init__.py +12 -0
- infrahub_sdk/graphql/constants.py +1 -0
- infrahub_sdk/graphql/plugin.py +85 -0
- infrahub_sdk/graphql/query.py +77 -0
- infrahub_sdk/{graphql.py → graphql/renderers.py} +88 -75
- infrahub_sdk/graphql/utils.py +40 -0
- infrahub_sdk/node/attribute.py +2 -0
- infrahub_sdk/node/node.py +28 -20
- infrahub_sdk/node/relationship.py +1 -3
- infrahub_sdk/playback.py +1 -2
- infrahub_sdk/protocols.py +54 -6
- infrahub_sdk/pytest_plugin/plugin.py +7 -4
- infrahub_sdk/pytest_plugin/utils.py +40 -0
- infrahub_sdk/repository.py +1 -2
- infrahub_sdk/schema/__init__.py +70 -4
- infrahub_sdk/schema/main.py +1 -0
- infrahub_sdk/schema/repository.py +8 -0
- infrahub_sdk/spec/models.py +7 -0
- infrahub_sdk/spec/object.py +54 -6
- infrahub_sdk/spec/processors/__init__.py +0 -0
- infrahub_sdk/spec/processors/data_processor.py +10 -0
- infrahub_sdk/spec/processors/factory.py +34 -0
- infrahub_sdk/spec/processors/range_expand_processor.py +56 -0
- infrahub_sdk/spec/range_expansion.py +118 -0
- infrahub_sdk/task/models.py +6 -4
- infrahub_sdk/timestamp.py +18 -6
- infrahub_sdk/transforms.py +1 -1
- {infrahub_server-1.4.12.dist-info → infrahub_server-1.5.0.dist-info}/METADATA +9 -10
- {infrahub_server-1.4.12.dist-info → infrahub_server-1.5.0.dist-info}/RECORD +233 -176
- infrahub_testcontainers/container.py +114 -2
- infrahub_testcontainers/docker-compose-cluster.test.yml +5 -0
- infrahub_testcontainers/docker-compose.test.yml +5 -0
- infrahub_testcontainers/models.py +2 -2
- infrahub_testcontainers/performance_test.py +4 -4
- infrahub/core/convert_object_type/conversion.py +0 -134
- {infrahub_server-1.4.12.dist-info → infrahub_server-1.5.0.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.4.12.dist-info → infrahub_server-1.5.0.dist-info}/WHEEL +0 -0
- {infrahub_server-1.4.12.dist-info → infrahub_server-1.5.0.dist-info}/entry_points.txt +0 -0
infrahub/core/query/attribute.py
CHANGED
|
@@ -133,7 +133,7 @@ class AttributeUpdateNodePropertyQuery(AttributeQuery):
|
|
|
133
133
|
def __init__(
|
|
134
134
|
self,
|
|
135
135
|
prop_name: str,
|
|
136
|
-
prop_id: str,
|
|
136
|
+
prop_id: str | None = None,
|
|
137
137
|
**kwargs: Any,
|
|
138
138
|
):
|
|
139
139
|
self.prop_name = prop_name
|
|
@@ -144,6 +144,8 @@ class AttributeUpdateNodePropertyQuery(AttributeQuery):
|
|
|
144
144
|
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
|
|
145
145
|
at = self.at or self.attr.at
|
|
146
146
|
|
|
147
|
+
branch_filter, branch_params = self.branch.get_query_filter_path(at=at)
|
|
148
|
+
self.params.update(branch_params)
|
|
147
149
|
self.params["attr_uuid"] = self.attr.id
|
|
148
150
|
self.params["branch"] = self.branch.name
|
|
149
151
|
self.params["branch_level"] = self.branch.hierarchy_level
|
|
@@ -151,21 +153,92 @@ class AttributeUpdateNodePropertyQuery(AttributeQuery):
|
|
|
151
153
|
self.params["prop_name"] = self.prop_name
|
|
152
154
|
self.params["prop_id"] = self.prop_id
|
|
153
155
|
|
|
154
|
-
|
|
156
|
+
rel_label = f"HAS_{self.prop_name.upper()}"
|
|
155
157
|
|
|
156
|
-
|
|
158
|
+
if self.branch.is_default or self.branch.is_global:
|
|
159
|
+
node_query = """
|
|
160
|
+
MATCH (np:Node { uuid: $prop_id })-[r:IS_PART_OF]->(:Root)
|
|
161
|
+
WHERE r.branch IN $branch0
|
|
162
|
+
AND r.status = "active"
|
|
163
|
+
AND r.from <= $at AND (r.to IS NULL OR r.to > $at)
|
|
164
|
+
WITH np
|
|
165
|
+
LIMIT 1
|
|
157
166
|
"""
|
|
167
|
+
else:
|
|
168
|
+
node_query = """
|
|
169
|
+
MATCH (np:Node { uuid: $prop_id })-[r:IS_PART_OF]->(:Root)
|
|
170
|
+
WHERE %(branch_filter)s
|
|
171
|
+
ORDER BY r.branch_level DESC, r.from DESC, r.status ASC
|
|
172
|
+
LIMIT 1
|
|
173
|
+
WITH np
|
|
174
|
+
WHERE r.status = "active"
|
|
175
|
+
""" % {"branch_filter": branch_filter}
|
|
176
|
+
self.add_to_query(node_query)
|
|
177
|
+
|
|
178
|
+
attr_query = """
|
|
158
179
|
MATCH (a:Attribute { uuid: $attr_uuid })
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
% rel_name
|
|
163
|
-
)
|
|
180
|
+
CREATE (a)-[r:%(rel_label)s { branch: $branch, branch_level: $branch_level, status: "active", from: $at }]->(np)
|
|
181
|
+
""" % {"rel_label": rel_label}
|
|
182
|
+
self.add_to_query(attr_query)
|
|
164
183
|
|
|
165
|
-
self.add_to_query(query)
|
|
166
184
|
self.return_labels = ["a", "np", "r"]
|
|
167
185
|
|
|
168
186
|
|
|
187
|
+
class AttributeClearNodePropertyQuery(AttributeQuery):
|
|
188
|
+
name = "attribute_clear_node_property"
|
|
189
|
+
type: QueryType = QueryType.WRITE
|
|
190
|
+
insert_return: bool = False
|
|
191
|
+
|
|
192
|
+
def __init__(
|
|
193
|
+
self,
|
|
194
|
+
prop_name: str,
|
|
195
|
+
prop_id: str | None = None,
|
|
196
|
+
**kwargs: Any,
|
|
197
|
+
):
|
|
198
|
+
self.prop_name = prop_name
|
|
199
|
+
self.prop_id = prop_id
|
|
200
|
+
|
|
201
|
+
super().__init__(**kwargs)
|
|
202
|
+
|
|
203
|
+
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
|
|
204
|
+
at = self.at or self.attr.at
|
|
205
|
+
|
|
206
|
+
branch_filter, branch_params = self.branch.get_query_filter_path(at=at)
|
|
207
|
+
self.params.update(branch_params)
|
|
208
|
+
self.params["attr_uuid"] = self.attr.id
|
|
209
|
+
self.params["branch"] = self.branch.name
|
|
210
|
+
self.params["branch_level"] = self.branch.hierarchy_level
|
|
211
|
+
self.params["at"] = at.to_string()
|
|
212
|
+
self.params["prop_name"] = self.prop_name
|
|
213
|
+
self.params["prop_id"] = self.prop_id
|
|
214
|
+
|
|
215
|
+
rel_label = f"HAS_{self.prop_name.upper()}"
|
|
216
|
+
query = """
|
|
217
|
+
MATCH (a:Attribute { uuid: $attr_uuid })-[r:%(rel_label)s]->(np:Node { uuid: $prop_id })
|
|
218
|
+
WITH DISTINCT a, np
|
|
219
|
+
CALL (a, np) {
|
|
220
|
+
MATCH (a)-[r:%(rel_label)s]->(np)
|
|
221
|
+
WHERE %(branch_filter)s
|
|
222
|
+
ORDER BY r.branch_level DESC, r.from DESC, r.status ASC
|
|
223
|
+
LIMIT 1
|
|
224
|
+
RETURN r AS property_edge
|
|
225
|
+
}
|
|
226
|
+
WITH a, np, property_edge
|
|
227
|
+
WHERE property_edge.status = "active"
|
|
228
|
+
CALL (property_edge) {
|
|
229
|
+
WITH property_edge
|
|
230
|
+
WHERE property_edge.branch = $branch
|
|
231
|
+
SET property_edge.to = $at
|
|
232
|
+
}
|
|
233
|
+
CALL (a, np, property_edge) {
|
|
234
|
+
WITH property_edge
|
|
235
|
+
WHERE property_edge.branch_level < $branch_level
|
|
236
|
+
CREATE (a)-[r:%(rel_label)s { branch: $branch, branch_level: $branch_level, status: "deleted", from: $at }]->(np)
|
|
237
|
+
}
|
|
238
|
+
""" % {"branch_filter": branch_filter, "rel_label": rel_label}
|
|
239
|
+
self.add_to_query(query)
|
|
240
|
+
|
|
241
|
+
|
|
169
242
|
class AttributeGetQuery(AttributeQuery):
|
|
170
243
|
name = "attribute_get"
|
|
171
244
|
type: QueryType = QueryType.READ
|
|
@@ -204,7 +277,6 @@ async def default_attribute_query_filter(
|
|
|
204
277
|
param_prefix: str | None = None,
|
|
205
278
|
db: InfrahubDatabase | None = None, # noqa: ARG001
|
|
206
279
|
partial_match: bool = False,
|
|
207
|
-
support_profiles: bool = False,
|
|
208
280
|
) -> tuple[list[QueryElement], dict[str, Any], list[str]]:
|
|
209
281
|
"""Generate Query String Snippet to filter the right node."""
|
|
210
282
|
attribute_value_label = GraphAttributeValueNode.get_default_label()
|
|
@@ -251,9 +323,6 @@ async def default_attribute_query_filter(
|
|
|
251
323
|
query_where.append(f"toString(av.{filter_name}) =~ ${param_prefix}_{filter_name}")
|
|
252
324
|
elif filter_name == "isnull":
|
|
253
325
|
query_filter.append(QueryNode(name="av", labels=[attribute_value_label]))
|
|
254
|
-
elif support_profiles:
|
|
255
|
-
query_filter.append(QueryNode(name="av", labels=[attribute_value_label]))
|
|
256
|
-
query_where.append(f"(av.{filter_name} = ${param_prefix}_{filter_name} OR av.is_default)")
|
|
257
326
|
else:
|
|
258
327
|
query_filter.append(
|
|
259
328
|
QueryNode(
|
|
@@ -271,8 +340,6 @@ async def default_attribute_query_filter(
|
|
|
271
340
|
if attribute_kind and attribute_kind == "List":
|
|
272
341
|
query_params[f"{param_prefix}_{filter_name}"] = build_regex_attrs(values=filter_value)
|
|
273
342
|
query_where.append(f"toString(av.value) =~ ${param_prefix}_{filter_name}")
|
|
274
|
-
elif support_profiles:
|
|
275
|
-
query_where.append(f"(av.value IN ${param_prefix}_value OR av.is_default)")
|
|
276
343
|
else:
|
|
277
344
|
query_where.append(f"av.value IN ${param_prefix}_value")
|
|
278
345
|
query_params[f"{param_prefix}_value"] = filter_value
|
infrahub/core/query/diff.py
CHANGED
|
@@ -301,13 +301,15 @@ WITH p, q, diff_rel, CASE
|
|
|
301
301
|
ELSE $from_time
|
|
302
302
|
END AS row_from_time
|
|
303
303
|
ORDER BY %(id_func)s(p) DESC
|
|
304
|
-
SKIP $offset
|
|
305
|
-
LIMIT $limit
|
|
304
|
+
SKIP toInteger($offset)
|
|
305
|
+
LIMIT toInteger($limit)
|
|
306
306
|
// -------------------------------------
|
|
307
307
|
// Add flag to indicate if there is more data after this
|
|
308
308
|
// -------------------------------------
|
|
309
309
|
WITH collect([p, q, diff_rel, row_from_time]) AS limited_results
|
|
310
|
-
|
|
310
|
+
// extra NULL row ensures that has_more_data is always returned, even if all results are filtered out below
|
|
311
|
+
WITH limited_results + [[NULL, NULL, NULL, NULL]] AS limited_results
|
|
312
|
+
WITH limited_results, size(limited_results) = ($limit + 1) AS has_more_data
|
|
311
313
|
UNWIND limited_results AS one_result
|
|
312
314
|
WITH one_result[0] AS p, one_result[1] AS q, one_result[2] AS diff_rel, one_result[3] AS row_from_time, has_more_data
|
|
313
315
|
// -------------------------------------
|
|
@@ -470,14 +472,16 @@ AND (
|
|
|
470
472
|
// Limit the number of paths
|
|
471
473
|
// -------------------------------------
|
|
472
474
|
WITH root, r_root, p, diff_rel, q
|
|
473
|
-
ORDER BY r_root.from, p.uuid, q.uuid, diff_rel.branch, diff_rel.from
|
|
474
|
-
SKIP $offset
|
|
475
|
-
LIMIT $limit
|
|
475
|
+
ORDER BY r_root.from, p.uuid, q.uuid, q.name, diff_rel.branch, diff_rel.from
|
|
476
|
+
SKIP toInteger($offset)
|
|
477
|
+
LIMIT toInteger($limit)
|
|
476
478
|
// -------------------------------------
|
|
477
479
|
// Add flag to indicate if there is more data after this
|
|
478
480
|
// -------------------------------------
|
|
479
481
|
WITH collect([root, r_root, p, diff_rel, q]) AS limited_results
|
|
480
|
-
|
|
482
|
+
// extra NULL row ensures that has_more_data is always returned, even if all results are filtered out below
|
|
483
|
+
WITH limited_results + [[NULL, NULL, NULL, NULL, NULL]] AS limited_results
|
|
484
|
+
WITH limited_results, size(limited_results) = ($limit + 1) AS has_more_data
|
|
481
485
|
UNWIND limited_results AS one_result
|
|
482
486
|
WITH one_result[0] AS root, one_result[1] AS r_root, one_result[2] AS p, one_result[3] AS diff_rel, one_result[4] AS q, has_more_data
|
|
483
487
|
// -------------------------------------
|
|
@@ -641,8 +645,28 @@ AND (
|
|
|
641
645
|
)
|
|
642
646
|
// skip paths where nodes/attrs/rels are updated after $from_time, those are handled in other queries
|
|
643
647
|
AND (
|
|
644
|
-
|
|
645
|
-
|
|
648
|
+
(
|
|
649
|
+
r_root.branch = diff_rel.branch
|
|
650
|
+
AND r_root.from <= $from_time
|
|
651
|
+
AND (r_root.to IS NULL OR r_root.to >= $to_time)
|
|
652
|
+
)
|
|
653
|
+
OR (
|
|
654
|
+
r_root.branch <> diff_rel.branch
|
|
655
|
+
AND r_root.from <= $from_time
|
|
656
|
+
AND (r_root.to IS NULL OR r_root.to >= $branch_from_time)
|
|
657
|
+
)
|
|
658
|
+
)
|
|
659
|
+
AND (
|
|
660
|
+
(
|
|
661
|
+
r_node.branch = diff_rel.branch
|
|
662
|
+
AND r_node.from <= $from_time
|
|
663
|
+
AND (r_node.to IS NULL OR r_node.to >= $to_time)
|
|
664
|
+
)
|
|
665
|
+
OR (
|
|
666
|
+
r_node.branch <> diff_rel.branch
|
|
667
|
+
AND r_node.from <= $from_time
|
|
668
|
+
AND (r_node.to IS NULL OR r_node.to >= $branch_from_time)
|
|
669
|
+
)
|
|
646
670
|
)
|
|
647
671
|
)
|
|
648
672
|
// time-based filters for new nodes
|
|
@@ -658,8 +682,27 @@ AND (
|
|
|
658
682
|
)
|
|
659
683
|
// skip paths where nodes/attrs/rels are updated after $branch_from_time, those are handled in other queries
|
|
660
684
|
AND (
|
|
661
|
-
|
|
662
|
-
|
|
685
|
+
(
|
|
686
|
+
r_root.branch = diff_rel.branch
|
|
687
|
+
AND (r_root.to IS NULL OR r_root.to >= $to_time)
|
|
688
|
+
)
|
|
689
|
+
OR (
|
|
690
|
+
r_root.branch <> diff_rel.branch
|
|
691
|
+
AND r_root.from <= $branch_from_time
|
|
692
|
+
AND (r_root.to IS NULL OR r_root.to >= $branch_from_time)
|
|
693
|
+
)
|
|
694
|
+
)
|
|
695
|
+
AND (
|
|
696
|
+
(
|
|
697
|
+
r_node.branch = diff_rel.branch
|
|
698
|
+
AND r_node.from <= $branch_from_time
|
|
699
|
+
AND (r_node.to IS NULL OR r_node.to >= $to_time)
|
|
700
|
+
)
|
|
701
|
+
OR (
|
|
702
|
+
r_node.branch <> diff_rel.branch
|
|
703
|
+
AND r_node.from <= $branch_from_time
|
|
704
|
+
AND (r_node.to IS NULL OR r_node.to >= $branch_from_time)
|
|
705
|
+
)
|
|
663
706
|
)
|
|
664
707
|
)
|
|
665
708
|
)
|
|
@@ -701,13 +744,15 @@ AND [%(id_func)s(n), type(r_node)] <> [%(id_func)s(q), type(diff_rel)]
|
|
|
701
744
|
// -------------------------------------
|
|
702
745
|
WITH diff_rel_path, r_root, n, r_node, p, diff_rel
|
|
703
746
|
ORDER BY r_root.from, n.uuid, p.uuid, type(diff_rel), diff_rel.branch, diff_rel.from
|
|
704
|
-
SKIP $offset
|
|
705
|
-
LIMIT $limit
|
|
747
|
+
SKIP toInteger($offset)
|
|
748
|
+
LIMIT toInteger($limit)
|
|
706
749
|
// -------------------------------------
|
|
707
750
|
// Add flag to indicate if there is more data after this
|
|
708
751
|
// -------------------------------------
|
|
709
752
|
WITH collect([diff_rel_path, r_root, n, r_node, p, diff_rel]) AS limited_results
|
|
710
|
-
|
|
753
|
+
// extra NULL row ensures that has_more_data is always returned, even if all results are filtered out below
|
|
754
|
+
WITH limited_results + [[NULL, NULL, NULL, NULL, NULL, NULL]] AS limited_results
|
|
755
|
+
WITH limited_results, size(limited_results) = ($limit + 1) AS has_more_data
|
|
711
756
|
UNWIND limited_results AS one_result
|
|
712
757
|
WITH one_result[0] AS diff_rel_path, one_result[1] AS r_root, one_result[2] AS n,
|
|
713
758
|
one_result[3] AS r_node, one_result[4] AS p, one_result[5] AS diff_rel, has_more_data
|
|
@@ -803,8 +848,8 @@ WHERE num_nodes_with_uuid > 1
|
|
|
803
848
|
// -------------------------------------
|
|
804
849
|
WITH node_uuid
|
|
805
850
|
ORDER BY node_uuid
|
|
806
|
-
SKIP $offset
|
|
807
|
-
LIMIT $limit
|
|
851
|
+
SKIP toInteger($offset)
|
|
852
|
+
LIMIT toInteger($limit)
|
|
808
853
|
WITH collect(node_uuid) AS node_uuids
|
|
809
854
|
WITH node_uuids, size(node_uuids) = $limit AS has_more_data
|
|
810
855
|
MATCH (:Root)<-[diff_rel:IS_PART_OF {branch: $branch_name}]-(n:Node)
|
infrahub/core/query/ipam.py
CHANGED
|
@@ -450,12 +450,23 @@ class IPPrefixReconcileQuery(Query):
|
|
|
450
450
|
// ------------------
|
|
451
451
|
CALL (ip_node) {
|
|
452
452
|
OPTIONAL MATCH parent_prefix_path = (ip_node)-[r1:IS_RELATED]->(:Relationship {name: "parent__child"})-[r2:IS_RELATED]->(current_parent:%(ip_prefix_kind)s)
|
|
453
|
-
WHERE
|
|
453
|
+
WHERE $is_prefix = TRUE
|
|
454
|
+
AND all(r IN relationships(parent_prefix_path) WHERE (%(branch_filter)s))
|
|
454
455
|
RETURN current_parent, (r1.status = "active" AND r2.status = "active") AS parent_is_active
|
|
455
456
|
ORDER BY r1.branch_level DESC, r1.from DESC, r1.status ASC, r2.branch_level DESC, r2.from DESC, r2.status ASC
|
|
456
457
|
LIMIT 1
|
|
457
458
|
}
|
|
458
|
-
WITH ip_namespace, ip_node, CASE WHEN parent_is_active THEN current_parent ELSE NULL END as
|
|
459
|
+
WITH ip_namespace, ip_node, CASE WHEN parent_is_active THEN current_parent ELSE NULL END as prefix_parent
|
|
460
|
+
CALL (ip_node) {
|
|
461
|
+
OPTIONAL MATCH parent_prefix_path = (ip_node)-[r1:IS_RELATED]->(:Relationship {name: "ip_prefix__ip_address"})<-[r2:IS_RELATED]-(current_parent:%(ip_prefix_kind)s)
|
|
462
|
+
WHERE $is_prefix = FALSE
|
|
463
|
+
AND all(r IN relationships(parent_prefix_path) WHERE (%(branch_filter)s))
|
|
464
|
+
RETURN current_parent, (r1.status = "active" AND r2.status = "active") AS parent_is_active
|
|
465
|
+
ORDER BY r1.branch_level DESC, r1.from DESC, r1.status ASC, r2.branch_level DESC, r2.from DESC, r2.status ASC
|
|
466
|
+
LIMIT 1
|
|
467
|
+
}
|
|
468
|
+
WITH ip_namespace, ip_node, prefix_parent, CASE WHEN parent_is_active THEN current_parent ELSE NULL END as address_parent
|
|
469
|
+
WITH ip_namespace, ip_node, COALESCE(prefix_parent, address_parent) AS current_parent
|
|
459
470
|
""" % {
|
|
460
471
|
"branch_filter": branch_filter,
|
|
461
472
|
"ip_prefix_kind": InfrahubKind.IPPREFIX,
|
|
@@ -467,7 +478,7 @@ class IPPrefixReconcileQuery(Query):
|
|
|
467
478
|
// Get prefix node's current prefix children, if any exist
|
|
468
479
|
// ------------------
|
|
469
480
|
CALL (ip_node) {
|
|
470
|
-
OPTIONAL MATCH child_prefix_path = (ip_node)<-[r1:IS_RELATED]-(:Relationship {name: "parent__child"})<-[r2:IS_RELATED]-(current_prefix_child:%(ip_prefix_kind)s)
|
|
481
|
+
OPTIONAL MATCH child_prefix_path = (ip_node:%(ip_prefix_kind)s)<-[r1:IS_RELATED]-(:Relationship {name: "parent__child"})<-[r2:IS_RELATED]-(current_prefix_child:%(ip_prefix_kind)s)
|
|
471
482
|
WHERE all(r IN relationships(child_prefix_path) WHERE (%(branch_filter)s))
|
|
472
483
|
WITH current_prefix_child, (r1.status = "active" AND r2.status = "active") AS is_active
|
|
473
484
|
ORDER BY current_prefix_child.uuid, r1.branch_level DESC, r1.from DESC, r2.branch_level DESC, r2.from DESC
|
|
@@ -479,7 +490,7 @@ class IPPrefixReconcileQuery(Query):
|
|
|
479
490
|
// Get prefix node's current address children, if any exist
|
|
480
491
|
// ------------------
|
|
481
492
|
CALL (ip_node) {
|
|
482
|
-
OPTIONAL MATCH child_address_path = (ip_node)-[r1:IS_RELATED]
|
|
493
|
+
OPTIONAL MATCH child_address_path = (ip_node:%(ip_prefix_kind)s)-[r1:IS_RELATED]->(:Relationship {name: "ip_prefix__ip_address"})<-[r2:IS_RELATED]-(current_address_child:%(ip_address_kind)s)
|
|
483
494
|
WHERE all(r IN relationships(child_address_path) WHERE (%(branch_filter)s))
|
|
484
495
|
WITH current_address_child, (r1.status = "active" AND r2.status = "active") AS is_active
|
|
485
496
|
ORDER BY current_address_child.uuid, r1.branch_level DESC, r1.from DESC, r2.branch_level DESC, r2.from DESC
|
|
@@ -688,6 +699,7 @@ class IPPrefixReconcileQuery(Query):
|
|
|
688
699
|
"ip_address_attribute_kind": ADDRESS_ATTRIBUTE_LABEL,
|
|
689
700
|
}
|
|
690
701
|
self.add_to_query(get_new_children_query)
|
|
702
|
+
self.order_by = ["ip_node.uuid"]
|
|
691
703
|
self.return_labels = ["ip_node", "current_parent", "current_children", "new_parent", "new_children"]
|
|
692
704
|
|
|
693
705
|
def _get_uuid_from_query(self, node_name: str) -> str | None:
|