fog-brightbox 1.5.0 → 1.7.1

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -0
  3. data/lib/fog/brightbox/compute/shared.rb +26 -10
  4. data/lib/fog/brightbox/compute.rb +11 -0
  5. data/lib/fog/brightbox/config.rb +12 -0
  6. data/lib/fog/brightbox/models/compute/account.rb +30 -18
  7. data/lib/fog/brightbox/models/compute/api_client.rb +10 -2
  8. data/lib/fog/brightbox/models/compute/application.rb +8 -0
  9. data/lib/fog/brightbox/models/compute/cloud_ip.rb +11 -11
  10. data/lib/fog/brightbox/models/compute/collaboration.rb +11 -0
  11. data/lib/fog/brightbox/models/compute/config_map.rb +14 -0
  12. data/lib/fog/brightbox/models/compute/config_maps.rb +22 -0
  13. data/lib/fog/brightbox/models/compute/database_server.rb +19 -15
  14. data/lib/fog/brightbox/models/compute/database_snapshot.rb +13 -6
  15. data/lib/fog/brightbox/models/compute/database_type.rb +6 -3
  16. data/lib/fog/brightbox/models/compute/event.rb +5 -4
  17. data/lib/fog/brightbox/models/compute/firewall_policy.rb +10 -4
  18. data/lib/fog/brightbox/models/compute/firewall_rule.rb +9 -6
  19. data/lib/fog/brightbox/models/compute/flavor.rb +3 -3
  20. data/lib/fog/brightbox/models/compute/image.rb +16 -14
  21. data/lib/fog/brightbox/models/compute/load_balancer.rb +12 -8
  22. data/lib/fog/brightbox/models/compute/server.rb +19 -17
  23. data/lib/fog/brightbox/models/compute/server_group.rb +13 -5
  24. data/lib/fog/brightbox/models/compute/user.rb +9 -4
  25. data/lib/fog/brightbox/models/compute/user_collaboration.rb +11 -0
  26. data/lib/fog/brightbox/models/compute/volume.rb +15 -14
  27. data/lib/fog/brightbox/models/compute/zone.rb +3 -4
  28. data/lib/fog/brightbox/models/storage/directory.rb +2 -2
  29. data/lib/fog/brightbox/oauth2.rb +47 -7
  30. data/lib/fog/brightbox/requests/compute/create_config_map.rb +22 -0
  31. data/lib/fog/brightbox/requests/compute/delete_config_map.rb +20 -0
  32. data/lib/fog/brightbox/requests/compute/get_config_map.rb +18 -0
  33. data/lib/fog/brightbox/requests/compute/list_config_maps.rb +18 -0
  34. data/lib/fog/brightbox/requests/compute/update_config_map.rb +22 -0
  35. data/lib/fog/brightbox/version.rb +1 -1
  36. data/spec/fog/brightbox/compute/credentials_spec.rb +41 -0
  37. data/spec/fog/brightbox/compute/get_access_token_spec.rb +305 -0
  38. data/spec/fog/brightbox/compute/two_factor_spec.rb +53 -0
  39. data/spec/fog/brightbox/oauth2/user_credentials_strategy_spec.rb +20 -0
  40. metadata +14 -1
@@ -5,32 +5,34 @@ module Fog
5
5
  include Fog::Brightbox::Compute::ResourceLocking
6
6
 
7
7
  identity :id
8
- attribute :url
9
8
  attribute :resource_type
9
+ attribute :url
10
10
 
11
11
  attribute :name
12
- attribute :username
13
12
  attribute :status
14
13
  attribute :description
15
14
 
16
- attribute :source
17
- attribute :source_type
18
15
  attribute :arch
19
- attribute :virtual_size
20
- attribute :disk_size
16
+ attribute :disk_size, type: :integer
21
17
  attribute :licence_name
18
+ attribute :min_ram, type: :integer
19
+ attribute :source
20
+ attribute :source_trigger
21
+ attribute :source_type
22
+ attribute :username
23
+ attribute :virtual_size, type: :integer
22
24
 
23
25
  # Boolean flags
24
- attribute :public
25
- attribute :official
26
- attribute :compatibility_mode
26
+ attribute :compatibility_mode, type: :boolean
27
+ attribute :official, type: :boolean
28
+ attribute :public, type: :boolean
27
29
 
28
- # Times
29
- attribute :created_at, :type => :time
30
+ # Timestamps
31
+ attribute :created_at, type: :time
30
32
 
31
- # Links - to be replaced
32
- attribute :ancestor_id, :aliases => "ancestor", :squash => "id"
33
- attribute :owner_id, :aliases => "owner", :squash => "id"
33
+ # Links
34
+ attribute :ancestor_id, aliases: "ancestor", squash: "id"
35
+ attribute :owner_id, aliases: "owner", squash: "id"
34
36
 
