infrahub-server 1.6.2__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 +12 -9
- 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 +26 -6
- 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 +11 -6
- 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_parameters.py +28 -1
- infrahub/core/schema/attribute_schema.py +11 -17
- 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 +115 -11
- 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 +6 -3
- 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/app.py +2 -2
- 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/diff/tree.py +5 -5
- 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.2.dist-info → infrahub_server-1.7.0.dist-info}/METADATA +17 -16
- {infrahub_server-1.6.2.dist-info → infrahub_server-1.7.0.dist-info}/RECORD +252 -231
- 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.2.dist-info → infrahub_server-1.7.0.dist-info}/WHEEL +0 -0
- {infrahub_server-1.6.2.dist-info → infrahub_server-1.7.0.dist-info}/entry_points.txt +0 -0
- {infrahub_server-1.6.2.dist-info → infrahub_server-1.7.0.dist-info}/licenses/LICENSE.txt +0 -0
infrahub/actions/tasks.py
CHANGED
|
@@ -211,8 +211,10 @@ async def configure_action_rules(
|
|
|
211
211
|
service: InfrahubServices,
|
|
212
212
|
) -> None:
|
|
213
213
|
await setup_triggers_specific(
|
|
214
|
-
gatherer=gather_trigger_action_rules,
|
|
215
|
-
|
|
214
|
+
gatherer=gather_trigger_action_rules, # type: ignore[arg-type]
|
|
215
|
+
trigger_type=TriggerType.ACTION_TRIGGER_RULE,
|
|
216
|
+
db=service.database,
|
|
217
|
+
)
|
|
216
218
|
|
|
217
219
|
|
|
218
220
|
async def _get_targets(
|
infrahub/api/exceptions.py
CHANGED
|
@@ -4,12 +4,12 @@ from infrahub.exceptions import Error
|
|
|
4
4
|
class QueryValidationError(Error):
|
|
5
5
|
HTTP_CODE = 400
|
|
6
6
|
|
|
7
|
-
def __init__(self, message: str):
|
|
7
|
+
def __init__(self, message: str) -> None:
|
|
8
8
|
self.message = message
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class SchemaNotValidError(Error):
|
|
12
12
|
HTTP_CODE = 422
|
|
13
13
|
|
|
14
|
-
def __init__(self, message: str):
|
|
14
|
+
def __init__(self, message: str) -> None:
|
|
15
15
|
self.message = message
|
infrahub/api/schema.py
CHANGED
|
@@ -366,6 +366,7 @@ async def load_schema(
|
|
|
366
366
|
diff=result.diff,
|
|
367
367
|
limit=result.diff.all,
|
|
368
368
|
update_db=True,
|
|
369
|
+
user_id=account_session.account_id,
|
|
369
370
|
)
|
|
370
371
|
branch.update_schema_hash()
|
|
371
372
|
log.info("Schema has been updated", branch=branch.name, hash=branch.active_schema_hash.main)
|
|
@@ -375,7 +376,7 @@ async def load_schema(
|
|
|
375
376
|
branch.is_isolated = True
|
|
376
377
|
log.info("Branch converted to isolated mode because the schema has changed", branch=branch.name)
|
|
377
378
|
|
|
378
|
-
await branch.save(db=dbt)
|
|
379
|
+
await branch.save(db=dbt, user_id=account_session.account_id)
|
|
379
380
|
updated_branch = registry.schema.get_schema_branch(name=branch.name)
|
|
380
381
|
updated_hash = updated_branch.get_hash()
|
|
381
382
|
|
|
@@ -387,6 +388,7 @@ async def load_schema(
|
|
|
387
388
|
new_schema=candidate_schema,
|
|
388
389
|
previous_schema=origin_schema,
|
|
389
390
|
migrations=result.migrations,
|
|
391
|
+
user_id=account_session.account_id,
|
|
390
392
|
)
|
|
391
393
|
migration_error_msgs = await service.workflow.execute_workflow(
|
|
392
394
|
workflow=SCHEMA_APPLY_MIGRATION,
|
infrahub/artifacts/tasks.py
CHANGED
|
@@ -14,6 +14,7 @@ async def create(model: CheckArtifactCreate) -> ValidatorConclusion:
|
|
|
14
14
|
await add_tags(branches=[model.branch_name], nodes=[model.target_id])
|
|
15
15
|
|
|
16
16
|
client = get_client()
|
|
17
|
+
client.request_context = model.context.to_request_context()
|
|
17
18
|
|
|
18
19
|
validator = await client.get(kind=InfrahubKind.ARTIFACTVALIDATOR, id=model.validator_id, include=["checks"])
|
|
19
20
|
|
infrahub/auth.py
CHANGED
|
@@ -73,8 +73,8 @@ async def authenticate_with_password(
|
|
|
73
73
|
) -> models.UserToken:
|
|
74
74
|
selected_branch = await registry.get_branch(db=db, branch=branch)
|
|
75
75
|
|
|
76
|
-
response
|
|
77
|
-
schema=
|
|
76
|
+
response = await NodeManager.query(
|
|
77
|
+
schema=CoreGenericAccount,
|
|
78
78
|
db=db,
|
|
79
79
|
branch=selected_branch,
|
|
80
80
|
filters={"name__value": credentials.username},
|
infrahub/cli/db.py
CHANGED
|
@@ -65,6 +65,7 @@ def get_timestamp_string() -> str:
|
|
|
65
65
|
if TYPE_CHECKING:
|
|
66
66
|
from infrahub.cli.context import CliContext
|
|
67
67
|
from infrahub.core.migrations.shared import MigrationTypes
|
|
68
|
+
from infrahub.core.root import Root
|
|
68
69
|
from infrahub.database import InfrahubDatabase
|
|
69
70
|
from infrahub.database.index import IndexManagerBase
|
|
70
71
|
|
|
@@ -93,12 +94,40 @@ def callback() -> None:
|
|
|
93
94
|
"""
|
|
94
95
|
|
|
95
96
|
|
|
97
|
+
async def do_migrate(
|
|
98
|
+
db: InfrahubDatabase,
|
|
99
|
+
root_node: Root,
|
|
100
|
+
check: bool = False,
|
|
101
|
+
migration_number: int | None = None,
|
|
102
|
+
) -> None:
|
|
103
|
+
"""Core migration logic that can be called independently of CLI.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
db: The database connection.
|
|
107
|
+
root_node: The root node containing the current graph version.
|
|
108
|
+
check: If True, only check which migrations need to run without applying them.
|
|
109
|
+
migration_number: If provided, run only this specific migration.
|
|
110
|
+
"""
|
|
111
|
+
migrations = await detect_migration_to_run(
|
|
112
|
+
current_graph_version=root_node.graph_version, migration_number=migration_number
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
if check or not migrations:
|
|
116
|
+
return
|
|
117
|
+
|
|
118
|
+
await migrate_database(
|
|
119
|
+
db=db, migrations=migrations, initialize=True, update_graph_version=(migration_number is None)
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
|
|
96
123
|
@app.command(name="migrate")
|
|
97
124
|
async def migrate_cmd(
|
|
98
125
|
ctx: typer.Context,
|
|
99
126
|
check: bool = typer.Option(False, help="Check the state of the database without applying the migrations."),
|
|
100
127
|
config_file: str = typer.Argument("infrahub.toml", envvar="INFRAHUB_CONFIG"),
|
|
101
|
-
migration_number: int | None = typer.Option(
|
|
128
|
+
migration_number: int | None = typer.Option(
|
|
129
|
+
None, help="Apply a specific migration by number, regardless of current database version"
|
|
130
|
+
),
|
|
102
131
|
) -> None:
|
|
103
132
|
"""Check the current format of the internal graph and apply the necessary migrations"""
|
|
104
133
|
logging.getLogger("infrahub").setLevel(logging.WARNING)
|
|
@@ -111,14 +140,7 @@ async def migrate_cmd(
|
|
|
111
140
|
dbdriver = await context.init_db(retry=1)
|
|
112
141
|
|
|
113
142
|
root_node = await get_root_node(db=dbdriver)
|
|
114
|
-
|
|
115
|
-
current_graph_version=root_node.graph_version, migration_number=migration_number
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
if check or not migrations:
|
|
119
|
-
return
|
|
120
|
-
|
|
121
|
-
await migrate_database(db=dbdriver, migrations=migrations, initialize=True)
|
|
143
|
+
await do_migrate(db=dbdriver, root_node=root_node, check=check, migration_number=migration_number)
|
|
122
144
|
|
|
123
145
|
await dbdriver.close()
|
|
124
146
|
|
|
@@ -292,18 +314,17 @@ async def detect_migration_to_run(
|
|
|
292
314
|
migration = get_migration_by_number(migration_number)
|
|
293
315
|
migrations.append(migration)
|
|
294
316
|
if current_graph_version > migration.minimum_version:
|
|
317
|
+
get_migration_console().log(f"Migration {migration_number} will be re-applied.")
|
|
318
|
+
else:
|
|
295
319
|
get_migration_console().log(
|
|
296
|
-
f"Migration {migration_number}
|
|
320
|
+
f"Migration {migration_number} needs to be applied. Run `infrahub db migrate` to apply all outstanding migrations."
|
|
297
321
|
)
|
|
298
|
-
return
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
if not migrations:
|
|
305
|
-
get_migration_console().log(f"Database up-to-date (v{current_graph_version}), no migration to execute.")
|
|
306
|
-
return []
|
|
322
|
+
return migrations
|
|
323
|
+
|
|
324
|
+
migrations.extend(await get_graph_migrations(current_graph_version=current_graph_version))
|
|
325
|
+
if not migrations:
|
|
326
|
+
get_migration_console().log(f"Database up-to-date (v{current_graph_version}), no migration to execute.")
|
|
327
|
+
return []
|
|
307
328
|
|
|
308
329
|
get_migration_console().log(
|
|
309
330
|
f"Database needs to be updated (v{current_graph_version} -> v{GRAPH_VERSION}), {len(migrations)} migrations pending"
|
|
@@ -312,7 +333,10 @@ async def detect_migration_to_run(
|
|
|
312
333
|
|
|
313
334
|
|
|
314
335
|
async def migrate_database(
|
|
315
|
-
db: InfrahubDatabase,
|
|
336
|
+
db: InfrahubDatabase,
|
|
337
|
+
migrations: Sequence[MigrationTypes],
|
|
338
|
+
initialize: bool = False,
|
|
339
|
+
update_graph_version: bool = True,
|
|
316
340
|
) -> bool:
|
|
317
341
|
"""Apply the latest migrations to the database, this function will print the status directly in the console.
|
|
318
342
|
|
|
@@ -322,6 +346,7 @@ async def migrate_database(
|
|
|
322
346
|
db: The database object.
|
|
323
347
|
migrations: Sequence of migrations to apply.
|
|
324
348
|
initialize: Whether to initialize the registry before running migrations.
|
|
349
|
+
update_graph_version: Whether to update the graph version after each migration.
|
|
325
350
|
"""
|
|
326
351
|
if not migrations:
|
|
327
352
|
return True
|
|
@@ -339,8 +364,9 @@ async def migrate_database(
|
|
|
339
364
|
validation_result = await migration.validate_migration(db=db)
|
|
340
365
|
if validation_result.success:
|
|
341
366
|
get_migration_console().log(f"Migration: {migration.name} {SUCCESS_BADGE}")
|
|
342
|
-
|
|
343
|
-
|
|
367
|
+
if update_graph_version:
|
|
368
|
+
root_node.graph_version = migration.minimum_version + 1
|
|
369
|
+
await root_node.save(db=db)
|
|
344
370
|
|
|
345
371
|
if not execution_result.success or (validation_result and not validation_result.success):
|
|
346
372
|
get_migration_console().log(f"Migration: {migration.name} {FAILED_BADGE}")
|
|
@@ -603,17 +629,17 @@ RETURN vertices, edges
|
|
|
603
629
|
edge_path = export_dir / Path("edges.csv")
|
|
604
630
|
edge_path.touch(exist_ok=True)
|
|
605
631
|
|
|
606
|
-
graph_node_schemas =
|
|
632
|
+
graph_node_schemas = (GraphNodeProperties, GraphRelationshipProperties, GraphAttributeProperties)
|
|
607
633
|
graph_vertex_properties = set()
|
|
608
|
-
for
|
|
609
|
-
for field_name, field_info in
|
|
634
|
+
for graph_node_schema in graph_node_schemas:
|
|
635
|
+
for field_name, field_info in graph_node_schema.model_fields.items():
|
|
610
636
|
property_name = field_info.alias or field_name
|
|
611
637
|
graph_vertex_properties.add(property_name)
|
|
612
638
|
|
|
613
|
-
graph_edge_schemas =
|
|
639
|
+
graph_edge_schemas = (GraphRelationshipIsPartOf, GraphRelationshipDefault)
|
|
614
640
|
graph_edge_properties = set()
|
|
615
|
-
for
|
|
616
|
-
for field_name, field_info in
|
|
641
|
+
for graph_edge_schema in graph_edge_schemas:
|
|
642
|
+
for field_name, field_info in graph_edge_schema.model_fields.items():
|
|
617
643
|
property_name = field_info.alias or field_name
|
|
618
644
|
graph_edge_properties.add(property_name)
|
|
619
645
|
|
|
@@ -7,9 +7,9 @@ from prefect import task
|
|
|
7
7
|
from prefect.cache_policies import NONE
|
|
8
8
|
from prefect.logging import get_run_logger
|
|
9
9
|
|
|
10
|
-
from infrahub.core.constants import InfrahubKind
|
|
11
10
|
from infrahub.core.manager import NodeManager
|
|
12
11
|
from infrahub.core.protocols import CoreGenericRepository, CoreGraphQLQuery
|
|
12
|
+
from infrahub.core.protocols import CoreTransformPython as CoreTransformPythonNode
|
|
13
13
|
from infrahub.core.registry import registry
|
|
14
14
|
from infrahub.database import InfrahubDatabase # noqa: TC001 needed for prefect flow
|
|
15
15
|
from infrahub.git.utils import get_repositories_commit_per_branch
|
|
@@ -24,7 +24,6 @@ from .models import (
|
|
|
24
24
|
)
|
|
25
25
|
|
|
26
26
|
if TYPE_CHECKING:
|
|
27
|
-
from infrahub.core.protocols import CoreTransformPython as CoreTransformPythonNode
|
|
28
27
|
from infrahub.git.models import RepositoryData
|
|
29
28
|
|
|
30
29
|
|
|
@@ -48,9 +47,9 @@ async def gather_python_transform_attributes(
|
|
|
48
47
|
if not transform_names:
|
|
49
48
|
return []
|
|
50
49
|
|
|
51
|
-
transforms
|
|
50
|
+
transforms = await NodeManager.query(
|
|
52
51
|
db=db,
|
|
53
|
-
schema=
|
|
52
|
+
schema=CoreTransformPythonNode,
|
|
54
53
|
branch=branch_name,
|
|
55
54
|
fields={"id": None, "name": None, "repository": None, "query": None},
|
|
56
55
|
filters={"name__values": transform_names},
|
|
@@ -42,8 +42,10 @@ mutation UpdateAttribute(
|
|
|
42
42
|
$kind: String!,
|
|
43
43
|
$attribute: String!,
|
|
44
44
|
$value: String!
|
|
45
|
+
$context_account_id: String!
|
|
45
46
|
) {
|
|
46
47
|
InfrahubUpdateComputedAttribute(
|
|
48
|
+
context: {account: {id: $context_account_id}},
|
|
47
49
|
data: {id: $id, attribute: $attribute, value: $value, kind: $kind}
|
|
48
50
|
) {
|
|
49
51
|
ok
|
|
@@ -62,7 +64,7 @@ async def process_transform(
|
|
|
62
64
|
object_id: str,
|
|
63
65
|
computed_attribute_name: str, # noqa: ARG001
|
|
64
66
|
computed_attribute_kind: str, # noqa: ARG001
|
|
65
|
-
context: InfrahubContext,
|
|
67
|
+
context: InfrahubContext,
|
|
66
68
|
updated_fields: list[str] | None = None, # noqa: ARG001
|
|
67
69
|
) -> None:
|
|
68
70
|
await add_tags(branches=[branch_name], nodes=[object_id])
|
|
@@ -103,7 +105,7 @@ async def process_transform(
|
|
|
103
105
|
name=transform.repository.peer.name.value,
|
|
104
106
|
repository_kind=str(transform.repository.peer.typename),
|
|
105
107
|
commit=repo_node.commit.value,
|
|
106
|
-
)
|
|
108
|
+
)
|
|
107
109
|
|
|
108
110
|
data = await client.query_gql_query(
|
|
109
111
|
name=transform.query.id,
|
|
@@ -120,11 +122,17 @@ async def process_transform(
|
|
|
120
122
|
location=f"{transform.file_path.value}::{transform.class_name.value}",
|
|
121
123
|
data=data,
|
|
122
124
|
convert_query_response=transform.convert_query_response.value,
|
|
123
|
-
) # type: ignore[
|
|
125
|
+
) # type: ignore[call-overload]
|
|
124
126
|
|
|
125
127
|
await client.execute_graphql(
|
|
126
128
|
query=UPDATE_ATTRIBUTE,
|
|
127
|
-
variables={
|
|
129
|
+
variables={
|
|
130
|
+
"id": object_id,
|
|
131
|
+
"kind": node_kind,
|
|
132
|
+
"attribute": attribute_name,
|
|
133
|
+
"value": transformed_data,
|
|
134
|
+
"context_account_id": context.account.account_id,
|
|
135
|
+
},
|
|
128
136
|
branch_name=branch_name,
|
|
129
137
|
)
|
|
130
138
|
|
|
@@ -168,6 +176,7 @@ async def computed_attribute_jinja2_update_value(
|
|
|
168
176
|
node_kind: str,
|
|
169
177
|
attribute_name: str,
|
|
170
178
|
template: Jinja2Template,
|
|
179
|
+
context: InfrahubContext,
|
|
171
180
|
) -> None:
|
|
172
181
|
log = get_run_logger()
|
|
173
182
|
client = get_client()
|
|
@@ -182,7 +191,13 @@ async def computed_attribute_jinja2_update_value(
|
|
|
182
191
|
try:
|
|
183
192
|
await client.execute_graphql(
|
|
184
193
|
query=UPDATE_ATTRIBUTE,
|
|
185
|
-
variables={
|
|
194
|
+
variables={
|
|
195
|
+
"id": obj.node_id,
|
|
196
|
+
"kind": node_kind,
|
|
197
|
+
"attribute": attribute_name,
|
|
198
|
+
"value": value,
|
|
199
|
+
"context_account_id": context.account.account_id,
|
|
200
|
+
},
|
|
186
201
|
branch_name=branch_name,
|
|
187
202
|
)
|
|
188
203
|
log.info(f"Updating computed attribute {node_kind}.{attribute_name}='{value}' ({obj.node_id})")
|
|
@@ -202,7 +217,7 @@ async def process_jinja2(
|
|
|
202
217
|
object_id: str,
|
|
203
218
|
computed_attribute_name: str,
|
|
204
219
|
computed_attribute_kind: str,
|
|
205
|
-
context: InfrahubContext,
|
|
220
|
+
context: InfrahubContext,
|
|
206
221
|
updated_fields: list[str] | None = None,
|
|
207
222
|
) -> None:
|
|
208
223
|
log = get_run_logger()
|
|
@@ -258,6 +273,7 @@ async def process_jinja2(
|
|
|
258
273
|
node_kind=node_schema.kind,
|
|
259
274
|
attribute_name=computed_macro.attribute.name,
|
|
260
275
|
template=jinja_template,
|
|
276
|
+
context=context,
|
|
261
277
|
)
|
|
262
278
|
|
|
263
279
|
_ = [response async for _, response in batch.execute()]
|
|
@@ -462,6 +478,7 @@ async def query_transform_targets(
|
|
|
462
478
|
"object_id": subscriber.object_id,
|
|
463
479
|
"computed_attribute_name": computed_attribute.name,
|
|
464
480
|
"computed_attribute_kind": subscriber.kind,
|
|
481
|
+
"context": context,
|
|
465
482
|
},
|
|
466
483
|
)
|
|
467
484
|
|
infrahub/config.py
CHANGED
|
@@ -207,6 +207,14 @@ class MainSettings(BaseSettings):
|
|
|
207
207
|
def convert_to_path(cls, value: Path | str) -> Path:
|
|
208
208
|
return Path(value) if isinstance(value, str) else value
|
|
209
209
|
|
|
210
|
+
@property
|
|
211
|
+
def infrahub_address(self) -> str:
|
|
212
|
+
"""This is the address that the Prefect worker will use to connect to Infrahub API."""
|
|
213
|
+
if self.internal_address:
|
|
214
|
+
return self.internal_address
|
|
215
|
+
|
|
216
|
+
raise InitializationError()
|
|
217
|
+
|
|
210
218
|
|
|
211
219
|
class FileSystemStorageSettings(BaseSettings):
|
|
212
220
|
# Make variable lookup case-sensitive to avoid fetching $PATH value
|
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__(
|
|
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
|
|
@@ -164,7 +167,7 @@ class AccountObjectPermissionQuery(Query):
|
|
|
164
167
|
name: str = "account_object_permissions"
|
|
165
168
|
type: QueryType = QueryType.READ
|
|
166
169
|
|
|
167
|
-
def __init__(self, account_id: str, **kwargs: Any):
|
|
170
|
+
def __init__(self, account_id: str, **kwargs: Any) -> None:
|
|
168
171
|
self.account_id = account_id
|
|
169
172
|
super().__init__(**kwargs)
|
|
170
173
|
|
|
@@ -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 =
|
|
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
|
|
|
@@ -308,7 +311,7 @@ class AccountRoleGlobalPermissionQuery(Query):
|
|
|
308
311
|
name: str = "account_role_global_permissions"
|
|
309
312
|
type: QueryType = QueryType.READ
|
|
310
313
|
|
|
311
|
-
def __init__(self, role_id: str, **kwargs: Any):
|
|
314
|
+
def __init__(self, role_id: str, **kwargs: Any) -> None:
|
|
312
315
|
self.role_id = role_id
|
|
313
316
|
super().__init__(**kwargs)
|
|
314
317
|
|
|
@@ -394,7 +397,7 @@ class AccountRoleObjectPermissionQuery(Query):
|
|
|
394
397
|
name: str = "account_role_object_permissions"
|
|
395
398
|
type: QueryType = QueryType.READ
|
|
396
399
|
|
|
397
|
-
def __init__(self, role_id: str, **kwargs: Any):
|
|
400
|
+
def __init__(self, role_id: str, **kwargs: Any) -> None:
|
|
398
401
|
self.role_id = role_id
|
|
399
402
|
super().__init__(**kwargs)
|
|
400
403
|
|
|
@@ -515,7 +518,7 @@ class AccountTokenValidateQuery(Query):
|
|
|
515
518
|
name: str = "account_token_validate"
|
|
516
519
|
type: QueryType = QueryType.READ
|
|
517
520
|
|
|
518
|
-
def __init__(self, token: str, **kwargs: Any):
|
|
521
|
+
def __init__(self, token: str, **kwargs: Any) -> None:
|
|
519
522
|
self.token = token
|
|
520
523
|
super().__init__(**kwargs)
|
|
521
524
|
|