kontena-cli 1.2.2 → 1.3.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/lib/kontena/callbacks/auth/01_list_and_select_grid_after_master_auth.rb +1 -1
  4. data/lib/kontena/callbacks/master/deploy/05_before_deploy_configuration_wizard.rb +1 -1
  5. data/lib/kontena/callbacks/master/deploy/50_authenticate_after_deploy.rb +7 -2
  6. data/lib/kontena/callbacks/master/deploy/55_create_initial_grid_after_deploy.rb +2 -3
  7. data/lib/kontena/callbacks/master/deploy/56_set_server_provider_after_deploy.rb +2 -2
  8. data/lib/kontena/callbacks/master/deploy/60_configure_auth_provider_after_deploy.rb +5 -10
  9. data/lib/kontena/callbacks/master/deploy/70_invite_self_after_deploy.rb +10 -16
  10. data/lib/kontena/cli/app_command.rb +2 -0
  11. data/lib/kontena/cli/cloud/master/add_command.rb +19 -10
  12. data/lib/kontena/cli/common.rb +2 -32
  13. data/lib/kontena/cli/grids/trusted_subnets/add_command.rb +6 -6
  14. data/lib/kontena/cli/grids/trusted_subnets/list_command.rb +3 -4
  15. data/lib/kontena/cli/grids/trusted_subnets/remove_command.rb +7 -7
  16. data/lib/kontena/cli/master/create_command.rb +2 -3
  17. data/lib/kontena/cli/master/init_cloud_command.rb +1 -1
  18. data/lib/kontena/cli/master/join_command.rb +3 -1
  19. data/lib/kontena/cli/master/ssh_command.rb +2 -6
  20. data/lib/kontena/cli/master/token/current_command.rb +1 -1
  21. data/lib/kontena/cli/master/user/invite_command.rb +2 -2
  22. data/lib/kontena/cli/master/user_command.rb +0 -2
  23. data/lib/kontena/cli/nodes/ssh_command.rb +1 -3
  24. data/lib/kontena/cli/stack_command.rb +2 -0
  25. data/lib/kontena/cli/stacks/common.rb +1 -1
  26. data/lib/kontena/cli/stacks/install_command.rb +1 -1
  27. data/lib/kontena/cli/stacks/restart_command.rb +23 -0
  28. data/lib/kontena/cli/stacks/stop_command.rb +23 -0
  29. data/lib/kontena/cli/stacks/upgrade_command.rb +1 -1
  30. data/lib/kontena/cli/stacks/yaml/validations.rb +1 -1
  31. data/lib/kontena/cli/vault/export_command.rb +2 -2
  32. data/lib/kontena/cli/vault/import_command.rb +4 -10
  33. data/lib/kontena/main_command.rb +1 -1
  34. data/lib/kontena/plugin_manager.rb +16 -1
  35. data/lib/kontena_cli.rb +23 -14
  36. data/spec/kontena/cli/cloud/master/add_command_spec.rb +5 -5
  37. data/spec/kontena/cli/grids/trusted_subnets/add_command_spec.rb +20 -4
  38. data/spec/kontena/cli/grids/trusted_subnets/list_command_spec.rb +12 -7
  39. data/spec/kontena/cli/grids/trusted_subnets/remove_command_spec.rb +20 -4
  40. data/spec/kontena/cli/master/init_cloud_command_spec.rb +1 -1
  41. data/spec/kontena/cli/master/user/invite_command_spec.rb +2 -2
  42. data/spec/kontena/cli/nodes/ssh_command_spec.rb +43 -0
  43. data/spec/kontena/cli/stacks/restart_command_spec.rb +16 -0
  44. data/spec/kontena/cli/stacks/stop_command_spec.rb +16 -0
  45. data/spec/kontena/cli/stacks/upgrade_command_spec.rb +2 -2
  46. data/spec/kontena/cli/stacks/yaml/validator_v3_spec.rb +22 -2
  47. data/spec/kontena/cli/vault/export_spec.rb +6 -6
  48. data/spec/kontena/cli/vault/import_spec.rb +11 -12
  49. data/spec/kontena/kontena_cli_spec.rb +40 -5
  50. data/spec/spec_helper.rb +9 -7
  51. metadata +12 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0ba6c6982719bd042e6289125deef78e98718195
