kontena-cli 1.0.6 → 1.1.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/VERSION +1 -1
  4. data/bin/kontena +4 -1
  5. data/kontena-cli.gemspec +1 -1
  6. data/lib/kontena/callback.rb +1 -1
  7. data/lib/kontena/callbacks/master/01_clear_current_master_after_terminate.rb +1 -1
  8. data/lib/kontena/callbacks/master/deploy/50_authenticate_after_deploy.rb +5 -5
  9. data/lib/kontena/callbacks/master/deploy/55_create_initial_grid_after_deploy.rb +1 -1
  10. data/lib/kontena/callbacks/master/deploy/56_set_server_provider_after_deploy.rb +25 -0
  11. data/lib/kontena/callbacks/master/deploy/70_invite_self_after_deploy.rb +1 -1
  12. data/lib/kontena/cli/common.rb +3 -3
  13. data/lib/kontena/cli/config.rb +1 -1
  14. data/lib/kontena/cli/grid_command.rb +2 -0
  15. data/lib/kontena/cli/grids/common.rb +12 -0
  16. data/lib/kontena/cli/grids/health_command.rb +69 -0
  17. data/lib/kontena/cli/helpers/health_helper.rb +53 -0
  18. data/lib/kontena/cli/localhost_web_server.rb +3 -3
  19. data/lib/kontena/cli/master/users/invite_command.rb +1 -1
  20. data/lib/kontena/cli/node_command.rb +2 -0
  21. data/lib/kontena/cli/nodes/health_command.rb +32 -0
  22. data/lib/kontena/cli/nodes/list_command.rb +40 -26
  23. data/lib/kontena/cli/nodes/show_command.rb +0 -1
  24. data/lib/kontena/cli/plugins/install_command.rb +28 -30
  25. data/lib/kontena/cli/plugins/search_command.rb +6 -14
  26. data/lib/kontena/cli/plugins/uninstall_command.rb +7 -11
  27. data/lib/kontena/cli/services/stats_command.rb +4 -2
  28. data/lib/kontena/cli/spinner.rb +20 -4
  29. data/lib/kontena/cli/stacks/show_command.rb +5 -1
  30. data/lib/kontena/cli/stacks/yaml/opto/service_instances_resolver.rb +22 -0
  31. data/lib/kontena/cli/stacks/yaml/opto/vault_setter.rb +1 -1
  32. data/lib/kontena/cli/stacks/yaml/reader.rb +1 -0
  33. data/lib/kontena/cli/vault/export_command.rb +22 -0
  34. data/lib/kontena/cli/vault/import_command.rb +80 -0
  35. data/lib/kontena/cli/vault/list_command.rb +4 -0
  36. data/lib/kontena/cli/vault/read_command.rb +8 -3
  37. data/lib/kontena/cli/vault/remove_command.rb +2 -1
  38. data/lib/kontena/cli/vault/update_command.rb +5 -7
  39. data/lib/kontena/cli/vault_command.rb +5 -1
  40. data/lib/kontena/client.rb +25 -2
  41. data/lib/kontena/command.rb +1 -1
  42. data/lib/kontena/debug_instrumentor.rb +70 -0
  43. data/lib/kontena/light_prompt.rb +103 -0
  44. data/lib/kontena/plugin_manager.rb +167 -6
  45. data/lib/kontena/stacks_cache.rb +1 -1
  46. data/lib/kontena_cli.rb +23 -6
  47. data/spec/kontena/cli/grids/health_command_spec.rb +390 -0
  48. data/spec/kontena/cli/nodes/health_command_spec.rb +206 -0
  49. data/spec/kontena/cli/nodes/list_command_spec.rb +205 -0
  50. data/spec/kontena/cli/vault/export_spec.rb +32 -0
  51. data/spec/kontena/cli/vault/import_spec.rb +69 -0
  52. data/spec/kontena/client_spec.rb +39 -0
  53. data/spec/kontena/plugin_manager_spec.rb +7 -7
  54. data/spec/spec_helper.rb +1 -0
  55. data/spec/support/output_helpers.rb +51 -0
  56. metadata +27 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 617ed6269bb5d4ebdfa64661b2c5d57513cb05f3
