mirror of https://github.com/docker/cli.git
Merge pull request #409 from alshabib/order
Support for rollback config in compose 3.7
This commit is contained in:
commit
5bc09ebf93
|
@ -162,6 +162,7 @@ func Service(
|
||||||
EndpointSpec: endpoint,
|
EndpointSpec: endpoint,
|
||||||
Mode: mode,
|
Mode: mode,
|
||||||
UpdateConfig: convertUpdateConfig(service.Deploy.UpdateConfig),
|
UpdateConfig: convertUpdateConfig(service.Deploy.UpdateConfig),
|
||||||
|
RollbackConfig: convertUpdateConfig(service.Deploy.RollbackConfig),
|
||||||
}
|
}
|
||||||
|
|
||||||
// add an image label to serviceSpec
|
// add an image label to serviceSpec
|
||||||
|
|
|
@ -550,3 +550,17 @@ func (c *fakeClient) ConfigList(ctx context.Context, options types.ConfigListOpt
|
||||||
}
|
}
|
||||||
return []swarm.Config{}, nil
|
return []swarm.Config{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConvertUpdateConfigParallelism(t *testing.T) {
|
||||||
|
parallel := uint64(4)
|
||||||
|
|
||||||
|
// test default behavior
|
||||||
|
updateConfig := convertUpdateConfig(&composetypes.UpdateConfig{})
|
||||||
|
assert.Check(t, is.Equal(uint64(1), updateConfig.Parallelism))
|
||||||
|
|
||||||
|
// Non default value
|
||||||
|
updateConfig = convertUpdateConfig(&composetypes.UpdateConfig{
|
||||||
|
Parallelism: ¶llel,
|
||||||
|
})
|
||||||
|
assert.Check(t, is.Equal(parallel, updateConfig.Parallelism))
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
version: "3.6"
|
version: "3.7"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
foo:
|
foo:
|
||||||
|
@ -39,6 +39,13 @@ services:
|
||||||
mode: replicated
|
mode: replicated
|
||||||
replicas: 6
|
replicas: 6
|
||||||
labels: [FOO=BAR]
|
labels: [FOO=BAR]
|
||||||
|
rollback_config:
|
||||||
|
parallelism: 3
|
||||||
|
delay: 10s
|
||||||
|
failure_action: continue
|
||||||
|
monitor: 60s
|
||||||
|
max_failure_ratio: 0.3
|
||||||
|
order: start-first
|
||||||
update_config:
|
update_config:
|
||||||
parallelism: 3
|
parallelism: 3
|
||||||
delay: 10s
|
delay: 10s
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
|
|
||||||
func fullExampleConfig(workingDir, homeDir string) *types.Config {
|
func fullExampleConfig(workingDir, homeDir string) *types.Config {
|
||||||
return &types.Config{
|
return &types.Config{
|
||||||
Version: "3.6",
|
Version: "3.7",
|
||||||
Services: services(workingDir, homeDir),
|
Services: services(workingDir, homeDir),
|
||||||
Networks: networks(),
|
Networks: networks(),
|
||||||
Volumes: volumes(),
|
Volumes: volumes(),
|
||||||
|
@ -41,6 +41,14 @@ func services(workingDir, homeDir string) []types.ServiceConfig {
|
||||||
Mode: "replicated",
|
Mode: "replicated",
|
||||||
Replicas: uint64Ptr(6),
|
Replicas: uint64Ptr(6),
|
||||||
Labels: map[string]string{"FOO": "BAR"},
|
Labels: map[string]string{"FOO": "BAR"},
|
||||||
|
RollbackConfig: &types.UpdateConfig{
|
||||||
|
Parallelism: uint64Ptr(3),
|
||||||
|
Delay: time.Duration(10 * time.Second),
|
||||||
|
FailureAction: "continue",
|
||||||
|
Monitor: time.Duration(60 * time.Second),
|
||||||
|
MaxFailureRatio: 0.3,
|
||||||
|
Order: "start-first",
|
||||||
|
},
|
||||||
UpdateConfig: &types.UpdateConfig{
|
UpdateConfig: &types.UpdateConfig{
|
||||||
Parallelism: uint64Ptr(3),
|
Parallelism: uint64Ptr(3),
|
||||||
Delay: time.Duration(10 * time.Second),
|
Delay: time.Duration(10 * time.Second),
|
||||||
|
@ -393,7 +401,7 @@ func volumes() map[string]types.VolumeConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
func fullExampleYAML(workingDir string) string {
|
func fullExampleYAML(workingDir string) string {
|
||||||
return fmt.Sprintf(`version: "3.6"
|
return fmt.Sprintf(`version: "3.7"
|
||||||
services:
|
services:
|
||||||
foo:
|
foo:
|
||||||
build:
|
build:
|
||||||
|
@ -436,6 +444,13 @@ services:
|
||||||
monitor: 1m0s
|
monitor: 1m0s
|
||||||
max_failure_ratio: 0.3
|
max_failure_ratio: 0.3
|
||||||
order: start-first
|
order: start-first
|
||||||
|
rollback_config:
|
||||||
|
parallelism: 3
|
||||||
|
delay: 10s
|
||||||
|
failure_action: continue
|
||||||
|
monitor: 1m0s
|
||||||
|
max_failure_ratio: 0.3
|
||||||
|
order: start-first
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
cpus: "0.001"
|
cpus: "0.001"
|
||||||
|
|
|
@ -19,7 +19,7 @@ func TestMarshallConfig(t *testing.T) {
|
||||||
assert.Check(t, is.Equal(expected, string(actual)))
|
assert.Check(t, is.Equal(expected, string(actual)))
|
||||||
|
|
||||||
// Make sure the expected still
|
// Make sure the expected still
|
||||||
dict, err := ParseYAML([]byte("version: '3.6'\n" + expected))
|
dict, err := ParseYAML([]byte("version: '3.7'\n" + expected))
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
_, err = Load(buildConfigDetails(dict, map[string]string{}))
|
_, err = Load(buildConfigDetails(dict, map[string]string{}))
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
|
@ -465,6 +465,49 @@ DoTuq9lAU9Q4O1xV/59X/w8AAP//zRo7vm9CAAA=
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"/data/config_schema_v3.7.json": {
|
||||||
|
local: "data/config_schema_v3.7.json",
|
||||||
|
size: 17540,
|
||||||
|
modtime: 1518458244,
|
||||||
|
compressed: `
|
||||||
|
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
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
|
||||||
"/": {
|
"/": {
|
||||||
isDir: true,
|
isDir: true,
|
||||||
local: "",
|
local: "",
|
||||||
|
|
|
@ -0,0 +1,596 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
"id": "config_schema_v3.7.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/list_or_dict"},
|
||||||
|
"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/list_or_dict"},
|
||||||
|
"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"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tmpfs": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"size": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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/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
|
||||||
|
},
|
||||||
|
"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"}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
"external": {
|
||||||
|
"type": ["boolean", "object"],
|
||||||
|
"properties": {
|
||||||
|
"name": {"type": "string"}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
"internal": {"type": "boolean"},
|
||||||
|
"attachable": {"type": "boolean"},
|
||||||
|
"labels": {"$ref": "#/definitions/list_or_dict"}
|
||||||
|
},
|
||||||
|
"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/list_or_dict"}
|
||||||
|
},
|
||||||
|
"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/list_or_dict"}
|
||||||
|
},
|
||||||
|
"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/list_or_dict"}
|
||||||
|
},
|
||||||
|
"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}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
"constraints": {
|
||||||
|
"service": {
|
||||||
|
"id": "#/definitions/constraints/service",
|
||||||
|
"anyOf": [
|
||||||
|
{"required": ["build"]},
|
||||||
|
{"required": ["image"]}
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"build": {
|
||||||
|
"required": ["context"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -114,3 +114,92 @@ func TestValidateIsolation(t *testing.T) {
|
||||||
}
|
}
|
||||||
assert.NilError(t, Validate(config, "3.5"))
|
assert.NilError(t, Validate(config, "3.5"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValidateRollbackConfig(t *testing.T) {
|
||||||
|
config := dict{
|
||||||
|
"version": "3.4",
|
||||||
|
"services": dict{
|
||||||
|
"foo": dict{
|
||||||
|
"image": "busybox",
|
||||||
|
"deploy": dict{
|
||||||
|
"rollback_config": dict{
|
||||||
|
"parallelism": 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NilError(t, Validate(config, "3.7"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateRollbackConfigWithOrder(t *testing.T) {
|
||||||
|
config := dict{
|
||||||
|
"version": "3.4",
|
||||||
|
"services": dict{
|
||||||
|
"foo": dict{
|
||||||
|
"image": "busybox",
|
||||||
|
"deploy": dict{
|
||||||
|
"rollback_config": dict{
|
||||||
|
"parallelism": 1,
|
||||||
|
"order": "start-first",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NilError(t, Validate(config, "3.7"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateRollbackConfigWithUpdateConfig(t *testing.T) {
|
||||||
|
config := dict{
|
||||||
|
"version": "3.4",
|
||||||
|
"services": dict{
|
||||||
|
"foo": dict{
|
||||||
|
"image": "busybox",
|
||||||
|
"deploy": dict{
|
||||||
|
"update_config": dict{
|
||||||
|
"parallelism": 1,
|
||||||
|
"order": "start-first",
|
||||||
|
},
|
||||||
|
"rollback_config": dict{
|
||||||
|
"parallelism": 1,
|
||||||
|
"order": "start-first",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NilError(t, Validate(config, "3.7"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateRollbackConfigWithUpdateConfigFull(t *testing.T) {
|
||||||
|
config := dict{
|
||||||
|
"version": "3.4",
|
||||||
|
"services": dict{
|
||||||
|
"foo": dict{
|
||||||
|
"image": "busybox",
|
||||||
|
"deploy": dict{
|
||||||
|
"update_config": dict{
|
||||||
|
"parallelism": 1,
|
||||||
|
"order": "start-first",
|
||||||
|
"delay": "10s",
|
||||||
|
"failure_action": "pause",
|
||||||
|
"monitor": "10s",
|
||||||
|
},
|
||||||
|
"rollback_config": dict{
|
||||||
|
"parallelism": 1,
|
||||||
|
"order": "start-first",
|
||||||
|
"delay": "10s",
|
||||||
|
"failure_action": "pause",
|
||||||
|
"monitor": "10s",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NilError(t, Validate(config, "3.7"))
|
||||||
|
}
|
||||||
|
|
|
@ -194,6 +194,7 @@ type DeployConfig struct {
|
||||||
Replicas *uint64 `yaml:",omitempty"`
|
Replicas *uint64 `yaml:",omitempty"`
|
||||||
Labels Labels `yaml:",omitempty"`
|
Labels Labels `yaml:",omitempty"`
|
||||||
UpdateConfig *UpdateConfig `mapstructure:"update_config" yaml:"update_config,omitempty"`
|
UpdateConfig *UpdateConfig `mapstructure:"update_config" yaml:"update_config,omitempty"`
|
||||||
|
RollbackConfig *UpdateConfig `mapstructure:"rollback_config" yaml:"rollback_config,omitempty"`
|
||||||
Resources Resources `yaml:",omitempty"`
|
Resources Resources `yaml:",omitempty"`
|
||||||
RestartPolicy *RestartPolicy `mapstructure:"restart_policy" yaml:"restart_policy,omitempty"`
|
RestartPolicy *RestartPolicy `mapstructure:"restart_policy" yaml:"restart_policy,omitempty"`
|
||||||
Placement Placement `yaml:",omitempty"`
|
Placement Placement `yaml:",omitempty"`
|
||||||
|
|
Loading…
Reference in New Issue