Skip to content

Commit

Permalink
Tests for compatibility mode
Browse files Browse the repository at this point in the history
Signed-off-by: Joffrey F <joffrey@docker.com>
  • Loading branch information
shin- committed Feb 17, 2018
1 parent 8c297f2 commit 51076b5
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 14 deletions.
15 changes: 8 additions & 7 deletions compose/cli/main.py
Expand Up @@ -168,8 +168,10 @@ class TopLevelCommand(object):
docker-compose -h|--help
Options:
-f, --file FILE Specify an alternate compose file (default: docker-compose.yml)
-p, --project-name NAME Specify an alternate project name (default: directory name)
-f, --file FILE Specify an alternate compose file
(default: docker-compose.yml)
-p, --project-name NAME Specify an alternate project name
(default: directory name)
--verbose Show more output
--no-ansi Do not print ANSI control characters
-v, --version Print version and exit
Expand All @@ -180,13 +182,12 @@ class TopLevelCommand(object):
--tlscert CLIENT_CERT_PATH Path to TLS certificate file
--tlskey TLS_KEY_PATH Path to TLS key file
--tlsverify Use TLS and verify the remote
--skip-hostname-check Don't check the daemon's hostname against the name specified
in the client certificate (for example if your docker host
is an IP address)
--skip-hostname-check Don't check the daemon's hostname against the
name specified in the client certificate
--project-directory PATH Specify an alternate working directory
(default: the path of the Compose file)
--compatibility If set, Compose will attempt to convert deploy keys in v3
files to their non-Swarm equivalent
--compatibility If set, Compose will attempt to convert deploy
keys in v3 files to their non-Swarm equivalent
Commands:
build Build or rebuild services
Expand Down
3 changes: 2 additions & 1 deletion compose/config/config.py
Expand Up @@ -896,6 +896,7 @@ def translate_resource_keys_to_container_config(resources_dict, service_dict):
service_dict['mem_reservation'] = resources_dict['reservations'].get('memory')
if 'cpus' in resources_dict['reservations']:
return ['resources.reservations.cpus']
return []


def convert_restart_policy(name):
Expand All @@ -919,7 +920,7 @@ def translate_deploy_keys_to_container_config(service_dict):
if k in deploy_dict
]

if 'replicas' in deploy_dict and deploy_dict.get('mode') == 'replicated':
if 'replicas' in deploy_dict and deploy_dict.get('mode', 'replicated') == 'replicated':
service_dict['scale'] = deploy_dict['replicas']

if 'restart_policy' in deploy_dict:
Expand Down
2 changes: 1 addition & 1 deletion compose/config/config_schema_v3.6.json
@@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "config_schema_v3.5.json",
"id": "config_schema_v3.6.json",
"type": "object",
"required": ["version"],

Expand Down
34 changes: 29 additions & 5 deletions tests/acceptance/cli_test.py
Expand Up @@ -395,7 +395,7 @@ def test_config_v3(self):
result = self.dispatch(['config'])

assert yaml.load(result.stdout) == {
'version': '3.2',
'version': '3.5',
'volumes': {
'foobar': {
'labels': {
Expand All @@ -419,22 +419,25 @@ def test_config_v3(self):
},
'resources': {
'limits': {
'cpus': '0.001',
'cpus': '0.05',
'memory': '50M',
},
'reservations': {
'cpus': '0.0001',
'cpus': '0.01',
'memory': '20M',
},
},
'restart_policy': {
'condition': 'on_failure',
'condition': 'on-failure',
'delay': '5s',
'max_attempts': 3,
'window': '120s',
},
'placement': {
'constraints': ['node=foo'],
'constraints': [
'node.hostname==foo', 'node.role != manager'
],
'preferences': [{'spread': 'node.labels.datacenter'}]
},
},

Expand Down Expand Up @@ -464,6 +467,27 @@ def test_config_v3(self):
},
}

def test_config_compatibility_mode(self):
self.base_dir = 'tests/fixtures/compatibility-mode'
result = self.dispatch(['--compatibility', 'config'])

assert yaml.load(result.stdout) == {
'version': '2.3',
'volumes': {'foo': {'driver': 'default'}},
'services': {
'foo': {
'command': '/bin/true',
'image': 'alpine:3.7',
'scale': 3,
'restart': 'always:7',
'mem_limit': '300M',
'mem_reservation': '100M',
'cpus': 0.7,
'volumes': ['foo:/bar:rw']
}
}
}

def test_ps(self):
self.project.get_service('simple').create_container()
result = self.dispatch(['ps'])
Expand Down
22 changes: 22 additions & 0 deletions tests/fixtures/compatibility-mode/docker-compose.yml
@@ -0,0 +1,22 @@
version: '3.5'
services:
foo:
image: alpine:3.7
command: /bin/true
deploy:
replicas: 3
restart_policy:
condition: any
max_attempts: 7
resources:
limits:
memory: 300M
cpus: '0.7'
reservations:
memory: 100M
volumes:
- foo:/bar

volumes:
foo:
driver: default
76 changes: 76 additions & 0 deletions tests/unit/config/config_test.py
Expand Up @@ -3303,6 +3303,82 @@ def test_unset_variable_produces_warning(self):
assert 'BAR' in warnings[0]
assert 'FOO' in warnings[1]

def test_compatibility_mode_warnings(self):
config_details = build_config_details({
'version': '3.5',
'services': {
'web': {
'deploy': {
'labels': ['abc=def'],
'endpoint_mode': 'dnsrr',
'update_config': {'max_failure_ratio': 0.4},
'placement': {'constraints': ['node.id==deadbeef']},
'resources': {
'reservations': {'cpus': '0.2'}
},
'restart_policy': {
'delay': '2s',
'window': '12s'
}
},
'image': 'busybox'
}
}
})

with mock.patch('compose.config.config.log') as log:
config.load(config_details, compatibility=True)

assert log.warn.call_count == 1
warn_message = log.warn.call_args[0][0]
assert warn_message.startswith(
'The following deploy sub-keys are not supported in compatibility mode'
)
assert 'labels' in warn_message
assert 'endpoint_mode' in warn_message
assert 'update_config' in warn_message
assert 'placement' in warn_message
assert 'resources.reservations.cpus' in warn_message
assert 'restart_policy.delay' in warn_message
assert 'restart_policy.window' in warn_message

def test_compatibility_mode_load(self):
config_details = build_config_details({
'version': '3.5',
'services': {
'foo': {
'image': 'alpine:3.7',
'deploy': {
'replicas': 3,
'restart_policy': {
'condition': 'any',
'max_attempts': 7,
},
'resources': {
'limits': {'memory': '300M', 'cpus': '0.7'},
'reservations': {'memory': '100M'},
},
},
},
},
})

with mock.patch('compose.config.config.log') as log:
cfg = config.load(config_details, compatibility=True)

assert log.warn.call_count == 0

service_dict = cfg.services[0]
assert service_dict == {
'image': 'alpine:3.7',
'scale': 3,
'restart': {'MaximumRetryCount': 7, 'Name': 'always'},
'mem_limit': '300M',
'mem_reservation': '100M',
'cpus': 0.7,
'name': 'foo'
}

@mock.patch.dict(os.environ)
def test_invalid_interpolation(self):
with pytest.raises(config.ConfigurationError) as cm:
Expand Down

0 comments on commit 51076b5

Please sign in to comment.