Ensure that an image is absent from the Minion. Image names can be
    specified either using ``repo:tag`` notation, or just the repo name (in
    which case a tag of ``latest`` is assumed).

    images
        Run this state on more than one image at a time. The following two
        examples accomplish the same thing:

        .. code-block:: yaml

            remove_images:
              docker_image.absent:
                - names:
                  - busybox
                  - centos:6
                  - nginx

        .. code-block:: yaml

            remove_images:
              docker_image.absent:
                - images:
                  - busybox
                  - centos:6
                  - nginx

        However, the second example will be a bit quicker since Salt will do
        all the deletions in a single run, rather than executing the state
        separately on each image (as it would in the first example).

    force : False
        Salt will fail to remove any images currently in use by a container.
        Set this option to true to remove the image even if it is already
        present.

        .. note::

            This option can also be overridden by Pillar data. If the Minion
            has a pillar variable named ``docker.running.force`` which is
            set to ``True``, it will turn on this option. This pillar variable
            can even be set at runtime. For example:

            .. code-block:: bash

                salt myminion state.sls docker_stuff pillar="{docker.force: True}"

            If this pillar variable is present and set to ``False``, then it
            will turn off this option.

            For more granular control, setting a pillar variable named
            ``docker.force.image_name`` will affect only the named image.

def absent(name=None, images=None, force=False):
    '''
    Ensure that an image is absent from the Minion. Image names can be
    specified either using ``repo:tag`` notation, or just the repo name (in
    which case a tag of ``latest`` is assumed).

    images
        Run this state on more than one image at a time. The following two
        examples accomplish the same thing:

        .. code-block:: yaml

            remove_images:
              docker_image.absent:
                - names:
                  - busybox
                  - centos:6
                  - nginx

        .. code-block:: yaml

            remove_images:
              docker_image.absent:
                - images:
                  - busybox
                  - centos:6
                  - nginx

        However, the second example will be a bit quicker since Salt will do
        all the deletions in a single run, rather than executing the state
        separately on each image (as it would in the first example).

    force : False
        Salt will fail to remove any images currently in use by a container.
        Set this option to true to remove the image even if it is already
        present.

        .. note::

            This option can also be overridden by Pillar data. If the Minion
            has a pillar variable named ``docker.running.force`` which is
            set to ``True``, it will turn on this option. This pillar variable
            can even be set at runtime. For example:

            .. code-block:: bash

                salt myminion state.sls docker_stuff pillar="{docker.force: True}"

            If this pillar variable is present and set to ``False``, then it
            will turn off this option.

            For more granular control, setting a pillar variable named
            ``docker.force.image_name`` will affect only the named image.
    '''
    ret = {'name': name,
           'changes': {},
           'result': False,
           'comment': ''}

    if not name and not images:
        ret['comment'] = 'One of \'name\' and \'images\' must be provided'
        return ret
    elif images is not None:
        targets = images
    elif name:
        targets = [name]

    to_delete = []
    for target in targets:
        resolved_tag = __salt__['docker.resolve_tag'](target)
        if resolved_tag is not False:
            to_delete.append(resolved_tag)

    if not to_delete:
        ret['result'] = True
        if len(targets) == 1:
            ret['comment'] = 'Image {0} is not present'.format(name)
        else:
            ret['comment'] = 'All specified images are not present'
        return ret

    if __opts__['test']:
        ret['result'] = None
        if len(to_delete) == 1:
            ret['comment'] = 'Image {0} will be removed'.format(to_delete[0])
        else:
            ret['comment'] = (
                'The following images will be removed: {0}'.format(
                    ', '.join(to_delete)
                )
            )
        return ret

    result = __salt__['docker.rmi'](*to_delete, force=force)
    post_tags = __salt__['docker.list_tags']()
    failed = [x for x in to_delete if x in post_tags]

    if failed:
        if [x for x in to_delete if x not in post_tags]:
            ret['changes'] = result
            ret['comment'] = (
                'The following image(s) failed to be removed: {0}'.format(
                    ', '.join(failed)
                )
            )
        else:
            ret['comment'] = 'None of the specified images were removed'
            if 'Errors' in result:
                ret['comment'] += (
                    '. The following errors were encountered: {0}'
                    .format('; '.join(result['Errors']))
                )
    else:
        ret['changes'] = result
        if len(to_delete) == 1:
            ret['comment'] = 'Image {0} was removed'.format(to_delete[0])
        else:
            ret['comment'] = (
                'The following images were removed: {0}'.format(
                    ', '.join(to_delete)
                )
            )
        ret['result'] = True

    return ret