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
@@ -1,6 +1,6 @@
1
1
  require 'kontena/cli/cloud/login_command'
2
2
  require 'kontena/cli/localhost_web_server'
3
- require 'launchy'
3
+ require 'kontena/cli/browser_launcher'
4
4
 
5
5
  describe Kontena::Cli::Cloud::LoginCommand do
6
6
 
@@ -145,7 +145,7 @@ describe Kontena::Cli::Cloud::LoginCommand do
145
145
  expect(webserver).to receive(:serve_one).and_return({
146
146
  'access_token' => 'abcd'
147
147
  })
148
- expect(Launchy).to receive(:open).and_return(true)
148
+ expect(Kontena::Cli::BrowserLauncher).to receive(:open).and_return(true)
149
149
  expect(subject).to receive(:finish).and_return(true)
150
150
  subject.run([])
151
151
  expect(account.token.access_token).to eq 'abcd'
@@ -159,7 +159,7 @@ describe Kontena::Cli::Cloud::LoginCommand do
159
159
  expect(webserver).to receive(:serve_one).and_return({
160
160
  'code' => 'abcd'
161
161
  })
162
- expect(Launchy).to receive(:open).and_return(true)
162
+ expect(Kontena::Cli::BrowserLauncher).to receive(:open).and_return(true)
163
163
  expect(client).to receive(:exchange_code).with('abcd').and_return({
164
164
  'access_token' => 'abcdefg'
165
165
  })
@@ -176,7 +176,7 @@ describe Kontena::Cli::Cloud::LoginCommand do
176
176
  expect(webserver).to receive(:serve_one).and_return({
177
177
  'error' => 'foo'
178
178
  })
179
- expect(Launchy).to receive(:open).and_return(true)
179
+ expect(Kontena::Cli::BrowserLauncher).to receive(:open).and_return(true)
180
180
  expect{subject.run([])}.to exit_with_error.and output(/Authentication failed: foo/).to_stderr
181
181
  end
182
182
  end
@@ -137,8 +137,15 @@ describe Kontena::Cli::Common do
137
137
  it 'returns true if input matches' do
138
138
  allow(subject).to receive(:ask).and_return('name-to-confirm')
139
139
 
140
- expect(subject.confirm_command('name-to-confirm')).to be_truthy
141
140
  expect{subject.confirm_command('name-to-confirm')}.to_not raise_error
141
+ expect(subject.confirm_command('name-to-confirm')).to be_truthy
142
+ end
143
+
144
+ it 'returns true if input matches and param is not a string' do
145
+ allow(subject).to receive(:ask).and_return('123')
146
+
147
+ expect{subject.confirm_command(123)}.to_not raise_error
148
+ expect(subject.confirm_command(123)).to be_truthy
142
149
  end
143
150
 
144
151
  it 'raises error unless input matches' do
@@ -51,6 +51,19 @@ describe Kontena::Cli::Grids::UpdateCommand do
51
51
  subject.run(['--no-statsd-server', 'test'])
52
52
  end
53
53
 
54
+ it 'should send "none" as log forwarder when --no-log-forwarder given' do
55
+ expect(client).to receive(:put).with(
56
+ 'grids/test', hash_including(
57
+ logs: hash_including(forwarder: 'none')
58
+ )
59
+ )
60
+ subject.run(['--no-log-forwarder', 'test'])
61
+ end
62
+
63
+ it 'should exit with error if --log-forwarder and --no-log-forwarder given' do
64
+ expect{subject.run(['--log-forwarder', 'fluentd', '--no-log-forwarder', 'test'])}.to exit_with_error.and output(/together/).to_stderr
65
+ end
66
+
54
67
  it 'should send empty default_affinity when --no-default-affinity given' do
