コード例 #1
0
 def save_issues_as_new_graph(self, issues):
     all_keys = []
     for issue in issues:
         all_keys.append(issue['Key'])
     graph = GS_Graph()  # save results in graph
     graph.add_nodes(all_keys)
     return Lambda_Graph().save_gs_graph(graph, graph_type='graph-search')
コード例 #2
0
 def test_save(self):
     (self.graph.add_node("RISK-424").add_node("ID-42").add_edge(
         "RISK-424", '', "ID-42").add_edge("RISK-424", '', "ID-7"))
     file = self.graph.save()
     loaded_graph = GS_Graph()
     loaded_graph.load(file)
     assert loaded_graph.nodes == self.graph.nodes
     assert len(loaded_graph.edges) == len(self.graph.edges)
     assert self.graph.render_puml().puml == loaded_graph.render_puml().puml
コード例 #3
0
ファイル: Lambda_Graph.py プロジェクト: filetrust/OSBot-jira
 def get_gs_graph_from_most_recent_version(self, lucene_query):
     data = self.save_to_elk().get_most_recent_version_of_document(lucene_query)
     if data is None: return None
     graph = GS_Graph()
     if data.get('nodes'):
         graph.nodes = data.get('nodes')
         graph.edges = data.get('edges')
         graph.puml.puml = data.get('extra_data').get('puml')
     return graph
コード例 #4
0
ファイル: Lambda_Graph.py プロジェクト: filetrust/OSBot-jira
    def graph_links(self, target, depth=1):
        if target is None:
            return None
        graph = self.get_gs_graph___by_name(target)             # check if the value provided is a saved graph
        if graph is not None:                                   # if it exists
            keys = graph.nodes                                  # set keys to graph nodes
        else:                                                   # if not
            keys = target.upper().split(",")                    # use value as keys

        graph = GS_Graph()
        graph.add_all_linked_issues(keys, depth)
        return graph
コード例 #5
0
ファイル: Lambda_Graph.py プロジェクト: filetrust/OSBot-jira
    def save_gs_graph(self, graph: GS_Graph, graph_name = None, graph_type = None, channel= None, user = None):
        nodes = graph.nodes
        edges = graph.edges
        puml  = graph.puml.puml
        if '@enduml' not in puml:       # means that graph is not rendered
            puml = graph.render_puml().puml

        extra_data = {
                        "user"    : user                ,
                        "channel" : channel             ,
                        "puml"    : puml                ,
                        "params"  : graph.create_params ,
                        "stats"   : graph.stats()
                    }
        return self.save_graph(nodes, edges, extra_data, None, graph_name, graph_type)
コード例 #6
0
    def test_to_json__from_json(self):
        graph = self.graph
        graph.add_nodes(['abc', 'xyz', '123']).add_edges([('abc', '', 'xyz'),
                                                          ('abc', '', '123')])
        graph.create_params = ['in', 'unit test']

        assert json.loads(graph.to_json()) == {
            'create_params': ['in', 'unit test'],
            'edges': [['abc', '', 'xyz'], ['abc', '', '123']],
            'node_type': {},
            'nodes': ['abc', 'xyz', '123'],
            'notes': [],
            'puml_config': True,
            'puml_options': {
                'height': None,
                'left-to-right': True,
                'link-types-to-add': [],
                'link-types-to-ignore': [],
                'node-text-value': 'Summary',
                'only-from-projects': [],
                'show-edge-labels': True,
                'show-key-in-text': True,
                'width': None
            },
            'skin_params': []
        }
        assert json.loads(graph.to_json(puml_config=False)) == {
            'edges': [['abc', '', 'xyz'], ['abc', '', '123']],
            'nodes': ['abc', 'xyz', '123']
        }

        graph_json = graph.to_json()
        new_graph = GS_Graph().from_json(graph_json)

        new_graph_json = new_graph.to_json()
        assert graph_json == new_graph_json
        assert graph_json != GS_Graph().to_json()

        assert GS_Graph().from_json(
            graph.to_json(puml_config=False)).nodes == ['abc', 'xyz', '123']