4
- data.tar.gz: 6d9483d2d5d8b7994ebffcc19adcb3505a1c9b0f
3
+ metadata.gz: 3fa4fdfff0c1b90c0954ec7e31f8f916c8636f16
4
+ data.tar.gz: 62e78df6ba2b65b1bfcaacde2290d81719d93e82
5
5
  SHA512:
6
- metadata.gz: 78b0b49d108cc919d604b46f83389bb17bd075d8693940f247f853073d2f422c30afeb32c065f1df06637204dca010c185165e58da03fc733587ef9d8a3bcd13
7
- data.tar.gz: 5d11bfbb81dc4c39fbb42f94f3d1f7b21ed455ab5d05cebfde7a9bd917d1ce894e6d4684688ea5d7ebfecc01e1f0554aa43312167822d968f611b694b6c450c9
6
+ metadata.gz: e2fb585c59f687236071ec28640e487f32e4b4a1426ef9152249bcdd0651dfb96d0250b1ec91df171e9c0c1b650c257c9bb0e9f2039d8fda9b5a553ddda9c55f
7
+ data.tar.gz: 7408e60150cbd48e54549a490af795bb6688af0e01c9969f2f53a20fb8b59417228b3d1fc798e877377a39d28540c9ba8c614a99be110ae86bc74bf07c60716a
data/Dockerfile CHANGED
@@ -1,4 +1,4 @@
1
- FROM alpine:3.4
1
+ FROM alpine:3.5
2
2
  MAINTAINER Kontena, Inc. <info@kontena.io>
3
3
 
4
4
  ADD https://get.docker.com/builds/Linux/x86_64/docker-1.10.3 /usr/local/bin/docker
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.6
1
+ 1.1.0.pre1
data/bin/kontena CHANGED
@@ -12,7 +12,7 @@ require 'kontena_cli'
12
12
  STDOUT.sync = true
13
13
 
14
14
  begin
15
- Kontena::PluginManager.instance.load_plugins
15
+ Kontena::PluginManager.instance.init
16
16
  Kontena::MainCommand.run
17
17
  rescue Excon::Errors::SocketError => exc
18
18
  if exc.message.include?('Unable to verify certificate')
@@ -27,6 +27,9 @@ rescue Kontena::Errors::StandardError => exc
27
27
  raise exc if ENV['DEBUG']
28
28
  puts " [#{Kontena.pastel.red('error')}] #{exc.message}"
29
29
  abort
30
+ rescue Errno::EPIPE
31
+ # If user is piping the command outputs to some other command that might exit before CLI has outputted everything
32
+ abort
30
33
  rescue => exc
31
34
  raise exc if ENV['DEBUG']
32
35
  $stderr.puts " [#{Kontena.pastel.red('error')}] #{exc.message}"
data/kontena-cli.gemspec CHANGED
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency "bundler", "~> 1.7"
24
24
  spec.add_development_dependency "rake", "~> 10.0"
25
25
  spec.add_runtime_dependency "excon", "~> 0.49.0"
26
- spec.add_runtime_dependency "tty-prompt", "~> 0.7.1"
26
+ spec.add_runtime_dependency "tty-prompt", "~> 0.10"
27
27
  spec.add_runtime_dependency "clamp", "~> 1.1.0"
28
28
  spec.add_runtime_dependency "ruby_dig", "~> 0.0.2"
29
29
  spec.add_runtime_dependency "launchy", "~> 2.4.3"
@@ -44,7 +44,7 @@ class Kontena::Callback
44
44
  if klass.instance_methods.include?(state)
45
45
  cb = klass.new(obj)
46
46
  if cb.send(state).kind_of?(FalseClass)
47
- ENV["DEBUG"] && puts("Execution aborted by #{klass}")
47
+ ENV["DEBUG"] && STDERR.puts("Execution aborted by #{klass}")
48
48
  exit 1
49
49
  end
50
50
  end
@@ -10,7 +10,7 @@ module Kontena
10
10
  return unless command.exit_code == 0
11
11
  return unless config.current_master
12
12
 
