infrahub-server 1.2.11__py3-none-any.whl → 1.3.0b1__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/constants.py +86 -0
- infrahub/actions/gather.py +114 -0
- infrahub/actions/models.py +241 -0
- infrahub/actions/parsers.py +104 -0
- infrahub/actions/schema.py +382 -0
- infrahub/actions/tasks.py +126 -0
- infrahub/actions/triggers.py +21 -0
- infrahub/cli/db.py +1 -2
- infrahub/core/account.py +24 -47
- infrahub/core/attribute.py +13 -15
- infrahub/core/constants/__init__.py +5 -0
- infrahub/core/constants/infrahubkind.py +9 -0
- infrahub/core/convert_object_type/__init__.py +0 -0
- infrahub/core/convert_object_type/conversion.py +122 -0
- infrahub/core/convert_object_type/schema_mapping.py +56 -0
- infrahub/core/diff/query/all_conflicts.py +1 -5
- infrahub/core/diff/query/artifact.py +10 -20
- infrahub/core/diff/query/diff_get.py +3 -6
- infrahub/core/diff/query/field_summary.py +2 -4
- infrahub/core/diff/query/merge.py +70 -123
- infrahub/core/diff/query/save.py +20 -32
- infrahub/core/diff/query/summary_counts_enricher.py +34 -54
- infrahub/core/manager.py +14 -11
- infrahub/core/migrations/graph/m003_relationship_parent_optional.py +1 -2
- infrahub/core/migrations/graph/m013_convert_git_password_credential.py +2 -4
- infrahub/core/migrations/graph/m019_restore_rels_to_time.py +11 -22
- infrahub/core/migrations/graph/m020_duplicate_edges.py +3 -6
- infrahub/core/migrations/graph/m021_missing_hierarchy_merge.py +1 -2
- infrahub/core/migrations/graph/m024_missing_hierarchy_backfill.py +1 -2
- infrahub/core/migrations/query/attribute_add.py +1 -2
- infrahub/core/migrations/query/attribute_rename.py +5 -10
- infrahub/core/migrations/query/delete_element_in_schema.py +19 -17
- infrahub/core/migrations/query/node_duplicate.py +19 -21
- infrahub/core/migrations/query/relationship_duplicate.py +19 -17
- infrahub/core/migrations/schema/node_attribute_remove.py +4 -8
- infrahub/core/migrations/schema/node_remove.py +19 -19
- infrahub/core/models.py +29 -2
- infrahub/core/node/__init__.py +90 -18
- infrahub/core/node/create.py +211 -0
- infrahub/core/node/resource_manager/number_pool.py +31 -5
- infrahub/core/node/standard.py +6 -1
- infrahub/core/protocols.py +56 -0
- infrahub/core/protocols_base.py +3 -0
- infrahub/core/query/__init__.py +2 -2
- infrahub/core/query/diff.py +19 -32
- infrahub/core/query/ipam.py +10 -20
- infrahub/core/query/node.py +28 -46
- infrahub/core/query/relationship.py +53 -32
- infrahub/core/query/resource_manager.py +1 -2
- infrahub/core/query/subquery.py +2 -4
- infrahub/core/relationship/model.py +3 -0
- infrahub/core/schema/__init__.py +2 -1
- infrahub/core/schema/attribute_parameters.py +160 -0
- infrahub/core/schema/attribute_schema.py +111 -8
- infrahub/core/schema/basenode_schema.py +25 -1
- infrahub/core/schema/definitions/core/__init__.py +29 -1
- infrahub/core/schema/definitions/core/group.py +45 -0
- infrahub/core/schema/definitions/internal.py +27 -4
- infrahub/core/schema/generated/attribute_schema.py +16 -3
- infrahub/core/schema/manager.py +3 -0
- infrahub/core/schema/schema_branch.py +67 -7
- infrahub/core/validators/__init__.py +13 -1
- infrahub/core/validators/attribute/choices.py +1 -3
- infrahub/core/validators/attribute/enum.py +1 -3
- infrahub/core/validators/attribute/kind.py +1 -3
- infrahub/core/validators/attribute/length.py +13 -7
- infrahub/core/validators/attribute/min_max.py +118 -0
- infrahub/core/validators/attribute/number_pool.py +106 -0
- infrahub/core/validators/attribute/optional.py +1 -4
- infrahub/core/validators/attribute/regex.py +5 -6
- infrahub/core/validators/attribute/unique.py +1 -3
- infrahub/core/validators/determiner.py +18 -2
- infrahub/core/validators/enum.py +12 -0
- infrahub/core/validators/node/hierarchy.py +3 -6
- infrahub/core/validators/query.py +1 -3
- infrahub/core/validators/relationship/count.py +6 -12
- infrahub/core/validators/relationship/optional.py +2 -4
- infrahub/core/validators/relationship/peer.py +3 -8
- infrahub/core/validators/uniqueness/query.py +5 -9
- infrahub/database/__init__.py +11 -2
- infrahub/events/group_action.py +1 -0
- infrahub/git/base.py +5 -3
- infrahub/git/integrator.py +102 -3
- infrahub/graphql/analyzer.py +139 -18
- infrahub/graphql/manager.py +4 -0
- infrahub/graphql/mutations/action.py +164 -0
- infrahub/graphql/mutations/convert_object_type.py +62 -0
- infrahub/graphql/mutations/main.py +24 -175
- infrahub/graphql/mutations/proposed_change.py +20 -17
- infrahub/graphql/mutations/resource_manager.py +62 -6
- infrahub/graphql/queries/convert_object_type_mapping.py +36 -0
- infrahub/graphql/queries/resource_manager.py +7 -1
- infrahub/graphql/schema.py +6 -0
- infrahub/menu/menu.py +31 -0
- infrahub/message_bus/messages/__init__.py +0 -10
- infrahub/message_bus/operations/__init__.py +0 -8
- infrahub/patch/queries/consolidate_duplicated_nodes.py +3 -6
- infrahub/patch/queries/delete_duplicated_edges.py +5 -10
- infrahub/pools/number.py +5 -3
- infrahub/prefect_server/models.py +1 -19
- infrahub/proposed_change/models.py +68 -3
- infrahub/proposed_change/tasks.py +907 -30
- infrahub/task_manager/models.py +10 -6
- infrahub/trigger/catalogue.py +2 -0
- infrahub/trigger/models.py +18 -2
- infrahub/trigger/tasks.py +3 -1
- infrahub/types.py +6 -0
- infrahub/workflows/catalogue.py +76 -0
- infrahub_sdk/client.py +43 -10
- infrahub_sdk/node/__init__.py +39 -0
- infrahub_sdk/node/attribute.py +122 -0
- infrahub_sdk/node/constants.py +21 -0
- infrahub_sdk/{node.py → node/node.py} +50 -749
- infrahub_sdk/node/parsers.py +15 -0
- infrahub_sdk/node/property.py +24 -0
- infrahub_sdk/node/related_node.py +266 -0
- infrahub_sdk/node/relationship.py +302 -0
- infrahub_sdk/protocols.py +112 -0
- infrahub_sdk/protocols_base.py +34 -2
- infrahub_sdk/query_groups.py +13 -2
- infrahub_sdk/schema/main.py +1 -0
- infrahub_sdk/schema/repository.py +16 -0
- infrahub_sdk/spec/object.py +1 -1
- infrahub_sdk/store.py +1 -1
- infrahub_sdk/testing/schemas/car_person.py +1 -0
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/METADATA +4 -4
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/RECORD +134 -122
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/WHEEL +1 -1
- infrahub_testcontainers/container.py +0 -1
- infrahub_testcontainers/docker-compose.test.yml +1 -1
- infrahub_testcontainers/helpers.py +8 -2
- infrahub/message_bus/messages/check_generator_run.py +0 -26
- infrahub/message_bus/messages/finalize_validator_execution.py +0 -15
- infrahub/message_bus/messages/proposed_change/base_with_diff.py +0 -16
- infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +0 -11
- infrahub/message_bus/messages/request_generatordefinition_check.py +0 -20
- infrahub/message_bus/messages/request_proposedchange_pipeline.py +0 -23
- infrahub/message_bus/operations/check/__init__.py +0 -3
- infrahub/message_bus/operations/check/generator.py +0 -156
- infrahub/message_bus/operations/finalize/__init__.py +0 -3
- infrahub/message_bus/operations/finalize/validator.py +0 -133
- infrahub/message_bus/operations/requests/__init__.py +0 -9
- infrahub/message_bus/operations/requests/generator_definition.py +0 -140
- infrahub/message_bus/operations/requests/proposed_change.py +0 -629
- /infrahub/{message_bus/messages/proposed_change → actions}/__init__.py +0 -0
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/entry_points.txt +0 -0
|
@@ -1,629 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from enum import IntFlag
|
|
4
|
-
from typing import TYPE_CHECKING
|
|
5
|
-
|
|
6
|
-
from prefect import flow, task
|
|
7
|
-
from prefect.logging import get_run_logger
|
|
8
|
-
from pydantic import BaseModel
|
|
9
|
-
|
|
10
|
-
from infrahub import lock
|
|
11
|
-
from infrahub.core.constants import CheckType, InfrahubKind, RepositoryInternalStatus
|
|
12
|
-
from infrahub.core.diff.coordinator import DiffCoordinator
|
|
13
|
-
from infrahub.core.registry import registry
|
|
14
|
-
from infrahub.dependencies.registry import get_component_registry
|
|
15
|
-
from infrahub.git.models import TriggerRepositoryInternalChecks
|
|
16
|
-
from infrahub.git.repository import InfrahubRepository
|
|
17
|
-
from infrahub.message_bus import InfrahubMessage, messages
|
|
18
|
-
from infrahub.message_bus.types import (
|
|
19
|
-
ProposedChangeArtifactDefinition,
|
|
20
|
-
ProposedChangeBranchDiff,
|
|
21
|
-
ProposedChangeRepository,
|
|
22
|
-
ProposedChangeSubscriber,
|
|
23
|
-
)
|
|
24
|
-
from infrahub.proposed_change.branch_diff import (
|
|
25
|
-
get_diff_summary_cache,
|
|
26
|
-
get_modified_kinds,
|
|
27
|
-
get_modified_node_ids,
|
|
28
|
-
has_data_changes,
|
|
29
|
-
has_node_changes,
|
|
30
|
-
set_diff_summary_cache,
|
|
31
|
-
)
|
|
32
|
-
from infrahub.proposed_change.models import (
|
|
33
|
-
RequestArtifactDefinitionCheck,
|
|
34
|
-
RequestProposedChangeDataIntegrity,
|
|
35
|
-
RequestProposedChangeRepositoryChecks,
|
|
36
|
-
RequestProposedChangeRunGenerators,
|
|
37
|
-
RequestProposedChangeSchemaIntegrity,
|
|
38
|
-
RequestProposedChangeUserTests,
|
|
39
|
-
)
|
|
40
|
-
from infrahub.services import InfrahubServices # noqa: TC001
|
|
41
|
-
from infrahub.workflows.catalogue import (
|
|
42
|
-
GIT_REPOSITORY_INTERNAL_CHECKS_TRIGGER,
|
|
43
|
-
REQUEST_ARTIFACT_DEFINITION_CHECK,
|
|
44
|
-
REQUEST_PROPOSED_CHANGE_DATA_INTEGRITY,
|
|
45
|
-
REQUEST_PROPOSED_CHANGE_REPOSITORY_CHECKS,
|
|
46
|
-
REQUEST_PROPOSED_CHANGE_RUN_GENERATORS,
|
|
47
|
-
REQUEST_PROPOSED_CHANGE_SCHEMA_INTEGRITY,
|
|
48
|
-
REQUEST_PROPOSED_CHANGE_USER_TESTS,
|
|
49
|
-
)
|
|
50
|
-
from infrahub.workflows.utils import add_tags
|
|
51
|
-
|
|
52
|
-
if TYPE_CHECKING:
|
|
53
|
-
from infrahub_sdk.diff import NodeDiff
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
class DefinitionSelect(IntFlag):
|
|
57
|
-
NONE = 0
|
|
58
|
-
MODIFIED_KINDS = 1
|
|
59
|
-
FILE_CHANGES = 2
|
|
60
|
-
|
|
61
|
-
@staticmethod
|
|
62
|
-
def add_flag(current: DefinitionSelect, flag: DefinitionSelect, condition: bool) -> DefinitionSelect:
|
|
63
|
-
if condition:
|
|
64
|
-
return current | flag
|
|
65
|
-
return current
|
|
66
|
-
|
|
67
|
-
@property
|
|
68
|
-
def log_line(self) -> str:
|
|
69
|
-
change_types = []
|
|
70
|
-
if DefinitionSelect.MODIFIED_KINDS in self:
|
|
71
|
-
change_types.append("data changes within relevant object kinds")
|
|
72
|
-
|
|
73
|
-
if DefinitionSelect.FILE_CHANGES in self:
|
|
74
|
-
change_types.append("file modifications in Git repositories")
|
|
75
|
-
|
|
76
|
-
if self:
|
|
77
|
-
return f"Requesting generation due to {' and '.join(change_types)}"
|
|
78
|
-
|
|
79
|
-
return "Doesn't require changes due to no relevant modified kinds or file changes in Git"
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
@flow(name="proposed-changed-pipeline", flow_run_name="Execute Pipeline")
|
|
83
|
-
async def pipeline(message: messages.RequestProposedChangePipeline, service: InfrahubServices) -> None:
|
|
84
|
-
events: list[InfrahubMessage] = []
|
|
85
|
-
|
|
86
|
-
repositories = await _get_proposed_change_repositories(message=message, service=service)
|
|
87
|
-
|
|
88
|
-
if message.source_branch_sync_with_git and await _validate_repository_merge_conflicts(
|
|
89
|
-
repositories=repositories, service=service
|
|
90
|
-
):
|
|
91
|
-
for repo in repositories:
|
|
92
|
-
if not repo.read_only and repo.internal_status == RepositoryInternalStatus.ACTIVE.value:
|
|
93
|
-
model = TriggerRepositoryInternalChecks(
|
|
94
|
-
proposed_change=message.proposed_change,
|
|
95
|
-
repository=repo.repository_id,
|
|
96
|
-
source_branch=repo.source_branch,
|
|
97
|
-
target_branch=repo.destination_branch,
|
|
98
|
-
)
|
|
99
|
-
await service.workflow.submit_workflow(
|
|
100
|
-
workflow=GIT_REPOSITORY_INTERNAL_CHECKS_TRIGGER,
|
|
101
|
-
context=message.context,
|
|
102
|
-
parameters={"model": model},
|
|
103
|
-
)
|
|
104
|
-
return
|
|
105
|
-
|
|
106
|
-
await _gather_repository_repository_diffs(repositories=repositories, service=service)
|
|
107
|
-
|
|
108
|
-
async with service.database.start_transaction() as dbt:
|
|
109
|
-
destination_branch = await registry.get_branch(db=dbt, branch=message.destination_branch)
|
|
110
|
-
source_branch = await registry.get_branch(db=dbt, branch=message.source_branch)
|
|
111
|
-
component_registry = get_component_registry()
|
|
112
|
-
diff_coordinator = await component_registry.get_component(DiffCoordinator, db=dbt, branch=source_branch)
|
|
113
|
-
await diff_coordinator.update_branch_diff(base_branch=destination_branch, diff_branch=source_branch)
|
|
114
|
-
|
|
115
|
-
diff_summary = await service.client.get_diff_summary(branch=message.source_branch)
|
|
116
|
-
await set_diff_summary_cache(pipeline_id=message.pipeline_id, diff_summary=diff_summary, cache=service.cache)
|
|
117
|
-
branch_diff = ProposedChangeBranchDiff(repositories=repositories, pipeline_id=message.pipeline_id)
|
|
118
|
-
await _populate_subscribers(
|
|
119
|
-
branch_diff=branch_diff, diff_summary=diff_summary, service=service, branch=message.source_branch
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
if message.check_type is CheckType.ARTIFACT:
|
|
123
|
-
events.append(
|
|
124
|
-
messages.RequestProposedChangeRefreshArtifacts(
|
|
125
|
-
context=message.context,
|
|
126
|
-
proposed_change=message.proposed_change,
|
|
127
|
-
source_branch=message.source_branch,
|
|
128
|
-
source_branch_sync_with_git=message.source_branch_sync_with_git,
|
|
129
|
-
destination_branch=message.destination_branch,
|
|
130
|
-
branch_diff=branch_diff,
|
|
131
|
-
)
|
|
132
|
-
)
|
|
133
|
-
|
|
134
|
-
if message.check_type in [CheckType.ALL, CheckType.GENERATOR]:
|
|
135
|
-
model_proposed_change_run_generator = RequestProposedChangeRunGenerators(
|
|
136
|
-
proposed_change=message.proposed_change,
|
|
137
|
-
source_branch=message.source_branch,
|
|
138
|
-
source_branch_sync_with_git=message.source_branch_sync_with_git,
|
|
139
|
-
destination_branch=message.destination_branch,
|
|
140
|
-
branch_diff=branch_diff,
|
|
141
|
-
refresh_artifacts=message.check_type is CheckType.ALL,
|
|
142
|
-
do_repository_checks=message.check_type is CheckType.ALL,
|
|
143
|
-
)
|
|
144
|
-
await service.workflow.submit_workflow(
|
|
145
|
-
workflow=REQUEST_PROPOSED_CHANGE_RUN_GENERATORS,
|
|
146
|
-
context=message.context,
|
|
147
|
-
parameters={"model": model_proposed_change_run_generator},
|
|
148
|
-
)
|
|
149
|
-
|
|
150
|
-
if message.check_type in [CheckType.ALL, CheckType.DATA] and has_node_changes(
|
|
151
|
-
diff_summary=diff_summary, branch=message.source_branch
|
|
152
|
-
):
|
|
153
|
-
model_proposed_change_data_integrity = RequestProposedChangeDataIntegrity(
|
|
154
|
-
proposed_change=message.proposed_change,
|
|
155
|
-
source_branch=message.source_branch,
|
|
156
|
-
source_branch_sync_with_git=message.source_branch_sync_with_git,
|
|
157
|
-
destination_branch=message.destination_branch,
|
|
158
|
-
branch_diff=branch_diff,
|
|
159
|
-
)
|
|
160
|
-
await service.workflow.submit_workflow(
|
|
161
|
-
workflow=REQUEST_PROPOSED_CHANGE_DATA_INTEGRITY,
|
|
162
|
-
context=message.context,
|
|
163
|
-
parameters={"model": model_proposed_change_data_integrity},
|
|
164
|
-
)
|
|
165
|
-
|
|
166
|
-
if message.check_type in [CheckType.REPOSITORY, CheckType.USER]:
|
|
167
|
-
model_proposed_change_repo_checks = RequestProposedChangeRepositoryChecks(
|
|
168
|
-
proposed_change=message.proposed_change,
|
|
169
|
-
source_branch=message.source_branch,
|
|
170
|
-
source_branch_sync_with_git=message.source_branch_sync_with_git,
|
|
171
|
-
destination_branch=message.destination_branch,
|
|
172
|
-
branch_diff=branch_diff,
|
|
173
|
-
)
|
|
174
|
-
await service.workflow.submit_workflow(
|
|
175
|
-
workflow=REQUEST_PROPOSED_CHANGE_REPOSITORY_CHECKS,
|
|
176
|
-
context=message.context,
|
|
177
|
-
parameters={"model": model_proposed_change_repo_checks},
|
|
178
|
-
)
|
|
179
|
-
|
|
180
|
-
if message.check_type in [CheckType.ALL, CheckType.SCHEMA] and has_data_changes(
|
|
181
|
-
diff_summary=diff_summary, branch=message.source_branch
|
|
182
|
-
):
|
|
183
|
-
await service.workflow.submit_workflow(
|
|
184
|
-
workflow=REQUEST_PROPOSED_CHANGE_SCHEMA_INTEGRITY,
|
|
185
|
-
context=message.context,
|
|
186
|
-
parameters={
|
|
187
|
-
"model": RequestProposedChangeSchemaIntegrity(
|
|
188
|
-
proposed_change=message.proposed_change,
|
|
189
|
-
source_branch=message.source_branch,
|
|
190
|
-
source_branch_sync_with_git=message.source_branch_sync_with_git,
|
|
191
|
-
destination_branch=message.destination_branch,
|
|
192
|
-
branch_diff=branch_diff,
|
|
193
|
-
)
|
|
194
|
-
},
|
|
195
|
-
)
|
|
196
|
-
|
|
197
|
-
if message.check_type in [CheckType.ALL, CheckType.TEST]:
|
|
198
|
-
await service.workflow.submit_workflow(
|
|
199
|
-
workflow=REQUEST_PROPOSED_CHANGE_USER_TESTS,
|
|
200
|
-
context=message.context,
|
|
201
|
-
parameters={
|
|
202
|
-
"model": RequestProposedChangeUserTests(
|
|
203
|
-
proposed_change=message.proposed_change,
|
|
204
|
-
source_branch=message.source_branch,
|
|
205
|
-
source_branch_sync_with_git=message.source_branch_sync_with_git,
|
|
206
|
-
destination_branch=message.destination_branch,
|
|
207
|
-
branch_diff=branch_diff,
|
|
208
|
-
)
|
|
209
|
-
},
|
|
210
|
-
)
|
|
211
|
-
|
|
212
|
-
for event in events:
|
|
213
|
-
event.assign_meta(parent=message)
|
|
214
|
-
await service.message_bus.send(message=event)
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
@flow(
|
|
218
|
-
name="proposed-changed-refresh-artifact",
|
|
219
|
-
flow_run_name="Trigger artifacts refresh",
|
|
220
|
-
)
|
|
221
|
-
async def refresh_artifacts(message: messages.RequestProposedChangeRefreshArtifacts, service: InfrahubServices) -> None:
|
|
222
|
-
await add_tags(branches=[message.source_branch], nodes=[message.proposed_change])
|
|
223
|
-
log = get_run_logger()
|
|
224
|
-
|
|
225
|
-
definition_information = await service.client.execute_graphql(
|
|
226
|
-
query=GATHER_ARTIFACT_DEFINITIONS,
|
|
227
|
-
branch_name=message.source_branch,
|
|
228
|
-
)
|
|
229
|
-
artifact_definitions = _parse_artifact_definitions(
|
|
230
|
-
definitions=definition_information[InfrahubKind.ARTIFACTDEFINITION]["edges"]
|
|
231
|
-
)
|
|
232
|
-
|
|
233
|
-
diff_summary = await get_diff_summary_cache(pipeline_id=message.branch_diff.pipeline_id, cache=service.cache)
|
|
234
|
-
modified_kinds = get_modified_kinds(diff_summary=diff_summary, branch=message.source_branch)
|
|
235
|
-
|
|
236
|
-
for artifact_definition in artifact_definitions:
|
|
237
|
-
# Request artifact definition checks if the source branch that is managed in combination
|
|
238
|
-
# to the Git repository containing modifications which could indicate changes to the transforms
|
|
239
|
-
# in code
|
|
240
|
-
# Alternatively if the queries used touches models that have been modified in the path
|
|
241
|
-
# impacted artifact definitions will be included for consideration
|
|
242
|
-
|
|
243
|
-
select = DefinitionSelect.NONE
|
|
244
|
-
select = select.add_flag(
|
|
245
|
-
current=select,
|
|
246
|
-
flag=DefinitionSelect.FILE_CHANGES,
|
|
247
|
-
condition=message.source_branch_sync_with_git and message.branch_diff.has_file_modifications,
|
|
248
|
-
)
|
|
249
|
-
|
|
250
|
-
for changed_model in modified_kinds:
|
|
251
|
-
condition = False
|
|
252
|
-
if (changed_model in artifact_definition.query_models) or (
|
|
253
|
-
changed_model.startswith("Profile")
|
|
254
|
-
and changed_model.replace("Profile", "", 1) in artifact_definition.query_models
|
|
255
|
-
):
|
|
256
|
-
condition = True
|
|
257
|
-
|
|
258
|
-
select = select.add_flag(
|
|
259
|
-
current=select,
|
|
260
|
-
flag=DefinitionSelect.MODIFIED_KINDS,
|
|
261
|
-
condition=condition,
|
|
262
|
-
)
|
|
263
|
-
|
|
264
|
-
if select:
|
|
265
|
-
log.info(f"Trigger processing of {artifact_definition.definition_name}")
|
|
266
|
-
model = RequestArtifactDefinitionCheck(
|
|
267
|
-
context=message.context,
|
|
268
|
-
artifact_definition=artifact_definition,
|
|
269
|
-
branch_diff=message.branch_diff,
|
|
270
|
-
proposed_change=message.proposed_change,
|
|
271
|
-
source_branch=message.source_branch,
|
|
272
|
-
source_branch_sync_with_git=message.source_branch_sync_with_git,
|
|
273
|
-
destination_branch=message.destination_branch,
|
|
274
|
-
)
|
|
275
|
-
|
|
276
|
-
await service.workflow.submit_workflow(REQUEST_ARTIFACT_DEFINITION_CHECK, parameters={"model": model})
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
GATHER_ARTIFACT_DEFINITIONS = """
|
|
280
|
-
query GatherArtifactDefinitions {
|
|
281
|
-
CoreArtifactDefinition {
|
|
282
|
-
edges {
|
|
283
|
-
node {
|
|
284
|
-
id
|
|
285
|
-
name {
|
|
286
|
-
value
|
|
287
|
-
}
|
|
288
|
-
artifact_name {
|
|
289
|
-
value
|
|
290
|
-
}
|
|
291
|
-
content_type {
|
|
292
|
-
value
|
|
293
|
-
}
|
|
294
|
-
transformation {
|
|
295
|
-
node {
|
|
296
|
-
__typename
|
|
297
|
-
timeout {
|
|
298
|
-
value
|
|
299
|
-
}
|
|
300
|
-
query {
|
|
301
|
-
node {
|
|
302
|
-
models {
|
|
303
|
-
value
|
|
304
|
-
}
|
|
305
|
-
name {
|
|
306
|
-
value
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
... on CoreTransformJinja2 {
|
|
311
|
-
template_path {
|
|
312
|
-
value
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
... on CoreTransformPython {
|
|
316
|
-
class_name {
|
|
317
|
-
value
|
|
318
|
-
}
|
|
319
|
-
file_path {
|
|
320
|
-
value
|
|
321
|
-
}
|
|
322
|
-
convert_query_response {
|
|
323
|
-
value
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
repository {
|
|
327
|
-
node {
|
|
328
|
-
id
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
"""
|
|
338
|
-
|
|
339
|
-
GATHER_GRAPHQL_QUERY_SUBSCRIBERS = """
|
|
340
|
-
query GatherGraphQLQuerySubscribers($members: [ID!]) {
|
|
341
|
-
CoreGraphQLQueryGroup(members__ids: $members) {
|
|
342
|
-
edges {
|
|
343
|
-
node {
|
|
344
|
-
subscribers {
|
|
345
|
-
edges {
|
|
346
|
-
node {
|
|
347
|
-
id
|
|
348
|
-
__typename
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
"""
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
DESTINATION_ALLREPOSITORIES = """
|
|
360
|
-
query DestinationBranchRepositories {
|
|
361
|
-
CoreGenericRepository {
|
|
362
|
-
edges {
|
|
363
|
-
node {
|
|
364
|
-
__typename
|
|
365
|
-
id
|
|
366
|
-
name {
|
|
367
|
-
value
|
|
368
|
-
}
|
|
369
|
-
internal_status {
|
|
370
|
-
value
|
|
371
|
-
}
|
|
372
|
-
... on CoreRepository {
|
|
373
|
-
commit {
|
|
374
|
-
value
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
... on CoreReadOnlyRepository {
|
|
378
|
-
commit {
|
|
379
|
-
value
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
"""
|
|
387
|
-
|
|
388
|
-
SOURCE_REPOSITORIES = """
|
|
389
|
-
query MyQuery {
|
|
390
|
-
CoreRepository {
|
|
391
|
-
edges {
|
|
392
|
-
node {
|
|
393
|
-
__typename
|
|
394
|
-
id
|
|
395
|
-
name {
|
|
396
|
-
value
|
|
397
|
-
}
|
|
398
|
-
internal_status {
|
|
399
|
-
value
|
|
400
|
-
}
|
|
401
|
-
commit {
|
|
402
|
-
value
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
"""
|
|
409
|
-
SOURCE_READONLY_REPOSITORIES = """
|
|
410
|
-
query MyQuery {
|
|
411
|
-
CoreReadOnlyRepository {
|
|
412
|
-
edges {
|
|
413
|
-
node {
|
|
414
|
-
__typename
|
|
415
|
-
id
|
|
416
|
-
name {
|
|
417
|
-
value
|
|
418
|
-
}
|
|
419
|
-
internal_status {
|
|
420
|
-
value
|
|
421
|
-
}
|
|
422
|
-
commit {
|
|
423
|
-
value
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
"""
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
class Repository(BaseModel):
|
|
433
|
-
repository_id: str
|
|
434
|
-
repository_name: str
|
|
435
|
-
read_only: bool
|
|
436
|
-
commit: str
|
|
437
|
-
internal_status: str
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
def _parse_proposed_change_repositories(
|
|
441
|
-
message: messages.RequestProposedChangePipeline, source: list[dict], destination: list[dict]
|
|
442
|
-
) -> list[ProposedChangeRepository]:
|
|
443
|
-
"""This function assumes that the repos is a list of the edges
|
|
444
|
-
|
|
445
|
-
The data should come from the queries:
|
|
446
|
-
* DESTINATION_ALLREPOSITORIES
|
|
447
|
-
* SOURCE_REPOSITORIES
|
|
448
|
-
* SOURCE_READONLY_REPOSITORIES
|
|
449
|
-
"""
|
|
450
|
-
destination_repos = _parse_repositories(repositories=destination)
|
|
451
|
-
source_repos = _parse_repositories(repositories=source)
|
|
452
|
-
pc_repos: dict[str, ProposedChangeRepository] = {}
|
|
453
|
-
for repo in destination_repos:
|
|
454
|
-
if repo.repository_id not in pc_repos:
|
|
455
|
-
pc_repos[repo.repository_id] = ProposedChangeRepository(
|
|
456
|
-
repository_id=repo.repository_id,
|
|
457
|
-
repository_name=repo.repository_name,
|
|
458
|
-
read_only=repo.read_only,
|
|
459
|
-
internal_status=repo.internal_status,
|
|
460
|
-
destination_commit=repo.commit,
|
|
461
|
-
source_branch=message.source_branch,
|
|
462
|
-
destination_branch=message.destination_branch,
|
|
463
|
-
)
|
|
464
|
-
else:
|
|
465
|
-
pc_repos[repo.repository_id].destination_commit = repo.commit
|
|
466
|
-
|
|
467
|
-
for repo in source_repos:
|
|
468
|
-
if repo.repository_id not in pc_repos:
|
|
469
|
-
pc_repos[repo.repository_id] = ProposedChangeRepository(
|
|
470
|
-
repository_id=repo.repository_id,
|
|
471
|
-
repository_name=repo.repository_name,
|
|
472
|
-
read_only=repo.read_only,
|
|
473
|
-
internal_status=repo.internal_status,
|
|
474
|
-
source_commit=repo.commit,
|
|
475
|
-
source_branch=message.source_branch,
|
|
476
|
-
destination_branch=message.destination_branch,
|
|
477
|
-
)
|
|
478
|
-
else:
|
|
479
|
-
pc_repos[repo.repository_id].source_commit = repo.commit
|
|
480
|
-
pc_repos[repo.repository_id].internal_status = repo.internal_status
|
|
481
|
-
|
|
482
|
-
return list(pc_repos.values())
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
def _parse_repositories(repositories: list[dict]) -> list[Repository]:
|
|
486
|
-
"""This function assumes that the repos is a list of the edges
|
|
487
|
-
|
|
488
|
-
The data should come from the queries:
|
|
489
|
-
* DESTINATION_ALLREPOSITORIES
|
|
490
|
-
* SOURCE_REPOSITORIES
|
|
491
|
-
* SOURCE_READONLY_REPOSITORIES
|
|
492
|
-
"""
|
|
493
|
-
parsed = []
|
|
494
|
-
for repo in repositories:
|
|
495
|
-
parsed.append(
|
|
496
|
-
Repository(
|
|
497
|
-
repository_id=repo["node"]["id"],
|
|
498
|
-
repository_name=repo["node"]["name"]["value"],
|
|
499
|
-
read_only=repo["node"]["__typename"] == InfrahubKind.READONLYREPOSITORY,
|
|
500
|
-
commit=repo["node"]["commit"]["value"] or "",
|
|
501
|
-
internal_status=repo["node"]["internal_status"]["value"],
|
|
502
|
-
)
|
|
503
|
-
)
|
|
504
|
-
return parsed
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
def _parse_artifact_definitions(definitions: list[dict]) -> list[ProposedChangeArtifactDefinition]:
|
|
508
|
-
"""This function assumes that definitions is a list of the edges
|
|
509
|
-
|
|
510
|
-
The edge should be of type CoreArtifactDefinition from the query
|
|
511
|
-
* GATHER_ARTIFACT_DEFINITIONS
|
|
512
|
-
"""
|
|
513
|
-
|
|
514
|
-
parsed = []
|
|
515
|
-
for definition in definitions:
|
|
516
|
-
artifact_definition = ProposedChangeArtifactDefinition(
|
|
517
|
-
definition_id=definition["node"]["id"],
|
|
518
|
-
definition_name=definition["node"]["name"]["value"],
|
|
519
|
-
artifact_name=definition["node"]["artifact_name"]["value"],
|
|
520
|
-
content_type=definition["node"]["content_type"]["value"],
|
|
521
|
-
timeout=definition["node"]["transformation"]["node"]["timeout"]["value"],
|
|
522
|
-
query_name=definition["node"]["transformation"]["node"]["query"]["node"]["name"]["value"],
|
|
523
|
-
query_models=definition["node"]["transformation"]["node"]["query"]["node"]["models"]["value"] or [],
|
|
524
|
-
repository_id=definition["node"]["transformation"]["node"]["repository"]["node"]["id"],
|
|
525
|
-
transform_kind=definition["node"]["transformation"]["node"]["__typename"],
|
|
526
|
-
)
|
|
527
|
-
if artifact_definition.transform_kind == InfrahubKind.TRANSFORMJINJA2:
|
|
528
|
-
artifact_definition.template_path = definition["node"]["transformation"]["node"]["template_path"]["value"]
|
|
529
|
-
elif artifact_definition.transform_kind == InfrahubKind.TRANSFORMPYTHON:
|
|
530
|
-
artifact_definition.class_name = definition["node"]["transformation"]["node"]["class_name"]["value"]
|
|
531
|
-
artifact_definition.file_path = definition["node"]["transformation"]["node"]["file_path"]["value"]
|
|
532
|
-
artifact_definition.convert_query_response = definition["node"]["transformation"]["node"][
|
|
533
|
-
"convert_query_response"
|
|
534
|
-
]["value"]
|
|
535
|
-
|
|
536
|
-
parsed.append(artifact_definition)
|
|
537
|
-
|
|
538
|
-
return parsed
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
async def _get_proposed_change_repositories(
|
|
542
|
-
message: messages.RequestProposedChangePipeline, service: InfrahubServices
|
|
543
|
-
) -> list[ProposedChangeRepository]:
|
|
544
|
-
destination_all = await service.client.execute_graphql(
|
|
545
|
-
query=DESTINATION_ALLREPOSITORIES, branch_name=message.destination_branch
|
|
546
|
-
)
|
|
547
|
-
source_managed = await service.client.execute_graphql(query=SOURCE_REPOSITORIES, branch_name=message.source_branch)
|
|
548
|
-
source_readonly = await service.client.execute_graphql(
|
|
549
|
-
query=SOURCE_READONLY_REPOSITORIES, branch_name=message.source_branch
|
|
550
|
-
)
|
|
551
|
-
|
|
552
|
-
destination_all = destination_all[InfrahubKind.GENERICREPOSITORY]["edges"]
|
|
553
|
-
source_all = (
|
|
554
|
-
source_managed[InfrahubKind.REPOSITORY]["edges"] + source_readonly[InfrahubKind.READONLYREPOSITORY]["edges"]
|
|
555
|
-
)
|
|
556
|
-
|
|
557
|
-
return _parse_proposed_change_repositories(message=message, source=source_all, destination=destination_all)
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
@task(name="proposed-change-validate-repository-conflicts", task_run_name="Validate conflicts on repository") # type: ignore[arg-type]
|
|
561
|
-
async def _validate_repository_merge_conflicts(
|
|
562
|
-
repositories: list[ProposedChangeRepository], service: InfrahubServices
|
|
563
|
-
) -> bool:
|
|
564
|
-
log = get_run_logger()
|
|
565
|
-
conflicts = False
|
|
566
|
-
for repo in repositories:
|
|
567
|
-
if repo.has_diff and not repo.is_staging:
|
|
568
|
-
git_repo = await InfrahubRepository.init(
|
|
569
|
-
id=repo.repository_id,
|
|
570
|
-
name=repo.repository_name,
|
|
571
|
-
client=service.client,
|
|
572
|
-
service=service,
|
|
573
|
-
)
|
|
574
|
-
async with lock.registry.get(name=repo.repository_name, namespace="repository"):
|
|
575
|
-
repo.conflicts = await git_repo.get_conflicts(
|
|
576
|
-
source_branch=repo.source_branch, dest_branch=repo.destination_branch
|
|
577
|
-
)
|
|
578
|
-
if repo.conflicts:
|
|
579
|
-
log.info(f"{len(repo.conflicts)} conflict(s) identified on {repo.repository_name}")
|
|
580
|
-
conflicts = True
|
|
581
|
-
else:
|
|
582
|
-
log.info(f"no conflict identified for {repo.repository_name}")
|
|
583
|
-
|
|
584
|
-
return conflicts
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
async def _gather_repository_repository_diffs(
|
|
588
|
-
repositories: list[ProposedChangeRepository], service: InfrahubServices
|
|
589
|
-
) -> None:
|
|
590
|
-
for repo in repositories:
|
|
591
|
-
if repo.has_diff and repo.source_commit and repo.destination_commit:
|
|
592
|
-
# TODO we need to find a way to return all files in the repo if the repo is new
|
|
593
|
-
git_repo = await InfrahubRepository.init(
|
|
594
|
-
id=repo.repository_id,
|
|
595
|
-
name=repo.repository_name,
|
|
596
|
-
client=service.client,
|
|
597
|
-
service=service,
|
|
598
|
-
)
|
|
599
|
-
|
|
600
|
-
files_changed: list[str] = []
|
|
601
|
-
files_added: list[str] = []
|
|
602
|
-
files_removed: list[str] = []
|
|
603
|
-
|
|
604
|
-
if repo.destination_branch:
|
|
605
|
-
files_changed, files_added, files_removed = await git_repo.calculate_diff_between_commits(
|
|
606
|
-
first_commit=repo.source_commit, second_commit=repo.destination_commit
|
|
607
|
-
)
|
|
608
|
-
else:
|
|
609
|
-
files_added = await git_repo.list_all_files(commit=repo.source_commit)
|
|
610
|
-
|
|
611
|
-
repo.files_removed = files_removed
|
|
612
|
-
repo.files_added = files_added
|
|
613
|
-
repo.files_changed = files_changed
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
async def _populate_subscribers(
|
|
617
|
-
branch_diff: ProposedChangeBranchDiff, diff_summary: list[NodeDiff], service: InfrahubServices, branch: str
|
|
618
|
-
) -> None:
|
|
619
|
-
result = await service.client.execute_graphql(
|
|
620
|
-
query=GATHER_GRAPHQL_QUERY_SUBSCRIBERS,
|
|
621
|
-
branch_name=branch,
|
|
622
|
-
variables={"members": get_modified_node_ids(diff_summary=diff_summary, branch=branch)},
|
|
623
|
-
)
|
|
624
|
-
|
|
625
|
-
for group in result[InfrahubKind.GRAPHQLQUERYGROUP]["edges"]:
|
|
626
|
-
for subscriber in group["node"]["subscribers"]["edges"]:
|
|
627
|
-
branch_diff.subscribers.append(
|
|
628
|
-
ProposedChangeSubscriber(subscriber_id=subscriber["node"]["id"], kind=subscriber["node"]["__typename"])
|
|
629
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|