def test_get_directives(self): """ Test getting directives from a template """ template_yaml = { 'Resources': { 'Type': 'AWS::S3::Bucket', 'myBucket': { 'Properties': { 'BucketName': "bucket_test" }, 'Type': 'AWS::S3::Bucket' }, 'myBucket1': { 'Metadata': { 'cfn-lint': { 'config': { 'ignore_checks': [ 'E3012', 'I1001' ] } } }, 'Properties': {}, 'Type': 'AWS::S3::Bucket' }, 'myBucket2': { 'Metadata': { 'cfn-lint': { 'config': { 'ignore_checks': [ 'E3012', ] } } }, 'Properties': {}, 'Type': 'AWS::S3::Bucket' } } } template = Template( 'test.yaml', cfnlint.decode.cfn_yaml.loads( json.dumps( template_yaml, sort_keys=True, indent=4, separators=(',', ': ') ) ) ) directives = template.get_directives() expected_result = { 'E3012': [ {'end': (23, 10), 'start': (10, 9)}, {'end': (36, 10), 'start': (24, 9)} ], 'I1001': [ {'end': (23, 10), 'start': (10, 9)} ] } self.assertEqual(len(expected_result), len(directives)) for key, items in directives.items(): self.assertIn(key, expected_result) if key in expected_result: self.assertEqualListOfDicts(items, expected_result.get(key))
class Runner(object): """Run all the rules""" def __init__(self, rules, filename, template, regions, verbosity=0, mandatory_rules=None): self.rules = rules self.filename = filename self.verbosity = verbosity self.mandatory_rules = mandatory_rules or [] self.cfn = Template(filename, template, regions) def transform(self): """Transform logic""" LOGGER.debug('Transform templates if needed') sam_transform = 'AWS::Serverless-2016-10-31' matches = [] transform_declaration = self.cfn.template.get('Transform', []) transform_type = transform_declaration if isinstance( transform_declaration, list) else [transform_declaration] # Don't call transformation if Transform is not specified to prevent # useless execution of the transformation. # Currently locked in to SAM specific if sam_transform not in transform_type: return matches # Save the Globals section so its available for rule processing self.cfn.transform_pre['Globals'] = self.cfn.template.get( 'Globals', {}) transform = Transform(self.filename, self.cfn.template, self.cfn.regions[0]) matches = transform.transform_template() self.cfn.template = transform.template() return matches def run(self): """Run rules""" LOGGER.info('Run scan of template %s', self.filename) matches = [] if self.cfn.template is not None: matches.extend(self.rules.run(self.filename, self.cfn)) # uniq the list of incidents and filter out exceptions from the template directives = self.cfn.get_directives() return_matches = [] for match in matches: if not any(match == u for u in return_matches): if match.rule.id not in directives: return_matches.append(match) else: for mandatory_rule in self.mandatory_rules: if match.rule.id.startswith(mandatory_rule): return_matches.append(match) break else: for directive in directives.get(match.rule.id): start = directive.get('start') end = directive.get('end') if start[0] < match.linenumber < end[0]: break if start[0] == match.linenumber and start[ 1] <= match.columnnumber: break if end[0] == match.linenumber and end[ 1] >= match.columnnumberend: break else: return_matches.append(match) return return_matches