We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
`EnableVersionUpgrade` Update Policy Not Recognized
*cfn-lint version: (`cfn-lint --version`)* 0.25.5

*Description of issue:*

cfn-lint does not understand `AWS::Elasticsearch::Domain`'s new `UpdatePolicy` of `EnableVersionUpgrade`. This key accepts a Boolean value.

> If `EnableVersionUpgrade` is set to true, you can update the `ElasticsearchVersion` property of the `AWS::Elasticsearch::Domain` resource, and CloudFormation will update that property without interruption. When `EnableVersionUpgrade` is set to `false`, or not specified, updating the `ElasticsearchVersion` property results in CloudFormation replacing the entire `AWS::Elasticsearch::Domain` resource.

I have a patch for this ready to go, and the PR should be created in a couple of minutes.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/cfnlint/rules/resources/updatepolicy/Configuration.py`
Content:
```
1 """
2 Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 SPDX-License-Identifier: MIT-0
4 """
5 import six
6 from cfnlint.rules import CloudFormationLintRule
7 from cfnlint.rules import RuleMatch
8 
9 
10 class Configuration(CloudFormationLintRule):
11     """Check Update Policy Configuration"""
12     id = 'E3016'
13     shortdesc = 'Check the configuration of a resources UpdatePolicy'
14     description = 'Make sure a resources UpdatePolicy is properly configured'
15     source_url = 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-updatepolicy.html'
16     tags = ['resources', 'updatepolicy']
17     valid_attributes = {
18         'sub': {
19             'AutoScalingReplacingUpdate': {
20                 'WillReplace': {
21                     'PrimitiveType': 'Boolean'
22                 }
23             },
24             'AutoScalingRollingUpdate': {
25                 'MaxBatchSize': {
26                     'PrimitiveType': 'Integer'
27                 },
28                 'MinInstancesInService': {
29                     'PrimitiveType': 'Integer'
30                 },
31                 'MinSuccessfulInstancesPercent': {
32                     'PrimitiveType': 'Integer'
33                 },
34                 'PauseTime': {
35                     'PrimitiveType': 'String'
36                 },
37                 'SuspendProcesses': {
38                     'PrimitiveType': 'List',
39                     'ValidValues': [
40                         'Launch', 'Terminate', 'HealthCheck',
41                         'ReplaceUnhealthy', 'AZRebalance', 'AlarmNotification',
42                         'ScheduledActions', 'AddToLoadBalancer'
43                     ]
44                 },
45                 'WaitOnResourceSignals': {
46                     'PrimitiveType': 'Boolean'
47                 }
48             },
49             'AutoScalingScheduledAction': {
50                 'IgnoreUnmodifiedGroupSizeProperties': {
51                     'PrimitiveType': 'Boolean'
52                 }
53             },
54             'CodeDeployLambdaAliasUpdate': {
55                 'AfterAllowTrafficHook': {
56                     'PrimitiveType': 'String'
57                 },
58                 'ApplicationName': {
59                     'PrimitiveType': 'String'
60                 },
61                 'BeforeAllowTrafficHook': {
62                     'PrimitiveType': 'String'
63                 },
64                 'DeploymentGroupName': {
65                     'PrimitiveType': 'String'
66                 },
67             }
68         },
69         'main': {
70             'AutoScalingReplacingUpdate': {
71                 'Type': 'AutoScalingReplacingUpdate',
72                 'ResourceTypes': [
73                     'AWS::AutoScaling::AutoScalingGroup'
74                 ]
75             },
76             'AutoScalingRollingUpdate': {
77                 'Type': 'AutoScalingRollingUpdate',
78                 'ResourceTypes': [
79                     'AWS::AutoScaling::AutoScalingGroup'
80                 ]
81             },
82             'AutoScalingScheduledAction': {
83                 'Type': 'AutoScalingScheduledAction',
84                 'ResourceTypes': [
85                     'AWS::AutoScaling::AutoScalingGroup'
86                 ]
87             },
88             'CodeDeployLambdaAliasUpdate': {
89                 'Type': 'CodeDeployLambdaAliasUpdate',
90                 'ResourceTypes': [
91                     'AWS::Lambda::Alias'
92                 ]
93             },
94             'UseOnlineResharding': {
95                 'PrimitiveType': 'Boolean',
96                 'ResourceTypes': [
97                     'AWS::ElastiCache::ReplicationGroup'
98                 ]
99             }
100         },
101         'primitive_types': {
102             'String': six.string_types,
103             'Integer': int,
104             'Boolean': bool,
105             'List': list
106         }
107     }
108 
109     def check_value(self, value, path, **kwargs):
110         """ Check a primitive value """
111         matches = []
112 
113         prim_type = kwargs.get('primitive_type')
114         if prim_type == 'List':
115             valid_values = kwargs.get('valid_values')
116             if valid_values:
117                 if value not in valid_values:
118                     message = 'Allowed values for {0} are ({1})'
119                     matches.append(
120                         RuleMatch(path, message.format(kwargs.get('key_name'), ', '.join(map(str, valid_values)))))
121         else:
122             default_message = 'Value for {0} must be of type {1}'
123             if not isinstance(value, self.valid_attributes.get('primitive_types').get(prim_type)):
124                 matches.append(
125                     RuleMatch(path, default_message.format(kwargs.get('key_name'), prim_type)))
126 
127         return matches
128 
129     def check_attributes(self, cfn, properties, spec_type, path):
130         """
131             Check the properties against the spec
132         """
133         matches = []
134         spec = self.valid_attributes.get('sub').get(spec_type)
135         if isinstance(properties, dict):
136             for p_value_safe, p_path_safe in properties.items_safe(path):
137                 for p_name, p_value in p_value_safe.items():
138                     if p_name in spec:
139                         up_type_spec = spec.get(p_name)
140                         if 'Type' in up_type_spec:
141                             matches.extend(
142                                 self.check_attributes(
143                                     cfn, p_value, up_type_spec.get('Type'), p_path_safe[:] + [p_name]))
144                         else:
145                             matches.extend(
146                                 cfn.check_value(
147                                     obj={p_name: p_value}, key=p_name, path=p_path_safe[:],
148                                     check_value=self.check_value,
149                                     valid_values=up_type_spec.get('ValidValues', []),
150                                     primitive_type=up_type_spec.get('PrimitiveType'),
151                                     key_name=p_name
152                                 )
153                             )
154                     else:
155                         message = 'UpdatePolicy doesn\'t support type {0}'
156                         matches.append(
157                             RuleMatch(path[:] + [p_name], message.format(p_name)))
158         else:
159             message = '{0} should be an object'
160             matches.append(
161                 RuleMatch(path, message.format(path[-1])))
162 
163         return matches
164 
165     def check_update_policy(self, cfn, update_policy, path, resource_type):
166         """Check an update policy"""
167         matches = []
168         for up_type, up_value in update_policy.items():
169             up_path = path[:] + [up_type]
170             up_type_spec = self.valid_attributes.get('main').get(up_type)
171             if up_type_spec:
172                 if resource_type not in up_type_spec.get('ResourceTypes'):
173                     message = 'UpdatePolicy only supports this type for resources of type ({0})'
174                     matches.append(
175                         RuleMatch(up_path, message.format(', '.join(map(str, up_type_spec.get('ResourceTypes'))))))
176                 if 'Type' in up_type_spec:
177                     matches.extend(
178                         self.check_attributes(
179                             cfn, up_value, up_type_spec.get('Type'), up_path[:]))
180 
181                 else:
182                     matches.extend(
183                         cfn.check_value(
184                             obj={up_type: up_value}, key=up_type, path=up_path[:],
185                             check_value=self.check_value,
186                             valid_values=up_type_spec.get('ValidValues', []),
187                             primitive_type=up_type_spec.get('PrimitiveType'),
188                             key_name=up_type
189                         )
190                     )
191             else:
192                 message = 'UpdatePolicy doesn\'t support type {0}'
193                 matches.append(
194                     RuleMatch(up_path, message.format(up_type)))
195 
196         return matches
197 
198     def match(self, cfn):
199         """Check CloudFormation Resources"""
200 
201         matches = []
202 
203         for r_name, r_values in cfn.get_resources().items():
204             update_policy = r_values.get('UpdatePolicy')
205             if update_policy is None:
206                 continue
207             resource_type = r_values.get('Type')
208             if isinstance(update_policy, dict):
209                 path = ['Resources', r_name, 'UpdatePolicy']
210                 for up_value_safe, up_path_safe in update_policy.items_safe(path):
211                     matches.extend(self.check_update_policy(
212                         cfn, up_value_safe, up_path_safe, resource_type))
213             else:
214                 message = 'UpdatePolicy should be an object'
215                 matches.append(
216                     RuleMatch(['Resources', r_name, 'UpdatePolicy'], message.format()))
217 
218         return matches
219
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/cfnlint/rules/resources/updatepolicy/Configuration.py b/src/cfnlint/rules/resources/updatepolicy/Configuration.py
--- a/src/cfnlint/rules/resources/updatepolicy/Configuration.py
+++ b/src/cfnlint/rules/resources/updatepolicy/Configuration.py
@@ -91,6 +91,12 @@
                     'AWS::Lambda::Alias'
                 ]
             },
