def build_graph_from_source_directory( self, source_dir: str, render_variables: bool = True, local_graph_class: Type[ CloudformationLocalGraph] = CloudformationLocalGraph, parsing_errors: Optional[Dict[str, Exception]] = None, download_external_modules: bool = False, excluded_paths: Optional[List[str]] = None, ) -> Tuple[CloudformationLocalGraph, Dict[str, DictNode]]: logging.info( f"[CloudformationGraphManager] Parsing files in source dir {source_dir}" ) parsing_errors = {} definitions, definitions_raw = get_folder_definitions( source_dir, excluded_paths, parsing_errors) local_graph = self.build_graph_from_definitions( definitions, render_variables) rendered_definitions, _ = convert_graph_vertices_to_definitions( local_graph.vertices, source_dir) # TODO: replace with real graph rendering for cf_file in rendered_definitions.keys(): file_definition = rendered_definitions.get(cf_file, None) file_definition_raw = definitions_raw.get(cf_file, None) if file_definition is not None and file_definition_raw is not None: cf_context_parser = ContextParser(cf_file, file_definition, file_definition_raw) logging.debug("Template Dump for {}: {}".format( cf_file, json.dumps(file_definition, indent=2, default=str))) cf_context_parser.evaluate_default_refs() return local_graph, rendered_definitions
def test_vertices_from_local_graph(self): resources_dir = os.path.realpath( os.path.join(TEST_DIRNAME, './resources/vertices')) definitions, _ = create_definitions(root_folder=resources_dir, files=None, runner_filter=RunnerFilter()) local_graph = CloudformationLocalGraph(definitions) local_graph.build_graph(render_variables=False) definitions, breadcrumbs = convert_graph_vertices_to_definitions( local_graph.vertices, resources_dir) self.assertIsNotNone(definitions) self.assertEqual(len(definitions.items()), 2) test_yaml_definitions = definitions[os.path.join( resources_dir, 'test.yaml')][TemplateSections.RESOURCES] self.assertEqual(len(test_yaml_definitions.keys()), 2) self.assertIn('MyDB', test_yaml_definitions.keys()) self.assertIn('MySourceQueue', test_yaml_definitions.keys()) test_json_definitions = definitions[os.path.join( resources_dir, 'test.json')][TemplateSections.RESOURCES] self.assertEqual(len(test_json_definitions.keys()), 2) self.assertIn('MyDB', test_json_definitions.keys()) self.assertIn('MySourceQueue', test_json_definitions.keys()) self.assertIsNotNone(breadcrumbs) self.assertDictEqual( breadcrumbs, {}) # Will be changed when we add breadcrumbs to cfn vertices
def run( self, root_folder: str, external_checks_dir: Optional[List[str]] = None, files: Optional[List[str]] = None, runner_filter: RunnerFilter = RunnerFilter(), collect_skip_comments: bool = True, ) -> Report: report = Report(self.check_type) parsing_errors = {} if self.context is None or self.definitions is None or self.breadcrumbs is None: self.definitions, self.definitions_raw = create_definitions( root_folder, files, runner_filter, parsing_errors) if external_checks_dir: for directory in external_checks_dir: cfn_registry.load_external_checks(directory) self.graph_registry.load_external_checks(directory) self.context = build_definitions_context(self.definitions, self.definitions_raw, root_folder) logging.info("creating cloudformation graph") local_graph = self.graph_manager.build_graph_from_definitions( self.definitions) for vertex in local_graph.vertices: if vertex.block_type == BlockType.RESOURCE: report.add_resource(f'{vertex.path}:{vertex.id}') self.graph_manager.save_graph(local_graph) self.definitions, self.breadcrumbs = convert_graph_vertices_to_definitions( local_graph.vertices, root_folder) # TODO: replace with real graph rendering for cf_file in self.definitions.keys(): file_definition = self.definitions.get(cf_file, None) file_definition_raw = self.definitions_raw.get(cf_file, None) if file_definition is not None and file_definition_raw is not None: cf_context_parser = ContextParser(cf_file, file_definition, file_definition_raw) logging.debug("Template Dump for {}: {}".format( cf_file, json.dumps(file_definition, indent=2, default=str))) cf_context_parser.evaluate_default_refs() report.add_parsing_errors(list(parsing_errors.keys())) # run checks self.check_definitions(root_folder, runner_filter, report) # run graph checks graph_report = self.get_graph_checks_report(root_folder, runner_filter) merge_reports(report, graph_report) return report
def validate_conditioned_vertices_from_local_graph(self, root_dir, file_name): true_condition_resources = {'BucketFnEqualsTrue', 'BucketFnNotTrue', 'BucketFnNotTrueThroughCondition', 'BucketFnAndTrue', 'BucketFnAndTrueWithCondition', 'BucketFnOrTrue', 'BucketFnOrTrueWithCondition'} definitions, _ = create_definitions(root_folder=root_dir, files=None, runner_filter=RunnerFilter()) local_graph = CloudformationLocalGraph(definitions) local_graph.build_graph(render_variables=True) definitions, breadcrumbs = convert_graph_vertices_to_definitions(local_graph.vertices, root_dir) self.assertIsNotNone(definitions) self.assertEqual(len(definitions.items()), 1) test_yaml_definitions = definitions[os.path.join(root_dir, file_name)][TemplateSections.RESOURCES] definitions_set = set(test_yaml_definitions.keys()) self.assertEqual(len(definitions_set), 7) self.assertSetEqual(true_condition_resources, definitions_set)