Put values into Consul

    :param consul_url: The Consul server URL.
    :param key: The key to use as the starting point for the list.
    :param value: The value to set the key to.
    :param flags: This can be used to specify an unsigned value
                  between 0 and 2^64-1. Clients can choose to use
                  this however makes sense for their application.
    :param cas: This flag is used to turn the PUT into a
                Check-And-Set operation.
    :param acquire: This flag is used to turn the PUT into a
                    lock acquisition operation.
    :param release: This flag is used to turn the PUT into a
                    lock release operation.
    :return: Boolean & message of success or failure.

    CLI Example:

    .. code-block:: bash

        salt '*' consul.put key='web/key1' value="Hello there"

        salt '*' consul.put key='web/key1' value="Hello there" acquire='d5d371f4-c380-5280-12fd-8810be175592'

        salt '*' consul.put key='web/key1' value="Hello there" release='d5d371f4-c380-5280-12fd-8810be175592'

def put(consul_url=None, token=None, key=None, value=None, **kwargs):
    '''
    Put values into Consul

    :param consul_url: The Consul server URL.
    :param key: The key to use as the starting point for the list.
    :param value: The value to set the key to.
    :param flags: This can be used to specify an unsigned value
                  between 0 and 2^64-1. Clients can choose to use
                  this however makes sense for their application.
    :param cas: This flag is used to turn the PUT into a
                Check-And-Set operation.
    :param acquire: This flag is used to turn the PUT into a
                    lock acquisition operation.
    :param release: This flag is used to turn the PUT into a
                    lock release operation.
    :return: Boolean & message of success or failure.

    CLI Example:

    .. code-block:: bash

        salt '*' consul.put key='web/key1' value="Hello there"

        salt '*' consul.put key='web/key1' value="Hello there" acquire='d5d371f4-c380-5280-12fd-8810be175592'

        salt '*' consul.put key='web/key1' value="Hello there" release='d5d371f4-c380-5280-12fd-8810be175592'

    '''
    ret = {}
    if not consul_url:
        consul_url = _get_config()
        if not consul_url:
            log.error('No Consul URL found.')
            ret['message'] = 'No Consul URL found.'
            ret['res'] = False
            return ret

    if not key:
        raise SaltInvocationError('Required argument "key" is missing.')

    # Invalid to specified these together
    conflicting_args = ['cas', 'release', 'acquire']
    for _l1 in conflicting_args:
        for _l2 in conflicting_args:
            if _l1 in kwargs and _l2 in kwargs and _l1 != _l2:
                raise SaltInvocationError('Using arguments `{0}` and `{1}`'
                                          ' together is invalid.'.format(_l1, _l2))

    query_params = {}

    available_sessions = session_list(consul_url=consul_url, return_list=True)
    _current = get(consul_url=consul_url, key=key)

    if 'flags' in kwargs:
        if kwargs['flags'] >= 0 and kwargs['flags'] <= 2**64:
            query_params['flags'] = kwargs['flags']

    if 'cas' in kwargs:
        if _current['res']:
            if kwargs['cas'] == 0:
                ret['message'] = ('Key {0} exists, index '
                                  'must be non-zero.'.format(key))
                ret['res'] = False
                return ret

            if kwargs['cas'] != _current['data']['ModifyIndex']:
                ret['message'] = ('Key {0} exists, but indexes '
                                  'do not match.'.format(key))
                ret['res'] = False
                return ret
            query_params['cas'] = kwargs['cas']
        else:
            ret['message'] = ('Key {0} does not exists, '
                              'CAS argument can not be used.'.format(key))
            ret['res'] = False
            return ret

    if 'acquire' in kwargs:
        if kwargs['acquire'] not in available_sessions:
            ret['message'] = '{0} is not a valid session.'.format(kwargs['acquire'])
            ret['res'] = False
            return ret

        query_params['acquire'] = kwargs['acquire']

    if 'release' in kwargs:
        if _current['res']:
            if 'Session' in _current['data']:
                if _current['data']['Session'] == kwargs['release']:
                    query_params['release'] = kwargs['release']
                else:
                    ret['message'] = '{0} locked by another session.'.format(key)
                    ret['res'] = False
                    return ret

            else:
                ret['message'] = '{0} is not a valid session.'.format(kwargs['acquire'])
                ret['res'] = False
        else:
            log.error('Key {0} does not exist. Skipping release.')

    data = value
    function = 'kv/{0}'.format(key)
    method = 'PUT'
    ret = _query(consul_url=consul_url,
                 token=token,
                 function=function,
                 method=method,
                 data=data,
                 query_params=query_params)

    if ret['res']:
        ret['res'] = True
        ret['data'] = 'Added key {0} with value {1}.'.format(key, value)
    else:
        ret['res'] = False
        ret['data'] = 'Unable to add key {0} with value {1}.'.format(key, value)
    return ret