Example #1
0
    def _get_nodes_and_edges(graph_data,
                             nodes=None,
                             edges=None,
                             text_field='Key',
                             append_key_to_text=False):
        if nodes is None: nodes = []
        if edges is None: edges = []
        if graph_data:
            for key, issue in graph_data.get('nodes').items():
                if issue and issue.get('Summary'):
                    text = issue.get(text_field)
                    if append_key_to_text:
                        text += " | {0}".format(key)
                else:
                    text = key
                nodes.append({
                    'key': key,
                    'text': text,
                    'color': Misc.get_random_color()
                })

            for edge in graph_data.get('edges'):
                if edge[0] and edge[2]:
                    edges.append({
                        'from': edge[0],
                        'text': edge[1],
                        'to': edge[2],
                        'color': Misc.get_random_color()
                    })
                else:
                    print(edge)
        return nodes, edges
Example #2
0
    def milestone(team_id=None, channel=None, params=None):
        Misc.array_pop(params)  # original slack event object

        if not params or len(params) < 2:
            return send_message(
                ':red_circle: You must provide the following params: `Server Id` and `jira ID`',
                channel, team_id)

        short_id = str(Misc.array_pop(params, 0))
        source = str(Misc.array_pop(params, 0)).upper()

        source_notebook = "icap/gwbot-reporting/TEST-milestones-TEST.ipynb"
        target_notebook = f"icap/gwbot-reporting/{source}.ipynb"

        send_message(f":python: creating milestone view for `{source}`",
                     channel, team_id)  # need to double check

        exec_params = [
            short_id,
            f"!papermill ../../{source_notebook} ../../{target_notebook} -p source {source}",
            {}
        ]
        preview_params = [short_id, f"{target_notebook}", {}]

        Jupyter_Web_Commands.exec(channel=channel, params=exec_params)
        Jupyter_Web_Commands.preview(channel=channel, params=preview_params)
Example #3
0
    def group_by_field(self, root_node, field_name):
        graph = self.graph
        issues = graph.get_nodes_issues()  # resolve current node's issues
        nodes = graph.nodes  # save current nodes
        edges = graph.edges  # save current edges
        graph.nodes = []  # reset nodes
        graph.edges = []  # reset edges
        graph.add_node(root_node)
        if field_name == 'Issue Links':
            for edge in edges:
                link_type = edge[1]
                to_key = edge[2]
                to_issue = Misc.get_value(issues, to_key, {})
                to_key = Misc.get_value(to_issue, 'Key')
                graph.add_node(link_type)
                graph.add_node(to_key)
                graph.add_edge(root_node, '', link_type)
                graph.add_edge(link_type, '', to_key)

        else:
            for node in nodes:
                issue = issues.get(node)
                if issue:
                    value = issue.get(field_name)
                    graph.add_node(value)
                    graph.add_node(node)
                    graph.add_edge(root_node, field_name, value)
                    graph.add_edge(value, '', node)
        return self
Example #4
0
    def cmd_screenshot(self, params, team_id=None, channel=None):
        attachments = []
        if len(params) < 2:
            text = ":exclamation: you must provide an issue id "
        else:
            params.pop(0)  # remove 'issue' command

            issue_id = params.pop(0).upper()
            width = to_int(Misc.array_pop(params), None)
            height = to_int(Misc.array_pop(params), None)
            delay = to_int(Misc.array_pop(params), None)

            text = ':point_right: Getting screenshot for issue `{0}`'.format(
                issue_id)
            if width:
                text += ' with width `{0}`'.format(width)
            if height:
                text += ' and height `{0}`'.format(height)
            if delay:
                text += ' and delay `{0}`'.format(delay)

            payload = {
                'issue_id': issue_id,
                'channel': channel,
                'team_id': team_id,
                'width': width,
                'height': height,
                'delay': delay
            }
            Lambda('osbot_browser.lambdas.jira_web').invoke_async(payload)

        return {"text": text, "attachments": attachments}
Example #5
0
 def test_message_send(self):
     message_1 = Misc.random_string_and_numbers(prefix='Hello_')
     message_2 = Misc.random_string_and_numbers(prefix='World_')
     self.queue.add(body=message_1).add(body=message_2)
     messages = [self.queue.get_message(), self.queue.get_message()]
     assert message_1 in messages
     assert message_2 in messages
     assert self.queue.get_message() is None
