.. versionadded:: 2016.3.7,2016.11.4,2017.7.0

    Performs a ``docker login`` to authenticate to one or more configured
    repositories. See the documentation at the top of this page to configure
    authentication credentials.

    Multiple registry URLs (matching those configured in Pillar) can be passed,
    and Salt will attempt to login to *just* those registries. If no registry
    URLs are provided, Salt will attempt to login to *all* configured
    registries.

    **RETURN DATA**

    A dictionary containing the following keys:

    - ``Results`` - A dictionary mapping registry URLs to the authentication
      result. ``True`` means a successful login, ``False`` means a failed
      login.
    - ``Errors`` - A list of errors encountered during the course of this
      function.

    CLI Example:

    .. code-block:: bash

        salt myminion docker.login
        salt myminion docker.login hub
        salt myminion docker.login hub https://mydomain.tld/registry/

def login(*registries):
    '''
    .. versionadded:: 2016.3.7,2016.11.4,2017.7.0

    Performs a ``docker login`` to authenticate to one or more configured
    repositories. See the documentation at the top of this page to configure
    authentication credentials.

    Multiple registry URLs (matching those configured in Pillar) can be passed,
    and Salt will attempt to login to *just* those registries. If no registry
    URLs are provided, Salt will attempt to login to *all* configured
    registries.

    **RETURN DATA**

    A dictionary containing the following keys:

    - ``Results`` - A dictionary mapping registry URLs to the authentication
      result. ``True`` means a successful login, ``False`` means a failed
      login.
    - ``Errors`` - A list of errors encountered during the course of this
      function.

    CLI Example:

    .. code-block:: bash

        salt myminion docker.login
        salt myminion docker.login hub
        salt myminion docker.login hub https://mydomain.tld/registry/
    '''
    # NOTE: This function uses the "docker login" CLI command so that login
    # information is added to the config.json, since docker-py isn't designed
    # to do so.
    registry_auth = __pillar__.get('docker-registries', {})
    ret = {'retcode': 0}
    errors = ret.setdefault('Errors', [])
    if not isinstance(registry_auth, dict):
        errors.append(
            '\'docker-registries\' Pillar value must be a dictionary')
        registry_auth = {}
    for key, data in six.iteritems(__pillar__):
        try:
            if key.endswith('-docker-registries'):
                try:
                    registry_auth.update(data)
                except TypeError:
                    errors.append(
                        '\'{0}\' Pillar value must be a dictionary'.format(key)
                    )
        except AttributeError:
            pass

    # If no registries passed, we will auth to all of them
    if not registries:
        registries = list(registry_auth)

    results = ret.setdefault('Results', {})
    for registry in registries:
        if registry not in registry_auth:
            errors.append(
                'No match found for registry \'{0}\''.format(registry)
            )
            continue
        try:
            username = registry_auth[registry]['username']
            password = registry_auth[registry]['password']
        except TypeError:
            errors.append(
                'Invalid configuration for registry \'{0}\''.format(registry)
            )
        except KeyError as exc:
            errors.append(
                'Missing {0} for registry \'{1}\''.format(exc, registry)
            )
        else:
            cmd = ['docker', 'login', '-u', username, '-p', password]
            if registry.lower() != 'hub':
                cmd.append(registry)
            log.debug(
                'Attempting to login to docker registry \'%s\' as user \'%s\'',
                registry, username
            )
            login_cmd = __salt__['cmd.run_all'](
                cmd,
                python_shell=False,
                output_loglevel='quiet',
            )
            results[registry] = login_cmd['retcode'] == 0
            if not results[registry]:
                if login_cmd['stderr']:
                    errors.append(login_cmd['stderr'])
                elif login_cmd['stdout']:
                    errors.append(login_cmd['stdout'])
    if errors:
        ret['retcode'] = 1
    return ret