4
- data.tar.gz: 82bb60f9a2047d1ddc5847edb97803836e31ce5d
3
+ metadata.gz: 94ab10349d6c3c14f160614a1889a8de25719076
4
+ data.tar.gz: 5969036b74c54688c2ced991d4ec63c02f84c539
5
5
  SHA512:
6
- metadata.gz: b880299d9fb59cfbf1bb800dd471411807bb1c170e7f8226781dc2fee1ca8ab4dff42df65c0eee2e628d5965168fa9302d3e1155f59c69abcbf202545249e034
7
- data.tar.gz: 52aa18034fac31b990c3b3d4d45eee5512f51681624e5c6f35dfc4ea241b51246d62d99edb26c87990fda5b3d10eae749086a061cc3d666492e209a939b585e1
6
+ metadata.gz: 8b54fac59b78a266deb4111a1e66841826e43bf41b494f9a63955cb661e9bd5f58c6251625e4f2e8fb62173a975cdc374336d47d4f6368d5076ee1db393da60f
7
+ data.tar.gz: c488fdc913c0806f16deb27c891064c48141c19fd67944f7b80117f946f6b9ad2a61034772e09837261625dab84469eee9606fbd2626aa15e8840b175b0aafdf
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.2.2
1
+ 1.3.0.pre1
@@ -20,7 +20,7 @@ module Kontena
20
20
  return unless command.exit_code == 0
21
21
  return unless current_master.grid.nil?
22
22
 
23
- Kontena.run('grid list --use --verbose')
23
+ Kontena.run(%w(grid list --use --verbose))
24
24
  end
25
25
  end
26
26
  end
@@ -39,7 +39,7 @@ module Kontena
39
39
  puts
40
40
  puts "You don't seem to be logged in to Kontena Cloud"
41
41
  puts
42
- Kontena.run("cloud login --verbose")
42
+ Kontena.run!(%w(cloud login --verbose))
43
43
  config.reset_instance
44
44
  reset_cloud_client
45
45
  result = false
@@ -50,10 +50,15 @@ module Kontena
50
50
  end
51
51
 
52
52
  require 'shellwords'
53
- 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
+ cmd = [
54
+ 'master', 'login', '--no-login-info' ,'--skip-grid-auto-select', '--verbose',
55
+ '--name', command.result[:name],
56
+ '--code', command.result[:code],
57
+ new_master.url
58
+ ]
54
59
  Retriable.retriable do
55
60
  ENV["DEBUG"] && $stderr.puts("Running: #{cmd}")
56
- Kontena.run(cmd)
61
+ Kontena.run!(cmd)
57
62
  end
58
63
  end
59
64
  end
@@ -11,10 +11,9 @@ module Kontena
11
11
  return unless config.current_master
12
12
  return unless config.current_master.name == command.result[:name]
13
13
 
14
- cmd = "grid create --silent test"
15
- ENV["DEBUG"] && $stderr.puts("Running: #{cmd}")
14
+ cmd = %w(grid create --silent test)
16
15
  Retriable.retriable do
17
- Kontena.run(cmd)
16
+ Kontena.run!(cmd)
18
17
  end
19
18
  end
20
19
  end
@@ -15,8 +15,8 @@ module Kontena
15
15
  require 'shellwords'
16
16
 
17
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)
18
+ spinner "Setting Master configuration server.provider to '#{command.result[:provider]}'" do |spin|
19
+ spin.fail! unless Kontena.run(cmd)
20
20
  end
21
21
  end
22
22
  end
@@ -8,15 +8,11 @@ module Kontena
8
8
 
9
9
  def init_cloud_args
10
10
  args = []
11
- args << '--force'
11
+ args << '--force'
12
12
  args << "--cloud-master-id #{command.cloud_master_id}" if command.cloud_master_id
13
13
  args << "--provider #{command.result[:provider]}" if command.result[:provider]
14
14
  args << "--version #{command.result[:version]}" if command.result[:version]
