.. versionadded:: 2014.7.0

    Append a value to a list in the grains config file. The grain that is being
    appended to (name) must exist before the new value can be added.

    name
        The grain name

    value
        The value to append

    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
        A delimiter different from the default can be provided.

        .. versionadded:: v2015.8.2

    .. code-block:: yaml

      grain_name:
        grains.append:
          - value: to_be_appended

def append(name, value, convert=False,
           delimiter=DEFAULT_TARGET_DELIM):
    '''
    .. versionadded:: 2014.7.0

    Append a value to a list in the grains config file. The grain that is being
    appended to (name) must exist before the new value can be added.

    name
        The grain name

    value
        The value to append

    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
        A delimiter different from the default can be provided.

        .. versionadded:: v2015.8.2

    .. code-block:: yaml

      grain_name:
        grains.append:
          - value: to_be_appended
    '''
    name = re.sub(delimiter, DEFAULT_TARGET_DELIM, name)
    ret = {'name': name,
           'changes': {},
           'result': True,
           'comment': ''}
    grain = __salt__['grains.get'](name, None)

    # Check if bool(grain) is False or if the grain is specified in the minions
    # grains. Grains can be set to a None value by omitting a value in the
    # definition.
    if grain or name in __grains__:
        if isinstance(grain, list):
            if value in grain:
                ret['comment'] = 'Value {1} is already in the list ' \
                                 'for grain {0}'.format(name, value)
                return ret
            if __opts__['test']:
                ret['result'] = None
                ret['comment'] = 'Value {1} in grain {0} is set to ' \
                                 'be added'.format(name, value)
                ret['changes'] = {'added': value}
                return ret
            __salt__['grains.append'](name, value)
            ret['comment'] = 'Value {1} was added to grain {0}'.format(name, value)
            ret['changes'] = {'added': value}
        else:
            if convert is True:
                if __opts__['test']:
                    ret['result'] = None
                    ret['comment'] = 'Grain {0} is set to be converted ' \
                                     'to list and value {1} will be ' \
                                     'added'.format(name, value)
                    ret['changes'] = {'added': value}
                    return ret
                grain = [] if grain is None else [grain]
                grain.append(value)
                __salt__['grains.setval'](name, grain)
                ret['comment'] = 'Value {1} was added to grain {0}'.format(name, value)
                ret['changes'] = {'added': value}
            else:
                ret['result'] = False
                ret['comment'] = 'Grain {0} is not a valid list'.format(name)
    else:
        ret['result'] = False
        ret['comment'] = 'Grain {0} does not exist'.format(name)
    return ret