.. versionadded:: 2017.7.0

    Ensure that packages related to certain advisory ids are installed.

    Currently supported for the following pkg providers:
    :mod:`yumpkg <salt.modules.yumpkg>` and :mod:`zypper <salt.modules.zypper>`

    CLI Example:

    .. code-block:: yaml

        issue-foo-fixed:
          pkg.patch_installed:
            - advisory_ids:
              - SUSE-SLE-SERVER-12-SP2-2017-185
              - SUSE-SLE-SERVER-12-SP2-2017-150
              - SUSE-SLE-SERVER-12-SP2-2017-120

def patch_installed(name, advisory_ids=None, downloadonly=None, **kwargs):
    '''
    .. versionadded:: 2017.7.0

    Ensure that packages related to certain advisory ids are installed.

    Currently supported for the following pkg providers:
    :mod:`yumpkg <salt.modules.yumpkg>` and :mod:`zypper <salt.modules.zypper>`

    CLI Example:

    .. code-block:: yaml

        issue-foo-fixed:
          pkg.patch_installed:
            - advisory_ids:
              - SUSE-SLE-SERVER-12-SP2-2017-185
              - SUSE-SLE-SERVER-12-SP2-2017-150
              - SUSE-SLE-SERVER-12-SP2-2017-120
    '''
    ret = {'name': name,
           'changes': {},
           'result': None,
           'comment': ''}

    if 'pkg.list_patches' not in __salt__:
        ret['result'] = False
        ret['comment'] = 'The pkg.patch_installed state is not available on ' \
                         'this platform'
        return ret

    if not advisory_ids and isinstance(advisory_ids, list):
        ret['result'] = True
        ret['comment'] = 'No advisory ids provided'
        return ret

    # Only downloading not yet downloaded packages
    targets = _find_advisory_targets(name, advisory_ids, **kwargs)
    if isinstance(targets, dict) and 'result' in targets:
        return targets
    elif not isinstance(targets, list):
        ret['result'] = False
        ret['comment'] = 'An error was encountered while checking targets: ' \
                         '{0}'.format(targets)
        return ret

    if __opts__['test']:
        summary = ', '.join(targets)
        ret['comment'] = 'The following advisory patches would be ' \
                         'downloaded: {0}'.format(summary)
        return ret

    try:
        pkg_ret = __salt__['pkg.install'](name=name,
                                          advisory_ids=advisory_ids,
                                          downloadonly=downloadonly,
                                          **kwargs)
        ret['result'] = True
        ret['changes'].update(pkg_ret)
    except CommandExecutionError as exc:
        ret = {'name': name, 'result': False}
        if exc.info:
            # Get information for state return from the exception.
            ret['changes'] = exc.info.get('changes', {})
            ret['comment'] = exc.strerror_without_changes
        else:
            ret['changes'] = {}
            ret['comment'] = ('An error was encountered while downloading '
                              'package(s): {0}'.format(exc))
        return ret

    if not ret['changes'] and not ret['comment']:
        status = 'downloaded' if downloadonly else 'installed'
        ret['result'] = True
        ret['comment'] = ('Advisory patch is not needed or related packages '
                          'are already {0}'.format(status))

    return ret