tugboat 3.1.0 → 4.0.0

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -1
  3. data/CODE_OF_CONDUCT.md +46 -0
  4. data/lib/tugboat/cli.rb +7 -1
  5. data/lib/tugboat/config.rb +11 -1
  6. data/lib/tugboat/middleware.rb +2 -0
  7. data/lib/tugboat/middleware/ask_for_credentials.rb +2 -1
  8. data/lib/tugboat/middleware/base.rb +31 -13
  9. data/lib/tugboat/middleware/check_snapshot_parameters.rb +16 -0
  10. data/lib/tugboat/middleware/info_droplet.rb +2 -2
  11. data/lib/tugboat/middleware/inject_client.rb +10 -1
  12. data/lib/tugboat/middleware/list_droplets.rb +5 -3
  13. data/lib/tugboat/version.rb +1 -1
  14. data/spec/cli/add_key_spec.rb +7 -9
  15. data/spec/cli/authorize_cli_spec.rb +4 -34
  16. data/spec/cli/config_cli_spec.rb +10 -5
  17. data/spec/cli/create_cli_spec.rb +20 -17
  18. data/spec/cli/debug_cli_spec.rb +11 -12
  19. data/spec/cli/destroy_cli_spec.rb +35 -12
  20. data/spec/cli/destroy_image_cli_spec.rb +12 -10
  21. data/spec/cli/droplets_cli_spec.rb +74 -48
  22. data/spec/cli/env_variable_spec.rb +4 -4
  23. data/spec/cli/halt_cli_spec.rb +16 -13
  24. data/spec/cli/help_cli_spec.rb +4 -4
  25. data/spec/cli/images_cli_spec.rb +9 -7
  26. data/spec/cli/info_cli_spec.rb +120 -50
  27. data/spec/cli/info_image_cli_spec.rb +24 -23
  28. data/spec/cli/keys_cli_spec.rb +3 -3
  29. data/spec/cli/password_reset_cli_spec.rb +12 -12
  30. data/spec/cli/rebuild_cli_spec.rb +31 -24
  31. data/spec/cli/regions_cli_spec.rb +3 -3
  32. data/spec/cli/resize_cli_spec.rb +16 -16
  33. data/spec/cli/restart_cli_spec.rb +32 -11
  34. data/spec/cli/sizes_cli_spec.rb +3 -3
  35. data/spec/cli/snapshot_cli_spec.rb +25 -9
  36. data/spec/cli/ssh_cli_spec.rb +10 -10
  37. data/spec/cli/start_cli_spec.rb +15 -15
  38. data/spec/cli/verify_cli_spec.rb +4 -7
  39. data/spec/cli/version_cli_spec.rb +1 -2
  40. data/spec/cli/wait_cli_spec.rb +16 -16
  41. data/spec/config_spec.rb +7 -1
  42. data/spec/fixtures/show_droplets.json +7 -4
  43. data/spec/fixtures/show_droplets_paginated_first.json +10 -7
  44. data/spec/fixtures/show_droplets_paginated_last.json +11 -5
  45. data/spec/fixtures/show_droplets_private_ip.json +7 -4
  46. data/spec/middleware/base_spec.rb +1 -2
  47. data/spec/middleware/check_configuration_spec.rb +1 -1
  48. data/spec/middleware/check_credentials_spec.rb +1 -1
  49. data/spec/middleware/check_droplet_active_spec.rb +1 -1
  50. data/spec/middleware/check_droplet_inactive_spec.rb +1 -1
  51. data/spec/middleware/find_droplet_spec.rb +3 -5
  52. data/spec/middleware/find_image_spec.rb +3 -5
  53. data/spec/middleware/ssh_droplet_spec.rb +5 -10
  54. data/spec/shared/environment.rb +2 -18
  55. data/tugboat.gemspec +1 -2
  56. metadata +8 -6
@@ -5,14 +5,14 @@ describe Tugboat::CLI do
5
5
 
6
6
  describe 'config' do
7
7
  it 'shows the full config' do
8
- cli.config
9
-
10
- expect($stdout.string).to eq <<-eos
8
+ expected_string = <<-eos
11
9
  Current Config\x20
12
10
  Path: #{Dir.pwd}/tmp/tugboat
