infrahub-server 1.4.11__py3-none-any.whl → 1.4.12__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.
@@ -1 +1 @@
1
- GRAPH_VERSION = 39
1
+ GRAPH_VERSION = 40
@@ -41,6 +41,7 @@ from .m036_drop_attr_value_index import Migration036
41
41
  from .m037_index_attr_vals import Migration037
42
42
  from .m038_redo_0000_prefix_fix import Migration038
43
43
  from .m039_ipam_reconcile import Migration039
44
+ from .m040_duplicated_attributes import Migration040
44
45
 
45
46
  if TYPE_CHECKING:
46
47
  from infrahub.core.root import Root
@@ -87,6 +88,7 @@ MIGRATIONS: list[type[GraphMigration | InternalSchemaMigration | ArbitraryMigrat
87
88
  Migration037,
88
89
  Migration038,
89
90
  Migration039,
91
+ Migration040,
90
92
  ]
91
93
 
92
94
 
@@ -0,0 +1,81 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Any, Sequence
4
+
5
+ from infrahub.core.migrations.shared import MigrationResult
6
+ from infrahub.core.query import Query, QueryType
7
+
8
+ from ..shared import GraphMigration
9
+
10
+ if TYPE_CHECKING:
11
+ from infrahub.database import InfrahubDatabase
12
+
13
+
14
+ class DeleteDuplicatedAttributesQuery(Query):
15
+ name: str = "delete_duplicated_attributes"
16
+ type: QueryType = QueryType.WRITE
17
+ insert_return: bool = False
18
+ insert_limit: bool = False
19
+
20
+ async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
21
+ query = """
22
+ // -------------
23
+ // get all the Nodes linked to multiple Attributes with the same name to drastically reduce the search space
24
+ // -------------
25
+ MATCH (n:Node)-[:HAS_ATTRIBUTE]->(attr:Attribute)
26
+ WITH DISTINCT n, attr
27
+ WITH n, attr.name AS attr_name, count(*) AS num_attrs
28
+ WHERE num_attrs > 1
29
+ // -------------
30
+ // for each Node-attr_name pair, get the possible duplicate Attributes
31
+ // -------------
32
+ MATCH (n)-[:HAS_ATTRIBUTE]->(dup_attr:Attribute {name: attr_name})
33
+ WITH DISTINCT n, dup_attr
34
+ // -------------
35
+ // get the branch(es) for each possible duplicate Attribute
36
+ // -------------
37
+ CALL (n, dup_attr) {
38
+ MATCH (n)-[r:HAS_ATTRIBUTE {status: "active"}]->(dup_attr)
39
+ WHERE r.to IS NULL
40
+ AND NOT exists((n)-[:HAS_ATTRIBUTE {status: "deleted", branch: r.branch}]->(dup_attr))
41
+ RETURN r.branch AS branch
42
+ }
43
+ // -------------
44
+ // get the latest update time for each duplicate Attribute on each branch
45
+ // -------------
46
+ CALL (dup_attr, branch) {
47
+ MATCH (dup_attr)-[r {branch: branch}]-()
48
+ RETURN max(r.from) AS latest_update
49
+ }
50
+ // -------------
51
+ // order the duplicate Attributes by latest update time
52
+ // -------------
53
+ WITH n, dup_attr, branch, latest_update
54
+ ORDER BY n, branch, dup_attr.name, latest_update DESC
55
+ // -------------
56
+ // for any Node-dup_attr_name pairs with multiple duplicate Attributes, keep the Attribute with the latest update
57
+ // on this branch and delete all the other edges on this branch for this Attribute
58
+ // -------------
59
+ WITH n, branch, dup_attr.name AS dup_attr_name, collect(dup_attr) AS dup_attrs_reverse_chronological
60
+ WHERE size(dup_attrs_reverse_chronological) > 1
61
+ WITH branch, tail(dup_attrs_reverse_chronological) AS dup_attrs_to_delete
62
+ UNWIND dup_attrs_to_delete AS dup_attr_to_delete
63
+ MATCH (dup_attr_to_delete)-[r {branch: branch}]-()
64
+ DELETE r
65
+ // -------------
66
+ // delete any orphaned Attributes
67
+ // -------------
68
+ WITH DISTINCT dup_attr_to_delete
69
+ WHERE NOT exists((dup_attr_to_delete)--())
70
+ DELETE dup_attr_to_delete
71
+ """
72
+ self.add_to_query(query)
73
+
74
+
75
+ class Migration040(GraphMigration):
76
+ name: str = "040_duplicated_attributes"
77
+ queries: Sequence[type[Query]] = [DeleteDuplicatedAttributesQuery]
78
+ minimum_version: int = 39
79
+
80
+ async def validate_migration(self, db: InfrahubDatabase) -> MigrationResult: # noqa: ARG002
81
+ return MigrationResult()
@@ -42,6 +42,16 @@ class NodeAttributeAddMigration(AttributeSchemaMigration):
42
42
  name: str = "node.attribute.add"
43
43
  queries: Sequence[type[AttributeMigrationQuery]] = [NodeAttributeAddMigrationQuery01] # type: ignore[assignment]
44
44
 
45
+ async def execute(
46
+ self,
47
+ db: InfrahubDatabase,
48
+ branch: Branch,
49
+ at: Timestamp | str | None = None,
50
+ ) -> MigrationResult:
51
+ if self.new_attribute_schema.inherited is True:
52
+ return MigrationResult()
53
+ return await super().execute(db=db, branch=branch, at=at)
54
+
45
55
  async def execute_post_queries(
46
56
  self,
47
57
  db: InfrahubDatabase,
@@ -57,14 +57,25 @@ async def extract_peer_data(
57
57
 
58
58
  for rel in template_peer.get_schema().relationship_names:
59
59
  rel_manager: RelationshipManager = getattr(template_peer, rel)
60
- if (
61
- rel_manager.schema.kind not in [RelationshipKind.COMPONENT, RelationshipKind.PARENT]
62
- or rel_manager.schema.name not in obj_peer_schema.relationship_names
63
- ):
60
+
61
+ if rel_manager.schema.name not in obj_peer_schema.relationship_names:
64
62
  continue
65
63
 
66
- if list(await rel_manager.get_peers(db=db)) == [current_template.id]:
64
+ peers_map = await rel_manager.get_peers(db=db)
65
+ if rel_manager.schema.kind in [RelationshipKind.COMPONENT, RelationshipKind.PARENT] and list(
66
+ peers_map.keys()
67
+ ) == [current_template.id]:
67
68
  obj_peer_data[rel] = {"id": parent_obj.id}
69
+ continue
70
+
71
+ rel_peer_ids = []
72
+ for peer_id, peer_object in peers_map.items():
73
+ # deeper templates are handled in the next level of recursion
74
+ if peer_object.get_schema().is_template_schema:
75
+ continue
76
+ rel_peer_ids.append({"id": peer_id})
77
+
78
+ obj_peer_data[rel] = rel_peer_ids
68
79
 
69
80
  return obj_peer_data
70
81
 
@@ -233,11 +233,15 @@ class NodeCreateAllQuery(NodeQuery):
233
233
  ipnetwork_prop_list = [f"{key}: {value}" for key, value in ipnetwork_prop.items()]
234
234
 
235
235
  attrs_nonindexed_query = """
236
- WITH distinct n
236
+ WITH DISTINCT n
237
237
  UNWIND $attrs AS attr
238
238
  // Try to find a matching vertex
239
- OPTIONAL MATCH (existing_av:AttributeValue {value: attr.content.value, is_default: attr.content.is_default})
240
- WHERE NOT existing_av:AttributeValueIndexed
239
+ CALL (attr) {
240
+ OPTIONAL MATCH (existing_av:AttributeValue {value: attr.content.value, is_default: attr.content.is_default})
241
+ WHERE NOT existing_av:AttributeValueIndexed
242
+ RETURN existing_av
243
+ LIMIT 1
244
+ }
241
245
  CALL (attr, existing_av) {
242
246
  // If none found, create a new one
243
247
  WITH existing_av
@@ -787,10 +787,7 @@ class GraphQLSchemaManager:
787
787
  attr_kind = get_attr_kind(schema, attr)
788
788
  attr_type = get_attribute_type(kind=attr_kind).get_graphql_update()
789
789
 
790
- # A Field is not required if explicitly indicated or if a default value has been provided
791
- required = not attr.optional if not attr.default_value else False
792
-
793
- attrs[attr.name] = graphene.InputField(attr_type, required=required, description=attr.description)
790
+ attrs[attr.name] = graphene.InputField(attr_type, description=attr.description)
794
791
 
795
792
  for rel in schema.relationships:
796
793
  if rel.internal_peer or rel.read_only:
@@ -798,14 +795,11 @@ class GraphQLSchemaManager:
798
795
 
799
796
  input_type = self._get_related_input_type(relationship=rel)
800
797
 
801
- required = not rel.optional
802
798
  if rel.cardinality == RelationshipCardinality.ONE:
803
- attrs[rel.name] = graphene.InputField(input_type, required=required, description=rel.description)
799
+ attrs[rel.name] = graphene.InputField(input_type, description=rel.description)
804
800
 
805
801
  elif rel.cardinality == RelationshipCardinality.MANY:
806
- attrs[rel.name] = graphene.InputField(
807
- graphene.List(input_type), required=required, description=rel.description
808
- )
802
+ attrs[rel.name] = graphene.InputField(graphene.List(input_type), description=rel.description)
809
803
 
810
804
  return type(f"{schema.kind}UpsertInput", (graphene.InputObjectType,), attrs)
811
805
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: infrahub-server
3
- Version: 1.4.11
3
+ Version: 1.4.12
4
4
  Summary: Infrahub is taking a new approach to Infrastructure Management by providing a new generation of datastore to organize and control all the data that defines how an infrastructure should run.
5
5
  License: Apache-2.0
6
6
  Author: OpsMill
@@ -140,7 +140,7 @@ infrahub/core/diff/repository/deserializer.py,sha256=bhN9ao8HxqKyRz273QGLNV9z9_S
140
140
  infrahub/core/diff/repository/repository.py,sha256=u0QTMY1e2dknG_DuRAwzFt-Lp1_mdj5lqF2ymt77k9E,25581
141
141
  infrahub/core/diff/tasks.py,sha256=jSXlenTJ5Fc189Xvm971e3-gBDRnfN19cxNaWvEFwAE,3306
142
142
  infrahub/core/enums.py,sha256=qGbhRVoH43Xi0iDkUfWdQiKapJbLT9UKsCobFk_paIk,491
143
- infrahub/core/graph/__init__.py,sha256=pqEHefyIWiA492sH7qk0HW4SxWc4ugXBFIhpI4DyvFY,19
143
+ infrahub/core/graph/__init__.py,sha256=2_7AH-ObUmILq-7DD7GPDWYxj_MZxk3VgQCBMNBIroI,19
144
144
  infrahub/core/graph/constraints.py,sha256=lmuzrKDFoeSKRiLtycB9PXi6zhMYghczKrPYvfWyy90,10396
145
145
  infrahub/core/graph/index.py,sha256=A9jzEE_wldBJsEsflODeMt4GM8sPmmbHAJRNdFioR1k,1736
146
146
  infrahub/core/graph/schema.py,sha256=o50Jcy6GBRk55RkDJSMIDDwHhLD7y_RWOirI9rCex4A,10776
@@ -159,7 +159,7 @@ infrahub/core/ipam/utilization.py,sha256=OKFvcCoxFTkYnwibLhBM2Kbb2vsyI4eX07gtCf_
159
159
  infrahub/core/manager.py,sha256=zlmxJnioJmZynjiRT3jFnBIWGe0Z38uwVm1ZLyxX_MU,47644
160
160
  infrahub/core/merge.py,sha256=TNZpxjNYcl3dnvE8eYXaWSXFDYeEa8DDsS9XbR2XKlA,11217
161
161
  infrahub/core/migrations/__init__.py,sha256=dIExw90CrdTByeJqpiWkaZBclpAfzatG2H6fXx54su0,1305
162
- infrahub/core/migrations/graph/__init__.py,sha256=nCm3XHpKwSrekrOU0WFMVJlnIdJmf9KayjjERIYGx7Q,4225
162
+ infrahub/core/migrations/graph/__init__.py,sha256=Y7X7lpmW7H7ER4ycgPOboZRzr1VYM_u31_cU5F5Vrf0,4296
163
163
  infrahub/core/migrations/graph/m001_add_version_to_graph.py,sha256=YcLN6cFjE6IGheXR4Ujb6CcyY8bJ7WE289hcKJaENOc,1515
164
164
  infrahub/core/migrations/graph/m002_attribute_is_default.py,sha256=wB6f2N_ChTvGajqHD-OWCG5ahRMDhhXZuwo79ieq_II,1036
165
165
  infrahub/core/migrations/graph/m003_relationship_parent_optional.py,sha256=Aya-s98XfE9C7YluOwEjilwgnjaBnZxp27w_Xdv_NmU,2330
@@ -199,6 +199,7 @@ infrahub/core/migrations/graph/m036_drop_attr_value_index.py,sha256=z2BplzX0mue3
199
199
  infrahub/core/migrations/graph/m037_index_attr_vals.py,sha256=bJB4yPWE73XA_ErUcnY90CR09_jbtA0jW6tE5U0GvQ4,22730
200
200
  infrahub/core/migrations/graph/m038_redo_0000_prefix_fix.py,sha256=8seWnXQhgEJDFLWxYHVcnMNDPcHq5C24c0RYrtn_WGE,2411
201
201
  infrahub/core/migrations/graph/m039_ipam_reconcile.py,sha256=gUf4Fo3CrzJ2hwbaKlQclripTDrI7cVk_GHsBlBNMKE,10916
202
+ infrahub/core/migrations/graph/m040_duplicated_attributes.py,sha256=2LxsG-CfcZnBirwGhwYL4kU-g3oxl6lNSM12vZTZ7Gw,2930
202
203
  infrahub/core/migrations/query/__init__.py,sha256=JoWOUWlV6IzwxWxObsfCnAAKUOHJkE7dZlOsfB64ZEo,876
203
204
  infrahub/core/migrations/query/attribute_add.py,sha256=oitzB-PPAclfyNtcwCWJY3RdI5Zi4oEnR62BDzn1UQk,4835
204
205
  infrahub/core/migrations/query/attribute_rename.py,sha256=onb9Nanht1Tz47JgneAcFsuhqqvPS6dvI2nNjRupLLo,6892
@@ -210,7 +211,7 @@ infrahub/core/migrations/schema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm
210
211
  infrahub/core/migrations/schema/attribute_kind_update.py,sha256=bJj33I9q1JlcA5RZG7elQVE8kaHcPJbgvm7RrdD86Po,6180
211
212
  infrahub/core/migrations/schema/attribute_name_update.py,sha256=gebaeQX1MLmOxupTPcCzLJdeEQlUzs3XIl7T15-RdXY,1595
212
213
  infrahub/core/migrations/schema/models.py,sha256=F1yp0GM-HutGdzhE0uPFq9JCTH9iHM3V4iDm2e2c4YU,1357
213
- infrahub/core/migrations/schema/node_attribute_add.py,sha256=xFaSahGbBvloSeya5Xqh5KbmlfkqQ4jfN2_DvLFdxEs,3002
214
+ infrahub/core/migrations/schema/node_attribute_add.py,sha256=XhH8nNWujWHORKVxZOKK2n_O7XNGwHxLr1yljhrrk5I,3322
214
215
  infrahub/core/migrations/schema/node_attribute_remove.py,sha256=Il2ccGTlzP8bpXWJmhKxT4sFZEJxsP7tk2YXi9cgzyY,5283
215
216
  infrahub/core/migrations/schema/node_kind_update.py,sha256=scVJz4FhiI2meIVSDTbc9Q6KfGksMDLMwnuxsaZX1aU,1454
216
217
  infrahub/core/migrations/schema/node_remove.py,sha256=NdPNZH9qXf6HbyTMSaQ3aU58XWauAg861w_3D_Lc5tc,7124
@@ -224,7 +225,7 @@ infrahub/core/node/constraints/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5
224
225
  infrahub/core/node/constraints/attribute_uniqueness.py,sha256=lcHBk4d3bc12sywxRTnQs18VEm_S6pDcUhNnsXnb-uI,2162
225
226
  infrahub/core/node/constraints/grouped_uniqueness.py,sha256=F5pmnXVuQNlVmdZY5FRxSGK4gGi1BK1IRgw4emCTlLw,9506
226
227
  infrahub/core/node/constraints/interface.py,sha256=fwB32pRLxteQyKRArqekQ0RXlrDkyzp7Vmq03vSpUEo,291
227
- infrahub/core/node/create.py,sha256=-Yy81om_gARdeCs1mNNag-WMijVX8S27uBIN08BdEqQ,8138
228
+ infrahub/core/node/create.py,sha256=O-KNCnmj3PqeMULrKFNejNTFWtqMcSJenqvyvHQnOCQ,8513
228
229
  infrahub/core/node/delete_validator.py,sha256=mj_HQXkTeP_A3po65-R5bCJnDM9CmFFmcUQIxwPlofc,10559
229
230
  infrahub/core/node/ipam.py,sha256=NWb3TUlVQOGAzq1VvDwISLh61HML0jnalsJ7QojqGwQ,2669
230
231
  infrahub/core/node/permissions.py,sha256=uQzQ62IHcSly6fzPre0nQzlrkCIKzH4HyQkODKB3ZWM,2207
@@ -244,7 +245,7 @@ infrahub/core/query/branch.py,sha256=aIYyDxpnw_Zw2lqTnMEVlhPUaYckZtJJJU1SFUht1o0
244
245
  infrahub/core/query/delete.py,sha256=7tPP1qtNV6QGYtmgE1RKsuQ9oxENnMTVkttLvJ2PiKg,1927
245
246
  infrahub/core/query/diff.py,sha256=jJCkZRo5jGaf-yPAnQ_5ju6sCnknDK0E7vGpqEnaU_k,36881
246
247
  infrahub/core/query/ipam.py,sha256=dOs_LZr-DONrCPw6t5Ug9mBPn8a-S2NKja3Vr-zIeaM,34523
247
- infrahub/core/query/node.py,sha256=OfWS9PfltP89aU4n0KhEjrvAkhAGj9Vl4hcfKcE9LD8,70969
248
+ infrahub/core/query/node.py,sha256=bILKB5fcd0rjPhY5IDtI0OkxsVm2pr4OO9-ayDLT84k,71060
248
249
  infrahub/core/query/relationship.py,sha256=GpaEcf8YRiVpqTxrp10NFOUCHeyE7SqhOFyf3F44eNo,48474
249
250
  infrahub/core/query/resource_manager.py,sha256=uSvs1WZmdbyt_PjaUi9lXnYdPt-lhJV1RjYoUHYjQdk,16620
250
251
  infrahub/core/query/standard_node.py,sha256=mPBXyqk4RzoWRUX4NoojoVi8zk-sJ03GmzmUaWqOgSI,4825
@@ -475,7 +476,7 @@ infrahub/graphql/loaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
475
476
  infrahub/graphql/loaders/node.py,sha256=p7qJxRpXSAddq2fcwJeaIRy-5ReSn2EUitQbDhlmdM4,2618
476
477
  infrahub/graphql/loaders/peers.py,sha256=wsB-ZtaU-BlR99EvWUbf6_SFhFJYOspz5QaTln_MZ4Q,2799
477
478
  infrahub/graphql/loaders/shared.py,sha256=hUxLy8iVgfpEZiUMKNkUAeshPKKzEVSDMDsuaBbjJW4,389
478
- infrahub/graphql/manager.py,sha256=9MAnX9kDGc-we27MwU9WhwQhuSdE7VFojdJqPIpPyLw,45737
479
+ infrahub/graphql/manager.py,sha256=CC5rX1hudgP_LOoma8b_hwHbDQpqp3nmJ3rMXorextk,45421
479
480
  infrahub/graphql/metrics.py,sha256=viq_M57mDYd4DDK7suUttf1FJTgzQ3U50yOuSw_Nd-s,2267
480
481
  infrahub/graphql/models.py,sha256=7kr3DSO_rujPocMIfPyZ5Hwy3Mpnu4ySDMAIE9G5Y7Y,147
481
482
  infrahub/graphql/mutations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -829,8 +830,8 @@ infrahub_testcontainers/models.py,sha256=ASYyvl7d_WQz_i7y8-3iab9hwwmCl3OCJavqVbe
829
830
  infrahub_testcontainers/performance_test.py,sha256=hvwiy6tc_lWniYqGkqfOXVGAmA_IV15VOZqbiD9ezno,6149
830
831
  infrahub_testcontainers/plugin.py,sha256=I3RuZQ0dARyKHuqCf0y1Yj731P2Mwf3BJUehRJKeWrs,5645
831
832
  infrahub_testcontainers/prometheus.yml,sha256=610xQEyj3xuVJMzPkC4m1fRnCrjGpiRBrXA2ytCLa54,599
832
- infrahub_server-1.4.11.dist-info/LICENSE.txt,sha256=7GQO7kxVoQYnZtFrjZBKLRXbrGwwwimHPPOJtqXsozQ,11340
833
- infrahub_server-1.4.11.dist-info/METADATA,sha256=VMpdBnV5ruFMqC3cVkWMi4etl5VoRNASmuJV6K1K_3E,6259
834
- infrahub_server-1.4.11.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
835
- infrahub_server-1.4.11.dist-info/entry_points.txt,sha256=UXIeFWDsrV-4IllNvUEd6KieYGzQfn9paga2YyABOQI,393
836
- infrahub_server-1.4.11.dist-info/RECORD,,
833
+ infrahub_server-1.4.12.dist-info/LICENSE.txt,sha256=7GQO7kxVoQYnZtFrjZBKLRXbrGwwwimHPPOJtqXsozQ,11340
834
+ infrahub_server-1.4.12.dist-info/METADATA,sha256=myn6mYFb-eFR9Kf5sjUYDCmgxz9GG1xxOsB07xvKmjU,6259
835
+ infrahub_server-1.4.12.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
836
+ infrahub_server-1.4.12.dist-info/entry_points.txt,sha256=UXIeFWDsrV-4IllNvUEd6KieYGzQfn9paga2YyABOQI,393
837
+ infrahub_server-1.4.12.dist-info/RECORD,,