kontena-cli 0.9.3 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/bin/kontena +3 -2
  4. data/lib/kontena/cli/app_command.rb +6 -2
  5. data/lib/kontena/cli/apps/build_command.rb +0 -1
  6. data/lib/kontena/cli/apps/common.rb +1 -0
  7. data/lib/kontena/cli/apps/deploy_command.rb +17 -13
  8. data/lib/kontena/cli/apps/init_command.rb +1 -2
  9. data/lib/kontena/cli/apps/list_command.rb +13 -5
  10. data/lib/kontena/cli/apps/logs_command.rb +22 -13
  11. data/lib/kontena/cli/apps/monitor_command.rb +91 -0
  12. data/lib/kontena/cli/apps/remove_command.rb +0 -2
  13. data/lib/kontena/cli/apps/scale_command.rb +32 -0
  14. data/lib/kontena/cli/apps/show_command.rb +22 -0
  15. data/lib/kontena/cli/apps/start_command.rb +0 -1
  16. data/lib/kontena/cli/apps/stop_command.rb +0 -1
  17. data/lib/kontena/cli/common.rb +12 -0
  18. data/lib/kontena/cli/containers/inspect_command.rb +8 -3
  19. data/lib/kontena/cli/etcd/common.rb +8 -0
  20. data/lib/kontena/cli/etcd/get_command.rb +4 -0
  21. data/lib/kontena/cli/etcd/list_command.rb +4 -0
  22. data/lib/kontena/cli/etcd/mkdir_command.rb +5 -0
  23. data/lib/kontena/cli/etcd/remove_command.rb +5 -0
  24. data/lib/kontena/cli/etcd/set_command.rb +5 -0
  25. data/lib/kontena/cli/grid_command.rb +2 -0
  26. data/lib/kontena/cli/grids/env_command.rb +22 -0
  27. data/lib/kontena/cli/grids/logs_command.rb +12 -1
  28. data/lib/kontena/cli/node_command.rb +2 -0
  29. data/lib/kontena/cli/nodes/ssh_command.rb +30 -0
  30. data/lib/kontena/cli/service_command.rb +4 -0
  31. data/lib/kontena/cli/services/create_command.rb +9 -0
  32. data/lib/kontena/cli/services/deploy_command.rb +1 -7
  33. data/lib/kontena/cli/services/envs_command.rb +19 -0
  34. data/lib/kontena/cli/services/list_command.rb +15 -3
  35. data/lib/kontena/cli/services/monitor_command.rb +57 -0
  36. data/lib/kontena/cli/services/scale_command.rb +2 -6
  37. data/lib/kontena/cli/services/services_helper.rb +94 -43
  38. data/lib/kontena/cli/services/update_command.rb +12 -1
  39. data/lib/kontena/machine/aws/cloudinit_master.yml +2 -2
  40. data/lib/kontena/machine/azure/cloudinit_master.yml +2 -2
  41. data/lib/kontena/machine/digital_ocean/cloudinit_master.yml +2 -2
  42. data/lib/kontena/scripts/completer +4 -2
  43. data/spec/kontena/cli/app/deploy_command_spec.rb +24 -7
  44. data/spec/kontena/cli/app/scale_spec.rb +64 -0
  45. data/spec/kontena/cli/services/services_helper_spec.rb +0 -7
  46. metadata +12 -2
@@ -0,0 +1,8 @@
1
+ module Kontena::Cli::Etcd
2
+ module Common
3
+
4
+ def validate_key
5
+ abort("Invalid key, did you mean /#{key} ?") unless key[0] == '/'
6
+ end
7
+ end
8
+ end
@@ -1,13 +1,17 @@
1
+ require_relative 'common'
1
2
 
2
3
  module Kontena::Cli::Etcd
3
4
  class GetCommand < Clamp::Command
4
5
  include Kontena::Cli::Common
6
+ include Common
5
7
 
6
8
  parameter "KEY", "Etcd key"
7
9
 
8
10
  def execute
9
11
  require_api_url
10
12
  token = require_token