13
11
  ---
14
12
  authentication:
15
13
  access_token: foo
14
+ connection:
15
+ timeout: '15'
16
16
  ssh:
17
17
  ssh_user: baz
18
18
  ssh_key_path: ~/.ssh/id_rsa2
@@ -26,18 +26,21 @@ defaults:
26
26
  backups_enabled: 'false'
27
27
  ip6: 'false'
28
28
  eos
29
+
30
+ expect { cli.config }.to output(expected_string).to_stdout
29
31
  end
30
32
 
31
33
  it 'hides sensitive data if option given' do
32
34
  cli.options = cli.options.merge(hide: true)
33
- cli.config
34
35
 
35
- expect($stdout.string).to eq <<-eos
36
+ expected_string = <<-eos
36
37
  Current Config (Keys Redacted)
37
38
  Path: #{Dir.pwd}/tmp/tugboat
38
39
  ---
39
40
  authentication:
40
41
  access_token:\x20\x20[REDACTED]
42
+ connection:
43
+ timeout: '15'
41
44
  ssh:
42
45
  ssh_user: baz
43
46
  ssh_key_path: ~/.ssh/id_rsa2
@@ -51,6 +54,8 @@ defaults:
51
54
  backups_enabled: 'false'
52
55
  ip6: 'false'
53
56
  eos
57
+
58
+ expect { cli.config }.to output(expected_string).to_stdout
54
59
  end
55
60
  end
56
61
  end
@@ -10,11 +10,11 @@ describe Tugboat::CLI do
10
10
  headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
11
11
  to_return(status: 200, body: fixture('create_droplet'), headers: {})
12
12
 
13
- cli.create(droplet_name)
14
-
15
- expect($stdout.string).to eq <<-eos
13
+ expected_string = <<-eos
16
14
  Queueing creation of droplet '#{droplet_name}'...Droplet created! Droplet ID is 3164494
17
15
  eos
16
+
17
+ expect { cli.create(droplet_name) }.to output(expected_string).to_stdout
18
18
  end
19
19
 
20
20
  it 'with args does not use defaults from configuration' do
@@ -24,11 +24,12 @@ Queueing creation of droplet '#{droplet_name}'...Droplet created! Droplet ID is
24
24
  to_return(status: 200, body: fixture('create_droplet'), headers: {})
25
25
 
26
26
  cli.options = cli.options.merge(image: 'ubuntu-12-04-x64', size: '1gb', region: 'nyc3', keys: 'foo_bar_key')
27
- cli.create('example.com')
28
27
 
29
- expect($stdout.string).to eq <<-eos
28
+ expected_string = <<-eos
30
29
  Queueing creation of droplet 'example.com'...Droplet created! Droplet ID is 3164494
31
30
  eos
31
+
32
+ expect { cli.create('example.com') }.to output(expected_string).to_stdout
32
33
  end
33
34
 
34
35
  it 'with ip6 enable args' do
@@ -38,11 +39,12 @@ Queueing creation of droplet 'example.com'...Droplet created! Droplet ID is 3164
38
39
  to_return(status: 200, body: fixture('create_droplet'), headers: {})
39
40
 
40
41
  cli.options = cli.options.merge(ip6: 'true')
41
- cli.create('example.com')
42
42
 
43
- expect($stdout.string).to eq <<-eos
43
+ expected_string = <<-eos
44
44
  Queueing creation of droplet 'example.com'...Droplet created! Droplet ID is 3164494
45
45
  eos
46
+
47
+ expect { cli.create('example.com') }.to output(expected_string).to_stdout
46
48
  end
47
49
 
48
50
  it 'with user data args' do
@@ -52,26 +54,28 @@ Queueing creation of droplet 'example.com'...Droplet created! Droplet ID is 3164
52
54
  to_return(status: 200, body: fixture('create_droplet'), headers: {})
53
55
 
54
56
  cli.options = cli.options.merge(user_data: project_path + '/spec/fixtures/user_data.sh')
55
- cli.create('example.com')
56
57
 
57
- expect($stdout.string).to eq <<-eos
58
+ expected_string = <<-eos
58
59
  Queueing creation of droplet 'example.com'...Droplet created! Droplet ID is 3164494