Example #6
0
 def test_array_find(self):
     array = ['1', 2, '3']
     self.assertEqual(Misc.array_find(array, '1'), 0)
     self.assertEqual(Misc.array_find(array, 2), 1)
     self.assertEqual(Misc.array_find(array, '3'), 2)
     self.assertEqual(Misc.array_find(array, 'a'), -1)
     self.assertEqual(Misc.array_find(array, None), -1)
     self.assertRaises(Exception, Misc.array_find, None, None)
     self.assertRaises(Exception, Misc.array_find, 'a', None)
    def slack(team_id=None, channel=None, params=None):
        target = Misc.array_pop(params, 0)
        height = Misc.to_int(Misc.array_pop(params, 0))
        width = Misc.to_int(Misc.array_pop(params, 0))
        scroll_by = Misc.to_int(Misc.array_pop(params, 0))
        delay = Misc.to_int(Misc.array_pop(params, 0))

        if target is None: target = 'general'
        if width is None: width = 800
        if height is None: height = 1000
        if scroll_by is None: scroll_by = 0
        if delay is None: delay = 0

        target_url = '/messages/{0}'.format(target)

        slack_message(
            ":point_right: Taking screenshot of slack channel: `{0}` with height `{1}`, width `{2}`, scroll_by `{3}` and delay `{4}`"
            .format(target, height, width, scroll_by,
                    delay), [], channel, team_id)

        payload = {
            'target': target_url,
            'channel': channel,
            'team_id': team_id,
            'width': width,
            'height': height,
            'scroll_by': scroll_by,
            'delay': delay
        }
        aws_lambda = Lambda('osbot_browser.lambdas.slack_web')
        aws_lambda.invoke_async(payload)
    def handle_action(self, event):
        action = Misc.get_value(Misc.array_pop(event.get('actions'), 0),
                                'value')
        try:
            target = getattr(self, action)
        except:
            return self.message_not_supported_action(action)

        try:
            return target(event)
        except Exception as error:
            return self.message_execution_error(error)
Example #9
0
 def test_array_pop(self):
     array = ['1', 2, '3']
     assert Misc.array_pop(array) == '3'
     assert Misc.array_pop(array) == 2
     assert Misc.array_pop(array) == '1'
     assert Misc.array_pop(array) is None
     assert Misc.array_pop(None) is None
     array = ['1', 2, '3']
     assert Misc.array_pop(array, 1) == 2
     assert Misc.array_pop(array, 1) == '3'
     assert Misc.array_pop(array, 1) is None
     assert Misc.array_pop(array, 0) == '1'
     assert Misc.array_pop(array, 0) is None
Example #10
0
    def test_is_number(self):
        assert is_number(42) is True
        assert is_number(4.2) is True
        assert is_number(-1) is True

        assert is_number(True) is False
        assert is_number('42') is False
        assert is_number(None) is False

        assert Misc.is_number(123) is True

        assert Misc.is_number('123') is False
        assert Misc.is_number('abc') is False
        assert Misc.is_number(None) is False
        assert Misc.is_number([]) is False
Example #11
0
    def view_exec_file(team_id=None, channel=None, params=None):
        #event = Misc.array_pop(params)  # original slack event object
        if not params or len(params) < 2:
            build_id = 'gscs'  # for now default to this one
            #return send_message(':red_circle: You must provide the following params: `Server Id`', channel, team_id)
        else:
            build_id = str(Misc.array_pop(params, 0))

        notebook = Live_Notebook()
        if notebook.set_build_from_short_id(build_id) is None:
            return ':red_circle: Could not find Jupyter server with id `{0}`. Please use `jupyter servers` to see the current list of live servers'.format(
                build_id)

        (target_notebook, created) = notebook.get_python_invoke_file()
        send_message(
            ":point_right: Today's python execution file in server `{0}` is `{1}`, here is what it looks like:"
            .format(build_id, target_notebook), channel, team_id)
        width = 1200
        height = 1200
        delay = 2
        png_data = notebook.screenshot(path=target_notebook,
                                       width=width,
                                       height=height,
                                       delay=delay,
                                       apply_ui_fixes=False)

        return send_png_to_slack(png_data, channel, team_id)
