Get a config source based on type and keyword args.

    This is meant to be used internally by the spec via ``add_source``.

    Args:
        label (str): The label for this source.
        source_type: The type of source. See ``yapconf.SUPPORTED_SOURCES``

    Keyword Args:
        The keyword arguments are based on the source_type. Please see the
        documentation of the individual sources for a detailed list of all
        possible arguments.

    Returns (yapconf.sources.ConfigSource):
        A valid config source which can be used for generating an override.

    Raises:
        YapconfSourceError: If there is some kind of error with this source
        definition.

def get_source(label, source_type, **kwargs):
    """Get a config source based on type and keyword args.

    This is meant to be used internally by the spec via ``add_source``.

    Args:
        label (str): The label for this source.
        source_type: The type of source. See ``yapconf.SUPPORTED_SOURCES``

    Keyword Args:
        The keyword arguments are based on the source_type. Please see the
        documentation of the individual sources for a detailed list of all
        possible arguments.

    Returns (yapconf.sources.ConfigSource):
        A valid config source which can be used for generating an override.

    Raises:
        YapconfSourceError: If there is some kind of error with this source
        definition.

    """
    if source_type not in yapconf.ALL_SUPPORTED_SOURCES:
        raise YapconfSourceError(
            'Invalid source type %s. Supported types are %s.' %
            (source_type, yapconf.ALL_SUPPORTED_SOURCES)
        )
    if source_type not in yapconf.SUPPORTED_SOURCES:
        raise YapconfSourceError(
            'Unsupported source type "%s". If you want to use this type, you '
            'will need to install the correct client for it (try `pip install '
            'yapconf[%s]. Currently supported types are %s. All supported '
            'types are %s' %
            (source_type, source_type, yapconf.SUPPORTED_SOURCES,
             yapconf.ALL_SUPPORTED_SOURCES)
        )

    # We pop arguments from kwargs because the individual config sources
    # have better error messages if a keyword argument is missed.
    if source_type == 'dict':
        return DictConfigSource(label, data=kwargs.get('data'))

    elif source_type == 'json':
        return JsonConfigSource(label, **kwargs)

    elif source_type == 'yaml':
        filename = kwargs.get('filename')
        if 'filename' in kwargs:
            kwargs.pop('filename')
        return YamlConfigSource(label, filename, **kwargs)

    elif source_type == 'environment':
        return EnvironmentConfigSource(label)

    elif source_type == 'etcd':
        return EtcdConfigSource(
            label, kwargs.get('client'), kwargs.get('key', '/')
        )

    elif source_type == 'kubernetes':
        name = kwargs.get('name')
        if 'name' in kwargs:
            kwargs.pop('name')

        client = kwargs.get('client')
        if 'client' in kwargs:
            kwargs.pop('client')
        return KubernetesConfigSource(label, client, name, **kwargs)

    else:
        raise NotImplementedError(
            'No implementation for source type %s' % source_type
        )