コード例 #7
0
    def test_to_json__from_json__store_issues(self):

        graph = self.graph
        graph.add_nodes(['RISK-12', 'RISK-24', 'RISK-1084'
                         ]).add_edges([('RISK-12', '', 'RISK-24'),
                                       ('RISK-12', '', 'RISK-1084')])

        graph_json = graph.to_json(store_issues=True)
        assert set(json.loads(graph_json).get('issues')) == {
            'RISK-12', 'RISK-24', 'RISK-1084'
        }
        assert set(GS_Graph().from_json(graph_json).issues) == {
            'RISK-12', 'RISK-24', 'RISK-1084'
        }
コード例 #8
0
    def test____create_stakeholder_graph_from_security_story(self):

        #from gs_elk.API_Jira_Diagrams import API_Jira_Diagrams
        #graph = API_Jira_Diagrams().risks_story_mixed_orders_v2__puml()

        file = '/tmp/graph-sec-9195.json'
        graph = GS_Graph().load(file)

        issue_types_path = [
            'is Stakeholder', 'is created by R2', 'is created by R3',
            'is created by R4', 'is created by VULN', 'is Vulnerability of',
            'RISK supported by', 'risk reduced by', 'is child of',
            'is fixed by'
        ]
        start_node = 'SEC-8651'
        self.graph.create_sub_graph_from_start_node(graph.nodes, start_node,
                                                    issue_types_path)
        self.graph.add_link_types_as_nodes()
        self.graph.puml.save_tmp()
コード例 #9
0
    def view_schema(self):

        issues = self.graph.get_nodes_issues()
        schema = {}
        puml = self.graph.puml
        for edge in self.graph.edges:
            if issues[edge[0]]:
                from_issue_type = puml.fix_id(
                    issues[edge[0]].get('Issue Type'))
            else:
                from_issue_type = 'NA'
            link_name = edge[1]
            if issues[edge[2]]:
                to_issue_type = puml.fix_id(issues[edge[2]].get('Issue Type'))
            else:
                to_issue_type = 'NA'
            schema_edge = (from_issue_type, link_name, to_issue_type)
            if schema.get(schema_edge) is None:
                schema[schema_edge] = {
                    'count': 0,
                    'from_issue_type': from_issue_type,
                    'link_name': link_name,
                    'to_issue_type': to_issue_type
                }
            schema.get(schema_edge)['count'] += 1

        new_graph = GS_Graph()
        for item in schema.values():
            new_graph.add_node(item.get('from_issue_type'))
            new_graph.add_node(item.get('to_issue_type'))
            new_graph.add_edge(item.get('from_issue_type'),
                               item.get('link_name'),
                               item.get('to_issue_type'))

        self.graph = new_graph
        self.graph.render_puml()
        return self.puml()
コード例 #10
0
 def setUp(self):
     self.graph = GS_Graph()
     self.result = None
コード例 #11
0
 def get_graph(self, graph_name):
     graph_json: str = self.get_graph_json(graph_name)
     graph: GS_Graph = GS_Graph().from_json(graph_json)
     return graph
コード例 #12
0
 def test_render_and_save_gs_graph_____org_chart(self):
     graph = GS_Graph()
     is_a_manager_nodes = graph.api_issues.all_link_types('it_assets')['is manager of'].keys()
     graph.add_nodes(is_a_manager_nodes)
     graph.add_linked_issues_of_type('is manager of')
     graph.render_and_save_to_elk   ("test_save_gs_graph_____org_chart", "from unit test")
コード例 #13
0
 def test_save_gs_graph(self):
     graph = GS_Graph()
     graph.add_node("aaa")
     graph.add_edge("aaa","->","bbb")
     result = self.lambda_graph.save_gs_graph(graph, "test_save_gs_graph", "from unit test")
     Dev.pprint(result)
コード例 #14
0
 def test_get_gs_graph___from_user(self):
     user = '******'
     graph = GS_Graph().add_node("aaa").add_edge("aaa", "->", "bbb")
     self.lambda_graph.save_gs_graph(graph, user = user)
     graph = self.lambda_graph.get_gs_graph___from_user(user)
     assert graph.stats() == {'count_edges': 1, 'count_nodes': 1, 'size_puml': 90}
コード例 #15
0
 def test____load_and_render_left_to_right(self):
     file = '/tmp/graph-sec-9195.json'
     graph = GS_Graph().load(file)
     graph.puml_options['left-to-right'] = True
     graph.render_puml()
     graph.puml.save_tmp()
コード例 #16
0
def epic_graph(key):
    return GS_Graph().add_nodes_from_epics()
