# Buggy code
def returner(ret):
    """
    Process the return from Salt
    """
    job_fun = ret["fun"]
    job_fun_escaped = job_fun.replace(".", "_")
    job_id = ret["jid"]
    job_minion_id = ret["id"]
    job_success = True if ret["return"] else False
    job_retcode = ret.get("retcode", 1)

    index = "salt-{0}".format(job_fun_escaped)
    if __salt__["config.option"]("elasticsearch:index_date", False):
        index = "{0}-{1}".format(index, datetime.date.today().strftime("%Y.%m.%d"))
    functions_blacklist = __salt__["config.option"](
        "elasticsearch:functions_blacklist", []
    )
    doc_type_version = __salt__["config.option"]("elasticsearch:doc_type", "default")

    if job_fun in functions_blacklist:
        log.info(
            "Won't push new data to Elasticsearch, job with jid={0} and "
            "function={1} which is in the user-defined list of ignored "
            "functions".format(job_id, job_fun)
        )
        return

    if not job_success:
        log.info(
            "Won't push new data to Elasticsearch, job with jid={0} was "
            "not succesful".format(job_id)
        )
        return

    _ensure_index(index)

    class UTC(tzinfo):
        def utcoffset(self, dt):
            return timedelta(0)

        def tzname(self, dt):
            return "UTC"

        def dst(self, dt):
            return timedelta(0)

    utc = UTC()

    data = {
        "@timestamp": datetime.now(utc).isoformat(),
        "success": job_success,
        "retcode": job_retcode,
        "minion": job_minion_id,
        "fun": job_fun,
        "jid": job_id,
        "data": ret["return"],
    }

    ret = __salt__["elasticsearch.document_create"](
        index=index, doc_type=doc_type_version, body=json.dumps(data)
    )


# Traceback (TransportError)
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: [ERROR   ] Error in function _return:
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: Traceback (most recent call last):
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: File "/usr/lib/python2.7/site-packages/salt/master.py", line 1543, in run_func
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: ret = getattr(self, func)(load)
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: File "/usr/lib/python2.7/site-packages/salt/master.py", line 1356, in _return
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: self.opts, load, event=self.event, mminion=self.mminion)
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: File "/usr/lib/python2.7/site-packages/salt/utils/job.py", line 90, in store_job
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: mminion.returners[fstr](load)
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: File "/usr/lib/python2.7/site-packages/salt/returners/elasticsearch_return.py", line 112, in returner
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: ret = __salt__['elasticsearch.document_create'](index=index, doc_type=doc_type_version, body=json.dumps(data))
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: File "/usr/lib/python2.7/site-packages/salt/modules/elasticsearch.py", line 187, in document_create
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: result = es.index(index=index, doc_type=doc_type, body=body, id=id)  # TODO error handling
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: File "/usr/lib/python2.7/site-packages/elasticsearch/client/utils.py", line 69, in _wrapped
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: return func(*args, params=params, **kwargs)
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: File "/usr/lib/python2.7/site-packages/elasticsearch/client/__init__.py", line 279, in index
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: _make_path(index, doc_type, id), params=params, body=body)
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: File "/usr/lib/python2.7/site-packages/elasticsearch/transport.py", line 327, in perform_request
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: status, headers, data = connection.perform_request(method, url, params, body, ignore=ignore, timeout=timeout)
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: File "/usr/lib/python2.7/site-packages/elasticsearch/connection/http_urllib3.py", line 109, in perform_request
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: self._raise_error(response.status, raw_data)
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: File "/usr/lib/python2.7/site-packages/elasticsearch/connection/base.py", line 113, in _raise_error
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: raise HTTP_EXCEPTIONS.get(status_code, TransportError)(status_code, error_message, additional_info)
Sep 14 23:17:16 ip-10-0-6-115.us-west-2.compute.internal salt-master[25533]: RequestError: TransportError(400, u'mapper_parsing_exception', u"Field name [file_|-Setup systemd_|-/etc/systemd/systemd.conf_|-managed] cannot contain '.'")

# Fixed code
def returner(ret):
    """
    Process the return from Salt
    """
    job_fun = ret["fun"]
    job_fun_escaped = job_fun.replace(".", "_")
    job_id = ret["jid"]
    job_minion_id = ret["id"]
    job_success = True if ret["return"] else False
    job_retcode = ret.get("retcode", 1)

    index = "salt-{0}".format(job_fun_escaped)
    if __salt__["config.option"]("elasticsearch:index_date", False):
        index = "{0}-{1}".format(index, datetime.date.today().strftime("%Y.%m.%d"))
    functions_blacklist = __salt__["config.option"](
        "elasticsearch:functions_blacklist", []
    )
    doc_type_version = __salt__["config.option"]("elasticsearch:doc_type", "default")

    if job_fun in functions_blacklist:
        log.info(
            "Won't push new data to Elasticsearch, job with jid={0} and "
            "function={1} which is in the user-defined list of ignored "
            "functions".format(job_id, job_fun)
        )
        return

    if not job_success:
        log.info(
            "Won't push new data to Elasticsearch, job with jid={0} was "
            "not succesful".format(job_id)
        )
        return

    _ensure_index(index)

    class UTC(tzinfo):
        def utcoffset(self, dt):
            return timedelta(0)

        def tzname(self, dt):
            return "UTC"

        def dst(self, dt):
            return timedelta(0)

    if isinstance(ret["return"], dict):
        sk = ""
        for k in ret["return"].keys():
            sk = k.replace(".", "_")
            ret["return"][sk] = ret["return"].pop(k)

    utc = UTC()
    data = {
        "@timestamp": datetime.now(utc).isoformat(),
        "success": job_success,
        "retcode": job_retcode,
        "minion": job_minion_id,
        "fun": job_fun,
        "jid": job_id,
        "data": ret["return"],
    }

    ret = __salt__["elasticsearch.document_create"](
        index=index, doc_type=doc_type_version, body=json.dumps(data)
    )