13
- ENV["DEBUG"] && puts("Removing current master from config")
13
+ ENV["DEBUG"] && STDERR.puts("Removing current master from config")
14
14
  config.servers.delete_at(config.find_server_index(config.current_master.name))
15
15
  config.current_server = nil
16
16
  config.write
@@ -8,8 +8,8 @@ module Kontena
8
8
  matches_commands 'master create'
9
9
 
10
10
  def after
11
- ENV["DEBUG"] && puts("Command result: #{command.result.inspect}")
12
- ENV["DEBUG"] && puts("Command exit code: #{command.exit_code.inspect}")
11
+ ENV["DEBUG"] && STDERR.puts("Command result: #{command.result.inspect}")
12
+ ENV["DEBUG"] && STDERR.puts("Command exit code: #{command.exit_code.inspect}")
13
13
  return unless command.exit_code == 0
14
14
  return unless command.result.kind_of?(Hash)
15
15
  return unless command.result.has_key?(:public_ip)
@@ -35,11 +35,11 @@ module Kontena
35
35
 
36
36
  # Figure out if HTTPS works, if not, try HTTP
37
37
  begin
38
- ENV["DEBUG"] && puts("Trying to request / from #{new_master.url}")
38
+ ENV["DEBUG"] && STDERR.puts("Trying to request / from #{new_master.url}")
39
39
  client = Kontena::Client.new(new_master.url, nil, ignore_ssl_errors: true)
40
40
  client.get('/')
41
41
  rescue
42
- ENV["DEBUG"] && puts("HTTPS test failed: #{$!} #{$!.message}")
42
+ ENV["DEBUG"] && STDERR.puts("HTTPS test failed: #{$!} #{$!.message}")
43
43
  unless retried
44
44
  new_master.url = "http://#{command.result[:public_ip]}"
45
45
  retried = true
@@ -51,7 +51,7 @@ module Kontena
51
51
  require 'shellwords'
52
52
  cmd = "master login --no-login-info --skip-grid-auto-select --verbose --name #{command.result[:name].shellescape} --code #{command.result[:code].shellescape} #{new_master.url.shellescape}"
53
53
  Retriable.retriable do
54
- ENV["DEBUG"] && puts("Running: #{cmd}")
54
+ ENV["DEBUG"] && STDERR.puts("Running: #{cmd}")
55
55
  Kontena.run(cmd)
56
56
  end
57
57
  end
@@ -12,7 +12,7 @@ module Kontena
12
12
  return unless config.current_master.name == command.result[:name]
13
13
 
14
14
  cmd = "grid create --silent test"
15
- ENV["DEBUG"] && puts("Running: #{cmd}")
15
+ ENV["DEBUG"] && STDERR.puts("Running: #{cmd}")
16
16
  Retriable.retriable do
17
17
  Kontena.run(cmd)
18
18
  end
@@ -0,0 +1,25 @@
1
+ module Kontena
2
+ module Callbacks
3
+ class SetServerProviderAfterDeploy < Kontena::Callback
4
+
5
+ include Kontena::Cli::Common
6
+
7
+ matches_commands 'master create'
8
+
9
+ def after
10
+ return unless command.exit_code == 0
11
+ return unless config.current_master
12
+ return unless config.current_master.name == command.result[:name]
13
+ return unless command.result[:provider]
14
+
15
+ require 'shellwords'
16
+
17
+ cmd = ['master', 'config', 'set', "server.provider=#{command.result[:provider]}"]
18
+ spinner "Setting Master configuration server.provider to '#{command.result[:provider]}'" do
19
+ Kontena.run(cmd.shelljoin)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
@@ -40,7 +40,7 @@ module Kontena
40
40
  end
41
41
 
42
42
  return nil unless invite_response
43
- ENV["DEBUG"] && puts("Got invite code: #{invite_response['invite_code']}")
43
+ ENV["DEBUG"] && STDERR.puts("Got invite code: #{invite_response['invite_code']}")
44
44
 
45
45
  role_status = nil
46
46
 
@@ -12,7 +12,7 @@ module Kontena
12
12
 
13
13
  def logger
14
14
  return @logger if @logger
