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
|
@@ -58,7 +58,7 @@ class SchemaMigration(BaseModel):
|
|
|
58
58
|
query = await migration_query.init(db=ts, branch=branch, at=at, migration=self)
|
|
59
59
|
await query.execute(db=ts)
|
|
60
60
|
result.nbr_migrations_executed += query.get_nbr_migrations_executed()
|
|
61
|
-
except Exception as exc:
|
|
61
|
+
except Exception as exc:
|
|
62
62
|
result.errors.append(str(exc))
|
|
63
63
|
return result
|
|
64
64
|
|
|
@@ -126,7 +126,7 @@ class GraphMigration(BaseModel):
|
|
|
126
126
|
try:
|
|
127
127
|
query = await migration_query.init(db=ts)
|
|
128
128
|
await query.execute(db=ts)
|
|
129
|
-
except Exception as exc:
|
|
129
|
+
except Exception as exc:
|
|
130
130
|
result.errors.append(str(exc))
|
|
131
131
|
return result
|
|
132
132
|
|
|
@@ -141,7 +141,7 @@ class InternalSchemaMigration(BaseModel):
|
|
|
141
141
|
|
|
142
142
|
@staticmethod
|
|
143
143
|
def get_internal_schema() -> SchemaBranch:
|
|
144
|
-
from infrahub.core.schema.schema_branch import SchemaBranch
|
|
144
|
+
from infrahub.core.schema.schema_branch import SchemaBranch
|
|
145
145
|
|
|
146
146
|
# load the internal schema from
|
|
147
147
|
schema = SchemaRoot(**internal_schema)
|
|
@@ -167,7 +167,7 @@ class InternalSchemaMigration(BaseModel):
|
|
|
167
167
|
try:
|
|
168
168
|
execution_result = await migration.execute(db=db, branch=default_branch)
|
|
169
169
|
result.errors.extend(execution_result.errors)
|
|
170
|
-
except Exception as exc:
|
|
170
|
+
except Exception as exc:
|
|
171
171
|
result.errors.append(str(exc))
|
|
172
172
|
return result
|
|
173
173
|
|
infrahub/core/models.py
CHANGED
|
@@ -105,7 +105,6 @@ class SchemaDiff(BaseModel):
|
|
|
105
105
|
|
|
106
106
|
indent_str = " " * indentation
|
|
107
107
|
|
|
108
|
-
# pylint: disable=too-many-nested-blocks
|
|
109
108
|
for node_action, node_info in data.items():
|
|
110
109
|
for node_name, elements in node_info.items():
|
|
111
110
|
print(f"{str(node_name).ljust(column_size)} | {str(node_action).title()}")
|
|
@@ -152,7 +151,7 @@ class SchemaUpdateConstraintInfo(BaseModel):
|
|
|
152
151
|
return "schema.validator.path"
|
|
153
152
|
|
|
154
153
|
def __hash__(self) -> int:
|
|
155
|
-
return hash((type(self),) + tuple(
|
|
154
|
+
return hash((type(self),) + tuple(self.constraint_name + self.path.get_path()))
|
|
156
155
|
|
|
157
156
|
|
|
158
157
|
class SchemaUpdateValidationResult(BaseModel):
|
|
@@ -170,7 +169,7 @@ class SchemaUpdateValidationResult(BaseModel):
|
|
|
170
169
|
return obj
|
|
171
170
|
|
|
172
171
|
def process_diff(self, schema: SchemaBranch) -> None:
|
|
173
|
-
for schema_name
|
|
172
|
+
for schema_name in self.diff.removed.keys():
|
|
174
173
|
self.migrations.append(
|
|
175
174
|
SchemaUpdateMigrationInfo(
|
|
176
175
|
path=SchemaPath( # type: ignore[call-arg]
|
|
@@ -331,7 +330,7 @@ class SchemaUpdateValidationResult(BaseModel):
|
|
|
331
330
|
|
|
332
331
|
def add_validator_for_migration(self, validator_map: dict[str, Any]) -> None:
|
|
333
332
|
for migration in self.migrations:
|
|
334
|
-
if validator_map.get(migration.migration_name
|
|
333
|
+
if validator_map.get(migration.migration_name):
|
|
335
334
|
self.constraints.append(
|
|
336
335
|
SchemaUpdateConstraintInfo(
|
|
337
336
|
path=migration.path,
|
|
@@ -384,7 +383,7 @@ class HashableModel(BaseModel):
|
|
|
384
383
|
md5hash.update(item)
|
|
385
384
|
|
|
386
385
|
if display_values:
|
|
387
|
-
from rich import print as rprint
|
|
386
|
+
from rich import print as rprint
|
|
388
387
|
|
|
389
388
|
rprint(tuple(values))
|
|
390
389
|
|
|
@@ -494,8 +493,8 @@ class HashableModel(BaseModel):
|
|
|
494
493
|
raise ValueError(f"Unable to merge the list for {field_name}, some items have the same _sorting_id")
|
|
495
494
|
|
|
496
495
|
shared_ids = intersection(list(local_sub_items.keys()), list(other_sub_items.keys()))
|
|
497
|
-
local_only_ids = set(
|
|
498
|
-
other_only_ids = set(
|
|
496
|
+
local_only_ids = set(local_sub_items.keys()) - set(shared_ids)
|
|
497
|
+
other_only_ids = set(other_sub_items.keys()) - set(shared_ids)
|
|
499
498
|
|
|
500
499
|
new_list = [value for key, value in local_sub_items.items() if key in local_only_ids]
|
|
501
500
|
new_list.extend(
|
|
@@ -536,7 +535,7 @@ class HashableModel(BaseModel):
|
|
|
536
535
|
if attr_other is None or attr_local == attr_other:
|
|
537
536
|
continue
|
|
538
537
|
|
|
539
|
-
if attr_local is None or isinstance(attr_other,
|
|
538
|
+
if attr_local is None or isinstance(attr_other, int | str | bool | float):
|
|
540
539
|
setattr(self, field_name, attr_other)
|
|
541
540
|
continue
|
|
542
541
|
|
infrahub/core/node/__init__.py
CHANGED
|
@@ -1,17 +1,27 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from enum import Enum
|
|
4
|
-
from typing import TYPE_CHECKING, Any, Optional, TypeVar, Union, overload
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Optional, Sequence, TypeVar, Union, overload
|
|
5
5
|
|
|
6
6
|
from infrahub_sdk.utils import is_valid_uuid
|
|
7
7
|
from infrahub_sdk.uuidt import UUIDT
|
|
8
8
|
|
|
9
9
|
from infrahub.core import registry
|
|
10
|
-
from infrahub.core.
|
|
10
|
+
from infrahub.core.changelog.models import NodeChangelog
|
|
11
|
+
from infrahub.core.constants import (
|
|
12
|
+
GLOBAL_BRANCH_NAME,
|
|
13
|
+
OBJECT_TEMPLATE_NAME_ATTR,
|
|
14
|
+
OBJECT_TEMPLATE_RELATIONSHIP_NAME,
|
|
15
|
+
BranchSupportType,
|
|
16
|
+
ComputedAttributeKind,
|
|
17
|
+
InfrahubKind,
|
|
18
|
+
RelationshipCardinality,
|
|
19
|
+
RelationshipKind,
|
|
20
|
+
)
|
|
11
21
|
from infrahub.core.constants.schema import SchemaElementPathType
|
|
12
|
-
from infrahub.core.protocols import CoreNumberPool
|
|
22
|
+
from infrahub.core.protocols import CoreNumberPool, CoreObjectTemplate
|
|
13
23
|
from infrahub.core.query.node import NodeCheckIDQuery, NodeCreateAllQuery, NodeDeleteQuery, NodeGetListQuery
|
|
14
|
-
from infrahub.core.schema import AttributeSchema, NodeSchema, ProfileSchema, RelationshipSchema
|
|
24
|
+
from infrahub.core.schema import AttributeSchema, NodeSchema, ProfileSchema, RelationshipSchema, TemplateSchema
|
|
15
25
|
from infrahub.core.timestamp import Timestamp
|
|
16
26
|
from infrahub.exceptions import InitializationError, NodeNotFoundError, PoolExhaustedError, ValidationError
|
|
17
27
|
from infrahub.support.macro import MacroDefinition
|
|
@@ -19,6 +29,7 @@ from infrahub.types import ATTRIBUTE_TYPES
|
|
|
19
29
|
|
|
20
30
|
from ...graphql.constants import KIND_GRAPHQL_FIELD_NAME
|
|
21
31
|
from ...graphql.models import OrderModel
|
|
32
|
+
from ..query.relationship import RelationshipDeleteAllQuery
|
|
22
33
|
from ..relationship import RelationshipManager
|
|
23
34
|
from ..utils import update_relationships_to
|
|
24
35
|
from .base import BaseNode, BaseNodeMeta, BaseNodeOptions
|
|
@@ -42,21 +53,17 @@ SchemaProtocol = TypeVar("SchemaProtocol")
|
|
|
42
53
|
# -
|
|
43
54
|
# ---------------------------------------------------------------------------------------
|
|
44
55
|
|
|
45
|
-
# pylint: disable=redefined-builtin,too-many-branches
|
|
46
|
-
|
|
47
56
|
|
|
48
57
|
class Node(BaseNode, metaclass=BaseNodeMeta):
|
|
49
58
|
@classmethod
|
|
50
|
-
def __init_subclass_with_meta__(
|
|
51
|
-
cls, _meta=None, default_filter=None, **options
|
|
52
|
-
) -> None:
|
|
59
|
+
def __init_subclass_with_meta__(cls, _meta=None, default_filter=None, **options) -> None:
|
|
53
60
|
if not _meta:
|
|
54
61
|
_meta = BaseNodeOptions(cls)
|
|
55
62
|
|
|
56
63
|
_meta.default_filter = default_filter
|
|
57
64
|
super().__init_subclass_with_meta__(_meta=_meta, **options)
|
|
58
65
|
|
|
59
|
-
def get_schema(self) -> Union[NodeSchema, ProfileSchema]:
|
|
66
|
+
def get_schema(self) -> Union[NodeSchema, ProfileSchema, TemplateSchema]:
|
|
60
67
|
return self._schema
|
|
61
68
|
|
|
62
69
|
def get_kind(self) -> str:
|
|
@@ -130,7 +137,7 @@ class Node(BaseNode, metaclass=BaseNodeMeta):
|
|
|
130
137
|
labels.append(InfrahubKind.NODE)
|
|
131
138
|
return labels
|
|
132
139
|
|
|
133
|
-
if isinstance(self._schema, ProfileSchema):
|
|
140
|
+
if isinstance(self._schema, ProfileSchema | TemplateSchema):
|
|
134
141
|
labels = [self.get_kind()] + self._schema.inherit_from
|
|
135
142
|
return labels
|
|
136
143
|
|
|
@@ -153,8 +160,8 @@ class Node(BaseNode, metaclass=BaseNodeMeta):
|
|
|
153
160
|
|
|
154
161
|
return f"{self.get_kind()}(ID: {str(self.id)})"
|
|
155
162
|
|
|
156
|
-
def __init__(self, schema: Union[NodeSchema, ProfileSchema], branch: Branch, at: Timestamp):
|
|
157
|
-
self._schema: Union[NodeSchema, ProfileSchema] = schema
|
|
163
|
+
def __init__(self, schema: Union[NodeSchema, ProfileSchema, TemplateSchema], branch: Branch, at: Timestamp):
|
|
164
|
+
self._schema: Union[NodeSchema, ProfileSchema, TemplateSchema] = schema
|
|
158
165
|
self._branch: Branch = branch
|
|
159
166
|
self._at: Timestamp = at
|
|
160
167
|
self._existing: bool = False
|
|
@@ -171,12 +178,20 @@ class Node(BaseNode, metaclass=BaseNodeMeta):
|
|
|
171
178
|
# Lists of attributes and relationships names
|
|
172
179
|
self._attributes: list[str] = []
|
|
173
180
|
self._relationships: list[str] = []
|
|
181
|
+
self._node_changelog: NodeChangelog | None = None
|
|
182
|
+
|
|
183
|
+
@property
|
|
184
|
+
def node_changelog(self) -> NodeChangelog:
|
|
185
|
+
if self._node_changelog:
|
|
186
|
+
return self._node_changelog
|
|
187
|
+
|
|
188
|
+
raise InitializationError("The node has not been saved so no changelog exists")
|
|
174
189
|
|
|
175
190
|
@overload
|
|
176
191
|
@classmethod
|
|
177
192
|
async def init(
|
|
178
193
|
cls,
|
|
179
|
-
schema: Union[NodeSchema, ProfileSchema, str],
|
|
194
|
+
schema: Union[NodeSchema, ProfileSchema, TemplateSchema, str],
|
|
180
195
|
db: InfrahubDatabase,
|
|
181
196
|
branch: Optional[Union[Branch, str]] = ...,
|
|
182
197
|
at: Optional[Union[Timestamp, str]] = ...,
|
|
@@ -195,7 +210,7 @@ class Node(BaseNode, metaclass=BaseNodeMeta):
|
|
|
195
210
|
@classmethod
|
|
196
211
|
async def init(
|
|
197
212
|
cls,
|
|
198
|
-
schema: Union[NodeSchema, ProfileSchema, str, type[SchemaProtocol]],
|
|
213
|
+
schema: Union[NodeSchema, ProfileSchema, TemplateSchema, str, type[SchemaProtocol]],
|
|
199
214
|
db: InfrahubDatabase,
|
|
200
215
|
branch: Optional[Union[Branch, str]] = None,
|
|
201
216
|
at: Optional[Union[Timestamp, str]] = None,
|
|
@@ -204,15 +219,17 @@ class Node(BaseNode, metaclass=BaseNodeMeta):
|
|
|
204
219
|
|
|
205
220
|
branch = await registry.get_branch(branch=branch, db=db)
|
|
206
221
|
|
|
207
|
-
if isinstance(schema,
|
|
222
|
+
if isinstance(schema, NodeSchema | ProfileSchema | TemplateSchema):
|
|
208
223
|
attrs["schema"] = schema
|
|
209
224
|
elif isinstance(schema, str):
|
|
210
225
|
# TODO need to raise a proper exception for this, right now it will raise a generic ValueError
|
|
211
226
|
attrs["schema"] = db.schema.get(name=schema, branch=branch)
|
|
212
|
-
elif hasattr(schema, "_is_runtime_protocol") and
|
|
227
|
+
elif hasattr(schema, "_is_runtime_protocol") and schema._is_runtime_protocol:
|
|
213
228
|
attrs["schema"] = db.schema.get(name=schema.__name__, branch=branch)
|
|
214
229
|
else:
|
|
215
|
-
raise ValueError(
|
|
230
|
+
raise ValueError(
|
|
231
|
+
f"Invalid schema provided {type(schema)}, expected NodeSchema, ProfileSchema or TemplateSchema"
|
|
232
|
+
)
|
|
216
233
|
|
|
217
234
|
attrs["branch"] = branch
|
|
218
235
|
attrs["at"] = Timestamp(at)
|
|
@@ -261,6 +278,56 @@ class Node(BaseNode, metaclass=BaseNodeMeta):
|
|
|
261
278
|
)
|
|
262
279
|
)
|
|
263
280
|
|
|
281
|
+
async def handle_object_template(self, fields: dict, db: InfrahubDatabase, errors: list) -> None:
|
|
282
|
+
"""Fill the `fields` parameters with values from an object template if one is in use."""
|
|
283
|
+
object_template_field = fields.get(OBJECT_TEMPLATE_RELATIONSHIP_NAME)
|
|
284
|
+
if not object_template_field:
|
|
285
|
+
return
|
|
286
|
+
|
|
287
|
+
try:
|
|
288
|
+
template: CoreObjectTemplate = await registry.manager.find_object(
|
|
289
|
+
db=db,
|
|
290
|
+
kind=self._schema.get_relationship(name=OBJECT_TEMPLATE_RELATIONSHIP_NAME).peer,
|
|
291
|
+
id=object_template_field.get("id"),
|
|
292
|
+
hfid=object_template_field.get("hfid"),
|
|
293
|
+
branch=self.get_branch_based_on_support_type(),
|
|
294
|
+
)
|
|
295
|
+
except NodeNotFoundError:
|
|
296
|
+
errors.append(
|
|
297
|
+
ValidationError(
|
|
298
|
+
{
|
|
299
|
+
f"{OBJECT_TEMPLATE_RELATIONSHIP_NAME}": (
|
|
300
|
+
"Unable to find the object template in the database "
|
|
301
|
+
f"'{object_template_field.get('id') or object_template_field.get('hfid')}'"
|
|
302
|
+
)
|
|
303
|
+
}
|
|
304
|
+
)
|
|
305
|
+
)
|
|
306
|
+
return
|
|
307
|
+
|
|
308
|
+
# Handle attributes, copy values from template
|
|
309
|
+
# Relationships handling in performed in GraphQL mutation to create nodes for relationships
|
|
310
|
+
for attribute_name in template._attributes:
|
|
311
|
+
if attribute_name in list(fields) + [OBJECT_TEMPLATE_NAME_ATTR]:
|
|
312
|
+
continue
|
|
313
|
+
fields[attribute_name] = {"value": getattr(template, attribute_name).value, "source": template.id}
|
|
314
|
+
|
|
315
|
+
for relationship_name in template._relationships:
|
|
316
|
+
relationship_schema = template._schema.get_relationship(name=relationship_name)
|
|
317
|
+
if (
|
|
318
|
+
relationship_name in list(fields)
|
|
319
|
+
or relationship_schema.kind not in [RelationshipKind.ATTRIBUTE, RelationshipKind.GENERIC]
|
|
320
|
+
or relationship_name == OBJECT_TEMPLATE_RELATIONSHIP_NAME
|
|
321
|
+
):
|
|
322
|
+
continue
|
|
323
|
+
|
|
324
|
+
relationship: RelationshipManager = getattr(template, relationship_name)
|
|
325
|
+
if relationship_schema.cardinality == RelationshipCardinality.ONE:
|
|
326
|
+
if relationship_peer := await relationship.get_peer(db=db):
|
|
327
|
+
fields[relationship_name] = {"id": relationship_peer.id}
|
|
328
|
+
elif relationship_peers := await relationship.get_peers(db=db):
|
|
329
|
+
fields[relationship_name] = [{"id": peer_id} for peer_id in relationship_peers]
|
|
330
|
+
|
|
264
331
|
async def _process_fields(self, fields: dict, db: InfrahubDatabase) -> None:
|
|
265
332
|
errors = []
|
|
266
333
|
|
|
@@ -279,6 +346,9 @@ class Node(BaseNode, metaclass=BaseNodeMeta):
|
|
|
279
346
|
if field_name not in self._schema.valid_input_names:
|
|
280
347
|
errors.append(ValidationError({field_name: f"{field_name} is not a valid input for {self.get_kind()}"}))
|
|
281
348
|
|
|
349
|
+
# Backfill fields with the ones from the template if there's one
|
|
350
|
+
await self.handle_object_template(fields=fields, db=db, errors=errors)
|
|
351
|
+
|
|
282
352
|
# If the object is new, we need to ensure that all mandatory attributes and relationships have been provided
|
|
283
353
|
if not self._existing:
|
|
284
354
|
for mandatory_attr in self._schema.mandatory_attribute_names:
|
|
@@ -440,7 +510,7 @@ class Node(BaseNode, metaclass=BaseNodeMeta):
|
|
|
440
510
|
|
|
441
511
|
async def _generate_relationship_default(
|
|
442
512
|
self,
|
|
443
|
-
name: str, #
|
|
513
|
+
name: str, # noqa: ARG002
|
|
444
514
|
schema: RelationshipSchema,
|
|
445
515
|
data: Any,
|
|
446
516
|
db: InfrahubDatabase,
|
|
@@ -461,7 +531,7 @@ class Node(BaseNode, metaclass=BaseNodeMeta):
|
|
|
461
531
|
name: str,
|
|
462
532
|
schema: AttributeSchema,
|
|
463
533
|
data: Any,
|
|
464
|
-
db: InfrahubDatabase, #
|
|
534
|
+
db: InfrahubDatabase, # noqa: ARG002
|
|
465
535
|
) -> BaseAttribute:
|
|
466
536
|
attr_class = ATTRIBUTE_TYPES[schema.kind].get_infrahub_class()
|
|
467
537
|
attr = attr_class(
|
|
@@ -476,10 +546,9 @@ class Node(BaseNode, metaclass=BaseNodeMeta):
|
|
|
476
546
|
)
|
|
477
547
|
return attr
|
|
478
548
|
|
|
479
|
-
async def process_label(self, db: Optional[InfrahubDatabase] = None) -> None: #
|
|
549
|
+
async def process_label(self, db: Optional[InfrahubDatabase] = None) -> None: # noqa: ARG002
|
|
480
550
|
# If there label and name are both defined for this node
|
|
481
551
|
# if label is not define, we'll automatically populate it with a human friendy vesion of name
|
|
482
|
-
# pylint: disable=no-member
|
|
483
552
|
if not self._existing and hasattr(self, "label") and hasattr(self, "name"):
|
|
484
553
|
if self.label.value is None and self.name.value:
|
|
485
554
|
self.label.value = " ".join([word.title() for word in self.name.value.split("_")])
|
|
@@ -526,7 +595,7 @@ class Node(BaseNode, metaclass=BaseNodeMeta):
|
|
|
526
595
|
await self._process_fields(db=db, fields=kwargs)
|
|
527
596
|
return self
|
|
528
597
|
|
|
529
|
-
async def _create(self, db: InfrahubDatabase, at:
|
|
598
|
+
async def _create(self, db: InfrahubDatabase, at: Timestamp | None = None) -> NodeChangelog:
|
|
530
599
|
create_at = Timestamp(at)
|
|
531
600
|
|
|
532
601
|
query = await NodeCreateAllQuery.init(db=db, node=self, at=create_at)
|
|
@@ -538,44 +607,63 @@ class Node(BaseNode, metaclass=BaseNodeMeta):
|
|
|
538
607
|
self._existing = True
|
|
539
608
|
|
|
540
609
|
new_ids = query.get_ids()
|
|
610
|
+
node_changelog = NodeChangelog(node_id=self.get_id(), node_kind=self.get_kind(), display_label="")
|
|
541
611
|
|
|
542
612
|
# Go over the list of Attribute and assign the new IDs one by one
|
|
543
613
|
for name in self._attributes:
|
|
544
614
|
attr: BaseAttribute = getattr(self, name)
|
|
545
615
|
attr.id, attr.db_id = new_ids[name]
|
|
546
616
|
attr.at = create_at
|
|
617
|
+
node_changelog.create_attribute(attribute=attr)
|
|
547
618
|
|
|
548
619
|
# Go over the list of relationships and assign the new IDs one by one
|
|
549
620
|
for name in self._relationships:
|
|
550
621
|
relm: RelationshipManager = getattr(self, name)
|
|
551
622
|
for rel in relm._relationships:
|
|
552
623
|
identifier = f"{rel.schema.identifier}::{rel.peer_id}"
|
|
624
|
+
|
|
553
625
|
rel.id, rel.db_id = new_ids[identifier]
|
|
554
626
|
|
|
627
|
+
node_changelog.create_relationship(relationship=rel)
|
|
628
|
+
|
|
629
|
+
node_changelog.display_label = await self.render_display_label(db=db)
|
|
630
|
+
return node_changelog
|
|
631
|
+
|
|
555
632
|
async def _update(
|
|
556
633
|
self, db: InfrahubDatabase, at: Optional[Timestamp] = None, fields: list[str] | None = None
|
|
557
|
-
) ->
|
|
634
|
+
) -> NodeChangelog:
|
|
558
635
|
"""Update the node in the database if needed."""
|
|
559
636
|
|
|
560
637
|
update_at = Timestamp(at)
|
|
638
|
+
node_changelog = NodeChangelog(node_id=self.get_id(), node_kind=self.get_kind(), display_label="")
|
|
561
639
|
|
|
562
640
|
# Go over the list of Attribute and update them one by one
|
|
563
641
|
for name in self._attributes:
|
|
564
|
-
if fields and name in fields:
|
|
642
|
+
if (fields and name in fields) or not fields:
|
|
565
643
|
attr: BaseAttribute = getattr(self, name)
|
|
566
|
-
await attr.save(at=update_at, db=db)
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
await attr.save(at=update_at, db=db)
|
|
644
|
+
updated_attribute = await attr.save(at=update_at, db=db)
|
|
645
|
+
if updated_attribute:
|
|
646
|
+
node_changelog.add_attribute(attribute=updated_attribute)
|
|
570
647
|
|
|
571
648
|
# Go over the list of relationships and update them one by one
|
|
649
|
+
processed_relationships: list[str] = []
|
|
572
650
|
for name in self._relationships:
|
|
573
|
-
if fields and name in fields:
|
|
651
|
+
if (fields and name in fields) or not fields:
|
|
652
|
+
processed_relationships.append(name)
|
|
574
653
|
rel: RelationshipManager = getattr(self, name)
|
|
575
|
-
await rel.save(at=update_at, db=db)
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
654
|
+
updated_relationship = await rel.save(at=update_at, db=db)
|
|
655
|
+
node_changelog.add_relationship(relationship_changelog=updated_relationship)
|
|
656
|
+
|
|
657
|
+
if len(processed_relationships) != len(self._relationships):
|
|
658
|
+
# Analyze if the node has a parent and add it to the changelog if missing
|
|
659
|
+
if parent_relationship := self._get_parent_relationship_name():
|
|
660
|
+
if parent_relationship not in processed_relationships:
|
|
661
|
+
rel: RelationshipManager = getattr(self, parent_relationship)
|
|
662
|
+
if parent := await rel.get_parent(db=db):
|
|
663
|
+
node_changelog.add_parent_from_relationship(parent=parent)
|
|
664
|
+
|
|
665
|
+
node_changelog.display_label = await self.render_display_label(db=db)
|
|
666
|
+
return node_changelog
|
|
579
667
|
|
|
580
668
|
async def save(self, db: InfrahubDatabase, at: Optional[Timestamp] = None, fields: list[str] | None = None) -> Self:
|
|
581
669
|
"""Create or Update the Node in the database."""
|
|
@@ -583,10 +671,10 @@ class Node(BaseNode, metaclass=BaseNodeMeta):
|
|
|
583
671
|
save_at = Timestamp(at)
|
|
584
672
|
|
|
585
673
|
if self._existing:
|
|
586
|
-
await self._update(at=save_at, db=db, fields=fields)
|
|
674
|
+
self._node_changelog = await self._update(at=save_at, db=db, fields=fields)
|
|
587
675
|
return self
|
|
588
676
|
|
|
589
|
-
await self._create(at=save_at, db=db)
|
|
677
|
+
self._node_changelog = await self._create(at=save_at, db=db)
|
|
590
678
|
return self
|
|
591
679
|
|
|
592
680
|
async def delete(self, db: InfrahubDatabase, at: Optional[Timestamp] = None) -> None:
|
|
@@ -594,20 +682,27 @@ class Node(BaseNode, metaclass=BaseNodeMeta):
|
|
|
594
682
|
|
|
595
683
|
delete_at = Timestamp(at)
|
|
596
684
|
|
|
685
|
+
node_changelog = NodeChangelog(
|
|
686
|
+
node_id=self.get_id(), node_kind=self.get_kind(), display_label=await self.render_display_label(db=db)
|
|
687
|
+
)
|
|
597
688
|
# Go over the list of Attribute and update them one by one
|
|
598
689
|
for name in self._attributes:
|
|
599
690
|
attr: BaseAttribute = getattr(self, name)
|
|
600
|
-
await attr.delete(at=delete_at, db=db)
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
for name in self._relationships:
|
|
604
|
-
rel: RelationshipManager = getattr(self, name)
|
|
605
|
-
await rel.delete(at=delete_at, db=db)
|
|
691
|
+
deleted_attribute = await attr.delete(at=delete_at, db=db)
|
|
692
|
+
if deleted_attribute:
|
|
693
|
+
node_changelog.add_attribute(attribute=deleted_attribute)
|
|
606
694
|
|
|
607
|
-
# Need to check if there are some unidirectional relationship as well
|
|
608
|
-
# For example, if we delete a tag, we must check the permissions and update all the relationships pointing at it
|
|
609
695
|
branch = self.get_branch_based_on_support_type()
|
|
610
696
|
|
|
697
|
+
delete_query = await RelationshipDeleteAllQuery.init(
|
|
698
|
+
db=db, node_id=self.get_id(), branch=branch, at=delete_at, branch_agnostic=branch.name == GLOBAL_BRANCH_NAME
|
|
699
|
+
)
|
|
700
|
+
await delete_query.execute(db=db)
|
|
701
|
+
|
|
702
|
+
deleted_relationships_changelogs = delete_query.get_deleted_relationships_changelog(self._schema)
|
|
703
|
+
for relationship_changelog in deleted_relationships_changelogs:
|
|
704
|
+
node_changelog.add_relationship(relationship_changelog=relationship_changelog)
|
|
705
|
+
|
|
611
706
|
# Update the relationship to the branch itself
|
|
612
707
|
query = await NodeGetListQuery.init(
|
|
613
708
|
db=db,
|
|
@@ -625,6 +720,7 @@ class Node(BaseNode, metaclass=BaseNodeMeta):
|
|
|
625
720
|
|
|
626
721
|
query = await NodeDeleteQuery.init(db=db, node=self, at=delete_at)
|
|
627
722
|
await query.execute(db=db)
|
|
723
|
+
self._node_changelog = node_changelog
|
|
628
724
|
|
|
629
725
|
async def to_graphql(
|
|
630
726
|
self,
|
|
@@ -633,6 +729,7 @@ class Node(BaseNode, metaclass=BaseNodeMeta):
|
|
|
633
729
|
related_node_ids: set | None = None,
|
|
634
730
|
filter_sensitive: bool = False,
|
|
635
731
|
permissions: dict | None = None,
|
|
732
|
+
include_properties: bool = True,
|
|
636
733
|
) -> dict:
|
|
637
734
|
"""Generate GraphQL Payload for all attributes
|
|
638
735
|
|
|
@@ -686,10 +783,14 @@ class Node(BaseNode, metaclass=BaseNodeMeta):
|
|
|
686
783
|
related_node_ids=related_node_ids,
|
|
687
784
|
filter_sensitive=filter_sensitive,
|
|
688
785
|
permissions=permissions,
|
|
786
|
+
include_properties=include_properties,
|
|
689
787
|
)
|
|
690
788
|
else:
|
|
691
789
|
response[field_name] = await field.to_graphql(
|
|
692
|
-
db=db,
|
|
790
|
+
db=db,
|
|
791
|
+
filter_sensitive=filter_sensitive,
|
|
792
|
+
permissions=permissions,
|
|
793
|
+
include_properties=include_properties,
|
|
693
794
|
)
|
|
694
795
|
|
|
695
796
|
for relationship_schema in self.get_schema().relationships:
|
|
@@ -731,7 +832,7 @@ class Node(BaseNode, metaclass=BaseNodeMeta):
|
|
|
731
832
|
|
|
732
833
|
return changed
|
|
733
834
|
|
|
734
|
-
async def render_display_label(self, db: Optional[InfrahubDatabase] = None) -> str: #
|
|
835
|
+
async def render_display_label(self, db: Optional[InfrahubDatabase] = None) -> str: # noqa: ARG002
|
|
735
836
|
if not self._schema.display_labels:
|
|
736
837
|
return repr(self)
|
|
737
838
|
|
|
@@ -757,3 +858,26 @@ class Node(BaseNode, metaclass=BaseNodeMeta):
|
|
|
757
858
|
if not display_label.strip():
|
|
758
859
|
return repr(self)
|
|
759
860
|
return display_label.strip()
|
|
861
|
+
|
|
862
|
+
def _get_parent_relationship_name(self) -> str | None:
|
|
863
|
+
"""Return the name of the parent relationship is one is present"""
|
|
864
|
+
for relationship in self._schema.relationships:
|
|
865
|
+
if relationship.kind == RelationshipKind.PARENT:
|
|
866
|
+
return relationship.name
|
|
867
|
+
|
|
868
|
+
async def get_object_template(self, db: InfrahubDatabase) -> Node | None:
|
|
869
|
+
object_template: RelationshipManager = getattr(self, OBJECT_TEMPLATE_RELATIONSHIP_NAME, None)
|
|
870
|
+
return await object_template.get_peer(db=db) if object_template is not None else None
|
|
871
|
+
|
|
872
|
+
def get_relationships(
|
|
873
|
+
self, kind: RelationshipKind, exclude: Sequence[str] | None = None
|
|
874
|
+
) -> list[RelationshipSchema]:
|
|
875
|
+
"""Return relationships of a given kind with the possiblity to exclude some of them by name."""
|
|
876
|
+
if exclude is None:
|
|
877
|
+
exclude = []
|
|
878
|
+
|
|
879
|
+
return [
|
|
880
|
+
relationship
|
|
881
|
+
for relationship in self.get_schema().relationships
|
|
882
|
+
if relationship.name not in exclude and relationship.kind == kind
|
|
883
|
+
]
|
infrahub/core/node/base.py
CHANGED
|
@@ -21,7 +21,7 @@ class BaseOptions:
|
|
|
21
21
|
if not self._frozen:
|
|
22
22
|
super().__setattr__(name, value)
|
|
23
23
|
else:
|
|
24
|
-
raise Exception(f"Can't modify frozen Options {self}")
|
|
24
|
+
raise Exception(f"Can't modify frozen Options {self}")
|
|
25
25
|
|
|
26
26
|
def __repr__(self):
|
|
27
27
|
return f"<{self.__class__.__name__} name={repr(self.name)}>"
|
|
@@ -35,7 +35,7 @@ class NodeGroupedUniquenessConstraint(NodeConstraintInterface):
|
|
|
35
35
|
self.branch = branch
|
|
36
36
|
self.schema_branch = registry.schema.get_schema_branch(branch.name)
|
|
37
37
|
|
|
38
|
-
def _build_query_request(
|
|
38
|
+
async def _build_query_request(
|
|
39
39
|
self,
|
|
40
40
|
updated_node: Node,
|
|
41
41
|
node_schema: MainSchemaTypes,
|
|
@@ -51,9 +51,16 @@ class NodeGroupedUniquenessConstraint(NodeConstraintInterface):
|
|
|
51
51
|
if attribute_path.related_schema and attribute_path.relationship_schema:
|
|
52
52
|
if filters and attribute_path.relationship_schema.name in filters:
|
|
53
53
|
include_in_query = True
|
|
54
|
+
|
|
55
|
+
relationship_manager: RelationshipManager = getattr(
|
|
56
|
+
updated_node, attribute_path.relationship_schema.name
|
|
57
|
+
)
|
|
58
|
+
related_node = await relationship_manager.get_peer(db=self.db)
|
|
59
|
+
related_node_id = related_node.get_id() if related_node else None
|
|
54
60
|
query_relationship_paths.add(
|
|
55
61
|
QueryRelationshipAttributePath(
|
|
56
62
|
identifier=attribute_path.relationship_schema.get_identifier(),
|
|
63
|
+
value=related_node_id,
|
|
57
64
|
)
|
|
58
65
|
)
|
|
59
66
|
continue
|
|
@@ -158,7 +165,7 @@ class NodeGroupedUniquenessConstraint(NodeConstraintInterface):
|
|
|
158
165
|
) -> None:
|
|
159
166
|
schema_branch = self.db.schema.get_schema_branch(name=self.branch.name)
|
|
160
167
|
path_groups = node_schema.get_unique_constraint_schema_attribute_paths(schema_branch=schema_branch)
|
|
161
|
-
query_request = self._build_query_request(
|
|
168
|
+
query_request = await self._build_query_request(
|
|
162
169
|
updated_node=node, node_schema=node_schema, path_groups=path_groups, filters=filters
|
|
163
170
|
)
|
|
164
171
|
if not query_request:
|
|
@@ -11,7 +11,7 @@ from infrahub.core.query.relationship import (
|
|
|
11
11
|
RelationshipGetByIdentifierQuery,
|
|
12
12
|
RelationshipPeersData,
|
|
13
13
|
)
|
|
14
|
-
from infrahub.core.schema import MainSchemaTypes, NodeSchema, ProfileSchema
|
|
14
|
+
from infrahub.core.schema import MainSchemaTypes, NodeSchema, ProfileSchema, TemplateSchema
|
|
15
15
|
from infrahub.core.timestamp import Timestamp
|
|
16
16
|
from infrahub.database import InfrahubDatabase
|
|
17
17
|
from infrahub.exceptions import ValidationError
|
|
@@ -28,7 +28,7 @@ class NodeDeleteIndex:
|
|
|
28
28
|
# {node_schema: {DeleteRelationshipType: {relationship_identifier: peer_node_schema}}}
|
|
29
29
|
self._dependency_graph: dict[str, dict[DeleteRelationshipType, dict[str, set[str]]]] = {}
|
|
30
30
|
|
|
31
|
-
def index(self, start_schemas: Iterable[NodeSchema | ProfileSchema]) -> None:
|
|
31
|
+
def index(self, start_schemas: Iterable[NodeSchema | ProfileSchema | TemplateSchema]) -> None:
|
|
32
32
|
self._index_cascading_deletes(start_schemas=start_schemas)
|
|
33
33
|
self._index_dependent_schema(start_schemas=start_schemas)
|
|
34
34
|
|
|
@@ -50,7 +50,7 @@ class NodeDeleteIndex:
|
|
|
50
50
|
self._dependency_graph[kind][relationship_type] = defaultdict(set)
|
|
51
51
|
self._dependency_graph[kind][relationship_type][relationship_identifier].update(peer_kinds)
|
|
52
52
|
|
|
53
|
-
def _index_cascading_deletes(self, start_schemas: Iterable[NodeSchema | ProfileSchema]) -> None:
|
|
53
|
+
def _index_cascading_deletes(self, start_schemas: Iterable[NodeSchema | ProfileSchema | TemplateSchema]) -> None:
|
|
54
54
|
kinds_to_check: set[str] = {schema.kind for schema in start_schemas}
|
|
55
55
|
while True:
|
|
56
56
|
try:
|
|
@@ -72,7 +72,7 @@ class NodeDeleteIndex:
|
|
|
72
72
|
if peer_kind not in self._dependency_graph:
|
|
73
73
|
kinds_to_check.add(peer_kind)
|
|
74
74
|
|
|
75
|
-
def _index_dependent_schema(self, start_schemas: Iterable[NodeSchema | ProfileSchema]) -> None:
|
|
75
|
+
def _index_dependent_schema(self, start_schemas: Iterable[NodeSchema | ProfileSchema | TemplateSchema]) -> None:
|
|
76
76
|
start_schema_kinds: set[str] = set()
|
|
77
77
|
for start_schema in start_schemas:
|
|
78
78
|
start_schema_kinds.add(start_schema.kind)
|
infrahub/core/node/ipam.py
CHANGED
|
@@ -19,10 +19,15 @@ class BuiltinIPPrefix(Node):
|
|
|
19
19
|
fields: Optional[dict] = None,
|
|
20
20
|
related_node_ids: Optional[set] = None,
|
|
21
21
|
filter_sensitive: bool = False,
|
|
22
|
-
permissions: Optional[dict] = None,
|
|
22
|
+
permissions: Optional[dict] = None, # noqa: ARG002
|
|
23
|
+
include_properties: bool = True,
|
|
23
24
|
) -> dict:
|
|
24
25
|
response = await super().to_graphql(
|
|
25
|
-
db,
|
|
26
|
+
db,
|
|
27
|
+
fields=fields,
|
|
28
|
+
related_node_ids=related_node_ids,
|
|
29
|
+
filter_sensitive=filter_sensitive,
|
|
30
|
+
include_properties=include_properties,
|
|
26
31
|
)
|
|
27
32
|
|
|
28
33
|
if fields:
|
|
@@ -35,8 +40,8 @@ class BuiltinIPPrefix(Node):
|
|
|
35
40
|
retrieved = await NodeManager.get_one(
|
|
36
41
|
db=db, branch=self._branch, id=self.id, fields={"member_type": None, "prefix": None}
|
|
37
42
|
)
|
|
38
|
-
self.member_type = retrieved.member_type # type: ignore[union-attr]
|
|
39
|
-
self.prefix = retrieved.prefix # type: ignore[union-attr]
|
|
43
|
+
self.member_type = retrieved.member_type # type: ignore[union-attr]
|
|
44
|
+
self.prefix = retrieved.prefix # type: ignore[union-attr]
|
|
40
45
|
utilization_getter = PrefixUtilizationGetter(db=db, ip_prefixes=[self])
|
|
41
46
|
utilization = await utilization_getter.get_use_percentage(
|
|
42
47
|
ip_prefixes=[self], branch_names=[self._branch.name]
|
|
@@ -46,12 +51,12 @@ class BuiltinIPPrefix(Node):
|
|
|
46
51
|
return response
|
|
47
52
|
|
|
48
53
|
async def get_resource_weight(self, db: InfrahubDatabase) -> int:
|
|
49
|
-
member_type = self.member_type.value # type: ignore[has-type]
|
|
50
|
-
prefixlen = self.prefix.prefixlen # type: ignore[has-type]
|
|
54
|
+
member_type = self.member_type.value # type: ignore[has-type]
|
|
55
|
+
prefixlen = self.prefix.prefixlen # type: ignore[has-type]
|
|
51
56
|
if member_type is None or prefixlen is None:
|
|
52
57
|
retrieved = await NodeManager.get_one(
|
|
53
58
|
db=db, branch=self._branch, id=self.id, fields={"member_type": None, "prefix": None}
|
|
54
59
|
)
|
|
55
|
-
self.member_type = retrieved.member_type # type: ignore[union-attr]
|
|
56
|
-
self.prefix = retrieved.prefix # type: ignore[union-attr]
|
|
60
|
+
self.member_type = retrieved.member_type # type: ignore[union-attr]
|
|
61
|
+
self.prefix = retrieved.prefix # type: ignore[union-attr]
|
|
57
62
|
return get_prefix_space(self)
|