Refactor config.load() to remove reduce() and document some types.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
Daniel Nephin 2015-09-17 15:07:53 -04:00
parent 577439ea7f
commit 22bc174650
1 changed files with 34 additions and 15 deletions

View File

@ -2,7 +2,6 @@ import logging
import os import os
import sys import sys
from collections import namedtuple from collections import namedtuple
from functools import reduce
import six import six
import yaml import yaml
@ -89,9 +88,22 @@ PATH_START_CHARS = [
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
ConfigDetails = namedtuple('ConfigDetails', 'working_dir configs') class ConfigDetails(namedtuple('_ConfigDetails', 'working_dir config_files')):
"""
:param working_dir: the directory to use for relative paths in the config
:type working_dir: string
:param config_files: list of configuration files to load
:type config_files: list of :class:`ConfigFile`
"""
ConfigFile = namedtuple('ConfigFile', 'filename config')
class ConfigFile(namedtuple('_ConfigFile', 'filename config')):
"""
:param filename: filename of the config file
:type filename: string
:param config: contents of the config file
:type config: :class:`dict`
"""
def find(base_dir, filenames): def find(base_dir, filenames):
@ -170,10 +182,19 @@ def pre_process_config(config):
def load(config_details): def load(config_details):
working_dir, configs = config_details """Load the configuration from a working directory and a list of
configuration files. Files are loaded in order, and merged on top
of each other to create the final configuration.
Return a fully interpolated, extended and validated configuration.
"""
def build_service(filename, service_name, service_dict): def build_service(filename, service_name, service_dict):
loader = ServiceLoader(working_dir, filename, service_name, service_dict) loader = ServiceLoader(
config_details.working_dir,
filename,
service_name,
service_dict)
service_dict = loader.make_service_dict() service_dict = loader.make_service_dict()
validate_paths(service_dict) validate_paths(service_dict)
return service_dict return service_dict
@ -187,21 +208,19 @@ def load(config_details):
] ]
def merge_services(base, override): def merge_services(base, override):
all_service_names = set(base) | set(override)
return { return {
name: merge_service_dicts(base.get(name, {}), override.get(name, {})) name: merge_service_dicts(base.get(name, {}), override.get(name, {}))
for name in set(base) | set(override) for name in all_service_names
} }
def combine_configs(base, override): config_file = config_details.config_files[0]
service_dicts = load_file(base.filename, base.config) for next_file in config_details.config_files[1:]:
if not override: config_file = ConfigFile(
return service_dicts config_file.filename,
merge_services(config_file.config, next_file.config))
return ConfigFile( return load_file(config_file.filename, config_file.config)
override.filename,
merge_services(base.config, override.config))
return reduce(combine_configs, configs + [None])
class ServiceLoader(object): class ServiceLoader(object):