def __init__()

in src/cfnlint/graph.py [0:0]


    def __init__(self, cfn):
        """Builds a graph where resources are nodes and edges are explicit (DependsOn) or implicit (Fn::GetAtt, Fn::Sub, Ref)
        relationships between resources"""

        # Directed graph that allows self loops and parallel edges
        self.graph = networkx.MultiDiGraph(name='template')

        # add all resources in the template as nodes
        for resourceId, resourceVals in cfn.template.get('Resources', {}).items():
            type_val = resourceVals.get('Type', '')
            graph_label = str.format('{0}\\n<{1}>', resourceId, type_val)
            self.graph.add_node(resourceId, label=graph_label)
            target_ids = resourceVals.get('DependsOn', [])
            if isinstance(target_ids, (list, six.string_types)):
                if isinstance(target_ids, (six.string_types)):
                    target_ids = [target_ids]
                for target_id in target_ids:
                    if isinstance(target_id, six.string_types):
                        if self._is_resource(cfn, target_id):
                            target_resource_id = target_id
                            self.graph.add_edge(resourceId, target_resource_id, label='DependsOn')

        # add edges for "Ref" tags. { "Ref" : "logicalNameOfResource" }
        refs_paths = cfn.search_deep_keys('Ref')
        for ref_path in refs_paths:
            ref_type, source_id = ref_path[:2]
            target_id = ref_path[-1]
            if not ref_type == 'Resources':
                continue

            if isinstance(target_id, (six.text_type, six.string_types, int)) and (self._is_resource(cfn, target_id)):
                target_resource_id = target_id
                self.graph.add_edge(source_id, target_resource_id, label='Ref')

        # add edges for "Fn::GetAtt" tags.
        # { "Fn::GetAtt" : [ "logicalNameOfResource", "attributeName" ] } or { "!GetAtt" : "logicalNameOfResource.attributeName" }
        getatt_paths = cfn.search_deep_keys('Fn::GetAtt')
        for getatt_path in getatt_paths:
            ref_type, source_id = getatt_path[:2]
            value = getatt_path[-1]
            if not ref_type == 'Resources':
                continue

            if isinstance(value, list) and len(value) == 2 and (self._is_resource(cfn, value[0])):
                target_resource_id = value[0]
                self.graph.add_edge(source_id, target_resource_id, label='GetAtt')

            if isinstance(value, (six.string_types, six.text_type)) and '.' in value:
                target_resource_id = value.split('.')[0]
                if self._is_resource(cfn, target_resource_id):
                    self.graph.add_edge(source_id, target_resource_id, label='GetAtt')

        # add edges for "Fn::Sub" tags. E.g. { "Fn::Sub": "arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:vpc/${vpc}" }
        sub_objs = cfn.search_deep_keys('Fn::Sub')
        for sub_obj in sub_objs:
            sub_parameters = []
            sub_parameter_values = {}
            value = sub_obj[-1]
            ref_type, source_id = sub_obj[:2]

            if not ref_type == 'Resources':
                continue

            if isinstance(value, list):
                if not value:
                    continue
                if len(value) == 2:
                    sub_parameter_values = value[1]
                sub_parameters = self._find_parameter(value[0])
            elif isinstance(value, (six.text_type, six.string_types)):
                sub_parameters = self._find_parameter(value)

            for sub_parameter in sub_parameters:
                if sub_parameter not in sub_parameter_values:
                    if '.' in sub_parameter:
                        sub_parameter = sub_parameter.split('.')[0]
                    if self._is_resource(cfn, sub_parameter):
                        self.graph.add_edge(source_id, sub_parameter, label='Sub')