Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Secrets using bind mounts #4368

Merged
merged 7 commits into from
Feb 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 44 additions & 13 deletions compose/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@
import yaml
from cached_property import cached_property

from . import types
from ..const import COMPOSEFILE_V1 as V1
from ..const import COMPOSEFILE_V2_0 as V2_0
from ..const import COMPOSEFILE_V2_1 as V2_1
from ..const import COMPOSEFILE_V3_0 as V3_0
from ..const import COMPOSEFILE_V3_1 as V3_1
from ..utils import build_string_dict
from ..utils import parse_nanoseconds_int
from ..utils import splitdrive
Expand Down Expand Up @@ -82,6 +84,7 @@
'privileged',
'read_only',
'restart',
'secrets',
'security_opt',
'shm_size',
'stdin_open',
Expand Down Expand Up @@ -202,8 +205,11 @@ def get_volumes(self):
def get_networks(self):
return {} if self.version == V1 else self.config.get('networks', {})

def get_secrets(self):
return {} if self.version < V3_1 else self.config.get('secrets', {})

class Config(namedtuple('_Config', 'version services volumes networks')):

class Config(namedtuple('_Config', 'version services volumes networks secrets')):
"""
:param version: configuration version
:type version: int
Expand Down Expand Up @@ -328,6 +334,7 @@ def load(config_details):
networks = load_mapping(
config_details.config_files, 'get_networks', 'Network'
)
secrets = load_secrets(config_details.config_files, config_details.working_dir)
service_dicts = load_services(config_details, main_file)

if main_file.version != V1:
Expand All @@ -342,7 +349,7 @@ def load(config_details):
"`docker stack deploy` to deploy to a swarm."
.format(", ".join(sorted(s['name'] for s in services_using_deploy))))

return Config(main_file.version, service_dicts, volumes, networks)
return Config(main_file.version, service_dicts, volumes, networks, secrets)


def load_mapping(config_files, get_func, entity_type):
Expand All @@ -356,22 +363,12 @@ def load_mapping(config_files, get_func, entity_type):

external = config.get('external')
if external:
if len(config.keys()) > 1:
raise ConfigurationError(
'{} {} declared as external but specifies'
' additional attributes ({}). '.format(
entity_type,
name,
', '.join([k for k in config.keys() if k != 'external'])
)
)
validate_external(entity_type, name, config)
if isinstance(external, dict):
config['external_name'] = external.get('name')
else:
config['external_name'] = name

mapping[name] = config

if 'driver_opts' in config:
config['driver_opts'] = build_string_dict(
config['driver_opts']
Expand All @@ -383,6 +380,39 @@ def load_mapping(config_files, get_func, entity_type):
return mapping


def validate_external(entity_type, name, config):
if len(config.keys()) <= 1:
return

raise ConfigurationError(
"{} {} declared as external but specifies additional attributes "
"({}).".format(
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 build_service(service_name, service_dict, service_names):
service_config = ServiceConfig.with_abs_paths(
Expand Down Expand Up @@ -820,6 +850,7 @@ def merge_service_dicts(base, override, version):
md.merge_mapping('sysctls', parse_sysctls)
md.merge_mapping('depends_on', parse_depends_on)
md.merge_sequence('links', ServiceLink.parse)
md.merge_sequence('secrets', types.ServiceSecret.parse)

for field in ['volumes', 'devices']:
md.merge_field(field, merge_path_mappings)
Expand Down
Loading