55
68
  expect(client).to receive(:put).with(
56
69
  'grids/test', hash_including({
@@ -1,7 +1,4 @@
1
1
  require 'kontena/cli/master/join_command'
2
- require 'kontena/cli/localhost_web_server'
3
- require 'launchy'
4
- require 'ostruct'
5
2
 
6
3
  describe Kontena::Cli::Master::JoinCommand do
7
4
 
@@ -30,4 +27,4 @@ describe Kontena::Cli::Master::JoinCommand do
30
27
  expect(Kontena).to receive(:run!).with(%w(master login --join xyz --verbose someurl))
31
28
  subject.run(%w(--verbose someurl xyz))
32
29
  end
33
- end
30
+ end
@@ -1,6 +1,6 @@
1
1
  require 'kontena/cli/master/login_command'
2
2
  require 'kontena/cli/localhost_web_server'
3
- require 'launchy'
3
+ require 'kontena/cli/browser_launcher'
4
4
  require 'ostruct'
5
5
 
6
6
  describe Kontena::Cli::Master::LoginCommand do
@@ -147,7 +147,7 @@ describe Kontena::Cli::Master::LoginCommand do
147
147
  allow(File).to receive(:exist?).and_return(true)
148
148
  allow(File).to receive(:readable?).and_return(true)
149
149
  allow(Kontena::Client).to receive(:new).and_return(client)
150
- allow(Launchy).to receive(:open).and_return(true)
150
+ allow(Kontena::Cli::BrowserLauncher).to receive(:open).and_return(true)
151
151
  allow(Kontena::LocalhostWebServer).to receive(:port).and_return(12345)
152
152
  allow(Kontena::LocalhostWebServer).to receive(:serve_one).and_return(
153
153
  { 'code' => 'abcd1234' }
@@ -254,7 +254,7 @@ describe Kontena::Cli::Master::LoginCommand do
254
254
  expect(opts[:path]).to eq "/authenticate?redirect_uri=http%3A%2F%2Flocalhost%3A12345%2Fcb&expires_in=7200"
255
255
  expect(opts[:http_method]).to eq :get
256
256
  end.and_return({})
257
- expect(Launchy).to receive(:open).with('http://authprovider.example.com/authplz').and_return(true)
257
+ expect(Kontena::Cli::BrowserLauncher).to receive(:open).with('http://authprovider.example.com/authplz').and_return(true)
258
258
  expect(client).to receive(:exchange_code).with('abcd1234').and_return('access_token' => 'defg456', 'server' => { 'name' => 'foobar' }, 'user' => { 'name' => 'testuser' })
259
259
  subject.run(%w(--no-remote --skip-grid-auto-select http://foobar.example.com))
260
260
  expect(subject.config.servers.size).to eq 1
@@ -328,7 +328,7 @@ describe Kontena::Cli::Master::LoginCommand do
328
328
  it 'changes current master to created master' do
329
329
  allow(client).to receive(:last_response).at_least(:once).and_return(OpenStruct.new(status: 302, headers: { 'Location' => 'http://authprovider.example.com/authplz' }))
330
330
  allow(client).to receive(:request).and_return({})
331
- allow(Launchy).to receive(:open).with('http://authprovider.example.com/authplz').and_return(true)
331
+ allow(Kontena::Cli::BrowserLauncher).to receive(:open).with('http://authprovider.example.com/authplz').and_return(true)
332
332
  allow(client).to receive(:exchange_code).with('abcd1234').and_return('access_token' => 'defg456', 'server' => { 'name' => 'foobar' }, 'user' => { 'name' => 'testuser' })
333
333
  subject.config.current_master = 'fooserver'
334
334
  subject.config.current_master
@@ -0,0 +1,132 @@
1
+ require 'kontena/cli/master/token_command'
2
+ require 'kontena/cli/master/token/create_command'
3
+
4
+ describe Kontena::Cli::Master::Token::CreateCommand do
5
+ include ClientHelpers
6
+ include RequirementsHelper
7
+ include OutputHelpers
8
+
9
+ expect_to_require_current_master
10
+ expect_to_require_current_master_token
11
+
12
+ let(:response) do
13
+ {
14
+ "id" => "123",
15
+ "token_type" => "bearer",
16
+ "access_token" => '1234abcd',
17
+ "refresh_token" => '2345defg',
18
+ "access_token_last_four" => "abcd",
19
+ "refresh_token_last_four" => "defg",
20
+ "expires_in" => 100,
21
+ "scopes" => "user",
22
+ "user" => {
23
+ "id" => "abc",
24
+ "email" => "user@email",
25
+ "name" => "username"
26
+ },
27
+ "server" => {
28
+ "name" => "foo"
29
+ },
30
+ "description" => "description test"
31
+ }
32
+ end
33
+
34
+ context '--description' do
35
+ it 'adds a description to token create request' do
36
+ expect(client).to receive(:post) do |path, data|
37
+ expect(path).to eq '/oauth2/authorize'
38
+ expect(data[:description]).to eq 'description test'
39
+ end.and_return(response)
40
+ expect{subject.run(['--description', 'description test'])}.not_to exit_with_error
41
+ end
42
+ end
43
+
44
+ context '--scopes' do
45
+ it 'accepts a comma separated list of scopes' do
46
+ expect(client).to receive(:post) do |path, data|
47
+ expect(path).to eq '/oauth2/authorize'
48
+ expect(data[:scope]).to eq 'xyz,zyx'
49
+ end.and_return(response)
50
+ expect{subject.run(['--scopes', 'xyz,zyx'])}.not_to exit_with_error
51
+ end
52
+ end
53
+
54
+ context '--code' do
55
+ it 'can request an authorization_code' do
56
+ expect(client).to receive(:post) do |path, data|
57
+ expect(path).to eq '/oauth2/authorize'
58
+ expect(data[:response_type]).to eq 'code'
59
+ end.and_return(response)
60
+ expect{subject.run(['--code'])}.not_to exit_with_error
61
+ end
62
+ end
63
+
64
+ context '--expires-in' do
65
+ it 'can request a token without expiration' do
66
+ expect(client).to receive(:post) do |path, data|
67
+ expect(path).to eq '/oauth2/authorize'
68
+ expect(data[:expires_in]).to eq '0'
69
+ end.and_return(response)
70
+ expect{subject.run(['--expires-in', '0'])}.not_to exit_with_error
71
+ end
72
+ end
73
+
74
+ context '--token' do
75
+ it 'requests a token and outputs the generated token' do
76
+ expect(client).to receive(:post) do |path, data|
77
+ expect(path).to eq '/oauth2/authorize'
78
+ expect(data[:response_type]).to eq 'token'
79
+ end.and_return(response)
80
+ expect{subject.run(['--token'])}.to output(/\A1234abcd\Z/).to_stdout
81
+ end
82
+ end
83
+
84
+ context '--id' do
85
+ it 'requests a token and outputs the generated token id' do
86
+ expect(client).to receive(:post) do |path, data|
87
+ expect(path).to eq '/oauth2/authorize'
88
+ expect(data[:response_type]).to eq 'token'
89
+ end.and_return(response)
90
+ expect{subject.run(['--id'])}.to output(/\A123\Z/).to_stdout
91
+ end
92
+ end
93
+
94
+ context '--user' do
95
+ it 'can request a token for another user' do
96
+ expect(client).to receive(:post) do |path, data|
97
+ expect(path).to eq '/oauth2/authorize'
98
+ expect(data[:user]).to eq 'foo@example.com'
99
+ end.and_return(response)
100
+ expect{subject.run(['--user', 'foo@example.com'])}.not_to exit_with_error
101
+ end
102
+ end
103
+
104
+ context 'no parameters' do
105
+ it 'requests an expiring user scoped token with an empty description and outputs token and refresh token' do
106
+ expect(client).to receive(:post) do |path, data|
107
+ expect(path).to eq '/oauth2/authorize'
108
+ expect(data[:user]).to be_nil
109
+ expect(data[:description]).to be_nil
110
+ expect(data[:response_type]).to eq 'token'
111
+ expect(data[:expires_in]).to eq '7200'
112
+ expect(data[:scope]).to eq 'user'
113
+ end.and_return(response)
114
+ expect{subject.run([])}.to output_yaml(
115
+ 123 => {
116
+ 'access_token' => '1234abcd',
117
+ 'refresh_token' => '2345defg',
118
+ 'access_token_last_four' => 'abcd',
119
+ 'refresh_token_last_four' => 'defg',
120
+ 'expires_in' => 100,
121
+ 'token_type' => 'bearer',
122
+ 'scopes' => 'user',
123
+ 'user_id' => 'abc',
124
+ 'user_email' => 'user@email',
125
+ 'user_name' => 'username',
126
+ 'server_name' => 'foo',
127
+ 'description' => 'description test'
128
+ }
129
+ )
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,90 @@
1
+ require 'kontena/cli/master/token_command'
2
+ require 'kontena/cli/master/token/show_command'
3
+
4
+ describe Kontena::Cli::Master::Token::ShowCommand do
5
+
6
+ include ClientHelpers
7
+ include RequirementsHelper
8
+ include OutputHelpers
9
+
10
+ expect_to_require_current_master
11
+ expect_to_require_current_master_token
12
+
13
+ context 'for an access token' do
14
+ let(:response) do
15
+ {
16
+ "id" => "123",
17
+ "token_type" => "bearer",
18
+ "access_token" => nil,
19
+ "refresh_token" => nil,
20
+ "access_token_last_four" => "abcd",
21
+ "refresh_token_last_four" => "efgh",
22
+ "expires_in" => 100,
23
+ "scopes" => "user",
24
+ "user" => {
25
+ "id" => "abc",
26
+ "email" => "user@email",
27
+ "name" => "username"
28
+ },
29
+ "server" => {
30
+ "name" => "foo"
31
+ },
32
+ "description" => "description test"
33
+ }
34
+ end
35
+
36
+ it 'requests token data from master and displays it' do
37
+ expect(client).to receive(:get).with("/oauth2/tokens/123").and_return(response)
38
+ expect{subject.run(['123'])}.to output_yaml(
39
+ 123 => {
40
+ 'token_type' => 'bearer',
41
+ 'scopes' => 'user',
42
+ 'user_id' => 'abc',
43
+ 'user_email' => 'user@email',
44
+ 'user_name' => 'username',
45
+ 'server_name' => 'foo',
46
+ 'access_token_last_four' => 'abcd',
47
+ 'refresh_token_last_four' => 'efgh',
48
+ 'expires_in' => 100,
49
+ 'description' => 'description test'
50
+ }
51
+ )
52
+ end
53
+ end
54
+
55
+ context 'for an authorization code' do
56
+ let(:response) do
57
+ {
58
+ "id" => 123,
59
+ "grant_type" => "authorization_code",
60
+ "code" => "abcd",
61
+ "scopes" => "user",
62
+ "user" => {
63
+ "id" => "abc",
64
+ "email" => "user@email",
65
+ "name" => "username"
66
+ },
67
+ "server" => {
68
+ "name" => "foo"
69
+ },
70
+ "description" => 'description test'
71
+ }
72
+ end
73
+
74
+ it 'requests auth code data from master and displays it' do
75
+ expect(client).to receive(:get).with("/oauth2/tokens/123").and_return(response)
76
+ expect{subject.run(['123'])}.to output_yaml(
77
+ 123 => {
78
+ 'code' => 'abcd',
79
+ 'token_type' => 'authorization_code',
80
+ 'scopes' => 'user',
81
+ 'user_id' => 'abc',
82
+ 'user_email' => 'user@email',
83
+ 'user_name' => 'username',
84
+ 'server_name' => 'foo',
85
+ 'description' => 'description test'
86
+ }
87
+ )
88
+ end
89
+ end
90
+ end
@@ -18,11 +18,20 @@ describe Kontena::Cli::Nodes::Labels::RemoveCommand do
18
18
  }
19
19
  end
20
20
 
21
- it "doesn't remove anything" do
22
- expect(client).to receive(:put).with('nodes/test-grid/node', {
23
- labels: [],
24
- })
25
- subject.run(['node', 'test=yes'])
21
+ context "when removing an unknown label" do
22
+ context "with --force" do
23
+ it 'does nothing' do
24
+ expect(client).not_to receive(:put)
25
+ expect{subject.run(['--force', 'node', 'test=yes'])}.not_to exit_with_error
26
+ end
27
+ end
28
+
29
+ context "without --force" do
30
+ it "exits with error" do
31
+ expect(client).not_to receive(:put)
32
+ expect{subject.run(['node', 'test=yes'])}.to exit_with_error.and output(/not found/).to_stderr
33
+ end
34
+ end
26
35
  end
27
36
  end
28
37
 
@@ -53,5 +62,26 @@ describe Kontena::Cli::Nodes::Labels::RemoveCommand do
53
62
 
54
63
  subject.run(['node', 'test=yes', 'test=no'])
55
64
  end
65
+
66
+ context "when removing an unknown label" do
67
+ context "without --force" do
68
+ it "exits with error" do
69
+ expect{subject.run(['node', 'test=yes', 'test=no', 'test=maybe'])}.to exit_with_error.and output(/Label test=maybe not found/).to_stderr
70
+ end
71
+
72
+ it "exits with plural error" do
73
+ expect{subject.run(['node', 'test=yes', 'test=no', 'test=maybe', 'test=almost'])}.to exit_with_error.and output(/Labels test=maybe, test=almost not found/).to_stderr
74
+ end
75
+ end
76
+ context "with --force" do
77
+ it 'ignores any labels that were not found with --force' do
78
+ expect(client).to receive(:put).with('nodes/test-grid/node', {
79
+ labels: ['test=yes'],
80
+ })
81
+
82
+ expect{subject.run(['--force', 'node', 'test=no', 'test=maybe', 'test=almost'])}.not_to exit_with_error
83
+ end
84
+ end
85
+ end
56
86
  end
57
87
  end
@@ -24,7 +24,7 @@ describe Kontena::Cli::Stacks::InstallCommand do
24
24
  'volumes' => [],
25
25
  'dependencies' => nil,
26
26
  'source' => /stack:/,
27
- 'parent_name' => nil,
27
+ 'parent' => nil,
28
28
  'expose' => nil
29
29
  }
30
30
  end
@@ -73,10 +73,14 @@ describe Kontena::Cli::Stacks::InstallCommand do
73
73
  end
74
74
 
75
75
  context 'with a stack including dependencies' do
76
-
77
76
  it 'installs all the dependencies' do
78
- expect(Kontena).to receive(:run!).with(["stack", "install", "-n", "deptest-dep_1", "--parent-name", "deptest", '-v', 'dep_1.dep_var=1', '--no-deploy', fixture_path('stack-with-dependencies-dep-1.yml')])
79
- expect(Kontena).to receive(:run!).with(["stack", "install", "-n", "deptest-dep_2", "--parent-name", "deptest", "-v", "dep_var=1", '--no-deploy', fixture_path('stack-with-dependencies-dep-2.yml')])
77
+ expect(Kontena).to receive(:run!).with([
78
+ "stack", "install", "-n", "deptest-dep_1", "--parent-name", "deptest", "--no-deploy",
79
+ '-v', 'dep_1.dep_var=1', fixture_path('stack-with-dependencies-dep-1.yml')
80
+ ])
81
+ expect(Kontena).to receive(:run!).with([
82
+ "stack", "install", "-n", "deptest-dep_2", "--parent-name", "deptest", '--no-deploy',
83
+ "-v", "dep_var=1", fixture_path('stack-with-dependencies-dep-2.yml')])
80
84
  expect(client).to receive(:post).with('grids/test-grid/stacks', hash_including('stack' => 'user/depstack1', 'name' => 'deptest'))
81
85
  subject.run(['-n', 'deptest', '--no-deploy', '-v', 'dep_1.dep_1.dep_var=1', fixture_path('stack-with-dependencies.yml')])
82
86
  end
@@ -143,8 +147,14 @@ describe Kontena::Cli::Stacks::InstallCommand do
143
147
  'children' => [ ]
144
148
  )
145
149
 
146
- expect(Kontena).to receive(:run!).with(["stack", "install", "-n", "deptest-dep_1", "--parent-name", "deptest", '-v', 'dep1var=test', '-v', 'dep_1.dep1dep1var=test11', '--no-deploy', fixture_path('stack-with-dependencies-dep-1.yml')]).and_return(true)
147
- expect(Kontena).to receive(:run!).with(["stack", "install", "-n", "deptest-dep_2", "--parent-name", "deptest", '-v', 'dep_var=1', '-v', 'dep2var=test2', '--no-deploy', fixture_path('stack-with-dependencies-dep-2.yml')]).and_return(true)
150
+ expect(Kontena).to receive(:run!).with([
151
+ "stack", "install", "-n", "deptest-dep_1", "--parent-name", "deptest", "--no-deploy",
152
+ '-v', 'dep1var=test', '-v', 'dep_1.dep1dep1var=test11', fixture_path('stack-with-dependencies-dep-1.yml')
153
+ ]).and_return(true)
154
+ expect(Kontena).to receive(:run!).with([
155
+ "stack", "install", "-n", "deptest-dep_2", "--parent-name", "deptest", "--no-deploy",
156
+ '-v', 'dep_var=1', '-v', 'dep2var=test2', fixture_path('stack-with-dependencies-dep-2.yml')
157
+ ]).and_return(true)
148
158
 
149
159
  allow(client).to receive(:post).and_return({})
150
160
 
@@ -50,9 +50,11 @@ describe Kontena::Cli::Stacks::RemoveCommand do
50
50
  { 'children' => [ { 'name' => 'foofoo' }, { 'name' => 'foobar' } ] }
51
51
  end
52
52
 
53
- it 'removes the children' do
53
+ before(:each) do
54
54
  allow(subject).to receive(:wait_stack_removal)
55
+ end
55
56
 
57
+ it 'removes the children' do
56
58
  expect(client).to receive(:get).with('stacks/test-grid/test-stack').and_return(
57
59
  stack_response_with_children
58
60
  )
@@ -61,7 +63,26 @@ describe Kontena::Cli::Stacks::RemoveCommand do
61
63
  expect(Kontena).to receive(:run!).with(['stack', 'remove', '--force', 'foobar'])
62
64
 
63
65
  expect(subject).to receive(:remove_stack).with('test-stack')
64
- expect{subject.run(['--force', 'test-stack'])}.not_to exit_with_error
66
+ expect {
67
+ subject.run(['--force', 'test-stack'])
68
+ }.not_to exit_with_error
69
+ end
70
+
71
+ it 'does not remove the children if keep dependencies given' do
72
+ allow(subject).to receive(:confirm_command)
73
+ expect(client).to receive(:get).with('stacks/test-grid/test-stack').and_return(
74
+ stack_response_with_children
75
+ )
76
+
77
+ expect(Kontena).not_to receive(:run!).with(['stack', 'remove', '--force', 'foofoo'])
78
+ expect(Kontena).not_to receive(:run!).with(['stack', 'remove', '--force', 'foobar'])
79
+
80
+ expect(subject).to receive(:remove_stack).with('test-stack')
81
+ expect {
82
+ expect {
83
+ subject.run(['--keep-dependencies', 'test-stack'])
84
+ }.not_to output(/depends on/).to_stdout
85
+ }.not_to exit_with_error
65
86
  end
66
87
  end
67
88
  end