Get all splunk search details. Produces results that can be used to create
    an sls file.

    if app or owner are specified, results will be limited to matching saved
    searches.

    if description_contains is specified, results will be limited to those
    where "description_contains in description" is true if name_not_contains is
    specified, results will be limited to those where "name_not_contains not in
    name" is true.

    If prefix parameter is given, alarm names in the output will be prepended
    with the prefix; alarms that have the prefix will be skipped. This can be
    used to convert existing alarms to be managed by salt, as follows:

    CLI example:

            1. Make a "backup" of all existing searches
                $ salt-call splunk_search.list_all --out=txt | sed "s/local: //" > legacy_searches.sls

            2. Get all searches with new prefixed names
                $ salt-call splunk_search.list_all "prefix=**MANAGED BY SALT** " --out=txt | sed "s/local: //" > managed_searches.sls

            3. Insert the managed searches into splunk
                $ salt-call state.sls managed_searches.sls

            4.  Manually verify that the new searches look right

            5.  Delete the original searches
                $ sed s/present/absent/ legacy_searches.sls > remove_legacy_searches.sls
                $ salt-call state.sls remove_legacy_searches.sls

            6.  Get all searches again, verify no changes
                $ salt-call splunk_search.list_all --out=txt | sed "s/local: //" > final_searches.sls
                $ diff final_searches.sls managed_searches.sls

def list_all(prefix=None, app=None, owner=None, description_contains=None,
             name_not_contains=None, profile="splunk"):
    '''
    Get all splunk search details. Produces results that can be used to create
    an sls file.

    if app or owner are specified, results will be limited to matching saved
    searches.

    if description_contains is specified, results will be limited to those
    where "description_contains in description" is true if name_not_contains is
    specified, results will be limited to those where "name_not_contains not in
    name" is true.

    If prefix parameter is given, alarm names in the output will be prepended
    with the prefix; alarms that have the prefix will be skipped. This can be
    used to convert existing alarms to be managed by salt, as follows:

    CLI example:

            1. Make a "backup" of all existing searches
                $ salt-call splunk_search.list_all --out=txt | sed "s/local: //" > legacy_searches.sls

            2. Get all searches with new prefixed names
                $ salt-call splunk_search.list_all "prefix=**MANAGED BY SALT** " --out=txt | sed "s/local: //" > managed_searches.sls

            3. Insert the managed searches into splunk
                $ salt-call state.sls managed_searches.sls

            4.  Manually verify that the new searches look right

            5.  Delete the original searches
                $ sed s/present/absent/ legacy_searches.sls > remove_legacy_searches.sls
                $ salt-call state.sls remove_legacy_searches.sls

            6.  Get all searches again, verify no changes
                $ salt-call splunk_search.list_all --out=txt | sed "s/local: //" > final_searches.sls
                $ diff final_searches.sls managed_searches.sls
    '''
    client = _get_splunk(profile)

    # splunklib doesn't provide the default settings for saved searches.
    # so, in order to get the defaults, we create a search with no
    # configuration, get that search, and then delete it. We use its contents
    # as the default settings
    name = "splunk_search.list_all get defaults"
    try:
        client.saved_searches.delete(name)
    except Exception:
        pass
    search = client.saved_searches.create(name, search="nothing")
    defaults = dict(search.content)
    client.saved_searches.delete(name)

    # stuff that splunk returns but that you should not attempt to set.
    # cf http://dev.splunk.com/view/python-sdk/SP-CAAAEK2
    readonly_keys = ("triggered_alert_count",
                     "action.email",
                     "action.populate_lookup",
                     "action.rss",
                     "action.script",
                     "action.summary_index",
                     "qualifiedSearch",
                     "next_scheduled_time")

    results = OrderedDict()
    # sort the splunk searches by name, so we get consistent output
    searches = sorted([(s.name, s) for s in client.saved_searches])
    for name, search in searches:
        if app and search.access.app != app:
            continue
        if owner and search.access.owner != owner:
            continue
        if name_not_contains and name_not_contains in name:
            continue
        if prefix:
            if name.startswith(prefix):
                continue
            name = prefix + name
        # put name in the OrderedDict first
        d = [{"name": name}]
        # add the rest of the splunk settings, ignoring any defaults
        description = ''
        for (k, v) in sorted(search.content.items()):
            if k in readonly_keys:
                continue
            if k.startswith("display."):
                continue
            if not v:
                continue
            if k in defaults and defaults[k] == v:
                continue
            d.append({k: v})
            if k == 'description':
                description = v
        if description_contains and description_contains not in description:
            continue
        results["manage splunk search " + name] = {"splunk_search.present": d}

    return salt.utils.yaml.safe_dump(results, default_flow_style=False, width=120)