1717from infrahub .git .repository import get_initialized_repo
1818from infrahub .services import services
1919from infrahub .support .macro import MacroDefinition
20+ from infrahub .tasks .registry import refresh_branches
2021from infrahub .workflows .catalogue import PROCESS_COMPUTED_MACRO , UPDATE_COMPUTED_ATTRIBUTE_TRANSFORM
2122from infrahub .workflows .utils import add_branch_tag
2223
2324from .constants import AUTOMATION_NAME , AUTOMATION_NAME_PREFIX
24- from .models import ComputedAttributeAutomations
25+ from .models import ComputedAttributeAutomations , PythonTransformComputedAttribute
2526
2627if TYPE_CHECKING :
2728 from infrahub .core .schema .computed_attribute import ComputedAttribute
@@ -48,6 +49,8 @@ async def process_transform(
4849 branch_name : str ,
4950 node_kind : str ,
5051 object_id : str ,
52+ computed_attribute_name : str , # pylint: disable=unused-argument
53+ computed_attribute_kind : str , # pylint: disable=unused-argument
5154 updated_fields : list [str ] | None = None , # pylint: disable=unused-argument
5255) -> None :
5356 """Request to the creation of git branches in available repositories."""
@@ -262,3 +265,114 @@ async def computed_attribute_setup() -> None:
262265 else :
263266 await client .create_automation (automation = automation )
264267 log .info (f"{ computed_attribute .key_name } Created" )
268+
269+
270+ @flow (
271+ name = "computed-attribute-setup-python" ,
272+ flow_run_name = "Setup computed attributes for Python transforms in task-manager" ,
273+ )
274+ async def computed_attribute_setup_python () -> None :
275+ service = services .service
276+ async with service .database .start_session () as db :
277+ await refresh_branches (db = db )
278+
279+ schema_branch = registry .schema .get_schema_branch (name = registry .default_branch )
280+ log = get_run_logger ()
281+
282+ transform_attributes = schema_branch .computed_attributes .python_attributes_by_transform
283+
284+ transform_names = list (transform_attributes .keys ())
285+
286+ transforms = await service .client .filters (
287+ kind = "CoreTransformPython" ,
288+ branch = registry .default_branch ,
289+ prefetch_relationships = True ,
290+ populate_store = True ,
291+ name__values = transform_names ,
292+ )
293+
294+ found_transforms_names = [transform .name .value for transform in transforms ]
295+ for transform_name in transform_names :
296+ if transform_name not in found_transforms_names :
297+ log .warning (
298+ msg = f"The transform { transform_name } is assigned to a computed attribute but the transform could not be found in the database."
299+ )
300+
301+ computed_attributes : list [PythonTransformComputedAttribute ] = []
302+ for transform in transforms :
303+ for attribute in transform_attributes [transform .name .value ]:
304+ computed_attributes .append (
305+ PythonTransformComputedAttribute (
306+ name = transform .name .value ,
307+ repository_id = transform .repository .peer .id ,
308+ repository_name = transform .repository .peer .name .value ,
309+ repository_kind = transform .repository .peer .typename ,
310+ query_name = transform .query .peer .name .value ,
311+ query_models = transform .query .peer .models .value ,
312+ computed_attribute = attribute ,
313+ )
314+ )
315+
316+ async with get_client (sync_client = False ) as client :
317+ deployments = {
318+ item .name : item
319+ for item in await client .read_deployments (
320+ deployment_filter = DeploymentFilter (
321+ name = DeploymentFilterName (any_ = [UPDATE_COMPUTED_ATTRIBUTE_TRANSFORM .name ])
322+ )
323+ )
324+ }
325+ if UPDATE_COMPUTED_ATTRIBUTE_TRANSFORM .name not in deployments :
326+ raise ValueError ("Unable to find the deployment for UPDATE_COMPUTED_ATTRIBUTE_TRANSFORM" )
327+
328+ deployment_id_python = deployments [UPDATE_COMPUTED_ATTRIBUTE_TRANSFORM .name ].id
329+
330+ automations = await client .read_automations ()
331+ existing_computed_attr_automations = ComputedAttributeAutomations .from_prefect (automations = automations )
332+
333+ for computed_attribute in computed_attributes :
334+ log .info (f"processing { computed_attribute .computed_attribute .key_name } " )
335+ scope = "default"
336+
337+ automation = AutomationCore (
338+ name = AUTOMATION_NAME .format (
339+ prefix = AUTOMATION_NAME_PREFIX ,
340+ identifier = computed_attribute .computed_attribute .key_name ,
341+ scope = scope ,
342+ ),
343+ description = f"Process value of the computed attribute for { computed_attribute .computed_attribute .key_name } [{ scope } ]" ,
344+ enabled = True ,
345+ trigger = EventTrigger (
346+ posture = Posture .Reactive ,
347+ expect = {"infrahub.node.*" },
348+ within = timedelta (0 ),
349+ match = ResourceSpecification ({"infrahub.node.kind" : [computed_attribute .computed_attribute .kind ]}),
350+ threshold = 1 ,
351+ ),
352+ actions = [
353+ RunDeployment (
354+ source = "selected" ,
355+ deployment_id = deployment_id_python ,
356+ parameters = {
357+ "branch_name" : "{{ event.resource['infrahub.branch.name'] }}" ,
358+ "node_kind" : "{{ event.resource['infrahub.node.kind'] }}" ,
359+ "object_id" : "{{ event.resource['infrahub.node.id'] }}" ,
360+ "computed_attribute_name" : computed_attribute .computed_attribute .attribute .name ,
361+ "computed_attribute_kind" : computed_attribute .computed_attribute .kind ,
362+ },
363+ job_variables = {},
364+ )
365+ ],
366+ )
367+
368+ if existing_computed_attr_automations .has (
369+ identifier = computed_attribute .computed_attribute .key_name , scope = scope
370+ ):
371+ existing = existing_computed_attr_automations .get (
372+ identifier = computed_attribute .computed_attribute .key_name , scope = scope
373+ )
374+ await client .update_automation (automation_id = existing .id , automation = automation )
375+ log .info (f"{ computed_attribute .computed_attribute .key_name } Updated" )
376+ else :
377+ await client .create_automation (automation = automation )
378+ log .info (f"{ computed_attribute .computed_attribute .key_name } Created" )
0 commit comments