kontena-cli 1.4.3 → 1.5.0.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +7 -3
  3. data/Gemfile +7 -3
  4. data/README.md +1 -1
  5. data/VERSION +1 -1
  6. data/bin/kontena +1 -0
  7. data/kontena-cli.gemspec +5 -6
  8. data/lib/kontena/cli/browser_launcher.rb +61 -0
  9. data/lib/kontena/cli/certificate/authorize_command.rb +40 -16
  10. data/lib/kontena/cli/certificate/get_command.rb +1 -1
  11. data/lib/kontena/cli/cloud/login_command.rb +3 -4
  12. data/lib/kontena/cli/cloud/master/add_command.rb +1 -1
  13. data/lib/kontena/cli/cloud/master/list_command.rb +1 -1
  14. data/lib/kontena/cli/cloud/master/remove_command.rb +1 -1
  15. data/lib/kontena/cli/cloud/master/update_command.rb +1 -1
  16. data/lib/kontena/cli/common.rb +2 -2
  17. data/lib/kontena/cli/etcd_command.rb +1 -1
  18. data/lib/kontena/cli/external_registries/add_command.rb +2 -2
  19. data/lib/kontena/cli/external_registries/remove_command.rb +1 -1
  20. data/lib/kontena/cli/grids/common.rb +14 -4
  21. data/lib/kontena/cli/grids/events_command.rb +2 -2
  22. data/lib/kontena/cli/grids/list_command.rb +1 -1
  23. data/lib/kontena/cli/grids/logs_command.rb +1 -1
  24. data/lib/kontena/cli/grids/remove_command.rb +12 -10
  25. data/lib/kontena/cli/grids/trusted_subnets/add_command.rb +1 -1
  26. data/lib/kontena/cli/grids/trusted_subnets/remove_command.rb +12 -10
  27. data/lib/kontena/cli/grids/use_command.rb +1 -1
  28. data/lib/kontena/cli/helpers/log_helper.rb +1 -1
  29. data/lib/kontena/cli/logout_command.rb +1 -1
  30. data/lib/kontena/cli/master/login_command.rb +2 -3
  31. data/lib/kontena/cli/master/logout_command.rb +2 -2
  32. data/lib/kontena/cli/master/token/common.rb +2 -1
  33. data/lib/kontena/cli/master/token/create_command.rb +5 -2
  34. data/lib/kontena/cli/master/token/current_command.rb +9 -4
  35. data/lib/kontena/cli/master/token/list_command.rb +1 -1
  36. data/lib/kontena/cli/master/token/show_command.rb +11 -1
  37. data/lib/kontena/cli/master/user/invite_command.rb +1 -1
  38. data/lib/kontena/cli/master_command.rb +0 -1
  39. data/lib/kontena/cli/nodes/create_command.rb +1 -1
  40. data/lib/kontena/cli/nodes/labels/remove_command.rb +17 -3
  41. data/lib/kontena/cli/nodes/remove_command.rb +12 -10
  42. data/lib/kontena/cli/nodes/reset_token_command.rb +1 -1
  43. data/lib/kontena/cli/nodes/update_command.rb +1 -1
  44. data/lib/kontena/cli/plugin_command.rb +2 -1
  45. data/lib/kontena/cli/plugins/install_command.rb +2 -2
  46. data/lib/kontena/cli/plugins/uninstall_command.rb +19 -10
  47. data/lib/kontena/cli/plugins/upgrade_command.rb +60 -0
  48. data/lib/kontena/cli/registry/create_command.rb +1 -1
  49. data/lib/kontena/cli/registry/remove_command.rb +2 -2
  50. data/lib/kontena/cli/services/containers_command.rb +1 -1
  51. data/lib/kontena/cli/services/create_command.rb +1 -1
  52. data/lib/kontena/cli/services/deploy_command.rb +1 -1
  53. data/lib/kontena/cli/services/envs/add_command.rb +1 -1
  54. data/lib/kontena/cli/services/envs/remove_command.rb +5 -3
  55. data/lib/kontena/cli/services/link_command.rb +1 -1
  56. data/lib/kontena/cli/services/logs_command.rb +1 -1
  57. data/lib/kontena/cli/services/monitor_command.rb +1 -1
  58. data/lib/kontena/cli/services/remove_command.rb +11 -9
  59. data/lib/kontena/cli/services/restart_command.rb +1 -1
  60. data/lib/kontena/cli/services/secrets/link_command.rb +1 -1
  61. data/lib/kontena/cli/services/services_helper.rb +6 -12
  62. data/lib/kontena/cli/services/start_command.rb +5 -3
  63. data/lib/kontena/cli/services/stop_command.rb +5 -3
  64. data/lib/kontena/cli/services/unlink_command.rb +1 -1
  65. data/lib/kontena/cli/services/update_command.rb +1 -1
  66. data/lib/kontena/cli/spinner.rb +10 -10
  67. data/lib/kontena/cli/stack_command.rb +1 -0
  68. data/lib/kontena/cli/stacks/build_command.rb +6 -6
  69. data/lib/kontena/cli/stacks/deploy_command.rb +12 -10
  70. data/lib/kontena/cli/stacks/inspect_command.rb +17 -0
  71. data/lib/kontena/cli/stacks/install_command.rb +15 -4
  72. data/lib/kontena/cli/stacks/list_command.rb +2 -3
  73. data/lib/kontena/cli/stacks/logs_command.rb +1 -1
  74. data/lib/kontena/cli/stacks/monitor_command.rb +2 -2
  75. data/lib/kontena/cli/stacks/remove_command.rb +28 -19
  76. data/lib/kontena/cli/stacks/restart_command.rb +5 -4
  77. data/lib/kontena/cli/stacks/stop_command.rb +6 -5
  78. data/lib/kontena/cli/stacks/upgrade_command.rb +84 -64
  79. data/lib/kontena/cli/stacks/yaml/reader.rb +9 -4
  80. data/lib/kontena/cli/vault/remove_command.rb +7 -5
  81. data/lib/kontena/cli/vault/update_command.rb +1 -1
  82. data/lib/kontena/cli/vault/write_command.rb +1 -1
  83. data/lib/kontena/cli/volumes/remove_command.rb +6 -4
  84. data/lib/kontena/cli/vpn/create_command.rb +1 -1
  85. data/lib/kontena/cli/vpn/remove_command.rb +1 -1
  86. data/lib/kontena/client.rb +23 -14
  87. data/lib/kontena/command.rb +2 -2
  88. data/lib/kontena/debug_instrumentor.rb +11 -2
  89. data/lib/kontena/plugin_manager/common.rb +5 -2
  90. data/lib/kontena/plugin_manager/installer.rb +34 -10
  91. data/lib/kontena/scripts/completer.rb +91 -43
  92. data/lib/kontena/{cli/stacks → stacks}/change_resolver.rb +38 -16
  93. data/lib/kontena/stacks/stack_data.rb +58 -0
  94. data/lib/kontena/stacks/stack_data_set.rb +51 -0
  95. data/lib/kontena_cli.rb +1 -0
  96. data/omnibus/Gemfile.lock +32 -22
  97. data/omnibus/config/projects/kontena.rb +2 -0
  98. data/omnibus/config/software/kontena-cli.rb +6 -4
  99. data/omnibus/package-scripts/kontena/postinstall +1 -1
  100. data/omnibus/wrappers/sh/kontena +1 -1
  101. data/spec/fixtures/kontena_v3_with_registry_extends.yml +20 -0
  102. data/spec/kontena/cli/certificates/authorize_command_spec.rb +81 -0
  103. data/spec/kontena/cli/cloud/login_command_spec.rb +4 -4
  104. data/spec/kontena/cli/common_spec.rb +8 -1
  105. data/spec/kontena/cli/grids/update_command_spec.rb +13 -0
  106. data/spec/kontena/cli/master/join_command_spec.rb +1 -4
  107. data/spec/kontena/cli/master/login_command_spec.rb +4 -4
  108. data/spec/kontena/cli/master/token/create_command_spec.rb +132 -0
  109. data/spec/kontena/cli/master/token/show_command_spec.rb +90 -0
  110. data/spec/kontena/cli/nodes/labels/remove_command_spec.rb +35 -5
  111. data/spec/kontena/cli/stacks/install_command_spec.rb +16 -6
  112. data/spec/kontena/cli/stacks/remove_command_spec.rb +23 -2
  113. data/spec/kontena/cli/stacks/validate_command_spec.rb +1 -1
  114. data/spec/kontena/cli/stacks/yaml/reader_spec.rb +33 -1
  115. data/spec/kontena/client_spec.rb +38 -1
  116. data/spec/kontena/stacks/change_resolver_spec.rb +44 -0
  117. data/spec/kontena/stacks/stack_data_set_spec.rb +59 -0
  118. metadata +36 -34
  119. data/lib/kontena/cli/master/users_command.rb +0 -13