15
- args.join(' ')
16
- end
17
-
18
- def configure_auth_provider
19
- Kontena.run("master init-cloud #{init_cloud_args}")
15
+ args
20
16
  end
21
17
 
22
18
  def after
@@ -25,11 +21,10 @@ module Kontena
25
21
  return unless command.result.has_key?(:name)
26
22
  return unless config.current_master
27
23
  return unless config.current_master.name == command.result[:name]
28
- if command.respond_to?(:skip_auth_provider?) && command.skip_auth_provider?
29
- return
30
- end
31
24
 
32
- configure_auth_provider
25
+ unless command.respond_to?(:skip_auth_provider?) && command.skip_auth_provider?
26
+ Kontena.run(['master', 'init-cloud'] + init_cloud_args)
27
+ end
33
28
  end
34
29
  end
35
30
  end
@@ -32,36 +32,30 @@ module Kontena
32
32
 
33
33
  invite_response = nil
34
34
  spinner "Creating user #{cloud_user_data[:email]} into Kontena Master" do |spin|
35
- invite_response = Kontena.run(["master", "user", "invite", "--external-id", cloud_user_data[:id], "--return", cloud_user_data[:email]], returning: :result)
36
- unless invite_response.kind_of?(Hash) && invite_response.has_key?('invite_code')
37
- spin.fail
38
- end
35
+ invite_response = Kontena.run(["master", "user", "invite", "--external-id", cloud_user_data[:id], "--return", cloud_user_data[:email]])
36
+ spin.fail! unless invite_response.kind_of?(Hash) && invite_response.has_key?('invite_code')
39
37
  end
40
38
 
41
39
  return nil unless invite_response
42
40
  ENV["DEBUG"] && $stderr.puts("Got invite code: #{invite_response['invite_code']}")
43
41
 
44
- role_status = nil
45
-
46
- spinner "Adding master_admin role for #{cloud_user_data[:email]}" do |spin|
47
- role_status = Kontena.run(["master", "user", "role", "add", "--silent", "master_admin", cloud_user_data[:email]])
48
- spin.fail if role_status.to_i > 0
42
+ success = spinner "Adding master_admin role for #{cloud_user_data[:email]}" do |spin|
43
+ spin.fail! unless Kontena.run(["master", "user", "role", "add", "--silent", "master_admin", cloud_user_data[:email]])
44
+ true
49
45
  end
50
46
 
51
- return nil if role_status.to_i > 0
47
+ return nil unless success
52
48
 
53
49
  if current_master.grid
54
50
  spinner "Adding #{cloud_user_data[:email]} to grid '#{current_master.grid}'" do |spin|
55
- grid_add_status = Kontena.run(["grid", "user", "add", "--grid", current_master.grid, cloud_user_data[:email]])
56
- spin.fail if grid_add_status.to_i > 0
51
+ spin.fail! unless Kontena.run(["grid", "user", "add", "--grid", current_master.grid, cloud_user_data[:email]])
57
52
  end
58
53
  end
59
54
 
60
- return unless current_master.username.to_s == 'admin'
55
+ return nil unless current_master.username.to_s == 'admin'
61
56
 
62
- new_user_token = nil
63
- spinner "Creating an access token for #{cloud_user_data[:email]}" do |spin|
64
- new_user_token = Kontena.run(["master", "token", "create", "-e", "0", "-s", "user", "--return", "-u", cloud_user_data[:email]], returning: :result)
57
+ new_user_token = spinner "Creating an access token for #{cloud_user_data[:email]}" do |spin|
58
+ Kontena.run!(["master", "token", "create", "-e", "0", "-s", "user", "--return", "-u", cloud_user_data[:email]])
65
59
  end
66
60
 
67
61
  master_name = current_master.name.dup
@@ -1,6 +1,8 @@
1
1
 
2
2
  class Kontena::Cli::AppCommand < Kontena::Command
3
3
 
4
+ warn Kontena.pastel.yellow("[DEPRECATED] The `kontena app` commands are deprecated in favor of `kontena stack` commands and will be removed in future releases")
5
+
4
6
  subcommand "init", "Init Kontena application", load_subcommand('apps/init_command')
