kontena-cli 1.4.0 → 1.4.1.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 (62) hide show
  1. checksums.yaml +5 -5
  2. data/VERSION +1 -1
  3. data/bin/kontena +2 -1
  4. data/kontena-cli.gemspec +1 -1
  5. data/lib/kontena/cli/certificate/common.rb +16 -0
  6. data/lib/kontena/cli/certificate/export_command.rb +28 -0
  7. data/lib/kontena/cli/certificate/import_command.rb +61 -0
  8. data/lib/kontena/cli/certificate/show_command.rb +5 -2
  9. data/lib/kontena/cli/certificate_command.rb +3 -1
  10. data/lib/kontena/cli/common.rb +5 -1
  11. data/lib/kontena/cli/config.rb +23 -5
  12. data/lib/kontena/cli/external_registries/add_command.rb +2 -0
  13. data/lib/kontena/cli/external_registries/list_command.rb +1 -1
  14. data/lib/kontena/cli/helpers/exec_helper.rb +12 -4
  15. data/lib/kontena/cli/master/config/import_command.rb +1 -1
  16. data/lib/kontena/cli/master/login_command.rb +1 -1
  17. data/lib/kontena/cli/stacks/common.rb +2 -1
  18. data/lib/kontena/cli/stacks/registry/show_command.rb +1 -1
  19. data/lib/kontena/cli/stacks/service_generator.rb +1 -0
  20. data/lib/kontena/cli/stacks/yaml/opto.rb +1 -0
  21. data/lib/kontena/cli/stacks/yaml/opto/certificates_resolver.rb +37 -0
  22. data/lib/kontena/cli/stacks/yaml/opto/vault_cert_prompt_resolver.rb +1 -1
  23. data/lib/kontena/cli/stacks/yaml/reader.rb +5 -2
  24. data/lib/kontena/cli/stacks/yaml/validations.rb +2 -1
  25. data/lib/kontena/cli/vault/import_command.rb +1 -1
  26. data/lib/kontena/client.rb +1 -1
  27. data/lib/kontena/command.rb +7 -5
  28. data/lib/kontena/plugin_manager.rb +1 -1
  29. data/lib/kontena/plugin_manager/cleaner.rb +1 -1
  30. data/lib/kontena/scripts/completer.rb +1 -1
  31. data/lib/kontena/stacks_cache.rb +2 -2
  32. data/lib/kontena_cli.rb +6 -2
  33. data/spec/fixtures/certificates/test/ca-key.pem +10 -0
  34. data/spec/fixtures/certificates/test/ca.pem +10 -0
  35. data/spec/fixtures/certificates/test/ca.srl +1 -0
  36. data/spec/fixtures/certificates/test/cert.pem +8 -0
  37. data/spec/fixtures/certificates/test/csr.pem +7 -0
  38. data/spec/fixtures/certificates/test/key.pem +10 -0
  39. data/spec/fixtures/certificates/test/real-cert.pem +30 -0
  40. data/spec/fixtures/docker-compose_v2.yml +1 -0
  41. data/spec/fixtures/docker-compose_v2_with_variables.yml +12 -0
  42. data/spec/fixtures/kontena_v3_with_compose_variables.yml +11 -0
  43. data/spec/fixtures/stack-with-anchors.yml +13 -0
  44. data/spec/kontena/cli/certificates/export_command_spec.rb +49 -0
  45. data/spec/kontena/cli/certificates/import_command_spec.rb +70 -0
  46. data/spec/kontena/cli/certificates/show_command_spec.rb +57 -0
  47. data/spec/kontena/cli/cloud/login_command_spec.rb +7 -14
  48. data/spec/kontena/cli/helpers/exec_helper_spec.rb +38 -0
  49. data/spec/kontena/cli/master/login_command_spec.rb +12 -24
  50. data/spec/kontena/cli/master/use_command_spec.rb +1 -1
  51. data/spec/kontena/cli/nodes/remove_command_spec.rb +1 -1
  52. data/spec/kontena/cli/registry/{create_spec.rb → create_command_spec.rb} +0 -0
  53. data/spec/kontena/cli/stacks/upgrade_command_spec.rb +1 -1
  54. data/spec/kontena/cli/stacks/yaml/opto/certificates_resolver_spec.rb +81 -0
  55. data/spec/kontena/cli/stacks/yaml/reader_spec.rb +22 -2
  56. data/spec/kontena/cli/stacks/yaml/validator_v3_spec.rb +17 -0
  57. data/spec/kontena/command_spec.rb +54 -0
  58. data/spec/kontena/config_spec.rb +17 -2
  59. data/spec/kontena/main_command_spec.rb +13 -0
  60. data/spec/spec_helper.rb +10 -17
  61. metadata +43 -11
  62. data/spec/kontena/cli/main_command_spec.rb +0 -19
