mirror of
https://github.com/docker/compose.git
synced 2025-07-27 15:44:08 +02:00
Merge pull request #7588 from aiordache/rm_version
Merge V2 - V3 compose file formats (optional version field)
This commit is contained in:
commit
52d2fcc274
@ -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
|
||||
)
|
||||
@ -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')
|
||||
)
|
||||
|
||||
@ -120,14 +118,14 @@ def get_config_path_from_options(base_dir, options, environment):
|
||||
|
||||
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',
|
||||
@ -188,13 +186,3 @@ def get_project_name(working_dir, project_name=None, environment=None):
|
||||
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
|
||||
|
@ -24,7 +24,6 @@ from ..config import resolve_build_args
|
||||
from ..config.environment import Environment
|
||||
from ..config.serialize import serialize_config
|
||||
from ..config.types import VolumeSpec
|
||||
from ..const import COMPOSEFILE_V2_2 as V2_2
|
||||
from ..const import IS_WINDOWS_PLATFORM
|
||||
from ..errors import StreamParseError
|
||||
from ..progress_stream import StreamOutputError
|
||||
@ -205,7 +204,7 @@ class TopLevelCommand(object):
|
||||
--project-directory PATH Specify an alternate working directory
|
||||
(default: the path of the Compose file)
|
||||
--compatibility If set, Compose will attempt to convert keys
|
||||
in v3 files to their non-Swarm equivalent
|
||||
in v3 files to their non-Swarm equivalent (DEPRECATED)
|
||||
--env-file PATH Specify an alternate environment file
|
||||
|
||||
Commands:
|
||||
@ -882,12 +881,6 @@ class TopLevelCommand(object):
|
||||
"""
|
||||
timeout = timeout_from_opts(options)
|
||||
|
||||
if self.project.config_version == V2_2:
|
||||
raise UserError(
|
||||
'The scale command is incompatible with the v2.2 format. '
|
||||
'Use the up command with the --scale flag instead.'
|
||||
)
|
||||
else:
|
||||
log.warning(
|
||||
'The scale command is deprecated. '
|
||||
'Use the up command with the --scale flag instead.'
|
||||
|
@ -12,18 +12,13 @@ import yaml
|
||||
from cached_property import cached_property
|
||||
|
||||
from . import types
|
||||
from .. import const
|
||||
from ..const import COMPOSE_SPEC as VERSION
|
||||
from ..const import COMPOSEFILE_V1 as V1
|
||||
from ..const import COMPOSEFILE_V2_1 as V2_1
|
||||
from ..const import COMPOSEFILE_V2_3 as V2_3
|
||||
from ..const import COMPOSEFILE_V3_0 as V3_0
|
||||
from ..const import COMPOSEFILE_V3_4 as V3_4
|
||||
from ..utils import build_string_dict
|
||||
from ..utils import json_hash
|
||||
from ..utils import parse_bytes
|
||||
from ..utils import parse_nanoseconds_int
|
||||
from ..utils import splitdrive
|
||||
from ..version import ComposeVersion
|
||||
from .environment import env_vars_from_file
|
||||
from .environment import Environment
|
||||
from .environment import split_env
|
||||
@ -189,15 +184,28 @@ class ConfigFile(namedtuple('_ConfigFile', 'filename config')):
|
||||
|
||||
@cached_property
|
||||
def version(self):
|
||||
if 'version' not in self.config:
|
||||
return V1
|
||||
version = self.config.get('version', None)
|
||||
if not version:
|
||||
# no version is specified in the config file
|
||||
services = self.config.get('services', None)
|
||||
networks = self.config.get('networks', None)
|
||||
volumes = self.config.get('volumes', None)
|
||||
if services or networks or volumes:
|
||||
# validate V2/V3 structure
|
||||
for section in ['services', 'networks', 'volumes']:
|
||||
validate_config_section(
|
||||
self.filename, self.config.get(section, {}), section)
|
||||
return VERSION
|
||||
|
||||
version = self.config['version']
|
||||
# validate V1 structure
|
||||
validate_config_section(
|
||||
self.filename, self.config, 'services')
|
||||
return V1
|
||||
|
||||
if isinstance(version, dict):
|
||||
log.warning('Unexpected type for "version" key in "{}". Assuming '
|
||||
'"version" is the name of a service, and defaulting to '
|
||||
'Compose file version 1.'.format(self.filename))
|
||||
'Compose file version {}.'.format(self.filename, V1))
|
||||
return V1
|
||||
|
||||
if not isinstance(version, str):
|
||||
@ -205,31 +213,32 @@ class ConfigFile(namedtuple('_ConfigFile', 'filename config')):
|
||||
'Version in "{}" is invalid - it should be a string.'
|
||||
.format(self.filename))
|
||||
|
||||
if version == '1':
|
||||
raise ConfigurationError(
|
||||
'Version in "{}" is invalid. {}'
|
||||
.format(self.filename, VERSION_EXPLANATION)
|
||||
)
|
||||
|
||||
version_pattern = re.compile(r"^[2-9]+(\.\d+)?$")
|
||||
if isinstance(version, str):
|
||||
version_pattern = re.compile(r"^[1-3]+(\.\d+)?$")
|
||||
if not version_pattern.match(version):
|
||||
raise ConfigurationError(
|
||||
'Version "{}" in "{}" is invalid.'
|
||||
.format(version, self.filename))
|
||||
|
||||
if version == '2':
|
||||
return const.COMPOSEFILE_V2_0
|
||||
if version.startswith("1"):
|
||||
version = V1
|
||||
else:
|
||||
version = VERSION
|
||||
|
||||
if version == '3':
|
||||
return const.COMPOSEFILE_V3_0
|
||||
|
||||
return ComposeVersion(version)
|
||||
if version == V1:
|
||||
raise ConfigurationError(
|
||||
'Version in "{}" is invalid. {}'
|
||||
.format(self.filename, VERSION_EXPLANATION)
|
||||
)
|
||||
return version
|
||||
|
||||
def get_service(self, name):
|
||||
return self.get_service_dicts()[name]
|
||||
|
||||
def get_service_dicts(self):
|
||||
return self.config if self.version == V1 else self.config.get('services', {})
|
||||
if self.version == V1:
|
||||
return self.config
|
||||
return self.config.get('services', {})
|
||||
|
||||
def get_volumes(self):
|
||||
return {} if self.version == V1 else self.config.get('volumes', {})
|
||||
@ -238,10 +247,10 @@ class ConfigFile(namedtuple('_ConfigFile', 'filename config')):
|
||||
return {} if self.version == V1 else self.config.get('networks', {})
|
||||
|
||||
def get_secrets(self):
|
||||
return {} if self.version < const.COMPOSEFILE_V3_1 else self.config.get('secrets', {})
|
||||
return {} if self.version == V1 else self.config.get('secrets', {})
|
||||
|
||||
def get_configs(self):
|
||||
return {} if self.version < const.COMPOSEFILE_V3_3 else self.config.get('configs', {})
|
||||
return {} if self.version == V1 else self.config.get('configs', {})
|
||||
|
||||
|
||||
class Config(namedtuple('_Config', 'version services volumes networks secrets configs')):
|
||||
@ -299,6 +308,7 @@ def find(base_dir, filenames, environment, override_dir=None):
|
||||
def validate_config_version(config_files):
|
||||
main_file = config_files[0]
|
||||
validate_top_level_object(main_file)
|
||||
|
||||
for next_file in config_files[1:]:
|
||||
validate_top_level_object(next_file)
|
||||
|
||||
@ -355,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 "
|
||||
@ -371,18 +381,20 @@ def check_swarm_only_config(service_dicts, compatibility=False):
|
||||
key=key
|
||||
)
|
||||
)
|
||||
if not compatibility:
|
||||
|
||||
check_swarm_only_key(service_dicts, 'deploy')
|
||||
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.
|
||||
|
||||
Return a fully interpolated, extended and validated configuration.
|
||||
"""
|
||||
|
||||
# validate against latest version and if fails do it against v1 schema
|
||||
validate_config_version(config_details.config_files)
|
||||
|
||||
processed_files = [
|
||||
@ -404,15 +416,15 @@ 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 = V2_3 if compatibility and main_file.version >= V3_0 else main_file.version
|
||||
version = main_file.version
|
||||
|
||||
return Config(version, service_dicts, volumes, networks, secrets, configs)
|
||||
|
||||
@ -449,14 +461,15 @@ def load_mapping(config_files, get_func, entity_type, working_dir=None):
|
||||
|
||||
|
||||
def validate_external(entity_type, name, config, version):
|
||||
if (version < V2_1 or (version >= V3_0 and version < V3_4)) and len(config.keys()) > 1:
|
||||
for k in config.keys():
|
||||
if k not in ['external', 'name']:
|
||||
raise ConfigurationError(
|
||||
"{} {} declared as external but specifies additional attributes "
|
||||
"({}).".format(
|
||||
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,
|
||||
@ -475,7 +488,6 @@ def load_services(config_details, config_file, compatibility=False, interpolate=
|
||||
service_names,
|
||||
config_file.version,
|
||||
config_details.environment,
|
||||
compatibility,
|
||||
interpolate
|
||||
)
|
||||
return service_dict
|
||||
@ -554,7 +566,6 @@ def process_config_file(config_file, environment, service_name=None, interpolate
|
||||
environment,
|
||||
interpolate,
|
||||
)
|
||||
if config_file.version >= const.COMPOSEFILE_V3_1:
|
||||
processed_config['secrets'] = process_config_section(
|
||||
config_file,
|
||||
config_file.get_secrets(),
|
||||
@ -562,7 +573,6 @@ def process_config_file(config_file, environment, service_name=None, interpolate
|
||||
environment,
|
||||
interpolate,
|
||||
)
|
||||
if config_file.version >= const.COMPOSEFILE_V3_3:
|
||||
processed_config['configs'] = process_config_section(
|
||||
config_file,
|
||||
config_file.get_configs(),
|
||||
@ -574,7 +584,7 @@ def process_config_file(config_file, environment, service_name=None, interpolate
|
||||
processed_config = services
|
||||
|
||||
config_file = config_file._replace(config=processed_config)
|
||||
validate_against_config_schema(config_file)
|
||||
validate_against_config_schema(config_file, config_file.version)
|
||||
|
||||
if service_name and service_name not in services:
|
||||
raise ConfigurationError(
|
||||
@ -876,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)
|
||||
|
||||
@ -918,106 +928,10 @@ 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)
|
||||
|
||||
|
||||
def translate_resource_keys_to_container_config(resources_dict, service_dict):
|
||||
if 'limits' in resources_dict:
|
||||
service_dict['mem_limit'] = resources_dict['limits'].get('memory')
|
||||
if 'cpus' in resources_dict['limits']:
|
||||
service_dict['cpus'] = float(resources_dict['limits']['cpus'])
|
||||
if 'reservations' in resources_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):
|
||||
try:
|
||||
return {
|
||||
'any': 'always',
|
||||
'none': 'no',
|
||||
'on-failure': 'on-failure'
|
||||
}[name]
|
||||
except KeyError:
|
||||
raise ConfigurationError('Invalid restart policy "{}"'.format(name))
|
||||
|
||||
|
||||
def convert_credential_spec_to_security_opt(credential_spec):
|
||||
if 'file' in credential_spec:
|
||||
return 'file://{file}'.format(file=credential_spec['file'])
|
||||
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:
|
||||
|
@ -1,14 +1,14 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"id": "config_schema_v3.6.json",
|
||||
"$schema": "http://json-schema.org/draft/2019-09/schema#",
|
||||
"id": "config_schema_compose_spec.json",
|
||||
"type": "object",
|
||||
"required": ["version"],
|
||||
|
||||
"title": "Compose Specification",
|
||||
"description": "The Compose file is a YAML file defining a multi-containers based application.",
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Version of the Compose specification used. Tools not implementing required version MUST reject the configuration file."
|
||||
},
|
||||
|
||||
"services": {
|
||||
"id": "#/properties/services",
|
||||
"type": "object",
|
||||
@ -19,7 +19,6 @@
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"networks": {
|
||||
"id": "#/properties/networks",
|
||||
"type": "object",
|
||||
@ -29,7 +28,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"volumes": {
|
||||
"id": "#/properties/volumes",
|
||||
"type": "object",
|
||||
@ -40,7 +38,6 @@
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"secrets": {
|
||||
"id": "#/properties/secrets",
|
||||
"type": "object",
|
||||
@ -51,7 +48,6 @@
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"configs": {
|
||||
"id": "#/properties/configs",
|
||||
"type": "object",
|
||||
@ -63,16 +59,12 @@
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false,
|
||||
|
||||
"definitions": {
|
||||
|
||||
"service": {
|
||||
"id": "#/definitions/service",
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"deploy": {"$ref": "#/definitions/deployment"},
|
||||
"build": {
|
||||
@ -88,12 +80,42 @@
|
||||
"cache_from": {"$ref": "#/definitions/list_of_strings"},
|
||||
"network": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"shm_size": {"type": ["integer", "string"]}
|
||||
"shm_size": {"type": ["integer", "string"]},
|
||||
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
||||
"isolation": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
}
|
||||
]
|
||||
},
|
||||
"blkio_config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"device_read_bps": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"device_read_iops": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"device_write_bps": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"device_write_iops": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"weight": {"type": "integer"},
|
||||
"weight_device": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_weight"}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"cap_add": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cap_drop": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cgroup_parent": {"type": "string"},
|
||||
@ -116,19 +138,60 @@
|
||||
"uid": {"type": "string"},
|
||||
"gid": {"type": "string"},
|
||||
"mode": {"type": "number"}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"container_name": {"type": "string"},
|
||||
"credential_spec": {"type": "object", "properties": {
|
||||
"cpu_count": {"type": "integer", "minimum": 0},
|
||||
"cpu_percent": {"type": "integer", "minimum": 0, "maximum": 100},
|
||||
"cpu_shares": {"type": ["number", "string"]},
|
||||
"cpu_quota": {"type": ["number", "string"]},
|
||||
"cpu_period": {"type": ["number", "string"]},
|
||||
"cpu_rt_period": {"type": ["number", "string"]},
|
||||
"cpu_rt_runtime": {"type": ["number", "string"]},
|
||||
"cpus": {"type": "number", "minimum": 0},
|
||||
"cpuset": {"type": "string"},
|
||||
"credential_spec": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"config": {"type": "string"},
|
||||
"file": {"type": "string"},
|
||||
"registry": {"type": "string"}
|
||||
}},
|
||||
"depends_on": {"$ref": "#/definitions/list_of_strings"},
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
},
|
||||
"depends_on": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/definitions/list_of_strings"},
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"condition": {
|
||||
"type": "string",
|
||||
"enum": ["service_started", "service_healthy"]
|
||||
}
|
||||
},
|
||||
"required": ["condition"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"device_cgroup_rules": {"$ref": "#/definitions/list_of_strings"},
|
||||
"devices": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"dns": {"$ref": "#/definitions/string_or_list"},
|
||||
|
||||
"dns_opt": {"type": "array","items": {"type": "string"}, "uniqueItems": true},
|
||||
"dns_search": {"$ref": "#/definitions/string_or_list"},
|
||||
"domainname": {"type": "string"},
|
||||
"entrypoint": {
|
||||
@ -149,19 +212,39 @@
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"extends": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"service": {"type": "string"},
|
||||
"file": {"type": "string"}
|
||||
},
|
||||
"required": ["service"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
||||
"group_add": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"]
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"healthcheck": {"$ref": "#/definitions/healthcheck"},
|
||||
"hostname": {"type": "string"},
|
||||
"image": {"type": "string"},
|
||||
"init": {"type": "boolean"},
|
||||
"ipc": {"type": "string"},
|
||||
"isolation": {"type": "string"},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"},
|
||||
"links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
|
||||
"logging": {
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"options": {
|
||||
@ -171,12 +254,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
},
|
||||
|
||||
"mac_address": {"type": "string"},
|
||||
"mem_limit": {"type": ["number", "string"]},
|
||||
"mem_reservation": {"type": ["string", "integer"]},
|
||||
"mem_swappiness": {"type": "integer"},
|
||||
"memswap_limit": {"type": ["number", "string"]},
|
||||
"network_mode": {"type": "string"},
|
||||
|
||||
"networks": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/definitions/list_of_strings"},
|
||||
@ -190,9 +276,12 @@
|
||||
"properties": {
|
||||
"aliases": {"$ref": "#/definitions/list_of_strings"},
|
||||
"ipv4_address": {"type": "string"},
|
||||
"ipv6_address": {"type": "string"}
|
||||
"ipv6_address": {"type": "string"},
|
||||
"link_local_ips": {"$ref": "#/definitions/list_of_strings"},
|
||||
"priority": {"type": "number"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
},
|
||||
{"type": "null"}
|
||||
]
|
||||
@ -202,8 +291,11 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"oom_kill_disable": {"type": "boolean"},
|
||||
"oom_score_adj": {"type": "integer", "minimum": -1000, "maximum": 1000},
|
||||
"pid": {"type": ["string", "null"]},
|
||||
|
||||
"pids_limit": {"type": ["number", "string"]},
|
||||
"platform": {"type": "string"},
|
||||
"ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
@ -218,16 +310,26 @@
|
||||
"published": {"type": "integer"},
|
||||
"protocol": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
}
|
||||
]
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"privileged": {"type": "boolean"},
|
||||
"pull_policy": {"type": "string", "enum": [
|
||||
"always", "never", "if_not_present"
|
||||
]},
|
||||
"read_only": {"type": "boolean"},
|
||||
"restart": {"type": "string"},
|
||||
"runtime": {
|
||||
"deprecated": true,
|
||||
"type": "string"
|
||||
},
|
||||
"scale": {
|
||||
"type": "integer"
|
||||
},
|
||||
"security_opt": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"shm_size": {"type": ["number", "string"]},
|
||||
"secrets": {
|
||||
@ -243,7 +345,9 @@
|
||||
"uid": {"type": "string"},
|
||||
"gid": {"type": "string"},
|
||||
"mode": {"type": "number"}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -261,13 +365,14 @@
|
||||
"oneOf": [
|
||||
{"type": "integer"},
|
||||
{
|
||||
"type":"object",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"hard": {"type": "integer"},
|
||||
"soft": {"type": "integer"}
|
||||
},
|
||||
"required": ["soft", "hard"],
|
||||
"additionalProperties": false
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -293,13 +398,17 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"propagation": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
},
|
||||
"volume": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"nocopy": {"type": "boolean"}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
},
|
||||
"tmpfs": {
|
||||
"type": "object",
|
||||
@ -308,24 +417,32 @@
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
}
|
||||
],
|
||||
"uniqueItems": true
|
||||
}
|
||||
},
|
||||
"volumes_from": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"working_dir": {"type": "string"}
|
||||
},
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"healthcheck": {
|
||||
"id": "#/definitions/healthcheck",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"disable": {"type": "boolean"},
|
||||
"interval": {"type": "string", "format": "duration"},
|
||||
@ -338,7 +455,9 @@
|
||||
},
|
||||
"timeout": {"type": "string", "format": "duration"},
|
||||
"start_period": {"type": "string", "format": "duration"}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
},
|
||||
"deployment": {
|
||||
"id": "#/definitions/deployment",
|
||||
@ -348,6 +467,21 @@
|
||||
"endpoint_mode": {"type": "string"},
|
||||
"replicas": {"type": "integer"},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"},
|
||||
"rollback_config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"parallelism": {"type": "integer"},
|
||||
"delay": {"type": "string", "format": "duration"},
|
||||
"failure_action": {"type": "string"},
|
||||
"monitor": {"type": "string", "format": "duration"},
|
||||
"max_failure_ratio": {"type": "number"},
|
||||
"order": {"type": "string", "enum": [
|
||||
"start-first", "stop-first"
|
||||
]}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
},
|
||||
"update_config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -360,7 +494,8 @@
|
||||
"start-first", "stop-first"
|
||||
]}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
},
|
||||
"resources": {
|
||||
"type": "object",
|
||||
@ -371,7 +506,8 @@
|
||||
"cpus": {"type": "string"},
|
||||
"memory": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
},
|
||||
"reservations": {
|
||||
"type": "object",
|
||||
@ -380,10 +516,12 @@
|
||||
"memory": {"type": "string"},
|
||||
"generic_resources": {"$ref": "#/definitions/generic_resources"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
},
|
||||
"restart_policy": {
|
||||
"type": "object",
|
||||
@ -393,7 +531,8 @@
|
||||
"max_attempts": {"type": "integer"},
|
||||
"window": {"type": "string", "format": "duration"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
},
|
||||
"placement": {
|
||||
"type": "object",
|
||||
@ -406,16 +545,19 @@
|
||||
"properties": {
|
||||
"spread": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"max_replicas_per_node": {"type": "integer"}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
},
|
||||
|
||||
"generic_resources": {
|
||||
"id": "#/definitions/generic_resources",
|
||||
"type": "array",
|
||||
@ -428,13 +570,14 @@
|
||||
"kind": {"type": "string"},
|
||||
"value": {"type": "number"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
}
|
||||
},
|
||||
|
||||
"network": {
|
||||
"id": "#/definitions/network",
|
||||
"type": ["object", "null"],
|
||||
@ -456,28 +599,46 @@
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"subnet": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"subnet": {"type": "string", "format": "subnet_ip_address"},
|
||||
"ip_range": {"type": "string"},
|
||||
"gateway": {"type": "string"},
|
||||
"aux_addresses": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^.+$": {"type": "string"}}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
},
|
||||
"options": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^.+$": {"type": "string"}}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
"name": {
|
||||
"deprecated": true,
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
},
|
||||
"internal": {"type": "boolean"},
|
||||
"attachable": {"type": "boolean"},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
},
|
||||
|
||||
"volume": {
|
||||
"id": "#/definitions/volume",
|
||||
"type": ["object", "null"],
|
||||
@ -493,15 +654,19 @@
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
"name": {
|
||||
"deprecated": true,
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
},
|
||||
|
||||
"secret": {
|
||||
"id": "#/definitions/secret",
|
||||
"type": "object",
|
||||
@ -514,11 +679,19 @@
|
||||
"name": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"}
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"},
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"template_driver": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
},
|
||||
|
||||
"config": {
|
||||
"id": "#/definitions/config",
|
||||
"type": "object",
|
||||
@ -528,27 +701,29 @@
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
"name": {
|
||||
"deprecated": true,
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"}
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"},
|
||||
"template_driver": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
},
|
||||
|
||||
"string_or_list": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"$ref": "#/definitions/list_of_strings"}
|
||||
]
|
||||
},
|
||||
|
||||
"list_of_strings": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"list_or_dict": {
|
||||
"oneOf": [
|
||||
{
|
||||
@ -563,7 +738,22 @@
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"blkio_limit": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {"type": "string"},
|
||||
"rate": {"type": ["integer", "string"]}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"blkio_weight": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {"type": "string"},
|
||||
"weight": {"type": "integer"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"constraints": {
|
||||
"service": {
|
||||
"id": "#/definitions/constraints/service",
|
@ -1,424 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"id": "config_schema_v2.0.json",
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
"services": {
|
||||
"id": "#/properties/services",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/service"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"networks": {
|
||||
"id": "#/properties/networks",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/network"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"volumes": {
|
||||
"id": "#/properties/volumes",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/volume"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false,
|
||||
|
||||
"definitions": {
|
||||
|
||||
"service": {
|
||||
"id": "#/definitions/service",
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"blkio_config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"device_read_bps": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"device_read_iops": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"device_write_bps": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"device_write_iops": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"weight": {"type": "integer"},
|
||||
"weight_device": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_weight"}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"build": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {"type": "string"},
|
||||
"dockerfile": {"type": "string"},
|
||||
"args": {"$ref": "#/definitions/list_or_dict"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"cap_add": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cap_drop": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cgroup_parent": {"type": "string"},
|
||||
"command": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"container_name": {"type": "string"},
|
||||
"cpu_shares": {"type": ["number", "string"]},
|
||||
"cpu_quota": {"type": ["number", "string"]},
|
||||
"cpuset": {"type": "string"},
|
||||
"depends_on": {"$ref": "#/definitions/list_of_strings"},
|
||||
"devices": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"dns": {"$ref": "#/definitions/string_or_list"},
|
||||
"dns_opt": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"dns_search": {"$ref": "#/definitions/string_or_list"},
|
||||
"domainname": {"type": "string"},
|
||||
"entrypoint": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"env_file": {"$ref": "#/definitions/string_or_list"},
|
||||
"environment": {"$ref": "#/definitions/list_or_dict"},
|
||||
|
||||
"expose": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"],
|
||||
"format": "expose"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"extends": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"service": {"type": "string"},
|
||||
"file": {"type": "string"}
|
||||
},
|
||||
"required": ["service"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
||||
"hostname": {"type": "string"},
|
||||
"image": {"type": "string"},
|
||||
"ipc": {"type": "string"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
|
||||
"logging": {
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"options": {"type": "object"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"mac_address": {"type": "string"},
|
||||
"mem_limit": {"type": ["number", "string"]},
|
||||
"mem_reservation": {"type": ["string", "integer"]},
|
||||
"mem_swappiness": {"type": "integer"},
|
||||
"memswap_limit": {"type": ["number", "string"]},
|
||||
"network_mode": {"type": "string"},
|
||||
|
||||
"networks": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/definitions/list_of_strings"},
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"aliases": {"$ref": "#/definitions/list_of_strings"},
|
||||
"ipv4_address": {"type": "string"},
|
||||
"ipv6_address": {"type": "string"},
|
||||
"priority": {"type": "number"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "null"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"oom_score_adj": {"type": "integer", "minimum": -1000, "maximum": 1000},
|
||||
"group_add": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"]
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"pid": {"type": ["string", "null"]},
|
||||
|
||||
"ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"],
|
||||
"format": "ports"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"privileged": {"type": "boolean"},
|
||||
"read_only": {"type": "boolean"},
|
||||
"restart": {"type": "string"},
|
||||
"security_opt": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"shm_size": {"type": ["number", "string"]},
|
||||
"stdin_open": {"type": "boolean"},
|
||||
"stop_grace_period": {"type": "string", "format": "duration"},
|
||||
"stop_signal": {"type": "string"},
|
||||
"tmpfs": {"$ref": "#/definitions/string_or_list"},
|
||||
"tty": {"type": "boolean"},
|
||||
"ulimits": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-z]+$": {
|
||||
"oneOf": [
|
||||
{"type": "integer"},
|
||||
{
|
||||
"type":"object",
|
||||
"properties": {
|
||||
"hard": {"type": "integer"},
|
||||
"soft": {"type": "integer"}
|
||||
},
|
||||
"required": ["soft", "hard"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"user": {"type": "string"},
|
||||
"volumes": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"volume_driver": {"type": "string"},
|
||||
"volumes_from": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"working_dir": {"type": "string"}
|
||||
},
|
||||
|
||||
"dependencies": {
|
||||
"memswap_limit": ["mem_limit"]
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"network": {
|
||||
"id": "#/definitions/network",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"ipam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"config": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/ipam_config"}
|
||||
},
|
||||
"options": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"internal": {"type": "boolean"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"ipam_config": {
|
||||
"id": "#/definitions/ipam_config",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"subnet": {"type": "string"},
|
||||
"ip_range": {"type": "string"},
|
||||
"gateway": {"type": "string"},
|
||||
"aux_addresses": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"volume": {
|
||||
"id": "#/definitions/volume",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"string_or_list": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"$ref": "#/definitions/list_of_strings"}
|
||||
]
|
||||
},
|
||||
|
||||
"list_of_strings": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"list_or_dict": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": ["string", "number", "null"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"labels": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"blkio_limit": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {"type": "string"},
|
||||
"rate": {"type": ["integer", "string"]}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"blkio_weight": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {"type": "string"},
|
||||
"weight": {"type": "integer"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"constraints": {
|
||||
"service": {
|
||||
"id": "#/definitions/constraints/service",
|
||||
"anyOf": [
|
||||
{"required": ["build"]},
|
||||
{"required": ["image"]}
|
||||
],
|
||||
"properties": {
|
||||
"build": {
|
||||
"required": ["context"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,480 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"id": "config_schema_v2.1.json",
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
"services": {
|
||||
"id": "#/properties/services",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/service"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"networks": {
|
||||
"id": "#/properties/networks",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/network"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"volumes": {
|
||||
"id": "#/properties/volumes",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/volume"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false,
|
||||
|
||||
"definitions": {
|
||||
|
||||
"service": {
|
||||
"id": "#/definitions/service",
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"blkio_config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"device_read_bps": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"device_read_iops": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"device_write_bps": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"device_write_iops": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"weight": {"type": "integer"},
|
||||
"weight_device": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_weight"}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"build": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {"type": "string"},
|
||||
"dockerfile": {"type": "string"},
|
||||
"args": {"$ref": "#/definitions/list_or_dict"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"isolation": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"cap_add": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cap_drop": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cgroup_parent": {"type": "string"},
|
||||
"command": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"container_name": {"type": "string"},
|
||||
"cpu_shares": {"type": ["number", "string"]},
|
||||
"cpu_quota": {"type": ["number", "string"]},
|
||||
"cpu_period": {"type": ["number", "string"]},
|
||||
"cpuset": {"type": "string"},
|
||||
"depends_on": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/definitions/list_of_strings"},
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"condition": {
|
||||
"type": "string",
|
||||
"enum": ["service_started", "service_healthy"]
|
||||
}
|
||||
},
|
||||
"required": ["condition"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"devices": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"dns_opt": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"dns": {"$ref": "#/definitions/string_or_list"},
|
||||
"dns_search": {"$ref": "#/definitions/string_or_list"},
|
||||
"domainname": {"type": "string"},
|
||||
"entrypoint": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"env_file": {"$ref": "#/definitions/string_or_list"},
|
||||
"environment": {"$ref": "#/definitions/list_or_dict"},
|
||||
|
||||
"expose": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"],
|
||||
"format": "expose"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"extends": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"service": {"type": "string"},
|
||||
"file": {"type": "string"}
|
||||
},
|
||||
"required": ["service"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
||||
"healthcheck": {"$ref": "#/definitions/healthcheck"},
|
||||
"hostname": {"type": "string"},
|
||||
"image": {"type": "string"},
|
||||
"ipc": {"type": "string"},
|
||||
"isolation": {"type": "string"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
|
||||
"logging": {
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"options": {"type": "object"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"mac_address": {"type": "string"},
|
||||
"mem_limit": {"type": ["number", "string"]},
|
||||
"mem_reservation": {"type": ["string", "integer"]},
|
||||
"mem_swappiness": {"type": "integer"},
|
||||
"memswap_limit": {"type": ["number", "string"]},
|
||||
"network_mode": {"type": "string"},
|
||||
|
||||
"networks": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/definitions/list_of_strings"},
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"aliases": {"$ref": "#/definitions/list_of_strings"},
|
||||
"ipv4_address": {"type": "string"},
|
||||
"ipv6_address": {"type": "string"},
|
||||
"link_local_ips": {"$ref": "#/definitions/list_of_strings"},
|
||||
"priority": {"type": "number"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "null"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"oom_kill_disable": {"type": "boolean"},
|
||||
"oom_score_adj": {"type": "integer", "minimum": -1000, "maximum": 1000},
|
||||
"group_add": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"]
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"pid": {"type": ["string", "null"]},
|
||||
|
||||
"ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"],
|
||||
"format": "ports"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"privileged": {"type": "boolean"},
|
||||
"read_only": {"type": "boolean"},
|
||||
"restart": {"type": "string"},
|
||||
"security_opt": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"shm_size": {"type": ["number", "string"]},
|
||||
"sysctls": {"$ref": "#/definitions/list_or_dict"},
|
||||
"pids_limit": {"type": ["number", "string"]},
|
||||
"stdin_open": {"type": "boolean"},
|
||||
"stop_grace_period": {"type": "string", "format": "duration"},
|
||||
"stop_signal": {"type": "string"},
|
||||
"storage_opt": {"type": "object"},
|
||||
"tmpfs": {"$ref": "#/definitions/string_or_list"},
|
||||
"tty": {"type": "boolean"},
|
||||
"ulimits": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-z]+$": {
|
||||
"oneOf": [
|
||||
{"type": "integer"},
|
||||
{
|
||||
"type":"object",
|
||||
"properties": {
|
||||
"hard": {"type": "integer"},
|
||||
"soft": {"type": "integer"}
|
||||
},
|
||||
"required": ["soft", "hard"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"user": {"type": "string"},
|
||||
"userns_mode": {"type": "string"},
|
||||
"volumes": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"volume_driver": {"type": "string"},
|
||||
"volumes_from": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"working_dir": {"type": "string"}
|
||||
},
|
||||
|
||||
"dependencies": {
|
||||
"memswap_limit": ["mem_limit"]
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"healthcheck": {
|
||||
"id": "#/definitions/healthcheck",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"disable": {"type": "boolean"},
|
||||
"interval": {"type": "string"},
|
||||
"retries": {"type": "number"},
|
||||
"test": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"timeout": {"type": "string"}
|
||||
}
|
||||
},
|
||||
|
||||
"network": {
|
||||
"id": "#/definitions/network",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"ipam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"config": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/ipam_config"}
|
||||
},
|
||||
"options": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"internal": {"type": "boolean"},
|
||||
"enable_ipv6": {"type": "boolean"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"ipam_config": {
|
||||
"id": "#/definitions/ipam_config",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"subnet": {"type": "string"},
|
||||
"ip_range": {"type": "string"},
|
||||
"gateway": {"type": "string"},
|
||||
"aux_addresses": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"volume": {
|
||||
"id": "#/definitions/volume",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"string_or_list": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"$ref": "#/definitions/list_of_strings"}
|
||||
]
|
||||
},
|
||||
|
||||
"list_of_strings": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"list_or_dict": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": ["string", "number", "null"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"labels": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"blkio_limit": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {"type": "string"},
|
||||
"rate": {"type": ["integer", "string"]}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"blkio_weight": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {"type": "string"},
|
||||
"weight": {"type": "integer"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"constraints": {
|
||||
"service": {
|
||||
"id": "#/definitions/constraints/service",
|
||||
"anyOf": [
|
||||
{"required": ["build"]},
|
||||
{"required": ["image"]}
|
||||
],
|
||||
"properties": {
|
||||
"build": {
|
||||
"required": ["context"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,489 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"id": "config_schema_v2.2.json",
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
"services": {
|
||||
"id": "#/properties/services",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/service"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"networks": {
|
||||
"id": "#/properties/networks",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/network"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"volumes": {
|
||||
"id": "#/properties/volumes",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/volume"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false,
|
||||
|
||||
"definitions": {
|
||||
|
||||
"service": {
|
||||
"id": "#/definitions/service",
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"blkio_config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"device_read_bps": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"device_read_iops": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"device_write_bps": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"device_write_iops": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"weight": {"type": "integer"},
|
||||
"weight_device": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_weight"}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"build": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {"type": "string"},
|
||||
"dockerfile": {"type": "string"},
|
||||
"args": {"$ref": "#/definitions/list_or_dict"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"cache_from": {"$ref": "#/definitions/list_of_strings"},
|
||||
"network": {"type": "string"},
|
||||
"isolation": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"cap_add": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cap_drop": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cgroup_parent": {"type": "string"},
|
||||
"command": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"container_name": {"type": "string"},
|
||||
"cpu_count": {"type": "integer", "minimum": 0},
|
||||
"cpu_percent": {"type": "integer", "minimum": 0, "maximum": 100},
|
||||
"cpu_shares": {"type": ["number", "string"]},
|
||||
"cpu_quota": {"type": ["number", "string"]},
|
||||
"cpu_period": {"type": ["number", "string"]},
|
||||
"cpu_rt_period": {"type": ["number", "string"]},
|
||||
"cpu_rt_runtime": {"type": ["number", "string"]},
|
||||
"cpus": {"type": "number", "minimum": 0},
|
||||
"cpuset": {"type": "string"},
|
||||
"depends_on": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/definitions/list_of_strings"},
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"condition": {
|
||||
"type": "string",
|
||||
"enum": ["service_started", "service_healthy"]
|
||||
}
|
||||
},
|
||||
"required": ["condition"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"devices": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"dns_opt": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"dns": {"$ref": "#/definitions/string_or_list"},
|
||||
"dns_search": {"$ref": "#/definitions/string_or_list"},
|
||||
"domainname": {"type": "string"},
|
||||
"entrypoint": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"env_file": {"$ref": "#/definitions/string_or_list"},
|
||||
"environment": {"$ref": "#/definitions/list_or_dict"},
|
||||
|
||||
"expose": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"],
|
||||
"format": "expose"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"extends": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"service": {"type": "string"},
|
||||
"file": {"type": "string"}
|
||||
},
|
||||
"required": ["service"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
||||
"healthcheck": {"$ref": "#/definitions/healthcheck"},
|
||||
"hostname": {"type": "string"},
|
||||
"image": {"type": "string"},
|
||||
"init": {"type": ["boolean", "string"]},
|
||||
"ipc": {"type": "string"},
|
||||
"isolation": {"type": "string"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
|
||||
"logging": {
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"options": {"type": "object"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"mac_address": {"type": "string"},
|
||||
"mem_limit": {"type": ["number", "string"]},
|
||||
"mem_reservation": {"type": ["string", "integer"]},
|
||||
"mem_swappiness": {"type": "integer"},
|
||||
"memswap_limit": {"type": ["number", "string"]},
|
||||
"network_mode": {"type": "string"},
|
||||
|
||||
"networks": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/definitions/list_of_strings"},
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"aliases": {"$ref": "#/definitions/list_of_strings"},
|
||||
"ipv4_address": {"type": "string"},
|
||||
"ipv6_address": {"type": "string"},
|
||||
"link_local_ips": {"$ref": "#/definitions/list_of_strings"},
|
||||
"priority": {"type": "number"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "null"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"oom_kill_disable": {"type": "boolean"},
|
||||
"oom_score_adj": {"type": "integer", "minimum": -1000, "maximum": 1000},
|
||||
"group_add": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"]
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"pid": {"type": ["string", "null"]},
|
||||
|
||||
"ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"],
|
||||
"format": "ports"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"privileged": {"type": "boolean"},
|
||||
"read_only": {"type": "boolean"},
|
||||
"restart": {"type": "string"},
|
||||
"scale": {"type": "integer"},
|
||||
"security_opt": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"shm_size": {"type": ["number", "string"]},
|
||||
"sysctls": {"$ref": "#/definitions/list_or_dict"},
|
||||
"pids_limit": {"type": ["number", "string"]},
|
||||
"stdin_open": {"type": "boolean"},
|
||||
"stop_grace_period": {"type": "string", "format": "duration"},
|
||||
"stop_signal": {"type": "string"},
|
||||
"storage_opt": {"type": "object"},
|
||||
"tmpfs": {"$ref": "#/definitions/string_or_list"},
|
||||
"tty": {"type": "boolean"},
|
||||
"ulimits": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-z]+$": {
|
||||
"oneOf": [
|
||||
{"type": "integer"},
|
||||
{
|
||||
"type":"object",
|
||||
"properties": {
|
||||
"hard": {"type": "integer"},
|
||||
"soft": {"type": "integer"}
|
||||
},
|
||||
"required": ["soft", "hard"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"user": {"type": "string"},
|
||||
"userns_mode": {"type": "string"},
|
||||
"volumes": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"volume_driver": {"type": "string"},
|
||||
"volumes_from": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"working_dir": {"type": "string"}
|
||||
},
|
||||
|
||||
"dependencies": {
|
||||
"memswap_limit": ["mem_limit"]
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"healthcheck": {
|
||||
"id": "#/definitions/healthcheck",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"disable": {"type": "boolean"},
|
||||
"interval": {"type": "string"},
|
||||
"retries": {"type": "number"},
|
||||
"test": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"timeout": {"type": "string"}
|
||||
}
|
||||
},
|
||||
|
||||
"network": {
|
||||
"id": "#/definitions/network",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"ipam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"config": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/ipam_config"}
|
||||
},
|
||||
"options": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"internal": {"type": "boolean"},
|
||||
"enable_ipv6": {"type": "boolean"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"ipam_config": {
|
||||
"id": "#/definitions/ipam_config",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"subnet": {"type": "string"},
|
||||
"ip_range": {"type": "string"},
|
||||
"gateway": {"type": "string"},
|
||||
"aux_addresses": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"volume": {
|
||||
"id": "#/definitions/volume",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"string_or_list": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"$ref": "#/definitions/list_of_strings"}
|
||||
]
|
||||
},
|
||||
|
||||
"list_of_strings": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"list_or_dict": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": ["string", "number", "null"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"labels": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"blkio_limit": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {"type": "string"},
|
||||
"rate": {"type": ["integer", "string"]}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"blkio_weight": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {"type": "string"},
|
||||
"weight": {"type": "integer"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"constraints": {
|
||||
"service": {
|
||||
"id": "#/definitions/constraints/service",
|
||||
"anyOf": [
|
||||
{"required": ["build"]},
|
||||
{"required": ["image"]}
|
||||
],
|
||||
"properties": {
|
||||
"build": {
|
||||
"required": ["context"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,533 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"id": "config_schema_v2.3.json",
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
"services": {
|
||||
"id": "#/properties/services",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/service"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"networks": {
|
||||
"id": "#/properties/networks",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/network"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"volumes": {
|
||||
"id": "#/properties/volumes",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/volume"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false,
|
||||
|
||||
"definitions": {
|
||||
|
||||
"service": {
|
||||
"id": "#/definitions/service",
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"blkio_config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"device_read_bps": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"device_read_iops": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"device_write_bps": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"device_write_iops": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"weight": {"type": "integer"},
|
||||
"weight_device": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_weight"}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"build": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {"type": "string"},
|
||||
"dockerfile": {"type": "string"},
|
||||
"args": {"$ref": "#/definitions/list_or_dict"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"cache_from": {"$ref": "#/definitions/list_of_strings"},
|
||||
"network": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"shm_size": {"type": ["integer", "string"]},
|
||||
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
||||
"isolation": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"cap_add": {"$ref": "#/definitions/list_of_strings"},
|
||||
"cap_drop": {"$ref": "#/definitions/list_of_strings"},
|
||||
"cgroup_parent": {"type": "string"},
|
||||
"command": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"container_name": {"type": "string"},
|
||||
"cpu_count": {"type": "integer", "minimum": 0},
|
||||
"cpu_percent": {"type": "integer", "minimum": 0, "maximum": 100},
|
||||
"cpu_shares": {"type": ["number", "string"]},
|
||||
"cpu_quota": {"type": ["number", "string"]},
|
||||
"cpu_period": {"type": ["number", "string"]},
|
||||
"cpu_rt_period": {"type": ["number", "string"]},
|
||||
"cpu_rt_runtime": {"type": ["number", "string"]},
|
||||
"cpus": {"type": "number", "minimum": 0},
|
||||
"cpuset": {"type": "string"},
|
||||
"depends_on": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/definitions/list_of_strings"},
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"condition": {
|
||||
"type": "string",
|
||||
"enum": ["service_started", "service_healthy"]
|
||||
}
|
||||
},
|
||||
"required": ["condition"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"device_cgroup_rules": {"$ref": "#/definitions/list_of_strings"},
|
||||
"devices": {"$ref": "#/definitions/list_of_strings"},
|
||||
"dns_opt": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"dns": {"$ref": "#/definitions/string_or_list"},
|
||||
"dns_search": {"$ref": "#/definitions/string_or_list"},
|
||||
"domainname": {"type": "string"},
|
||||
"entrypoint": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"env_file": {"$ref": "#/definitions/string_or_list"},
|
||||
"environment": {"$ref": "#/definitions/list_or_dict"},
|
||||
|
||||
"expose": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"],
|
||||
"format": "expose"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"extends": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"service": {"type": "string"},
|
||||
"file": {"type": "string"}
|
||||
},
|
||||
"required": ["service"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"external_links": {"$ref": "#/definitions/list_of_strings"},
|
||||
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
||||
"healthcheck": {"$ref": "#/definitions/healthcheck"},
|
||||
"hostname": {"type": "string"},
|
||||
"image": {"type": "string"},
|
||||
"init": {"type": ["boolean", "string"]},
|
||||
"ipc": {"type": "string"},
|
||||
"isolation": {"type": "string"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"links": {"$ref": "#/definitions/list_of_strings"},
|
||||
|
||||
"logging": {
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"options": {"type": "object"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"mac_address": {"type": "string"},
|
||||
"mem_limit": {"type": ["number", "string"]},
|
||||
"mem_reservation": {"type": ["string", "integer"]},
|
||||
"mem_swappiness": {"type": "integer"},
|
||||
"memswap_limit": {"type": ["number", "string"]},
|
||||
"network_mode": {"type": "string"},
|
||||
|
||||
"networks": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/definitions/list_of_strings"},
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"aliases": {"$ref": "#/definitions/list_of_strings"},
|
||||
"ipv4_address": {"type": "string"},
|
||||
"ipv6_address": {"type": "string"},
|
||||
"link_local_ips": {"$ref": "#/definitions/list_of_strings"},
|
||||
"priority": {"type": "number"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "null"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"oom_kill_disable": {"type": "boolean"},
|
||||
"oom_score_adj": {"type": "integer", "minimum": -1000, "maximum": 1000},
|
||||
"group_add": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"]
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"pid": {"type": ["string", "null"]},
|
||||
|
||||
"ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"],
|
||||
"format": "ports"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"privileged": {"type": "boolean"},
|
||||
"read_only": {"type": "boolean"},
|
||||
"restart": {"type": "string"},
|
||||
"runtime": {"type": "string"},
|
||||
"scale": {"type": "integer"},
|
||||
"security_opt": {"$ref": "#/definitions/list_of_strings"},
|
||||
"shm_size": {"type": ["number", "string"]},
|
||||
"sysctls": {"$ref": "#/definitions/list_or_dict"},
|
||||
"pids_limit": {"type": ["number", "string"]},
|
||||
"stdin_open": {"type": "boolean"},
|
||||
"stop_grace_period": {"type": "string", "format": "duration"},
|
||||
"stop_signal": {"type": "string"},
|
||||
"storage_opt": {"type": "object"},
|
||||
"tmpfs": {"$ref": "#/definitions/string_or_list"},
|
||||
"tty": {"type": "boolean"},
|
||||
"ulimits": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-z]+$": {
|
||||
"oneOf": [
|
||||
{"type": "integer"},
|
||||
{
|
||||
"type":"object",
|
||||
"properties": {
|
||||
"hard": {"type": "integer"},
|
||||
"soft": {"type": "integer"}
|
||||
},
|
||||
"required": ["soft", "hard"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"user": {"type": "string"},
|
||||
"userns_mode": {"type": "string"},
|
||||
"volumes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["type"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {"type": "string"},
|
||||
"source": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"read_only": {"type": "boolean"},
|
||||
"consistency": {"type": "string"},
|
||||
"bind": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"propagation": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"volume": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"nocopy": {"type": "boolean"}
|
||||
}
|
||||
},
|
||||
"tmpfs": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"size": {"type": ["integer", "string"]}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"uniqueItems": true
|
||||
}
|
||||
},
|
||||
"volume_driver": {"type": "string"},
|
||||
"volumes_from": {"$ref": "#/definitions/list_of_strings"},
|
||||
"working_dir": {"type": "string"}
|
||||
},
|
||||
|
||||
"dependencies": {
|
||||
"memswap_limit": ["mem_limit"]
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"healthcheck": {
|
||||
"id": "#/definitions/healthcheck",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"disable": {"type": "boolean"},
|
||||
"interval": {"type": "string"},
|
||||
"retries": {"type": "number"},
|
||||
"start_period": {"type": "string"},
|
||||
"test": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"timeout": {"type": "string"}
|
||||
}
|
||||
},
|
||||
|
||||
"network": {
|
||||
"id": "#/definitions/network",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"ipam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"config": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/ipam_config"}
|
||||
},
|
||||
"options": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"internal": {"type": "boolean"},
|
||||
"enable_ipv6": {"type": "boolean"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"ipam_config": {
|
||||
"id": "#/definitions/ipam_config",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"subnet": {"type": "string"},
|
||||
"ip_range": {"type": "string"},
|
||||
"gateway": {"type": "string"},
|
||||
"aux_addresses": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"volume": {
|
||||
"id": "#/definitions/volume",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"string_or_list": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"$ref": "#/definitions/list_of_strings"}
|
||||
]
|
||||
},
|
||||
|
||||
"list_of_strings": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"list_or_dict": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": ["string", "number", "null"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"labels": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"blkio_limit": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {"type": "string"},
|
||||
"rate": {"type": ["integer", "string"]}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"blkio_weight": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {"type": "string"},
|
||||
"weight": {"type": "integer"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"constraints": {
|
||||
"service": {
|
||||
"id": "#/definitions/constraints/service",
|
||||
"anyOf": [
|
||||
{"required": ["build"]},
|
||||
{"required": ["image"]}
|
||||
],
|
||||
"properties": {
|
||||
"build": {
|
||||
"required": ["context"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,535 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"id": "config_schema_v2.4.json",
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
"services": {
|
||||
"id": "#/properties/services",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/service"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"networks": {
|
||||
"id": "#/properties/networks",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/network"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"volumes": {
|
||||
"id": "#/properties/volumes",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/volume"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false,
|
||||
|
||||
"definitions": {
|
||||
|
||||
"service": {
|
||||
"id": "#/definitions/service",
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"blkio_config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"device_read_bps": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"device_read_iops": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"device_write_bps": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"device_write_iops": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_limit"}
|
||||
},
|
||||
"weight": {"type": "integer"},
|
||||
"weight_device": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/blkio_weight"}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"build": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {"type": "string"},
|
||||
"dockerfile": {"type": "string"},
|
||||
"args": {"$ref": "#/definitions/list_or_dict"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"cache_from": {"$ref": "#/definitions/list_of_strings"},
|
||||
"network": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"shm_size": {"type": ["integer", "string"]},
|
||||
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
||||
"isolation": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"cap_add": {"$ref": "#/definitions/list_of_strings"},
|
||||
"cap_drop": {"$ref": "#/definitions/list_of_strings"},
|
||||
"cgroup_parent": {"type": "string"},
|
||||
"command": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"container_name": {"type": "string"},
|
||||
"cpu_count": {"type": "integer", "minimum": 0},
|
||||
"cpu_percent": {"type": "integer", "minimum": 0, "maximum": 100},
|
||||
"cpu_shares": {"type": ["number", "string"]},
|
||||
"cpu_quota": {"type": ["number", "string"]},
|
||||
"cpu_period": {"type": ["number", "string"]},
|
||||
"cpu_rt_period": {"type": ["number", "string"]},
|
||||
"cpu_rt_runtime": {"type": ["number", "string"]},
|
||||
"cpus": {"type": "number", "minimum": 0},
|
||||
"cpuset": {"type": "string"},
|
||||
"depends_on": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/definitions/list_of_strings"},
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"condition": {
|
||||
"type": "string",
|
||||
"enum": ["service_started", "service_healthy"]
|
||||
}
|
||||
},
|
||||
"required": ["condition"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"device_cgroup_rules": {"$ref": "#/definitions/list_of_strings"},
|
||||
"devices": {"$ref": "#/definitions/list_of_strings"},
|
||||
"dns_opt": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"dns": {"$ref": "#/definitions/string_or_list"},
|
||||
"dns_search": {"$ref": "#/definitions/string_or_list"},
|
||||
"domainname": {"type": "string"},
|
||||
"entrypoint": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"env_file": {"$ref": "#/definitions/string_or_list"},
|
||||
"environment": {"$ref": "#/definitions/list_or_dict"},
|
||||
|
||||
"expose": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"],
|
||||
"format": "expose"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"extends": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"service": {"type": "string"},
|
||||
"file": {"type": "string"}
|
||||
},
|
||||
"required": ["service"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"external_links": {"$ref": "#/definitions/list_of_strings"},
|
||||
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
||||
"group_add": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"]
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"healthcheck": {"$ref": "#/definitions/healthcheck"},
|
||||
"hostname": {"type": "string"},
|
||||
"image": {"type": "string"},
|
||||
"init": {"type": ["boolean", "string"]},
|
||||
"ipc": {"type": "string"},
|
||||
"isolation": {"type": "string"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"links": {"$ref": "#/definitions/list_of_strings"},
|
||||
|
||||
"logging": {
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"options": {"type": "object"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"mac_address": {"type": "string"},
|
||||
"mem_limit": {"type": ["number", "string"]},
|
||||
"mem_reservation": {"type": ["string", "integer"]},
|
||||
"mem_swappiness": {"type": "integer"},
|
||||
"memswap_limit": {"type": ["number", "string"]},
|
||||
"network_mode": {"type": "string"},
|
||||
|
||||
"networks": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/definitions/list_of_strings"},
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"aliases": {"$ref": "#/definitions/list_of_strings"},
|
||||
"ipv4_address": {"type": "string"},
|
||||
"ipv6_address": {"type": "string"},
|
||||
"link_local_ips": {"$ref": "#/definitions/list_of_strings"},
|
||||
"priority": {"type": "number"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "null"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"oom_kill_disable": {"type": "boolean"},
|
||||
"oom_score_adj": {"type": "integer", "minimum": -1000, "maximum": 1000},
|
||||
"pid": {"type": ["string", "null"]},
|
||||
"platform": {"type": "string"},
|
||||
"ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"],
|
||||
"format": "ports"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"privileged": {"type": "boolean"},
|
||||
"read_only": {"type": "boolean"},
|
||||
"restart": {"type": "string"},
|
||||
"runtime": {"type": "string"},
|
||||
"scale": {"type": "integer"},
|
||||
"security_opt": {"$ref": "#/definitions/list_of_strings"},
|
||||
"shm_size": {"type": ["number", "string"]},
|
||||
"sysctls": {"$ref": "#/definitions/list_or_dict"},
|
||||
"pids_limit": {"type": ["number", "string"]},
|
||||
"stdin_open": {"type": "boolean"},
|
||||
"stop_grace_period": {"type": "string", "format": "duration"},
|
||||
"stop_signal": {"type": "string"},
|
||||
"storage_opt": {"type": "object"},
|
||||
"tmpfs": {"$ref": "#/definitions/string_or_list"},
|
||||
"tty": {"type": "boolean"},
|
||||
"ulimits": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-z]+$": {
|
||||
"oneOf": [
|
||||
{"type": "integer"},
|
||||
{
|
||||
"type":"object",
|
||||
"properties": {
|
||||
"hard": {"type": "integer"},
|
||||
"soft": {"type": "integer"}
|
||||
},
|
||||
"required": ["soft", "hard"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"user": {"type": "string"},
|
||||
"userns_mode": {"type": "string"},
|
||||
"volumes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["type"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {"type": "string"},
|
||||
"source": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"read_only": {"type": "boolean"},
|
||||
"consistency": {"type": "string"},
|
||||
"bind": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"propagation": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"volume": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"nocopy": {"type": "boolean"}
|
||||
}
|
||||
},
|
||||
"tmpfs": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"size": {"type": ["integer", "string"]}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"uniqueItems": true
|
||||
}
|
||||
},
|
||||
"volume_driver": {"type": "string"},
|
||||
"volumes_from": {"$ref": "#/definitions/list_of_strings"},
|
||||
"working_dir": {"type": "string"}
|
||||
},
|
||||
|
||||
"dependencies": {
|
||||
"memswap_limit": ["mem_limit"]
|
||||
},
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"healthcheck": {
|
||||
"id": "#/definitions/healthcheck",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"disable": {"type": "boolean"},
|
||||
"interval": {"type": "string"},
|
||||
"retries": {"type": "number"},
|
||||
"start_period": {"type": "string"},
|
||||
"test": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"timeout": {"type": "string"}
|
||||
}
|
||||
},
|
||||
|
||||
"network": {
|
||||
"id": "#/definitions/network",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"ipam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"config": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/ipam_config"}
|
||||
},
|
||||
"options": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"internal": {"type": "boolean"},
|
||||
"enable_ipv6": {"type": "boolean"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"ipam_config": {
|
||||
"id": "#/definitions/ipam_config",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"subnet": {"type": "string"},
|
||||
"ip_range": {"type": "string"},
|
||||
"gateway": {"type": "string"},
|
||||
"aux_addresses": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"volume": {
|
||||
"id": "#/definitions/volume",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"string_or_list": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"$ref": "#/definitions/list_of_strings"}
|
||||
]
|
||||
},
|
||||
|
||||
"list_of_strings": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"list_or_dict": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": ["string", "number", "null"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"labels": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"blkio_limit": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {"type": "string"},
|
||||
"rate": {"type": ["integer", "string"]}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"blkio_weight": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {"type": "string"},
|
||||
"weight": {"type": "integer"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"constraints": {
|
||||
"service": {
|
||||
"id": "#/definitions/constraints/service",
|
||||
"anyOf": [
|
||||
{"required": ["build"]},
|
||||
{"required": ["image"]}
|
||||
],
|
||||
"properties": {
|
||||
"build": {
|
||||
"required": ["context"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,399 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"id": "config_schema_v3.0.json",
|
||||
"type": "object",
|
||||
"required": ["version"],
|
||||
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
"services": {
|
||||
"id": "#/properties/services",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/service"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"networks": {
|
||||
"id": "#/properties/networks",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/network"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"volumes": {
|
||||
"id": "#/properties/volumes",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/volume"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
|
||||
"additionalProperties": false,
|
||||
|
||||
"definitions": {
|
||||
|
||||
"service": {
|
||||
"id": "#/definitions/service",
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"deploy": {"$ref": "#/definitions/deployment"},
|
||||
"build": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {"type": "string"},
|
||||
"dockerfile": {"type": "string"},
|
||||
"args": {"$ref": "#/definitions/list_or_dict"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"cap_add": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cap_drop": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cgroup_parent": {"type": "string"},
|
||||
"command": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"container_name": {"type": "string"},
|
||||
"depends_on": {"$ref": "#/definitions/list_of_strings"},
|
||||
"devices": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"dns": {"$ref": "#/definitions/string_or_list"},
|
||||
"dns_search": {"$ref": "#/definitions/string_or_list"},
|
||||
"domainname": {"type": "string"},
|
||||
"entrypoint": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"env_file": {"$ref": "#/definitions/string_or_list"},
|
||||
"environment": {"$ref": "#/definitions/list_or_dict"},
|
||||
|
||||
"expose": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"],
|
||||
"format": "expose"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
||||
"healthcheck": {"$ref": "#/definitions/healthcheck"},
|
||||
"hostname": {"type": "string"},
|
||||
"image": {"type": "string"},
|
||||
"ipc": {"type": "string"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
|
||||
"logging": {
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"options": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number", "null"]}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"mac_address": {"type": "string"},
|
||||
"network_mode": {"type": "string"},
|
||||
|
||||
"networks": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/definitions/list_of_strings"},
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"aliases": {"$ref": "#/definitions/list_of_strings"},
|
||||
"ipv4_address": {"type": "string"},
|
||||
"ipv6_address": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "null"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"pid": {"type": ["string", "null"]},
|
||||
|
||||
"ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"],
|
||||
"format": "ports"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"privileged": {"type": "boolean"},
|
||||
"read_only": {"type": "boolean"},
|
||||
"restart": {"type": "string"},
|
||||
"security_opt": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"shm_size": {"type": ["number", "string"]},
|
||||
"sysctls": {"$ref": "#/definitions/list_or_dict"},
|
||||
"stdin_open": {"type": "boolean"},
|
||||
"stop_grace_period": {"type": "string", "format": "duration"},
|
||||
"stop_signal": {"type": "string"},
|
||||
"tmpfs": {"$ref": "#/definitions/string_or_list"},
|
||||
"tty": {"type": "boolean"},
|
||||
"ulimits": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-z]+$": {
|
||||
"oneOf": [
|
||||
{"type": "integer"},
|
||||
{
|
||||
"type":"object",
|
||||
"properties": {
|
||||
"hard": {"type": "integer"},
|
||||
"soft": {"type": "integer"}
|
||||
},
|
||||
"required": ["soft", "hard"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"user": {"type": "string"},
|
||||
"userns_mode": {"type": "string"},
|
||||
"volumes": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"working_dir": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"healthcheck": {
|
||||
"id": "#/definitions/healthcheck",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"disable": {"type": "boolean"},
|
||||
"interval": {"type": "string"},
|
||||
"retries": {"type": "number"},
|
||||
"test": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"timeout": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"deployment": {
|
||||
"id": "#/definitions/deployment",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"mode": {"type": "string"},
|
||||
"replicas": {"type": "integer"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"update_config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"parallelism": {"type": "integer"},
|
||||
"delay": {"type": "string", "format": "duration"},
|
||||
"failure_action": {"type": "string"},
|
||||
"monitor": {"type": "string", "format": "duration"},
|
||||
"max_failure_ratio": {"type": "number"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"resources": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"limits": {"$ref": "#/definitions/resource"},
|
||||
"reservations": {"$ref": "#/definitions/resource"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"restart_policy": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"condition": {"type": "string"},
|
||||
"delay": {"type": "string", "format": "duration"},
|
||||
"max_attempts": {"type": "integer"},
|
||||
"window": {"type": "string", "format": "duration"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"placement": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"constraints": {"type": "array", "items": {"type": "string"}}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"resource": {
|
||||
"id": "#/definitions/resource",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cpus": {"type": "string"},
|
||||
"memory": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"network": {
|
||||
"id": "#/definitions/network",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"ipam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"config": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"subnet": {"type": "string", "format": "subnet_ip_address"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"internal": {"type": "boolean"},
|
||||
"labels": {"$ref": "#/definitions/labels"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"volume": {
|
||||
"id": "#/definitions/volume",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/labels"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"string_or_list": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"$ref": "#/definitions/list_of_strings"}
|
||||
]
|
||||
},
|
||||
|
||||
"list_of_strings": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"list_or_dict": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": ["string", "number", "null"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"labels": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"constraints": {
|
||||
"service": {
|
||||
"id": "#/definitions/constraints/service",
|
||||
"anyOf": [
|
||||
{"required": ["build"]},
|
||||
{"required": ["image"]}
|
||||
],
|
||||
"properties": {
|
||||
"build": {
|
||||
"required": ["context"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,444 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"id": "config_schema_v3.1.json",
|
||||
"type": "object",
|
||||
"required": ["version"],
|
||||
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
"services": {
|
||||
"id": "#/properties/services",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/service"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"networks": {
|
||||
"id": "#/properties/networks",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/network"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"volumes": {
|
||||
"id": "#/properties/volumes",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/volume"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"secrets": {
|
||||
"id": "#/properties/secrets",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/secret"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
|
||||
"additionalProperties": false,
|
||||
|
||||
"definitions": {
|
||||
|
||||
"service": {
|
||||
"id": "#/definitions/service",
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"deploy": {"$ref": "#/definitions/deployment"},
|
||||
"build": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {"type": "string"},
|
||||
"dockerfile": {"type": "string"},
|
||||
"args": {"$ref": "#/definitions/list_or_dict"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"cap_add": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cap_drop": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cgroup_parent": {"type": "string"},
|
||||
"command": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"container_name": {"type": "string"},
|
||||
"depends_on": {"$ref": "#/definitions/list_of_strings"},
|
||||
"devices": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"dns": {"$ref": "#/definitions/string_or_list"},
|
||||
"dns_search": {"$ref": "#/definitions/string_or_list"},
|
||||
"domainname": {"type": "string"},
|
||||
"entrypoint": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"env_file": {"$ref": "#/definitions/string_or_list"},
|
||||
"environment": {"$ref": "#/definitions/list_or_dict"},
|
||||
|
||||
"expose": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"],
|
||||
"format": "expose"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
||||
"healthcheck": {"$ref": "#/definitions/healthcheck"},
|
||||
"hostname": {"type": "string"},
|
||||
"image": {"type": "string"},
|
||||
"ipc": {"type": "string"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
|
||||
"logging": {
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"options": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number", "null"]}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"mac_address": {"type": "string"},
|
||||
"network_mode": {"type": "string"},
|
||||
|
||||
"networks": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/definitions/list_of_strings"},
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"aliases": {"$ref": "#/definitions/list_of_strings"},
|
||||
"ipv4_address": {"type": "string"},
|
||||
"ipv6_address": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "null"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"pid": {"type": ["string", "null"]},
|
||||
|
||||
"ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"],
|
||||
"format": "ports"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"privileged": {"type": "boolean"},
|
||||
"read_only": {"type": "boolean"},
|
||||
"restart": {"type": "string"},
|
||||
"security_opt": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"shm_size": {"type": ["number", "string"]},
|
||||
"secrets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"source": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"uid": {"type": "string"},
|
||||
"gid": {"type": "string"},
|
||||
"mode": {"type": "number"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"sysctls": {"$ref": "#/definitions/list_or_dict"},
|
||||
"stdin_open": {"type": "boolean"},
|
||||
"stop_grace_period": {"type": "string", "format": "duration"},
|
||||
"stop_signal": {"type": "string"},
|
||||
"tmpfs": {"$ref": "#/definitions/string_or_list"},
|
||||
"tty": {"type": "boolean"},
|
||||
"ulimits": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-z]+$": {
|
||||
"oneOf": [
|
||||
{"type": "integer"},
|
||||
{
|
||||
"type":"object",
|
||||
"properties": {
|
||||
"hard": {"type": "integer"},
|
||||
"soft": {"type": "integer"}
|
||||
},
|
||||
"required": ["soft", "hard"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"user": {"type": "string"},
|
||||
"userns_mode": {"type": "string"},
|
||||
"volumes": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"working_dir": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"healthcheck": {
|
||||
"id": "#/definitions/healthcheck",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"disable": {"type": "boolean"},
|
||||
"interval": {"type": "string"},
|
||||
"retries": {"type": "number"},
|
||||
"test": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"timeout": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"deployment": {
|
||||
"id": "#/definitions/deployment",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"mode": {"type": "string"},
|
||||
"replicas": {"type": "integer"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"update_config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"parallelism": {"type": "integer"},
|
||||
"delay": {"type": "string", "format": "duration"},
|
||||
"failure_action": {"type": "string"},
|
||||
"monitor": {"type": "string", "format": "duration"},
|
||||
"max_failure_ratio": {"type": "number"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"resources": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"limits": {"$ref": "#/definitions/resource"},
|
||||
"reservations": {"$ref": "#/definitions/resource"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"restart_policy": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"condition": {"type": "string"},
|
||||
"delay": {"type": "string", "format": "duration"},
|
||||
"max_attempts": {"type": "integer"},
|
||||
"window": {"type": "string", "format": "duration"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"placement": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"constraints": {"type": "array", "items": {"type": "string"}}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"resource": {
|
||||
"id": "#/definitions/resource",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cpus": {"type": "string"},
|
||||
"memory": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"network": {
|
||||
"id": "#/definitions/network",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"ipam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"config": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"subnet": {"type": "string", "format": "subnet_ip_address"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"internal": {"type": "boolean"},
|
||||
"labels": {"$ref": "#/definitions/labels"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"volume": {
|
||||
"id": "#/definitions/volume",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/labels"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"secret": {
|
||||
"id": "#/definitions/secret",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file": {"type": "string"},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/labels"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"string_or_list": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"$ref": "#/definitions/list_of_strings"}
|
||||
]
|
||||
},
|
||||
|
||||
"list_of_strings": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"list_or_dict": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": ["string", "number", "null"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"labels": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"constraints": {
|
||||
"service": {
|
||||
"id": "#/definitions/constraints/service",
|
||||
"anyOf": [
|
||||
{"required": ["build"]},
|
||||
{"required": ["image"]}
|
||||
],
|
||||
"properties": {
|
||||
"build": {
|
||||
"required": ["context"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,492 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"id": "config_schema_v3.2.json",
|
||||
"type": "object",
|
||||
"required": ["version"],
|
||||
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
"services": {
|
||||
"id": "#/properties/services",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/service"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"networks": {
|
||||
"id": "#/properties/networks",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/network"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"volumes": {
|
||||
"id": "#/properties/volumes",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/volume"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"secrets": {
|
||||
"id": "#/properties/secrets",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/secret"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
|
||||
"additionalProperties": false,
|
||||
|
||||
"definitions": {
|
||||
|
||||
"service": {
|
||||
"id": "#/definitions/service",
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"deploy": {"$ref": "#/definitions/deployment"},
|
||||
"build": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {"type": "string"},
|
||||
"dockerfile": {"type": "string"},
|
||||
"args": {"$ref": "#/definitions/list_or_dict"},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"},
|
||||
"cache_from": {"$ref": "#/definitions/list_of_strings"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"cap_add": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cap_drop": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cgroup_parent": {"type": "string"},
|
||||
"command": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"container_name": {"type": "string"},
|
||||
"depends_on": {"$ref": "#/definitions/list_of_strings"},
|
||||
"devices": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"dns": {"$ref": "#/definitions/string_or_list"},
|
||||
"dns_search": {"$ref": "#/definitions/string_or_list"},
|
||||
"domainname": {"type": "string"},
|
||||
"entrypoint": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"env_file": {"$ref": "#/definitions/string_or_list"},
|
||||
"environment": {"$ref": "#/definitions/list_or_dict"},
|
||||
|
||||
"expose": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"],
|
||||
"format": "expose"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
||||
"healthcheck": {"$ref": "#/definitions/healthcheck"},
|
||||
"hostname": {"type": "string"},
|
||||
"image": {"type": "string"},
|
||||
"ipc": {"type": "string"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
|
||||
"logging": {
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"options": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number", "null"]}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"mac_address": {"type": "string"},
|
||||
"network_mode": {"type": "string"},
|
||||
|
||||
"networks": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/definitions/list_of_strings"},
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"aliases": {"$ref": "#/definitions/list_of_strings"},
|
||||
"ipv4_address": {"type": "string"},
|
||||
"ipv6_address": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "null"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"pid": {"type": ["string", "null"]},
|
||||
|
||||
"ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "number", "format": "ports"},
|
||||
{"type": "string", "format": "ports"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mode": {"type": "string"},
|
||||
"target": {"type": "integer"},
|
||||
"published": {"type": "integer"},
|
||||
"protocol": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"privileged": {"type": "boolean"},
|
||||
"read_only": {"type": "boolean"},
|
||||
"restart": {"type": "string"},
|
||||
"security_opt": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"shm_size": {"type": ["number", "string"]},
|
||||
"secrets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"source": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"uid": {"type": "string"},
|
||||
"gid": {"type": "string"},
|
||||
"mode": {"type": "number"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"sysctls": {"$ref": "#/definitions/list_or_dict"},
|
||||
"stdin_open": {"type": "boolean"},
|
||||
"stop_grace_period": {"type": "string", "format": "duration"},
|
||||
"stop_signal": {"type": "string"},
|
||||
"tmpfs": {"$ref": "#/definitions/string_or_list"},
|
||||
"tty": {"type": "boolean"},
|
||||
"ulimits": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-z]+$": {
|
||||
"oneOf": [
|
||||
{"type": "integer"},
|
||||
{
|
||||
"type":"object",
|
||||
"properties": {
|
||||
"hard": {"type": "integer"},
|
||||
"soft": {"type": "integer"}
|
||||
},
|
||||
"required": ["soft", "hard"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"user": {"type": "string"},
|
||||
"userns_mode": {"type": "string"},
|
||||
"volumes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["type"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {"type": "string"},
|
||||
"source": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"read_only": {"type": "boolean"},
|
||||
"consistency": {"type": "string"},
|
||||
"bind": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"propagation": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"volume": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"nocopy": {"type": "boolean"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"uniqueItems": true
|
||||
}
|
||||
},
|
||||
"working_dir": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"healthcheck": {
|
||||
"id": "#/definitions/healthcheck",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"disable": {"type": "boolean"},
|
||||
"interval": {"type": "string"},
|
||||
"retries": {"type": "number"},
|
||||
"test": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"timeout": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"deployment": {
|
||||
"id": "#/definitions/deployment",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"mode": {"type": "string"},
|
||||
"endpoint_mode": {"type": "string"},
|
||||
"replicas": {"type": "integer"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"update_config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"parallelism": {"type": "integer"},
|
||||
"delay": {"type": "string", "format": "duration"},
|
||||
"failure_action": {"type": "string"},
|
||||
"monitor": {"type": "string", "format": "duration"},
|
||||
"max_failure_ratio": {"type": "number"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"resources": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"limits": {"$ref": "#/definitions/resource"},
|
||||
"reservations": {"$ref": "#/definitions/resource"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"restart_policy": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"condition": {"type": "string"},
|
||||
"delay": {"type": "string", "format": "duration"},
|
||||
"max_attempts": {"type": "integer"},
|
||||
"window": {"type": "string", "format": "duration"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"placement": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"constraints": {"type": "array", "items": {"type": "string"}}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"resource": {
|
||||
"id": "#/definitions/resource",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cpus": {"type": "string"},
|
||||
"memory": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"network": {
|
||||
"id": "#/definitions/network",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"ipam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"config": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"subnet": {"type": "string", "format": "subnet_ip_address"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"internal": {"type": "boolean"},
|
||||
"attachable": {"type": "boolean"},
|
||||
"labels": {"$ref": "#/definitions/labels"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"volume": {
|
||||
"id": "#/definitions/volume",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/labels"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"secret": {
|
||||
"id": "#/definitions/secret",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file": {"type": "string"},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/labels"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"string_or_list": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"$ref": "#/definitions/list_of_strings"}
|
||||
]
|
||||
},
|
||||
|
||||
"list_of_strings": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"list_or_dict": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": ["string", "number", "null"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"labels": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"constraints": {
|
||||
"service": {
|
||||
"id": "#/definitions/constraints/service",
|
||||
"anyOf": [
|
||||
{"required": ["build"]},
|
||||
{"required": ["image"]}
|
||||
],
|
||||
"properties": {
|
||||
"build": {
|
||||
"required": ["context"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,551 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"id": "config_schema_v3.3.json",
|
||||
"type": "object",
|
||||
"required": ["version"],
|
||||
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
"services": {
|
||||
"id": "#/properties/services",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/service"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"networks": {
|
||||
"id": "#/properties/networks",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/network"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"volumes": {
|
||||
"id": "#/properties/volumes",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/volume"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"secrets": {
|
||||
"id": "#/properties/secrets",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/secret"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"configs": {
|
||||
"id": "#/properties/configs",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/config"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
|
||||
"additionalProperties": false,
|
||||
|
||||
"definitions": {
|
||||
|
||||
"service": {
|
||||
"id": "#/definitions/service",
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"deploy": {"$ref": "#/definitions/deployment"},
|
||||
"build": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {"type": "string"},
|
||||
"dockerfile": {"type": "string"},
|
||||
"args": {"$ref": "#/definitions/list_or_dict"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"cache_from": {"$ref": "#/definitions/list_of_strings"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"cap_add": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cap_drop": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cgroup_parent": {"type": "string"},
|
||||
"command": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"configs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"source": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"uid": {"type": "string"},
|
||||
"gid": {"type": "string"},
|
||||
"mode": {"type": "number"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"container_name": {"type": "string"},
|
||||
"credential_spec": {"type": "object", "properties": {
|
||||
"file": {"type": "string"},
|
||||
"registry": {"type": "string"}
|
||||
}},
|
||||
"depends_on": {"$ref": "#/definitions/list_of_strings"},
|
||||
"devices": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"dns": {"$ref": "#/definitions/string_or_list"},
|
||||
"dns_search": {"$ref": "#/definitions/string_or_list"},
|
||||
"domainname": {"type": "string"},
|
||||
"entrypoint": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"env_file": {"$ref": "#/definitions/string_or_list"},
|
||||
"environment": {"$ref": "#/definitions/list_or_dict"},
|
||||
|
||||
"expose": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"],
|
||||
"format": "expose"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
||||
"healthcheck": {"$ref": "#/definitions/healthcheck"},
|
||||
"hostname": {"type": "string"},
|
||||
"image": {"type": "string"},
|
||||
"ipc": {"type": "string"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
|
||||
"logging": {
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"options": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number", "null"]}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"mac_address": {"type": "string"},
|
||||
"network_mode": {"type": "string"},
|
||||
|
||||
"networks": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/definitions/list_of_strings"},
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"aliases": {"$ref": "#/definitions/list_of_strings"},
|
||||
"ipv4_address": {"type": "string"},
|
||||
"ipv6_address": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "null"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"pid": {"type": ["string", "null"]},
|
||||
|
||||
"ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "number", "format": "ports"},
|
||||
{"type": "string", "format": "ports"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mode": {"type": "string"},
|
||||
"target": {"type": "integer"},
|
||||
"published": {"type": "integer"},
|
||||
"protocol": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"privileged": {"type": "boolean"},
|
||||
"read_only": {"type": "boolean"},
|
||||
"restart": {"type": "string"},
|
||||
"security_opt": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"shm_size": {"type": ["number", "string"]},
|
||||
"secrets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"source": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"uid": {"type": "string"},
|
||||
"gid": {"type": "string"},
|
||||
"mode": {"type": "number"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"sysctls": {"$ref": "#/definitions/list_or_dict"},
|
||||
"stdin_open": {"type": "boolean"},
|
||||
"stop_grace_period": {"type": "string", "format": "duration"},
|
||||
"stop_signal": {"type": "string"},
|
||||
"tmpfs": {"$ref": "#/definitions/string_or_list"},
|
||||
"tty": {"type": "boolean"},
|
||||
"ulimits": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-z]+$": {
|
||||
"oneOf": [
|
||||
{"type": "integer"},
|
||||
{
|
||||
"type":"object",
|
||||
"properties": {
|
||||
"hard": {"type": "integer"},
|
||||
"soft": {"type": "integer"}
|
||||
},
|
||||
"required": ["soft", "hard"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"user": {"type": "string"},
|
||||
"userns_mode": {"type": "string"},
|
||||
"volumes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["type"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {"type": "string"},
|
||||
"source": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"read_only": {"type": "boolean"},
|
||||
"consistency": {"type": "string"},
|
||||
"bind": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"propagation": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"volume": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"nocopy": {"type": "boolean"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"uniqueItems": true
|
||||
}
|
||||
},
|
||||
"working_dir": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"healthcheck": {
|
||||
"id": "#/definitions/healthcheck",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"disable": {"type": "boolean"},
|
||||
"interval": {"type": "string"},
|
||||
"retries": {"type": "number"},
|
||||
"test": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"timeout": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"deployment": {
|
||||
"id": "#/definitions/deployment",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"mode": {"type": "string"},
|
||||
"endpoint_mode": {"type": "string"},
|
||||
"replicas": {"type": "integer"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"update_config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"parallelism": {"type": "integer"},
|
||||
"delay": {"type": "string", "format": "duration"},
|
||||
"failure_action": {"type": "string"},
|
||||
"monitor": {"type": "string", "format": "duration"},
|
||||
"max_failure_ratio": {"type": "number"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"resources": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"limits": {"$ref": "#/definitions/resource"},
|
||||
"reservations": {"$ref": "#/definitions/resource"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"restart_policy": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"condition": {"type": "string"},
|
||||
"delay": {"type": "string", "format": "duration"},
|
||||
"max_attempts": {"type": "integer"},
|
||||
"window": {"type": "string", "format": "duration"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"placement": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"constraints": {"type": "array", "items": {"type": "string"}},
|
||||
"preferences": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"spread": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"resource": {
|
||||
"id": "#/definitions/resource",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cpus": {"type": "string"},
|
||||
"memory": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"network": {
|
||||
"id": "#/definitions/network",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"ipam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"config": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"subnet": {"type": "string", "format": "subnet_ip_address"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"internal": {"type": "boolean"},
|
||||
"attachable": {"type": "boolean"},
|
||||
"labels": {"$ref": "#/definitions/labels"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"volume": {
|
||||
"id": "#/definitions/volume",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/labels"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"secret": {
|
||||
"id": "#/definitions/secret",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file": {"type": "string"},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/labels"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"config": {
|
||||
"id": "#/definitions/config",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file": {"type": "string"},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/labels"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"string_or_list": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"$ref": "#/definitions/list_of_strings"}
|
||||
]
|
||||
},
|
||||
|
||||
"list_of_strings": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"list_or_dict": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": ["string", "number", "null"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"labels": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"constraints": {
|
||||
"service": {
|
||||
"id": "#/definitions/constraints/service",
|
||||
"anyOf": [
|
||||
{"required": ["build"]},
|
||||
{"required": ["image"]}
|
||||
],
|
||||
"properties": {
|
||||
"build": {
|
||||
"required": ["context"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,560 +0,0 @@
|
||||
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"id": "config_schema_v3.4.json",
|
||||
"type": "object",
|
||||
"required": ["version"],
|
||||
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
"services": {
|
||||
"id": "#/properties/services",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/service"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"networks": {
|
||||
"id": "#/properties/networks",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/network"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"volumes": {
|
||||
"id": "#/properties/volumes",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/volume"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"secrets": {
|
||||
"id": "#/properties/secrets",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/secret"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"configs": {
|
||||
"id": "#/properties/configs",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/config"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false,
|
||||
|
||||
"definitions": {
|
||||
|
||||
"service": {
|
||||
"id": "#/definitions/service",
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"deploy": {"$ref": "#/definitions/deployment"},
|
||||
"build": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {"type": "string"},
|
||||
"dockerfile": {"type": "string"},
|
||||
"args": {"$ref": "#/definitions/list_or_dict"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"cache_from": {"$ref": "#/definitions/list_of_strings"},
|
||||
"network": {"type": "string"},
|
||||
"target": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"cap_add": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cap_drop": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cgroup_parent": {"type": "string"},
|
||||
"command": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"configs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"source": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"uid": {"type": "string"},
|
||||
"gid": {"type": "string"},
|
||||
"mode": {"type": "number"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"container_name": {"type": "string"},
|
||||
"credential_spec": {"type": "object", "properties": {
|
||||
"file": {"type": "string"},
|
||||
"registry": {"type": "string"}
|
||||
}},
|
||||
"depends_on": {"$ref": "#/definitions/list_of_strings"},
|
||||
"devices": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"dns": {"$ref": "#/definitions/string_or_list"},
|
||||
"dns_search": {"$ref": "#/definitions/string_or_list"},
|
||||
"domainname": {"type": "string"},
|
||||
"entrypoint": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"env_file": {"$ref": "#/definitions/string_or_list"},
|
||||
"environment": {"$ref": "#/definitions/list_or_dict"},
|
||||
|
||||
"expose": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"],
|
||||
"format": "expose"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
||||
"healthcheck": {"$ref": "#/definitions/healthcheck"},
|
||||
"hostname": {"type": "string"},
|
||||
"image": {"type": "string"},
|
||||
"ipc": {"type": "string"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
|
||||
"logging": {
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"options": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number", "null"]}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"mac_address": {"type": "string"},
|
||||
"network_mode": {"type": "string"},
|
||||
|
||||
"networks": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/definitions/list_of_strings"},
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"aliases": {"$ref": "#/definitions/list_of_strings"},
|
||||
"ipv4_address": {"type": "string"},
|
||||
"ipv6_address": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "null"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"pid": {"type": ["string", "null"]},
|
||||
|
||||
"ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "number", "format": "ports"},
|
||||
{"type": "string", "format": "ports"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mode": {"type": "string"},
|
||||
"target": {"type": "integer"},
|
||||
"published": {"type": "integer"},
|
||||
"protocol": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"privileged": {"type": "boolean"},
|
||||
"read_only": {"type": "boolean"},
|
||||
"restart": {"type": "string"},
|
||||
"security_opt": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"shm_size": {"type": ["number", "string"]},
|
||||
"secrets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"source": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"uid": {"type": "string"},
|
||||
"gid": {"type": "string"},
|
||||
"mode": {"type": "number"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"sysctls": {"$ref": "#/definitions/list_or_dict"},
|
||||
"stdin_open": {"type": "boolean"},
|
||||
"stop_grace_period": {"type": "string", "format": "duration"},
|
||||
"stop_signal": {"type": "string"},
|
||||
"tmpfs": {"$ref": "#/definitions/string_or_list"},
|
||||
"tty": {"type": "boolean"},
|
||||
"ulimits": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-z]+$": {
|
||||
"oneOf": [
|
||||
{"type": "integer"},
|
||||
{
|
||||
"type":"object",
|
||||
"properties": {
|
||||
"hard": {"type": "integer"},
|
||||
"soft": {"type": "integer"}
|
||||
},
|
||||
"required": ["soft", "hard"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"user": {"type": "string"},
|
||||
"userns_mode": {"type": "string"},
|
||||
"volumes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["type"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {"type": "string"},
|
||||
"source": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"read_only": {"type": "boolean"},
|
||||
"consistency": {"type": "string"},
|
||||
"bind": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"propagation": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"volume": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"nocopy": {"type": "boolean"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"uniqueItems": true
|
||||
}
|
||||
},
|
||||
"working_dir": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"healthcheck": {
|
||||
"id": "#/definitions/healthcheck",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"disable": {"type": "boolean"},
|
||||
"interval": {"type": "string", "format": "duration"},
|
||||
"retries": {"type": "number"},
|
||||
"test": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"timeout": {"type": "string", "format": "duration"},
|
||||
"start_period": {"type": "string", "format": "duration"}
|
||||
}
|
||||
},
|
||||
"deployment": {
|
||||
"id": "#/definitions/deployment",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"mode": {"type": "string"},
|
||||
"endpoint_mode": {"type": "string"},
|
||||
"replicas": {"type": "integer"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"update_config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"parallelism": {"type": "integer"},
|
||||
"delay": {"type": "string", "format": "duration"},
|
||||
"failure_action": {"type": "string"},
|
||||
"monitor": {"type": "string", "format": "duration"},
|
||||
"max_failure_ratio": {"type": "number"},
|
||||
"order": {"type": "string", "enum": [
|
||||
"start-first", "stop-first"
|
||||
]}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"resources": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"limits": {"$ref": "#/definitions/resource"},
|
||||
"reservations": {"$ref": "#/definitions/resource"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"restart_policy": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"condition": {"type": "string"},
|
||||
"delay": {"type": "string", "format": "duration"},
|
||||
"max_attempts": {"type": "integer"},
|
||||
"window": {"type": "string", "format": "duration"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"placement": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"constraints": {"type": "array", "items": {"type": "string"}},
|
||||
"preferences": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"spread": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"resource": {
|
||||
"id": "#/definitions/resource",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cpus": {"type": "string"},
|
||||
"memory": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"network": {
|
||||
"id": "#/definitions/network",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"ipam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"config": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"subnet": {"type": "string", "format": "subnet_ip_address"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"internal": {"type": "boolean"},
|
||||
"attachable": {"type": "boolean"},
|
||||
"labels": {"$ref": "#/definitions/labels"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"volume": {
|
||||
"id": "#/definitions/volume",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/labels"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"secret": {
|
||||
"id": "#/definitions/secret",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file": {"type": "string"},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/labels"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"config": {
|
||||
"id": "#/definitions/config",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file": {"type": "string"},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/labels"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"string_or_list": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"$ref": "#/definitions/list_of_strings"}
|
||||
]
|
||||
},
|
||||
|
||||
"list_of_strings": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"list_or_dict": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": ["string", "number", "null"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"labels": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"constraints": {
|
||||
"service": {
|
||||
"id": "#/definitions/constraints/service",
|
||||
"anyOf": [
|
||||
{"required": ["build"]},
|
||||
{"required": ["image"]}
|
||||
],
|
||||
"properties": {
|
||||
"build": {
|
||||
"required": ["context"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,588 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"id": "config_schema_v3.5.json",
|
||||
"type": "object",
|
||||
"required": ["version"],
|
||||
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
"services": {
|
||||
"id": "#/properties/services",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/service"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"networks": {
|
||||
"id": "#/properties/networks",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/network"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"volumes": {
|
||||
"id": "#/properties/volumes",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/volume"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"secrets": {
|
||||
"id": "#/properties/secrets",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/secret"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"configs": {
|
||||
"id": "#/properties/configs",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/config"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false,
|
||||
|
||||
"definitions": {
|
||||
|
||||
"service": {
|
||||
"id": "#/definitions/service",
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"deploy": {"$ref": "#/definitions/deployment"},
|
||||
"build": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {"type": "string"},
|
||||
"dockerfile": {"type": "string"},
|
||||
"args": {"$ref": "#/definitions/list_or_dict"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"cache_from": {"$ref": "#/definitions/list_of_strings"},
|
||||
"network": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"shm_size": {"type": ["integer", "string"]}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"cap_add": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cap_drop": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cgroup_parent": {"type": "string"},
|
||||
"command": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"configs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"source": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"uid": {"type": "string"},
|
||||
"gid": {"type": "string"},
|
||||
"mode": {"type": "number"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"container_name": {"type": "string"},
|
||||
"credential_spec": {"type": "object", "properties": {
|
||||
"file": {"type": "string"},
|
||||
"registry": {"type": "string"}
|
||||
}},
|
||||
"depends_on": {"$ref": "#/definitions/list_of_strings"},
|
||||
"devices": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"dns": {"$ref": "#/definitions/string_or_list"},
|
||||
"dns_search": {"$ref": "#/definitions/string_or_list"},
|
||||
"domainname": {"type": "string"},
|
||||
"entrypoint": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"env_file": {"$ref": "#/definitions/string_or_list"},
|
||||
"environment": {"$ref": "#/definitions/list_or_dict"},
|
||||
|
||||
"expose": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"],
|
||||
"format": "expose"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
||||
"healthcheck": {"$ref": "#/definitions/healthcheck"},
|
||||
"hostname": {"type": "string"},
|
||||
"image": {"type": "string"},
|
||||
"ipc": {"type": "string"},
|
||||
"isolation": {"type": "string"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
|
||||
"logging": {
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"options": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number", "null"]}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"mac_address": {"type": "string"},
|
||||
"network_mode": {"type": "string"},
|
||||
|
||||
"networks": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/definitions/list_of_strings"},
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"aliases": {"$ref": "#/definitions/list_of_strings"},
|
||||
"ipv4_address": {"type": "string"},
|
||||
"ipv6_address": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "null"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"pid": {"type": ["string", "null"]},
|
||||
|
||||
"ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "number", "format": "ports"},
|
||||
{"type": "string", "format": "ports"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mode": {"type": "string"},
|
||||
"target": {"type": "integer"},
|
||||
"published": {"type": "integer"},
|
||||
"protocol": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"privileged": {"type": "boolean"},
|
||||
"read_only": {"type": "boolean"},
|
||||
"restart": {"type": "string"},
|
||||
"security_opt": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"shm_size": {"type": ["number", "string"]},
|
||||
"secrets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"source": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"uid": {"type": "string"},
|
||||
"gid": {"type": "string"},
|
||||
"mode": {"type": "number"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"sysctls": {"$ref": "#/definitions/list_or_dict"},
|
||||
"stdin_open": {"type": "boolean"},
|
||||
"stop_grace_period": {"type": "string", "format": "duration"},
|
||||
"stop_signal": {"type": "string"},
|
||||
"tmpfs": {"$ref": "#/definitions/string_or_list"},
|
||||
"tty": {"type": "boolean"},
|
||||
"ulimits": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-z]+$": {
|
||||
"oneOf": [
|
||||
{"type": "integer"},
|
||||
{
|
||||
"type":"object",
|
||||
"properties": {
|
||||
"hard": {"type": "integer"},
|
||||
"soft": {"type": "integer"}
|
||||
},
|
||||
"required": ["soft", "hard"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"user": {"type": "string"},
|
||||
"userns_mode": {"type": "string"},
|
||||
"volumes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["type"],
|
||||
"properties": {
|
||||
"type": {"type": "string"},
|
||||
"source": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"read_only": {"type": "boolean"},
|
||||
"consistency": {"type": "string"},
|
||||
"bind": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"propagation": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"volume": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"nocopy": {"type": "boolean"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
],
|
||||
"uniqueItems": true
|
||||
}
|
||||
},
|
||||
"working_dir": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"healthcheck": {
|
||||
"id": "#/definitions/healthcheck",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"disable": {"type": "boolean"},
|
||||
"interval": {"type": "string", "format": "duration"},
|
||||
"retries": {"type": "number"},
|
||||
"test": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"timeout": {"type": "string", "format": "duration"},
|
||||
"start_period": {"type": "string", "format": "duration"}
|
||||
}
|
||||
},
|
||||
"deployment": {
|
||||
"id": "#/definitions/deployment",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"mode": {"type": "string"},
|
||||
"endpoint_mode": {"type": "string"},
|
||||
"replicas": {"type": "integer"},
|
||||
"labels": {"$ref": "#/definitions/labels"},
|
||||
"update_config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"parallelism": {"type": "integer"},
|
||||
"delay": {"type": "string", "format": "duration"},
|
||||
"failure_action": {"type": "string"},
|
||||
"monitor": {"type": "string", "format": "duration"},
|
||||
"max_failure_ratio": {"type": "number"},
|
||||
"order": {"type": "string", "enum": [
|
||||
"start-first", "stop-first"
|
||||
]}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"resources": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"limits": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cpus": {"type": "string"},
|
||||
"memory": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"reservations": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cpus": {"type": "string"},
|
||||
"memory": {"type": "string"},
|
||||
"generic_resources": {"$ref": "#/definitions/generic_resources"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"restart_policy": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"condition": {"type": "string"},
|
||||
"delay": {"type": "string", "format": "duration"},
|
||||
"max_attempts": {"type": "integer"},
|
||||
"window": {"type": "string", "format": "duration"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"placement": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"constraints": {"type": "array", "items": {"type": "string"}},
|
||||
"preferences": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"spread": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"generic_resources": {
|
||||
"id": "#/definitions/generic_resources",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"discrete_resource_spec": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"kind": {"type": "string"},
|
||||
"value": {"type": "number"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
|
||||
"network": {
|
||||
"id": "#/definitions/network",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"ipam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"config": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"subnet": {"type": "string", "format": "subnet_ip_address"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"internal": {"type": "boolean"},
|
||||
"attachable": {"type": "boolean"},
|
||||
"labels": {"$ref": "#/definitions/labels"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"volume": {
|
||||
"id": "#/definitions/volume",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/labels"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"secret": {
|
||||
"id": "#/definitions/secret",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"file": {"type": "string"},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/labels"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"config": {
|
||||
"id": "#/definitions/config",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"file": {"type": "string"},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/labels"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"string_or_list": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"$ref": "#/definitions/list_of_strings"}
|
||||
]
|
||||
},
|
||||
|
||||
"list_of_strings": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"list_or_dict": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": ["string", "number", "null"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"labels": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"constraints": {
|
||||
"service": {
|
||||
"id": "#/definitions/constraints/service",
|
||||
"anyOf": [
|
||||
{"required": ["build"]},
|
||||
{"required": ["image"]}
|
||||
],
|
||||
"properties": {
|
||||
"build": {
|
||||
"required": ["context"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,7 @@ import re
|
||||
from string import Template
|
||||
|
||||
from .errors import ConfigurationError
|
||||
from compose.const import COMPOSEFILE_V2_0 as V2_0
|
||||
from compose.const import COMPOSEFILE_V1 as V1
|
||||
from compose.utils import parse_bytes
|
||||
from compose.utils import parse_nanoseconds_int
|
||||
|
||||
@ -25,7 +25,7 @@ class Interpolator(object):
|
||||
|
||||
|
||||
def interpolate_environment_variables(version, config, section, environment):
|
||||
if version <= V2_0:
|
||||
if version == V1:
|
||||
interpolator = Interpolator(Template, environment)
|
||||
else:
|
||||
interpolator = Interpolator(TemplateWithDefaults, environment)
|
||||
|
@ -1,13 +1,8 @@
|
||||
import yaml
|
||||
|
||||
from compose.config import types
|
||||
from compose.const import COMPOSE_SPEC as VERSION
|
||||
from compose.const import COMPOSEFILE_V1 as V1
|
||||
from compose.const import COMPOSEFILE_V2_1 as V2_1
|
||||
from compose.const import COMPOSEFILE_V2_3 as V2_3
|
||||
from compose.const import COMPOSEFILE_V3_0 as V3_0
|
||||
from compose.const import COMPOSEFILE_V3_2 as V3_2
|
||||
from compose.const import COMPOSEFILE_V3_4 as V3_4
|
||||
from compose.const import COMPOSEFILE_V3_5 as V3_5
|
||||
|
||||
|
||||
def serialize_config_type(dumper, data):
|
||||
@ -49,7 +44,7 @@ yaml.SafeDumper.add_representer(types.ServicePort, serialize_dict_type)
|
||||
|
||||
|
||||
def denormalize_config(config, image_digests=None):
|
||||
result = {'version': str(V2_1) if config.version == V1 else str(config.version)}
|
||||
result = {'version': str(config.version)}
|
||||
denormalized_services = [
|
||||
denormalize_service_dict(
|
||||
service_dict,
|
||||
@ -72,25 +67,11 @@ def denormalize_config(config, image_digests=None):
|
||||
del conf['external_name']
|
||||
|
||||
if 'name' in conf:
|
||||
if config.version < V2_1 or (
|
||||
config.version >= V3_0 and config.version < v3_introduced_name_key(key)):
|
||||
del conf['name']
|
||||
elif 'external' in conf:
|
||||
if 'external' in conf:
|
||||
conf['external'] = bool(conf['external'])
|
||||
|
||||
if 'attachable' in conf and config.version < V3_2:
|
||||
# For compatibility mode, this option is invalid in v2
|
||||
del conf['attachable']
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def v3_introduced_name_key(key):
|
||||
if key == 'volumes':
|
||||
return V3_4
|
||||
return V3_5
|
||||
|
||||
|
||||
def serialize_config(config, image_digests=None, escape_dollar=True):
|
||||
if escape_dollar:
|
||||
yaml.SafeDumper.add_representer(str, serialize_string_escape_dollar)
|
||||
@ -140,7 +121,7 @@ def denormalize_service_dict(service_dict, version, image_digest=None):
|
||||
if version == V1 and 'network_mode' not in service_dict:
|
||||
service_dict['network_mode'] = 'bridge'
|
||||
|
||||
if 'depends_on' in service_dict and (version < V2_1 or version >= V3_0):
|
||||
if 'depends_on' in service_dict:
|
||||
service_dict['depends_on'] = sorted([
|
||||
svc for svc in service_dict['depends_on'].keys()
|
||||
])
|
||||
@ -162,10 +143,10 @@ def denormalize_service_dict(service_dict, version, image_digest=None):
|
||||
|
||||
if 'ports' in service_dict:
|
||||
service_dict['ports'] = [
|
||||
p.legacy_repr() if p.external_ip or version < V3_2 else p
|
||||
p.legacy_repr() if p.external_ip or version < VERSION else p
|
||||
for p in service_dict['ports']
|
||||
]
|
||||
if 'volumes' in service_dict and (version < V2_3 or (version > V3_0 and version < V3_2)):
|
||||
if 'volumes' in service_dict and (version == V1):
|
||||
service_dict['volumes'] = [
|
||||
v.legacy_repr() if isinstance(v, types.MountSpec) else v for v in service_dict['volumes']
|
||||
]
|
||||
|
@ -282,7 +282,7 @@ def handle_error_for_schema_with_id(error, path):
|
||||
invalid_config_key = parse_key_from_error_msg(error)
|
||||
return get_unsupported_config_msg(path, invalid_config_key)
|
||||
|
||||
if schema_id.startswith('config_schema_v'):
|
||||
if schema_id.startswith('config_schema_'):
|
||||
invalid_config_key = parse_key_from_error_msg(error)
|
||||
return ('Invalid top-level property "{key}". Valid top-level '
|
||||
'sections for this Compose file are: {properties}, and '
|
||||
@ -435,15 +435,29 @@ def process_config_schema_errors(error):
|
||||
return handle_generic_error(error, path)
|
||||
|
||||
|
||||
def validate_against_config_schema(config_file):
|
||||
schema = load_jsonschema(config_file)
|
||||
def keys_to_str(config_file):
|
||||
"""
|
||||
Non-string keys may break validator with patterned fields.
|
||||
"""
|
||||
d = {}
|
||||
for k, v in config_file.items():
|
||||
d[str(k)] = v
|
||||
if isinstance(v, dict):
|
||||
d[str(k)] = keys_to_str(v)
|
||||
return d
|
||||
|
||||
|
||||
def validate_against_config_schema(config_file, version):
|
||||
schema = load_jsonschema(version)
|
||||
config = keys_to_str(config_file.config)
|
||||
|
||||
format_checker = FormatChecker(["ports", "expose", "subnet_ip_address"])
|
||||
validator = Draft4Validator(
|
||||
schema,
|
||||
resolver=RefResolver(get_resolver_path(), schema),
|
||||
format_checker=format_checker)
|
||||
handle_errors(
|
||||
validator.iter_errors(config_file.config),
|
||||
validator.iter_errors(config),
|
||||
process_config_schema_errors,
|
||||
config_file.filename)
|
||||
|
||||
@ -453,7 +467,7 @@ def validate_service_constraints(config, service_name, config_file):
|
||||
return process_service_constraint_errors(
|
||||
errors, service_name, config_file.version)
|
||||
|
||||
schema = load_jsonschema(config_file)
|
||||
schema = load_jsonschema(config_file.version)
|
||||
validator = Draft4Validator(schema['definitions']['constraints']['service'])
|
||||
handle_errors(validator.iter_errors(config), handler, None)
|
||||
|
||||
@ -472,16 +486,19 @@ def get_schema_path():
|
||||
return os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
def load_jsonschema(config_file):
|
||||
def load_jsonschema(version):
|
||||
suffix = "compose_spec"
|
||||
if version == V1:
|
||||
suffix = "v1"
|
||||
|
||||
filename = os.path.join(
|
||||
get_schema_path(),
|
||||
"config_schema_v{0}.json".format(config_file.version))
|
||||
"config_schema_{0}.json".format(suffix))
|
||||
|
||||
if not os.path.exists(filename):
|
||||
raise ConfigurationError(
|
||||
'Version in "{}" is unsupported. {}'
|
||||
.format(config_file.filename, VERSION_EXPLANATION))
|
||||
|
||||
.format(filename, VERSION_EXPLANATION))
|
||||
with open(filename, "r") as fh:
|
||||
return json.load(fh)
|
||||
|
||||
|
@ -24,56 +24,16 @@ SECRETS_PATH = '/run/secrets'
|
||||
WINDOWS_LONGPATH_PREFIX = '\\\\?\\'
|
||||
|
||||
COMPOSEFILE_V1 = ComposeVersion('1')
|
||||
COMPOSEFILE_V2_0 = ComposeVersion('2.0')
|
||||
COMPOSEFILE_V2_1 = ComposeVersion('2.1')
|
||||
COMPOSEFILE_V2_2 = ComposeVersion('2.2')
|
||||
COMPOSEFILE_V2_3 = ComposeVersion('2.3')
|
||||
COMPOSEFILE_V2_4 = ComposeVersion('2.4')
|
||||
|
||||
COMPOSEFILE_V3_0 = ComposeVersion('3.0')
|
||||
COMPOSEFILE_V3_1 = ComposeVersion('3.1')
|
||||
COMPOSEFILE_V3_2 = ComposeVersion('3.2')
|
||||
COMPOSEFILE_V3_3 = ComposeVersion('3.3')
|
||||
COMPOSEFILE_V3_4 = ComposeVersion('3.4')
|
||||
COMPOSEFILE_V3_5 = ComposeVersion('3.5')
|
||||
COMPOSEFILE_V3_6 = ComposeVersion('3.6')
|
||||
COMPOSEFILE_V3_7 = ComposeVersion('3.7')
|
||||
COMPOSEFILE_V3_8 = ComposeVersion('3.8')
|
||||
COMPOSE_SPEC = ComposeVersion('3')
|
||||
|
||||
# minimum DOCKER ENGINE API version needed to support
|
||||
# features for each compose schema version
|
||||
API_VERSIONS = {
|
||||
COMPOSEFILE_V1: '1.21',
|
||||
COMPOSEFILE_V2_0: '1.22',
|
||||
COMPOSEFILE_V2_1: '1.24',
|
||||
COMPOSEFILE_V2_2: '1.25',
|
||||
COMPOSEFILE_V2_3: '1.30',
|
||||
COMPOSEFILE_V2_4: '1.35',
|
||||
COMPOSEFILE_V3_0: '1.25',
|
||||
COMPOSEFILE_V3_1: '1.25',
|
||||
COMPOSEFILE_V3_2: '1.25',
|
||||
COMPOSEFILE_V3_3: '1.30',
|
||||
COMPOSEFILE_V3_4: '1.30',
|
||||
COMPOSEFILE_V3_5: '1.30',
|
||||
COMPOSEFILE_V3_6: '1.36',
|
||||
COMPOSEFILE_V3_7: '1.38',
|
||||
COMPOSEFILE_V3_8: '1.38',
|
||||
COMPOSE_SPEC: '1.38',
|
||||
}
|
||||
|
||||
API_VERSION_TO_ENGINE_VERSION = {
|
||||
API_VERSIONS[COMPOSEFILE_V1]: '1.9.0',
|
||||
API_VERSIONS[COMPOSEFILE_V2_0]: '1.10.0',
|
||||
API_VERSIONS[COMPOSEFILE_V2_1]: '1.12.0',
|
||||
API_VERSIONS[COMPOSEFILE_V2_2]: '1.13.0',
|
||||
API_VERSIONS[COMPOSEFILE_V2_3]: '17.06.0',
|
||||
API_VERSIONS[COMPOSEFILE_V2_4]: '17.12.0',
|
||||
API_VERSIONS[COMPOSEFILE_V3_0]: '1.13.0',
|
||||
API_VERSIONS[COMPOSEFILE_V3_1]: '1.13.0',
|
||||
API_VERSIONS[COMPOSEFILE_V3_2]: '1.13.0',
|
||||
API_VERSIONS[COMPOSEFILE_V3_3]: '17.06.0',
|
||||
API_VERSIONS[COMPOSEFILE_V3_4]: '17.06.0',
|
||||
API_VERSIONS[COMPOSEFILE_V3_5]: '17.06.0',
|
||||
API_VERSIONS[COMPOSEFILE_V3_6]: '18.02.0',
|
||||
API_VERSIONS[COMPOSEFILE_V3_7]: '18.06.0',
|
||||
API_VERSIONS[COMPOSEFILE_V3_8]: '18.06.0',
|
||||
API_VERSIONS[COMPOSE_SPEC]: '18.06.0',
|
||||
}
|
||||
|
@ -123,6 +123,18 @@ class Project(object):
|
||||
service_dict.pop('secrets', None) or [],
|
||||
config_data.secrets)
|
||||
|
||||
service_dict['scale'] = project.get_service_scale(service_dict)
|
||||
|
||||
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 and have'
|
||||
' been ignored: {}'.format(', '.join(ignored_keys))
|
||||
)
|
||||
|
||||
project.services.append(
|
||||
Service(
|
||||
service_dict.pop('name'),
|
||||
@ -262,6 +274,35 @@ class Project(object):
|
||||
|
||||
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', None)
|
||||
deploy_dict = service_dict.get('deploy', None)
|
||||
if not deploy_dict:
|
||||
return 1 if scale is None else scale
|
||||
|
||||
if deploy_dict.get('mode', 'replicated') != 'replicated':
|
||||
return 1 if scale is None else scale
|
||||
|
||||
replicas = deploy_dict.get('replicas', None)
|
||||
if scale and replicas:
|
||||
raise ConfigurationError(
|
||||
"Both service.scale and service.deploy.replicas are set."
|
||||
" Only one of them must be set."
|
||||
)
|
||||
if replicas:
|
||||
scale = replicas
|
||||
# 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 = []
|
||||
|
||||
@ -777,6 +818,81 @@ class Project(object):
|
||||
return container_operation_with_timeout
|
||||
|
||||
|
||||
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_resource_keys_to_container_config(resources_dict, service_dict):
|
||||
if 'limits' in resources_dict:
|
||||
service_dict['mem_limit'] = resources_dict['limits'].get('memory')
|
||||
if 'cpus' in resources_dict['limits']:
|
||||
service_dict['cpus'] = float(resources_dict['limits']['cpus'])
|
||||
if 'reservations' in resources_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):
|
||||
try:
|
||||
return {
|
||||
'any': 'always',
|
||||
'none': 'no',
|
||||
'on-failure': 'on-failure'
|
||||
}[name]
|
||||
except KeyError:
|
||||
raise ConfigurationError('Invalid restart policy "{}"'.format(name))
|
||||
|
||||
|
||||
def convert_credential_spec_to_security_opt(credential_spec):
|
||||
if 'file' in credential_spec:
|
||||
return 'file://{file}'.format(file=credential_spec['file'])
|
||||
return 'registry://{registry}'.format(registry=credential_spec['registry'])
|
||||
|
||||
|
||||
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 '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 get_volumes_from(project, service_dict):
|
||||
volumes_from = service_dict.pop('volumes_from', None)
|
||||
if not volumes_from:
|
||||
|
@ -23,73 +23,8 @@ exe = EXE(pyz,
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v2.0.json',
|
||||
'compose/config/config_schema_v2.0.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v2.1.json',
|
||||
'compose/config/config_schema_v2.1.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v2.2.json',
|
||||
'compose/config/config_schema_v2.2.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v2.3.json',
|
||||
'compose/config/config_schema_v2.3.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v2.4.json',
|
||||
'compose/config/config_schema_v2.4.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v3.0.json',
|
||||
'compose/config/config_schema_v3.0.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v3.1.json',
|
||||
'compose/config/config_schema_v3.1.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v3.2.json',
|
||||
'compose/config/config_schema_v3.2.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v3.3.json',
|
||||
'compose/config/config_schema_v3.3.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v3.4.json',
|
||||
'compose/config/config_schema_v3.4.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v3.5.json',
|
||||
'compose/config/config_schema_v3.5.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v3.6.json',
|
||||
'compose/config/config_schema_v3.6.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v3.7.json',
|
||||
'compose/config/config_schema_v3.7.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v3.8.json',
|
||||
'compose/config/config_schema_v3.8.json',
|
||||
'compose/config/config_schema_compose_spec.json',
|
||||
'compose/config/config_schema_compose_spec.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
|
@ -32,73 +32,8 @@ coll = COLLECT(exe,
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v2.0.json',
|
||||
'compose/config/config_schema_v2.0.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v2.1.json',
|
||||
'compose/config/config_schema_v2.1.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v2.2.json',
|
||||
'compose/config/config_schema_v2.2.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v2.3.json',
|
||||
'compose/config/config_schema_v2.3.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v2.4.json',
|
||||
'compose/config/config_schema_v2.4.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v3.0.json',
|
||||
'compose/config/config_schema_v3.0.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v3.1.json',
|
||||
'compose/config/config_schema_v3.1.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v3.2.json',
|
||||
'compose/config/config_schema_v3.2.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v3.3.json',
|
||||
'compose/config/config_schema_v3.3.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v3.4.json',
|
||||
'compose/config/config_schema_v3.4.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v3.5.json',
|
||||
'compose/config/config_schema_v3.5.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v3.6.json',
|
||||
'compose/config/config_schema_v3.6.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v3.7.json',
|
||||
'compose/config/config_schema_v3.7.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
'compose/config/config_schema_v3.8.json',
|
||||
'compose/config/config_schema_v3.8.json',
|
||||
'compose/config/config_schema_compose_spec.json',
|
||||
'compose/config/config_schema_compose_spec.json',
|
||||
'DATA'
|
||||
),
|
||||
(
|
||||
|
@ -20,6 +20,8 @@ from ..helpers import BUSYBOX_IMAGE_WITH_TAG
|
||||
from ..helpers import create_host_file
|
||||
from compose.cli.command import get_project
|
||||
from compose.config.errors import DuplicateOverrideFileFound
|
||||
from compose.const import COMPOSE_SPEC as VERSION
|
||||
from compose.const import COMPOSEFILE_V1 as V1
|
||||
from compose.container import Container
|
||||
from compose.project import OneOffFilter
|
||||
from compose.utils import nanoseconds_from_time_seconds
|
||||
@ -29,10 +31,6 @@ from tests.integration.testcases import is_cluster
|
||||
from tests.integration.testcases import no_cluster
|
||||
from tests.integration.testcases import pull_busybox
|
||||
from tests.integration.testcases import SWARM_SKIP_RM_VOLUMES
|
||||
from tests.integration.testcases import v2_1_only
|
||||
from tests.integration.testcases import v2_2_only
|
||||
from tests.integration.testcases import v2_only
|
||||
from tests.integration.testcases import v3_only
|
||||
|
||||
DOCKER_COMPOSE_EXECUTABLE = 'docker-compose'
|
||||
|
||||
@ -42,7 +40,7 @@ ProcessResult = namedtuple('ProcessResult', 'stdout stderr')
|
||||
BUILD_CACHE_TEXT = 'Using cache'
|
||||
BUILD_PULL_TEXT = 'Status: Image is up to date for busybox:1.27.2'
|
||||
COMPOSE_COMPATIBILITY_DICT = {
|
||||
'version': '2.3',
|
||||
'version': str(VERSION),
|
||||
'volumes': {'foo': {'driver': 'default'}},
|
||||
'networks': {'bar': {}},
|
||||
'services': {
|
||||
@ -287,7 +285,7 @@ services:
|
||||
|
||||
output = yaml.safe_load(result.stdout)
|
||||
expected = {
|
||||
'version': '2.0',
|
||||
'version': str(VERSION),
|
||||
'volumes': {'data': {'driver': 'local'}},
|
||||
'networks': {'front': {}},
|
||||
'services': {
|
||||
@ -311,7 +309,7 @@ services:
|
||||
self.base_dir = 'tests/fixtures/restart'
|
||||
result = self.dispatch(['config'])
|
||||
assert yaml.safe_load(result.stdout) == {
|
||||
'version': '2.0',
|
||||
'version': str(VERSION),
|
||||
'services': {
|
||||
'never': {
|
||||
'image': 'busybox',
|
||||
@ -343,10 +341,12 @@ services:
|
||||
assert 'networks' in json_result
|
||||
assert json_result['networks'] == {
|
||||
'networks_foo': {
|
||||
'external': True # {'name': 'networks_foo'}
|
||||
'external': True,
|
||||
'name': 'networks_foo'
|
||||
},
|
||||
'bar': {
|
||||
'external': {'name': 'networks_bar'}
|
||||
'external': True,
|
||||
'name': 'networks_bar'
|
||||
}
|
||||
}
|
||||
|
||||
@ -355,14 +355,14 @@ services:
|
||||
result = self.dispatch(['config'])
|
||||
json_result = yaml.safe_load(result.stdout)
|
||||
assert json_result == {
|
||||
'version': str(VERSION),
|
||||
'services': {
|
||||
'web': {
|
||||
'command': 'true',
|
||||
'image': 'alpine:latest',
|
||||
'ports': ['5643/tcp', '9999/tcp']
|
||||
'ports': [{'target': 5643}, {'target': 9999}]
|
||||
}
|
||||
}
|
||||
},
|
||||
'version': '2.4'
|
||||
}
|
||||
|
||||
def test_config_with_env_file(self):
|
||||
@ -370,14 +370,14 @@ services:
|
||||
result = self.dispatch(['--env-file', '.env2', 'config'])
|
||||
json_result = yaml.safe_load(result.stdout)
|
||||
assert json_result == {
|
||||
'version': str(VERSION),
|
||||
'services': {
|
||||
'web': {
|
||||
'command': 'false',
|
||||
'image': 'alpine:latest',
|
||||
'ports': ['5644/tcp', '9998/tcp']
|
||||
'ports': [{'target': 5644}, {'target': 9998}]
|
||||
}
|
||||
}
|
||||
},
|
||||
'version': '2.4'
|
||||
}
|
||||
|
||||
def test_config_with_dot_env_and_override_dir(self):
|
||||
@ -385,14 +385,14 @@ services:
|
||||
result = self.dispatch(['--project-directory', 'alt/', 'config'])
|
||||
json_result = yaml.safe_load(result.stdout)
|
||||
assert json_result == {
|
||||
'version': str(VERSION),
|
||||
'services': {
|
||||
'web': {
|
||||
'command': 'echo uwu',
|
||||
'image': 'alpine:3.10.1',
|
||||
'ports': ['3341/tcp', '4449/tcp']
|
||||
'ports': [{'target': 3341}, {'target': 4449}]
|
||||
}
|
||||
}
|
||||
},
|
||||
'version': '2.4'
|
||||
}
|
||||
|
||||
def test_config_external_volume_v2(self):
|
||||
@ -403,11 +403,11 @@ services:
|
||||
assert json_result['volumes'] == {
|
||||
'foo': {
|
||||
'external': True,
|
||||
'name': 'foo',
|
||||
},
|
||||
'bar': {
|
||||
'external': {
|
||||
'external': True,
|
||||
'name': 'some_bar',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -435,11 +435,11 @@ services:
|
||||
assert json_result['volumes'] == {
|
||||
'foo': {
|
||||
'external': True,
|
||||
'name': 'foo',
|
||||
},
|
||||
'bar': {
|
||||
'external': {
|
||||
'external': True,
|
||||
'name': 'some_bar',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -479,7 +479,7 @@ services:
|
||||
self.base_dir = 'tests/fixtures/v1-config'
|
||||
result = self.dispatch(['config'])
|
||||
assert yaml.safe_load(result.stdout) == {
|
||||
'version': '2.1',
|
||||
'version': str(V1),
|
||||
'services': {
|
||||
'net': {
|
||||
'image': 'busybox',
|
||||
@ -498,13 +498,11 @@ services:
|
||||
},
|
||||
}
|
||||
|
||||
@v3_only()
|
||||
def test_config_v3(self):
|
||||
self.base_dir = 'tests/fixtures/v3-full'
|
||||
result = self.dispatch(['config'])
|
||||
|
||||
assert yaml.safe_load(result.stdout) == {
|
||||
'version': '3.5',
|
||||
'version': str(VERSION),
|
||||
'volumes': {
|
||||
'foobar': {
|
||||
'labels': {
|
||||
@ -576,12 +574,14 @@ services:
|
||||
},
|
||||
}
|
||||
|
||||
@pytest.mark.skip(reason='deprecated option')
|
||||
def test_config_compatibility_mode(self):
|
||||
self.base_dir = 'tests/fixtures/compatibility-mode'
|
||||
result = self.dispatch(['--compatibility', 'config'])
|
||||
|
||||
assert yaml.load(result.stdout) == COMPOSE_COMPATIBILITY_DICT
|
||||
|
||||
@pytest.mark.skip(reason='deprecated option')
|
||||
@mock.patch.dict(os.environ)
|
||||
def test_config_compatibility_mode_from_env(self):
|
||||
self.base_dir = 'tests/fixtures/compatibility-mode'
|
||||
@ -590,6 +590,7 @@ services:
|
||||
|
||||
assert yaml.load(result.stdout) == COMPOSE_COMPATIBILITY_DICT
|
||||
|
||||
@pytest.mark.skip(reason='deprecated option')
|
||||
@mock.patch.dict(os.environ)
|
||||
def test_config_compatibility_mode_from_env_and_option_precedence(self):
|
||||
self.base_dir = 'tests/fixtures/compatibility-mode'
|
||||
@ -1018,7 +1019,6 @@ services:
|
||||
result = self.dispatch(['down', '--rmi', 'bogus'], returncode=1)
|
||||
assert '--rmi flag must be' in result.stderr
|
||||
|
||||
@v2_only()
|
||||
def test_down(self):
|
||||
self.base_dir = 'tests/fixtures/v2-full'
|
||||
|
||||
@ -1103,7 +1103,6 @@ services:
|
||||
assert '{} exited with code 0'.format(simple_name) in result.stdout
|
||||
assert '{} exited with code 0'.format(another_name) in result.stdout
|
||||
|
||||
@v2_only()
|
||||
def test_up(self):
|
||||
self.base_dir = 'tests/fixtures/v2-simple'
|
||||
self.dispatch(['up', '-d'], None)
|
||||
@ -1135,7 +1134,6 @@ services:
|
||||
for service in services:
|
||||
assert self.lookup(container, service.name)
|
||||
|
||||
@v2_only()
|
||||
def test_up_no_start(self):
|
||||
self.base_dir = 'tests/fixtures/v2-full'
|
||||
self.dispatch(['up', '--no-start'], None)
|
||||
@ -1166,7 +1164,6 @@ services:
|
||||
]
|
||||
assert len(remote_volumes) > 0
|
||||
|
||||
@v2_only()
|
||||
def test_up_no_start_remove_orphans(self):
|
||||
self.base_dir = 'tests/fixtures/v2-simple'
|
||||
self.dispatch(['up', '--no-start'], None)
|
||||
@ -1182,7 +1179,6 @@ services:
|
||||
stopped=True) + next.containers(stopped=True)), services)
|
||||
assert len(stopped2) == 1
|
||||
|
||||
@v2_only()
|
||||
def test_up_no_ansi(self):
|
||||
self.base_dir = 'tests/fixtures/v2-simple'
|
||||
result = self.dispatch(['--no-ansi', 'up', '-d'], None)
|
||||
@ -1190,7 +1186,6 @@ services:
|
||||
assert "%c[1A" % 27 not in result.stderr
|
||||
assert "%c[1B" % 27 not in result.stderr
|
||||
|
||||
@v2_only()
|
||||
def test_up_with_default_network_config(self):
|
||||
filename = 'default-network-config.yml'
|
||||
|
||||
@ -1204,7 +1199,6 @@ services:
|
||||
|
||||
assert networks[0]['Options']['com.docker.network.bridge.enable_icc'] == 'false'
|
||||
|
||||
@v2_only()
|
||||
def test_up_with_network_aliases(self):
|
||||
filename = 'network-aliases.yml'
|
||||
self.base_dir = 'tests/fixtures/networks'
|
||||
@ -1232,7 +1226,6 @@ services:
|
||||
assert 'forward_facing' in front_aliases
|
||||
assert 'ahead' in front_aliases
|
||||
|
||||
@v2_only()
|
||||
def test_up_with_network_internal(self):
|
||||
self.require_api_version('1.23')
|
||||
filename = 'network-internal.yml'
|
||||
@ -1250,7 +1243,6 @@ services:
|
||||
|
||||
assert networks[0]['Internal'] is True
|
||||
|
||||
@v2_only()
|
||||
def test_up_with_network_static_addresses(self):
|
||||
filename = 'network-static-addresses.yml'
|
||||
ipv4_address = '172.16.100.100'
|
||||
@ -1274,7 +1266,6 @@ services:
|
||||
assert ipv4_address in ipam_config.values()
|
||||
assert ipv6_address in ipam_config.values()
|
||||
|
||||
@v2_only()
|
||||
def test_up_with_networks(self):
|
||||
self.base_dir = 'tests/fixtures/networks'
|
||||
self.dispatch(['up', '-d'], None)
|
||||
@ -1322,7 +1313,6 @@ services:
|
||||
# app has aliased db to "database"
|
||||
assert self.lookup(app_container, "database")
|
||||
|
||||
@v2_only()
|
||||
def test_up_missing_network(self):
|
||||
self.base_dir = 'tests/fixtures/networks'
|
||||
|
||||
@ -1332,7 +1322,6 @@ services:
|
||||
|
||||
assert 'Service "web" uses an undefined network "foo"' in result.stderr
|
||||
|
||||
@v2_only()
|
||||
@no_cluster('container networks not supported in Swarm')
|
||||
def test_up_with_network_mode(self):
|
||||
c = self.client.create_container(
|
||||
@ -1371,7 +1360,6 @@ services:
|
||||
assert not container_mode_container.get('NetworkSettings.Networks')
|
||||
assert container_mode_container.get('HostConfig.NetworkMode') == container_mode_source
|
||||
|
||||
@v2_only()
|
||||
def test_up_external_networks(self):
|
||||
filename = 'external-networks.yml'
|
||||
|
||||
@ -1395,7 +1383,6 @@ services:
|
||||
container = self.project.containers()[0]
|
||||
assert sorted(list(container.get('NetworkSettings.Networks'))) == sorted(network_names)
|
||||
|
||||
@v2_only()
|
||||
def test_up_with_external_default_network(self):
|
||||
filename = 'external-default.yml'
|
||||
|
||||
@ -1418,7 +1405,6 @@ services:
|
||||
container = self.project.containers()[0]
|
||||
assert list(container.get('NetworkSettings.Networks')) == [network_name]
|
||||
|
||||
@v2_1_only()
|
||||
def test_up_with_network_labels(self):
|
||||
filename = 'network-label.yml'
|
||||
|
||||
@ -1438,7 +1424,6 @@ services:
|
||||
assert 'label_key' in networks[0]['Labels']
|
||||
assert networks[0]['Labels']['label_key'] == 'label_val'
|
||||
|
||||
@v2_1_only()
|
||||
def test_up_with_volume_labels(self):
|
||||
filename = 'volume-label.yml'
|
||||
|
||||
@ -1458,7 +1443,6 @@ services:
|
||||
assert 'label_key' in volumes[0]['Labels']
|
||||
assert volumes[0]['Labels']['label_key'] == 'label_val'
|
||||
|
||||
@v2_only()
|
||||
def test_up_no_services(self):
|
||||
self.base_dir = 'tests/fixtures/no-services'
|
||||
self.dispatch(['up', '-d'], None)
|
||||
@ -1515,7 +1499,6 @@ services:
|
||||
bar_container.id
|
||||
)
|
||||
|
||||
@v3_only()
|
||||
def test_up_with_healthcheck(self):
|
||||
def wait_on_health_status(container, status):
|
||||
def condition():
|
||||
@ -1649,7 +1632,6 @@ services:
|
||||
os.kill(proc.pid, signal.SIGTERM)
|
||||
wait_on_condition(ContainerCountCondition(self.project, 0))
|
||||
|
||||
@v2_only()
|
||||
def test_up_handles_force_shutdown(self):
|
||||
self.base_dir = 'tests/fixtures/sleeps-composefile'
|
||||
proc = start_process(self.base_dir, ['up', '-t', '200'])
|
||||
@ -1674,7 +1656,6 @@ services:
|
||||
proc.wait()
|
||||
assert proc.returncode == 1
|
||||
|
||||
@v2_only()
|
||||
@no_cluster('Container PID mode does not work across clusters')
|
||||
def test_up_with_pid_mode(self):
|
||||
c = self.client.create_container(
|
||||
@ -1738,7 +1719,6 @@ services:
|
||||
assert stdout == "operator\n"
|
||||
assert stderr == ""
|
||||
|
||||
@v3_only()
|
||||
def test_exec_workdir(self):
|
||||
self.base_dir = 'tests/fixtures/links-composefile'
|
||||
os.environ['COMPOSE_API_VERSION'] = '1.35'
|
||||
@ -1748,7 +1728,6 @@ services:
|
||||
stdout, stderr = self.dispatch(['exec', '-T', '--workdir', '/etc', 'console', 'ls'])
|
||||
assert 'passwd' in stdout
|
||||
|
||||
@v2_2_only()
|
||||
def test_exec_service_with_environment_overridden(self):
|
||||
name = 'service'
|
||||
self.base_dir = 'tests/fixtures/environment-exec'
|
||||
@ -1793,7 +1772,6 @@ services:
|
||||
assert len(db.containers()) == 1
|
||||
assert len(console.containers()) == 0
|
||||
|
||||
@v2_only()
|
||||
def test_run_service_with_dependencies(self):
|
||||
self.base_dir = 'tests/fixtures/v2-dependencies'
|
||||
self.dispatch(['run', 'web', '/bin/true'], None)
|
||||
@ -2105,7 +2083,6 @@ services:
|
||||
container = service.containers(stopped=True, one_off=True)[0]
|
||||
assert workdir == container.get('Config.WorkingDir')
|
||||
|
||||
@v2_only()
|
||||
def test_run_service_with_use_aliases(self):
|
||||
filename = 'network-aliases.yml'
|
||||
self.base_dir = 'tests/fixtures/networks'
|
||||
@ -2127,7 +2104,6 @@ services:
|
||||
assert 'forward_facing' in front_aliases
|
||||
assert 'ahead' in front_aliases
|
||||
|
||||
@v2_only()
|
||||
def test_run_interactive_connects_to_network(self):
|
||||
self.base_dir = 'tests/fixtures/networks'
|
||||
|
||||
@ -2153,7 +2129,6 @@ services:
|
||||
aliases = set(config['Aliases'] or []) - {container.short_id}
|
||||
assert not aliases
|
||||
|
||||
@v2_only()
|
||||
def test_run_detached_connects_to_network(self):
|
||||
self.base_dir = 'tests/fixtures/networks'
|
||||
self.dispatch(['up', '-d'])
|
||||
@ -2332,7 +2307,6 @@ services:
|
||||
assert 'failed' in result.stderr
|
||||
assert 'No containers to start' in result.stderr
|
||||
|
||||
@v2_only()
|
||||
def test_up_logging(self):
|
||||
self.base_dir = 'tests/fixtures/logging-composefile'
|
||||
self.dispatch(['up', '-d'])
|
||||
@ -2563,11 +2537,6 @@ services:
|
||||
assert len(project.get_service('simple').containers()) == 0
|
||||
assert len(project.get_service('another').containers()) == 0
|
||||
|
||||
def test_scale_v2_2(self):
|
||||
self.base_dir = 'tests/fixtures/scale'
|
||||
result = self.dispatch(['scale', 'web=1'], returncode=1)
|
||||
assert 'incompatible with the v2.2 format' in result.stderr
|
||||
|
||||
def test_up_scale_scale_up(self):
|
||||
self.base_dir = 'tests/fixtures/scale'
|
||||
project = self.project
|
||||
|
@ -21,11 +21,7 @@ from compose.config import ConfigurationError
|
||||
from compose.config import types
|
||||
from compose.config.types import VolumeFromSpec
|
||||
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_V2_2 as V2_2
|
||||
from compose.const import COMPOSEFILE_V2_3 as V2_3
|
||||
from compose.const import COMPOSEFILE_V3_1 as V3_1
|
||||
from compose.const import COMPOSE_SPEC as VERSION
|
||||
from compose.const import LABEL_PROJECT
|
||||
from compose.const import LABEL_SERVICE
|
||||
from compose.container import Container
|
||||
@ -37,16 +33,11 @@ from compose.service import ConvergenceStrategy
|
||||
from tests.integration.testcases import if_runtime_available
|
||||
from tests.integration.testcases import is_cluster
|
||||
from tests.integration.testcases import no_cluster
|
||||
from tests.integration.testcases import v2_1_only
|
||||
from tests.integration.testcases import v2_2_only
|
||||
from tests.integration.testcases import v2_3_only
|
||||
from tests.integration.testcases import v2_only
|
||||
from tests.integration.testcases import v3_only
|
||||
|
||||
|
||||
def build_config(**kwargs):
|
||||
return config.Config(
|
||||
version=kwargs.get('version'),
|
||||
version=kwargs.get('version', VERSION),
|
||||
services=kwargs.get('services'),
|
||||
volumes=kwargs.get('volumes'),
|
||||
networks=kwargs.get('networks'),
|
||||
@ -106,7 +97,6 @@ class ProjectTest(DockerClientTestCase):
|
||||
|
||||
def test_parallel_pull_with_no_image(self):
|
||||
config_data = build_config(
|
||||
version=V2_3,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'build': {'context': '.'},
|
||||
@ -162,14 +152,12 @@ class ProjectTest(DockerClientTestCase):
|
||||
db = project.get_service('db')
|
||||
assert db._get_volumes_from() == [data_container.id + ':rw']
|
||||
|
||||
@v2_only()
|
||||
@no_cluster('container networks not supported in Swarm')
|
||||
def test_network_mode_from_service(self):
|
||||
project = Project.from_config(
|
||||
name='composetest',
|
||||
client=self.client,
|
||||
config_data=load_config({
|
||||
'version': str(V2_0),
|
||||
'services': {
|
||||
'net': {
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -190,14 +178,12 @@ class ProjectTest(DockerClientTestCase):
|
||||
net = project.get_service('net')
|
||||
assert web.network_mode.mode == 'container:' + net.containers()[0].id
|
||||
|
||||
@v2_only()
|
||||
@no_cluster('container networks not supported in Swarm')
|
||||
def test_network_mode_from_container(self):
|
||||
def get_project():
|
||||
return Project.from_config(
|
||||
name='composetest',
|
||||
config_data=load_config({
|
||||
'version': str(V2_0),
|
||||
'services': {
|
||||
'web': {
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -448,7 +434,6 @@ class ProjectTest(DockerClientTestCase):
|
||||
assert db_container.id != old_db_id
|
||||
assert db_container.get('Volumes./etc') == db_volume_path
|
||||
|
||||
@v2_3_only()
|
||||
def test_recreate_preserves_mounts(self):
|
||||
web = self.create_service('web')
|
||||
db = self.create_service('db', volumes=[types.MountSpec(type='volume', target='/etc')])
|
||||
@ -656,10 +641,8 @@ class ProjectTest(DockerClientTestCase):
|
||||
service = project.get_service('web')
|
||||
assert len(service.containers()) == 1
|
||||
|
||||
@v2_only()
|
||||
def test_project_up_networks(self):
|
||||
config_data = build_config(
|
||||
version=V2_0,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -701,10 +684,8 @@ class ProjectTest(DockerClientTestCase):
|
||||
foo_data = self.client.inspect_network('composetest_foo')
|
||||
assert foo_data['Driver'] == 'bridge'
|
||||
|
||||
@v2_only()
|
||||
def test_up_with_ipam_config(self):
|
||||
config_data = build_config(
|
||||
version=V2_0,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -761,10 +742,8 @@ class ProjectTest(DockerClientTestCase):
|
||||
}],
|
||||
}
|
||||
|
||||
@v2_only()
|
||||
def test_up_with_ipam_options(self):
|
||||
config_data = build_config(
|
||||
version=V2_0,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -796,10 +775,8 @@ class ProjectTest(DockerClientTestCase):
|
||||
"com.docker.compose.network.test": "9-29-045"
|
||||
}
|
||||
|
||||
@v2_1_only()
|
||||
def test_up_with_network_static_addresses(self):
|
||||
config_data = build_config(
|
||||
version=V2_1,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -845,13 +822,11 @@ class ProjectTest(DockerClientTestCase):
|
||||
assert ipam_config.get('IPv4Address') == '172.16.100.100'
|
||||
assert ipam_config.get('IPv6Address') == 'fe80::1001:102'
|
||||
|
||||
@v2_3_only()
|
||||
def test_up_with_network_priorities(self):
|
||||
mac_address = '74:6f:75:68:6f:75'
|
||||
|
||||
def get_config_data(p1, p2, p3):
|
||||
return build_config(
|
||||
version=V2_3,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -910,11 +885,9 @@ class ProjectTest(DockerClientTestCase):
|
||||
net_config = service_container.inspect()['NetworkSettings']['Networks']['composetest_n3']
|
||||
assert net_config['MacAddress'] == mac_address
|
||||
|
||||
@v2_1_only()
|
||||
def test_up_with_enable_ipv6(self):
|
||||
self.require_api_version('1.23')
|
||||
config_data = build_config(
|
||||
version=V2_1,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -954,10 +927,8 @@ class ProjectTest(DockerClientTestCase):
|
||||
get('IPAMConfig', {}))
|
||||
assert ipam_config.get('IPv6Address') == 'fe80::1001:102'
|
||||
|
||||
@v2_only()
|
||||
def test_up_with_network_static_addresses_missing_subnet(self):
|
||||
config_data = build_config(
|
||||
version=V2_0,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -990,10 +961,8 @@ class ProjectTest(DockerClientTestCase):
|
||||
with pytest.raises(ProjectError):
|
||||
project.up()
|
||||
|
||||
@v2_1_only()
|
||||
def test_up_with_network_link_local_ips(self):
|
||||
config_data = build_config(
|
||||
version=V2_1,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -1025,10 +994,8 @@ class ProjectTest(DockerClientTestCase):
|
||||
assert 'LinkLocalIPs' in ipam_config
|
||||
assert ipam_config['LinkLocalIPs'] == ['169.254.8.8']
|
||||
|
||||
@v2_1_only()
|
||||
def test_up_with_custom_name_resources(self):
|
||||
config_data = build_config(
|
||||
version=V2_2,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'volumes': [VolumeSpec.parse('foo:/container-path')],
|
||||
@ -1062,11 +1029,9 @@ class ProjectTest(DockerClientTestCase):
|
||||
assert network['Labels']['com.docker.compose.test_value'] == 'sharpdressedman'
|
||||
assert volume['Labels']['com.docker.compose.test_value'] == 'thefuror'
|
||||
|
||||
@v2_1_only()
|
||||
def test_up_with_isolation(self):
|
||||
self.require_api_version('1.24')
|
||||
config_data = build_config(
|
||||
version=V2_1,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -1082,11 +1047,9 @@ class ProjectTest(DockerClientTestCase):
|
||||
service_container = project.get_service('web').containers(stopped=True)[0]
|
||||
assert service_container.inspect()['HostConfig']['Isolation'] == 'default'
|
||||
|
||||
@v2_1_only()
|
||||
def test_up_with_invalid_isolation(self):
|
||||
self.require_api_version('1.24')
|
||||
config_data = build_config(
|
||||
version=V2_1,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -1101,12 +1064,10 @@ class ProjectTest(DockerClientTestCase):
|
||||
with pytest.raises(ProjectError):
|
||||
project.up()
|
||||
|
||||
@v2_3_only()
|
||||
@if_runtime_available('runc')
|
||||
def test_up_with_runtime(self):
|
||||
self.require_api_version('1.30')
|
||||
config_data = build_config(
|
||||
version=V2_3,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -1122,11 +1083,9 @@ class ProjectTest(DockerClientTestCase):
|
||||
service_container = project.get_service('web').containers(stopped=True)[0]
|
||||
assert service_container.inspect()['HostConfig']['Runtime'] == 'runc'
|
||||
|
||||
@v2_3_only()
|
||||
def test_up_with_invalid_runtime(self):
|
||||
self.require_api_version('1.30')
|
||||
config_data = build_config(
|
||||
version=V2_3,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -1141,12 +1100,10 @@ class ProjectTest(DockerClientTestCase):
|
||||
with pytest.raises(ProjectError):
|
||||
project.up()
|
||||
|
||||
@v2_3_only()
|
||||
@if_runtime_available('nvidia')
|
||||
def test_up_with_nvidia_runtime(self):
|
||||
self.require_api_version('1.30')
|
||||
config_data = build_config(
|
||||
version=V2_3,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -1162,11 +1119,9 @@ class ProjectTest(DockerClientTestCase):
|
||||
service_container = project.get_service('web').containers(stopped=True)[0]
|
||||
assert service_container.inspect()['HostConfig']['Runtime'] == 'nvidia'
|
||||
|
||||
@v2_only()
|
||||
def test_project_up_with_network_internal(self):
|
||||
self.require_api_version('1.23')
|
||||
config_data = build_config(
|
||||
version=V2_0,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -1188,14 +1143,12 @@ class ProjectTest(DockerClientTestCase):
|
||||
|
||||
assert network['Internal'] is True
|
||||
|
||||
@v2_1_only()
|
||||
def test_project_up_with_network_label(self):
|
||||
self.require_api_version('1.23')
|
||||
|
||||
network_name = 'network_with_label'
|
||||
|
||||
config_data = build_config(
|
||||
version=V2_1,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -1223,12 +1176,10 @@ class ProjectTest(DockerClientTestCase):
|
||||
assert 'label_key' in networks[0]['Labels']
|
||||
assert networks[0]['Labels']['label_key'] == 'label_val'
|
||||
|
||||
@v2_only()
|
||||
def test_project_up_volumes(self):
|
||||
vol_name = '{0:x}'.format(random.getrandbits(32))
|
||||
full_vol_name = 'composetest_{0}'.format(vol_name)
|
||||
config_data = build_config(
|
||||
version=V2_0,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -1248,14 +1199,12 @@ class ProjectTest(DockerClientTestCase):
|
||||
assert volume_data['Name'].split('/')[-1] == full_vol_name
|
||||
assert volume_data['Driver'] == 'local'
|
||||
|
||||
@v2_1_only()
|
||||
def test_project_up_with_volume_labels(self):
|
||||
self.require_api_version('1.23')
|
||||
|
||||
volume_name = 'volume_with_label'
|
||||
|
||||
config_data = build_config(
|
||||
version=V2_1,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -1290,12 +1239,10 @@ class ProjectTest(DockerClientTestCase):
|
||||
assert 'label_key' in volumes[0]['Labels']
|
||||
assert volumes[0]['Labels']['label_key'] == 'label_val'
|
||||
|
||||
@v2_only()
|
||||
def test_project_up_logging_with_multiple_files(self):
|
||||
base_file = config.ConfigFile(
|
||||
'base.yml',
|
||||
{
|
||||
'version': str(V2_0),
|
||||
'services': {
|
||||
'simple': {'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top'},
|
||||
'another': {
|
||||
@ -1314,7 +1261,6 @@ class ProjectTest(DockerClientTestCase):
|
||||
override_file = config.ConfigFile(
|
||||
'override.yml',
|
||||
{
|
||||
'version': str(V2_0),
|
||||
'services': {
|
||||
'another': {
|
||||
'logging': {
|
||||
@ -1342,12 +1288,10 @@ class ProjectTest(DockerClientTestCase):
|
||||
assert log_config
|
||||
assert log_config.get('Type') == 'none'
|
||||
|
||||
@v2_only()
|
||||
def test_project_up_port_mappings_with_multiple_files(self):
|
||||
base_file = config.ConfigFile(
|
||||
'base.yml',
|
||||
{
|
||||
'version': str(V2_0),
|
||||
'services': {
|
||||
'simple': {
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -1360,7 +1304,6 @@ class ProjectTest(DockerClientTestCase):
|
||||
override_file = config.ConfigFile(
|
||||
'override.yml',
|
||||
{
|
||||
'version': str(V2_0),
|
||||
'services': {
|
||||
'simple': {
|
||||
'ports': ['1234:1234']
|
||||
@ -1378,10 +1321,8 @@ class ProjectTest(DockerClientTestCase):
|
||||
containers = project.containers()
|
||||
assert len(containers) == 1
|
||||
|
||||
@v2_2_only()
|
||||
def test_project_up_config_scale(self):
|
||||
config_data = build_config(
|
||||
version=V2_2,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -1406,12 +1347,10 @@ class ProjectTest(DockerClientTestCase):
|
||||
project.up()
|
||||
assert len(project.containers()) == 3
|
||||
|
||||
@v2_only()
|
||||
def test_initialize_volumes(self):
|
||||
vol_name = '{0:x}'.format(random.getrandbits(32))
|
||||
full_vol_name = 'composetest_{0}'.format(vol_name)
|
||||
config_data = build_config(
|
||||
version=V2_0,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -1430,12 +1369,10 @@ class ProjectTest(DockerClientTestCase):
|
||||
assert volume_data['Name'].split('/')[-1] == full_vol_name
|
||||
assert volume_data['Driver'] == 'local'
|
||||
|
||||
@v2_only()
|
||||
def test_project_up_implicit_volume_driver(self):
|
||||
vol_name = '{0:x}'.format(random.getrandbits(32))
|
||||
full_vol_name = 'composetest_{0}'.format(vol_name)
|
||||
config_data = build_config(
|
||||
version=V2_0,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -1454,12 +1391,10 @@ class ProjectTest(DockerClientTestCase):
|
||||
assert volume_data['Name'].split('/')[-1] == full_vol_name
|
||||
assert volume_data['Driver'] == 'local'
|
||||
|
||||
@v3_only()
|
||||
def test_project_up_with_secrets(self):
|
||||
node = create_host_file(self.client, os.path.abspath('tests/fixtures/secrets/default'))
|
||||
|
||||
config_data = build_config(
|
||||
version=V3_1,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -1491,12 +1426,10 @@ class ProjectTest(DockerClientTestCase):
|
||||
output = container.logs()
|
||||
assert output == b"This is the secret\n"
|
||||
|
||||
@v3_only()
|
||||
def test_project_up_with_added_secrets(self):
|
||||
node = create_host_file(self.client, os.path.abspath('tests/fixtures/secrets/default'))
|
||||
|
||||
config_input1 = {
|
||||
'version': V3_1,
|
||||
'services': [
|
||||
{
|
||||
'name': 'web',
|
||||
@ -1545,12 +1478,11 @@ class ProjectTest(DockerClientTestCase):
|
||||
output = container.logs()
|
||||
assert output == b"This is the secret\n"
|
||||
|
||||
@v2_only()
|
||||
def test_initialize_volumes_invalid_volume_driver(self):
|
||||
vol_name = '{0:x}'.format(random.getrandbits(32))
|
||||
|
||||
config_data = build_config(
|
||||
version=V2_0,
|
||||
version=VERSION,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -1566,14 +1498,12 @@ class ProjectTest(DockerClientTestCase):
|
||||
with pytest.raises(APIError if is_cluster(self.client) else config.ConfigurationError):
|
||||
project.volumes.initialize()
|
||||
|
||||
@v2_only()
|
||||
@no_cluster('inspect volume by name defect on Swarm Classic')
|
||||
def test_initialize_volumes_updated_driver(self):
|
||||
vol_name = '{0:x}'.format(random.getrandbits(32))
|
||||
full_vol_name = 'composetest_{0}'.format(vol_name)
|
||||
|
||||
config_data = build_config(
|
||||
version=V2_0,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -1605,7 +1535,6 @@ class ProjectTest(DockerClientTestCase):
|
||||
vol_name
|
||||
) in str(e.value)
|
||||
|
||||
@v2_only()
|
||||
@no_cluster('inspect volume by name defect on Swarm Classic')
|
||||
def test_initialize_volumes_updated_driver_opts(self):
|
||||
vol_name = '{0:x}'.format(random.getrandbits(32))
|
||||
@ -1615,7 +1544,6 @@ class ProjectTest(DockerClientTestCase):
|
||||
driver_opts = {'o': 'bind', 'device': tmpdir, 'type': 'none'}
|
||||
|
||||
config_data = build_config(
|
||||
version=V2_0,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -1651,13 +1579,11 @@ class ProjectTest(DockerClientTestCase):
|
||||
vol_name, driver_opts['device']
|
||||
) in str(e.value)
|
||||
|
||||
@v2_only()
|
||||
def test_initialize_volumes_updated_blank_driver(self):
|
||||
vol_name = '{0:x}'.format(random.getrandbits(32))
|
||||
full_vol_name = 'composetest_{0}'.format(vol_name)
|
||||
|
||||
config_data = build_config(
|
||||
version=V2_0,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -1688,7 +1614,6 @@ class ProjectTest(DockerClientTestCase):
|
||||
assert volume_data['Name'].split('/')[-1] == full_vol_name
|
||||
assert volume_data['Driver'] == 'local'
|
||||
|
||||
@v2_only()
|
||||
@no_cluster('inspect volume by name defect on Swarm Classic')
|
||||
def test_initialize_volumes_external_volumes(self):
|
||||
# Use composetest_ prefix so it gets garbage-collected in tearDown()
|
||||
@ -1696,7 +1621,6 @@ class ProjectTest(DockerClientTestCase):
|
||||
full_vol_name = 'composetest_{0}'.format(vol_name)
|
||||
self.client.create_volume(vol_name)
|
||||
config_data = build_config(
|
||||
version=V2_0,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -1715,12 +1639,10 @@ class ProjectTest(DockerClientTestCase):
|
||||
with pytest.raises(NotFound):
|
||||
self.client.inspect_volume(full_vol_name)
|
||||
|
||||
@v2_only()
|
||||
def test_initialize_volumes_inexistent_external_volume(self):
|
||||
vol_name = '{0:x}'.format(random.getrandbits(32))
|
||||
|
||||
config_data = build_config(
|
||||
version=V2_0,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -1740,7 +1662,6 @@ class ProjectTest(DockerClientTestCase):
|
||||
vol_name
|
||||
) in str(e.value)
|
||||
|
||||
@v2_only()
|
||||
def test_project_up_named_volumes_in_binds(self):
|
||||
vol_name = '{0:x}'.format(random.getrandbits(32))
|
||||
full_vol_name = 'composetest_{0}'.format(vol_name)
|
||||
@ -1748,7 +1669,6 @@ class ProjectTest(DockerClientTestCase):
|
||||
base_file = config.ConfigFile(
|
||||
'base.yml',
|
||||
{
|
||||
'version': str(V2_0),
|
||||
'services': {
|
||||
'simple': {
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -1839,7 +1759,6 @@ class ProjectTest(DockerClientTestCase):
|
||||
|
||||
mock_log.warning.assert_not_called()
|
||||
|
||||
@v2_1_only()
|
||||
def test_project_up_healthy_dependency(self):
|
||||
config_dict = {
|
||||
'version': '2.1',
|
||||
@ -1876,7 +1795,6 @@ class ProjectTest(DockerClientTestCase):
|
||||
assert 'svc1' in svc2.get_dependency_names()
|
||||
assert svc1.is_healthy()
|
||||
|
||||
@v2_1_only()
|
||||
def test_project_up_unhealthy_dependency(self):
|
||||
config_dict = {
|
||||
'version': '2.1',
|
||||
@ -1915,7 +1833,6 @@ class ProjectTest(DockerClientTestCase):
|
||||
with pytest.raises(HealthCheckFailed):
|
||||
svc1.is_healthy()
|
||||
|
||||
@v2_1_only()
|
||||
def test_project_up_no_healthcheck_dependency(self):
|
||||
config_dict = {
|
||||
'version': '2.1',
|
||||
|
@ -11,14 +11,8 @@ from compose.cli.docker_client import docker_client
|
||||
from compose.config.config import resolve_environment
|
||||
from compose.config.environment import Environment
|
||||
from compose.const import API_VERSIONS
|
||||
from compose.const import COMPOSE_SPEC as VERSION
|
||||
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_V2_2 as V2_2
|
||||
from compose.const import COMPOSEFILE_V2_3 as V2_3
|
||||
from compose.const import COMPOSEFILE_V3_0 as V3_0
|
||||
from compose.const import COMPOSEFILE_V3_2 as V3_2
|
||||
from compose.const import COMPOSEFILE_V3_5 as V3_5
|
||||
from compose.const import LABEL_PROJECT
|
||||
from compose.progress_stream import stream_output
|
||||
from compose.service import Service
|
||||
@ -45,17 +39,11 @@ def get_links(container):
|
||||
|
||||
def engine_max_version():
|
||||
if 'DOCKER_VERSION' not in os.environ:
|
||||
return V3_5
|
||||
return VERSION
|
||||
version = os.environ['DOCKER_VERSION'].partition('-')[0]
|
||||
if version_lt(version, '1.10'):
|
||||
return V1
|
||||
if version_lt(version, '1.12'):
|
||||
return V2_0
|
||||
if version_lt(version, '1.13'):
|
||||
return V2_1
|
||||
if version_lt(version, '17.06'):
|
||||
return V3_2
|
||||
return V3_5
|
||||
return VERSION
|
||||
|
||||
|
||||
def min_version_skip(version):
|
||||
@ -66,23 +54,23 @@ def min_version_skip(version):
|
||||
|
||||
|
||||
def v2_only():
|
||||
return min_version_skip(V2_0)
|
||||
return min_version_skip(VERSION)
|
||||
|
||||
|
||||
def v2_1_only():
|
||||
return min_version_skip(V2_1)
|
||||
return min_version_skip(VERSION)
|
||||
|
||||
|
||||
def v2_2_only():
|
||||
return min_version_skip(V2_2)
|
||||
return min_version_skip(VERSION)
|
||||
|
||||
|
||||
def v2_3_only():
|
||||
return min_version_skip(V2_3)
|
||||
return min_version_skip(VERSION)
|
||||
|
||||
|
||||
def v3_only():
|
||||
return min_version_skip(V3_0)
|
||||
return min_version_skip(VERSION)
|
||||
|
||||
|
||||
class DockerClientTestCase(unittest.TestCase):
|
||||
|
@ -34,19 +34,19 @@ class TestHandleConnectionErrors(object):
|
||||
|
||||
def test_api_error_version_mismatch(self, mock_logging):
|
||||
with pytest.raises(errors.ConnectionError):
|
||||
with handle_connection_errors(mock.Mock(api_version='1.22')):
|
||||
with handle_connection_errors(mock.Mock(api_version='1.38')):
|
||||
raise APIError(None, None, b"client is newer than server")
|
||||
|
||||
_, args, _ = mock_logging.error.mock_calls[0]
|
||||
assert "Docker Engine of version 1.10.0 or greater" in args[0]
|
||||
assert "Docker Engine of version 18.06.0 or greater" in args[0]
|
||||
|
||||
def test_api_error_version_mismatch_unicode_explanation(self, mock_logging):
|
||||
with pytest.raises(errors.ConnectionError):
|
||||
with handle_connection_errors(mock.Mock(api_version='1.22')):
|
||||
with handle_connection_errors(mock.Mock(api_version='1.38')):
|
||||
raise APIError(None, None, u"client is newer than server")
|
||||
|
||||
_, args, _ = mock_logging.error.mock_calls[0]
|
||||
assert "Docker Engine of version 1.10.0 or greater" in args[0]
|
||||
assert "Docker Engine of version 18.06.0 or greater" in args[0]
|
||||
|
||||
def test_api_error_version_other(self, mock_logging):
|
||||
msg = b"Something broke!"
|
||||
|
@ -26,21 +26,13 @@ from compose.config.serialize import denormalize_service_dict
|
||||
from compose.config.serialize import serialize_config
|
||||
from compose.config.serialize import serialize_ns_time_value
|
||||
from compose.config.types import VolumeSpec
|
||||
from compose.const import COMPOSE_SPEC as VERSION
|
||||
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_V2_2 as V2_2
|
||||
from compose.const import COMPOSEFILE_V2_3 as V2_3
|
||||
from compose.const import COMPOSEFILE_V3_0 as V3_0
|
||||
from compose.const import COMPOSEFILE_V3_1 as V3_1
|
||||
from compose.const import COMPOSEFILE_V3_2 as V3_2
|
||||
from compose.const import COMPOSEFILE_V3_3 as V3_3
|
||||
from compose.const import COMPOSEFILE_V3_5 as V3_5
|
||||
from compose.const import IS_WINDOWS_PLATFORM
|
||||
from tests import mock
|
||||
from tests import unittest
|
||||
|
||||
DEFAULT_VERSION = V2_0
|
||||
DEFAULT_VERSION = VERSION
|
||||
|
||||
|
||||
def make_service_dict(name, service_dict, working_dir='.', filename=None):
|
||||
@ -73,8 +65,10 @@ class ConfigTest(unittest.TestCase):
|
||||
service_dicts = config.load(
|
||||
build_config_details(
|
||||
{
|
||||
'services': {
|
||||
'foo': {'image': 'busybox'},
|
||||
'bar': {'image': 'busybox', 'environment': ['FOO=1']},
|
||||
}
|
||||
},
|
||||
'tests/fixtures/extends',
|
||||
'common.yml'
|
||||
@ -169,23 +163,23 @@ class ConfigTest(unittest.TestCase):
|
||||
def test_valid_versions(self):
|
||||
for version in ['2', '2.0']:
|
||||
cfg = config.load(build_config_details({'version': version}))
|
||||
assert cfg.version == V2_0
|
||||
assert cfg.version == VERSION
|
||||
|
||||
cfg = config.load(build_config_details({'version': '2.1'}))
|
||||
assert cfg.version == V2_1
|
||||
assert cfg.version == VERSION
|
||||
|
||||
cfg = config.load(build_config_details({'version': '2.2'}))
|
||||
assert cfg.version == V2_2
|
||||
assert cfg.version == VERSION
|
||||
|
||||
cfg = config.load(build_config_details({'version': '2.3'}))
|
||||
assert cfg.version == V2_3
|
||||
assert cfg.version == VERSION
|
||||
|
||||
for version in ['3', '3.0']:
|
||||
cfg = config.load(build_config_details({'version': version}))
|
||||
assert cfg.version == V3_0
|
||||
assert cfg.version == VERSION
|
||||
|
||||
cfg = config.load(build_config_details({'version': '3.1'}))
|
||||
assert cfg.version == V3_1
|
||||
assert cfg.version == VERSION
|
||||
|
||||
def test_v1_file_version(self):
|
||||
cfg = config.load(build_config_details({'web': {'image': 'busybox'}}))
|
||||
@ -197,7 +191,7 @@ class ConfigTest(unittest.TestCase):
|
||||
assert list(s['name'] for s in cfg.services) == ['version']
|
||||
|
||||
def test_wrong_version_type(self):
|
||||
for version in [None, 1, 2, 2.0]:
|
||||
for version in [1, 2, 2.0]:
|
||||
with pytest.raises(ConfigurationError) as excinfo:
|
||||
config.load(
|
||||
build_config_details(
|
||||
@ -213,12 +207,12 @@ class ConfigTest(unittest.TestCase):
|
||||
with pytest.raises(ConfigurationError) as excinfo:
|
||||
config.load(
|
||||
build_config_details(
|
||||
{'version': '2.18'},
|
||||
{'version': '1'},
|
||||
filename='filename.yml',
|
||||
)
|
||||
)
|
||||
|
||||
assert 'Version in "filename.yml" is unsupported' in excinfo.exconly()
|
||||
assert 'Version in "filename.yml" is invalid' in excinfo.exconly()
|
||||
assert VERSION_EXPLANATION in excinfo.exconly()
|
||||
|
||||
def test_version_1_is_invalid(self):
|
||||
@ -328,7 +322,6 @@ class ConfigTest(unittest.TestCase):
|
||||
}
|
||||
}, 'working_dir', 'filename.yml')
|
||||
)
|
||||
|
||||
assert 'Unexpected type for "version" key in "filename.yml"' \
|
||||
in mock_logging.warning.call_args[0][0]
|
||||
|
||||
@ -376,7 +369,7 @@ class ConfigTest(unittest.TestCase):
|
||||
base_file = config.ConfigFile(
|
||||
'base.yaml',
|
||||
{
|
||||
'version': str(V2_1),
|
||||
'version': '2',
|
||||
'services': {
|
||||
'web': {
|
||||
'image': 'example/web',
|
||||
@ -511,7 +504,15 @@ class ConfigTest(unittest.TestCase):
|
||||
for invalid_name in ['?not?allowed', ' ', '', '!', '/', '\xe2']:
|
||||
with pytest.raises(ConfigurationError) as exc:
|
||||
config.load(build_config_details(
|
||||
{invalid_name: {'image': 'busybox'}}))
|
||||
{
|
||||
'version': '2',
|
||||
'services': {
|
||||
invalid_name:
|
||||
{
|
||||
'image': 'busybox'
|
||||
}
|
||||
}
|
||||
}))
|
||||
assert 'Invalid service name \'%s\'' % invalid_name in exc.exconly()
|
||||
|
||||
def test_load_config_invalid_service_names_v2(self):
|
||||
@ -543,17 +544,24 @@ class ConfigTest(unittest.TestCase):
|
||||
with pytest.raises(ConfigurationError) as exc:
|
||||
config.load(build_config_details(
|
||||
{
|
||||
'web': {'image': 'busybox', 'name': 'bogus'},
|
||||
'version': '2',
|
||||
'services': {
|
||||
'web': {'image': 'busybox', 'name': 'bogus'}
|
||||
}
|
||||
},
|
||||
'working_dir',
|
||||
'filename.yml',
|
||||
))
|
||||
|
||||
assert "Unsupported config option for web: 'name'" in exc.exconly()
|
||||
assert "Unsupported config option for services.web: 'name'" in exc.exconly()
|
||||
|
||||
def test_load_invalid_service_definition(self):
|
||||
config_details = build_config_details(
|
||||
{'web': 'wrong'},
|
||||
{
|
||||
'version': '2',
|
||||
'services': {
|
||||
'web': 'wrong'
|
||||
}
|
||||
},
|
||||
'working_dir',
|
||||
'filename.yml')
|
||||
with pytest.raises(ConfigurationError) as exc:
|
||||
@ -585,7 +593,10 @@ class ConfigTest(unittest.TestCase):
|
||||
with pytest.raises(ConfigurationError) as excinfo:
|
||||
config.load(
|
||||
build_config_details(
|
||||
{1: {'image': 'busybox'}},
|
||||
{
|
||||
'version': '2',
|
||||
'services': {1: {'image': 'busybox'}}
|
||||
},
|
||||
'working_dir',
|
||||
'filename.yml'
|
||||
)
|
||||
@ -836,10 +847,10 @@ class ConfigTest(unittest.TestCase):
|
||||
def test_load_with_multiple_files_and_invalid_override(self):
|
||||
base_file = config.ConfigFile(
|
||||
'base.yaml',
|
||||
{'web': {'image': 'example/web'}})
|
||||
{'version': '2', 'services': {'web': {'image': 'example/web'}}})
|
||||
override_file = config.ConfigFile(
|
||||
'override.yaml',
|
||||
{'bogus': 'thing'})
|
||||
{'version': '2', 'services': {'bogus': 'thing'}})
|
||||
details = config.ConfigDetails('.', [base_file, override_file])
|
||||
|
||||
with pytest.raises(ConfigurationError) as exc:
|
||||
@ -977,7 +988,6 @@ class ConfigTest(unittest.TestCase):
|
||||
service = config.load(
|
||||
build_config_details(
|
||||
{
|
||||
'version': str(V3_3),
|
||||
'services': {
|
||||
'web': {
|
||||
'build': {
|
||||
@ -1424,7 +1434,7 @@ class ConfigTest(unittest.TestCase):
|
||||
config.load(
|
||||
build_config_details(
|
||||
{
|
||||
'version': str(V2_1),
|
||||
'version': str(VERSION),
|
||||
'networks': {
|
||||
'foo': {
|
||||
'driver': 'default',
|
||||
@ -1455,7 +1465,6 @@ class ConfigTest(unittest.TestCase):
|
||||
networks = config.load(
|
||||
build_config_details(
|
||||
{
|
||||
'version': str(V2_1),
|
||||
'networks': {
|
||||
'foo': {
|
||||
'driver': 'default',
|
||||
@ -1487,7 +1496,10 @@ class ConfigTest(unittest.TestCase):
|
||||
config.load(
|
||||
build_config_details(
|
||||
{
|
||||
'version': str(VERSION),
|
||||
'services': {
|
||||
'foo': {'image': 'busybox', 'privilige': 'something'},
|
||||
}
|
||||
},
|
||||
'tests/fixtures/extends',
|
||||
'filename.yml'
|
||||
@ -1508,7 +1520,10 @@ class ConfigTest(unittest.TestCase):
|
||||
config.load(
|
||||
build_config_details(
|
||||
{
|
||||
'version': str(VERSION),
|
||||
'services': {
|
||||
'foo': {'image': 1},
|
||||
}
|
||||
},
|
||||
'tests/fixtures/extends',
|
||||
'filename.yml'
|
||||
@ -1555,7 +1570,10 @@ class ConfigTest(unittest.TestCase):
|
||||
config.load(
|
||||
build_config_details(
|
||||
{
|
||||
'version': str(VERSION),
|
||||
'services': {
|
||||
'foo': {'image': 'busybox', 'links': 'an_link'},
|
||||
}
|
||||
},
|
||||
'tests/fixtures/extends',
|
||||
'filename.yml'
|
||||
@ -1583,7 +1601,10 @@ class ConfigTest(unittest.TestCase):
|
||||
config.load(
|
||||
build_config_details(
|
||||
{
|
||||
'version': str(VERSION),
|
||||
'services': {
|
||||
'web': {'build': '.', 'devices': ['/dev/foo:/dev/foo', '/dev/foo:/dev/foo']}
|
||||
}
|
||||
},
|
||||
'tests/fixtures/extends',
|
||||
'filename.yml'
|
||||
@ -1597,7 +1618,10 @@ class ConfigTest(unittest.TestCase):
|
||||
config.load(
|
||||
build_config_details(
|
||||
{
|
||||
'version': str(VERSION),
|
||||
'services': {
|
||||
'web': {'build': '.', 'command': [1]}
|
||||
}
|
||||
},
|
||||
'tests/fixtures/extends',
|
||||
'filename.yml'
|
||||
@ -1622,10 +1646,13 @@ class ConfigTest(unittest.TestCase):
|
||||
with pytest.raises(ConfigurationError) as excinfo:
|
||||
config.load(
|
||||
build_config_details(
|
||||
{'web': {
|
||||
{
|
||||
'version': str(VERSION),
|
||||
'services': {
|
||||
'web': {
|
||||
'image': 'busybox',
|
||||
'extra_hosts': 'somehost:162.242.195.82'
|
||||
}},
|
||||
'extra_hosts': 'somehost:162.242.195.82'}}
|
||||
},
|
||||
'working_dir',
|
||||
'filename.yml'
|
||||
)
|
||||
@ -1638,13 +1665,16 @@ class ConfigTest(unittest.TestCase):
|
||||
with pytest.raises(ConfigurationError) as excinfo:
|
||||
config.load(
|
||||
build_config_details(
|
||||
{'web': {
|
||||
{
|
||||
'version': str(VERSION),
|
||||
'services': {
|
||||
'web': {
|
||||
'image': 'busybox',
|
||||
'extra_hosts': [
|
||||
{'somehost': '162.242.195.82'},
|
||||
{'otherhost': '50.31.209.229'}
|
||||
]
|
||||
}},
|
||||
]}}
|
||||
},
|
||||
'working_dir',
|
||||
'filename.yml'
|
||||
)
|
||||
@ -1658,6 +1688,8 @@ class ConfigTest(unittest.TestCase):
|
||||
with pytest.raises(ConfigurationError) as exc:
|
||||
config.load(build_config_details(
|
||||
{
|
||||
'version': str(VERSION),
|
||||
'services': {
|
||||
'web': {
|
||||
'image': 'busybox',
|
||||
'ulimits': {
|
||||
@ -1668,6 +1700,7 @@ class ConfigTest(unittest.TestCase):
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'working_dir',
|
||||
'filename.yml'))
|
||||
@ -1679,10 +1712,13 @@ class ConfigTest(unittest.TestCase):
|
||||
with pytest.raises(ConfigurationError) as exc:
|
||||
config.load(build_config_details(
|
||||
{
|
||||
'version': str(VERSION),
|
||||
'services': {
|
||||
'web': {
|
||||
'image': 'busybox',
|
||||
'ulimits': {'nofile': {"soft": 10000}}
|
||||
}
|
||||
}
|
||||
},
|
||||
'working_dir',
|
||||
'filename.yml'))
|
||||
@ -1695,12 +1731,15 @@ class ConfigTest(unittest.TestCase):
|
||||
with pytest.raises(ConfigurationError) as exc:
|
||||
config.load(build_config_details(
|
||||
{
|
||||
'version': str(VERSION),
|
||||
'services': {
|
||||
'web': {
|
||||
'image': 'busybox',
|
||||
'ulimits': {
|
||||
'nofile': {"soft": 10000, "hard": 1000}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'working_dir',
|
||||
'filename.yml'))
|
||||
@ -1711,10 +1750,12 @@ class ConfigTest(unittest.TestCase):
|
||||
for expose in expose_values:
|
||||
service = config.load(
|
||||
build_config_details(
|
||||
{'web': {
|
||||
{
|
||||
'version': str(VERSION),
|
||||
'services': {
|
||||
'web': {
|
||||
'image': 'busybox',
|
||||
'expose': expose
|
||||
}},
|
||||
'expose': expose}}},
|
||||
'working_dir',
|
||||
'filename.yml'
|
||||
)
|
||||
@ -1726,10 +1767,12 @@ class ConfigTest(unittest.TestCase):
|
||||
for entrypoint in entrypoint_values:
|
||||
service = config.load(
|
||||
build_config_details(
|
||||
{'web': {
|
||||
{
|
||||
'version': str(VERSION),
|
||||
'services': {
|
||||
'web': {
|
||||
'image': 'busybox',
|
||||
'entrypoint': entrypoint
|
||||
}},
|
||||
'entrypoint': entrypoint}}},
|
||||
'working_dir',
|
||||
'filename.yml'
|
||||
)
|
||||
@ -1738,10 +1781,13 @@ class ConfigTest(unittest.TestCase):
|
||||
|
||||
def test_logs_warning_for_boolean_in_environment(self):
|
||||
config_details = build_config_details({
|
||||
'version': str(VERSION),
|
||||
'services': {
|
||||
'web': {
|
||||
'image': 'busybox',
|
||||
'environment': {'SHOW_STUFF': True}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
with pytest.raises(ConfigurationError) as exc:
|
||||
@ -1752,10 +1798,12 @@ class ConfigTest(unittest.TestCase):
|
||||
def test_config_valid_environment_dict_key_contains_dashes(self):
|
||||
services = config.load(
|
||||
build_config_details(
|
||||
{'web': {
|
||||
{
|
||||
'version': str(VERSION),
|
||||
'services': {
|
||||
'web': {
|
||||
'image': 'busybox',
|
||||
'environment': {'SPRING_JPA_HIBERNATE_DDL-AUTO': 'none'}
|
||||
}},
|
||||
'environment': {'SPRING_JPA_HIBERNATE_DDL-AUTO': 'none'}}}},
|
||||
'working_dir',
|
||||
'filename.yml'
|
||||
)
|
||||
@ -1794,16 +1842,21 @@ web:
|
||||
def test_validate_extra_hosts_invalid(self):
|
||||
with pytest.raises(ConfigurationError) as exc:
|
||||
config.load(build_config_details({
|
||||
'version': str(VERSION),
|
||||
'services': {
|
||||
'web': {
|
||||
'image': 'alpine',
|
||||
'extra_hosts': "www.example.com: 192.168.0.17",
|
||||
}
|
||||
}
|
||||
}))
|
||||
assert "web.extra_hosts contains an invalid type" in exc.exconly()
|
||||
|
||||
def test_validate_extra_hosts_invalid_list(self):
|
||||
with pytest.raises(ConfigurationError) as exc:
|
||||
config.load(build_config_details({
|
||||
'version': str(VERSION),
|
||||
'services': {
|
||||
'web': {
|
||||
'image': 'alpine',
|
||||
'extra_hosts': [
|
||||
@ -1811,16 +1864,20 @@ web:
|
||||
{'api.example.com': '192.168.0.18'}
|
||||
],
|
||||
}
|
||||
}
|
||||
}))
|
||||
assert "which is an invalid type" in exc.exconly()
|
||||
|
||||
def test_normalize_dns_options(self):
|
||||
actual = config.load(build_config_details({
|
||||
'version': str(VERSION),
|
||||
'services': {
|
||||
'web': {
|
||||
'image': 'alpine',
|
||||
'dns': '8.8.8.8',
|
||||
'dns_search': 'domain.local',
|
||||
}
|
||||
}
|
||||
}))
|
||||
assert actual.services == [
|
||||
{
|
||||
@ -1947,7 +2004,6 @@ web:
|
||||
|
||||
def test_isolation_option(self):
|
||||
actual = config.load(build_config_details({
|
||||
'version': str(V2_1),
|
||||
'services': {
|
||||
'web': {
|
||||
'image': 'win10',
|
||||
@ -1966,7 +2022,6 @@ web:
|
||||
|
||||
def test_runtime_option(self):
|
||||
actual = config.load(build_config_details({
|
||||
'version': str(V2_3),
|
||||
'services': {
|
||||
'web': {
|
||||
'image': 'nvidia/cuda',
|
||||
@ -2088,7 +2143,7 @@ web:
|
||||
}
|
||||
|
||||
actual = config.merge_service_dicts_from_files(
|
||||
base, override, V3_2
|
||||
base, override, VERSION
|
||||
)
|
||||
|
||||
assert actual['volumes'] == [
|
||||
@ -2135,7 +2190,7 @@ web:
|
||||
}
|
||||
}
|
||||
|
||||
actual = config.merge_service_dicts(base, override, V2_0)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual == {
|
||||
'image': 'alpine:edge',
|
||||
'logging': {
|
||||
@ -2169,7 +2224,7 @@ web:
|
||||
}
|
||||
}
|
||||
|
||||
actual = config.merge_service_dicts(base, override, V2_0)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual == {
|
||||
'image': 'alpine:edge',
|
||||
'logging': {
|
||||
@ -2201,7 +2256,7 @@ web:
|
||||
}
|
||||
}
|
||||
|
||||
actual = config.merge_service_dicts(base, override, V2_0)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual == {
|
||||
'image': 'alpine:edge',
|
||||
'logging': {
|
||||
@ -2233,7 +2288,7 @@ web:
|
||||
}
|
||||
}
|
||||
|
||||
actual = config.merge_service_dicts(base, override, V2_0)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual == {
|
||||
'image': 'alpine:edge',
|
||||
'logging': {
|
||||
@ -2262,7 +2317,7 @@ web:
|
||||
}
|
||||
}
|
||||
|
||||
actual = config.merge_service_dicts(base, override, V2_0)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual == {
|
||||
'image': 'alpine:edge',
|
||||
'logging': {
|
||||
@ -2282,7 +2337,7 @@ web:
|
||||
}
|
||||
}
|
||||
}
|
||||
actual = config.merge_service_dicts(base, override, V2_0)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual == {
|
||||
'image': 'alpine:edge',
|
||||
'logging': {
|
||||
@ -2304,7 +2359,7 @@ web:
|
||||
}
|
||||
}
|
||||
override = {}
|
||||
actual = config.merge_service_dicts(base, override, V2_0)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual == {
|
||||
'image': 'alpine:edge',
|
||||
'logging': {
|
||||
@ -2332,7 +2387,7 @@ web:
|
||||
'ports': ['1245:1245/udp']
|
||||
}
|
||||
|
||||
actual = config.merge_service_dicts(base, override, V3_1)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual == {
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
'command': 'top',
|
||||
@ -2348,7 +2403,7 @@ web:
|
||||
}
|
||||
}
|
||||
override = {}
|
||||
actual = config.merge_service_dicts(base, override, V2_1)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual == base
|
||||
|
||||
def test_merge_depends_on_mixed_syntax(self):
|
||||
@ -2363,7 +2418,7 @@ web:
|
||||
'depends_on': ['app3']
|
||||
}
|
||||
|
||||
actual = config.merge_service_dicts(base, override, V2_1)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual == {
|
||||
'image': 'busybox',
|
||||
'depends_on': {
|
||||
@ -2401,7 +2456,7 @@ web:
|
||||
'labels': {'com.docker.compose.test': 'yes'}
|
||||
}
|
||||
|
||||
actual = config.merge_service_dicts(base, override, V2_0)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual == {
|
||||
'image': 'busybox',
|
||||
'pid': 'host',
|
||||
@ -2417,7 +2472,7 @@ web:
|
||||
}
|
||||
override = {'secrets': ['other-src.txt']}
|
||||
|
||||
actual = config.merge_service_dicts(base, override, V3_1)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert secret_sort(actual['secrets']) == secret_sort([
|
||||
{'source': 'src.txt'},
|
||||
{'source': 'other-src.txt'}
|
||||
@ -2437,7 +2492,7 @@ web:
|
||||
}
|
||||
]
|
||||
}
|
||||
actual = config.merge_service_dicts(base, override, V3_1)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual['secrets'] == override['secrets']
|
||||
|
||||
def test_merge_different_configs(self):
|
||||
@ -2449,7 +2504,7 @@ web:
|
||||
}
|
||||
override = {'configs': ['other-src.txt']}
|
||||
|
||||
actual = config.merge_service_dicts(base, override, V3_3)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert secret_sort(actual['configs']) == secret_sort([
|
||||
{'source': 'src.txt'},
|
||||
{'source': 'other-src.txt'}
|
||||
@ -2469,7 +2524,7 @@ web:
|
||||
}
|
||||
]
|
||||
}
|
||||
actual = config.merge_service_dicts(base, override, V3_3)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual['configs'] == override['configs']
|
||||
|
||||
def test_merge_deploy(self):
|
||||
@ -2484,7 +2539,7 @@ web:
|
||||
}
|
||||
}
|
||||
}
|
||||
actual = config.merge_service_dicts(base, override, V3_0)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual['deploy'] == override['deploy']
|
||||
|
||||
def test_merge_deploy_override(self):
|
||||
@ -2540,7 +2595,7 @@ web:
|
||||
'update_config': {'max_failure_ratio': 0.712, 'parallelism': 4}
|
||||
}
|
||||
}
|
||||
actual = config.merge_service_dicts(base, override, V3_5)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual['deploy'] == {
|
||||
'mode': 'replicated',
|
||||
'endpoint_mode': 'vip',
|
||||
@ -2596,7 +2651,7 @@ web:
|
||||
}
|
||||
}
|
||||
|
||||
actual = config.merge_service_dicts(base, override, V3_3)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual['credential_spec'] == override['credential_spec']
|
||||
|
||||
def test_merge_scale(self):
|
||||
@ -2609,7 +2664,7 @@ web:
|
||||
'scale': 4,
|
||||
}
|
||||
|
||||
actual = config.merge_service_dicts(base, override, V2_2)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual == {'image': 'bar', 'scale': 4}
|
||||
|
||||
def test_merge_blkio_config(self):
|
||||
@ -2644,7 +2699,7 @@ web:
|
||||
}
|
||||
}
|
||||
|
||||
actual = config.merge_service_dicts(base, override, V2_2)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual == {
|
||||
'image': 'bar',
|
||||
'blkio_config': {
|
||||
@ -2671,7 +2726,7 @@ web:
|
||||
'extra_hosts': ['bar:5.6.7.8', 'foo:127.0.0.1']
|
||||
}
|
||||
|
||||
actual = config.merge_service_dicts(base, override, V2_0)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual['extra_hosts'] == {
|
||||
'foo': '127.0.0.1',
|
||||
'bar': '5.6.7.8',
|
||||
@ -2695,7 +2750,7 @@ web:
|
||||
}
|
||||
}
|
||||
|
||||
actual = config.merge_service_dicts(base, override, V2_3)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual['healthcheck'] == {
|
||||
'start_period': base['healthcheck']['start_period'],
|
||||
'test': override['healthcheck']['test'],
|
||||
@ -2721,7 +2776,7 @@ web:
|
||||
}
|
||||
}
|
||||
|
||||
actual = config.merge_service_dicts(base, override, V2_3)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual['healthcheck'] == {'disabled': True}
|
||||
|
||||
def test_merge_healthcheck_override_enables(self):
|
||||
@ -2743,7 +2798,7 @@ web:
|
||||
}
|
||||
}
|
||||
|
||||
actual = config.merge_service_dicts(base, override, V2_3)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual['healthcheck'] == override['healthcheck']
|
||||
|
||||
def test_merge_device_cgroup_rules(self):
|
||||
@ -2756,7 +2811,7 @@ web:
|
||||
'device_cgroup_rules': ['c 7:128 rwm', 'f 0:128 n']
|
||||
}
|
||||
|
||||
actual = config.merge_service_dicts(base, override, V2_3)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert sorted(actual['device_cgroup_rules']) == sorted(
|
||||
['c 7:128 rwm', 'x 3:244 rw', 'f 0:128 n']
|
||||
)
|
||||
@ -2771,7 +2826,7 @@ web:
|
||||
'isolation': 'hyperv',
|
||||
}
|
||||
|
||||
actual = config.merge_service_dicts(base, override, V2_3)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual == {
|
||||
'image': 'bar',
|
||||
'isolation': 'hyperv',
|
||||
@ -2793,7 +2848,7 @@ web:
|
||||
}
|
||||
}
|
||||
|
||||
actual = config.merge_service_dicts(base, override, V2_3)
|
||||
actual = config.merge_service_dicts(base, override, VERSION)
|
||||
assert actual['storage_opt'] == {
|
||||
'size': '2G',
|
||||
'readonly': 'false',
|
||||
@ -3350,6 +3405,7 @@ class PortsTest(unittest.TestCase):
|
||||
|
||||
assert "non-unique" in exc.value.msg
|
||||
|
||||
@pytest.mark.skip(reason="Validator is one_off (generic error)")
|
||||
def test_config_invalid_ports_format_validation(self):
|
||||
for invalid_ports in self.INVALID_PORT_MAPPINGS:
|
||||
with pytest.raises(ConfigurationError) as exc:
|
||||
@ -3599,6 +3655,7 @@ class InterpolationTest(unittest.TestCase):
|
||||
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',
|
||||
@ -3637,6 +3694,7 @@ class InterpolationTest(unittest.TestCase):
|
||||
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',
|
||||
@ -4369,7 +4427,8 @@ class EnvTest(unittest.TestCase):
|
||||
|
||||
service_dict = config.load(
|
||||
build_config_details(
|
||||
{'foo': {'build': '.', 'volumes': ['$HOSTENV:$CONTAINERENV']}},
|
||||
{'services': {
|
||||
'foo': {'build': '.', 'volumes': ['$HOSTENV:$CONTAINERENV']}}},
|
||||
"tests/fixtures/env",
|
||||
)
|
||||
).services[0]
|
||||
@ -4377,7 +4436,8 @@ class EnvTest(unittest.TestCase):
|
||||
|
||||
service_dict = config.load(
|
||||
build_config_details(
|
||||
{'foo': {'build': '.', 'volumes': ['/opt${HOSTENV}:/opt${CONTAINERENV}']}},
|
||||
{'services': {
|
||||
'foo': {'build': '.', 'volumes': ['/opt${HOSTENV}:/opt${CONTAINERENV}']}}},
|
||||
"tests/fixtures/env",
|
||||
)
|
||||
).services[0]
|
||||
@ -4497,8 +4557,12 @@ class ExtendsTest(unittest.TestCase):
|
||||
with pytest.raises(ConfigurationError) as excinfo:
|
||||
config.load(
|
||||
build_config_details(
|
||||
{
|
||||
'version': '3',
|
||||
'services':
|
||||
{
|
||||
'web': {'image': 'busybox', 'extends': {}},
|
||||
}
|
||||
},
|
||||
'tests/fixtures/extends',
|
||||
'filename.yml'
|
||||
@ -4512,7 +4576,14 @@ class ExtendsTest(unittest.TestCase):
|
||||
config.load(
|
||||
build_config_details(
|
||||
{
|
||||
'web': {'image': 'busybox', 'extends': {'file': 'common.yml'}},
|
||||
'version': '3',
|
||||
'services':
|
||||
{
|
||||
'web': {
|
||||
'image': 'busybox',
|
||||
'extends': {'file': 'common.yml'}
|
||||
}
|
||||
}
|
||||
},
|
||||
'tests/fixtures/extends',
|
||||
'filename.yml'
|
||||
@ -4525,6 +4596,9 @@ class ExtendsTest(unittest.TestCase):
|
||||
with pytest.raises(ConfigurationError) as excinfo:
|
||||
config.load(
|
||||
build_config_details(
|
||||
{
|
||||
'version': '3',
|
||||
'services':
|
||||
{
|
||||
'web': {
|
||||
'image': 'busybox',
|
||||
@ -4534,6 +4608,7 @@ class ExtendsTest(unittest.TestCase):
|
||||
'rogue_key': 'is not allowed'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
'tests/fixtures/extends',
|
||||
'filename.yml'
|
||||
@ -4548,12 +4623,15 @@ class ExtendsTest(unittest.TestCase):
|
||||
config.load(
|
||||
build_config_details(
|
||||
{
|
||||
'version': '3',
|
||||
'services': {
|
||||
'web': {
|
||||
'image': 'busybox',
|
||||
'extends': {
|
||||
'file': 1,
|
||||
'service': 'web',
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
'tests/fixtures/extends',
|
||||
@ -5205,7 +5283,7 @@ class SerializeTest(unittest.TestCase):
|
||||
}
|
||||
}
|
||||
|
||||
assert denormalize_service_dict(service_dict, V3_0) == {
|
||||
assert denormalize_service_dict(service_dict, VERSION) == {
|
||||
'image': 'busybox',
|
||||
'command': 'true',
|
||||
'depends_on': ['service2', 'service3']
|
||||
@ -5221,7 +5299,11 @@ class SerializeTest(unittest.TestCase):
|
||||
}
|
||||
}
|
||||
|
||||
assert denormalize_service_dict(service_dict, V2_1) == service_dict
|
||||
assert denormalize_service_dict(service_dict, VERSION) == {
|
||||
'image': 'busybox',
|
||||
'command': 'true',
|
||||
'depends_on': ['service2', 'service3']
|
||||
}
|
||||
|
||||
def test_serialize_time(self):
|
||||
data = {
|
||||
@ -5255,7 +5337,7 @@ class SerializeTest(unittest.TestCase):
|
||||
processed_service = config.process_service(config.ServiceConfig(
|
||||
'.', 'test', 'test', service_dict
|
||||
))
|
||||
denormalized_service = denormalize_service_dict(processed_service, V2_3)
|
||||
denormalized_service = denormalize_service_dict(processed_service, VERSION)
|
||||
assert denormalized_service['healthcheck']['interval'] == '100s'
|
||||
assert denormalized_service['healthcheck']['timeout'] == '30s'
|
||||
assert denormalized_service['healthcheck']['start_period'] == '2090ms'
|
||||
@ -5266,7 +5348,7 @@ class SerializeTest(unittest.TestCase):
|
||||
}
|
||||
image_digest = 'busybox@sha256:abcde'
|
||||
|
||||
assert denormalize_service_dict(service_dict, V3_0, image_digest) == {
|
||||
assert denormalize_service_dict(service_dict, VERSION, image_digest) == {
|
||||
'image': 'busybox@sha256:abcde'
|
||||
}
|
||||
|
||||
@ -5275,7 +5357,7 @@ class SerializeTest(unittest.TestCase):
|
||||
'image': 'busybox'
|
||||
}
|
||||
|
||||
assert denormalize_service_dict(service_dict, V3_0) == {
|
||||
assert denormalize_service_dict(service_dict, VERSION) == {
|
||||
'image': 'busybox'
|
||||
}
|
||||
|
||||
@ -5308,10 +5390,10 @@ class SerializeTest(unittest.TestCase):
|
||||
serialized_service = serialized_config['services']['web']
|
||||
assert secret_sort(serialized_service['secrets']) == secret_sort(service_dict['secrets'])
|
||||
assert 'secrets' in serialized_config
|
||||
assert serialized_config['secrets']['two'] == secrets_dict['two']
|
||||
assert serialized_config['secrets']['two'] == {'external': True, 'name': 'two'}
|
||||
|
||||
def test_serialize_ports(self):
|
||||
config_dict = config.Config(version=V2_0, services=[
|
||||
config_dict = config.Config(version=VERSION, services=[
|
||||
{
|
||||
'ports': [types.ServicePort('80', '8080', None, None, None)],
|
||||
'image': 'alpine',
|
||||
@ -5320,10 +5402,10 @@ class SerializeTest(unittest.TestCase):
|
||||
], volumes={}, networks={}, secrets={}, configs={})
|
||||
|
||||
serialized_config = yaml.safe_load(serialize_config(config_dict))
|
||||
assert '8080:80/tcp' in serialized_config['services']['web']['ports']
|
||||
assert [{'published': 8080, 'target': 80}] == serialized_config['services']['web']['ports']
|
||||
|
||||
def test_serialize_ports_with_ext_ip(self):
|
||||
config_dict = config.Config(version=V3_5, services=[
|
||||
config_dict = config.Config(version=VERSION, services=[
|
||||
{
|
||||
'ports': [types.ServicePort('80', '8080', None, None, '127.0.0.1')],
|
||||
'image': 'alpine',
|
||||
@ -5363,7 +5445,7 @@ class SerializeTest(unittest.TestCase):
|
||||
serialized_service = serialized_config['services']['web']
|
||||
assert secret_sort(serialized_service['configs']) == secret_sort(service_dict['configs'])
|
||||
assert 'configs' in serialized_config
|
||||
assert serialized_config['configs']['two'] == configs_dict['two']
|
||||
assert serialized_config['configs']['two'] == {'external': True, 'name': 'two'}
|
||||
|
||||
def test_serialize_bool_string(self):
|
||||
cfg = {
|
||||
|
@ -8,9 +8,7 @@ from compose.config.interpolation import Interpolator
|
||||
from compose.config.interpolation import InvalidInterpolation
|
||||
from compose.config.interpolation import TemplateWithDefaults
|
||||
from compose.config.interpolation import UnsetRequiredSubstitution
|
||||
from compose.const import COMPOSEFILE_V2_0 as V2_0
|
||||
from compose.const import COMPOSEFILE_V2_3 as V2_3
|
||||
from compose.const import COMPOSEFILE_V3_4 as V3_4
|
||||
from compose.const import COMPOSE_SPEC as VERSION
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -63,7 +61,7 @@ def test_interpolate_environment_variables_in_services(mock_env):
|
||||
}
|
||||
}
|
||||
}
|
||||
value = interpolate_environment_variables(V2_0, services, 'service', mock_env)
|
||||
value = interpolate_environment_variables(VERSION, services, 'service', mock_env)
|
||||
assert value == expected
|
||||
|
||||
|
||||
@ -88,7 +86,7 @@ def test_interpolate_environment_variables_in_volumes(mock_env):
|
||||
},
|
||||
'other': {},
|
||||
}
|
||||
value = interpolate_environment_variables(V2_0, volumes, 'volume', mock_env)
|
||||
value = interpolate_environment_variables(VERSION, volumes, 'volume', mock_env)
|
||||
assert value == expected
|
||||
|
||||
|
||||
@ -113,7 +111,7 @@ def test_interpolate_environment_variables_in_secrets(mock_env):
|
||||
},
|
||||
'other': {},
|
||||
}
|
||||
value = interpolate_environment_variables(V3_4, secrets, 'secret', mock_env)
|
||||
value = interpolate_environment_variables(VERSION, secrets, 'secret', mock_env)
|
||||
assert value == expected
|
||||
|
||||
|
||||
@ -184,7 +182,7 @@ def test_interpolate_environment_services_convert_types_v2(mock_env):
|
||||
}
|
||||
}
|
||||
|
||||
value = interpolate_environment_variables(V2_3, entry, 'service', mock_env)
|
||||
value = interpolate_environment_variables(VERSION, entry, 'service', mock_env)
|
||||
assert value == expected
|
||||
|
||||
|
||||
@ -257,7 +255,7 @@ def test_interpolate_environment_services_convert_types_v3(mock_env):
|
||||
}
|
||||
}
|
||||
|
||||
value = interpolate_environment_variables(V3_4, entry, 'service', mock_env)
|
||||
value = interpolate_environment_variables(VERSION, entry, 'service', mock_env)
|
||||
assert value == expected
|
||||
|
||||
|
||||
@ -265,21 +263,21 @@ def test_interpolate_environment_services_convert_types_invalid(mock_env):
|
||||
entry = {'service1': {'privileged': '${POSINT}'}}
|
||||
|
||||
with pytest.raises(ConfigurationError) as exc:
|
||||
interpolate_environment_variables(V2_3, entry, 'service', mock_env)
|
||||
interpolate_environment_variables(VERSION, entry, 'service', mock_env)
|
||||
|
||||
assert 'Error while attempting to convert service.service1.privileged to '\
|
||||
'appropriate type: "50" is not a valid boolean value' in exc.exconly()
|
||||
|
||||
entry = {'service1': {'cpus': '${TRUE}'}}
|
||||
with pytest.raises(ConfigurationError) as exc:
|
||||
interpolate_environment_variables(V2_3, entry, 'service', mock_env)
|
||||
interpolate_environment_variables(VERSION, entry, 'service', mock_env)
|
||||
|
||||
assert 'Error while attempting to convert service.service1.cpus to '\
|
||||
'appropriate type: "True" is not a valid float' in exc.exconly()
|
||||
|
||||
entry = {'service1': {'ulimits': {'nproc': '${FLOAT}'}}}
|
||||
with pytest.raises(ConfigurationError) as exc:
|
||||
interpolate_environment_variables(V2_3, entry, 'service', mock_env)
|
||||
interpolate_environment_variables(VERSION, entry, 'service', mock_env)
|
||||
|
||||
assert 'Error while attempting to convert service.service1.ulimits.nproc to '\
|
||||
'appropriate type: "0.145" is not a valid integer' in exc.exconly()
|
||||
@ -302,7 +300,7 @@ def test_interpolate_environment_network_convert_types(mock_env):
|
||||
}
|
||||
}
|
||||
|
||||
value = interpolate_environment_variables(V3_4, entry, 'network', mock_env)
|
||||
value = interpolate_environment_variables(VERSION, entry, 'network', mock_env)
|
||||
assert value == expected
|
||||
|
||||
|
||||
@ -319,13 +317,13 @@ def test_interpolate_environment_external_resource_convert_types(mock_env):
|
||||
}
|
||||
}
|
||||
|
||||
value = interpolate_environment_variables(V3_4, entry, 'network', mock_env)
|
||||
value = interpolate_environment_variables(VERSION, entry, 'network', mock_env)
|
||||
assert value == expected
|
||||
value = interpolate_environment_variables(V3_4, entry, 'volume', mock_env)
|
||||
value = interpolate_environment_variables(VERSION, entry, 'volume', mock_env)
|
||||
assert value == expected
|
||||
value = interpolate_environment_variables(V3_4, entry, 'secret', mock_env)
|
||||
value = interpolate_environment_variables(VERSION, entry, 'secret', mock_env)
|
||||
assert value == expected
|
||||
value = interpolate_environment_variables(V3_4, entry, 'config', mock_env)
|
||||
value = interpolate_environment_variables(VERSION, entry, 'config', mock_env)
|
||||
assert value == expected
|
||||
|
||||
|
||||
@ -356,7 +354,7 @@ def test_interpolate_service_name_uses_dot(mock_env):
|
||||
}
|
||||
}
|
||||
|
||||
value = interpolate_environment_variables(V3_4, entry, 'service', mock_env)
|
||||
value = interpolate_environment_variables(VERSION, entry, 'service', mock_env)
|
||||
assert value == expected
|
||||
|
||||
|
||||
|
@ -5,8 +5,8 @@ from compose.config.types import parse_extra_hosts
|
||||
from compose.config.types import ServicePort
|
||||
from compose.config.types import VolumeFromSpec
|
||||
from compose.config.types import VolumeSpec
|
||||
from compose.const import COMPOSE_SPEC as VERSION
|
||||
from compose.const import COMPOSEFILE_V1 as V1
|
||||
from compose.const import COMPOSEFILE_V2_0 as V2_0
|
||||
|
||||
|
||||
def test_parse_extra_hosts_list():
|
||||
@ -233,26 +233,26 @@ class TestVolumesFromSpec(object):
|
||||
VolumeFromSpec.parse('unknown:format:ro', self.services, V1)
|
||||
|
||||
def test_parse_v2_from_service(self):
|
||||
volume_from = VolumeFromSpec.parse('servicea', self.services, V2_0)
|
||||
volume_from = VolumeFromSpec.parse('servicea', self.services, VERSION)
|
||||
assert volume_from == VolumeFromSpec('servicea', 'rw', 'service')
|
||||
|
||||
def test_parse_v2_from_service_with_mode(self):
|
||||
volume_from = VolumeFromSpec.parse('servicea:ro', self.services, V2_0)
|
||||
volume_from = VolumeFromSpec.parse('servicea:ro', self.services, VERSION)
|
||||
assert volume_from == VolumeFromSpec('servicea', 'ro', 'service')
|
||||
|
||||
def test_parse_v2_from_container(self):
|
||||
volume_from = VolumeFromSpec.parse('container:foo', self.services, V2_0)
|
||||
volume_from = VolumeFromSpec.parse('container:foo', self.services, VERSION)
|
||||
assert volume_from == VolumeFromSpec('foo', 'rw', 'container')
|
||||
|
||||
def test_parse_v2_from_container_with_mode(self):
|
||||
volume_from = VolumeFromSpec.parse('container:foo:ro', self.services, V2_0)
|
||||
volume_from = VolumeFromSpec.parse('container:foo:ro', self.services, VERSION)
|
||||
assert volume_from == VolumeFromSpec('foo', 'ro', 'container')
|
||||
|
||||
def test_parse_v2_invalid_type(self):
|
||||
with pytest.raises(ConfigurationError) as exc:
|
||||
VolumeFromSpec.parse('bogus:foo:ro', self.services, V2_0)
|
||||
VolumeFromSpec.parse('bogus:foo:ro', self.services, VERSION)
|
||||
assert "Unknown volumes_from type 'bogus'" in exc.exconly()
|
||||
|
||||
def test_parse_v2_invalid(self):
|
||||
with pytest.raises(ConfigurationError):
|
||||
VolumeFromSpec.parse('unknown:format:ro', self.services, V2_0)
|
||||
VolumeFromSpec.parse('unknown:format:ro', self.services, VERSION)
|
||||
|
@ -13,10 +13,8 @@ from ..helpers import BUSYBOX_IMAGE_WITH_TAG
|
||||
from compose.config import ConfigurationError
|
||||
from compose.config.config import Config
|
||||
from compose.config.types import VolumeFromSpec
|
||||
from compose.const import COMPOSE_SPEC as VERSION
|
||||
from compose.const import COMPOSEFILE_V1 as V1
|
||||
from compose.const import COMPOSEFILE_V2_0 as V2_0
|
||||
from compose.const import COMPOSEFILE_V2_4 as V2_4
|
||||
from compose.const import COMPOSEFILE_V3_7 as V3_7
|
||||
from compose.const import DEFAULT_TIMEOUT
|
||||
from compose.const import LABEL_SERVICE
|
||||
from compose.container import Container
|
||||
@ -29,6 +27,17 @@ from compose.service import ImageType
|
||||
from compose.service import Service
|
||||
|
||||
|
||||
def build_config(**kwargs):
|
||||
return Config(
|
||||
version=kwargs.get('version', VERSION),
|
||||
services=kwargs.get('services'),
|
||||
volumes=kwargs.get('volumes'),
|
||||
networks=kwargs.get('networks'),
|
||||
secrets=kwargs.get('secrets'),
|
||||
configs=kwargs.get('configs'),
|
||||
)
|
||||
|
||||
|
||||
class ProjectTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.mock_client = mock.create_autospec(docker.APIClient)
|
||||
@ -36,7 +45,7 @@ class ProjectTest(unittest.TestCase):
|
||||
self.mock_client.api_version = docker.constants.DEFAULT_DOCKER_API_VERSION
|
||||
|
||||
def test_from_config_v1(self):
|
||||
config = Config(
|
||||
config = build_config(
|
||||
version=V1,
|
||||
services=[
|
||||
{
|
||||
@ -67,8 +76,7 @@ class ProjectTest(unittest.TestCase):
|
||||
|
||||
@mock.patch('compose.network.Network.true_name', lambda n: n.full_name)
|
||||
def test_from_config_v2(self):
|
||||
config = Config(
|
||||
version=V2_0,
|
||||
config = build_config(
|
||||
services=[
|
||||
{
|
||||
'name': 'web',
|
||||
@ -174,8 +182,7 @@ class ProjectTest(unittest.TestCase):
|
||||
project = Project.from_config(
|
||||
name='test',
|
||||
client=self.mock_client,
|
||||
config_data=Config(
|
||||
version=V2_0,
|
||||
config_data=build_config(
|
||||
services=[{
|
||||
'name': 'test',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -202,8 +209,7 @@ class ProjectTest(unittest.TestCase):
|
||||
project = Project.from_config(
|
||||
name='test',
|
||||
client=self.mock_client,
|
||||
config_data=Config(
|
||||
version=V2_0,
|
||||
config_data=build_config(
|
||||
services=[
|
||||
{
|
||||
'name': 'vol',
|
||||
@ -230,8 +236,7 @@ class ProjectTest(unittest.TestCase):
|
||||
project = Project.from_config(
|
||||
name='test',
|
||||
client=None,
|
||||
config_data=Config(
|
||||
version=V2_0,
|
||||
config_data=build_config(
|
||||
services=[
|
||||
{
|
||||
'name': 'vol',
|
||||
@ -540,7 +545,7 @@ class ProjectTest(unittest.TestCase):
|
||||
project = Project.from_config(
|
||||
name='test',
|
||||
client=self.mock_client,
|
||||
config_data=Config(
|
||||
config_data=build_config(
|
||||
version=V1,
|
||||
services=[
|
||||
{
|
||||
@ -565,8 +570,7 @@ class ProjectTest(unittest.TestCase):
|
||||
project = Project.from_config(
|
||||
name='test',
|
||||
client=self.mock_client,
|
||||
config_data=Config(
|
||||
version=V2_0,
|
||||
config_data=build_config(
|
||||
services=[
|
||||
{
|
||||
'name': 'test',
|
||||
@ -596,8 +600,7 @@ class ProjectTest(unittest.TestCase):
|
||||
project = Project.from_config(
|
||||
name='test',
|
||||
client=self.mock_client,
|
||||
config_data=Config(
|
||||
version=V2_0,
|
||||
config_data=build_config(
|
||||
services=[
|
||||
{
|
||||
'name': 'aaa',
|
||||
@ -623,8 +626,7 @@ class ProjectTest(unittest.TestCase):
|
||||
project = Project.from_config(
|
||||
name='test',
|
||||
client=self.mock_client,
|
||||
config_data=Config(
|
||||
version=V2_0,
|
||||
config_data=build_config(
|
||||
services=[
|
||||
{
|
||||
'name': 'foo',
|
||||
@ -644,8 +646,7 @@ class ProjectTest(unittest.TestCase):
|
||||
project = Project.from_config(
|
||||
name='test',
|
||||
client=self.mock_client,
|
||||
config_data=Config(
|
||||
version=V2_0,
|
||||
config_data=build_config(
|
||||
services=[
|
||||
{
|
||||
'name': 'foo',
|
||||
@ -679,8 +680,7 @@ class ProjectTest(unittest.TestCase):
|
||||
project = Project.from_config(
|
||||
name='test',
|
||||
client=self.mock_client,
|
||||
config_data=Config(
|
||||
version=V2_0,
|
||||
config_data=build_config(
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -697,8 +697,7 @@ class ProjectTest(unittest.TestCase):
|
||||
project = Project.from_config(
|
||||
name='test',
|
||||
client=self.mock_client,
|
||||
config_data=Config(
|
||||
version=V2_0,
|
||||
config_data=build_config(
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
@ -748,8 +747,8 @@ class ProjectTest(unittest.TestCase):
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
}
|
||||
config_data = Config(
|
||||
version=V2_4, services=[service_config], networks={}, volumes={}, secrets=None, configs=None
|
||||
config_data = build_config(
|
||||
services=[service_config], networks={}, volumes={}, secrets=None, configs=None
|
||||
)
|
||||
|
||||
project = Project.from_config(name='test', client=self.mock_client, config_data=config_data)
|
||||
@ -770,8 +769,7 @@ class ProjectTest(unittest.TestCase):
|
||||
assert project.get_service('web').platform == 'linux/s390x'
|
||||
|
||||
def test_build_container_operation_with_timeout_func_does_not_mutate_options_with_timeout(self):
|
||||
config_data = Config(
|
||||
version=V3_7,
|
||||
config_data = build_config(
|
||||
services=[
|
||||
{'name': 'web', 'image': BUSYBOX_IMAGE_WITH_TAG},
|
||||
{'name': 'db', 'image': BUSYBOX_IMAGE_WITH_TAG, 'stop_grace_period': '1s'},
|
||||
@ -802,8 +800,7 @@ class ProjectTest(unittest.TestCase):
|
||||
project = Project.from_config(
|
||||
name='test',
|
||||
client=self.mock_client,
|
||||
config_data=Config(
|
||||
version=V2_0,
|
||||
config_data=build_config(
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': BUSYBOX_IMAGE_WITH_TAG,
|
||||
|
Loading…
x
Reference in New Issue
Block a user