5
7
  subcommand "build", "Build Kontena services", load_subcommand('apps/build_command')
6
8
  subcommand "config", "View service configurations", load_subcommand('apps/config_command')
@@ -47,7 +47,7 @@ module Kontena::Cli::Cloud::Master
47
47
  masters = []
48
48
  spinner "Retrieving a list of your registered Kontena Masters in Kontena Cloud" do |spin|
49
49
  begin
50
- masters = Kontena.run("cloud master list --return", returning: :result)
50
+ masters = Kontena.run!(%w(cloud master list --return))
51
51
  rescue SystemExit
52
52
  spin.fail
53
53
  end
@@ -96,12 +96,12 @@ module Kontena::Cli::Cloud::Master
96
96
  end
97
97
  if response && response.kind_of?(Hash) && response.has_key?('data') && response['data']['attributes']
98
98
  if (self.provider && response['data']['attributes']['provider'] != self.provider) || (self.version && response['data']['attributes']['version'] != self.version)
99
- spinner "Updating provider and version attributes to Kontena Cloud master" do
99
+ spinner "Updating provider and version attributes to Kontena Cloud master" do |spin|
100
100
  args = []
101
- args << "--provider #{self.provider.shellescape}" if self.provider
102
- args << "--version #{self.version.shellescape}" if self.version
101
+ args += ['--provider', self.provider] if self.provider
102
+ args += ['--version', self.version] if self.version
103
103
  args << self.cloud_master_id
104
- Kontena.run("cloud master update #{args.join(' ')}")
104
+ spin.fail! unless Kontena.run(['cloud', 'master', 'update'] + args)
105
105
  end
106
106
  end
107
107
  end
@@ -111,18 +111,27 @@ module Kontena::Cli::Cloud::Master
111
111
  end
112
112
  end
113
113
 
114
- spinner "Loading Kontena Cloud auth provider base configuration to Kontena Master" do
115
- Kontena.run('master config import --force --preset kontena_auth_provider')
114
+ spinner "Loading Kontena Cloud auth provider base configuration to Kontena Master" do |spin|
115
+ spin.fail! unless Kontena.run(%w(master config import --force --preset kontena_auth_provider))
116
116
  end
117
117
 
118
- spinner "Updating OAuth2 client-id and client-secret to Kontena Master" do
119
- Kontena.run("master config set oauth2.client_id=#{response['data']['attributes']['client-id'].shellescape} oauth2.client_secret=#{response['data']['attributes']['client-secret'].shellescape} server.root_url=#{current_master.url.shellescape} server.name=#{current_master.name.shellescape} cloud.provider_is_kontena=true")
118
+ spinner "Updating OAuth2 client-id and client-secret to Kontena Master" do |spin|
119
+ spin.fail! unless Kontena.run(
120
+ [
121
+ 'master', 'config', 'set',
122
+ "oauth2.client_id=#{response['data']['attributes']['client-id'].shellescape}",
123
+ "oauth2.client_secret=#{response['data']['attributes']['client-secret'].shellescape}",
124
+ "server.root_url=#{current_master.url.shellescape}",
125
+ "server.name=#{current_master.name.shellescape}",
126
+ "cloud.provider_is_kontena=true"
127
+ ]
128
+ )
120
129
  end
121
130
  end
122
131
 
123
132
  def execute
124
133
  unless cloud_client.authentication_ok?(kontena_account.userinfo_endpoint)
125
- Kontena.run('cloud login')
134
+ Kontena.run!(%w(cloud login))
126
135
  config.reset_instance
127
136
  reset_cloud_client
128
137
  end
@@ -296,44 +296,14 @@ module Kontena
296
296
  def any_key_to_continue_with_timeout(timeout=9)
297
297
  return nil if running_silent?
298
298
  return nil unless $stdout.tty?
