1"""
2Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3SPDX-License-Identifier: MIT-0
4"""
5import six
6from cfnlint.rules import CloudFormationLintRule
7from cfnlint.rules import RuleMatch
8
9
10class Configuration(CloudFormationLintRule):
11    """Check if Mappings are configured correctly"""
12    id = 'E7001'
13    shortdesc = 'Mappings are appropriately configured'
14    description = 'Check if Mappings are properly configured'
15    source_url = 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html'
16    tags = ['mappings']
17
18    def match(self, cfn):
19        matches = []
20
21        valid_map_types = (six.string_types, list, six.integer_types, float)
22
23        mappings = cfn.template.get('Mappings', {})
24        if mappings:
25            for mapname, mapobj in mappings.items():
26                if not isinstance(mapobj, dict):
27                    message = 'Mapping {0} has invalid property'
28                    matches.append(RuleMatch(
29                        ['Mappings', mapname],
30                        message.format(mapname)
31                    ))
32                else:
33                    for firstkey in mapobj:
34                        firstkeyobj = mapobj[firstkey]
35                        if not isinstance(firstkeyobj, dict):
36                            message = 'Mapping {0} has invalid property at {1}'
37                            matches.append(RuleMatch(
38                                ['Mappings', mapname, firstkey],
39                                message.format(mapname, firstkeyobj)
40                            ))
41                        else:
42                            for secondkey in firstkeyobj:
43                                if not isinstance(
44                                        firstkeyobj[secondkey], valid_map_types):
45                                    message = 'Mapping {0} has invalid property at {1}'
46                                    matches.append(RuleMatch(
47                                        ['Mappings', mapname, firstkey, secondkey],
48                                        message.format(mapname, secondkey)
49                                    ))
50
51        return matches
52