59
60
  eos
61
+
62
+ expect { cli.create('example.com') }.to output(expected_string).to_stdout
60
63
  end
61
64
 
62
65
  it 'fails when user data file does not exist' do
63
66
  cli.options = cli.options.merge(user_data: '/foo/bar/baz.sh')
64
- expect { cli.create('example.com') }.to raise_error(SystemExit)
65
67
 
66
- expect($stdout.string).to eq <<-eos
68
+ expected_string = <<-eos
67
69
  Queueing creation of droplet 'example.com'...Could not find file: /foo/bar/baz.sh, check your user_data setting
68
70
  eos
71
+
72
+ expect { expect { cli.create('example.com') }.to raise_error(SystemExit) }.to output(expected_string).to_stdout
69
73
  end
70
74
 
71
75
  context "doesn't create a droplet when mistyping help command" do
72
76
  ['help', '--help', '-h'].each do |help_attempt|
73
77
  it "tugboat create #{help_attempt}" do
74
- help_text = <<-eos
78
+ expected_string = <<-eos
75
79
  Usage:
76
80
  rspec create NAME
77
81
 
@@ -89,8 +93,7 @@ Options:
89
93
  Create a droplet.
90
94
  eos
91
95
 
92
- cli.create(help_attempt)
93
- expect($stdout.string).to eq help_text
96
+ expect { cli.create(help_attempt) }.to output(expected_string).to_stdout
94
97
  end
95
98
  end
96
99
  end
@@ -101,11 +104,11 @@ eos
101
104
  headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
102
105
  to_return(status: 200, body: fixture('create_droplet'), headers: {})
103
106
 
104
- cli.create('somethingblahblah--help')
105
-
106
- expect($stdout.string).to eq <<-eos
107
+ expected_string = <<-eos
107
108
  Queueing creation of droplet 'somethingblahblah--help'...Droplet created! Droplet ID is 3164494
108
109
  eos
110
+
111
+ expect { cli.create('somethingblahblah--help') }.to output(expected_string).to_stdout
109
112
  end
110
113
  end
111
114
  end
@@ -17,16 +17,15 @@ describe Tugboat::CLI do
17
17
  with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
18
18
  to_return(status: 200, body: fixture('show_droplets'), headers: {})
19
19
 
20
- stub_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=200').
20
+ stub_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=20').
21
21
  with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
22
22
  to_return(status: 200, body: fixture('show_droplets'), headers: {})
23
23
 
24
- cli.droplets
24
+ debug_droplets_expectation = expect { cli.droplets }
25
25
 
26
- expect($stdout.string).to include 'Started GET request to: https://api.digitalocean.com/v2/droplets?page=1&per_page=200'
27
- expect($stdout.string).to include 'DEBUG -- : Request Headers:'
28
-
29
- expect($stdout.string).to include 'Bearer foo'
26
+ debug_droplets_expectation.to output(%r{DEBUG -- : Request Headers:}).to_stdout
27
+ debug_droplets_expectation.to output(%r{Bearer foo}).to_stdout
28
+ debug_droplets_expectation.to output(%r{Started GET request to}).to_stdout
30
29
  end
31
30
  end
32
31
 
@@ -44,15 +43,15 @@ describe Tugboat::CLI do
44
43
  with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
45
44
  to_return(status: 200, body: fixture('show_droplets'), headers: {})
46
45
 
47
- stub_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=200').
46
+ stub_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=20').
48
47
  with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
49
48
  to_return(status: 200, body: fixture('show_droplets'), headers: {})
50
- cli.droplets
51
-
52
- expect($stdout.string).to include 'Started GET request to: https://api.digitalocean.com/v2/droplets?page=1&per_page=200'
53
- expect($stdout.string).to include 'DEBUG -- : Request Headers:'
54
49
 
55
- expect($stdout.string).not_to include 'Bearer foo'
50
+ debug_droplets_expectation = expect { cli.droplets }
51
+ debug_droplets_expectation.to output(%r{Started GET request to}).to_stdout
52
+ debug_droplets_expectation.to output(%r{DEBUG -- : Request Headers:}).to_stdout
53
+ debug_droplets_expectation.to output(%r{Bearer \[TOKEN REDACTED\]}).to_stdout
54
+ debug_droplets_expectation.not_to output(%r{Bearer foo}).to_stdout
56
55
  end