13
+ validate_key
14
+
11
15
  response = client(token).get("etcd/#{current_grid}/#{key}")
12
16
  if response['value']
13
17
  puts response['value']
@@ -1,7 +1,9 @@
1
+ require_relative 'common'
1
2
 
2
3
  module Kontena::Cli::Etcd
3
4
  class ListCommand < Clamp::Command
4
5
  include Kontena::Cli::Common
6
+ include Common
5
7
 
6
8
  parameter "KEY", "Etcd key"
7
9
 
@@ -10,6 +12,8 @@ module Kontena::Cli::Etcd
10
12
  def execute
11
13
  require_api_url
12
14
  token = require_token
15
+ validate_key
16
+
13
17
  opts = []
14
18
  opts << 'recursive=true' if recursive?
15
19
  response = client(token).get("etcd/#{current_grid}/#{key}?#{opts.join('&')}")
@@ -1,12 +1,17 @@
1
+ require_relative 'common'
2
+
1
3
  module Kontena::Cli::Etcd
2
4
  class MkdirCommand < Clamp::Command
3
5
  include Kontena::Cli::Common
6
+ include Common
4
7
 
5
8
  parameter "KEY", "Etcd key"
6
9
 
7
10
  def execute
8
11
  require_api_url
9
12
  token = require_token
13
+ validate_key
14
+
10
15
  data = {}
11
16
  response = client(token).post("etcd/#{current_grid}/#{key}", data)
12
17
  if response['error']
@@ -1,6 +1,9 @@
1
+ require_relative 'common'
2
+
1
3
  module Kontena::Cli::Etcd
2
4
  class RemoveCommand < Clamp::Command
3
5
  include Kontena::Cli::Common
6
+ include Common
4
7
 
5
8
  parameter "KEY", "Etcd key"
6
9
 
@@ -9,6 +12,8 @@ module Kontena::Cli::Etcd
9
12
  def execute
10
13
  require_api_url
11
14
  token = require_token
15
+ validate_key
16
+
12
17
  data = {}
13
18
  data[:recursive] = true if recursive?
14
19
  response = client(token).delete("etcd/#{current_grid}/#{key}", data)
@@ -1,6 +1,9 @@
1
+ require_relative 'common'
2
+
1
3
  module Kontena::Cli::Etcd
2
4
  class SetCommand < Clamp::Command
3
5
  include Kontena::Cli::Common
6
+ include Common
4
7
 
5
8
  parameter "KEY", "Etcd key"
6
9
  parameter "VALUE", "Etcd value"
@@ -8,6 +11,8 @@ module Kontena::Cli::Etcd
8
11
  def execute
9
12
  require_api_url
10
13
  token = require_token
14
+ validate_key
15
+
11
16
  data = {value: value}
12
17
  response = client(token).post("etcd/#{current_grid}/#{key}", data)
13
18
  if response['error']
@@ -5,6 +5,7 @@ require_relative 'grids/show_command'
5
5
  require_relative 'grids/logs_command'
6
6
  require_relative 'grids/remove_command'
7
7
  require_relative 'grids/current_command'
8
+ require_relative 'grids/env_command'
8
9
  require_relative 'grids/audit_log_command'
9
10
  require_relative 'grids/list_users_command'
10
11
  require_relative 'grids/add_user_command'
@@ -19,6 +20,7 @@ class Kontena::Cli::GridCommand < Clamp::Command
19
20
  subcommand "logs", "Show logs from grid containers", Kontena::Cli::Grids::LogsCommand
20
21
  subcommand "remove", "Remove a grid", Kontena::Cli::Grids::RemoveCommand
21
22
  subcommand "current", "Show current grid details", Kontena::Cli::Grids::CurrentCommand
23
+ subcommand "env", "Show the current grid environment details", Kontena::Cli::Grids::EnvCommand
22
24
  subcommand "audit-log", "Show audit log of the current grid", Kontena::Cli::Grids::AuditLogCommand
23
25
  subcommand "list-users", "List current grid users", Kontena::Cli::Grids::ListUsersCommand
