kontena-cli 0.14.7 → 0.15.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -1
- data/VERSION +1 -1
- data/bin/kontena +3 -50
- data/examples/kontena-plugin-hello/.gitignore +9 -0
- data/examples/kontena-plugin-hello/Gemfile +4 -0
- data/examples/kontena-plugin-hello/README.md +3 -0
- data/examples/kontena-plugin-hello/bin/console +14 -0
- data/examples/kontena-plugin-hello/bin/setup +8 -0
- data/examples/kontena-plugin-hello/kontena-plugin-hello.gemspec +22 -0
- data/examples/kontena-plugin-hello/lib/kontena/plugin/hello.rb +7 -0
- data/examples/kontena-plugin-hello/lib/kontena/plugin/hello/world_command.rb +6 -0
- data/examples/kontena-plugin-hello/lib/kontena/plugin/hello_command.rb +9 -0
- data/examples/kontena-plugin-hello/lib/kontena_cli_plugin.rb +5 -0
- data/kontena-cli.gemspec +1 -3
- data/lib/kontena/cli/apps/build_command.rb +3 -0
- data/lib/kontena/cli/apps/common.rb +6 -1
- data/lib/kontena/cli/apps/deploy_command.rb +1 -1
- data/lib/kontena/cli/apps/docker_helper.rb +13 -14
- data/lib/kontena/cli/apps/service_generator.rb +19 -11
- data/lib/kontena/cli/apps/service_generator_v2.rb +1 -0
- data/lib/kontena/cli/apps/yaml/reader.rb +15 -0
- data/lib/kontena/cli/apps/yaml/service_extender.rb +28 -0
- data/lib/kontena/cli/apps/yaml/validations.rb +38 -24
- data/lib/kontena/cli/apps/yaml/validator.rb +7 -7
- data/lib/kontena/cli/apps/yaml/validator_v2.rb +7 -6
- data/lib/kontena/cli/certificate/authorize_command.rb +23 -0
- data/lib/kontena/cli/certificate/get_command.rb +25 -0
- data/lib/kontena/cli/certificate/register_command.rb +19 -0
- data/lib/kontena/cli/certificate_command.rb +14 -0
- data/lib/kontena/cli/containers/containers_helper.rb +22 -0
- data/lib/kontena/cli/containers/exec_command.rb +9 -2
- data/lib/kontena/cli/grids/logs_command.rb +14 -3
- data/lib/kontena/cli/master_command.rb +1 -12
- data/lib/kontena/cli/node_command.rb +0 -16
- data/lib/kontena/cli/plugin_command.rb +15 -0
- data/lib/kontena/cli/plugins/install_command.rb +28 -0
- data/lib/kontena/cli/plugins/list_command.rb +13 -0
- data/lib/kontena/cli/plugins/search_command.rb +29 -0
- data/lib/kontena/cli/plugins/uninstall_command.rb +30 -0
- data/lib/kontena/cli/registry/create_command.rb +1 -1
- data/lib/kontena/cli/services/create_command.rb +16 -0
- data/lib/kontena/cli/services/list_command.rb +17 -3
- data/lib/kontena/cli/services/logs_command.rb +63 -18
- data/lib/kontena/cli/services/services_helper.rb +47 -4
- data/lib/kontena/cli/services/update_command.rb +16 -0
- data/lib/kontena/cli/stack_command.rb +20 -0
- data/lib/kontena/cli/stacks/common.rb +39 -0
- data/lib/kontena/cli/stacks/create_command.rb +27 -0
- data/lib/kontena/cli/stacks/deploy_command.rb +26 -0
- data/lib/kontena/cli/stacks/list_command.rb +38 -0
- data/lib/kontena/cli/stacks/remove_command.rb +26 -0
- data/lib/kontena/cli/stacks/show_command.rb +38 -0
- data/lib/kontena/cli/stacks/update_command.rb +27 -0
- data/lib/kontena/client.rb +11 -4
- data/lib/kontena/command.rb +4 -0
- data/lib/kontena/main_command.rb +61 -0
- data/lib/kontena/plugin_manager.rb +38 -0
- data/lib/kontena/util.rb +17 -0
- data/lib/kontena_cli.rb +6 -0
- data/spec/fixtures/health.yml +26 -0
- data/spec/fixtures/kontena-build.yml +16 -0
- data/spec/fixtures/kontena_build_v2.yaml +26 -0
- data/spec/kontena/cli/app/build_command_spec.rb +13 -1
- data/spec/kontena/cli/app/common_spec.rb +11 -0
- data/spec/kontena/cli/app/deploy_command_spec.rb +1 -1
- data/spec/kontena/cli/app/docker_helper_spec.rb +45 -0
- data/spec/kontena/cli/app/service_generator_spec.rb +52 -1
- data/spec/kontena/cli/app/yaml/service_extender_spec.rb +24 -0
- data/spec/kontena/cli/app/yaml/validator_spec.rb +97 -14
- data/spec/kontena/cli/common_spec.rb +0 -5
- data/spec/kontena/cli/containers/containers_helper_spec.rb +16 -0
- data/spec/kontena/cli/services/services_helper_spec.rb +50 -1
- data/spec/kontena/cli/version_command_spec.rb +1 -1
- data/spec/kontena/client_spec.rb +156 -0
- data/spec/kontena/plugin_manager_spec.rb +22 -0
- data/spec/spec_helper.rb +1 -0
- metadata +54 -125
- data/lib/kontena/cli/master/aws/create_command.rb +0 -48
- data/lib/kontena/cli/master/aws_command.rb +0 -8
- data/lib/kontena/cli/master/azure/create_command.rb +0 -37
- data/lib/kontena/cli/master/azure_command.rb +0 -13
- data/lib/kontena/cli/master/digital_ocean/create_command.rb +0 -38
- data/lib/kontena/cli/master/digital_ocean_command.rb +0 -13
- data/lib/kontena/cli/master/packet/create_command.rb +0 -42
- data/lib/kontena/cli/master/packet_command.rb +0 -14
- data/lib/kontena/cli/master/upcloud/create_command.rb +0 -39
- data/lib/kontena/cli/master/upcloud_command.rb +0 -13
- data/lib/kontena/cli/master/vagrant/create_command.rb +0 -25
- data/lib/kontena/cli/master/vagrant/restart_command.rb +0 -20
- data/lib/kontena/cli/master/vagrant/ssh_command.rb +0 -15
- data/lib/kontena/cli/master/vagrant/start_command.rb +0 -20
- data/lib/kontena/cli/master/vagrant/stop_command.rb +0 -20
- data/lib/kontena/cli/master/vagrant/terminate_command.rb +0 -13
- data/lib/kontena/cli/master/vagrant_command.rb +0 -23
- data/lib/kontena/cli/nodes/aws/create_command.rb +0 -44
- data/lib/kontena/cli/nodes/aws/restart_command.rb +0 -29
- data/lib/kontena/cli/nodes/aws/terminate_command.rb +0 -21
- data/lib/kontena/cli/nodes/aws_command.rb +0 -15
- data/lib/kontena/cli/nodes/azure/create_command.rb +0 -38
- data/lib/kontena/cli/nodes/azure/restart_command.rb +0 -32
- data/lib/kontena/cli/nodes/azure/terminate_command.rb +0 -21
- data/lib/kontena/cli/nodes/azure_command.rb +0 -15
- data/lib/kontena/cli/nodes/digital_ocean/create_command.rb +0 -32
- data/lib/kontena/cli/nodes/digital_ocean/restart_command.rb +0 -27
- data/lib/kontena/cli/nodes/digital_ocean/terminate_command.rb +0 -19
- data/lib/kontena/cli/nodes/digital_ocean_command.rb +0 -15
- data/lib/kontena/cli/nodes/packet/create_command.rb +0 -35
- data/lib/kontena/cli/nodes/packet/restart_command.rb +0 -17
- data/lib/kontena/cli/nodes/packet/terminate_command.rb +0 -20
- data/lib/kontena/cli/nodes/packet_command.rb +0 -15
- data/lib/kontena/cli/nodes/upcloud/create_command.rb +0 -33
- data/lib/kontena/cli/nodes/upcloud/restart_command.rb +0 -20
- data/lib/kontena/cli/nodes/upcloud/terminate_command.rb +0 -20
- data/lib/kontena/cli/nodes/upcloud_command.rb +0 -15
- data/lib/kontena/cli/nodes/vagrant/create_command.rb +0 -27
- data/lib/kontena/cli/nodes/vagrant/restart_command.rb +0 -26
- data/lib/kontena/cli/nodes/vagrant/ssh_command.rb +0 -21
- data/lib/kontena/cli/nodes/vagrant/start_command.rb +0 -26
- data/lib/kontena/cli/nodes/vagrant/stop_command.rb +0 -26
- data/lib/kontena/cli/nodes/vagrant/terminate_command.rb +0 -17
- data/lib/kontena/cli/nodes/vagrant_command.rb +0 -21
- data/lib/kontena/machine/aws.rb +0 -13
- data/lib/kontena/machine/aws/cloudinit.yml +0 -71
- data/lib/kontena/machine/aws/cloudinit_master.yml +0 -118
- data/lib/kontena/machine/aws/common.rb +0 -58
- data/lib/kontena/machine/aws/master_provisioner.rb +0 -187
- data/lib/kontena/machine/aws/node_destroyer.rb +0 -51
- data/lib/kontena/machine/aws/node_provisioner.rb +0 -204
- data/lib/kontena/machine/azure.rb +0 -13
- data/lib/kontena/machine/azure/cloudinit.yml +0 -64
- data/lib/kontena/machine/azure/cloudinit_master.yml +0 -106
- data/lib/kontena/machine/azure/logger.rb +0 -27
- data/lib/kontena/machine/azure/master_provisioner.rb +0 -128
- data/lib/kontena/machine/azure/node_destroyer.rb +0 -53
- data/lib/kontena/machine/azure/node_provisioner.rb +0 -132
- data/lib/kontena/machine/digital_ocean.rb +0 -13
- data/lib/kontena/machine/digital_ocean/cloudinit.yml +0 -64
- data/lib/kontena/machine/digital_ocean/cloudinit_master.yml +0 -118
- data/lib/kontena/machine/digital_ocean/master_provisioner.rb +0 -99
- data/lib/kontena/machine/digital_ocean/node_destroyer.rb +0 -40
- data/lib/kontena/machine/digital_ocean/node_provisioner.rb +0 -88
- data/lib/kontena/machine/packet.rb +0 -17
- data/lib/kontena/machine/packet/cloudinit.yml +0 -66
- data/lib/kontena/machine/packet/cloudinit_master.yml +0 -118
- data/lib/kontena/machine/packet/master_provisioner.rb +0 -93
- data/lib/kontena/machine/packet/node_destroyer.rb +0 -42
- data/lib/kontena/machine/packet/node_provisioner.rb +0 -77
- data/lib/kontena/machine/packet/node_restarter.rb +0 -41
- data/lib/kontena/machine/packet/packet_common.rb +0 -89
- data/lib/kontena/machine/upcloud.rb +0 -9
- data/lib/kontena/machine/upcloud/cloudinit.yml +0 -64
- data/lib/kontena/machine/upcloud/cloudinit_master.yml +0 -118
- data/lib/kontena/machine/upcloud/master_provisioner.rb +0 -138
- data/lib/kontena/machine/upcloud/node_destroyer.rb +0 -85
- data/lib/kontena/machine/upcloud/node_provisioner.rb +0 -121
- data/lib/kontena/machine/upcloud/node_restarter.rb +0 -49
- data/lib/kontena/machine/upcloud/upcloud_common.rb +0 -74
- data/lib/kontena/machine/vagrant.rb +0 -12
- data/lib/kontena/machine/vagrant/Vagrantfile.master.rb.erb +0 -104
- data/lib/kontena/machine/vagrant/Vagrantfile.node.rb.erb +0 -32
- data/lib/kontena/machine/vagrant/cloudinit.yml +0 -73
- data/lib/kontena/machine/vagrant/master_destroyer.rb +0 -37
- data/lib/kontena/machine/vagrant/master_provisioner.rb +0 -79
- data/lib/kontena/machine/vagrant/node_destroyer.rb +0 -40
- data/lib/kontena/machine/vagrant/node_provisioner.rb +0 -68
@@ -12,8 +12,8 @@ module Kontena::Cli::Services
|
|
12
12
|
|
13
13
|
grids = client(token).get("grids/#{current_grid}/services")
|
14
14
|
services = grids['services'].sort_by{|s| s['updated_at'] }.reverse
|
15
|
-
titles = ['NAME', 'INSTANCES', 'STATEFUL', 'STATE', 'EXPOSED PORTS']
|
16
|
-
puts "%-60s %-10s %-8s %-10s %-50s" % titles
|
15
|
+
titles = ['NAME', 'INSTANCES', 'STATEFUL', 'STATE', 'HEALTH', 'EXPOSED PORTS']
|
16
|
+
puts "%-60s %-10s %-8s %-10s %-10s %-50s" % titles
|
17
17
|
services.each do |service|
|
18
18
|
stateful = service['stateful'] ? 'yes' : 'no'
|
19
19
|
running = service['instances']['running']
|
@@ -22,14 +22,28 @@ module Kontena::Cli::Services
|
|
22
22
|
ports = service['ports'].map{|p|
|
23
23
|
"#{p['ip']}:#{p['node_port']}->#{p['container_port']}/#{p['protocol']}"
|
24
24
|
}.join(", ")
|
25
|
+
health = 'unknown'
|
26
|
+
if service['health_status']
|
27
|
+
icon = "■"
|
28
|
+
healthy = service.dig('health_status', 'healthy')
|
29
|
+
total = service.dig('health_status', 'total')
|
30
|
+
color = :green
|
31
|
+
if healthy == 0
|
32
|
+
color = :red
|
33
|
+
elsif healthy > 0 && healthy < total
|
34
|
+
color = :yellow
|
35
|
+
end
|
36
|
+
health = "■".colorize(color)
|
37
|
+
end
|
25
38
|
vars = [
|
26
39
|
service['name'],
|
27
40
|
instances,
|
28
41
|
stateful,
|
29
42
|
service['state'],
|
43
|
+
health,
|
30
44
|
ports
|
31
45
|
]
|
32
|
-
puts "%-60.60s %-10.10s %-8s %-10s %-50s" % vars
|
46
|
+
puts "%-60.60s %-10.10s %-8s %-10s %-10s %-50s" % vars
|
33
47
|
end
|
34
48
|
end
|
35
49
|
end
|
@@ -15,26 +15,71 @@ module Kontena::Cli::Services
|
|
15
15
|
def execute
|
16
16
|
require_api_url
|
17
17
|
token = require_token
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
18
|
+
|
19
|
+
|
20
|
+
query_params = {}
|
21
|
+
query_params[:limit] = lines if lines
|
22
|
+
query_params[:since] = since if since
|
23
|
+
query_params[:container] = "#{name}-#{instance}" if instance
|
24
|
+
|
25
|
+
if tail?
|
26
|
+
@buffer = ''
|
27
|
+
query_params[:follow] = 1
|
28
|
+
stream_logs(token, query_params)
|
29
|
+
else
|
30
|
+
list_logs(token, query_params)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
def render_log_line(log)
|
36
|
+
color = color_for_container(log['name'])
|
37
|
+
instance_number = log['name'].match(/^.+-(\d+)$/)[1]
|
38
|
+
name = instance_number.nil? ? log['name'] : instance_number
|
39
|
+
prefix = "#{log['created_at']} [#{name}]:".colorize(color)
|
40
|
+
puts "#{prefix} #{log['data']}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def list_logs(token, query_params)
|
44
|
+
result = client(token).get("services/#{current_grid}/#{name}/container_logs", query_params)
|
45
|
+
result['logs'].each do |log|
|
46
|
+
render_log_line(log)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def stream_logs(token, query_params)
|
51
|
+
streamer = lambda do |chunk, remaining_bytes, total_bytes|
|
52
|
+
begin
|
53
|
+
unless @buffer.empty?
|
54
|
+
chunk = @buffer + chunk
|
55
|
+
end
|
56
|
+
unless chunk.empty?
|
57
|
+
log = JSON.parse(chunk)
|
58
|
+
end
|
59
|
+
@buffer = ''
|
60
|
+
rescue => exc
|
61
|
+
@buffer << chunk
|
62
|
+
end
|
63
|
+
if log
|
64
|
+
@last_seen = log['id']
|
65
|
+
render_log_line(log)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
begin
|
70
|
+
query_params[:follow] = true
|
71
|
+
if @last_seen
|
72
|
+
query_params[:from] = @last_seen
|
73
|
+
end
|
74
|
+
result = client(token).get_stream(
|
75
|
+
"services/#{current_grid}/#{name}/container_logs", streamer, query_params
|
76
|
+
)
|
77
|
+
rescue => exc
|
78
|
+
if exc.cause.is_a?(EOFError) # Excon wraps the EOFerror into SockerError
|
79
|
+
retry
|
34
80
|
end
|
35
|
-
break unless tail?
|
36
|
-
sleep(2)
|
37
81
|
end
|
82
|
+
|
38
83
|
end
|
39
84
|
|
40
85
|
def color_for_container(container_id)
|
@@ -46,6 +46,7 @@ module Kontena
|
|
46
46
|
puts "#{service['id']}:"
|
47
47
|
puts " status: #{service['state'] }"
|
48
48
|
puts " image: #{service['image']}"
|
49
|
+
puts " revision: #{service['revision']}"
|
49
50
|
puts " stateful: #{service['stateful'] == true ? 'yes' : 'no' }"
|
50
51
|
puts " scaling: #{service['container_count'] }"
|
51
52
|
puts " strategy: #{service['strategy']}"
|
@@ -170,11 +171,28 @@ module Kontena
|
|
170
171
|
puts " pid: #{service['pid']}"
|
171
172
|
end
|
172
173
|
|
174
|
+
if service['health_check']
|
175
|
+
puts " health check:"
|
176
|
+
puts " protocol: #{service['health_check']['protocol']}"
|
177
|
+
puts " uri: #{service['health_check']['uri']}" if service['health_check']['protocol'] == 'http'
|
178
|
+
puts " port: #{service['health_check']['port']}"
|
179
|
+
puts " timeout: #{service['health_check']['timeout']}"
|
180
|
+
puts " interval: #{service['health_check']['interval']}"
|
181
|
+
puts " initial_delay: #{service['health_check']['initial_delay']}"
|
182
|
+
end
|
183
|
+
|
184
|
+
if service['health_status']
|
185
|
+
puts " health status:"
|
186
|
+
puts " healthy: #{service['health_status']['healthy']}"
|
187
|
+
puts " total: #{service['health_status']['total']}"
|
188
|
+
end
|
189
|
+
|
173
190
|
puts " instances:"
|
174
191
|
result = client(token).get("services/#{parse_service_id(service_id)}/containers")
|
175
192
|
result['containers'].each do |container|
|
176
193
|
puts " #{container['name']}:"
|
177
194
|
puts " rev: #{container['deploy_rev']}"
|
195
|
+
puts " service_rev: #{container['service_rev']}"
|
178
196
|
puts " node: #{container['node']['name'] rescue 'unknown'}"
|
179
197
|
puts " dns: #{container['name']}.#{grid}.kontena.local"
|
180
198
|
puts " ip: #{container['overlay_cidr'].to_s.split('/')[0]}"
|
@@ -251,14 +269,20 @@ module Kontena
|
|
251
269
|
# @return [Array<Hash>]
|
252
270
|
def parse_ports(port_options)
|
253
271
|
port_options.map{|p|
|
254
|
-
|
272
|
+
port, protocol = p.split('/')
|
273
|
+
protocol ||= 'tcp'
|
274
|
+
port_elements = port.split(':')
|
275
|
+
container_port = port_elements[-1]
|
276
|
+
node_port = port_elements[-2]
|
277
|
+
ip = port_elements[-3] || '0.0.0.0'
|
255
278
|
if node_port.nil? || container_port.nil?
|
256
279
|
raise ArgumentError.new("Invalid port value #{p}")
|
257
280
|
end
|
258
281
|
{
|
259
|
-
|
260
|
-
|
261
|
-
|
282
|
+
ip: ip,
|
283
|
+
container_port: container_port,
|
284
|
+
node_port: node_port,
|
285
|
+
protocol: protocol
|
262
286
|
}
|
263
287
|
}
|
264
288
|
end
|
@@ -356,6 +380,25 @@ module Kontena
|
|
356
380
|
'TB' => 1000 * 1000 * 1000 * 1000 * 1000
|
357
381
|
}.each_pair { |e, s| return "#{(int.to_i / (s / 1000))}#{e}" if int < s }
|
358
382
|
end
|
383
|
+
|
384
|
+
def parse_build_args(args)
|
385
|
+
build_args = {}
|
386
|
+
if args.kind_of?(Array)
|
387
|
+
args.each do |arg|
|
388
|
+
key, val = arg.split('=')
|
389
|
+
build_args[key] = val
|
390
|
+
end
|
391
|
+
elsif args.kind_of?(Hash)
|
392
|
+
build_args = build_args.merge(args)
|
393
|
+
build_args.each do |k, v|
|
394
|
+
if v.nil?
|
395
|
+
build_args[k] = ENV[k.to_s] # follow docker compose functionality here
|
396
|
+
end
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
build_args
|
401
|
+
end
|
359
402
|
end
|
360
403
|
end
|
361
404
|
end
|
@@ -31,6 +31,12 @@ module Kontena::Cli::Services
|
|
31
31
|
option "--deploy-interval", "TIME", "Auto-deploy with given interval (format: <number><unit>, where unit = min, h, d)"
|
32
32
|
option "--pid", "PID", "Pid namespace to use"
|
33
33
|
option "--secret", "SECRET", "Import secret from Vault (format: <secret>:<name>:<type>)", multivalued: true
|
34
|
+
option "--health-check-uri", "HEALTH CHECK URI", "URI path for HTTP health check"
|
35
|
+
option "--health-check-timeout", "HEALTH CHECK TIMEOUT", "Timeout for HTTP health check"
|
36
|
+
option "--health-check-interval", "HEALTH CHECK INTERVAL", "Interval for HTTP health check"
|
37
|
+
option "--health-check-initial-delay", "HEALTH CHECK INITIAL DELAY", "Initial for HTTP health check"
|
38
|
+
option "--health-check-port", "HEALTH CHECK PORT", "Port for HTTP health check"
|
39
|
+
option "--health-check-protocol", "HEALTH CHECK PROTOCOL", "Protocol of health check"
|
34
40
|
|
35
41
|
def execute
|
36
42
|
require_api_url
|
@@ -70,6 +76,16 @@ module Kontena::Cli::Services
|
|
70
76
|
if deploy_interval
|
71
77
|
data[:deploy_opts][:interval] = parse_relative_time(deploy_interval)
|
72
78
|
end
|
79
|
+
if health_check_port
|
80
|
+
data[:health_check] = {
|
81
|
+
protocol: health_check_protocol,
|
82
|
+
uri: health_check_uri,
|
83
|
+
port: health_check_port,
|
84
|
+
timeout: health_check_timeout,
|
85
|
+
interval: health_check_interval,
|
86
|
+
initial_delay: health_check_initial_delay
|
87
|
+
}
|
88
|
+
end
|
73
89
|
data.delete(:deploy_opts) if data[:deploy_opts].empty?
|
74
90
|
data[:pid] = pid if pid
|
75
91
|
data
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative 'stacks/create_command'
|
2
|
+
require_relative 'stacks/remove_command'
|
3
|
+
require_relative 'stacks/deploy_command'
|
4
|
+
require_relative 'stacks/update_command'
|
5
|
+
require_relative 'stacks/list_command'
|
6
|
+
require_relative 'stacks/show_command'
|
7
|
+
|
8
|
+
class Kontena::Cli::StackCommand < Clamp::Command
|
9
|
+
|
10
|
+
subcommand "create", "Create stack", Kontena::Cli::Stacks::CreateCommand
|
11
|
+
subcommand ["ls", "list"], "List stacks", Kontena::Cli::Stacks::ListCommand
|
12
|
+
subcommand "show", "Show stack details", Kontena::Cli::Stacks::ShowCommand
|
13
|
+
subcommand "update", "Update stack", Kontena::Cli::Stacks::UpdateCommand
|
14
|
+
subcommand "deploy", "Deploy Kontena stack", Kontena::Cli::Stacks::DeployCommand
|
15
|
+
subcommand ["remove","rm"], "Remove stack", Kontena::Cli::Stacks::RemoveCommand
|
16
|
+
|
17
|
+
def execute
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative '../apps/yaml/reader'
|
2
|
+
|
3
|
+
module Kontena::Cli::Stacks
|
4
|
+
module Common
|
5
|
+
include Kontena::Cli::Apps::Common
|
6
|
+
|
7
|
+
def service_prefix
|
8
|
+
@service_prefix ||= project_name_from_yaml(filename)
|
9
|
+
end
|
10
|
+
|
11
|
+
def stack_from_yaml(filename)
|
12
|
+
set_env_variables(service_prefix, current_grid)
|
13
|
+
outcome = read_yaml(filename)
|
14
|
+
if outcome[:version] != '2'
|
15
|
+
STDERR.puts "Stack supported only in v2 YAML! Aborting.".colorize(:red)
|
16
|
+
abort
|
17
|
+
end
|
18
|
+
if outcome[:name].nil?
|
19
|
+
STDERR.puts "Stack MUST have name in YAML! Aborting.".colorize(:red)
|
20
|
+
abort
|
21
|
+
end
|
22
|
+
hint_on_validation_notifications(outcome[:notifications]) if outcome[:notifications].size > 0
|
23
|
+
abort_on_validation_errors(outcome[:errors]) if outcome[:errors].size > 0
|
24
|
+
kontena_services = generate_services(outcome[:services], outcome[:version])
|
25
|
+
# services now as hash, needs to be array in stacks API
|
26
|
+
services = []
|
27
|
+
kontena_services.each do |name, service|
|
28
|
+
service['name'] = prefixed_name(name)
|
29
|
+
services << service
|
30
|
+
end
|
31
|
+
stack = {
|
32
|
+
'name' => outcome[:name],
|
33
|
+
'services' => services
|
34
|
+
}
|
35
|
+
stack
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative 'common'
|
2
|
+
|
3
|
+
module Kontena::Cli::Stacks
|
4
|
+
class CreateCommand < Clamp::Command
|
5
|
+
include Kontena::Cli::Common
|
6
|
+
include Kontena::Cli::GridOptions
|
7
|
+
include Common
|
8
|
+
|
9
|
+
option ['-f', '--file'], 'FILE', 'Specify an alternate Kontena stack file', attribute_name: :filename, default: 'kontena.yml'
|
10
|
+
|
11
|
+
def execute
|
12
|
+
require_api_url
|
13
|
+
require_token
|
14
|
+
require_config_file(filename)
|
15
|
+
@stack = stack_from_yaml(filename)
|
16
|
+
|
17
|
+
create_stack
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def create_stack
|
23
|
+
client(token).post("stacks/#{current_grid}", @stack)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative 'common'
|
2
|
+
|
3
|
+
module Kontena::Cli::Stacks
|
4
|
+
class DeployCommand < Clamp::Command
|
5
|
+
include Kontena::Cli::Common
|
6
|
+
include Kontena::Cli::GridOptions
|
7
|
+
include Common
|
8
|
+
|
9
|
+
parameter "NAME", "Stack name"
|
10
|
+
|
11
|
+
def execute
|
12
|
+
require_api_url
|
13
|
+
require_token
|
14
|
+
|
15
|
+
deploy_stack(name)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
|
21
|
+
def deploy_stack
|
22
|
+
client(token).post("stacks/#{current_grid}/#{name}/deploy", {})
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative 'common'
|
2
|
+
|
3
|
+
module Kontena::Cli::Stacks
|
4
|
+
class ListCommand < Clamp::Command
|
5
|
+
include Kontena::Cli::Common
|
6
|
+
include Kontena::Cli::GridOptions
|
7
|
+
include Common
|
8
|
+
|
9
|
+
COLUMNS = "%-30s %-10s %-10s".freeze
|
10
|
+
|
11
|
+
def execute
|
12
|
+
require_api_url
|
13
|
+
require_token
|
14
|
+
|
15
|
+
list_stacks
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def list_stacks
|
21
|
+
response = client(token).get("stacks/#{current_grid}")
|
22
|
+
|
23
|
+
titles = ['NAME', 'SERVICES', 'STATE']
|
24
|
+
puts COLUMNS % titles
|
25
|
+
|
26
|
+
response['stacks'].each do |stack|
|
27
|
+
vars = [
|
28
|
+
stack['name'],
|
29
|
+
stack['grid_services'].size,
|
30
|
+
stack['state']
|
31
|
+
]
|
32
|
+
|
33
|
+
puts COLUMNS % vars
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative 'common'
|
2
|
+
|
3
|
+
module Kontena::Cli::Stacks
|
4
|
+
class RemoveCommand < Clamp::Command
|
5
|
+
include Kontena::Cli::Common
|
6
|
+
include Kontena::Cli::GridOptions
|
7
|
+
include Common
|
8
|
+
|
9
|
+
parameter "NAME", "Service name"
|
10
|
+
|
11
|
+
def execute
|
12
|
+
require_api_url
|
13
|
+
require_token
|
14
|
+
|
15
|
+
remove_stack(name)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
|
21
|
+
def remove_stack(name)
|
22
|
+
client(token).delete("stacks/#{current_grid}/#{name}")
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative 'common'
|
2
|
+
|
3
|
+
module Kontena::Cli::Stacks
|
4
|
+
class ShowCommand < Clamp::Command
|
5
|
+
include Kontena::Cli::Common
|
6
|
+
include Kontena::Cli::GridOptions
|
7
|
+
include Common
|
8
|
+
|
9
|
+
parameter "NAME", "Service name"
|
10
|
+
|
11
|
+
def execute
|
12
|
+
require_api_url
|
13
|
+
require_token
|
14
|
+
|
15
|
+
show_stack(name)
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def show_stack(name)
|
22
|
+
stack = client(token).get("stacks/#{current_grid}/#{name}")
|
23
|
+
|
24
|
+
puts stack
|
25
|
+
|
26
|
+
puts "#{stack['id']}:"
|
27
|
+
puts " state: #{stack['state']}"
|
28
|
+
puts " created_at: #{stack['created_at']}"
|
29
|
+
puts " updated_at: #{stack['updated_at']}"
|
30
|
+
puts " version: #{stack['version']}"
|
31
|
+
puts " services:"
|
32
|
+
stack['grid_services'].each do |service|
|
33
|
+
puts " id: #{service['id']}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|