Support V3.2

Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
Daniel Nephin 2017-03-13 15:57:13 -04:00
parent 0ba1f61e9b
commit 2acf286ed6
9 changed files with 49 additions and 48 deletions

View File

@ -13,11 +13,8 @@ import yaml
from cached_property import cached_property from cached_property import cached_property
from . import types from . import types
from .. import const
from ..const import COMPOSEFILE_V1 as V1 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 build_string_dict
from ..utils import parse_nanoseconds_int from ..utils import parse_nanoseconds_int
from ..utils import splitdrive from ..utils import splitdrive
@ -185,10 +182,10 @@ class ConfigFile(namedtuple('_ConfigFile', 'filename config')):
.format(self.filename, VERSION_EXPLANATION)) .format(self.filename, VERSION_EXPLANATION))
if version == '2': if version == '2':
version = V2_0 version = const.COMPOSEFILE_V2_0
if version == '3': if version == '3':
version = V3_0 version = const.COMPOSEFILE_V3_0
return version return version
@ -205,7 +202,7 @@ class ConfigFile(namedtuple('_ConfigFile', 'filename config')):
return {} if self.version == V1 else self.config.get('networks', {}) return {} if self.version == V1 else self.config.get('networks', {})
def get_secrets(self): def get_secrets(self):
return {} if self.version < V3_1 else self.config.get('secrets', {}) return {} if self.version < const.COMPOSEFILE_V3_1 else self.config.get('secrets', {})
class Config(namedtuple('_Config', 'version services volumes networks secrets')): class Config(namedtuple('_Config', 'version services volumes networks secrets')):
@ -427,7 +424,7 @@ def load_services(config_details, config_file):
service_dict = process_service(resolver.run()) service_dict = process_service(resolver.run())
service_config = service_config._replace(config=service_dict) service_config = service_config._replace(config=service_dict)
validate_service(service_config, service_names, config_file.version) validate_service(service_config, service_names, config_file)
service_dict = finalize_service( service_dict = finalize_service(
service_config, service_config,
service_names, service_names,
@ -480,7 +477,7 @@ def process_config_file(config_file, environment, service_name=None):
'service', 'service',
environment) environment)
if config_file.version in (V2_0, V2_1, V3_0, V3_1): if config_file.version != V1:
processed_config = dict(config_file.config) processed_config = dict(config_file.config)
processed_config['services'] = services processed_config['services'] = services
processed_config['volumes'] = interpolate_config_section( processed_config['volumes'] = interpolate_config_section(
@ -493,19 +490,13 @@ def process_config_file(config_file, environment, service_name=None):
config_file.get_networks(), config_file.get_networks(),
'network', 'network',
environment) environment)
if config_file.version in (V3_1,): processed_config['secrets'] = interpolate_config_section(
processed_config['secrets'] = interpolate_config_section( config_file,
config_file, config_file.get_secrets(),
config_file.get_secrets(), 'secrets',
'secrets', environment)
environment
)
elif config_file.version == V1:
processed_config = services
else: else:
raise ConfigurationError( processed_config = services
'Version in "{}" is unsupported. {}'
.format(config_file.filename, VERSION_EXPLANATION))
config_file = config_file._replace(config=processed_config) config_file = config_file._replace(config=processed_config)
validate_against_config_schema(config_file) validate_against_config_schema(config_file)
@ -642,9 +633,9 @@ def validate_extended_service_dict(service_dict, filename, service):
"%s services with 'depends_on' cannot be extended" % error_prefix) "%s services with 'depends_on' cannot be extended" % error_prefix)
def validate_service(service_config, service_names, version): def validate_service(service_config, service_names, config_file):
service_dict, service_name = service_config.config, service_config.name service_dict, service_name = service_config.config, service_config.name
validate_service_constraints(service_dict, service_name, version) validate_service_constraints(service_dict, service_name, config_file)
validate_paths(service_dict) validate_paths(service_dict)
validate_ulimits(service_config) validate_ulimits(service_config)

View File

