infrahub-server 1.6.1__py3-none-any.whl → 1.6.2__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.
@@ -157,7 +157,12 @@ async def rebase_branch(branch: str, context: InfrahubContext, send_events: bool
157
157
  responses = await schema_validate_migrations(
158
158
  message=SchemaValidateMigrationData(branch=obj, schema_branch=candidate_schema, constraints=constraints)
159
159
  )
160
- error_messages = [violation.message for response in responses for violation in response.violations]
160
+ error_messages = [
161
+ f"{violation.message} for constraint {response.constraint_name} {response.schema_path.field_name} {response.schema_path.property_name} and node {violation.node_id} {violation.node_kind}" # noqa: E501
162
+ for response in responses
163
+ for violation in response.violations
164
+ ]
165
+
161
166
  if error_messages:
162
167
  raise ValidationError(",\n".join(error_messages))
163
168
 
@@ -1 +1 @@
1
- GRAPH_VERSION = 47
1
+ GRAPH_VERSION = 48
@@ -49,6 +49,7 @@ from .m044_backfill_hfid_display_label_in_db import Migration044
49
49
  from .m045_backfill_hfid_display_label_in_db_profile_template import Migration045
50
50
  from .m046_fill_agnostic_hfid_display_labels import Migration046
51
51
  from .m047_backfill_or_null_display_label import Migration047
52
+ from .m048_undelete_rel_props import Migration048
52
53
 
53
54
  if TYPE_CHECKING:
54
55
  from ..shared import MigrationTypes
@@ -102,6 +103,7 @@ MIGRATIONS: list[type[MigrationTypes]] = [
102
103
  Migration045,
103
104
  Migration046,
104
105
  Migration047,
106
+ Migration048,
105
107
  ]
106
108
 
107
109
 
@@ -68,33 +68,49 @@ DELETE added_e
68
68
  self.add_to_query(query)
69
69
 
70
70
 
71
- class DeleteDuplicateEdgesForMigratedKindNodes(Query):
72
- name = "delete_duplicate_edges_for_migrated_kind_nodes_query"
71
+ class DeleteDuplicatedRelationshipEdges(Query):
72
+ name = "delete_duplicated_relationship_edges_query"
73
73
  type = QueryType.WRITE
74
74
  insert_return = False
75
75
 
76
+ def __init__(self, migrated_kind_nodes_only: bool = True, **kwargs: Any):
77
+ self.migrated_kind_nodes_only = migrated_kind_nodes_only
78
+ super().__init__(**kwargs)
79
+
76
80
  async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
77
- query = """
81
+ if not self.migrated_kind_nodes_only:
82
+ relationship_filter_query = """
83
+ MATCH (rel:Relationship)
84
+ """
85
+
86
+ else:
87
+ relationship_filter_query = """
78
88
  // ------------
79
89
  // get UUIDs for migrated kind/inheritance nodes
80
90
  // ------------
81
91
  MATCH (n:Node)
82
92
  WITH n.uuid AS node_uuid, count(*) AS num_nodes_with_uuid
83
93
  WHERE num_nodes_with_uuid > 1
84
- CALL (node_uuid) {
85
- // ------------
86
- // find any Relationships for these nodes
87
- // ------------
88
- MATCH (n:Node {uuid: node_uuid})-[:IS_RELATED]-(rel:Relationship)
89
- WITH DISTINCT rel
90
- MATCH (rel)-[e]->(peer)
94
+ // ------------
95
+ // find any Relationships for these nodes
96
+ // ------------
97
+ MATCH (n:Node {uuid: node_uuid})-[:IS_RELATED]-(rel:Relationship)
98
+ WITH DISTINCT rel
99
+
100
+ """
101
+ self.add_to_query(relationship_filter_query)
102
+
103
+ query = """
104
+ CALL (rel) {
105
+ MATCH (rel)-[e]-(peer)
91
106
  WITH
107
+ elementId(rel) AS rel_element_id,
92
108
  type(e) AS e_type,
93
109
  e.branch AS e_branch,
94
110
  e.from AS e_from,
95
111
  e.to AS e_to,
96
112
  e.status AS e_status,
97
- e.peer AS e_peer,
113
+ elementId(peer) AS peer_element_id,
98
114
  CASE
99
115
  WHEN startNode(e) = rel THEN "out" ELSE "in"
100
116
  END AS direction,
@@ -142,7 +158,9 @@ class Migration041(ArbitraryMigration):
142
158
  rprint("done")
143
159
 
144
160
  rprint("Deleting duplicate edges for migrated kind/inheritance nodes", end="...")
145
- delete_duplicate_edges_query = await DeleteDuplicateEdgesForMigratedKindNodes.init(db=db)
161
+ delete_duplicate_edges_query = await DeleteDuplicatedRelationshipEdges.init(
162
+ db=db, migrated_kind_nodes_only=True
163
+ )
146
164
  await delete_duplicate_edges_query.execute(db=db)
147
165
  rprint("done")
148
166
 
@@ -0,0 +1,161 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Any
4
+
5
+ from infrahub.core.migrations.graph.m041_deleted_dup_edges import DeleteDuplicatedRelationshipEdges
6
+ from infrahub.core.migrations.shared import ArbitraryMigration, MigrationResult, get_migration_console
7
+ from infrahub.core.query import Query, QueryType
8
+
9
+ if TYPE_CHECKING:
10
+ from infrahub.database import InfrahubDatabase
11
+
12
+
13
+ class UndeleteRelationshipProperties(Query):
14
+ """
15
+ Find Relationship vertices that are missing IS_VISIBLE and/or IS_PROTECTED edges linking them to Boolean vertices
16
+
17
+ Use the existing IS_RELATED edges to determine when the IS_VISIBLE/IS_PROTECTED edges should exist on each branch
18
+ and add the missing edges
19
+
20
+ Sets IS_VISIBLE to TRUE and IS_PROTECTED to FALSE
21
+ """
22
+
23
+ name = "undelete_relationship_properties"
24
+ type = QueryType.WRITE
25
+ insert_return = False
26
+
27
+ async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
28
+ query = """
29
+ // --------------
30
+ // find all Relationships that are missing IS_VISIBLE/IS_PROTECTED edges
31
+ // --------------
32
+ MATCH (rel:Relationship)-[:IS_RELATED]-()
33
+ WHERE NOT exists((rel)-[:IS_VISIBLE]->())
34
+ OR NOT exists((rel)-[:IS_PROTECTED]->())
35
+ WITH DISTINCT rel
36
+ WITH rel, exists((rel)-[:IS_VISIBLE]->()) AS has_visible, exists((rel)-[:IS_PROTECTED]->()) AS has_protected
37
+ WHERE has_visible = FALSE OR has_protected = FALSE
38
+
39
+ // --------------
40
+ // one row for each branch the Relationship has changes on
41
+ // --------------
42
+ CALL (rel) {
43
+ MATCH (rel)-[e:IS_RELATED]-()
44
+ RETURN DISTINCT e.branch AS branch
45
+ }
46
+
47
+ // --------------
48
+ // get the earliest from edge on this branch, if any
49
+ // --------------
50
+ CALL (rel, branch) {
51
+ OPTIONAL MATCH (rel)-[e:IS_RELATED {status: "active", branch: branch}]-()
52
+ // ignore schema kind/inheritance migration edges
53
+ WHERE NOT exists((rel)-[:IS_RELATED {status: "deleted", branch: branch, from: e.from}]-())
54
+ RETURN e AS earliest_from_edge
55
+ ORDER BY e.from ASC
56
+ LIMIT 1
57
+ }
58
+
59
+ // --------------
60
+ // get the latest to time on this branch, if any
61
+ // --------------
62
+ CALL (rel, branch) {
63
+ OPTIONAL MATCH (rel)-[e:IS_RELATED {status: "active", branch: branch}]-()
64
+ // ignore schema kind/inheritance migration edges
65
+ WHERE NOT exists((rel)-[:IS_RELATED {status: "active", branch: branch, from: e.to}]-())
66
+ RETURN e.to AS latest_to_time
67
+ ORDER BY e.to DESC
68
+ LIMIT 1
69
+ }
70
+
71
+ // --------------
72
+ // get the latest deleted edge on this branch, if any
73
+ // --------------
74
+ CALL (rel, branch) {
75
+ OPTIONAL MATCH (rel)-[deleted_e:IS_RELATED {status: "deleted", branch: branch}]-()
76
+ // ignore schema kind/inheritance migration edges
77
+ WHERE NOT exists((rel)-[:IS_RELATED {status: "active", branch: branch, from: deleted_e.from}]-())
78
+ RETURN deleted_e AS latest_deleted_edge
79
+ ORDER BY deleted_e.from DESC
80
+ LIMIT 1
81
+ }
82
+
83
+ // --------------
84
+ // add active IS_VISIBLE edge on the branch, if necessary
85
+ // --------------
86
+ CALL (rel, earliest_from_edge, latest_to_time, has_visible) {
87
+ WITH *, has_visible
88
+ WHERE has_visible = FALSE
89
+ AND earliest_from_edge IS NOT NULL
90
+ MERGE (bool:Boolean {value: TRUE})
91
+ CREATE (rel)-[new_edge:IS_VISIBLE]->(bool)
92
+ SET new_edge = properties(earliest_from_edge)
93
+ SET new_edge.to = latest_to_time
94
+ }
95
+ // --------------
96
+ // add deleted IS_VISIBLE edge on the branch, if necessary
97
+ // --------------
98
+ CALL (rel, latest_deleted_edge, has_visible) {
99
+ WITH *, has_visible
100
+ WHERE has_visible = FALSE
101
+ AND latest_deleted_edge IS NOT NULL
102
+ MERGE (bool:Boolean {value: TRUE})
103
+ CREATE (rel)-[new_edge:IS_VISIBLE]->(bool)
104
+ SET new_edge = properties(latest_deleted_edge)
105
+ }
106
+ // --------------
107
+ // add active IS_PROTECTED edge on the branch, if necessary
108
+ // --------------
109
+ CALL (rel, earliest_from_edge, latest_to_time, has_protected) {
110
+ WITH *, has_protected
111
+ WHERE has_protected = FALSE
112
+ AND earliest_from_edge IS NOT NULL
113
+ MERGE (bool:Boolean {value: FALSE})
114
+ CREATE (rel)-[new_edge:IS_PROTECTED]->(bool)
115
+ SET new_edge = properties(earliest_from_edge)
116
+ SET new_edge.to = latest_to_time
117
+ }
118
+ // --------------
119
+ // add deleted IS_PROTECTED edge on the branch, if necessary
120
+ // --------------
121
+ CALL (rel, latest_deleted_edge, has_protected) {
122
+ WITH *, has_protected
123
+ WHERE has_protected = FALSE
124
+ AND latest_deleted_edge IS NOT NULL
125
+ MERGE (bool:Boolean {value: FALSE})
126
+ CREATE (rel)-[new_edge:IS_PROTECTED]->(bool)
127
+ SET new_edge = properties(latest_deleted_edge)
128
+ }
129
+ """
130
+ self.add_to_query(query)
131
+
132
+
133
+ class Migration048(ArbitraryMigration):
134
+ """
135
+ Fix Relationship vertices that are missing IS_VISIBLE and/or IS_PROTECTED edges.
136
+
137
+ This can happen due to a bug in Migration041 that deleted these edges incorrectly.
138
+ """
139
+
140
+ name: str = "048_undelete_rel_props"
141
+ minimum_version: int = 47
142
+
143
+ async def validate_migration(self, db: InfrahubDatabase) -> MigrationResult: # noqa: ARG002
144
+ return MigrationResult()
145
+
146
+ async def execute(self, db: InfrahubDatabase) -> MigrationResult:
147
+ console = get_migration_console()
148
+
149
+ console.log("Deleting duplicate edges for all Relationships", end="...")
150
+ delete_duplicate_edges_query = await DeleteDuplicatedRelationshipEdges.init(
151
+ db=db, migrated_kind_nodes_only=False
152
+ )
153
+ await delete_duplicate_edges_query.execute(db=db)
154
+ console.log("done")
155
+
156
+ console.log("Undeleting Relationship properties", end="...")
157
+ undelete_rel_props_query = await UndeleteRelationshipProperties.init(db=db)
158
+ await undelete_rel_props_query.execute(db=db)
159
+ console.log("done")
160
+
161
+ return MigrationResult()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: infrahub-server
3
- Version: 1.6.1
3
+ Version: 1.6.2
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
  Project-URL: Homepage, https://opsmill.com
6
6
  Project-URL: Repository, https://github.com/opsmill/infrahub
@@ -98,7 +98,7 @@ infrahub/core/branch/__init__.py,sha256=h0oIj0gHp1xI-N1cYW8_N6VZ81CBOmLuiUt5cS5n
98
98
  infrahub/core/branch/enums.py,sha256=wE_TvKxd-r3zeHgLOMuZhsyKRwDWWC8BMxAEC_aX7A8,212
99
99
  infrahub/core/branch/models.py,sha256=NWbDbK5EjwafopEtiZVzArvxpZKHC8RcWPDyHmYZTcg,21268
100
100
  infrahub/core/branch/needs_rebase_status.py,sha256=purrg93k9zWcV9NONjIdMF8cWLXEKHq6YjO0ayC3C04,407
101
- infrahub/core/branch/tasks.py,sha256=RnQlWdFmAj3VIALb4WNaMiL7ZuvtGcW1zgdbnemjE-Q,23558
101
+ infrahub/core/branch/tasks.py,sha256=Z5hYlhsUR2NRz2BJx-2E4f3nEesK4aFJYtpTjVCvybs,23804
102
102
  infrahub/core/changelog/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
103
103
  infrahub/core/changelog/diff.py,sha256=0BxCpsgJ-38x5BBz5XDtAvc9FPy82M0NlzXl8nQ-c70,13752
104
104
  infrahub/core/changelog/models.py,sha256=pA8Tvq37ia58rGZjFb6OWXIH974J43s3_LG9VEvt-tw,29832
@@ -171,7 +171,7 @@ infrahub/core/diff/query/update_conflict_query.py,sha256=kQkFazz88wnApr8UU_qb0ru
171
171
  infrahub/core/diff/repository/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
172
172
  infrahub/core/diff/repository/deserializer.py,sha256=bhN9ao8HxqKyRz273QGLNV9z9_SS4EQnM9JoY5ptx78,21337
173
173
  infrahub/core/diff/repository/repository.py,sha256=u0QTMY1e2dknG_DuRAwzFt-Lp1_mdj5lqF2ymt77k9E,25581
174
- infrahub/core/graph/__init__.py,sha256=FMzJuQKTgUQn8LmPwha2EHaGv3YswDBNG-1ttoZzjAA,19
174
+ infrahub/core/graph/__init__.py,sha256=uSqGhFuXphIN54hyFRnktc-l81hPHwfKpgNgI5_amKQ,19
175
175
  infrahub/core/graph/constraints.py,sha256=ePTN1FtvTX01R1CcnYDNDGwC82YyIIux2_Jnf0e0PeI,10397
176
176
  infrahub/core/graph/index.py,sha256=A9jzEE_wldBJsEsflODeMt4GM8sPmmbHAJRNdFioR1k,1736
177
177
  infrahub/core/graph/schema.py,sha256=o50Jcy6GBRk55RkDJSMIDDwHhLD7y_RWOirI9rCex4A,10776
@@ -190,7 +190,7 @@ infrahub/core/migrations/__init__.py,sha256=ttA1YkKhiG9Zc0fwIIcMLIDCrIhN5xVOIh6o
190
190
  infrahub/core/migrations/exceptions.py,sha256=gEAkWzjvN-IXr0YPqUrEqnu_GsR-uqucsu1QUaWhEmM,147
191
191
  infrahub/core/migrations/runner.py,sha256=d_HxhO1RRh3Ec7cG5Z8SKV2X0mqc4J5Y9UZwHb4d6Co,2145
192
192
  infrahub/core/migrations/shared.py,sha256=eP-OltT87Aw0I5MLm90YZ50iwxbNbC229eO8HPwC7kc,9575
193
- infrahub/core/migrations/graph/__init__.py,sha256=UAdfeIHwuRGb6F6tGykQOWLcT873k6VeUzkXvL4yztU,4638
193
+ infrahub/core/migrations/graph/__init__.py,sha256=5q-xHmDCWGIrbAZVIn2TlgzNMk0NURJQjoVtON042Sc,4706
194
194
  infrahub/core/migrations/graph/load_schema_branch.py,sha256=OvjowaeDnx4djD1aGPjE7Rqyh1p843LSodOf_Frdt9U,1008
195
195
  infrahub/core/migrations/graph/m001_add_version_to_graph.py,sha256=YcLN6cFjE6IGheXR4Ujb6CcyY8bJ7WE289hcKJaENOc,1515
196
196
  infrahub/core/migrations/graph/m002_attribute_is_default.py,sha256=wB6f2N_ChTvGajqHD-OWCG5ahRMDhhXZuwo79ieq_II,1036
@@ -232,13 +232,14 @@ infrahub/core/migrations/graph/m037_index_attr_vals.py,sha256=pc-223N-jhAglpPIeU
232
232
  infrahub/core/migrations/graph/m038_redo_0000_prefix_fix.py,sha256=8seWnXQhgEJDFLWxYHVcnMNDPcHq5C24c0RYrtn_WGE,2411
233
233
  infrahub/core/migrations/graph/m039_ipam_reconcile.py,sha256=yRWTE73Rq1Qh6tPLu98w60zJdx8cgdO7_DL-g10x87s,11112
234
234
  infrahub/core/migrations/graph/m040_duplicated_attributes.py,sha256=2LxsG-CfcZnBirwGhwYL4kU-g3oxl6lNSM12vZTZ7Gw,2930
235
- infrahub/core/migrations/graph/m041_deleted_dup_edges.py,sha256=eP2BqUfvwkjACJrKI5fVyBBmXxEDwxtAD9O_CcbwBMw,5409
235
+ infrahub/core/migrations/graph/m041_deleted_dup_edges.py,sha256=ydQ73MuhCNhl8cDrZ5N_jCP5vFCUIQTlJTGiTHMQVeM,5911
236
236
  infrahub/core/migrations/graph/m042_profile_attrs_in_db.py,sha256=KdEaNPHovJxxiNL3CFRjWBnNzaMdidj1nmW5Jbhrt-4,6431
237
237
  infrahub/core/migrations/graph/m043_create_hfid_display_label_in_db.py,sha256=giICX6Dwd_z1GaWTWyX3KD5Va34LGth0Vv2uyaof044,7290
238
238
  infrahub/core/migrations/graph/m044_backfill_hfid_display_label_in_db.py,sha256=FuV3EBWS4lY4dtOn7-1Qgo6J7j4XDq4s5yIQjfCCVDM,39575
239
239
  infrahub/core/migrations/graph/m045_backfill_hfid_display_label_in_db_profile_template.py,sha256=mnND7TIdPSVcN9uJeYMmRpVjlAU6QBqfu7e1CS31D9Q,7934
240
240
  infrahub/core/migrations/graph/m046_fill_agnostic_hfid_display_labels.py,sha256=labPu3UwH2L6X3VCVmNQHGSbRS-De0ihVzsaUiTf2so,10210
241
241
  infrahub/core/migrations/graph/m047_backfill_or_null_display_label.py,sha256=0ZrkeYWKhWERGOg_IH74KNuJtV8bR0bw1jOEkeZBFtE,24328
242
+ infrahub/core/migrations/graph/m048_undelete_rel_props.py,sha256=6xlWsWtzzDwtyGmdRGKZa3hCpt-mp5QX7hNeJMnw3NM,5647
242
243
  infrahub/core/migrations/query/__init__.py,sha256=nUbKk8bX6Ei4RkLe0VNNAm7c-d2zDoAMgdFGkYW0Czw,850
243
244
  infrahub/core/migrations/query/attribute_add.py,sha256=wKChMnqcd8hb8YCTIU3rUrtVqwHFSI5bdvXAPUcnRIA,4969
244
245
  infrahub/core/migrations/query/attribute_remove.py,sha256=IhAPlv9jyZTWMf8f8HZJ8G0ImWebt-ER78NrP3vIWhU,5307
@@ -887,8 +888,8 @@ infrahub_testcontainers/models.py,sha256=hT7WEX2o7gxTFPE9uhtP5yigKgP5YSsy2c3tFB-
887
888
  infrahub_testcontainers/performance_test.py,sha256=_nf7Uk15mHwqpN4y7XUfI4JI54-UaXW-Yu4uwMIx21w,6185
888
889
  infrahub_testcontainers/plugin.py,sha256=I3RuZQ0dARyKHuqCf0y1Yj731P2Mwf3BJUehRJKeWrs,5645
889
890
  infrahub_testcontainers/prometheus.yml,sha256=610xQEyj3xuVJMzPkC4m1fRnCrjGpiRBrXA2ytCLa54,599
890
- infrahub_server-1.6.1.dist-info/METADATA,sha256=VB7CaatQzYcU337oiEq4fAs6P_tOohGrNzOs0q0HGG0,5898
891
- infrahub_server-1.6.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
892
- infrahub_server-1.6.1.dist-info/entry_points.txt,sha256=_xSAw1Wp-GslD95j4FESCxU1H7G7B9b42zp8-LAmC8Q,406
893
- infrahub_server-1.6.1.dist-info/licenses/LICENSE.txt,sha256=7GQO7kxVoQYnZtFrjZBKLRXbrGwwwimHPPOJtqXsozQ,11340
894
- infrahub_server-1.6.1.dist-info/RECORD,,
891
+ infrahub_server-1.6.2.dist-info/METADATA,sha256=ADBUZvxk66UJvWBYXRzF7z31TGIaJ0TgiJ-SyIieaVU,5898
892
+ infrahub_server-1.6.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
893
+ infrahub_server-1.6.2.dist-info/entry_points.txt,sha256=_xSAw1Wp-GslD95j4FESCxU1H7G7B9b42zp8-LAmC8Q,406
894
+ infrahub_server-1.6.2.dist-info/licenses/LICENSE.txt,sha256=7GQO7kxVoQYnZtFrjZBKLRXbrGwwwimHPPOJtqXsozQ,11340
895
+ infrahub_server-1.6.2.dist-info/RECORD,,