Jelajahi Sumber

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

WIP: Fix output of 'config' for v1 files
Aanand Prasad 9 tahun lalu
induk
melakukan
7ad7eb71ca

+ 26 - 2
compose/config/serialize.py

@@ -5,6 +5,8 @@ import six
 import yaml
 
 from compose.config import types
+from compose.config.config import V1
+from compose.config.config import V2_0
 
 
 def serialize_config_type(dumper, data):
@@ -17,14 +19,36 @@ yaml.SafeDumper.add_representer(types.VolumeSpec, serialize_config_type)
 
 
 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 = {
-        'version': config.version,
-        'services': {service.pop('name'): service for service in config.services},
+        'version': V2_0,
+        'services': services,
         'networks': config.networks,
         'volumes': config.volumes,
     }
+
     return yaml.safe_dump(
         output,
         default_flow_style=False,
         indent=2,
         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

+ 9 - 0
compose/config/types.py

@@ -7,6 +7,8 @@ from __future__ import unicode_literals
 import os
 from collections import namedtuple
 
+import six
+
 from compose.config.config import V1
 from compose.config.errors import ConfigurationError
 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)}
 
 
+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):
     if not extra_hosts_config:
         return {}

+ 53 - 11
tests/acceptance/cli_test.py

@@ -145,15 +145,11 @@ class CLITestCase(DockerClientTestCase):
         # Prevent tearDown from trying to create a project
         self.base_dir = None
 
-    # TODO: this shouldn't be v2-dependent
-    @v2_only()
     def test_config_list_services(self):
         self.base_dir = 'tests/fixtures/v2-full'
         result = self.dispatch(['config', '--services'])
         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):
         self.base_dir = None
         result = self.dispatch([
@@ -162,14 +158,10 @@ class CLITestCase(DockerClientTestCase):
         ], returncode=1)
         assert "'notaservice' must be a mapping" in result.stderr
 
-    # TODO: this shouldn't be v2-dependent
-    @v2_only()
     def test_config_quiet(self):
         self.base_dir = 'tests/fixtures/v2-full'
         assert self.dispatch(['config', '-q']).stdout == ''
 
-    # TODO: this shouldn't be v2-dependent
-    @v2_only()
     def test_config_default(self):
         self.base_dir = 'tests/fixtures/v2-full'
         result = self.dispatch(['config'])
@@ -198,6 +190,58 @@ class CLITestCase(DockerClientTestCase):
         }
         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):
         self.project.get_service('simple').create_container()
         result = self.dispatch(['ps'])
@@ -683,9 +727,7 @@ class CLITestCase(DockerClientTestCase):
             ['-f', 'v2-invalid.yml', 'up', '-d'],
             returncode=1)
 
-        # TODO: fix validation error messages for v2 files
-        # assert "Unsupported config option for service 'web': 'net'" in exc.exconly()
-        assert "Unsupported config option" in result.stderr
+        assert "Unsupported config option for services.bar: 'net'" in result.stderr
 
     def test_up_with_net_v1(self):
         self.base_dir = 'tests/fixtures/net-container'

+ 14 - 0
tests/fixtures/restart/docker-compose.yml

@@ -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"

+ 10 - 0
tests/fixtures/v1-config/docker-compose.yml

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