299
- start_time = Time.now.to_i
300
- end_time = start_time + timeout
301
- Thread.main['any_key.timed_out'] = false
302
- msg = "Press any key to continue or ctrl-c to cancel.. (Automatically continuing in ? seconds)"
303
-
304
- reader_thread = Thread.new do
305
- Thread.main['any_key.char'] = $stdin.getch
306
- end
307
-
308
- countdown_thread = Thread.new do
309
- time_left = timeout
310
- while time_left > 0 && Thread.main['any_key.char'].nil?
311
- print "\r#{pastel.bright_white("#{msg.sub("?", time_left.to_s)}")} "
312
- time_left = end_time - Time.now.to_i
313
- sleep 0.1
314
- end
315
- print "\r#{' ' * msg.length} \r"
316
- reader_thread.kill if reader_thread.alive?
317
- end
318
-
319
- countdown_thread.join
320
-
321
- if Thread.main['any_key.char'] == "\u0003"
322
- error "Canceled"
323
- end
299
+ prompt.keypress("Press any key to continue or ctrl-c to cancel (Automatically continuing in :countdown seconds) ...", timeout: timeout)
324
300
  end
325
301
 
326
302
  def any_key_to_continue(timeout = nil)
327
303
  return nil if running_silent?
328
304
  return nil unless $stdout.tty?
329
305
  return any_key_to_continue_with_timeout(timeout) if timeout
330
- msg = "Press any key to continue or ctrl-c to cancel.. "
331
- print pastel.bright_cyan("#{msg}")
332
- char = $stdin.getch
333
- print "\r#{' ' * msg.length}\r"
334
- if char == "\u0003"
335
- error "Canceled"
336
- end
306
+ prompt.keypress("Press any key to continue or ctrl-c to cancel..")
337
307
  end
338
308
 
339
309
  def display_account_login_info
@@ -1,17 +1,17 @@
1
1
  module Kontena::Cli::Grids::TrustedSubnets
2
2
  class AddCommand < Kontena::Command
3
3
  include Kontena::Cli::Common
4
+ include Kontena::Cli::GridOptions
4
5
 
5
- parameter "NAME", "Grid name"
6
6
  parameter "SUBNET", "Trusted subnet"
7
7
 
8
+ requires_current_master
9
+
8
10
  def execute
9
- require_api_url
10
- token = require_token
11
- grid = client(token).get("grids/#{name}")
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 #{name.colorize(:cyan)} grid " do
14
- client(token).put("grids/#{name}", data)
13
+ spinner "Adding #{subnet.colorize(:cyan)} as a trusted subnet in #{current_grid.colorize(:cyan)} grid " do
14
+ client.put("grids/#{current_grid}", data)
15
15
  end
16
16
  end
17
17
  end
@@ -1,13 +1,12 @@
1
1
  module Kontena::Cli::Grids::TrustedSubnets
2
2
  class ListCommand < Kontena::Command
3
3
  include Kontena::Cli::Common
4
+ include Kontena::Cli::GridOptions
4
5
 
5
- parameter "NAME", "Grid name"
6
+ requires_current_master
6
7
 
7
8
  def execute
8
- require_api_url
9
- token = require_token
10
- grid = client(token).get("grids/#{current_grid}")
9
+ grid = client.get("grids/#{current_grid}")
11
10
  trusted_subnets = grid['trusted_subnets'] || []
12
11
  trusted_subnets.each do |subnet|
13
12
  puts subnet
@@ -1,23 +1,23 @@
1
1
  module Kontena::Cli::Grids::TrustedSubnets
2
2
  class RemoveCommand < Kontena::Command
3
3
  include Kontena::Cli::Common
4
+ include Kontena::Cli::GridOptions
4
5
 
5
- parameter "NAME", "Grid name"
6
6
  parameter "SUBNET", "Trusted subnet"
7
7
  option "--force", :flag, "Force remove", default: false, attribute_name: :forced
8
8
 
9
+ requires_current_master
10
+
9
11
  def execute
10
- require_api_url
11
- token = require_token
12
- grid = client(token).get("grids/#{name}")
12
+ grid = client.get("grids/#{current_grid}")
13
13
  confirm_command(subnet) unless forced?
14
14
  trusted_subnets = grid['trusted_subnets'] || []
15
15
  unless trusted_subnets.delete(self.subnet)
