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)
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 test_from_gs_graph(self): graph = Graph() #graph_name = 'graph_QIN' # (SOW-18 128 nodes) #graph_name = 'graph_YXT' # person-42 (manages, 43 nodes) #graph_name = 'graph_CXJ' # Playbook-2 (103 nodes) graph_name = 'graph_SCE' # PERSON-4 (8 nodes) graph_dot = Lambda_Graph().get_graph_dot(graph_name) (graph_dot.set_layout_engine_dot().render_svg_to_file(self.svg_file))
def project_schema(project_name): jp_graph = Jp_Graph_Data() api_issues = jp_graph.api_issues elk_to_slack = jp_graph.elk_to_slack issues = api_issues.search_using_lucene(f'Project:{project_name.upper()}') graph_name = elk_to_slack.save_issues_as_new_graph(issues) Lambda_Graph().wait_for_elk_to_index_graph(graph_name) graph = jp_graph.jira_links(graph_name) display(HTML(f"<h2>{project_name}</h2>")) render_puml(Graph_View(graph).view_schema())
def run(event, context): try: load_dependencies( 'elastic,slack,requests' ) # load dependency (download and unzip if first run) from osbot_jira.api.graph.Lambda_Graph import Lambda_Graph # import Lambda_Graph class return Lambda_Graph().handle_lambda_event( event) # invoke lambda handler from Lambda_Graph class except Exception as error: return ":red_circle: error in `osbot_jira.lambdas.graph`: {0}".format( error)
def render_and_save_to_elk( self, graph_name=None, graph_type=None, channel=None, user=None): # might need to move this to a Lambda function from osbot_jira.api.graph.Lambda_Graph import Lambda_Graph # todo: find out why this needs to be here of it fail to load the dependency (could be caused by a cyclic dependency) lambda_graph = Lambda_Graph() graph_name = lambda_graph.save_gs_graph(self, graph_name, graph_type, channel, user) if lambda_graph.wait_for_elk_to_index_graph( graph_name ): # wait for ELK to index the graph (to prevent a fetch before the data is available in ELK) return graph_name return None
def raw_data(team_id=None, channel=None, params=None, data=None): data = None text = None attachments = [] if len(params) < 1: text = ':red_circle: Hi, for the `data` command, you need to provide a graph name' else: graph_name = params.pop(0) graph = Lambda_Graph().get_gs_graph___by_name(graph_name) if graph: data = { 'graph_name': graph_name, 'nodes': graph.nodes, 'edges': graph.edges } if len(params) == 1 and params.pop(0) == 'details': data['nodes'] = graph.get_nodes_issues() s3_bucket = 'gw-bot-lambdas' import tempfile with tempfile.NamedTemporaryFile(suffix='.json') as temp: temp.write(str.encode(json.dumps(data))) temp.flush() data = S3().file_upload_as_temp_file( temp.name, s3_bucket) attachments = [{ "color": "good", "text": "{0}".format(pprint.pformat(data)) }] else: from osbot_jira.api.API_Issues import API_Issues # if a graph wasn't found try to get the issue with that name issue = API_Issues().issue(graph_name) if issue: data = { 'nodes': { graph_name: issue }, # return as the first node 'edges': [] # with no edges } else: text = ':red_circle: Graph or issue with name `{0}` not found! Use the command `graph last` to see a list of the latest graphs generated'.format( graph_name) slack_message(text, attachments, channel, team_id) return data
def render_view(self, view_name, slack_channel=None, team_id=None, graph_name=None): if self.graph: try: method_name = "view_{0}".format(view_name) method = getattr(Graph_View, method_name) try: if slack_channel: slack_message( "Generating view `{0}` for graph with `{1}` nodes and `{2}` edges" .format(view_name, len(self.graph.nodes), len(self.graph.edges)), [], slack_channel, team_id) method(self) if slack_channel: saved_graph = Lambda_Graph().save_gs_graph( self.graph, None, "{0} - {0}".format(view_name, graph_name), slack_channel) slack_message( "Saved view `{0}` as new graph `{1}`".format( view_name, saved_graph), [], slack_channel, team_id) except Exception as error: slack_message( ":red_circle: Error executing view `{0}`".format( view_name), [{ "text": "{0}".format(error) }], slack_channel, team_id) except Exception: slack_message( ":red_circle: view not found: `{0}`".format(view_name), [], slack_channel, team_id) slack_message(self.bad_params_message(), [], slack_channel, team_id) return self
def plantuml(team_id, channel, params, data): puml = '' attachments = [] if len(params) < 1: text = ':red_circle: Hi, for the `plantuml` command, you need to provide a graph name' else: graph_name = params.pop() graph = Lambda_Graph().get_gs_graph___by_name(graph_name) if graph: puml = graph.puml.puml text = 'Here is the PlantUml code for `{0}`'.format(graph_name) attachments = [{ "color": "good", "text": "```{0}```".format(puml) }] else: text = ':red_circle: Graph with name `{0}` not found! Use the command `graph last` to see a list of the latest graphs generated'.format( graph_name) slack_message(text, attachments, channel, team_id) return puml
def last(team_id, channel, params, data=None): n = 10 if len(params) == 1: n = int(params.pop()) graphs = Lambda_Graph().get_last_n_graphs_of_type('lambda_graph', n) row_separator = '|{0}|\n'.format("-" * 72) row_format = '| {0:2} | {1:9} | {2:5} | {3:5} | {4:24} | {5:10} |\n' graphs_text = '```' graphs_text += row_format.format('#', ' who ', 'nodes', 'edges', ' type', ' name') graphs_text += row_separator count = 1 for graph in graphs: graph_value = graph.get('value') graph_name = graph_value.get('doc_data').get('name') graph_type = graph_value.get('doc_data').get('type') extra_data = graph_value.get('doc_data').get('extra_data') user = extra_data.get('user') nodes = extra_data.get('stats').get('count_nodes') edges = extra_data.get('stats').get('count_edges') if user is None: user = "******" if graph_type is None: graph_type = "...." if graph_name is None: graph_name = "" graphs_text += row_format.format(count, user, nodes, edges, graph_type[0:24], graph_name[0:10]) count += 1 graphs_text += '```' attachments = API_Slack_Attachment(graphs_text, 'good').render() if channel: slack_message( '*Here are the last {0} graphs generated* (use `graph last n` to see more results)' .format(n), attachments, channel, team_id) else: return attachments
def __init__(self, graph=None): self.graph = graph self.lambda_graph = Lambda_Graph()
def _save_graph(graph): graph.reset_puml().render_puml() # re-render puml return Lambda_Graph().save_gs_graph(graph) # save graph and return new graph name
def _get_graph(graph_name): return Lambda_Graph().get_gs_graph___by_name(graph_name)
def viva_graph(graph, height=None): view_name = 'default' graph_name = Lambda_Graph().save_gs_graph(graph) view.show(['viva_graph', graph_name, view_name], height)
def chord(graph, height=None): graph_name = Lambda_Graph().save_gs_graph(graph) view.show(['am_charts', graph_name, 'chord'], height)
def node_label(graph, label, height=None): graph_name = Lambda_Graph().save_gs_graph(graph) view.show(['graph', graph_name, 'node_label', label], height)
def cmd_links(self, params, team_id=None, channel=None, user=None, only_create=False, save_graph=True): if len(params) < 2: text = ':point_right: Hi, here are the valid parameters for the `jira links` command: ' \ '\n\t\t - `jira key` ' \ '\n\t\t - `depth` (default to 1)' \ '\n\t\t - `view engine`: viva_graph (default), or plantuml' \ '\n\t\t - `width` (of graph)' \ '\n\t\t - `delay` (before screenshot)' return {"text": text, "attachments": []} target = array_get(params, 1) depth = to_int(array_get(params, 2), 1) # default to depth 1 view_engine = array_get(params, 3, 'viva_graph') width = to_int(array_get(params, 4), None) delay = to_int(array_get(params, 5), None) if depth > 5: text = f':red_circle: sorry depths bigger than 5 are not supported (since 5 will already give you the only graph)' return {"text": text, "attachments": []} #direction = 'all' # change behaviour to only show all graph = Lambda_Graph().graph_links(target, depth) if graph is None: text = f':red_circle: graph not created for target `{target}`' return {"text": text, "attachments": []} if len(graph.edges) == 0: text = f':red_circle: no graph created from `{target}` (please double check that the issue ID exists)' return {"text": text, "attachments": []} graph_type = f"{target}___depth_{depth}" if save_graph is False: return graph graph_name = graph.render_and_save_to_elk(None, graph_type, channel, user) if only_create: return graph, graph_name, depth, target if channel: message = f':point_right: Created graph with *name* `{graph_name}` *from* `{target}` *depth* `{depth}`' slack_message(message, [], channel) if view_engine == 'plantuml': params = ['show', graph_name, view_engine] Lambda('osbot_jira.lambdas.graph').invoke_async({ "params": params, 'data': { 'team_id': team_id, 'channel': channel } }) else: params = [view_engine, graph_name, 'default', width, delay] Lambda('osbot_browser.lambdas.lambda_browser').invoke_async({ "params": params, 'data': { 'team_id': team_id, 'channel': channel } }) else: return graph, graph_name, depth, target
def show(team_id, channel, params, data=None): if len(params) < 1: text = ':red_circle: Hi, for the `show` command, you need to provide an `graph_name`' slack_message(text, [], channel, team_id) return graph_name = Misc.array_pop(params, 0) graph = Lambda_Graph().get_gs_graph___by_name(graph_name) if graph is None: text = ':red_circle: Graph with name `{0}` not found'.format( graph_name) slack_message(text, [], channel, team_id) else: default_engine = 'viva_graph' engines = Misc.array_pop(params, 0) if engines is None: engines = default_engine if engines != default_engine: # only show in case there is more than one engine text = f":point_right: Showing graph with name `{graph_name}`, with `{len(graph.nodes)}` nodes and `{len(graph.edges)}` edges)" slack_message(text, [], channel, team_id) if 'plantuml' in engines: slack_message('...using `plantuml`', [], channel, team_id) Lambda('gw_bot.lambdas.puml_to_slack').invoke_async({ "puml": graph.get_puml(), "channel": channel, "team_id": team_id }) if 'vis_js' in engines: slack_message('...using `vis_js`', [], channel, team_id) params = ['graph', graph_name, 'default'] Lambda('osbot_browser.lambdas.lambda_browser').invoke_async({ "params": params, 'data': { 'team_id': team_id, 'channel': channel } }) if 'viva_graph' in engines: if engines != default_engine: # only show in case there is more than one engine slack_message('...using `viva_graph`', [], channel, team_id) params = ['viva_graph', graph_name, 'default'] Lambda('osbot_browser.lambdas.lambda_browser').invoke_async({ "params": params, 'data': { 'team_id': team_id, 'channel': channel } }) if 'go_js' in engines: slack_message('...using `go_js`', [], channel, team_id) params = ['go_js', graph_name, 'circular'] Lambda('osbot_browser.lambdas.lambda_browser').invoke_async({ "params": params, 'data': { 'team_id': team_id, 'channel': channel } })
def show_graph(graph_name, height=500): print('creating plantuml graph for: {0}'.format(graph_name)) png_data = Lambda_Graph().get_graph_png___by_name(graph_name).get( 'png_base64') show_png(png_data, height)
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)
def setUp(self): super().setUp() self.lambda_graph = Lambda_Graph()
def save_graph(graph): return Lambda_Graph().save_gs_graph(graph)
def graph(graph_name): print('creating plantuml graph for: {0}'.format(graph_name)) from osbot_jira.api.graph.Lambda_Graph import Lambda_Graph png_data = Lambda_Graph().get_graph_png___by_name(graph_name).get( 'png_base64') Jp_Helper.show_png(png_data)
def go_js(graph, view_name, height=None): graph_name = Lambda_Graph().save_gs_graph(graph) view.show(['go_js', graph_name, view_name], height)
def lambda_graph(self): if self._lambda_graph is None: self._lambda_graph = Lambda_Graph() return self._lambda_graph
def table(graph, view_name, height=None): graph_name = Lambda_Graph().save_gs_graph(graph) view.show(['table', graph_name, view_name], height)