@@ -32,7 +32,7 @@ module Kontena::Cli::Grids
32
32
 
33
33
  if gridlist.size == 0
34
34
  self.verbose? && puts
35
- puts "Kontena Master #{config.current_master.name} doesn't have any grids yet. Create one now using 'kontena grid create' command".colorize(:yellow)
35
+ puts pastel.yellow("Kontena Master #{config.current_master.name} doesn't have any grids yet. Create one now using 'kontena grid create' command")
36
36
  self.verbose? && puts
37
37
  else
38
38
  vputs
@@ -29,7 +29,7 @@ module Kontena::Cli::Grids
29
29
  prefix = "#{log['created_at']} #{log['name']}:"
30
30
  end
31
31
 
32
- puts "#{prefix.colorize(color)} #{log['data']}"
32
+ puts "#{pastel.send(color, prefix)} #{log['data']}"
33
33
  end
34
34
  end
35
35
  end
@@ -5,24 +5,26 @@ module Kontena::Cli::Grids
5
5
  include Kontena::Cli::Common
6
6
  include Common
7
7
 
8
- parameter "NAME", "Grid name"
8
+ parameter "NAME ...", "Grid name", attribute_name: :grids
9
9
  option "--force", :flag, "Force remove", default: false, attribute_name: :forced
