Kill the salt minion.

    timeout
        int seconds to wait for the minion to die.

    If you have a monitor that restarts ``salt-minion`` when it dies then this is
    a great way to restart after a minion upgrade.

    CLI example::

        >$ salt minion[12] minion.kill
        minion1:
            ----------
            killed:
                7874
            retcode:
                0
        minion2:
            ----------
            killed:
                29071
            retcode:
                0

    The result of the salt command shows the process ID of the minions and the
    results of a kill signal to the minion in as the ``retcode`` value: ``0``
    is success, anything else is a failure.

def kill(timeout=15):
    '''
    Kill the salt minion.

    timeout
        int seconds to wait for the minion to die.

    If you have a monitor that restarts ``salt-minion`` when it dies then this is
    a great way to restart after a minion upgrade.

    CLI example::

        >$ salt minion[12] minion.kill
        minion1:
            ----------
            killed:
                7874
            retcode:
                0
        minion2:
            ----------
            killed:
                29071
            retcode:
                0

    The result of the salt command shows the process ID of the minions and the
    results of a kill signal to the minion in as the ``retcode`` value: ``0``
    is success, anything else is a failure.
    '''

    ret = {
        'killed': None,
        'retcode': 1,
    }
    comment = []
    pid = __grains__.get('pid')
    if not pid:
        comment.append('Unable to find "pid" in grains')
        ret['retcode'] = salt.defaults.exitcodes.EX_SOFTWARE
    else:
        if 'ps.kill_pid' not in __salt__:
            comment.append('Missing command: ps.kill_pid')
            ret['retcode'] = salt.defaults.exitcodes.EX_SOFTWARE
        else:
            # The retcode status comes from the first kill signal
            ret['retcode'] = int(not __salt__['ps.kill_pid'](pid))

            # If the signal was successfully delivered then wait for the
            # process to die - check by sending signals until signal delivery
            # fails.
            if ret['retcode']:
                comment.append('ps.kill_pid failed')
            else:
                for _ in range(timeout):
                    time.sleep(1)
                    signaled = __salt__['ps.kill_pid'](pid)
                    if not signaled:
                        ret['killed'] = pid
                        break
                else:
                    # The process did not exit before the timeout
                    comment.append('Timed out waiting for minion to exit')
                    ret['retcode'] = salt.defaults.exitcodes.EX_TEMPFAIL

    if comment:
        ret['comment'] = comment
    return ret