infrahub-server 1.6.1__py3-none-any.whl → 1.6.3__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/core/account.py CHANGED
@@ -54,11 +54,15 @@ class AccountGlobalPermissionQuery(Query):
54
54
  name: str = "account_global_permissions"
55
55
  type: QueryType = QueryType.READ
56
56
 
57
- def __init__(self, account_id: str, **kwargs: Any):
57
+ def __init__(
58
+ self,
59
+ account_id: str,
60
+ branch: Branch | None = None,
61
+ branch_agnostic: bool = False,
62
+ ) -> None:
63
+ super().__init__(branch=branch, branch_agnostic=branch_agnostic)
58
64
  self.account_id = account_id
59
- super().__init__(**kwargs)
60
65
 
61
- async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
62
66
  self.params["account_id"] = self.account_id
63
67
 
64
68
  branch_filter, branch_params = self.branch.get_query_filter_path(
@@ -66,7 +70,6 @@ class AccountGlobalPermissionQuery(Query):
66
70
  )
67
71
  self.params.update(branch_params)
68
72
 
69
- # ruff: noqa: E501
70
73
  query = """
71
74
  MATCH (account:%(generic_account_node)s)
72
75
  WHERE account.uuid = $account_id
@@ -293,7 +296,7 @@ class AccountObjectPermissionQuery(Query):
293
296
 
294
297
 
295
298
  async def fetch_permissions(account_id: str, db: InfrahubDatabase, branch: Branch) -> AssignedPermissions:
296
- query1 = await AccountGlobalPermissionQuery.init(db=db, branch=branch, account_id=account_id, branch_agnostic=True)
299
+ query1 = AccountGlobalPermissionQuery(branch=branch, account_id=account_id, branch_agnostic=True)
297
300
  await query1.execute(db=db)
298
301
  global_permissions = query1.get_permissions()
299
302
 
@@ -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()
@@ -34,7 +34,7 @@ class AttributeKindUpdateMigrationQuery(AttributeMigrationQuery):
34
34
  // ------------
35
35
  // start with all the Attribute vertices we might care about
36
36
  // ------------
37
- MATCH (n:%(schema_kind)s)-[:HAS_ATTRIBUTE]->(attr:Attribute)
37
+ MATCH (n:%(schema_kinds)s)-[:HAS_ATTRIBUTE]->(attr:Attribute)
38
38
  WHERE attr.name = $attr_name
39
39
  WITH DISTINCT n, attr
40
40
 
@@ -70,7 +70,7 @@ CALL (av_is_default, av_value) {
70
70
  // ------------
71
71
  WITH 1 AS one
72
72
  LIMIT 1
73
- MATCH (n:%(schema_kind)s)-[:HAS_ATTRIBUTE]->(attr:Attribute)
73
+ MATCH (n:%(schema_kinds)s)-[:HAS_ATTRIBUTE]->(attr:Attribute)
74
74
  WHERE attr.name = $attr_name
75
75
  WITH DISTINCT n, attr
76
76
 
@@ -88,7 +88,6 @@ CALL (n, attr) {
88
88
  RETURN has_value_e, av
89
89
  }
90
90
 
91
-
92
91
  // ------------
93
92
  // create and update the HAS_VALUE edges
94
93
  // ------------
@@ -136,7 +135,9 @@ CALL (has_value_e) {
136
135
  SET has_value_e.to = $at
137
136
  }
138
137
  """ % {
139
- "schema_kind": self.migration.previous_schema.kind,
138
+ "schema_kinds": (
139
+ f"{self.migration.previous_schema.kind}|Profile{self.migration.previous_schema.kind}|Template{self.migration.previous_schema.kind}"
140
+ ),
140
141
  "branch_filter": branch_filter,
141
142
  "new_attr_value_labels": new_attr_value_labels,
142
143
  }
@@ -1,6 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- from abc import ABC, abstractmethod
4
3
  from collections import defaultdict
5
4
  from dataclasses import dataclass, field
6
5
  from enum import Enum
@@ -336,7 +335,7 @@ class QueryStat:
336
335
  return cls(**data)
337
336
 
338
337
 
339
- class Query(ABC):
338
+ class Query:
340
339
  name: str = "base-query"
