kontena-cli 1.1.1 → 1.1.2.rc1
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/LOGO +1 -1
- data/VERSION +1 -1
- data/lib/kontena/cli/services/create_command.rb +4 -20
- data/lib/kontena/cli/services/services_helper.rb +29 -0
- data/lib/kontena/cli/services/update_command.rb +4 -17
- data/lib/kontena/cli/stacks/common.rb +1 -1
- data/lib/kontena/cli/stacks/service_generator.rb +12 -12
- data/lib/kontena/cli/stacks/yaml/reader.rb +12 -6
- data/lib/kontena/stacks_cache.rb +3 -2
- data/lib/kontena/stacks_client.rb +4 -0
- data/spec/kontena/cli/services/update_command_spec.rb +68 -0
- data/spec/kontena/cli/stacks/service_generator_spec.rb +49 -0
- data/spec/kontena/cli/stacks/yaml/reader_spec.rb +13 -7
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c08178a70fa7abd31742032c4a32bfcd3c448c6e
|
|
4
|
+
data.tar.gz: d425757f104f91eef926f0cc73a212ad60fb7df1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b2d8888c0b79d53b134dd3b9399afbcfac958fc6e2d8ed31ea2846eaeee2f8da905ed9e70afdba11ced3bb961e50c55e586980acfca81d0796e96e0f190d1fe2
|
|
7
|
+
data.tar.gz: 13356fee387db7005b1588a7c0a277e9f98172fbcc252d38610638a7f493cc291ad8ab3e34bcbea3c834edbf3747da5b0e27439ca4205be49230dcaed3024b41
|
data/LOGO
CHANGED
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.1.
|
|
1
|
+
1.1.2.rc1
|
|
@@ -82,26 +82,10 @@ module Kontena::Cli::Services
|
|
|
82
82
|
data[:log_driver] = log_driver if log_driver
|
|
83
83
|
data[:log_opts] = parse_log_opts(log_opt_list)
|
|
84
84
|
data[:strategy] = deploy_strategy if deploy_strategy
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
if deploy_wait_for_port
|
|
90
|
-
data[:deploy_opts][:wait_for_port] = deploy_wait_for_port.to_i
|
|
91
|
-
end
|
|
92
|
-
if deploy_interval
|
|
93
|
-
data[:deploy_opts][:interval] = parse_relative_time(deploy_interval)
|
|
94
|
-
end
|
|
95
|
-
if health_check_port
|
|
96
|
-
data[:health_check] = {
|
|
97
|
-
protocol: health_check_protocol,
|
|
98
|
-
uri: health_check_uri,
|
|
99
|
-
port: health_check_port,
|
|
100
|
-
timeout: health_check_timeout,
|
|
101
|
-
interval: health_check_interval,
|
|
102
|
-
initial_delay: health_check_initial_delay
|
|
103
|
-
}
|
|
104
|
-
end
|
|
85
|
+
deploy_opts = parse_deploy_opts
|
|
86
|
+
data[:deploy_opts] = deploy_opts unless deploy_opts.empty?
|
|
87
|
+
health_check = parse_health_check
|
|
88
|
+
data[:health_check] = health_check unless health_check.empty?
|
|
105
89
|
data[:pid] = pid if pid
|
|
106
90
|
data
|
|
107
91
|
end
|
|
@@ -432,6 +432,35 @@ module Kontena
|
|
|
432
432
|
build_args
|
|
433
433
|
end
|
|
434
434
|
|
|
435
|
+
# @return [Hash]
|
|
436
|
+
def parse_deploy_opts
|
|
437
|
+
deploy_opts = {}
|
|
438
|
+
deploy_opts[:min_health] = deploy_min_health.to_f if deploy_min_health
|
|
439
|
+
deploy_opts[:wait_for_port] = deploy_wait_for_port.to_i if deploy_wait_for_port
|
|
440
|
+
if deploy_interval
|
|
441
|
+
deploy_opts[:interval] = parse_relative_time(deploy_interval)
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
deploy_opts
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
# @return [Hash]
|
|
448
|
+
def parse_health_check
|
|
449
|
+
health_check = {}
|
|
450
|
+
if health_check_port
|
|
451
|
+
health_check[:port] = health_check_port == 'none' ? nil : health_check_port
|
|
452
|
+
end
|
|
453
|
+
if health_check_protocol
|
|
454
|
+
health_check[:protocol] = health_check_protocol == 'none' ? nil : health_check_protocol
|
|
455
|
+
end
|
|
456
|
+
health_check[:uri] = health_check_uri if health_check_uri
|
|
457
|
+
health_check[:timeout] = health_check_timeout if health_check_timeout
|
|
458
|
+
health_check[:interval] = health_check_interval if health_check_interval
|
|
459
|
+
health_check[:initial_delay] = health_check_initial_delay if health_check_initial_delay
|
|
460
|
+
|
|
461
|
+
health_check
|
|
462
|
+
end
|
|
463
|
+
|
|
435
464
|
# @param [Symbol] health
|
|
436
465
|
# @return [String]
|
|
437
466
|
def health_status_icon(health)
|
|
@@ -73,23 +73,10 @@ module Kontena::Cli::Services
|
|
|
73
73
|
data[:net] = net if net
|
|
74
74
|
data[:log_driver] = log_driver if log_driver
|
|
75
75
|
data[:log_opts] = parse_log_opts(log_opt_list) if log_opt_list
|
|
76
|
-
|
|
77
|
-
data[:deploy_opts]
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
data[:deploy_opts][:interval] = parse_relative_time(deploy_interval)
|
|
81
|
-
end
|
|
82
|
-
if health_check_port
|
|
83
|
-
data[:health_check] = {
|
|
84
|
-
protocol: health_check_protocol,
|
|
85
|
-
uri: health_check_uri,
|
|
86
|
-
port: health_check_port,
|
|
87
|
-
timeout: health_check_timeout,
|
|
88
|
-
interval: health_check_interval,
|
|
89
|
-
initial_delay: health_check_initial_delay
|
|
90
|
-
}
|
|
91
|
-
end
|
|
92
|
-
data.delete(:deploy_opts) if data[:deploy_opts].empty?
|
|
76
|
+
deploy_opts = parse_deploy_opts
|
|
77
|
+
data[:deploy_opts] = deploy_opts unless deploy_opts.empty?
|
|
78
|
+
health_check = parse_health_check
|
|
79
|
+
data[:health_check] = health_check unless health_check.empty?
|
|
93
80
|
data[:pid] = pid if pid
|
|
94
81
|
data
|
|
95
82
|
end
|
|
@@ -71,7 +71,7 @@ module Kontena::Cli::Stacks
|
|
|
71
71
|
'expose' => outcome[:expose],
|
|
72
72
|
'version' => outcome[:version],
|
|
73
73
|
'source' => reader.raw_content,
|
|
74
|
-
'registry' =>
|
|
74
|
+
'registry' => outcome[:registry],
|
|
75
75
|
'services' => kontena_services,
|
|
76
76
|
'variables' => outcome[:variables]
|
|
77
77
|
}
|
|
@@ -57,22 +57,12 @@ module Kontena::Cli::Stacks
|
|
|
57
57
|
deploy['interval'] = parse_relative_time(deploy_opts['interval'])
|
|
58
58
|
else
|
|
59
59
|
deploy['interval'] = nil
|
|
60
|
-
end
|
|
60
|
+
end
|
|
61
61
|
data['deploy_opts'] = deploy
|
|
62
62
|
data['hooks'] = options['hooks'] || {}
|
|
63
63
|
data['secrets'] = options['secrets'] if options['secrets']
|
|
64
64
|
data['build'] = parse_build_options(options) if options['build']
|
|
65
|
-
health_check =
|
|
66
|
-
health_opts = options['health_check'] || {}
|
|
67
|
-
health_check['protocol'] = health_opts['protocol'] if health_opts.has_key?('protocol')
|
|
68
|
-
health_check['uri'] = health_opts['uri'] if health_opts.has_key?('uri')
|
|
69
|
-
health_check['port'] = health_opts['port'] if health_opts.has_key?('port')
|
|
70
|
-
health_check['timeout'] = health_opts['timeout'] if health_opts.has_key?('timeout')
|
|
71
|
-
health_check['interval'] = health_opts['interval'] if health_opts.has_key?('interval')
|
|
72
|
-
health_check['initial_delay'] = health_opts['initial_delay'] if health_opts.has_key?('initial_delay')
|
|
73
|
-
unless health_check.empty?
|
|
74
|
-
data['health_check'] = health_check
|
|
75
|
-
end
|
|
65
|
+
data['health_check'] = parse_health_check(options)
|
|
76
66
|
data
|
|
77
67
|
end
|
|
78
68
|
|
|
@@ -113,5 +103,15 @@ module Kontena::Cli::Stacks
|
|
|
113
103
|
build['dockerfile'] = options['dockerfile'] if options['dockerfile']
|
|
114
104
|
build
|
|
115
105
|
end
|
|
106
|
+
|
|
107
|
+
# @param [Hash] options
|
|
108
|
+
# @return [Hash]
|
|
109
|
+
def parse_health_check(options)
|
|
110
|
+
health_check = {}
|
|
111
|
+
%w(port protocol uri timeout interval initial_delay).each do |k|
|
|
112
|
+
health_check[k] = options.dig('health_check', k)
|
|
113
|
+
end
|
|
114
|
+
health_check
|
|
115
|
+
end
|
|
116
116
|
end
|
|
117
117
|
end
|
|
@@ -11,7 +11,7 @@ module Kontena::Cli::Stacks
|
|
|
11
11
|
include Kontena::Util
|
|
12
12
|
include Kontena::Cli::Common
|
|
13
13
|
|
|
14
|
-
attr_reader :file, :raw_content, :errors, :notifications, :defaults, :values
|
|
14
|
+
attr_reader :file, :raw_content, :errors, :notifications, :defaults, :values, :registry
|
|
15
15
|
|
|
16
16
|
def initialize(file, skip_validation: false, skip_variables: false, variables: nil, values: nil, defaults: nil)
|
|
17
17
|
require 'yaml'
|
|
@@ -25,13 +25,13 @@ module Kontena::Cli::Stacks
|
|
|
25
25
|
if from_registry?
|
|
26
26
|
require 'shellwords'
|
|
27
27
|
@raw_content = Kontena::StacksCache.pull(file)
|
|
28
|
-
@registry =
|
|
28
|
+
@registry = current_account.stacks_url
|
|
29
29
|
elsif from_url?
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
@raw_content = stream.read
|
|
30
|
+
@raw_content = load_from_url(file)
|
|
31
|
+
@registry = nil
|
|
33
32
|
else
|
|
34
33
|
@raw_content = File.read(File.expand_path(file))
|
|
34
|
+
@registry = nil
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
@errors = []
|
|
@@ -43,6 +43,12 @@ module Kontena::Cli::Stacks
|
|
|
43
43
|
@defaults = defaults
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
+
def load_from_url(url)
|
|
47
|
+
require 'open-uri'
|
|
48
|
+
stream = open(url)
|
|
49
|
+
stream.read
|
|
50
|
+
end
|
|
51
|
+
|
|
46
52
|
def internals_interpolated_yaml
|
|
47
53
|
@internals_interpolated_yaml ||= ::YAML.safe_load(
|
|
48
54
|
replace_dollar_dollars(
|
|
@@ -121,7 +127,7 @@ module Kontena::Cli::Stacks
|
|
|
121
127
|
result[:stack] = raw_yaml['stack']
|
|
122
128
|
result[:version] = self.stack_version
|
|
123
129
|
result[:name] = self.stack_name
|
|
124
|
-
result[:registry] =
|
|
130
|
+
result[:registry] = registry
|
|
125
131
|
result[:expose] = fully_interpolated_yaml['expose']
|
|
126
132
|
result[:errors] = errors unless skip_validation?
|
|
127
133
|
result[:notifications] = notifications
|
data/lib/kontena/stacks_cache.rb
CHANGED
|
@@ -2,6 +2,7 @@ require_relative 'stacks_client'
|
|
|
2
2
|
require_relative 'cli/common'
|
|
3
3
|
require_relative 'cli/stacks/common'
|
|
4
4
|
require 'yaml'
|
|
5
|
+
require 'uri'
|
|
5
6
|
|
|
6
7
|
module Kontena
|
|
7
8
|
class StacksCache
|
|
@@ -94,8 +95,8 @@ module Kontena
|
|
|
94
95
|
stack
|
|
95
96
|
end
|
|
96
97
|
|
|
97
|
-
def registry_url
|
|
98
|
-
client.
|
|
98
|
+
def registry_url(stack, version = nil)
|
|
99
|
+
client.full_uri(stack, version)
|
|
99
100
|
end
|
|
100
101
|
|
|
101
102
|
def client
|
|
@@ -7,6 +7,10 @@ module Kontena
|
|
|
7
7
|
ACCEPT_YAML = { 'Accept' => 'application/yaml' }
|
|
8
8
|
CT_YAML = { 'Content-Type' => 'application/yaml' }
|
|
9
9
|
|
|
10
|
+
def full_uri(stack_name, version = nil)
|
|
11
|
+
URI.join(api_url, path_to(stack_name, version)).to_s
|
|
12
|
+
end
|
|
13
|
+
|
|
10
14
|
def path_to(stack_name, version = nil)
|
|
11
15
|
version ? "/stack/#{stack_name}/version/#{version}" : "/stack/#{stack_name}"
|
|
12
16
|
end
|
|
@@ -52,5 +52,73 @@ describe Kontena::Cli::Services::UpdateCommand do
|
|
|
52
52
|
'--log-opt', 'gelf-address=udp://log_forwarder-logstash_internal:12201', 'service'
|
|
53
53
|
])
|
|
54
54
|
end
|
|
55
|
+
|
|
56
|
+
context 'health check' do
|
|
57
|
+
it 'sends --health-check-port' do
|
|
58
|
+
expect(subject).to receive(:update_service).with(
|
|
59
|
+
duck_type(:access_token), 'service', hash_including(health_check: {
|
|
60
|
+
port: '8080'
|
|
61
|
+
})
|
|
62
|
+
)
|
|
63
|
+
subject.run([
|
|
64
|
+
'--health-check-port', '8080', 'service'
|
|
65
|
+
])
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'sends --health-check-port as nil if none given' do
|
|
69
|
+
expect(subject).to receive(:update_service).with(
|
|
70
|
+
duck_type(:access_token), 'service', hash_including(health_check: {
|
|
71
|
+
port: nil
|
|
72
|
+
})
|
|
73
|
+
)
|
|
74
|
+
subject.run([
|
|
75
|
+
'--health-check-port', 'none', 'service'
|
|
76
|
+
])
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it 'sends --health-check-protocol' do
|
|
80
|
+
expect(subject).to receive(:update_service).with(
|
|
81
|
+
duck_type(:access_token), 'service', hash_including(health_check: {
|
|
82
|
+
protocol: 'tcp'
|
|
83
|
+
})
|
|
84
|
+
)
|
|
85
|
+
subject.run([
|
|
86
|
+
'--health-check-protocol', 'tcp', 'service'
|
|
87
|
+
])
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it 'sends --health-check-protocol as nil if none given' do
|
|
91
|
+
expect(subject).to receive(:update_service).with(
|
|
92
|
+
duck_type(:access_token), 'service', hash_including(health_check: {
|
|
93
|
+
protocol: nil
|
|
94
|
+
})
|
|
95
|
+
)
|
|
96
|
+
subject.run([
|
|
97
|
+
'--health-check-protocol', 'none', 'service'
|
|
98
|
+
])
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it 'sends --health-check-timeout' do
|
|
102
|
+
expect(subject).to receive(:update_service).with(
|
|
103
|
+
duck_type(:access_token), 'service', hash_including(health_check: {
|
|
104
|
+
timeout: '30'
|
|
105
|
+
})
|
|
106
|
+
)
|
|
107
|
+
subject.run([
|
|
108
|
+
'--health-check-timeout', '30', 'service'
|
|
109
|
+
])
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it 'sends --health-check-uri' do
|
|
113
|
+
expect(subject).to receive(:update_service).with(
|
|
114
|
+
duck_type(:access_token), 'service', hash_including(health_check: {
|
|
115
|
+
uri: '/health'
|
|
116
|
+
})
|
|
117
|
+
)
|
|
118
|
+
subject.run([
|
|
119
|
+
'--health-check-uri', '/health', 'service'
|
|
120
|
+
])
|
|
121
|
+
end
|
|
122
|
+
end
|
|
55
123
|
end
|
|
56
124
|
end
|
|
@@ -385,5 +385,54 @@ describe Kontena::Cli::Stacks::ServiceGenerator do
|
|
|
385
385
|
expect(result['secrets']).to be_nil
|
|
386
386
|
end
|
|
387
387
|
end
|
|
388
|
+
|
|
389
|
+
context 'health_check' do
|
|
390
|
+
it 'returns health_check with nils by default' do
|
|
391
|
+
data = {
|
|
392
|
+
'image' => 'foo/bar:latest'
|
|
393
|
+
}
|
|
394
|
+
result = subject.send(:parse_data, data)
|
|
395
|
+
health_check = result['health_check']
|
|
396
|
+
expect(health_check['port']).to be_nil
|
|
397
|
+
expect(health_check['protocol']).to be_nil
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
it 'returns health_check with port & protocol' do
|
|
401
|
+
data = {
|
|
402
|
+
'image' => 'foo/bar:latest',
|
|
403
|
+
'health_check' => {
|
|
404
|
+
'port' => 8080,
|
|
405
|
+
'protocol' => 'tcp'
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
result = subject.send(:parse_data, data)
|
|
409
|
+
health_check = result['health_check']
|
|
410
|
+
expect(health_check['port']).to eq(8080)
|
|
411
|
+
expect(health_check['protocol']).to eq('tcp')
|
|
412
|
+
expect(health_check['uri']).to be_nil
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
it 'returns health_check with all values' do
|
|
416
|
+
data = {
|
|
417
|
+
'image' => 'foo/bar:latest',
|
|
418
|
+
'health_check' => {
|
|
419
|
+
'port' => 8080,
|
|
420
|
+
'protocol' => 'http',
|
|
421
|
+
'uri' => '/health',
|
|
422
|
+
'interval' => 60,
|
|
423
|
+
'timeout' => 5,
|
|
424
|
+
'initial_delay' => 30
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
result = subject.send(:parse_data, data)
|
|
428
|
+
health_check = result['health_check']
|
|
429
|
+
expect(health_check['port']).to eq(8080)
|
|
430
|
+
expect(health_check['protocol']).to eq('http')
|
|
431
|
+
expect(health_check['uri']).to eq('/health')
|
|
432
|
+
expect(health_check['interval']).to eq(60)
|
|
433
|
+
expect(health_check['timeout']).to eq(5)
|
|
434
|
+
expect(health_check['initial_delay']).to eq(30)
|
|
435
|
+
end
|
|
436
|
+
end
|
|
388
437
|
end
|
|
389
438
|
end
|
|
@@ -398,19 +398,25 @@ describe Kontena::Cli::Stacks::YAML::Reader do
|
|
|
398
398
|
.with(absolute_yaml_path('kontena_v3.yml'))
|
|
399
399
|
.and_return(fixture('stack-with-liquid.yml'))
|
|
400
400
|
expect(subject.from_file?).to be_truthy
|
|
401
|
+
expect(subject.execute[:registry]).to be_nil
|
|
401
402
|
end
|
|
402
403
|
|
|
403
404
|
it 'can read from the registry' do
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
expect(
|
|
408
|
-
|
|
405
|
+
stack_double = double
|
|
406
|
+
allow_any_instance_of(Kontena::StacksCache::RegistryClientFactory).to receive(:cloud_auth?).and_return(true)
|
|
407
|
+
expect(Kontena::StacksCache).to receive(:cache).with('foo/foo', nil).and_return(stack_double)
|
|
408
|
+
expect(stack_double).to receive(:read).and_return(fixture('kontena_v3.yml'))
|
|
409
|
+
instance = described_class.new('foo/foo')
|
|
410
|
+
expect(instance.from_registry?).to be_truthy
|
|
411
|
+
expect(instance.execute[:registry]).to eq instance.current_account.stacks_url
|
|
409
412
|
end
|
|
410
413
|
|
|
411
414
|
it 'can read from an url' do
|
|
412
|
-
|
|
413
|
-
|
|
415
|
+
stub_request(:get, "http://foo.example.com/foo").to_return(:status => 200, :body => fixture('stack-with-liquid.yml'), :headers => {})
|
|
416
|
+
allow_any_instance_of(described_class).to receive(:load_from_url).and_return(fixture('stack-with-liquid.yml'))
|
|
417
|
+
instance = described_class.new('http://foo.example.com/foo')
|
|
418
|
+
expect(instance.from_url?).to be_truthy
|
|
419
|
+
expect(instance.execute[:registry]).to be_nil
|
|
414
420
|
end
|
|
415
421
|
end
|
|
416
422
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kontena-cli
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.1.
|
|
4
|
+
version: 1.1.2.rc1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kontena, Inc
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2017-02-
|
|
11
|
+
date: 2017-02-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -621,9 +621,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
621
621
|
version: 2.1.0
|
|
622
622
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
623
623
|
requirements:
|
|
624
|
-
- - "
|
|
624
|
+
- - ">"
|
|
625
625
|
- !ruby/object:Gem::Version
|
|
626
|
-
version:
|
|
626
|
+
version: 1.3.1
|
|
627
627
|
requirements: []
|
|
628
628
|
rubyforge_project:
|
|
629
629
|
rubygems_version: 2.6.8
|