infrahub-server 1.1.9__py3-none-any.whl → 1.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- infrahub/api/artifact.py +16 -4
- infrahub/api/dependencies.py +14 -6
- infrahub/api/diff/validation_models.py +7 -7
- infrahub/api/oauth2.py +0 -1
- infrahub/api/oidc.py +0 -1
- infrahub/api/query.py +18 -7
- infrahub/api/schema.py +33 -7
- infrahub/api/transformation.py +12 -5
- infrahub/{message_bus/messages/check_artifact_create.py → artifacts/models.py} +6 -6
- infrahub/{message_bus/operations/check/artifact.py → artifacts/tasks.py} +27 -28
- infrahub/cli/__init__.py +12 -10
- infrahub/cli/constants.py +3 -0
- infrahub/cli/db.py +166 -185
- infrahub/cli/events.py +8 -3
- infrahub/cli/git_agent.py +9 -7
- infrahub/cli/tasks.py +4 -6
- infrahub/cli/upgrade.py +146 -0
- infrahub/computed_attribute/gather.py +174 -0
- infrahub/computed_attribute/models.py +202 -11
- infrahub/computed_attribute/tasks.py +103 -421
- infrahub/computed_attribute/triggers.py +56 -0
- infrahub/config.py +33 -33
- infrahub/context.py +53 -0
- infrahub/core/account.py +9 -12
- infrahub/core/attribute.py +104 -75
- infrahub/core/branch/models.py +4 -4
- infrahub/core/branch/tasks.py +133 -125
- infrahub/core/changelog/__init__.py +0 -0
- infrahub/core/changelog/diff.py +291 -0
- infrahub/core/changelog/models.py +662 -0
- infrahub/core/constants/__init__.py +47 -2
- infrahub/core/constants/infrahubkind.py +3 -0
- infrahub/core/constants/schema.py +2 -0
- infrahub/core/constraint/node/runner.py +2 -2
- infrahub/core/diff/branch_differ.py +10 -10
- infrahub/core/diff/combiner.py +1 -1
- infrahub/core/diff/enricher/cardinality_one.py +1 -1
- infrahub/core/diff/enricher/hierarchy.py +5 -3
- infrahub/core/diff/enricher/labels.py +1 -1
- infrahub/core/diff/enricher/path_identifier.py +1 -2
- infrahub/core/diff/enricher/summary_counts.py +107 -0
- infrahub/core/diff/ipam_diff_parser.py +4 -5
- infrahub/core/diff/merger/merger.py +3 -1
- infrahub/core/diff/model/diff.py +27 -27
- infrahub/core/diff/model/path.py +13 -13
- infrahub/core/diff/query/all_conflicts.py +1 -1
- infrahub/core/diff/query/artifact.py +1 -1
- infrahub/core/diff/query/delete_query.py +1 -1
- infrahub/core/diff/query/diff_get.py +1 -1
- infrahub/core/diff/query/diff_summary.py +1 -1
- infrahub/core/diff/query/field_specifiers.py +1 -1
- infrahub/core/diff/query/field_summary.py +1 -1
- infrahub/core/diff/query/filters.py +2 -2
- infrahub/core/diff/query/get_conflict_query.py +1 -1
- infrahub/core/diff/query/has_conflicts_query.py +1 -1
- infrahub/core/diff/query/merge.py +3 -3
- infrahub/core/diff/query/merge_tracking_id.py +1 -1
- infrahub/core/diff/query/roots_metadata.py +1 -1
- infrahub/core/diff/query/save.py +3 -3
- infrahub/core/diff/query/summary_counts_enricher.py +2 -2
- infrahub/core/diff/query/time_range_query.py +1 -1
- infrahub/core/diff/query/update_conflict_query.py +1 -1
- infrahub/core/diff/query_parser.py +4 -4
- infrahub/core/diff/repository/deserializer.py +1 -1
- infrahub/core/diff/tasks.py +9 -8
- infrahub/core/enums.py +1 -1
- infrahub/core/initialization.py +1 -10
- infrahub/core/integrity/object_conflict/conflict_recorder.py +1 -1
- infrahub/core/ipam/constants.py +3 -4
- infrahub/core/ipam/reconciler.py +13 -13
- infrahub/core/ipam/tasks.py +2 -3
- infrahub/core/ipam/utilization.py +10 -13
- infrahub/core/manager.py +52 -47
- infrahub/core/merge.py +12 -9
- infrahub/core/migrations/__init__.py +1 -3
- infrahub/core/migrations/graph/__init__.py +5 -3
- 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 +2 -6
- infrahub/core/migrations/graph/m018_uniqueness_nulls.py +3 -3
- infrahub/core/migrations/graph/m019_restore_rels_to_time.py +4 -4
- infrahub/core/migrations/graph/m020_duplicate_edges.py +3 -3
- infrahub/core/migrations/graph/m021_missing_hierarchy_merge.py +2 -2
- infrahub/core/migrations/graph/m022_add_generate_template_attr.py +48 -0
- infrahub/core/migrations/query/attribute_add.py +3 -3
- 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 +1 -1
- infrahub/core/migrations/query/relationship_duplicate.py +1 -1
- infrahub/core/migrations/query/schema_attribute_update.py +3 -3
- infrahub/core/migrations/schema/models.py +19 -4
- infrahub/core/migrations/schema/node_attribute_remove.py +1 -1
- infrahub/core/migrations/schema/node_remove.py +1 -1
- infrahub/core/migrations/schema/tasks.py +7 -7
- infrahub/core/migrations/shared.py +10 -12
- infrahub/core/models.py +13 -14
- infrahub/core/node/__init__.py +172 -57
- infrahub/core/node/base.py +3 -5
- infrahub/core/node/constraints/attribute_uniqueness.py +2 -2
- infrahub/core/node/constraints/grouped_uniqueness.py +5 -5
- infrahub/core/node/constraints/interface.py +1 -2
- infrahub/core/node/delete_validator.py +7 -9
- infrahub/core/node/ipam.py +10 -10
- infrahub/core/node/permissions.py +7 -7
- infrahub/core/node/resource_manager/ip_address_pool.py +6 -6
- infrahub/core/node/resource_manager/ip_prefix_pool.py +14 -11
- infrahub/core/node/resource_manager/number_pool.py +3 -3
- infrahub/core/node/standard.py +3 -5
- infrahub/core/path.py +12 -12
- infrahub/core/property.py +12 -12
- infrahub/core/protocols.py +11 -0
- infrahub/core/protocols_base.py +25 -23
- infrahub/core/query/__init__.py +35 -38
- infrahub/core/query/attribute.py +13 -13
- infrahub/core/query/branch.py +5 -5
- infrahub/core/query/delete.py +1 -1
- infrahub/core/query/diff.py +7 -7
- infrahub/core/query/ipam.py +4 -4
- infrahub/core/query/node.py +23 -24
- infrahub/core/query/relationship.py +143 -46
- infrahub/core/query/resource_manager.py +10 -10
- infrahub/core/query/standard_node.py +9 -9
- infrahub/core/query/subquery.py +9 -9
- 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 +13 -17
- infrahub/core/relationship/constraints/count.py +4 -5
- infrahub/core/relationship/constraints/peer_kind.py +4 -5
- infrahub/core/relationship/constraints/profiles_kind.py +2 -2
- infrahub/core/relationship/model.py +103 -67
- infrahub/core/schema/__init__.py +6 -4
- infrahub/core/schema/attribute_schema.py +16 -8
- infrahub/core/schema/basenode_schema.py +38 -26
- infrahub/core/schema/computed_attribute.py +3 -3
- infrahub/core/schema/definitions/core/__init__.py +147 -0
- infrahub/core/schema/definitions/core/account.py +171 -0
- infrahub/core/schema/definitions/core/artifact.py +136 -0
- infrahub/core/schema/definitions/core/builtin.py +24 -0
- infrahub/core/schema/definitions/core/check.py +68 -0
- infrahub/core/schema/definitions/core/core.py +17 -0
- infrahub/core/schema/definitions/core/generator.py +100 -0
- infrahub/core/schema/definitions/core/graphql_query.py +79 -0
- infrahub/core/schema/definitions/core/group.py +108 -0
- infrahub/core/schema/definitions/core/ipam.py +193 -0
- infrahub/core/schema/definitions/core/lineage.py +19 -0
- infrahub/core/schema/definitions/core/menu.py +48 -0
- infrahub/core/schema/definitions/core/permission.py +163 -0
- infrahub/core/schema/definitions/core/profile.py +18 -0
- infrahub/core/schema/definitions/core/propose_change.py +97 -0
- infrahub/core/schema/definitions/core/propose_change_comment.py +193 -0
- infrahub/core/schema/definitions/core/propose_change_validator.py +328 -0
- infrahub/core/schema/definitions/core/repository.py +286 -0
- infrahub/core/schema/definitions/core/resource_pool.py +170 -0
- infrahub/core/schema/definitions/core/template.py +27 -0
- infrahub/core/schema/definitions/core/transform.py +96 -0
- infrahub/core/schema/definitions/core/webhook.py +134 -0
- infrahub/core/schema/definitions/internal.py +32 -16
- infrahub/core/schema/dropdown.py +3 -4
- infrahub/core/schema/generated/attribute_schema.py +15 -18
- infrahub/core/schema/generated/base_node_schema.py +12 -14
- infrahub/core/schema/generated/genericnode_schema.py +5 -0
- infrahub/core/schema/generated/node_schema.py +8 -5
- infrahub/core/schema/generated/relationship_schema.py +9 -11
- infrahub/core/schema/generic_schema.py +6 -2
- infrahub/core/schema/manager.py +46 -43
- infrahub/core/schema/node_schema.py +6 -2
- infrahub/core/schema/profile_schema.py +4 -0
- infrahub/core/schema/relationship_schema.py +15 -7
- infrahub/core/schema/schema_branch.py +423 -89
- infrahub/core/schema/schema_branch_computed.py +41 -4
- infrahub/core/schema/template_schema.py +36 -0
- infrahub/core/task/task.py +3 -3
- infrahub/core/task/user_task.py +21 -19
- infrahub/core/timestamp.py +3 -3
- infrahub/core/utils.py +12 -12
- infrahub/core/validators/__init__.py +1 -3
- infrahub/core/validators/aggregated_checker.py +2 -2
- infrahub/core/validators/attribute/choices.py +3 -3
- infrahub/core/validators/attribute/enum.py +3 -3
- infrahub/core/validators/attribute/kind.py +3 -3
- infrahub/core/validators/attribute/length.py +3 -3
- infrahub/core/validators/attribute/optional.py +3 -3
- infrahub/core/validators/attribute/regex.py +3 -3
- infrahub/core/validators/attribute/unique.py +3 -3
- infrahub/core/validators/checks_runner.py +60 -0
- infrahub/core/validators/determiner.py +1 -3
- infrahub/core/validators/model.py +1 -3
- infrahub/core/validators/models/validate_migration.py +17 -4
- infrahub/core/validators/node/attribute.py +2 -2
- infrahub/core/validators/node/generate_profile.py +3 -3
- infrahub/core/validators/node/hierarchy.py +3 -3
- infrahub/core/validators/node/inherit_from.py +2 -2
- infrahub/core/validators/node/relationship.py +2 -2
- infrahub/core/validators/query.py +1 -1
- infrahub/core/validators/relationship/count.py +5 -5
- infrahub/core/validators/relationship/optional.py +3 -3
- infrahub/core/validators/relationship/peer.py +3 -3
- infrahub/core/validators/shared.py +2 -2
- infrahub/core/validators/tasks.py +8 -6
- infrahub/core/validators/uniqueness/checker.py +5 -6
- infrahub/core/validators/uniqueness/index.py +2 -2
- infrahub/core/validators/uniqueness/model.py +11 -11
- infrahub/core/validators/uniqueness/query.py +1 -1
- infrahub/database/__init__.py +19 -23
- infrahub/database/memgraph.py +1 -1
- infrahub/dependencies/builder/diff/combiner.py +1 -1
- infrahub/dependencies/builder/diff/conflicts_enricher.py +1 -1
- infrahub/dependencies/builder/diff/deserializer.py +1 -1
- infrahub/dependencies/builder/diff/enricher/summary_counts.py +8 -0
- infrahub/dependencies/builder/diff/parent_node_adder.py +1 -1
- infrahub/dependencies/component/registry.py +2 -2
- infrahub/events/__init__.py +25 -2
- infrahub/events/artifact_action.py +64 -0
- infrahub/events/branch_action.py +57 -20
- infrahub/events/generator.py +71 -0
- infrahub/events/group_action.py +103 -0
- infrahub/events/models.py +160 -53
- infrahub/events/node_action.py +140 -23
- infrahub/events/repository_action.py +7 -20
- infrahub/events/schema_action.py +18 -10
- infrahub/events/utils.py +16 -0
- infrahub/events/validator_action.py +55 -0
- infrahub/exceptions.py +12 -3
- infrahub/generators/models.py +2 -3
- infrahub/generators/tasks.py +34 -15
- infrahub/git/base.py +10 -12
- infrahub/git/constants.py +0 -1
- infrahub/git/integrator.py +82 -57
- infrahub/git/models.py +101 -9
- infrahub/git/repository.py +9 -10
- infrahub/git/tasks.py +450 -112
- infrahub/git/utils.py +48 -0
- infrahub/git/worktree.py +1 -2
- infrahub/git_credential/askpass.py +1 -2
- infrahub/git_credential/helper.py +2 -3
- infrahub/graphql/analyzer.py +572 -11
- infrahub/graphql/app.py +47 -41
- 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 +39 -0
- infrahub/graphql/enums.py +1 -1
- infrahub/graphql/initialization.py +5 -1
- infrahub/graphql/loaders/node.py +1 -1
- infrahub/graphql/loaders/shared.py +1 -1
- infrahub/graphql/manager.py +75 -72
- infrahub/graphql/mutations/account.py +20 -13
- infrahub/graphql/mutations/artifact_definition.py +18 -14
- infrahub/graphql/mutations/branch.py +86 -40
- infrahub/graphql/mutations/computed_attribute.py +26 -18
- infrahub/graphql/mutations/diff.py +17 -8
- infrahub/graphql/mutations/diff_conflict.py +14 -8
- infrahub/graphql/mutations/generator.py +83 -0
- infrahub/graphql/mutations/graphql_query.py +21 -13
- infrahub/graphql/mutations/ipam.py +41 -39
- infrahub/graphql/mutations/main.py +226 -66
- infrahub/graphql/mutations/menu.py +12 -12
- infrahub/graphql/mutations/models.py +2 -4
- infrahub/graphql/mutations/node_getter/by_default_filter.py +1 -3
- infrahub/graphql/mutations/node_getter/by_hfid.py +1 -3
- infrahub/graphql/mutations/node_getter/by_id.py +1 -3
- infrahub/graphql/mutations/node_getter/interface.py +1 -2
- infrahub/graphql/mutations/proposed_change.py +39 -31
- infrahub/graphql/mutations/relationship.py +372 -129
- infrahub/graphql/mutations/repository.py +46 -40
- infrahub/graphql/mutations/resource_manager.py +26 -26
- infrahub/graphql/mutations/schema.py +70 -37
- infrahub/graphql/mutations/tasks.py +10 -7
- infrahub/graphql/mutations/webhook.py +137 -0
- infrahub/graphql/parser.py +5 -5
- 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 +67 -56
- infrahub/graphql/queries/event.py +115 -0
- infrahub/graphql/queries/internal.py +3 -3
- infrahub/graphql/queries/ipam.py +25 -20
- infrahub/graphql/queries/relationship.py +13 -12
- infrahub/graphql/queries/resource_manager.py +37 -25
- infrahub/graphql/queries/search.py +11 -10
- infrahub/graphql/queries/status.py +12 -9
- infrahub/graphql/queries/task.py +11 -9
- infrahub/graphql/resolvers/many_relationship.py +15 -15
- infrahub/graphql/resolvers/resolver.py +58 -37
- 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 +167 -0
- infrahub/graphql/types/interface.py +2 -2
- infrahub/graphql/types/node.py +5 -5
- 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 +30 -184
- infrahub/groups/ancestors.py +29 -0
- infrahub/groups/parsers.py +107 -0
- infrahub/groups/tasks.py +2 -3
- infrahub/lock.py +21 -21
- infrahub/menu/generator.py +7 -8
- infrahub/menu/menu.py +107 -139
- infrahub/menu/models.py +121 -20
- infrahub/menu/repository.py +111 -0
- infrahub/menu/utils.py +5 -8
- infrahub/message_bus/__init__.py +11 -13
- infrahub/message_bus/messages/__init__.py +1 -25
- infrahub/message_bus/messages/check_generator_run.py +3 -3
- infrahub/message_bus/messages/event_branch_merge.py +3 -0
- infrahub/message_bus/messages/finalize_validator_execution.py +3 -0
- infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +6 -0
- infrahub/message_bus/messages/request_generatordefinition_check.py +2 -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 -15
- infrahub/message_bus/operations/check/__init__.py +2 -2
- infrahub/message_bus/operations/check/generator.py +2 -3
- infrahub/message_bus/operations/event/__init__.py +2 -2
- infrahub/message_bus/operations/event/branch.py +7 -3
- infrahub/message_bus/operations/event/worker.py +0 -3
- infrahub/message_bus/operations/finalize/validator.py +52 -2
- 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 +22 -24
- infrahub/message_bus/operations/requests/proposed_change.py +39 -20
- infrahub/message_bus/operations/send/echo.py +1 -1
- infrahub/message_bus/types.py +1 -1
- infrahub/permissions/globals.py +15 -0
- infrahub/pools/number.py +2 -4
- 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 +204 -53
- infrahub/pytest_plugin.py +13 -10
- 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 +11 -19
- 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 +275 -0
- infrahub/task_manager/models.py +147 -3
- infrahub/task_manager/task.py +1 -1
- infrahub/tasks/artifact.py +20 -21
- infrahub/tasks/registry.py +1 -1
- infrahub/telemetry/__init__.py +0 -0
- infrahub/telemetry/constants.py +9 -0
- infrahub/telemetry/database.py +86 -0
- infrahub/telemetry/models.py +65 -0
- infrahub/telemetry/task_manager.py +77 -0
- infrahub/telemetry/tasks.py +119 -0
- infrahub/telemetry/utils.py +11 -0
- infrahub/transformations/tasks.py +5 -7
- infrahub/trigger/__init__.py +0 -0
- infrahub/trigger/catalogue.py +13 -0
- infrahub/trigger/constants.py +1 -0
- infrahub/trigger/models.py +118 -0
- infrahub/trigger/setup.py +90 -0
- infrahub/trigger/tasks.py +36 -0
- infrahub/types.py +1 -1
- infrahub/utils.py +12 -2
- infrahub/validators/__init__.py +0 -0
- infrahub/validators/events.py +42 -0
- infrahub/validators/tasks.py +41 -0
- infrahub/webhook/gather.py +17 -0
- infrahub/webhook/models.py +180 -42
- infrahub/webhook/tasks.py +149 -203
- infrahub/webhook/triggers.py +44 -0
- infrahub/workers/infrahub_async.py +38 -27
- infrahub/workers/utils.py +63 -0
- infrahub/workflows/catalogue.py +98 -71
- infrahub/workflows/initialization.py +12 -8
- infrahub/workflows/models.py +29 -5
- infrahub/workflows/utils.py +11 -2
- infrahub_sdk/client.py +19 -0
- infrahub_sdk/context.py +13 -0
- infrahub_sdk/ctl/branch.py +3 -2
- infrahub_sdk/ctl/utils.py +0 -16
- infrahub_sdk/exceptions.py +6 -0
- infrahub_sdk/generator.py +3 -0
- infrahub_sdk/graphql.py +45 -13
- infrahub_sdk/node.py +66 -20
- infrahub_sdk/protocols.py +21 -8
- infrahub_sdk/protocols_base.py +32 -11
- infrahub_sdk/schema/__init__.py +14 -2
- infrahub_sdk/schema/main.py +7 -0
- infrahub_sdk/task/__init__.py +11 -0
- infrahub_sdk/task/constants.py +3 -0
- infrahub_sdk/task/exceptions.py +25 -0
- infrahub_sdk/task/manager.py +551 -0
- infrahub_sdk/task/models.py +74 -0
- infrahub_sdk/timestamp.py +142 -33
- infrahub_sdk/utils.py +29 -1
- {infrahub_server-1.1.9.dist-info → infrahub_server-1.2.0.dist-info}/METADATA +8 -6
- infrahub_server-1.2.0.dist-info/RECORD +746 -0
- infrahub_testcontainers/container.py +5 -6
- infrahub_testcontainers/docker-compose.test.yml +2 -2
- infrahub_testcontainers/helpers.py +5 -1
- infrahub/core/branch/constants.py +0 -2
- infrahub/core/schema/definitions/core.py +0 -2275
- 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/event_branch_create.py +0 -11
- infrahub/message_bus/messages/event_branch_delete.py +0 -11
- infrahub/message_bus/messages/event_branch_rebased.py +0 -9
- infrahub/message_bus/messages/event_node_mutated.py +0 -15
- infrahub/message_bus/messages/event_schema_update.py +0 -9
- 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/event/node.py +0 -20
- infrahub/message_bus/operations/event/schema.py +0 -17
- 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/tasks/telemetry.py +0 -127
- infrahub/webhook/constants.py +0 -3
- infrahub_server-1.1.9.dist-info/RECORD +0 -688
- /infrahub/{schema → artifacts}/__init__.py +0 -0
- {infrahub_server-1.1.9.dist-info → infrahub_server-1.2.0.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.1.9.dist-info → infrahub_server-1.2.0.dist-info}/WHEEL +0 -0
- {infrahub_server-1.1.9.dist-info → infrahub_server-1.2.0.dist-info}/entry_points.txt +0 -0
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
1
|
+
from infrahub_sdk.protocols import CoreGeneratorValidator
|
|
3
2
|
from infrahub_sdk.uuidt import UUIDT
|
|
4
3
|
from prefect import flow
|
|
5
4
|
from prefect.logging import get_run_logger
|
|
6
5
|
|
|
7
|
-
from infrahub.core.constants import InfrahubKind
|
|
6
|
+
from infrahub.core.constants import InfrahubKind
|
|
8
7
|
from infrahub.core.timestamp import Timestamp
|
|
9
8
|
from infrahub.message_bus import InfrahubMessage, Meta, messages
|
|
10
9
|
from infrahub.message_bus.types import KVTTL
|
|
11
10
|
from infrahub.services import InfrahubServices
|
|
11
|
+
from infrahub.validators.tasks import start_validator
|
|
12
12
|
from infrahub.workflows.utils import add_tags
|
|
13
13
|
|
|
14
14
|
|
|
@@ -29,31 +29,26 @@ async def check(message: messages.RequestGeneratorDefinitionCheck, service: Infr
|
|
|
29
29
|
|
|
30
30
|
await proposed_change.validations.fetch()
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
previous_validator: CoreGeneratorValidator | None = None
|
|
33
33
|
for relationship in proposed_change.validations.peers:
|
|
34
34
|
existing_validator = relationship.peer
|
|
35
35
|
if (
|
|
36
36
|
existing_validator.typename == InfrahubKind.GENERATORVALIDATOR
|
|
37
37
|
and existing_validator.definition.id == message.generator_definition.definition_id
|
|
38
38
|
):
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
validator
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
"proposed_change": message.proposed_change,
|
|
53
|
-
"definition": message.generator_definition.definition_id,
|
|
54
|
-
},
|
|
55
|
-
)
|
|
56
|
-
await validator.save()
|
|
39
|
+
previous_validator = existing_validator
|
|
40
|
+
|
|
41
|
+
validator = await start_validator(
|
|
42
|
+
service=service,
|
|
43
|
+
validator=previous_validator,
|
|
44
|
+
validator_type=CoreGeneratorValidator,
|
|
45
|
+
proposed_change=message.proposed_change,
|
|
46
|
+
data={
|
|
47
|
+
"label": validator_name,
|
|
48
|
+
"definition": message.generator_definition.definition_id,
|
|
49
|
+
},
|
|
50
|
+
context=message.context,
|
|
51
|
+
)
|
|
57
52
|
|
|
58
53
|
group = await service.client.get(
|
|
59
54
|
kind=InfrahubKind.GENERICGROUP,
|
|
@@ -92,6 +87,7 @@ async def check(message: messages.RequestGeneratorDefinitionCheck, service: Infr
|
|
|
92
87
|
log.info(f"Trigger execution of {message.generator_definition.definition_name} for {member.display_label}")
|
|
93
88
|
events.append(
|
|
94
89
|
messages.CheckGeneratorRun(
|
|
90
|
+
context=message.context,
|
|
95
91
|
generator_definition=message.generator_definition,
|
|
96
92
|
generator_instance=generator_instance,
|
|
97
93
|
commit=repository.source_commit,
|
|
@@ -121,14 +117,16 @@ async def check(message: messages.RequestGeneratorDefinitionCheck, service: Infr
|
|
|
121
117
|
validator_id=validator.id,
|
|
122
118
|
validator_execution_id=validator_execution_id,
|
|
123
119
|
validator_type=InfrahubKind.GENERATORVALIDATOR,
|
|
120
|
+
context=message.context,
|
|
121
|
+
proposed_change=message.proposed_change,
|
|
124
122
|
)
|
|
125
123
|
)
|
|
126
124
|
for event in events:
|
|
127
125
|
event.assign_meta(parent=message)
|
|
128
|
-
await service.send(message=event)
|
|
126
|
+
await service.message_bus.send(message=event)
|
|
129
127
|
|
|
130
128
|
|
|
131
|
-
def _run_generator(instance_id:
|
|
129
|
+
def _run_generator(instance_id: str | None, managed_branch: bool, impacted_instances: list[str]) -> bool:
|
|
132
130
|
"""Returns a boolean to indicate if a generator instance needs to be executed
|
|
133
131
|
Will return true if:
|
|
134
132
|
* The instance_id wasn't set which could be that it's a new object that doesn't have a previous generator instance
|
|
@@ -11,6 +11,7 @@ from infrahub.core.constants import CheckType, InfrahubKind, RepositoryInternalS
|
|
|
11
11
|
from infrahub.core.diff.coordinator import DiffCoordinator
|
|
12
12
|
from infrahub.core.registry import registry
|
|
13
13
|
from infrahub.dependencies.registry import get_component_registry
|
|
14
|
+
from infrahub.git.models import TriggerRepositoryInternalChecks
|
|
14
15
|
from infrahub.git.repository import InfrahubRepository
|
|
15
16
|
from infrahub.message_bus import InfrahubMessage, messages
|
|
16
17
|
from infrahub.message_bus.types import (
|
|
@@ -20,6 +21,7 @@ from infrahub.message_bus.types import (
|
|
|
20
21
|
ProposedChangeSubscriber,
|
|
21
22
|
)
|
|
22
23
|
from infrahub.proposed_change.models import (
|
|
24
|
+
RequestArtifactDefinitionCheck,
|
|
23
25
|
RequestProposedChangeDataIntegrity,
|
|
24
26
|
RequestProposedChangeRepositoryChecks,
|
|
25
27
|
RequestProposedChangeRunGenerators,
|
|
@@ -28,6 +30,8 @@ from infrahub.proposed_change.models import (
|
|
|
28
30
|
)
|
|
29
31
|
from infrahub.services import InfrahubServices # noqa: TC001
|
|
30
32
|
from infrahub.workflows.catalogue import (
|
|
33
|
+
GIT_REPOSITORY_INTERNAL_CHECKS_TRIGGER,
|
|
34
|
+
REQUEST_ARTIFACT_DEFINITION_CHECK,
|
|
31
35
|
REQUEST_PROPOSED_CHANGE_DATA_INTEGRITY,
|
|
32
36
|
REQUEST_PROPOSED_CHANGE_REPOSITORY_CHECKS,
|
|
33
37
|
REQUEST_PROPOSED_CHANGE_RUN_GENERATORS,
|
|
@@ -74,17 +78,17 @@ async def pipeline(message: messages.RequestProposedChangePipeline, service: Inf
|
|
|
74
78
|
):
|
|
75
79
|
for repo in repositories:
|
|
76
80
|
if not repo.read_only and repo.internal_status == RepositoryInternalStatus.ACTIVE.value:
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
model = TriggerRepositoryInternalChecks(
|
|
82
|
+
proposed_change=message.proposed_change,
|
|
83
|
+
repository=repo.repository_id,
|
|
84
|
+
source_branch=repo.source_branch,
|
|
85
|
+
target_branch=repo.destination_branch,
|
|
86
|
+
)
|
|
87
|
+
await service.workflow.submit_workflow(
|
|
88
|
+
workflow=GIT_REPOSITORY_INTERNAL_CHECKS_TRIGGER,
|
|
89
|
+
context=message.context,
|
|
90
|
+
parameters={"model": model},
|
|
84
91
|
)
|
|
85
|
-
for event in events:
|
|
86
|
-
event.assign_meta(parent=message)
|
|
87
|
-
await service.send(message=event)
|
|
88
92
|
return
|
|
89
93
|
|
|
90
94
|
await _gather_repository_repository_diffs(repositories=repositories, service=service)
|
|
@@ -103,6 +107,7 @@ async def pipeline(message: messages.RequestProposedChangePipeline, service: Inf
|
|
|
103
107
|
if message.check_type is CheckType.ARTIFACT:
|
|
104
108
|
events.append(
|
|
105
109
|
messages.RequestProposedChangeRefreshArtifacts(
|
|
110
|
+
context=message.context,
|
|
106
111
|
proposed_change=message.proposed_change,
|
|
107
112
|
source_branch=message.source_branch,
|
|
108
113
|
source_branch_sync_with_git=message.source_branch_sync_with_git,
|
|
@@ -122,7 +127,9 @@ async def pipeline(message: messages.RequestProposedChangePipeline, service: Inf
|
|
|
122
127
|
do_repository_checks=message.check_type is CheckType.ALL,
|
|
123
128
|
)
|
|
124
129
|
await service.workflow.submit_workflow(
|
|
125
|
-
workflow=REQUEST_PROPOSED_CHANGE_RUN_GENERATORS,
|
|
130
|
+
workflow=REQUEST_PROPOSED_CHANGE_RUN_GENERATORS,
|
|
131
|
+
context=message.context,
|
|
132
|
+
parameters={"model": model_proposed_change_run_generator},
|
|
126
133
|
)
|
|
127
134
|
|
|
128
135
|
if message.check_type in [CheckType.ALL, CheckType.DATA] and branch_diff.has_node_changes(
|
|
@@ -136,7 +143,9 @@ async def pipeline(message: messages.RequestProposedChangePipeline, service: Inf
|
|
|
136
143
|
branch_diff=branch_diff,
|
|
137
144
|
)
|
|
138
145
|
await service.workflow.submit_workflow(
|
|
139
|
-
workflow=REQUEST_PROPOSED_CHANGE_DATA_INTEGRITY,
|
|
146
|
+
workflow=REQUEST_PROPOSED_CHANGE_DATA_INTEGRITY,
|
|
147
|
+
context=message.context,
|
|
148
|
+
parameters={"model": model_proposed_change_data_integrity},
|
|
140
149
|
)
|
|
141
150
|
|
|
142
151
|
if message.check_type in [CheckType.REPOSITORY, CheckType.USER]:
|
|
@@ -148,7 +157,9 @@ async def pipeline(message: messages.RequestProposedChangePipeline, service: Inf
|
|
|
148
157
|
branch_diff=branch_diff,
|
|
149
158
|
)
|
|
150
159
|
await service.workflow.submit_workflow(
|
|
151
|
-
workflow=REQUEST_PROPOSED_CHANGE_REPOSITORY_CHECKS,
|
|
160
|
+
workflow=REQUEST_PROPOSED_CHANGE_REPOSITORY_CHECKS,
|
|
161
|
+
context=message.context,
|
|
162
|
+
parameters={"model": model_proposed_change_repo_checks},
|
|
152
163
|
)
|
|
153
164
|
|
|
154
165
|
if message.check_type in [CheckType.ALL, CheckType.SCHEMA] and branch_diff.has_data_changes(
|
|
@@ -156,6 +167,7 @@ async def pipeline(message: messages.RequestProposedChangePipeline, service: Inf
|
|
|
156
167
|
):
|
|
157
168
|
await service.workflow.submit_workflow(
|
|
158
169
|
workflow=REQUEST_PROPOSED_CHANGE_SCHEMA_INTEGRITY,
|
|
170
|
+
context=message.context,
|
|
159
171
|
parameters={
|
|
160
172
|
"model": RequestProposedChangeSchemaIntegrity(
|
|
161
173
|
proposed_change=message.proposed_change,
|
|
@@ -170,6 +182,7 @@ async def pipeline(message: messages.RequestProposedChangePipeline, service: Inf
|
|
|
170
182
|
if message.check_type in [CheckType.ALL, CheckType.TEST]:
|
|
171
183
|
await service.workflow.submit_workflow(
|
|
172
184
|
workflow=REQUEST_PROPOSED_CHANGE_USER_TESTS,
|
|
185
|
+
context=message.context,
|
|
173
186
|
parameters={
|
|
174
187
|
"model": RequestProposedChangeUserTests(
|
|
175
188
|
proposed_change=message.proposed_change,
|
|
@@ -183,7 +196,7 @@ async def pipeline(message: messages.RequestProposedChangePipeline, service: Inf
|
|
|
183
196
|
|
|
184
197
|
for event in events:
|
|
185
198
|
event.assign_meta(parent=message)
|
|
186
|
-
await service.send(message=event)
|
|
199
|
+
await service.message_bus.send(message=event)
|
|
187
200
|
|
|
188
201
|
|
|
189
202
|
@flow(
|
|
@@ -232,7 +245,8 @@ async def refresh_artifacts(message: messages.RequestProposedChangeRefreshArtifa
|
|
|
232
245
|
|
|
233
246
|
if select:
|
|
234
247
|
log.info(f"Trigger processing of {artifact_definition.definition_name}")
|
|
235
|
-
|
|
248
|
+
model = RequestArtifactDefinitionCheck(
|
|
249
|
+
context=message.context,
|
|
236
250
|
artifact_definition=artifact_definition,
|
|
237
251
|
branch_diff=message.branch_diff,
|
|
238
252
|
proposed_change=message.proposed_change,
|
|
@@ -241,8 +255,7 @@ async def refresh_artifacts(message: messages.RequestProposedChangeRefreshArtifa
|
|
|
241
255
|
destination_branch=message.destination_branch,
|
|
242
256
|
)
|
|
243
257
|
|
|
244
|
-
|
|
245
|
-
await service.send(message=msg)
|
|
258
|
+
await service.workflow.submit_workflow(REQUEST_ARTIFACT_DEFINITION_CHECK, parameters={"model": model})
|
|
246
259
|
|
|
247
260
|
|
|
248
261
|
GATHER_ARTIFACT_DEFINITIONS = """
|
|
@@ -520,7 +533,7 @@ async def _get_proposed_change_repositories(
|
|
|
520
533
|
return _parse_proposed_change_repositories(message=message, source=source_all, destination=destination_all)
|
|
521
534
|
|
|
522
535
|
|
|
523
|
-
@task(name="proposed-change-validate-repository-conflicts", task_run_name="Validate conflicts on repository")
|
|
536
|
+
@task(name="proposed-change-validate-repository-conflicts", task_run_name="Validate conflicts on repository") # type: ignore[arg-type]
|
|
524
537
|
async def _validate_repository_merge_conflicts(
|
|
525
538
|
repositories: list[ProposedChangeRepository], service: InfrahubServices
|
|
526
539
|
) -> bool:
|
|
@@ -529,7 +542,10 @@ async def _validate_repository_merge_conflicts(
|
|
|
529
542
|
for repo in repositories:
|
|
530
543
|
if repo.has_diff and not repo.is_staging:
|
|
531
544
|
git_repo = await InfrahubRepository.init(
|
|
532
|
-
id=repo.repository_id,
|
|
545
|
+
id=repo.repository_id,
|
|
546
|
+
name=repo.repository_name,
|
|
547
|
+
client=service.client,
|
|
548
|
+
service=service,
|
|
533
549
|
)
|
|
534
550
|
async with lock.registry.get(name=repo.repository_name, namespace="repository"):
|
|
535
551
|
repo.conflicts = await git_repo.get_conflicts(
|
|
@@ -551,7 +567,10 @@ async def _gather_repository_repository_diffs(
|
|
|
551
567
|
if repo.has_diff and repo.source_commit and repo.destination_commit:
|
|
552
568
|
# TODO we need to find a way to return all files in the repo if the repo is new
|
|
553
569
|
git_repo = await InfrahubRepository.init(
|
|
554
|
-
id=repo.repository_id,
|
|
570
|
+
id=repo.repository_id,
|
|
571
|
+
name=repo.repository_name,
|
|
572
|
+
client=service.client,
|
|
573
|
+
service=service,
|
|
555
574
|
)
|
|
556
575
|
|
|
557
576
|
files_changed: list[str] = []
|
|
@@ -10,4 +10,4 @@ async def request(message: messages.SendEchoRequest, service: InfrahubServices)
|
|
|
10
10
|
service.log.info(f"Received message: {message.message}")
|
|
11
11
|
if message.reply_requested:
|
|
12
12
|
response = SendEchoRequestResponse(data=SendEchoRequestResponseData(response=f"Reply to: {message.message}"))
|
|
13
|
-
await service.
|
|
13
|
+
await service.message_bus.reply_if_initiator_meta(message=response, initiator=message)
|
infrahub/message_bus/types.py
CHANGED
|
@@ -9,7 +9,7 @@ from pydantic import BaseModel, Field
|
|
|
9
9
|
from infrahub.core.constants import InfrahubKind, RepositoryInternalStatus
|
|
10
10
|
from infrahub.exceptions import NodeNotFoundError
|
|
11
11
|
|
|
12
|
-
SCHEMA_CHANGE = re.compile("^Schema[A-Z]")
|
|
12
|
+
SCHEMA_CHANGE = re.compile(r"^Schema[A-Z]")
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class MessageTTL(int, Enum):
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from infrahub.core.account import GlobalPermission
|
|
2
|
+
from infrahub.core.constants import GLOBAL_BRANCH_NAME, GlobalPermissions, PermissionDecision
|
|
3
|
+
from infrahub.core.registry import registry
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def define_global_permission_from_branch(permission: GlobalPermissions, branch_name: str) -> GlobalPermission:
|
|
7
|
+
if branch_name in (GLOBAL_BRANCH_NAME, registry.default_branch):
|
|
8
|
+
decision = PermissionDecision.ALLOW_DEFAULT
|
|
9
|
+
else:
|
|
10
|
+
decision = PermissionDecision.ALLOW_OTHER
|
|
11
|
+
|
|
12
|
+
return GlobalPermission(
|
|
13
|
+
action=permission.value,
|
|
14
|
+
decision=decision.value,
|
|
15
|
+
)
|
infrahub/pools/number.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
|
-
from typing import TYPE_CHECKING
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
5
|
|
|
6
6
|
from infrahub.core.query.resource_manager import NumberPoolGetAllocated
|
|
7
7
|
from infrahub.core.registry import registry
|
|
@@ -20,9 +20,7 @@ class UsedNumber:
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
class NumberUtilizationGetter:
|
|
23
|
-
def __init__(
|
|
24
|
-
self, db: InfrahubDatabase, pool: CoreNode, branch: Branch, at: Optional[Union[Timestamp, str]] = None
|
|
25
|
-
) -> None:
|
|
23
|
+
def __init__(self, db: InfrahubDatabase, pool: CoreNode, branch: Branch, at: Timestamp | str | None = None) -> None:
|
|
26
24
|
self.db = db
|
|
27
25
|
self.at = at
|
|
28
26
|
self.pool = pool
|
infrahub/pools/prefix.py
CHANGED
|
@@ -1,174 +1,38 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import ipaddress
|
|
4
|
-
from
|
|
5
|
-
from ipaddress import IPv4Network, IPv6Network
|
|
6
|
-
from typing import Optional, Union
|
|
4
|
+
from typing import TYPE_CHECKING, Literal
|
|
7
5
|
|
|
6
|
+
from netaddr import IPSet
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
Class to automatically manage Prefixes and help to carve out sub-prefixes
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
def __init__(self, network: str) -> None:
|
|
15
|
-
self.network = ipaddress.ip_network(network)
|
|
16
|
-
|
|
17
|
-
# Define biggest and smallest possible masks
|
|
18
|
-
self.mask_biggest = self.network.prefixlen + 1
|
|
19
|
-
if self.network.version == 4:
|
|
20
|
-
self.mask_smallest = 32
|
|
21
|
-
else:
|
|
22
|
-
self.mask_smallest = 128
|
|
23
|
-
|
|
24
|
-
self.available_subnets = defaultdict(list)
|
|
25
|
-
self.sub_by_key: dict[str, Optional[str]] = OrderedDict()
|
|
26
|
-
self.sub_by_id: dict[str, str] = OrderedDict()
|
|
27
|
-
|
|
28
|
-
# Save the top level available subnet
|
|
29
|
-
for subnet in list(self.network.subnets(new_prefix=self.mask_biggest)):
|
|
30
|
-
self.available_subnets[self.mask_biggest].append(str(subnet))
|
|
31
|
-
|
|
32
|
-
def reserve(self, subnet: str, identifier: Optional[str] = None) -> bool:
|
|
33
|
-
"""
|
|
34
|
-
Indicate that a specific subnet is already reserved/used
|
|
35
|
-
"""
|
|
36
|
-
|
|
37
|
-
# TODO Add check to make sure the subnet provided has the right size
|
|
38
|
-
sub = ipaddress.ip_network(subnet)
|
|
39
|
-
|
|
40
|
-
if int(sub.prefixlen) <= int(self.network.prefixlen):
|
|
41
|
-
raise ValueError(f"{subnet} do not have the right size ({sub.prefixlen},{self.network.prefixlen})")
|
|
42
|
-
|
|
43
|
-
if sub.supernet(new_prefix=self.network.prefixlen) != self.network:
|
|
44
|
-
raise ValueError(f"{subnet} is not part of this network")
|
|
45
|
-
|
|
46
|
-
# Check first if this ID as already done a reservation
|
|
47
|
-
if identifier and identifier in self.sub_by_id.keys():
|
|
48
|
-
if self.sub_by_id[identifier] == str(sub):
|
|
49
|
-
return True
|
|
50
|
-
raise ValueError(
|
|
51
|
-
f"this identifier ({identifier}) is already used but for a different resource ({self.sub_by_id[identifier]})"
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
if identifier and str(sub) in self.sub_by_key.keys():
|
|
55
|
-
raise ValueError(f"this subnet is already reserved but not with this identifier ({identifier})")
|
|
56
|
-
|
|
57
|
-
if str(sub) in self.sub_by_key.keys():
|
|
58
|
-
self.remove_subnet_from_available_list(sub)
|
|
59
|
-
return True
|
|
60
|
-
|
|
61
|
-
# Check if the subnet itself is available
|
|
62
|
-
# if available reserve and return
|
|
63
|
-
if subnet in self.available_subnets[sub.prefixlen]:
|
|
64
|
-
if identifier:
|
|
65
|
-
self.sub_by_id[identifier] = subnet
|
|
66
|
-
self.sub_by_key[subnet] = identifier
|
|
67
|
-
else:
|
|
68
|
-
self.sub_by_key[subnet] = None
|
|
69
|
-
|
|
70
|
-
self.remove_subnet_from_available_list(sub)
|
|
71
|
-
return True
|
|
72
|
-
|
|
73
|
-
# If not reserved already, check if the subnet is available
|
|
74
|
-
# start at sublen and check all available subnet
|
|
75
|
-
# increase 1 by 1 until we find the closer supernet available
|
|
76
|
-
# break it down and keep track of the other available subnets
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from infrahub.core.ipam.constants import IPNetworkType
|
|
77
10
|
|
|
78
|
-
for sublen in range(sub.prefixlen - 1, self.network.prefixlen, -1):
|
|
79
|
-
supernet = sub.supernet(new_prefix=sublen)
|
|
80
|
-
if str(supernet) in self.available_subnets[sublen]:
|
|
81
|
-
self.split_supernet(supernet=supernet, subnet=sub)
|
|
82
|
-
return self.reserve(subnet=subnet, identifier=identifier)
|
|
83
11
|
|
|
84
|
-
|
|
12
|
+
def get_next_available_prefix(pool: IPSet, prefix_length: int, prefix_ver: Literal[4, 6] = 4) -> IPNetworkType:
|
|
13
|
+
"""Get the next available prefix of a given prefix length from an IPSet.
|
|
85
14
|
|
|
86
|
-
|
|
87
|
-
|
|
15
|
+
Args:
|
|
16
|
+
pool: netaddr IPSet object with available subnets
|
|
17
|
+
prefix_length: length of the desired prefix
|
|
18
|
+
prefix_ver: IPSet can contain a mix of IPv4 and IPv6 subnets. This parameter specifies the IP version of prefix to acquire.
|
|
88
19
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
subs = supernet.subnets(new_prefix=clean_prefixlen)
|
|
109
|
-
next_sub: Union[IPv4Network, IPv6Network] = next(subs) # type: ignore[assignment]
|
|
110
|
-
self.split_supernet(supernet=supernet, subnet=next_sub)
|
|
111
|
-
self.reserve(subnet=str(next_sub), identifier=identifier)
|
|
112
|
-
return next_sub
|
|
113
|
-
|
|
114
|
-
raise IndexError("No More subnet available")
|
|
115
|
-
|
|
116
|
-
def get_nbr_available_subnets(self) -> dict[int, int]:
|
|
117
|
-
tmp = {}
|
|
118
|
-
for i in range(self.mask_biggest, self.mask_smallest + 1):
|
|
119
|
-
tmp[i] = len(self.available_subnets[i])
|
|
120
|
-
|
|
121
|
-
return tmp
|
|
122
|
-
|
|
123
|
-
def check_if_already_allocated(self, identifier: str) -> bool:
|
|
124
|
-
"""
|
|
125
|
-
Check if a subnet has already been allocated based on an identifier
|
|
126
|
-
|
|
127
|
-
Need to add the same capability based on Network address
|
|
128
|
-
If both identifier and subnet are provided, identifier take precedence
|
|
129
|
-
"""
|
|
130
|
-
if identifier in self.sub_by_id.keys():
|
|
131
|
-
return True
|
|
132
|
-
return False
|
|
133
|
-
|
|
134
|
-
def split_supernet(
|
|
135
|
-
self, supernet: Union[IPv4Network, IPv6Network], subnet: Union[IPv4Network, IPv6Network]
|
|
136
|
-
) -> None:
|
|
137
|
-
"""Split a supernet into smaller networks"""
|
|
138
|
-
|
|
139
|
-
# TODO ensure subnet is small than supernet
|
|
140
|
-
# TODO ensure that subnet is part of supernet
|
|
141
|
-
parent_net = supernet
|
|
142
|
-
for i in range(supernet.prefixlen + 1, subnet.prefixlen + 1):
|
|
143
|
-
tmp_net: list[Union[IPv4Network, IPv6Network]] = list(parent_net.subnets(new_prefix=i))
|
|
144
|
-
|
|
145
|
-
if i == subnet.prefixlen:
|
|
146
|
-
for net in tmp_net:
|
|
147
|
-
self.available_subnets[i].append(str(net))
|
|
148
|
-
else:
|
|
149
|
-
if subnet.subnet_of(other=tmp_net[0]): # type: ignore[arg-type]
|
|
150
|
-
parent = 0
|
|
151
|
-
other = 1
|
|
152
|
-
else:
|
|
153
|
-
parent = 1
|
|
154
|
-
other = 0
|
|
155
|
-
|
|
156
|
-
parent_net = tmp_net[parent]
|
|
157
|
-
self.available_subnets[i].append(str(tmp_net[other]))
|
|
158
|
-
|
|
159
|
-
self.remove_subnet_from_available_list(supernet)
|
|
160
|
-
|
|
161
|
-
def remove_subnet_from_available_list(self, subnet: Union[IPv4Network, IPv6Network]) -> None:
|
|
162
|
-
"""Remove a subnet from the list of available Subnet."""
|
|
163
|
-
try:
|
|
164
|
-
idx = self.available_subnets[subnet.prefixlen].index(str(subnet))
|
|
165
|
-
del self.available_subnets[subnet.prefixlen][idx]
|
|
166
|
-
except ValueError:
|
|
167
|
-
# Already removed
|
|
168
|
-
pass
|
|
169
|
-
|
|
170
|
-
# if idx:
|
|
171
|
-
# return True
|
|
172
|
-
# except:
|
|
173
|
-
# log.warn("Unable to remove %s from list of available subnets" % str(subnet))
|
|
174
|
-
# return False
|
|
20
|
+
Raises:
|
|
21
|
+
ValueError: If there are no available subnets in the pool
|
|
22
|
+
"""
|
|
23
|
+
prefix_ver_map = {
|
|
24
|
+
4: ipaddress.IPv4Network,
|
|
25
|
+
6: ipaddress.IPv6Network,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
filtered_pool = IPSet([])
|
|
29
|
+
for subnet in pool.iter_cidrs():
|
|
30
|
+
if isinstance(ipaddress.ip_network(str(subnet)), prefix_ver_map[prefix_ver]):
|
|
31
|
+
filtered_pool.add(subnet)
|
|
32
|
+
|
|
33
|
+
for cidr in filtered_pool.iter_cidrs():
|
|
34
|
+
if cidr.prefixlen <= prefix_length:
|
|
35
|
+
next_available = ipaddress.ip_network(f"{cidr.network}/{prefix_length}")
|
|
36
|
+
return next_available
|
|
37
|
+
|
|
38
|
+
raise ValueError("No available subnets in pool")
|
|
File without changes
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from fastapi import APIRouter, FastAPI
|
|
4
|
+
from prefect.server.api.server import create_app
|
|
5
|
+
|
|
6
|
+
from . import events
|
|
7
|
+
|
|
8
|
+
router = APIRouter(prefix="/infrahub")
|
|
9
|
+
|
|
10
|
+
router.include_router(events.router)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def create_infrahub_prefect() -> FastAPI:
|
|
14
|
+
app = create_app()
|
|
15
|
+
api_app: FastAPI = app.__dict__["api_app"]
|
|
16
|
+
api_app.include_router(router=router)
|
|
17
|
+
|
|
18
|
+
return app
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from prefect.server.events.schemas.events import ReceivedEvent
|
|
6
|
+
from prefect.server.events.storage import INTERACTIVE_PAGE_SIZE
|
|
7
|
+
from prefect.server.events.storage.database import raw_count_events, read_events
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from prefect.server.events.filters import EventFilter
|
|
11
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
async def query_events(
|
|
15
|
+
session: AsyncSession, filter: EventFilter, page_size: int = INTERACTIVE_PAGE_SIZE, offset: int | None = None
|
|
16
|
+
) -> tuple[list[ReceivedEvent], int]:
|
|
17
|
+
count = await raw_count_events(session, filter) # type: ignore[attr-defined]
|
|
18
|
+
page = await read_events(session, filter, limit=page_size, offset=offset) # type: ignore[attr-defined]
|
|
19
|
+
events = [ReceivedEvent.model_validate(e, from_attributes=True) for e in page]
|
|
20
|
+
return events, count
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from fastapi import APIRouter
|
|
2
|
+
from fastapi.param_functions import Depends
|
|
3
|
+
from prefect.server.database import PrefectDBInterface, provide_database_interface
|
|
4
|
+
|
|
5
|
+
from .database import query_events
|
|
6
|
+
from .models import InfrahubEventfilterInput, InfrahubEventPage
|
|
7
|
+
|
|
8
|
+
router = APIRouter(prefix="/events", tags=["Infrahub"])
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@router.post(
|
|
12
|
+
"/filter",
|
|
13
|
+
)
|
|
14
|
+
async def read_events(
|
|
15
|
+
event_filter: InfrahubEventfilterInput,
|
|
16
|
+
db: PrefectDBInterface = Depends(provide_database_interface), # noqa: B008
|
|
17
|
+
) -> InfrahubEventPage:
|
|
18
|
+
event_filter.filter.set_prefix()
|
|
19
|
+
|
|
20
|
+
async with db.session_context() as session:
|
|
21
|
+
events, total = await query_events(
|
|
22
|
+
session=session, filter=event_filter.filter, page_size=event_filter.limit, offset=event_filter.offset
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
return InfrahubEventPage(
|
|
26
|
+
events=events,
|
|
27
|
+
total=total,
|
|
28
|
+
)
|
|
@@ -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")
|