.. versionadded:: 0.17.0

    Append a value to a list in the grains config file. If the grain doesn't
    exist, the grain key is added and the value is appended to the new grain
    as a list item.

    key
        The grain key to be appended to

    val
        The value to append to the grain key

    convert
        If convert is True, convert non-list contents into a list.
        If convert is False and the grain contains non-list contents, an error
        is given. Defaults to False.

    delimiter
        The key can be a nested dict key. Use this parameter to
        specify the delimiter you use, instead of the default ``:``.
        You can now append values to a list in nested dictionary grains. If the
        list doesn't exist at this level, it will be created.

        .. versionadded:: 2014.7.6

    CLI Example:

    .. code-block:: bash

        salt '*' grains.append key val

def append(key, val, convert=False, delimiter=DEFAULT_TARGET_DELIM):
    '''
    .. versionadded:: 0.17.0

    Append a value to a list in the grains config file. If the grain doesn't
    exist, the grain key is added and the value is appended to the new grain
    as a list item.

    key
        The grain key to be appended to

    val
        The value to append to the grain key

    convert
        If convert is True, convert non-list contents into a list.
        If convert is False and the grain contains non-list contents, an error
        is given. Defaults to False.

    delimiter
        The key can be a nested dict key. Use this parameter to
        specify the delimiter you use, instead of the default ``:``.
        You can now append values to a list in nested dictionary grains. If the
        list doesn't exist at this level, it will be created.

        .. versionadded:: 2014.7.6

    CLI Example:

    .. code-block:: bash

        salt '*' grains.append key val
    '''
    grains = get(key, [], delimiter)
    if convert:
        if not isinstance(grains, list):
            grains = [] if grains is None else [grains]
    if not isinstance(grains, list):
        return 'The key {0} is not a valid list'.format(key)
    if val in grains:
        return 'The val {0} was already in the list {1}'.format(val, key)
    if isinstance(val, list):
        for item in val:
            grains.append(item)
    else:
        grains.append(val)

    while delimiter in key:
        key, rest = key.rsplit(delimiter, 1)
        _grain = get(key, _infinitedict(), delimiter)
        if isinstance(_grain, dict):
            _grain.update({rest: grains})
        grains = _grain

    return setval(key, grains)