コード例 #17
0
class Test_GS_Graph(TestCase):
    def setUp(self):
        self.graph = GS_Graph()
        self.result = None

    def tearDown(self):
        if self.result is not None:
            Dev.pprint(self.result)

    def test_add_node(self):
        self.graph.add_node('a')
        assert self.graph.nodes == ['a']

    def test_add_linked_issues_of_type(self):
        self.graph.add_node('SEC-9195')
        self.graph.add_linked_issues_of_types([
            'is parent of', 'supports RISK', 'creates RISK',
            'is Vulnerability of', 'creates R2', 'creates R1',
            'has Stakeholder'
        ])

        self.graph.render_puml()
        self.graph.puml.save_tmp()
        #self.graph.save('/tmp/graph-sec-9195.json')
        #print(self.graph.puml.puml)

        # self.graph.puml.add_line("scale 2.25")

        # self.graph.puml.add_line("\tscale 2024 height   \n")
        #self.graph.puml.add_line('skinparam handwritten true')

    # def test_add_all_linked_issues(self):
    #     keys = ['RISK-1494']
    #     (self.graph.set_links_path_mode_to_down()
    #                .set_puml_show_key_in_text  (True)
    #                #.set_puml_only_from_projects(['RISK', 'VULN'])
    #                .set_puml_width             (4000)
    #                #.set_puml_height            (6000)
    #                .add_all_linked_issues      (keys, 5)
    #                #.add_link_types_as_nodes(self.graph.risk_links_paths_down)
    #                .render_puml_and_save_tmp   ()
    #      )
    #
    #     Dev.pprint(len(self.graph.nodes))
    #     Dev.pprint(len(self.graph.edges))

    def test_add_all_linked_issues____with_color_coding_on_rating(self):

        issues = None

        def on_add_node(element, title, id, original_id):
            key = id.replace('_', '-')
            issue = issues.get(key)
            color = '#FFFFFF'
            if issue:
                rating = issue['Rating']
                if rating == 'High': color = '#F37071'
                elif rating == 'Medium': color = '#F0BF99'
                elif rating == 'Low': color = '#78999D'
                elif rating == 'TBD': color = '#F7A4A4'

            node_puml = '{0} "<color:#000000>{1}</color>" as {2} {3}'.format(
                element, title, id, color)
            return node_puml

        self.graph.puml.on_add_node = on_add_node

        self.graph.puml.add_line("\tscale 3024 width   \n")
        keys = ['RISK-1610']  # ['GSP-95'] # 'FACT-47', #
        (self.graph.set_puml_left_to_right(True).set_puml_only_from_projects([
            'RISK', 'VULN'
        ]).set_puml_show_key_in_text(False).set_puml_show_edge_labels(
            False).add_all_linked_issues(keys, 2))
        issues = self.graph.get_nodes_issues()

        self.graph.render_puml()
        self.graph.puml.save_tmp()

        Dev.pprint(len(self.graph.nodes))
        Dev.pprint(len(self.graph.edges))

        #self.graph.render_puml_and_save_tmp()

    def test_add_all_linked_issues____with___risk_links_paths_down(self):
        issues = None

        def on_add_node(element, title, id, original_id):
            key = id.replace('_', '-')
            issue = issues.get(key)
            color = '#FFFFFF'
            if issue:
                status = issue['Status']
                if status in ['Blocked', 'Backlog']: color = '#F37071'
                elif status in ['To VULN Assess', 'To Validate']:
                    color = '#F0BF99'
                elif status == 'Allocated for Fix':
                    color = '#78999D'
                elif status == 'Fixed':
                    color = '#6DD1A3'

            node_puml = '{0} "<color:#000000>{1}</color>" as {2} {3}'.format(
                element, title, id, color)
            return node_puml

        self.graph.puml.on_add_node = on_add_node

        keys = ['IA-333'
                ]  #['RISK-1526'] #['RISK-1610']  # ['GSP-95'] # 'FACT-47', #
        graph = self.graph
        #self.risk_links_paths_down
        (graph  #.set_puml_node_edge_value("Status")
         .set_puml_link_types_to_add(
             graph.risk_links_paths_down
         ).set_puml_show_key_in_text(False).add_all_linked_issues(keys, 4))

        issues = self.graph.get_nodes_issues()

        graph.render_puml_and_save_tmp()
        Dev.pprint(len(graph.nodes))
        Dev.pprint(len(graph.edges))

    def test_add_all_linked_issues____with___risk_links_paths_up(self):
        keys = ['SEC-8708']  #['RISK-1610']  # ['GSP-95'] # 'FACT-47', #
        graph = self.graph
        #self.risk_links_paths_down
        (graph  #.set_puml_node_edge_value(None)
         .set_puml_link_types_to_add(graph.risk_links_paths_up
                                     ).add_all_linked_issues(keys, 5))
        graph.render_puml_and_save_tmp()

        #self.graph.add_link_types_as_nodes()

        Dev.pprint(len(graph.nodes))
        Dev.pprint(len(graph.edges))

    @unittest.skip("needs fixing the ES index")
    def test_add_all_linked_issues____IT_Assets(self):
        it_systems = self.graph.api_issues.elastic(
        ).search_using_lucene_index_by_id('Issue\ Type: "IT Assets"')
        keys = list(it_systems.keys())[0:20]
        self.graph.set_puml_width(5000)
        self.graph.set_link_types_from_issues(it_systems)
        self.graph.set_puml_link_types_to_add(['has to be done after'])

        self.graph.add_all_linked_issues(keys, 1)
        self.graph.render_puml_and_save_tmp()

        return

    def test_add_link_types_as_nodes____GitHub(self):

        self.graph.add_node('IA-333')
        self.graph.add_linked_issues_of_types(
            ['is Vulnerable to', 'has Stakeholder'])
        self.graph.add_link_types_as_nodes()
        self.graph.render_puml_and_save_tmp()

        return

    # def test_edges__link_types(self):
    #     self.graph.add_all_linked_issues( ['RISK-1610'], 2)
    #     result = self.graph.get_unique_link_types()
    #     #Dev.pprint(result)
    #     assert len(result) == 22

    def test_graph(self):
        self.result = self.graph.add_node('aaa').graph().nodes()

    def test_remove_with_links(self):

        (self.graph.add_node("RISK-424").add_node("ID-42").add_node(
            "ID-41").add_edge("RISK-424", '',
                              "ID-42").add_edge("RISK-424", '', "ID-7"))

        Dev.pprint(self.graph.nodes)
        Dev.pprint(self.graph.edges)
        self.graph.remove_with_links()
        Dev.pprint(self.graph.nodes)
        Dev.pprint(self.graph.edges)

    def test_save(self):
        (self.graph.add_node("RISK-424").add_node("ID-42").add_edge(
            "RISK-424", '', "ID-42").add_edge("RISK-424", '', "ID-7"))
        file = self.graph.save()
        loaded_graph = GS_Graph()
        loaded_graph.load(file)
        assert loaded_graph.nodes == self.graph.nodes
        assert len(loaded_graph.edges) == len(self.graph.edges)
        assert self.graph.render_puml().puml == loaded_graph.render_puml().puml
        #loaded_graph.puml.save_tmp()

    #### use cases

    def test____create_org_chart_everybody(self):
        is_a_manager_nodes = self.graph.all_link_types(
            'it_assets')['is manager of'].keys()
        self.graph.add_nodes(is_a_manager_nodes)
        self.graph.add_linked_issues_of_type('is manager of')

        self.graph.render_puml()
        self.graph.puml.save_tmp()

    def test____load_and_render_left_to_right(self):
        file = '/tmp/graph-sec-9195.json'
        graph = GS_Graph().load(file)
        graph.puml_options['left-to-right'] = True
        graph.render_puml()
        graph.puml.save_tmp()

    def test____create_stakeholder_graph_from_security_story(self):

        #from gs_elk.API_Jira_Diagrams import API_Jira_Diagrams
        #graph = API_Jira_Diagrams().risks_story_mixed_orders_v2__puml()

        file = '/tmp/graph-sec-9195.json'
        graph = GS_Graph().load(file)

        issue_types_path = [
            'is Stakeholder', 'is created by R2', 'is created by R3',
            'is created by R4', 'is created by VULN', 'is Vulnerability of',
            'RISK supported by', 'risk reduced by', 'is child of',
            'is fixed by'
        ]
        start_node = 'SEC-8651'
        self.graph.create_sub_graph_from_start_node(graph.nodes, start_node,
                                                    issue_types_path)
        self.graph.add_link_types_as_nodes()
        self.graph.puml.save_tmp()

    def test__create_graph_with_epic_data__top_level_okrs_up(self):
        graph = self.graph
        (graph.add_all_linked_issues(
            ['GSOKR-924']).add_nodes_from_epics().set_link_paths_to_ignore([
                'is child of', 'has Stakeholder'
            ]).set_links_path_mode_to_up().add_all_linked_issues(depth=3))
        graph.render_puml_and_save_tmp()

    def test__create_graph_with_epic_data__top_level_okrs_down(self):
        graph = self.graph
        (graph.add_all_linked_issues(['GSOKR-924']).add_nodes_from_epics().
         set_links_path_mode_to_up().set_link_paths_to_ignore([
             'is child of', 'has Stakeholder'
         ]).set_links_path_mode_to_up().add_all_linked_issues(depth=4))
        graph.render_puml_and_save_tmp()

    def test__create_graph_for_epic_SEC_8694(self):
        graph = self.graph
        (graph.add_all_linked_issues(['SEC-8694']).add_nodes_from_epics().
         set_links_path_mode_to_up().add_all_linked_issues(depth=2))
        graph.render_puml_and_save_tmp()

    def test__create_graph_with_epic_data__sec_9195(self):
        graph = self.graph

        #Dev.pprint(self.graph.api_issues.epic_issues('SEC-9195'))
        #return
        (graph.add_all_linked_issues(
            ['GSOKR-924']).add_nodes_from_epics().set_link_paths_to_ignore([
                'is child of', 'has Stakeholder'
            ]).set_links_path_mode_to_up().add_all_linked_issues(depth=3))
        Dev.pprint(len(graph.nodes))
        graph.render_puml_and_save_tmp()

    # def test__create_graph_with_epic_data__assignee(self):
    #     keys = ['SEC-9696']
    #     graph = self.graph
    #     (graph  .set_links_path_mode_to_down()
    #             .add_all_linked_issues(keys, 1)
    #             .add_nodes_from_epics()
    #             .add_all_linked_issues()
    #             .set_puml_node_text_value('Assignee')
    #     )
    #     self.graph.render_puml()
    #     self.graph.puml.save_tmp()
    #
    #     #graph.render_puml_and_save_tmp()
    #
    #     API_Slack('DDKUZTK6X').puml_to_slack(graph.puml.puml)

    def test__create_graph_with_up_down_data(self):
        keys = ['SEC-9696']

        graph = self.graph
        (graph  # .set_puml_node_edge_value(None)
         .set_puml_link_types_to_add(graph.risk_links_paths_down
                                     ).add_all_linked_issues(keys, 1))
        graph.render_puml_and_save_tmp()

    def test__create_graph_with_up_down_data(self):
        keys = ['IA-386']
        graph = self.graph
        (graph.set_puml_link_types_to_add(["is parent of"
                                           ]).add_all_linked_issues(keys,
                                                                    2)  # was 6
         .set_puml_direction_top_down())
        graph.render_puml_and_save_tmp()

    def tests_expand_link_types_to_add(self):

        self.graph.set_puml_link_types_to_add(['risks_up','stakeholders_up'])     \
                  .expand_link_types_to_add()

    def test__create_graph_with_special_link_types(self):
        keys = ['RISK-1494']

        graph = self.graph
        (graph  # .set_puml_node_edge_value(None)
         .set_puml_link_types_to_add(['risks_down']
                                     ).add_all_linked_issues(keys, 5))
        graph.render_puml_and_save_tmp()
        #Dev.pprint(result)

    def test_to_json__from_json(self):
        graph = self.graph
        graph.add_nodes(['abc', 'xyz', '123']).add_edges([('abc', '', 'xyz'),
                                                          ('abc', '', '123')])
        graph.create_params = ['in', 'unit test']

        assert json.loads(graph.to_json()) == {
            'create_params': ['in', 'unit test'],
            'edges': [['abc', '', 'xyz'], ['abc', '', '123']],
            'node_type': {},
            'nodes': ['abc', 'xyz', '123'],
            'notes': [],
            'puml_config': True,
            'puml_options': {
                'height': None,
                'left-to-right': True,
                'link-types-to-add': [],
                'link-types-to-ignore': [],
                'node-text-value': 'Summary',
                'only-from-projects': [],
                'show-edge-labels': True,
                'show-key-in-text': True,
                'width': None
            },
            'skin_params': []
        }
        assert json.loads(graph.to_json(puml_config=False)) == {
            'edges': [['abc', '', 'xyz'], ['abc', '', '123']],
            'nodes': ['abc', 'xyz', '123']
        }

        graph_json = graph.to_json()
        new_graph = GS_Graph().from_json(graph_json)

        new_graph_json = new_graph.to_json()
        assert graph_json == new_graph_json
        assert graph_json != GS_Graph().to_json()

        assert GS_Graph().from_json(
            graph.to_json(puml_config=False)).nodes == ['abc', 'xyz', '123']

    def test_to_json__from_json__store_issues(self):

        graph = self.graph
        graph.add_nodes(['RISK-12', 'RISK-24', 'RISK-1084'
                         ]).add_edges([('RISK-12', '', 'RISK-24'),
                                       ('RISK-12', '', 'RISK-1084')])

        graph_json = graph.to_json(store_issues=True)
        assert set(json.loads(graph_json).get('issues')) == {
            'RISK-12', 'RISK-24', 'RISK-1084'
        }
        assert set(GS_Graph().from_json(graph_json).issues) == {
            'RISK-12', 'RISK-24', 'RISK-1084'
        }