10
10
 
11
11
  def execute
12
12
  require_api_url
13
13
  token = require_token
14
- confirm_command(name) unless forced?
15
- grid = find_grid_by_name(name)
14
+ grids.each do |name|
15
+ confirm_command(name) unless forced?
16
+ grid = find_grid_by_name(name)
16
17
 
17
- if !grid.nil?
18
- spinner "removing #{pastel.cyan(name)} grid " do
19
- response = client(token).delete("grids/#{grid['id']}")
20
- if response
21
- clear_current_grid if grid['id'] == current_grid
18
+ if !grid.nil?
19
+ spinner "removing #{pastel.cyan(name)} grid " do
20
+ response = client(token).delete("grids/#{grid['id']}")
21
+ if response
22
+ clear_current_grid if grid['id'] == current_grid
23
+ end
22
24
  end
25
+ else
26
+ exit_with_error "Could not resolve grid by name [#{name}]. For a list of existing grids please run: kontena grid list"
23
27
  end
24
- else
25
- exit_with_error "Could not resolve grid by name [#{name}]. For a list of existing grids please run: kontena grid list"
26
28
  end
27
29
  end
28
30
  end
@@ -10,7 +10,7 @@ module Kontena::Cli::Grids::TrustedSubnets
10
10
  def execute
11
11
  grid = client.get("grids/#{current_grid}")
12
12
  data = {trusted_subnets: grid['trusted_subnets'] + [self.subnet]}
13
- spinner "Adding #{subnet.colorize(:cyan)} as a trusted subnet in #{current_grid.colorize(:cyan)} grid " do
13
+ spinner "Adding #{pastel.cyan(subnet)} as a trusted subnet in #{pastel.cyan(current_grid)} grid " do
14
14
  client.put("grids/#{current_grid}", data)
15
15
  end
16
16
  end
@@ -3,21 +3,23 @@ module Kontena::Cli::Grids::TrustedSubnets
3
3
  include Kontena::Cli::Common
4
4
  include Kontena::Cli::GridOptions
5
5
 
6
- parameter "SUBNET", "Trusted subnet"
6
+ parameter "SUBNET ...", "Trusted subnet", attribute_name: :subnets
7
7
  option "--force", :flag, "Force remove", default: false, attribute_name: :forced
8
8
 
9
9
  requires_current_master
10
10
 
11
11
  def execute