24
26
  subcommand "add-user", "Add user to the current grid", Kontena::Cli::Grids::AddUserCommand
@@ -0,0 +1,22 @@
1
+ require_relative 'common'
2
+
3
+ module Kontena::Cli::Grids
4
+ class EnvCommand < Clamp::Command
5
+ include Kontena::Cli::Common
6
+ include Common
7
+
8
+ option ["-e", "--export"], :flag, "Add export", default: false
9
+
10
+ def execute
11
+ require_api_url
12
+ if current_grid.nil?
13
+ abort 'No grid selected. To select grid, please run: kontena grid use <grid name>'
14
+ else
15
+ grid = client(require_token).get("grids/#{current_grid}")
16
+ prefix = export? ? 'export ' : ''
17
+ puts "#{prefix}KONTENA_URI=#{settings['server']['url'].sub('http', 'ws')}"
18
+ puts "#{prefix}KONTENA_TOKEN=#{grid['token']}"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -22,6 +22,7 @@ module Kontena::Cli::Grids
22
22
 
23
23
 
24
24
  if follow?
25
+ @buffer = ''
25
26
  query_params[:follow] = 1
26
27
  stream_logs(token, query_params)
27
28
  else
@@ -39,7 +40,17 @@ module Kontena::Cli::Grids
39
40
 
40
41
  def stream_logs(token, query_params)
41
42
  streamer = lambda do |chunk, remaining_bytes, total_bytes|
42
- log = JSON.parse(chunk)
43
+ begin
44
+ unless @buffer.empty?
45
+ chunk = @buffer + chunk
46
+ end
47
+ unless chunk.empty?
48
+ log = JSON.parse(chunk)
49
+ end
50
+ @buffer = ''
51
+ rescue => exc
52
+ @buffer << chunk
53
+ end
43
54
  if log
44
55
  color = color_for_container(log['name'])
45
56
  puts "#{log['name'].colorize(color)} | #{log['data']}"
@@ -2,6 +2,7 @@ require_relative 'nodes/list_command'
2
2
  require_relative 'nodes/remove_command'
3
3
  require_relative 'nodes/show_command'
4
4
  require_relative 'nodes/update_command'
5
+ require_relative 'nodes/ssh_command'
5
6
 
6
7
  require_relative 'nodes/vagrant_command'
7
8
  require_relative 'nodes/digital_ocean_command'
@@ -12,6 +13,7 @@ class Kontena::Cli::NodeCommand < Clamp::Command
12
13
 
13
14
  subcommand "list", "List grid nodes", Kontena::Cli::Nodes::ListCommand
14
15
  subcommand "show", "Show node", Kontena::Cli::Nodes::ShowCommand
16
+ subcommand "ssh", "Ssh into node", Kontena::Cli::Nodes::SshCommand
15
17
  subcommand "update", "Update node", Kontena::Cli::Nodes::UpdateCommand
16
18
  subcommand "remove", "Remove node", Kontena::Cli::Nodes::RemoveCommand
17
19
 
@@ -0,0 +1,30 @@
1
+ module Kontena::Cli::Nodes
2
+ class SshCommand < Clamp::Command
3
+ include Kontena::Cli::Common
4
+
5
+ parameter "NODE_ID", "Node id"
6
+ option ["-i", "--identity-file"], "IDENTITY_FILE", "Path to ssh private key"
7
+ option ["-u", "--user"], "USER", "Login as a user", default: "core"
8
+ option "--private-ip", :flag, "Connect to node's private IP address"
9
+ option "--internal-ip", :flag, "Connect to node's internal IP address (requires VPN connection)"
10
+
11
+ def execute
12
+ require_api_url
13
+ require_current_grid
14
+ token = require_token
15
+
16
+ node = client(token).get("grids/#{current_grid}/nodes/#{node_id}")
17
+ cmd = ['ssh']
18
+ cmd << "-i #{identity_file}" if identity_file
19
+ if internal_ip?
20
+ ip = "10.81.0.#{node['node_number']}"
21
+ elsif private_ip?
22
+ ip = node['private_ip']
23
+ else
24
+ ip = node['public_ip']
25
+ end
26
+ cmd << "#{user}@#{ip}"
27
+ exec(cmd.join(" "))
28
+ end
29
+ end
30
+ end
@@ -11,8 +11,10 @@ require_relative 'services/delete_command'
11
11
  require_relative 'services/containers_command'