35
37
  def ready?
36
38
  status == "available"
@@ -5,13 +5,13 @@ module Fog
5
5
  include Fog::Brightbox::Compute::ResourceLocking
6
6
 
7
7
  identity :id
8
- attribute :url
9
8
  attribute :resource_type
9
+ attribute :url
10
10
 
11
11
  attribute :name
12
12
  attribute :status
13
13
 
14
- attribute :buffer_size
14
+ attribute :buffer_size, type: :integer
15
15
 
16
16
  attribute :policy
17
17
  attribute :nodes
@@ -34,14 +34,18 @@ module Fog
34
34
  # List of domains for ACME
35
35
  attribute :domains
36
36
 
37
- # Times
38
- attribute :created_at, :type => :time
39
- attribute :deleted_at, :type => :time
37
+ # Booleans
38
+ attribute :https_redirect, type: :boolean
39
+
40
+ # Timestamps
41
+ attribute :created_at, type: :time
42
+ attribute :deleted_at, type: :time
40
43
 
41
- # Links - to be replaced
44
+ # Links
42
45
  attribute :account
43
- attribute :server
44
- attribute :cloud_ip
46
+
47
+ attribute :nodes
48
+ attribute :cloud_ips
45
49
 
46
50
  def ready?
47
51
  status == "active"
@@ -14,35 +14,37 @@ module Fog
14
14
  attribute :url
15
15
 
16
16
  attribute :name
17
- attribute :state, :aliases => "status"
17
+ attribute :state, aliases: "status"
18
18
 
19
- attribute :hostname
20
- attribute :fqdn
21
- attribute :user_data
19
+ attribute :console_token
22
20
  attribute :console_url
23
21
  attribute :fqdn
24
- attribute :console_token
22
+ attribute :hostname
23
+ attribute :user_data
25
24
 
26
- attribute :disk_encrypted
25
+ # Boolean flags
26
+ attribute :compatibility_mode, type: :boolean
27
+ attribute :disk_encrypted, type: :boolean
27
28
 
28
- # Times
29
- attribute :created_at, :type => :time
30
- attribute :started_at, :type => :time
31
- attribute :console_token_expires, :type => :time
32
- attribute :deleted_at, :type => :time
29
+ # Timestamps
30
+ attribute :created_at, type: :time
31
+ attribute :started_at, type: :time
32
+ attribute :console_token_expires, type: :time
33
+ attribute :deleted_at, type: :time
33
34
 
34
- # Links - to be replaced
35
- attribute :account_id, :aliases => "account", :squash => "id"
36
- attribute :image_id, :aliases => "image", :squash => "id"
35
+ # Links
36
+ attribute :account_id, aliases: "account", squash: "id"
37
+ attribute :image_id, aliases: "image", squash: "id"
37
38
 
38
- attribute :snapshots
39
+ attribute :server_type
40
+ attribute :zone
39
41
  attribute :cloud_ip # Creation option only
42
+
40
43
  attribute :cloud_ips
41
44
  attribute :interfaces
42
45
  attribute :server_groups
46
+ attribute :snapshots
43
47
  attribute :volumes
44
- attribute :zone
45
- attribute :server_type
46
48
 
47
49
  def initialize(attributes = {})
48
50
  # Call super first to initialize the service object for our default image
@@ -6,15 +6,23 @@ module Fog
6
6
  # Certain actions can accept a server group and affect all members
7
7
  class ServerGroup < Fog::Brightbox::Model
8
8
  identity :id
9
-
10
- attribute :url
11
9
  attribute :resource_type
10
+ attribute :url
11
+
12
12
  attribute :name
13
13
  attribute :description
14
- attribute :default
15
- attribute :created_at, :type => :time
14
+ attribute :fqdn
15
+
16
+ # Booleans
17
+ attribute :default, type: :boolean
18
+
19
+ # Timestamps
20
+ attribute :created_at, type: :time
16
21
 
17
- attribute :server_ids, :aliases => "servers"
22
+ # Links
23
+ attribute :account_id, aliases: "account", squash: "id"
24
+ attribute :firewall_policy_id, aliases: "firewall_policy", squash: "id"
25
+ attribute :server_ids, aliases: "servers"
18
26
 
19
27
  def save