12
- grid = client.get("grids/#{current_grid}")
13
- confirm_command(subnet) unless forced?
14
- trusted_subnets = grid['trusted_subnets'] || []
15
- unless trusted_subnets.delete(self.subnet)
16
- exit_with_error("Grid #{current_grid.colorize(:cyan)} does not have trusted subnet #{subnet.colorize(:cyan)}")
17
- end
18
- data = {trusted_subnets: trusted_subnets}
19
- spinner "Removing trusted subnet #{subnet.colorize(:cyan)} from #{current_grid.colorize(:cyan)} grid " do
20
- client.put("grids/#{current_grid}", data)
12
+ subnets.each do |subnet|
13
+ grid = client.get("grids/#{current_grid}")
14
+ confirm_command(subnet) unless forced?
15
+ trusted_subnets = grid['trusted_subnets'] || []
16
+ unless trusted_subnets.delete(subnet)
17
+ exit_with_error("Grid #{pastel.cyan(current_grid)} does not have trusted subnet #{pastel.cyan(subnet)}")
18
+ end
19
+ data = {trusted_subnets: trusted_subnets}
20
+ spinner "Removing trusted subnet #{pastel.cyan(subnet)} from #{pastel.cyan(current_grid)} grid " do
21
+ client.put("grids/#{current_grid}", data)
22
+ end
21
23
  end
22
24
  end
23
25
  end
@@ -14,7 +14,7 @@ module Kontena::Cli::Grids
14
14
  def execute
15
15
  grid = find_grid_by_name(name)
16
16
  unless grid
17
- exit_with_error "Could not resolve grid by name [#{name}]. For a list of existing grids please run: kontena grid list".colorize(:red)
17
+ exit_with_error pastel.red("Could not resolve grid by name [#{name}]. For a list of existing grids please run: kontena grid list")
18
18
  end
19
19
  config.current_master.grid = grid['name']
20
20
  config.write
@@ -84,7 +84,7 @@ module Kontena::Cli::Helpers
84
84
  color = color_for_container(log['name'])
85
85
  prefix = "#{log['created_at']} #{log['name']}:"
86
86
 
87
- puts "#{prefix.colorize(color)} #{log['data']}"
87
+ puts "#{pastel.send(color, prefix)} #{log['data']}"
88
88
  end
89
89
 
90
90
  # @param [String] container_id
@@ -5,6 +5,6 @@ class Kontena::Cli::LogoutCommand < Kontena::Command
5
5
  banner "or 'kontena cloud logout' to log out of the Kontena Cloud", false
6
6
 
7
7
  def execute
8
- exit_with_error("Command removed. Use #{"kontena master logout".colorize(:yellow)} to log out of the Kontena Master")
8
+ exit_with_error("Command removed. Use #{pastel.yellow("kontena master logout")} to log out of the Kontena Master")
9
9
  end
10
10
  end
@@ -176,7 +176,7 @@ module Kontena::Cli::Master
176
176
 
177
177
  def web_flow(server, auth_params)
178
178
  require_relative '../localhost_web_server'
179
- require 'launchy'
179
+ require 'kontena/cli/browser_launcher'
180
180
 
181
181
 
182
182
  web_server = Kontena::LocalhostWebServer.new
@@ -202,12 +202,11 @@ module Kontena::Cli::Master
202
202
  puts
203
203
 
204
204
  server_thread = Thread.new { Thread.main['response'] = web_server.serve_one }
205
- browser_thread = Thread.new { Launchy.open(uri.to_s) }
205
+ Kontena::Cli::BrowserLauncher.open(uri.to_s)
206
206
 
207
207
  spinner "Waiting for browser authorization response" do
208
208
  server_thread.join
209
209
  end
210
- browser_thread.join
211
210
 
212
211
  update_server(server, Thread.main['response'])
213
212
  update_server_to_config(server)
@@ -9,12 +9,12 @@ module Kontena::Cli::Master
9
9
  config.servers.each do |server|
10
10
  use_refresh_token(server)
11
11
  server.token = nil
12
- puts "Logged out of #{server.name.colorize(:green)}"
12
+ puts "Logged out of #{pastel.green(server.name)}"
13
13
  end
14
14
  elsif config.current_master
15
15
  use_refresh_token(config.current_master)
16
16
  config.current_master.token = nil
17
- puts "Logged out of #{config.current_master.name.colorize(:green)}"
17
+ puts "Logged out of #{pastel.green(config.current_master.name)}"
18
18
  else
19
19
  warn "Current master has not been selected"
20
20
  exit 0 # exiting with 0 not 1, it's not really an error situation (kontena logout && kontena master login...)
@@ -9,7 +9,8 @@ module Kontena::Cli::Master::Token
9
9
  user_id: data["user"]["id"],
10
10
  user_email: data["user"]["email"],
11
11
  user_name: data["user"]["name"],
12
- server_name: data["server"]["name"]
12
+ server_name: data["server"]["name"],
13
+ description: data['description']
13
14
  }