12
12
  require_relative 'services/logs_command'
13
13
  require_relative 'services/stats_command'
14
+ require_relative 'services/envs_command'
14
15
  require_relative 'services/add_env_command'
15
16
  require_relative 'services/remove_env_command'
17
+ require_relative 'services/monitor_command'
16
18
 
17
19
  class Kontena::Cli::ServiceCommand < Clamp::Command
18
20
 
@@ -29,8 +31,10 @@ class Kontena::Cli::ServiceCommand < Clamp::Command
29
31
  subcommand "containers", "List service containers", Kontena::Cli::Services::ContainersCommand
30
32
  subcommand "logs", "Show service logs", Kontena::Cli::Services::LogsCommand
31
33
  subcommand "stats", "Show service statistics", Kontena::Cli::Services::StatsCommand
34
+ subcommand "envs", "Show environment variables", Kontena::Cli::Services::EnvsCommand
32
35
  subcommand "add-env", "Add environment variable", Kontena::Cli::Services::AddEnvCommand
33
36
  subcommand "remove-env", "Remove environment variable", Kontena::Cli::Services::RemoveEnvCommand
37
+ subcommand "monitor", "Monitor", Kontena::Cli::Services::MonitorCommand
34
38
 
35
39
  def execute
36
40
  end
@@ -27,6 +27,10 @@ module Kontena::Cli::Services
27
27
  option "--net", "NET", "Network mode"
28
28
  option "--log-driver", "LOG_DRIVER", "Set logging driver"
29
29
  option "--log-opt", "LOG_OPT", "Add logging options", multivalued: true
30
+ option "--deploy-strategy", "STRATEGY", "Deploy strategy to use (ha, random)"
31
+ option "--deploy-wait-for-port", "PORT", "Wait for port to respond when deploying"
32
+ option "--deploy-min-health", "FLOAT", "The minimum percentage (0.0 - 1.0) of healthy instances that do not sacrifice overall service availability while deploying"
33
+ option "--pid", "PID", "Pid namespace to use"
30
34
 
31
35
  def execute
32
36
  require_api_url
@@ -64,6 +68,11 @@ module Kontena::Cli::Services
64
68
  data[:net] = net if net
65
69
  data[:log_driver] = log_driver if log_driver
66
70
  data[:log_opts] = parse_log_opts(log_opt_list)
71
+ data[:strategy] = deploy_strategy if deploy_strategy
72
+ data[:deploy_opts] = {}
73
+ data[:deploy_opts][:min_health] = deploy_min_health.to_f if deploy_min_health
74
+ data[:deploy_opts][:wait_for_port] = deploy_wait_for_port.to_i if deploy_wait_for_port
75
+ data[:pid] = pid if pid
67
76
  data
68
77
  end
69
78
  end
@@ -6,18 +6,12 @@ module Kontena::Cli::Services
6
6
  include ServicesHelper
7
7
 
8
8
  parameter "NAME", "Service name"
9
- option '--strategy', 'STRATEGY', 'Define deploy strategy (ha / random)'
10
- option '--wait-for-port', 'WAIT_FOR_PORT', 'Wait for given container port to open before deploying next container'
11
9
 
12
10
  def execute
13
11
  require_api_url
14
12
  token = require_token
15
13
  service_id = name
16
- data = {}
17
- data[:strategy] = strategy if strategy
18
- data[:wait_for_port] = wait_for_port if wait_for_port
19
- deploy_service(token, service_id, data)
20
- show_service(token, service_id)
14
+ deploy_service(token, service_id, {})
21
15
  end
22
16
  end
23
17
  end