15
- @logger = Logger.new(STDOUT)
15
+ @logger = Logger.new(ENV["DEBUG"] ? STDERR : STDOUT)
16
16
  @logger.level = ENV["DEBUG"].nil? ? Logger::INFO : Logger::DEBUG
17
17
  @logger.progname = 'COMMON'
18
18
  @logger
@@ -129,10 +129,10 @@ module Kontena
129
129
  return unless server.token.refresh_token
130
130
  return if server.token.expired?
131
131
  client = Kontena::Client.new(server.url, server.token)
132
- ENV["DEBUG"] && puts("Trying to invalidate refresh token on #{server.name}")
132
+ logger.debug "Trying to invalidate refresh token on #{server.name}"
133
133
  client.refresh_token
134
134
  rescue
135
- ENV["DEBUG"] && puts("Refreshing failed: #{$!} : #{$!.message}")
135
+ logger.debug "Refreshing failed: #{$!} : #{$!.message}"
136
136
  end
137
137
 
138
138
  def require_current_master
@@ -26,7 +26,7 @@ module Kontena
26
26
 
27
27
  def initialize
28
28
  super
29
- @logger = Logger.new(STDOUT)
29
+ @logger = Logger.new(ENV["DEBUG"] ? STDERR : STDOUT)
30
30
  @logger.level = ENV["DEBUG"].nil? ? Logger::INFO : Logger::DEBUG
31
31
  @logger.progname = 'CONFIG'
32
32
  load_settings_from_env || load_settings_from_config_file
@@ -11,6 +11,7 @@ require_relative 'grids/audit_log_command'
11
11
  require_relative 'grids/user_command'
12
12
  require_relative 'grids/cloud_config_command'
13
13
  require_relative 'grids/trusted_subnet_command'
14
+ require_relative 'grids/health_command'
14
15
 
15
16
  class Kontena::Cli::GridCommand < Kontena::Command
16
17
 
@@ -27,6 +28,7 @@ class Kontena::Cli::GridCommand < Kontena::Command
27
28
  subcommand "user", "User specific commands", Kontena::Cli::Grids::UserCommand
28
29
  subcommand "cloud-config", "Generate cloud-config", Kontena::Cli::Grids::CloudConfigCommand
29
30
  subcommand "trusted-subnet", "Trusted subnet related commands", Kontena::Cli::Grids::TrustedSubnetCommand
31
+ subcommand "health", "Check grid health", Kontena::Cli::Grids::HealthCommand
30
32
 
31
33
  def execute
32
34
  end
@@ -7,6 +7,7 @@ module Kontena::Cli::Grids
7
7
  host = ENV['KONTENA_URL'] || self.current_master['url']
8
8
  puts "#{grid['name']}:"
9
9
  puts " uri: #{host.sub('http', 'ws')}"
10
+ puts " initial_size: #{grid['initial_size']}"
10
11
  root_dir = grid['engine_root_dir']
11
12
  nodes = client(require_token).get("grids/#{grid['name']}/nodes")
12
13
  nodes = nodes['nodes'].select{|n| n['connected'] == true }
@@ -92,5 +93,16 @@ module Kontena::Cli::Grids
92
93
  return 0.0 if amount.nil?
93
94
  (amount.to_f / 1024 / 1024 / 1024).to_f.round(2)
94
95
  end
96
+
97
+ # @return [Hash] /v1/grids/:grid JSON { ... }
98
+ def get_grid(name = nil)
99
+ if name
100
+ client(require_token).get("grids/#{name}")
101
+ elsif current_grid
102
+ client(require_token).get("grids/#{current_grid}")
103
+ else
104
+ exit_with_error "No grid given or selected"
105
+ end
106
+ end
95
107
  end
96
108
  end