@@ -20,18 +20,15 @@ describe Kontena::Cli::Cloud::LoginCommand do
20
20
  end
21
21
 
22
22
  it 'should give error if trying to use --code and --force' do
23
- expect(subject).to receive(:exit_with_error).and_throw(:exit_with_error)
24
- subject.run(['--code', 'abcd', '--force'])
23
+ expect{subject.run(['--code', 'abcd', '--force'])}.to exit_with_error
25
24
  end
26
25
 
27
26
  it 'should give error if trying to use --token and --force' do
28
- expect(subject).to receive(:exit_with_error).and_throw(:exit_with_error)
29
- subject.run(['--token', 'abcd', '--force'])
27
+ expect{subject.run(['--token', 'abcd', '--force'])}.to exit_with_error
30
28
  end
31
29
 
32
30
  it 'should give error if trying to use --token and --code' do
33
- expect(subject).to receive(:exit_with_error).and_throw(:exit_with_error)
34
- subject.run(['--token', 'abcd', '--code', 'defg'])
31
+ expect{subject.run(['--token', 'abcd', '--code', 'defg'])}.to exit_with_error
35
32
  end
36
33
 
37
34
  context 'when config has token' do
@@ -180,8 +177,7 @@ describe Kontena::Cli::Cloud::LoginCommand do
180
177
  'error' => 'foo'
181
178
  })
182
179
  expect(Launchy).to receive(:open).and_return(true)
183
- expect(subject).to receive(:exit_with_error).and_throw(:exit_with_error)
184
- subject.run([])
180
+ expect{subject.run([])}.to exit_with_error.and output(/Authentication failed: foo/).to_stderr
185
181
  end
186
182
  end
187
183
  end
@@ -283,14 +279,12 @@ describe Kontena::Cli::Cloud::LoginCommand do
283
279
 
284
280
  it 'should exit with error if cloud responds with error' do
285
281
  expect(client).to receive(:get).and_return('error' => 'foo')
286
- expect(subject).to receive(:exit_with_error).and_throw(:exit_with_error)
287
- subject.update_userinfo
282
+ expect{subject.update_userinfo}.to exit_with_error
288
283
  end
289
284
 
290
285
  it 'should exit with error if cloud responds with something silly' do
291
286
  expect(client).to receive(:get).and_return('foo')
292
- expect(subject).to receive(:exit_with_error).and_throw(:exit_with_error)
293
- subject.update_userinfo
287
+ expect{subject.update_userinfo}.to exit_with_error
294
288
  end
295
289
  end
296
290
 
@@ -313,8 +307,7 @@ describe Kontena::Cli::Cloud::LoginCommand do
313
307
  end
314
308
 
315
309
  it 'should give error when response has error' do
316
- expect(subject).to receive(:exit_with_error).and_throw(:exit_with_error)
317
- subject.update_token('error' => 'fail!')
310
+ expect{subject.update_token('error' => 'fail!')}.to exit_with_error
318
311
  end
319
312
 
320
313
  it 'should raise if response is not a hash' do
@@ -57,6 +57,44 @@ describe Kontena::Cli::Helpers::ExecHelper do
57
57
  "\n",
