fog-brightbox 1.4.2 → 1.6.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 (29) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -0
  3. data/lib/fog/brightbox/compute/shared.rb +26 -10
  4. data/lib/fog/brightbox/compute.rb +17 -0
  5. data/lib/fog/brightbox/config.rb +12 -0
  6. data/lib/fog/brightbox/models/compute/server.rb +9 -1
  7. data/lib/fog/brightbox/models/compute/volume.rb +152 -0
  8. data/lib/fog/brightbox/models/compute/volumes.rb +23 -0
  9. data/lib/fog/brightbox/oauth2.rb +47 -7
  10. data/lib/fog/brightbox/requests/compute/attach_volume.rb +23 -0
  11. data/lib/fog/brightbox/requests/compute/copy_volume.rb +25 -0
  12. data/lib/fog/brightbox/requests/compute/create_volume.rb +25 -0
  13. data/lib/fog/brightbox/requests/compute/delete_volume.rb +20 -0
  14. data/lib/fog/brightbox/requests/compute/detach_volume.rb +21 -0
  15. data/lib/fog/brightbox/requests/compute/get_volume.rb +20 -0
  16. data/lib/fog/brightbox/requests/compute/list_volumes.rb +18 -0
  17. data/lib/fog/brightbox/requests/compute/lock_resource_volume.rb +18 -0
  18. data/lib/fog/brightbox/requests/compute/resize_volume.rb +26 -0
  19. data/lib/fog/brightbox/requests/compute/unlock_resource_volume.rb +18 -0
  20. data/lib/fog/brightbox/requests/compute/update_volume.rb +26 -0
  21. data/lib/fog/brightbox/version.rb +1 -1
  22. data/spec/fog/brightbox/compute/credentials_spec.rb +41 -0
  23. data/spec/fog/brightbox/compute/get_access_token_spec.rb +305 -0
  24. data/spec/fog/brightbox/compute/two_factor_spec.rb +53 -0
  25. data/spec/fog/brightbox/oauth2/user_credentials_strategy_spec.rb +20 -0
  26. data/spec/fog/compute/brightbox/volume_spec.rb +348 -0
  27. data/tests/brightbox/compute/schema.rb +74 -0
  28. data/tests/brightbox/requests/compute/volume_tests.rb +57 -0
  29. metadata +23 -1
