infrahub-server 1.6.3__py3-none-any.whl → 1.7.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 +4 -2
- infrahub/api/exceptions.py +2 -2
- infrahub/api/schema.py +3 -1
- infrahub/artifacts/tasks.py +1 -0
- infrahub/auth.py +2 -2
- infrahub/cli/db.py +54 -28
- infrahub/computed_attribute/gather.py +3 -4
- infrahub/computed_attribute/tasks.py +23 -6
- infrahub/config.py +8 -0
- infrahub/constants/enums.py +12 -0
- infrahub/core/account.py +4 -4
- infrahub/core/attribute.py +106 -108
- infrahub/core/branch/models.py +44 -71
- infrahub/core/branch/tasks.py +5 -3
- infrahub/core/changelog/diff.py +1 -20
- infrahub/core/changelog/models.py +0 -7
- infrahub/core/constants/__init__.py +17 -0
- infrahub/core/constants/database.py +0 -1
- infrahub/core/constants/schema.py +0 -1
- infrahub/core/convert_object_type/repository_conversion.py +3 -4
- infrahub/core/diff/branch_differ.py +1 -1
- infrahub/core/diff/conflict_transferer.py +1 -1
- infrahub/core/diff/data_check_synchronizer.py +4 -3
- infrahub/core/diff/enricher/cardinality_one.py +2 -2
- infrahub/core/diff/enricher/hierarchy.py +1 -1
- infrahub/core/diff/enricher/labels.py +1 -1
- infrahub/core/diff/merger/merger.py +28 -2
- infrahub/core/diff/merger/serializer.py +3 -10
- infrahub/core/diff/model/diff.py +1 -1
- infrahub/core/diff/query/merge.py +376 -135
- infrahub/core/diff/repository/repository.py +3 -1
- infrahub/core/graph/__init__.py +1 -1
- infrahub/core/graph/constraints.py +3 -3
- infrahub/core/graph/schema.py +2 -12
- infrahub/core/ipam/reconciler.py +8 -6
- infrahub/core/ipam/utilization.py +8 -15
- infrahub/core/manager.py +133 -152
- infrahub/core/merge.py +1 -1
- infrahub/core/metadata/__init__.py +0 -0
- infrahub/core/metadata/interface.py +37 -0
- infrahub/core/metadata/model.py +31 -0
- infrahub/core/metadata/query/__init__.py +0 -0
- infrahub/core/metadata/query/node_metadata.py +301 -0
- infrahub/core/migrations/graph/__init__.py +4 -0
- infrahub/core/migrations/graph/m012_convert_account_generic.py +12 -12
- infrahub/core/migrations/graph/m013_convert_git_password_credential.py +7 -12
- infrahub/core/migrations/graph/m017_add_core_profile.py +5 -2
- infrahub/core/migrations/graph/m018_uniqueness_nulls.py +2 -1
- infrahub/core/migrations/graph/m019_restore_rels_to_time.py +0 -10
- infrahub/core/migrations/graph/m020_duplicate_edges.py +0 -8
- infrahub/core/migrations/graph/m025_uniqueness_nulls.py +2 -1
- infrahub/core/migrations/graph/m026_0000_prefix_fix.py +2 -1
- infrahub/core/migrations/graph/m029_duplicates_cleanup.py +0 -1
- infrahub/core/migrations/graph/m031_check_number_attributes.py +2 -2
- infrahub/core/migrations/graph/m038_redo_0000_prefix_fix.py +2 -1
- infrahub/core/migrations/graph/m041_deleted_dup_edges.py +1 -1
- infrahub/core/migrations/graph/m049_remove_is_visible_relationship.py +53 -0
- infrahub/core/migrations/graph/m050_backfill_vertex_metadata.py +168 -0
- infrahub/core/migrations/query/__init__.py +2 -2
- infrahub/core/migrations/query/attribute_add.py +17 -6
- infrahub/core/migrations/query/attribute_remove.py +19 -5
- infrahub/core/migrations/query/attribute_rename.py +21 -5
- infrahub/core/migrations/query/node_duplicate.py +19 -4
- infrahub/core/migrations/query/schema_attribute_update.py +1 -1
- infrahub/core/migrations/schema/attribute_kind_update.py +21 -2
- infrahub/core/migrations/schema/attribute_name_update.py +1 -1
- infrahub/core/migrations/schema/attribute_supports_profile.py +5 -3
- infrahub/core/migrations/schema/models.py +3 -0
- infrahub/core/migrations/schema/node_attribute_add.py +5 -2
- infrahub/core/migrations/schema/node_attribute_remove.py +1 -1
- infrahub/core/migrations/schema/node_kind_update.py +1 -1
- infrahub/core/migrations/schema/node_remove.py +24 -2
- infrahub/core/migrations/schema/tasks.py +4 -1
- infrahub/core/migrations/shared.py +13 -6
- infrahub/core/models.py +6 -6
- infrahub/core/node/__init__.py +157 -58
- infrahub/core/node/base.py +9 -5
- infrahub/core/node/create.py +7 -3
- infrahub/core/node/delete_validator.py +1 -1
- infrahub/core/node/standard.py +100 -14
- infrahub/core/order.py +30 -0
- infrahub/core/property.py +0 -1
- infrahub/core/protocols.py +1 -0
- infrahub/core/protocols_base.py +10 -2
- infrahub/core/query/__init__.py +5 -3
- infrahub/core/query/attribute.py +164 -49
- infrahub/core/query/branch.py +58 -70
- infrahub/core/query/delete.py +1 -1
- infrahub/core/query/diff.py +7 -7
- infrahub/core/query/ipam.py +104 -43
- infrahub/core/query/node.py +1072 -281
- infrahub/core/query/relationship.py +531 -325
- infrahub/core/query/resource_manager.py +107 -18
- infrahub/core/query/standard_node.py +25 -5
- infrahub/core/query/utils.py +2 -4
- infrahub/core/relationship/constraints/count.py +1 -1
- infrahub/core/relationship/constraints/peer_kind.py +1 -1
- infrahub/core/relationship/constraints/peer_parent.py +1 -1
- infrahub/core/relationship/constraints/peer_relatives.py +1 -1
- infrahub/core/relationship/constraints/profiles_kind.py +1 -1
- infrahub/core/relationship/constraints/profiles_removal.py +168 -0
- infrahub/core/relationship/model.py +293 -139
- infrahub/core/schema/attribute_schema.py +2 -2
- infrahub/core/schema/basenode_schema.py +3 -0
- infrahub/core/schema/definitions/core/__init__.py +8 -2
- infrahub/core/schema/definitions/core/account.py +10 -10
- infrahub/core/schema/definitions/core/artifact.py +14 -8
- infrahub/core/schema/definitions/core/check.py +10 -4
- infrahub/core/schema/definitions/core/generator.py +26 -6
- infrahub/core/schema/definitions/core/graphql_query.py +1 -1
- infrahub/core/schema/definitions/core/group.py +9 -2
- infrahub/core/schema/definitions/core/ipam.py +80 -10
- infrahub/core/schema/definitions/core/menu.py +41 -7
- infrahub/core/schema/definitions/core/permission.py +16 -2
- infrahub/core/schema/definitions/core/profile.py +16 -2
- infrahub/core/schema/definitions/core/propose_change.py +24 -4
- infrahub/core/schema/definitions/core/propose_change_comment.py +23 -11
- infrahub/core/schema/definitions/core/propose_change_validator.py +50 -21
- infrahub/core/schema/definitions/core/repository.py +10 -0
- infrahub/core/schema/definitions/core/resource_pool.py +8 -1
- infrahub/core/schema/definitions/core/template.py +19 -2
- infrahub/core/schema/definitions/core/transform.py +11 -5
- infrahub/core/schema/definitions/core/webhook.py +27 -9
- infrahub/core/schema/manager.py +63 -43
- infrahub/core/schema/relationship_schema.py +6 -2
- infrahub/core/schema/schema_branch.py +48 -10
- infrahub/core/task/task.py +4 -2
- infrahub/core/utils.py +3 -25
- infrahub/core/validators/aggregated_checker.py +1 -1
- infrahub/core/validators/attribute/choices.py +1 -1
- infrahub/core/validators/attribute/enum.py +1 -1
- infrahub/core/validators/attribute/kind.py +1 -1
- infrahub/core/validators/attribute/length.py +1 -1
- infrahub/core/validators/attribute/min_max.py +1 -1
- infrahub/core/validators/attribute/number_pool.py +1 -1
- infrahub/core/validators/attribute/optional.py +1 -1
- infrahub/core/validators/attribute/regex.py +1 -1
- infrahub/core/validators/determiner.py +3 -3
- infrahub/core/validators/node/attribute.py +1 -1
- infrahub/core/validators/node/relationship.py +1 -1
- infrahub/core/validators/relationship/peer.py +1 -1
- infrahub/database/__init__.py +4 -4
- infrahub/dependencies/builder/constraint/grouped/node_runner.py +2 -0
- infrahub/dependencies/builder/constraint/relationship_manager/profiles_removal.py +8 -0
- infrahub/dependencies/registry.py +2 -0
- infrahub/display_labels/tasks.py +12 -3
- infrahub/git/integrator.py +18 -18
- infrahub/git/tasks.py +1 -1
- infrahub/git/utils.py +1 -1
- infrahub/graphql/constants.py +3 -0
- infrahub/graphql/context.py +1 -1
- infrahub/graphql/field_extractor.py +1 -1
- infrahub/graphql/initialization.py +11 -0
- infrahub/graphql/loaders/account.py +134 -0
- infrahub/graphql/loaders/node.py +5 -12
- infrahub/graphql/loaders/peers.py +5 -7
- infrahub/graphql/manager.py +175 -21
- infrahub/graphql/metadata.py +91 -0
- infrahub/graphql/mutations/account.py +6 -6
- infrahub/graphql/mutations/attribute.py +0 -2
- infrahub/graphql/mutations/branch.py +9 -5
- infrahub/graphql/mutations/computed_attribute.py +1 -1
- infrahub/graphql/mutations/display_label.py +1 -1
- infrahub/graphql/mutations/hfid.py +1 -1
- infrahub/graphql/mutations/ipam.py +4 -6
- infrahub/graphql/mutations/main.py +9 -4
- infrahub/graphql/mutations/profile.py +16 -22
- infrahub/graphql/mutations/proposed_change.py +4 -4
- infrahub/graphql/mutations/relationship.py +40 -10
- infrahub/graphql/mutations/repository.py +14 -12
- infrahub/graphql/mutations/schema.py +2 -2
- infrahub/graphql/order.py +14 -0
- infrahub/graphql/queries/branch.py +62 -6
- infrahub/graphql/queries/resource_manager.py +25 -24
- infrahub/graphql/resolvers/account_metadata.py +84 -0
- infrahub/graphql/resolvers/ipam.py +6 -8
- infrahub/graphql/resolvers/many_relationship.py +77 -35
- infrahub/graphql/resolvers/resolver.py +59 -14
- infrahub/graphql/resolvers/single_relationship.py +87 -23
- infrahub/graphql/subscription/graphql_query.py +2 -0
- infrahub/graphql/types/__init__.py +0 -1
- infrahub/graphql/types/attribute.py +10 -5
- infrahub/graphql/types/branch.py +40 -53
- infrahub/graphql/types/enums.py +3 -0
- infrahub/graphql/types/metadata.py +28 -0
- infrahub/graphql/types/node.py +22 -2
- infrahub/graphql/types/relationship.py +10 -2
- infrahub/graphql/types/standard_node.py +12 -7
- infrahub/hfid/tasks.py +12 -3
- infrahub/lock.py +7 -0
- infrahub/menu/repository.py +1 -1
- infrahub/patch/queries/base.py +1 -1
- infrahub/pools/number.py +1 -8
- infrahub/profiles/gather.py +56 -0
- infrahub/profiles/mandatory_fields_checker.py +116 -0
- infrahub/profiles/models.py +66 -0
- infrahub/profiles/node_applier.py +154 -13
- infrahub/profiles/queries/get_profile_data.py +143 -31
- infrahub/profiles/tasks.py +79 -27
- infrahub/profiles/triggers.py +22 -0
- infrahub/proposed_change/action_checker.py +1 -1
- infrahub/proposed_change/tasks.py +4 -1
- infrahub/services/__init__.py +1 -1
- infrahub/services/adapters/cache/nats.py +1 -1
- infrahub/services/adapters/cache/redis.py +7 -0
- infrahub/tasks/artifact.py +1 -0
- infrahub/transformations/tasks.py +2 -2
- infrahub/trigger/catalogue.py +2 -0
- infrahub/trigger/models.py +1 -0
- infrahub/trigger/setup.py +3 -3
- infrahub/trigger/tasks.py +3 -0
- infrahub/validators/tasks.py +1 -0
- infrahub/webhook/gather.py +1 -1
- infrahub/webhook/models.py +1 -1
- infrahub/webhook/tasks.py +23 -7
- infrahub/workers/dependencies.py +9 -3
- infrahub/workers/infrahub_async.py +13 -4
- infrahub/workflows/catalogue.py +19 -0
- infrahub_sdk/analyzer.py +2 -2
- infrahub_sdk/branch.py +12 -39
- infrahub_sdk/checks.py +4 -4
- infrahub_sdk/client.py +36 -0
- infrahub_sdk/ctl/cli_commands.py +2 -1
- infrahub_sdk/ctl/graphql.py +15 -4
- infrahub_sdk/ctl/utils.py +2 -2
- infrahub_sdk/enums.py +6 -0
- infrahub_sdk/graphql/renderers.py +21 -0
- infrahub_sdk/graphql/utils.py +85 -0
- infrahub_sdk/node/attribute.py +12 -2
- infrahub_sdk/node/constants.py +12 -0
- infrahub_sdk/node/metadata.py +69 -0
- infrahub_sdk/node/node.py +65 -14
- infrahub_sdk/node/property.py +3 -0
- infrahub_sdk/node/related_node.py +37 -5
- infrahub_sdk/node/relationship.py +18 -1
- infrahub_sdk/operation.py +2 -2
- infrahub_sdk/schema/repository.py +1 -2
- infrahub_sdk/transforms.py +2 -2
- infrahub_sdk/types.py +18 -2
- {infrahub_server-1.6.3.dist-info → infrahub_server-1.7.0.dist-info}/METADATA +17 -16
- {infrahub_server-1.6.3.dist-info → infrahub_server-1.7.0.dist-info}/RECORD +249 -228
- infrahub_testcontainers/container.py +3 -3
- infrahub_testcontainers/docker-compose-cluster.test.yml +7 -7
- infrahub_testcontainers/docker-compose.test.yml +13 -5
- infrahub_testcontainers/models.py +3 -3
- infrahub_testcontainers/performance_test.py +1 -1
- infrahub/graphql/models.py +0 -6
- {infrahub_server-1.6.3.dist-info → infrahub_server-1.7.0.dist-info}/WHEEL +0 -0
- {infrahub_server-1.6.3.dist-info → infrahub_server-1.7.0.dist-info}/entry_points.txt +0 -0
- {infrahub_server-1.6.3.dist-info → infrahub_server-1.7.0.dist-info}/licenses/LICENSE.txt +0 -0
infrahub/core/attribute.py
CHANGED
|
@@ -15,18 +15,27 @@ from pydantic import BaseModel, Field
|
|
|
15
15
|
from infrahub import config
|
|
16
16
|
from infrahub.core import registry
|
|
17
17
|
from infrahub.core.changelog.models import AttributeChangelog
|
|
18
|
-
from infrahub.core.constants import
|
|
18
|
+
from infrahub.core.constants import (
|
|
19
|
+
NULL_VALUE,
|
|
20
|
+
SYSTEM_USER_ID,
|
|
21
|
+
AttributeDBNodeType,
|
|
22
|
+
BranchSupportType,
|
|
23
|
+
InfrahubKind,
|
|
24
|
+
MetadataOptions,
|
|
25
|
+
)
|
|
26
|
+
from infrahub.core.metadata.interface import MetadataInterface
|
|
27
|
+
from infrahub.core.metadata.model import MetadataInfo
|
|
19
28
|
from infrahub.core.property import FlagPropertyMixin, NodePropertyData, NodePropertyMixin
|
|
20
29
|
from infrahub.core.query.attribute import (
|
|
21
30
|
AttributeClearNodePropertyQuery,
|
|
22
|
-
|
|
31
|
+
AttributeDeleteQuery,
|
|
23
32
|
AttributeUpdateFlagQuery,
|
|
24
33
|
AttributeUpdateNodePropertyQuery,
|
|
25
34
|
AttributeUpdateValueQuery,
|
|
26
35
|
)
|
|
27
36
|
from infrahub.core.query.node import AttributeFromDB, NodeListGetAttributeQuery
|
|
28
37
|
from infrahub.core.timestamp import Timestamp
|
|
29
|
-
from infrahub.core.utils import
|
|
38
|
+
from infrahub.core.utils import convert_ip_to_binary_str
|
|
30
39
|
from infrahub.exceptions import ValidationError
|
|
31
40
|
from infrahub.helpers import hash_password
|
|
32
41
|
|
|
@@ -70,12 +79,11 @@ class AttributeCreateData(BaseModel):
|
|
|
70
79
|
content: dict[str, Any]
|
|
71
80
|
is_default: bool
|
|
72
81
|
is_protected: bool
|
|
73
|
-
is_visible: bool
|
|
74
82
|
source_prop: list[NodePropertyData] = Field(default_factory=list)
|
|
75
83
|
owner_prop: list[NodePropertyData] = Field(default_factory=list)
|
|
76
84
|
|
|
77
85
|
|
|
78
|
-
class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
86
|
+
class BaseAttribute(FlagPropertyMixin, NodePropertyMixin, MetadataInterface):
|
|
79
87
|
type: type | tuple[type] | None = None
|
|
80
88
|
|
|
81
89
|
_rel_to_node_label: str = RELATIONSHIP_TO_NODE_LABEL
|
|
@@ -91,7 +99,6 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
91
99
|
id: str | None = None,
|
|
92
100
|
db_id: str | None = None,
|
|
93
101
|
data: dict | str | AttributeFromDB | None = None,
|
|
94
|
-
updated_at: Timestamp | str | None = None,
|
|
95
102
|
is_default: bool = False,
|
|
96
103
|
is_from_profile: bool = False,
|
|
97
104
|
**kwargs: dict[str, Any],
|
|
@@ -99,7 +106,6 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
99
106
|
self.id = id
|
|
100
107
|
self.db_id = db_id
|
|
101
108
|
|
|
102
|
-
self.updated_at = updated_at
|
|
103
109
|
self.name = name
|
|
104
110
|
self.node = node
|
|
105
111
|
self.schema = schema
|
|
@@ -112,6 +118,13 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
112
118
|
self._init_node_property_mixin(kwargs)
|
|
113
119
|
self._init_flag_property_mixin(kwargs)
|
|
114
120
|
|
|
121
|
+
self._metadata = MetadataInfo(
|
|
122
|
+
created_at=kwargs.get("created_at"),
|
|
123
|
+
created_by=kwargs.get("created_by"),
|
|
124
|
+
updated_at=kwargs.get("updated_at"),
|
|
125
|
+
updated_by=kwargs.get("updated_by"),
|
|
126
|
+
)
|
|
127
|
+
|
|
115
128
|
self.value = None
|
|
116
129
|
|
|
117
130
|
if isinstance(data, AttributeFromDB):
|
|
@@ -130,8 +143,6 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
130
143
|
for field_name in fields_to_extract_from_data:
|
|
131
144
|
setattr(self, field_name, data.get(field_name, None))
|
|
132
145
|
|
|
133
|
-
if not self.updated_at and "updated_at" in data:
|
|
134
|
-
self.updated_at = Timestamp(data.get("updated_at"))
|
|
135
146
|
elif data is None:
|
|
136
147
|
self.is_default = True
|
|
137
148
|
else:
|
|
@@ -151,9 +162,6 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
151
162
|
if self.is_protected is None:
|
|
152
163
|
self.is_protected = False
|
|
153
164
|
|
|
154
|
-
if self.is_visible is None:
|
|
155
|
-
self.is_visible = True
|
|
156
|
-
|
|
157
165
|
@property
|
|
158
166
|
def is_enum(self) -> bool:
|
|
159
167
|
return bool(self.schema.enum)
|
|
@@ -187,6 +195,30 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
187
195
|
if self.is_enum and self.value:
|
|
188
196
|
self.value = self.schema.convert_value_to_enum(self.value)
|
|
189
197
|
|
|
198
|
+
def _set_created_at(self, value: Timestamp | None) -> None:
|
|
199
|
+
self._metadata.created_at = value
|
|
200
|
+
|
|
201
|
+
def _set_created_by(self, value: str | None) -> None:
|
|
202
|
+
self._metadata.created_by = value
|
|
203
|
+
|
|
204
|
+
def _set_updated_at(self, value: Timestamp | None) -> None:
|
|
205
|
+
self._metadata.updated_at = value
|
|
206
|
+
|
|
207
|
+
def _set_updated_by(self, value: str | None) -> None:
|
|
208
|
+
self._metadata.updated_by = value
|
|
209
|
+
|
|
210
|
+
def _get_created_at(self) -> Timestamp | None:
|
|
211
|
+
return self._metadata.created_at
|
|
212
|
+
|
|
213
|
+
def _get_created_by(self) -> str | None:
|
|
214
|
+
return self._metadata.created_by
|
|
215
|
+
|
|
216
|
+
def _get_updated_at(self) -> Timestamp | None:
|
|
217
|
+
return self._metadata.updated_at
|
|
218
|
+
|
|
219
|
+
def _get_updated_by(self) -> str | None:
|
|
220
|
+
return self._metadata.updated_by
|
|
221
|
+
|
|
190
222
|
@staticmethod
|
|
191
223
|
def get_allowed_property_in_path() -> list[str]:
|
|
192
224
|
return ["value"]
|
|
@@ -302,8 +334,10 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
302
334
|
if prop_name in data.node_properties:
|
|
303
335
|
setattr(self, prop_name, data.node_properties[prop_name].uuid)
|
|
304
336
|
|
|
305
|
-
|
|
306
|
-
|
|
337
|
+
self._set_created_at(data.created_at)
|
|
338
|
+
self._set_created_by(data.created_by)
|
|
339
|
+
self._set_updated_at(data.updated_at)
|
|
340
|
+
self._set_updated_by(data.updated_by)
|
|
307
341
|
|
|
308
342
|
def value_from_db(self, data: AttributeFromDB) -> Any:
|
|
309
343
|
if data.value == NULL_VALUE:
|
|
@@ -320,7 +354,9 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
320
354
|
"""Deserialize the value coming from the database."""
|
|
321
355
|
return data.value
|
|
322
356
|
|
|
323
|
-
async def save(
|
|
357
|
+
async def save(
|
|
358
|
+
self, db: InfrahubDatabase, user_id: str = SYSTEM_USER_ID, at: Timestamp | None = None
|
|
359
|
+
) -> AttributeChangelog | None:
|
|
324
360
|
"""Create or Update the Attribute in the database."""
|
|
325
361
|
|
|
326
362
|
save_at = Timestamp(at)
|
|
@@ -328,70 +364,34 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
328
364
|
if not self.id:
|
|
329
365
|
return None
|
|
330
366
|
|
|
331
|
-
return await self._update(
|
|
367
|
+
return await self._update(db=db, user_id=user_id, at=save_at)
|
|
332
368
|
|
|
333
|
-
async def delete(
|
|
369
|
+
async def delete(
|
|
370
|
+
self, db: InfrahubDatabase, user_id: str = SYSTEM_USER_ID, at: Timestamp | None = None
|
|
371
|
+
) -> AttributeChangelog | None:
|
|
334
372
|
if not self.db_id:
|
|
335
373
|
return None
|
|
336
374
|
|
|
337
375
|
delete_at = Timestamp(at)
|
|
376
|
+
branch = self.get_branch_based_on_support_type()
|
|
338
377
|
|
|
339
|
-
query = await
|
|
378
|
+
query = await AttributeDeleteQuery.init(db=db, branch=branch, attr=self, user_id=user_id, at=delete_at)
|
|
340
379
|
await query.execute(db=db)
|
|
341
|
-
|
|
380
|
+
previous_value = query.get_previous_property_value()
|
|
342
381
|
|
|
343
|
-
if not
|
|
382
|
+
if not previous_value:
|
|
344
383
|
return None
|
|
345
384
|
|
|
346
|
-
|
|
385
|
+
return AttributeChangelog(
|
|
347
386
|
name=self.name,
|
|
348
387
|
value=None,
|
|
349
|
-
value_previous=
|
|
388
|
+
value_previous=previous_value,
|
|
350
389
|
kind=self.schema.kind,
|
|
351
390
|
)
|
|
352
391
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
# Check all the relationship and update the one that are in the same branch
|
|
357
|
-
rel_ids_to_update = set()
|
|
358
|
-
for result in results:
|
|
359
|
-
if result.get_rel("r2").type == "HAS_VALUE":
|
|
360
|
-
changelog.value_previous = result.get_node("ap").get("value")
|
|
361
|
-
properties_to_delete.append((result.get_rel("r2").type, result.get_node("ap").element_id))
|
|
362
|
-
|
|
363
|
-
await add_relationship(
|
|
364
|
-
src_node_id=self.db_id,
|
|
365
|
-
dst_node_id=result.get_node("ap").element_id,
|
|
366
|
-
rel_type=result.get_rel("r2").type,
|
|
367
|
-
branch_name=branch.name,
|
|
368
|
-
branch_level=branch.hierarchy_level,
|
|
369
|
-
at=delete_at,
|
|
370
|
-
status=RelationshipStatus.DELETED,
|
|
371
|
-
db=db,
|
|
372
|
-
)
|
|
373
|
-
|
|
374
|
-
for rel in result.get_rels():
|
|
375
|
-
if rel.get("branch") == branch.name:
|
|
376
|
-
rel_ids_to_update.add(rel.element_id)
|
|
377
|
-
|
|
378
|
-
if rel_ids_to_update:
|
|
379
|
-
await update_relationships_to(ids=list(rel_ids_to_update), to=delete_at, db=db)
|
|
380
|
-
|
|
381
|
-
await add_relationship(
|
|
382
|
-
src_node_id=self.node.db_id,
|
|
383
|
-
dst_node_id=self.db_id,
|
|
384
|
-
rel_type="HAS_ATTRIBUTE",
|
|
385
|
-
branch_name=branch.name,
|
|
386
|
-
branch_level=branch.hierarchy_level,
|
|
387
|
-
at=delete_at,
|
|
388
|
-
status=RelationshipStatus.DELETED,
|
|
389
|
-
db=db,
|
|
390
|
-
)
|
|
391
|
-
|
|
392
|
-
return changelog
|
|
393
|
-
|
|
394
|
-
async def _update(self, db: InfrahubDatabase, at: Timestamp | None = None) -> AttributeChangelog | None:
|
|
392
|
+
async def _update(
|
|
393
|
+
self, db: InfrahubDatabase, user_id: str, at: Timestamp | None = None
|
|
394
|
+
) -> AttributeChangelog | None:
|
|
395
395
|
"""Update the attribute in the database.
|
|
396
396
|
|
|
397
397
|
Get the current value
|
|
@@ -422,13 +422,10 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
422
422
|
fields={self.name: True},
|
|
423
423
|
branch=self.branch,
|
|
424
424
|
at=update_at,
|
|
425
|
-
|
|
426
|
-
include_owner=True,
|
|
425
|
+
include_metadata=MetadataOptions.LINKED_NODES,
|
|
427
426
|
)
|
|
428
427
|
await query.execute(db=db)
|
|
429
|
-
current_attr_data,
|
|
430
|
-
|
|
431
|
-
branch = self.get_branch_based_on_support_type()
|
|
428
|
+
current_attr_data, _ = query.get_result_by_id_and_name(self.node.id, self.name)
|
|
432
429
|
|
|
433
430
|
changelog = AttributeChangelog(
|
|
434
431
|
name=self.name,
|
|
@@ -437,36 +434,26 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
437
434
|
kind=self.schema.kind,
|
|
438
435
|
)
|
|
439
436
|
|
|
437
|
+
branch = self.get_branch_based_on_support_type()
|
|
438
|
+
|
|
440
439
|
# ---------- Update the Value ----------
|
|
441
440
|
if current_attr_data.content != self.to_db():
|
|
442
441
|
# Create the new AttributeValue and update the existing relationship
|
|
443
|
-
query = await AttributeUpdateValueQuery.init(db=db, attr=self, at=update_at)
|
|
442
|
+
query = await AttributeUpdateValueQuery.init(db=db, branch=branch, attr=self, user_id=user_id, at=update_at)
|
|
444
443
|
await query.execute(db=db)
|
|
445
444
|
|
|
446
|
-
# TODO check that everything went well
|
|
447
|
-
rel = current_attr_result.get_rel("r2")
|
|
448
|
-
if rel.get("branch") == branch.name:
|
|
449
|
-
await update_relationships_to([rel.element_id], to=update_at, db=db)
|
|
450
|
-
|
|
451
445
|
# ---------- Update the Flags ----------
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
(
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
)
|
|
464
|
-
query = await AttributeUpdateFlagQuery.init(db=db, attr=self, at=update_at, flag_name=flag_name)
|
|
465
|
-
await query.execute(db=db)
|
|
466
|
-
|
|
467
|
-
rel = current_attr_result.get(rel_name)
|
|
468
|
-
if rel.get("branch") == branch.name:
|
|
469
|
-
await update_relationships_to([rel.element_id], to=update_at, db=db)
|
|
446
|
+
flag_name = "is_protected"
|
|
447
|
+
if current_attr_data.flag_properties[flag_name] != getattr(self, flag_name):
|
|
448
|
+
changelog.add_property(
|
|
449
|
+
name=flag_name,
|
|
450
|
+
value_current=getattr(self, flag_name),
|
|
451
|
+
value_previous=current_attr_data.flag_properties[flag_name],
|
|
452
|
+
)
|
|
453
|
+
query = await AttributeUpdateFlagQuery.init(
|
|
454
|
+
db=db, branch=branch, attr=self, user_id=user_id, at=update_at, flag_name=flag_name
|
|
455
|
+
)
|
|
456
|
+
await query.execute(db=db)
|
|
470
457
|
|
|
471
458
|
# ---------- Update the Node Properties ----------
|
|
472
459
|
for prop_name in self._node_properties:
|
|
@@ -488,21 +475,27 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
488
475
|
|
|
489
476
|
if needs_update:
|
|
490
477
|
query = await AttributeUpdateNodePropertyQuery.init(
|
|
491
|
-
db=db,
|
|
478
|
+
db=db,
|
|
479
|
+
branch=branch,
|
|
480
|
+
attr=self,
|
|
481
|
+
user_id=user_id,
|
|
482
|
+
at=update_at,
|
|
483
|
+
prop_name=prop_name,
|
|
484
|
+
prop_id=current_prop_id,
|
|
492
485
|
)
|
|
493
486
|
await query.execute(db=db)
|
|
494
487
|
|
|
495
488
|
if needs_clear:
|
|
496
489
|
query = await AttributeClearNodePropertyQuery.init(
|
|
497
|
-
db=db,
|
|
490
|
+
db=db,
|
|
491
|
+
branch=branch,
|
|
492
|
+
attr=self,
|
|
493
|
+
user_id=user_id,
|
|
494
|
+
at=update_at,
|
|
495
|
+
prop_name=prop_name,
|
|
498
496
|
)
|
|
499
497
|
await query.execute(db=db)
|
|
500
498
|
|
|
501
|
-
# set the to time on the previously active edge
|
|
502
|
-
rel = current_attr_result.get(f"rel_{prop_name}")
|
|
503
|
-
if rel and rel.get("branch") == branch.name:
|
|
504
|
-
await update_relationships_to([rel.element_id], to=update_at, db=db)
|
|
505
|
-
|
|
506
499
|
if changelog.has_updates:
|
|
507
500
|
return changelog
|
|
508
501
|
|
|
@@ -531,10 +524,19 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
531
524
|
|
|
532
525
|
for field_name in field_names:
|
|
533
526
|
if field_name == "updated_at":
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
527
|
+
updated_at = self._get_updated_at()
|
|
528
|
+
response[field_name] = await updated_at.to_graphql() if updated_at else None
|
|
529
|
+
continue
|
|
530
|
+
|
|
531
|
+
if field_name == "updated_by":
|
|
532
|
+
response[field_name] = (
|
|
533
|
+
{
|
|
534
|
+
"id": self._get_updated_by(),
|
|
535
|
+
"__kind__": InfrahubKind.ACCOUNT,
|
|
536
|
+
}
|
|
537
|
+
if self._get_updated_by()
|
|
538
|
+
else None
|
|
539
|
+
)
|
|
538
540
|
continue
|
|
539
541
|
|
|
540
542
|
if field_name == "__typename":
|
|
@@ -620,9 +622,6 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
620
622
|
if "is_protected" in data and data["is_protected"] != self.is_protected:
|
|
621
623
|
self.is_protected = data["is_protected"]
|
|
622
624
|
changed = True
|
|
623
|
-
if "is_visible" in data and data["is_visible"] != self.is_visible:
|
|
624
|
-
self.is_visible = data["is_visible"]
|
|
625
|
-
changed = True
|
|
626
625
|
|
|
627
626
|
if "source" in data and data["source"] != self.source_id:
|
|
628
627
|
self.source = data["source"]
|
|
@@ -657,7 +656,6 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
657
656
|
content=self.to_db(),
|
|
658
657
|
is_default=self.is_default,
|
|
659
658
|
is_protected=self.is_protected,
|
|
660
|
-
is_visible=self.is_visible,
|
|
661
659
|
)
|
|
662
660
|
if self.source_id:
|
|
663
661
|
data.source_prop.append(NodePropertyData(name="source", peer_id=self.source_id))
|
infrahub/core/branch/models.py
CHANGED
|
@@ -6,17 +6,15 @@ from typing import TYPE_CHECKING, Any, Optional, Self, Union, cast
|
|
|
6
6
|
from pydantic import Field, field_validator
|
|
7
7
|
|
|
8
8
|
from infrahub.core.branch.enums import BranchStatus
|
|
9
|
-
from infrahub.core.constants import GLOBAL_BRANCH_NAME
|
|
9
|
+
from infrahub.core.constants import GLOBAL_BRANCH_NAME, SYSTEM_USER_ID
|
|
10
10
|
from infrahub.core.graph import GRAPH_VERSION
|
|
11
11
|
from infrahub.core.models import SchemaBranchHash # noqa: TC001
|
|
12
|
-
from infrahub.core.node.standard import StandardNode
|
|
12
|
+
from infrahub.core.node.standard import StandardNode, StandardNodeOrdering
|
|
13
13
|
from infrahub.core.query import Query, QueryType
|
|
14
14
|
from infrahub.core.query.branch import (
|
|
15
15
|
BranchNodeGetListQuery,
|
|
16
16
|
DeleteBranchRelationshipsQuery,
|
|
17
|
-
|
|
18
|
-
RebaseBranchDeleteRelationshipQuery,
|
|
19
|
-
RebaseBranchUpdateRelationshipQuery,
|
|
17
|
+
RebaseBranchQuery,
|
|
20
18
|
)
|
|
21
19
|
from infrahub.core.registry import registry
|
|
22
20
|
from infrahub.core.timestamp import Timestamp
|
|
@@ -37,7 +35,6 @@ class Branch(StandardNode):
|
|
|
37
35
|
origin_branch: str = "main"
|
|
38
36
|
branched_from: Optional[str] = Field(default=None, validate_default=True)
|
|
39
37
|
hierarchy_level: int = 2
|
|
40
|
-
created_at: Optional[str] = Field(default=None, validate_default=True)
|
|
41
38
|
is_default: bool = False
|
|
42
39
|
is_global: bool = False
|
|
43
40
|
is_protected: bool = False
|
|
@@ -93,11 +90,6 @@ class Branch(StandardNode):
|
|
|
93
90
|
raise RuntimeError(f"branched_from not set for branch {self.name}")
|
|
94
91
|
return self.branched_from
|
|
95
92
|
|
|
96
|
-
@field_validator("created_at", mode="before")
|
|
97
|
-
@classmethod
|
|
98
|
-
def set_created_at(cls, value: str) -> str:
|
|
99
|
-
return Timestamp(value).to_string()
|
|
100
|
-
|
|
101
93
|
def get_created_at(self) -> str:
|
|
102
94
|
if not self.created_at:
|
|
103
95
|
raise RuntimeError(f"created_at not set for branch {self.name}")
|
|
@@ -162,10 +154,18 @@ class Branch(StandardNode):
|
|
|
162
154
|
limit: int = 1000,
|
|
163
155
|
ids: list[str] | None = None,
|
|
164
156
|
name: str | None = None,
|
|
157
|
+
node_ordering: StandardNodeOrdering | None = None,
|
|
165
158
|
**kwargs: Any,
|
|
166
159
|
) -> list[Self]:
|
|
160
|
+
node_ordering = node_ordering or StandardNodeOrdering()
|
|
167
161
|
query: Query = await BranchNodeGetListQuery.init(
|
|
168
|
-
db=db,
|
|
162
|
+
db=db,
|
|
163
|
+
node_class=cls,
|
|
164
|
+
ids=ids,
|
|
165
|
+
node_name=name,
|
|
166
|
+
limit=limit,
|
|
167
|
+
node_ordering=node_ordering,
|
|
168
|
+
**kwargs,
|
|
169
169
|
)
|
|
170
170
|
await query.execute(db=db)
|
|
171
171
|
|
|
@@ -178,10 +178,18 @@ class Branch(StandardNode):
|
|
|
178
178
|
limit: int = 1000,
|
|
179
179
|
ids: list[str] | None = None,
|
|
180
180
|
name: str | None = None,
|
|
181
|
+
partial_match: bool = False,
|
|
181
182
|
**kwargs: Any,
|
|
182
183
|
) -> int:
|
|
183
184
|
query: Query = await BranchNodeGetListQuery.init(
|
|
184
|
-
db=db,
|
|
185
|
+
db=db,
|
|
186
|
+
node_class=cls,
|
|
187
|
+
ids=ids,
|
|
188
|
+
node_name=name,
|
|
189
|
+
limit=limit,
|
|
190
|
+
exclude_global=True,
|
|
191
|
+
partial_match=partial_match,
|
|
192
|
+
**kwargs,
|
|
185
193
|
)
|
|
186
194
|
return await query.count(db=db)
|
|
187
195
|
|
|
@@ -208,7 +216,7 @@ class Branch(StandardNode):
|
|
|
208
216
|
|
|
209
217
|
return [default_branch, self.name]
|
|
210
218
|
|
|
211
|
-
def get_branches_and_times_to_query(self, at: Optional[
|
|
219
|
+
def get_branches_and_times_to_query(self, at: Optional[Timestamp] = None) -> dict[frozenset, str]:
|
|
212
220
|
"""Return all the names of the branches that are constituing this branch with the associated times excluding the global branch"""
|
|
213
221
|
|
|
214
222
|
at = Timestamp(at)
|
|
@@ -229,7 +237,7 @@ class Branch(StandardNode):
|
|
|
229
237
|
|
|
230
238
|
def get_branches_and_times_to_query_global(
|
|
231
239
|
self,
|
|
232
|
-
at: Optional[
|
|
240
|
+
at: Optional[Timestamp] = None,
|
|
233
241
|
is_isolated: bool = True,
|
|
234
242
|
) -> dict[frozenset, str]:
|
|
235
243
|
"""Return all the names of the branches that are constituting this branch with the associated times."""
|
|
@@ -281,9 +289,9 @@ class Branch(StandardNode):
|
|
|
281
289
|
|
|
282
290
|
return start, end
|
|
283
291
|
|
|
284
|
-
async def create(self, db: InfrahubDatabase) -> bool:
|
|
292
|
+
async def create(self, db: InfrahubDatabase, user_id: str = SYSTEM_USER_ID) -> bool:
|
|
285
293
|
self.graph_version = GRAPH_VERSION
|
|
286
|
-
return await super().create(db=db)
|
|
294
|
+
return await super().create(db=db, user_id=user_id)
|
|
287
295
|
|
|
288
296
|
async def delete(self, db: InfrahubDatabase) -> None:
|
|
289
297
|
if self.is_default:
|
|
@@ -299,7 +307,7 @@ class Branch(StandardNode):
|
|
|
299
307
|
await super().delete(db=db)
|
|
300
308
|
|
|
301
309
|
def get_query_filter_relationships(
|
|
302
|
-
self, rel_labels: list, at: Optional[
|
|
310
|
+
self, rel_labels: list, at: Optional[Timestamp] = None, include_outside_parentheses: bool = False
|
|
303
311
|
) -> tuple[list, dict]:
|
|
304
312
|
"""
|
|
305
313
|
Generate a CYPHER Query filter based on a list of relationships to query a part of the graph at a specific time and on a specific branch.
|
|
@@ -362,7 +370,7 @@ class Branch(StandardNode):
|
|
|
362
370
|
params[f"{pp}time1"] = at_str
|
|
363
371
|
return filter_str, params
|
|
364
372
|
|
|
365
|
-
branches_times = self.get_branches_and_times_to_query_global(at=
|
|
373
|
+
branches_times = self.get_branches_and_times_to_query_global(at=at, is_isolated=is_isolated)
|
|
366
374
|
|
|
367
375
|
for idx, (branch_name, time_to_query) in enumerate(branches_times.items()):
|
|
368
376
|
params[f"{pp}branch{idx}"] = list(branch_name)
|
|
@@ -387,8 +395,8 @@ class Branch(StandardNode):
|
|
|
387
395
|
def get_query_filter_relationships_range(
|
|
388
396
|
self,
|
|
389
397
|
rel_labels: list,
|
|
390
|
-
start_time:
|
|
391
|
-
end_time:
|
|
398
|
+
start_time: Timestamp,
|
|
399
|
+
end_time: Timestamp,
|
|
392
400
|
include_outside_parentheses: bool = False,
|
|
393
401
|
include_global: bool = False,
|
|
394
402
|
) -> tuple[list, dict]:
|
|
@@ -468,9 +476,7 @@ class Branch(StandardNode):
|
|
|
468
476
|
|
|
469
477
|
return filters, params
|
|
470
478
|
|
|
471
|
-
def get_query_filter_range(
|
|
472
|
-
self, rel_label: list, start_time: Union[Timestamp, str], end_time: Union[Timestamp, str]
|
|
473
|
-
) -> tuple[list, dict]:
|
|
479
|
+
def get_query_filter_range(self, rel_label: list, start_time: Timestamp, end_time: Timestamp) -> tuple[list, dict]:
|
|
474
480
|
"""
|
|
475
481
|
Generate a CYPHER Query filter to query a range of values in the graph between start_time and end_time."""
|
|
476
482
|
|
|
@@ -496,67 +502,34 @@ class Branch(StandardNode):
|
|
|
496
502
|
|
|
497
503
|
return filters, params
|
|
498
504
|
|
|
499
|
-
async def rebase(self, db: InfrahubDatabase,
|
|
505
|
+
async def rebase(self, db: InfrahubDatabase, user_id: str = SYSTEM_USER_ID) -> None:
|
|
500
506
|
"""Rebase the current Branch with its origin branch"""
|
|
501
507
|
|
|
502
|
-
at = Timestamp(
|
|
503
|
-
|
|
504
|
-
# Find all relationships with the name of the branch
|
|
505
|
-
# Delete all relationship that have a to date defined in the past
|
|
506
|
-
# Update the from time on all other relationships
|
|
507
|
-
# If conflict is set, ignore the one with Drop
|
|
508
|
+
at = Timestamp()
|
|
508
509
|
|
|
509
510
|
await self.rebase_graph(db=db, at=at)
|
|
510
511
|
|
|
511
|
-
# FIXME, we must ensure that there is no conflict before rebasing a branch
|
|
512
|
-
# Otherwise we could endup with a complicated situation
|
|
513
512
|
self.branched_from = at.to_string()
|
|
514
513
|
self.status = BranchStatus.OPEN
|
|
515
|
-
await self.save(db=db)
|
|
514
|
+
await self.save(db=db, user_id=user_id)
|
|
516
515
|
|
|
517
516
|
# Update the branch in the registry after the rebase
|
|
518
517
|
registry.branch[self.name] = self
|
|
519
518
|
|
|
520
|
-
async def rebase_graph(self, db: InfrahubDatabase, at:
|
|
521
|
-
|
|
519
|
+
async def rebase_graph(self, db: InfrahubDatabase, at: Timestamp) -> None:
|
|
520
|
+
"""Rebase all relationships on this branch to a new point in time.
|
|
522
521
|
|
|
523
|
-
|
|
524
|
-
|
|
522
|
+
This method updates the graph to reflect the state of the branch as if it had been created
|
|
523
|
+
at the specified timestamp. Relationships are processed as follows:
|
|
525
524
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
element_id = result.get("r").element_id
|
|
525
|
+
- Relationships with no `to` timestamp and `from` <= at: Updated to start from `at`
|
|
526
|
+
- Relationships with `to` < at: Deleted (ended before rebase point)
|
|
527
|
+
- Relationships with `to` >= at: Updated to start from `at`
|
|
530
528
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
time_to_str = result.get("r").get("to", None)
|
|
537
|
-
time_from_str = result.get("r").get("from")
|
|
538
|
-
time_from = Timestamp(time_from_str)
|
|
539
|
-
|
|
540
|
-
if not time_to_str and time_from_str and time_from <= at:
|
|
541
|
-
rels_to_update.append(element_id)
|
|
542
|
-
continue
|
|
543
|
-
|
|
544
|
-
if not time_to_str and time_from_str and time_from > at:
|
|
545
|
-
rels_to_delete.append(element_id)
|
|
546
|
-
continue
|
|
547
|
-
|
|
548
|
-
time_to = Timestamp(time_to_str)
|
|
549
|
-
if time_to < at:
|
|
550
|
-
rels_to_delete.append(element_id)
|
|
551
|
-
continue
|
|
552
|
-
|
|
553
|
-
rels_to_update.append(element_id)
|
|
554
|
-
|
|
555
|
-
update_query = await RebaseBranchUpdateRelationshipQuery.init(db=db, ids=rels_to_update, at=at)
|
|
556
|
-
await update_query.execute(db=db)
|
|
557
|
-
|
|
558
|
-
delete_query = await RebaseBranchDeleteRelationshipQuery.init(db=db, ids=rels_to_delete, at=at)
|
|
559
|
-
await delete_query.execute(db=db)
|
|
529
|
+
Orphaned nodes (nodes with no remaining relationships) are also cleaned up.
|
|
530
|
+
"""
|
|
531
|
+
query = await RebaseBranchQuery.init(db=db, branch=self, at=at)
|
|
532
|
+
await query.execute(db=db)
|
|
560
533
|
|
|
561
534
|
|
|
562
535
|
registry.branch_object = Branch
|
infrahub/core/branch/tasks.py
CHANGED
|
@@ -170,7 +170,7 @@ async def rebase_branch(branch: str, context: InfrahubContext, send_events: bool
|
|
|
170
170
|
migrations = []
|
|
171
171
|
async with lock.registry.global_graph_lock():
|
|
172
172
|
async with db.start_transaction() as dbt:
|
|
173
|
-
await obj.rebase(db=dbt)
|
|
173
|
+
await obj.rebase(db=dbt, user_id=context.account.account_id)
|
|
174
174
|
log.info("Branch successfully rebased")
|
|
175
175
|
|
|
176
176
|
if obj.has_schema_changes:
|
|
@@ -187,7 +187,7 @@ async def rebase_branch(branch: str, context: InfrahubContext, send_events: bool
|
|
|
187
187
|
)
|
|
188
188
|
registry.schema.set_schema_branch(name=obj.name, schema=updated_schema)
|
|
189
189
|
obj.update_schema_hash()
|
|
190
|
-
await obj.save(db=db)
|
|
190
|
+
await obj.save(db=db, user_id=context.account.account_id)
|
|
191
191
|
|
|
192
192
|
# Execute the migrations
|
|
193
193
|
migrations = await merger.calculate_migrations(target_schema=updated_schema)
|
|
@@ -198,6 +198,7 @@ async def rebase_branch(branch: str, context: InfrahubContext, send_events: bool
|
|
|
198
198
|
new_schema=candidate_schema,
|
|
199
199
|
previous_schema=schema_in_main_before,
|
|
200
200
|
migrations=migrations,
|
|
201
|
+
user_id=context.account.account_id,
|
|
201
202
|
)
|
|
202
203
|
)
|
|
203
204
|
for error in errors:
|
|
@@ -302,6 +303,7 @@ async def merge_branch(branch: str, context: InfrahubContext, proposed_change_id
|
|
|
302
303
|
new_schema=merger.destination_schema,
|
|
303
304
|
previous_schema=merger.initial_source_schema,
|
|
304
305
|
migrations=merger.migrations,
|
|
306
|
+
user_id=context.account.account_id,
|
|
305
307
|
)
|
|
306
308
|
)
|
|
307
309
|
for error in errors:
|
|
@@ -431,7 +433,7 @@ async def create_branch(model: BranchCreateModel, context: InfrahubContext) -> N
|
|
|
431
433
|
new_schema = origin_schema.duplicate(name=obj.name)
|
|
432
434
|
registry.schema.set_schema_branch(name=obj.name, schema=new_schema)
|
|
433
435
|
obj.update_schema_hash()
|
|
434
|
-
await obj.save(db=db)
|
|
436
|
+
await obj.save(db=db, user_id=context.account.account_id)
|
|
435
437
|
|
|
436
438
|
# Add Branch to registry
|
|
437
439
|
registry.branch[obj.name] = obj
|