58
58
  ).and raise_error(EOFError)
59
59
  end
60
+
61
+ it 'yields chunks of UTF-8 input that are JSON-encodable' do
62
+ data = "f\u00e5\u00e5".encode('UTF-8').force_encoding('ASCII-8BIT')
63
+
64
+ expect(stdin_raw).to receive(:readpartial).and_return(data[0..2])
65
+ expect(stdin_raw).to receive(:readpartial).and_return(data[3..4])
66
+ expect(stdin_raw).to receive(:readpartial).and_raise(EOFError)
67
+
68
+ chunks = []
69
+
70
+ expect{subject.read_stdin(tty: true) do |chunk|
71
+ chunks << JSON.dump('stdin' => chunk)
72
+ end}.to raise_error(EOFError)
73
+
74
+ expect(chunks).to eq [
75
+ '{"stdin":"f' + "\u00e5" + '"}',
76
+ '{"stdin":"' + "\u00e5" + '"}',
77
+ ]
78
+ end
79
+
80
+ it 'yields tty control characters that are JSON-encodable' do
81
+ data = "\x03\x04".force_encoding('ASCII-8BIT')
82
+
83
+ expect(stdin_raw).to receive(:readpartial).and_return(data[0])
84
+ expect(stdin_raw).to receive(:readpartial).and_return(data[1])
85
+ expect(stdin_raw).to receive(:readpartial).and_raise(EOFError)
86
+
87
+ chunks = []
88
+
89
+ expect{subject.read_stdin(tty: true) do |chunk|
90
+ chunks << JSON.dump('stdin' => chunk)
91
+ end}.to raise_error(EOFError)
92
+
93
+ expect(chunks).to eq [
94
+ '{"stdin":"\\u0003"}',
95
+ '{"stdin":"\\u0004"}',
96
+ ]
97
+ end
60
98
  end
61
99
  end
62
100
 
@@ -14,23 +14,19 @@ describe Kontena::Cli::Master::LoginCommand do
14
14
  let(:client) { double(:client) }
15
15
 
16
16
  it 'should exit with error if --code and --token both given' do
17
- expect(subject).to receive(:exit_with_error).and_throw(:exit_with_error)
18
- subject.run(%w(--code abcd --token defg))
17
+ expect{subject.run(%w(--code abcd --token defg))}.to exit_with_error
19
18
  end
20
19
 
21
20
  it 'should exit with error if --code and --join both given' do
22
- expect(subject).to receive(:exit_with_error).and_throw(:exit_with_error)
23
- subject.run(%w(--code abcd --join defg))
21
+ expect{subject.run(%w(--code abcd --join defg))}.to exit_with_error
24
22
  end
25
23
 
26
24
  it 'should exit with error if --code and --force both given' do
27
- expect(subject).to receive(:exit_with_error).and_throw(:exit_with_error)
28
- subject.run(%w(--code abcd --force))
25
+ expect{subject.run(%w(--code abcd --force))}.to exit_with_error
29
26
  end
30
27
 
31
28
  it 'should exit with error if --token and --force both given' do
32
- expect(subject).to receive(:exit_with_error).and_throw(:exit_with_error)
33
- subject.run(%w(--token abcd --force))
29
+ expect{subject.run(%w(--token abcd --force))}.to exit_with_error
34
30
  end
35
31
 
36
32
  describe '#select_a_server' do
@@ -49,8 +45,7 @@ describe Kontena::Cli::Master::LoginCommand do
49
45
 
50
46
  it 'exits with error if current_master not set' do
51
47
  expect(config).to receive(:current_master).and_return(nil)
52
- expect(subject).to receive(:exit_with_error).and_throw(:exit_with_error)
53
- subject.select_a_server(nil, nil)
48
+ expect{subject.select_a_server(nil, nil)}.to exit_with_error
54
49
  end
55
50
  end
56
51
 