@@ -0,0 +1,18 @@
1
+ module Fog
2
+ module Brightbox
3
+ class Compute
4
+ class Real
5
+ # Lists summary details of volumes available for use by the Account
6
+ #
7
+ # @param [Hash] options
8
+ # @option options [Boolean] :nested passed through with the API request. When true nested resources are expanded.
9
+ #
10
+ # @return [Hash] if successful Hash version of JSON object
11
+ #
12
+ def list_volumes(options = {})
13
+ wrapped_request("get", "/1.0/volumes", [200], options)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ module Fog
2
+ module Brightbox
3
+ class Compute
4
+ class Real
5
+ # @param [String] identifier Unique reference to identify the resource
6
+ # @param [Hash] options
7
+ # @option options [Boolean] :nested passed through with the API request. When true nested resources are expanded.
8
+ #
9
+ # @return [Hash] if successful Hash version of JSON object
10
+ #
11
+ def lock_resource_volume(identifier, options = {})
12
+ return nil if identifier.nil? || identifier == ""
13
+ wrapped_request("put", "/1.0/volumes/#{identifier}/lock_resource", [200], options)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,26 @@
1
+ module Fog
2
+ module Brightbox
3
+ class Compute
4
+ class Real
5
+ # Resize a volume, currently limited to expanding volumes.
6
+ #
7
+ # Partitions will need to be expanded within the OS.
8
+ #
9
+ # @param [String] identifier Unique reference to identify the resource
10
+ # @param [Hash] options
11
+ # @option options [Boolean] :nested passed through with the API request. When true nested resources are expanded.
12
+ # @option options [Integer] :from The original size (in MiB) to act as a preflight check to prevent duplicate requests
13
+ # @option options [Integer] :to The new size in MiB to change the volume to
14
+ #
15
+ # @return [Hash] if successful Hash version of JSON object
16
+ # @return [NilClass] if no options were passed
17
+ #
18
+ def resize_volume(identifier, options)
19
+ return nil if identifier.nil? || identifier == ""
20
+ return nil if options.empty? || options.nil?
21
+ wrapped_request("post", "/1.0/volumes/#{identifier}/resize", [202], options)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,18 @@
1
+ module Fog
2
+ module Brightbox
3
+ class Compute
4
+ class Real
5
+ # @param [String] identifier Unique reference to identify the resource
6
+ # @param [Hash] options
7
+ # @option options [Boolean] :nested passed through with the API request. When true nested resources are expanded.
8
+ #
9
+ # @return [Hash] if successful Hash version of JSON object
10
+ #
11
+ def unlock_resource_volume(identifier, options = {})
12
+ return nil if identifier.nil? || identifier == ""
13
+ wrapped_request("put", "/1.0/volumes/#{identifier}/unlock_resource", [200], options)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,26 @@
1
+ module Fog
2
+ module Brightbox
3
+ class Compute
4
+ class Real
5
+ # Update some volume attributes.
6
+ #
7
+ # @param [String] identifier Unique reference to identify the resource
8
+ # @param [Hash] options
9
+ # @option options [Boolean] :nested passed through with the API request. When true nested resources are expanded.
10
+ # @option options [Boolean] :delete_with_server Set +true+ the volume will be removed if attached to a server that is deleted
11
+ # @option options [String] :description
12
+ # @option options [String] :name
13
+ # @option options [String] :serial
14
+ #
15
+ # @return [Hash] if successful Hash version of JSON object
16
+ # @return [NilClass] if no options were passed
17
+ #
18
+ def update_volume(identifier, options)
19
+ return nil if identifier.nil? || identifier == ""
20
+ return nil if options.empty? || options.nil?
21
+ wrapped_request("put", "/1.0/volumes/#{identifier}", [202], options)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,5 +1,5 @@
1
1
  module Fog
2
2
  module Brightbox
3
- VERSION = "1.4.2"
3
+ VERSION = "1.6.0"
4
4
  end
5
5
  end
