infrahub-server 1.1.6__py3-none-any.whl → 1.2.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/api/artifact.py +16 -4
- infrahub/api/dependencies.py +8 -0
- infrahub/api/oauth2.py +0 -1
- infrahub/api/oidc.py +0 -1
- infrahub/api/query.py +18 -7
- infrahub/api/schema.py +32 -6
- infrahub/api/transformation.py +12 -5
- infrahub/{message_bus/messages/check_artifact_create.py → artifacts/models.py} +5 -3
- infrahub/{message_bus/operations/check/artifact.py → artifacts/tasks.py} +26 -25
- infrahub/cli/__init__.py +0 -2
- infrahub/cli/db.py +6 -7
- infrahub/cli/events.py +8 -3
- infrahub/cli/git_agent.py +9 -7
- infrahub/cli/tasks.py +4 -6
- infrahub/computed_attribute/models.py +1 -1
- infrahub/computed_attribute/tasks.py +64 -17
- infrahub/computed_attribute/triggers.py +90 -0
- infrahub/config.py +1 -1
- infrahub/context.py +39 -0
- infrahub/core/account.py +5 -8
- infrahub/core/attribute.py +54 -22
- infrahub/core/branch/models.py +4 -4
- infrahub/core/branch/tasks.py +137 -129
- infrahub/core/changelog/__init__.py +0 -0
- infrahub/core/changelog/diff.py +283 -0
- infrahub/core/changelog/models.py +499 -0
- infrahub/core/constants/__init__.py +43 -2
- infrahub/core/constants/infrahubkind.py +1 -0
- infrahub/core/constants/schema.py +2 -0
- infrahub/core/diff/combiner.py +12 -8
- infrahub/core/diff/coordinator.py +49 -70
- infrahub/core/diff/data_check_synchronizer.py +86 -7
- infrahub/core/diff/enricher/aggregated.py +3 -3
- infrahub/core/diff/enricher/cardinality_one.py +7 -7
- infrahub/core/diff/enricher/hierarchy.py +22 -7
- infrahub/core/diff/enricher/labels.py +19 -4
- infrahub/core/diff/enricher/path_identifier.py +7 -9
- infrahub/core/diff/enricher/summary_counts.py +3 -1
- infrahub/core/diff/merger/merger.py +8 -4
- infrahub/core/diff/model/path.py +76 -35
- infrahub/core/diff/parent_node_adder.py +78 -0
- infrahub/core/diff/payload_builder.py +13 -2
- infrahub/core/diff/query/all_conflicts.py +6 -3
- infrahub/core/diff/query/artifact.py +1 -1
- infrahub/core/diff/query/delete_query.py +1 -1
- infrahub/core/diff/query/diff_get.py +3 -2
- infrahub/core/diff/query/diff_summary.py +1 -1
- infrahub/core/diff/query/field_specifiers.py +3 -1
- infrahub/core/diff/query/field_summary.py +3 -2
- infrahub/core/diff/query/filters.py +14 -3
- infrahub/core/diff/query/get_conflict_query.py +1 -1
- infrahub/core/diff/query/has_conflicts_query.py +6 -3
- infrahub/core/diff/query/merge.py +3 -3
- infrahub/core/diff/query/{drop_tracking_id.py → merge_tracking_id.py} +4 -4
- infrahub/core/diff/query/roots_metadata.py +9 -2
- infrahub/core/diff/query/save.py +233 -142
- infrahub/core/diff/query/summary_counts_enricher.py +267 -0
- infrahub/core/diff/query/time_range_query.py +3 -2
- infrahub/core/diff/query/update_conflict_query.py +1 -1
- infrahub/core/diff/query_parser.py +49 -24
- infrahub/core/diff/repository/deserializer.py +32 -28
- infrahub/core/diff/repository/repository.py +215 -41
- infrahub/core/diff/tasks.py +13 -12
- infrahub/core/enums.py +1 -1
- infrahub/core/graph/__init__.py +1 -1
- infrahub/core/graph/index.py +3 -0
- infrahub/core/integrity/object_conflict/conflict_recorder.py +1 -1
- infrahub/core/ipam/reconciler.py +1 -1
- infrahub/core/ipam/tasks.py +2 -3
- infrahub/core/manager.py +20 -15
- infrahub/core/merge.py +5 -2
- infrahub/core/migrations/graph/__init__.py +4 -0
- infrahub/core/migrations/graph/m001_add_version_to_graph.py +1 -1
- infrahub/core/migrations/graph/m002_attribute_is_default.py +2 -2
- infrahub/core/migrations/graph/m003_relationship_parent_optional.py +2 -2
- infrahub/core/migrations/graph/m004_add_attr_documentation.py +1 -1
- infrahub/core/migrations/graph/m005_add_rel_read_only.py +1 -1
- infrahub/core/migrations/graph/m006_add_rel_on_delete.py +1 -1
- infrahub/core/migrations/graph/m007_add_rel_allow_override.py +1 -1
- infrahub/core/migrations/graph/m008_add_human_friendly_id.py +1 -1
- infrahub/core/migrations/graph/m009_add_generate_profile_attr.py +1 -1
- infrahub/core/migrations/graph/m010_add_generate_profile_attr_generic.py +1 -1
- infrahub/core/migrations/graph/m011_remove_profile_relationship_schema.py +2 -2
- infrahub/core/migrations/graph/m012_convert_account_generic.py +12 -23
- infrahub/core/migrations/graph/m013_convert_git_password_credential.py +7 -11
- infrahub/core/migrations/graph/m014_remove_index_attr_value.py +2 -2
- infrahub/core/migrations/graph/m015_diff_format_update.py +1 -1
- infrahub/core/migrations/graph/m016_diff_delete_bug_fix.py +1 -1
- infrahub/core/migrations/graph/m017_add_core_profile.py +1 -1
- infrahub/core/migrations/graph/m018_uniqueness_nulls.py +2 -2
- infrahub/core/migrations/graph/m019_restore_rels_to_time.py +256 -0
- infrahub/core/migrations/graph/m020_add_generate_template_attr.py +48 -0
- infrahub/core/migrations/query/attribute_add.py +1 -1
- infrahub/core/migrations/query/attribute_rename.py +1 -1
- infrahub/core/migrations/query/delete_element_in_schema.py +1 -1
- infrahub/core/migrations/query/node_duplicate.py +39 -19
- infrahub/core/migrations/query/relationship_duplicate.py +1 -1
- infrahub/core/migrations/query/schema_attribute_update.py +1 -1
- infrahub/core/migrations/schema/node_attribute_remove.py +1 -1
- infrahub/core/migrations/schema/node_remove.py +27 -13
- infrahub/core/migrations/schema/tasks.py +5 -5
- infrahub/core/migrations/shared.py +4 -4
- infrahub/core/models.py +7 -8
- infrahub/core/node/__init__.py +170 -46
- infrahub/core/node/base.py +1 -1
- infrahub/core/node/constraints/grouped_uniqueness.py +9 -2
- infrahub/core/node/delete_validator.py +4 -4
- infrahub/core/node/ipam.py +13 -8
- infrahub/core/node/permissions.py +4 -0
- infrahub/core/node/resource_manager/ip_prefix_pool.py +8 -5
- infrahub/core/node/standard.py +3 -5
- infrahub/core/property.py +1 -1
- infrahub/core/protocols.py +6 -0
- infrahub/core/protocols_base.py +4 -2
- infrahub/core/query/__init__.py +2 -5
- infrahub/core/query/attribute.py +9 -9
- infrahub/core/query/branch.py +5 -5
- infrahub/core/query/delete.py +1 -1
- infrahub/core/query/diff.py +45 -7
- infrahub/core/query/ipam.py +4 -4
- infrahub/core/query/node.py +19 -14
- infrahub/core/query/relationship.py +213 -26
- infrahub/core/query/resource_manager.py +13 -11
- infrahub/core/query/standard_node.py +6 -6
- infrahub/core/query/task.py +3 -3
- infrahub/core/query/task_log.py +1 -1
- infrahub/core/query/utils.py +5 -5
- infrahub/core/registry.py +0 -2
- infrahub/core/relationship/constraints/count.py +1 -1
- infrahub/core/relationship/constraints/peer_kind.py +1 -1
- infrahub/core/relationship/model.py +76 -38
- infrahub/core/schema/__init__.py +6 -4
- infrahub/core/schema/attribute_schema.py +8 -0
- infrahub/core/schema/basenode_schema.py +13 -3
- infrahub/core/schema/definitions/core/__init__.py +153 -0
- infrahub/core/schema/definitions/core/account.py +168 -0
- infrahub/core/schema/definitions/core/artifact.py +127 -0
- infrahub/core/schema/definitions/core/builtin.py +21 -0
- infrahub/core/schema/definitions/core/check.py +60 -0
- infrahub/core/schema/definitions/core/generator.py +96 -0
- infrahub/core/schema/definitions/core/graphql_query.py +77 -0
- infrahub/core/schema/definitions/core/group.py +105 -0
- infrahub/core/schema/definitions/core/ipam.py +252 -0
- infrahub/core/schema/definitions/core/lineage.py +17 -0
- infrahub/core/schema/definitions/core/menu.py +46 -0
- infrahub/core/schema/definitions/core/permission.py +161 -0
- infrahub/core/schema/definitions/core/profile.py +29 -0
- infrahub/core/schema/definitions/core/propose_change.py +88 -0
- infrahub/core/schema/definitions/core/propose_change_comment.py +188 -0
- infrahub/core/schema/definitions/core/propose_change_validator.py +326 -0
- infrahub/core/schema/definitions/core/repository.py +280 -0
- infrahub/core/schema/definitions/core/resource_pool.py +180 -0
- infrahub/core/schema/definitions/core/template.py +12 -0
- infrahub/core/schema/definitions/core/transform.py +87 -0
- infrahub/core/schema/definitions/core/webhook.py +108 -0
- infrahub/core/schema/definitions/internal.py +16 -0
- infrahub/core/schema/generated/genericnode_schema.py +5 -0
- infrahub/core/schema/generated/node_schema.py +5 -0
- infrahub/core/schema/generic_schema.py +5 -1
- infrahub/core/schema/manager.py +45 -42
- infrahub/core/schema/node_schema.py +4 -0
- infrahub/core/schema/profile_schema.py +4 -0
- infrahub/core/schema/relationship_schema.py +10 -2
- infrahub/core/schema/schema_branch.py +260 -16
- infrahub/core/schema/template_schema.py +36 -0
- infrahub/core/task/user_task.py +7 -5
- infrahub/core/timestamp.py +3 -3
- infrahub/core/utils.py +3 -2
- 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/optional.py +1 -1
- infrahub/core/validators/attribute/regex.py +1 -1
- infrahub/core/validators/attribute/unique.py +1 -1
- infrahub/core/validators/checks_runner.py +37 -0
- infrahub/core/validators/node/generate_profile.py +1 -1
- infrahub/core/validators/node/hierarchy.py +1 -1
- infrahub/core/validators/query.py +1 -1
- infrahub/core/validators/relationship/count.py +1 -1
- infrahub/core/validators/relationship/optional.py +1 -1
- infrahub/core/validators/relationship/peer.py +1 -1
- infrahub/core/validators/tasks.py +8 -6
- infrahub/core/validators/uniqueness/query.py +20 -17
- infrahub/database/__init__.py +16 -2
- infrahub/database/memgraph.py +1 -1
- infrahub/dependencies/builder/constraint/grouped/node_runner.py +0 -2
- infrahub/dependencies/builder/diff/combiner.py +1 -1
- infrahub/dependencies/builder/diff/conflicts_enricher.py +1 -1
- infrahub/dependencies/builder/diff/coordinator.py +0 -2
- infrahub/dependencies/builder/diff/deserializer.py +4 -2
- infrahub/dependencies/builder/diff/enricher/hierarchy.py +3 -1
- infrahub/dependencies/builder/diff/enricher/summary_counts.py +1 -1
- infrahub/dependencies/builder/diff/parent_node_adder.py +8 -0
- infrahub/events/artifact_action.py +76 -0
- infrahub/events/branch_action.py +50 -21
- infrahub/events/group_action.py +117 -0
- infrahub/events/models.py +164 -51
- infrahub/events/node_action.py +70 -8
- infrahub/events/repository_action.py +8 -8
- infrahub/events/schema_action.py +21 -8
- infrahub/exceptions.py +9 -0
- infrahub/generators/models.py +1 -0
- infrahub/generators/tasks.py +34 -15
- infrahub/git/base.py +3 -5
- infrahub/git/constants.py +0 -1
- infrahub/git/integrator.py +60 -36
- infrahub/git/models.py +80 -1
- infrahub/git/repository.py +7 -8
- infrahub/git/tasks.py +432 -112
- infrahub/git_credential/helper.py +2 -3
- infrahub/graphql/analyzer.py +572 -11
- infrahub/graphql/app.py +34 -26
- infrahub/graphql/auth/query_permission_checker/anonymous_checker.py +5 -5
- infrahub/graphql/auth/query_permission_checker/default_branch_checker.py +4 -4
- infrahub/graphql/auth/query_permission_checker/merge_operation_checker.py +4 -4
- infrahub/graphql/auth/query_permission_checker/object_permission_checker.py +28 -35
- infrahub/graphql/auth/query_permission_checker/super_admin_checker.py +5 -5
- infrahub/graphql/context.py +33 -0
- infrahub/graphql/enums.py +1 -1
- infrahub/graphql/initialization.py +5 -1
- infrahub/graphql/loaders/node.py +2 -2
- infrahub/graphql/manager.py +63 -63
- infrahub/graphql/mutations/account.py +20 -13
- infrahub/graphql/mutations/artifact_definition.py +16 -12
- infrahub/graphql/mutations/branch.py +86 -40
- infrahub/graphql/mutations/computed_attribute.py +24 -13
- infrahub/graphql/mutations/diff.py +54 -14
- infrahub/graphql/mutations/diff_conflict.py +14 -8
- infrahub/graphql/mutations/generator.py +83 -0
- infrahub/graphql/mutations/graphql_query.py +19 -11
- infrahub/graphql/mutations/ipam.py +25 -23
- infrahub/graphql/mutations/main.py +243 -50
- infrahub/graphql/mutations/menu.py +10 -10
- infrahub/graphql/mutations/proposed_change.py +36 -28
- infrahub/graphql/mutations/relationship.py +343 -104
- infrahub/graphql/mutations/repository.py +41 -35
- infrahub/graphql/mutations/resource_manager.py +26 -26
- infrahub/graphql/mutations/schema.py +66 -33
- infrahub/graphql/mutations/tasks.py +16 -10
- infrahub/graphql/parser.py +1 -1
- infrahub/graphql/permissions.py +3 -10
- infrahub/graphql/queries/account.py +22 -18
- infrahub/graphql/queries/branch.py +6 -4
- infrahub/graphql/queries/diff/tree.py +63 -52
- infrahub/graphql/queries/event.py +115 -0
- infrahub/graphql/queries/internal.py +3 -3
- infrahub/graphql/queries/ipam.py +23 -18
- infrahub/graphql/queries/relationship.py +11 -10
- infrahub/graphql/queries/resource_manager.py +43 -27
- infrahub/graphql/queries/search.py +9 -8
- infrahub/graphql/queries/status.py +12 -9
- infrahub/graphql/queries/task.py +11 -9
- infrahub/graphql/resolvers/resolver.py +69 -43
- infrahub/graphql/resolvers/single_relationship.py +16 -10
- infrahub/graphql/schema.py +4 -0
- infrahub/graphql/subscription/__init__.py +1 -1
- infrahub/graphql/subscription/events.py +1 -1
- infrahub/graphql/subscription/graphql_query.py +8 -8
- infrahub/graphql/types/branch.py +2 -2
- infrahub/graphql/types/common.py +6 -1
- infrahub/graphql/types/context.py +12 -0
- infrahub/graphql/types/enums.py +2 -0
- infrahub/graphql/types/event.py +158 -0
- infrahub/graphql/types/interface.py +2 -2
- infrahub/graphql/types/node.py +3 -3
- infrahub/graphql/types/permission.py +2 -2
- infrahub/graphql/types/relationship.py +3 -3
- infrahub/graphql/types/standard_node.py +9 -11
- infrahub/graphql/utils.py +28 -182
- infrahub/groups/tasks.py +2 -3
- infrahub/lock.py +21 -21
- infrahub/menu/generator.py +0 -1
- infrahub/menu/menu.py +116 -138
- infrahub/menu/models.py +4 -4
- infrahub/message_bus/__init__.py +11 -13
- infrahub/message_bus/messages/__init__.py +0 -14
- infrahub/message_bus/messages/check_generator_run.py +1 -3
- infrahub/message_bus/messages/event_branch_merge.py +3 -0
- infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +6 -0
- infrahub/message_bus/messages/request_proposedchange_pipeline.py +2 -0
- infrahub/message_bus/messages/send_echo_request.py +1 -1
- infrahub/message_bus/operations/__init__.py +4 -13
- infrahub/message_bus/operations/check/__init__.py +2 -2
- infrahub/message_bus/operations/check/generator.py +1 -3
- infrahub/message_bus/operations/event/branch.py +7 -3
- infrahub/message_bus/operations/event/schema.py +1 -1
- infrahub/message_bus/operations/event/worker.py +0 -3
- infrahub/message_bus/operations/finalize/validator.py +1 -1
- infrahub/message_bus/operations/git/file.py +2 -2
- infrahub/message_bus/operations/git/repository.py +1 -1
- infrahub/message_bus/operations/requests/__init__.py +0 -4
- infrahub/message_bus/operations/requests/generator_definition.py +2 -4
- infrahub/message_bus/operations/requests/proposed_change.py +37 -20
- infrahub/message_bus/operations/send/echo.py +1 -1
- infrahub/message_bus/types.py +1 -1
- infrahub/permissions/__init__.py +2 -1
- infrahub/permissions/globals.py +15 -0
- infrahub/permissions/types.py +26 -0
- infrahub/pools/prefix.py +29 -165
- infrahub/prefect_server/__init__.py +0 -0
- infrahub/prefect_server/app.py +18 -0
- infrahub/prefect_server/database.py +20 -0
- infrahub/prefect_server/events.py +28 -0
- infrahub/prefect_server/models.py +46 -0
- infrahub/proposed_change/models.py +18 -1
- infrahub/proposed_change/tasks.py +195 -53
- infrahub/pytest_plugin.py +4 -4
- infrahub/server.py +13 -12
- infrahub/services/__init__.py +148 -63
- infrahub/services/adapters/cache/__init__.py +11 -11
- infrahub/services/adapters/cache/nats.py +42 -25
- infrahub/services/adapters/cache/redis.py +3 -11
- infrahub/services/adapters/event/__init__.py +10 -18
- infrahub/services/adapters/http/__init__.py +0 -5
- infrahub/services/adapters/http/httpx.py +22 -15
- infrahub/services/adapters/message_bus/__init__.py +25 -8
- infrahub/services/adapters/message_bus/local.py +9 -7
- infrahub/services/adapters/message_bus/nats.py +14 -8
- infrahub/services/adapters/message_bus/rabbitmq.py +23 -10
- infrahub/services/adapters/workflow/__init__.py +11 -8
- infrahub/services/adapters/workflow/local.py +27 -6
- infrahub/services/adapters/workflow/worker.py +23 -7
- infrahub/services/component.py +43 -40
- infrahub/services/protocols.py +7 -7
- infrahub/services/scheduler.py +30 -29
- infrahub/storage.py +2 -4
- infrahub/task_manager/constants.py +1 -1
- infrahub/task_manager/event.py +261 -0
- infrahub/task_manager/models.py +147 -3
- infrahub/task_manager/task.py +1 -1
- infrahub/tasks/artifact.py +19 -18
- infrahub/tasks/registry.py +1 -1
- infrahub/tasks/telemetry.py +13 -14
- infrahub/transformations/tasks.py +3 -5
- infrahub/trigger/__init__.py +0 -0
- infrahub/trigger/catalogue.py +16 -0
- infrahub/trigger/constants.py +9 -0
- infrahub/trigger/models.py +105 -0
- infrahub/trigger/tasks.py +91 -0
- infrahub/types.py +1 -1
- infrahub/utils.py +1 -1
- infrahub/webhook/constants.py +0 -2
- infrahub/webhook/models.py +161 -40
- infrahub/webhook/tasks.py +123 -202
- infrahub/webhook/triggers.py +27 -0
- infrahub/workers/infrahub_async.py +36 -25
- infrahub/workers/utils.py +63 -0
- infrahub/workflows/catalogue.py +71 -52
- infrahub/workflows/initialization.py +14 -8
- infrahub/workflows/models.py +28 -4
- infrahub/workflows/utils.py +1 -1
- infrahub_sdk/client.py +8 -0
- infrahub_sdk/ctl/branch.py +3 -2
- infrahub_sdk/ctl/check.py +3 -3
- infrahub_sdk/ctl/cli_commands.py +16 -11
- infrahub_sdk/ctl/exceptions.py +0 -6
- infrahub_sdk/ctl/exporter.py +1 -1
- infrahub_sdk/ctl/generator.py +5 -5
- infrahub_sdk/ctl/importer.py +3 -2
- infrahub_sdk/ctl/menu.py +1 -1
- infrahub_sdk/ctl/object.py +1 -1
- infrahub_sdk/ctl/repository.py +23 -15
- infrahub_sdk/ctl/schema.py +2 -2
- infrahub_sdk/ctl/utils.py +4 -19
- infrahub_sdk/ctl/validate.py +2 -1
- infrahub_sdk/exceptions.py +12 -0
- infrahub_sdk/generator.py +3 -0
- infrahub_sdk/node.py +4 -4
- infrahub_sdk/protocols.py +21 -8
- infrahub_sdk/schema/__init__.py +14 -2
- infrahub_sdk/schema/main.py +7 -0
- infrahub_sdk/task/__init__.py +1 -0
- infrahub_sdk/task/constants.py +3 -0
- infrahub_sdk/task/exceptions.py +25 -0
- infrahub_sdk/task/manager.py +545 -0
- infrahub_sdk/task/models.py +74 -0
- infrahub_sdk/timestamp.py +134 -33
- infrahub_sdk/utils.py +39 -1
- infrahub_sdk/yaml.py +2 -3
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0b1.dist-info}/METADATA +47 -12
- infrahub_server-1.2.0b1.dist-info/RECORD +725 -0
- infrahub_testcontainers/container.py +14 -6
- infrahub_testcontainers/docker-compose.test.yml +24 -5
- infrahub_testcontainers/haproxy.cfg +43 -0
- infrahub_testcontainers/helpers.py +85 -1
- infrahub/core/branch/constants.py +0 -2
- infrahub/core/schema/definitions/core.py +0 -2274
- infrahub/graphql/query.py +0 -52
- infrahub/message_bus/messages/check_repository_checkdefinition.py +0 -20
- infrahub/message_bus/messages/check_repository_mergeconflicts.py +0 -16
- infrahub/message_bus/messages/check_repository_usercheck.py +0 -26
- infrahub/message_bus/messages/request_artifactdefinition_check.py +0 -17
- infrahub/message_bus/messages/request_repository_checks.py +0 -12
- infrahub/message_bus/messages/request_repository_userchecks.py +0 -18
- infrahub/message_bus/operations/check/repository.py +0 -293
- infrahub/message_bus/operations/requests/artifact_definition.py +0 -148
- infrahub/message_bus/operations/requests/repository.py +0 -133
- infrahub/schema/constants.py +0 -1
- infrahub/schema/tasks.py +0 -76
- infrahub/services/adapters/database/__init__.py +0 -9
- infrahub_sdk/ctl/_file.py +0 -13
- infrahub_server-1.1.6.dist-info/RECORD +0 -681
- /infrahub/{schema → artifacts}/__init__.py +0 -0
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0b1.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0b1.dist-info}/WHEEL +0 -0
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0b1.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any, Sequence
|
|
4
|
+
|
|
5
|
+
from infrahub.core.migrations.shared import GraphMigration, MigrationResult
|
|
6
|
+
from infrahub.log import get_logger
|
|
7
|
+
|
|
8
|
+
from ...constants import GLOBAL_BRANCH_NAME, BranchSupportType
|
|
9
|
+
from ...query import Query, QueryType
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from infrahub.database import InfrahubDatabase
|
|
13
|
+
|
|
14
|
+
log = get_logger()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class FixBranchAwareEdgesQuery(Query):
|
|
18
|
+
name = "replace_global_edges"
|
|
19
|
+
type = QueryType.WRITE
|
|
20
|
+
insert_return = False
|
|
21
|
+
|
|
22
|
+
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
|
|
23
|
+
"""
|
|
24
|
+
Between a Node and a Relationship, if Relationship.branch_support=aware, replace any global edge
|
|
25
|
+
to the branch of a non-global edge leaving out of the Relationship node. Note that there can't
|
|
26
|
+
be multiple non-global branches on these edges, as a dedicated Relationship node would exist for that.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
query = """
|
|
30
|
+
MATCH (node:Node)-[global_edge:IS_RELATED {branch: $global_branch}]-(rel:Relationship)
|
|
31
|
+
WHERE rel.branch_support=$branch_aware
|
|
32
|
+
MATCH (rel)-[non_global_edge:IS_RELATED]-(node_2: Node)
|
|
33
|
+
WHERE non_global_edge.branch <> $global_branch
|
|
34
|
+
SET global_edge.branch = non_global_edge.branch
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
params = {
|
|
38
|
+
"global_branch": GLOBAL_BRANCH_NAME,
|
|
39
|
+
"branch_aware": BranchSupportType.AWARE.value,
|
|
40
|
+
"branch_agnostic": BranchSupportType.AGNOSTIC.value,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
self.params.update(params)
|
|
44
|
+
self.add_to_query(query)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class SetMissingToTimeQuery(Query):
|
|
48
|
+
name = "set_missing_to_time"
|
|
49
|
+
type = QueryType.WRITE
|
|
50
|
+
insert_return = False
|
|
51
|
+
|
|
52
|
+
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
|
|
53
|
+
"""
|
|
54
|
+
If both a deleted edge and an active edge with no time exist between 2 nodes on the same branch,
|
|
55
|
+
set `to` time of active edge using `from` time of the deleted one. This would typically happen after having
|
|
56
|
+
replaced a deleted edge on global branch by correct branch with above query.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
query = """
|
|
60
|
+
MATCH (node:Node)-[deleted_edge:IS_RELATED {status: "deleted"}]-(rel:Relationship)
|
|
61
|
+
MATCH (rel)-[active_edge:IS_RELATED {status: "active"}]-(node)
|
|
62
|
+
WHERE active_edge.to IS NULL AND deleted_edge.branch = active_edge.branch
|
|
63
|
+
SET active_edge.to = deleted_edge.from
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
self.add_to_query(query)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class DeleteNodesRelsQuery(Query):
|
|
70
|
+
name = "delete_relationships_of_deleted_nodes"
|
|
71
|
+
type = QueryType.WRITE
|
|
72
|
+
insert_return = False
|
|
73
|
+
|
|
74
|
+
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
|
|
75
|
+
"""
|
|
76
|
+
Some nodes may have been incorrectly deleted, typically, while these nodes edges connected to Root
|
|
77
|
+
are correctly deleted, edges connected to other `Node` through a `Relationship` node may still be active.
|
|
78
|
+
Following query correctly deletes these edges by both setting correct to time and creating corresponding deleted edge.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
query = """
|
|
82
|
+
MATCH (deleted_node: Node)-[deleted_edge:IS_PART_OF {status: "deleted"}]->(:Root)
|
|
83
|
+
MATCH (deleted_node)-[:IS_RELATED]-(rel:Relationship)
|
|
84
|
+
|
|
85
|
+
// exclude nodes having been deleted through migration. find those with same uuid and exclude the one with earlier
|
|
86
|
+
// timestamp on active branch
|
|
87
|
+
WHERE NOT EXISTS {
|
|
88
|
+
MATCH (deleted_node)-[e1:IS_RELATED]-(rel)-[e2:IS_RELATED]-(other_node)
|
|
89
|
+
WITH deleted_node, other_node, MIN(e1.from) AS min_e1_from, MIN(e2.from) AS min_e2_from
|
|
90
|
+
WHERE deleted_node <> other_node AND deleted_node.uuid = other_node.uuid AND min_e1_from < min_e2_from
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Note that if an AWARE node has been deleted on a branch and relationship is AGNOSTIC, we do not "delete" this relationship
|
|
94
|
+
// right now as this aware node might exist on another branch.
|
|
95
|
+
|
|
96
|
+
// Set to time if there is an active edge:
|
|
97
|
+
// - on deleted edge branch
|
|
98
|
+
// - or on any branch and deleted node is agnostic
|
|
99
|
+
// - or deleted node is aware and rel is agnostic
|
|
100
|
+
CALL {
|
|
101
|
+
WITH rel, deleted_edge
|
|
102
|
+
OPTIONAL MATCH (rel)-[peer_active_edge {status: "active"}]-(peer_1)
|
|
103
|
+
WHERE (peer_active_edge.branch = deleted_edge.branch OR (rel.branch_support <> $branch_agnostic AND deleted_edge.branch = $global_branch))
|
|
104
|
+
AND peer_active_edge.to IS NULL
|
|
105
|
+
SET peer_active_edge.to = deleted_edge.from
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Get distinct rel nodes linked to a deleted node, with the time at which we should delete rel edges.
|
|
109
|
+
// Take the MAX time so if it does not take the deleted time of a node deleted through a duplication migration.
|
|
110
|
+
WITH DISTINCT rel,
|
|
111
|
+
deleted_edge.branch AS deleted_edge_branch,
|
|
112
|
+
deleted_edge.branch_level AS branch_level,
|
|
113
|
+
MAX(deleted_edge.from) as deleted_time,
|
|
114
|
+
deleted_node.branch_support as deleted_node_branch_support
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
// No need to check deleted edge branch because
|
|
118
|
+
// If deleted_node has different branch support type (agnostic/aware) than rel type,
|
|
119
|
+
// there might already be a deleted edge that we would not match if we filter on deleted_edge_branch.
|
|
120
|
+
// If both are aware, it still works, as we would have one Relationship node for each branch on which this relationship exists.
|
|
121
|
+
MATCH (rel)-[]-(peer_2)
|
|
122
|
+
WHERE NOT exists((rel)-[{status: "deleted"}]-(peer_2))
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
// If res is agnostic and delete node is agnostic, we should delete on global branch
|
|
126
|
+
// If rel is aware and deleted node is aware, we should use deleted edge branch
|
|
127
|
+
// If rel is aware and delete node is agnostic, we need to create deleted edges for every distinct branch on which this relationship exists.
|
|
128
|
+
WITH DISTINCT
|
|
129
|
+
CASE
|
|
130
|
+
// Branch on which `deleted` edge should be created depends on rel.branch_support.
|
|
131
|
+
WHEN rel.branch_support = $branch_agnostic
|
|
132
|
+
THEN CASE
|
|
133
|
+
WHEN deleted_node_branch_support = $branch_agnostic THEN [$global_branch]
|
|
134
|
+
ELSE []
|
|
135
|
+
END
|
|
136
|
+
ELSE
|
|
137
|
+
CASE
|
|
138
|
+
WHEN deleted_node_branch_support = $branch_agnostic
|
|
139
|
+
THEN COLLECT {
|
|
140
|
+
WITH rel
|
|
141
|
+
MATCH (rel)-[active_edge {status: "active"}]-(peer_2)
|
|
142
|
+
RETURN DISTINCT active_edge.branch
|
|
143
|
+
}
|
|
144
|
+
ELSE
|
|
145
|
+
CASE
|
|
146
|
+
// if no active edge on this branch exists it means this relationship node is dedicated for another branch
|
|
147
|
+
WHEN exists((rel)-[{status: "active", branch: deleted_edge_branch}]-(peer_2)) THEN [deleted_edge_branch]
|
|
148
|
+
ELSE []
|
|
149
|
+
END
|
|
150
|
+
END
|
|
151
|
+
END AS branches,
|
|
152
|
+
branch_level,
|
|
153
|
+
deleted_time,
|
|
154
|
+
peer_2,
|
|
155
|
+
rel
|
|
156
|
+
|
|
157
|
+
UNWIND branches as branch
|
|
158
|
+
|
|
159
|
+
// Then creates `deleted` edge.
|
|
160
|
+
// Below CALL subqueries are called once for each rel-peer_2 pair for which we want to create a deleted edge.
|
|
161
|
+
// Note that with current infrahub relationships edges design, only one of this CALL should be matched per pair.
|
|
162
|
+
|
|
163
|
+
CALL {
|
|
164
|
+
WITH rel, peer_2, branch, branch_level, deleted_time
|
|
165
|
+
MATCH (rel)-[:IS_RELATED]->(peer_2)
|
|
166
|
+
MERGE (rel)-[:IS_RELATED {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]->(peer_2)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
CALL {
|
|
170
|
+
WITH rel, peer_2, branch, branch_level, deleted_time
|
|
171
|
+
MATCH (rel)-[:IS_PROTECTED]->(peer_2)
|
|
172
|
+
MERGE (rel)-[:IS_PROTECTED {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]->(peer_2)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
CALL {
|
|
176
|
+
WITH rel, peer_2, branch, branch_level, deleted_time
|
|
177
|
+
MATCH (rel)-[:IS_VISIBLE]->(peer_2)
|
|
178
|
+
MERGE (rel)-[:IS_VISIBLE {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]->(peer_2)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
CALL {
|
|
182
|
+
WITH rel, peer_2, branch, branch_level, deleted_time
|
|
183
|
+
MATCH (rel)-[:HAS_OWNER]->(peer_2)
|
|
184
|
+
MERGE (rel)-[:HAS_OWNER {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]->(peer_2)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
CALL {
|
|
188
|
+
WITH rel, peer_2, branch, branch_level, deleted_time
|
|
189
|
+
MATCH (rel)-[:HAS_SOURCE]->(peer_2)
|
|
190
|
+
MERGE (rel)-[:HAS_SOURCE {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]->(peer_2)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
CALL {
|
|
194
|
+
WITH rel, peer_2, branch, branch_level, deleted_time
|
|
195
|
+
MATCH (rel)<-[:IS_RELATED]-(peer_2)
|
|
196
|
+
MERGE (rel)<-[:IS_RELATED {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]-(peer_2)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
CALL {
|
|
200
|
+
WITH rel, peer_2, branch, branch_level, deleted_time
|
|
201
|
+
MATCH (rel)<-[:IS_PROTECTED]-(peer_2)
|
|
202
|
+
MERGE (rel)<-[:IS_PROTECTED {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]-(peer_2)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
CALL {
|
|
206
|
+
WITH rel, peer_2, branch, branch_level, deleted_time
|
|
207
|
+
MATCH (rel)<-[:IS_VISIBLE]-(peer_2)
|
|
208
|
+
MERGE (rel)<-[:IS_VISIBLE {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]-(peer_2)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
CALL {
|
|
212
|
+
WITH rel, peer_2, branch, branch_level, deleted_time
|
|
213
|
+
MATCH (rel)<-[:HAS_OWNER]-(peer_2)
|
|
214
|
+
MERGE (rel)<-[:HAS_OWNER {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]-(peer_2)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
CALL {
|
|
218
|
+
WITH rel, peer_2, branch, branch_level, deleted_time
|
|
219
|
+
MATCH (rel)<-[:HAS_SOURCE]-(peer_2)
|
|
220
|
+
MERGE (rel)<-[:HAS_SOURCE {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]-(peer_2)
|
|
221
|
+
}
|
|
222
|
+
"""
|
|
223
|
+
|
|
224
|
+
params = {
|
|
225
|
+
"global_branch": GLOBAL_BRANCH_NAME,
|
|
226
|
+
"branch_aware": BranchSupportType.AWARE.value,
|
|
227
|
+
"branch_agnostic": BranchSupportType.AGNOSTIC.value,
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
self.params.update(params)
|
|
231
|
+
self.add_to_query(query)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class Migration019(GraphMigration):
|
|
235
|
+
"""
|
|
236
|
+
Fix corrupted state introduced by Migration012 when duplicating a CoreAccount (branch Aware)
|
|
237
|
+
being part of a CoreStandardGroup (branch Agnostic). Database is corrupted at multiple points:
|
|
238
|
+
- Old CoreAccount node <> group_member node `active` edge has no `to` time (possibly because of #5590).
|
|
239
|
+
- Old CoreAccount node <> group_member node `deleted` edge is on `$global_branch` branch instead of `main`.
|
|
240
|
+
- New CoreAccount node <> group_member node `active` edge is on `$global_branch` branch instead of `main`.
|
|
241
|
+
|
|
242
|
+
Also, users having deleted corresponding CoreStandardGroup will also have the following data corruption,
|
|
243
|
+
as deletion did not happen correctly due to above issues:
|
|
244
|
+
- Both CoreAccount <> group_member and CoreStandardGroup <> group_member edges
|
|
245
|
+
have not been deleted (ie status is `active` without `to` time and no additional `deleted` edge).
|
|
246
|
+
|
|
247
|
+
This migration fixes all above issues to have consistent edges, and fixes IFC-1204.
|
|
248
|
+
"""
|
|
249
|
+
|
|
250
|
+
name: str = "019_fix_edges_state"
|
|
251
|
+
minimum_version: int = 18
|
|
252
|
+
queries: Sequence[type[Query]] = [FixBranchAwareEdgesQuery, SetMissingToTimeQuery, DeleteNodesRelsQuery]
|
|
253
|
+
|
|
254
|
+
async def validate_migration(self, db: InfrahubDatabase) -> MigrationResult: # noqa: ARG002
|
|
255
|
+
result = MigrationResult()
|
|
256
|
+
return result
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
|
+
|
|
5
|
+
from typing_extensions import Self
|
|
6
|
+
|
|
7
|
+
from infrahub.core.constants import SchemaPathType
|
|
8
|
+
from infrahub.core.migrations.shared import MigrationResult
|
|
9
|
+
from infrahub.core.path import SchemaPath
|
|
10
|
+
|
|
11
|
+
from ..schema.node_attribute_add import NodeAttributeAddMigration
|
|
12
|
+
from ..shared import InternalSchemaMigration
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from infrahub.database import InfrahubDatabase
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Migration020(InternalSchemaMigration):
|
|
19
|
+
name: str = "020_add_generate_template_attr"
|
|
20
|
+
minimum_version: int = 19
|
|
21
|
+
|
|
22
|
+
@classmethod
|
|
23
|
+
def init(cls, **kwargs: dict[str, Any]) -> Self:
|
|
24
|
+
internal_schema = cls.get_internal_schema()
|
|
25
|
+
schema_node = internal_schema.get_node(name="SchemaNode")
|
|
26
|
+
schema_generic = internal_schema.get_node(name="SchemaGeneric")
|
|
27
|
+
|
|
28
|
+
migrations = [
|
|
29
|
+
NodeAttributeAddMigration(
|
|
30
|
+
new_node_schema=schema_node,
|
|
31
|
+
previous_node_schema=schema_node,
|
|
32
|
+
schema_path=SchemaPath(
|
|
33
|
+
schema_kind="SchemaNode", path_type=SchemaPathType.ATTRIBUTE, field_name="generate_template"
|
|
34
|
+
),
|
|
35
|
+
),
|
|
36
|
+
NodeAttributeAddMigration(
|
|
37
|
+
new_node_schema=schema_generic,
|
|
38
|
+
previous_node_schema=schema_generic,
|
|
39
|
+
schema_path=SchemaPath(
|
|
40
|
+
schema_kind="SchemaNode", path_type=SchemaPathType.ATTRIBUTE, field_name="generate_template"
|
|
41
|
+
),
|
|
42
|
+
),
|
|
43
|
+
]
|
|
44
|
+
return cls(migrations=migrations, **kwargs) # type: ignore[arg-type]
|
|
45
|
+
|
|
46
|
+
async def validate_migration(self, db: InfrahubDatabase) -> MigrationResult: # noqa: ARG002
|
|
47
|
+
result = MigrationResult()
|
|
48
|
+
return result
|
|
@@ -30,7 +30,7 @@ class AttributeAddQuery(Query):
|
|
|
30
30
|
|
|
31
31
|
super().__init__(**kwargs)
|
|
32
32
|
|
|
33
|
-
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None:
|
|
33
|
+
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
|
|
34
34
|
branch_filter, branch_params = self.branch.get_query_filter_path(at=self.at.to_string())
|
|
35
35
|
self.params.update(branch_params)
|
|
36
36
|
|
|
@@ -86,7 +86,7 @@ class AttributeRenameQuery(Query):
|
|
|
86
86
|
subquery.append("RETURN peer_node as p2")
|
|
87
87
|
return "\n".join(subquery)
|
|
88
88
|
|
|
89
|
-
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None:
|
|
89
|
+
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
|
|
90
90
|
branch_filter, branch_params = self.branch.get_query_filter_path(at=self.at.to_string())
|
|
91
91
|
self.params.update(branch_params)
|
|
92
92
|
|
|
@@ -90,7 +90,7 @@ class DeleteElementInSchemaQuery(Query):
|
|
|
90
90
|
sub_query_in = "\nUNION\n".join(sub_queries_in)
|
|
91
91
|
return sub_query_in
|
|
92
92
|
|
|
93
|
-
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None:
|
|
93
|
+
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
|
|
94
94
|
branch_filter, branch_params = self.branch.get_query_filter_path(at=self.at.to_string())
|
|
95
95
|
self.params.update(branch_params)
|
|
96
96
|
|
|
@@ -48,19 +48,37 @@ class NodeDuplicateQuery(Query):
|
|
|
48
48
|
|
|
49
49
|
@staticmethod
|
|
50
50
|
def _render_sub_query_per_rel_type(
|
|
51
|
-
rel_name: str,
|
|
51
|
+
rel_name: str,
|
|
52
|
+
rel_type: str,
|
|
53
|
+
rel_def: FieldInfo,
|
|
52
54
|
) -> str:
|
|
53
55
|
subquery = [
|
|
54
56
|
f"WITH peer_node, {rel_name}, active_node, new_node",
|
|
55
57
|
f"WITH peer_node, {rel_name}, active_node, new_node",
|
|
56
58
|
f'WHERE type({rel_name}) = "{rel_type}"',
|
|
57
59
|
]
|
|
58
|
-
if rel_def.default.direction in [
|
|
59
|
-
subquery.append(f"
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
if rel_def.default.direction in [GraphRelDirection.OUTBOUND, GraphRelDirection.EITHER]:
|
|
61
|
+
subquery.append(f"""
|
|
62
|
+
CREATE (new_node)-[new_active_edge:{rel_type} $rel_props_new ]->(peer_node)
|
|
63
|
+
SET new_active_edge.branch = CASE WHEN {rel_name}.branch = "-global-" THEN "-global-" ELSE $branch END
|
|
64
|
+
SET new_active_edge.branch_level = CASE WHEN {rel_name}.branch = "-global-" THEN {rel_name}.branch_level ELSE $branch_level END
|
|
65
|
+
""")
|
|
66
|
+
subquery.append(f"""
|
|
67
|
+
CREATE (active_node)-[deleted_edge:{rel_type} $rel_props_prev ]->(peer_node)
|
|
68
|
+
SET deleted_edge.branch = CASE WHEN {rel_name}.branch = "-global-" THEN "-global-" ELSE $branch END
|
|
69
|
+
SET deleted_edge.branch_level = CASE WHEN {rel_name}.branch = "-global-" THEN {rel_name}.branch_level ELSE $branch_level END
|
|
70
|
+
""")
|
|
71
|
+
elif rel_def.default.direction in [GraphRelDirection.INBOUND, GraphRelDirection.EITHER]:
|
|
72
|
+
subquery.append(f"""
|
|
73
|
+
CREATE (new_node)<-[new_active_edge:{rel_type} $rel_props_new ]-(peer_node)
|
|
74
|
+
SET new_active_edge.branch = CASE WHEN {rel_name}.branch = "-global-" THEN "-global-" ELSE $branch END
|
|
75
|
+
SET new_active_edge.branch_level = CASE WHEN {rel_name}.branch = "-global-" THEN {rel_name}.branch_level ELSE $branch_level END
|
|
76
|
+
""")
|
|
77
|
+
subquery.append(f"""
|
|
78
|
+
CREATE (active_node)<-[deleted_edge:{rel_type} $rel_props_prev ]-(peer_node)
|
|
79
|
+
SET new_active_edge.branch = CASE WHEN {rel_name}.branch = "-global-" THEN "-global-" ELSE $branch END
|
|
80
|
+
SET new_active_edge.branch_level = CASE WHEN {rel_name}.branch = "-global-" THEN {rel_name}.branch_level ELSE $branch_level END
|
|
81
|
+
""")
|
|
64
82
|
subquery.append("RETURN peer_node as p2")
|
|
65
83
|
return "\n".join(subquery)
|
|
66
84
|
|
|
@@ -68,7 +86,9 @@ class NodeDuplicateQuery(Query):
|
|
|
68
86
|
def _render_sub_query_out(cls) -> str:
|
|
69
87
|
sub_queries_out = [
|
|
70
88
|
cls._render_sub_query_per_rel_type(
|
|
71
|
-
rel_name="rel_outband",
|
|
89
|
+
rel_name="rel_outband",
|
|
90
|
+
rel_type=rel_type,
|
|
91
|
+
rel_def=rel_def,
|
|
72
92
|
)
|
|
73
93
|
for rel_type, rel_def in GraphNodeRelationships.model_fields.items()
|
|
74
94
|
]
|
|
@@ -79,14 +99,16 @@ class NodeDuplicateQuery(Query):
|
|
|
79
99
|
def _render_sub_query_in(cls) -> str:
|
|
80
100
|
sub_queries_in = [
|
|
81
101
|
cls._render_sub_query_per_rel_type(
|
|
82
|
-
rel_name="rel_inband",
|
|
102
|
+
rel_name="rel_inband",
|
|
103
|
+
rel_type=rel_type,
|
|
104
|
+
rel_def=rel_def,
|
|
83
105
|
)
|
|
84
106
|
for rel_type, rel_def in GraphNodeRelationships.model_fields.items()
|
|
85
107
|
]
|
|
86
108
|
sub_query_in = "\nUNION\n".join(sub_queries_in)
|
|
87
109
|
return sub_query_in
|
|
88
110
|
|
|
89
|
-
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None:
|
|
111
|
+
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
|
|
90
112
|
branch_filter, branch_params = self.branch.get_query_filter_path(at=self.at.to_string())
|
|
91
113
|
self.params.update(branch_params)
|
|
92
114
|
|
|
@@ -94,19 +116,16 @@ class NodeDuplicateQuery(Query):
|
|
|
94
116
|
self.params["previous_node"] = self.previous_node.model_dump()
|
|
95
117
|
|
|
96
118
|
self.params["current_time"] = self.at.to_string()
|
|
97
|
-
self.params["
|
|
119
|
+
self.params["branch"] = self.branch.name
|
|
120
|
+
self.params["branch_level"] = self.branch.hierarchy_level
|
|
98
121
|
self.params["branch_support"] = self.new_node.branch_support
|
|
99
122
|
|
|
100
123
|
self.params["rel_props_new"] = {
|
|
101
|
-
"branch": self.branch.name,
|
|
102
|
-
"branch_level": self.branch.hierarchy_level,
|
|
103
124
|
"status": RelationshipStatus.ACTIVE.value,
|
|
104
125
|
"from": self.at.to_string(),
|
|
105
126
|
}
|
|
106
127
|
|
|
107
128
|
self.params["rel_props_prev"] = {
|
|
108
|
-
"branch": self.branch.name,
|
|
109
|
-
"branch_level": self.branch.hierarchy_level,
|
|
110
129
|
"status": RelationshipStatus.DELETED.value,
|
|
111
130
|
"from": self.at.to_string(),
|
|
112
131
|
}
|
|
@@ -141,12 +160,12 @@ class NodeDuplicateQuery(Query):
|
|
|
141
160
|
LIMIT 1
|
|
142
161
|
}
|
|
143
162
|
WITH n1 as active_node, rel_outband1 as rel_outband, p1 as peer_node, new_node
|
|
144
|
-
WHERE rel_outband.status = "active"
|
|
163
|
+
WHERE rel_outband.status = "active" AND rel_outband.to IS NULL
|
|
145
164
|
CALL {
|
|
146
165
|
%(sub_query_out)s
|
|
147
166
|
}
|
|
148
167
|
WITH p2 as peer_node, rel_outband, active_node, new_node
|
|
149
|
-
FOREACH (i in CASE WHEN rel_outband.branch
|
|
168
|
+
FOREACH (i in CASE WHEN rel_outband.branch IN ["-global-", $branch] THEN [1] ELSE [] END |
|
|
150
169
|
SET rel_outband.to = $current_time
|
|
151
170
|
)
|
|
152
171
|
WITH active_node, new_node
|
|
@@ -160,14 +179,15 @@ class NodeDuplicateQuery(Query):
|
|
|
160
179
|
LIMIT 1
|
|
161
180
|
}
|
|
162
181
|
WITH n1 as active_node, rel_inband1 as rel_inband, p1 as peer_node, new_node
|
|
163
|
-
WHERE rel_inband.status = "active"
|
|
182
|
+
WHERE rel_inband.status = "active" AND rel_inband.to IS NULL
|
|
164
183
|
CALL {
|
|
165
184
|
%(sub_query_in)s
|
|
166
185
|
}
|
|
167
186
|
WITH p2 as peer_node, rel_inband, active_node, new_node
|
|
168
|
-
FOREACH (i in CASE WHEN rel_inband.branch
|
|
187
|
+
FOREACH (i in CASE WHEN rel_inband.branch IN ["-global-", $branch] THEN [1] ELSE [] END |
|
|
169
188
|
SET rel_inband.to = $current_time
|
|
170
189
|
)
|
|
190
|
+
|
|
171
191
|
RETURN DISTINCT new_node
|
|
172
192
|
""" % {
|
|
173
193
|
"branch_filter": branch_filter,
|
|
@@ -84,7 +84,7 @@ class RelationshipDuplicateQuery(Query):
|
|
|
84
84
|
sub_query_in = "\nUNION\n".join(sub_queries_in)
|
|
85
85
|
return sub_query_in
|
|
86
86
|
|
|
87
|
-
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None:
|
|
87
|
+
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
|
|
88
88
|
branch_filter, branch_params = self.branch.get_query_filter_path(at=self.at.to_string())
|
|
89
89
|
self.params.update(branch_params)
|
|
90
90
|
|
|
@@ -67,7 +67,7 @@ class SchemaAttributeUpdateQuery(Query):
|
|
|
67
67
|
|
|
68
68
|
return query
|
|
69
69
|
|
|
70
|
-
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None:
|
|
70
|
+
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
|
|
71
71
|
self.params["attr_name"] = self.attr_name
|
|
72
72
|
self.params["attr_new_value"] = (
|
|
73
73
|
ujson.dumps(self.attr_new_value) if isinstance(self.attr_new_value, list) else self.attr_new_value
|
|
@@ -18,7 +18,7 @@ class NodeAttributeRemoveMigrationQuery01(AttributeMigrationQuery):
|
|
|
18
18
|
name = "migration_node_attribute_remove_01"
|
|
19
19
|
insert_return: bool = False
|
|
20
20
|
|
|
21
|
-
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None:
|
|
21
|
+
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
|
|
22
22
|
branch_filter, branch_params = self.branch.get_query_filter_path(at=self.at.to_string())
|
|
23
23
|
self.params.update(branch_params)
|
|
24
24
|
|
|
@@ -15,33 +15,44 @@ if TYPE_CHECKING:
|
|
|
15
15
|
|
|
16
16
|
class NodeRemoveMigrationBaseQuery(MigrationQuery):
|
|
17
17
|
def render_sub_query_per_rel_type(
|
|
18
|
-
self,
|
|
18
|
+
self,
|
|
19
|
+
rel_name: str,
|
|
20
|
+
rel_type: str,
|
|
21
|
+
rel_def: FieldInfo,
|
|
19
22
|
) -> str:
|
|
20
23
|
subquery = [
|
|
21
24
|
f"WITH peer_node, {rel_name}, active_node",
|
|
22
25
|
f"WITH peer_node, {rel_name}, active_node",
|
|
23
26
|
f'WHERE type({rel_name}) = "{rel_type}"',
|
|
24
27
|
]
|
|
25
|
-
if rel_def.default.direction in [
|
|
26
|
-
subquery.append(f"
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
if rel_def.default.direction in [GraphRelDirection.OUTBOUND, GraphRelDirection.EITHER]:
|
|
29
|
+
subquery.append(f"""
|
|
30
|
+
CREATE (active_node)-[edge:{rel_type} $rel_props ]->(peer_node)
|
|
31
|
+
SET edge.branch = CASE WHEN {rel_name}.branch = "-global-" THEN "-global-" ELSE $branch END
|
|
32
|
+
SET edge.branch_level = CASE WHEN {rel_name}.branch = "-global-" THEN {rel_name}.branch_level ELSE $branch_level END
|
|
33
|
+
""")
|
|
34
|
+
elif rel_def.default.direction in [GraphRelDirection.INBOUND, GraphRelDirection.EITHER]:
|
|
35
|
+
subquery.append(f"""
|
|
36
|
+
CREATE (active_node)<-[edge:{rel_type} $rel_props ]-(peer_node)
|
|
37
|
+
SET edge.branch = CASE WHEN {rel_name}.branch = "-global-" THEN "-global-" ELSE $branch END
|
|
38
|
+
SET edge.branch_level = CASE WHEN {rel_name}.branch = "-global-" THEN {rel_name}.branch_level ELSE $branch_level END
|
|
39
|
+
""")
|
|
29
40
|
subquery.append("RETURN peer_node as p2")
|
|
30
41
|
return "\n".join(subquery)
|
|
31
42
|
|
|
32
43
|
def render_node_remove_query(self, branch_filter: str) -> str:
|
|
33
44
|
raise NotImplementedError()
|
|
34
45
|
|
|
35
|
-
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None:
|
|
46
|
+
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
|
|
36
47
|
branch_filter, branch_params = self.branch.get_query_filter_path(at=self.at.to_string())
|
|
37
48
|
self.params.update(branch_params)
|
|
38
49
|
|
|
39
50
|
self.params["current_time"] = self.at.to_string()
|
|
40
51
|
self.params["branch_name"] = self.branch.name
|
|
52
|
+
self.params["branch"] = self.branch.name
|
|
53
|
+
self.params["branch_level"] = self.branch.hierarchy_level
|
|
41
54
|
|
|
42
55
|
self.params["rel_props"] = {
|
|
43
|
-
"branch": self.branch.name,
|
|
44
|
-
"branch_level": self.branch.hierarchy_level,
|
|
45
56
|
"status": RelationshipStatus.DELETED.value,
|
|
46
57
|
"from": self.at.to_string(),
|
|
47
58
|
}
|
|
@@ -99,7 +110,7 @@ class NodeRemoveMigrationQueryIn(NodeRemoveMigrationBaseQuery):
|
|
|
99
110
|
%(sub_query)s
|
|
100
111
|
}
|
|
101
112
|
WITH p2 as peer_node, rel_inband, active_node
|
|
102
|
-
FOREACH (i in CASE WHEN rel_inband.branch
|
|
113
|
+
FOREACH (i in CASE WHEN rel_inband.branch IN ["-global-", $branch] THEN [1] ELSE [] END |
|
|
103
114
|
SET rel_inband.to = $current_time
|
|
104
115
|
)
|
|
105
116
|
""" % {"sub_query": sub_query, "branch_filter": branch_filter}
|
|
@@ -108,7 +119,9 @@ class NodeRemoveMigrationQueryIn(NodeRemoveMigrationBaseQuery):
|
|
|
108
119
|
def render_sub_query_in(self) -> str:
|
|
109
120
|
sub_queries_in = [
|
|
110
121
|
self.render_sub_query_per_rel_type(
|
|
111
|
-
rel_name="rel_inband",
|
|
122
|
+
rel_name="rel_inband",
|
|
123
|
+
rel_type=rel_type,
|
|
124
|
+
rel_def=rel_def,
|
|
112
125
|
)
|
|
113
126
|
for rel_type, rel_def in GraphNodeRelationships.model_fields.items()
|
|
114
127
|
]
|
|
@@ -142,8 +155,7 @@ class NodeRemoveMigrationQueryOut(NodeRemoveMigrationBaseQuery):
|
|
|
142
155
|
CALL {
|
|
143
156
|
%(sub_query)s
|
|
144
157
|
}
|
|
145
|
-
|
|
146
|
-
FOREACH (i in CASE WHEN rel_outband.branch = $branch_name THEN [1] ELSE [] END |
|
|
158
|
+
FOREACH (i in CASE WHEN rel_outband.branch IN ["-global-", $branch] THEN [1] ELSE [] END |
|
|
147
159
|
SET rel_outband.to = $current_time
|
|
148
160
|
)
|
|
149
161
|
""" % {"sub_query": sub_query, "branch_filter": branch_filter}
|
|
@@ -153,7 +165,9 @@ class NodeRemoveMigrationQueryOut(NodeRemoveMigrationBaseQuery):
|
|
|
153
165
|
def render_sub_query_out(self) -> str:
|
|
154
166
|
sub_queries_out = [
|
|
155
167
|
self.render_sub_query_per_rel_type(
|
|
156
|
-
rel_name="rel_outband",
|
|
168
|
+
rel_name="rel_outband",
|
|
169
|
+
rel_type=rel_type,
|
|
170
|
+
rel_def=rel_def,
|
|
157
171
|
)
|
|
158
172
|
for rel_type, rel_def in GraphNodeRelationships.model_fields.items()
|
|
159
173
|
]
|
|
@@ -10,7 +10,7 @@ from prefect.logging import get_run_logger
|
|
|
10
10
|
from infrahub.core.branch import Branch # noqa: TC001
|
|
11
11
|
from infrahub.core.migrations import MIGRATION_MAP
|
|
12
12
|
from infrahub.core.path import SchemaPath # noqa: TC001
|
|
13
|
-
from infrahub.services import
|
|
13
|
+
from infrahub.services import InfrahubServices # noqa: TC001 needed for prefect flow
|
|
14
14
|
from infrahub.workflows.utils import add_branch_tag
|
|
15
15
|
|
|
16
16
|
from .models import SchemaApplyMigrationData, SchemaMigrationPathResponseData
|
|
@@ -20,7 +20,7 @@ if TYPE_CHECKING:
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
@flow(name="schema_apply_migrations", flow_run_name="Apply schema migrations", persist_result=True)
|
|
23
|
-
async def schema_apply_migrations(message: SchemaApplyMigrationData) -> list[str]:
|
|
23
|
+
async def schema_apply_migrations(message: SchemaApplyMigrationData, service: InfrahubServices) -> list[str]:
|
|
24
24
|
await add_branch_tag(branch_name=message.branch.name)
|
|
25
25
|
log = get_run_logger()
|
|
26
26
|
|
|
@@ -34,7 +34,6 @@ async def schema_apply_migrations(message: SchemaApplyMigrationData) -> list[str
|
|
|
34
34
|
log.info(f"Preparing migration for {migration.migration_name!r} ({migration.routing_key})")
|
|
35
35
|
|
|
36
36
|
new_node_schema: Optional[MainSchemaTypes] = None
|
|
37
|
-
previous_node_schema: Optional[MainSchemaTypes] = None
|
|
38
37
|
|
|
39
38
|
if message.new_schema.has(name=migration.path.schema_kind):
|
|
40
39
|
new_node_schema = message.new_schema.get(name=migration.path.schema_kind)
|
|
@@ -56,6 +55,7 @@ async def schema_apply_migrations(message: SchemaApplyMigrationData) -> list[str
|
|
|
56
55
|
new_node_schema=new_node_schema,
|
|
57
56
|
previous_node_schema=previous_node_schema,
|
|
58
57
|
schema_path=migration.path,
|
|
58
|
+
service=service,
|
|
59
59
|
)
|
|
60
60
|
|
|
61
61
|
async for _, result in batch.execute():
|
|
@@ -64,7 +64,7 @@ async def schema_apply_migrations(message: SchemaApplyMigrationData) -> list[str
|
|
|
64
64
|
return error_messages
|
|
65
65
|
|
|
66
66
|
|
|
67
|
-
@task(
|
|
67
|
+
@task( # type: ignore[arg-type]
|
|
68
68
|
name="schema-path-migrate",
|
|
69
69
|
task_run_name="Migrate Schema Path {migration_name} on {branch.name}",
|
|
70
70
|
description="Apply a given migration to the database",
|
|
@@ -75,10 +75,10 @@ async def schema_path_migrate(
|
|
|
75
75
|
branch: Branch,
|
|
76
76
|
migration_name: str,
|
|
77
77
|
schema_path: SchemaPath,
|
|
78
|
+
service: InfrahubServices,
|
|
78
79
|
new_node_schema: MainSchemaTypes | None = None,
|
|
79
80
|
previous_node_schema: MainSchemaTypes | None = None,
|
|
80
81
|
) -> SchemaMigrationPathResponseData:
|
|
81
|
-
service = services.service
|
|
82
82
|
log = get_run_logger()
|
|
83
83
|
|
|
84
84
|
async with service.database.start_session() as db:
|