@@ -0,0 +1,19 @@
1
+ require_relative 'services_helper'
2
+
3
+ module Kontena::Cli::Services
4
+ class EnvsCommand < Clamp::Command
5
+ include Kontena::Cli::Common
6
+ include ServicesHelper
7
+
8
+ parameter "NAME", "Service name"
9
+
10
+ def execute
11
+ require_api_url
12
+ token = require_token
13
+ service = client(token).get("services/#{parse_service_id(name)}")
14
+ service["env"].each do |env|
15
+ puts env
16
+ end
17
+ end
18
+ end
19
+ end
@@ -10,10 +10,22 @@ module Kontena::Cli::Services
10
10
  token = require_token
11
11
 
12
12
  grids = client(token).get("grids/#{current_grid}/services")
13
- puts "%-30.30s %-40.40s %-10s %-8s" % ['NAME', 'IMAGE', 'INSTANCES', 'STATEFUL']
13
+ titles = ['NAME', 'IMAGE', 'INSTANCES', 'STATEFUL', 'STATE']
14
+ puts "%-30.30s %-50.50s %-10s %-8s %-10s" % titles
14
15
  grids['services'].each do |service|
15
- state = service['stateful'] ? 'yes' : 'no'
16
- puts "%-30.30s %-40.40s %-10.10s %-8s" % [service['name'], service['image'], service['container_count'], state]
16
+ stateful = service['stateful'] ? 'yes' : 'no'
17
+ image = service['image']
18
+ if image.length > 50
19
+ image = image[0..10] << '...' << image[-35..-1]
20
+ end
21
+ vars = [
22
+ service['name'],
23
+ image,
24
+ service['container_count'],
25
+ stateful,
26
+ service['state']
27
+ ]
28
+ puts "%-30.30s %-50.50s %-10.10s %-8s %-10s" % vars
17
29
  end
18
30
  end
19
31
  end
@@ -0,0 +1,57 @@
1
+ require_relative 'services_helper'
2
+
3
+ module Kontena::Cli::Services
4
+ class MonitorCommand < Clamp::Command
5
+ include Kontena::Cli::Common
6
+ include ServicesHelper
7
+
8
+ parameter "NAME", "Service name"
9
+ option "--interval", "SECONDS", "How often view is refreshed", default: 2
10
+
11
+ def execute
12
+ require_api_url
13
+ token = require_token
14
+
15
+ loop do
16
+ nodes = {}
17
+ service = client(token).get("services/#{current_grid}/#{name}")
18
+ result = client(token).get("services/#{current_grid}/#{name}/containers")
19
+ result['containers'].each do |container|
20
+ nodes[container['node']['name']] ||= []
21
+ nodes[container['node']['name']] << container
22
+ end
23
+ clear_terminal
24
+ puts "service: #{name} (#{result['containers'].size}/#{service['container_count']} instances)"
25
+ puts "strategy: #{service['strategy']}"
26
+ puts "status: #{service['state']}"
27
+ puts "stateful: #{service['stateful'] == true ? 'yes' : 'no' }"
28
+ puts "nodes:"
29
+ node_names = nodes.keys.sort
30
+ node_names.each do |name|
31
+ containers = nodes[name]
32
+ puts " #{name} (#{containers.size} instances)"
33
+ print " "
34
+ containers.each do |container|
35
+ color = container['status']
36
+ if container['status'] == 'running'
37
+ color = :green
38
+ elsif container['status'] == 'killed'
39
+ color = :red
40
+ elsif container['status'] == 'stopped'
41
+ color = :gray
42
+ else
43
+ color = :yellow
44
+ end
45
+ print "■".colorize(color)
46
+ end
47
+ puts ''
48
+ end
49
+ sleep interval.to_f
50
+ end
51
+ end
52
+
53
+ def clear_terminal
54
+ print "\e[H\e[2J"
55
+ end
56
+ end
57
+ end
@@ -7,14 +7,10 @@ module Kontena::Cli::Services
7
7
 
8
8
  parameter "NAME", "Service name"
9
9
  parameter "INSTANCES", "Scales service to given number of instances"
