def extract_default_earliest_latest(input_element): default = input_element.find("default") if default is not None and list(default.iter()): earliest = get_text(default.find("earliest")) latest = get_text(default.find("latest")) return earliest, latest return "", ""
def extract_dynamic_options(input_element): """ Extract dynamic search options from form input element :param input_element: :return: DynamicOptions object """ field_for_label = get_text(input_element.find("fieldForLabel")) field_for_value = get_text(input_element.find("fieldForValue")) search_element = input_element.find("search") if field_for_label and field_for_value and search_element is not None: v, search = build_dashboard_visualization_search(search_element=search_element) return DynamicOptions(field_for_value, field_for_label, v, search) return None
def extract_choice_value_list(input_element): choice_value_list = input_element.findall("choice") choices = [] for choice in choice_value_list: key = get_text(choice) value = choice.get("value") choices.append(ChoiceValue(key, value)) return choices
def extract_choice_value_map(input_element): choice_value_list = input_element.findall("choice") choice_map = {} for choice in choice_value_list: key = get_text(choice) value = choice.get("value") choice_map[key] = value return choice_map
def populate_meta(root): """ extract dashboard deep link from xml and return Meta object :param root: xml root node :return: """ dashboard_deep_link = root.find("originalDashboardDeepLink") if dashboard_deep_link is None: return None return Meta(get_text(dashboard_deep_link))
def build_eval(eval_element=None): """ Parse <eval> element into a DrillDown Eval object :param eval_element: :return: """ if eval_element is None: return None token = eval_element.attrib.get('token', '') value = get_text(eval_element) return Eval(token=token, value=value)
def build_set(set_element=None): """ Parse <set> element into a DrillDown Set object :param set_element: :return: """ if set_element is None: return None token = set_element.attrib.get('token', '') value = get_text(set_element) return Set(token=token, value=value)
def build_link(link_element=None): """ Parse <link> element into a DrillDown Link object :param link_element: :return: """ if link_element is None: return None target = link_element.attrib.get('target', '') url = get_text(link_element) dashboard_id, input_map = parse_dashboard_link(url=url) link = Link(target=target, url=url, dashboard_id=dashboard_id, input_map=input_map) return link
def to_input_token(input_element): """ Parse an <input> element into and InputToken object :param input_element: :return: """ # If input doesn't have value, skip if input_element is None: return None token = input_element.get("token", "") default = input_element.find("default") input_type = parse_input_type_from_token(input_element) depends = to_token_list(input_element.attrib.get('depends', '')) rejects = to_token_list(input_element.attrib.get('rejects', '')) change_element = input_element.findall("change") # check if default tag has multiple children. If it does, we don't parse it. We only parse it if # the tag is of the form <default>default_value</default> if default is not None and not list(default): default_value = get_text(default) else: default_value = None change = None # Find last change because that's the only one considered valid if change_element: change_element = change_element[-1] change = to_change_condition(change_element) search_when_changed = True if input_element.get( "searchWhenChanged", "").lower().strip() == "true" else False input_token = InputToken(token_name=token, default_value=default_value, input_type=input_type, depends=depends, rejects=rejects, change=change, search_when_changed=search_when_changed) return input_token
async def to_dashboard_definition(request_context=None, app_name="", root=None, dashboard_id="", show_refresh=True, async_splunk_client=None): """ Pass in a Dashboard xml data string, with a dashboard_id to return a Dashboard Definition :param request_context: :param app_name: :param root: :param dashboard_id: :param show_refresh: show refresh params, default True :param async_splunk_client: :return: DashboardDefinition object """ # populate fields description = get_text(root.find('description')) title = get_text(root.find('label')) dashboard_refresh = to_str(root.get('refresh')) # populate meta meta = populate_meta(root) # search_mapper user to resolve inherited search properties like refresh interval search_mapper = None if not dashboard_refresh: search_mapper = SearchMapper() # populate any root searches search_elements = root.findall('search') list_searches = [] for search_element in search_elements: # v, the visualization_id is not used v, search = build_dashboard_visualization_search(search_element=search_element, dashboard_refresh=dashboard_refresh, show_refresh=show_refresh) list_searches.append(search) if search_mapper: search_mapper.add_search_object(search) # populate any input_tokens specified at root in <fieldset> input_token_set = InputTokenSet() fieldset = root.find("fieldset") submit_button = False auto_run = False if fieldset is not None: input_token_set.add_input_element_list(fieldset.findall("input")) submit_button = True if fieldset.get('submitButton', "").lower().strip() == "true" else False auto_run = True if fieldset.get('autoRun', "").lower().strip() == "true" else False # Create DashboardRow List from child element 'row' row_elements = root.findall('row') list_rows = [] ar_compatible_dashboard = True for row_index, row_element in enumerate(row_elements): dashboard_row, ar_compatible_row = await to_dashboard_row(request_context=request_context, app_name=app_name, row_element=row_element, row_index=row_index, dashboard_refresh=dashboard_refresh, show_refresh=show_refresh, search_mapper=search_mapper, async_splunk_client=async_splunk_client) list_rows.append(dashboard_row) # Dashboard is not AR compatible if even one row is AR incompatible if ar_compatible_dashboard and not ar_compatible_row: ar_compatible_dashboard = False # A post processing step to override the refresh, refresh_type for base searches if not dashboard_refresh: search_mapper.update_mappings() # Check if dashboard is AR compatible ar_compatible = input_token_set.are_input_tokens_ar_compatible() and ar_compatible_dashboard return DashboardDefinition(dashboard_id=dashboard_id, title=title, description=description, list_rows=list_rows, refresh=dashboard_refresh, list_searches=list_searches, input_tokens=input_token_set.get_input_tokens(), meta=meta, ar_compatible=ar_compatible, submit_button=submit_button, auto_run=auto_run)
async def to_dashboard_visualization(request_context, app_name, element, row_index, panel_index, visualization_type=common_pb2.DashboardVisualization.DASHBOARD_VISUALIZATION_UNKNOWN, dashboard_refresh=None, show_refresh=True, search_mapper=None, async_splunk_client=None): """ Parse a <chart> element into a DashboardVisualization object :param request_context: :param app_name: :param element: :param row_index: :param panel_index: :param visualization_type: default: DASHBOARD_VISUALIZATION_UNKNOWN :param dashboard_refresh: :param show_refresh: show refresh params, default True :param search_mapper: :param async_splunk_client: :return: """ # Parse title object title = get_text(element.find('title')) # Parse depends depends = to_token_list(element.attrib.get('depends', '')) # Parse rejects rejects = to_token_list(element.attrib.get('rejects', '')) fields_element = element.find('fields') fields = [] fields_visualization_types = [VisualizationType.DASHBOARD_VISUALIZATION_EVENT, VisualizationType.DASHBOARD_VISUALIZATION_TABLE] if fields_element is not None and VisualizationType(visualization_type) in fields_visualization_types: fields = [field.strip() for field in get_text(fields_element).split(',')] # Parse Search Object search_elements = element.findall('search') for search_element in search_elements: search_type = search_element.attrib.get('type', '') if search_type != 'annotation': visualization_id, search = build_dashboard_visualization_search(search_element=search_element, row_index=row_index, panel_index=panel_index, dashboard_refresh=dashboard_refresh, show_refresh=show_refresh) # Only support a single search node so break after finding one break # Populate Options option_elements = element.findall('option') options_map = {option_element.get('name'): to_str(option_element.text) for option_element in option_elements} # Populate Ref Options if search.ref: try: saved_search = await fetch_saved_search(auth_header=request_context.auth_header, owner=request_context.current_user, app_name=app_name, ref=search.ref, async_splunk_client=async_splunk_client) if saved_search and saved_search.name: # This will override values from saved_search options_map with those defined in options_map saved_search.options_map.update(options_map) options_map = saved_search.options_map except SpacebridgeApiRequestError: # Ignore the Exception here as we still want to attempt to parse rest of dashboard pass # Populate Formats format_elements = element.findall('format') list_formats = [build_format(format_element) for format_element in format_elements] # Populate DrillDown drill_down_element = element.find('drilldown') drill_down = build_drill_down(drill_down_element=drill_down_element) # Create Dashboard Visualization dashboard_visualization = DashboardVisualization(visualization_type=visualization_type, title=title, visualization_id=visualization_id, options_map=options_map, search=search, list_formats=list_formats, drill_down=drill_down, depends=depends, rejects=rejects, fields=fields) # Add search to search_mapper if defined if search_mapper: search_mapper.add_search_object(dashboard_visualization) # Check if panel is AR compatible ar_compatible = is_visualization_ar_compatible(dashboard_visualization) return_tuple = (dashboard_visualization, ar_compatible) return return_tuple
async def to_dashboard_panel(request_context, app_name, panel_element, row_index, panel_index, dashboard_refresh=None, show_refresh=True, search_mapper=None, async_splunk_client=None): """ Parse a <panel> element into a DashboardPanel object :param request_context: :param app_name: :param panel_element: :param row_index: :param panel_index: :param dashboard_refresh: :param show_refresh: show refresh params, default True :param search_mapper: :param async_splunk_client: :return: """ # populate input_tokens input_token_set = InputTokenSet() input_token_set.add_input_element_list(panel_element.findall('input')) # Set Panel Title title = get_text(panel_element.find('title')) # Add depends depends = to_token_list(panel_element.attrib.get('depends', '')) # Add rejects rejects = to_token_list(panel_element.attrib.get('rejects', '')) # Process different visualization types visualizations = [] ar_compatible_panel = True for child_element in panel_element: visualization_type = None if child_element.tag == 'chart': visualization_type = common_pb2.DashboardVisualization.DASHBOARD_VISUALIZATION_CHART elif child_element.tag == 'map': visualization_type = common_pb2.DashboardVisualization.DASHBOARD_VISUALIZATION_MAP elif child_element.tag == 'single': visualization_type = common_pb2.DashboardVisualization.DASHBOARD_VISUALIZATION_SINGLE elif child_element.tag == 'table': visualization_type = common_pb2.DashboardVisualization.DASHBOARD_VISUALIZATION_TABLE elif child_element.tag == 'event': visualization_type = common_pb2.DashboardVisualization.DASHBOARD_VISUALIZATION_EVENT if visualization_type: visualization, ar_compatible_visualization = await to_dashboard_visualization( request_context=request_context, app_name=app_name, element=child_element, row_index=row_index, panel_index=panel_index, visualization_type=visualization_type, dashboard_refresh=dashboard_refresh, show_refresh=show_refresh, search_mapper=search_mapper, async_splunk_client=async_splunk_client) visualizations.append(visualization) # Panel is not AR compatible if even one visualization is AR incompatible if ar_compatible_panel and not ar_compatible_visualization: ar_compatible_panel = False dashboard_panel = DashboardPanel(title=title, list_dashboard_visualizations=visualizations, depends=depends, rejects=rejects, input_tokens=input_token_set.get_input_tokens()) return_tuple = (dashboard_panel, ar_compatible_panel) return return_tuple
def extract_default_value(input_element): return get_text(input_element.find("default"))
async def to_dashboard_description(json_object, is_ar=False, request_context=None, async_splunk_client=None, show_refresh=True): """ Parse a dashboard json object and return a DashboardDescription :param json_object: [dict] representing json object :param is_ar: if true, only return dashboard description if the dashboard is AR compatible :param request_context: :param async_splunk_client: :param show_refresh: show refresh params, default True :return: """ if json_object is not None and isinstance(json_object, dict): dashboard_id = helper.shorten_dashboard_id_from_url( get_string(json_object.get('id'))) name = get_string(json_object.get('name')) content = json_object.get('content') acl = json_object.get('acl') if acl is not None: app_name = get_string(acl.get('app')) if content is not None: title = get_string(content.get('label')) description = get_string(content.get('description')) dashboard_type = get_string(content.get('eai:type')) # TODO: Client not using currently, figure out how to fill out uses_custom_css = False uses_custom_javascript = False uses_custom_visualization = False uses_custom_html = dashboard_type == 'html' # Pull out dashboard xml data and parse to get DashboardDefinition dashboard_xml_data = content.get('eai:data') # If the dashboard version > 1, it's a UDF dashboard if 'version' in content and parse_version(str(content.get('version'))) > parse_version("1") \ and dashboard_xml_data: root = get_root_element(dashboard_xml_data) jsn = json.loads( parse_helpers.get_text(root.find('definition'))) definition = UdfDashboardDescription.from_json(jsn) definition.dashboard_id = dashboard_id elif dashboard_xml_data and dashboard_type == 'views': root_element = get_root_element(dashboard_xml_data) definition = await to_dashboard_definition( request_context=request_context, app_name=app_name, root=root_element, dashboard_id=dashboard_id, show_refresh=show_refresh, async_splunk_client=async_splunk_client) if is_ar and (not definition.ar_compatible or is_legacy_ar_dashboard(name, app_name)): return None else: definition = DashboardDefinition(dashboard_id=dashboard_id, title=title, description=description) # Populate display_app_name display_app_name = "" if async_splunk_client is not None: display_app_name = await fetch_display_app_name( request_context=request_context, app_name=app_name, async_splunk_client=async_splunk_client) input_tokens = definition.input_tokens if hasattr( definition, 'input_tokens') else {} meta = definition.meta if hasattr(definition, 'meta') else None submit_button = definition.submit_button if hasattr( definition, 'submit_button') else False auto_run = definition.auto_run if hasattr(definition, 'auto_run') else False dashboard_description = DashboardDescription( dashboard_id=dashboard_id, title=title, description=description, app_name=app_name, display_app_name=display_app_name, uses_custom_css=uses_custom_css, uses_custom_javascript=uses_custom_javascript, uses_custom_visualization=uses_custom_visualization, uses_custom_html=uses_custom_html, input_tokens=input_tokens, meta=meta, definition=definition, submit_button=submit_button, auto_run=auto_run) return dashboard_description # Return empty proto in default case return DashboardDescription()
def build_dashboard_visualization_search(search_element=None, row_index=0, panel_index=0, dashboard_refresh=None, show_refresh=True): """ Parse a <search> element into Search object :param search_element: :param row_index: :param panel_index: :param dashboard_refresh: :param show_refresh: show refresh params, default True :return: """ # Return Query Value query = '' earliest = '' latest = '' search = None if search_element is not None: earliest = get_text(search_element.find('earliest')) latest = get_text(search_element.find('latest')) sample_ratio = get_int(search_element.find('sampleRatio'), 0) post_search = get_text(search_element.find('postSearch')) query = dashboard_query_to_spl(get_text(search_element.find('query'))) ref = search_element.attrib.get('ref', '') base = search_element.attrib.get('base', '') id = search_element.attrib.get('id', '') depends = to_token_list(search_element.attrib.get('depends', '')) rejects = to_token_list(search_element.attrib.get('rejects', '')) # Only store values if show_refresh if show_refresh: if dashboard_refresh: refresh = dashboard_refresh refresh_type = common_pb2.DashboardVisualization.Search.REFRESH_TYPE_DELAY else: refresh = get_text(search_element.find('refresh')) refresh_type = string_to_refresh_type( get_text(search_element.find('refreshType'))) else: refresh = '' refresh_type = common_pb2.DashboardVisualization.Search.REFRESH_TYPE_UNKNOWN # Populate Search object search = Search(earliest=earliest, latest=latest, refresh=refresh, refresh_type=refresh_type, sample_ratio=sample_ratio, post_search=post_search, query=query, ref=ref, base=base, id=id, depends=depends, rejects=rejects) return generate_visualization_id(earliest=earliest, latest=latest, query=query, refresh=refresh, refresh_type=refresh_type, sample_ratio=sample_ratio, row_index=row_index, panel_index=panel_index, ref=ref), search
def extract_value(element, value_name): return get_text(element.find(value_name))
def extract_label(input_element): return get_text(input_element.find("label"))