Example #12
0
 def transition_to(self, action):
     value_split = action.get('value').split('::')
     issue_id = Misc.array_pop(value_split, 0)
     transition_to = Misc.array_pop(value_split, 0)
     transition_name = Misc.array_pop(value_split, 0)
     try:
         self.api_jira.issue_transition_to_id(issue_id, transition_to)
         self.send_message(
             ':white_check_mark: Changed `{0}` status to: *{1}*. Here are the new transitions available '
             .format(issue_id, transition_name))
         self.create_ui_actions_with_transitions(issue_id,
                                                 transition_name,
                                                 show_intro=False)
     except Exception as error:
         self.send_message(
             ':red_circle: Error in transition_to: {0}'.format(error))
Example #13
0
    def _create_table_with_headers(team_id,
                                   channel,
                                   graph_name,
                                   headers,
                                   columns_defs=[],
                                   table_width='1200px'):
        graph_data = DataTable_Js_Views._get_data(graph_name)
        if graph_data:
            nodes = graph_data.get('nodes')
            rows = []
            for index, node in enumerate(nodes.values()):
                row = [index + 1]
                for header in headers:
                    value = node.get(header)
                    if type(value).__name__ == 'dict':
                        value = json.dumps(value)
                    else:
                        value = Misc.remove_html_tags(value)
                    row.append(value)
                rows.append(row)
            headers.insert(0, '#')

            return DataTable_Js_Views._create_table(
                headers,
                rows,
                team_id,
                channel,
                table_width=table_width,
                columns_defs=columns_defs,
                table_title=
                "<b>{0}</b> <small><small><i>(data from graph)</i></small></small>"
                .format(graph_name))
Example #14
0
 def test_update_to_json_string(self):
     data = {
         'the answer is': 42,
         'random_string': Misc.random_string_and_numbers()
     }
     self.secrets.update_to_json_string(data)
     assert self.secrets.value_from_json_string() == data
Example #15
0
def run(event, context):
    try:
        load_dependencies('requests,syncer,pyppeteer,websocket-client')
        from osbot_jupyter.osbot.Jupyter_Commands import Jupyter_Commands
        params = Misc.get_value(event, 'params', [])
        if not params: params = ['']
        data = event.get('data')
        channel = Misc.get_value(data, 'channel')
        team_id = Misc.get_value(data, 'team_id')
        params.append({"data": data})
        return Slack_Commands_Helper(Jupyter_Commands).invoke(
            team_id, channel, params)
    except Exception as error:
        message = "[lambda_osbot] Error: {0}".format(error)
        #log_to_elk(message, level='error')
        return message
Example #16
0
    def node_label(team_id=None, channel=None, params=None, headless=True):
        if len(params) < 2:
            return "':red_circle: Hi, for the `node_label` view, you need to provide the label field name. Try: `Key`, `Summary`, `Rating`, `Status`"

        label_key = ' '.join(params[1:])

        (graph_name, nodes, edges, graph_data,
         vis_js) = Vis_Js_Views.default(params=params,
                                        no_render=True,
                                        headless=headless)
        graph_name += ' | node_label | ' + label_key
        if graph_data:
            issues = graph_data.get('nodes')
            for node in nodes:
                issue = issues.get(node['label'])
                if issue:
                    value = str(issue.get(label_key))
                    node['label'] = Misc.word_wrap(value, 40)

            for edge in edges:
                del edge['label']

            options = {'nodes': {'shape': 'box'}, 'edges': {'arrows': 'to'}}
            options = None
            return vis_js.create_graph_and_send_screenshot_to_slack(
                graph_name, nodes, edges, options, team_id, channel)
Example #17
0
        def format_node(node):
            issue = graph_data.get('nodes').get(node.get('id'))
            if issue:
                node['label'] = Misc.word_wrap(issue.get('Summary'), 20)
                #node['label'] = issue.get('Rating')
                labels = issue.get('Labels')
                if 'R0' in labels:
                    #node['label'] = issue.get('Summary')
                    node['color'] = '#FF0000'
                    node['font'] = {'color': 'white', 'size': 25}
                    node['mass'] = 2
                    return node

                if 'R1' in labels:
                    node['color'] = '#FF6666'
                    node['font'] = {'size': 20}
                    node['mass'] = 3
                    return node

                if 'R2' in labels:
                    node['color'] = '#FFAAAA'
                    node['font'] = {'size': 15}
                    #node['mass'] = 1
                    return node

                if 'R3' in labels:
                    node['color'] = '#FFDDDD'

                    return node

                if 'R4' in labels:
                    node['color'] = '#00DDDD'

                    return node