@@ -0,0 +1,69 @@
1
+ require_relative 'common'
2
+ require "kontena/cli/helpers/health_helper"
3
+
4
+ module Kontena::Cli::Grids
5
+ class HealthCommand < Kontena::Command
6
+ include Kontena::Cli::Common
7
+ include Kontena::Cli::Helpers::HealthHelper
8
+ include Common
9
+
10
+ parameter "[NAME]", "Grid name"
11
+
12
+ def execute
13
+ require_api_url
14
+
15
+ grid = get_grid(name)
16
+ grid_nodes = client(require_token).get("grids/#{grid['name']}/nodes")
17
+
18
+ return show_grid_health(grid, grid_nodes['nodes'])
19
+ end
20
+
21
+ # Validate grid/nodes configuration for grid operation
22
+ #
23
+ # @return [Boolean] false if unhealthy
24
+ def show_grid_health(grid, nodes)
25
+ initial_size = grid['initial_size']
26
+ minimum_size = grid['initial_size'] / 2 + 1 # a majority is required for etcd quorum
27
+
28
+ grid_health = grid_health(grid, nodes)
29
+ initial_nodes = nodes.select{|node| node['initial_member']}
30
+ online_nodes = initial_nodes.select{|node| node['connected']}
31
+
32
+ # configuration and status
33
+ if initial_nodes.length == 0
34
+ puts "#{health_icon :error} Grid does not have any initial nodes, and requires at least #{minimum_size} of #{initial_size} initial nodes for operation"
35
+ elsif online_nodes.empty?
36
+ puts "#{health_icon :error} Grid does not have any initial nodes online, and requires at least #{minimum_size} of #{initial_size} initial nodes for operation"
37
+ elsif initial_nodes.length < minimum_size
38
+ puts "#{health_icon :error} Grid only has #{initial_nodes.length} initial nodes, and requires at least #{minimum_size} of #{initial_size} initial nodes for operation"
39
+ elsif online_nodes.length < minimum_size
40
+ puts "#{health_icon :error} Grid only has #{online_nodes.length} initial nodes online, and requires at least #{minimum_size} of #{initial_size} initial nodes for operation"
41
+ elsif initial_nodes.length < initial_size
42
+ puts "#{health_icon :warning} Grid only has #{initial_nodes.length} initial nodes of #{initial_size} required for high-availability"
43
+ elsif online_nodes.length < initial_size
44
+ puts "#{health_icon :warning} Grid only has #{online_nodes.length} initial nodes online of #{initial_size} required for high-availability"
45
+ elsif initial_nodes.length == 2
46
+ puts "#{health_icon :warning} Grid only has #{initial_nodes.length} initial nodes, and is not high-availability"
47
+ elsif initial_nodes.length == 1
48
+ puts "#{health_icon :warning} Grid only has #{initial_nodes.length} initial node, and is not high-availability"
49
+ else
50
+ puts "#{health_icon :ok} Grid has all #{online_nodes.length} of #{initial_size} initial nodes online"
51
+ end
52
+
53
+ nodes.each do |node|
54
+ node_health = node_health(node, grid_health)
55
+
56
+ if node['connected']
57
+
58
+ elsif node['initial_member']
59
+ puts "#{health_icon grid_health} Initial node #{node['name']} is offline"
60
+ else
61
+ puts "#{health_icon node_health} Grid node #{node['name']} is offline"
62
+ end
63
+ end
64
+
65
+ # operational if we have etcd quorum
66
+ return online_nodes.length >= minimum_size
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,53 @@
1
+ module Kontena::Cli::Helpers
2
+ module HealthHelper
3
+ def health_icon(health)
4
+ case health
5
+ when nil
6
+ " "
7
+ when :ok
8
+ pastel.green('⊛')
9
+ when :warning
10
+ pastel.yellow('⊙')
11
+ when :error
12
+ pastel.red('⊗')
13
+ when :offline
14
+ pastel.dark('⊝')
15
+ else
16
+ fail "Invalid health=#{health}"
17
+ end
18
+ end
19
+
20
+ # Validate grid nodes configuration and status
21
+ #
22
+ # @param grid [Hash] get(/grids/:grid) => { ... }
23
+ # @param nodes [Array<Hash>] get(/grids/:grid/nodes)[nodes] => [ { ... } ]
24
+ # @return [Symbol] health
25
+ def grid_health(grid, nodes)
26
+ initial = grid['initial_size']
27
+ minimum = grid['initial_size'] / 2 + 1 # a majority is required for etcd quorum
28
+
29
+ online = nodes.select{|node| node['initial_member'] && node['connected']}
30
+
31
+ if online.length < minimum
32
+ return :error
33
+ elsif online.length < initial
34
+ return :warning
35
+ else
36
+ return :ok
37
+ end
38
+ end
39
+
40
+ # Validate grid node status based on the grid health
41
+ #
42
+ # @param node [Hash] GET /nodes/:grid/:node
43
+ # @param grid_health [Symbol] @see #grid_health
44
+ # @return [Symbol] health
45
+ def node_health(node, grid_health)
46
+ if node['initial_member']
47
+ return node['connected'] ? grid_health : :offline
48
+ else
49
+ return node['connected'] ? :ok : :offline
50
+ end
51
+ end
52
+ end
53
+ end
@@ -39,7 +39,7 @@ module Kontena
39
39
  #