@@ -0,0 +1,41 @@
1
+ require "spec_helper"
2
+
3
+ describe Fog::Brightbox::Compute, "#credentials" do
4
+ describe "when 2FA support is disabled" do
5
+ before do
6
+ @options = {
7
+ brightbox_client_id: "app-12345",
8
+ brightbox_secret: "1234567890",
9
+ brightbox_username: "jason.null@brightbox.com",
10
+ brightbox_password: "HR4life",
11
+ brightbox_one_time_password: "123456"
12
+ }
13
+ @service = Fog::Brightbox::Compute.new(@options)
14
+ end
15
+
16
+ it "does not add passed OTP to credentials" do
17
+ assert_kind_of Fog::Brightbox::OAuth2::CredentialSet, @service.credentials
18
+ assert_nil @service.credentials.one_time_password
19
+ end
20
+ end
21
+
22
+ describe "with 2FA support is enabled" do
23
+ before do
24
+ @expected_otp = "123456"
25
+ @options = {
26
+ brightbox_client_id: "app-12345",
27
+ brightbox_secret: "1234567890",
28
+ brightbox_username: "jason.null@brightbox.com",
29
+ brightbox_password: "HR4life",
30
+ brightbox_support_two_factor: true,
31
+ brightbox_one_time_password: @expected_otp
32
+ }
33
+ @service = Fog::Brightbox::Compute.new(@options)
34
+ end
35
+
36
+ it "adds passed OTP to credentials" do
37
+ assert_kind_of Fog::Brightbox::OAuth2::CredentialSet, @service.credentials
38
+ assert @expected_otp, @service.credentials.one_time_password
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,305 @@
1
+ require "spec_helper"
2
+
3
+ describe Fog::Brightbox::Compute, "#get_access_token" do
4
+ before do
5
+ @new_access_token = "0987654321"
6
+ @new_refresh_token = "5432167890"
7
+
8
+ @options = {
9
+ brightbox_client_id: "app-12345",
10
+ brightbox_secret: "1234567890",
11
+ brightbox_username: "jason.null@brightbox.com",
12
+ brightbox_password: "HR4life",
13
+ brightbox_support_two_factor: true,
14
+ brightbox_one_time_password: "123456"
15
+ }
16
+ @service = Fog::Brightbox::Compute.new(@options)
17
+ end
18
+
19
+ describe "when user does not have 2FA enabled" do
20
+ describe "and authenticates correctly" do
21
+ before do
22
+ stub_authentication_request(auth_correct: true)
23
+
24
+ assert @service.two_factor?
25
+ end
26
+
27
+ describe "without !" do
28
+ it "updates credentials" do
29
+ token = @service.get_access_token
30
+ assert_equal "0987654321", token
31
+
32
+ assert_equal token, @service.access_token
33
+ end
34
+ end
35
+
36
+ describe "with !" do
37
+ it "updates credentials" do
38
+ token = @service.get_access_token!
39
+ assert_equal "0987654321", token
40
+
41
+ assert_equal token, @service.access_token
42
+ end
43
+ end
44
+ end
45
+
46
+ describe "and authenticates incorrectly" do
47
+ before do
48
+ stub_authentication_request(auth_correct: false)
49
+
50
+ assert @service.two_factor?
51
+ end
52
+
53
+ describe "without !" do
54
+ it "returns nil" do
55
+ assert_nil @service.get_access_token
56
+
57
+ assert_nil @service.access_token
58
+ assert_nil @service.refresh_token
59
+ end
60
+ end
61
+
62
+ describe "with !" do
63
+ it "raises an error" do
64
+ begin
65
+ @service.get_access_token!
66
+ rescue Excon::Error::Unauthorized
67
+ assert_nil @service.access_token
68
+ assert_nil @service.refresh_token
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ describe "when user does have 2FA enabled" do
76
+ describe "and authenticates correctly" do
77
+ describe "without OTP" do
78
+ before do
79
+ stub_authentication_request(auth_correct: true,
80
+ two_factor_user: true)
81
+
82
+ assert @service.two_factor?
83
+ end
84
+
85
+ describe "without !" do
86
+ it "returns nil" do
87
+ assert_nil @service.get_access_token
88
+
89
+ assert_nil @service.access_token
90
+ assert_nil @service.refresh_token
91
+ end
92
+ end
93
+
94
+ describe "with !" do
95
+ it "raises an error" do
96
+ begin
97
+ @service.get_access_token!
98
+ rescue Fog::Brightbox::OAuth2::TwoFactorMissingError
99
+ assert_nil @service.access_token
100
+ assert_nil @service.refresh_token
101
+ end
102
+ end
103
+ end
104
+ end
105
+
106
+ describe "with OTP" do
107
+ before do
108
+ stub_authentication_request(auth_correct: true,
109
+ two_factor_user: true,
110
+ otp_sent: true)
111
+
112
+ assert @service.two_factor?
113
+ end
114
+
115
+ describe "without !" do
116
+ it "updates credentials" do
117
+ token = @service.get_access_token
118
+ assert_equal "0987654321", token
119
+
120
+ assert_equal token, @service.access_token
121
+ end
122
+ end
123
+
124
+ describe "with !" do
125
+ it "updates credentials" do
126
+ token = @service.get_access_token!
127
+ assert_equal "0987654321", token
128
+
129
+ assert_equal token, @service.access_token
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ describe "and authenticates incorrectly" do
136
+ before do
137
+ stub_authentication_request(auth_correct: false,
138
+ two_factor_user: true)
139
+
140
+ assert @service.two_factor?
141
+ end
142
+
143
+ describe "without !" do
144
+ it "returns nil" do
145
+ assert_nil @service.get_access_token
146
+
147
+ assert_nil @service.access_token
148
+ assert_nil @service.refresh_token
149
+ end
150
+ end
151
+
152
+ describe "with !" do
153
+ it "raises an error" do
154
+ begin
155
+ @service.get_access_token!
156
+ rescue Fog::Brightbox::OAuth2::TwoFactorMissingError
157
+ assert_nil @service.access_token
158
+ assert_nil @service.refresh_token
159
+ end
160
+ end
161
+ end
162
+ end
163
+
164
+ describe "without 2FA support enabled" do
165
+ before do
166
+ @options = {
167
+ brightbox_client_id: "app-12345",
168
+ brightbox_secret: "1234567890",
169
+ brightbox_username: "jason.null@brightbox.com",
170
+ brightbox_password: "HR4life",
171
+ brightbox_support_two_factor: false,
172
+ brightbox_one_time_password: "123456"
173
+ }
174
+ @service = Fog::Brightbox::Compute.new(@options)
175
+
176
+ refute @service.two_factor?
177
+ end
178
+
179
+ describe "without !" do
180
+ it "returns nil" do
181
+ stub_authentication_request(auth_correct: false,
182
+ two_factor_user: true)
183
+
184
+ assert_nil @service.get_access_token
185
+
186
+ assert_nil @service.access_token
187
+ assert_nil @service.refresh_token
188
+ end
189
+ end
190
+
191
+ describe "with !" do
192
+ describe "when authentication incorrect" do
193
+ it "raises an error" do
194
+ stub_authentication_request(auth_correct: false,
195
+ two_factor_user: true,
196
+ otp_sent: true)
197
+
198
+ begin
199
+ @service.get_access_token!
200
+ rescue Excon::Error::Unauthorized
201
+ assert_nil @service.access_token
202
+ assert_nil @service.refresh_token
203
+ end
204
+ end
205
+ end
206
+
207
+ describe "with missing OTP" do
208
+ before do
209
+ @options = {
210
+ brightbox_client_id: "app-12345",
211
+ brightbox_secret: "1234567890",
212
+ brightbox_username: "jason.null@brightbox.com",
213
+ brightbox_password: "HR4life",
214
+ brightbox_support_two_factor: false
215
+ }
216
+ @service = Fog::Brightbox::Compute.new(@options)
217
+
218
+ refute @service.two_factor?
219
+ end
220
+
221
+ it "raises an error" do
222
+ stub_authentication_request(auth_correct: true,
223
+ two_factor_user: true,
224
+ otp_sent: false)
225
+
226
+ begin
227
+ @service.get_access_token!
228
+ rescue Excon::Error::Unauthorized
229
+ assert_nil @service.access_token
230
+ assert_nil @service.refresh_token
231
+ end
232
+ end
233
+ end
234
+ end
235
+ end
236
+ end
237
+
238
+ # @param auth_correct [Boolean] Treat username/password as correct
239
+ # @param two_factor_user [Boolean] Is user protected by 2FA on server
240
+ # @param otp_sent [Boolean] Is an OTP sent in the request?
241
+ def stub_authentication_request(auth_correct:,
242
+ two_factor_user: false,
243
+ otp_sent: nil)
244
+
245
+ two_factor_supported = @service.two_factor?
246
+
247
+ request = {
248
+ headers: {
249
+ "Authorization" => "Basic YXBwLTEyMzQ1OjEyMzQ1Njc4OTA=",
250
+ "Content-Type" => "application/json",
251
+ },
252
+ body: {
253
+ grant_type: "password",
254
+ username: "jason.null@brightbox.com",
255
+ password: "HR4life"
256
+ }.to_json
257
+ }.tap do |req|
258
+ # Only expect the header if the service should send it
259
+ # Without this, we stub a request that demands an OTP but it is not sent
260
+ if two_factor_supported && otp_sent
261
+ req[:headers]["X-Brightbox-OTP"] = "123456"
262
+ end
263
+ end
264
+
265
+ # The cases we are testing are:
266
+ #
267
+ # * User does not use 2FA and authenticate
268
+ # * User does not use 2FA and FAILS to authenticate
269
+ # * User does use 2FA and authenticate
270
+ # * User does use 2FA and FAILS to authenticate
271
+ # * User does use 2FA and FAILS to send OTP
272
+ #
273
+ response = if two_factor_user && !otp_sent
274
+ # OTP required header
275
+ {
276
+ status: 401,
277
+ headers: {
278
+ "X-Brightbox-OTP" => "required"
279
+ },
280
+ body: { error: "invalid_client" }.to_json
281
+ }
282
+ elsif !auth_correct
283
+ # No OTP header
284
+ {
285
+ status: 401,
286
+ headers: {},
287
+ body: { error: "invalid_client" }.to_json
288
+ }
289
+ else
290
+ {
291
+ status: 200,
292
+ headers: {},
293
+ body: {
294
+ access_token: @new_access_token,
295
+ refresh_token: @new_refresh_token,
296
+ expires_in: 7200
297
+ }.to_json
298
+ }
299
+ end
300
+
301
+ stub_request(:post, "https://api.gb1.brightbox.com/token")
302
+ .with(request)
303
+ .to_return(response)
304
+ end
305
+ end
@@ -0,0 +1,53 @@
1
+ require "spec_helper"
2
+
3
+ describe Fog::Brightbox::Compute, "#two_factor?" do
4
+ describe "when omitted" do
5
+ before do
6
+ @options = {
7
+ brightbox_client_id: "app-12345",
8
+ brightbox_secret: "1234567890",
9
+ brightbox_username: "jason.null@brightbox.com",
10
+ brightbox_password: "HR4life"
11
+ }
12
+ @service = Fog::Brightbox::Compute.new(@options)
13
+ end
14
+
15
+ it do
16
+ refute @service.two_factor?
17
+ end
18
+ end
19
+
20
+ describe "when disabled" do
21
+ before do
22
+ @options = {
23
+ brightbox_client_id: "app-12345",
24
+ brightbox_secret: "1234567890",
25
+ brightbox_username: "jason.null@brightbox.com",
26
+ brightbox_password: "HR4life",
27
+ brightbox_support_two_factor: false
28
+ }
29
+ @service = Fog::Brightbox::Compute.new(@options)
30
+ end
31
+
32
+ it do
33
+ refute @service.two_factor?
34
+ end
35
+ end
36
+
37
+ describe "when enabled" do
38
+ before do
39
+ @options = {
40
+ brightbox_client_id: "app-12345",
41
+ brightbox_secret: "1234567890",
42
+ brightbox_username: "jason.null@brightbox.com",
43
+ brightbox_password: "HR4life",
44
+ brightbox_support_two_factor: true
45
+ }
46
+ @service = Fog::Brightbox::Compute.new(@options)
47
+ end
48
+
49
+ it do
50
+ assert @service.two_factor?
51
+ end
52
+ end
53
+ end
@@ -37,4 +37,24 @@ describe Fog::Brightbox::OAuth2::UserCredentialsStrategy do
37
37
  assert_equal "Basic YXBwLTEyMzQ1Ol9fbWFzaGVkX2tleXNfMTIzX18=", headers["Authorization"]
38
38
  assert_equal "application/json", headers["Content-Type"]
39
39
  end
40
+
41
+ describe "when 2FA OTP is included" do
42
+ before do
43
+ options = {
44
+ username: @username,
45
+ password: @password,
46
+ one_time_password: "123456"
47
+ }
48
+
49
+ @credentials = Fog::Brightbox::OAuth2::CredentialSet.new(@client_id, @client_secret, options)
50
+ @strategy = Fog::Brightbox::OAuth2::UserCredentialsStrategy.new(@credentials)
51
+ end
52
+
53
+ it "tests #headers" do
54
+ headers = @strategy.headers
55
+ assert_equal "Basic YXBwLTEyMzQ1Ol9fbWFzaGVkX2tleXNfMTIzX18=", headers["Authorization"]
56
+ assert_equal "application/json", headers["Content-Type"]
57
+ assert_equal "123456", headers["X-Brightbox-OTP"]
58
+ end
59
+ end
40
60
  end