infrahub-server 1.1.6__py3-none-any.whl → 1.2.0b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- infrahub/api/artifact.py +16 -4
- infrahub/api/dependencies.py +8 -0
- infrahub/api/oauth2.py +0 -1
- infrahub/api/oidc.py +0 -1
- infrahub/api/query.py +18 -7
- infrahub/api/schema.py +32 -6
- infrahub/api/transformation.py +12 -5
- infrahub/{message_bus/messages/check_artifact_create.py → artifacts/models.py} +5 -3
- infrahub/{message_bus/operations/check/artifact.py → artifacts/tasks.py} +26 -25
- infrahub/cli/__init__.py +0 -2
- infrahub/cli/db.py +6 -7
- infrahub/cli/events.py +8 -3
- infrahub/cli/git_agent.py +9 -7
- infrahub/cli/tasks.py +4 -6
- infrahub/computed_attribute/models.py +1 -1
- infrahub/computed_attribute/tasks.py +64 -17
- infrahub/computed_attribute/triggers.py +90 -0
- infrahub/config.py +1 -1
- infrahub/context.py +39 -0
- infrahub/core/account.py +5 -8
- infrahub/core/attribute.py +54 -22
- infrahub/core/branch/models.py +4 -4
- infrahub/core/branch/tasks.py +137 -129
- infrahub/core/changelog/__init__.py +0 -0
- infrahub/core/changelog/diff.py +283 -0
- infrahub/core/changelog/models.py +499 -0
- infrahub/core/constants/__init__.py +43 -2
- infrahub/core/constants/infrahubkind.py +1 -0
- infrahub/core/constants/schema.py +2 -0
- infrahub/core/diff/combiner.py +12 -8
- infrahub/core/diff/coordinator.py +49 -70
- infrahub/core/diff/data_check_synchronizer.py +86 -7
- infrahub/core/diff/enricher/aggregated.py +3 -3
- infrahub/core/diff/enricher/cardinality_one.py +7 -7
- infrahub/core/diff/enricher/hierarchy.py +22 -7
- infrahub/core/diff/enricher/labels.py +19 -4
- infrahub/core/diff/enricher/path_identifier.py +7 -9
- infrahub/core/diff/enricher/summary_counts.py +3 -1
- infrahub/core/diff/merger/merger.py +8 -4
- infrahub/core/diff/model/path.py +76 -35
- infrahub/core/diff/parent_node_adder.py +78 -0
- infrahub/core/diff/payload_builder.py +13 -2
- infrahub/core/diff/query/all_conflicts.py +6 -3
- infrahub/core/diff/query/artifact.py +1 -1
- infrahub/core/diff/query/delete_query.py +1 -1
- infrahub/core/diff/query/diff_get.py +3 -2
- infrahub/core/diff/query/diff_summary.py +1 -1
- infrahub/core/diff/query/field_specifiers.py +3 -1
- infrahub/core/diff/query/field_summary.py +3 -2
- infrahub/core/diff/query/filters.py +14 -3
- infrahub/core/diff/query/get_conflict_query.py +1 -1
- infrahub/core/diff/query/has_conflicts_query.py +6 -3
- infrahub/core/diff/query/merge.py +3 -3
- infrahub/core/diff/query/{drop_tracking_id.py → merge_tracking_id.py} +4 -4
- infrahub/core/diff/query/roots_metadata.py +9 -2
- infrahub/core/diff/query/save.py +233 -142
- infrahub/core/diff/query/summary_counts_enricher.py +267 -0
- infrahub/core/diff/query/time_range_query.py +3 -2
- infrahub/core/diff/query/update_conflict_query.py +1 -1
- infrahub/core/diff/query_parser.py +49 -24
- infrahub/core/diff/repository/deserializer.py +32 -28
- infrahub/core/diff/repository/repository.py +215 -41
- infrahub/core/diff/tasks.py +13 -12
- infrahub/core/enums.py +1 -1
- infrahub/core/graph/__init__.py +1 -1
- infrahub/core/graph/index.py +3 -0
- infrahub/core/integrity/object_conflict/conflict_recorder.py +1 -1
- infrahub/core/ipam/reconciler.py +1 -1
- infrahub/core/ipam/tasks.py +2 -3
- infrahub/core/manager.py +20 -15
- infrahub/core/merge.py +5 -2
- infrahub/core/migrations/graph/__init__.py +4 -0
- infrahub/core/migrations/graph/m001_add_version_to_graph.py +1 -1
- infrahub/core/migrations/graph/m002_attribute_is_default.py +2 -2
- infrahub/core/migrations/graph/m003_relationship_parent_optional.py +2 -2
- infrahub/core/migrations/graph/m004_add_attr_documentation.py +1 -1
- infrahub/core/migrations/graph/m005_add_rel_read_only.py +1 -1
- infrahub/core/migrations/graph/m006_add_rel_on_delete.py +1 -1
- infrahub/core/migrations/graph/m007_add_rel_allow_override.py +1 -1
- infrahub/core/migrations/graph/m008_add_human_friendly_id.py +1 -1
- infrahub/core/migrations/graph/m009_add_generate_profile_attr.py +1 -1
- infrahub/core/migrations/graph/m010_add_generate_profile_attr_generic.py +1 -1
- infrahub/core/migrations/graph/m011_remove_profile_relationship_schema.py +2 -2
- infrahub/core/migrations/graph/m012_convert_account_generic.py +12 -23
- infrahub/core/migrations/graph/m013_convert_git_password_credential.py +7 -11
- infrahub/core/migrations/graph/m014_remove_index_attr_value.py +2 -2
- infrahub/core/migrations/graph/m015_diff_format_update.py +1 -1
- infrahub/core/migrations/graph/m016_diff_delete_bug_fix.py +1 -1
- infrahub/core/migrations/graph/m017_add_core_profile.py +1 -1
- infrahub/core/migrations/graph/m018_uniqueness_nulls.py +2 -2
- infrahub/core/migrations/graph/m019_restore_rels_to_time.py +256 -0
- infrahub/core/migrations/graph/m020_add_generate_template_attr.py +48 -0
- infrahub/core/migrations/query/attribute_add.py +1 -1
- infrahub/core/migrations/query/attribute_rename.py +1 -1
- infrahub/core/migrations/query/delete_element_in_schema.py +1 -1
- infrahub/core/migrations/query/node_duplicate.py +39 -19
- infrahub/core/migrations/query/relationship_duplicate.py +1 -1
- infrahub/core/migrations/query/schema_attribute_update.py +1 -1
- infrahub/core/migrations/schema/node_attribute_remove.py +1 -1
- infrahub/core/migrations/schema/node_remove.py +27 -13
- infrahub/core/migrations/schema/tasks.py +5 -5
- infrahub/core/migrations/shared.py +4 -4
- infrahub/core/models.py +7 -8
- infrahub/core/node/__init__.py +170 -46
- infrahub/core/node/base.py +1 -1
- infrahub/core/node/constraints/grouped_uniqueness.py +9 -2
- infrahub/core/node/delete_validator.py +4 -4
- infrahub/core/node/ipam.py +13 -8
- infrahub/core/node/permissions.py +4 -0
- infrahub/core/node/resource_manager/ip_prefix_pool.py +8 -5
- infrahub/core/node/standard.py +3 -5
- infrahub/core/property.py +1 -1
- infrahub/core/protocols.py +6 -0
- infrahub/core/protocols_base.py +4 -2
- infrahub/core/query/__init__.py +2 -5
- infrahub/core/query/attribute.py +9 -9
- infrahub/core/query/branch.py +5 -5
- infrahub/core/query/delete.py +1 -1
- infrahub/core/query/diff.py +45 -7
- infrahub/core/query/ipam.py +4 -4
- infrahub/core/query/node.py +19 -14
- infrahub/core/query/relationship.py +213 -26
- infrahub/core/query/resource_manager.py +13 -11
- infrahub/core/query/standard_node.py +6 -6
- infrahub/core/query/task.py +3 -3
- infrahub/core/query/task_log.py +1 -1
- infrahub/core/query/utils.py +5 -5
- infrahub/core/registry.py +0 -2
- infrahub/core/relationship/constraints/count.py +1 -1
- infrahub/core/relationship/constraints/peer_kind.py +1 -1
- infrahub/core/relationship/model.py +76 -38
- infrahub/core/schema/__init__.py +6 -4
- infrahub/core/schema/attribute_schema.py +8 -0
- infrahub/core/schema/basenode_schema.py +13 -3
- infrahub/core/schema/definitions/core/__init__.py +153 -0
- infrahub/core/schema/definitions/core/account.py +168 -0
- infrahub/core/schema/definitions/core/artifact.py +127 -0
- infrahub/core/schema/definitions/core/builtin.py +21 -0
- infrahub/core/schema/definitions/core/check.py +60 -0
- infrahub/core/schema/definitions/core/generator.py +96 -0
- infrahub/core/schema/definitions/core/graphql_query.py +77 -0
- infrahub/core/schema/definitions/core/group.py +105 -0
- infrahub/core/schema/definitions/core/ipam.py +252 -0
- infrahub/core/schema/definitions/core/lineage.py +17 -0
- infrahub/core/schema/definitions/core/menu.py +46 -0
- infrahub/core/schema/definitions/core/permission.py +161 -0
- infrahub/core/schema/definitions/core/profile.py +29 -0
- infrahub/core/schema/definitions/core/propose_change.py +88 -0
- infrahub/core/schema/definitions/core/propose_change_comment.py +188 -0
- infrahub/core/schema/definitions/core/propose_change_validator.py +326 -0
- infrahub/core/schema/definitions/core/repository.py +280 -0
- infrahub/core/schema/definitions/core/resource_pool.py +180 -0
- infrahub/core/schema/definitions/core/template.py +12 -0
- infrahub/core/schema/definitions/core/transform.py +87 -0
- infrahub/core/schema/definitions/core/webhook.py +108 -0
- infrahub/core/schema/definitions/internal.py +16 -0
- infrahub/core/schema/generated/genericnode_schema.py +5 -0
- infrahub/core/schema/generated/node_schema.py +5 -0
- infrahub/core/schema/generic_schema.py +5 -1
- infrahub/core/schema/manager.py +45 -42
- infrahub/core/schema/node_schema.py +4 -0
- infrahub/core/schema/profile_schema.py +4 -0
- infrahub/core/schema/relationship_schema.py +10 -2
- infrahub/core/schema/schema_branch.py +260 -16
- infrahub/core/schema/template_schema.py +36 -0
- infrahub/core/task/user_task.py +7 -5
- infrahub/core/timestamp.py +3 -3
- infrahub/core/utils.py +3 -2
- infrahub/core/validators/attribute/choices.py +1 -1
- infrahub/core/validators/attribute/enum.py +1 -1
- infrahub/core/validators/attribute/kind.py +1 -1
- infrahub/core/validators/attribute/length.py +1 -1
- infrahub/core/validators/attribute/optional.py +1 -1
- infrahub/core/validators/attribute/regex.py +1 -1
- infrahub/core/validators/attribute/unique.py +1 -1
- infrahub/core/validators/checks_runner.py +37 -0
- infrahub/core/validators/node/generate_profile.py +1 -1
- infrahub/core/validators/node/hierarchy.py +1 -1
- infrahub/core/validators/query.py +1 -1
- infrahub/core/validators/relationship/count.py +1 -1
- infrahub/core/validators/relationship/optional.py +1 -1
- infrahub/core/validators/relationship/peer.py +1 -1
- infrahub/core/validators/tasks.py +8 -6
- infrahub/core/validators/uniqueness/query.py +20 -17
- infrahub/database/__init__.py +16 -2
- infrahub/database/memgraph.py +1 -1
- infrahub/dependencies/builder/constraint/grouped/node_runner.py +0 -2
- infrahub/dependencies/builder/diff/combiner.py +1 -1
- infrahub/dependencies/builder/diff/conflicts_enricher.py +1 -1
- infrahub/dependencies/builder/diff/coordinator.py +0 -2
- infrahub/dependencies/builder/diff/deserializer.py +4 -2
- infrahub/dependencies/builder/diff/enricher/hierarchy.py +3 -1
- infrahub/dependencies/builder/diff/enricher/summary_counts.py +1 -1
- infrahub/dependencies/builder/diff/parent_node_adder.py +8 -0
- infrahub/events/artifact_action.py +76 -0
- infrahub/events/branch_action.py +50 -21
- infrahub/events/group_action.py +117 -0
- infrahub/events/models.py +164 -51
- infrahub/events/node_action.py +70 -8
- infrahub/events/repository_action.py +8 -8
- infrahub/events/schema_action.py +21 -8
- infrahub/exceptions.py +9 -0
- infrahub/generators/models.py +1 -0
- infrahub/generators/tasks.py +34 -15
- infrahub/git/base.py +3 -5
- infrahub/git/constants.py +0 -1
- infrahub/git/integrator.py +60 -36
- infrahub/git/models.py +80 -1
- infrahub/git/repository.py +7 -8
- infrahub/git/tasks.py +432 -112
- infrahub/git_credential/helper.py +2 -3
- infrahub/graphql/analyzer.py +572 -11
- infrahub/graphql/app.py +34 -26
- infrahub/graphql/auth/query_permission_checker/anonymous_checker.py +5 -5
- infrahub/graphql/auth/query_permission_checker/default_branch_checker.py +4 -4
- infrahub/graphql/auth/query_permission_checker/merge_operation_checker.py +4 -4
- infrahub/graphql/auth/query_permission_checker/object_permission_checker.py +28 -35
- infrahub/graphql/auth/query_permission_checker/super_admin_checker.py +5 -5
- infrahub/graphql/context.py +33 -0
- infrahub/graphql/enums.py +1 -1
- infrahub/graphql/initialization.py +5 -1
- infrahub/graphql/loaders/node.py +2 -2
- infrahub/graphql/manager.py +63 -63
- infrahub/graphql/mutations/account.py +20 -13
- infrahub/graphql/mutations/artifact_definition.py +16 -12
- infrahub/graphql/mutations/branch.py +86 -40
- infrahub/graphql/mutations/computed_attribute.py +24 -13
- infrahub/graphql/mutations/diff.py +54 -14
- infrahub/graphql/mutations/diff_conflict.py +14 -8
- infrahub/graphql/mutations/generator.py +83 -0
- infrahub/graphql/mutations/graphql_query.py +19 -11
- infrahub/graphql/mutations/ipam.py +25 -23
- infrahub/graphql/mutations/main.py +243 -50
- infrahub/graphql/mutations/menu.py +10 -10
- infrahub/graphql/mutations/proposed_change.py +36 -28
- infrahub/graphql/mutations/relationship.py +343 -104
- infrahub/graphql/mutations/repository.py +41 -35
- infrahub/graphql/mutations/resource_manager.py +26 -26
- infrahub/graphql/mutations/schema.py +66 -33
- infrahub/graphql/mutations/tasks.py +16 -10
- infrahub/graphql/parser.py +1 -1
- infrahub/graphql/permissions.py +3 -10
- infrahub/graphql/queries/account.py +22 -18
- infrahub/graphql/queries/branch.py +6 -4
- infrahub/graphql/queries/diff/tree.py +63 -52
- infrahub/graphql/queries/event.py +115 -0
- infrahub/graphql/queries/internal.py +3 -3
- infrahub/graphql/queries/ipam.py +23 -18
- infrahub/graphql/queries/relationship.py +11 -10
- infrahub/graphql/queries/resource_manager.py +43 -27
- infrahub/graphql/queries/search.py +9 -8
- infrahub/graphql/queries/status.py +12 -9
- infrahub/graphql/queries/task.py +11 -9
- infrahub/graphql/resolvers/resolver.py +69 -43
- infrahub/graphql/resolvers/single_relationship.py +16 -10
- infrahub/graphql/schema.py +4 -0
- infrahub/graphql/subscription/__init__.py +1 -1
- infrahub/graphql/subscription/events.py +1 -1
- infrahub/graphql/subscription/graphql_query.py +8 -8
- infrahub/graphql/types/branch.py +2 -2
- infrahub/graphql/types/common.py +6 -1
- infrahub/graphql/types/context.py +12 -0
- infrahub/graphql/types/enums.py +2 -0
- infrahub/graphql/types/event.py +158 -0
- infrahub/graphql/types/interface.py +2 -2
- infrahub/graphql/types/node.py +3 -3
- infrahub/graphql/types/permission.py +2 -2
- infrahub/graphql/types/relationship.py +3 -3
- infrahub/graphql/types/standard_node.py +9 -11
- infrahub/graphql/utils.py +28 -182
- infrahub/groups/tasks.py +2 -3
- infrahub/lock.py +21 -21
- infrahub/menu/generator.py +0 -1
- infrahub/menu/menu.py +116 -138
- infrahub/menu/models.py +4 -4
- infrahub/message_bus/__init__.py +11 -13
- infrahub/message_bus/messages/__init__.py +0 -14
- infrahub/message_bus/messages/check_generator_run.py +1 -3
- infrahub/message_bus/messages/event_branch_merge.py +3 -0
- infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +6 -0
- infrahub/message_bus/messages/request_proposedchange_pipeline.py +2 -0
- infrahub/message_bus/messages/send_echo_request.py +1 -1
- infrahub/message_bus/operations/__init__.py +4 -13
- infrahub/message_bus/operations/check/__init__.py +2 -2
- infrahub/message_bus/operations/check/generator.py +1 -3
- infrahub/message_bus/operations/event/branch.py +7 -3
- infrahub/message_bus/operations/event/schema.py +1 -1
- infrahub/message_bus/operations/event/worker.py +0 -3
- infrahub/message_bus/operations/finalize/validator.py +1 -1
- infrahub/message_bus/operations/git/file.py +2 -2
- infrahub/message_bus/operations/git/repository.py +1 -1
- infrahub/message_bus/operations/requests/__init__.py +0 -4
- infrahub/message_bus/operations/requests/generator_definition.py +2 -4
- infrahub/message_bus/operations/requests/proposed_change.py +37 -20
- infrahub/message_bus/operations/send/echo.py +1 -1
- infrahub/message_bus/types.py +1 -1
- infrahub/permissions/__init__.py +2 -1
- infrahub/permissions/globals.py +15 -0
- infrahub/permissions/types.py +26 -0
- infrahub/pools/prefix.py +29 -165
- infrahub/prefect_server/__init__.py +0 -0
- infrahub/prefect_server/app.py +18 -0
- infrahub/prefect_server/database.py +20 -0
- infrahub/prefect_server/events.py +28 -0
- infrahub/prefect_server/models.py +46 -0
- infrahub/proposed_change/models.py +18 -1
- infrahub/proposed_change/tasks.py +195 -53
- infrahub/pytest_plugin.py +4 -4
- infrahub/server.py +13 -12
- infrahub/services/__init__.py +148 -63
- infrahub/services/adapters/cache/__init__.py +11 -11
- infrahub/services/adapters/cache/nats.py +42 -25
- infrahub/services/adapters/cache/redis.py +3 -11
- infrahub/services/adapters/event/__init__.py +10 -18
- infrahub/services/adapters/http/__init__.py +0 -5
- infrahub/services/adapters/http/httpx.py +22 -15
- infrahub/services/adapters/message_bus/__init__.py +25 -8
- infrahub/services/adapters/message_bus/local.py +9 -7
- infrahub/services/adapters/message_bus/nats.py +14 -8
- infrahub/services/adapters/message_bus/rabbitmq.py +23 -10
- infrahub/services/adapters/workflow/__init__.py +11 -8
- infrahub/services/adapters/workflow/local.py +27 -6
- infrahub/services/adapters/workflow/worker.py +23 -7
- infrahub/services/component.py +43 -40
- infrahub/services/protocols.py +7 -7
- infrahub/services/scheduler.py +30 -29
- infrahub/storage.py +2 -4
- infrahub/task_manager/constants.py +1 -1
- infrahub/task_manager/event.py +261 -0
- infrahub/task_manager/models.py +147 -3
- infrahub/task_manager/task.py +1 -1
- infrahub/tasks/artifact.py +19 -18
- infrahub/tasks/registry.py +1 -1
- infrahub/tasks/telemetry.py +13 -14
- infrahub/transformations/tasks.py +3 -5
- infrahub/trigger/__init__.py +0 -0
- infrahub/trigger/catalogue.py +16 -0
- infrahub/trigger/constants.py +9 -0
- infrahub/trigger/models.py +105 -0
- infrahub/trigger/tasks.py +91 -0
- infrahub/types.py +1 -1
- infrahub/utils.py +1 -1
- infrahub/webhook/constants.py +0 -2
- infrahub/webhook/models.py +161 -40
- infrahub/webhook/tasks.py +123 -202
- infrahub/webhook/triggers.py +27 -0
- infrahub/workers/infrahub_async.py +36 -25
- infrahub/workers/utils.py +63 -0
- infrahub/workflows/catalogue.py +71 -52
- infrahub/workflows/initialization.py +14 -8
- infrahub/workflows/models.py +28 -4
- infrahub/workflows/utils.py +1 -1
- infrahub_sdk/client.py +8 -0
- infrahub_sdk/ctl/branch.py +3 -2
- infrahub_sdk/ctl/check.py +3 -3
- infrahub_sdk/ctl/cli_commands.py +16 -11
- infrahub_sdk/ctl/exceptions.py +0 -6
- infrahub_sdk/ctl/exporter.py +1 -1
- infrahub_sdk/ctl/generator.py +5 -5
- infrahub_sdk/ctl/importer.py +3 -2
- infrahub_sdk/ctl/menu.py +1 -1
- infrahub_sdk/ctl/object.py +1 -1
- infrahub_sdk/ctl/repository.py +23 -15
- infrahub_sdk/ctl/schema.py +2 -2
- infrahub_sdk/ctl/utils.py +4 -19
- infrahub_sdk/ctl/validate.py +2 -1
- infrahub_sdk/exceptions.py +12 -0
- infrahub_sdk/generator.py +3 -0
- infrahub_sdk/node.py +4 -4
- infrahub_sdk/protocols.py +21 -8
- infrahub_sdk/schema/__init__.py +14 -2
- infrahub_sdk/schema/main.py +7 -0
- infrahub_sdk/task/__init__.py +1 -0
- infrahub_sdk/task/constants.py +3 -0
- infrahub_sdk/task/exceptions.py +25 -0
- infrahub_sdk/task/manager.py +545 -0
- infrahub_sdk/task/models.py +74 -0
- infrahub_sdk/timestamp.py +134 -33
- infrahub_sdk/utils.py +39 -1
- infrahub_sdk/yaml.py +2 -3
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0b1.dist-info}/METADATA +47 -12
- infrahub_server-1.2.0b1.dist-info/RECORD +725 -0
- infrahub_testcontainers/container.py +14 -6
- infrahub_testcontainers/docker-compose.test.yml +24 -5
- infrahub_testcontainers/haproxy.cfg +43 -0
- infrahub_testcontainers/helpers.py +85 -1
- infrahub/core/branch/constants.py +0 -2
- infrahub/core/schema/definitions/core.py +0 -2274
- infrahub/graphql/query.py +0 -52
- infrahub/message_bus/messages/check_repository_checkdefinition.py +0 -20
- infrahub/message_bus/messages/check_repository_mergeconflicts.py +0 -16
- infrahub/message_bus/messages/check_repository_usercheck.py +0 -26
- infrahub/message_bus/messages/request_artifactdefinition_check.py +0 -17
- infrahub/message_bus/messages/request_repository_checks.py +0 -12
- infrahub/message_bus/messages/request_repository_userchecks.py +0 -18
- infrahub/message_bus/operations/check/repository.py +0 -293
- infrahub/message_bus/operations/requests/artifact_definition.py +0 -148
- infrahub/message_bus/operations/requests/repository.py +0 -133
- infrahub/schema/constants.py +0 -1
- infrahub/schema/tasks.py +0 -76
- infrahub/services/adapters/database/__init__.py +0 -9
- infrahub_sdk/ctl/_file.py +0 -13
- infrahub_server-1.1.6.dist-info/RECORD +0 -681
- /infrahub/{schema → artifacts}/__init__.py +0 -0
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0b1.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0b1.dist-info}/WHEEL +0 -0
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.2.0b1.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Sequence, cast
|
|
2
|
+
|
|
3
|
+
from prefect.server.database import PrefectDBInterface, db_injector
|
|
4
|
+
from prefect.server.events.filters import EventFilter, EventNameFilter, EventOrder, EventRelatedFilter
|
|
5
|
+
from prefect.server.events.schemas.events import ReceivedEvent
|
|
6
|
+
from prefect.server.utilities.schemas import PrefectBaseModel
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from sqlalchemy.sql.expression import ColumnExpressionArgument
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class InfrahubEventFilter(EventFilter):
|
|
14
|
+
matching_related: list[EventRelatedFilter] = Field(default_factory=list)
|
|
15
|
+
|
|
16
|
+
def set_prefix(self) -> None:
|
|
17
|
+
if self.event:
|
|
18
|
+
if self.event.prefix is not None and "infrahub." not in self.event.prefix:
|
|
19
|
+
self.event.prefix.append("infrahub.")
|
|
20
|
+
else:
|
|
21
|
+
self.event = EventNameFilter(prefix=["infrahub."], name=[], exclude_prefix=None, exclude_name=None)
|
|
22
|
+
|
|
23
|
+
@db_injector
|
|
24
|
+
def build_where_clauses(self, db: PrefectDBInterface) -> Sequence["ColumnExpressionArgument[bool]"]:
|
|
25
|
+
result = cast(list["ColumnExpressionArgument[bool]"], super().build_where_clauses())
|
|
26
|
+
top_level_filter = self._scoped_event_resources(db)
|
|
27
|
+
for matching_related in self.matching_related:
|
|
28
|
+
matching_related._top_level_filter = top_level_filter
|
|
29
|
+
result.extend(matching_related.build_where_clauses())
|
|
30
|
+
|
|
31
|
+
return result
|
|
32
|
+
|
|
33
|
+
@classmethod
|
|
34
|
+
def default(cls) -> "InfrahubEventFilter":
|
|
35
|
+
return cls(event=None, any_resource=None, resource=None, related=None, order=EventOrder.DESC)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class InfrahubEventPage(PrefectBaseModel):
|
|
39
|
+
events: list[ReceivedEvent] = Field(..., description="The Events matching the query")
|
|
40
|
+
total: int = Field(..., description="The total number of matching Events")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class InfrahubEventfilterInput(BaseModel):
|
|
44
|
+
limit: int = Field(default=50)
|
|
45
|
+
filter: InfrahubEventFilter = Field(default_factory=InfrahubEventFilter.default)
|
|
46
|
+
offset: int | None = Field(default=None)
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
from pydantic import Field
|
|
1
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
2
2
|
|
|
3
|
+
from infrahub.context import InfrahubContext
|
|
3
4
|
from infrahub.message_bus.messages.proposed_change.base_with_diff import BaseProposedChangeWithDiffMessage
|
|
5
|
+
from infrahub.message_bus.types import ProposedChangeArtifactDefinition, ProposedChangeBranchDiff
|
|
4
6
|
|
|
5
7
|
|
|
6
8
|
class RequestProposedChangeDataIntegrity(BaseProposedChangeWithDiffMessage):
|
|
@@ -26,3 +28,18 @@ class RequestProposedChangeSchemaIntegrity(BaseProposedChangeWithDiffMessage):
|
|
|
26
28
|
|
|
27
29
|
class RequestProposedChangeUserTests(BaseProposedChangeWithDiffMessage):
|
|
28
30
|
"""Sent trigger to run tests (smoke, units, integrations) for a proposed change."""
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class RequestArtifactDefinitionCheck(BaseModel):
|
|
34
|
+
"""Sent to validate the generation of artifacts in relation to a proposed change."""
|
|
35
|
+
|
|
36
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
37
|
+
|
|
38
|
+
artifact_definition: ProposedChangeArtifactDefinition = Field(..., description="The Artifact Definition")
|
|
39
|
+
branch_diff: ProposedChangeBranchDiff = Field(..., description="The calculated diff between the two branches")
|
|
40
|
+
proposed_change: str = Field(..., description="The unique ID of the Proposed Change")
|
|
41
|
+
source_branch: str = Field(..., description="The source branch")
|
|
42
|
+
source_branch_sync_with_git: bool = Field(..., description="Indicates if the source branch should sync with git")
|
|
43
|
+
destination_branch: str = Field(..., description="The target branch")
|
|
44
|
+
|
|
45
|
+
context: InfrahubContext = Field(..., description="The context of the task")
|
|
@@ -17,28 +17,33 @@ from prefect.logging import get_run_logger
|
|
|
17
17
|
from prefect.states import Completed, Failed
|
|
18
18
|
|
|
19
19
|
from infrahub import config
|
|
20
|
+
from infrahub.artifacts.models import CheckArtifactCreate
|
|
21
|
+
from infrahub.context import InfrahubContext # noqa: TC001 needed for prefect flow
|
|
20
22
|
from infrahub.core import registry
|
|
21
23
|
from infrahub.core.branch import Branch
|
|
22
24
|
from infrahub.core.branch.tasks import merge_branch
|
|
23
|
-
from infrahub.core.constants import InfrahubKind, RepositoryInternalStatus, ValidatorConclusion
|
|
25
|
+
from infrahub.core.constants import InfrahubKind, RepositoryInternalStatus, ValidatorConclusion, ValidatorState
|
|
24
26
|
from infrahub.core.diff.coordinator import DiffCoordinator
|
|
25
27
|
from infrahub.core.diff.model.diff import DiffElementType, SchemaConflict
|
|
26
28
|
from infrahub.core.diff.model.path import NodeDiffFieldSummary
|
|
27
29
|
from infrahub.core.integrity.object_conflict.conflict_recorder import ObjectConflictValidatorRecorder
|
|
28
30
|
from infrahub.core.protocols import CoreDataCheck, CoreValidator
|
|
29
31
|
from infrahub.core.protocols import CoreProposedChange as InternalCoreProposedChange
|
|
32
|
+
from infrahub.core.validators.checks_runner import run_checks_and_update_validator
|
|
30
33
|
from infrahub.core.validators.determiner import ConstraintValidatorDeterminer
|
|
31
34
|
from infrahub.core.validators.models.validate_migration import SchemaValidateMigrationData
|
|
32
35
|
from infrahub.core.validators.tasks import schema_validate_migrations
|
|
33
36
|
from infrahub.dependencies.registry import get_component_registry
|
|
34
37
|
from infrahub.exceptions import MergeFailedError
|
|
35
38
|
from infrahub.generators.models import ProposedChangeGeneratorDefinition
|
|
39
|
+
from infrahub.git.models import TriggerRepositoryInternalChecks, TriggerRepositoryUserChecks
|
|
36
40
|
from infrahub.git.repository import get_initialized_repo
|
|
37
41
|
from infrahub.log import get_logger
|
|
38
42
|
from infrahub.message_bus import InfrahubMessage, messages
|
|
39
43
|
from infrahub.message_bus.operations.requests.proposed_change import DefinitionSelect
|
|
40
44
|
from infrahub.proposed_change.constants import ProposedChangeState
|
|
41
45
|
from infrahub.proposed_change.models import (
|
|
46
|
+
RequestArtifactDefinitionCheck,
|
|
42
47
|
RequestProposedChangeDataIntegrity,
|
|
43
48
|
RequestProposedChangeRepositoryChecks,
|
|
44
49
|
RequestProposedChangeRunGenerators,
|
|
@@ -46,8 +51,14 @@ from infrahub.proposed_change.models import (
|
|
|
46
51
|
RequestProposedChangeUserTests,
|
|
47
52
|
)
|
|
48
53
|
from infrahub.pytest_plugin import InfrahubBackendPlugin
|
|
49
|
-
from infrahub.services import
|
|
50
|
-
from infrahub.workflows.catalogue import
|
|
54
|
+
from infrahub.services import InfrahubServices # noqa: TC001 needed for prefect flow
|
|
55
|
+
from infrahub.workflows.catalogue import (
|
|
56
|
+
COMPUTED_ATTRIBUTE_SETUP_PYTHON,
|
|
57
|
+
GIT_REPOSITORIES_CHECK_ARTIFACT_CREATE,
|
|
58
|
+
GIT_REPOSITORY_INTERNAL_CHECKS_TRIGGER,
|
|
59
|
+
GIT_REPOSITORY_USER_CHECKS_TRIGGER,
|
|
60
|
+
REQUEST_PROPOSED_CHANGE_REPOSITORY_CHECKS,
|
|
61
|
+
)
|
|
51
62
|
from infrahub.workflows.utils import add_tags
|
|
52
63
|
|
|
53
64
|
if TYPE_CHECKING:
|
|
@@ -60,10 +71,10 @@ if TYPE_CHECKING:
|
|
|
60
71
|
|
|
61
72
|
async def _proposed_change_transition_state(
|
|
62
73
|
state: ProposedChangeState,
|
|
74
|
+
service: InfrahubServices,
|
|
63
75
|
proposed_change: InternalCoreProposedChange | None = None,
|
|
64
76
|
proposed_change_id: str | None = None,
|
|
65
77
|
) -> None:
|
|
66
|
-
service = services.service
|
|
67
78
|
async with service.database.start_session() as db:
|
|
68
79
|
if proposed_change is None and proposed_change_id:
|
|
69
80
|
proposed_change = await registry.manager.get_one(
|
|
@@ -96,8 +107,12 @@ async def _proposed_change_transition_state(
|
|
|
96
107
|
# on_crashed=[proposed_change_transition_open], # type: ignore
|
|
97
108
|
# on_cancellation=[proposed_change_transition_open], # type: ignore
|
|
98
109
|
)
|
|
99
|
-
async def merge_proposed_change(
|
|
100
|
-
|
|
110
|
+
async def merge_proposed_change(
|
|
111
|
+
proposed_change_id: str,
|
|
112
|
+
proposed_change_name: str, # noqa: ARG001
|
|
113
|
+
context: InfrahubContext,
|
|
114
|
+
service: InfrahubServices,
|
|
115
|
+
) -> State:
|
|
101
116
|
log = get_run_logger()
|
|
102
117
|
|
|
103
118
|
await add_tags(nodes=[proposed_change_id])
|
|
@@ -118,14 +133,16 @@ async def merge_proposed_change(proposed_change_id: str, proposed_change_name: s
|
|
|
118
133
|
and validation.conclusion.value.value != ValidatorConclusion.SUCCESS.value
|
|
119
134
|
):
|
|
120
135
|
# Ignoring Data integrity checks as they are handled again later
|
|
121
|
-
await _proposed_change_transition_state(
|
|
136
|
+
await _proposed_change_transition_state(
|
|
137
|
+
proposed_change=proposed_change, state=ProposedChangeState.OPEN, service=service
|
|
138
|
+
)
|
|
122
139
|
return Failed(message="Unable to merge proposed change containing failing checks")
|
|
123
140
|
if validator_kind == InfrahubKind.DATAVALIDATOR:
|
|
124
141
|
data_checks = await validation.checks.get_peers(db=db, peer_type=CoreDataCheck)
|
|
125
142
|
for check in data_checks.values():
|
|
126
143
|
if check.conflicts.value and not check.keep_branch.value:
|
|
127
144
|
await _proposed_change_transition_state(
|
|
128
|
-
proposed_change=proposed_change, state=ProposedChangeState.OPEN
|
|
145
|
+
proposed_change=proposed_change, state=ProposedChangeState.OPEN, service=service
|
|
129
146
|
)
|
|
130
147
|
return Failed(
|
|
131
148
|
message="Data conflicts found on branch and missing decisions about what branch to keep"
|
|
@@ -133,15 +150,19 @@ async def merge_proposed_change(proposed_change_id: str, proposed_change_name: s
|
|
|
133
150
|
|
|
134
151
|
log.info("Proposed change is eligible to be merged")
|
|
135
152
|
try:
|
|
136
|
-
await merge_branch(branch=source_branch.name)
|
|
153
|
+
await merge_branch(branch=source_branch.name, context=context, service=service)
|
|
137
154
|
except MergeFailedError as exc:
|
|
138
|
-
await _proposed_change_transition_state(
|
|
155
|
+
await _proposed_change_transition_state(
|
|
156
|
+
proposed_change=proposed_change, state=ProposedChangeState.OPEN, service=service
|
|
157
|
+
)
|
|
139
158
|
return Failed(message=f"Merge failure when trying to merge {exc.message}")
|
|
140
159
|
|
|
141
160
|
log.info(f"Branch {source_branch.name} has been merged successfully")
|
|
142
161
|
|
|
143
|
-
await _proposed_change_transition_state(
|
|
144
|
-
|
|
162
|
+
await _proposed_change_transition_state(
|
|
163
|
+
proposed_change=proposed_change, state=ProposedChangeState.MERGED, service=service
|
|
164
|
+
)
|
|
165
|
+
await service.workflow.submit_workflow(workflow=COMPUTED_ATTRIBUTE_SETUP_PYTHON, context=context)
|
|
145
166
|
return Completed(message="proposed change merged successfully")
|
|
146
167
|
|
|
147
168
|
|
|
@@ -150,9 +171,7 @@ async def merge_proposed_change(proposed_change_id: str, proposed_change_name: s
|
|
|
150
171
|
flow_run_name="Cancel all proposed change associated with branch {branch_name}",
|
|
151
172
|
description="Cancel all Proposed change associated with a branch.",
|
|
152
173
|
)
|
|
153
|
-
async def cancel_proposed_changes_branch(branch_name: str) -> None:
|
|
154
|
-
service = services.service
|
|
155
|
-
|
|
174
|
+
async def cancel_proposed_changes_branch(branch_name: str, service: InfrahubServices) -> None:
|
|
156
175
|
await add_tags(branches=[branch_name])
|
|
157
176
|
|
|
158
177
|
proposed_changed_opened = await service.client.filters(
|
|
@@ -169,13 +188,11 @@ async def cancel_proposed_changes_branch(branch_name: str) -> None:
|
|
|
169
188
|
)
|
|
170
189
|
|
|
171
190
|
for proposed_change in proposed_changed_opened + proposed_changed_closed:
|
|
172
|
-
await cancel_proposed_change(proposed_change=proposed_change)
|
|
173
|
-
|
|
191
|
+
await cancel_proposed_change(proposed_change=proposed_change, service=service)
|
|
174
192
|
|
|
175
|
-
@task(name="Cancel a propose change", description="Cancel a propose change", cache_policy=NONE)
|
|
176
|
-
async def cancel_proposed_change(proposed_change: CoreProposedChange) -> None:
|
|
177
|
-
service = services.service
|
|
178
193
|
|
|
194
|
+
@task(name="Cancel a propose change", description="Cancel a propose change", cache_policy=NONE) # type: ignore[arg-type]
|
|
195
|
+
async def cancel_proposed_change(proposed_change: CoreProposedChange, service: InfrahubServices) -> None:
|
|
179
196
|
await add_tags(nodes=[proposed_change.id])
|
|
180
197
|
log = get_run_logger()
|
|
181
198
|
|
|
@@ -189,11 +206,12 @@ async def cancel_proposed_change(proposed_change: CoreProposedChange) -> None:
|
|
|
189
206
|
name="proposed-changed-data-integrity",
|
|
190
207
|
flow_run_name="Triggers data integrity check",
|
|
191
208
|
)
|
|
192
|
-
async def run_proposed_change_data_integrity_check(
|
|
209
|
+
async def run_proposed_change_data_integrity_check(
|
|
210
|
+
model: RequestProposedChangeDataIntegrity, service: InfrahubServices
|
|
211
|
+
) -> None:
|
|
193
212
|
"""Triggers a data integrity validation check on the provided proposed change to start."""
|
|
194
213
|
await add_tags(branches=[model.source_branch], nodes=[model.proposed_change])
|
|
195
214
|
|
|
196
|
-
service = services.service
|
|
197
215
|
async with service.database.start_transaction() as dbt:
|
|
198
216
|
destination_branch = await registry.get_branch(db=dbt, branch=model.destination_branch)
|
|
199
217
|
source_branch = await registry.get_branch(db=dbt, branch=model.source_branch)
|
|
@@ -207,8 +225,9 @@ async def run_proposed_change_data_integrity_check(model: RequestProposedChangeD
|
|
|
207
225
|
name="proposed-changed-run-generator",
|
|
208
226
|
flow_run_name="Run generators",
|
|
209
227
|
)
|
|
210
|
-
async def run_generators(
|
|
211
|
-
|
|
228
|
+
async def run_generators(
|
|
229
|
+
model: RequestProposedChangeRunGenerators, context: InfrahubContext, service: InfrahubServices
|
|
230
|
+
) -> None:
|
|
212
231
|
await add_tags(branches=[model.source_branch], nodes=[model.proposed_change], db_change=True)
|
|
213
232
|
|
|
214
233
|
generators = await service.client.filters(
|
|
@@ -264,12 +283,13 @@ async def run_generators(model: RequestProposedChangeRunGenerators) -> None:
|
|
|
264
283
|
destination_branch=model.destination_branch,
|
|
265
284
|
)
|
|
266
285
|
msg.assign_meta(parent=model)
|
|
267
|
-
await service.send(message=msg)
|
|
286
|
+
await service.message_bus.send(message=msg)
|
|
268
287
|
|
|
269
288
|
next_messages: list[InfrahubMessage] = []
|
|
270
289
|
if model.refresh_artifacts:
|
|
271
290
|
next_messages.append(
|
|
272
291
|
messages.RequestProposedChangeRefreshArtifacts(
|
|
292
|
+
context=context,
|
|
273
293
|
proposed_change=model.proposed_change,
|
|
274
294
|
source_branch=model.source_branch,
|
|
275
295
|
source_branch_sync_with_git=model.source_branch_sync_with_git,
|
|
@@ -287,12 +307,14 @@ async def run_generators(model: RequestProposedChangeRunGenerators) -> None:
|
|
|
287
307
|
branch_diff=model.branch_diff,
|
|
288
308
|
)
|
|
289
309
|
await service.workflow.submit_workflow(
|
|
290
|
-
workflow=REQUEST_PROPOSED_CHANGE_REPOSITORY_CHECKS,
|
|
310
|
+
workflow=REQUEST_PROPOSED_CHANGE_REPOSITORY_CHECKS,
|
|
311
|
+
context=context,
|
|
312
|
+
parameters={"model": model_proposed_change_repo_checks},
|
|
291
313
|
)
|
|
292
314
|
|
|
293
315
|
for next_msg in next_messages:
|
|
294
316
|
next_msg.assign_meta(parent=model)
|
|
295
|
-
await service.send(message=next_msg)
|
|
317
|
+
await service.message_bus.send(message=next_msg)
|
|
296
318
|
|
|
297
319
|
|
|
298
320
|
@flow(
|
|
@@ -300,11 +322,10 @@ async def run_generators(model: RequestProposedChangeRunGenerators) -> None:
|
|
|
300
322
|
flow_run_name="Process schema integrity",
|
|
301
323
|
)
|
|
302
324
|
async def run_proposed_change_schema_integrity_check(
|
|
303
|
-
model: RequestProposedChangeSchemaIntegrity,
|
|
325
|
+
model: RequestProposedChangeSchemaIntegrity, service: InfrahubServices
|
|
304
326
|
) -> None:
|
|
305
327
|
# For now, we retrieve the latest schema for each branch from the registry
|
|
306
328
|
# In the future it would be good to generate the object SchemaUpdateValidationResult from message.branch_diff
|
|
307
|
-
service = services.service
|
|
308
329
|
await add_tags(branches=[model.source_branch], nodes=[model.proposed_change])
|
|
309
330
|
|
|
310
331
|
source_schema = registry.schema.get_schema_branch(name=model.source_branch).duplicate()
|
|
@@ -331,7 +352,8 @@ async def run_proposed_change_schema_integrity_check(
|
|
|
331
352
|
responses = await schema_validate_migrations(
|
|
332
353
|
message=SchemaValidateMigrationData(
|
|
333
354
|
branch=source_branch, schema_branch=candidate_schema, constraints=list(constraints)
|
|
334
|
-
)
|
|
355
|
+
),
|
|
356
|
+
service=service,
|
|
335
357
|
)
|
|
336
358
|
|
|
337
359
|
# TODO we need to report a failure if an error happened during the execution of a validator
|
|
@@ -393,48 +415,44 @@ async def _get_proposed_change_schema_integrity_constraints(
|
|
|
393
415
|
name="proposed-changed-repository-checks",
|
|
394
416
|
flow_run_name="Process user defined checks",
|
|
395
417
|
)
|
|
396
|
-
async def repository_checks(model: RequestProposedChangeRepositoryChecks) -> None:
|
|
397
|
-
service = services.service
|
|
418
|
+
async def repository_checks(model: RequestProposedChangeRepositoryChecks, service: InfrahubServices) -> None:
|
|
398
419
|
await add_tags(branches=[model.source_branch], nodes=[model.proposed_change])
|
|
399
420
|
|
|
400
|
-
events: list[InfrahubMessage] = []
|
|
401
421
|
for repository in model.branch_diff.repositories:
|
|
402
422
|
if (
|
|
403
423
|
model.source_branch_sync_with_git
|
|
404
424
|
and not repository.read_only
|
|
405
425
|
and repository.internal_status == RepositoryInternalStatus.ACTIVE.value
|
|
406
426
|
):
|
|
407
|
-
|
|
408
|
-
messages.RequestRepositoryChecks(
|
|
409
|
-
proposed_change=model.proposed_change,
|
|
410
|
-
repository=repository.repository_id,
|
|
411
|
-
source_branch=model.source_branch,
|
|
412
|
-
target_branch=model.destination_branch,
|
|
413
|
-
)
|
|
414
|
-
)
|
|
415
|
-
|
|
416
|
-
events.append(
|
|
417
|
-
messages.RequestRepositoryUserChecks(
|
|
427
|
+
trigger_internal_checks_model = TriggerRepositoryInternalChecks(
|
|
418
428
|
proposed_change=model.proposed_change,
|
|
419
|
-
|
|
420
|
-
repository_name=repository.repository_name,
|
|
429
|
+
repository=repository.repository_id,
|
|
421
430
|
source_branch=model.source_branch,
|
|
422
|
-
source_branch_sync_with_git=model.source_branch_sync_with_git,
|
|
423
431
|
target_branch=model.destination_branch,
|
|
424
|
-
branch_diff=model.branch_diff,
|
|
425
432
|
)
|
|
433
|
+
await service.workflow.submit_workflow(
|
|
434
|
+
workflow=GIT_REPOSITORY_INTERNAL_CHECKS_TRIGGER, parameters={"model": trigger_internal_checks_model}
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
trigger_user_checks_model = TriggerRepositoryUserChecks(
|
|
438
|
+
proposed_change=model.proposed_change,
|
|
439
|
+
repository_id=repository.repository_id,
|
|
440
|
+
repository_name=repository.repository_name,
|
|
441
|
+
source_branch=model.source_branch,
|
|
442
|
+
source_branch_sync_with_git=model.source_branch_sync_with_git,
|
|
443
|
+
target_branch=model.destination_branch,
|
|
444
|
+
branch_diff=model.branch_diff,
|
|
445
|
+
)
|
|
446
|
+
await service.workflow.submit_workflow(
|
|
447
|
+
workflow=GIT_REPOSITORY_USER_CHECKS_TRIGGER, parameters={"model": trigger_user_checks_model}
|
|
426
448
|
)
|
|
427
|
-
for event in events:
|
|
428
|
-
event.assign_meta(parent=model)
|
|
429
|
-
await service.send(message=event)
|
|
430
449
|
|
|
431
450
|
|
|
432
451
|
@flow(
|
|
433
452
|
name="proposed-changed-user-tests",
|
|
434
453
|
flow_run_name="Run unit tests in repositories",
|
|
435
454
|
)
|
|
436
|
-
async def run_proposed_change_user_tests(model: RequestProposedChangeUserTests) -> None:
|
|
437
|
-
service = services.service
|
|
455
|
+
async def run_proposed_change_user_tests(model: RequestProposedChangeUserTests, service: InfrahubServices) -> None:
|
|
438
456
|
log = get_run_logger()
|
|
439
457
|
await add_tags(branches=[model.source_branch], nodes=[model.proposed_change])
|
|
440
458
|
proposed_change = await service.client.get(kind=InfrahubKind.PROPOSEDCHANGE, id=model.proposed_change)
|
|
@@ -493,3 +511,127 @@ async def run_proposed_change_user_tests(model: RequestProposedChangeUserTests)
|
|
|
493
511
|
|
|
494
512
|
return_code = await asyncio.to_thread(_execute, worktree_directory, repository, proposed_change)
|
|
495
513
|
log.info(msg=f"repository_tests_completed return_code={return_code}")
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
@flow(
|
|
517
|
+
name="artifacts-generation-validation",
|
|
518
|
+
flow_run_name="Validating generation of artifacts for {model.artifact_definition.definition_name}",
|
|
519
|
+
)
|
|
520
|
+
async def validate_artifacts_generation(model: RequestArtifactDefinitionCheck, service: InfrahubServices) -> None:
|
|
521
|
+
await add_tags(branches=[model.source_branch], nodes=[model.proposed_change], db_change=True)
|
|
522
|
+
|
|
523
|
+
log = get_run_logger()
|
|
524
|
+
artifact_definition = await service.client.get(
|
|
525
|
+
kind=InfrahubKind.ARTIFACTDEFINITION,
|
|
526
|
+
id=model.artifact_definition.definition_id,
|
|
527
|
+
branch=model.source_branch,
|
|
528
|
+
)
|
|
529
|
+
proposed_change = await service.client.get(kind=InfrahubKind.PROPOSEDCHANGE, id=model.proposed_change)
|
|
530
|
+
|
|
531
|
+
validator_name = f"Artifact Validator: {model.artifact_definition.definition_name}"
|
|
532
|
+
|
|
533
|
+
await proposed_change.validations.fetch()
|
|
534
|
+
|
|
535
|
+
validator = None
|
|
536
|
+
for relationship in proposed_change.validations.peers:
|
|
537
|
+
existing_validator = relationship.peer
|
|
538
|
+
if (
|
|
539
|
+
existing_validator.typename == InfrahubKind.ARTIFACTVALIDATOR
|
|
540
|
+
and existing_validator.definition.id == model.artifact_definition.definition_id
|
|
541
|
+
):
|
|
542
|
+
validator = existing_validator
|
|
543
|
+
|
|
544
|
+
if validator:
|
|
545
|
+
validator.conclusion.value = ValidatorConclusion.UNKNOWN.value
|
|
546
|
+
validator.state.value = ValidatorState.QUEUED.value
|
|
547
|
+
validator.started_at.value = ""
|
|
548
|
+
validator.completed_at.value = ""
|
|
549
|
+
await validator.save()
|
|
550
|
+
else:
|
|
551
|
+
validator = await service.client.create(
|
|
552
|
+
kind=InfrahubKind.ARTIFACTVALIDATOR,
|
|
553
|
+
data={
|
|
554
|
+
"label": validator_name,
|
|
555
|
+
"proposed_change": model.proposed_change,
|
|
556
|
+
"definition": model.artifact_definition.definition_id,
|
|
557
|
+
},
|
|
558
|
+
)
|
|
559
|
+
await validator.save()
|
|
560
|
+
|
|
561
|
+
await artifact_definition.targets.fetch()
|
|
562
|
+
group = artifact_definition.targets.peer
|
|
563
|
+
await group.members.fetch()
|
|
564
|
+
|
|
565
|
+
existing_artifacts = await service.client.filters(
|
|
566
|
+
kind=InfrahubKind.ARTIFACT,
|
|
567
|
+
definition__ids=[model.artifact_definition.definition_id],
|
|
568
|
+
include=["object"],
|
|
569
|
+
branch=model.source_branch,
|
|
570
|
+
)
|
|
571
|
+
artifacts_by_member = {}
|
|
572
|
+
for artifact in existing_artifacts:
|
|
573
|
+
artifacts_by_member[artifact.object.peer.id] = artifact.id
|
|
574
|
+
|
|
575
|
+
repository = model.branch_diff.get_repository(repository_id=model.artifact_definition.repository_id)
|
|
576
|
+
impacted_artifacts = model.branch_diff.get_subscribers_ids(kind=InfrahubKind.ARTIFACT)
|
|
577
|
+
|
|
578
|
+
checks = []
|
|
579
|
+
|
|
580
|
+
for relationship in group.members.peers:
|
|
581
|
+
member = relationship.peer
|
|
582
|
+
artifact_id = artifacts_by_member.get(member.id)
|
|
583
|
+
if _should_render_artifact(
|
|
584
|
+
artifact_id=artifact_id,
|
|
585
|
+
managed_branch=model.source_branch_sync_with_git,
|
|
586
|
+
impacted_artifacts=impacted_artifacts,
|
|
587
|
+
):
|
|
588
|
+
log.info(f"Trigger Artifact processing for {member.display_label}")
|
|
589
|
+
|
|
590
|
+
check_model = CheckArtifactCreate(
|
|
591
|
+
context=model.context,
|
|
592
|
+
artifact_name=model.artifact_definition.artifact_name,
|
|
593
|
+
artifact_id=artifact_id,
|
|
594
|
+
artifact_definition=model.artifact_definition.definition_id,
|
|
595
|
+
commit=repository.source_commit,
|
|
596
|
+
content_type=model.artifact_definition.content_type,
|
|
597
|
+
transform_type=model.artifact_definition.transform_kind,
|
|
598
|
+
transform_location=model.artifact_definition.transform_location,
|
|
599
|
+
repository_id=repository.repository_id,
|
|
600
|
+
repository_name=repository.repository_name,
|
|
601
|
+
repository_kind=repository.kind,
|
|
602
|
+
branch_name=model.source_branch,
|
|
603
|
+
query=model.artifact_definition.query_name,
|
|
604
|
+
variables=member.extract(params=artifact_definition.parameters.value),
|
|
605
|
+
target_id=member.id,
|
|
606
|
+
target_kind=member.get_kind(),
|
|
607
|
+
target_name=member.display_label,
|
|
608
|
+
timeout=model.artifact_definition.timeout,
|
|
609
|
+
validator_id=validator.id,
|
|
610
|
+
)
|
|
611
|
+
|
|
612
|
+
checks.append(
|
|
613
|
+
service.workflow.execute_workflow(
|
|
614
|
+
workflow=GIT_REPOSITORIES_CHECK_ARTIFACT_CREATE,
|
|
615
|
+
parameters={"model": check_model},
|
|
616
|
+
expected_return=ValidatorConclusion,
|
|
617
|
+
)
|
|
618
|
+
)
|
|
619
|
+
|
|
620
|
+
await run_checks_and_update_validator(checks, validator)
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
def _should_render_artifact(artifact_id: str | None, managed_branch: bool, impacted_artifacts: list[str]) -> bool: # noqa: ARG001
|
|
624
|
+
"""Returns a boolean to indicate if an artifact should be generated or not.
|
|
625
|
+
Will return true if:
|
|
626
|
+
* The artifact_id wasn't set which could be that it's a new object that doesn't have a previous artifact
|
|
627
|
+
* The source brance is not data only which would indicate that it could contain updates in git to the transform
|
|
628
|
+
* The artifact_id exists in the impacted_artifacts list
|
|
629
|
+
Will return false if:
|
|
630
|
+
* The source branch is a data only branch and the artifact_id exists and is not in the impacted list
|
|
631
|
+
"""
|
|
632
|
+
|
|
633
|
+
# if not artifact_id or managed_branch:
|
|
634
|
+
# return True
|
|
635
|
+
# return artifact_id in impacted_artifacts
|
|
636
|
+
# Temporary workaround tracked in https://github.com/opsmill/infrahub/issues/4991
|
|
637
|
+
return True
|
infrahub/pytest_plugin.py
CHANGED
|
@@ -52,7 +52,7 @@ class InfrahubBackendPlugin:
|
|
|
52
52
|
|
|
53
53
|
return validator, True
|
|
54
54
|
|
|
55
|
-
def pytest_collection_modifyitems(self, session: Session, config: Config, items: list[Item]) -> None: #
|
|
55
|
+
def pytest_collection_modifyitems(self, session: Session, config: Config, items: list[Item]) -> None: # noqa: ARG002
|
|
56
56
|
"""This function is called after item collection and gives the opportunity to work on the collection before sending the items for testing.
|
|
57
57
|
|
|
58
58
|
All items without an "infrahub" marker will be discarded. Items will also be re-ordered to be run in a specific order:
|
|
@@ -82,7 +82,7 @@ class InfrahubBackendPlugin:
|
|
|
82
82
|
filtered_items.sort(key=sort_key)
|
|
83
83
|
items[:] = filtered_items
|
|
84
84
|
|
|
85
|
-
def pytest_collection_finish(self, session: Session) -> None: #
|
|
85
|
+
def pytest_collection_finish(self, session: Session) -> None: # noqa: ARG002
|
|
86
86
|
"""This function is called when tests have been collected and modified, meaning they are ready to be run."""
|
|
87
87
|
self.proposed_change = self.client.get(kind=InfrahubKind.PROPOSEDCHANGE, id=self.proposed_change_id)
|
|
88
88
|
self.proposed_change.validations.fetch()
|
|
@@ -95,7 +95,7 @@ class InfrahubBackendPlugin:
|
|
|
95
95
|
check = relationship.peer
|
|
96
96
|
self.checks[check.origin.value] = check
|
|
97
97
|
|
|
98
|
-
def pytest_runtestloop(self, session: Session) -> Optional[object]: #
|
|
98
|
+
def pytest_runtestloop(self, session: Session) -> Optional[object]: # noqa: ARG002
|
|
99
99
|
"""This function is called when the test loop is being run."""
|
|
100
100
|
self.validator.conclusion.value = "unknown"
|
|
101
101
|
self.validator.state.value = "in_progress"
|
|
@@ -144,7 +144,7 @@ class InfrahubBackendPlugin:
|
|
|
144
144
|
# Workaround for https://github.com/opsmill/infrahub/issues/2184
|
|
145
145
|
check.update(do_full_update=True)
|
|
146
146
|
|
|
147
|
-
def pytest_sessionfinish(self, session: Session) -> None: #
|
|
147
|
+
def pytest_sessionfinish(self, session: Session) -> None: # noqa: ARG002
|
|
148
148
|
"""Set the final RepositoryValidator details after completing the test session."""
|
|
149
149
|
conclusion = "success"
|
|
150
150
|
|
infrahub/server.py
CHANGED
|
@@ -14,7 +14,7 @@ from fastapi.middleware.gzip import GZipMiddleware
|
|
|
14
14
|
from fastapi.responses import RedirectResponse
|
|
15
15
|
from fastapi.staticfiles import StaticFiles
|
|
16
16
|
from fastapi.templating import Jinja2Templates
|
|
17
|
-
from infrahub_sdk.
|
|
17
|
+
from infrahub_sdk.exceptions import TimestampFormatError
|
|
18
18
|
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
|
|
19
19
|
from opentelemetry.trace import Span
|
|
20
20
|
from pydantic import ValidationError
|
|
@@ -33,7 +33,7 @@ from infrahub.graphql.api.endpoints import router as graphql_router
|
|
|
33
33
|
from infrahub.lock import initialize_lock
|
|
34
34
|
from infrahub.log import clear_log_context, get_logger, set_log_data
|
|
35
35
|
from infrahub.middleware import InfrahubCORSMiddleware
|
|
36
|
-
from infrahub.services import InfrahubServices
|
|
36
|
+
from infrahub.services import InfrahubServices
|
|
37
37
|
from infrahub.services.adapters.cache.nats import NATSCache
|
|
38
38
|
from infrahub.services.adapters.cache.redis import RedisCache
|
|
39
39
|
from infrahub.services.adapters.message_bus.nats import NATSMessageBus
|
|
@@ -70,26 +70,27 @@ async def app_initialization(application: FastAPI, enable_scheduler: bool = True
|
|
|
70
70
|
if config.SETTINGS.workflow.driver == config.WorkflowDriver.WORKER
|
|
71
71
|
else WorkflowLocalExecution()
|
|
72
72
|
)
|
|
73
|
-
|
|
73
|
+
component_type = ComponentType.API_SERVER
|
|
74
74
|
message_bus = config.OVERRIDE.message_bus or (
|
|
75
|
-
NATSMessageBus
|
|
75
|
+
await NATSMessageBus.new(component_type=component_type)
|
|
76
|
+
if config.SETTINGS.broker.driver == config.BrokerDriver.NATS
|
|
77
|
+
else await RabbitMQMessageBus.new(component_type=component_type)
|
|
76
78
|
)
|
|
77
79
|
cache = config.OVERRIDE.cache or (
|
|
78
|
-
NATSCache() if config.SETTINGS.cache.driver == config.CacheDriver.NATS else RedisCache()
|
|
80
|
+
await NATSCache.new() if config.SETTINGS.cache.driver == config.CacheDriver.NATS else RedisCache()
|
|
79
81
|
)
|
|
80
|
-
service = InfrahubServices(
|
|
82
|
+
service = await InfrahubServices.new(
|
|
81
83
|
cache=cache,
|
|
82
84
|
database=database,
|
|
83
85
|
message_bus=message_bus,
|
|
84
86
|
workflow=workflow,
|
|
85
|
-
component_type=
|
|
87
|
+
component_type=component_type,
|
|
86
88
|
)
|
|
87
|
-
await service.initialize()
|
|
88
89
|
initialize_lock(service=service)
|
|
89
90
|
# We must initialize DB after initialize lock and initialize lock depends on cache initialization
|
|
90
91
|
async with application.state.db.start_session() as db:
|
|
91
92
|
await initialization(db=db)
|
|
92
|
-
|
|
93
|
+
|
|
93
94
|
application.state.service = service
|
|
94
95
|
application.state.response_delay = config.SETTINGS.miscellaneous.response_delay
|
|
95
96
|
if enable_scheduler:
|
|
@@ -97,7 +98,7 @@ async def app_initialization(application: FastAPI, enable_scheduler: bool = True
|
|
|
97
98
|
|
|
98
99
|
|
|
99
100
|
async def shutdown(application: FastAPI) -> None:
|
|
100
|
-
await
|
|
101
|
+
await application.state.service.shutdown()
|
|
101
102
|
await application.state.db.close()
|
|
102
103
|
|
|
103
104
|
|
|
@@ -118,7 +119,7 @@ app = FastAPI(
|
|
|
118
119
|
)
|
|
119
120
|
|
|
120
121
|
|
|
121
|
-
def server_request_hook(span: Span, scope: dict) -> None: #
|
|
122
|
+
def server_request_hook(span: Span, scope: dict) -> None: # noqa: ARG001
|
|
122
123
|
if span and span.is_recording():
|
|
123
124
|
span.set_attribute("worker", WORKER_IDENTITY)
|
|
124
125
|
|
|
@@ -217,5 +218,5 @@ async def documentation() -> RedirectResponse:
|
|
|
217
218
|
|
|
218
219
|
|
|
219
220
|
@app.get("/{rest_of_path:path}", include_in_schema=False)
|
|
220
|
-
async def react_app(req: Request, rest_of_path: str) -> Response: #
|
|
221
|
+
async def react_app(req: Request, rest_of_path: str) -> Response: # noqa: ARG001
|
|
221
222
|
return templates.TemplateResponse("index.html", {"request": req})
|