Skip to content

Commit

Permalink
cleanup compatibility and tests
Browse files Browse the repository at this point in the history
Signed-off-by: aiordache <[email protected]>
  • Loading branch information
aiordache committed Jul 8, 2020
1 parent b78c1ec commit c06b305
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 88 deletions.
16 changes: 2 additions & 14 deletions compose/cli/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ def project_from_options(project_dir, options, additional_options=None):
context=context,
environment=environment,
override_dir=override_dir,
compatibility=compatibility_from_options(project_dir, options, environment),
interpolate=(not additional_options.get('--no-interpolate')),
environment_file=environment_file
)
Expand Down Expand Up @@ -98,7 +97,6 @@ def get_config_from_options(base_dir, options, additional_options=None):
)
return config.load(
config.find(base_dir, config_path, environment, override_dir),
compatibility_from_options(config_path, options, environment),
not additional_options.get('--no-interpolate')
)

Expand All @@ -120,14 +118,14 @@ def unicode_paths(paths):

def get_project(project_dir, config_path=None, project_name=None, verbose=False,
context=None, environment=None, override_dir=None,
compatibility=False, interpolate=True, environment_file=None):
interpolate=True, environment_file=None):
if not environment:
environment = Environment.from_env_file(project_dir)
config_details = config.find(project_dir, config_path, environment, override_dir)
project_name = get_project_name(
config_details.working_dir, project_name, environment
)
config_data = config.load(config_details, compatibility, interpolate)
config_data = config.load(config_details, interpolate)