14
15
  if data["token_type"] == "bearer"
15
16
  output[:access_token_last_four] = data["access_token_last_four"]
@@ -15,6 +15,7 @@ module Kontena::Cli::Master::Token
15
15
  option ['-u', '--user'], '[EMAIL]', 'Generate a token for another user'
16
16
  option ['--id'], :flag, "Only output the token ID"
17
17
  option ['--token'], :flag, "Only output the access_token (or authorization code)"
18
+ option ['-d', '--description'], '[DESCRIPTION]', 'Token description'
18
19
 
19
20
  option ['--return'], :flag, "Return the response hash", hidden: true
20
21
 
@@ -22,8 +23,9 @@ module Kontena::Cli::Master::Token
22
23
  params = {
23
24
  response_type: self.code? ? 'code' : 'token',
24
25
  scope: self.scopes,
25
- expires_in: self.expires_in
26
+ expires_in: self.expires_in,
26
27
  }
28
+ params[:description] = self.description if self.description
27
29
  params[:user] = self.user if self.user
28
30
  data = token_data_to_hash(client.post("/oauth2/authorize", params))
29
31
 
@@ -39,8 +41,9 @@ module Kontena::Cli::Master::Token
39
41
  exit 0
40
42
  end
41
43
 
44
+ puts '%s:' % data.delete(:id)
42
45
  data.each do |key, value|
43
- puts "%26.26s : %s" % [key, value]
46
+ puts " %s: %s" % [key, value]
44
47
  end
45
48
  end
46
49
  end
@@ -12,28 +12,33 @@ module Kontena::Cli::Master::Token
12
12
  option '--token', :flag, "Only output access token"
13
13
  option '--refresh-token', :flag, "Only output refresh token"
14
14
  option '--expires-in', :flag, "Only output expires in seconds"
15
+ option '--id', :flag, "Only output access token id"
15
16
 
16
17
  def execute
17
18
  if self.token?
18
19
  puts current_master.token.access_token
19
- exit 0
20
+ return
20
21
  end
21
22
 
22
23
  if self.refresh_token?
23
24
  if current_master.token.refresh_token
24
25
  puts current_master.token.refresh_token
25
26
  end
26
- exit 0
27
+ return
27
28
  end
28
29
 
29
30
  if self.expires_in?
30
31
  if current_master.token.expires_at.to_i > 0
31
32
  puts current_master.token.expires_at - Time.now.utc.to_i
32
33
  end
33
- exit 0
34
+ return
34
35
  end
35
36
 
36
- Kontena.run!(['master', 'token', 'show', current_master.token.access_token])
37
+ if self.id?
38
+ Kontena.run!(['master', 'token', 'show', '--id', current_master.token.access_token])
39
+ else
40
+ Kontena.run!(['master', 'token', 'show', current_master.token.access_token])
41
+ end
37
42
  end
38
43
  end
39
44
  end
@@ -12,7 +12,7 @@ module Kontena::Cli::Master::Token
12
12
 
13
13
  def fields
14
14
  return ['id'] if quiet?
15
- { id: 'id', token_type: 'token_type', token_last4: 'access_token_last_four', expires_in: 'expires_in', scopes: 'scopes' }
15
+ { id: 'id', token_type: 'token_type', token_last4: 'access_token_last_four', expires_in: 'expires_in', scopes: 'scopes', description: 'description' }
16
16
  end
17
17
 
18
18
  def execute
@@ -11,11 +11,21 @@ module Kontena::Cli::Master::Token
11
11
  requires_current_master
12
12
  requires_current_master_token
13
13
 
14
+ option '--id', :flag, "Only output access token id", hidden: true
15
+
14
16
  def execute
15
17
  data = client.get("/oauth2/tokens/#{token_or_id}")
16
18
  output = token_data_to_hash(data)
19
+
20
+ if id?
21
+ puts output[:id]
22
+ return
23
+ end
24
+
25
+ id = output.delete(:id)
26
+ puts '%s:' % id
17
27
  output.each do |key, value|
18
- puts "%26.26s : %s" % [key, value]
28
+ puts " %s: %s" % [key, value.nil? ? '-' : value]
19
29
  end
20
30
  end
21
31
  end
@@ -34,7 +34,7 @@ module Kontena::Cli::Master::User
34
34
  elsif self.return?
35
35
  return response
36
36
  else