@@ -88,8 +83,7 @@ describe Kontena::Cli::Master::LoginCommand do
88
83
  it 'should exit with error if a server with that name is found but it does not have an url' do
89
84
  server.url = nil
90
85
  expect(config).to receive(:find_server).with('foo').and_return(server)
91
- expect(subject).to receive(:exit_with_error).and_throw(:exit_with_error)
92
- subject.select_a_server('foo', nil)
86
+ expect{subject.select_a_server('foo', nil)}.to exit_with_error
93
87
  end
94
88
  end
95
89
  end
@@ -119,14 +113,12 @@ describe Kontena::Cli::Master::LoginCommand do
119
113
  it 'should exit with error if a server with that name is found but it does not have an url' do
120
114
  server.url = nil
121
115
  expect(config).to receive(:find_server).with('foo').and_return(server)
122
- expect(subject).to receive(:exit_with_error).and_throw(:exit_with_error)
123
- subject.select_a_server(nil, 'foo')
116
+ expect{subject.select_a_server(nil, 'foo')}.to exit_with_error
124
117
  end
125
118
 
126
119
  it 'should exit with error if a server with that name is not found' do
127
120
  expect(config).to receive(:find_server).with('foo').and_return(nil)
128
- expect(subject).to receive(:exit_with_error).and_throw(:exit_with_error)
129
- subject.select_a_server(nil, 'foo')
121
+ expect{subject.select_a_server(nil, 'foo')}.to exit_with_error
130
122
  end
131
123
  end
132
124
  end
@@ -350,24 +342,21 @@ describe Kontena::Cli::Master::LoginCommand do
350
342
  allow(Kontena::Client).to receive(:new).and_return(client)
351
343
  expect(client).to receive(:last_response).at_least(:once).and_return(OpenStruct.new(status: 400, headers: {}))
352
344
  expect(client).to receive(:request).and_return('error' => 'no good')
353
- expect(subject).to receive(:exit_with_error).with(/no good/).and_throw(:exit_with_error)
354
- subject.authentication_url_from_master('https://foo.example.com', remote: true)
345
+ expect{subject.authentication_url_from_master('https://foo.example.com', remote: true)}.to exit_with_error
355
346
  end
356
347
 
357
348
  it 'should exit with error if master returns text' do
358
349
  allow(Kontena::Client).to receive(:new).and_return(client)
359
350
  expect(client).to receive(:last_response).at_least(:once).and_return(OpenStruct.new(status: 400, headers: {}))
360
351
  expect(client).to receive(:request).and_return('Fail!')
361
- expect(subject).to receive(:exit_with_error).and_throw(:exit_with_error)
362
- subject.authentication_url_from_master('https://foo.example.com', remote: true)
352
+ expect{subject.authentication_url_from_master('https://foo.example.com', remote: true)}.to exit_with_error
363
353
  end
364
354
 
365
355
  it 'should exit with error if master returns nil' do
366
356
  allow(Kontena::Client).to receive(:new).and_return(client)
367
357
  expect(client).to receive(:last_response).at_least(:once).and_return(OpenStruct.new(status: 400, headers: {}))
368
358
  expect(client).to receive(:request).and_return(nil)
369
- expect(subject).to receive(:exit_with_error).with(/Invalid.+?400/).and_throw(:exit_with_error)
370
- subject.authentication_url_from_master('https://foo.example.com', remote: true)
359
+ expect{subject.authentication_url_from_master('https://foo.example.com', remote: true)}.to exit_with_error
371
360
  end
372
361
  end
373
362
 
@@ -399,8 +388,7 @@ describe Kontena::Cli::Master::LoginCommand do
399
388
  end
400
389
 
401
390
  it 'should exit with error if response has error' do
402
- expect(subject).to receive(:exit_with_error).and_throw(:exit_with_error)
403
- subject.update_server_token(server, "error" => "abcd")
391
+ expect{subject.update_server_token(server, "error" => "abcd")}.to exit_with_error
404
392
  end
405
393
 
406
394
  it 'should update the token if all is good' do
