kontena-cli 1.4.3 → 1.5.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
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