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
infrahub/tasks/telemetry.py
CHANGED
|
@@ -13,14 +13,14 @@ from infrahub.core import registry, utils
|
|
|
13
13
|
from infrahub.core.branch import Branch
|
|
14
14
|
from infrahub.core.constants import InfrahubKind
|
|
15
15
|
from infrahub.core.graph.schema import GRAPH_SCHEMA
|
|
16
|
-
from infrahub.services import InfrahubServices
|
|
16
|
+
from infrahub.services import InfrahubServices
|
|
17
17
|
|
|
18
18
|
TELEMETRY_KIND: str = "community"
|
|
19
19
|
TELEMETRY_VERSION: str = "20240524"
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
@task(name="telemetry-gather-db", task_run_name="Gather Database Information", cache_policy=NONE)
|
|
23
|
-
async def gather_database_information(service: InfrahubServices
|
|
22
|
+
@task(name="telemetry-gather-db", task_run_name="Gather Database Information", cache_policy=NONE) # type: ignore[arg-type]
|
|
23
|
+
async def gather_database_information(service: InfrahubServices) -> dict:
|
|
24
24
|
async with service.database.start_session() as db:
|
|
25
25
|
data: dict[str, Any] = {
|
|
26
26
|
"database_type": db.db_type.value,
|
|
@@ -37,8 +37,8 @@ async def gather_database_information(service: InfrahubServices, branch: Branch)
|
|
|
37
37
|
return data
|
|
38
38
|
|
|
39
39
|
|
|
40
|
-
@task(name="telemetry-schema-information", task_run_name="Gather Schema Information", cache_policy=NONE)
|
|
41
|
-
async def gather_schema_information(
|
|
40
|
+
@task(name="telemetry-schema-information", task_run_name="Gather Schema Information", cache_policy=NONE) # type: ignore[arg-type]
|
|
41
|
+
async def gather_schema_information(branch: Branch) -> dict:
|
|
42
42
|
data: dict[str, Any] = {}
|
|
43
43
|
main_schema = registry.schema.get_schema_branch(name=branch.name)
|
|
44
44
|
data["node_count"] = len(main_schema.node_names)
|
|
@@ -48,8 +48,8 @@ async def gather_schema_information(service: InfrahubServices, branch: Branch) -
|
|
|
48
48
|
return data
|
|
49
49
|
|
|
50
50
|
|
|
51
|
-
@task(name="telemetry-feature-information", task_run_name="Gather Feature Information", cache_policy=NONE)
|
|
52
|
-
async def gather_feature_information(service: InfrahubServices
|
|
51
|
+
@task(name="telemetry-feature-information", task_run_name="Gather Feature Information", cache_policy=NONE) # type: ignore[arg-type]
|
|
52
|
+
async def gather_feature_information(service: InfrahubServices) -> dict:
|
|
53
53
|
async with service.database.start_session() as db:
|
|
54
54
|
data = {}
|
|
55
55
|
features_to_count = [
|
|
@@ -67,7 +67,7 @@ async def gather_feature_information(service: InfrahubServices, branch: Branch)
|
|
|
67
67
|
return data
|
|
68
68
|
|
|
69
69
|
|
|
70
|
-
@task(name="telemetry-gather-data", task_run_name="Gather Anonynous Data", cache_policy=NONE)
|
|
70
|
+
@task(name="telemetry-gather-data", task_run_name="Gather Anonynous Data", cache_policy=NONE) # type: ignore[arg-type]
|
|
71
71
|
async def gather_anonymous_telemetry_data(service: InfrahubServices) -> dict:
|
|
72
72
|
start_time = time.time()
|
|
73
73
|
|
|
@@ -87,9 +87,9 @@ async def gather_anonymous_telemetry_data(service: InfrahubServices) -> dict:
|
|
|
87
87
|
"branches": {
|
|
88
88
|
"total": len(registry.branch),
|
|
89
89
|
},
|
|
90
|
-
"features": await gather_feature_information(service=service
|
|
91
|
-
"schema": await gather_schema_information(
|
|
92
|
-
"database": await gather_database_information(service=service
|
|
90
|
+
"features": await gather_feature_information(service=service),
|
|
91
|
+
"schema": await gather_schema_information(branch=default_branch),
|
|
92
|
+
"database": await gather_database_information(service=service),
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
data["execution_time"] = time.time() - start_time
|
|
@@ -97,7 +97,7 @@ async def gather_anonymous_telemetry_data(service: InfrahubServices) -> dict:
|
|
|
97
97
|
return data
|
|
98
98
|
|
|
99
99
|
|
|
100
|
-
@task(name="telemetry-post-data", task_run_name="Upload data", retries=5, cache_policy=NONE)
|
|
100
|
+
@task(name="telemetry-post-data", task_run_name="Upload data", retries=5, cache_policy=NONE) # type: ignore[arg-type]
|
|
101
101
|
async def post_telemetry_data(service: InfrahubServices, url: str, payload: dict[str, Any]) -> None:
|
|
102
102
|
"""Send the telemetry data to the specified URL, using HTTP POST."""
|
|
103
103
|
response = await service.http.post(url=url, json=payload)
|
|
@@ -105,8 +105,7 @@ async def post_telemetry_data(service: InfrahubServices, url: str, payload: dict
|
|
|
105
105
|
|
|
106
106
|
|
|
107
107
|
@flow(name="anonymous_telemetry_send", flow_run_name="Send anonymous telemetry")
|
|
108
|
-
async def send_telemetry_push() -> None:
|
|
109
|
-
service = services.service
|
|
108
|
+
async def send_telemetry_push(service: InfrahubServices) -> None:
|
|
110
109
|
log = get_run_logger()
|
|
111
110
|
if config.SETTINGS.main.telemetry_optout:
|
|
112
111
|
log.info("Skipping, User opted out of this service.")
|
|
@@ -4,7 +4,7 @@ from prefect import flow
|
|
|
4
4
|
|
|
5
5
|
from infrahub.git.repository import get_initialized_repo
|
|
6
6
|
from infrahub.log import get_logger
|
|
7
|
-
from infrahub.services import
|
|
7
|
+
from infrahub.services import InfrahubServices
|
|
8
8
|
from infrahub.workflows.utils import add_branch_tag
|
|
9
9
|
|
|
10
10
|
from .models import TransformJinjaTemplateData, TransformPythonData
|
|
@@ -13,8 +13,7 @@ log = get_logger()
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
@flow(name="transform_render_python", flow_run_name="Render transform python", persist_result=True)
|
|
16
|
-
async def transform_python(message: TransformPythonData) -> Any:
|
|
17
|
-
service = services.service
|
|
16
|
+
async def transform_python(message: TransformPythonData, service: InfrahubServices) -> Any:
|
|
18
17
|
await add_branch_tag(branch_name=message.branch)
|
|
19
18
|
|
|
20
19
|
repo = await get_initialized_repo(
|
|
@@ -37,8 +36,7 @@ async def transform_python(message: TransformPythonData) -> Any:
|
|
|
37
36
|
|
|
38
37
|
|
|
39
38
|
@flow(name="transform_render_jinja2_template", flow_run_name="Render transform Jinja2", persist_result=True)
|
|
40
|
-
async def transform_render_jinja2_template(message: TransformJinjaTemplateData) -> str:
|
|
41
|
-
service = services.service
|
|
39
|
+
async def transform_render_jinja2_template(message: TransformJinjaTemplateData, service: InfrahubServices) -> str:
|
|
42
40
|
await add_branch_tag(branch_name=message.branch)
|
|
43
41
|
|
|
44
42
|
repo = await get_initialized_repo(
|
|
File without changes
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from infrahub.computed_attribute.triggers import (
|
|
2
|
+
TRIGGER_COMPUTED_ATTRIBUTE_ALL_SCHEMA,
|
|
3
|
+
TRIGGER_COMPUTED_ATTRIBUTE_PYTHON_CLEAN_BRANCH,
|
|
4
|
+
TRIGGER_COMPUTED_ATTRIBUTE_PYTHON_SETUP_BRANCH,
|
|
5
|
+
TRIGGER_COMPUTED_ATTRIBUTE_PYTHON_SETUP_COMMIT,
|
|
6
|
+
)
|
|
7
|
+
from infrahub.trigger.models import TriggerDefinition
|
|
8
|
+
from infrahub.webhook.triggers import TRIGGER_WEBHOOK_SETUP_UPDATE
|
|
9
|
+
|
|
10
|
+
builtin_triggers: list[TriggerDefinition] = [
|
|
11
|
+
TRIGGER_COMPUTED_ATTRIBUTE_ALL_SCHEMA,
|
|
12
|
+
TRIGGER_COMPUTED_ATTRIBUTE_PYTHON_CLEAN_BRANCH,
|
|
13
|
+
TRIGGER_COMPUTED_ATTRIBUTE_PYTHON_SETUP_BRANCH,
|
|
14
|
+
TRIGGER_COMPUTED_ATTRIBUTE_PYTHON_SETUP_COMMIT,
|
|
15
|
+
TRIGGER_WEBHOOK_SETUP_UPDATE,
|
|
16
|
+
]
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
DEPRECATED_STATIC_TRIGGER_NAMES = [
|
|
2
|
+
"Trigger-branch-create-events", # used in 1.1.x
|
|
3
|
+
"Trigger-branch-remove-events", # used in 1.1.x
|
|
4
|
+
"Trigger-webhook-update-configuration", # used in 1.1.x
|
|
5
|
+
"Trigger-repository-commit-update-event", # used in 1.1.x
|
|
6
|
+
"Trigger-schema-update-event", # used in 1.1.x
|
|
7
|
+
]
|
|
8
|
+
|
|
9
|
+
NAME_SEPARATOR = "::"
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from datetime import timedelta
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from typing import TYPE_CHECKING, Any
|
|
6
|
+
|
|
7
|
+
from prefect.events.actions import RunDeployment
|
|
8
|
+
from prefect.events.schemas.automations import EventTrigger as PrefectEventTrigger
|
|
9
|
+
from prefect.events.schemas.automations import Posture
|
|
10
|
+
from prefect.events.schemas.events import ResourceSpecification
|
|
11
|
+
from pydantic import BaseModel, Field
|
|
12
|
+
|
|
13
|
+
from infrahub.workflows.models import WorkflowDefinition # noqa: TC001
|
|
14
|
+
|
|
15
|
+
from .constants import NAME_SEPARATOR
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from uuid import UUID
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class TriggerType(str, Enum):
|
|
22
|
+
BUILTIN = "builtin"
|
|
23
|
+
WEBHOOK = "webhook"
|
|
24
|
+
# OBJECT = "object"
|
|
25
|
+
# COMPUTED_ATTR = "computed_attr"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class EventTrigger(BaseModel):
|
|
29
|
+
events: set = Field(default_factory=set)
|
|
30
|
+
match: dict[str, Any] = Field(default_factory=dict)
|
|
31
|
+
match_related: dict[str, Any] = Field(default_factory=dict)
|
|
32
|
+
|
|
33
|
+
def get_prefect(self) -> PrefectEventTrigger:
|
|
34
|
+
return PrefectEventTrigger(
|
|
35
|
+
posture=Posture.Reactive,
|
|
36
|
+
expect=self.events,
|
|
37
|
+
within=timedelta(0),
|
|
38
|
+
match=ResourceSpecification(self.match),
|
|
39
|
+
match_related=ResourceSpecification(self.match_related),
|
|
40
|
+
threshold=1,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class ExecuteWorkflow(BaseModel):
|
|
45
|
+
workflow: WorkflowDefinition
|
|
46
|
+
parameters: dict[str, Any] = Field(default_factory=dict)
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def name(self) -> str:
|
|
50
|
+
return self.workflow.name
|
|
51
|
+
|
|
52
|
+
def get_prefect(self, mapping: dict[str, UUID]) -> RunDeployment:
|
|
53
|
+
deployment_id = mapping[self.name]
|
|
54
|
+
return self.get(deployment_id)
|
|
55
|
+
|
|
56
|
+
def get(self, id: UUID) -> RunDeployment:
|
|
57
|
+
return RunDeployment(
|
|
58
|
+
source="selected",
|
|
59
|
+
deployment_id=id,
|
|
60
|
+
parameters=self.parameters,
|
|
61
|
+
job_variables={},
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
def validate_parameters(self) -> None:
|
|
65
|
+
if not self.parameters:
|
|
66
|
+
return
|
|
67
|
+
|
|
68
|
+
workflow_params = self.workflow.get_parameters()
|
|
69
|
+
workflow_required_params = [p.name for p in workflow_params.values() if p.required]
|
|
70
|
+
trigger_params = list(self.parameters.keys())
|
|
71
|
+
|
|
72
|
+
missing_required_params = set(workflow_required_params) - set(trigger_params)
|
|
73
|
+
wrong_params = set(trigger_params) - set(workflow_params)
|
|
74
|
+
|
|
75
|
+
if missing_required_params:
|
|
76
|
+
raise ValueError(
|
|
77
|
+
f"Missing required parameters: {missing_required_params} for workflow {self.workflow.name}"
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
if wrong_params:
|
|
81
|
+
raise ValueError(f"Workflow {self.workflow.name} doesn't support parameters: {wrong_params}")
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class TriggerDefinition(BaseModel):
|
|
85
|
+
name: str
|
|
86
|
+
type: TriggerType
|
|
87
|
+
previous_names: set = Field(default_factory=set)
|
|
88
|
+
description: str = ""
|
|
89
|
+
trigger: EventTrigger
|
|
90
|
+
actions: list[ExecuteWorkflow]
|
|
91
|
+
|
|
92
|
+
def get_deployment_names(self) -> list[str]:
|
|
93
|
+
"""Return the name of all deployments used by this trigger"""
|
|
94
|
+
return [action.name for action in self.actions]
|
|
95
|
+
|
|
96
|
+
def generate_name(self) -> str:
|
|
97
|
+
return f"{self.type.value}{NAME_SEPARATOR}{self.name}"
|
|
98
|
+
|
|
99
|
+
def validate_actions(self) -> None:
|
|
100
|
+
for action in self.actions:
|
|
101
|
+
action.validate_parameters()
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class BuiltinTriggerDefinition(TriggerDefinition):
|
|
105
|
+
type: TriggerType = TriggerType.BUILTIN
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
|
+
|
|
3
|
+
from prefect import get_run_logger, task
|
|
4
|
+
from prefect.automations import AutomationCore
|
|
5
|
+
from prefect.cache_policies import NONE
|
|
6
|
+
from prefect.client.orchestration import PrefectClient
|
|
7
|
+
from prefect.client.schemas.filters import DeploymentFilter, DeploymentFilterName
|
|
8
|
+
|
|
9
|
+
from infrahub.trigger.models import TriggerDefinition
|
|
10
|
+
|
|
11
|
+
# from .catalogue import triggers
|
|
12
|
+
from .models import TriggerType
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from uuid import UUID
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@task(name="trigger-setup", task_run_name="Setup triggers of type {trigger_type.value}", cache_policy=NONE) # type: ignore[arg-type]
|
|
19
|
+
async def setup_triggers(
|
|
20
|
+
client: PrefectClient,
|
|
21
|
+
triggers: list[TriggerDefinition],
|
|
22
|
+
trigger_type: TriggerType = TriggerType.BUILTIN,
|
|
23
|
+
deprecated_triggers: list[str] | None = None,
|
|
24
|
+
) -> None:
|
|
25
|
+
log = get_run_logger()
|
|
26
|
+
|
|
27
|
+
# -------------------------------------------------------------
|
|
28
|
+
# Retrieve existing Deployments and Automation from the server
|
|
29
|
+
# -------------------------------------------------------------
|
|
30
|
+
deployment_names = list({name for trigger in triggers for name in trigger.get_deployment_names()})
|
|
31
|
+
deployments = {
|
|
32
|
+
item.name: item
|
|
33
|
+
for item in await client.read_deployments(
|
|
34
|
+
deployment_filter=DeploymentFilter(name=DeploymentFilterName(any_=deployment_names))
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
deployments_mapping: dict[str, UUID] = {name: item.id for name, item in deployments.items()}
|
|
38
|
+
existing_automations = {item.name: item for item in await client.read_automations()}
|
|
39
|
+
|
|
40
|
+
trigger_automations = [
|
|
41
|
+
item.name for item in await client.read_automations() if item.name.startswith(trigger_type.value)
|
|
42
|
+
]
|
|
43
|
+
trigger_names = [trigger.generate_name() for trigger in triggers]
|
|
44
|
+
|
|
45
|
+
to_delete = set(trigger_automations) - set(trigger_names)
|
|
46
|
+
|
|
47
|
+
# -------------------------------------------------------------
|
|
48
|
+
# Create or Update all triggers
|
|
49
|
+
# -------------------------------------------------------------
|
|
50
|
+
for trigger in triggers:
|
|
51
|
+
automation = AutomationCore(
|
|
52
|
+
name=trigger.generate_name(),
|
|
53
|
+
description=trigger.description,
|
|
54
|
+
enabled=True,
|
|
55
|
+
trigger=trigger.trigger.get_prefect(),
|
|
56
|
+
actions=[action.get_prefect(mapping=deployments_mapping) for action in trigger.actions],
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
existing_automation = existing_automations.get(trigger.name, None)
|
|
60
|
+
|
|
61
|
+
if existing_automation:
|
|
62
|
+
await client.update_automation(automation_id=existing_automation.id, automation=automation)
|
|
63
|
+
log.info(f"{trigger.name} Updated")
|
|
64
|
+
else:
|
|
65
|
+
await client.create_automation(automation=automation)
|
|
66
|
+
log.info(f"{trigger.name} Created")
|
|
67
|
+
|
|
68
|
+
# -------------------------------------------------------------
|
|
69
|
+
# Delete Triggers that shouldn't be there
|
|
70
|
+
# -------------------------------------------------------------
|
|
71
|
+
for item_to_delete in to_delete:
|
|
72
|
+
existing_automation = existing_automations.get(item_to_delete)
|
|
73
|
+
|
|
74
|
+
if not existing_automation:
|
|
75
|
+
continue
|
|
76
|
+
|
|
77
|
+
await client.delete_automation(automation_id=existing_automation.id)
|
|
78
|
+
log.info(f"{item_to_delete} Deleted")
|
|
79
|
+
|
|
80
|
+
# -------------------------------------------------------------
|
|
81
|
+
# Delete Deprecated triggers
|
|
82
|
+
# -------------------------------------------------------------
|
|
83
|
+
if deprecated_triggers:
|
|
84
|
+
for trigger_name in deprecated_triggers:
|
|
85
|
+
existing_automation = existing_automations.get(trigger_name)
|
|
86
|
+
|
|
87
|
+
if not existing_automation:
|
|
88
|
+
continue
|
|
89
|
+
|
|
90
|
+
await client.delete_automation(automation_id=existing_automation.id)
|
|
91
|
+
log.info(f"{trigger_name} Deleted")
|
infrahub/types.py
CHANGED
|
@@ -354,7 +354,7 @@ ATTRIBUTE_PYTHON_TYPES: dict[str, type] = {
|
|
|
354
354
|
"Color": str, # Colors often represented as hex strings
|
|
355
355
|
"Number": float, # Numbers can be floats for general use
|
|
356
356
|
"Bandwidth": float, # Bandwidth in some units, represented as a float
|
|
357
|
-
"IPHost": IPvAnyAddress,
|
|
357
|
+
"IPHost": IPvAnyAddress, # type: ignore[dict-item]
|
|
358
358
|
"IPNetwork": str,
|
|
359
359
|
"Boolean": bool,
|
|
360
360
|
"Checkbox": bool, # Checkboxes represent boolean values
|
infrahub/utils.py
CHANGED
infrahub/webhook/constants.py
CHANGED
infrahub/webhook/models.py
CHANGED
|
@@ -1,64 +1,158 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import base64
|
|
2
4
|
import hashlib
|
|
3
5
|
import hmac
|
|
4
|
-
from
|
|
5
|
-
from
|
|
6
|
-
from typing import Any, Optional, Union
|
|
7
|
-
from uuid import uuid4
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Optional, Union
|
|
7
|
+
from uuid import UUID, uuid4
|
|
8
8
|
|
|
9
|
-
from
|
|
10
|
-
from
|
|
9
|
+
from pydantic import BaseModel, ConfigDict, Field, computed_field
|
|
10
|
+
from typing_extensions import Self
|
|
11
11
|
|
|
12
|
+
from infrahub.core import registry
|
|
12
13
|
from infrahub.core.constants import InfrahubKind
|
|
14
|
+
from infrahub.core.timestamp import Timestamp
|
|
13
15
|
from infrahub.git.repository import InfrahubReadOnlyRepository, InfrahubRepository
|
|
14
|
-
from infrahub.
|
|
15
|
-
from infrahub.
|
|
16
|
+
from infrahub.trigger.models import EventTrigger, ExecuteWorkflow, TriggerDefinition, TriggerType
|
|
17
|
+
from infrahub.workflows.catalogue import WEBHOOK_PROCESS
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from httpx import Response
|
|
21
|
+
from infrahub_sdk.protocols import CoreCustomWebhook, CoreStandardWebhook, CoreTransformPython, CoreWebhook
|
|
22
|
+
|
|
23
|
+
from infrahub.services import InfrahubServices
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class WebhookTriggerDefinition(TriggerDefinition):
|
|
27
|
+
type: TriggerType = TriggerType.WEBHOOK
|
|
28
|
+
|
|
29
|
+
@classmethod
|
|
30
|
+
def from_object(cls, obj: CoreWebhook) -> Self:
|
|
31
|
+
event_trigger = EventTrigger()
|
|
32
|
+
if obj.event_type.value == "all":
|
|
33
|
+
event_trigger.events.add("infrahub.*")
|
|
34
|
+
else:
|
|
35
|
+
event_trigger.events.add(obj.event_type.value)
|
|
36
|
+
|
|
37
|
+
if obj.branch_scope.value == "default_branch":
|
|
38
|
+
event_trigger.match_related = {
|
|
39
|
+
"prefect.resource.role": "infrahub.branch",
|
|
40
|
+
"infrahub.resource.label": registry.default_branch,
|
|
41
|
+
}
|
|
42
|
+
elif obj.branch_scope.value == "other_branches":
|
|
43
|
+
event_trigger.match_related = {
|
|
44
|
+
"prefect.resource.role": "infrahub.branch",
|
|
45
|
+
"infrahub.resource.label": f"!{registry.default_branch}",
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
definition = cls(
|
|
49
|
+
name=obj.name.value,
|
|
50
|
+
trigger=event_trigger,
|
|
51
|
+
actions=[
|
|
52
|
+
ExecuteWorkflow(
|
|
53
|
+
workflow=WEBHOOK_PROCESS,
|
|
54
|
+
parameters={
|
|
55
|
+
"webhook_id": obj.id,
|
|
56
|
+
"webhook_kind": obj.get_kind(),
|
|
57
|
+
"event_id": "{{ event.id }}",
|
|
58
|
+
"event_type": "{{ event.event }}",
|
|
59
|
+
"event_occured_at": "{{ event.occurred }}",
|
|
60
|
+
"event_payload": {
|
|
61
|
+
"__prefect_kind": "json",
|
|
62
|
+
"value": {"__prefect_kind": "jinja", "template": "{{ event.payload | tojson }}"},
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
),
|
|
66
|
+
],
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
return definition
|
|
16
70
|
|
|
17
71
|
|
|
18
|
-
class
|
|
19
|
-
"
|
|
72
|
+
class EventContext(BaseModel):
|
|
73
|
+
id: str = Field(..., description="The internal id of the event")
|
|
74
|
+
branch: str | None = Field(None, description="The branch associated with the event")
|
|
75
|
+
account_id: str | None = Field(None, description="The id of the account associated with the event")
|
|
76
|
+
occured_at: str = Field(..., description="The time when the event occurred")
|
|
77
|
+
event: str = Field(..., description="The event type")
|
|
20
78
|
|
|
21
|
-
|
|
22
|
-
event_type: str
|
|
23
|
-
|
|
79
|
+
@classmethod
|
|
80
|
+
def from_event(cls, event_id: str, event_type: str, event_occured_at: str, event_payload: dict[str, Any]) -> Self:
|
|
81
|
+
"""Extract the context from the raw event we are getting from Prefect."""
|
|
82
|
+
|
|
83
|
+
infrahub_context: dict[str, Any] = event_payload.get("context", {})
|
|
84
|
+
account_info: dict[str, Any] = infrahub_context.get("account", {})
|
|
85
|
+
branch_info: dict[str, Any] = infrahub_context.get("branch", {})
|
|
86
|
+
|
|
87
|
+
return cls(
|
|
88
|
+
id=event_id,
|
|
89
|
+
branch=branch_info.get("name")
|
|
90
|
+
if branch_info and branch_info.get("name") != registry.get_global_branch().name
|
|
91
|
+
else None,
|
|
92
|
+
account_id=account_info.get("account_id"),
|
|
93
|
+
occured_at=event_occured_at,
|
|
94
|
+
event=event_type,
|
|
95
|
+
)
|
|
24
96
|
|
|
25
97
|
|
|
26
98
|
class Webhook(BaseModel):
|
|
27
99
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
28
|
-
|
|
100
|
+
name: str = Field(...)
|
|
29
101
|
url: str = Field(...)
|
|
30
102
|
event_type: str = Field(...)
|
|
31
|
-
data: dict[str, Any] = Field(...)
|
|
32
103
|
validate_certificates: bool = Field(...)
|
|
33
104
|
_payload: Any = None
|
|
34
105
|
_headers: Optional[dict[str, Any]] = None
|
|
35
106
|
|
|
36
|
-
async def _prepare_payload(self) -> None:
|
|
37
|
-
self._payload = {"
|
|
107
|
+
async def _prepare_payload(self, data: dict[str, Any], context: EventContext, service: InfrahubServices) -> None: # noqa: ARG002
|
|
108
|
+
self._payload = {"data": data, **context.model_dump()}
|
|
38
109
|
|
|
39
110
|
def _assign_headers(self) -> None:
|
|
40
111
|
self._headers = {}
|
|
41
112
|
|
|
113
|
+
@computed_field # type: ignore[prop-decorator]
|
|
42
114
|
@property
|
|
43
115
|
def webhook_type(self) -> str:
|
|
44
116
|
return self.__class__.__name__
|
|
45
117
|
|
|
46
|
-
async def
|
|
47
|
-
await self._prepare_payload()
|
|
118
|
+
async def prepare(self, data: dict[str, Any], context: EventContext, service: InfrahubServices) -> None:
|
|
119
|
+
await self._prepare_payload(data=data, context=context, service=service)
|
|
48
120
|
self._assign_headers()
|
|
49
|
-
|
|
121
|
+
|
|
122
|
+
async def send(self, data: dict[str, Any], context: EventContext, service: InfrahubServices) -> Response:
|
|
123
|
+
await self.prepare(data=data, context=context, service=service)
|
|
124
|
+
return await service.http.post(url=self.url, json=self.get_payload(), headers=self._headers)
|
|
125
|
+
|
|
126
|
+
def get_payload(self) -> dict[str, Any]:
|
|
127
|
+
return self._payload
|
|
128
|
+
|
|
129
|
+
def to_cache(self) -> dict[str, Any]:
|
|
130
|
+
return self.model_dump()
|
|
131
|
+
|
|
132
|
+
@classmethod
|
|
133
|
+
def from_cache(cls, data: dict[str, Any]) -> Self:
|
|
134
|
+
return cls(**data)
|
|
50
135
|
|
|
51
136
|
|
|
52
137
|
class CustomWebhook(Webhook):
|
|
53
138
|
"""Custom webhook"""
|
|
54
139
|
|
|
140
|
+
@classmethod
|
|
141
|
+
def from_object(cls, obj: CoreCustomWebhook) -> Self:
|
|
142
|
+
return cls(
|
|
143
|
+
name=obj.name.value,
|
|
144
|
+
url=obj.url.value,
|
|
145
|
+
event_type=obj.event_type.value,
|
|
146
|
+
validate_certificates=obj.validate_certificates.value or False,
|
|
147
|
+
)
|
|
148
|
+
|
|
55
149
|
|
|
56
150
|
class StandardWebhook(Webhook):
|
|
57
|
-
shared_key:
|
|
151
|
+
shared_key: str = Field(...)
|
|
58
152
|
|
|
59
|
-
def _assign_headers(self) -> None:
|
|
60
|
-
message_id = f"msg_{uuid4().hex}"
|
|
61
|
-
timestamp = str(
|
|
153
|
+
def _assign_headers(self, uuid: UUID | None = None, at: Timestamp | None = None) -> None:
|
|
154
|
+
message_id = f"msg_{uuid.hex}" if uuid else f"msg_{uuid4().hex}"
|
|
155
|
+
timestamp = str(at.to_timestamp()) if at else str(Timestamp().to_timestamp())
|
|
62
156
|
payload = self._payload or {}
|
|
63
157
|
unsigned_data = f"{message_id}.{timestamp}.{payload}".encode()
|
|
64
158
|
signature = self._sign(data=unsigned_data)
|
|
@@ -72,7 +166,17 @@ class StandardWebhook(Webhook):
|
|
|
72
166
|
}
|
|
73
167
|
|
|
74
168
|
def _sign(self, data: bytes) -> bytes:
|
|
75
|
-
return hmac.new(key=self.shared_key, msg=data, digestmod=hashlib.sha256).digest()
|
|
169
|
+
return hmac.new(key=self.shared_key.encode(), msg=data, digestmod=hashlib.sha256).digest()
|
|
170
|
+
|
|
171
|
+
@classmethod
|
|
172
|
+
def from_object(cls, obj: CoreStandardWebhook) -> Self:
|
|
173
|
+
return cls(
|
|
174
|
+
name=obj.name.value,
|
|
175
|
+
url=obj.url.value,
|
|
176
|
+
event_type=obj.event_type.value,
|
|
177
|
+
validate_certificates=obj.validate_certificates.value or False,
|
|
178
|
+
shared_key=obj.shared_key.value,
|
|
179
|
+
)
|
|
76
180
|
|
|
77
181
|
|
|
78
182
|
class TransformWebhook(Webhook):
|
|
@@ -82,31 +186,48 @@ class TransformWebhook(Webhook):
|
|
|
82
186
|
transform_name: str = Field(...)
|
|
83
187
|
transform_class: str = Field(...)
|
|
84
188
|
transform_file: str = Field(...)
|
|
189
|
+
transform_timeout: int = Field(...)
|
|
85
190
|
|
|
86
|
-
async def _prepare_payload(self) -> None:
|
|
191
|
+
async def _prepare_payload(self, data: dict[str, Any], context: EventContext, service: InfrahubServices) -> None:
|
|
87
192
|
repo: Union[InfrahubReadOnlyRepository, InfrahubRepository]
|
|
88
193
|
if self.repository_kind == InfrahubKind.READONLYREPOSITORY:
|
|
89
194
|
repo = await InfrahubReadOnlyRepository.init(
|
|
90
|
-
id=self.repository_id,
|
|
195
|
+
id=self.repository_id,
|
|
196
|
+
name=self.repository_name,
|
|
197
|
+
client=service.client,
|
|
198
|
+
service=service,
|
|
91
199
|
)
|
|
92
200
|
else:
|
|
93
201
|
repo = await InfrahubRepository.init(
|
|
94
|
-
id=self.repository_id,
|
|
202
|
+
id=self.repository_id,
|
|
203
|
+
name=self.repository_name,
|
|
204
|
+
client=service.client,
|
|
205
|
+
service=service,
|
|
95
206
|
)
|
|
96
207
|
|
|
97
|
-
|
|
98
|
-
commit = repo.get_commit_value(branch_name=
|
|
99
|
-
|
|
100
|
-
timeout = DEFAULT_TRANSFORM_TIMEOUT
|
|
101
|
-
if transform := await self.service.client.get(
|
|
102
|
-
kind=CoreTransformPython, name__value=self.transform_name, raise_when_missing=False
|
|
103
|
-
):
|
|
104
|
-
timeout = transform.timeout.value
|
|
208
|
+
branch = context.branch or repo.default_branch
|
|
209
|
+
commit = repo.get_commit_value(branch_name=branch)
|
|
105
210
|
|
|
106
|
-
self._payload = await repo.execute_python_transform.with_options(timeout_seconds=
|
|
107
|
-
branch_name=
|
|
211
|
+
self._payload = await repo.execute_python_transform.with_options(timeout_seconds=self.transform_timeout)(
|
|
212
|
+
branch_name=branch,
|
|
108
213
|
commit=commit,
|
|
109
214
|
location=f"{self.transform_file}::{self.transform_class}",
|
|
110
|
-
data={"
|
|
111
|
-
client=
|
|
215
|
+
data={"data": data, **context.model_dump()},
|
|
216
|
+
client=service.client,
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
@classmethod
|
|
220
|
+
def from_object(cls, obj: CoreCustomWebhook, transform: CoreTransformPython) -> Self:
|
|
221
|
+
return cls(
|
|
222
|
+
name=obj.name.value,
|
|
223
|
+
url=obj.url.value,
|
|
224
|
+
event_type=obj.event_type.value,
|
|
225
|
+
validate_certificates=obj.validate_certificates.value or False,
|
|
226
|
+
repository_id=transform.repository.id,
|
|
227
|
+
repository_name=transform.repository.peer.name.value,
|
|
228
|
+
repository_kind=transform.repository.peer.get_kind(),
|
|
229
|
+
transform_name=transform.name.value,
|
|
230
|
+
transform_class=transform.class_name.value,
|
|
231
|
+
transform_file=transform.file_path.value,
|
|
232
|
+
transform_timeout=transform.timeout.value,
|
|
112
233
|
)
|