16
- exit_with_error("Grid #{name.colorize(:cyan)} does not have trusted subnet #{subnet.colorize(:cyan)}")
16
+ exit_with_error("Grid #{current_grid.colorize(:cyan)} does not have trusted subnet #{subnet.colorize(:cyan)}")
17
17
  end
18
18
  data = {trusted_subnets: trusted_subnets}
19
- spinner "Removing trusted subnet #{subnet.colorize(:cyan)} from #{name.colorize(:cyan)} grid " do
20
- client(token).put("grids/#{name}", data)
19
+ spinner "Removing trusted subnet #{subnet.colorize(:cyan)} from #{current_grid.colorize(:cyan)} grid " do
20
+ client.put("grids/#{current_grid}", data)
21
21
  end
22
22
  end
23
23
  end
@@ -66,9 +66,8 @@ module Kontena::Cli::Master
66
66
  end
67
67
  end
68
68
  end
69
- command = cmd_class.to_s[/Plugin::(.+?)::/, 1].downcase
70
- command << " master create #{options.join(" ")}"
71
- Kontena.run(command)
69
+ cmd = [cmd_class.to_s[/Plugin::(.+?)::/, 1].downcase, 'master', 'create'] + options
70
+ Kontena.run!(cmd)
72
71
  end
73
72
  end
74
73
 
@@ -20,7 +20,7 @@ module Kontena::Cli::Master
20
20
  args += ["--cloud-master-id", self.cloud_master_id.shellescape] if self.cloud_master_id
21
21
  args += ["--provider", self.provider.shellescape] if self.provider
22
22
  args += ["--version", self.version.shellescape] if self.version
23
- Kontena.run("cloud master add #{args.join(' ')}")
23
+ Kontena.run!(['cloud', 'master', 'add'] + args)
24
24
  end
25
25
  end
26
26
  end
@@ -14,7 +14,9 @@ module Kontena::Cli::Master
14
14
  params << "--name #{self.name.shellescape}" if self.name
15
15
  params << "--verbose" if self.verbose?
16
16
 
17
- Kontena.run("master login #{params.join(' ')} #{self.url.shellescape}")
17
+ cmd = ['master', 'login'] + params
18
+ cmd << url
19
+ Kontena.run!(cmd)
18
20
  end
19
21
  end
20
22
  end
@@ -16,20 +16,17 @@ module Kontena::Cli::Master
16
16
  end
17
17
 
18
18
  def master_provider
19
- Kontena.run('master config get --return server.provider', returning: :result)
19
+ Kontena.run!(%w(master config get --return server.provider))
20
20
  end
21
21
 
22
22
  def execute
23
-
24
- commands_list.insert('--') unless commands_list.empty?
25
-
26
23
  if master_provider == 'vagrant'
27
24
  unless Kontena::PluginManager.instance.plugins.find { |plugin| plugin.name == 'kontena-plugin-vagrant' }
28
25
  exit_with_error 'You need to install vagrant plugin to ssh into this node. Use kontena plugin install vagrant'
29
26
  end
30
27
  cmd = ['vagrant', 'master', 'ssh']
31
28
  cmd += commands_list
32
- Kontena.run(cmd)
29
+ Kontena.run!(cmd)
33
30
  else
34
31
  cmd = ['ssh']
35
32
  cmd << "#{user}@#{master_host}"
@@ -40,4 +37,3 @@ module Kontena::Cli::Master
40
37
  end
41
38
  end
42
39
  end
43
-
@@ -33,7 +33,7 @@ module Kontena::Cli::Master::Token
33
33
  exit 0
34
34
  end
35
35
 
36
- Kontena.run("master token show #{current_master.token.access_token}")
36
+ Kontena.run!(['master', 'token', 'show', current_master.token.access_token])
37
37
  end
38
38
  end
39
39
  end
@@ -39,11 +39,11 @@ module Kontena::Cli::Master::User
39
39
  puts " * command: kontena master join #{current_master.url} #{response['invite_code']}"
40
40
  end
41
41
  roles.each do |role|
42
- Kontena.run(["master", "user", "role", "add", role, email])
42
+ raise "Failed to add role" unless Kontena.run(["master", "user", "role", "add", role, email])
43
43
  end