40
40
  # @return [Hash] query_params
41
41
  def serve_one
42
- ENV["DEBUG"] && puts("Waiting for connection on port #{port}..")
42
+ ENV["DEBUG"] && STDERR.puts("Waiting for connection on port #{port}..")
43
43
  socket = server.accept
44
44
 
45
45
  content = socket.recvfrom(2048).first.split(/(?:\r)?\n/)
@@ -56,7 +56,7 @@ module Kontena
56
56
 
57
57
  body = content.join("\n")
58
58
 
59
- ENV["DEBUG"] && puts("Got request: \"#{request.inspect}\n Headers: #{headers.inspect}\n Body: #{body}\"")
59
+ ENV["DEBUG"] && STDERR.puts("Got request: \"#{request.inspect}\n Headers: #{headers.inspect}\n Body: #{body}\"")
60
60
 
61
61
  get_request = request[/GET (\/cb.+?) HTTP/, 1]
62
62
  if get_request
@@ -81,7 +81,7 @@ module Kontena
81
81
  socket.close
82
82
  server.close
83
83
  uri = URI.parse("http://localhost#{get_request}")
84
- ENV["DEBUG"] && puts(" * Parsing params: \"#{uri.query}\"")
84
+ ENV["DEBUG"] && STDERR.puts(" * Parsing params: \"#{uri.query}\"")
85
85
  params = {}
86
86
  URI.decode_www_form(uri.query).each do |key, value|
87
87
  if value.to_s == ''
@@ -43,7 +43,7 @@ module Kontena::Cli::Master::Users
43
43
  end
44
44
  rescue
45
45
  STDERR.puts "Failed to invite #{email}".colorize(:red)
46
- ENV["DEBUG"] && puts("#{$!} - #{$!.message} -- #{$!.backtrace}")
46
+ ENV["DEBUG"] && STDERR.puts("#{$!} - #{$!.message} -- #{$!.backtrace}")
47
47
  end
48
48
  end
49
49
  end
@@ -4,6 +4,7 @@ require_relative 'nodes/show_command'
4
4
  require_relative 'nodes/update_command'
5
5
  require_relative 'nodes/ssh_command'
6
6
  require_relative 'nodes/label_command'
7
+ require_relative 'nodes/health_command'
7
8
 
8
9
  class Kontena::Cli::NodeCommand < Kontena::Command
9
10
 
@@ -13,6 +14,7 @@ class Kontena::Cli::NodeCommand < Kontena::Command
13
14
  subcommand "update", "Update node", Kontena::Cli::Nodes::UpdateCommand
14
15
  subcommand ["remove","rm"], "Remove node", Kontena::Cli::Nodes::RemoveCommand
15
16
  subcommand "label", "Node label specific commands", Kontena::Cli::Nodes::LabelCommand
17
+ subcommand "health", "Check node health", Kontena::Cli::Nodes::HealthCommand
16
18
 
17
19
  def execute
18
20
  end
