infrahub-server 1.2.11__py3-none-any.whl → 1.3.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/actions/constants.py +86 -0
- infrahub/actions/gather.py +114 -0
- infrahub/actions/models.py +241 -0
- infrahub/actions/parsers.py +104 -0
- infrahub/actions/schema.py +382 -0
- infrahub/actions/tasks.py +126 -0
- infrahub/actions/triggers.py +21 -0
- infrahub/cli/db.py +1 -2
- infrahub/core/account.py +24 -47
- infrahub/core/attribute.py +13 -15
- infrahub/core/constants/__init__.py +5 -0
- infrahub/core/constants/infrahubkind.py +9 -0
- infrahub/core/convert_object_type/__init__.py +0 -0
- infrahub/core/convert_object_type/conversion.py +122 -0
- infrahub/core/convert_object_type/schema_mapping.py +56 -0
- infrahub/core/diff/query/all_conflicts.py +1 -5
- infrahub/core/diff/query/artifact.py +10 -20
- infrahub/core/diff/query/diff_get.py +3 -6
- infrahub/core/diff/query/field_summary.py +2 -4
- infrahub/core/diff/query/merge.py +70 -123
- infrahub/core/diff/query/save.py +20 -32
- infrahub/core/diff/query/summary_counts_enricher.py +34 -54
- infrahub/core/manager.py +14 -11
- infrahub/core/migrations/graph/m003_relationship_parent_optional.py +1 -2
- infrahub/core/migrations/graph/m013_convert_git_password_credential.py +2 -4
- infrahub/core/migrations/graph/m019_restore_rels_to_time.py +11 -22
- infrahub/core/migrations/graph/m020_duplicate_edges.py +3 -6
- infrahub/core/migrations/graph/m021_missing_hierarchy_merge.py +1 -2
- infrahub/core/migrations/graph/m024_missing_hierarchy_backfill.py +1 -2
- infrahub/core/migrations/query/attribute_add.py +1 -2
- infrahub/core/migrations/query/attribute_rename.py +5 -10
- infrahub/core/migrations/query/delete_element_in_schema.py +19 -17
- infrahub/core/migrations/query/node_duplicate.py +19 -21
- infrahub/core/migrations/query/relationship_duplicate.py +19 -17
- infrahub/core/migrations/schema/node_attribute_remove.py +4 -8
- infrahub/core/migrations/schema/node_remove.py +19 -19
- infrahub/core/models.py +29 -2
- infrahub/core/node/__init__.py +90 -18
- infrahub/core/node/create.py +211 -0
- infrahub/core/node/resource_manager/number_pool.py +31 -5
- infrahub/core/node/standard.py +6 -1
- infrahub/core/protocols.py +56 -0
- infrahub/core/protocols_base.py +3 -0
- infrahub/core/query/__init__.py +2 -2
- infrahub/core/query/diff.py +19 -32
- infrahub/core/query/ipam.py +10 -20
- infrahub/core/query/node.py +28 -46
- infrahub/core/query/relationship.py +53 -32
- infrahub/core/query/resource_manager.py +1 -2
- infrahub/core/query/subquery.py +2 -4
- infrahub/core/relationship/model.py +3 -0
- infrahub/core/schema/__init__.py +2 -1
- infrahub/core/schema/attribute_parameters.py +160 -0
- infrahub/core/schema/attribute_schema.py +111 -8
- infrahub/core/schema/basenode_schema.py +25 -1
- infrahub/core/schema/definitions/core/__init__.py +29 -1
- infrahub/core/schema/definitions/core/group.py +45 -0
- infrahub/core/schema/definitions/internal.py +27 -4
- infrahub/core/schema/generated/attribute_schema.py +16 -3
- infrahub/core/schema/manager.py +3 -0
- infrahub/core/schema/schema_branch.py +67 -7
- infrahub/core/validators/__init__.py +13 -1
- infrahub/core/validators/attribute/choices.py +1 -3
- infrahub/core/validators/attribute/enum.py +1 -3
- infrahub/core/validators/attribute/kind.py +1 -3
- infrahub/core/validators/attribute/length.py +13 -7
- infrahub/core/validators/attribute/min_max.py +118 -0
- infrahub/core/validators/attribute/number_pool.py +106 -0
- infrahub/core/validators/attribute/optional.py +1 -4
- infrahub/core/validators/attribute/regex.py +5 -6
- infrahub/core/validators/attribute/unique.py +1 -3
- infrahub/core/validators/determiner.py +18 -2
- infrahub/core/validators/enum.py +12 -0
- infrahub/core/validators/node/hierarchy.py +3 -6
- infrahub/core/validators/query.py +1 -3
- infrahub/core/validators/relationship/count.py +6 -12
- infrahub/core/validators/relationship/optional.py +2 -4
- infrahub/core/validators/relationship/peer.py +3 -8
- infrahub/core/validators/uniqueness/query.py +5 -9
- infrahub/database/__init__.py +11 -2
- infrahub/events/group_action.py +1 -0
- infrahub/git/base.py +5 -3
- infrahub/git/integrator.py +102 -3
- infrahub/graphql/analyzer.py +139 -18
- infrahub/graphql/manager.py +4 -0
- infrahub/graphql/mutations/action.py +164 -0
- infrahub/graphql/mutations/convert_object_type.py +62 -0
- infrahub/graphql/mutations/main.py +24 -175
- infrahub/graphql/mutations/proposed_change.py +20 -17
- infrahub/graphql/mutations/resource_manager.py +62 -6
- infrahub/graphql/queries/convert_object_type_mapping.py +36 -0
- infrahub/graphql/queries/resource_manager.py +7 -1
- infrahub/graphql/schema.py +6 -0
- infrahub/menu/menu.py +31 -0
- infrahub/message_bus/messages/__init__.py +0 -10
- infrahub/message_bus/operations/__init__.py +0 -8
- infrahub/patch/queries/consolidate_duplicated_nodes.py +3 -6
- infrahub/patch/queries/delete_duplicated_edges.py +5 -10
- infrahub/pools/number.py +5 -3
- infrahub/prefect_server/models.py +1 -19
- infrahub/proposed_change/models.py +68 -3
- infrahub/proposed_change/tasks.py +907 -30
- infrahub/task_manager/models.py +10 -6
- infrahub/trigger/catalogue.py +2 -0
- infrahub/trigger/models.py +18 -2
- infrahub/trigger/tasks.py +3 -1
- infrahub/types.py +6 -0
- infrahub/workflows/catalogue.py +76 -0
- infrahub_sdk/client.py +43 -10
- infrahub_sdk/node/__init__.py +39 -0
- infrahub_sdk/node/attribute.py +122 -0
- infrahub_sdk/node/constants.py +21 -0
- infrahub_sdk/{node.py → node/node.py} +50 -749
- infrahub_sdk/node/parsers.py +15 -0
- infrahub_sdk/node/property.py +24 -0
- infrahub_sdk/node/related_node.py +266 -0
- infrahub_sdk/node/relationship.py +302 -0
- infrahub_sdk/protocols.py +112 -0
- infrahub_sdk/protocols_base.py +34 -2
- infrahub_sdk/query_groups.py +13 -2
- infrahub_sdk/schema/main.py +1 -0
- infrahub_sdk/schema/repository.py +16 -0
- infrahub_sdk/spec/object.py +1 -1
- infrahub_sdk/store.py +1 -1
- infrahub_sdk/testing/schemas/car_person.py +1 -0
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/METADATA +4 -4
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/RECORD +134 -122
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/WHEEL +1 -1
- infrahub_testcontainers/container.py +0 -1
- infrahub_testcontainers/docker-compose.test.yml +1 -1
- infrahub_testcontainers/helpers.py +8 -2
- infrahub/message_bus/messages/check_generator_run.py +0 -26
- infrahub/message_bus/messages/finalize_validator_execution.py +0 -15
- infrahub/message_bus/messages/proposed_change/base_with_diff.py +0 -16
- infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +0 -11
- infrahub/message_bus/messages/request_generatordefinition_check.py +0 -20
- infrahub/message_bus/messages/request_proposedchange_pipeline.py +0 -23
- infrahub/message_bus/operations/check/__init__.py +0 -3
- infrahub/message_bus/operations/check/generator.py +0 -156
- infrahub/message_bus/operations/finalize/__init__.py +0 -3
- infrahub/message_bus/operations/finalize/validator.py +0 -133
- infrahub/message_bus/operations/requests/__init__.py +0 -9
- infrahub/message_bus/operations/requests/generator_definition.py +0 -140
- infrahub/message_bus/operations/requests/proposed_change.py +0 -629
- /infrahub/{message_bus/messages/proposed_change → actions}/__init__.py +0 -0
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0b1.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
from infrahub.core.constants import InfrahubKind
|
|
6
|
+
from infrahub.core.schema.dropdown import DropdownChoice
|
|
7
|
+
from infrahub.utils import InfrahubStringEnum
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class NodeAction(InfrahubStringEnum):
|
|
11
|
+
CREATED = "created"
|
|
12
|
+
DELETED = "deleted"
|
|
13
|
+
UPDATED = "updated"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class BranchScope(Enum):
|
|
17
|
+
ALL_BRANCHES = DropdownChoice(
|
|
18
|
+
name="all_branches",
|
|
19
|
+
label="All Branches",
|
|
20
|
+
description="All branches",
|
|
21
|
+
color="#fef08a",
|
|
22
|
+
)
|
|
23
|
+
DEFAULT_BRANCH = DropdownChoice(
|
|
24
|
+
name="default_branch",
|
|
25
|
+
label="Default Branch",
|
|
26
|
+
description="Only the default branch",
|
|
27
|
+
color="#86efac",
|
|
28
|
+
)
|
|
29
|
+
OTHER_BRANCHES = DropdownChoice(
|
|
30
|
+
name="other_branches",
|
|
31
|
+
label="Other Branches",
|
|
32
|
+
description="All branches except the default branch",
|
|
33
|
+
color="#e5e7eb",
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
@classmethod
|
|
37
|
+
def available_types(cls) -> list[DropdownChoice]:
|
|
38
|
+
return [cls.__members__[member].value for member in list(cls.__members__)]
|
|
39
|
+
|
|
40
|
+
@classmethod
|
|
41
|
+
def from_value(cls, value: str) -> BranchScope:
|
|
42
|
+
for member in cls.__members__:
|
|
43
|
+
if value == cls.__members__[member].value.name:
|
|
44
|
+
return cls.__members__[member]
|
|
45
|
+
|
|
46
|
+
raise NotImplementedError(f"The defined value {value} doesn't match a branch scope")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class ValueMatch(Enum):
|
|
50
|
+
VALUE = DropdownChoice(
|
|
51
|
+
name="value",
|
|
52
|
+
label="Value",
|
|
53
|
+
description="Match against the current value",
|
|
54
|
+
color="#fef08a",
|
|
55
|
+
)
|
|
56
|
+
VALUE_PREVIOUS = DropdownChoice(
|
|
57
|
+
name="value_previous",
|
|
58
|
+
label="Value Previous",
|
|
59
|
+
description="Match against the previous value",
|
|
60
|
+
color="#86efac",
|
|
61
|
+
)
|
|
62
|
+
VALUE_FULL = DropdownChoice(
|
|
63
|
+
name="value_full",
|
|
64
|
+
label="Full value match",
|
|
65
|
+
description="Match against both the current and previous values",
|
|
66
|
+
color="#e5e7eb",
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
@classmethod
|
|
70
|
+
def available_types(cls) -> list[DropdownChoice]:
|
|
71
|
+
return [cls.__members__[member].value for member in list(cls.__members__)]
|
|
72
|
+
|
|
73
|
+
@classmethod
|
|
74
|
+
def from_value(cls, value: str) -> ValueMatch:
|
|
75
|
+
for member in cls.__members__:
|
|
76
|
+
if value == cls.__members__[member].value.name:
|
|
77
|
+
return cls.__members__[member]
|
|
78
|
+
|
|
79
|
+
raise NotImplementedError(f"The defined value {value} doesn't match a ValueMatch")
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
NODES_THAT_TRIGGER_ACTION_RULES_SETUP = [
|
|
83
|
+
InfrahubKind.GROUPACTION,
|
|
84
|
+
InfrahubKind.GROUPTRIGGERRULE,
|
|
85
|
+
InfrahubKind.NODETRIGGERRULE,
|
|
86
|
+
]
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from graphql import graphql
|
|
4
|
+
from infrahub_sdk.graphql import Query
|
|
5
|
+
from prefect import task
|
|
6
|
+
from prefect.cache_policies import NONE
|
|
7
|
+
|
|
8
|
+
from infrahub.core.constants import InfrahubKind
|
|
9
|
+
from infrahub.core.registry import registry
|
|
10
|
+
from infrahub.database import InfrahubDatabase # noqa: TC001 needed for prefect flow
|
|
11
|
+
from infrahub.graphql.initialization import prepare_graphql_params
|
|
12
|
+
|
|
13
|
+
from .models import ActionTriggerRuleTriggerDefinition
|
|
14
|
+
from .parsers import parse_trigger_rule_response
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@task(
|
|
18
|
+
name="gather-trigger-action-rules",
|
|
19
|
+
cache_policy=NONE,
|
|
20
|
+
)
|
|
21
|
+
async def gather_trigger_action_rules(db: InfrahubDatabase) -> list[ActionTriggerRuleTriggerDefinition]:
|
|
22
|
+
trigger_query = Query(
|
|
23
|
+
name=InfrahubKind.TRIGGERRULE,
|
|
24
|
+
query={
|
|
25
|
+
InfrahubKind.TRIGGERRULE: {
|
|
26
|
+
"edges": {
|
|
27
|
+
"node": {
|
|
28
|
+
"__typename": None,
|
|
29
|
+
"id": None,
|
|
30
|
+
"name": {"value": None},
|
|
31
|
+
"branch_scope": {"value": None},
|
|
32
|
+
"active": {"value": None},
|
|
33
|
+
"... on CoreNodeTriggerRule": {
|
|
34
|
+
"node_kind": {"value": None},
|
|
35
|
+
"mutation_action": {"value": None},
|
|
36
|
+
"matches": {
|
|
37
|
+
"edges": {
|
|
38
|
+
"node": {
|
|
39
|
+
"__typename": None,
|
|
40
|
+
"id": None,
|
|
41
|
+
"... on CoreNodeTriggerAttributeMatch": {
|
|
42
|
+
"attribute_name": {"value": None},
|
|
43
|
+
"value": {"value": None},
|
|
44
|
+
"value_previous": {"value": None},
|
|
45
|
+
"value_match": {"value": None},
|
|
46
|
+
},
|
|
47
|
+
"... on CoreNodeTriggerRelationshipMatch": {
|
|
48
|
+
"relationship_name": {"value": None},
|
|
49
|
+
"added": {"value": None},
|
|
50
|
+
"peer": {"value": None},
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
"... on CoreGroupTriggerRule": {
|
|
57
|
+
"members_added": {"value": None},
|
|
58
|
+
"group": {
|
|
59
|
+
"node": {
|
|
60
|
+
"id": None,
|
|
61
|
+
"__typename": None,
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
"action": {
|
|
66
|
+
"node": {
|
|
67
|
+
"__typename": None,
|
|
68
|
+
"id": None,
|
|
69
|
+
"name": {"value": None},
|
|
70
|
+
"... on CoreGroupAction": {
|
|
71
|
+
"add_members": {"value": None},
|
|
72
|
+
"group": {
|
|
73
|
+
"node": {
|
|
74
|
+
"id": None,
|
|
75
|
+
"__typename": None,
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
"... on CoreGeneratorAction": {
|
|
80
|
+
"generator": {
|
|
81
|
+
"node": {
|
|
82
|
+
"__typename": None,
|
|
83
|
+
"id": None,
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
)
|
|
94
|
+
gql_params = await prepare_graphql_params(
|
|
95
|
+
db=db,
|
|
96
|
+
branch=registry.default_branch,
|
|
97
|
+
)
|
|
98
|
+
response = await graphql(
|
|
99
|
+
schema=gql_params.schema,
|
|
100
|
+
source=trigger_query.render(),
|
|
101
|
+
context_value=gql_params.context,
|
|
102
|
+
root_value=None,
|
|
103
|
+
variable_values={},
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
data = response.data or {}
|
|
107
|
+
trigger_rules = parse_trigger_rule_response(data)
|
|
108
|
+
trigger_candidates = [
|
|
109
|
+
ActionTriggerRuleTriggerDefinition.from_trigger_rule(trigger_rule=trigger_rule)
|
|
110
|
+
for trigger_rule in trigger_rules
|
|
111
|
+
if trigger_rule.active
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
return [trigger_rule for trigger_rule in trigger_candidates if trigger_rule]
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
from typing import Self
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
|
|
5
|
+
from infrahub.core.registry import registry
|
|
6
|
+
from infrahub.events import (
|
|
7
|
+
GroupMemberAddedEvent,
|
|
8
|
+
GroupMemberRemovedEvent,
|
|
9
|
+
NodeCreatedEvent,
|
|
10
|
+
NodeDeletedEvent,
|
|
11
|
+
NodeUpdatedEvent,
|
|
12
|
+
)
|
|
13
|
+
from infrahub.trigger.models import (
|
|
14
|
+
EventTrigger,
|
|
15
|
+
ExecuteWorkflow,
|
|
16
|
+
TriggerDefinition,
|
|
17
|
+
TriggerType,
|
|
18
|
+
)
|
|
19
|
+
from infrahub.workflows.catalogue import (
|
|
20
|
+
ACTION_ADD_NODE_TO_GROUP,
|
|
21
|
+
ACTION_RUN_GENERATOR,
|
|
22
|
+
ACTION_RUN_GENERATOR_GROUP_EVENT,
|
|
23
|
+
REMOVE_ADD_NODE_FROM_GROUP,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
from .constants import BranchScope, ValueMatch
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class EventGroupMember(BaseModel):
|
|
30
|
+
id: str
|
|
31
|
+
kind: str
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class CoreAction(BaseModel):
|
|
35
|
+
"""CoreAction generic"""
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class CoreGeneratorAction(CoreAction):
|
|
39
|
+
generator_id: str
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class CoreGroupAction(CoreAction):
|
|
43
|
+
add_members: bool
|
|
44
|
+
group_id: str
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class CoreTriggerRule(BaseModel):
|
|
48
|
+
name: str
|
|
49
|
+
branch_scope: BranchScope
|
|
50
|
+
action: CoreAction
|
|
51
|
+
active: bool
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class CoreGroupTriggerRule(CoreTriggerRule):
|
|
55
|
+
members_added: bool
|
|
56
|
+
group_id: str
|
|
57
|
+
group_kind: str
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class CoreNodeTriggerMatch(BaseModel):
|
|
61
|
+
"""Node Trigger Match Generic"""
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class CoreNodeTriggerAttributeMatch(CoreNodeTriggerMatch):
|
|
65
|
+
attribute_name: str
|
|
66
|
+
value: str | None
|
|
67
|
+
value_previous: str | None
|
|
68
|
+
value_match: ValueMatch
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class CoreNodeTriggerRelationshipMatch(CoreNodeTriggerMatch):
|
|
72
|
+
relationship_name: str
|
|
73
|
+
added: bool
|
|
74
|
+
peer: str | None
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class CoreNodeTriggerRule(CoreTriggerRule):
|
|
78
|
+
node_kind: str
|
|
79
|
+
mutation_action: str
|
|
80
|
+
matches: list[CoreNodeTriggerMatch]
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class ActionTriggerRuleTriggerDefinition(TriggerDefinition):
|
|
84
|
+
type: TriggerType = TriggerType.ACTION_TRIGGER_RULE
|
|
85
|
+
|
|
86
|
+
@classmethod
|
|
87
|
+
def from_trigger_rule(cls, trigger_rule: CoreTriggerRule) -> Self | None:
|
|
88
|
+
if isinstance(trigger_rule, CoreNodeTriggerRule):
|
|
89
|
+
return cls._from_node_trigger(trigger_rule=trigger_rule)
|
|
90
|
+
|
|
91
|
+
if isinstance(trigger_rule, CoreGroupTriggerRule):
|
|
92
|
+
return cls._from_group_trigger(trigger_rule=trigger_rule)
|
|
93
|
+
|
|
94
|
+
return None
|
|
95
|
+
|
|
96
|
+
@classmethod
|
|
97
|
+
def _from_node_trigger(
|
|
98
|
+
cls,
|
|
99
|
+
trigger_rule: CoreNodeTriggerRule,
|
|
100
|
+
) -> Self:
|
|
101
|
+
event_trigger = EventTrigger()
|
|
102
|
+
|
|
103
|
+
match trigger_rule.mutation_action:
|
|
104
|
+
case "created":
|
|
105
|
+
event_trigger.events.add(NodeCreatedEvent.event_name)
|
|
106
|
+
case "deleted":
|
|
107
|
+
event_trigger.events.add(NodeDeletedEvent.event_name)
|
|
108
|
+
case "updated":
|
|
109
|
+
event_trigger.events.add(NodeUpdatedEvent.event_name)
|
|
110
|
+
|
|
111
|
+
event_trigger.match = {"infrahub.node.kind": trigger_rule.node_kind}
|
|
112
|
+
|
|
113
|
+
match trigger_rule.branch_scope:
|
|
114
|
+
case BranchScope.DEFAULT_BRANCH:
|
|
115
|
+
event_trigger.match["infrahub.branch.name"] = registry.default_branch
|
|
116
|
+
case BranchScope.OTHER_BRANCHES:
|
|
117
|
+
event_trigger.match["infrahub.branch.name"] = f"!{registry.default_branch}"
|
|
118
|
+
|
|
119
|
+
related_matches: list[dict[str, str | list[str]]] = []
|
|
120
|
+
for match in trigger_rule.matches:
|
|
121
|
+
if isinstance(match, CoreNodeTriggerAttributeMatch):
|
|
122
|
+
match_related: dict[str, str | list[str]] = {
|
|
123
|
+
"prefect.resource.role": "infrahub.node.attribute_update",
|
|
124
|
+
"infrahub.field.name": match.attribute_name,
|
|
125
|
+
"infrahub.attribute.action": ["added", "updated", "removed"],
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
match match.value_match:
|
|
129
|
+
case ValueMatch.VALUE:
|
|
130
|
+
match_related["infrahub.attribute.value"] = match.value or ""
|
|
131
|
+
case ValueMatch.VALUE_PREVIOUS:
|
|
132
|
+
match_related["infrahub.attribute.value_previous"] = match.value_previous or ""
|
|
133
|
+
case ValueMatch.VALUE_FULL:
|
|
134
|
+
match_related["infrahub.attribute.value"] = match.value or ""
|
|
135
|
+
match_related["infrahub.attribute.value_previous"] = match.value_previous or ""
|
|
136
|
+
|
|
137
|
+
elif isinstance(match, CoreNodeTriggerRelationshipMatch):
|
|
138
|
+
peer_status = "added" if match.added else "removed"
|
|
139
|
+
match_related = {
|
|
140
|
+
"prefect.resource.role": "infrahub.node.relationship_update",
|
|
141
|
+
"infrahub.field.name": match.relationship_name,
|
|
142
|
+
"infrahub.relationship.peer_status": peer_status,
|
|
143
|
+
}
|
|
144
|
+
if isinstance(match.peer, str):
|
|
145
|
+
match_related["infrahub.relationship.peer_id"] = match.peer
|
|
146
|
+
related_matches.append(match_related)
|
|
147
|
+
|
|
148
|
+
event_trigger.match_related = related_matches or {}
|
|
149
|
+
|
|
150
|
+
if isinstance(trigger_rule.action, CoreGeneratorAction):
|
|
151
|
+
workflow = ExecuteWorkflow(
|
|
152
|
+
workflow=ACTION_RUN_GENERATOR,
|
|
153
|
+
parameters={
|
|
154
|
+
"branch_name": "{{ event.resource['infrahub.branch.name'] }}",
|
|
155
|
+
"generator_definition_id": trigger_rule.action.generator_id,
|
|
156
|
+
"node_ids": ["{{ event.resource['infrahub.node.id'] }}"],
|
|
157
|
+
"context": {
|
|
158
|
+
"__prefect_kind": "json",
|
|
159
|
+
"value": {
|
|
160
|
+
"__prefect_kind": "jinja",
|
|
161
|
+
"template": "{{ event.payload['context'] | tojson }}",
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
)
|
|
166
|
+
elif isinstance(trigger_rule.action, CoreGroupAction):
|
|
167
|
+
if trigger_rule.action.add_members:
|
|
168
|
+
flow = ACTION_ADD_NODE_TO_GROUP
|
|
169
|
+
else:
|
|
170
|
+
flow = REMOVE_ADD_NODE_FROM_GROUP
|
|
171
|
+
|
|
172
|
+
workflow = ExecuteWorkflow(
|
|
173
|
+
workflow=flow,
|
|
174
|
+
parameters={
|
|
175
|
+
"branch_name": "{{ event.resource['infrahub.branch.name'] }}",
|
|
176
|
+
"group_id": trigger_rule.action.group_id,
|
|
177
|
+
"node_id": "{{ event.resource['infrahub.node.id'] }}",
|
|
178
|
+
"context": {
|
|
179
|
+
"__prefect_kind": "json",
|
|
180
|
+
"value": {
|
|
181
|
+
"__prefect_kind": "jinja",
|
|
182
|
+
"template": "{{ event.payload['context'] | tojson }}",
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
return cls(
|
|
189
|
+
name=trigger_rule.name,
|
|
190
|
+
trigger=event_trigger,
|
|
191
|
+
actions=[workflow],
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
@classmethod
|
|
195
|
+
def _from_group_trigger(
|
|
196
|
+
cls,
|
|
197
|
+
trigger_rule: CoreGroupTriggerRule,
|
|
198
|
+
) -> Self:
|
|
199
|
+
event_trigger = EventTrigger()
|
|
200
|
+
|
|
201
|
+
if trigger_rule.members_added:
|
|
202
|
+
event_trigger.events.add(GroupMemberAddedEvent.event_name)
|
|
203
|
+
else:
|
|
204
|
+
event_trigger.events.add(GroupMemberRemovedEvent.event_name)
|
|
205
|
+
|
|
206
|
+
event_trigger.match = {"infrahub.node.kind": trigger_rule.group_kind, "infrahub.node.id": trigger_rule.group_id}
|
|
207
|
+
|
|
208
|
+
match trigger_rule.branch_scope:
|
|
209
|
+
case BranchScope.DEFAULT_BRANCH:
|
|
210
|
+
event_trigger.match["infrahub.branch.name"] = registry.default_branch
|
|
211
|
+
case BranchScope.OTHER_BRANCHES:
|
|
212
|
+
event_trigger.match["infrahub.branch.name"] = f"!{registry.default_branch}"
|
|
213
|
+
|
|
214
|
+
if isinstance(trigger_rule.action, CoreGeneratorAction):
|
|
215
|
+
workflow = ExecuteWorkflow(
|
|
216
|
+
workflow=ACTION_RUN_GENERATOR_GROUP_EVENT,
|
|
217
|
+
parameters={
|
|
218
|
+
"branch_name": "{{ event.resource['infrahub.branch.name'] }}",
|
|
219
|
+
"generator_definition_id": trigger_rule.action.generator_id,
|
|
220
|
+
"members": {
|
|
221
|
+
"__prefect_kind": "json",
|
|
222
|
+
"value": {
|
|
223
|
+
"__prefect_kind": "jinja",
|
|
224
|
+
"template": "{{ event.payload['data']['members']| tojson }}",
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
"context": {
|
|
228
|
+
"__prefect_kind": "json",
|
|
229
|
+
"value": {
|
|
230
|
+
"__prefect_kind": "jinja",
|
|
231
|
+
"template": "{{ event.payload['context'] | tojson }}",
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
return cls(
|
|
238
|
+
name=trigger_rule.name,
|
|
239
|
+
trigger=event_trigger,
|
|
240
|
+
actions=[workflow],
|
|
241
|
+
)
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from infrahub.core.constants import InfrahubKind
|
|
4
|
+
|
|
5
|
+
from .constants import BranchScope, ValueMatch
|
|
6
|
+
from .models import (
|
|
7
|
+
CoreAction,
|
|
8
|
+
CoreGeneratorAction,
|
|
9
|
+
CoreGroupAction,
|
|
10
|
+
CoreGroupTriggerRule,
|
|
11
|
+
CoreNodeTriggerAttributeMatch,
|
|
12
|
+
CoreNodeTriggerMatch,
|
|
13
|
+
CoreNodeTriggerRelationshipMatch,
|
|
14
|
+
CoreNodeTriggerRule,
|
|
15
|
+
CoreTriggerRule,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def parse_trigger_rule_response(data: dict[str, Any]) -> list[CoreTriggerRule]:
|
|
20
|
+
rules: list[CoreTriggerRule] = []
|
|
21
|
+
if kind := data.get(InfrahubKind.TRIGGERRULE):
|
|
22
|
+
if edges := kind.get("edges"):
|
|
23
|
+
for edge in edges:
|
|
24
|
+
if rule := _parse_graphql_node(edge["node"]):
|
|
25
|
+
rules.append(rule)
|
|
26
|
+
|
|
27
|
+
return rules
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _parse_graphql_node(data: dict[str, Any]) -> CoreTriggerRule | None:
|
|
31
|
+
typename = data.get("__typename")
|
|
32
|
+
name = data["name"]["value"]
|
|
33
|
+
active = data["active"]["value"]
|
|
34
|
+
branch_scope = BranchScope.from_value(value=data["branch_scope"]["value"])
|
|
35
|
+
action = _parse_graphql_action_response(data=data["action"]["node"])
|
|
36
|
+
match typename:
|
|
37
|
+
case "CoreGroupTriggerRule":
|
|
38
|
+
members_added = data["members_added"]["value"]
|
|
39
|
+
group_id = data["group"]["node"]["id"]
|
|
40
|
+
group_kind = data["group"]["node"]["__typename"]
|
|
41
|
+
return CoreGroupTriggerRule(
|
|
42
|
+
name=name,
|
|
43
|
+
branch_scope=branch_scope,
|
|
44
|
+
action=action,
|
|
45
|
+
members_added=members_added,
|
|
46
|
+
group_id=group_id,
|
|
47
|
+
group_kind=group_kind,
|
|
48
|
+
active=active,
|
|
49
|
+
)
|
|
50
|
+
case "CoreNodeTriggerRule":
|
|
51
|
+
node_kind = data["node_kind"]["value"]
|
|
52
|
+
mutation_action = data["mutation_action"]["value"]
|
|
53
|
+
matches = _parse_node_trigger_matches(data=data["matches"]["edges"])
|
|
54
|
+
return CoreNodeTriggerRule(
|
|
55
|
+
name=name,
|
|
56
|
+
branch_scope=branch_scope,
|
|
57
|
+
action=action,
|
|
58
|
+
node_kind=node_kind,
|
|
59
|
+
mutation_action=mutation_action,
|
|
60
|
+
matches=matches,
|
|
61
|
+
active=active,
|
|
62
|
+
)
|
|
63
|
+
return None
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _parse_graphql_action_response(data: dict[str, Any]) -> CoreAction:
|
|
67
|
+
typename = data["__typename"]
|
|
68
|
+
match typename:
|
|
69
|
+
case "CoreGeneratorAction":
|
|
70
|
+
generator_id = data["generator"]["node"]["id"]
|
|
71
|
+
return CoreGeneratorAction(generator_id=generator_id)
|
|
72
|
+
case "CoreGroupAction":
|
|
73
|
+
add_members = data["add_members"]["value"]
|
|
74
|
+
group_id = data["group"]["node"]["id"]
|
|
75
|
+
return CoreGroupAction(add_members=add_members, group_id=group_id)
|
|
76
|
+
|
|
77
|
+
raise NotImplementedError(f"{typename} is not a valid CoreAction")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _parse_node_trigger_matches(data: list[dict[str, Any]]) -> list[CoreNodeTriggerMatch]:
|
|
81
|
+
matches: list[CoreNodeTriggerMatch] = []
|
|
82
|
+
for entry in data:
|
|
83
|
+
node = entry["node"]
|
|
84
|
+
typename = node["__typename"]
|
|
85
|
+
match typename:
|
|
86
|
+
case "CoreNodeTriggerAttributeMatch":
|
|
87
|
+
matches.append(
|
|
88
|
+
CoreNodeTriggerAttributeMatch(
|
|
89
|
+
attribute_name=node["attribute_name"]["value"],
|
|
90
|
+
value=node["value"]["value"],
|
|
91
|
+
value_previous=node["value_previous"]["value"],
|
|
92
|
+
value_match=ValueMatch.from_value(value=node["value_match"]["value"]),
|
|
93
|
+
)
|
|
94
|
+
)
|
|
95
|
+
case "CoreNodeTriggerRelationshipMatch":
|
|
96
|
+
matches.append(
|
|
97
|
+
CoreNodeTriggerRelationshipMatch(
|
|
98
|
+
relationship_name=node["relationship_name"]["value"],
|
|
99
|
+
added=node["added"]["value"],
|
|
100
|
+
peer=node["peer"]["value"],
|
|
101
|
+
)
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
return matches
|