10
- option '--strategy', 'STRATEGY', 'Define deploy strategy (ha / random)'
11
10
 
12
11
  def execute
13
- token = require_token
14
- client(token).put("services/#{parse_service_id(name)}", {container_count: instances})
15
- opts = {}
16
- opts[:strategy] = strategy if strategy
17
- deploy_service(token, name, opts)
12
+ token = require_token
13
+ scale_service(token, name, instances)
18
14
  end
19
15
  end
20
16
  end
@@ -22,6 +22,14 @@ module Kontena
22
22
  client(token).put("services/#{param}", data)
23
23
  end
24
24
 
25
+ # @param [String] token
26
+ # @param [String] service_id
27
+ # @param [Integer] instances
28
+ def scale_service(token, service_id, instances)
29
+ param = parse_service_id(service_id)
30
+ client(token).post("services/#{param}/scale", {instances: instances})
31
+ end
32
+
25
33
  # @param [String] token
26
34
  # @param [String] service_id
27
35
  def get_service(token, service_id)
@@ -36,76 +44,126 @@ module Kontena
36
44
  grid = service['id'].split('/')[0]
37
45
  puts "#{service['id']}:"
38
46
  puts " status: #{service['state'] }"
47
+ puts " image: #{service['image']}"
39
48
  puts " stateful: #{service['stateful'] == true ? 'yes' : 'no' }"
40
49
  puts " scaling: #{service['container_count'] }"
41
- puts " image: #{service['image']}"
50
+ puts " strategy: #{service['strategy']}"
51
+ puts " deploy_opts:"
52
+ puts " wait_for_port: #{service['deploy_opts']['wait_for_port'] || '-'}"
53
+ puts " min_health: #{service['deploy_opts']['min_health']}"
42
54
  puts " dns: #{service['name']}.#{grid}.kontena.local"
43
55
 
44
- puts " affinity: "
45
- service['affinity'].to_a.each do |a|
46
- puts " - #{a}"
56
+ if service['affinity'].to_a.size > 0
57
+ puts " affinity: "
58
+ service['affinity'].to_a.each do |a|
59
+ puts " - #{a}"
60
+ end
47
61
  end
48
62
 
49
- if service['cmd']
50
- puts " cmd: #{service['cmd'].join(' ')}"
51
- else
52
- puts " cmd: "
63
+ unless service['cmd'].to_s.empty?
64
+ if service['cmd']
65
+ puts " cmd: #{service['cmd'].join(' ')}"
66
+ else
67
+ puts " cmd: "
68
+ end
69
+ end
70
+
71
+ if service['hooks'].to_a.size > 0
72
+ puts " hooks: "
73
+ service['hooks'].to_a.each do |hook|
74
+ puts " - name: #{hook['name']}"
75
+ puts " type: #{hook['type']}"
76
+ puts " cmd: #{hook['cmd']}"
77
+ puts " oneshot: #{hook['oneshot']}"
78
+ end
53
79
  end
54
80
 
55
- puts " env: "
56
- service['env'].to_a.each{|e| puts " - #{e}"}
81
+ if service['env'].to_a.size > 0
82
+ puts " env: "
83
+ service['env'].to_a.each do |e|
84
+ if e.length > 50
85
+ puts " - #{e[0..50]}..."
86
+ else
87
+ puts " - #{e}"
88
+ end
89
+ end
90
+ end
57
91
 
58
- puts " ports:"
59
- service['ports'].to_a.each do |p|
60
- puts " - #{p['node_port']}:#{p['container_port']}/#{p['protocol']}"
92
+ unless service['net'].to_s.empty?
93
+ puts " net: #{service['net']}"
61
94
  end
62
95
 
63
- puts " volumes:"
64
- service['volumes'].to_a.each do |v|
65
- puts " - #{v}"
96
+ if service['ports'].to_a.size > 0
97
+ puts " ports:"
98
+ service['ports'].to_a.each do |p|
99
+ puts " - #{p['node_port']}:#{p['container_port']}/#{p['protocol']}"
100
+ end
66
101
  end