37
- puts "Invitation created for #{response['email']}".colorize(:green)
37
+ puts pastel.green("Invitation created for #{response['email']}")
38
38
  puts " * code: #{response['invite_code']}"
39
39
  puts " * command: kontena master join #{current_master.url} #{response['invite_code']}"
40
40
  end
@@ -5,7 +5,6 @@ class Kontena::Cli::MasterCommand < Kontena::Command
5
5
  subcommand ["remove", "rm"], "Remove a master from configuration", load_subcommand('master/remove_command')
6
6
  subcommand ["config", "cfg"], "Configure master settings", load_subcommand('master/config_command')
7
7
  subcommand "use", "Switch to use selected master", load_subcommand('master/use_command')
8
- subcommand "users", "Users specific commands [DEPRECATED]", load_subcommand('master/users_command')
9
8
  subcommand "user", "User specific commands", load_subcommand('master/user_command')
10
9
  subcommand "current", "Show current master details", load_subcommand('master/current_command')
11
10
  subcommand "login", "Authenticate to Kontena Master", load_subcommand('master/login_command')
@@ -17,7 +17,7 @@ module Kontena::Cli::Nodes
17
17
  data[:token] = token if token
18
18
  data[:labels] = label_list
19
19
 
20
- spinner "Creating #{name.colorize(:cyan)} node " do
20
+ spinner "Creating #{pastel.cyan(name)} node " do
21
21
  client.post("grids/#{current_grid}/nodes", data)
22
22
  end
23
23
  end
@@ -5,14 +5,28 @@ module Kontena::Cli::Nodes::Labels
5
5
  parameter "NODE", "Node name"
6
6
  parameter "LABEL ...", "Labels"
7
7
 
8
+ option '--force', :flag, "Do not abort if items in label list are not found"
9
+
8
10
  requires_current_master
9
11
  requires_current_master_token
10
12
  requires_current_grid
11
13
 
12
14
  def execute
13
- node = client.get("nodes/#{current_grid}/#{self.node}")
14
- data = { labels: Array(node['labels']).reject {|label| label_list.include?(label) } }
15
- client.put("nodes/#{node['id']}", data)
15
+ node_data = client.get("nodes/#{current_grid}/#{self.node}")
16
+
17
+ node_data['labels'] ||= []
18
+
19
+ found_labels = label_list.uniq & node_data['labels']
20
+
21
+ if !force? && found_labels.size != label_list.uniq.size
22
+ missing = label_list - found_labels
23
+ exit_with_error "Label#{'s' if missing.size > 1} #{pastel.cyan(missing.join(', '))} not found on node #{pastel.cyan(node)}"
24
+ end
25
+
26
+ return nil if found_labels.empty?
27
+
28
+ data = { labels: node_data['labels'] - found_labels }
29
+ client.put("nodes/#{node_data['id']}", data)
16
30
  end
17
31
  end
18
32
  end
@@ -3,7 +3,7 @@ module Kontena::Cli::Nodes
3
3
  include Kontena::Cli::Common
4
4
  include Kontena::Cli::GridOptions
5
5
 
6
- parameter "NODE", "Node name"
6
+ parameter "NODE ...", "Node name", attribute_name: :nodes
7
7
  option "--force", :flag, "Force remove", default: false, attribute_name: :forced
8
8
 
9
9
  def execute
@@ -11,18 +11,20 @@ module Kontena::Cli::Nodes
11
11
  require_current_grid
12
12
  token = require_token
13
13
 
14
- node = client(token).get("nodes/#{current_grid}/#{self.node}")
14
+ nodes.each do |node_name|
15
+ node = client(token).get("nodes/#{current_grid}/#{node_name}")
15
16
 
16
- if node['has_token'] && node['connected']
17
- warning "Node #{node['name']} is still connected using a node token, but will be force-disconnected"
18
- elsif node['connected']
19
- exit_with_error "Node #{node['name']} is still connected using a grid token. You must terminate the node before removing it."
20
- end
17
+ if node['has_token'] && node['connected']
18
+ warning "Node #{node['name']} is still connected using a node token, but will be force-disconnected"
19
+ elsif node['connected']
20
+ exit_with_error "Node #{node['name']} is still connected using a grid token. You must terminate the node before removing it."
21
+ end
21
22
 
22
- confirm_command(self.node) unless forced?
23
+ confirm_command(node_name) unless forced?
23
24
 
