kontena-cli 0.16.0.pre7 → 0.16.0.pre8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/kontena-cli.gemspec +2 -5
- data/lib/kontena/callbacks/master/deploy/05_before_deploy_configuration_wizard.rb +15 -21
- data/lib/kontena/callbacks/master/deploy/50_authenticate_after_deploy.rb +5 -3
- data/lib/kontena/callbacks/master/deploy/55_create_initial_grid_after_deploy.rb +3 -1
- data/lib/kontena/callbacks/master/deploy/60_configure_auth_provider_after_deploy.rb +7 -18
- data/lib/kontena/callbacks/master/deploy/70_invite_self_after_deploy.rb +93 -0
- data/lib/kontena/callbacks/master/deploy/90_proptip_after_deploy.rb +33 -0
- data/lib/kontena/cli/apps/build_command.rb +2 -1
- data/lib/kontena/cli/apps/common.rb +3 -2
- data/lib/kontena/cli/apps/config_command.rb +3 -3
- data/lib/kontena/cli/apps/deploy_command.rb +1 -0
- data/lib/kontena/cli/apps/docker_helper.rb +7 -7
- data/lib/kontena/cli/apps/list_command.rb +1 -1
- data/lib/kontena/cli/apps/logs_command.rb +1 -1
- data/lib/kontena/cli/apps/monitor_command.rb +2 -2
- data/lib/kontena/cli/apps/remove_command.rb +1 -1
- data/lib/kontena/cli/apps/restart_command.rb +1 -1
- data/lib/kontena/cli/apps/scale_command.rb +1 -1
- data/lib/kontena/cli/apps/start_command.rb +1 -1
- data/lib/kontena/cli/apps/stop_command.rb +1 -1
- data/lib/kontena/cli/apps/yaml/custom_validators/affinities_validator.rb +19 -0
- data/lib/kontena/cli/apps/yaml/custom_validators/build_validator.rb +22 -0
- data/lib/kontena/cli/apps/yaml/custom_validators/extends_validator.rb +21 -0
- data/lib/kontena/cli/apps/yaml/custom_validators/hooks_validator.rb +54 -0
- data/lib/kontena/cli/apps/yaml/custom_validators/secrets_validator.rb +22 -0
- data/lib/kontena/cli/apps/yaml/validations.rb +60 -90
- data/lib/kontena/cli/apps/yaml/validator.rb +9 -31
- data/lib/kontena/cli/apps/yaml/validator_v2.rb +13 -40
- data/lib/kontena/cli/cloud/login_command.rb +2 -2
- data/lib/kontena/cli/cloud/master/add_command.rb +114 -34
- data/lib/kontena/cli/cloud/master/list_command.rb +5 -2
- data/lib/kontena/cli/cloud/master/remove_command.rb +69 -0
- data/lib/kontena/cli/cloud/master_command.rb +2 -2
- data/lib/kontena/cli/common.rb +10 -17
- data/lib/kontena/cli/config.rb +4 -3
- data/lib/kontena/cli/grids/env_command.rb +5 -5
- data/lib/kontena/cli/localhost_web_server.rb +1 -1
- data/lib/kontena/cli/master/init_cloud_command.rb +21 -0
- data/lib/kontena/cli/master/login_command.rb +28 -29
- data/lib/kontena/cli/master/remove_command.rb +58 -0
- data/lib/kontena/cli/master/token/create_command.rb +6 -0
- data/lib/kontena/cli/master/users/invite_command.rb +4 -1
- data/lib/kontena/cli/master/users/roles/add_command.rb +4 -3
- data/lib/kontena/cli/master_command.rb +8 -9
- data/lib/kontena/cli/services/list_command.rb +3 -2
- data/lib/kontena/cli/services/services_helper.rb +1 -1
- data/lib/kontena/client.rb +31 -47
- data/lib/kontena/presets/kontena_auth_provider.yml +2 -2
- data/lib/kontena_cli.rb +12 -0
- data/spec/kontena/cli/app/docker_helper_spec.rb +9 -4
- data/spec/kontena/cli/app/yaml/validator_spec.rb +66 -71
- data/spec/kontena/cli/app/yaml/validator_v2_spec.rb +51 -58
- metadata +25 -59
- data/lib/kontena/callbacks/master/deploy/90_suggest_inviting_yourself_after_deploy.rb +0 -24
- data/lib/kontena/cli/cloud/master/delete_command.rb +0 -20
@@ -15,7 +15,7 @@ module Kontena::Cli::Apps
|
|
15
15
|
def execute
|
16
16
|
require_config_file(filename)
|
17
17
|
|
18
|
-
@services = services_from_yaml(filename, service_list, service_prefix)
|
18
|
+
@services = services_from_yaml(filename, service_list, service_prefix, true)
|
19
19
|
if services.size > 0
|
20
20
|
restart_services(services)
|
21
21
|
elsif !service_list.empty?
|
@@ -16,7 +16,7 @@ module Kontena::Cli::Apps
|
|
16
16
|
|
17
17
|
def execute
|
18
18
|
require_config_file(filename)
|
19
|
-
yml_service = services_from_yaml(filename, [service], service_prefix)
|
19
|
+
yml_service = services_from_yaml(filename, [service], service_prefix, true)
|
20
20
|
if yml_service[service]
|
21
21
|
options = yml_service[service]
|
22
22
|
exit_with_error("Service has already instances defined in #{filename}. Please update #{filename} and deploy service instead") if options['container_count']
|
@@ -16,7 +16,7 @@ module Kontena::Cli::Apps
|
|
16
16
|
def execute
|
17
17
|
require_config_file(filename)
|
18
18
|
|
19
|
-
@services = services_from_yaml(filename, service_list, service_prefix)
|
19
|
+
@services = services_from_yaml(filename, service_list, service_prefix, true)
|
20
20
|
if services.size > 0
|
21
21
|
start_services(services)
|
22
22
|
elsif !service_list.empty?
|
@@ -16,7 +16,7 @@ module Kontena::Cli::Apps
|
|
16
16
|
def execute
|
17
17
|
require_config_file(filename)
|
18
18
|
|
19
|
-
@services = services_from_yaml(filename, service_list, service_prefix)
|
19
|
+
@services = services_from_yaml(filename, service_list, service_prefix, true)
|
20
20
|
if services.size > 0
|
21
21
|
stop_services(services)
|
22
22
|
elsif !service_list.empty?
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Kontena::Cli::Apps::YAML::Validations::CustomValidators
|
2
|
+
class AffinitiesValidator < HashValidator::Validator::Base
|
3
|
+
def initialize
|
4
|
+
super('valid_affinities')
|
5
|
+
end
|
6
|
+
|
7
|
+
def validate(key, value, validations, errors)
|
8
|
+
unless value.is_a?(Array)
|
9
|
+
errors[key] = 'affinity must be array'
|
10
|
+
return
|
11
|
+
end
|
12
|
+
|
13
|
+
invalid_formats = value.find_all { |a| !a.match(/(?<=\!|\=)=/) }
|
14
|
+
if invalid_formats.count > 0
|
15
|
+
errors[key] = "affinity contains invalid formats: #{invalid_formats.join(', ')}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Kontena::Cli::Apps::YAML::Validations::CustomValidators
|
2
|
+
class BuildValidator < HashValidator::Validator::Base
|
3
|
+
def initialize
|
4
|
+
super('valid_build')
|
5
|
+
end
|
6
|
+
|
7
|
+
def validate(key, value, validations, errors)
|
8
|
+
unless value.is_a?(String) || value.is_a?(Hash)
|
9
|
+
errors[key] = 'build must be string or hash'
|
10
|
+
return
|
11
|
+
end
|
12
|
+
if value.is_a?(Hash)
|
13
|
+
build_validation = {
|
14
|
+
'context' => 'string',
|
15
|
+
'dockerfile' => HashValidator.optional('string'),
|
16
|
+
'args' => HashValidator.optional(-> (value) { value.is_a?(Array) || value.is_a?(Hash) })
|
17
|
+
}
|
18
|
+
HashValidator.validator_for(build_validation).validate(key, value, build_validation, errors)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Kontena::Cli::Apps::YAML::Validations::CustomValidators
|
2
|
+
class ExtendsValidator < HashValidator::Validator::Base
|
3
|
+
def initialize
|
4
|
+
super('valid_extends')
|
5
|
+
end
|
6
|
+
|
7
|
+
def validate(key, value, validations, errors)
|
8
|
+
unless value.is_a?(String) || value.is_a?(Hash)
|
9
|
+
errors[key] = 'extends must be string or hash'
|
10
|
+
return
|
11
|
+
end
|
12
|
+
if value.is_a?(Hash)
|
13
|
+
extends_validation = {
|
14
|
+
'service' => 'string',
|
15
|
+
'file' => HashValidator.optional('string')
|
16
|
+
}
|
17
|
+
HashValidator.validator_for(extends_validation).validate(key, value, extends_validation, errors)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Kontena::Cli::Apps::YAML::Validations::CustomValidators
|
2
|
+
class HooksValidator < HashValidator::Validator::Base
|
3
|
+
def initialize
|
4
|
+
super('valid_hooks')
|
5
|
+
end
|
6
|
+
|
7
|
+
def validate(key, value, validations, errors)
|
8
|
+
unless value.is_a?(Hash)
|
9
|
+
errors[key] = 'hooks must be array'
|
10
|
+
return
|
11
|
+
end
|
12
|
+
|
13
|
+
if value['pre_build']
|
14
|
+
validate_pre_build_hooks(key, value['pre_build'], errors)
|
15
|
+
end
|
16
|
+
|
17
|
+
if value['post_start']
|
18
|
+
validate_post_start_hooks(key, value['post_start'], errors)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def validate_pre_build_hooks(key, pre_build_hooks, errors)
|
23
|
+
unless pre_build_hooks.is_a?(Array)
|
24
|
+
errors[key] = 'pre_build must be array'
|
25
|
+
return
|
26
|
+
end
|
27
|
+
pre_build_validation = {
|
28
|
+
'name' => 'string',
|
29
|
+
'cmd' => 'string'
|
30
|
+
}
|
31
|
+
validator = HashValidator.validator_for(pre_build_validation)
|
32
|
+
pre_build_hooks.each do |pre_build|
|
33
|
+
validator.validate('hooks.pre_build', pre_build, pre_build_validation, errors)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def validate_post_start_hooks(key, post_start_hooks, errors)
|
38
|
+
unless post_start_hooks.is_a?(Array)
|
39
|
+
errors[key] = 'post_start must be array'
|
40
|
+
return
|
41
|
+
end
|
42
|
+
post_start_validation = {
|
43
|
+
'name' => 'string',
|
44
|
+
'instances' => (-> (value) { value.is_a?(Integer) || value == '*' }),
|
45
|
+
'cmd' => 'string',
|
46
|
+
'oneshot' => HashValidator.optional('boolean')
|
47
|
+
}
|
48
|
+
validator = HashValidator.validator_for(post_start_validation)
|
49
|
+
post_start_hooks.each do |post_start|
|
50
|
+
validator.validate('hooks.post_start', post_start, post_start_validation, errors)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Kontena::Cli::Apps::YAML::Validations::CustomValidators
|
2
|
+
class SecretsValidator < HashValidator::Validator::Base
|
3
|
+
def initialize
|
4
|
+
super('valid_secrets')
|
5
|
+
end
|
6
|
+
|
7
|
+
def validate(key, value, validations, errors)
|
8
|
+
unless value.is_a?(Array)
|
9
|
+
errors[key] = 'secrets must be array'
|
10
|
+
return
|
11
|
+
end
|
12
|
+
secret_item_validation = {
|
13
|
+
'secret' => 'string',
|
14
|
+
'name' => 'string',
|
15
|
+
'type' => 'string'
|
16
|
+
}
|
17
|
+
value.each do |secret|
|
18
|
+
HashValidator.validator_for(secret_item_validation).validate(key, secret, secret_item_validation, errors)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,97 +1,67 @@
|
|
1
1
|
module Kontena::Cli::Apps::YAML
|
2
2
|
module Validations
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
base.optional('stateful') { bool? }
|
16
|
-
base.optional('affinity') { array? { each { format?(/(?<=\!|\=)=/) } } }
|
17
|
-
base.optional('cap_add').maybe(:array?)
|
18
|
-
base.optional('cap_drop').maybe(:array?)
|
19
|
-
base.optional('command').maybe(:str?)
|
20
|
-
base.optional('cpu_shares').maybe(:int?)
|
21
|
-
base.optional('external_links') { array? }
|
22
|
-
base.optional('mem_limit') { int? | str? }
|
23
|
-
base.optional('memswap_limit') { int? | str? }
|
24
|
-
base.optional('environment') { array? | type?(Hash) }
|
25
|
-
base.optional('env_file') { str? | array? }
|
26
|
-
base.optional('instances') { int? }
|
27
|
-
base.optional('links') { array? | empty? }
|
28
|
-
base.optional('ports').value(:array?)
|
29
|
-
base.optional('volumes').value(:array?)
|
30
|
-
base.optional('volumes_from').value(:array?)
|
31
|
-
|
32
|
-
base.optional('deploy').schema do
|
33
|
-
optional('strategy').value(included_in?: %w(ha daemon random))
|
34
|
-
optional('wait_for_port').value(:int?)
|
35
|
-
optional('min_health').value(:float?)
|
36
|
-
optional('interval').value(format?: /^\d+(min|h|d|)$/)
|
37
|
-
end
|
38
|
-
|
39
|
-
base.optional('hooks').schema do
|
40
|
-
optional('post_start').each do
|
41
|
-
required('name').filled
|
42
|
-
required('cmd').filled
|
43
|
-
required('instances') { int? | eql?('*') }
|
44
|
-
optional('oneshot').value(:bool?)
|
45
|
-
end
|
46
|
-
|
47
|
-
optional('pre_build').each do
|
48
|
-
required('cmd').filled
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
base.optional('secrets').each do
|
53
|
-
required('secret').filled
|
54
|
-
required('name').filled
|
55
|
-
required('type').filled
|
56
|
-
end
|
57
|
-
base.optional('health_check').schema do
|
58
|
-
required('protocol').filled(format?: /^(http|tcp)$/)
|
59
|
-
required('port').filled(:int?)
|
60
|
-
optional('uri').value(format?: /\/[\S]*/)
|
61
|
-
optional('timeout').value(:int?)
|
62
|
-
optional('interval').value(:int?)
|
63
|
-
optional('initial_delay').value(:int?)
|
64
|
-
end
|
3
|
+
module CustomValidators
|
4
|
+
require_relative 'custom_validators/affinities_validator'
|
5
|
+
require_relative 'custom_validators/build_validator'
|
6
|
+
require_relative 'custom_validators/extends_validator'
|
7
|
+
require_relative 'custom_validators/hooks_validator'
|
8
|
+
require_relative 'custom_validators/secrets_validator'
|
9
|
+
|
10
|
+
HashValidator.append_validator(AffinitiesValidator.new)
|
11
|
+
HashValidator.append_validator(BuildValidator.new)
|
12
|
+
HashValidator.append_validator(ExtendsValidator.new)
|
13
|
+
HashValidator.append_validator(SecretsValidator.new)
|
14
|
+
HashValidator.append_validator(HooksValidator.new)
|
65
15
|
end
|
66
16
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
17
|
+
def common_validations
|
18
|
+
{
|
19
|
+
'image' => optional('string'), # it's optional because some base yml file might contain image option
|
20
|
+
'extends' => optional('valid_extends'),
|
21
|
+
'stateful' => optional('boolean'),
|
22
|
+
'affinity' => optional('valid_affinities'),
|
23
|
+
'cap_add' => optional('array'),
|
24
|
+
'cap_drop' => optional('array'),
|
25
|
+
'command' => optional('string'),
|
26
|
+
'cpu_shares' => optional('integer'),
|
27
|
+
'external_links' => optional('array'),
|
28
|
+
'mem_limit' => optional('string'),
|
29
|
+
'mem_swaplimit' => optional('string'),
|
30
|
+
'environment' => optional(-> (value) { value.is_a?(Array) || value.is_a?(Hash) }),
|
31
|
+
'env_file' => optional(-> (value) { value.is_a?(String) || value.is_a?(Array) }),
|
32
|
+
'instances' => optional('integer'),
|
33
|
+
'links' => optional(-> (value) { value.is_a?(Array) || value.nil? }),
|
34
|
+
'ports' => optional('array'),
|
35
|
+
'pid' => optional('string'),
|
36
|
+
'privileged' => optional('boolean'),
|
37
|
+
'user' => optional('string'),
|
38
|
+
'volumes' => optional('array'),
|
39
|
+
'volumes_from' => optional('array'),
|
40
|
+
'secrets' => optional('valid_secrets'),
|
41
|
+
'hooks' => optional('valid_hooks'),
|
42
|
+
'deploy' => optional({
|
43
|
+
'strategy' => optional(%w(ha daemon random)),
|
44
|
+
'wait_for_port' => optional('integer'),
|
45
|
+
'min_health' => optional('float'),
|
46
|
+
'interval' => optional(/^\d+(min|h|d|)$/)
|
47
|
+
}),
|
48
|
+
'health_check' => optional({
|
49
|
+
'protocol' => /^(http|tcp)$/,
|
50
|
+
'port' => 'integer',
|
51
|
+
'uri' => optional(/\/[\S]*/),
|
52
|
+
'timeout' => optional('integer'),
|
53
|
+
'interval' => optional('integer'),
|
54
|
+
'initial_delay' => optional('integer')
|
55
|
+
})
|
56
|
+
}
|
57
|
+
end
|
72
58
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
def validate_keys(service_config)
|
77
|
-
errors = {}
|
78
|
-
service_config.keys.each do |key|
|
79
|
-
error = validate_required(key)
|
80
|
-
errors[key] = error if error
|
81
|
-
end
|
82
|
-
errors
|
83
|
-
end
|
59
|
+
def optional(type)
|
60
|
+
HashValidator.optional(type)
|
61
|
+
end
|
84
62
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
['unsupported option']
|
90
|
-
elsif !self.class::VALID_KEYS.include?(key)
|
91
|
-
['invalid option']
|
92
|
-
else
|
93
|
-
nil
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
63
|
+
def validate_options(service_config)
|
64
|
+
HashValidator.validate(service_config, @schema, true)
|
65
|
+
end
|
66
|
+
end
|
97
67
|
end
|
@@ -1,36 +1,17 @@
|
|
1
|
-
require '
|
1
|
+
require 'hash_validator'
|
2
2
|
module Kontena::Cli::Apps
|
3
3
|
module YAML
|
4
4
|
class Validator
|
5
5
|
require_relative 'validations'
|
6
6
|
include Validations
|
7
7
|
|
8
|
-
VALID_KEYS = %w(
|
9
|
-
affinity build dockerfile cap_add cap_drop command deploy env_file environment extends external_links
|
10
|
-
image links log_driver log_opt net pid ports volumes volumes_from cpu_shares
|
11
|
-
mem_limit memswap_limit privileged stateful user instances hooks secrets health_check
|
12
|
-
).freeze
|
13
|
-
|
14
|
-
UNSUPPORTED_KEYS = %w(
|
15
|
-
cgroup_parent container_name devices depends_on dns dns_search tmpfs entrypoint
|
16
|
-
expose extra_hosts labels logging network_mode networks security_opt stop_signal ulimits volume_driver
|
17
|
-
cpu_quota cpuset domainname hostname ipc mac_address
|
18
|
-
read_only restart shm_size stdin_open tty working_dir
|
19
|
-
).freeze
|
20
|
-
|
21
|
-
##
|
22
|
-
# rubocop:disable Metrics/MethodLength,Metrics/AbcSize
|
23
8
|
def initialize(need_image=false)
|
24
|
-
|
25
|
-
@
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
optional('net').value(included_in?: (%w(host bridge)))
|
31
|
-
optional('log_driver').value(:str?)
|
32
|
-
optional('log_opts').value(type?: Hash)
|
33
|
-
end
|
9
|
+
@schema = common_validations
|
10
|
+
@schema['build'] = optional('string')
|
11
|
+
@schema['dockerfile'] = optional('string')
|
12
|
+
@schema['net'] = optional(%w(host bridge))
|
13
|
+
@schema['log_driver'] = optional('string')
|
14
|
+
@schema['log_opts'] = optional({})
|
34
15
|
end
|
35
16
|
|
36
17
|
##
|
@@ -41,16 +22,13 @@ module Kontena::Cli::Apps
|
|
41
22
|
errors: [],
|
42
23
|
notifications: []
|
43
24
|
}
|
44
|
-
|
45
25
|
yaml.each do |service, options|
|
46
26
|
unless options.is_a?(Hash)
|
47
|
-
result[:errors] << { service => { 'options' => 'must be a mapping not a string'} }
|
27
|
+
result[:errors] << { service => { 'options' => 'must be a mapping not a string'} }
|
48
28
|
next
|
49
29
|
end
|
50
|
-
key_errors = validate_keys(options)
|
51
30
|
option_errors = validate_options(options)
|
52
|
-
result[:errors] << { service => option_errors.
|
53
|
-
result[:notifications] << { service => key_errors } if key_errors.size > 0
|
31
|
+
result[:errors] << { service => option_errors.errors } unless option_errors.valid?
|
54
32
|
end
|
55
33
|
result
|
56
34
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'hash_validator'
|
2
2
|
require_relative 'validator'
|
3
3
|
|
4
4
|
module Kontena::Cli::Apps
|
@@ -7,45 +7,20 @@ module Kontena::Cli::Apps
|
|
7
7
|
require_relative 'validations'
|
8
8
|
include Validations
|
9
9
|
|
10
|
-
VALID_KEYS = %w(
|
11
|
-
affinity build cap_add cap_drop command deploy depends_on env_file environment extends external_links
|
12
|
-
image links logging network_mode pid ports volumes volumes_from cpu_shares
|
13
|
-
mem_limit memswap_limit privileged stateful user instances hooks secrets health_check
|
14
|
-
).freeze
|
15
|
-
|
16
|
-
UNSUPPORTED_KEYS = %w(
|
17
|
-
cgroup_parent container_name devices dns dns_search tmpfs entrypoint
|
18
|
-
expose extra_hosts labels log_driver log_opt net networks security_opt stop_signal ulimits volume_driver
|
19
|
-
cpu_quota cpuset domainname hostname ipc mac_address
|
20
|
-
read_only restart shm_size stdin_open tty working_dir
|
21
|
-
).freeze
|
22
|
-
|
23
|
-
##
|
24
|
-
# rubocop:disable Metrics/MethodLength,Metrics/AbcSize
|
25
10
|
def initialize
|
26
|
-
|
27
|
-
@
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
optional('dockerfile').value(:str?)
|
35
|
-
optional('args') { array? | type?(Hash) }
|
36
|
-
end
|
37
|
-
end
|
38
|
-
optional('depends_on').value(:array?)
|
39
|
-
optional('network_mode').value(included_in?: (%w(host bridge)))
|
40
|
-
optional('logging').schema do
|
41
|
-
optional('driver').value(:str?)
|
42
|
-
optional('options') { type?(Hash) }
|
43
|
-
end
|
44
|
-
end
|
11
|
+
@schema = common_validations
|
12
|
+
@schema['build'] = optional('valid_build')
|
13
|
+
@schema['depends_on'] = optional('array')
|
14
|
+
@schema['network_mode'] = optional(%w(host bridge))
|
15
|
+
@schema['logging'] = optional({
|
16
|
+
'driver' => optional('string'),
|
17
|
+
'options' => optional(-> (value) { value.is_a?(Hash) })
|
18
|
+
})
|
45
19
|
end
|
46
20
|
|
47
21
|
##
|
48
22
|
# @param [Hash] yaml
|
23
|
+
# @param [TrueClass|FalseClass] strict
|
49
24
|
# @return [Array] validation_errors
|
50
25
|
def validate(yaml)
|
51
26
|
result = {
|
@@ -53,15 +28,13 @@ module Kontena::Cli::Apps
|
|
53
28
|
notifications: []
|
54
29
|
}
|
55
30
|
if yaml.key?('services')
|
56
|
-
yaml['services'].each do |service, options|
|
31
|
+
yaml['services'].each do |service, options|
|
57
32
|
unless options.is_a?(Hash)
|
58
|
-
result[:errors] << { service => { 'options' => 'must be a mapping not a string'}
|
33
|
+
result[:errors] << { service => { 'options' => 'must be a mapping not a string'} }
|
59
34
|
next
|
60
35
|
end
|
61
|
-
key_errors = validate_keys(options)
|
62
36
|
option_errors = validate_options(options)
|
63
|
-
result[:errors] << { service => option_errors.
|
64
|
-
result[:notifications] << { service => key_errors } if key_errors.size > 0
|
37
|
+
result[:errors] << { service => option_errors.errors } unless option_errors.valid?
|
65
38
|
end
|
66
39
|
else
|
67
40
|
result[:errors] << { 'file' => 'services missing' }
|