67
102
 
68
- puts " volumes_from:"
69
- service['volumes_from'].to_a.each do |v|
70
- puts " - #{v}"
103
+ if service['volumes'].to_a.size > 0
104
+ puts " volumes:"
105
+ service['volumes'].to_a.each do |v|
106
+ puts " - #{v}"
107
+ end
108
+ end
109
+
110
+ if service['volumes_from'].to_a.size > 0
111
+ puts " volumes_from:"
112
+ service['volumes_from'].to_a.each do |v|
113
+ puts " - #{v}"
114
+ end
71
115
  end
72
116
 
73
- puts " links: "
74
- service['links'].to_a.each do |l|
75
- puts " - #{l['alias']}"
117
+ if service['links'].to_a.size > 0
118
+ puts " links: "
119
+ service['links'].to_a.each do |l|
120
+ puts " - #{l['alias']}"
121
+ end
76
122
  end
77
123
 
78
- puts " cap_add:"
79
- service['cap_add'].to_a.each do |c|
80
- puts " - #{c}"
124
+ if service['cap_add'].to_a.size > 0
125
+ puts " cap_add:"
126
+ service['cap_add'].to_a.each do |c|
127
+ puts " - #{c}"
128
+ end
81
129
  end
82
130
 
83
- puts " cap_drop:"
84
- service['cap_drop'].to_a.each do |c|
85
- puts " - #{c}"
131
+ if service['cap_drop'].to_a.size > 0
132
+ puts " cap_drop:"
133
+ service['cap_drop'].to_a.each do |c|
134
+ puts " - #{c}"
135
+ end
86
136
  end
87
137
 
88
- puts " log_driver: #{service['log_driver']}"
138
+ unless service['log_driver'].to_s.empty?
139
+ puts " log_driver: #{service['log_driver']}"
140
+ puts " log_opts:"
141
+ service['log_opts'].each do |opt, value|
142
+ puts " #{opt}: #{value}"
143
+ end
144
+ end
89
145
 
90
- puts " log_opts:"
91
- service['log_opts'].each do |opt, value|
92
- puts " #{opt}: #{value}"
146
+ unless service['pid'].to_s.empty?
147
+ puts " pid: #{service['pid']}"
93
148
  end
94
149
 
95
- puts " containers:"
150
+ puts " instances:"
96
151
  result = client(token).get("services/#{parse_service_id(service_id)}/containers")
97
152
  result['containers'].each do |container|
98
153
  puts " #{container['name']}:"
99
154
  puts " rev: #{container['deploy_rev']}"
100
- puts " node: #{container['node']['name']}"
155
+ puts " node: #{container['node']['name'] rescue 'unknown'}"
101
156
  puts " dns: #{container['name']}.#{grid}.kontena.local"
102
- puts " ip: #{container['overlay_cidr'].split('/')[0]}"
103
- puts " public ip: #{container['node']['public_ip']}"
157
+ puts " ip: #{container['overlay_cidr'].to_s.split('/')[0]}"
158
+ puts " public ip: #{container['node']['public_ip'] rescue 'unknown'}"
104
159
  if container['status'] == 'unknown'
105
160
  puts " status: #{container['status'].colorize(:yellow)}"
106
161
  else
107
162
  puts " status: #{container['status']}"
108
163
  end
164
+ if container['state']['error'] && container['state']['error'] != ''
165
+ puts " reason: #{container['state']['error']}"
166
+ end
109
167
  end
110
168
  end
111
169
 
@@ -115,13 +173,6 @@ module Kontena
115
173
  def deploy_service(token, service_id, data)
116
174
  param = parse_service_id(service_id)
117
175
  client(token).post("services/#{param}/deploy", data)
118
- print 'deploying '
119
- until client(token).get("services/#{param}")['state'] != 'deploying' do
120
- print '.'
121
- sleep 1
122
- end
123
- puts ' done'.colorize(:green)
124
- puts ''
125
176
  end
126
177
 
127
178
  # @param [String] token