infrahub-server 1.1.7__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 +50 -21
- infrahub/core/branch/models.py +4 -4
- infrahub/core/branch/tasks.py +130 -125
- 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 +1 -1
- infrahub/core/diff/enricher/cardinality_one.py +6 -1
- infrahub/core/diff/enricher/hierarchy.py +22 -7
- infrahub/core/diff/enricher/labels.py +6 -1
- infrahub/core/diff/enricher/path_identifier.py +5 -1
- infrahub/core/diff/enricher/summary_counts.py +107 -0
- infrahub/core/diff/merger/merger.py +3 -1
- infrahub/core/diff/model/path.py +34 -11
- infrahub/core/diff/parent_node_adder.py +78 -0
- infrahub/core/diff/payload_builder.py +13 -2
- infrahub/core/diff/query/all_conflicts.py +1 -1
- infrahub/core/diff/query/artifact.py +1 -1
- infrahub/core/diff/query/delete_query.py +1 -1
- infrahub/core/diff/query/diff_get.py +1 -1
- infrahub/core/diff/query/diff_summary.py +1 -1
- infrahub/core/diff/query/field_specifiers.py +1 -1
- infrahub/core/diff/query/field_summary.py +1 -1
- infrahub/core/diff/query/filters.py +2 -2
- infrahub/core/diff/query/get_conflict_query.py +1 -1
- infrahub/core/diff/query/has_conflicts_query.py +1 -1
- infrahub/core/diff/query/merge.py +3 -3
- infrahub/core/diff/query/merge_tracking_id.py +1 -1
- infrahub/core/diff/query/roots_metadata.py +1 -1
- infrahub/core/diff/query/save.py +191 -185
- infrahub/core/diff/query/summary_counts_enricher.py +52 -5
- infrahub/core/diff/query/time_range_query.py +1 -1
- infrahub/core/diff/query/update_conflict_query.py +1 -1
- infrahub/core/diff/repository/deserializer.py +9 -4
- infrahub/core/diff/repository/repository.py +156 -38
- 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 +164 -45
- infrahub/core/node/base.py +1 -1
- infrahub/core/node/delete_validator.py +4 -4
- infrahub/core/node/ipam.py +7 -7
- 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 +4 -4
- infrahub/core/query/ipam.py +4 -4
- infrahub/core/query/node.py +11 -12
- infrahub/core/query/relationship.py +211 -25
- infrahub/core/query/resource_manager.py +10 -10
- 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 +2 -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 +1 -1
- infrahub/database/__init__.py +3 -2
- infrahub/database/memgraph.py +1 -1
- infrahub/dependencies/builder/diff/combiner.py +1 -1
- infrahub/dependencies/builder/diff/conflicts_enricher.py +1 -1
- 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 +8 -0
- 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 -15
- infrahub/graphql/mutations/diff.py +33 -17
- 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 +233 -45
- infrahub/graphql/mutations/menu.py +10 -10
- infrahub/graphql/mutations/proposed_change.py +36 -28
- infrahub/graphql/mutations/relationship.py +341 -130
- 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 +10 -7
- 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 +37 -25
- 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/globals.py +15 -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/batch.py +2 -2
- infrahub_sdk/client.py +8 -0
- infrahub_sdk/config.py +1 -1
- infrahub_sdk/ctl/branch.py +3 -2
- infrahub_sdk/ctl/check.py +4 -4
- 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 +6 -21
- infrahub_sdk/ctl/validate.py +2 -1
- infrahub_sdk/data.py +1 -1
- infrahub_sdk/exceptions.py +12 -0
- infrahub_sdk/generator.py +3 -0
- infrahub_sdk/node.py +5 -8
- infrahub_sdk/protocols.py +20 -8
- infrahub_sdk/schema/__init__.py +14 -5
- 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/testing/docker.py +30 -0
- infrahub_sdk/timestamp.py +134 -33
- infrahub_sdk/transfer/exporter/json.py +1 -1
- infrahub_sdk/utils.py +39 -1
- infrahub_sdk/yaml.py +2 -3
- {infrahub_server-1.1.7.dist-info → infrahub_server-1.2.0b1.dist-info}/METADATA +7 -6
- {infrahub_server-1.1.7.dist-info → infrahub_server-1.2.0b1.dist-info}/RECORD +383 -339
- infrahub_testcontainers/container.py +2 -3
- infrahub_testcontainers/docker-compose.test.yml +2 -2
- 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/{schema → artifacts}/__init__.py +0 -0
- {infrahub_server-1.1.7.dist-info → infrahub_server-1.2.0b1.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.1.7.dist-info → infrahub_server-1.2.0b1.dist-info}/WHEEL +0 -0
- {infrahub_server-1.1.7.dist-info → infrahub_server-1.2.0b1.dist-info}/entry_points.txt +0 -0
infrahub/core/attribute.py
CHANGED
|
@@ -7,13 +7,14 @@ from typing import TYPE_CHECKING, Any, Optional, Union
|
|
|
7
7
|
|
|
8
8
|
import netaddr
|
|
9
9
|
import ujson
|
|
10
|
-
from infrahub_sdk.
|
|
10
|
+
from infrahub_sdk.exceptions import TimestampFormatError
|
|
11
11
|
from infrahub_sdk.utils import is_valid_url
|
|
12
12
|
from infrahub_sdk.uuidt import UUIDT
|
|
13
13
|
from pydantic import BaseModel, Field
|
|
14
14
|
|
|
15
15
|
from infrahub import config
|
|
16
16
|
from infrahub.core import registry
|
|
17
|
+
from infrahub.core.changelog.models import AttributeChangelog
|
|
17
18
|
from infrahub.core.constants import NULL_VALUE, AttributeDBNodeType, BranchSupportType, RelationshipStatus
|
|
18
19
|
from infrahub.core.property import FlagPropertyMixin, NodePropertyData, NodePropertyMixin
|
|
19
20
|
from infrahub.core.query.attribute import (
|
|
@@ -37,8 +38,6 @@ if TYPE_CHECKING:
|
|
|
37
38
|
from infrahub.core.schema import AttributeSchema
|
|
38
39
|
from infrahub.database import InfrahubDatabase
|
|
39
40
|
|
|
40
|
-
# pylint: disable=redefined-builtin,c-extension-no-member,too-many-lines,too-many-public-methods
|
|
41
|
-
|
|
42
41
|
|
|
43
42
|
# Use a more user-friendly threshold than Neo4j one (8167 bytes).
|
|
44
43
|
MAX_STRING_LENGTH = 4096
|
|
@@ -81,7 +80,7 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
81
80
|
_rel_to_node_label: str = RELATIONSHIP_TO_NODE_LABEL
|
|
82
81
|
_rel_to_value_label: str = RELATIONSHIP_TO_VALUE_LABEL
|
|
83
82
|
|
|
84
|
-
def __init__(
|
|
83
|
+
def __init__(
|
|
85
84
|
self,
|
|
86
85
|
name: str,
|
|
87
86
|
schema: AttributeSchema,
|
|
@@ -218,7 +217,7 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
218
217
|
value_to_check = value
|
|
219
218
|
if schema.enum and isinstance(value, Enum):
|
|
220
219
|
value_to_check = value.value
|
|
221
|
-
if not isinstance(value_to_check, cls.type):
|
|
220
|
+
if not isinstance(value_to_check, cls.type):
|
|
222
221
|
raise ValidationError({name: f"{value} is not a valid {schema.kind}"})
|
|
223
222
|
|
|
224
223
|
@classmethod
|
|
@@ -267,7 +266,7 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
267
266
|
@classmethod
|
|
268
267
|
def deserialize_from_string(cls, value_as_string: str) -> Any:
|
|
269
268
|
"""Return a value corresponding to the attribute type given it formatted as a string."""
|
|
270
|
-
return cls.type(value_as_string)
|
|
269
|
+
return cls.type(value_as_string)
|
|
271
270
|
|
|
272
271
|
def to_db(self) -> dict[str, Any]:
|
|
273
272
|
"""Return the properties of the AttributeValue node in Dict format."""
|
|
@@ -318,19 +317,19 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
318
317
|
"""Deserialize the value coming from the database."""
|
|
319
318
|
return data.value
|
|
320
319
|
|
|
321
|
-
async def save(self, db: InfrahubDatabase, at: Optional[Timestamp] = None) ->
|
|
320
|
+
async def save(self, db: InfrahubDatabase, at: Optional[Timestamp] = None) -> AttributeChangelog | None:
|
|
322
321
|
"""Create or Update the Attribute in the database."""
|
|
323
322
|
|
|
324
323
|
save_at = Timestamp(at)
|
|
325
324
|
|
|
326
325
|
if not self.id or self.is_from_profile:
|
|
327
|
-
return
|
|
326
|
+
return None
|
|
328
327
|
|
|
329
328
|
return await self._update(at=save_at, db=db)
|
|
330
329
|
|
|
331
|
-
async def delete(self, db: InfrahubDatabase, at: Optional[Timestamp] = None) ->
|
|
330
|
+
async def delete(self, db: InfrahubDatabase, at: Optional[Timestamp] = None) -> AttributeChangelog | None:
|
|
332
331
|
if not self.db_id:
|
|
333
|
-
return
|
|
332
|
+
return None
|
|
334
333
|
|
|
335
334
|
delete_at = Timestamp(at)
|
|
336
335
|
|
|
@@ -339,7 +338,14 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
339
338
|
results = query.get_results()
|
|
340
339
|
|
|
341
340
|
if not results:
|
|
342
|
-
return
|
|
341
|
+
return None
|
|
342
|
+
|
|
343
|
+
changelog = AttributeChangelog(
|
|
344
|
+
name=self.name,
|
|
345
|
+
value=None,
|
|
346
|
+
value_previous=None,
|
|
347
|
+
kind=self.schema.kind,
|
|
348
|
+
)
|
|
343
349
|
|
|
344
350
|
properties_to_delete = []
|
|
345
351
|
branch = self.get_branch_based_on_support_type()
|
|
@@ -347,6 +353,8 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
347
353
|
# Check all the relationship and update the one that are in the same branch
|
|
348
354
|
rel_ids_to_update = set()
|
|
349
355
|
for result in results:
|
|
356
|
+
if result.get_rel("r2").type == "HAS_VALUE":
|
|
357
|
+
changelog.value_previous = result.get_node("ap").get("value")
|
|
350
358
|
properties_to_delete.append((result.get_rel("r2").type, result.get_node("ap").element_id))
|
|
351
359
|
|
|
352
360
|
await add_relationship(
|
|
@@ -378,9 +386,9 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
378
386
|
db=db,
|
|
379
387
|
)
|
|
380
388
|
|
|
381
|
-
return
|
|
389
|
+
return changelog
|
|
382
390
|
|
|
383
|
-
async def _update(self, db: InfrahubDatabase, at: Optional[Timestamp] = None) ->
|
|
391
|
+
async def _update(self, db: InfrahubDatabase, at: Optional[Timestamp] = None) -> AttributeChangelog | None:
|
|
384
392
|
"""Update the attribute in the database.
|
|
385
393
|
|
|
386
394
|
Get the current value
|
|
@@ -420,6 +428,13 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
420
428
|
|
|
421
429
|
branch = self.get_branch_based_on_support_type()
|
|
422
430
|
|
|
431
|
+
changelog = AttributeChangelog(
|
|
432
|
+
name=self.name,
|
|
433
|
+
value=self.to_db().get("value"),
|
|
434
|
+
value_previous=current_attr_data.value,
|
|
435
|
+
kind=self.schema.kind,
|
|
436
|
+
)
|
|
437
|
+
|
|
423
438
|
# ---------- Update the Value ----------
|
|
424
439
|
if current_attr_data.content != self.to_db():
|
|
425
440
|
# Create the new AttributeValue and update the existing relationship
|
|
@@ -439,6 +454,11 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
439
454
|
|
|
440
455
|
for flag_name, _, rel_name in SUPPORTED_FLAGS:
|
|
441
456
|
if current_attr_data.flag_properties[flag_name] != getattr(self, flag_name):
|
|
457
|
+
changelog.add_property(
|
|
458
|
+
name=flag_name,
|
|
459
|
+
value_current=getattr(self, flag_name),
|
|
460
|
+
value_previous=current_attr_data.flag_properties[flag_name],
|
|
461
|
+
)
|
|
442
462
|
query = await AttributeUpdateFlagQuery.init(db=db, attr=self, at=update_at, flag_name=flag_name)
|
|
443
463
|
await query.execute(db=db)
|
|
444
464
|
|
|
@@ -452,6 +472,16 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
452
472
|
prop_name in current_attr_data.node_properties
|
|
453
473
|
and current_attr_data.node_properties[prop_name].uuid == getattr(self, f"{prop_name}_id")
|
|
454
474
|
):
|
|
475
|
+
previous_attribute_node_property = current_attr_data.node_properties.get(prop_name)
|
|
476
|
+
previous_value = None
|
|
477
|
+
if previous_attribute_node_property:
|
|
478
|
+
previous_value = previous_attribute_node_property.uuid
|
|
479
|
+
|
|
480
|
+
changelog.add_property(
|
|
481
|
+
name=prop_name,
|
|
482
|
+
value_current=getattr(self, f"{prop_name}_id"),
|
|
483
|
+
value_previous=previous_value,
|
|
484
|
+
)
|
|
455
485
|
query = await AttributeUpdateNodePropertyQuery.init(
|
|
456
486
|
db=db, attr=self, at=update_at, prop_name=prop_name, prop_id=getattr(self, f"{prop_name}_id")
|
|
457
487
|
)
|
|
@@ -461,7 +491,8 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
461
491
|
if rel and rel.get("branch") == branch.name:
|
|
462
492
|
await update_relationships_to([rel.element_id], to=update_at, db=db)
|
|
463
493
|
|
|
464
|
-
|
|
494
|
+
if changelog.has_updates:
|
|
495
|
+
return changelog
|
|
465
496
|
|
|
466
497
|
async def to_graphql(
|
|
467
498
|
self,
|
|
@@ -473,7 +504,6 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
473
504
|
include_properties: bool = True,
|
|
474
505
|
) -> dict:
|
|
475
506
|
"""Generate GraphQL Payload for this attribute."""
|
|
476
|
-
# pylint: disable=too-many-branches
|
|
477
507
|
|
|
478
508
|
response: dict[str, Any] = {"id": self.id}
|
|
479
509
|
|
|
@@ -530,11 +560,11 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
530
560
|
field = field.value
|
|
531
561
|
if isinstance(field, str):
|
|
532
562
|
response[field_name] = self._filter_sensitive(value=field, filter_sensitive=filter_sensitive)
|
|
533
|
-
elif isinstance(field,
|
|
563
|
+
elif isinstance(field, int | bool | dict | list):
|
|
534
564
|
response[field_name] = field
|
|
535
565
|
|
|
536
|
-
if related_node_ids and self.is_from_profile and
|
|
537
|
-
related_node_ids.add(
|
|
566
|
+
if related_node_ids and self.is_from_profile and self.source_id:
|
|
567
|
+
related_node_ids.add(self.source_id)
|
|
538
568
|
|
|
539
569
|
return response
|
|
540
570
|
|
|
@@ -592,7 +622,6 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
|
|
|
592
622
|
return AttributeDBNodeType.DEFAULT
|
|
593
623
|
|
|
594
624
|
def get_create_data(self) -> AttributeCreateData:
|
|
595
|
-
# pylint: disable=no-member
|
|
596
625
|
branch = self.branch
|
|
597
626
|
hierarchy_level = branch.hierarchy_level
|
|
598
627
|
if self.schema.branch == BranchSupportType.AGNOSTIC:
|
|
@@ -1162,7 +1191,7 @@ class ListAttribute(BaseAttribute):
|
|
|
1162
1191
|
|
|
1163
1192
|
def deserialize_value(self, data: AttributeFromDB) -> Any:
|
|
1164
1193
|
"""Deserialize the value (potentially) coming from the database."""
|
|
1165
|
-
if isinstance(data.value,
|
|
1194
|
+
if isinstance(data.value, str | bytes):
|
|
1166
1195
|
return ujson.loads(data.value)
|
|
1167
1196
|
return data.value
|
|
1168
1197
|
|
|
@@ -1198,7 +1227,7 @@ class JSONAttribute(BaseAttribute):
|
|
|
1198
1227
|
|
|
1199
1228
|
def deserialize_value(self, data: AttributeFromDB) -> Any:
|
|
1200
1229
|
"""Deserialize the value (potentially) coming from the database."""
|
|
1201
|
-
if data.value and isinstance(data.value,
|
|
1230
|
+
if data.value and isinstance(data.value, str | bytes):
|
|
1202
1231
|
return ujson.loads(data.value)
|
|
1203
1232
|
return data.value
|
|
1204
1233
|
|
infrahub/core/branch/models.py
CHANGED
|
@@ -25,7 +25,7 @@ if TYPE_CHECKING:
|
|
|
25
25
|
from infrahub.database import InfrahubDatabase
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
class Branch(StandardNode):
|
|
28
|
+
class Branch(StandardNode):
|
|
29
29
|
name: str = Field(
|
|
30
30
|
max_length=250, min_length=3, description="Name of the branch (git ref standard)", validate_default=True
|
|
31
31
|
)
|
|
@@ -274,7 +274,7 @@ class Branch(StandardNode): # pylint: disable=too-many-public-methods
|
|
|
274
274
|
|
|
275
275
|
for rel in rel_labels:
|
|
276
276
|
filters_per_rel = []
|
|
277
|
-
for idx
|
|
277
|
+
for idx in range(len(branches_times)):
|
|
278
278
|
filters_per_rel.append(
|
|
279
279
|
f"({rel}.branch IN $branch{idx} AND {rel}.from <= $time{idx} AND {rel}.to IS NULL)"
|
|
280
280
|
)
|
|
@@ -324,7 +324,7 @@ class Branch(StandardNode): # pylint: disable=too-many-public-methods
|
|
|
324
324
|
params[f"time{idx}"] = time_to_query
|
|
325
325
|
|
|
326
326
|
filters = []
|
|
327
|
-
for idx
|
|
327
|
+
for idx in range(len(branches_times)):
|
|
328
328
|
filters.append(
|
|
329
329
|
f"({variable_name}.branch IN $branch{idx} AND {variable_name}.from <= $time{idx} AND {variable_name}.to IS NULL)"
|
|
330
330
|
)
|
|
@@ -404,7 +404,7 @@ class Branch(StandardNode): # pylint: disable=too-many-public-methods
|
|
|
404
404
|
|
|
405
405
|
for rel in rel_labels:
|
|
406
406
|
filters_per_rel = []
|
|
407
|
-
for idx
|
|
407
|
+
for idx in range(len(start_times)):
|
|
408
408
|
filters_per_rel.extend(
|
|
409
409
|
[
|
|
410
410
|
f"""({rel}.branch = $branch{idx}
|
infrahub/core/branch/tasks.py
CHANGED
|
@@ -1,66 +1,62 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from datetime import timedelta
|
|
4
3
|
from typing import Any
|
|
4
|
+
from uuid import uuid4
|
|
5
5
|
|
|
6
6
|
import pydantic
|
|
7
7
|
from prefect import flow, get_run_logger
|
|
8
|
-
from prefect.automations import AutomationCore
|
|
9
|
-
from prefect.client.orchestration import get_client
|
|
10
|
-
from prefect.client.schemas.filters import DeploymentFilter, DeploymentFilterName
|
|
11
8
|
from prefect.client.schemas.objects import State # noqa: TC002
|
|
12
|
-
from prefect.events.actions import RunDeployment
|
|
13
|
-
from prefect.events.schemas.automations import EventTrigger, Posture
|
|
14
9
|
from prefect.states import Completed, Failed
|
|
15
10
|
|
|
16
11
|
from infrahub import lock
|
|
12
|
+
from infrahub.context import InfrahubContext # noqa: TC001 needed for prefect flow
|
|
17
13
|
from infrahub.core import registry
|
|
18
14
|
from infrahub.core.branch import Branch
|
|
15
|
+
from infrahub.core.changelog.diff import DiffChangelogCollector, MigrationTracker
|
|
16
|
+
from infrahub.core.constants import MutationAction
|
|
19
17
|
from infrahub.core.diff.coordinator import DiffCoordinator
|
|
20
18
|
from infrahub.core.diff.ipam_diff_parser import IpamDiffParser
|
|
21
19
|
from infrahub.core.diff.merger.merger import DiffMerger
|
|
22
|
-
from infrahub.core.diff.model.path import BranchTrackingId
|
|
20
|
+
from infrahub.core.diff.model.path import BranchTrackingId, EnrichedDiffRoot, EnrichedDiffRootMetadata
|
|
23
21
|
from infrahub.core.diff.repository.repository import DiffRepository
|
|
24
22
|
from infrahub.core.merge import BranchMerger
|
|
25
23
|
from infrahub.core.migrations.schema.models import SchemaApplyMigrationData
|
|
26
24
|
from infrahub.core.migrations.schema.tasks import schema_apply_migrations
|
|
25
|
+
from infrahub.core.timestamp import Timestamp
|
|
27
26
|
from infrahub.core.validators.determiner import ConstraintValidatorDeterminer
|
|
28
27
|
from infrahub.core.validators.models.validate_migration import SchemaValidateMigrationData
|
|
29
28
|
from infrahub.core.validators.tasks import schema_validate_migrations
|
|
30
29
|
from infrahub.dependencies.registry import get_component_registry
|
|
31
|
-
from infrahub.events.branch_action import
|
|
30
|
+
from infrahub.events.branch_action import BranchCreatedEvent, BranchDeletedEvent, BranchMergedEvent, BranchRebasedEvent
|
|
31
|
+
from infrahub.events.models import EventMeta, InfrahubEvent
|
|
32
|
+
from infrahub.events.node_action import NodeMutatedEvent
|
|
32
33
|
from infrahub.exceptions import BranchNotFoundError, MergeFailedError, ValidationError
|
|
33
34
|
from infrahub.graphql.mutations.models import BranchCreateModel # noqa: TC001
|
|
34
35
|
from infrahub.log import get_log_data
|
|
35
36
|
from infrahub.message_bus import Meta, messages
|
|
36
|
-
from infrahub.services import
|
|
37
|
+
from infrahub.services import InfrahubServices # noqa: TC001 needed for prefect flow
|
|
37
38
|
from infrahub.worker import WORKER_IDENTITY
|
|
38
39
|
from infrahub.workflows.catalogue import (
|
|
39
40
|
BRANCH_CANCEL_PROPOSED_CHANGES,
|
|
40
|
-
COMPUTED_ATTRIBUTE_REMOVE_PYTHON,
|
|
41
|
-
COMPUTED_ATTRIBUTE_SETUP_PYTHON,
|
|
42
41
|
DIFF_REFRESH_ALL,
|
|
43
42
|
GIT_REPOSITORIES_CREATE_BRANCH,
|
|
44
43
|
IPAM_RECONCILIATION,
|
|
45
44
|
)
|
|
46
|
-
from infrahub.workflows.utils import
|
|
47
|
-
|
|
48
|
-
from .constants import AUTOMATION_NAME_CREATE, AUTOMATION_NAME_REMOVE
|
|
45
|
+
from infrahub.workflows.utils import add_tags
|
|
49
46
|
|
|
50
47
|
|
|
51
48
|
@flow(name="branch-rebase", flow_run_name="Rebase branch {branch}")
|
|
52
|
-
async def rebase_branch(branch: str) -> None:
|
|
53
|
-
service = services.service
|
|
54
|
-
|
|
49
|
+
async def rebase_branch(branch: str, context: InfrahubContext, service: InfrahubServices) -> None:
|
|
55
50
|
async with service.database.start_session() as db:
|
|
56
51
|
log = get_run_logger()
|
|
57
|
-
await
|
|
52
|
+
await add_tags(branches=[branch])
|
|
58
53
|
obj = await Branch.get_by_name(db=db, name=branch)
|
|
59
54
|
base_branch = await Branch.get_by_name(db=db, name=registry.default_branch)
|
|
60
55
|
component_registry = get_component_registry()
|
|
61
56
|
diff_repository = await component_registry.get_component(DiffRepository, db=db, branch=obj)
|
|
62
57
|
diff_coordinator = await component_registry.get_component(DiffCoordinator, db=db, branch=obj)
|
|
63
58
|
diff_merger = await component_registry.get_component(DiffMerger, db=db, branch=obj)
|
|
59
|
+
initial_from_time = Timestamp(obj.get_branched_from())
|
|
64
60
|
merger = BranchMerger(
|
|
65
61
|
db=db,
|
|
66
62
|
diff_coordinator=diff_coordinator,
|
|
@@ -69,7 +65,7 @@ async def rebase_branch(branch: str) -> None:
|
|
|
69
65
|
source_branch=obj,
|
|
70
66
|
service=service,
|
|
71
67
|
)
|
|
72
|
-
|
|
68
|
+
|
|
73
69
|
enriched_diff_metadata = await diff_coordinator.update_branch_diff(base_branch=base_branch, diff_branch=obj)
|
|
74
70
|
async for _ in diff_repository.get_all_conflicts_for_diff(
|
|
75
71
|
diff_branch_name=enriched_diff_metadata.diff_branch_name, diff_id=enriched_diff_metadata.uuid
|
|
@@ -94,14 +90,17 @@ async def rebase_branch(branch: str) -> None:
|
|
|
94
90
|
constraints += await merger.calculate_validations(target_schema=candidate_schema)
|
|
95
91
|
if constraints:
|
|
96
92
|
responses = await schema_validate_migrations(
|
|
97
|
-
message=SchemaValidateMigrationData(
|
|
93
|
+
message=SchemaValidateMigrationData(
|
|
94
|
+
branch=obj, schema_branch=candidate_schema, constraints=constraints
|
|
95
|
+
),
|
|
96
|
+
service=service,
|
|
98
97
|
)
|
|
99
98
|
error_messages = [violation.message for response in responses for violation in response.violations]
|
|
100
99
|
if error_messages:
|
|
101
100
|
raise ValidationError(",\n".join(error_messages))
|
|
102
101
|
|
|
103
102
|
schema_in_main_before = merger.destination_schema.duplicate()
|
|
104
|
-
|
|
103
|
+
migrations = []
|
|
105
104
|
async with lock.registry.global_graph_lock():
|
|
106
105
|
async with db.start_transaction() as dbt:
|
|
107
106
|
await obj.rebase(db=dbt)
|
|
@@ -132,11 +131,20 @@ async def rebase_branch(branch: str) -> None:
|
|
|
132
131
|
new_schema=candidate_schema,
|
|
133
132
|
previous_schema=schema_in_main_before,
|
|
134
133
|
migrations=migrations,
|
|
135
|
-
)
|
|
134
|
+
),
|
|
135
|
+
service=service,
|
|
136
136
|
)
|
|
137
137
|
for error in errors:
|
|
138
138
|
log.error(error)
|
|
139
139
|
|
|
140
|
+
default_branch_diff = await _get_diff_root(
|
|
141
|
+
diff_coordinator=diff_coordinator,
|
|
142
|
+
enriched_diff_metadata=enriched_diff_metadata,
|
|
143
|
+
diff_repository=diff_repository,
|
|
144
|
+
base_branch=base_branch,
|
|
145
|
+
target_from=initial_from_time,
|
|
146
|
+
)
|
|
147
|
+
|
|
140
148
|
# -------------------------------------------------------------
|
|
141
149
|
# Trigger the reconciliation of IPAM data after the rebase
|
|
142
150
|
# -------------------------------------------------------------
|
|
@@ -147,28 +155,55 @@ async def rebase_branch(branch: str) -> None:
|
|
|
147
155
|
)
|
|
148
156
|
if ipam_node_details:
|
|
149
157
|
await service.workflow.submit_workflow(
|
|
150
|
-
workflow=IPAM_RECONCILIATION,
|
|
158
|
+
workflow=IPAM_RECONCILIATION,
|
|
159
|
+
context=context,
|
|
160
|
+
parameters={"branch": obj.name, "ipam_node_details": ipam_node_details},
|
|
151
161
|
)
|
|
152
162
|
|
|
153
|
-
await service.workflow.submit_workflow(
|
|
163
|
+
await service.workflow.submit_workflow(
|
|
164
|
+
workflow=DIFF_REFRESH_ALL, context=context, parameters={"branch_name": obj.name}
|
|
165
|
+
)
|
|
154
166
|
|
|
155
167
|
# -------------------------------------------------------------
|
|
156
168
|
# Generate an event to indicate that a branch has been rebased
|
|
157
169
|
# -------------------------------------------------------------
|
|
158
|
-
|
|
170
|
+
rebase_event = BranchRebasedEvent(
|
|
171
|
+
branch_name=obj.name, branch_id=str(obj.uuid), meta=EventMeta(branch=obj, context=context)
|
|
172
|
+
)
|
|
173
|
+
events: list[InfrahubEvent] = [rebase_event]
|
|
174
|
+
changelog_collector = DiffChangelogCollector(
|
|
175
|
+
diff=default_branch_diff, branch=obj, db=db, migration_tracker=MigrationTracker(migrations=migrations)
|
|
176
|
+
)
|
|
177
|
+
for action, node_changelog in changelog_collector.collect_changelogs():
|
|
178
|
+
mutate_event = NodeMutatedEvent(
|
|
179
|
+
kind=node_changelog.node_kind,
|
|
180
|
+
node_id=node_changelog.node_id,
|
|
181
|
+
data=node_changelog,
|
|
182
|
+
action=MutationAction.from_diff_action(diff_action=action),
|
|
183
|
+
fields=node_changelog.updated_fields,
|
|
184
|
+
meta=EventMeta.from_parent(parent=rebase_event, branch=obj),
|
|
185
|
+
)
|
|
186
|
+
events.append(mutate_event)
|
|
187
|
+
|
|
188
|
+
for event in events:
|
|
189
|
+
await service.event.send(event)
|
|
159
190
|
|
|
160
191
|
|
|
161
192
|
@flow(name="branch-merge", flow_run_name="Merge branch {branch} into main")
|
|
162
|
-
async def merge_branch(branch: str) -> None:
|
|
163
|
-
service = services.service
|
|
193
|
+
async def merge_branch(branch: str, context: InfrahubContext, service: InfrahubServices) -> None:
|
|
164
194
|
async with service.database.start_session() as db:
|
|
165
195
|
log = get_run_logger()
|
|
166
196
|
|
|
167
|
-
await
|
|
168
|
-
await add_branch_tag(branch_name=registry.default_branch)
|
|
197
|
+
await add_tags(branches=[branch, registry.default_branch])
|
|
169
198
|
|
|
170
199
|
obj = await Branch.get_by_name(db=db, name=branch)
|
|
200
|
+
default_branch = await registry.get_branch(db=db, branch=registry.default_branch)
|
|
171
201
|
component_registry = get_component_registry()
|
|
202
|
+
merge_event = BranchMergedEvent(
|
|
203
|
+
branch_name=obj.name,
|
|
204
|
+
branch_id=str(obj.get_uuid()),
|
|
205
|
+
meta=EventMeta.from_context(context=context, branch=registry.get_global_branch()),
|
|
206
|
+
)
|
|
172
207
|
|
|
173
208
|
merger: BranchMerger | None = None
|
|
174
209
|
async with lock.registry.global_graph_lock():
|
|
@@ -186,13 +221,15 @@ async def merge_branch(branch: str) -> None:
|
|
|
186
221
|
service=service,
|
|
187
222
|
)
|
|
188
223
|
try:
|
|
189
|
-
await merger.merge()
|
|
224
|
+
branch_diff = await merger.merge()
|
|
190
225
|
except Exception as exc:
|
|
191
226
|
log.exception("Merge failed, beginning rollback")
|
|
192
227
|
await merger.rollback()
|
|
193
228
|
raise MergeFailedError(branch_name=branch) from exc
|
|
194
229
|
await merger.update_schema()
|
|
195
230
|
|
|
231
|
+
changelog_collector = DiffChangelogCollector(diff=branch_diff, branch=obj, db=db)
|
|
232
|
+
node_events = changelog_collector.collect_changelogs()
|
|
196
233
|
if merger and merger.migrations:
|
|
197
234
|
errors = await schema_apply_migrations(
|
|
198
235
|
message=SchemaApplyMigrationData(
|
|
@@ -200,7 +237,8 @@ async def merge_branch(branch: str) -> None:
|
|
|
200
237
|
new_schema=merger.destination_schema,
|
|
201
238
|
previous_schema=merger.initial_source_schema,
|
|
202
239
|
migrations=merger.migrations,
|
|
203
|
-
)
|
|
240
|
+
),
|
|
241
|
+
service=service,
|
|
204
242
|
)
|
|
205
243
|
for error in errors:
|
|
206
244
|
log.error(error)
|
|
@@ -216,6 +254,7 @@ async def merge_branch(branch: str) -> None:
|
|
|
216
254
|
if ipam_node_details:
|
|
217
255
|
await service.workflow.submit_workflow(
|
|
218
256
|
workflow=IPAM_RECONCILIATION,
|
|
257
|
+
context=context,
|
|
219
258
|
parameters={"branch": registry.default_branch, "ipam_node_details": ipam_node_details},
|
|
220
259
|
)
|
|
221
260
|
# -------------------------------------------------------------
|
|
@@ -234,24 +273,46 @@ async def merge_branch(branch: str) -> None:
|
|
|
234
273
|
message = messages.EventBranchMerge(
|
|
235
274
|
source_branch=obj.name,
|
|
236
275
|
target_branch=registry.default_branch,
|
|
276
|
+
context=context,
|
|
237
277
|
meta=Meta(initiator_id=WORKER_IDENTITY, request_id=request_id),
|
|
238
278
|
)
|
|
239
|
-
await service.send(message=message)
|
|
279
|
+
await service.message_bus.send(message=message)
|
|
280
|
+
|
|
281
|
+
events: list[InfrahubEvent] = [merge_event]
|
|
282
|
+
|
|
283
|
+
for action, node_changelog in node_events:
|
|
284
|
+
meta = EventMeta.from_parent(parent=merge_event, branch=default_branch)
|
|
285
|
+
mutate_event = NodeMutatedEvent(
|
|
286
|
+
kind=node_changelog.node_kind,
|
|
287
|
+
node_id=node_changelog.node_id,
|
|
288
|
+
data=node_changelog,
|
|
289
|
+
action=MutationAction.from_diff_action(diff_action=action),
|
|
290
|
+
fields=node_changelog.updated_fields,
|
|
291
|
+
meta=meta,
|
|
292
|
+
)
|
|
293
|
+
events.append(mutate_event)
|
|
240
294
|
|
|
295
|
+
for event in events:
|
|
296
|
+
await service.event.send(event=event)
|
|
241
297
|
|
|
242
|
-
@flow(name="branch-delete", flow_run_name="Delete branch {branch}")
|
|
243
|
-
async def delete_branch(branch: str) -> None:
|
|
244
|
-
service = services.service
|
|
245
298
|
|
|
246
|
-
|
|
299
|
+
@flow(name="branch-delete", flow_run_name="Delete branch {branch}")
|
|
300
|
+
async def delete_branch(branch: str, context: InfrahubContext, service: InfrahubServices) -> None:
|
|
301
|
+
await add_tags(branches=[branch])
|
|
247
302
|
|
|
248
303
|
async with service.database.start_session() as db:
|
|
249
304
|
obj = await Branch.get_by_name(db=db, name=str(branch))
|
|
250
|
-
event = BranchDeleteEvent(branch=branch, branch_id=obj.get_id(), sync_with_git=obj.sync_with_git)
|
|
251
305
|
await obj.delete(db=db)
|
|
252
306
|
|
|
307
|
+
event = BranchDeletedEvent(
|
|
308
|
+
branch_name=branch,
|
|
309
|
+
branch_id=str(obj.uuid),
|
|
310
|
+
sync_with_git=obj.sync_with_git,
|
|
311
|
+
meta=EventMeta.from_context(context=context, branch=registry.get_global_branch()),
|
|
312
|
+
)
|
|
313
|
+
|
|
253
314
|
await service.workflow.submit_workflow(
|
|
254
|
-
workflow=BRANCH_CANCEL_PROPOSED_CHANGES, parameters={"branch_name": branch}
|
|
315
|
+
workflow=BRANCH_CANCEL_PROPOSED_CHANGES, context=context, parameters={"branch_name": branch}
|
|
255
316
|
)
|
|
256
317
|
|
|
257
318
|
await service.event.send(event=event)
|
|
@@ -263,9 +324,8 @@ async def delete_branch(branch: str) -> None:
|
|
|
263
324
|
description="Validate if the branch has some conflicts",
|
|
264
325
|
persist_result=True,
|
|
265
326
|
)
|
|
266
|
-
async def validate_branch(branch: str) -> State:
|
|
267
|
-
|
|
268
|
-
await add_branch_tag(branch_name=branch)
|
|
327
|
+
async def validate_branch(branch: str, service: InfrahubServices) -> State:
|
|
328
|
+
await add_tags(branches=[branch])
|
|
269
329
|
|
|
270
330
|
async with service.database.start_session() as db:
|
|
271
331
|
obj = await Branch.get_by_name(db=db, name=branch)
|
|
@@ -281,9 +341,8 @@ async def validate_branch(branch: str) -> State:
|
|
|
281
341
|
|
|
282
342
|
|
|
283
343
|
@flow(name="create-branch", flow_run_name="Create branch {model.name}")
|
|
284
|
-
async def create_branch(model: BranchCreateModel) -> None:
|
|
285
|
-
|
|
286
|
-
await add_branch_tag(model.name)
|
|
344
|
+
async def create_branch(model: BranchCreateModel, context: InfrahubContext, service: InfrahubServices) -> None:
|
|
345
|
+
await add_tags(branches=[model.name])
|
|
287
346
|
|
|
288
347
|
async with service.database.start_session() as db:
|
|
289
348
|
try:
|
|
@@ -293,8 +352,7 @@ async def create_branch(model: BranchCreateModel) -> None:
|
|
|
293
352
|
pass
|
|
294
353
|
|
|
295
354
|
data_dict: dict[str, Any] = dict(model)
|
|
296
|
-
|
|
297
|
-
del data_dict["is_isolated"]
|
|
355
|
+
data_dict.pop("is_isolated", None)
|
|
298
356
|
|
|
299
357
|
try:
|
|
300
358
|
obj = Branch(**data_dict)
|
|
@@ -314,93 +372,40 @@ async def create_branch(model: BranchCreateModel) -> None:
|
|
|
314
372
|
registry.branch[obj.name] = obj
|
|
315
373
|
await service.component.refresh_schema_hash(branches=[obj.name])
|
|
316
374
|
|
|
317
|
-
event =
|
|
375
|
+
event = BranchCreatedEvent(
|
|
376
|
+
branch_name=obj.name,
|
|
377
|
+
branch_id=str(obj.uuid),
|
|
378
|
+
sync_with_git=obj.sync_with_git,
|
|
379
|
+
meta=EventMeta.from_context(context=context, branch=registry.get_global_branch()),
|
|
380
|
+
)
|
|
318
381
|
await service.event.send(event=event)
|
|
319
382
|
|
|
320
383
|
if obj.sync_with_git:
|
|
321
384
|
await service.workflow.submit_workflow(
|
|
322
385
|
workflow=GIT_REPOSITORIES_CREATE_BRANCH,
|
|
386
|
+
context=context,
|
|
323
387
|
parameters={"branch": obj.name, "branch_id": str(obj.uuid)},
|
|
324
388
|
)
|
|
325
389
|
|
|
326
390
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
branch_create_automation = await client.find_automation(id_or_name=AUTOMATION_NAME_CREATE)
|
|
346
|
-
|
|
347
|
-
automation = AutomationCore(
|
|
348
|
-
name=AUTOMATION_NAME_CREATE,
|
|
349
|
-
description="Trigger actions on branch create event",
|
|
350
|
-
enabled=True,
|
|
351
|
-
trigger=EventTrigger(
|
|
352
|
-
posture=Posture.Reactive,
|
|
353
|
-
expect={"infrahub.branch.created"},
|
|
354
|
-
within=timedelta(0),
|
|
355
|
-
threshold=1,
|
|
356
|
-
),
|
|
357
|
-
actions=[
|
|
358
|
-
RunDeployment(
|
|
359
|
-
source="selected",
|
|
360
|
-
deployment_id=deployment_id_computed_attribute_setup_python,
|
|
361
|
-
parameters={
|
|
362
|
-
"branch_name": "{{ event.resource['infrahub.branch.name'] }}",
|
|
363
|
-
"trigger_updates": False,
|
|
364
|
-
},
|
|
365
|
-
job_variables={},
|
|
366
|
-
),
|
|
367
|
-
],
|
|
368
|
-
)
|
|
369
|
-
|
|
370
|
-
if branch_create_automation:
|
|
371
|
-
await client.update_automation(automation_id=branch_create_automation.id, automation=automation)
|
|
372
|
-
log.info(f"{AUTOMATION_NAME_CREATE} Updated")
|
|
373
|
-
else:
|
|
374
|
-
await client.create_automation(automation=automation)
|
|
375
|
-
log.info(f"{AUTOMATION_NAME_CREATE} Created")
|
|
376
|
-
|
|
377
|
-
branch_remove_automation = await client.find_automation(id_or_name=AUTOMATION_NAME_REMOVE)
|
|
378
|
-
|
|
379
|
-
automation = AutomationCore(
|
|
380
|
-
name=AUTOMATION_NAME_REMOVE,
|
|
381
|
-
description="Trigger actions on branch delete event",
|
|
382
|
-
enabled=True,
|
|
383
|
-
trigger=EventTrigger(
|
|
384
|
-
posture=Posture.Reactive,
|
|
385
|
-
expect={"infrahub.branch.deleted"},
|
|
386
|
-
within=timedelta(0),
|
|
387
|
-
threshold=1,
|
|
388
|
-
),
|
|
389
|
-
actions=[
|
|
390
|
-
RunDeployment(
|
|
391
|
-
source="selected",
|
|
392
|
-
deployment_id=deployment_id_computed_attribute_remove_python,
|
|
393
|
-
parameters={
|
|
394
|
-
"branch_name": "{{ event.resource['infrahub.branch.name'] }}",
|
|
395
|
-
},
|
|
396
|
-
job_variables={},
|
|
397
|
-
),
|
|
398
|
-
],
|
|
391
|
+
async def _get_diff_root(
|
|
392
|
+
diff_coordinator: DiffCoordinator,
|
|
393
|
+
enriched_diff_metadata: EnrichedDiffRootMetadata,
|
|
394
|
+
diff_repository: DiffRepository,
|
|
395
|
+
base_branch: Branch,
|
|
396
|
+
target_from: Timestamp,
|
|
397
|
+
) -> EnrichedDiffRoot:
|
|
398
|
+
default_branch_diff = await diff_coordinator.create_or_update_arbitrary_timeframe_diff(
|
|
399
|
+
base_branch=base_branch,
|
|
400
|
+
diff_branch=base_branch,
|
|
401
|
+
from_time=target_from,
|
|
402
|
+
to_time=enriched_diff_metadata.to_time,
|
|
403
|
+
name=str(uuid4()),
|
|
404
|
+
)
|
|
405
|
+
# make sure we have the actual diff with data and not just the metadata
|
|
406
|
+
if not isinstance(default_branch_diff, EnrichedDiffRoot):
|
|
407
|
+
default_branch_diff = await diff_repository.get_one(
|
|
408
|
+
diff_branch_name=base_branch.name, diff_id=default_branch_diff.uuid
|
|
399
409
|
)
|
|
400
410
|
|
|
401
|
-
|
|
402
|
-
await client.update_automation(automation_id=branch_remove_automation.id, automation=automation)
|
|
403
|
-
log.info(f"{AUTOMATION_NAME_REMOVE} Updated")
|
|
404
|
-
else:
|
|
405
|
-
await client.create_automation(automation=automation)
|
|
406
|
-
log.info(f"{AUTOMATION_NAME_REMOVE} Created")
|
|
411
|
+
return default_branch_diff
|