20
28
  options = {
@@ -11,13 +11,18 @@ module Fog
11
11
  attribute :ssh_key
12
12
 
13
13
  # Boolean flags
14
- attribute :email_verified
15
- attribute :messaging_pref
14
+ attribute :email_verified, type: :boolean
16
15
 
17
- # Links - to be replaced
18
- attribute :account_id, :aliases => "default_account", :squash => "id"
16
+ # Timestamps
17
+ attribute :created_at, type: :time
18
+
19
+ # Links
20
+ attribute :account_id, aliases: "default_account", squash: "id"
19
21
  attribute :accounts
20
22
 
23
+ # Deprecated
24
+ attribute :messaging_pref, type: :boolean
25
+
21
26
  def save
22
27
  requires :identity
23
28
 
@@ -3,10 +3,21 @@ module Fog
3
3
  class Compute
4
4
  class UserCollaboration < Fog::Brightbox::Model
5
5
  identity :id
6
+ # resource_type is buggy for this resource
7
+ attribute :url
8
+
6
9
  attribute :status
10
+
7
11
  attribute :email
8
12
  attribute :role
9
13
  attribute :role_label
14
+
15
+ # Timestamps
16
+ attribute :created_at, type: :time
17
+ attribute :started_at, type: :time
18
+ attribute :finished_at, type: :time
19
+
20
+ # Links
10
21
  attribute :account
11
22
  attribute :user
12
23
  attribute :inviter
@@ -5,34 +5,35 @@ module Fog
5
5
  include Fog::Brightbox::Compute::ResourceLocking
6
6
 
7
7
  identity :id
8
- attribute :url
9
8
  attribute :resource_type
9
+ attribute :url
10
10
 
11
11
  attribute :name
12
- attribute :state, :aliases => "status"
13
-
12
+ attribute :state, aliases: "status"
14
13
  attribute :description
14
+
15
15
  attribute :filesystem_label
16
16
  attribute :filesystem_type
17
17
  attribute :serial
18
- attribute :size
18
+ attribute :size, type: :integer
19
19
  attribute :source
20
20
  attribute :source_type
21
21
  attribute :storage_type
22
22
 
23
- attribute :boot
24
- attribute :delete_with_server
25
- attribute :encrypted
23
+ # Boolean flags
24
+ attribute :boot, type: :boolean
25
+ attribute :delete_with_server, type: :boolean
26
+ attribute :encrypted, type: :boolean
26
27
 
27
- # Times
28
- attribute :created_at, :type => :time
29
- attribute :updated_at, :type => :time
30
- attribute :deleted_at, :type => :time
28
+ # Timestamps
29
+ attribute :created_at, type: :time
30
+ attribute :updated_at, type: :time
31
+ attribute :deleted_at, type: :time
31
32
 
32
33
  # Links
33
- attribute :account_id, :aliases => "account", :squash => "id"
34
- attribute :image_id, :aliases => "image", :squash => "id"
35
- attribute :server_id, :aliases => "server", :squash => "id"
34
+ attribute :account_id, aliases: "account", squash: "id"
35
+ attribute :image_id, aliases: "image", squash: "id"
36
+ attribute :server_id, aliases: "server", squash: "id"
36
37
 
37
38
  def attach(server)
38
39
  requires :identity
@@ -3,13 +3,12 @@ module Fog
3
3
  class Compute
4
4
  class Zone < Fog::Brightbox::Model
5
5
  identity :id
6
- attribute :url
7
6
  attribute :resource_type
8
-
9
- attribute :status
10
- attribute :handle
7
+ attribute :url
11
8
 
12
9
  attribute :description
10
+ attribute :handle
11
+ attribute :status
13
12
  end
14
13
  end
15
14
  end
@@ -31,8 +31,8 @@ module Fog
31
31
  attr_writer :public
32
32
 
33
33
  def public_url
34
- # raise NotImplementedError
35
- ""
34
+ requires :key
35
+ @public_url ||= [service.management_url , Fog::Brightbox::Storage.escape(key, "/")].join("/")
36
36
  end
37
37
 
38
38
  def save
@@ -6,6 +6,10 @@ module Fog
6
6
  # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-10
7
7
  #
8
8
  module OAuth2
9
+ TWO_FACTOR_HEADER = "X-Brightbox-OTP".freeze
10
+
11
+ class TwoFactorMissingError < StandardError; end
12
+
9
13
  # This builds the simplest form of requesting an access token
10
14
  # based on the arguments passed in
11
15
  #
@@ -13,16 +17,38 @@ module Fog
13
17
  # @param [CredentialSet] credentials
14
18
  #
15
19
  # @return [Excon::Response]
20
+ # @raise [Excon::Errors::Unauthorized] if the credentials are rejected by the server
21
+ # @raise [Fog::Brightbox::OAuth2::TwoFactorMissingError] if opted in to 2FA and server reports header is required
16
22
  def request_access_token(connection, credentials)
17
23
  token_strategy = credentials.best_grant_strategy
18
24
 
19
- connection.request(
20
- :path => "/token",
21
- :expects => 200,
22
- :headers => token_strategy.headers,
23
- :method => "POST",
24
- :body => Fog::JSON.encode(token_strategy.authorization_body_data)
25
- )
25
+ if two_factor?
26
+ # When 2FA opt-in is set, we can expect 401 responses as well
27
+ response = connection.request(
28
+ :path => "/token",
29
+ :expects => [200, 401],
30
+ :headers => token_strategy.headers,
31
+ :method => "POST",
32
+ :body => Fog::JSON.encode(token_strategy.authorization_body_data)
33
+ )
34
+
35
+ if response.status == 401 && response.headers[Fog::Brightbox::OAuth2::TWO_FACTOR_HEADER] == "required"
36
+ raise TwoFactorMissingError
37
+ elsif response.status == 401
38
+ raise Excon::Errors.status_error({ expects: 200 }, status: 401)
39
+ else
40
+ response
41
+ end
42
+ else
43
+ # Use classic behaviour and return Excon::
44
+ connection.request(
45
+ :path => "/token",
46
+ :expects => 200,
47
+ :headers => token_strategy.headers,
48
+ :method => "POST",
49
+ :body => Fog::JSON.encode(token_strategy.authorization_body_data)
50
+ )
51
+ end
26
52
  end
27
53
 
28
54
  # Encapsulates credentials required to request access tokens from the
@@ -33,12 +59,14 @@ module Fog
33
59
  class CredentialSet
34
60
  attr_reader :client_id, :client_secret, :username, :password
35
61
  attr_reader :access_token, :refresh_token, :expires_in
62
+ attr_reader :one_time_password
36
63
  #
37
64
  # @param [String] client_id
38
65
  # @param [String] client_secret
39
66
  # @param [Hash] options
40
67
  # @option options [String] :username
41
68
  # @option options [String] :password
69
+ # @option options [String] :one_time_password One Time Password for Two Factor authentication
42
70
  #
43
71
  def initialize(client_id, client_secret, options = {})
44
72
  @client_id = client_id
@@ -48,6 +76,7 @@ module Fog
48
76
  @access_token = options[:access_token]
49
77
  @refresh_token = options[:refresh_token]
50
78
  @expires_in = options[:expires_in]
79
+ @one_time_password = options[:one_time_password]
51
80
  end
52
81
 
53
82
  # Returns true if user details are available
@@ -142,6 +171,17 @@ module Fog
142
171
  "password" => @credentials.password
143
172
  }