Example #18
0
 def __init__(self, web_root=None):
     self.src_tmp = '/tmp/temp_web_server'
     self.python_path = 'python3'
     if web_root: self.web_root = web_root
     else: self.web_root = self.src_tmp + '/html'
     self.html_file = Files.path_combine(self.web_root, 'index.html')
     self.port = Misc.random_number(10000, 60000)
     self.server_proc = None
Example #19
0
 def __init__(self, blocks, action_id=None, block_id=None):
     self.action_id = action_id
     self.block_id = block_id
     self.blocks = blocks
     self.text = None
     self.fields = []
     self.accessory = {}
     if block_id is None:
         self.block_id = Misc.random_string_and_numbers(4, 'block_')
Example #20
0
 def render(self):
     if self.block_id is None:
         self.block_id = Misc.random_string_and_numbers(4, 'block_')
     self.blocks.append({
         "type": "actions",
         "block_id": self.block_id,
         "elements": self.elements
     })
     return self
Example #21
0
    def _test_lambda_write_cloud_watch__with_asserts(self):
        group_name = '/unit-tests/test_log_group'
        stream_name = Misc.random_string_and_numbers(prefix='tmp_stream_')
        message = 'this is a message sent from an lambda function'
        lambda_name = 'osbot_aws.lambdas.dev.write_cloud_watch_log'
        log_group_arn = 'arn:aws:logs:eu-west-2:244560807427:log-group:{0}*'.format(
            group_name)
        policy_name = 'temp_policy_for_lambda_write_cloud_watch'
        role_name = 'temp_role_for_lambda_invocation'
        policy_actions = ['logs:PutLogEvents']

        logs = Logs(group_name=group_name, stream_name=stream_name)
        logs.group_create()
        logs.stream_create()

        iam_role = IAM(role_name=role_name)
        iam_policy = IAM_Policy(policy_name=policy_name)
        iam_policy.add_statement_allow(policy_actions, [log_group_arn])

        policy_arn = iam_policy.create(
            delete_before_create=True).get('policy_arn')

        assert iam_policy.exists() is True
        assert iam_role.role_exists() is True
        assert logs.group_exists() is True
        assert logs.stream_exists() is True
        assert set(iam_role.role_policies()) == {
            'AWSXrayWriteOnlyAccess', 'policy_temp_role_for_lambda_invocation'
        }

        iam_role.role_policy_attach(policy_arn)

        assert set(iam_role.role_policies()) == {
            'AWSXrayWriteOnlyAccess', 'policy_temp_role_for_lambda_invocation',
            'temp_policy_for_lambda_write_cloud_watch'
        }

        sleep(10)  # wait for AWS to propagate role update
        payload = {
            'group_name': group_name,
            'stream_name': stream_name,
            'message': message
        }
        lambda_obj = Lambda_Package(lambda_name)  #.update_with_root_folder()
        result = lambda_obj.invoke(payload)

        sleep(1)  # wait for Cloudwatch to update
        assert result.get('status') == 'ok'
        assert logs.messages() == [message]

        assert iam_policy.delete() is True
        assert logs.group_delete() is True
        assert logs.group_exists() is False
        assert set(iam_role.role_policies()) == {
            'AWSXrayWriteOnlyAccess', 'policy_temp_role_for_lambda_invocation'
        }
Example #22
0
 def __init__(self, file_ids=None, sheet_name=None):
     self.gsuite_secret_id = 'gsuite_gsbot_user'
     self.file_id = Misc.array_get(file_ids, 0)
     self.other_files = file_ids
     self.sheet_name = sheet_name
     self.gsheets = GSheets(self.gsuite_secret_id)
     self.gsheets_sync = API_Jira_Sheets_Sync(self.file_id,
                                              self.gsuite_secret_id)
     self.jira_api_rest = API_Jira_Rest()
     self.gsheets_create = API_Jira_Sheets_Create(self.file_id)
 def files(team_id=None, channel=None, params=None):
     event    = params.pop()                             # needed due to injection of event param
     short_id = Misc.array_pop(params,0)
     target   = " ".join(params)
     if short_id is None:
         return send_message(":red_circle: missing `short id`. The syntax for this method is `contents {short_id} [{path}]`", channel, team_id)
     notebook = Live_Notebook(short_id=short_id)
     text_title, text_body = notebook.files(target)
     attachments = [{'text':text_body, 'color':'good'}]
     slack_message(text_title, attachments,channel,team_id)
