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.
Files changed (166) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -1
  3. data/VERSION +1 -1
  4. data/bin/kontena +3 -50
  5. data/examples/kontena-plugin-hello/.gitignore +9 -0
  6. data/examples/kontena-plugin-hello/Gemfile +4 -0
  7. data/examples/kontena-plugin-hello/README.md +3 -0
  8. data/examples/kontena-plugin-hello/bin/console +14 -0
  9. data/examples/kontena-plugin-hello/bin/setup +8 -0
  10. data/examples/kontena-plugin-hello/kontena-plugin-hello.gemspec +22 -0
  11. data/examples/kontena-plugin-hello/lib/kontena/plugin/hello.rb +7 -0
  12. data/examples/kontena-plugin-hello/lib/kontena/plugin/hello/world_command.rb +6 -0
  13. data/examples/kontena-plugin-hello/lib/kontena/plugin/hello_command.rb +9 -0
  14. data/examples/kontena-plugin-hello/lib/kontena_cli_plugin.rb +5 -0
  15. data/kontena-cli.gemspec +1 -3
  16. data/lib/kontena/cli/apps/build_command.rb +3 -0
  17. data/lib/kontena/cli/apps/common.rb +6 -1
  18. data/lib/kontena/cli/apps/deploy_command.rb +1 -1
  19. data/lib/kontena/cli/apps/docker_helper.rb +13 -14
  20. data/lib/kontena/cli/apps/service_generator.rb +19 -11
  21. data/lib/kontena/cli/apps/service_generator_v2.rb +1 -0
  22. data/lib/kontena/cli/apps/yaml/reader.rb +15 -0
  23. data/lib/kontena/cli/apps/yaml/service_extender.rb +28 -0
  24. data/lib/kontena/cli/apps/yaml/validations.rb +38 -24
  25. data/lib/kontena/cli/apps/yaml/validator.rb +7 -7
  26. data/lib/kontena/cli/apps/yaml/validator_v2.rb +7 -6
  27. data/lib/kontena/cli/certificate/authorize_command.rb +23 -0
  28. data/lib/kontena/cli/certificate/get_command.rb +25 -0
  29. data/lib/kontena/cli/certificate/register_command.rb +19 -0
  30. data/lib/kontena/cli/certificate_command.rb +14 -0
  31. data/lib/kontena/cli/containers/containers_helper.rb +22 -0
  32. data/lib/kontena/cli/containers/exec_command.rb +9 -2
  33. data/lib/kontena/cli/grids/logs_command.rb +14 -3
  34. data/lib/kontena/cli/master_command.rb +1 -12
  35. data/lib/kontena/cli/node_command.rb +0 -16
  36. data/lib/kontena/cli/plugin_command.rb +15 -0
  37. data/lib/kontena/cli/plugins/install_command.rb +28 -0
  38. data/lib/kontena/cli/plugins/list_command.rb +13 -0
  39. data/lib/kontena/cli/plugins/search_command.rb +29 -0
  40. data/lib/kontena/cli/plugins/uninstall_command.rb +30 -0
  41. data/lib/kontena/cli/registry/create_command.rb +1 -1
  42. data/lib/kontena/cli/services/create_command.rb +16 -0
  43. data/lib/kontena/cli/services/list_command.rb +17 -3
  44. data/lib/kontena/cli/services/logs_command.rb +63 -18
  45. data/lib/kontena/cli/services/services_helper.rb +47 -4
  46. data/lib/kontena/cli/services/update_command.rb +16 -0
  47. data/lib/kontena/cli/stack_command.rb +20 -0
  48. data/lib/kontena/cli/stacks/common.rb +39 -0
  49. data/lib/kontena/cli/stacks/create_command.rb +27 -0
  50. data/lib/kontena/cli/stacks/deploy_command.rb +26 -0
  51. data/lib/kontena/cli/stacks/list_command.rb +38 -0
  52. data/lib/kontena/cli/stacks/remove_command.rb +26 -0
  53. data/lib/kontena/cli/stacks/show_command.rb +38 -0
  54. data/lib/kontena/cli/stacks/update_command.rb +27 -0
  55. data/lib/kontena/client.rb +11 -4
  56. data/lib/kontena/command.rb +4 -0
  57. data/lib/kontena/main_command.rb +61 -0
  58. data/lib/kontena/plugin_manager.rb +38 -0
  59. data/lib/kontena/util.rb +17 -0
  60. data/lib/kontena_cli.rb +6 -0
  61. data/spec/fixtures/health.yml +26 -0
  62. data/spec/fixtures/kontena-build.yml +16 -0
  63. data/spec/fixtures/kontena_build_v2.yaml +26 -0
  64. data/spec/kontena/cli/app/build_command_spec.rb +13 -1
  65. data/spec/kontena/cli/app/common_spec.rb +11 -0
  66. data/spec/kontena/cli/app/deploy_command_spec.rb +1 -1
  67. data/spec/kontena/cli/app/docker_helper_spec.rb +45 -0
  68. data/spec/kontena/cli/app/service_generator_spec.rb +52 -1
  69. data/spec/kontena/cli/app/yaml/service_extender_spec.rb +24 -0
  70. data/spec/kontena/cli/app/yaml/validator_spec.rb +97 -14
  71. data/spec/kontena/cli/common_spec.rb +0 -5
  72. data/spec/kontena/cli/containers/containers_helper_spec.rb +16 -0
  73. data/spec/kontena/cli/services/services_helper_spec.rb +50 -1
  74. data/spec/kontena/cli/version_command_spec.rb +1 -1
  75. data/spec/kontena/client_spec.rb +156 -0
  76. data/spec/kontena/plugin_manager_spec.rb +22 -0
  77. data/spec/spec_helper.rb +1 -0
  78. metadata +54 -125
  79. data/lib/kontena/cli/master/aws/create_command.rb +0 -48
  80. data/lib/kontena/cli/master/aws_command.rb +0 -8
  81. data/lib/kontena/cli/master/azure/create_command.rb +0 -37
  82. data/lib/kontena/cli/master/azure_command.rb +0 -13
  83. data/lib/kontena/cli/master/digital_ocean/create_command.rb +0 -38
  84. data/lib/kontena/cli/master/digital_ocean_command.rb +0 -13
  85. data/lib/kontena/cli/master/packet/create_command.rb +0 -42
  86. data/lib/kontena/cli/master/packet_command.rb +0 -14
  87. data/lib/kontena/cli/master/upcloud/create_command.rb +0 -39
  88. data/lib/kontena/cli/master/upcloud_command.rb +0 -13
  89. data/lib/kontena/cli/master/vagrant/create_command.rb +0 -25
  90. data/lib/kontena/cli/master/vagrant/restart_command.rb +0 -20
  91. data/lib/kontena/cli/master/vagrant/ssh_command.rb +0 -15
  92. data/lib/kontena/cli/master/vagrant/start_command.rb +0 -20
  93. data/lib/kontena/cli/master/vagrant/stop_command.rb +0 -20
  94. data/lib/kontena/cli/master/vagrant/terminate_command.rb +0 -13
  95. data/lib/kontena/cli/master/vagrant_command.rb +0 -23
  96. data/lib/kontena/cli/nodes/aws/create_command.rb +0 -44
  97. data/lib/kontena/cli/nodes/aws/restart_command.rb +0 -29
  98. data/lib/kontena/cli/nodes/aws/terminate_command.rb +0 -21
  99. data/lib/kontena/cli/nodes/aws_command.rb +0 -15
  100. data/lib/kontena/cli/nodes/azure/create_command.rb +0 -38
  101. data/lib/kontena/cli/nodes/azure/restart_command.rb +0 -32
  102. data/lib/kontena/cli/nodes/azure/terminate_command.rb +0 -21
  103. data/lib/kontena/cli/nodes/azure_command.rb +0 -15
  104. data/lib/kontena/cli/nodes/digital_ocean/create_command.rb +0 -32
  105. data/lib/kontena/cli/nodes/digital_ocean/restart_command.rb +0 -27
  106. data/lib/kontena/cli/nodes/digital_ocean/terminate_command.rb +0 -19
  107. data/lib/kontena/cli/nodes/digital_ocean_command.rb +0 -15
  108. data/lib/kontena/cli/nodes/packet/create_command.rb +0 -35
  109. data/lib/kontena/cli/nodes/packet/restart_command.rb +0 -17
  110. data/lib/kontena/cli/nodes/packet/terminate_command.rb +0 -20
  111. data/lib/kontena/cli/nodes/packet_command.rb +0 -15
  112. data/lib/kontena/cli/nodes/upcloud/create_command.rb +0 -33
  113. data/lib/kontena/cli/nodes/upcloud/restart_command.rb +0 -20
  114. data/lib/kontena/cli/nodes/upcloud/terminate_command.rb +0 -20
  115. data/lib/kontena/cli/nodes/upcloud_command.rb +0 -15
  116. data/lib/kontena/cli/nodes/vagrant/create_command.rb +0 -27
  117. data/lib/kontena/cli/nodes/vagrant/restart_command.rb +0 -26
  118. data/lib/kontena/cli/nodes/vagrant/ssh_command.rb +0 -21
  119. data/lib/kontena/cli/nodes/vagrant/start_command.rb +0 -26
  120. data/lib/kontena/cli/nodes/vagrant/stop_command.rb +0 -26
  121. data/lib/kontena/cli/nodes/vagrant/terminate_command.rb +0 -17
  122. data/lib/kontena/cli/nodes/vagrant_command.rb +0 -21
  123. data/lib/kontena/machine/aws.rb +0 -13
  124. data/lib/kontena/machine/aws/cloudinit.yml +0 -71
  125. data/lib/kontena/machine/aws/cloudinit_master.yml +0 -118
  126. data/lib/kontena/machine/aws/common.rb +0 -58
  127. data/lib/kontena/machine/aws/master_provisioner.rb +0 -187
  128. data/lib/kontena/machine/aws/node_destroyer.rb +0 -51
  129. data/lib/kontena/machine/aws/node_provisioner.rb +0 -204
  130. data/lib/kontena/machine/azure.rb +0 -13
  131. data/lib/kontena/machine/azure/cloudinit.yml +0 -64
  132. data/lib/kontena/machine/azure/cloudinit_master.yml +0 -106
  133. data/lib/kontena/machine/azure/logger.rb +0 -27
  134. data/lib/kontena/machine/azure/master_provisioner.rb +0 -128
  135. data/lib/kontena/machine/azure/node_destroyer.rb +0 -53
  136. data/lib/kontena/machine/azure/node_provisioner.rb +0 -132
  137. data/lib/kontena/machine/digital_ocean.rb +0 -13
  138. data/lib/kontena/machine/digital_ocean/cloudinit.yml +0 -64
  139. data/lib/kontena/machine/digital_ocean/cloudinit_master.yml +0 -118
  140. data/lib/kontena/machine/digital_ocean/master_provisioner.rb +0 -99
  141. data/lib/kontena/machine/digital_ocean/node_destroyer.rb +0 -40
  142. data/lib/kontena/machine/digital_ocean/node_provisioner.rb +0 -88
  143. data/lib/kontena/machine/packet.rb +0 -17
  144. data/lib/kontena/machine/packet/cloudinit.yml +0 -66
  145. data/lib/kontena/machine/packet/cloudinit_master.yml +0 -118
  146. data/lib/kontena/machine/packet/master_provisioner.rb +0 -93
  147. data/lib/kontena/machine/packet/node_destroyer.rb +0 -42
  148. data/lib/kontena/machine/packet/node_provisioner.rb +0 -77
  149. data/lib/kontena/machine/packet/node_restarter.rb +0 -41
  150. data/lib/kontena/machine/packet/packet_common.rb +0 -89
  151. data/lib/kontena/machine/upcloud.rb +0 -9
  152. data/lib/kontena/machine/upcloud/cloudinit.yml +0 -64
  153. data/lib/kontena/machine/upcloud/cloudinit_master.yml +0 -118
  154. data/lib/kontena/machine/upcloud/master_provisioner.rb +0 -138
  155. data/lib/kontena/machine/upcloud/node_destroyer.rb +0 -85
  156. data/lib/kontena/machine/upcloud/node_provisioner.rb +0 -121
  157. data/lib/kontena/machine/upcloud/node_restarter.rb +0 -49
  158. data/lib/kontena/machine/upcloud/upcloud_common.rb +0 -74
  159. data/lib/kontena/machine/vagrant.rb +0 -12
  160. data/lib/kontena/machine/vagrant/Vagrantfile.master.rb.erb +0 -104
  161. data/lib/kontena/machine/vagrant/Vagrantfile.node.rb.erb +0 -32
  162. data/lib/kontena/machine/vagrant/cloudinit.yml +0 -73
  163. data/lib/kontena/machine/vagrant/master_destroyer.rb +0 -37
  164. data/lib/kontena/machine/vagrant/master_provisioner.rb +0 -79
  165. data/lib/kontena/machine/vagrant/node_destroyer.rb +0 -40
  166. 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
- last_id = nil
19
- loop do
20
- query_params = []
21
- query_params << "limit=#{lines}"
22
- query_params << "from=#{last_id}" unless last_id.nil?
23
- query_params << "since=#{since}" if !since.nil? && last_id.nil?
24
- query_params << "container=#{name}-#{instance}" if instance
25
-
26
- result = client(token).get("services/#{current_grid}/#{name}/container_logs?#{query_params.join('&')}")
27
- result['logs'].each do |log|
28
- color = color_for_container(log['name'])
29
- instance_number = log['name'].match(/^.+-(\d+)$/)[1]
30
- name = instance_number.nil? ? log['name'] : instance_number
31
- prefix = "#{log['created_at']} [#{name}]:".colorize(color)
32
- puts "#{prefix} #{log['data']}"
33
- last_id = log['id']
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
- node_port, container_port, protocol = p.split(':')
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
- container_port: container_port,
260
- node_port: node_port,
261
- protocol: protocol || 'tcp'
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