mirror of
https://github.com/docker/compose.git
synced 2025-07-31 01:24:15 +02:00
Merge pull request #2626 from shin-/dbonev-2503-move-logging-config-under-separate-key
Move logging config under separate key in v2 compose files
This commit is contained in:
commit
52e50a9d9a
@ -51,8 +51,6 @@ DOCKER_CONFIG_KEYS = [
|
|||||||
'ipc',
|
'ipc',
|
||||||
'labels',
|
'labels',
|
||||||
'links',
|
'links',
|
||||||
'log_driver',
|
|
||||||
'log_opt',
|
|
||||||
'mac_address',
|
'mac_address',
|
||||||
'mem_limit',
|
'mem_limit',
|
||||||
'memswap_limit',
|
'memswap_limit',
|
||||||
@ -78,6 +76,7 @@ ALLOWED_KEYS = DOCKER_CONFIG_KEYS + [
|
|||||||
'dockerfile',
|
'dockerfile',
|
||||||
'expose',
|
'expose',
|
||||||
'external_links',
|
'external_links',
|
||||||
|
'logging',
|
||||||
]
|
]
|
||||||
|
|
||||||
DOCKER_VALID_URL_PREFIXES = (
|
DOCKER_VALID_URL_PREFIXES = (
|
||||||
@ -288,7 +287,7 @@ def load_services(working_dir, config_files, version):
|
|||||||
service_dict = process_service(resolver.run())
|
service_dict = process_service(resolver.run())
|
||||||
|
|
||||||
# TODO: move to validate_service()
|
# TODO: move to validate_service()
|
||||||
validate_against_service_schema(service_dict, service_config.name)
|
validate_against_service_schema(service_dict, service_config.name, version)
|
||||||
validate_paths(service_dict)
|
validate_paths(service_dict)
|
||||||
|
|
||||||
service_dict = finalize_service(service_config._replace(config=service_dict))
|
service_dict = finalize_service(service_config._replace(config=service_dict))
|
||||||
@ -505,6 +504,20 @@ def finalize_service(service_config):
|
|||||||
if 'restart' in service_dict:
|
if 'restart' in service_dict:
|
||||||
service_dict['restart'] = parse_restart_spec(service_dict['restart'])
|
service_dict['restart'] = parse_restart_spec(service_dict['restart'])
|
||||||
|
|
||||||
|
return normalize_v1_service_format(service_dict)
|
||||||
|
|
||||||
|
|
||||||
|
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:
|
||||||
|
service_dict['logging'] = {}
|
||||||
|
if 'log_driver' in service_dict:
|
||||||
|
service_dict['logging']['driver'] = service_dict['log_driver']
|
||||||
|
del service_dict['log_driver']
|
||||||
|
if 'log_opt' in service_dict:
|
||||||
|
service_dict['logging']['options'] = service_dict['log_opt']
|
||||||
|
del service_dict['log_opt']
|
||||||
|
|
||||||
return service_dict
|
return service_dict
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,158 +6,8 @@
|
|||||||
|
|
||||||
"patternProperties": {
|
"patternProperties": {
|
||||||
"^[a-zA-Z0-9._-]+$": {
|
"^[a-zA-Z0-9._-]+$": {
|
||||||
"$ref": "#/definitions/service"
|
"$ref": "service_schema_v1.json#/definitions/service"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false
|
||||||
|
|
||||||
"definitions": {
|
|
||||||
"service": {
|
|
||||||
"id": "#/definitions/service",
|
|
||||||
"type": "object",
|
|
||||||
|
|
||||||
"properties": {
|
|
||||||
"build": {"type": "string"},
|
|
||||||
"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"},
|
|
||||||
"devices": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
|
||||||
"dns": {"$ref": "#/definitions/string_or_list"},
|
|
||||||
"dns_search": {"$ref": "#/definitions/string_or_list"},
|
|
||||||
"dockerfile": {"type": "string"},
|
|
||||||
"domainname": {"type": "string"},
|
|
||||||
"entrypoint": {"$ref": "#/definitions/string_or_list"},
|
|
||||||
"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
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
|
||||||
"external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
|
||||||
"hostname": {"type": "string"},
|
|
||||||
"image": {"type": "string"},
|
|
||||||
"ipc": {"type": "string"},
|
|
||||||
"labels": {"$ref": "#/definitions/list_or_dict"},
|
|
||||||
"links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
|
||||||
|
|
||||||
"log_driver": {"type": "string"},
|
|
||||||
"log_opt": {"type": "object"},
|
|
||||||
|
|
||||||
"mac_address": {"type": "string"},
|
|
||||||
"mem_limit": {"type": ["number", "string"]},
|
|
||||||
"memswap_limit": {"type": ["number", "string"]},
|
|
||||||
"net": {"type": "string"},
|
|
||||||
"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},
|
|
||||||
"stdin_open": {"type": "boolean"},
|
|
||||||
"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
|
|
||||||
},
|
|
||||||
|
|
||||||
"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", "boolean", "null"],
|
|
||||||
"format": "bool-value-in-mapping"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"patternProperties": {
|
"patternProperties": {
|
||||||
"^[a-zA-Z0-9._-]+$": {
|
"^[a-zA-Z0-9._-]+$": {
|
||||||
"$ref": "fields_schema_v1.json#/definitions/service"
|
"$ref": "service_schema_v2.json#/definitions/service"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
|
||||||
"id": "service_schema.json",
|
|
||||||
|
|
||||||
"type": "object",
|
|
||||||
|
|
||||||
"allOf": [
|
|
||||||
{"$ref": "fields_schema_v1.json#/definitions/service"},
|
|
||||||
{"$ref": "#/definitions/constraints"}
|
|
||||||
],
|
|
||||||
|
|
||||||
"definitions": {
|
|
||||||
"constraints": {
|
|
||||||
"id": "#/definitions/constraints",
|
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"required": ["build"],
|
|
||||||
"not": {"required": ["image"]}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"required": ["image"],
|
|
||||||
"not": {"anyOf": [
|
|
||||||
{"required": ["build"]},
|
|
||||||
{"required": ["dockerfile"]}
|
|
||||||
]}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
175
compose/config/service_schema_v1.json
Normal file
175
compose/config/service_schema_v1.json
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
"id": "service_schema_v1.json",
|
||||||
|
|
||||||
|
"type": "object",
|
||||||
|
|
||||||
|
"allOf": [
|
||||||
|
{"$ref": "#/definitions/service"},
|
||||||
|
{"$ref": "#/definitions/constraints"}
|
||||||
|
],
|
||||||
|
|
||||||
|
"definitions": {
|
||||||
|
"service": {
|
||||||
|
"id": "#/definitions/service",
|
||||||
|
"type": "object",
|
||||||
|
|
||||||
|
"properties": {
|
||||||
|
"build": {"type": "string"},
|
||||||
|
"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"},
|
||||||
|
"devices": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||||
|
"dns": {"$ref": "#/definitions/string_or_list"},
|
||||||
|
"dns_search": {"$ref": "#/definitions/string_or_list"},
|
||||||
|
"dockerfile": {"type": "string"},
|
||||||
|
"domainname": {"type": "string"},
|
||||||
|
"entrypoint": {"$ref": "#/definitions/string_or_list"},
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
||||||
|
"external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||||
|
"hostname": {"type": "string"},
|
||||||
|
"image": {"type": "string"},
|
||||||
|
"ipc": {"type": "string"},
|
||||||
|
"labels": {"$ref": "#/definitions/list_or_dict"},
|
||||||
|
"links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||||
|
"log_driver": {"type": "string"},
|
||||||
|
"log_opt": {"type": "object"},
|
||||||
|
"mac_address": {"type": "string"},
|
||||||
|
"mem_limit": {"type": ["number", "string"]},
|
||||||
|
"memswap_limit": {"type": ["number", "string"]},
|
||||||
|
"net": {"type": "string"},
|
||||||
|
"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},
|
||||||
|
"stdin_open": {"type": "boolean"},
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
|
||||||
|
"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", "boolean", "null"],
|
||||||
|
"format": "bool-value-in-mapping"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"constraints": {
|
||||||
|
"id": "#/definitions/constraints",
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"required": ["build"],
|
||||||
|
"not": {"required": ["image"]}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": ["image"],
|
||||||
|
"not": {"anyOf": [
|
||||||
|
{"required": ["build"]},
|
||||||
|
{"required": ["dockerfile"]}
|
||||||
|
]}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
184
compose/config/service_schema_v2.json
Normal file
184
compose/config/service_schema_v2.json
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
"id": "service_schema_v2.json",
|
||||||
|
|
||||||
|
"type": "object",
|
||||||
|
|
||||||
|
"allOf": [
|
||||||
|
{"$ref": "#/definitions/service"},
|
||||||
|
{"$ref": "#/definitions/constraints"}
|
||||||
|
],
|
||||||
|
|
||||||
|
"definitions": {
|
||||||
|
"service": {
|
||||||
|
"id": "#/definitions/service",
|
||||||
|
"type": "object",
|
||||||
|
|
||||||
|
"properties": {
|
||||||
|
"build": {"type": "string"},
|
||||||
|
"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"},
|
||||||
|
"devices": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||||
|
"dns": {"$ref": "#/definitions/string_or_list"},
|
||||||
|
"dns_search": {"$ref": "#/definitions/string_or_list"},
|
||||||
|
"dockerfile": {"type": "string"},
|
||||||
|
"domainname": {"type": "string"},
|
||||||
|
"entrypoint": {"$ref": "#/definitions/string_or_list"},
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
||||||
|
"external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||||
|
"hostname": {"type": "string"},
|
||||||
|
"image": {"type": "string"},
|
||||||
|
"ipc": {"type": "string"},
|
||||||
|
"labels": {"$ref": "#/definitions/list_or_dict"},
|
||||||
|
"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"]},
|
||||||
|
"memswap_limit": {"type": ["number", "string"]},
|
||||||
|
"net": {"type": "string"},
|
||||||
|
"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},
|
||||||
|
"stdin_open": {"type": "boolean"},
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
|
||||||
|
"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", "boolean", "null"],
|
||||||
|
"format": "bool-value-in-mapping"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"constraints": {
|
||||||
|
"id": "#/definitions/constraints",
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"required": ["build"],
|
||||||
|
"not": {"required": ["image"]}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": ["image"],
|
||||||
|
"not": {"anyOf": [
|
||||||
|
{"required": ["build"]},
|
||||||
|
{"required": ["dockerfile"]}
|
||||||
|
]}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -298,10 +298,10 @@ def validate_against_fields_schema(config, filename, version):
|
|||||||
filename=filename)
|
filename=filename)
|
||||||
|
|
||||||
|
|
||||||
def validate_against_service_schema(config, service_name):
|
def validate_against_service_schema(config, service_name, version):
|
||||||
_validate_against_schema(
|
_validate_against_schema(
|
||||||
config,
|
config,
|
||||||
"service_schema.json",
|
"service_schema_v{0}.json".format(version),
|
||||||
format_checker=["ports"],
|
format_checker=["ports"],
|
||||||
service_name=service_name)
|
service_name=service_name)
|
||||||
|
|
||||||
|
@ -590,10 +590,9 @@ class Service(object):
|
|||||||
def _get_container_host_config(self, override_options, one_off=False):
|
def _get_container_host_config(self, override_options, one_off=False):
|
||||||
options = dict(self.options, **override_options)
|
options = dict(self.options, **override_options)
|
||||||
|
|
||||||
log_config = LogConfig(
|
logging_dict = options.get('logging', None)
|
||||||
type=options.get('log_driver', ""),
|
log_config = get_log_config(logging_dict)
|
||||||
config=options.get('log_opt', None)
|
|
||||||
)
|
|
||||||
return self.client.create_host_config(
|
return self.client.create_host_config(
|
||||||
links=self._get_links(link_to_self=one_off),
|
links=self._get_links(link_to_self=one_off),
|
||||||
port_bindings=build_port_bindings(options.get('ports') or []),
|
port_bindings=build_port_bindings(options.get('ports') or []),
|
||||||
@ -954,3 +953,12 @@ def build_ulimits(ulimit_config):
|
|||||||
ulimits.append(ulimit_dict)
|
ulimits.append(ulimit_dict)
|
||||||
|
|
||||||
return ulimits
|
return ulimits
|
||||||
|
|
||||||
|
|
||||||
|
def get_log_config(logging_dict):
|
||||||
|
log_driver = logging_dict.get('driver', "") if logging_dict else ""
|
||||||
|
log_options = logging_dict.get('options', None) if logging_dict else None
|
||||||
|
return LogConfig(
|
||||||
|
type=log_driver,
|
||||||
|
config=log_options
|
||||||
|
)
|
||||||
|
@ -28,8 +28,13 @@ exe = EXE(pyz,
|
|||||||
'DATA'
|
'DATA'
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
'compose/config/service_schema.json',
|
'compose/config/service_schema_v1.json',
|
||||||
'compose/config/service_schema.json',
|
'compose/config/service_schema_v1.json',
|
||||||
|
'DATA'
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'compose/config/service_schema_v2.json',
|
||||||
|
'compose/config/service_schema_v2.json',
|
||||||
'DATA'
|
'DATA'
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
@ -324,29 +324,37 @@ for this service, e.g:
|
|||||||
Environment variables will also be created - see the [environment variable
|
Environment variables will also be created - see the [environment variable
|
||||||
reference](env.md) for details.
|
reference](env.md) for details.
|
||||||
|
|
||||||
### log_driver
|
### logging
|
||||||
|
|
||||||
Specify a logging driver for the service's containers, as with the ``--log-driver``
|
Logging configuration for the service. This configuration replaces the previous
|
||||||
option for docker run ([documented here](https://docs.docker.com/engine/reference/logging/overview/)).
|
`log_driver` and `log_opt` keys.
|
||||||
|
|
||||||
|
logging:
|
||||||
|
driver: log_driver
|
||||||
|
options:
|
||||||
|
syslog-address: "tcp://192.168.0.42:123"
|
||||||
|
|
||||||
|
The `driver` name specifies a logging driver for the service's
|
||||||
|
containers, as with the ``--log-driver`` option for docker run
|
||||||
|
([documented here](https://docs.docker.com/engine/reference/logging/overview/)).
|
||||||
|
|
||||||
The default value is json-file.
|
The default value is json-file.
|
||||||
|
|
||||||
log_driver: "json-file"
|
driver: "json-file"
|
||||||
log_driver: "syslog"
|
driver: "syslog"
|
||||||
log_driver: "none"
|
driver: "none"
|
||||||
|
|
||||||
> **Note:** Only the `json-file` driver makes the logs available directly from
|
> **Note:** Only the `json-file` driver makes the logs available directly from
|
||||||
> `docker-compose up` and `docker-compose logs`. Using any other driver will not
|
> `docker-compose up` and `docker-compose logs`. Using any other driver will not
|
||||||
> print any logs.
|
> print any logs.
|
||||||
|
|
||||||
### log_opt
|
Specify logging options for the logging driver with the ``options`` key, as with the ``--log-opt`` option for `docker run`.
|
||||||
|
|
||||||
Specify logging options with `log_opt` for the logging driver, as with the ``--log-opt`` option for `docker run`.
|
|
||||||
|
|
||||||
Logging options are key value pairs. An example of `syslog` options:
|
Logging options are key value pairs. An example of `syslog` options:
|
||||||
|
|
||||||
log_driver: "syslog"
|
driver: "syslog"
|
||||||
log_opt:
|
options:
|
||||||
syslog-address: "tcp://192.168.0.42:123"
|
syslog-address: "tcp://192.168.0.42:123"
|
||||||
|
|
||||||
### net
|
### net
|
||||||
|
@ -718,6 +718,34 @@ class CLITestCase(DockerClientTestCase):
|
|||||||
result = self.dispatch(['start'], returncode=1)
|
result = self.dispatch(['start'], returncode=1)
|
||||||
assert 'No containers to start' in result.stderr
|
assert 'No containers to start' in result.stderr
|
||||||
|
|
||||||
|
def test_up_logging(self):
|
||||||
|
self.base_dir = 'tests/fixtures/logging-composefile'
|
||||||
|
self.dispatch(['up', '-d'])
|
||||||
|
simple = self.project.get_service('simple').containers()[0]
|
||||||
|
log_config = simple.get('HostConfig.LogConfig')
|
||||||
|
self.assertTrue(log_config)
|
||||||
|
self.assertEqual(log_config.get('Type'), 'none')
|
||||||
|
|
||||||
|
another = self.project.get_service('another').containers()[0]
|
||||||
|
log_config = another.get('HostConfig.LogConfig')
|
||||||
|
self.assertTrue(log_config)
|
||||||
|
self.assertEqual(log_config.get('Type'), 'json-file')
|
||||||
|
self.assertEqual(log_config.get('Config')['max-size'], '10m')
|
||||||
|
|
||||||
|
def test_up_logging_legacy(self):
|
||||||
|
self.base_dir = 'tests/fixtures/logging-composefile-legacy'
|
||||||
|
self.dispatch(['up', '-d'])
|
||||||
|
simple = self.project.get_service('simple').containers()[0]
|
||||||
|
log_config = simple.get('HostConfig.LogConfig')
|
||||||
|
self.assertTrue(log_config)
|
||||||
|
self.assertEqual(log_config.get('Type'), 'none')
|
||||||
|
|
||||||
|
another = self.project.get_service('another').containers()[0]
|
||||||
|
log_config = another.get('HostConfig.LogConfig')
|
||||||
|
self.assertTrue(log_config)
|
||||||
|
self.assertEqual(log_config.get('Type'), 'json-file')
|
||||||
|
self.assertEqual(log_config.get('Config')['max-size'], '10m')
|
||||||
|
|
||||||
def test_pause_unpause(self):
|
def test_pause_unpause(self):
|
||||||
self.dispatch(['up', '-d'], None)
|
self.dispatch(['up', '-d'], None)
|
||||||
service = self.project.get_service('simple')
|
service = self.project.get_service('simple')
|
||||||
|
10
tests/fixtures/logging-composefile-legacy/docker-compose.yml
vendored
Normal file
10
tests/fixtures/logging-composefile-legacy/docker-compose.yml
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
simple:
|
||||||
|
image: busybox:latest
|
||||||
|
command: top
|
||||||
|
log_driver: "none"
|
||||||
|
another:
|
||||||
|
image: busybox:latest
|
||||||
|
command: top
|
||||||
|
log_driver: "json-file"
|
||||||
|
log_opt:
|
||||||
|
max-size: "10m"
|
14
tests/fixtures/logging-composefile/docker-compose.yml
vendored
Normal file
14
tests/fixtures/logging-composefile/docker-compose.yml
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
version: 2
|
||||||
|
services:
|
||||||
|
simple:
|
||||||
|
image: busybox:latest
|
||||||
|
command: top
|
||||||
|
logging:
|
||||||
|
driver: "none"
|
||||||
|
another:
|
||||||
|
image: busybox:latest
|
||||||
|
command: top
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
@ -3,6 +3,8 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
import random
|
import random
|
||||||
|
|
||||||
|
import py
|
||||||
|
|
||||||
from .testcases import DockerClientTestCase
|
from .testcases import DockerClientTestCase
|
||||||
from compose.cli.docker_client import docker_client
|
from compose.cli.docker_client import docker_client
|
||||||
from compose.config import config
|
from compose.config import config
|
||||||
@ -534,6 +536,57 @@ class ProjectTest(DockerClientTestCase):
|
|||||||
self.assertEqual(volume_data['Name'], full_vol_name)
|
self.assertEqual(volume_data['Name'], full_vol_name)
|
||||||
self.assertEqual(volume_data['Driver'], 'local')
|
self.assertEqual(volume_data['Driver'], 'local')
|
||||||
|
|
||||||
|
def test_project_up_logging_with_multiple_files(self):
|
||||||
|
base_file = config.ConfigFile(
|
||||||
|
'base.yml',
|
||||||
|
{
|
||||||
|
'version': 2,
|
||||||
|
'services': {
|
||||||
|
'simple': {'image': 'busybox:latest', 'command': 'top'},
|
||||||
|
'another': {
|
||||||
|
'image': 'busybox:latest',
|
||||||
|
'command': 'top',
|
||||||
|
'logging': {
|
||||||
|
'driver': "json-file",
|
||||||
|
'options': {
|
||||||
|
'max-size': "10m"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
override_file = config.ConfigFile(
|
||||||
|
'override.yml',
|
||||||
|
{
|
||||||
|
'version': 2,
|
||||||
|
'services': {
|
||||||
|
'another': {
|
||||||
|
'logging': {
|
||||||
|
'driver': "none"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
details = config.ConfigDetails('.', [base_file, override_file])
|
||||||
|
|
||||||
|
tmpdir = py.test.ensuretemp('logging_test')
|
||||||
|
self.addCleanup(tmpdir.remove)
|
||||||
|
with tmpdir.as_cwd():
|
||||||
|
config_data = config.load(details)
|
||||||
|
project = Project.from_config(
|
||||||
|
name='composetest', config_data=config_data, client=self.client
|
||||||
|
)
|
||||||
|
project.up()
|
||||||
|
containers = project.containers()
|
||||||
|
self.assertEqual(len(containers), 2)
|
||||||
|
|
||||||
|
another = project.get_service('another').containers()[0]
|
||||||
|
log_config = another.get('HostConfig.LogConfig')
|
||||||
|
self.assertTrue(log_config)
|
||||||
|
self.assertEqual(log_config.get('Type'), 'none')
|
||||||
|
|
||||||
def test_initialize_volumes(self):
|
def test_initialize_volumes(self):
|
||||||
vol_name = '{0:x}'.format(random.getrandbits(32))
|
vol_name = '{0:x}'.format(random.getrandbits(32))
|
||||||
full_vol_name = 'composetest_{0}'.format(vol_name)
|
full_vol_name = 'composetest_{0}'.format(vol_name)
|
||||||
|
@ -888,7 +888,7 @@ class ServiceTest(DockerClientTestCase):
|
|||||||
self.assertNotEqual(one_off_container.name, 'my-web-container')
|
self.assertNotEqual(one_off_container.name, 'my-web-container')
|
||||||
|
|
||||||
def test_log_drive_invalid(self):
|
def test_log_drive_invalid(self):
|
||||||
service = self.create_service('web', log_driver='xxx')
|
service = self.create_service('web', logging={'driver': 'xxx'})
|
||||||
expected_error_msg = "logger: no log driver named 'xxx' is registered"
|
expected_error_msg = "logger: no log driver named 'xxx' is registered"
|
||||||
|
|
||||||
with self.assertRaisesRegexp(APIError, expected_error_msg):
|
with self.assertRaisesRegexp(APIError, expected_error_msg):
|
||||||
@ -902,7 +902,7 @@ class ServiceTest(DockerClientTestCase):
|
|||||||
self.assertFalse(log_config['Config'])
|
self.assertFalse(log_config['Config'])
|
||||||
|
|
||||||
def test_log_drive_none(self):
|
def test_log_drive_none(self):
|
||||||
service = self.create_service('web', log_driver='none')
|
service = self.create_service('web', logging={'driver': 'none'})
|
||||||
log_config = create_and_start_container(service).log_config
|
log_config = create_and_start_container(service).log_config
|
||||||
|
|
||||||
self.assertEqual('none', log_config['Type'])
|
self.assertEqual('none', log_config['Type'])
|
||||||
|
@ -156,7 +156,8 @@ class ServiceTest(unittest.TestCase):
|
|||||||
self.mock_client.create_host_config.return_value = {}
|
self.mock_client.create_host_config.return_value = {}
|
||||||
|
|
||||||
log_opt = {'syslog-address': 'tcp://192.168.0.42:123'}
|
log_opt = {'syslog-address': 'tcp://192.168.0.42:123'}
|
||||||
service = Service(name='foo', image='foo', hostname='name', client=self.mock_client, log_driver='syslog', log_opt=log_opt)
|
logging = {'driver': 'syslog', 'options': log_opt}
|
||||||
|
service = Service(name='foo', image='foo', hostname='name', client=self.mock_client, logging=logging)
|
||||||
service._get_container_create_options({'some': 'overrides'}, 1)
|
service._get_container_create_options({'some': 'overrides'}, 1)
|
||||||
|
|
||||||
self.assertTrue(self.mock_client.create_host_config.called)
|
self.assertTrue(self.mock_client.create_host_config.called)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user