Repository: cloud-custodian/cloud-custodian

Issue:
cloudwatch event-rule tagging
**Is your feature request related to a problem? Please describe.**
It would be nice if Custodian support event rule tagging.

policies:
  - name: event-rule-tag
    resource: event-rule
    filters:
     - type: value
       key: RuleName
       value: custodian
       value_type: normalize
       op: contains
    actions:
     - type: tag
       key: 'owner'
       value: 'lakshmi'
     - type: tag
       key: 'Project'
       value: 'Infrastructure'
     - type: tag
       key: 'ProjectId'
       value: '1234567'



Discussion:
kapilt: @pendyalal do you have a policy that went with?
pendyalal: policies:

 -  name: event-rule-tag
    resource: event-rule
    filters:
        type: value
        key: RuleName
        value: custodian
        value_type: normalize
        op: contains
        actions:
        type: tag
        key: 'owner'
        value: 'lakshmi'
        type: tag
        key: 'Project'
        value: 'Infrastructure'
        type: tag
        key: 'ProjectId'
        value: '1234567'


Patch:
diff --git a/Makefile b/Makefile
index c2b37e65a..fe9cd569a 100644
--- a/Makefile
+++ b/Makefile
@@ -85,7 +85,6 @@ ftest:
 
 sphinx:
 # if this errors either tox -e docs or cd tools/c7n_sphinext && poetry install
-	which c7n-sphinxext
 	make -f docs/Makefile.sphinx html
 
 ghpages:
diff --git a/c7n/query.py b/c7n/query.py
index 78b2cf986..c254b0d24 100644
--- a/c7n/query.py
+++ b/c7n/query.py
@@ -142,7 +142,12 @@ class ChildResourceQuery(ResourceQuery):
 
         parent_type, parent_key, annotate_parent = m.parent_spec
         parents = self.manager.get_resource_manager(parent_type)
-        parent_ids = [p[parents.resource_type.id] for p in parents.resources()]
+        parent_ids = []
+        for p in parents.resources(augment=False):
+            if isinstance(p, str):
+                parent_ids.append(p)
+            else:
+                parent_ids.append(p[parents.resource_type.id])
 
         # Bail out with no parent ids...
         existing_param = parent_key in params
diff --git a/c7n/resources/cw.py b/c7n/resources/cw.py
index 7a0ff0dad..b0ccf6e14 100644
--- a/c7n/resources/cw.py
+++ b/c7n/resources/cw.py
@@ -82,13 +82,16 @@ class EventRule(QueryResourceManager):
 
     class resource_type(TypeInfo):
         service = 'events'
-        arn_type = 'event-rule'
+        arn_type = 'rule'
         enum_spec = ('list_rules', 'Rules', None)
         name = "Name"
         id = "Name"
         filter_name = "NamePrefix"
         filter_type = "scalar"
         cfn_type = 'AWS::Events::Rule'
+        universal_taggable = object()
+
+    augment = universal_augment
 
 
 @EventRule.filter_registry.register('metrics')
diff --git a/c7n/resources/vpc.py b/c7n/resources/vpc.py
index a81b0e2f4..df4023b33 100644
--- a/c7n/resources/vpc.py
+++ b/c7n/resources/vpc.py
@@ -766,7 +766,8 @@ class SGUsage(Filter):
         sg_ids = set()
         expr = jmespath.compile(
             'EcsParameters.NetworkConfiguration.awsvpcConfiguration.SecurityGroups[]')
-        for rule in self.manager.get_resource_manager('event-rule-target').resources():
+        for rule in self.manager.get_resource_manager(
+                'event-rule-target').resources(augment=False):
             ids = expr.search(rule)
             if ids:
                 sg_ids.update(ids)
diff --git a/tox.ini b/tox.ini
index 58cafa670..876cdba6e 100644
--- a/tox.ini
+++ b/tox.ini
@@ -84,8 +84,6 @@ commands = make lint
 [testenv:docs]
 whitelist_externals = make
 commands = make sphinx
-setenv =
-   PATH="$PWD/.tox/docs/bin:$PATH"
 deps =
   -rrequirements-dev.txt
   -rrequirements-docs.txt


