コード例 #1
0
class ELK_to_Slack:
    def __init__(self):
        self.api_issues  = API_Issues()
        self.attachments = API_Slack_Attachment()
        self.default_max =  20

    def set_default_max(self, value): self.default_max = value ; return self

    def get_search_mappings(self):
        return {
            'assign'   : 'Assignee:',
            'summary'  : 'Summary:',
            #'asset'    : 'Issue\\ Type:"IT Asset" AND Summary:',
            #'entity'   : 'Issue\\ Type:"Business Entity"  AND Summary:',
            #'epic'     : 'Issue\\ Type:"Epic"  AND Summary:',
            #'incident' : 'Issue\\ Type:"Incident" AND Summary:',
            #'meeting'  : 'Issue\\ Type:Meeting AND Summary:',
            'person'   : 'Issue\ Type:Person AND Summary:',
            #'project'  : 'Issue\\ Type:"GS-Project" AND Summary:',
            #'programme': 'Issue\\ Type:"Programme" AND Summary:',
            #'risk'     : 'Issue\\ Type:Risk AND Summary:',
            #'sc'       : 'Issue\\ Type:"Security Controls AND Summary:',
            #'service'  : 'Issue\\ Type:"GS Service" AND Summary:',

            #'vuln'     : 'Issue\\ Type:Vulnerability AND Summary:',
            #'supplier': 'Project:"Supplier\\ Log" AND Summary:',
            'task'       : 'Issue\ Type:"Task"  AND Summary:',
            'squad'      : 'Issue\ Type:Squad AND Summary:',
            'outcomes'   : 'Issue\ Type:Outcome AND Summary:',
            'keyresult'  : 'Issue\ Type:Key Result AND Summary:',
            'sow'        : 'Issue\ Type:Sow AND Summary:',

            'label'   : 'Labels:',
            'high'    : 'Rating:High      AND Summary:',
            'low'     : 'Rating:Low      AND Summary:',
            'medium'  : 'Rating:Medium      AND Summary:',


        }

    def get_search_query(self,params):
        search_type  = Lists.first(params,strip=True)
        if search_type:
            query = self.get_search_mappings().get(search_type)
            if query:
                return query + ' '.join(params[1:])
            #if index_name.lower() in ['people']: return 'Issue\ Type:People AND Summary ' +' '.join[1:]

        return ' '.join(params)

    def get_text_with_issues_key_and_summary(self, results):
        issues_list = ""
        keys        = []
        for issue in results[0:self.default_max]:
            key         = issue['Key']
            summary     = issue['Summary']
            jira_link   = "https://glasswall.atlassian.net/browse/{0}".format(key)
            issues_list += "<{0}|{1}>  {2} \n".format(jira_link, key, summary)
            keys.append(key)
        return issues_list

    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')

    def get_slack_message(self, issues, graph_name):
        text = ":point_right: Elk search had `{0}` matches (results saved to graph `{1}` ) \n" \
            .format(len(issues), graph_name)
        if len(issues) > self.default_max:
            text += ":point_right: showing first `{0}`".format(self.default_max)
        return text

    def cmd_search(self, params, user=None, team_id=None, channel=None):
        if Lists.empty(params):
            text = ':red_circle: for the `search` command, please provide the type of search you want to do. \nHere are the the options:'
            for name in sorted(list(set(self.get_search_mappings()))):
                text +=  '\n\t\t • `{0}` '.format(name)
            text += '\n\n:point_right: the syntax is: `jira search {type} {what to search}` (note search is done on the Summary field)'
            return slack_message(text, [], channel, team_id)

        query       = self.get_search_query(params)
        issues      = self.api_issues.search_using_lucene(query)
        if channel:
            if len(issues) > 0:
                issues_text = self.get_text_with_issues_key_and_summary(issues)
                graph_name  = self.save_issues_as_new_graph(issues)
                text        = self.get_slack_message(issues, graph_name)

                self.attachments.set_text(issues_text)
                self.attachments.set_callback_id("search-results")

                return slack_message(text, self.attachments.render(), channel, team_id)
            else:
                text = ":red_circle: Elk search for `{0}` had `{1}` matches".format(query, len(issues))
                return slack_message(text, self.attachments.render(), channel, team_id)

        else:
            return issues
    # def cmd_search_graph(self, params, user, team_id, channel):
    #     results = self.api_issues.search_using_lucene(' '.join(params))
    #     keys = [issue.get('Key') for issue in results]
    #     if len(keys) == 0:
    #         text = ':black_circle: ELK search returned 0 results'
    #     else:
    #         text =  'ELK search resulted in `{0}` keys'.format(len(keys))
    #
    #         slack_cmd = 'links {0} all 1'.format(','.join(keys))
    #         params    = slack_cmd.split(' ')
    #         result    = Lambda('gs.elastic_jira').invoke({"params": params,  "user": user, "channel": channel})
    #         #slack_message(result.get('text'), result.get('attachments'), channel)
    #         self.attachments.set_text(result.get('text'))
    #
    #     slack_message(text, self.attachments.render(), channel, team_id)

    def handle_lambda_event(self, event):

        channel = event.get('channel' )
        params  = event.get("params"  )
        user    = event.get('user'    )
        team_id  = event.get('team_id')
        log_to_elk('[Elk_to_Slack.handle_lambda_event]: {0}'.format(event))
        try:
            if params:
                command = params.pop(0)
                if command == 'search'      : return self.cmd_search      (params, user, team_id, channel)
                #if command == 'search-graph': return self.cmd_search_graph(params, user, team_id, channel)

                #return slack_message(":point_right: in handle_lambda_event with params: {0}".format(event), [], channel)
            slack_message(":red_circle: in ELK_to_Slack, un-supported command :`{0}`. Data received was: {1}".format(command,event), [], channel)
        except Exception as error:
            message = ":red_circle: error in ELK_to_Slack:`{0}`. Data received was: {1}".format(error,event)
            log_to_elk(message, level = 'error')
            slack_message(message , [], channel)

    # def save_search_in_elk(self, message):
    #     index   = 'slack_interaction'
    #     item    = { 'data': message,
    #                 'date': datetime.datetime.utcnow() }
    #     elastic = Log_To_Elk().setup(index)
    #     return elastic.add(item)