44
44
  rescue => ex
45
- $stderr.puts pastel.red("Failed to invite #{email}")
46
45
  ENV["DEBUG"] && $stderr.puts("#{ex} : #{ex.message}\n#{ex.backtrace.join("\n ")}")
46
+ exit_with_error "Failed to invite #{email} : #{ex.message}"
47
47
  end
48
48
  end
49
49
  end
@@ -1,5 +1,3 @@
1
- require 'kontena/cli/master/user_command'
2
-
3
1
  module Kontena::Cli::Master
4
2
  class UserCommand < Kontena::Command
5
3
  subcommand "invite", "Invite user to Kontena Master", load_subcommand('master/user/invite_command')
@@ -28,14 +28,12 @@ module Kontena::Cli::Nodes
28
28
 
29
29
  provider = Array(node["labels"]).find{ |l| l.start_with?('provider=')}.to_s.split('=').last
30
30
 
31
- commands_list.insert('--') unless commands_list.empty?
32
-
33
31
  if provider == 'vagrant'
34
32
  unless Kontena::PluginManager.instance.plugins.find { |plugin| plugin.name == 'kontena-plugin-vagrant' }
35
33
  exit_with_error 'You need to install vagrant plugin to ssh into this node. Use kontena plugin install vagrant'
36
34
  end
37
35
  cmd = ['vagrant', 'node', 'ssh', node['name']] + commands_list
38
- Kontena.run(cmd)
36
+ Kontena.run!(cmd)
39
37
  else
40
38
  cmd = ['ssh']
41
39
  cmd += ["-i", identity_file] if identity_file
@@ -11,6 +11,8 @@ class Kontena::Cli::StackCommand < Kontena::Command
11
11
  subcommand "build", "Build images listed in a stack file and push them to an image registry", load_subcommand('stacks/build_command')
12
12
  subcommand ["reg", "registry"], "Stack registry related commands", load_subcommand('stacks/registry_command')
13
13
  subcommand "validate", "Process and validate a stack file", load_subcommand('stacks/validate_command')
14
+ subcommand "stop", "Stop stacks services", load_subcommand('stacks/stop_command')
15
+ subcommand "restart", "Restart stacks services", load_subcommand('stacks/restart_command')
14
16
 
15
17
  def execute
16
18
  end
@@ -154,7 +154,7 @@ module Kontena::Cli::Stacks
154
154
 
155
155
  def stacks_client
156
156
  return @stacks_client if @stacks_client
157
- Kontena.run('cloud login') unless cloud_auth?
157
+ Kontena.run!(%w(cloud login)) unless cloud_auth?
158
158
  config.reset_instance
159
159
  @stacks_client = Kontena::StacksClient.new(kontena_account.stacks_url, kontena_account.token)
160
160
  end
@@ -26,7 +26,7 @@ module Kontena::Cli::Stacks
26
26
  spinner "Creating stack #{pastel.cyan(stack['name'])} " do
27
27
  create_stack(stack)
28
28
  end
29
- Kontena.run("stack deploy #{stack['name']}") if deploy?
29
+ Kontena.run!(['stack', 'deploy', stack['name']]) if deploy?
30
30
  end
31
31
 
32
32
  def create_stack(stack)
@@ -0,0 +1,23 @@
1
+ require_relative 'common'
2
+
3
+ module Kontena::Cli::Stacks
4
+ class RestartCommand < Kontena::Command
5
+ include Kontena::Cli::Common
6
+ include Kontena::Cli::GridOptions
7
+ include Common
8
+
9
+ banner "Restarts all services of a stack that has been installed in a grid on Kontena Master"
10
+
11
+ parameter "NAME", "Stack name"
12
+
13
+ requires_current_master
14
+ requires_current_master_token
15
+
16
+ def execute
17
+ spinner "Sending restart signal for stack services" do
18
+ client.post("stacks/#{current_grid}/#{name}/restart", {})
19
+ end
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ require_relative 'common'
2
+
3
+ module Kontena::Cli::Stacks
4
+ class StopCommand < Kontena::Command
5
+ include Kontena::Cli::Common
6
+ include Kontena::Cli::GridOptions
7
+ include Common
8
+
9
+ banner "Stops all services of a stack that has been installed in a grid on Kontena Master"
10
+
11
+ parameter "NAME", "Stack name"
12
+
13
+ requires_current_master
14
+ requires_current_master_token
15
+
16
+ def execute
17
+ spinner "Sending stop signal for stack services" do
18
+ client.post("stacks/#{current_grid}/#{name}/stop", {})
19
+ end
20
+ end
21
+
22
+ end
23
+ end
@@ -37,7 +37,7 @@ module Kontena::Cli::Stacks
37
37
  update_stack(stack) || spin.fail!
