Merge pull request #3164 from aanand/fix-config-v1

WIP: Fix output of 'config' for v1 files
This commit is contained in:
Aanand Prasad 2016-04-26 20:34:18 +01:00
commit 7ad7eb71ca
5 changed files with 112 additions and 13 deletions

View File

@ -5,6 +5,8 @@ import six
import yaml import yaml
from compose.config import types from compose.config import types
from compose.config.config import V1
from compose.config.config import V2_0
def serialize_config_type(dumper, data): def serialize_config_type(dumper, data):
@ -17,14 +19,36 @@ yaml.SafeDumper.add_representer(types.VolumeSpec, serialize_config_type)
def serialize_config(config): def serialize_config(config):
denormalized_services = [
denormalize_service_dict(service_dict, config.version)
for service_dict in config.services
]
services = {
service_dict.pop('name'): service_dict
for service_dict in denormalized_services
}
output = { output = {
'version': config.version, 'version': V2_0,
'services': {service.pop('name'): service for service in config.services}, 'services': services,
'networks': config.networks, 'networks': config.networks,
'volumes': config.volumes, 'volumes': config.volumes,
} }
return yaml.safe_dump( return yaml.safe_dump(
output, output,
default_flow_style=False, default_flow_style=False,
indent=2, indent=2,
width=80) width=80)
def denormalize_service_dict(service_dict, version):
service_dict = service_dict.copy()
if 'restart' in service_dict:
service_dict['restart'] = types.serialize_restart_spec(service_dict['restart'])
if version == V1 and 'network_mode' not in service_dict:
service_dict['network_mode'] = 'bridge'
return service_dict

View File

@ -7,6 +7,8 @@ from __future__ import unicode_literals
import os import os
from collections import namedtuple from collections import namedtuple
import six
from compose.config.config import V1 from compose.config.config import V1
from compose.config.errors import ConfigurationError from compose.config.errors import ConfigurationError
from compose.const import IS_WINDOWS_PLATFORM from compose.const import IS_WINDOWS_PLATFORM
@ -89,6 +91,13 @@ def parse_restart_spec(restart_config):
return {'Name': name, 'MaximumRetryCount': int(max_retry_count)} return {'Name': name, 'MaximumRetryCount': int(max_retry_count)}
def serialize_restart_spec(restart_spec):
parts = [restart_spec['Name']]
if restart_spec['MaximumRetryCount']:
parts.append(six.text_type(restart_spec['MaximumRetryCount']))
return ':'.join(parts)
def parse_extra_hosts(extra_hosts_config): def parse_extra_hosts(extra_hosts_config):
if not extra_hosts_config: if not extra_hosts_config:
return {} return {}

View File

@ -145,15 +145,11 @@ class CLITestCase(DockerClientTestCase):
# Prevent tearDown from trying to create a project # Prevent tearDown from trying to create a project
self.base_dir = None self.base_dir = None
# TODO: this shouldn't be v2-dependent
@v2_only()
def test_config_list_services(self): def test_config_list_services(self):
self.base_dir = 'tests/fixtures/v2-full' self.base_dir = 'tests/fixtures/v2-full'
result = self.dispatch(['config', '--services']) result = self.dispatch(['config', '--services'])
assert set(result.stdout.rstrip().split('\n')) == {'web', 'other'} assert set(result.stdout.rstrip().split('\n')) == {'web', 'other'}
# TODO: this shouldn't be v2-dependent
@v2_only()
def test_config_quiet_with_error(self): def test_config_quiet_with_error(self):
self.base_dir = None self.base_dir = None
result = self.dispatch([ result = self.dispatch([
@ -162,14 +158,10 @@ class CLITestCase(DockerClientTestCase):
], returncode=1) ], returncode=1)
assert "'notaservice' must be a mapping" in result.stderr assert "'notaservice' must be a mapping" in result.stderr
# TODO: this shouldn't be v2-dependent
@v2_only()
def test_config_quiet(self): def test_config_quiet(self):
self.base_dir = 'tests/fixtures/v2-full' self.base_dir = 'tests/fixtures/v2-full'
assert self.dispatch(['config', '-q']).stdout == '' assert self.dispatch(['config', '-q']).stdout == ''
# TODO: this shouldn't be v2-dependent
@v2_only()
def test_config_default(self): def test_config_default(self):
self.base_dir = 'tests/fixtures/v2-full' self.base_dir = 'tests/fixtures/v2-full'
result = self.dispatch(['config']) result = self.dispatch(['config'])
@ -198,6 +190,58 @@ class CLITestCase(DockerClientTestCase):
} }
assert output == expected assert output == expected
def test_config_restart(self):
self.base_dir = 'tests/fixtures/restart'
result = self.dispatch(['config'])
assert yaml.load(result.stdout) == {
'version': '2.0',
'services': {
'never': {
'image': 'busybox',
'restart': 'no',
},
'always': {
'image': 'busybox',
'restart': 'always',
},
'on-failure': {
'image': 'busybox',
'restart': 'on-failure',
},
'on-failure-5': {
'image': 'busybox',
'restart': 'on-failure:5',
},
},
'networks': {},
'volumes': {},
}
def test_config_v1(self):
self.base_dir = 'tests/fixtures/v1-config'
result = self.dispatch(['config'])
assert yaml.load(result.stdout) == {
'version': '2.0',
'services': {
'net': {
'image': 'busybox',
'network_mode': 'bridge',
},
'volume': {
'image': 'busybox',
'volumes': ['/data:rw'],
'network_mode': 'bridge',
},
'app': {
'image': 'busybox',
'volumes_from': ['service:volume:rw'],
'network_mode': 'service:net',
},
},
'networks': {},
'volumes': {},
}
def test_ps(self): def test_ps(self):
self.project.get_service('simple').create_container() self.project.get_service('simple').create_container()
result = self.dispatch(['ps']) result = self.dispatch(['ps'])
@ -683,9 +727,7 @@ class CLITestCase(DockerClientTestCase):
['-f', 'v2-invalid.yml', 'up', '-d'], ['-f', 'v2-invalid.yml', 'up', '-d'],
returncode=1) returncode=1)
# TODO: fix validation error messages for v2 files assert "Unsupported config option for services.bar: 'net'" in result.stderr
# assert "Unsupported config option for service 'web': 'net'" in exc.exconly()
assert "Unsupported config option" in result.stderr
def test_up_with_net_v1(self): def test_up_with_net_v1(self):
self.base_dir = 'tests/fixtures/net-container' self.base_dir = 'tests/fixtures/net-container'

View File

@ -0,0 +1,14 @@
version: "2"
services:
never:
image: busybox
restart: "no"
always:
image: busybox
restart: always
on-failure:
image: busybox
restart: on-failure
on-failure-5:
image: busybox
restart: "on-failure:5"

View File

@ -0,0 +1,10 @@
net:
image: busybox
volume:
image: busybox
volumes:
- /data
app:
image: busybox
net: "container:net"
volumes_from: ["volume"]