Apply the loaded cloud providers configuration.

def apply_cloud_providers_config(overrides, defaults=None):
    '''
    Apply the loaded cloud providers configuration.
    '''
    if defaults is None:
        defaults = PROVIDER_CONFIG_DEFAULTS

    config = defaults.copy()
    if overrides:
        config.update(overrides)

    # Is the user still using the old format in the new configuration file?!
    for name, settings in six.iteritems(config.copy()):
        if '.' in name:
            log.warning(
                'Please switch to the new providers configuration syntax'
            )

            # Let's help out and migrate the data
            config = old_to_new(config)

            # old_to_new will migrate the old data into the 'providers' key of
            # the config dictionary. Let's map it correctly
            for prov_name, prov_settings in six.iteritems(config.pop('providers')):
                config[prov_name] = prov_settings
            break

    providers = {}
    ext_count = 0
    for key, val in six.iteritems(config):
        if key in ('conf_file', 'include', 'default_include', 'user'):
            continue

        if not isinstance(val, (list, tuple)):
            val = [val]
        else:
            # Need to check for duplicate cloud provider entries per "alias" or
            # we won't be able to properly reference it.
            handled_providers = set()
            for details in val:
                if 'driver' not in details:
                    if 'extends' not in details:
                        log.error(
                            'Please check your cloud providers configuration. '
                            'There\'s no \'driver\' nor \'extends\' definition '
                            'referenced.'
                        )
                    continue

                if details['driver'] in handled_providers:
                    log.error(
                        'You can only have one entry per cloud provider. For '
                        'example, if you have a cloud provider configuration '
                        'section named, \'production\', you can only have a '
                        'single entry for EC2, Joyent, Openstack, and so '
                        'forth.'
                    )
                    raise salt.exceptions.SaltCloudConfigError(
                        'The cloud provider alias \'{0}\' has multiple entries '
                        'for the \'{1[driver]}\' driver.'.format(key, details)
                    )
                handled_providers.add(details['driver'])

        for entry in val:

            if 'driver' not in entry:
                entry['driver'] = '-only-extendable-{0}'.format(ext_count)
                ext_count += 1

            if key not in providers:
                providers[key] = {}

            provider = entry['driver']
            if provider not in providers[key]:
                providers[key][provider] = entry

    # Is any provider extending data!?
    while True:
        keep_looping = False
        for provider_alias, entries in six.iteritems(providers.copy()):
            for driver, details in six.iteritems(entries):
                # Set a holder for the defined profiles
                providers[provider_alias][driver]['profiles'] = {}

                if 'extends' not in details:
                    continue

                extends = details.pop('extends')

                if ':' in extends:
                    alias, provider = extends.split(':')
                    if alias not in providers:
                        raise salt.exceptions.SaltCloudConfigError(
                            'The \'{0}\' cloud provider entry in \'{1}\' is '
                            'trying to extend data from \'{2}\' though '
                            '\'{2}\' is not defined in the salt cloud '
                            'providers loaded data.'.format(
                                details['driver'],
                                provider_alias,
                                alias
                            )
                        )

                    if provider not in providers.get(alias):
                        raise salt.exceptions.SaltCloudConfigError(
                            'The \'{0}\' cloud provider entry in \'{1}\' is '
                            'trying to extend data from \'{2}:{3}\' though '
                            '\'{3}\' is not defined in \'{1}\''.format(
                                details['driver'],
                                provider_alias,
                                alias,
                                provider
                            )
                        )
                    details['extends'] = '{0}:{1}'.format(alias, provider)
                    # change provider details '-only-extendable-' to extended
                    # provider name
                    details['driver'] = provider
                elif providers.get(extends):
                    raise salt.exceptions.SaltCloudConfigError(
                        'The \'{0}\' cloud provider entry in \'{1}\' is '
                        'trying to extend from \'{2}\' and no provider was '
                        'specified. Not extending!'.format(
                            details['driver'], provider_alias, extends
                        )
                    )
                elif extends not in providers:
                    raise salt.exceptions.SaltCloudConfigError(
                        'The \'{0}\' cloud provider entry in \'{1}\' is '
                        'trying to extend data from \'{2}\' though \'{2}\' '
                        'is not defined in the salt cloud providers loaded '
                        'data.'.format(
                            details['driver'], provider_alias, extends
                        )
                    )
                else:
                    if driver in providers.get(extends):
                        details['extends'] = '{0}:{1}'.format(extends, driver)
                    elif '-only-extendable-' in providers.get(extends):
                        details['extends'] = '{0}:{1}'.format(
                            extends, '-only-extendable-{0}'.format(ext_count)
                        )
                    else:
                        # We're still not aware of what we're trying to extend
                        # from. Let's try on next iteration
                        details['extends'] = extends
                        keep_looping = True
        if not keep_looping:
            break

    while True:
        # Merge provided extends
        keep_looping = False
        for alias, entries in six.iteritems(providers.copy()):
            for driver, details in six.iteritems(entries):

                if 'extends' not in details:
                    # Extends resolved or non existing, continue!
                    continue

                if 'extends' in details['extends']:
                    # Since there's a nested extends, resolve this one in the
                    # next iteration
                    keep_looping = True
                    continue

                # Let's get a reference to what we're supposed to extend
                extends = details.pop('extends')
                # Split the setting in (alias, driver)
                ext_alias, ext_driver = extends.split(':')
                # Grab a copy of what should be extended
                extended = providers.get(ext_alias).get(ext_driver).copy()
                # Merge the data to extend with the details
                extended = salt.utils.dictupdate.update(extended, details)
                # Update the providers dictionary with the merged data
                providers[alias][driver] = extended
                # Update name of the driver, now that it's populated with extended information
                if driver.startswith('-only-extendable-'):
                    providers[alias][ext_driver] = providers[alias][driver]
                    # Delete driver with old name to maintain dictionary size
                    del providers[alias][driver]

        if not keep_looping:
            break

    # Now clean up any providers entry that was just used to be a data tree to
    # extend from
    for provider_alias, entries in six.iteritems(providers.copy()):
        for driver, details in six.iteritems(entries.copy()):
            if not driver.startswith('-only-extendable-'):
                continue

            log.info(
                "There's at least one cloud driver under the '%s' "
                'cloud provider alias which does not have the required '
                "'driver' setting. Removing it from the available "
                'providers listing.', provider_alias
            )
            providers[provider_alias].pop(driver)

        if not providers[provider_alias]:
            providers.pop(provider_alias)

    return providers