api_version = environment.get(
'COMPOSE_API_VERSION',
Expand Down Expand Up @@ -188,13 +186,3 @@ def normalize_name(name):
return normalize_name(project)

return 'default'


def compatibility_from_options(working_dir, options=None, environment=None):
"""Get compose v3 compatibility from --compatibility option
or from COMPOSE_COMPATIBILITY environment variable."""

compatibility_option = options.get('--compatibility')
compatibility_environment = environment.get_boolean('COMPOSE_COMPATIBILITY')

return compatibility_option or compatibility_environment
80 changes: 6 additions & 74 deletions compose/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ def find_candidates_in_parent_dirs(filenames, path):
return (candidates, path)


def check_swarm_only_config(service_dicts, compatibility=False):
def check_swarm_only_config(service_dicts):
warning_template = (
"Some services ({services}) use the '{key}' key, which will be ignored. "
"Compose does not support '{key}' configuration - use "
Expand All @@ -386,7 +386,7 @@ def check_swarm_only_key(service_dicts, key):
check_swarm_only_key(service_dicts, 'configs')


def load(config_details, compatibility=False, interpolate=True):
def load(config_details, interpolate=True):
"""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.
Expand Down Expand Up @@ -416,13 +416,13 @@ def load(config_details, compatibility=False, interpolate=True):
configs = load_mapping(
config_details.config_files, 'get_configs', 'Config', config_details.working_dir
)
service_dicts = load_services(config_details, main_file, compatibility, interpolate=interpolate)
service_dicts = load_services(config_details, main_file, interpolate=interpolate)

if main_file.version != V1:
for service_dict in service_dicts:
match_named_volumes(service_dict, volumes)

check_swarm_only_config(service_dicts, compatibility)
check_swarm_only_config(service_dicts)

version = main_file.version

Expand Down Expand Up @@ -469,7 +469,7 @@ def validate_external(entity_type, name, config, version):
entity_type, name, ', '.join(k for k in config if k != 'external')))


def load_services(config_details, config_file, compatibility=False, interpolate=True):
def load_services(config_details, config_file, interpolate=True):
def build_service(service_name, service_dict, service_names):
service_config = ServiceConfig.with_abs_paths(
config_details.working_dir,
Expand All @@ -488,7 +488,6 @@ def build_service(service_name, service_dict, service_names):
service_names,
config_file.version,
config_details.environment,
compatibility,
interpolate
)
return service_dict
Expand Down Expand Up @@ -887,7 +886,7 @@ def finalize_service_volumes(service_dict, environment):
return service_dict


def finalize_service(service_config, service_names, version, environment, compatibility,
def finalize_service(service_config, service_names, version, environment,
interpolate=True):
service_dict = dict(service_config.config)

Expand Down Expand Up @@ -929,17 +928,6 @@ def finalize_service(service_config, service_names, version, environment, compat

normalize_build(service_dict, service_config.working_dir, environment)

if compatibility:
service_dict = translate_credential_spec_to_security_opt(service_dict)
service_dict, ignored_keys = translate_deploy_keys_to_container_config(
service_dict
)
if ignored_keys:
log.warning(
'The following deploy sub-keys are not supported in compatibility mode and have'
' been ignored: {}'.format(', '.join(ignored_keys))
)

service_dict['name'] = service_config.name
return normalize_v1_service_format(service_dict)

Expand Down Expand Up @@ -973,62 +961,6 @@ def convert_credential_spec_to_security_opt(credential_spec):
return 'registry://{registry}'.format(registry=credential_spec['registry'])


def translate_credential_spec_to_security_opt(service_dict):
result = []

if 'credential_spec' in service_dict:
spec = convert_credential_spec_to_security_opt(service_dict['credential_spec'])
result.append('credentialspec={spec}'.format(spec=spec))

if result:
service_dict['security_opt'] = result

return service_dict


def translate_deploy_keys_to_container_config(service_dict):
if 'credential_spec' in service_dict:
del service_dict['credential_spec']
if 'configs' in service_dict:
del service_dict['configs']

if 'deploy' not in service_dict:
return service_dict, []

deploy_dict = service_dict['deploy']
ignored_keys = [
k for k in ['endpoint_mode', 'labels', 'update_config', 'rollback_config']
if k in deploy_dict
]

if 'replicas' in deploy_dict and deploy_dict.get('mode', 'replicated') == 'replicated':
scale = deploy_dict.get('replicas', 1)
max_replicas = deploy_dict.get('placement', {}).get('max_replicas_per_node', scale)
service_dict['scale'] = min(scale, max_replicas)
if max_replicas < scale:
log.warning("Scale is limited to {} ('max_replicas_per_node' field).".format(
max_replicas))

if 'restart_policy' in deploy_dict:
service_dict['restart'] = {
'Name': convert_restart_policy(deploy_dict['restart_policy'].get('condition', 'any')),
'MaximumRetryCount': deploy_dict['restart_policy'].get('max_attempts', 0)
}
for k in deploy_dict['restart_policy'].keys():
if k != 'condition' and k != 'max_attempts':
ignored_keys.append('restart_policy.{}'.format(k))

ignored_keys.extend(
translate_resource_keys_to_container_config(
deploy_dict.get('resources', {}), service_dict
)
)

del service_dict['deploy']

return service_dict, ignored_keys


def normalize_v1_service_format(service_dict):
if 'log_driver' in service_dict or 'log_opt' in service_dict:
if 'logging' not in service_dict:
Expand Down
19 changes: 19 additions & 0 deletions compose/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ def from_config(cls, name, config_data, client, default_platform=None, extra_lab
service_dict.pop('secrets', None) or [],
config_data.secrets)

service_dict['scale'] = project.get_service_scale(service_dict)

project.services.append(
Service(
service_dict.pop('name'),
Expand Down Expand Up @@ -262,6 +264,23 @@ def get_pid_mode(self, service_dict):

return PidMode(pid_mode)

def get_service_scale(self, service_dict):
# service.scale for v2 and deploy.replicas for v3
scale = service_dict.get('scale', 1)
deploy_dict = service_dict.get('deploy', None)
if deploy_dict:
if deploy_dict.get('mode', 'replicated') == 'replicated':
scale = deploy_dict.get('replicas', scale)
# deploy may contain placement constraints introduced in v3.8
max_replicas = deploy_dict.get('placement', {}).get(
'max_replicas_per_node',
scale)
scale = min(scale, max_replicas)
if max_replicas < scale:
log.warning("Scale is limited to {} ('max_replicas_per_node' field).".format(
max_replicas))
return scale

def start(self, service_names=None, **options):
containers = []

Expand Down
2 changes: 2 additions & 0 deletions tests/unit/config/config_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3655,6 +3655,7 @@ def test_unset_variable_produces_warning(self):
assert 'BAR' in warnings[0]
assert 'FOO' in warnings[1]

@pytest.mark.skip(reason='compatibility mode was removed internally')
def test_compatibility_mode_warnings(self):
config_details = build_config_details({
'version': '3.5',
Expand Down Expand Up @@ -3693,6 +3694,7 @@ def test_compatibility_mode_warnings(self):
assert 'restart_policy.delay' in warn_message
assert 'restart_policy.window' in warn_message

@pytest.mark.skip(reason='compatibility mode was removed internally')
def test_compatibility_mode_load(self):
config_details = build_config_details({
'version': '3.5',
Expand Down

0 comments on commit c06b305

Please sign in to comment.