コード例 #18
0
    def expand(team_id=None,
               channel=None,
               params=None,
               data=None,
               only_create=False,
               save_graph=True):

        if len(params) < 3:
            text = ':red_circle: Hi, for the `expand` command, you need to provide the following parameters: '
            attachment_text =  '- *graph_name*: the graph to expand\n'  \
                               '- *depth* : how many cycles to expand\n'  \
                               '- *links to expand*: as a comma-delimited list '
            slack_message(text, [{'text': attachment_text}], channel, team_id)
            return
        create_params = ["expand"] + list(
            params
        )  # create copy of array so that we don't lose data with the pops below
        graph_or_key = params.pop(0)
        depth = int(params.pop(0))
        link_types_to_add = ' '.join(params).split(',')

        graph = Lambda_Graph().get_gs_graph___by_name(graph_or_key)
        if graph is None:
            graph = GS_Graph()  # if it wasn't a graph
            graph.add_node(graph_or_key)  # use it as key

        (graph.set_puml_link_types_to_add(
            link_types_to_add).add_all_linked_issues(
                [], depth).set_create_params(create_params))
        if save_graph:
            new_graph_name = graph.reset_puml().render_and_save_to_elk()
        else:
            return graph

        if only_create:
            return graph, new_graph_name, graph_or_key, depth, link_types_to_add

        if channel:  # if the channel value is provided render the new graph and send it to slack, if not, just return the new graph data
            text = "Rendering new graph called `{0}`,\n Which was created by expanding the graph/key `{1}` with depth `{2}`, for link types `{3}` (`{4}` nodes, `{5}` edges)"\
                        .format(new_graph_name, graph_or_key, depth, link_types_to_add,
                                len(graph.nodes), len(graph.edges))
            slack_message(text, [], channel, team_id)

            Lambda('gw_bot.lambdas.puml_to_slack').invoke({
                "puml":
                graph.get_puml(),
                "channel":
                channel,
                "team_id":
                team_id
            })
        else:
            data = {
                "graph_or_key": graph_or_key,
                "depth": depth,
                "nodes": graph.nodes,
                "edges": graph.edges,
                "puml": graph.puml.puml,
                "graph_name": new_graph_name
            }
            return json.dumps(data, indent=4)
コード例 #19
0
    def test_get_graph_data(self):

        graph_name = 'graph_I3H'
        #graph_name = 'graph_782' #
        graph_name = 'graph_N59'

        source_graph_data = Lambda_Graph().get_graph_data(graph_name)
        root_key = 'Issues Created'
        gs_graph = GS_Graph()
        gs_graph.add_node(root_key)

        for key, node in source_graph_data['nodes'].items():
            if node is None:
                continue
            creator = node.get('Creator')
            issue_type = node.get('Issue Type')

            issue_type_key = f'{issue_type}-{creator}'

            gs_graph.add_node(key)
            gs_graph.add_node(creator)
            gs_graph.add_node(issue_type_key)

            gs_graph.add_edge(root_key, '..', creator)
            gs_graph.add_edge(creator, '..', issue_type_key)
            gs_graph.add_edge(issue_type_key, '..', key)

        self.result = Lambda_Graph().save_gs_graph(gs_graph)