コード例 #2
0
class Jp_Graph_Data:
    def __init__(self):
        self.lambda_graph = Lambda('osbot_jira.lambdas.graph')
        self.api_issues = API_Issues()
        self.gs_bot_jira = GS_Bot_Jira()
        self.graph_commands = Lambda_Graph_Commands()
        self.elk_to_slack = ELK_to_Slack()

    def lambda_invoke(self, params):
        result = self.lambda_graph.invoke({'params': params, 'data': {}})
        return json_loads(result)

    def issue(self, issue_id):
        return self.api_issues.issue(issue_id)

    def issues(self, issue_id):
        return self.api_issues.issues(issue_id)

    def jira_links(self, source, depth=1):
        params = ['links', source, depth]
        return self.gs_bot_jira.cmd_links(params, save_graph=False)

    def jira_search(self, query):
        params = query.split(' ')
        query = self.elk_to_slack.get_search_query(params)
        return self.api_issues.search_using_lucene(query)

    def graph_expand(self, source, depth, link_types):
        params = [source, depth, link_types]
        return self.graph_commands.expand(params=params, save_graph=False)

        #data = json..invoke(params))
        #nodes = data.get('nodes')
        #edges = data.get('edges')

    def draw_graph(self, graph):
        nodes = graph.nodes
        edges = graph.edges
        import networkx as nx
        import matplotlib.pyplot as plt

        size = 40
        plt.figure(figsize=(size, size))
        G = nx.DiGraph()

        for node in nodes:
            G.add_node(node)

        for edge in edges:
            G.add_edge(edge[0], edge[2], label=edge[1])

        edge_labels = nx.get_edge_attributes(G, 'label')

        # pos = nx.spring_layout(G)
        # pos=nx.nx_pydot.graphviz_layout(G,prog='dot')
        pos = nx.nx_pydot.graphviz_layout(G)

        nx.draw_networkx_nodes(G, pos, node_shape='', node_size=100)
        nx.draw_networkx_labels(G, pos, font_size=16)
        nx.draw_networkx_edges(G, pos)
        nx.draw_networkx_edge_labels(G,
                                     pos=pos,
                                     edge_labels=edge_labels,
                                     font_size=10)
コード例 #3
0
class Test_API_Issues(unittest.TestCase):
    def setUp(self):
        self.key = 'RISK-1515'
        self.api = API_Issues()

    def test_epic_issues(self):
        results = self.api.epic_issues('SEC-2024')
        assert len(list(results)) > 10

    def test_issue(self):
        issue = self.api.issue(self.key)
        assert issue.get('Key') == self.key

    @unittest.skip('todo: fix: error on "if item[\'found\'] is False:" line')
    def test_issues(self):
        keys = ['RISK-1499', 'RISK-1496', 'AAA']
        #result = self.api.elastic.es.mget(index='jira',
        #                                    doc_type='item',
        #                       body={'ids': keys})
        results = self.api.elastic().get_many(keys)
        #Dev.pprint(results)

    def test_issues_all(self):
        assert len(self.api.issues_all('jira')) > 2000

    def test_issues_created_in_last(self):
        result = self.api.issues_created_in_last("3d")
        assert len(result) > 10

    def test_issues_updated_in_last(self):
        result = self.api.issues_updated_in_last("3d")
        assert len(result) > 10

    def test_issues_created_in_last_nnn(self):
        assert len(self.api.issues_created_in_last_seconds(
            1 * 24 * 60 * 60)) > 0
        assert len(self.api.issues_created_in_last_minutes(1 * 24 * 60)) > 0
        assert len(self.api.issues_created_in_last_hours(1 * 24)) > 0
        assert len(self.api.issues_created_in_last_days(1)) > 0
        assert len(self.api.issues_created_in_last_weeks(1)) > 0
        assert len(self.api.issues_created_in_last_months(1)) > 0

    @unittest.skip('fails in CodeBuild')
    def test_create_issue_table(self):
        table = self.api.create_issue_table('RISK-424')
        table.save_tmp()
        #Dev.print(table.puml)

    def test_labels(self):
        result = self.api.labels()
        assert 'VULN-2160' in result['AWSrisk']
        assert len(result) > 650

    def test_link_types(self):
        result = self.api.link_types()
        assert len(result) > 100

    def test_keys(self):
        keys = self.api.keys()
        assert 'VULN-10' in keys
        assert len(keys) > 15000

    def test_search(self):
        assert len(self.api.search("aw", "Summary", 100)) > 0
        assert len(self.api.search("R1", "Labels", 10)) > 0
        assert self.api.search("GSP-95", "Key",
                               10).pop().get('Key') == "GSP-95"

    def test_search_using_lucene(self):
        query = 'Project:RISK AND Status:"Fixed"'
        results = self.api.search_using_lucene(query)
        assert len(results) > 200

    # def test_stakeholders(self):
    #     result = self.api.stakeholders()
    #     #Dev.pprint(result)
    #     #Dev.pprint(len(set(result)))

    ### move these to separate analysis file

    @unittest.skip('Fails in CodeBuild')
    def test_graph_issue_links_plant_uml(self):
        puml = self.api.graph_issue_links_plant_uml(self.key)
        puml.save_tmp()
        puml._dev_send_to_slack()