144
173
  end
174
+
175
+ def headers
176
+ {
177
+ "Authorization" => authorization_header,
178
+ "Content-Type" => "application/json"
179
+ }.tap do |headers|
180
+ if @credentials.one_time_password
181
+ headers[TWO_FACTOR_HEADER] = @credentials.one_time_password
182
+ end
183
+ end
184
+ end
145
185
  end
146
186
 
147
187
  # This strategy attempts to use a refresh_token gained during an earlier
@@ -0,0 +1,22 @@
1
+ module Fog
2
+ module Brightbox
3
+ class Compute
4
+ class Real
5
+ # Create a new config map
6
+ #
7
+ # @param [Hash] options
8
+ # @option options [String] :name to identify this config map
9
+ # @option options [Hash] :data key/values to expose in config map
10
+ # @option options [Boolean] :nested passed through with the API request. When true nested resources are expanded.
11
+ #
12
+ # @return [Hash] if successful Hash version of JSON object
13
+ # @return [NilClass] if no options were passed
14
+ #
15
+ def create_config_map(options)
16
+ return nil if options.empty? || options.nil?
17
+ wrapped_request("post", "/1.0/config_maps", [200], options)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,20 @@
1
+ module Fog
2
+ module Brightbox
3
+ class Compute
4
+ class Real
5
+ # Destroy the config map
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
+ #
11
+ # @return [Hash] if successful Hash version of JSON object
12
+ #
13
+ def delete_config_map(identifier, options = {})
14
+ return nil if identifier.nil? || identifier == ""
15
+ wrapped_request("delete", "/1.0/config_maps/#{identifier}", [200], options)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ 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 get_config_map(identifier, options = {})
12
+ return nil if identifier.nil? || identifier == ""
13
+ wrapped_request("get", "/1.0/config_maps/#{identifier}", [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
+ # Lists summary details of config maps owned 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_config_maps(options = {})
13
+ wrapped_request("get", "/1.0/config_maps", [200], options)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,22 @@
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 [String] :name to identifier this config map
8
+ # @option options [Hash] :data key/values to expose in config map
9
+ # @option options [Boolean] :nested passed through with the API request. When true nested resources are expanded.
10
+ #
11
+ # @return [Hash] if successful Hash version of JSON object
12
+ # @return [NilClass] if no options were passed
13
+ #
14
+ def update_config_map(identifier, options)
15
+ return nil if identifier.nil? || identifier == ""
16
+ return nil if options.empty? || options.nil?
17
+ wrapped_request("put", "/1.0/config_maps/#{identifier}", [200], options)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,5 +1,5 @@
1
1
  module Fog
2
2
  module Brightbox
3
- VERSION = "1.5.0"
3
+ VERSION = "1.7.1"
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