3535 UpdateRuleRequest ,
3636)
3737from sift .rules .v1 .rules_pb2_grpc import RuleServiceStub
38+ from sift .tags .v2 .tags_pb2 import Tag , TagType
39+ from sift .tags .v2 .tags_pb2_grpc import TagServiceStub
3840from sift .users .v2 .users_pb2_grpc import UserServiceStub
3941
4042from sift_py ._internal .cel import cel_in
5557 RuleActionKind ,
5658 RuleConfig ,
5759)
60+ from sift_py .tag ._internal .shared import list_tags_impl
5861from sift_py .yaml .rule import load_rule_modules
5962
6063
@@ -72,13 +75,15 @@ class RuleService:
7275 _channel_service_stub : ChannelServiceStub
7376 _rule_service_stub : RuleServiceStub
7477 _user_service_stub : UserServiceStub
78+ _tag_service_stub : TagServiceStub
7579 _enable_caching : bool
7680
7781 def __init__ (self , channel : SiftChannel , enable_caching = False ):
7882 self ._asset_service_stub = AssetServiceStub (channel )
7983 self ._channel_service_stub = ChannelServiceStub (channel )
8084 self ._rule_service_stub = RuleServiceStub (channel )
8185 self ._user_service_stub = UserServiceStub (channel )
86+ self ._tag_service_stub = TagServiceStub (channel )
8287 self ._enable_caching = enable_caching
8388
8489 def load_rules_from_yaml (
@@ -244,6 +249,7 @@ def _parse_rules_from_yaml(
244249 channel_references = rule_channel_references ,
245250 contextual_channels = contextual_channels ,
246251 asset_names = rule_yaml .get ("asset_names" , []),
252+ tag_names = rule_yaml .get ("tag_names" , []),
247253 sub_expressions = subexpr ,
248254 is_external = rule_yaml .get ("is_external" , False ),
249255 is_live = rule_yaml .get ("is_live" , False ),
@@ -402,8 +408,17 @@ def _update_req_from_rule_config(
402408 "See `sift_py.rule.config.RuleAction` for available actions."
403409 )
404410
405- # TODO: once we have TagService_ListTags we can do asset-agnostic rules via tags
406411 assets = self ._get_assets (names = config .asset_names ) if config .asset_names else None
412+ asset_tags = (
413+ self ._get_tags (names = config .tag_names , tag_type = TagType .TAG_TYPE_ASSET )
414+ if config .tag_names
415+ else None
416+ )
417+ annotation_tags = list_tags_impl (
418+ self ._tag_service_stub ,
419+ names = [tag for tag in config .action .tags ],
420+ tag_type = TagType .TAG_TYPE_ANNOTATION ,
421+ )
407422
408423 actions = []
409424 if config .action .kind () == RuleActionKind .NOTIFICATION :
@@ -431,7 +446,7 @@ def _update_req_from_rule_config(
431446 annotation = AnnotationActionConfiguration (
432447 assigned_to_user_id = user_id ,
433448 annotation_type = AnnotationType .ANNOTATION_TYPE_DATA_REVIEW ,
434- # tag_ids=config.action.tags, # TODO: Requires TagService
449+ tag_ids = annotation_tags ,
435450 )
436451 ),
437452 )
@@ -442,7 +457,7 @@ def _update_req_from_rule_config(
442457 configuration = RuleActionConfiguration (
443458 annotation = AnnotationActionConfiguration (
444459 annotation_type = AnnotationType .ANNOTATION_TYPE_PHASE ,
445- # tag_ids=config.action.tags, # TODO: Requires TagService
460+ tag_ids = annotation_tags ,
446461 )
447462 ),
448463 )
@@ -523,6 +538,7 @@ def _update_req_from_rule_config(
523538 ],
524539 asset_configuration = RuleAssetConfiguration (
525540 asset_ids = [asset .asset_id for asset in assets ] if assets else None ,
541+ tag_ids = [tag .tag_id for tag in asset_tags ] if asset_tags else None ,
526542 ),
527543 contextual_channels = ContextualChannels (channels = contextual_channel_names ),
528544 is_external = config .is_external ,
@@ -574,6 +590,12 @@ def get_rule(self, rule: str) -> Optional[RuleConfig]:
574590 )
575591 asset_names = [asset .name for asset in assets ]
576592
593+ asset_tags = self ._get_tags (
594+ ids = [tag_id for tag_id in rule_pb .asset_configuration .tag_ids ],
595+ tag_type = TagType .TAG_TYPE_ASSET ,
596+ )
597+ asset_tag_names = [tag .name for tag in asset_tags ]
598+
577599 contextual_channels = []
578600 for channel_ref in rule_pb .contextual_channels .channels :
579601 contextual_channels .append (channel_ref .name )
@@ -585,6 +607,7 @@ def get_rule(self, rule: str) -> Optional[RuleConfig]:
585607 channel_references = channel_references , # type: ignore
586608 contextual_channels = contextual_channels ,
587609 asset_names = asset_names ,
610+ tag_names = asset_tag_names ,
588611 action = action ,
589612 expression = expression ,
590613 )
@@ -616,6 +639,14 @@ def _get_assets(self, names: List[str] = [], ids: List[str] = []) -> List[Asset]
616639 else :
617640 return list_assets_impl (self ._asset_service_stub , names , ids )
618641
642+ def _get_tags (
643+ self , names : List [str ] = [], ids : List [str ] = [], tag_type : Optional [TagType ] = None
644+ ) -> List [Tag ]:
645+ if self ._enable_caching :
646+ return self ._get_tags_cached (tuple (sorted (names )), tuple (sorted (ids )), tag_type )
647+ else :
648+ return list_tags_impl (self ._tag_service_stub , names , ids , tag_type )
649+
619650 def _get_channels (self , filter : str ) -> List [ChannelPb ]:
620651 if self ._enable_caching :
621652 return self ._get_channels_cached (filter )
@@ -632,6 +663,12 @@ def _get_active_users(self, filter: str) -> List[UserPb]:
632663 def _get_assets_cached (self , names : Tuple [str ], ids : Tuple [str ]) -> List [Asset ]:
633664 return list_assets_impl (self ._asset_service_stub , names , ids )
634665
666+ @cache
667+ def _get_tags_cached (
668+ self , names : Tuple [str ], ids : Tuple [str ], tag_type : Optional [TagType ] = None
669+ ) -> List [Asset ]:
670+ return list_tags_impl (self ._tag_service_stub , names , ids , tag_type )
671+
635672 @cache
636673 def _get_channels_cached (self , filter : str ) -> List [ChannelPb ]:
637674 return get_channels (channel_service = self ._channel_service_stub , filter = filter )
0 commit comments