mirror of
https://github.com/docker/compose.git
synced 2025-07-20 20:24:30 +02:00
Partial support for service configs
Signed-off-by: Joffrey F <joffrey@docker.com>
This commit is contained in:
parent
bfc7ac4995
commit
70b2e64c1b
@ -211,8 +211,11 @@ class ConfigFile(namedtuple('_ConfigFile', 'filename config')):
|
|||||||
def get_secrets(self):
|
def get_secrets(self):
|
||||||
return {} if self.version < const.COMPOSEFILE_V3_1 else self.config.get('secrets', {})
|
return {} if self.version < const.COMPOSEFILE_V3_1 else self.config.get('secrets', {})
|
||||||
|
|
||||||
|
def get_configs(self):
|
||||||
|
return {} if self.version < const.COMPOSEFILE_V3_3 else self.config.get('configs', {})
|
||||||
|
|
||||||
class Config(namedtuple('_Config', 'version services volumes networks secrets')):
|
|
||||||
|
class Config(namedtuple('_Config', 'version services volumes networks secrets configs')):
|
||||||
"""
|
"""
|
||||||
:param version: configuration version
|
:param version: configuration version
|
||||||
:type version: int
|
:type version: int
|
||||||
@ -224,6 +227,8 @@ class Config(namedtuple('_Config', 'version services volumes networks secrets'))
|
|||||||
:type networks: :class:`dict`
|
:type networks: :class:`dict`
|
||||||
:param secrets: Dictionary mapping secret names to description dictionaries
|
:param secrets: Dictionary mapping secret names to description dictionaries
|
||||||
:type secrets: :class:`dict`
|
:type secrets: :class:`dict`
|
||||||
|
:param configs: Dictionary mapping config names to description dictionaries
|
||||||
|
:type configs: :class:`dict`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@ -340,6 +345,7 @@ def check_swarm_only_config(service_dicts):
|
|||||||
|
|
||||||
check_swarm_only_key(service_dicts, 'deploy')
|
check_swarm_only_key(service_dicts, 'deploy')
|
||||||
check_swarm_only_key(service_dicts, 'credential_spec')
|
check_swarm_only_key(service_dicts, 'credential_spec')
|
||||||
|
check_swarm_only_key(service_dicts, 'configs')
|
||||||
|
|
||||||
|
|
||||||
def load(config_details):
|
def load(config_details):
|
||||||
@ -364,7 +370,12 @@ def load(config_details):
|
|||||||
networks = load_mapping(
|
networks = load_mapping(
|
||||||
config_details.config_files, 'get_networks', 'Network'
|
config_details.config_files, 'get_networks', 'Network'
|
||||||
)
|
)
|
||||||
secrets = load_secrets(config_details.config_files, config_details.working_dir)
|
secrets = load_mapping(
|
||||||
|
config_details.config_files, 'get_secrets', 'Secret', config_details.working_dir
|
||||||
|
)
|
||||||
|
configs = load_mapping(
|
||||||
|
config_details.config_files, 'get_configs', 'Config', config_details.working_dir
|
||||||
|
)
|
||||||
service_dicts = load_services(config_details, main_file)
|
service_dicts = load_services(config_details, main_file)
|
||||||
|
|
||||||
if main_file.version != V1:
|
if main_file.version != V1:
|
||||||
@ -373,10 +384,10 @@ def load(config_details):
|
|||||||
|
|
||||||
check_swarm_only_config(service_dicts)
|
check_swarm_only_config(service_dicts)
|
||||||
|
|
||||||
return Config(main_file.version, service_dicts, volumes, networks, secrets)
|
return Config(main_file.version, service_dicts, volumes, networks, secrets, configs)
|
||||||
|
|
||||||
|
|
||||||
def load_mapping(config_files, get_func, entity_type):
|
def load_mapping(config_files, get_func, entity_type, working_dir=None):
|
||||||
mapping = {}
|
mapping = {}
|
||||||
|
|
||||||
for config_file in config_files:
|
for config_file in config_files:
|
||||||
@ -401,6 +412,9 @@ def load_mapping(config_files, get_func, entity_type):
|
|||||||
if 'labels' in config:
|
if 'labels' in config:
|
||||||
config['labels'] = parse_labels(config['labels'])
|
config['labels'] = parse_labels(config['labels'])
|
||||||
|
|
||||||
|
if 'file' in config:
|
||||||
|
config['file'] = expand_path(working_dir, config['file'])
|
||||||
|
|
||||||
return mapping
|
return mapping
|
||||||
|
|
||||||
|
|
||||||
@ -414,29 +428,6 @@ def validate_external(entity_type, name, config):
|
|||||||
entity_type, name, ', '.join(k for k in config if k != 'external')))
|
entity_type, name, ', '.join(k for k in config if k != 'external')))
|
||||||
|
|
||||||
|
|
||||||
def load_secrets(config_files, working_dir):
|
|
||||||
mapping = {}
|
|
||||||
|
|
||||||
for config_file in config_files:
|
|
||||||
for name, config in config_file.get_secrets().items():
|
|
||||||
mapping[name] = config or {}
|
|
||||||
if not config:
|
|
||||||
continue
|
|
||||||
|
|
||||||
external = config.get('external')
|
|
||||||
if external:
|
|
||||||
validate_external('Secret', name, config)
|
|
||||||
if isinstance(external, dict):
|
|
||||||
config['external_name'] = external.get('name')
|
|
||||||
else:
|
|
||||||
config['external_name'] = name
|
|
||||||
|
|
||||||
if 'file' in config:
|
|
||||||
config['file'] = expand_path(working_dir, config['file'])
|
|
||||||
|
|
||||||
return mapping
|
|
||||||
|
|
||||||
|
|
||||||
def load_services(config_details, config_file):
|
def load_services(config_details, config_file):
|
||||||
def build_service(service_name, service_dict, service_names):
|
def build_service(service_name, service_dict, service_names):
|
||||||
service_config = ServiceConfig.with_abs_paths(
|
service_config = ServiceConfig.with_abs_paths(
|
||||||
@ -815,6 +806,11 @@ def finalize_service(service_config, service_names, version, environment):
|
|||||||
types.ServiceSecret.parse(s) for s in service_dict['secrets']
|
types.ServiceSecret.parse(s) for s in service_dict['secrets']
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if 'configs' in service_dict:
|
||||||
|
service_dict['configs'] = [
|
||||||
|
types.ServiceConfig.parse(c) for c in service_dict['configs']
|
||||||
|
]
|
||||||
|
|
||||||
normalize_build(service_dict, service_config.working_dir, environment)
|
normalize_build(service_dict, service_config.working_dir, environment)
|
||||||
|
|
||||||
service_dict['name'] = service_config.name
|
service_dict['name'] = service_config.name
|
||||||
@ -906,6 +902,7 @@ def merge_service_dicts(base, override, version):
|
|||||||
md.merge_mapping('depends_on', parse_depends_on)
|
md.merge_mapping('depends_on', parse_depends_on)
|
||||||
md.merge_sequence('links', ServiceLink.parse)
|
md.merge_sequence('links', ServiceLink.parse)
|
||||||
md.merge_sequence('secrets', types.ServiceSecret.parse)
|
md.merge_sequence('secrets', types.ServiceSecret.parse)
|
||||||
|
md.merge_sequence('configs', types.ServiceConfig.parse)
|
||||||
md.merge_mapping('deploy', parse_deploy)
|
md.merge_mapping('deploy', parse_deploy)
|
||||||
|
|
||||||
for field in ['volumes', 'devices']:
|
for field in ['volumes', 'devices']:
|
||||||
|
@ -8,7 +8,6 @@ from compose.config import types
|
|||||||
from compose.const import COMPOSEFILE_V1 as V1
|
from compose.const import COMPOSEFILE_V1 as V1
|
||||||
from compose.const import COMPOSEFILE_V2_1 as V2_1
|
from compose.const import COMPOSEFILE_V2_1 as V2_1
|
||||||
from compose.const import COMPOSEFILE_V2_2 as V2_2
|
from compose.const import COMPOSEFILE_V2_2 as V2_2
|
||||||
from compose.const import COMPOSEFILE_V3_1 as V3_1
|
|
||||||
from compose.const import COMPOSEFILE_V3_2 as V3_2
|
from compose.const import COMPOSEFILE_V3_2 as V3_2
|
||||||
from compose.const import COMPOSEFILE_V3_3 as V3_3
|
from compose.const import COMPOSEFILE_V3_3 as V3_3
|
||||||
|
|
||||||
@ -25,6 +24,7 @@ def serialize_dict_type(dumper, data):
|
|||||||
yaml.SafeDumper.add_representer(types.VolumeFromSpec, serialize_config_type)
|
yaml.SafeDumper.add_representer(types.VolumeFromSpec, serialize_config_type)
|
||||||
yaml.SafeDumper.add_representer(types.VolumeSpec, serialize_config_type)
|
yaml.SafeDumper.add_representer(types.VolumeSpec, serialize_config_type)
|
||||||
yaml.SafeDumper.add_representer(types.ServiceSecret, serialize_dict_type)
|
yaml.SafeDumper.add_representer(types.ServiceSecret, serialize_dict_type)
|
||||||
|
yaml.SafeDumper.add_representer(types.ServiceConfig, serialize_dict_type)
|
||||||
yaml.SafeDumper.add_representer(types.ServicePort, serialize_dict_type)
|
yaml.SafeDumper.add_representer(types.ServicePort, serialize_dict_type)
|
||||||
|
|
||||||
|
|
||||||
@ -41,21 +41,15 @@ def denormalize_config(config, image_digests=None):
|
|||||||
service_dict.pop('name'): service_dict
|
service_dict.pop('name'): service_dict
|
||||||
for service_dict in denormalized_services
|
for service_dict in denormalized_services
|
||||||
}
|
}
|
||||||
result['networks'] = config.networks.copy()
|
for key in ('networks', 'volumes', 'secrets', 'configs'):
|
||||||
for net_name, net_conf in result['networks'].items():
|
config_dict = getattr(config, key)
|
||||||
if 'external_name' in net_conf:
|
if not config_dict:
|
||||||
del net_conf['external_name']
|
continue
|
||||||
|
result[key] = config_dict.copy()
|
||||||
|
for name, conf in result[key].items():
|
||||||
|
if 'external_name' in conf:
|
||||||
|
del conf['external_name']
|
||||||
|
|
||||||
result['volumes'] = config.volumes.copy()
|
|
||||||
for vol_name, vol_conf in result['volumes'].items():
|
|
||||||
if 'external_name' in vol_conf:
|
|
||||||
del vol_conf['external_name']
|
|
||||||
|
|
||||||
if config.version in (V3_1, V3_2, V3_3):
|
|
||||||
result['secrets'] = config.secrets.copy()
|
|
||||||
for secret_name, secret_conf in result['secrets'].items():
|
|
||||||
if 'external_name' in secret_conf:
|
|
||||||
del secret_conf['external_name']
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@ -238,8 +238,7 @@ class ServiceLink(namedtuple('_ServiceLink', 'target alias')):
|
|||||||
return self.alias
|
return self.alias
|
||||||
|
|
||||||
|
|
||||||
class ServiceSecret(namedtuple('_ServiceSecret', 'source target uid gid mode')):
|
class ServiceConfigBase(namedtuple('_ServiceConfigBase', 'source target uid gid mode')):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse(cls, spec):
|
def parse(cls, spec):
|
||||||
if isinstance(spec, six.string_types):
|
if isinstance(spec, six.string_types):
|
||||||
@ -262,6 +261,14 @@ class ServiceSecret(namedtuple('_ServiceSecret', 'source target uid gid mode')):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ServiceSecret(ServiceConfigBase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ServiceConfig(ServiceConfigBase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ServicePort(namedtuple('_ServicePort', 'target published protocol mode external_ip')):
|
class ServicePort(namedtuple('_ServicePort', 'target published protocol mode external_ip')):
|
||||||
def __new__(cls, target, published, *args, **kwargs):
|
def __new__(cls, target, published, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user