@@ -16,7 +16,7 @@ describe Kontena::Cli::Master::UseCommand do
16
16
  end
17
17
 
18
18
  it 'should abort with error message if master is not configured' do
19
- expect { subject.run(['not_existing']) }.to output(/Could not resolve master with name: 'not_existing'/).to_stderr
19
+ expect { subject.run(['not_existing']) }.to exit_with_error.and output(/Could not resolve master by name 'not_existing'/).to_stderr
20
20
  end
21
21
 
22
22
  it 'should abort with error message if master is not given' do
@@ -49,7 +49,7 @@ describe Kontena::Cli::Nodes::RemoveCommand do
49
49
  it 'does not remove the node' do
50
50
  expect(client).not_to receive(:delete)
51
51
 
52
- expect{subject.run(['node-1'])}.to output(" [error] Node node-1 is still online. You must terminate the node before removing it.\n").to_stderr
52
+ expect{subject.run(['node-1'])}.to exit_with_error.and output(" [error] Node node-1 is still connected using a grid token. You must terminate the node before removing it.\n").to_stderr
53
53
  end
54
54
  end
55
55
 
@@ -76,7 +76,7 @@ describe Kontena::Cli::Stacks::UpgradeCommand do
76
76
  'stacks/test-grid/stack-a', anything
77
77
  ).and_return({})
78
78
  expect(Kontena).not_to receive(:run!).with(['stack', 'deploy', 'stack-a'])
79
- subject.run(['--no-deploy', 'stack-a', fixture_path('kontena_v3.yml')])
79
+ subject.run(['--no-deploy', '--force', 'stack-a', fixture_path('kontena_v3.yml')])
80
80
  end
81
81
  end
82
82
 
@@ -0,0 +1,81 @@
1
+ require 'opto'
2
+ require 'kontena/cli/stacks/yaml/opto/certificates_resolver'
3
+
4
+ describe Kontena::Cli::Stacks::YAML::Opto::Resolvers::Certificates do
5
+ let(:client) { instance_double(Kontena::Client) }
6
+ let(:prompt) { double(:prompt) }
7
+ let(:prompt_menu) { double(:prompt_menu) }
8
+
9
+ let(:option_hint) { "Select SSL certificates" }
10
+ let(:option_default) { nil }
11
+ let(:option) { Opto::Option.new(default: option_default) }
12
+ subject { described_class.new(option_hint, option) }
13
+
14
+ before do
15
+ allow(subject).to receive(:current_master).and_return("test-master")
16
+ allow(subject).to receive(:current_grid).and_return("test-grid")
17
+ allow(subject).to receive(:client).and_return(client)
18
+ allow(subject).to receive(:prompt).and_return(prompt)
19
+ end
20
+
21
+ context 'with grid certificates' do
22
+ let(:certificates) { [
23
+ { 'subject' => 'test.example.com' },
24
+ { 'subject' => 'test-2.example.com' },
25
+ ] }
26
+
27
+ before do
28
+ allow(client).to receive(:get).with('grids/test-grid/certificates').and_return('certificates' => certificates)
29
+ end
30
+
31
+ it 'lists grid certificates and prompts' do
32
+ expect(prompt).to receive(:multi_select).with(option_hint) do |&block|
33
+ expect(prompt_menu).to_not receive(:default)
34
+ expect(prompt_menu).to receive(:choice).with('test.example.com')
35
+ expect(prompt_menu).to receive(:choice).with('test-2.example.com')
36
+
37
+ block.call(prompt_menu)
38
+
39
+ ['test.example.com']
40
+ end
41
+
42
+ expect(subject.resolve).to eq ['test.example.com']
43
+ end
44
+
45
+ context 'with default value' do
46
+ let(:option_default) { ['test.example.com'] }
47
+
48
+ it 'lists grid certificates and prompts' do
49
+ expect(prompt).to receive(:multi_select).with(option_hint) do |&block|
50
+ expect(prompt_menu).to receive(:default).with(1)
51
+ expect(prompt_menu).to receive(:choice).with('test.example.com')
52
+ expect(prompt_menu).to receive(:choice).with('test-2.example.com')
53
+
54
+ block.call(prompt_menu)
55
+
56
+ ['test.example.com']
57
+ end
58
+
59
+ expect(subject.resolve).to eq ['test.example.com']
60
+ end
61
+ end
62
+
63
+ context 'with default values' do
64
+ let(:option_default) { ['test.example.com', 'test-2.example.com'] }
65
+
66
+ it 'lists grid certificates and prompts' do
67
+ expect(prompt).to receive(:multi_select).with(option_hint) do |&block|
68
+ expect(prompt_menu).to receive(:default).with(1, 2)
69
+ expect(prompt_menu).to receive(:choice).with('test.example.com')
70
+ expect(prompt_menu).to receive(:choice).with('test-2.example.com')
71
+
72
+ block.call(prompt_menu)
73
+
74
+ ['test.example.com', 'test-2.example.com']
75
+ end
76
+
77
+ expect(subject.resolve).to eq ['test.example.com', 'test-2.example.com']
78
+ end
79
+ end
80
+ end
81
+ end
@@ -112,7 +112,21 @@ describe Kontena::Cli::Stacks::YAML::Reader do
112
112
  "links"=>[],
