infrahub-server 1.2.12__py3-none-any.whl → 1.3.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.
Files changed (205) hide show
  1. infrahub/actions/constants.py +130 -0
  2. infrahub/actions/gather.py +114 -0
  3. infrahub/actions/models.py +243 -0
  4. infrahub/actions/parsers.py +104 -0
  5. infrahub/actions/schema.py +393 -0
  6. infrahub/actions/tasks.py +119 -0
  7. infrahub/actions/triggers.py +21 -0
  8. infrahub/branch/__init__.py +0 -0
  9. infrahub/branch/tasks.py +29 -0
  10. infrahub/branch/triggers.py +22 -0
  11. infrahub/cli/db.py +3 -4
  12. infrahub/computed_attribute/gather.py +3 -1
  13. infrahub/computed_attribute/tasks.py +23 -29
  14. infrahub/core/account.py +24 -47
  15. infrahub/core/attribute.py +13 -15
  16. infrahub/core/constants/__init__.py +10 -0
  17. infrahub/core/constants/infrahubkind.py +9 -0
  18. infrahub/core/constraint/node/runner.py +3 -1
  19. infrahub/core/convert_object_type/__init__.py +0 -0
  20. infrahub/core/convert_object_type/conversion.py +124 -0
  21. infrahub/core/convert_object_type/schema_mapping.py +56 -0
  22. infrahub/core/diff/coordinator.py +8 -1
  23. infrahub/core/diff/query/all_conflicts.py +1 -5
  24. infrahub/core/diff/query/artifact.py +10 -20
  25. infrahub/core/diff/query/delete_query.py +8 -4
  26. infrahub/core/diff/query/diff_get.py +3 -6
  27. infrahub/core/diff/query/field_specifiers.py +1 -1
  28. infrahub/core/diff/query/field_summary.py +2 -4
  29. infrahub/core/diff/query/merge.py +72 -125
  30. infrahub/core/diff/query/save.py +28 -43
  31. infrahub/core/diff/query/summary_counts_enricher.py +34 -54
  32. infrahub/core/diff/query/time_range_query.py +0 -1
  33. infrahub/core/diff/repository/repository.py +4 -0
  34. infrahub/core/manager.py +14 -11
  35. infrahub/core/migrations/graph/m003_relationship_parent_optional.py +1 -2
  36. infrahub/core/migrations/graph/m012_convert_account_generic.py +1 -1
  37. infrahub/core/migrations/graph/m013_convert_git_password_credential.py +2 -6
  38. infrahub/core/migrations/graph/m015_diff_format_update.py +1 -2
  39. infrahub/core/migrations/graph/m016_diff_delete_bug_fix.py +1 -2
  40. infrahub/core/migrations/graph/m019_restore_rels_to_time.py +11 -22
  41. infrahub/core/migrations/graph/m020_duplicate_edges.py +3 -6
  42. infrahub/core/migrations/graph/m021_missing_hierarchy_merge.py +1 -2
  43. infrahub/core/migrations/graph/m023_deduplicate_cardinality_one_relationships.py +2 -2
  44. infrahub/core/migrations/graph/m024_missing_hierarchy_backfill.py +1 -2
  45. infrahub/core/migrations/graph/m028_delete_diffs.py +1 -2
  46. infrahub/core/migrations/graph/m029_duplicates_cleanup.py +30 -48
  47. infrahub/core/migrations/graph/m030_illegal_edges.py +1 -2
  48. infrahub/core/migrations/query/attribute_add.py +1 -2
  49. infrahub/core/migrations/query/attribute_rename.py +6 -11
  50. infrahub/core/migrations/query/delete_element_in_schema.py +19 -17
  51. infrahub/core/migrations/query/node_duplicate.py +19 -21
  52. infrahub/core/migrations/query/relationship_duplicate.py +19 -18
  53. infrahub/core/migrations/schema/node_attribute_remove.py +4 -8
  54. infrahub/core/migrations/schema/node_remove.py +19 -20
  55. infrahub/core/models.py +29 -2
  56. infrahub/core/node/__init__.py +131 -28
  57. infrahub/core/node/base.py +1 -1
  58. infrahub/core/node/create.py +211 -0
  59. infrahub/core/node/resource_manager/number_pool.py +31 -5
  60. infrahub/core/node/standard.py +6 -1
  61. infrahub/core/path.py +15 -1
  62. infrahub/core/protocols.py +57 -0
  63. infrahub/core/protocols_base.py +3 -0
  64. infrahub/core/query/__init__.py +2 -2
  65. infrahub/core/query/delete.py +3 -3
  66. infrahub/core/query/diff.py +19 -32
  67. infrahub/core/query/ipam.py +10 -20
  68. infrahub/core/query/node.py +29 -47
  69. infrahub/core/query/relationship.py +55 -34
  70. infrahub/core/query/resource_manager.py +1 -2
  71. infrahub/core/query/standard_node.py +19 -5
  72. infrahub/core/query/subquery.py +2 -4
  73. infrahub/core/relationship/constraints/count.py +10 -9
  74. infrahub/core/relationship/constraints/interface.py +2 -1
  75. infrahub/core/relationship/constraints/peer_kind.py +2 -1
  76. infrahub/core/relationship/constraints/peer_parent.py +56 -0
  77. infrahub/core/relationship/constraints/peer_relatives.py +72 -0
  78. infrahub/core/relationship/constraints/profiles_kind.py +1 -1
  79. infrahub/core/relationship/model.py +4 -1
  80. infrahub/core/schema/__init__.py +2 -1
  81. infrahub/core/schema/attribute_parameters.py +160 -0
  82. infrahub/core/schema/attribute_schema.py +130 -7
  83. infrahub/core/schema/basenode_schema.py +27 -3
  84. infrahub/core/schema/definitions/core/__init__.py +29 -1
  85. infrahub/core/schema/definitions/core/group.py +45 -0
  86. infrahub/core/schema/definitions/core/resource_pool.py +9 -0
  87. infrahub/core/schema/definitions/internal.py +43 -5
  88. infrahub/core/schema/generated/attribute_schema.py +16 -3
  89. infrahub/core/schema/generated/relationship_schema.py +11 -1
  90. infrahub/core/schema/manager.py +7 -2
  91. infrahub/core/schema/schema_branch.py +104 -9
  92. infrahub/core/validators/__init__.py +15 -2
  93. infrahub/core/validators/attribute/choices.py +1 -3
  94. infrahub/core/validators/attribute/enum.py +1 -3
  95. infrahub/core/validators/attribute/kind.py +1 -3
  96. infrahub/core/validators/attribute/length.py +13 -7
  97. infrahub/core/validators/attribute/min_max.py +118 -0
  98. infrahub/core/validators/attribute/number_pool.py +106 -0
  99. infrahub/core/validators/attribute/optional.py +1 -4
  100. infrahub/core/validators/attribute/regex.py +5 -6
  101. infrahub/core/validators/attribute/unique.py +1 -3
  102. infrahub/core/validators/determiner.py +18 -2
  103. infrahub/core/validators/enum.py +12 -0
  104. infrahub/core/validators/node/hierarchy.py +3 -6
  105. infrahub/core/validators/query.py +1 -3
  106. infrahub/core/validators/relationship/count.py +6 -12
  107. infrahub/core/validators/relationship/optional.py +2 -4
  108. infrahub/core/validators/relationship/peer.py +177 -12
  109. infrahub/core/validators/tasks.py +1 -1
  110. infrahub/core/validators/uniqueness/query.py +5 -9
  111. infrahub/database/__init__.py +12 -4
  112. infrahub/database/validation.py +1 -2
  113. infrahub/dependencies/builder/constraint/grouped/node_runner.py +4 -0
  114. infrahub/dependencies/builder/constraint/relationship_manager/peer_parent.py +8 -0
  115. infrahub/dependencies/builder/constraint/relationship_manager/peer_relatives.py +8 -0
  116. infrahub/dependencies/builder/constraint/schema/aggregated.py +2 -0
  117. infrahub/dependencies/builder/constraint/schema/relationship_peer.py +8 -0
  118. infrahub/dependencies/builder/diff/deserializer.py +1 -1
  119. infrahub/dependencies/registry.py +4 -0
  120. infrahub/events/group_action.py +1 -0
  121. infrahub/events/models.py +1 -1
  122. infrahub/git/base.py +5 -3
  123. infrahub/git/integrator.py +96 -5
  124. infrahub/git/tasks.py +1 -0
  125. infrahub/graphql/analyzer.py +139 -18
  126. infrahub/graphql/manager.py +4 -0
  127. infrahub/graphql/mutations/action.py +164 -0
  128. infrahub/graphql/mutations/convert_object_type.py +71 -0
  129. infrahub/graphql/mutations/main.py +24 -175
  130. infrahub/graphql/mutations/proposed_change.py +20 -17
  131. infrahub/graphql/mutations/relationship.py +32 -0
  132. infrahub/graphql/mutations/resource_manager.py +63 -7
  133. infrahub/graphql/queries/convert_object_type_mapping.py +34 -0
  134. infrahub/graphql/queries/resource_manager.py +7 -1
  135. infrahub/graphql/resolvers/many_relationship.py +1 -1
  136. infrahub/graphql/resolvers/resolver.py +2 -2
  137. infrahub/graphql/resolvers/single_relationship.py +1 -1
  138. infrahub/graphql/schema.py +6 -0
  139. infrahub/menu/menu.py +34 -2
  140. infrahub/message_bus/messages/__init__.py +0 -10
  141. infrahub/message_bus/operations/__init__.py +0 -8
  142. infrahub/message_bus/operations/refresh/registry.py +3 -6
  143. infrahub/patch/queries/delete_duplicated_edges.py +10 -15
  144. infrahub/pools/models.py +14 -0
  145. infrahub/pools/number.py +5 -3
  146. infrahub/pools/registration.py +22 -0
  147. infrahub/pools/tasks.py +126 -0
  148. infrahub/prefect_server/models.py +1 -19
  149. infrahub/proposed_change/models.py +68 -3
  150. infrahub/proposed_change/tasks.py +911 -34
  151. infrahub/schema/__init__.py +0 -0
  152. infrahub/schema/tasks.py +27 -0
  153. infrahub/schema/triggers.py +23 -0
  154. infrahub/task_manager/models.py +10 -6
  155. infrahub/trigger/catalogue.py +6 -0
  156. infrahub/trigger/models.py +23 -6
  157. infrahub/trigger/setup.py +26 -2
  158. infrahub/trigger/tasks.py +4 -2
  159. infrahub/types.py +6 -0
  160. infrahub/webhook/tasks.py +4 -8
  161. infrahub/workflows/catalogue.py +103 -1
  162. infrahub_sdk/client.py +43 -10
  163. infrahub_sdk/ctl/generator.py +4 -4
  164. infrahub_sdk/ctl/repository.py +1 -1
  165. infrahub_sdk/node/__init__.py +39 -0
  166. infrahub_sdk/node/attribute.py +122 -0
  167. infrahub_sdk/node/constants.py +21 -0
  168. infrahub_sdk/{node.py → node/node.py} +158 -803
  169. infrahub_sdk/node/parsers.py +15 -0
  170. infrahub_sdk/node/property.py +24 -0
  171. infrahub_sdk/node/related_node.py +266 -0
  172. infrahub_sdk/node/relationship.py +302 -0
  173. infrahub_sdk/protocols.py +112 -0
  174. infrahub_sdk/protocols_base.py +34 -2
  175. infrahub_sdk/pytest_plugin/items/python_transform.py +2 -1
  176. infrahub_sdk/query_groups.py +17 -5
  177. infrahub_sdk/schema/main.py +1 -0
  178. infrahub_sdk/schema/repository.py +16 -0
  179. infrahub_sdk/spec/object.py +1 -1
  180. infrahub_sdk/store.py +1 -1
  181. infrahub_sdk/testing/schemas/car_person.py +1 -0
  182. infrahub_sdk/utils.py +7 -20
  183. infrahub_sdk/yaml.py +6 -5
  184. {infrahub_server-1.2.12.dist-info → infrahub_server-1.3.0.dist-info}/METADATA +3 -3
  185. {infrahub_server-1.2.12.dist-info → infrahub_server-1.3.0.dist-info}/RECORD +192 -166
  186. infrahub_testcontainers/container.py +0 -1
  187. infrahub_testcontainers/docker-compose.test.yml +1 -1
  188. infrahub_testcontainers/helpers.py +8 -2
  189. infrahub/message_bus/messages/check_generator_run.py +0 -26
  190. infrahub/message_bus/messages/finalize_validator_execution.py +0 -15
  191. infrahub/message_bus/messages/proposed_change/base_with_diff.py +0 -16
  192. infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +0 -11
  193. infrahub/message_bus/messages/request_generatordefinition_check.py +0 -20
  194. infrahub/message_bus/messages/request_proposedchange_pipeline.py +0 -23
  195. infrahub/message_bus/operations/check/__init__.py +0 -3
  196. infrahub/message_bus/operations/check/generator.py +0 -156
  197. infrahub/message_bus/operations/finalize/__init__.py +0 -3
  198. infrahub/message_bus/operations/finalize/validator.py +0 -133
  199. infrahub/message_bus/operations/requests/__init__.py +0 -9
  200. infrahub/message_bus/operations/requests/generator_definition.py +0 -140
  201. infrahub/message_bus/operations/requests/proposed_change.py +0 -629
  202. /infrahub/{message_bus/messages/proposed_change → actions}/__init__.py +0 -0
  203. {infrahub_server-1.2.12.dist-info → infrahub_server-1.3.0.dist-info}/LICENSE.txt +0 -0
  204. {infrahub_server-1.2.12.dist-info → infrahub_server-1.3.0.dist-info}/WHEEL +0 -0
  205. {infrahub_server-1.2.12.dist-info → infrahub_server-1.3.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,393 @@
1
+ from infrahub.actions.constants import (
2
+ BranchScope,
3
+ MemberAction,
4
+ MemberUpdate,
5
+ NodeAction,
6
+ RelationshipMatch,
7
+ ValueMatch,
8
+ )
9
+ from infrahub.core.constants import AllowOverrideType, BranchSupportType, InfrahubKind
10
+ from infrahub.core.constants import RelationshipCardinality as Cardinality
11
+ from infrahub.core.constants import RelationshipKind as RelKind
12
+ from infrahub.core.schema.attribute_schema import AttributeSchema as Attr
13
+ from infrahub.core.schema.generic_schema import GenericSchema
14
+ from infrahub.core.schema.node_schema import NodeSchema
15
+ from infrahub.core.schema.relationship_schema import (
16
+ RelationshipSchema as Rel,
17
+ )
18
+
19
+ core_trigger_rule = GenericSchema(
20
+ name="TriggerRule",
21
+ namespace="Core",
22
+ description="A rule that allows you to define a trigger and map it to an action that runs once the trigger condition is met.",
23
+ include_in_menu=False,
24
+ icon="mdi:filter-cog-outline",
25
+ label="Trigger Rule",
26
+ human_friendly_id=["name__value"],
27
+ order_by=["name__value"],
28
+ display_labels=["name__value"],
29
+ branch=BranchSupportType.AGNOSTIC,
30
+ uniqueness_constraints=[["name__value"]],
31
+ generate_profile=False,
32
+ attributes=[
33
+ Attr(
34
+ name="name",
35
+ kind="Text",
36
+ description="The name of the trigger rule",
37
+ unique=True,
38
+ order_weight=100,
39
+ ),
40
+ Attr(
41
+ name="description",
42
+ kind="Text",
43
+ description="A longer description to define the purpose of this trigger",
44
+ optional=True,
45
+ order_weight=200,
46
+ ),
47
+ Attr(
48
+ name="active",
49
+ kind="Boolean",
50
+ description="Indicates if this trigger is enabled or if it's just prepared, could be useful as you are setting up a trigger",
51
+ optional=False,
52
+ default_value=True,
53
+ order_weight=200,
54
+ ),
55
+ Attr(
56
+ name="branch_scope",
57
+ kind="Dropdown",
58
+ description="Limits the scope with regards to what kind of branches to match against",
59
+ choices=BranchScope.available_types(),
60
+ default_value=BranchScope.DEFAULT_BRANCH.value.name,
61
+ optional=False,
62
+ order_weight=200,
63
+ allow_override=AllowOverrideType.NONE,
64
+ ),
65
+ ],
66
+ relationships=[
67
+ Rel(
68
+ name="action",
69
+ peer=InfrahubKind.ACTION,
70
+ description="The action to execute once the trigger conditions has been met",
71
+ identifier="core_action__core_triggerrule",
72
+ kind=RelKind.ATTRIBUTE,
73
+ cardinality=Cardinality.ONE,
74
+ optional=False,
75
+ order_weight=1000,
76
+ ),
77
+ ],
78
+ )
79
+
80
+ core_action = GenericSchema(
81
+ name="Action",
82
+ namespace="Core",
83
+ description="An action that can be executed by a trigger",
84
+ include_in_menu=False,
85
+ icon="mdi:cards-diamond-outline",
86
+ label="Core Action",
87
+ human_friendly_id=["name__value"],
88
+ order_by=["name__value"],
89
+ display_labels=["name__value"],
90
+ branch=BranchSupportType.AGNOSTIC,
91
+ uniqueness_constraints=[["name__value"]],
92
+ generate_profile=False,
93
+ attributes=[
94
+ Attr(
95
+ name="name",
96
+ description="Short descriptive name",
97
+ kind="Text",
98
+ unique=True,
99
+ order_weight=100,
100
+ ),
101
+ Attr(
102
+ name="description",
103
+ description="A detailed description of the action",
104
+ kind="Text",
105
+ optional=True,
106
+ order_weight=200,
107
+ ),
108
+ ],
109
+ relationships=[
110
+ Rel(
111
+ name="triggers",
112
+ description="The triggers that would execute this action once the triggering condition is met",
113
+ peer=InfrahubKind.TRIGGERRULE,
114
+ kind=RelKind.ATTRIBUTE,
115
+ cardinality=Cardinality.MANY,
116
+ identifier="core_action__core_triggerrule",
117
+ optional=True,
118
+ order_weight=1000,
119
+ ),
120
+ ],
121
+ )
122
+
123
+ core_node_trigger_match = GenericSchema(
124
+ name="NodeTriggerMatch",
125
+ namespace="Core",
126
+ description="A trigger match condition related to changes to nodes within the Infrahub database",
127
+ include_in_menu=False,
128
+ icon="mdi:match",
129
+ label="Node Trigger Match",
130
+ branch=BranchSupportType.AGNOSTIC,
131
+ generate_profile=False,
132
+ attributes=[],
133
+ relationships=[
134
+ Rel(
135
+ name="trigger",
136
+ peer="CoreNodeTriggerRule",
137
+ description="The node trigger that this match is connected to",
138
+ kind=RelKind.PARENT,
139
+ cardinality=Cardinality.ONE,
140
+ optional=False,
141
+ identifier="core_node_trigger_match__core_trigger_rule",
142
+ order_weight=1000,
143
+ ),
144
+ ],
145
+ )
146
+
147
+
148
+ core_generator_action = NodeSchema(
149
+ name="GeneratorAction",
150
+ namespace="Core",
151
+ description="An action that runs a generator definition once triggered",
152
+ include_in_menu=False,
153
+ icon="mdi:cards-diamond-outline",
154
+ label="Generator Action",
155
+ human_friendly_id=["name__value"],
156
+ order_by=["name__value"],
157
+ display_labels=["name__value"],
158
+ branch=BranchSupportType.AGNOSTIC,
159
+ uniqueness_constraints=[["name__value"]],
160
+ generate_profile=False,
161
+ inherit_from=[InfrahubKind.ACTION],
162
+ relationships=[
163
+ Rel(
164
+ name="generator",
165
+ description="The generator definition to execute once this action gets triggered",
166
+ peer=InfrahubKind.GENERATORDEFINITION,
167
+ kind=RelKind.ATTRIBUTE,
168
+ cardinality=Cardinality.ONE,
169
+ identifier="core_generator_action__generator_definition",
170
+ optional=False,
171
+ order_weight=400,
172
+ ),
173
+ ],
174
+ )
175
+
176
+ core_group_action = NodeSchema(
177
+ name="GroupAction",
178
+ namespace="Core",
179
+ description="A group action that adds or removes members from a group once triggered",
180
+ include_in_menu=False,
181
+ icon="mdi:cards-diamond-outline",
182
+ label="Group Action",
183
+ human_friendly_id=["name__value"],
184
+ order_by=["name__value"],
185
+ display_labels=["name__value"],
186
+ branch=BranchSupportType.AGNOSTIC,
187
+ uniqueness_constraints=[["name__value"]],
188
+ generate_profile=False,
189
+ inherit_from=[InfrahubKind.ACTION],
190
+ attributes=[
191
+ Attr(
192
+ name="member_action",
193
+ kind="Dropdown",
194
+ description="Defines if the action should add or remove members from a group when triggered",
195
+ choices=MemberAction.available_types(),
196
+ default_value=MemberAction.ADD_MEMBER.value.name,
197
+ unique=False,
198
+ optional=False,
199
+ order_weight=300,
200
+ ),
201
+ ],
202
+ relationships=[
203
+ Rel(
204
+ name="group",
205
+ peer=InfrahubKind.GENERICGROUP,
206
+ description="The target group of this action",
207
+ kind=RelKind.ATTRIBUTE,
208
+ cardinality=Cardinality.ONE,
209
+ identifier="core_action__group",
210
+ optional=False,
211
+ order_weight=400,
212
+ ),
213
+ ],
214
+ )
215
+
216
+
217
+ core_node_trigger_rule = NodeSchema(
218
+ name="NodeTriggerRule",
219
+ namespace="Core",
220
+ description="A trigger rule that evaluates modifications to nodes within the Infrahub database",
221
+ include_in_menu=False,
222
+ icon="mdi:filter-cog-outline",
223
+ label="Node Trigger Rule",
224
+ human_friendly_id=["name__value"],
225
+ order_by=["name__value"],
226
+ display_labels=["name__value"],
227
+ branch=BranchSupportType.AGNOSTIC,
228
+ uniqueness_constraints=[["name__value"]],
229
+ generate_profile=False,
230
+ inherit_from=[InfrahubKind.TRIGGERRULE],
231
+ attributes=[
232
+ Attr(
233
+ name="node_kind",
234
+ kind="Text",
235
+ description="The kind of node to match against",
236
+ unique=False,
237
+ optional=False,
238
+ order_weight=300,
239
+ ),
240
+ Attr(
241
+ name="mutation_action",
242
+ kind="Text",
243
+ description="The type of modification to match against",
244
+ enum=NodeAction.available_types(),
245
+ unique=False,
246
+ optional=False,
247
+ order_weight=400,
248
+ ),
249
+ ],
250
+ relationships=[
251
+ Rel(
252
+ name="matches",
253
+ peer="CoreNodeTriggerMatch",
254
+ description="Use matches to configure the match condition for the selected node kind",
255
+ kind=RelKind.COMPONENT,
256
+ cardinality=Cardinality.MANY,
257
+ optional=True,
258
+ identifier="core_node_trigger_match__core_trigger_rule",
259
+ order_weight=800,
260
+ ),
261
+ ],
262
+ )
263
+
264
+ core_node_trigger_attribute_match = NodeSchema(
265
+ name="NodeTriggerAttributeMatch",
266
+ namespace="Core",
267
+ description="A trigger match that matches against attribute changes on a node",
268
+ include_in_menu=False,
269
+ icon="mdi:match",
270
+ label="Node Trigger Attribute Match",
271
+ branch=BranchSupportType.AGNOSTIC,
272
+ generate_profile=False,
273
+ inherit_from=["CoreNodeTriggerMatch"],
274
+ display_labels=["attribute_name__value"],
275
+ attributes=[
276
+ Attr(
277
+ name="attribute_name",
278
+ kind="Text",
279
+ description="The attribue to match against",
280
+ unique=False,
281
+ optional=False,
282
+ order_weight=100,
283
+ ),
284
+ Attr(
285
+ name="value",
286
+ kind="Text",
287
+ description="The value the attribute is updated to",
288
+ unique=False,
289
+ optional=True,
290
+ order_weight=200,
291
+ ),
292
+ Attr(
293
+ name="value_previous",
294
+ kind="Text",
295
+ description="The previous value of the targeted attribute",
296
+ unique=False,
297
+ optional=True,
298
+ order_weight=300,
299
+ ),
300
+ Attr(
301
+ name="value_match",
302
+ kind="Dropdown",
303
+ description="The value_match defines how the update will be evaluated, if it has to match the new value, the previous value or both",
304
+ choices=ValueMatch.available_types(),
305
+ default_value=ValueMatch.VALUE.value.name,
306
+ optional=False,
307
+ order_weight=500,
308
+ ),
309
+ ],
310
+ relationships=[],
311
+ )
312
+
313
+ core_node_trigger_relationship_match = NodeSchema(
314
+ name="NodeTriggerRelationshipMatch",
315
+ namespace="Core",
316
+ description="A trigger match that matches against relationship changes on a node",
317
+ include_in_menu=False,
318
+ icon="mdi:match",
319
+ label="Node Trigger Relationship Match",
320
+ branch=BranchSupportType.AGNOSTIC,
321
+ generate_profile=False,
322
+ inherit_from=["CoreNodeTriggerMatch"],
323
+ display_labels=["relationship_name__value", "modification_type__value"],
324
+ attributes=[
325
+ Attr(
326
+ name="relationship_name",
327
+ kind="Text",
328
+ description="The name of the relationship to match against",
329
+ unique=False,
330
+ optional=False,
331
+ order_weight=100,
332
+ ),
333
+ Attr(
334
+ name="modification_type",
335
+ kind="Dropdown",
336
+ description="Indicates if the relationship was added or removed or just updated in any way",
337
+ choices=RelationshipMatch.available_types(),
338
+ default_value=RelationshipMatch.ADDED.value.name,
339
+ optional=False,
340
+ order_weight=200,
341
+ allow_override=AllowOverrideType.NONE,
342
+ ),
343
+ Attr(
344
+ name="peer",
345
+ kind="Text",
346
+ description="The node_id of the relationship peer to match against",
347
+ unique=False,
348
+ optional=True,
349
+ order_weight=300,
350
+ ),
351
+ ],
352
+ relationships=[],
353
+ )
354
+
355
+
356
+ core_group_trigger_rule = NodeSchema(
357
+ name="GroupTriggerRule",
358
+ namespace="Core",
359
+ description="A trigger rule that matches against updates to memberships within groups",
360
+ include_in_menu=False,
361
+ icon="mdi:filter-cog-outline",
362
+ label="Group Trigger Rule",
363
+ human_friendly_id=["name__value"],
364
+ order_by=["name__value"],
365
+ display_labels=["name__value"],
366
+ branch=BranchSupportType.AGNOSTIC,
367
+ uniqueness_constraints=[["name__value"]],
368
+ generate_profile=False,
369
+ inherit_from=[InfrahubKind.TRIGGERRULE],
370
+ attributes=[
371
+ Attr(
372
+ name="member_update",
373
+ kind="Dropdown",
374
+ description="Indicate if the match should be for when members are added or removed",
375
+ choices=MemberUpdate.available_types(),
376
+ default_value=MemberUpdate.ADDED.value.name,
377
+ optional=False,
378
+ order_weight=300,
379
+ ),
380
+ ],
381
+ relationships=[
382
+ Rel(
383
+ name="group",
384
+ peer=InfrahubKind.GENERICGROUP,
385
+ description="The group to match against",
386
+ kind=RelKind.ATTRIBUTE,
387
+ cardinality=Cardinality.ONE,
388
+ identifier="core_group_trigger__group",
389
+ optional=False,
390
+ order_weight=400,
391
+ ),
392
+ ],
393
+ )
@@ -0,0 +1,119 @@
1
+ from __future__ import annotations
2
+
3
+ from infrahub_sdk.graphql import Mutation
4
+ from prefect import flow
5
+
6
+ from infrahub.context import InfrahubContext # noqa: TC001 needed for prefect flow
7
+ from infrahub.services import InfrahubServices # noqa: TC001 needed for prefect flow
8
+ from infrahub.trigger.models import TriggerType
9
+ from infrahub.trigger.setup import setup_triggers_specific
10
+ from infrahub.workflows.utils import add_tags
11
+
12
+ from .gather import gather_trigger_action_rules
13
+ from .models import EventGroupMember # noqa: TC001 needed for prefect flow
14
+
15
+
16
+ @flow(
17
+ name="action-add-node-to-group",
18
+ flow_run_name="Adding node={node_id} to group={group_id}",
19
+ )
20
+ async def add_node_to_group(
21
+ branch_name: str,
22
+ node_id: str,
23
+ group_id: str,
24
+ context: InfrahubContext, # noqa: ARG001
25
+ service: InfrahubServices,
26
+ ) -> None:
27
+ await add_tags(branches=[branch_name], nodes=[node_id, group_id])
28
+
29
+ mutation = Mutation(
30
+ mutation="RelationshipAdd",
31
+ input_data={"data": {"id": group_id, "name": "members", "nodes": [{"id": node_id}]}},
32
+ query={"ok": None},
33
+ )
34
+
35
+ await service.client.execute_graphql(query=mutation.render(), branch_name=branch_name)
36
+
37
+
38
+ @flow(
39
+ name="action-remove-node-from-group",
40
+ flow_run_name="Removing node={node_id} from group={group_id}",
41
+ )
42
+ async def remove_node_from_group(
43
+ branch_name: str,
44
+ node_id: str,
45
+ group_id: str,
46
+ context: InfrahubContext, # noqa: ARG001
47
+ service: InfrahubServices,
48
+ ) -> None:
49
+ await add_tags(branches=[branch_name], nodes=[node_id, group_id])
50
+
51
+ mutation = Mutation(
52
+ mutation="RelationshipRemove",
53
+ input_data={"data": {"id": group_id, "name": "members", "nodes": [{"id": node_id}]}},
54
+ query={"ok": None},
55
+ )
56
+
57
+ await service.client.execute_graphql(query=mutation.render(), branch_name=branch_name)
58
+
59
+
60
+ @flow(
61
+ name="action-run-generator",
62
+ flow_run_name="Running generator generator_definition_id={generator_definition_id} for nodes={node_ids}",
63
+ )
64
+ async def run_generator(
65
+ branch_name: str,
66
+ node_ids: list[str],
67
+ generator_definition_id: str,
68
+ context: InfrahubContext, # noqa: ARG001
69
+ service: InfrahubServices,
70
+ ) -> None:
71
+ await add_tags(branches=[branch_name], nodes=node_ids + [generator_definition_id])
72
+ await _run_generator(
73
+ branch_name=branch_name, generator_definition_id=generator_definition_id, node_ids=node_ids, service=service
74
+ )
75
+
76
+
77
+ @flow(
78
+ name="action-run-generator-group-event",
79
+ flow_run_name="Running generator",
80
+ )
81
+ async def run_generator_group_event(
82
+ branch_name: str,
83
+ members: list[EventGroupMember],
84
+ generator_definition_id: str,
85
+ context: InfrahubContext, # noqa: ARG001
86
+ service: InfrahubServices,
87
+ ) -> None:
88
+ node_ids = [node.id for node in members]
89
+ await add_tags(branches=[branch_name], nodes=node_ids + [generator_definition_id])
90
+ await _run_generator(
91
+ branch_name=branch_name, generator_definition_id=generator_definition_id, node_ids=node_ids, service=service
92
+ )
93
+
94
+
95
+ @flow(
96
+ name="configure-action-rules",
97
+ flow_run_name="Configure updated action rules and triggers",
98
+ )
99
+ async def configure_action_rules(
100
+ service: InfrahubServices,
101
+ ) -> None:
102
+ await setup_triggers_specific(
103
+ gatherer=gather_trigger_action_rules, trigger_type=TriggerType.ACTION_TRIGGER_RULE, db=service.database
104
+ ) # type: ignore[misc]
105
+
106
+
107
+ async def _run_generator(
108
+ branch_name: str,
109
+ node_ids: list[str],
110
+ generator_definition_id: str,
111
+ service: InfrahubServices,
112
+ ) -> None:
113
+ mutation = Mutation(
114
+ mutation="CoreGeneratorDefinitionRun",
115
+ input_data={"data": {"id": generator_definition_id, "nodes": node_ids}},
116
+ query={"ok": None},
117
+ )
118
+
119
+ await service.client.execute_graphql(query=mutation.render(), branch_name=branch_name)
@@ -0,0 +1,21 @@
1
+ from infrahub.events.node_action import NodeCreatedEvent, NodeDeletedEvent, NodeUpdatedEvent
2
+ from infrahub.trigger.models import BuiltinTriggerDefinition, EventTrigger, ExecuteWorkflow
3
+ from infrahub.workflows.catalogue import CONFIGURE_ACTION_RULES
4
+
5
+ from .constants import NODES_THAT_TRIGGER_ACTION_RULES_SETUP
6
+
7
+ TRIGGER_ACTION_RULE_UPDATE = BuiltinTriggerDefinition(
8
+ name="action-trigger-setup-all",
9
+ trigger=EventTrigger(
10
+ events={NodeCreatedEvent.event_name, NodeDeletedEvent.event_name, NodeUpdatedEvent.event_name},
11
+ match={
12
+ "infrahub.node.kind": NODES_THAT_TRIGGER_ACTION_RULES_SETUP,
13
+ },
14
+ ),
15
+ actions=[
16
+ ExecuteWorkflow(
17
+ workflow=CONFIGURE_ACTION_RULES,
18
+ parameters={},
19
+ ),
20
+ ],
21
+ )
File without changes
@@ -0,0 +1,29 @@
1
+ from __future__ import annotations
2
+
3
+ from prefect import flow
4
+ from prefect.logging import get_run_logger
5
+
6
+ from infrahub.context import InfrahubContext # noqa: TC001 needed for prefect flow
7
+ from infrahub.core.registry import registry
8
+ from infrahub.pools.tasks import validate_schema_number_pools
9
+ from infrahub.services import InfrahubServices # noqa: TC001 needed for prefect flow
10
+ from infrahub.workflows.utils import wait_for_schema_to_converge
11
+
12
+
13
+ @flow(
14
+ name="branch-merged",
15
+ flow_run_name="Running actions after '{source_branch}' was merged",
16
+ )
17
+ async def branch_merged(
18
+ source_branch: str, # noqa: ARG001
19
+ context: InfrahubContext,
20
+ service: InfrahubServices,
21
+ target_branch: str | None = None,
22
+ ) -> None:
23
+ target_branch = target_branch or registry.default_branch
24
+ log = get_run_logger()
25
+ await wait_for_schema_to_converge(
26
+ branch_name=target_branch, component=service.component, db=service.database, log=log
27
+ )
28
+
29
+ await validate_schema_number_pools(branch_name=target_branch, context=context, service=service)
@@ -0,0 +1,22 @@
1
+ from infrahub.events.branch_action import BranchMergedEvent
2
+ from infrahub.trigger.models import BuiltinTriggerDefinition, EventTrigger, ExecuteWorkflow
3
+ from infrahub.workflows.catalogue import BRANCH_MERGED
4
+
5
+ TRIGGER_BRANCH_MERGED = BuiltinTriggerDefinition(
6
+ name="branch-merged-trigger",
7
+ trigger=EventTrigger(
8
+ events={BranchMergedEvent.event_name},
9
+ ),
10
+ actions=[
11
+ ExecuteWorkflow(
12
+ workflow=BRANCH_MERGED,
13
+ parameters={
14
+ "source_branch": "{{ event.payload['data']['branch_name'] }}",
15
+ "context": {
16
+ "__prefect_kind": "json",
17
+ "value": {"__prefect_kind": "jinja", "template": "{{ event.payload['context'] | tojson }}"},
18
+ },
19
+ },
20
+ ),
21
+ ],
22
+ )
infrahub/cli/db.py CHANGED
@@ -326,7 +326,7 @@ async def migrate_database(db: InfrahubDatabase, initialize: bool = False, check
326
326
  root_node.graph_version = migration.minimum_version + 1
327
327
  await root_node.save(db=db)
328
328
 
329
- if not execution_result.success or validation_result and not validation_result.success:
329
+ if not execution_result.success or (validation_result and not validation_result.success):
330
330
  rprint(f"Migration: {migration.name} {FAILED_BADGE}")
331
331
  for error in execution_result.errors:
332
332
  rprint(f" {error}")
@@ -449,7 +449,7 @@ async def selected_export_cmd(
449
449
  ctx: typer.Context,
450
450
  kinds: list[str] = typer.Option([], help="Node kinds to export"), # noqa: B008
451
451
  uuids: list[str] = typer.Option([], help="UUIDs of nodes to export"), # noqa: B008
452
- query_limit: int = typer.Option(1000, help="Maximum batch size of export query"), # noqa: B008
452
+ query_limit: int = typer.Option(1000, help="Maximum batch size of export query"),
453
453
  export_dir: Path = typer.Option(Path("infrahub-exports"), help="Path of directory to save exports"), # noqa: B008
454
454
  config_file: str = typer.Argument("infrahub.toml", envvar="INFRAHUB_CONFIG"),
455
455
  ) -> None:
@@ -489,11 +489,10 @@ WITH n
489
489
  ORDER BY %(id_func)s(n)
490
490
  SKIP toInteger($offset)
491
491
  LIMIT toInteger($limit)
492
- CALL {
492
+ CALL (n) {
493
493
  // --------------
494
494
  // get all the nodes and edges linked to this node up to 2 steps away, excluding IS_PART_OF
495
495
  // --------------
496
- WITH n
497
496
  MATCH (n)-[r1]-(v1)-[r2]-(v2)
498
497
  WHERE type(r1) <> "IS_PART_OF"
499
498
  WITH collect([v1, v2]) AS vertex_pairs, collect([r1, r2]) AS edge_pairs
@@ -100,7 +100,9 @@ async def gather_python_transform_attributes(
100
100
  name="gather-trigger-computed-attribute-jinja2",
101
101
  cache_policy=NONE,
102
102
  )
103
- async def gather_trigger_computed_attribute_jinja2() -> list[ComputedAttrJinja2TriggerDefinition]:
103
+ async def gather_trigger_computed_attribute_jinja2(
104
+ db: InfrahubDatabase | None = None, # noqa: ARG001 Needed to have a common function signature for gathering functions
105
+ ) -> list[ComputedAttrJinja2TriggerDefinition]:
104
106
  log = get_run_logger()
105
107
 
106
108
  # Build a list of all branches to process based on which branch is different from main