Test patch:
diff --git a/tests/data/placebo/test_cwe_rule_tags/events.ListRules_1.json b/tests/data/placebo/test_cwe_rule_tags/events.ListRules_1.json
new file mode 100644
index 000000000..c7368ccda
--- /dev/null
+++ b/tests/data/placebo/test_cwe_rule_tags/events.ListRules_1.json
@@ -0,0 +1,16 @@
+{
+    "status_code": 200,
+    "data": {
+        "Rules": [
+            {
+                "Name": "cloud-custodian-mailer",
+                "Arn": "arn:aws:events:us-west-2:644160558196:rule/cloud-custodian-mailer",
+                "State": "ENABLED",
+                "Description": "Cloud Custodian Mailer",
+                "ScheduleExpression": "rate(5 minutes)",
+                "EventBusName": "default"
+            }
+        ],
+        "ResponseMetadata": {}
+    }
+}
diff --git a/tests/data/placebo/test_cwe_rule_tags/events.ListTagsForResource_1.json b/tests/data/placebo/test_cwe_rule_tags/events.ListTagsForResource_1.json
new file mode 100644
index 000000000..954290d0f
--- /dev/null
+++ b/tests/data/placebo/test_cwe_rule_tags/events.ListTagsForResource_1.json
@@ -0,0 +1,12 @@
+{
+    "status_code": 200,
+    "data": {
+        "Tags": [
+            {
+                "Key": "App",
+                "Value": "Custodian"
+            }
+        ],
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_cwe_rule_tags/tagging.GetResources_1.json b/tests/data/placebo/test_cwe_rule_tags/tagging.GetResources_1.json
new file mode 100644
index 000000000..d35bd3667
--- /dev/null
+++ b/tests/data/placebo/test_cwe_rule_tags/tagging.GetResources_1.json
@@ -0,0 +1,13 @@
+{
+    "status_code": 200,
+    "data": {
+        "PaginationToken": "",
+        "ResourceTagMappingList": [
+            {
+                "ResourceARN": "arn:aws:events:us-west-2:644160558196:rule/cloud-custodian-mailer",
+                "Tags": []
+            }
+        ],
+        "ResponseMetadata": {}
+    }
+}
diff --git a/tests/data/placebo/test_cwe_rule_tags/tagging.TagResources_1.json b/tests/data/placebo/test_cwe_rule_tags/tagging.TagResources_1.json
new file mode 100644
index 000000000..bd2dead85
--- /dev/null
+++ b/tests/data/placebo/test_cwe_rule_tags/tagging.TagResources_1.json
@@ -0,0 +1,7 @@
+{
+    "status_code": 200,
+    "data": {
+        "FailedResourcesMap": {},
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_cwe_rule_target_cross/tagging.GetResources_1.json b/tests/data/placebo/test_cwe_rule_target_cross/tagging.GetResources_1.json
new file mode 100644
index 000000000..958027559
--- /dev/null
+++ b/tests/data/placebo/test_cwe_rule_target_cross/tagging.GetResources_1.json
@@ -0,0 +1,8 @@
+{
+    "status_code": 200,
+    "data": {
+        "PaginationToken": "",
+        "ResourceTagMappingList": [],
+        "ResponseMetadata": {}
+    }
+}
diff --git a/tests/test_cwe.py b/tests/test_cwe.py
index b34ff1509..76c6afe09 100644
--- a/tests/test_cwe.py
+++ b/tests/test_cwe.py
@@ -19,7 +19,28 @@ from .common import event_data, BaseTest
 from c7n.cwe import CloudWatchEvents
 
 
-class CloudWatchRuleTarget(BaseTest):
+class CloudWatchEventTest(BaseTest):
+
+    def test_event_rule_tags(self):
+        factory = self.replay_flight_data('test_cwe_rule_tags')
+        client = factory().client('events')
+        policy = self.load_policy(
+            {
+                'name': 'cwe-rule',
+                'resource': 'aws.event-rule',
+                'filters': [
+                    {'tag:App': 'absent'},
+                    {'Name': 'cloud-custodian-mailer'}],
+                'actions': [
+                    {'type': 'tag', 'tags': {'App': 'Custodian'}}]
+            }, session_factory=factory, config={'region': 'us-west-2'})
+        resources = policy.run()
+        self.assertEqual(len(resources), 1)
+        tags = {t['Key']: t['Value'] for t in
+                client.list_tags_for_resource(
+                    ResourceARN=policy.resource_manager.get_arns(resources)[0]).get(
+                        'Tags')}
+        self.assertEqual(tags, {'App': 'Custodian'})
 
     def test_target_cross_account_remove(self):
         session_factory = self.replay_flight_data("test_cwe_rule_target_cross")