113
113
  "ports"=>[],
114
114
  "stateful"=>true,
115
- "name"=>"mysql"
115
+ "name"=>"mysql",
116
+ "entrypoint" => "test"
117
+ )
118
+ )
119
+ end
120
+
121
+ it 'passes variables to extended file' do
122
+ allow(File).to receive(:exist?).with(fixture_path('docker-compose_v2_with_variables.yml')).and_call_original
123
+ allow(File).to receive(:read).with(fixture_path('docker-compose_v2_with_variables.yml')).and_call_original
124
+ allow(File).to receive(:exist?).with(fixture_path('kontena_v3.yml')).and_call_original
125
+ allow(File).to receive(:read).with(fixture_path('kontena_v3.yml')).and_return(fixture('kontena_v3_with_compose_variables.yml'))
126
+ expect(subject.execute['services']).to match array_including(
127
+ hash_including(
128
+ "name" => 'mysql',
129
+ "env" => ["ENV_VAR=abcd"]
116
130
  )
117
131
  )
118
132
  end
@@ -146,7 +160,6 @@ describe Kontena::Cli::Stacks::YAML::Reader do
146
160
  it 'extends services from the same file' do
147
161
  app_svc = subject.execute['services'].find { |s| s['name'] == 'app' }
148
162
  expect(app_svc).not_to be_nil
149
- puts app_svc.inspect
150
163
  expect(app_svc).to match hash_including(
151
164
  "image" => "base:latest",
152
165
  "instances" => 2,
@@ -514,4 +527,11 @@ describe Kontena::Cli::Stacks::YAML::Reader do
514
527
  )
515
528
  end
516
529
  end
530
+
531
+ context "yaml with anchors" do
532
+ subject { described_class.new(fixture_path('stack-with-anchors.yml')) }
533
+ it 'parses correctly' do
534
+ expect(subject.execute['services'].all? { |svc| svc['affinity'] == ['abc==dfg']}).to be_truthy
535
+ end
536
+ end
517
537
  end
@@ -52,6 +52,23 @@ describe Kontena::Cli::Stacks::YAML::ValidatorV3 do
52
52
  expect(result.errors.key?('network_mode')).to be_falsey
53
53
  end
54
54
 
55
+ context 'entrypoint' do
56
+ it 'is optional' do
57
+ result = subject.validate_options({})
58
+ expect(result.errors.key?('entrypoint')).to be_falsey
59
+ end
60
+
61
+ it 'passes validation when string' do
62
+ result = subject.validate_options({'entrypoint' => 'abcd'})
63
+ expect(result.errors.key?('entrypoint')).to be_falsey
64
+ end
65
+
66
+ it 'fails validation when not a string' do
67
+ result = subject.validate_options({'entrypoint' => 1})
68
+ expect(result.errors.key?('entrypoint')).to be_truthy
69
+ end
70
+ end
71
+
55
72
  context 'affinity' do
