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 "", ""
예제 #2
0
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
예제 #5
0
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))
예제 #6
0
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)
예제 #7
0
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
예제 #10
0
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)
예제 #11
0
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
예제 #12
0
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"))
예제 #14
0
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()
예제 #15
0
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"))