Repository: cloud-custodian/cloud-custodian

Issue:
Custodian errors when using example conditional policy with a gcp resource
**Describe the bug**
Attempting to run the [example conditional execution policy ](https://cloudcustodian.io/docs/quickstart/advanced.html#conditional-policy-execution) in combination with a gcp resource results in an error when validating the condition.

**To Reproduce**
Steps to reproduce the behavior:
1. Create a policy using the condition of the example for a gcp resource, I used `gcp.function`.
2. `custodian run` the policy

**Expected behavior**
The example policy runs successfully.


**Background Information:**

- Policy:

```yaml
policies:
  - name: cloudfunction
    resource: gcp.function
    conditions:
       - type: value
         key: now
         op: greater-than
         value_type: date
         value: "2018-12-15"
       - type: value
         key: now
         op: less-than
         value_type: date
         value: "2018-12-31"
```

 - Traceback:

```
custodian run ~/Projects/policies/policy.yaml -v -s ~/Projects/policies/.custodian
2020-10-15 16:44:26,694: custodian.commands:DEBUG Loaded file /Users/kevinkessels/Projects/policies/policy.yaml. Contains 1 policies
Traceback (most recent call last):
  File "/Users/kevinkessels/Projects/custodian/venv/bin/custodian", line 8, in <module>
    sys.exit(main())
  File "/Users/kevinkessels/Projects/custodian/venv/lib/python3.8/site-packages/c7n/cli.py", line 352, in main
    command(config)
  File "/Users/kevinkessels/Projects/custodian/venv/lib/python3.8/site-packages/c7n/commands.py", line 124, in _load_policies
    p.validate()
  File "/Users/kevinkessels/Projects/custodian/venv/lib/python3.8/site-packages/c7n/policy.py", line 1046, in validate
    self.conditions.validate()
  File "/Users/kevinkessels/Projects/custodian/venv/lib/python3.8/site-packages/c7n/policy.py", line 929, in validate
    self.filters = self.filter_registry.parse(self.filters, self)
  File "/Users/kevinkessels/Projects/custodian/venv/lib/python3.8/site-packages/c7n/filters/core.py", line 122, in parse
    results.append(self.factory(d, manager))
  File "/Users/kevinkessels/Projects/custodian/venv/lib/python3.8/site-packages/c7n/filters/core.py", line 146, in factory
    filter_type = data.get('type')
AttributeError: 'ValueFilter' object has no attribute 'get'
```

 - `custodian version --debug` output

```
Custodian:   0.9.6
Python:      3.8.5 (default, Jul 21 2020, 10:48:26)
             [Clang 11.0.3 (clang-1103.0.32.62)]
Platform:    posix.uname_result(sysname='Darwin', nodename='M22252.fritz.box', release='19.6.0', version='Darwin Kernel Version 19.6.0: Mon Aug 31 22:12:52 PDT 2020; root:xnu-6153.141.2~1/RELEASE_X86_64', machine='x86_64')
Using venv:  True
Docker: False
Installed:

argcomplete==1.12.1
attrs==20.2.0
boto3==1.15.12
botocore==1.18.12
c7n==0.9.6
cachetools==4.1.1
certifi==2020.6.20
chardet==3.0.4
docutils==0.15.2
google-api-core==1.22.2
google-api-python-client==1.12.3
google-auth==1.21.2
google-auth-httplib2==0.0.4
google-cloud-core==1.4.1
google-cloud-logging==1.15.1
google-cloud-monitoring==0.34.0
google-cloud-storage==1.31.0
google-crc32c==1.0.0
google-resumable-media==1.0.0
googleapis-common-protos==1.52.0
httplib2==0.18.1
idna==2.10
importlib-metadata==1.7.0
jmespath==0.10.0
jsonschema==3.2.0
protobuf==3.13.0
pyasn1==0.4.8
pyasn1-modules==0.2.8
pyrsistent==0.16.1
python-dateutil==2.8.1
pytz==2020.1
pyyaml==5.3.1
ratelimiter==1.2.0.post0
requests==2.24.0
retrying==1.3.3
rsa==4.6
s3transfer==0.3.3
setuptools==50.0.0
six==1.15.0
tabulate==0.8.7
uritemplate==3.0.1
urllib3==1.25.10
zipp==3.3.0
```

Note that validating the policy with `custodian validate` succeeds.

Discussion:
kapilt: would like to see a cli test here

Patch:
diff --git a/c7n/policy.py b/c7n/policy.py
index c0baaa1a7..40d40ea62 100644
--- a/c7n/policy.py
+++ b/c7n/policy.py
@@ -927,10 +927,13 @@ class PolicyConditions:
         self.session_factory = rm.session_factory
         # used by c7n-org to extend evaluation conditions
         self.env_vars = {}
+        self.initialized = False
 
     def validate(self):
-        self.filters.extend(self.convert_deprecated())
-        self.filters = self.filter_registry.parse(self.filters, self)
+        if not self.initialized:
+            self.filters.extend(self.convert_deprecated())
+            self.filters = self.filter_registry.parse(self.filters, self)
+            self.initialized = True
 
     def evaluate(self, event=None):
         policy_vars = dict(self.env_vars)
diff --git a/c7n/resources/mq.py b/c7n/resources/mq.py
index 6df25f9d7..4b24f312c 100644
--- a/c7n/resources/mq.py
+++ b/c7n/resources/mq.py
@@ -7,7 +7,7 @@ from c7n.filters.vpc import SecurityGroupFilter, SubnetFilter
 from c7n.manager import resources
 from c7n.query import QueryResourceManager, TypeInfo
 from c7n.utils import local_session, type_schema
-from c7n.tags import RemoveTag, Tag, TagDelayedAction, TagActionFilter
+from c7n.tags import RemoveTag, Tag, TagDelayedAction, TagActionFilter, universal_augment
 
 
 @resources.register('message-broker')
@@ -157,3 +157,19 @@ class MarkForOpMessageBroker(TagDelayedAction):
                     op: delete
                     days: 7
     """
+
+
+@resources.register('message-config')
+class MessageConfig(QueryResourceManager):
+
+    class resource_type(TypeInfo):
+        service = 'mq'
+        enum_spec = ('list_configurations', 'Configurations', None)
+        cfn_type = 'AWS::AmazonMQ::Configuration'
+        id = 'Id'
+        arn = 'Arn'
+        arn_type = 'configuration'
+        name = 'Name'
+        universal_taggable = object()
+
+    augment = universal_augment
diff --git a/c7n/resources/resource_map.py b/c7n/resources/resource_map.py
index 74b8b7c56..a39c253f1 100644
--- a/c7n/resources/resource_map.py
+++ b/c7n/resources/resource_map.py
@@ -114,6 +114,7 @@ ResourceMap = {
     "aws.lightsail-instance": "c7n.resources.lightsail.Instance",
     "aws.log-group": "c7n.resources.cw.LogGroup",
     "aws.message-broker": "c7n.resources.mq.MessageBroker",
+    "aws.message-config": "c7n.resources.mq.MessageConfig",
     "aws.ml-model": "c7n.resources.ml.MLModel",
     "aws.nat-gateway": "c7n.resources.vpc.NATGateway",
     "aws.network-acl": "c7n.resources.vpc.NetworkAcl",


Test patch:
diff --git a/tests/data/placebo/test_mq_config_tagging/mq.ListConfigurations_1.json b/tests/data/placebo/test_mq_config_tagging/mq.ListConfigurations_1.json
new file mode 100644
index 000000000..b32569dd2
--- /dev/null
+++ b/tests/data/placebo/test_mq_config_tagging/mq.ListConfigurations_1.json
@@ -0,0 +1,15 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "Configurations": [
+            {
+                "Arn": "arn:aws:mq:us-east-1:644160558196:configuration:c-1cd76ad8-81bc-46f6-b43f-56fb118b426c",
+                "EngineType": "ActiveMQ",
+                "EngineVersion": "5.15.12",
+                "Id": "c-1cd76ad8-81bc-46f6-b43f-56fb118b426c",
+                "Name": "test-config"
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_mq_config_tagging/mq.ListTags_1.json b/tests/data/placebo/test_mq_config_tagging/mq.ListTags_1.json
new file mode 100644
index 000000000..0c7b233ed
--- /dev/null
+++ b/tests/data/placebo/test_mq_config_tagging/mq.ListTags_1.json
@@ -0,0 +1,9 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "Tags": {
+            "Env": "Dev"
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_mq_config_tagging/tagging.GetResources_1.json b/tests/data/placebo/test_mq_config_tagging/tagging.GetResources_1.json
new file mode 100644
index 000000000..d6743bbbc
--- /dev/null
+++ b/tests/data/placebo/test_mq_config_tagging/tagging.GetResources_1.json
@@ -0,0 +1,18 @@
+{
+    "status_code": 200,
+    "data": {
+        "PaginationToken": "",
+        "ResourceTagMappingList": [
+            {
+                "ResourceARN": "arn:aws:mq:us-east-1:644160558196:configuration:c-1cd76ad8-81bc-46f6-b43f-56fb118b426c",
+                "Tags": [
+                    {
+                        "Key": "Role",
+                        "Value": "Dev"
+                    }
+                ]
+            }
+        ],
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_mq_config_tagging/tagging.TagResources_1.json b/tests/data/placebo/test_mq_config_tagging/tagging.TagResources_1.json
new file mode 100644
index 000000000..bd2dead85
--- /dev/null
+++ b/tests/data/placebo/test_mq_config_tagging/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_mq_config_tagging/tagging.UntagResources_1.json b/tests/data/placebo/test_mq_config_tagging/tagging.UntagResources_1.json
new file mode 100644
index 000000000..bd2dead85
--- /dev/null
+++ b/tests/data/placebo/test_mq_config_tagging/tagging.UntagResources_1.json
@@ -0,0 +1,7 @@
+{
+    "status_code": 200,
+    "data": {
+        "FailedResourcesMap": {},
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/test_mq.py b/tests/test_mq.py
index 9bd8cb33b..c03c09768 100644
--- a/tests/test_mq.py
+++ b/tests/test_mq.py
@@ -96,3 +96,31 @@ class MessageQueue(BaseTest):
             tags,
             {'Env': 'Dev',
              'maid_status': 'Resource does not meet policy: delete@2019/01/31'})
+
+    def test_mq_config_tagging(self):
+        factory = self.replay_flight_data("test_mq_config_tagging")
+        p = self.load_policy(
+            {
+                "name": "mark-unused-mq-delete",
+                "resource": "message-config",
+                'filters': [{'tag:Role': 'Dev'}],
+                "actions": [
+                    {'type': 'tag',
+                     'tags': {'Env': 'Dev'}},
+                    {'type': 'remove-tag',
+                     'tags': ['Role']}]},
+            config={'region': 'us-east-1'},
+            session_factory=factory,
+        )
+        resources = p.run()
+        self.assertTrue(len(resources), 1)
+        client = factory().client("mq")
+        if self.recording:
+            time.sleep(1)
+        tags = client.list_tags(ResourceArn=resources[0]["Arn"])["Tags"]
+        self.assertEqual(
+            {t['Key']: t['Value'] for t in resources[0]['Tags']},
+            {'Role': 'Dev'})
+        self.assertEqual(
+            tags,
+            {'Env': 'Dev'})