24
- spinner "Removing #{self.node.colorize(:cyan)} node from #{current_grid.colorize(:cyan)} grid " do
25
- client(token).delete("nodes/#{node['id']}")
25
+ spinner "Removing #{pastel.cyan(node_name)} node from #{pastel.cyan(current_grid)} grid " do
26
+ client(token).delete("nodes/#{node['id']}")
27
+ end
26
28
  end
27
29
  end
28
30
  end
@@ -17,7 +17,7 @@ module Kontena::Cli::Nodes
17
17
  def execute
18
18
  confirm("Resetting the node token will disconnect the agent (unless using --no-reset-connection), and require you to reconfigure the kontena-agent using the new `kontena node env` values before it will be able to reconnect. Are you sure?")
19
19
 
20
- spinner "Resetting node #{self.node.colorize(:cyan)} websocket connection token" do
20
+ spinner "Resetting node #{pastel.cyan(self.node)} websocket connection token" do
21
21
  if self.clear_token?
22
22
  client.delete("nodes/#{current_grid}/#{self.node}/token",
23
23
  reset_connection: self.reset_connection?,
@@ -20,7 +20,7 @@ module Kontena::Cli::Nodes
20
20
  data[:labels] = [] if self.clear_labels?
21
21
 
22
22
  data[:availability] = availability if availability
23
- spinner "Updating #{self.node.colorize(:cyan)} node " do
23
+ spinner "Updating #{pastel.cyan(self.node)} node " do
24
24
  client.put("nodes/#{current_grid}/#{self.node}", data)
25
25
  end
26
26
  end
@@ -5,7 +5,8 @@ class Kontena::Cli::PluginCommand < Kontena::Command
5
5
  subcommand "search", "Search plugins", load_subcommand('plugins/search_command')
6
6
  subcommand "install", "Install a plugin", load_subcommand('plugins/install_command')
7
7
  subcommand "uninstall", "Uninstall a plugin", load_subcommand('plugins/uninstall_command')
8
+ subcommand "upgrade", "Upgrade plugins", load_subcommand('plugins/upgrade_command')
8
9
 
9
10
  def execute
10
11
  end
11
- end
12
+ end
@@ -17,7 +17,7 @@ module Kontena::Cli::Plugins
17
17
 
18
18
  def execute
19
19
  if installed?(name)
20
- installed = spinner "Upgrading plugin #{name.colorize(:cyan)}" do
20
+ installed = spinner "Upgrading plugin #{pastel.cyan(name)}" do
21
21
  installer.upgrade
22
22
  end
23
23
 
@@ -25,7 +25,7 @@ module Kontena::Cli::Plugins
25
25
  Kontena::PluginManager::Cleaner.new(name).cleanup
26
26
  end
27
27
  else
28
- installed = spinner "Installing plugin #{name.colorize(:cyan)}" do
28
+ installed = spinner "Installing plugin #{pastel.cyan(name)}" do
29
29
  installer.install
30
30
  end
31
31
  end
@@ -4,19 +4,28 @@ module Kontena::Cli::Plugins
4
4
  class UninstallCommand < Kontena::Command
5
5
  include Kontena::Util
6
6
  include Kontena::Cli::Common
7
- include Kontena::PluginManager::Common
8
7
 
9
- parameter 'NAME', 'Plugin name'
10
-
11
- def uninstaller
12
- Kontena::PluginManager::Uninstaller.new(name)
13
- end
8
+ parameter 'NAME ...', 'Plugin name'
14
9
 
15
10
  def execute
16
- exit_with_error "Plugin #{name} has not been installed" unless installed?(name)
17
- spinner "Uninstalling plugin #{pastel.cyan(name)}" do
18
- uninstaller.uninstall
11
+ name_list.each do |name|
12
+ exit_with_error "Plugin #{name} has not been installed" unless plugin_installed?(name)
13
+ spinner "Uninstalling plugin #{pastel.cyan(name)}" do
14
+ plugin_uninstaller(name).uninstall
15
+ end
19
16
  end
20
17
  end
18
+
19
+ # @param name [String]
20
+ # @return [Boolean]
21
+ def plugin_installed?(name)
22
+ Kontena::PluginManager::Common.installed?(name)
23
+ end
24
+
25
+ # @param name [String]
26
+ # @return [Kontena::PluginManager::Uninstaller]
27
+ def plugin_uninstaller(name)
28
+ Kontena::PluginManager::Uninstaller.new(name)
29
+ end
21
30
  end
22
- end
31
+ end