Example #24
0
 def __init__(self):
     self.require_js = {
         "paths": {
             "vis":
             "https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min"
         }
     }
     self.div_id = Misc.random_string_and_numbers(prefix='network_')
     #self.test = 42
     self.setup_code = """
Example #25
0
 def test_log_group_create_delete_exists_info(self):
     tmp_log_group = Misc.random_string_and_numbers(
         prefix='/unit-tests/test_log_group_')
     temp_logs = Logs(tmp_log_group, '')
     assert temp_logs.group_exists() is False
     assert temp_logs.group_create() is True
     assert temp_logs.group_exists() is True
     assert temp_logs.group_info().get('logGroupName') == tmp_log_group
     assert temp_logs.group_delete() == True
     assert temp_logs.group_exists() is False
Example #26
0
    def _get_graph_data(params,layout=None, headless=True):
        load_dependencies('syncer,requests,pyppeteer,websocket-client');
        from osbot_browser.view_helpers.Am_Charts import Am_Charts

        am_charts  = Am_Charts(headless=headless,layout=layout)
        graph_name = Misc.array_pop(params,0)
        if graph_name:
            graph_data = am_charts.get_graph_data(graph_name)
            return am_charts, graph_data
        return am_charts,None
Example #27
0
 def test_array_get(self):
     array = ['1', 2, '3']
     assert Misc.array_get(array, 0) == '1'
     assert Misc.array_get(array, 1) == 2
     assert Misc.array_get(array, 2) == '3'
     assert Misc.array_get(array, -1) is None
     assert Misc.array_get(array, 3) is None
     assert Misc.array_get(array, None) is None
     assert Misc.array_get(None, None) is None
Example #28
0
    def exec(team_id=None, channel=None, params=None):
        try:
            event = Misc.array_pop(params)  # original slack event object

            if not params or len(params) < 2:
                return send_message(
                    ':red_circle: You must provide the following params: `Server Id` and `code` (to execute)',
                    channel, team_id)

            short_id = str(Misc.array_pop(params, 0))
            code = ' '.join(params).replace('“',
                                            '"').replace('”', '"').replace(
                                                '‘', "'").replace('’', "'")
            notebook = Live_Notebook()

            if notebook.set_build_from_short_id(short_id) is None:
                return ':red_circle: Could not find Jupyter server with id `{0}`. Please use `jupyter servers` to see the current list of live servers'.format(
                    short_id)

            (target_notebook, created) = notebook.get_python_invoke_file()
            if created:
                send_message(
                    ':point_right: Created temp file for dynamic execution: `{0}`'
                    .format(target_notebook), channel, team_id)

            send_message(
                ':point_right: Running code with size `{0}` on server `{1}` (on file `{2}`)'
                .format(len(code), short_id,
                        target_notebook), channel, team_id)

            result = notebook.execute_python_in_notebook(
                target_notebook, code, event)

            if channel:
                return send_message(
                    ':point_right: Code executed, here is the output:\n ```{0}```'
                    .format(result), channel, team_id)
            else:
                return result
        except Exception as error:
            return send_message(':red_circle: Error: {0}'.format(error),
                                channel, team_id)
Example #29
0
 def render(team_id=None,
            channel=None,
            params=None,
            no_render=False,
            headless=True):
     page = Misc.array_pop(params, 0)
     if page is None:
         return ':red_circle: you need to provide a map to render, try `cup-of-tea`'
     maps = Maps(headless, page)
     maps.load_page(True)
     return maps.send_screenshot_to_slack('not-used', channel)
Example #30
0
 def __init__(self, width="100%", height=800):
     self.frame_id = Misc.random_string_and_numbers(prefix='go_view_')
     self.frame_id = 'go_view_12345'
     self.src = '/view/html/go-js/incremental-tree.html'
     self.nodes = []  # keep track of nodes added
     self.edges = []
     self.link_types = []
     self.width = width
     self.height = height
     self.verbose = False
     pass