57
56
  end
58
57
  end
@@ -19,11 +19,11 @@ describe Tugboat::CLI do
19
19
 
20
20
  expect($stdin).to receive(:gets).and_return('y')
21
21
 
22
- cli.destroy('example.com')
23
-
24
- expect($stdout.string).to eq <<-eos
22
+ expected_string = <<-eos
25
23
  Droplet fuzzy name provided. Finding droplet ID...done\e[0m, 6918990 (example.com)\nWarning! Potentially destructive action. Please confirm [y/n]: Queuing destroy for 6918990 (example.com)...Deletion Successful!
26
24
  eos
25
+
26
+ expect { cli.destroy('example.com') }.to output(expected_string).to_stdout
27
27
  end
28
28
 
29
29
  it 'destroys a droplet with an id' do
@@ -38,11 +38,12 @@ eos
38
38
  expect($stdin).to receive(:gets).and_return('y')
39
39
 
40
40
  cli.options = cli.options.merge(id: '6918990')
41
- cli.destroy
42
41
 
43
- expect($stdout.string).to eq <<-eos
42
+ expected_string = <<-eos
44
43
  Droplet id provided. Finding Droplet...done\e[0m, 6918990 (example.com)\nWarning! Potentially destructive action. Please confirm [y/n]: Queuing destroy for 6918990 (example.com)...Deletion Successful!
45
44
  eos
45
+
46
+ expect { cli.destroy }.to output(expected_string).to_stdout
46
47
  end
47
48
 
48
49
  it 'destroys a droplet with a name' do
@@ -61,11 +62,12 @@ Droplet id provided. Finding Droplet...done\e[0m, 6918990 (example.com)\nWarning
61
62
  expect($stdin).to receive(:gets).and_return('y')
62
63
 
63
64
  cli.options = cli.options.merge(name: 'example.com')
64
- cli.destroy
65
65
 
66
- expect($stdout.string).to eq <<-eos
66
+ expected_string = <<-eos
67
67
  Droplet name provided. Finding droplet ID...done\e[0m, 6918990 (example.com)\nWarning! Potentially destructive action. Please confirm [y/n]: Queuing destroy for 6918990 (example.com)...Deletion Successful!
68
68
  eos
69
+
70
+ expect { cli.destroy }.to output(expected_string).to_stdout
69
71
  end
70
72
 
71
73
  it 'destroys a droplet with confirm flag set' do
@@ -82,12 +84,13 @@ Droplet name provided. Finding droplet ID...done\e[0m, 6918990 (example.com)\nWa
82
84
  to_return(status: 204, body: '', headers: {})
83
85
 
84
86
  cli.options = cli.options.merge(name: 'example.com', confirm: true)
85
- cli.destroy
86
87
 
87
- expect($stdout.string).to eq <<-eos
88
+ expected_string = <<-eos
88
89
  Droplet name provided. Finding droplet ID...done\e[0m, 6918990 (example.com)
89
90
  Queuing destroy for 6918990 (example.com)...Deletion Successful!
90
91
  eos
92
+
93
+ expect { cli.destroy }.to output(expected_string).to_stdout
91
94
  end
92
95
 
93
96
  it 'does not destroy a droplet if no is chosen' do
@@ -101,11 +104,31 @@ Queuing destroy for 6918990 (example.com)...Deletion Successful!
101
104
 
102
105
  expect($stdin).to receive(:gets).and_return('n')
103
106
 
104
- expect { cli.destroy('example.com') }.to raise_error(SystemExit)
105
-
106
- expect($stdout.string).to eq <<-eos
107
+ expected_string = <<-eos
107
108
  Droplet fuzzy name provided. Finding droplet ID...done\e[0m, 6918990 (example.com)\nWarning! Potentially destructive action. Please confirm [y/n]: Aborted due to user request.
108
109
  eos
110
+
111
+ expect { cli.destroy('example.com') }.to raise_error(SystemExit).and output(expected_string).to_stdout
112
+ end
113
+
114
+ it 'raises SystemExit when a request fails' do
115
+ stub_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=1').
116
+ with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
117
+ to_return(status: 200, body: fixture('show_droplets'), headers: {})
118
+
119
+ stub_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=200').
120
+ with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
121
+ to_return(status: 200, body: fixture('show_droplets'), headers: {})
122
+
123
+ stub_request(:delete, 'https://api.digitalocean.com/v2/droplets/6918990').
124
+ with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
125
+ to_return(headers: { 'Content-Type' => 'application/json' }, status: 500, body: '{"status":"ERROR","message":"Some error"}')
126
+
127
+ expect($stdin).to receive(:gets).and_return('y')
128
+
129
+ cli.options = cli.options.merge(name: 'example.com')
130
+
131
+ expect { cli.destroy }.to raise_error(SystemExit).and output(%r{Failed to destroy Droplet: Some error}).to_stdout
109
132
  end
110
133
  end
111
134
  end
@@ -15,11 +15,11 @@ describe Tugboat::CLI do
15
15
 
16
16
  expect($stdin).to receive(:gets).and_return('y')
17
17
 
18
- cli.destroy_image('My application image')
19
-
20
- expect($stdout.string).to eq <<-eos
18
+ expected_string = <<-eos
21
19
  Image fuzzy name provided. Finding image ID...done\e[0m, 6376601 (My application image)\nWarning! Potentially destructive action. Please confirm [y/n]: Queuing destroy image for 6376601 (My application image)...Image deletion successful!
22
20
  eos
21
+
22
+ expect { cli.destroy_image('My application image') }.to output(expected_string).to_stdout
23
23
  end
24
24
 
25
25
  it 'destroys an image with an id' do
@@ -34,11 +34,12 @@ Image fuzzy name provided. Finding image ID...done\e[0m, 6376601 (My application
34
34
  expect($stdin).to receive(:gets).and_return('y')
35
35
 
36
36
  cli.options = cli.options.merge(id: 6_376_601)
37
- cli.destroy_image
38
37
 
39
- expect($stdout.string).to eq <<-eos
38
+ expected_string = <<-eos
40
39
  Image id provided. Finding Image...done\e[0m, 6376601 (My application image)\nWarning! Potentially destructive action. Please confirm [y/n]: Queuing destroy image for 6376601 (My application image)...Image deletion successful!
41
40
  eos
41
+
42
+ expect { cli.destroy_image }.to output(expected_string).to_stdout
42
43
  end
43
44
 
44
45
  it 'destroys an image with a name' do
@@ -52,10 +53,10 @@ Image id provided. Finding Image...done\e[0m, 6376601 (My application image)\nWa
52
53
 
53
54
  expect($stdin).to receive(:gets).and_return('y')
54
55
 
55
- cli.options = cli.options.merge(name: 'My application image')
56
- cli.destroy_image
56
+ expected_string = "Image name provided. Finding Image...done\e[0m, 6376601 (My application image)\nWarning! Potentially destructive action. Please confirm [y/n]: Queuing destroy image for 6376601 (My application image)...Image deletion successful!\n"
57
57
 
58
- expect($stdout.string).to eq "Image name provided. Finding Image...done\e[0m, 6376601 (My application image)\nWarning! Potentially destructive action. Please confirm [y/n]: Queuing destroy image for 6376601 (My application image)...Image deletion successful!\n"
58
+ cli.options = cli.options.merge(name: 'My application image')
59
+ expect { cli.destroy_image }.to output(expected_string).to_stdout
59
60
  end
60
61
 
61
62
  it 'destroys an image with confirm flag set' do
@@ -69,11 +70,12 @@ Image id provided. Finding Image...done\e[0m, 6376601 (My application image)\nWa
69
70
 
70
71
  cli.options = cli.options.merge(name: 'My application image')
71
72
  cli.options = cli.options.merge(confirm: true)
72
- cli.destroy_image('NLP Final')
73
73
 
74
- expect($stdout.string).to eq <<-eos
74
+ expected_string = <<-eos
75
75
  Image name provided. Finding Image...done\e[0m, 6376601 (My application image)\nQueuing destroy image for 6376601 (My application image)...Image deletion successful!
76
76
  eos
77
+
78
+ expect { cli.destroy_image('NLP Final') }.to output(expected_string).to_stdout
77
79
  end
78
80
  end
79
81
  end
@@ -9,19 +9,20 @@ describe Tugboat::CLI do
9
9
  with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
10
10
  to_return(status: 200, body: fixture('show_droplets'), headers: {})
11
11
 
12
- stub_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=200').
12
+ stub_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=20').
13
13
  with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
14
14
  to_return(status: 200, body: fixture('show_droplets'), headers: { 'Content-Type' => 'application/json' })
15
15
 
16
- cli.droplets
17
-
18
- expect($stdout.string).to eq <<-eos
19
- example.com (ip: 104.236.32.182, status: \e[32mactive\e[0m, region: nyc3, id: 6918990)
20
- example2.com (ip: 104.236.32.172, status: \e[32mactive\e[0m, region: nyc3, id: 3164956)
21
- example3.com (ip: 104.236.32.173, status: \e[31moff\e[0m, region: nyc3, id: 3164444)
16
+ expected_string = <<-eos
17
+ example.com (ip: 104.236.32.182, status: \e[32mactive\e[0m, region: nyc3, size: 512mb, id: 6918990)
18
+ example2.com (ip: 104.236.32.172, status: \e[32mactive\e[0m, region: nyc3, size: 512mb, id: 3164956)
19
+ example3.com (ip: 104.236.32.173, status: \e[31moff\e[0m, region: nyc3, size: 512mb, id: 3164444)
22
20
  eos
23
21
 
24
- expect(a_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=200')).to have_been_made
22
+ expect { cli.droplets }.to output(expected_string).to_stdout
23
+
24
+ expect(a_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=1')).to have_been_made.twice
25
+ expect(a_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=20')).to have_been_made
25
26
  end
26
27
 
27
28
  it 'shows a private IP if droplet in list has private IP' do
@@ -29,19 +30,21 @@ example3.com (ip: 104.236.32.173, status: \e[31moff\e[0m, region: nyc3, id: 3164
29
30
  with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
30
31
  to_return(status: 200, body: fixture('show_droplets'), headers: {})
31
32
 
32
- stub_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=200').
33
+ stub_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=20').
33
34
  with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
34
35
  to_return(status: 200, body: fixture('show_droplets_private_ip'), headers: { 'Content-Type' => 'application/json' })
35
36
 
36
- cli.droplets
37
37
 
38
- expect($stdout.string).to eq <<-eos
39
- exampleprivate.com (ip: 104.236.32.182, private_ip: 10.131.99.89, status: \e[32mactive\e[0m, region: nyc3, id: 6918990)
40
- example2.com (ip: 104.236.32.172, status: \e[32mactive\e[0m, region: nyc3, id: 3164956)
41
- example3.com (ip: 104.236.32.173, status: \e[31moff\e[0m, region: nyc3, id: 3164444)
38
+ expected_string = <<-eos
39
+ exampleprivate.com (ip: 104.236.32.182, private_ip: 10.131.99.89, status: \e[32mactive\e[0m, region: nyc3, size: 512mb, id: 6918990)
40
+ example2.com (ip: 104.236.32.172, status: \e[32mactive\e[0m, region: nyc3, size: 512mb, id: 3164956)
41
+ example3.com (ip: 104.236.32.173, status: \e[31moff\e[0m, region: nyc3, size: 512mb, id: 3164444)
42
42
  eos
43
43
 
44
- expect(a_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=200')).to have_been_made
44
+ expect { cli.droplets }.to output(expected_string).to_stdout
45
+
46
+ expect(a_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=1')).to have_been_made.twice
47
+ expect(a_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=20')).to have_been_made
45
48
  end
46
49
 
47
50
  it 'returns an error message when no droplets exist' do
@@ -49,18 +52,19 @@ example3.com (ip: 104.236.32.173, status: \e[31moff\e[0m, region: nyc3, id: 3164
49
52
  with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
50
53
  to_return(status: 200, body: fixture('show_droplets'), headers: {})
51
54
 
52
- stub_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=200').
55
+ stub_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=20').
53
56
  with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
54
57
  to_return(status: 200, body: fixture('show_droplets_empty'), headers: { 'Content-Type' => 'application/json' })
55
58
 
56
- cli.droplets
57
-
58
- expect($stdout.string).to eq <<-eos
59
+ expected_string = <<-eos
59
60
  You don't appear to have any droplets.
60
61
  Try creating one with \e[32m`tugboat create`\e[0m
61
62
  eos
62
63
 
63
- expect(a_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=200')).to have_been_made
64
+ expect { cli.droplets }.to output(expected_string).to_stdout
65
+
66
+ expect(a_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=1')).to have_been_made.twice
67
+ expect(a_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=20')).to have_been_made
64
68
  end
65
69
 
66
70
  it 'shows no output when --quiet is set' do
@@ -68,17 +72,15 @@ Try creating one with \e[32m`tugboat create`\e[0m
68
72
  with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
69
73
  to_return(status: 200, body: fixture('show_droplets'), headers: {})
70
74
 
71
- stub_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=200').
75
+ stub_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=20').
72
76
  with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
73
77
  to_return(status: 200, body: fixture('show_droplets'), headers: { 'Content-Type' => 'application/json' })
74
78
 
75
79
  cli.options = cli.options.merge(quiet: true)
76
- cli.droplets
80
+ expect { cli.droplets }.not_to output.to_stderr
77
81
 
78
- # Should be /dev/null not stringIO
79
- expect($stdout).to be_a File
80
-
81
- expect(a_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=200')).to have_been_made
82
+ expect(a_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=1')).to have_been_made.twice
83
+ expect(a_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=20')).to have_been_made
82
84
  end
83
85
 
84
86
  it 'includes urls when --include-urls is set' do
@@ -86,48 +88,72 @@ Try creating one with \e[32m`tugboat create`\e[0m
86
88
  with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
87
89
  to_return(status: 200, body: fixture('show_droplets'), headers: {})
88
90
 
89
- stub_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=200').
91
+ stub_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=20').
90
92
  with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
91
93
  to_return(status: 200, body: fixture('show_droplets'), headers: { 'Content-Type' => 'application/json' })
92
94
 
93
95
  cli.options = cli.options.merge('include_urls' => true)
94
- cli.droplets
95
96
 
96
- expect($stdout.string).to eq <<-eos
97
- example.com (ip: 104.236.32.182, status: \e[32mactive\e[0m, region: nyc3, id: 6918990, url: 'https://cloud.digitalocean.com/droplets/6918990')
98
- example2.com (ip: 104.236.32.172, status: \e[32mactive\e[0m, region: nyc3, id: 3164956, url: 'https://cloud.digitalocean.com/droplets/3164956')
99
- example3.com (ip: 104.236.32.173, status: \e[31moff\e[0m, region: nyc3, id: 3164444, url: 'https://cloud.digitalocean.com/droplets/3164444')
97
+ expected_string = <<-eos
98
+ example.com (ip: 104.236.32.182, status: \e[32mactive\e[0m, region: nyc3, size: 512mb, id: 6918990, url: 'https://cloud.digitalocean.com/droplets/6918990')
99
+ example2.com (ip: 104.236.32.172, status: \e[32mactive\e[0m, region: nyc3, size: 512mb, id: 3164956, url: 'https://cloud.digitalocean.com/droplets/3164956')
100
+ example3.com (ip: 104.236.32.173, status: \e[31moff\e[0m, region: nyc3, size: 512mb, id: 3164444, url: 'https://cloud.digitalocean.com/droplets/3164444')
100
101
  eos
101
102
 
102
- expect(a_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=200')).to have_been_made
103
+ expect { cli.droplets }.to output(expected_string).to_stdout
104
+
105
+ expect(a_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=1')).to have_been_made.twice
106
+ expect(a_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=20')).to have_been_made
103
107
  end
104
108
 
105
- it 'paginates when multiple pages are returned' do
109
+ it 'allows specifying per_page' do
106
110
  stub_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=1').
107
111
  with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
108
112
  to_return(status: 200, body: fixture('show_droplets'), headers: {})
109
113
 
110
- stub_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=200').
114
+ stub_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=3').
111
115
  with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
112
- to_return(status: 200, body: fixture('show_droplets_paginated_first'), headers: { 'Content-Type' => 'application/json' })
116
+ to_return(status: 200, body: fixture('show_droplets_paginated_first'), headers: {})
113
117
 
114
- stub_request(:get, 'https://api.digitalocean.com/v2/droplets?page=2&per_page=200').
118
+ stub_request(:get, 'https://api.digitalocean.com/v2/droplets?page=2&per_page=3').
115
119
  with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
116
120
  to_return(status: 200, body: fixture('show_droplets_paginated_last'), headers: { 'Content-Type' => 'application/json' })
117
121
 
118
- cli.options = cli.options.merge('include_urls' => true)
119
- cli.droplets
120
-
121
- expect($stdout.string).to eq <<-eos
122
- page1example.com (ip: 104.236.32.182, status: \e[32mactive\e[0m, region: nyc3, id: 6918990, url: 'https://cloud.digitalocean.com/droplets/6918990')
123
- page1example2.com (ip: 104.236.32.172, status: \e[32mactive\e[0m, region: nyc3, id: 3164956, url: 'https://cloud.digitalocean.com/droplets/3164956')
124
- page1example3.com (ip: 104.236.32.173, status: \e[31moff\e[0m, region: nyc3, id: 3164444, url: 'https://cloud.digitalocean.com/droplets/3164444')
125
- page2example.com (ip: 104.236.32.182, status: \e[32mactive\e[0m, region: nyc3, id: 6918990, url: 'https://cloud.digitalocean.com/droplets/6918990')
126
- page2example2.com (ip: 104.236.32.172, status: \e[32mactive\e[0m, region: nyc3, id: 3164956, url: 'https://cloud.digitalocean.com/droplets/3164956')
127
- page2example3.com (ip: 104.236.32.173, status: \e[31moff\e[0m, region: nyc3, id: 3164444, url: 'https://cloud.digitalocean.com/droplets/3164444')
122
+
123
+ cli.options = cli.options.merge('per_page' => '3')
124
+
125
+ expected_string = <<-eos
126
+ page1example.com (ip: 104.236.32.182, status: \e[32mactive\e[0m, region: nyc3, size: 512mb, id: 6918990)
127
+ page1example2.com (ip: 104.236.32.172, status: \e[32mactive\e[0m, region: nyc3, size: 512mb, id: 3164956)
128
+ page1example3.com (ip: 104.236.32.173, status: \e[31moff\e[0m, region: nyc3, size: 512mb, id: 3164444)
129
+ page2example.com (ip: 104.236.32.182, status: \e[32mactive\e[0m, region: nyc3, size: 512mb, id: 6918990)
130
+ page2example2.com (ip: 104.236.32.172, status: \e[32mactive\e[0m, region: nyc3, size: 512mb, id: 3164956)
131
+ page2example3.com (ip: 104.236.32.173, status: \e[31moff\e[0m, region: nyc3, size: 512mb, id: 3164444)
128
132
  eos
129
133
 
130
- expect(a_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=200')).to have_been_made
134
+ expect { cli.droplets }.to output(expected_string).to_stdout
135
+
136
+ expect(a_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=3')).to have_been_made
137
+ expect(a_request(:get, 'https://api.digitalocean.com/v2/droplets?page=2&per_page=3')).to have_been_made
131
138
  end
139
+
140
+ it 'shows error on failure in initial stage' do
141
+ stub_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=1').
142
+ with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => 'Bearer foo', 'Content-Type' => 'application/json', 'User-Agent' => 'Faraday v0.9.2' }).
143
+ to_return(headers: { 'Content-Type' => 'text/html' }, status: 401, body: fixture('401'))
144
+
145
+ expected_string = <<-eos
146
+ Failed to connect to DigitalOcean. Reason given from API:
147
+ 401: {
148
+ \"id\": \"unauthorized\",
149
+ \"message\": \"Unable to authenticate you.\"
150
+ }
151
+ eos
152
+
153
+ expect { cli.droplets }.to raise_error(SystemExit).and output(expected_string).to_stdout
154
+
155
+ expect(a_request(:get, 'https://api.digitalocean.com/v2/droplets?page=1&per_page=1')).to have_been_made.once
156
+ end
157
+
132
158
  end
133
159
  end