38
38
  end
39
39
 
40
- Kontena.run(['stack', 'deploy', name]) if deploy?
40
+ Kontena.run!(['stack', 'deploy', name]) if deploy?
41
41
  end
42
42
 
43
43
  def update_stack(stack)
@@ -43,7 +43,7 @@ module Kontena::Cli::Stacks::YAML
43
43
  )
44
44
  end
45
45
  elsif value.is_a?(Array)
46
- value.all? { |v| v.kind_of?(String) && v =~ /\A\S+(?<!\\)=.*/ }
46
+ value.all? { |v| v.kind_of?(String) && v =~ /\A[^=]+=/ }
47
47
  else
48
48
  false
49
49
  end
@@ -13,8 +13,8 @@ module Kontena::Cli::Vault
13
13
  require 'shellwords'
14
14
  meth = json? ? :to_json : :to_yaml
15
15
  puts Hash[
16
- *Kontena.run('vault ls --return', returning: :result).sort.flat_map do |secret|
17
- [secret, Kontena.run("vault read --return #{secret.shellescape}", returning: :result)]
16
+ *Kontena.run!(['vault', 'ls', '--return']).sort.flat_map do |secret|
17
+ [secret, Kontena.run!(['vault', 'read', '--return', secret])]
18
18
  end
19
19
  ].send(meth)
20
20
  end
@@ -14,10 +14,6 @@ module Kontena::Cli::Vault
14
14
 
15
15
  requires_current_master
16
16
 
17
- UPDATE_CMD = 'vault update --upsert --silent %{key} %{value}'
18
- DELETE_CMD = 'vault rm --silent --force %{key}'
19
-
20
-
21
17
  def parsed_input
22
18
  json? ? JSON.load(input) : YAML.safe_load(input)
23
19
  end
@@ -60,18 +56,16 @@ module Kontena::Cli::Vault
60
56
 
61
57
  unless updates.empty?
62
58
  spinner "Updating #{updates.size} secrets" do |spin|
63
- updates.each do |pair|
64
- result = Kontena.run(UPDATE_CMD % { key: pair.first.shellescape, value: pair.last.shellescape })
65
- spin.fail! unless result.zero?
59
+ updates.each do |key_value_pair|
60
+ spin.fail! unless Kontena.run(['vault', 'update', '--upsert', '--silent'] + key_value_pair)
66
61
  end
67
62
  end
68
63
  end
69
64
 
70
65
  unless deletes.empty? || skip_null?
71
66
  spinner "Deleting #{deletes.size} secrets" do |spin|
72
- deletes.map(&:shellescape).each do |del|
73
- result = Kontena.run(DELETE_CMD % { key: del })
74
- spin.fail! unless result.zero?
67
+ deletes.map(&:shellescape).each do |key_to_delete|
68
+ spin.fail! unless Kontena.run(['vault', 'rm', '--silent', '--force', key_to_delete])
75
69
  end
76
70
  end
77
71
  end
@@ -51,6 +51,6 @@ class Kontena::MainCommand < Kontena::Command
51
51
  end
52
52
 
53
53
  def known_plugin_subcommand?(name)
54
- ['vagrant', 'packet', 'digitalocean', 'azure', 'upcloud', 'aws'].include?(name)
54
+ ['vagrant', 'packet', 'digitalocean', 'azure', 'upcloud', 'aws', 'shell'].include?(name)
55
55
  end
56
56
  end