infrahub-server 1.6.2__py3-none-any.whl → 1.7.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/actions/tasks.py +4 -2
- infrahub/api/exceptions.py +2 -2
- infrahub/api/schema.py +3 -1
- infrahub/artifacts/tasks.py +1 -0
- infrahub/auth.py +2 -2
- infrahub/cli/db.py +54 -28
- infrahub/computed_attribute/gather.py +3 -4
- infrahub/computed_attribute/tasks.py +23 -6
- infrahub/config.py +8 -0
- infrahub/constants/enums.py +12 -0
- infrahub/core/account.py +12 -9
- infrahub/core/attribute.py +106 -108
- infrahub/core/branch/models.py +44 -71
- infrahub/core/branch/tasks.py +5 -3
- infrahub/core/changelog/diff.py +1 -20
- infrahub/core/changelog/models.py +0 -7
- infrahub/core/constants/__init__.py +17 -0
- infrahub/core/constants/database.py +0 -1
- infrahub/core/constants/schema.py +0 -1
- infrahub/core/convert_object_type/repository_conversion.py +3 -4
- infrahub/core/diff/branch_differ.py +1 -1
- infrahub/core/diff/conflict_transferer.py +1 -1
- infrahub/core/diff/data_check_synchronizer.py +4 -3
- infrahub/core/diff/enricher/cardinality_one.py +2 -2
- infrahub/core/diff/enricher/hierarchy.py +1 -1
- infrahub/core/diff/enricher/labels.py +1 -1
- infrahub/core/diff/merger/merger.py +28 -2
- infrahub/core/diff/merger/serializer.py +3 -10
- infrahub/core/diff/model/diff.py +1 -1
- infrahub/core/diff/query/merge.py +376 -135
- infrahub/core/diff/repository/repository.py +3 -1
- infrahub/core/graph/__init__.py +1 -1
- infrahub/core/graph/constraints.py +3 -3
- infrahub/core/graph/schema.py +2 -12
- infrahub/core/ipam/reconciler.py +8 -6
- infrahub/core/ipam/utilization.py +8 -15
- infrahub/core/manager.py +133 -152
- infrahub/core/merge.py +1 -1
- infrahub/core/metadata/__init__.py +0 -0
- infrahub/core/metadata/interface.py +37 -0
- infrahub/core/metadata/model.py +31 -0
- infrahub/core/metadata/query/__init__.py +0 -0
- infrahub/core/metadata/query/node_metadata.py +301 -0
- infrahub/core/migrations/graph/__init__.py +4 -0
- infrahub/core/migrations/graph/m012_convert_account_generic.py +12 -12
- infrahub/core/migrations/graph/m013_convert_git_password_credential.py +7 -12
- infrahub/core/migrations/graph/m017_add_core_profile.py +5 -2
- infrahub/core/migrations/graph/m018_uniqueness_nulls.py +2 -1
- infrahub/core/migrations/graph/m019_restore_rels_to_time.py +0 -10
- infrahub/core/migrations/graph/m020_duplicate_edges.py +0 -8
- infrahub/core/migrations/graph/m025_uniqueness_nulls.py +2 -1
- infrahub/core/migrations/graph/m026_0000_prefix_fix.py +2 -1
- infrahub/core/migrations/graph/m029_duplicates_cleanup.py +0 -1
- infrahub/core/migrations/graph/m031_check_number_attributes.py +2 -2
- infrahub/core/migrations/graph/m038_redo_0000_prefix_fix.py +2 -1
- infrahub/core/migrations/graph/m041_deleted_dup_edges.py +1 -1
- infrahub/core/migrations/graph/m049_remove_is_visible_relationship.py +53 -0
- infrahub/core/migrations/graph/m050_backfill_vertex_metadata.py +168 -0
- infrahub/core/migrations/query/__init__.py +2 -2
- infrahub/core/migrations/query/attribute_add.py +17 -6
- infrahub/core/migrations/query/attribute_remove.py +19 -5
- infrahub/core/migrations/query/attribute_rename.py +21 -5
- infrahub/core/migrations/query/node_duplicate.py +19 -4
- infrahub/core/migrations/query/schema_attribute_update.py +1 -1
- infrahub/core/migrations/schema/attribute_kind_update.py +26 -6
- infrahub/core/migrations/schema/attribute_name_update.py +1 -1
- infrahub/core/migrations/schema/attribute_supports_profile.py +5 -3
- infrahub/core/migrations/schema/models.py +3 -0
- infrahub/core/migrations/schema/node_attribute_add.py +5 -2
- infrahub/core/migrations/schema/node_attribute_remove.py +1 -1
- infrahub/core/migrations/schema/node_kind_update.py +1 -1
- infrahub/core/migrations/schema/node_remove.py +24 -2
- infrahub/core/migrations/schema/tasks.py +4 -1
- infrahub/core/migrations/shared.py +13 -6
- infrahub/core/models.py +6 -6
- infrahub/core/node/__init__.py +157 -58
- infrahub/core/node/base.py +9 -5
- infrahub/core/node/create.py +7 -3
- infrahub/core/node/delete_validator.py +1 -1
- infrahub/core/node/standard.py +100 -14
- infrahub/core/order.py +30 -0
- infrahub/core/property.py +0 -1
- infrahub/core/protocols.py +1 -0
- infrahub/core/protocols_base.py +10 -2
- infrahub/core/query/__init__.py +11 -6
- infrahub/core/query/attribute.py +164 -49
- infrahub/core/query/branch.py +58 -70
- infrahub/core/query/delete.py +1 -1
- infrahub/core/query/diff.py +7 -7
- infrahub/core/query/ipam.py +104 -43
- infrahub/core/query/node.py +1072 -281
- infrahub/core/query/relationship.py +531 -325
- infrahub/core/query/resource_manager.py +107 -18
- infrahub/core/query/standard_node.py +25 -5
- infrahub/core/query/utils.py +2 -4
- infrahub/core/relationship/constraints/count.py +1 -1
- infrahub/core/relationship/constraints/peer_kind.py +1 -1
- infrahub/core/relationship/constraints/peer_parent.py +1 -1
- infrahub/core/relationship/constraints/peer_relatives.py +1 -1
- infrahub/core/relationship/constraints/profiles_kind.py +1 -1
- infrahub/core/relationship/constraints/profiles_removal.py +168 -0
- infrahub/core/relationship/model.py +293 -139
- infrahub/core/schema/attribute_parameters.py +28 -1
- infrahub/core/schema/attribute_schema.py +11 -17
- infrahub/core/schema/basenode_schema.py +3 -0
- infrahub/core/schema/definitions/core/__init__.py +8 -2
- infrahub/core/schema/definitions/core/account.py +10 -10
- infrahub/core/schema/definitions/core/artifact.py +14 -8
- infrahub/core/schema/definitions/core/check.py +10 -4
- infrahub/core/schema/definitions/core/generator.py +26 -6
- infrahub/core/schema/definitions/core/graphql_query.py +1 -1
- infrahub/core/schema/definitions/core/group.py +9 -2
- infrahub/core/schema/definitions/core/ipam.py +80 -10
- infrahub/core/schema/definitions/core/menu.py +41 -7
- infrahub/core/schema/definitions/core/permission.py +16 -2
- infrahub/core/schema/definitions/core/profile.py +16 -2
- infrahub/core/schema/definitions/core/propose_change.py +24 -4
- infrahub/core/schema/definitions/core/propose_change_comment.py +23 -11
- infrahub/core/schema/definitions/core/propose_change_validator.py +50 -21
- infrahub/core/schema/definitions/core/repository.py +10 -0
- infrahub/core/schema/definitions/core/resource_pool.py +8 -1
- infrahub/core/schema/definitions/core/template.py +19 -2
- infrahub/core/schema/definitions/core/transform.py +11 -5
- infrahub/core/schema/definitions/core/webhook.py +27 -9
- infrahub/core/schema/manager.py +63 -43
- infrahub/core/schema/relationship_schema.py +6 -2
- infrahub/core/schema/schema_branch.py +115 -11
- infrahub/core/task/task.py +4 -2
- infrahub/core/utils.py +3 -25
- infrahub/core/validators/aggregated_checker.py +1 -1
- infrahub/core/validators/attribute/choices.py +1 -1
- infrahub/core/validators/attribute/enum.py +1 -1
- infrahub/core/validators/attribute/kind.py +6 -3
- infrahub/core/validators/attribute/length.py +1 -1
- infrahub/core/validators/attribute/min_max.py +1 -1
- infrahub/core/validators/attribute/number_pool.py +1 -1
- infrahub/core/validators/attribute/optional.py +1 -1
- infrahub/core/validators/attribute/regex.py +1 -1
- infrahub/core/validators/determiner.py +3 -3
- infrahub/core/validators/node/attribute.py +1 -1
- infrahub/core/validators/node/relationship.py +1 -1
- infrahub/core/validators/relationship/peer.py +1 -1
- infrahub/database/__init__.py +4 -4
- infrahub/dependencies/builder/constraint/grouped/node_runner.py +2 -0
- infrahub/dependencies/builder/constraint/relationship_manager/profiles_removal.py +8 -0
- infrahub/dependencies/registry.py +2 -0
- infrahub/display_labels/tasks.py +12 -3
- infrahub/git/integrator.py +18 -18
- infrahub/git/tasks.py +1 -1
- infrahub/git/utils.py +1 -1
- infrahub/graphql/app.py +2 -2
- infrahub/graphql/constants.py +3 -0
- infrahub/graphql/context.py +1 -1
- infrahub/graphql/field_extractor.py +1 -1
- infrahub/graphql/initialization.py +11 -0
- infrahub/graphql/loaders/account.py +134 -0
- infrahub/graphql/loaders/node.py +5 -12
- infrahub/graphql/loaders/peers.py +5 -7
- infrahub/graphql/manager.py +175 -21
- infrahub/graphql/metadata.py +91 -0
- infrahub/graphql/mutations/account.py +6 -6
- infrahub/graphql/mutations/attribute.py +0 -2
- infrahub/graphql/mutations/branch.py +9 -5
- infrahub/graphql/mutations/computed_attribute.py +1 -1
- infrahub/graphql/mutations/display_label.py +1 -1
- infrahub/graphql/mutations/hfid.py +1 -1
- infrahub/graphql/mutations/ipam.py +4 -6
- infrahub/graphql/mutations/main.py +9 -4
- infrahub/graphql/mutations/profile.py +16 -22
- infrahub/graphql/mutations/proposed_change.py +4 -4
- infrahub/graphql/mutations/relationship.py +40 -10
- infrahub/graphql/mutations/repository.py +14 -12
- infrahub/graphql/mutations/schema.py +2 -2
- infrahub/graphql/order.py +14 -0
- infrahub/graphql/queries/branch.py +62 -6
- infrahub/graphql/queries/diff/tree.py +5 -5
- infrahub/graphql/queries/resource_manager.py +25 -24
- infrahub/graphql/resolvers/account_metadata.py +84 -0
- infrahub/graphql/resolvers/ipam.py +6 -8
- infrahub/graphql/resolvers/many_relationship.py +77 -35
- infrahub/graphql/resolvers/resolver.py +59 -14
- infrahub/graphql/resolvers/single_relationship.py +87 -23
- infrahub/graphql/subscription/graphql_query.py +2 -0
- infrahub/graphql/types/__init__.py +0 -1
- infrahub/graphql/types/attribute.py +10 -5
- infrahub/graphql/types/branch.py +40 -53
- infrahub/graphql/types/enums.py +3 -0
- infrahub/graphql/types/metadata.py +28 -0
- infrahub/graphql/types/node.py +22 -2
- infrahub/graphql/types/relationship.py +10 -2
- infrahub/graphql/types/standard_node.py +12 -7
- infrahub/hfid/tasks.py +12 -3
- infrahub/lock.py +7 -0
- infrahub/menu/repository.py +1 -1
- infrahub/patch/queries/base.py +1 -1
- infrahub/pools/number.py +1 -8
- infrahub/profiles/gather.py +56 -0
- infrahub/profiles/mandatory_fields_checker.py +116 -0
- infrahub/profiles/models.py +66 -0
- infrahub/profiles/node_applier.py +154 -13
- infrahub/profiles/queries/get_profile_data.py +143 -31
- infrahub/profiles/tasks.py +79 -27
- infrahub/profiles/triggers.py +22 -0
- infrahub/proposed_change/action_checker.py +1 -1
- infrahub/proposed_change/tasks.py +4 -1
- infrahub/services/__init__.py +1 -1
- infrahub/services/adapters/cache/nats.py +1 -1
- infrahub/services/adapters/cache/redis.py +7 -0
- infrahub/tasks/artifact.py +1 -0
- infrahub/transformations/tasks.py +2 -2
- infrahub/trigger/catalogue.py +2 -0
- infrahub/trigger/models.py +1 -0
- infrahub/trigger/setup.py +3 -3
- infrahub/trigger/tasks.py +3 -0
- infrahub/validators/tasks.py +1 -0
- infrahub/webhook/gather.py +1 -1
- infrahub/webhook/models.py +1 -1
- infrahub/webhook/tasks.py +23 -7
- infrahub/workers/dependencies.py +9 -3
- infrahub/workers/infrahub_async.py +13 -4
- infrahub/workflows/catalogue.py +19 -0
- infrahub_sdk/analyzer.py +2 -2
- infrahub_sdk/branch.py +12 -39
- infrahub_sdk/checks.py +4 -4
- infrahub_sdk/client.py +36 -0
- infrahub_sdk/ctl/cli_commands.py +2 -1
- infrahub_sdk/ctl/graphql.py +15 -4
- infrahub_sdk/ctl/utils.py +2 -2
- infrahub_sdk/enums.py +6 -0
- infrahub_sdk/graphql/renderers.py +21 -0
- infrahub_sdk/graphql/utils.py +85 -0
- infrahub_sdk/node/attribute.py +12 -2
- infrahub_sdk/node/constants.py +12 -0
- infrahub_sdk/node/metadata.py +69 -0
- infrahub_sdk/node/node.py +65 -14
- infrahub_sdk/node/property.py +3 -0
- infrahub_sdk/node/related_node.py +37 -5
- infrahub_sdk/node/relationship.py +18 -1
- infrahub_sdk/operation.py +2 -2
- infrahub_sdk/schema/repository.py +1 -2
- infrahub_sdk/transforms.py +2 -2
- infrahub_sdk/types.py +18 -2
- {infrahub_server-1.6.2.dist-info → infrahub_server-1.7.0.dist-info}/METADATA +17 -16
- {infrahub_server-1.6.2.dist-info → infrahub_server-1.7.0.dist-info}/RECORD +252 -231
- infrahub_testcontainers/container.py +3 -3
- infrahub_testcontainers/docker-compose-cluster.test.yml +7 -7
- infrahub_testcontainers/docker-compose.test.yml +13 -5
- infrahub_testcontainers/models.py +3 -3
- infrahub_testcontainers/performance_test.py +1 -1
- infrahub/graphql/models.py +0 -6
- {infrahub_server-1.6.2.dist-info → infrahub_server-1.7.0.dist-info}/WHEEL +0 -0
- {infrahub_server-1.6.2.dist-info → infrahub_server-1.7.0.dist-info}/entry_points.txt +0 -0
- {infrahub_server-1.6.2.dist-info → infrahub_server-1.7.0.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -1,33 +1,67 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
from typing import Any
|
|
3
3
|
|
|
4
|
-
from infrahub.core.constants import NULL_VALUE
|
|
4
|
+
from infrahub.core.constants import NULL_VALUE, RelationshipDirection
|
|
5
5
|
from infrahub.core.query import Query, QueryType
|
|
6
6
|
from infrahub.database import InfrahubDatabase
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
@dataclass
|
|
10
|
+
class RelationshipFilter:
|
|
11
|
+
relationship_identifier: str
|
|
12
|
+
direction: RelationshipDirection
|
|
13
|
+
|
|
14
|
+
def __hash__(self) -> int:
|
|
15
|
+
return hash((self.relationship_identifier, self.direction))
|
|
16
|
+
|
|
17
|
+
|
|
9
18
|
@dataclass
|
|
10
19
|
class ProfileData:
|
|
11
20
|
uuid: str
|
|
12
21
|
priority: float | int
|
|
13
22
|
attribute_values: dict[str, Any]
|
|
23
|
+
relationship_peers: dict[RelationshipFilter, list[str]]
|
|
14
24
|
|
|
15
25
|
|
|
16
26
|
class GetProfileDataQuery(Query):
|
|
17
27
|
type: QueryType = QueryType.READ
|
|
18
28
|
insert_return: bool = False
|
|
19
29
|
|
|
20
|
-
def __init__(
|
|
30
|
+
def __init__(
|
|
31
|
+
self,
|
|
32
|
+
*args: Any,
|
|
33
|
+
profile_ids: list[str],
|
|
34
|
+
attr_names: list[str],
|
|
35
|
+
relationship_filters: list[RelationshipFilter] | None = None,
|
|
36
|
+
**kwargs: Any,
|
|
37
|
+
) -> None:
|
|
21
38
|
super().__init__(*args, **kwargs)
|
|
22
39
|
self.profile_ids = profile_ids
|
|
23
40
|
self.attr_names = attr_names
|
|
41
|
+
self.relationship_filters = relationship_filters or []
|
|
24
42
|
|
|
25
43
|
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
|
|
26
|
-
branch_filter, branch_params = self.branch.get_query_filter_path(at=self.at
|
|
44
|
+
branch_filter, branch_params = self.branch.get_query_filter_path(at=self.at)
|
|
27
45
|
self.params.update(branch_params)
|
|
28
46
|
self.params["profile_ids"] = self.profile_ids
|
|
29
47
|
self.params["attr_names"] = self.attr_names + ["profile_priority"]
|
|
30
48
|
|
|
49
|
+
# Prepare relationship filters
|
|
50
|
+
outbound_identifiers = []
|
|
51
|
+
inbound_identifiers = []
|
|
52
|
+
bidirectional_identifiers = []
|
|
53
|
+
for rf in self.relationship_filters:
|
|
54
|
+
if rf.direction == RelationshipDirection.OUTBOUND:
|
|
55
|
+
outbound_identifiers.append(rf.relationship_identifier)
|
|
56
|
+
elif rf.direction == RelationshipDirection.INBOUND:
|
|
57
|
+
inbound_identifiers.append(rf.relationship_identifier)
|
|
58
|
+
elif rf.direction == RelationshipDirection.BIDIR:
|
|
59
|
+
bidirectional_identifiers.append(rf.relationship_identifier)
|
|
60
|
+
|
|
61
|
+
self.params["outbound_identifiers"] = outbound_identifiers
|
|
62
|
+
self.params["inbound_identifiers"] = inbound_identifiers
|
|
63
|
+
self.params["bidirectional_identifiers"] = bidirectional_identifiers
|
|
64
|
+
|
|
31
65
|
query = """
|
|
32
66
|
// --------------
|
|
33
67
|
// get the Profile nodes
|
|
@@ -48,51 +82,129 @@ WHERE is_active = TRUE
|
|
|
48
82
|
// --------------
|
|
49
83
|
// get the attributes that we care about
|
|
50
84
|
// --------------
|
|
51
|
-
MATCH (profile)-[:HAS_ATTRIBUTE]-(attr:Attribute)
|
|
85
|
+
OPTIONAL MATCH (profile)-[:HAS_ATTRIBUTE]-(attr:Attribute)
|
|
52
86
|
WHERE attr.name IN $attr_names
|
|
53
87
|
WITH DISTINCT profile, attr
|
|
54
88
|
CALL (profile, attr) {
|
|
55
|
-
MATCH (profile)-[r:HAS_ATTRIBUTE]->(attr)
|
|
89
|
+
OPTIONAL MATCH (profile)-[r:HAS_ATTRIBUTE]->(attr)
|
|
56
90
|
WHERE %(branch_filter)s
|
|
57
91
|
ORDER BY r.branch_level DESC, r.from DESC, r.status ASC
|
|
58
|
-
RETURN r.status = "active" AS
|
|
92
|
+
RETURN r.status = "active" AS r1_is_active
|
|
59
93
|
}
|
|
60
|
-
WITH profile, attr
|
|
61
|
-
WHERE is_active = TRUE
|
|
62
94
|
// --------------
|
|
63
95
|
// get the attribute values
|
|
64
96
|
// --------------
|
|
65
97
|
CALL (attr) {
|
|
66
|
-
MATCH (attr)-[r:HAS_VALUE]->(av)
|
|
98
|
+
OPTIONAL MATCH (attr)-[r:HAS_VALUE]->(av)
|
|
67
99
|
WHERE %(branch_filter)s
|
|
68
100
|
ORDER BY r.branch_level DESC, r.from DESC, r.status ASC
|
|
69
|
-
RETURN av, r.status = "active" AS
|
|
101
|
+
RETURN av, r.status = "active" AS r2_is_active
|
|
70
102
|
LIMIT 1
|
|
71
103
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
104
|
+
// --------------
|
|
105
|
+
// filter out null and inactive attributes
|
|
106
|
+
// --------------
|
|
107
|
+
WITH profile, CASE
|
|
108
|
+
WHEN attr IS NOT NULL AND av IS NOT NULL AND r1_is_active = TRUE AND r2_is_active = TRUE THEN [attr.name, av.value]
|
|
109
|
+
ELSE NULL
|
|
110
|
+
END AS attribute_details
|
|
111
|
+
WITH profile, collect(attribute_details) AS attributes
|
|
112
|
+
// --------------
|
|
113
|
+
// get all possible relationships we might want for this profile
|
|
114
|
+
// --------------
|
|
115
|
+
OPTIONAL MATCH (profile)-[r:IS_RELATED]-(rel:Relationship)
|
|
116
|
+
WHERE rel.name IN $outbound_identifiers + $bidirectional_identifiers + $inbound_identifiers
|
|
117
|
+
AND %(branch_filter)s
|
|
118
|
+
WITH DISTINCT profile, attributes, rel
|
|
119
|
+
// --------------
|
|
120
|
+
// filter to active near-side relationships with names and directions we want
|
|
121
|
+
// --------------
|
|
122
|
+
CALL (profile, rel) {
|
|
123
|
+
OPTIONAL MATCH (profile)-[r:IS_RELATED]-(rel)
|
|
124
|
+
WHERE (
|
|
125
|
+
(rel.name IN $outbound_identifiers AND startNode(r) = profile)
|
|
126
|
+
OR (rel.name IN $bidirectional_identifiers AND startNode(r) = profile)
|
|
127
|
+
OR (rel.name IN $inbound_identifiers AND startNode(r) = rel)
|
|
128
|
+
)
|
|
129
|
+
AND %(branch_filter)s
|
|
130
|
+
RETURN r AS r1
|
|
131
|
+
ORDER BY r1.branch_level DESC, r1.from DESC, r1.status ASC
|
|
132
|
+
LIMIT 1
|
|
133
|
+
}
|
|
134
|
+
WITH profile, attributes, r1, rel
|
|
135
|
+
// --------------
|
|
136
|
+
// filter to active far-side relationships with names and directions we want
|
|
137
|
+
// --------------
|
|
138
|
+
CALL (profile, rel) {
|
|
139
|
+
OPTIONAL MATCH (rel)-[r:IS_RELATED]-(peer)
|
|
140
|
+
WHERE peer <> profile
|
|
141
|
+
AND (
|
|
142
|
+
(rel.name IN $outbound_identifiers AND startNode(r) = rel)
|
|
143
|
+
OR (rel.name IN $bidirectional_identifiers AND startNode(r) = peer)
|
|
144
|
+
OR (rel.name IN $inbound_identifiers AND startNode(r) = peer)
|
|
145
|
+
)
|
|
146
|
+
AND %(branch_filter)s
|
|
147
|
+
RETURN r AS r2, peer
|
|
148
|
+
ORDER BY r2.branch_level DESC, r2.from DESC, r2.status ASC
|
|
149
|
+
LIMIT 1
|
|
150
|
+
}
|
|
151
|
+
WITH profile, attributes, r1, rel, r2, peer
|
|
152
|
+
// --------------
|
|
153
|
+
// save the direction of the relationship
|
|
154
|
+
// --------------
|
|
155
|
+
WITH *, CASE
|
|
156
|
+
WHEN r1 IS NULL OR r2 IS NULL THEN NULL
|
|
157
|
+
WHEN startNode(r1) = profile AND startNode(r2) = rel THEN "outbound"
|
|
158
|
+
WHEN startNode(r1) = rel AND startNode(r2) = peer THEN "inbound"
|
|
159
|
+
ELSE "bidirectional"
|
|
160
|
+
END AS direction
|
|
161
|
+
// --------------
|
|
162
|
+
// filter out null and inactive relationships
|
|
163
|
+
// --------------
|
|
164
|
+
WITH profile, attributes, CASE
|
|
165
|
+
WHEN rel IS NOT NULL AND peer IS NOT NULL AND r1.status = "active" AND r2.status = "active" THEN [rel.name, direction, peer.uuid]
|
|
166
|
+
ELSE NULL
|
|
167
|
+
END AS relationship_details
|
|
168
|
+
WITH profile, attributes, collect(relationship_details) AS relationships
|
|
169
|
+
RETURN profile.uuid AS profile_uuid, attributes, relationships
|
|
75
170
|
""" % {"branch_filter": branch_filter}
|
|
76
171
|
self.add_to_query(query)
|
|
77
|
-
self.return_labels = ["profile_uuid", "
|
|
172
|
+
self.return_labels = ["profile_uuid", "attributes", "relationships"]
|
|
78
173
|
|
|
79
174
|
def get_profile_data(self) -> list[ProfileData]:
|
|
80
|
-
|
|
175
|
+
profile_data_list: list[ProfileData] = []
|
|
81
176
|
for result in self.results:
|
|
82
177
|
profile_uuid = result.get_as_type(label="profile_uuid", return_type=str)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
178
|
+
attributes = result.get(label="attributes")
|
|
179
|
+
relationships = result.get(label="relationships")
|
|
180
|
+
|
|
181
|
+
profile_data = ProfileData(
|
|
182
|
+
uuid=profile_uuid, priority=float("inf"), attribute_values={}, relationship_peers={}
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
for attr_pair in attributes:
|
|
186
|
+
if not isinstance(attr_pair, list) or len(attr_pair) != 2:
|
|
187
|
+
continue
|
|
188
|
+
attr_name, attr_value = attr_pair
|
|
189
|
+
if attr_value == NULL_VALUE:
|
|
190
|
+
attr_value = None
|
|
191
|
+
if attr_name == "profile_priority":
|
|
192
|
+
if attr_value is not None and not isinstance(attr_value, int):
|
|
193
|
+
attr_value = int(attr_value)
|
|
194
|
+
profile_data.priority = attr_value
|
|
195
|
+
else:
|
|
196
|
+
profile_data.attribute_values[attr_name] = attr_value
|
|
197
|
+
|
|
198
|
+
# Parse relationships
|
|
199
|
+
for rel_tuple in relationships:
|
|
200
|
+
if not isinstance(rel_tuple, list) or len(rel_tuple) != 3:
|
|
201
|
+
continue
|
|
202
|
+
rel_name, direction_str, peer_uuid = rel_tuple
|
|
203
|
+
direction = RelationshipDirection(direction_str)
|
|
204
|
+
rel_filter = RelationshipFilter(relationship_identifier=rel_name, direction=direction)
|
|
205
|
+
if rel_filter not in profile_data.relationship_peers:
|
|
206
|
+
profile_data.relationship_peers[rel_filter] = []
|
|
207
|
+
profile_data.relationship_peers[rel_filter].append(peer_uuid)
|
|
208
|
+
|
|
209
|
+
profile_data_list.append(profile_data)
|
|
210
|
+
return profile_data_list
|
infrahub/profiles/tasks.py
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
3
5
|
from prefect import flow
|
|
4
6
|
from prefect.logging import get_run_logger
|
|
5
7
|
|
|
6
|
-
from infrahub.
|
|
8
|
+
from infrahub.context import InfrahubContext # noqa: TC001 needed for prefect flow
|
|
9
|
+
from infrahub.trigger.models import TriggerSetupReport, TriggerType
|
|
10
|
+
from infrahub.trigger.setup import setup_triggers_specific
|
|
11
|
+
from infrahub.workers.dependencies import get_client, get_component, get_database, get_workflow
|
|
7
12
|
from infrahub.workflows.catalogue import PROFILE_REFRESH
|
|
8
|
-
from infrahub.workflows.utils import add_tags
|
|
13
|
+
from infrahub.workflows.utils import add_tags, wait_for_schema_to_converge
|
|
14
|
+
|
|
15
|
+
from .gather import gather_trigger_profile_refresh
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from infrahub_sdk.node.relationship import RelationshipManager
|
|
9
19
|
|
|
10
20
|
REFRESH_PROFILES_MUTATION = """
|
|
11
21
|
mutation RefreshProfiles(
|
|
@@ -20,44 +30,86 @@ mutation RefreshProfiles(
|
|
|
20
30
|
"""
|
|
21
31
|
|
|
22
32
|
|
|
23
|
-
@flow(
|
|
24
|
-
|
|
25
|
-
flow_run_name="Refresh profiles for {node_id}",
|
|
26
|
-
)
|
|
27
|
-
async def object_profiles_refresh(
|
|
28
|
-
branch_name: str,
|
|
29
|
-
node_id: str,
|
|
30
|
-
) -> None:
|
|
33
|
+
@flow(name="object-profiles-refresh", flow_run_name="Refresh profiles for {node_id}")
|
|
34
|
+
async def object_profiles_refresh(branch_name: str, node_id: str) -> None:
|
|
31
35
|
log = get_run_logger()
|
|
32
36
|
client = get_client()
|
|
33
37
|
|
|
34
38
|
await add_tags(branches=[branch_name], nodes=[node_id], db_change=True)
|
|
35
|
-
await client.execute_graphql(
|
|
36
|
-
query=REFRESH_PROFILES_MUTATION,
|
|
37
|
-
variables={"id": node_id},
|
|
38
|
-
branch_name=branch_name,
|
|
39
|
-
)
|
|
39
|
+
await client.execute_graphql(query=REFRESH_PROFILES_MUTATION, variables={"id": node_id}, branch_name=branch_name)
|
|
40
40
|
log.info(f"Profiles refreshed for {node_id}")
|
|
41
41
|
|
|
42
42
|
|
|
43
|
-
@flow(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
@flow(name="objects-profiles-refresh-multiple", flow_run_name="Refresh profiles for multiple objects")
|
|
44
|
+
async def objects_profiles_refresh_multiple(branch_name: str, node_ids: list[str]) -> None:
|
|
45
|
+
log = get_run_logger()
|
|
46
|
+
|
|
47
|
+
await add_tags(branches=[branch_name])
|
|
48
|
+
|
|
49
|
+
for node_id in node_ids:
|
|
50
|
+
log.info(f"Requesting profile refresh for {node_id}")
|
|
51
|
+
await get_workflow().submit_workflow(
|
|
52
|
+
workflow=PROFILE_REFRESH, parameters={"branch_name": branch_name, "node_id": node_id}
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@flow(name="profile-refresh-setup", flow_run_name="Setup profile refresh triggers")
|
|
57
|
+
async def profile_refresh_setup(
|
|
58
|
+
context: InfrahubContext, # noqa: ARG001
|
|
59
|
+
branch_name: str | None = None,
|
|
60
|
+
event_name: str | None = None, # noqa: ARG001
|
|
61
|
+
) -> None:
|
|
62
|
+
"""Setup Prefect automations for profile refresh triggers.
|
|
63
|
+
|
|
64
|
+
This flow is triggered by schema changes and sets up automations that will
|
|
65
|
+
listen for profile updates. When a profile's attributes or relationships
|
|
66
|
+
change, the corresponding automation will trigger profile refresh for all
|
|
67
|
+
related nodes.
|
|
68
|
+
"""
|
|
69
|
+
database = await get_database()
|
|
70
|
+
async with database.start_session() as db:
|
|
71
|
+
log = get_run_logger()
|
|
72
|
+
|
|
73
|
+
if branch_name:
|
|
74
|
+
await add_tags(branches=[branch_name])
|
|
75
|
+
component = await get_component()
|
|
76
|
+
await wait_for_schema_to_converge(branch_name=branch_name, component=component, db=db, log=log)
|
|
77
|
+
|
|
78
|
+
report: TriggerSetupReport = await setup_triggers_specific(
|
|
79
|
+
gatherer=gather_trigger_profile_refresh, trigger_type=TriggerType.PROFILE
|
|
80
|
+
) # type: ignore[misc]
|
|
81
|
+
|
|
82
|
+
log.info(f"{report.in_use_count} Profile refresh automation configuration completed")
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@flow(name="profile-refresh-process", flow_run_name="Process profile refresh for {profile_kind}")
|
|
86
|
+
async def profile_refresh_process(
|
|
48
87
|
branch_name: str,
|
|
49
|
-
|
|
88
|
+
profile_kind: str,
|
|
89
|
+
profile_id: str,
|
|
90
|
+
context: InfrahubContext, # noqa: ARG001
|
|
50
91
|
) -> None:
|
|
92
|
+
"""Process profile refresh when a profile's attributes or relationships change.
|
|
93
|
+
|
|
94
|
+
This flow fetches all nodes related to the profile via the `related_nodes`
|
|
95
|
+
relationship and submits profile refresh workflows for each of them.
|
|
96
|
+
"""
|
|
51
97
|
log = get_run_logger()
|
|
98
|
+
client = get_client()
|
|
52
99
|
|
|
53
100
|
await add_tags(branches=[branch_name])
|
|
54
101
|
|
|
55
|
-
|
|
102
|
+
profile = await client.get(kind=profile_kind, id=profile_id, branch=branch_name, include=["related_nodes"])
|
|
103
|
+
related_nodes: RelationshipManager = profile.related_nodes # type: ignore
|
|
104
|
+
|
|
105
|
+
if not related_nodes.peer_ids:
|
|
106
|
+
log.info(f"No related nodes found for profile {profile_id}")
|
|
107
|
+
return
|
|
108
|
+
|
|
109
|
+
log.info(f"Found {len(related_nodes.peer_ids)} related nodes for profile {profile_id}")
|
|
110
|
+
|
|
111
|
+
for node_id in related_nodes.peer_ids:
|
|
56
112
|
log.info(f"Requesting profile refresh for {node_id}")
|
|
57
113
|
await get_workflow().submit_workflow(
|
|
58
|
-
workflow=PROFILE_REFRESH,
|
|
59
|
-
parameters={
|
|
60
|
-
"branch_name": branch_name,
|
|
61
|
-
"node_id": node_id,
|
|
62
|
-
},
|
|
114
|
+
workflow=PROFILE_REFRESH, parameters={"branch_name": branch_name, "node_id": node_id}
|
|
63
115
|
)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from infrahub.events.branch_action import BranchDeletedEvent
|
|
2
|
+
from infrahub.events.schema_action import SchemaUpdatedEvent
|
|
3
|
+
from infrahub.trigger.models import BuiltinTriggerDefinition, EventTrigger, ExecuteWorkflow
|
|
4
|
+
from infrahub.workflows.catalogue import PROFILE_REFRESH_SETUP
|
|
5
|
+
|
|
6
|
+
TRIGGER_PROFILE_REFRESH_SETUP = BuiltinTriggerDefinition(
|
|
7
|
+
name="profile-refresh-setup-all",
|
|
8
|
+
trigger=EventTrigger(events={SchemaUpdatedEvent.event_name, BranchDeletedEvent.event_name}),
|
|
9
|
+
actions=[
|
|
10
|
+
ExecuteWorkflow(
|
|
11
|
+
workflow=PROFILE_REFRESH_SETUP,
|
|
12
|
+
parameters={
|
|
13
|
+
"branch_name": "{{ event.resource['infrahub.branch.name'] }}",
|
|
14
|
+
"event_name": "{{ event.event }}",
|
|
15
|
+
"context": {
|
|
16
|
+
"__prefect_kind": "json",
|
|
17
|
+
"value": {"__prefect_kind": "jinja", "template": "{{ event.payload['context'] | tojson }}"},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
),
|
|
21
|
+
],
|
|
22
|
+
)
|
|
@@ -622,6 +622,7 @@ async def validate_artifacts_generation(model: RequestArtifactDefinitionCheck, c
|
|
|
622
622
|
|
|
623
623
|
log = get_run_logger()
|
|
624
624
|
client = get_client()
|
|
625
|
+
client.request_context = context.to_request_context()
|
|
625
626
|
|
|
626
627
|
artifact_definition = await client.get(
|
|
627
628
|
kind=CoreArtifactDefinition,
|
|
@@ -781,6 +782,7 @@ async def run_generator_as_check(model: RunGeneratorAsCheckModel, context: Infra
|
|
|
781
782
|
await add_tags(branches=[model.branch_name], nodes=[model.proposed_change], db_change=True)
|
|
782
783
|
|
|
783
784
|
client = get_client()
|
|
785
|
+
client.request_context = context.to_request_context()
|
|
784
786
|
log = get_run_logger()
|
|
785
787
|
|
|
786
788
|
repository = await get_initialized_repo(
|
|
@@ -859,7 +861,7 @@ async def run_generator_as_check(model: RunGeneratorAsCheckModel, context: Infra
|
|
|
859
861
|
if check:
|
|
860
862
|
check.created_at.value = Timestamp().to_string()
|
|
861
863
|
check.conclusion.value = conclusion.value
|
|
862
|
-
await check.save()
|
|
864
|
+
await check.save(request_context=context.to_request_context())
|
|
863
865
|
else:
|
|
864
866
|
check = await client.create(
|
|
865
867
|
kind=InfrahubKind.GENERATORCHECK,
|
|
@@ -925,6 +927,7 @@ async def request_generator_definition_check(model: RequestGeneratorDefinitionCh
|
|
|
925
927
|
|
|
926
928
|
log = get_run_logger()
|
|
927
929
|
client = get_client()
|
|
930
|
+
client.request_context = context.to_request_context()
|
|
928
931
|
|
|
929
932
|
proposed_change = await client.get(kind=InfrahubKind.PROPOSEDCHANGE, id=model.proposed_change)
|
|
930
933
|
|
infrahub/services/__init__.py
CHANGED
|
@@ -54,7 +54,7 @@ class InfrahubServices:
|
|
|
54
54
|
message_bus: InfrahubMessageBus | None = None,
|
|
55
55
|
workflow: InfrahubWorkflow | None = None,
|
|
56
56
|
component: InfrahubComponent | None = None,
|
|
57
|
-
):
|
|
57
|
+
) -> None:
|
|
58
58
|
"""
|
|
59
59
|
This method should not be called directly, use `new` instead for a proper initialization.
|
|
60
60
|
"""
|
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
5
|
import redis.asyncio as redis
|
|
6
|
+
from redis import UsernamePasswordCredentialProvider
|
|
6
7
|
|
|
7
8
|
from infrahub import config
|
|
8
9
|
from infrahub.services.adapters.cache import InfrahubCache
|
|
@@ -13,10 +14,16 @@ if TYPE_CHECKING:
|
|
|
13
14
|
|
|
14
15
|
class RedisCache(InfrahubCache):
|
|
15
16
|
def __init__(self) -> None:
|
|
17
|
+
credential_provider: UsernamePasswordCredentialProvider | None = None
|
|
18
|
+
if config.SETTINGS.cache.username and config.SETTINGS.cache.password:
|
|
19
|
+
credential_provider = UsernamePasswordCredentialProvider(
|
|
20
|
+
username=config.SETTINGS.cache.username, password=config.SETTINGS.cache.password
|
|
21
|
+
)
|
|
16
22
|
self.connection = redis.Redis(
|
|
17
23
|
host=config.SETTINGS.cache.address,
|
|
18
24
|
port=config.SETTINGS.cache.service_port,
|
|
19
25
|
db=config.SETTINGS.cache.database,
|
|
26
|
+
credential_provider=credential_provider,
|
|
20
27
|
ssl=config.SETTINGS.cache.tls_enabled,
|
|
21
28
|
ssl_cert_reqs="optional" if not config.SETTINGS.cache.tls_insecure else "none",
|
|
22
29
|
ssl_check_hostname=not config.SETTINGS.cache.tls_insecure,
|
infrahub/tasks/artifact.py
CHANGED
|
@@ -13,6 +13,7 @@ from infrahub.workers.dependencies import get_client
|
|
|
13
13
|
async def define_artifact(model: CheckArtifactCreate | RequestArtifactGenerate) -> tuple[InfrahubNode, bool]:
|
|
14
14
|
"""Return an artifact together with a flag to indicate if the artifact is created now or already existed."""
|
|
15
15
|
client = get_client()
|
|
16
|
+
client.request_context = model.context.to_request_context()
|
|
16
17
|
created = False
|
|
17
18
|
if model.artifact_id:
|
|
18
19
|
artifact = await client.get(kind=InfrahubKind.ARTIFACT, id=model.artifact_id, branch=model.branch_name)
|
|
@@ -33,7 +33,7 @@ async def transform_python(message: TransformPythonData) -> Any:
|
|
|
33
33
|
location=message.transform_location,
|
|
34
34
|
data=message.data,
|
|
35
35
|
convert_query_response=message.convert_query_response,
|
|
36
|
-
) # type: ignore[
|
|
36
|
+
) # type: ignore[call-overload]
|
|
37
37
|
|
|
38
38
|
return transformed_data
|
|
39
39
|
|
|
@@ -54,6 +54,6 @@ async def transform_render_jinja2_template(message: TransformJinjaTemplateData)
|
|
|
54
54
|
|
|
55
55
|
rendered_template = await repo.render_jinja2_template.with_options(timeout_seconds=message.timeout)(
|
|
56
56
|
commit=message.commit, location=message.template_location, data={"data": message.data}
|
|
57
|
-
) # type: ignore[
|
|
57
|
+
) # type: ignore[call-overload]
|
|
58
58
|
|
|
59
59
|
return rendered_template
|
infrahub/trigger/catalogue.py
CHANGED
|
@@ -6,6 +6,7 @@ from infrahub.computed_attribute.triggers import (
|
|
|
6
6
|
)
|
|
7
7
|
from infrahub.display_labels.triggers import TRIGGER_DISPLAY_LABELS_ALL_SCHEMA
|
|
8
8
|
from infrahub.hfid.triggers import TRIGGER_HFID_ALL_SCHEMA
|
|
9
|
+
from infrahub.profiles.triggers import TRIGGER_PROFILE_REFRESH_SETUP
|
|
9
10
|
from infrahub.schema.triggers import TRIGGER_SCHEMA_UPDATED
|
|
10
11
|
from infrahub.trigger.models import TriggerDefinition
|
|
11
12
|
from infrahub.webhook.triggers import TRIGGER_WEBHOOK_DELETE, TRIGGER_WEBHOOK_SETUP_UPDATE
|
|
@@ -17,6 +18,7 @@ builtin_triggers: list[TriggerDefinition] = [
|
|
|
17
18
|
TRIGGER_COMPUTED_ATTRIBUTE_PYTHON_SETUP_COMMIT,
|
|
18
19
|
TRIGGER_DISPLAY_LABELS_ALL_SCHEMA,
|
|
19
20
|
TRIGGER_HFID_ALL_SCHEMA,
|
|
21
|
+
TRIGGER_PROFILE_REFRESH_SETUP,
|
|
20
22
|
TRIGGER_SCHEMA_UPDATED,
|
|
21
23
|
TRIGGER_WEBHOOK_DELETE,
|
|
22
24
|
TRIGGER_WEBHOOK_SETUP_UPDATE,
|
infrahub/trigger/models.py
CHANGED
infrahub/trigger/setup.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import TYPE_CHECKING, Awaitable, Callable
|
|
1
|
+
from typing import TYPE_CHECKING, Awaitable, Callable, Sequence
|
|
2
2
|
|
|
3
3
|
from prefect import get_run_logger, task
|
|
4
4
|
from prefect.automations import AutomationCore
|
|
@@ -46,7 +46,7 @@ def compare_automations(
|
|
|
46
46
|
|
|
47
47
|
@task(name="trigger-setup-specific", task_run_name="Setup triggers of a specific kind", cache_policy=NONE) # type: ignore[arg-type]
|
|
48
48
|
async def setup_triggers_specific(
|
|
49
|
-
gatherer: Callable[[InfrahubDatabase | None], Awaitable[
|
|
49
|
+
gatherer: Callable[[InfrahubDatabase | None], Awaitable[Sequence[TriggerDefinition]]],
|
|
50
50
|
trigger_type: TriggerType,
|
|
51
51
|
db: InfrahubDatabase | None = None,
|
|
52
52
|
) -> TriggerSetupReport:
|
|
@@ -69,7 +69,7 @@ async def setup_triggers_specific(
|
|
|
69
69
|
@task(name="trigger-setup", task_run_name="Setup triggers", cache_policy=NONE)
|
|
70
70
|
async def setup_triggers(
|
|
71
71
|
client: PrefectClient,
|
|
72
|
-
triggers:
|
|
72
|
+
triggers: Sequence[TriggerDefinition],
|
|
73
73
|
trigger_type: TriggerType | None = None,
|
|
74
74
|
force_update: bool = False,
|
|
75
75
|
) -> TriggerSetupReport:
|
infrahub/trigger/tasks.py
CHANGED
|
@@ -8,6 +8,7 @@ from infrahub.computed_attribute.gather import (
|
|
|
8
8
|
)
|
|
9
9
|
from infrahub.display_labels.gather import gather_trigger_display_labels_jinja2
|
|
10
10
|
from infrahub.hfid.gather import gather_trigger_hfid
|
|
11
|
+
from infrahub.profiles.gather import gather_trigger_profile_refresh
|
|
11
12
|
from infrahub.trigger.catalogue import builtin_triggers
|
|
12
13
|
from infrahub.webhook.gather import gather_trigger_webhook
|
|
13
14
|
from infrahub.workers.dependencies import get_database
|
|
@@ -28,6 +29,7 @@ async def trigger_configure_all() -> None:
|
|
|
28
29
|
computed_attribute_python_query_triggers,
|
|
29
30
|
) = await gather_trigger_computed_attribute_python(db=db)
|
|
30
31
|
action_rules = await gather_trigger_action_rules(db=db)
|
|
32
|
+
profile_refresh_triggers = await gather_trigger_profile_refresh()
|
|
31
33
|
triggers = (
|
|
32
34
|
computed_attribute_j2_triggers
|
|
33
35
|
+ computed_attribute_python_triggers
|
|
@@ -35,6 +37,7 @@ async def trigger_configure_all() -> None:
|
|
|
35
37
|
+ display_label_triggers
|
|
36
38
|
+ human_friendly_id_triggers
|
|
37
39
|
+ builtin_triggers
|
|
40
|
+
+ profile_refresh_triggers
|
|
38
41
|
+ webhook_trigger
|
|
39
42
|
+ action_rules
|
|
40
43
|
)
|
infrahub/validators/tasks.py
CHANGED
|
@@ -29,6 +29,7 @@ async def start_validator[ValidatorType: CoreValidator](
|
|
|
29
29
|
validator = cast("ValidatorType", validator)
|
|
30
30
|
else:
|
|
31
31
|
data["proposed_change"] = proposed_change
|
|
32
|
+
client.request_context = context.to_request_context()
|
|
32
33
|
validator = await client.create(kind=validator_type, data=data)
|
|
33
34
|
await validator.save()
|
|
34
35
|
|
infrahub/webhook/gather.py
CHANGED
|
@@ -13,5 +13,5 @@ from .models import WebhookTriggerDefinition
|
|
|
13
13
|
@task(name="gather-trigger-webhook", task_run_name="Gather webhook triggers", cache_policy=NONE)
|
|
14
14
|
async def gather_trigger_webhook(db: InfrahubDatabase) -> list[WebhookTriggerDefinition]:
|
|
15
15
|
webhooks = await NodeManager.query(db=db, schema=CoreWebhook)
|
|
16
|
-
triggers = [WebhookTriggerDefinition.from_object(webhook) for webhook in webhooks]
|
|
16
|
+
triggers = [WebhookTriggerDefinition.from_object(webhook) for webhook in webhooks if webhook.active.value]
|
|
17
17
|
return triggers
|
infrahub/webhook/models.py
CHANGED
|
@@ -233,7 +233,7 @@ class TransformWebhook(Webhook):
|
|
|
233
233
|
convert_query_response=self.convert_query_response,
|
|
234
234
|
data={"data": {"data": data, **context.model_dump()}},
|
|
235
235
|
client=client,
|
|
236
|
-
) # type: ignore[
|
|
236
|
+
) # type: ignore[call-overload]
|
|
237
237
|
|
|
238
238
|
@classmethod
|
|
239
239
|
def from_object(cls, obj: CoreCustomWebhook, transform: CoreTransformPython) -> Self:
|