+            'EnableVersionUpgrade': {
+                'PrimitiveType': 'Boolean',
+                'ResourceTypes': [
+                    'AWS::Elasticsearch::Domain'
+                ]
+            },
             'UseOnlineResharding': {
                 'PrimitiveType': 'Boolean',
                 'ResourceTypes': [

{"golden_diff": "diff --git a/src/cfnlint/rules/resources/updatepolicy/Configuration.py b/src/cfnlint/rules/resources/updatepolicy/Configuration.py\n--- a/src/cfnlint/rules/resources/updatepolicy/Configuration.py\n+++ b/src/cfnlint/rules/resources/updatepolicy/Configuration.py\n@@ -91,6 +91,12 @@\n                     'AWS::Lambda::Alias'\n                 ]\n             },\n+            'EnableVersionUpgrade': {\n+                'PrimitiveType': 'Boolean',\n+                'ResourceTypes': [\n+                    'AWS::Elasticsearch::Domain'\n+                ]\n+            },\n             'UseOnlineResharding': {\n                 'PrimitiveType': 'Boolean',\n                 'ResourceTypes': [\n", "issue": "`EnableVersionUpgrade` Update Policy Not Recognized\n*cfn-lint version: (`cfn-lint --version`)* 0.25.5\r\n\r\n*Description of issue:*\r\n\r\ncfn-lint does not understand `AWS::Elasticsearch::Domain`'s new `UpdatePolicy` of `EnableVersionUpgrade`. This key accepts a Boolean value.\r\n\r\n> If `EnableVersionUpgrade` is set to true, you can update the `ElasticsearchVersion` property of the `AWS::Elasticsearch::Domain` resource, and CloudFormation will update that property without interruption. When `EnableVersionUpgrade` is set to `false`, or not specified, updating the `ElasticsearchVersion` property results in CloudFormation replacing the entire `AWS::Elasticsearch::Domain` resource.\r\n\r\nI have a patch for this ready to go, and the PR should be created in a couple of minutes.\r\n\n", "before_files": [{"content": "\"\"\"\nCopyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.\nSPDX-License-Identifier: MIT-0\n\"\"\"\nimport six\nfrom cfnlint.rules import CloudFormationLintRule\nfrom cfnlint.rules import RuleMatch\n\n\nclass Configuration(CloudFormationLintRule):\n    \"\"\"Check Update Policy Configuration\"\"\"\n    id = 'E3016'\n    shortdesc = 'Check the configuration of a resources UpdatePolicy'\n    description = 'Make sure a resources UpdatePolicy is properly configured'\n    source_url = 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-updatepolicy.html'\n    tags = ['resources', 'updatepolicy']\n    valid_attributes = {\n        'sub': {\n            'AutoScalingReplacingUpdate': {\n                'WillReplace': {\n                    'PrimitiveType': 'Boolean'\n                }\n            },\n            'AutoScalingRollingUpdate': {\n                'MaxBatchSize': {\n                    'PrimitiveType': 'Integer'\n                },\n                'MinInstancesInService': {\n                    'PrimitiveType': 'Integer'\n                },\n                'MinSuccessfulInstancesPercent': {\n                    'PrimitiveType': 'Integer'\n                },\n                'PauseTime': {\n                    'PrimitiveType': 'String'\n                },\n                'SuspendProcesses': {\n                    'PrimitiveType': 'List',\n                    'ValidValues': [\n                        'Launch', 'Terminate', 'HealthCheck',\n                        'ReplaceUnhealthy', 'AZRebalance', 'AlarmNotification',\n                        'ScheduledActions', 'AddToLoadBalancer'\n                    ]\n                },\n                'WaitOnResourceSignals': {\n                    'PrimitiveType': 'Boolean'\n                }\n            },\n            'AutoScalingScheduledAction': {\n                'IgnoreUnmodifiedGroupSizeProperties': {\n                    'PrimitiveType': 'Boolean'\n                }\n            },\n            'CodeDeployLambdaAliasUpdate': {\n                'AfterAllowTrafficHook': {\n                    'PrimitiveType': 'String'\n                },\n                'ApplicationName': {\n                    'PrimitiveType': 'String'\n                },\n                'BeforeAllowTrafficHook': {\n                    'PrimitiveType': 'String'\n                },\n                'DeploymentGroupName': {\n                    'PrimitiveType': 'String'\n                },\n            }\n        },\n        'main': {\n            'AutoScalingReplacingUpdate': {\n                'Type': 'AutoScalingReplacingUpdate',\n                'ResourceTypes': [\n                    'AWS::AutoScaling::AutoScalingGroup'\n                ]\n            },\n            'AutoScalingRollingUpdate': {\n                'Type': 'AutoScalingRollingUpdate',\n                'ResourceTypes': [\n                    'AWS::AutoScaling::AutoScalingGroup'\n                ]\n            },\n            'AutoScalingScheduledAction': {\n                'Type': 'AutoScalingScheduledAction',\n                'ResourceTypes': [\n                    'AWS::AutoScaling::AutoScalingGroup'\n                ]\n            },\n            'CodeDeployLambdaAliasUpdate': {\n                'Type': 'CodeDeployLambdaAliasUpdate',\n                'ResourceTypes': [\n                    'AWS::Lambda::Alias'\n                ]\n            },\n            'UseOnlineResharding': {\n                'PrimitiveType': 'Boolean',\n                'ResourceTypes': [\n                    'AWS::ElastiCache::ReplicationGroup'\n                ]\n            }\n        },\n        'primitive_types': {\n            'String': six.string_types,\n            'Integer': int,\n            'Boolean': bool,\n            'List': list\n        }\n    }\n\n    def check_value(self, value, path, **kwargs):\n        \"\"\" Check a primitive value \"\"\"\n        matches = []\n\n        prim_type = kwargs.get('primitive_type')\n        if prim_type == 'List':\n            valid_values = kwargs.get('valid_values')\n            if valid_values:\n                if value not in valid_values:\n                    message = 'Allowed values for {0} are ({1})'\n                    matches.append(\n                        RuleMatch(path, message.format(kwargs.get('key_name'), ', '.join(map(str, valid_values)))))\n        else:\n            default_message = 'Value for {0} must be of type {1}'\n            if not isinstance(value, self.valid_attributes.get('primitive_types').get(prim_type)):\n                matches.append(\n                    RuleMatch(path, default_message.format(kwargs.get('key_name'), prim_type)))\n\n        return matches\n\n    def check_attributes(self, cfn, properties, spec_type, path):\n        \"\"\"\n            Check the properties against the spec\n        \"\"\"\n        matches = []\n        spec = self.valid_attributes.get('sub').get(spec_type)\n        if isinstance(properties, dict):\n            for p_value_safe, p_path_safe in properties.items_safe(path):\n                for p_name, p_value in p_value_safe.items():\n                    if p_name in spec:\n                        up_type_spec = spec.get(p_name)\n                        if 'Type' in up_type_spec:\n                            matches.extend(\n                                self.check_attributes(\n                                    cfn, p_value, up_type_spec.get('Type'), p_path_safe[:] + [p_name]))\n                        else:\n                            matches.extend(\n                                cfn.check_value(\n                                    obj={p_name: p_value}, key=p_name, path=p_path_safe[:],\n                                    check_value=self.check_value,\n                                    valid_values=up_type_spec.get('ValidValues', []),\n                                    primitive_type=up_type_spec.get('PrimitiveType'),\n                                    key_name=p_name\n                                )\n                            )\n                    else:\n                        message = 'UpdatePolicy doesn\\'t support type {0}'\n                        matches.append(\n                            RuleMatch(path[:] + [p_name], message.format(p_name)))\n        else:\n            message = '{0} should be an object'\n            matches.append(\n                RuleMatch(path, message.format(path[-1])))\n\n        return matches\n\n    def check_update_policy(self, cfn, update_policy, path, resource_type):\n        \"\"\"Check an update policy\"\"\"\n        matches = []\n        for up_type, up_value in update_policy.items():\n            up_path = path[:] + [up_type]\n            up_type_spec = self.valid_attributes.get('main').get(up_type)\n            if up_type_spec:\n                if resource_type not in up_type_spec.get('ResourceTypes'):\n                    message = 'UpdatePolicy only supports this type for resources of type ({0})'\n                    matches.append(\n                        RuleMatch(up_path, message.format(', '.join(map(str, up_type_spec.get('ResourceTypes'))))))\n                if 'Type' in up_type_spec:\n                    matches.extend(\n                        self.check_attributes(\n                            cfn, up_value, up_type_spec.get('Type'), up_path[:]))\n\n                else:\n                    matches.extend(\n                        cfn.check_value(\n                            obj={up_type: up_value}, key=up_type, path=up_path[:],\n                            check_value=self.check_value,\n                            valid_values=up_type_spec.get('ValidValues', []),\n                            primitive_type=up_type_spec.get('PrimitiveType'),\n                            key_name=up_type\n                        )\n                    )\n            else:\n                message = 'UpdatePolicy doesn\\'t support type {0}'\n                matches.append(\n                    RuleMatch(up_path, message.format(up_type)))\n\n        return matches\n\n    def match(self, cfn):\n        \"\"\"Check CloudFormation Resources\"\"\"\n\n        matches = []\n\n        for r_name, r_values in cfn.get_resources().items():\n            update_policy = r_values.get('UpdatePolicy')\n            if update_policy is None:\n                continue\n            resource_type = r_values.get('Type')\n            if isinstance(update_policy, dict):\n                path = ['Resources', r_name, 'UpdatePolicy']\n                for up_value_safe, up_path_safe in update_policy.items_safe(path):\n                    matches.extend(self.check_update_policy(\n                        cfn, up_value_safe, up_path_safe, resource_type))\n            else:\n                message = 'UpdatePolicy should be an object'\n                matches.append(\n                    RuleMatch(['Resources', r_name, 'UpdatePolicy'], message.format()))\n\n        return matches\n", "path": "src/cfnlint/rules/resources/updatepolicy/Configuration.py"}], "after_files": [{"content": "\"\"\"\nCopyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.\nSPDX-License-Identifier: MIT-0\n\"\"\"\nimport six\nfrom cfnlint.rules import CloudFormationLintRule\nfrom cfnlint.rules import RuleMatch\n\n\nclass Configuration(CloudFormationLintRule):\n    \"\"\"Check Update Policy Configuration\"\"\"\n    id = 'E3016'\n    shortdesc = 'Check the configuration of a resources UpdatePolicy'\n    description = 'Make sure a resources UpdatePolicy is properly configured'\n    source_url = 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-updatepolicy.html'\n    tags = ['resources', 'updatepolicy']\n    valid_attributes = {\n        'sub': {\n            'AutoScalingReplacingUpdate': {\n                'WillReplace': {\n                    'PrimitiveType': 'Boolean'\n                }\n            },\n            'AutoScalingRollingUpdate': {\n                'MaxBatchSize': {\n                    'PrimitiveType': 'Integer'\n                },\n                'MinInstancesInService': {\n                    'PrimitiveType': 'Integer'\n                },\n                'MinSuccessfulInstancesPercent': {\n                    'PrimitiveType': 'Integer'\n                },\n                'PauseTime': {\n                    'PrimitiveType': 'String'\n                },\n                'SuspendProcesses': {\n                    'PrimitiveType': 'List',\n                    'ValidValues': [\n                        'Launch', 'Terminate', 'HealthCheck',\n                        'ReplaceUnhealthy', 'AZRebalance', 'AlarmNotification',\n                        'ScheduledActions', 'AddToLoadBalancer'\n                    ]\n                },\n                'WaitOnResourceSignals': {\n                    'PrimitiveType': 'Boolean'\n                }\n            },\n            'AutoScalingScheduledAction': {\n                'IgnoreUnmodifiedGroupSizeProperties': {\n                    'PrimitiveType': 'Boolean'\n                }\n            },\n            'CodeDeployLambdaAliasUpdate': {\n                'AfterAllowTrafficHook': {\n                    'PrimitiveType': 'String'\n                },\n                'ApplicationName': {\n                    'PrimitiveType': 'String'\n                },\n                'BeforeAllowTrafficHook': {\n                    'PrimitiveType': 'String'\n                },\n                'DeploymentGroupName': {\n                    'PrimitiveType': 'String'\n                },\n            }\n        },\n        'main': {\n            'AutoScalingReplacingUpdate': {\n                'Type': 'AutoScalingReplacingUpdate',\n                'ResourceTypes': [\n                    'AWS::AutoScaling::AutoScalingGroup'\n                ]\n            },\n            'AutoScalingRollingUpdate': {\n                'Type': 'AutoScalingRollingUpdate',\n                'ResourceTypes': [\n                    'AWS::AutoScaling::AutoScalingGroup'\n                ]\n            },\n            'AutoScalingScheduledAction': {\n                'Type': 'AutoScalingScheduledAction',\n                'ResourceTypes': [\n                    'AWS::AutoScaling::AutoScalingGroup'\n                ]\n            },\n            'CodeDeployLambdaAliasUpdate': {\n                'Type': 'CodeDeployLambdaAliasUpdate',\n                'ResourceTypes': [\n                    'AWS::Lambda::Alias'\n                ]\n            },\n            'EnableVersionUpgrade': {\n                'PrimitiveType': 'Boolean',\n                'ResourceTypes': [\n                    'AWS::Elasticsearch::Domain'\n                ]\n            },\n            'UseOnlineResharding': {\n                'PrimitiveType': 'Boolean',\n                'ResourceTypes': [\n                    'AWS::ElastiCache::ReplicationGroup'\n                ]\n            }\n        },\n        'primitive_types': {\n            'String': six.string_types,\n            'Integer': int,\n            'Boolean': bool,\n            'List': list\n        }\n    }\n\n    def check_value(self, value, path, **kwargs):\n        \"\"\" Check a primitive value \"\"\"\n        matches = []\n\n        prim_type = kwargs.get('primitive_type')\n        if prim_type == 'List':\n            valid_values = kwargs.get('valid_values')\n            if valid_values:\n                if value not in valid_values:\n                    message = 'Allowed values for {0} are ({1})'\n                    matches.append(\n                        RuleMatch(path, message.format(kwargs.get('key_name'), ', '.join(map(str, valid_values)))))\n        else:\n            default_message = 'Value for {0} must be of type {1}'\n            if not isinstance(value, self.valid_attributes.get('primitive_types').get(prim_type)):\n                matches.append(\n                    RuleMatch(path, default_message.format(kwargs.get('key_name'), prim_type)))\n\n        return matches\n\n    def check_attributes(self, cfn, properties, spec_type, path):\n        \"\"\"\n            Check the properties against the spec\n        \"\"\"\n        matches = []\n        spec = self.valid_attributes.get('sub').get(spec_type)\n        if isinstance(properties, dict):\n            for p_value_safe, p_path_safe in properties.items_safe(path):\n                for p_name, p_value in p_value_safe.items():\n                    if p_name in spec:\n                        up_type_spec = spec.get(p_name)\n                        if 'Type' in up_type_spec:\n                            matches.extend(\n                                self.check_attributes(\n                                    cfn, p_value, up_type_spec.get('Type'), p_path_safe[:] + [p_name]))\n                        else:\n                            matches.extend(\n                                cfn.check_value(\n                                    obj={p_name: p_value}, key=p_name, path=p_path_safe[:],\n                                    check_value=self.check_value,\n                                    valid_values=up_type_spec.get('ValidValues', []),\n                                    primitive_type=up_type_spec.get('PrimitiveType'),\n                                    key_name=p_name\n                                )\n                            )\n                    else:\n                        message = 'UpdatePolicy doesn\\'t support type {0}'\n                        matches.append(\n                            RuleMatch(path[:] + [p_name], message.format(p_name)))\n        else:\n            message = '{0} should be an object'\n            matches.append(\n                RuleMatch(path, message.format(path[-1])))\n\n        return matches\n\n    def check_update_policy(self, cfn, update_policy, path, resource_type):\n        \"\"\"Check an update policy\"\"\"\n        matches = []\n        for up_type, up_value in update_policy.items():\n            up_path = path[:] + [up_type]\n            up_type_spec = self.valid_attributes.get('main').get(up_type)\n            if up_type_spec:\n                if resource_type not in up_type_spec.get('ResourceTypes'):\n                    message = 'UpdatePolicy only supports this type for resources of type ({0})'\n                    matches.append(\n                        RuleMatch(up_path, message.format(', '.join(map(str, up_type_spec.get('ResourceTypes'))))))\n                if 'Type' in up_type_spec:\n                    matches.extend(\n                        self.check_attributes(\n                            cfn, up_value, up_type_spec.get('Type'), up_path[:]))\n\n                else:\n                    matches.extend(\n                        cfn.check_value(\n                            obj={up_type: up_value}, key=up_type, path=up_path[:],\n                            check_value=self.check_value,\n                            valid_values=up_type_spec.get('ValidValues', []),\n                            primitive_type=up_type_spec.get('PrimitiveType'),\n                            key_name=up_type\n                        )\n                    )\n            else:\n                message = 'UpdatePolicy doesn\\'t support type {0}'\n                matches.append(\n                    RuleMatch(up_path, message.format(up_type)))\n\n        return matches\n\n    def match(self, cfn):\n        \"\"\"Check CloudFormation Resources\"\"\"\n\n        matches = []\n\n        for r_name, r_values in cfn.get_resources().items():\n            update_policy = r_values.get('UpdatePolicy')\n            if update_policy is None:\n                continue\n            resource_type = r_values.get('Type')\n            if isinstance(update_policy, dict):\n                path = ['Resources', r_name, 'UpdatePolicy']\n                for up_value_safe, up_path_safe in update_policy.items_safe(path):\n                    matches.extend(self.check_update_policy(\n                        cfn, up_value_safe, up_path_safe, resource_type))\n            else:\n                message = 'UpdatePolicy should be an object'\n                matches.append(\n                    RuleMatch(['Resources', r_name, 'UpdatePolicy'], message.format()))\n\n        return matches\n", "path": "src/cfnlint/rules/resources/updatepolicy/Configuration.py"}]}