341
340
  type: QueryType
342
341
 
@@ -403,8 +402,12 @@ class Query(ABC):
403
402
 
404
403
  return query
405
404
 
406
- @abstractmethod
407
405
  async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None:
406
+ # Avoid using this method for new queries and look at migrating older queries. The
407
+ # problem here is that we loose so much information with the `**kwargs` we should instead
408
+ # populate this information via the constructor and anything done within the existing query_init methods
409
+ # could either be handled within __init__ or via dedicated methods within each Query class where appropriate,
410
+ # i.e. things might need to happend in a certain order or we just want to separate the logic better.
408
411
  raise NotImplementedError
409
412
 
410
413
  def get_context(self) -> dict[str, str]:
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import sys
4
- from typing import Self
4
+ from typing import Any, Self
5
5
 
6
6
  from pydantic import ConfigDict, Field, model_validator
7
7
 
@@ -24,6 +24,33 @@ def get_attribute_parameters_class_for_kind(kind: str) -> type[AttributeParamete
24
24
  class AttributeParameters(HashableModel):
25
25
  model_config = ConfigDict(extra="forbid")
26
26
 
27
+ @classmethod
28
+ def convert_from(cls, source: AttributeParameters) -> Self:
29
+ """Convert from another AttributeParameters subclass.
30
+
31
+ Args:
32
+ source: The source AttributeParameters instance to convert from
33
+
34
+ Returns:
35
+ A new instance of the target class with compatible fields populated
36
+ """
37
+ source_data = source.model_dump()
38
+ return cls.convert_from_dict(source_data=source_data)
39
+
40
+ @classmethod
41
+ def convert_from_dict(cls, source_data: dict[str, Any]) -> Self:
42
+ """Convert from a dictionary to the target class.
43
+
44
+ Args:
45
+ source_data: The source dictionary to convert from
46
+
47
+ Returns:
48
+ A new instance of the target class with compatible fields populated
49
+ """
50
+ target_fields = set(cls.model_fields.keys())
51
+ filtered_data = {k: v for k, v in source_data.items() if k in target_fields}
52
+ return cls(**filtered_data)
53
+
27
54
 
28
55
  class TextAttributeParameters(AttributeParameters):
29
56
  regex: str | None = Field(
@@ -114,13 +114,20 @@ class AttributeSchema(GeneratedAttributeSchema):
114
114
  @field_validator("parameters", mode="before")
115
115
  @classmethod
116
116
  def set_parameters_type(cls, value: Any, info: ValidationInfo) -> Any:
117
- """Override parameters class if using base AttributeParameters class and should be using a subclass"""
117
+ """Override parameters class if using base AttributeParameters class and should be using a subclass.
118
+
119
+ This validator handles parameter type conversion when an attribute's kind changes.
120
+ Fields from the source that don't exist in the target are silently dropped.
121
+ Fields with the same name in both classes are preserved.
122
+ """
118
123
  kind = info.data["kind"]
119
124
  expected_parameters_class = get_attribute_parameters_class_for_kind(kind=kind)
120
125
  if value is None:
121
126
  return expected_parameters_class()
122
127
  if not isinstance(value, expected_parameters_class) and isinstance(value, AttributeParameters):
123
- return expected_parameters_class(**value.model_dump())
128
+ return expected_parameters_class.convert_from(value)
129
+ if isinstance(value, dict):
130
+ return expected_parameters_class.convert_from_dict(source_data=value)
124
131
  return value
125
132
 
126
133
  @model_validator(mode="after")
@@ -238,19 +245,6 @@ class TextAttributeSchema(AttributeSchema):
238
245
  json_schema_extra={"update": UpdateSupport.VALIDATE_CONSTRAINT.value},
239
246
  )
240
247
 
241
- @model_validator(mode="after")
242
- def reconcile_parameters(self) -> Self:
243
- if self.regex != self.parameters.regex:
244
- final_regex = self.parameters.regex if self.parameters.regex is not None else self.regex
245
- self.regex = self.parameters.regex = final_regex
246
- if self.min_length != self.parameters.min_length:
247
- final_min_length = self.parameters.min_length if self.parameters.min_length is not None else self.min_length
248
- self.min_length = self.parameters.min_length = final_min_length
249
- if self.max_length != self.parameters.max_length:
250
- final_max_length = self.parameters.max_length if self.parameters.max_length is not None else self.max_length
251
- self.max_length = self.parameters.max_length = final_max_length
252
- return self
253
-
254
248
  def get_regex(self) -> str | None:
255
249
  return self.parameters.regex
256
250
 
@@ -54,7 +54,7 @@ from infrahub.core.schema import (
54
54
  SchemaRoot,
55
55
  TemplateSchema,
56
56
  )
57
- from infrahub.core.schema.attribute_parameters import NumberPoolParameters
57
+ from infrahub.core.schema.attribute_parameters import NumberPoolParameters, TextAttributeParameters
58
58
  from infrahub.core.schema.attribute_schema import get_attribute_schema_class_for_kind
59
59
  from infrahub.core.schema.definitions.core import core_profile_schema_definition
60
60
  from infrahub.core.validators import CONSTRAINT_VALIDATOR_MAP
@@ -501,11 +501,76 @@ class SchemaBranch:
501
501
 
502
502
  return fields or None
503
503
 
504
+ def _text_attr_needs_reconciliation(self, attr: AttributeSchema) -> bool:
505
+ """Check if a Text attribute needs reconciliation between deprecated fields and parameters."""
506
+ if not isinstance(attr.parameters, TextAttributeParameters):
507
+ return False
508
+ return (
509
+ attr.regex != attr.parameters.regex
510
+ or attr.min_length != attr.parameters.min_length
511
+ or attr.max_length != attr.parameters.max_length
512
+ )
513
+
514
+ def _reconcile_text_attr(self, attr: AttributeSchema) -> None:
515
+ """Reconcile a single Text attribute's deprecated fields with parameters.
516
+
517
+ Parameters take precedence over deprecated top-level fields when both are set.
518
+ """
519
+ if not isinstance(attr.parameters, TextAttributeParameters):
520
+ return
521
+
522
+ # Sync regex: parameters takes precedence
523
+ if attr.parameters.regex is not None:
524
+ attr.regex = attr.parameters.regex
525
+ elif attr.regex is not None:
526
+ attr.parameters.regex = attr.regex
527
+
528
+ # Sync min_length: parameters takes precedence
529
+ if attr.parameters.min_length is not None:
530
+ attr.min_length = attr.parameters.min_length
531
+ elif attr.min_length is not None:
532
+ attr.parameters.min_length = attr.min_length
533
+
534
+ # Sync max_length: parameters takes precedence
535
+ if attr.parameters.max_length is not None:
536
+ attr.max_length = attr.parameters.max_length
537
+ elif attr.max_length is not None:
538
+ attr.parameters.max_length = attr.max_length
539
+
540
+ def _reconcile_text_attribute_parameters(self, schema: SchemaRoot | None = None) -> None:
541
+ """Reconcile regex, min_length, max_length between deprecated fields and parameters for Text attributes.
542
+
543
+ Args:
544
+ schema: If provided, reconcile incoming schema data before merging.
545
+ If None, reconcile already-loaded schemas (e.g., from database).
546
+ """
547
+ if schema:
548
+ # Incoming schema: modify in place
549
+ for item in schema.nodes + schema.generics:
550
+ for attr in item.attributes:
551
+ self._reconcile_text_attr(attr)
552
+ return
553
+
554
+ # Loaded schemas: need to duplicate before modifying
555
+ for name in self.all_names:
556
+ node = self.get(name=name, duplicate=False)
557
+
558
+ if not any(self._text_attr_needs_reconciliation(attr) for attr in node.attributes):
559
+ continue
560
+
561
+ node = node.duplicate()
562
+ for attr in node.attributes:
563
+ self._reconcile_text_attr(attr)
564
+ self.set(name=name, schema=node)
565
+
504
566
  def load_schema(self, schema: SchemaRoot) -> None:
505
567
  """Load a SchemaRoot object and store all NodeSchema or GenericSchema.
506
568
 
507
569
  In the current implementation, if a schema object present in the SchemaRoot already exist, it will be overwritten.
508
570
  """
571
+ # Reconcile deprecated text attribute parameters before merging
572
+ self._reconcile_text_attribute_parameters(schema)
573
+
509
574
  for item in schema.nodes + schema.generics:
510
575
  try:
511
576
  if item.id:
@@ -545,6 +610,7 @@ class SchemaBranch:
545
610
  self.generate_identifiers()
546
611
  self.process_default_values()
547
612
  self.process_deprecations()
613
+ self._reconcile_text_attribute_parameters()
548
614
  self.process_cardinality_counts()
549
615
  self.process_inheritance()
550
616
  self.process_hierarchy()
@@ -36,7 +36,7 @@ class AttributeKindUpdateValidatorQuery(AttributeSchemaValidatorQuery):
36
36
  self.params["null_value"] = NULL_VALUE
37
37
 
38
38
  query = """
39
- MATCH p = (n:%(node_kind)s)
39
+ MATCH (n:%(node_kinds)s)
40
40
  CALL (n) {
41
41
  MATCH path = (root:Root)<-[rr:IS_PART_OF]-(n)-[ra:HAS_ATTRIBUTE]-(:Attribute { name: $attr_name } )-[rv:HAS_VALUE]-(av:AttributeValue)
42
42
  WHERE all(
@@ -51,7 +51,10 @@ class AttributeKindUpdateValidatorQuery(AttributeSchemaValidatorQuery):
51
51
  WHERE all(r in relationships(full_path) WHERE r.status = "active")
52
52
  AND attribute_value IS NOT NULL
53
53
  AND attribute_value <> $null_value
54
- """ % {"branch_filter": branch_filter, "node_kind": self.node_schema.kind}
54
+ """ % {
55
+ "branch_filter": branch_filter,
56
+ "node_kinds": f"{self.node_schema.kind}|Profile{self.node_schema.kind}|Template{self.node_schema.kind}",
57
+ }
55
58
 
56
59
  self.add_to_query(query)
57
60
  self.return_labels = ["node.uuid", "attribute_value", "value_relationship.branch as value_branch"]
infrahub/graphql/app.py CHANGED
@@ -172,9 +172,9 @@ class InfrahubGraphQLApp:
172
172
 
173
173
  response = handler(request)
174
174
  if isawaitable(response):
175
- return await cast("Awaitable[Response]", response)
175
+ return await response
176
176
 
177
- return cast("Response", response)
177
+ return response
178
178
 
179
179
  async def _handle_http_request(
180
180
  self, request: Request, db: InfrahubDatabase, branch: Branch, account_session: AccountSession
@@ -60,10 +60,10 @@ class ConflictDetails(ObjectType):
60
60
 
61
61
 
62
62
  class DiffSummaryCounts(ObjectType):
63
- num_added = Int(required=False)
64
- num_updated = Int(required=False)
65
- num_removed = Int(required=False)
66
- num_conflicts = Int(required=False)
63
+ num_added = Int(required=True)
64
+ num_updated = Int(required=True)
65
+ num_removed = Int(required=True)
66
+ num_conflicts = Int(required=True)
67
67
 
68
68
 
69
69
  class DiffProperty(ObjectType):
@@ -146,7 +146,7 @@ class DiffTreeSummary(DiffSummaryCounts):
146
146
  diff_branch = String(required=True)
147
147
  from_time = DateTime(required=True)
148
148
  to_time = DateTime(required=True)
149
- num_unchanged = Int(required=False)
149
+ num_unchanged = Int(required=True)
150
150
  num_untracked_base_changes = Int(required=False)
151
151
  num_untracked_diff_changes = Int(required=False)
152
152
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: infrahub-server
3
- Version: 1.6.1
3
+ Version: 1.6.3
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
@@ -79,7 +79,7 @@ infrahub/constants/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuF
79
79
  infrahub/constants/database.py,sha256=p0Ga54CQLnjziSWmLRDzdUUBJs2ImPWPyPPozofmGhI,502
80
80
  infrahub/constants/environment.py,sha256=ry-6qsBzSumOjjiq1D3XNoquf1LWqFKiQSJj8t6nET4,32
81
81
  infrahub/core/__init__.py,sha256=z6EJBZyCYCBqinoBtX9li6BTBbbGV8WCkE_4CrEsmDA,104
82
- infrahub/core/account.py,sha256=6f1cIDWvL-HsbzL0UwWoCbDTzx55wzd_SkpQXiKDjcE,27477
82
+ infrahub/core/account.py,sha256=uXr12tcA6rqufAb0FGgd68y3W79qqlDxnkSonazt4Mc,27470
83
83
  infrahub/core/attribute.py,sha256=quW5lG-e4c3VjIhiSta12TUTB8Uv_Gmi8mwTenwBSIo,44921
84
84
  infrahub/core/enums.py,sha256=qGbhRVoH43Xi0iDkUfWdQiKapJbLT9UKsCobFk_paIk,491
85
85
  infrahub/core/initialization.py,sha256=MuhZR6VDFfEiQw_ZPm-LBcBQmpvEdaxovGWtx_YKtVc,22081
@@ -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
@@ -248,7 +249,7 @@ infrahub/core/migrations/query/node_duplicate.py,sha256=yaxeZBYd52jgEB5XY1PZxksT
248
249
  infrahub/core/migrations/query/relationship_duplicate.py,sha256=hjUFjNqhaFc2tEg79BXR2xDr_4Wdmu9fVF02cTEICTk,7319
249
250
  infrahub/core/migrations/query/schema_attribute_update.py,sha256=fLclNEgoikO_ddlFEo1ts-dZwTXITA85kdJ00fXFxqo,3382
250
251
  infrahub/core/migrations/schema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
251
- infrahub/core/migrations/schema/attribute_kind_update.py,sha256=uJmGdNnAg2fDYqLUw_kM7qQXTdo_V785817u0DotUKo,6323
252
+ infrahub/core/migrations/schema/attribute_kind_update.py,sha256=hCu7LP8hS_LMv9zHmByb_gFEm1xcN_wREkuO1qDWJf4,6453
252
253
  infrahub/core/migrations/schema/attribute_name_update.py,sha256=gebaeQX1MLmOxupTPcCzLJdeEQlUzs3XIl7T15-RdXY,1595
253
254
  infrahub/core/migrations/schema/attribute_supports_profile.py,sha256=xEmLV1Km-GOpvUAia0izN9VWERveSGcikb0AHbuFs5g,3465
254
255
  infrahub/core/migrations/schema/models.py,sha256=F1yp0GM-HutGdzhE0uPFq9JCTH9iHM3V4iDm2e2c4YU,1357
@@ -276,7 +277,7 @@ infrahub/core/node/resource_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQ
276
277
  infrahub/core/node/resource_manager/ip_address_pool.py,sha256=pJa3peul-sNNN_tNNsMn8TB6Jp8cbuh4xwrIf6-3Nd0,5265
277
278
  infrahub/core/node/resource_manager/ip_prefix_pool.py,sha256=z1CY7OM41p-X3dJcuGu7coDHDoGHvnB4puvmmleVmrU,5527
278
279
  infrahub/core/node/resource_manager/number_pool.py,sha256=KaDxJdIspQ_riXcDGn6RSBDltxEIonmoj68vsQvhFwE,5829
279
- infrahub/core/query/__init__.py,sha256=2qIMaODLwJ6pK6BUd5vODTlA15Aecf5I8_-J44UlCso,23089
280
+ infrahub/core/query/__init__.py,sha256=XPnVyuCQ-Vf5f6yZGZ4Foe2P-CW4DiIC3XECxMRVwmY,23557
280
281
  infrahub/core/query/attribute.py,sha256=eHrxXo-5YV4oUOx9kaU0rMKv-9lCRcqz2PMWNtqPuUM,14867
281
282
  infrahub/core/query/branch.py,sha256=yZ7lasZ06-F0P7t_l40GFWM_JP1q_6_IxRhiVxvEG4o,4809
282
283
  infrahub/core/query/delete.py,sha256=7tPP1qtNV6QGYtmgE1RKsuQ9oxENnMTVkttLvJ2PiKg,1927
@@ -300,8 +301,8 @@ infrahub/core/relationship/constraints/peer_parent.py,sha256=z7elpC8xS_ovAF28Haq
300
301
  infrahub/core/relationship/constraints/peer_relatives.py,sha256=Ye79l7njaWxZkU2chTOaptIjvKBIawsNCl0IQxCTDtM,2737
301
302
  infrahub/core/relationship/constraints/profiles_kind.py,sha256=nEZPGtGcmelZ1Nb8EPcQ-7_zCLCNIYwwWbU6C9fLj5E,2464
302
303
  infrahub/core/schema/__init__.py,sha256=_vOy96uKjAxj8nvTR0qzHcnIYUzdVAAcUIk2kyUKjCQ,6641
303
- infrahub/core/schema/attribute_parameters.py,sha256=ABL1GEsOl4_CcDvK9_NucGMaF6LUeOjAxbDQVm_G7eg,6516
304
- infrahub/core/schema/attribute_schema.py,sha256=kYyTtNtvz6Zli3Kw3dtLaR3RtnNdxNTtDG-kvXnmE5A,10502
304
+ infrahub/core/schema/attribute_parameters.py,sha256=EMkjs7x0Rakxqu-ckXJ0VZCPzRGrRt2DBoKX6OWrJWM,7477
305
+ infrahub/core/schema/attribute_schema.py,sha256=1DVEwFnHYq08cyehJA3dl5-p8cSoBXaR2YECXqxkWXM,10049
305
306
  infrahub/core/schema/basenode_schema.py,sha256=Se-pEYgnL2Y6_OSMZrl5BWgW9taBaBaqddL2NoXfArE,29765
306
307
  infrahub/core/schema/computed_attribute.py,sha256=9rznZJpGqX8fxLx0EguPmww8LoHsadMtQQUKaMoJPcI,1809
307
308
  infrahub/core/schema/constants.py,sha256=KtFrvwNckyKZSGIMD4XfxI5eFTZqBRiw54R7BE5h39Q,374
@@ -311,7 +312,7 @@ infrahub/core/schema/manager.py,sha256=Zz1kRc5g_-1U5xlj6kuOG1ltnpntkkbyMQeP1z0we
311
312
  infrahub/core/schema/node_schema.py,sha256=W2Jx5QXrQ5ygUEyTKnIHhj6Xe7jJ6Y-iQArEo05cWRI,6341
312
313
  infrahub/core/schema/profile_schema.py,sha256=sV4lp1UyBye12M7BJcA2obb4tx3M9J5P89SLqkmFxJY,1237
313
314
  infrahub/core/schema/relationship_schema.py,sha256=ryCvmUQl3HBo_Sk07Xl5rT48PPuhlBkYRmm-lSdfJPI,8445
314
- infrahub/core/schema/schema_branch.py,sha256=eLxy1lDR1K5F2OvO4h3jrr_V_8_1amoEc-QaGnXbTL4,120204
315
+ infrahub/core/schema/schema_branch.py,sha256=IsD8NZ9454ohju_Wp-2n2amtjw1GDuRx_dgc0c3CTzA,123061
315
316
  infrahub/core/schema/schema_branch_computed.py,sha256=14UUsQJDLMHkYhg7QMqeLiTF3PO8c8rGa90ul3F2ZZo,10629
316
317
  infrahub/core/schema/schema_branch_display.py,sha256=bvXVSZZC1uilBicTXeUdrPkxIVuIIY0aLjkJQkvrTbY,6098
317
318
  infrahub/core/schema/schema_branch_hfid.py,sha256=XcNV2nNbpOhif5HHN6wvXXuM-nY8eMWhlidr4g8riro,5276
@@ -358,7 +359,7 @@ infrahub/core/validators/tasks.py,sha256=Qb9q2l55NKhvWXCrZclVWvJhzsN3yniN7nsYqUL
358
359
  infrahub/core/validators/attribute/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
359
360
  infrahub/core/validators/attribute/choices.py,sha256=Zt_iy6g2ANK4wBOgWqnhvU0dZ2ZYGvyhu93t7eNwj8Q,5380
360
361
  infrahub/core/validators/attribute/enum.py,sha256=3PzkYUuzbt8NqRH4IP4cMjoDxzUvJzbNYC5ZpW5zKZQ,4161
361
- infrahub/core/validators/attribute/kind.py,sha256=uzMo4Qf-AyvSlwgURgALd7QVMEl6237tb148-wgTDjE,4611
362
+ infrahub/core/validators/attribute/kind.py,sha256=nJFV9Dh164013_8AtMCEZvo5TH7r4L15IaPsTqqBC-E,4712
362
363
  infrahub/core/validators/attribute/length.py,sha256=H0nP2x2ynzcbMnc6neIje01wXipbt8Wr49iNTqIvWxI,4526
363
364
  infrahub/core/validators/attribute/min_max.py,sha256=3x6iCJuVdt3vim6wPaF4Bar8RlR3FhJu3DYQiR2GZRI,5661
364
365
  infrahub/core/validators/attribute/number_pool.py,sha256=edWmpHbme9YqWxeZJ5V0dvTCyIqLFyej2YNTyM-Emq4,4709
@@ -488,7 +489,7 @@ infrahub/git_credential/askpass.py,sha256=BL7e4Xkx5la7XFk-GQR6MXxV5B29Mzb5ZnVnlj
488
489
  infrahub/git_credential/helper.py,sha256=cwSMKRTgqrqIBM66jEOtlj4MMLf647KJWmtnnVxFtTY,2337
489
490
  infrahub/graphql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
490
491
  infrahub/graphql/analyzer.py,sha256=2-C1Wli0fXpXTVvNtP7IxiKWBJN97lqOeEP2L0oy3ho,30944
491
- infrahub/graphql/app.py,sha256=JwLNHbsEBKLameZ2UhK2RRxnt6kt2AoQUUpHOvk8wCo,21186
492
+ infrahub/graphql/app.py,sha256=5BudFFwmV0LJizN0m4Cioe5-DbpTp5-QxHUhwlPIHpk,21139
492
493
  infrahub/graphql/constants.py,sha256=iVvo3HK-ch7YmHw1Eg2E_ja3I45cNAwjpYahsnu85CI,37
493
494
  infrahub/graphql/context.py,sha256=ahp-MvX_0glg9mSPbPVhEwvbYzrIKtaEAGt7CVnAusE,1681
494
495
  infrahub/graphql/directives.py,sha256=wyIkJFp7l0J4JqNl1Lqu7YfKXP7glrewlQFMDTUAPcE,645
@@ -566,7 +567,7 @@ infrahub/graphql/queries/search.py,sha256=22MCNHMHrc0C6MjMSNxzIdnDUug-Gp2NGtO4qP
566
567
  infrahub/graphql/queries/status.py,sha256=BSCBT4abaswlfh7JZB8mk_rR-6FXIx-wxQA_YwiWvI4,2124
567
568
  infrahub/graphql/queries/task.py,sha256=UG9Ur2CH5GOmfyk34ItqAPuCEkqIhdU-G1n6C3iK_lc,3921
568
569
  infrahub/graphql/queries/diff/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
569
- infrahub/graphql/queries/diff/tree.py,sha256=QM4y7uQE-bP48bmfpWBfA22mcWEWTTrwZYCxIhBRz8Y,25256
570
+ infrahub/graphql/queries/diff/tree.py,sha256=nCnjQbCP6VzV8ZEO62NYa5_Eiz9Pd-KAC9ms6gmqkUs,25251
570
571
  infrahub/graphql/resolvers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
571
572
  infrahub/graphql/resolvers/ipam.py,sha256=kGrr5X6nseA-N8UCK9Hh2V-U3txyL3wIX7oQYJ7oi-U,17625
572
573
  infrahub/graphql/resolvers/many_relationship.py,sha256=ECWGpRUG22kvY6BkxCMNYex_ZaJopuEWgejGHD28wVY,9743
@@ -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.3.dist-info/METADATA,sha256=LbmpeUrNY4vGz6V7ngsWfSHfvseeQGWjw94Cap_4ziQ,5898
892
+ infrahub_server-1.6.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
893
+ infrahub_server-1.6.3.dist-info/entry_points.txt,sha256=_xSAw1Wp-GslD95j4FESCxU1H7G7B9b42zp8-LAmC8Q,406
894
+ infrahub_server-1.6.3.dist-info/licenses/LICENSE.txt,sha256=7GQO7kxVoQYnZtFrjZBKLRXbrGwwwimHPPOJtqXsozQ,11340
895
+ infrahub_server-1.6.3.dist-info/RECORD,,