56
73
  it 'is optional' do
57
74
  result = subject.validate_options({})
@@ -0,0 +1,54 @@
1
+ require 'kontena/command'
2
+
3
+ describe Kontena::Command do
4
+ let(:subject) { described_class.new('kontena') }
5
+
6
+ context 'for a command that raises RuntimeError without including Kontena::Cli::Common' do
7
+ let(:command_class) { Class.new(Kontena::Command) do
8
+ def execute
9
+ fail 'test'
10
+ end
11
+ end}
12
+
13
+ subject { command_class.new('test') }
14
+
15
+ it 'logs an error and aborts' do
16
+ expect{subject.run([])}.to raise_error(SystemExit).and output(/\[error\] RuntimeError : test\s+See .* or run the command again with environment DEBUG=true set to see the full exception/m).to_stderr
17
+ end
18
+
19
+ context 'with DEBUG' do
20
+ before do
21
+ allow(Kontena).to receive(:debug?).and_return(true)
22
+ end
23
+
24
+ it 'lets the error raise through' do
25
+ expect{subject.run([])}.to raise_error(RuntimeError, 'test')
26
+ end
27
+
28
+ end
29
+ end
30
+
31
+ context 'for a command that raises StandardError without including Kontena::Cli::Common' do
32
+ let(:command_class) { Class.new(Kontena::Command) do
33
+ def execute
34
+ raise Kontena::Errors::StandardError.new(404, "Not Found")
35
+ end
36
+ end}
37
+
38
+ subject { command_class.new('test') }
39
+
40
+ it 'logs an error and aborts' do
41
+ expect{subject.run([])}.to raise_error(SystemExit).and output(" [error] 404 : Not Found\n").to_stderr
42
+ end
43
+
44
+ context 'with DEBUG' do
45
+ before do
46
+ allow(Kontena).to receive(:debug?).and_return(true)
47
+ end
48
+
49
+ it 'lets the error raise through' do
50
+ expect{subject.run([])}.to raise_error(Kontena::Errors::StandardError)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -59,11 +59,11 @@ describe Kontena::Cli::Config do
59
59
  allow(File).to receive(:read).and_return <<-EOB
60
60
  {"current_server": "test123",
61
61
  "servers" : [
62
- {
62
+ {
63
63
  "name": "test123",
64
64
  "url": "https://foo.example.com"
65
65
  },
66
- {
66
+ {
67
67
  "name": "test123",
68
68
  "url": "https://foo2.example.com"
69
69
  }
@@ -82,6 +82,21 @@ describe Kontena::Cli::Config do
82
82
  end
83
83
  end
84
84
 
85
+ context 'environment variables' do
86
+ it 'sets cloud account on KONTENA_CLOUD_TOKEN' do
87
+ allow(ENV).to receive(:[]).with('KONTENA_CLOUD_TOKEN').and_return('abc')
88
+ expect(subject.current_account.token.access_token).to eq('abc')
89
+ end
90
+
91
+ it 'sets master information on KONTENA_URL, KONTENA_TOKEN & KONTENA_GRID' do
92
+ allow(ENV).to receive(:[]).with('KONTENA_URL').and_return('http://localhost')
93
+ allow(ENV).to receive(:[]).with('KONTENA_TOKEN').and_return('abc')
94
+ allow(ENV).to receive(:[]).with('KONTENA_GRID').and_return('test')
95
+ expect(subject.current_master.url).to eq('http://localhost')
96
+ expect(subject.current_master.grid).to eq('test')
97
+ end
98
+ end
99
+
85
100
  describe 'Token' do
86
101
  let(:subject) { Kontena::Cli::Config::Token.new(access_token: 'abcd', expires_at: Time.now.utc - 100) }
87
102