@ -4,10 +4,10 @@ from __future__ import unicode_literals
import six import six
import yaml import yaml
from compose import const
from compose.config import types from compose.config import types
from compose.config.config import V1 from compose.const import COMPOSEFILE_V1 as V1
from compose.config.config import V2_1 from compose.const import COMPOSEFILE_V2_1 as V2_1
from compose.config.config import V3_1
def serialize_config_type(dumper, data): def serialize_config_type(dumper, data):
@ -103,7 +103,7 @@ def denormalize_service_dict(service_dict, version):
service_dict['healthcheck']['timeout'] service_dict['healthcheck']['timeout']
) )
if 'ports' in service_dict and version != V3_1: if 'ports' in service_dict and version < const.COMPOSEFILE_V3_2:
service_dict['ports'] = map( service_dict['ports'] = map(
lambda p: p.legacy_repr() if isinstance(p, types.ServicePort) else p, lambda p: p.legacy_repr() if isinstance(p, types.ServicePort) else p,
service_dict['ports'] service_dict['ports']

View File

@ -365,7 +365,7 @@ def process_config_schema_errors(error):
def validate_against_config_schema(config_file): def validate_against_config_schema(config_file):
schema = load_jsonschema(config_file.version) schema = load_jsonschema(config_file)
format_checker = FormatChecker(["ports", "expose"]) format_checker = FormatChecker(["ports", "expose"])
validator = Draft4Validator( validator = Draft4Validator(
schema, schema,
@ -377,11 +377,12 @@ def validate_against_config_schema(config_file):
config_file.filename) config_file.filename)
def validate_service_constraints(config, service_name, version): def validate_service_constraints(config, service_name, config_file):
def handler(errors): def handler(errors):
return process_service_constraint_errors(errors, service_name, version) return process_service_constraint_errors(
errors, service_name, config_file.version)
schema = load_jsonschema(version) schema = load_jsonschema(config_file)
validator = Draft4Validator(schema['definitions']['constraints']['service']) validator = Draft4Validator(schema['definitions']['constraints']['service'])
handle_errors(validator.iter_errors(config), handler, None) handle_errors(validator.iter_errors(config), handler, None)
@ -390,10 +391,15 @@ def get_schema_path():
return os.path.dirname(os.path.abspath(__file__)) return os.path.dirname(os.path.abspath(__file__))
def load_jsonschema(version): def load_jsonschema(config_file):
filename = os.path.join( filename = os.path.join(
get_schema_path(), get_schema_path(),
"config_schema_v{0}.json".format(version)) "config_schema_v{0}.json".format(config_file.version))
if not os.path.exists(filename):
raise ConfigurationError(
'Version in "{}" is unsupported. {}'
.format(config_file.filename, VERSION_EXPLANATION))
with open(filename, "r") as fh: with open(filename, "r") as fh:
return json.load(fh) return json.load(fh)

View File

@ -21,8 +21,10 @@ SECRETS_PATH = '/run/secrets'
COMPOSEFILE_V1 = '1' COMPOSEFILE_V1 = '1'
COMPOSEFILE_V2_0 = '2.0' COMPOSEFILE_V2_0 = '2.0'
COMPOSEFILE_V2_1 = '2.1' COMPOSEFILE_V2_1 = '2.1'
COMPOSEFILE_V3_0 = '3.0' COMPOSEFILE_V3_0 = '3.0'
COMPOSEFILE_V3_1 = '3.1' COMPOSEFILE_V3_1 = '3.1'
COMPOSEFILE_V3_2 = '3.2'
API_VERSIONS = { API_VERSIONS = {
COMPOSEFILE_V1: '1.21', COMPOSEFILE_V1: '1.21',
@ -30,6 +32,7 @@ API_VERSIONS = {
COMPOSEFILE_V2_1: '1.24', COMPOSEFILE_V2_1: '1.24',
COMPOSEFILE_V3_0: '1.25', COMPOSEFILE_V3_0: '1.25',
COMPOSEFILE_V3_1: '1.25', COMPOSEFILE_V3_1: '1.25',
COMPOSEFILE_V3_2: '1.25',
} }
API_VERSION_TO_ENGINE_VERSION = { API_VERSION_TO_ENGINE_VERSION = {
@ -38,4 +41,5 @@ API_VERSION_TO_ENGINE_VERSION = {
API_VERSIONS[COMPOSEFILE_V2_1]: '1.12.0', API_VERSIONS[COMPOSEFILE_V2_1]: '1.12.0',
API_VERSIONS[COMPOSEFILE_V3_0]: '1.13.0', API_VERSIONS[COMPOSEFILE_V3_0]: '1.13.0',
API_VERSIONS[COMPOSEFILE_V3_1]: '1.13.0', API_VERSIONS[COMPOSEFILE_V3_1]: '1.13.0',
API_VERSIONS[COMPOSEFILE_V3_2]: '1.13.0',
} }

View File

@ -1,4 +1,4 @@
version: '3.1' version: '3.2'
services: services:
simple: simple:
image: busybox:latest image: busybox:latest

View File

@ -15,11 +15,11 @@ from .testcases import DockerClientTestCase
from compose.config import config from compose.config import config
from compose.config import ConfigurationError from compose.config import ConfigurationError
from compose.config import types from compose.config import types
from compose.config.config import V2_0
from compose.config.config import V2_1
from compose.config.config import V3_1
from compose.config.types import VolumeFromSpec from compose.config.types import VolumeFromSpec
from compose.config.types import VolumeSpec from compose.config.types import VolumeSpec
from compose.const import COMPOSEFILE_V2_0 as V2_0
from compose.const import COMPOSEFILE_V2_1 as V2_1
from compose.const import COMPOSEFILE_V3_1 as V3_1
from compose.const import LABEL_PROJECT from compose.const import LABEL_PROJECT
from compose.const import LABEL_SERVICE from compose.const import LABEL_SERVICE
from compose.container import Container from compose.container import Container

View File

@ -10,12 +10,12 @@ from pytest import skip
from .. import unittest from .. import unittest
from compose.cli.docker_client import docker_client from compose.cli.docker_client import docker_client
from compose.config.config import resolve_environment from compose.config.config import resolve_environment
from compose.config.config import V1
from compose.config.config import V2_0
from compose.config.config import V2_1
from compose.config.config import V3_0
from compose.config.environment import Environment from compose.config.environment import Environment
from compose.const import API_VERSIONS from compose.const import API_VERSIONS
from compose.const import COMPOSEFILE_V1 as V1
from compose.const import COMPOSEFILE_V2_0 as V2_0
from compose.const import COMPOSEFILE_V2_0 as V2_1
from compose.const import COMPOSEFILE_V3_0 as V3_0
from compose.const import LABEL_PROJECT from compose.const import LABEL_PROJECT
from compose.progress_stream import stream_output from compose.progress_stream import stream_output
from compose.service import Service from compose.service import Service

View File

@ -17,11 +17,6 @@ from compose.config import config
from compose.config import types from compose.config import types
from compose.config.config import resolve_build_args from compose.config.config import resolve_build_args
from compose.config.config import resolve_environment from compose.config.config import resolve_environment
from compose.config.config import V1
from compose.config.config import V2_0
from compose.config.config import V2_1
from compose.config.config import V3_0
from compose.config.config import V3_1
from compose.config.environment import Environment from compose.config.environment import Environment
from compose.config.errors import ConfigurationError from compose.config.errors import ConfigurationError
from compose.config.errors import VERSION_EXPLANATION from compose.config.errors import VERSION_EXPLANATION
@ -29,6 +24,11 @@ from compose.config.serialize import denormalize_service_dict
from compose.config.serialize import serialize_config from compose.config.serialize import serialize_config
from compose.config.serialize import serialize_ns_time_value from compose.config.serialize import serialize_ns_time_value
from compose.config.types import VolumeSpec from compose.config.types import VolumeSpec
from compose.const import COMPOSEFILE_V1 as V1
from compose.const import COMPOSEFILE_V2_0 as V2_0
from compose.const import COMPOSEFILE_V2_1 as V2_1
from compose.const import COMPOSEFILE_V3_0 as V3_0
from compose.const import COMPOSEFILE_V3_1 as V3_1
from compose.const import IS_WINDOWS_PLATFORM from compose.const import IS_WINDOWS_PLATFORM
from compose.utils import nanoseconds_from_time_seconds from compose.utils import nanoseconds_from_time_seconds
from tests import mock from tests import mock

View File

@ -3,13 +3,13 @@ from __future__ import unicode_literals
import pytest import pytest
from compose.config.config import V1
from compose.config.config import V2_0
from compose.config.errors import ConfigurationError from compose.config.errors import ConfigurationError
from compose.config.types import parse_extra_hosts from compose.config.types import parse_extra_hosts
from compose.config.types import ServicePort from compose.config.types import ServicePort
from compose.config.types import VolumeFromSpec from compose.config.types import VolumeFromSpec
from compose.config.types import VolumeSpec from compose.config.types import VolumeSpec
from compose.const import COMPOSEFILE_V1 as V1
from compose.const import COMPOSEFILE_V2_0 as V2_0
def test_parse_extra_hosts_list(): def test_parse_extra_hosts_list():