Execute a runner function. This function must be run on the master,
    either by targeting a minion running on a master or by using
    salt-call on a master.

    .. versionadded:: 2014.7.0

    name
        The name of the function to run

    kwargs
        Any keyword arguments to pass to the runner function

    asynchronous
        Run the salt command but don't wait for a reply.

        .. versionadded:: neon

    CLI Example:

    In this example, assume that `master_minion` is a minion running
    on a master.

    .. code-block:: bash

        salt master_minion saltutil.runner jobs.list_jobs
        salt master_minion saltutil.runner test.arg arg="['baz']" kwarg="{'foo': 'bar'}"

def runner(name, arg=None, kwarg=None, full_return=False, saltenv='base', jid=None, asynchronous=False, **kwargs):
    '''
    Execute a runner function. This function must be run on the master,
    either by targeting a minion running on a master or by using
    salt-call on a master.

    .. versionadded:: 2014.7.0

    name
        The name of the function to run

    kwargs
        Any keyword arguments to pass to the runner function

    asynchronous
        Run the salt command but don't wait for a reply.

        .. versionadded:: neon

    CLI Example:

    In this example, assume that `master_minion` is a minion running
    on a master.

    .. code-block:: bash

        salt master_minion saltutil.runner jobs.list_jobs
        salt master_minion saltutil.runner test.arg arg="['baz']" kwarg="{'foo': 'bar'}"
    '''
    if arg is None:
        arg = []
    if kwarg is None:
        kwarg = {}
    jid = kwargs.pop('__orchestration_jid__', jid)
    saltenv = kwargs.pop('__env__', saltenv)
    kwargs = salt.utils.args.clean_kwargs(**kwargs)
    if kwargs:
        kwarg.update(kwargs)

    if 'master_job_cache' not in __opts__:
        master_config = os.path.join(os.path.dirname(__opts__['conf_file']),
                                     'master')
        master_opts = salt.config.master_config(master_config)
        rclient = salt.runner.RunnerClient(master_opts)
    else:
        rclient = salt.runner.RunnerClient(__opts__)

    if name in rclient.functions:
        aspec = salt.utils.args.get_function_argspec(rclient.functions[name])
        if 'saltenv' in aspec.args:
            kwarg['saltenv'] = saltenv

    if name in ['state.orchestrate', 'state.orch', 'state.sls']:
        kwarg['orchestration_jid'] = jid

    if jid:
        salt.utils.event.fire_args(
            __opts__,
            jid,
            {'type': 'runner', 'name': name, 'args': arg, 'kwargs': kwarg},
            prefix='run'
        )

    if asynchronous:
        master_key = salt.utils.master.get_master_key('root', __opts__)
        low = {'arg': arg, 'kwarg': kwarg, 'fun': name, 'key': master_key}
        return rclient.cmd_async(low)
    else:
        return rclient.cmd(name,
                           arg=arg,
                           kwarg=kwarg,
                           print_event=False,
                           full_return=full_return)