@@ -0,0 +1,32 @@
1
+ require_relative '../helpers/health_helper'
2
+
3
+ module Kontena::Cli::Nodes
4
+ class HealthCommand < Kontena::Command
5
+ include Kontena::Cli::Common
6
+ include Kontena::Cli::GridOptions
7
+ include Kontena::Cli::Helpers::HealthHelper
8
+
9
+ parameter "NODE_ID", "Node id"
10
+
11
+ def execute
12
+ require_api_url
13
+ require_current_grid
14
+ token = require_token
15
+
16
+ node = client(token).get("nodes/#{current_grid}/#{node_id}")
17
+
18
+ return show_node_health(node)
19
+ end
20
+
21
+ # @return [Boolean] true if healthy
22
+ def show_node_health(node)
23
+ if node['connected']
24
+ puts "#{health_icon(:ok)} Node is online"
25
+ return true
26
+ else
27
+ puts "#{health_icon(:offline)} Node is offline"
28
+ return false
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,46 +1,60 @@
1
+ require_relative '../helpers/health_helper'
2
+
1
3
  module Kontena::Cli::Nodes
2
4
  class ListCommand < Kontena::Command
3
5
  include Kontena::Cli::Common
4
6
  include Kontena::Cli::GridOptions
7
+ include Kontena::Cli::Helpers::HealthHelper
5
8
 
6
9
  option ["--all"], :flag, "List nodes for all grids", default: false
7
10
 
11
+ def node_initial(node, grid)
12
+ if node['initial_member']
13
+ return "#{node['node_number']} / #{grid['initial_size']}"
14
+ else
15
+ return "-"
16
+ end
17
+ end
18
+
19
+ def node_labels(node)
20
+ (node['labels'] || ['-']).join(",")
21
+ end
22
+
23
+ def show_grid_nodes(grid, nodes, multi: false)
24
+ grid_health = grid_health(grid, nodes)
25
+
26
+ nodes = nodes.sort_by{|n| n['node_number'] }
27
+ nodes.each do |node|
28
+ puts [
29
+ "%s" % health_icon(node_health(node, grid_health)),
30
+ "%-70.70s" % [multi ? "#{grid['name']}/#{node['name']}" : node['name']],
31
+ "%-10s" % node['agent_version'],
32
+ "%-10s" % (node['connected'] ? "online" : "offline"),
33
+ "%-10s" % node_initial(node, grid),
34
+ "%s" % [node_labels(node)],
35
+ ].join ' '
36
+ end
37
+ end
38
+
8
39
  def execute
9
40
  require_api_url
10
41
  require_current_grid
11
42
  token = require_token
12
43
 
44
+ puts "%s %-70s %-10s %-10s %-10s %-s" % [health_icon(nil), "Name", "Version", "Status", "Initial", "Labels"]
45
+
13
46
  if all?
14
47
  grids = client(token).get("grids")
15
- puts "%-70s %-10s %-40s" % [ 'Name', 'Status', 'Labels']
16
-
17
48
  grids['grids'].each do |grid|
18
- nodes = client(token).get("grids/#{grid['name']}/nodes")
19
- nodes['nodes'].each do |node|
20
- if node['connected']
21
- status = 'online'
22
- else
23
- status = 'offline'
24
- end
25
- puts "%-70.70s %-10s %-40s" % [
26
- "#{grid['name']}/#{node['name']}",
27
- status,
28
- (node['labels'] || ['-']).join(",")
29
- ]
30
- end
49
+ nodes = client(require_token).get("grids/#{grid['id']}/nodes")['nodes']
50
+
51
+ show_grid_nodes(grid, nodes, multi: true)
31
52
  end
32
53
  else
33
- nodes = client(token).get("grids/#{current_grid}/nodes")
34
- puts "%-70s %-10s %-10s %-40s" % ['Name', 'Status', 'Initial', 'Labels']
35
- nodes = nodes['nodes'].sort_by{|n| n['node_number'] }
36
- nodes.each do |node|
37
- puts "%-70.70s %-10s %-10s %-40s" % [
38
- node['name'],
39
- node['connected'] ? 'online' : 'offline',
40
- node['initial_member'] ? 'yes' : 'no',
41
- (node['labels'] || ['-']).join(",")
42
- ]
43
- end
54
+ grid = client(token).get("grids/#{current_grid}")
55
+ nodes = client(require_token).get("grids/#{current_grid}/nodes")['nodes']
56
+
57
+ show_grid_nodes(grid, nodes)
44
58
  end
45
59
  end
46
60
  end