fog-brightbox 1.4.2 → 1.5.0.rc1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e093d1f19cc306dee85aed2df1cd8cdfd1103a4384732decce4a68855397bca5
4
- data.tar.gz: 5672ef5e5d920037120861bfa1bda35ce4ffb6f1530cc62d61a0cb02aeb22d4e
3
+ metadata.gz: 21377239d27fb6e504db5619e6ce945fdee02066f01f75629efd9028df3ba6e5
4
+ data.tar.gz: a7d34f4986720231418c445f1d121faa7001626e7984fe4b9e022afde73f807c
5
5
  SHA512:
6
- metadata.gz: cce99fc4e5978804b72374022bb42b43035709608012dbc4feb8791fa1b689d98aa2d7ee44289117986e457b8243453fe22a307b9012938a86c1485e5e43cd5d
7
- data.tar.gz: df8c06dcc583f25291bf7bd89bea248ccd7f2f0e5675330bc82cb520e6d6ab946427bce9fbbd35ef4f279b165c06c4a4e7272060ae47e5a900b12b3447f3fcc6
6
+ metadata.gz: e69f8b23071481ccc0642a12e237f82de430e149cdf171e2d1a8b1275a69e13081ff62df96c5df0128a311a7fcf0883cb10daf699296928147f6c02d7287eb5d
7
+ data.tar.gz: 38e0912ad00a805b6828c0238cf19408a16b29011d997b4876b322d0375793701160724b0b29c328127330a0ed1328091b0338bc3e11f57f84f0f95923c60746
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ### 1.5.0 / 2022-06-09
2
+
3
+ Changes:
4
+
5
+ * Added support for `Volume` resources. These are dynamic, network attached
6
+ volumes. Servers with `nbs` (Network Block Storage) types can be created
7
+ from volumes. Additional volumes can be attached to a server. The volumes
8
+ can be quickly copied and resized.
9
+
1
10
  ### 1.4.2 / 2022-06-09
2
11
 
3
12
  Bug fixes:
@@ -63,6 +63,8 @@ module Fog
63
63
  model :user
64
64
  collection :user_collaborations
65
65
  model :user_collaboration
66
+ collection :volumes
67
+ model :volume
66
68
 
67
69
  request_path "fog/brightbox/requests/compute"
68
70
  request :accept_user_collaboration
@@ -72,7 +74,9 @@ module Fog
72
74
  request :add_servers_server_group
73
75
  request :apply_to_firewall_policy
74
76
  request :accept_user_collaboration
77
+ request :attach_volume
75
78
  request :remove_firewall_policy
79
+ request :copy_volume
76
80
  request :create_api_client
77
81
  request :create_application
78
82
  request :create_cloud_ip
@@ -84,6 +88,7 @@ module Fog
84
88
  request :create_database_server
85
89
  request :create_server
86
90
  request :create_server_group
91
+ request :create_volume
87
92
  request :delete_api_client
88
93
  request :delete_application
89
94
  request :delete_cloud_ip
@@ -97,6 +102,8 @@ module Fog
97
102
  request :delete_server
98
103
  request :delete_server_group
99
104
  request :delete_user_collaboration
105
+ request :delete_volume
106
+ request :detach_volume
100
107
  request :get_account
101
108
  request :get_api_client
102
109
  request :get_application
@@ -117,6 +124,7 @@ module Fog
117
124
  request :get_server_type
118
125
  request :get_user
119
126
  request :get_user_collaboration
127
+ request :get_volume
120
128
  request :get_zone
121
129
  request :list_accounts
122
130
  request :list_api_clients
@@ -135,12 +143,14 @@ module Fog
135
143
  request :list_servers
136
144
  request :list_users
137
145
  request :list_user_collaborations
146
+ request :list_volumes
138
147
  request :list_zones
139
148
  request :lock_resource_database_server
140
149
  request :lock_resource_database_snapshot
141
150
  request :lock_resource_image
142
151
  request :lock_resource_load_balancer
143
152
  request :lock_resource_server
153
+ request :lock_resource_volume
144
154
  request :map_cloud_ip
145
155
  request :move_servers_server_group
146
156
  request :reboot_server
@@ -156,6 +166,7 @@ module Fog
156
166
  request :reset_secret_application
157
167
  request :reset_server
158
168
  request :resend_collaboration
169
+ request :resize_volume
159
170
  request :reject_user_collaboration
160
171
  request :shutdown_server
161
172
  request :snapshot_database_server
@@ -167,6 +178,7 @@ module Fog
167
178
  request :unlock_resource_image
168
179
  request :unlock_resource_load_balancer
169
180
  request :unlock_resource_server
181
+ request :unlock_resource_volume
170
182
  request :unmap_cloud_ip
171
183
  request :update_account
172
184
  request :update_api_client
@@ -182,6 +194,7 @@ module Fog
182
194
  request :update_server
183
195
  request :update_server_group
184
196
  request :update_user
197
+ request :update_volume
185
198
 
186
199
  # The Mock Service allows you to run a fake instance of the Service
187
200
  # which makes no real connections.
@@ -7,6 +7,8 @@ module Fog
7
7
  include Fog::Brightbox::ModelHelper
8
8
  include Fog::Brightbox::Compute::ResourceLocking
9
9
 
10
+ attr_accessor :volume_id
11
+
10
12
  identity :id
11
13
  attribute :resource_type
12
14
  attribute :url
@@ -38,6 +40,7 @@ module Fog
38
40
  attribute :cloud_ips
39
41
  attribute :interfaces
40
42
  attribute :server_groups
43
+ attribute :volumes
41
44
  attribute :zone
42
45
  attribute :server_type
43
46
 
@@ -181,7 +184,6 @@ module Fog
181
184
  raise Fog::Errors::Error.new("Resaving an existing object may create a duplicate") if persisted?
182
185
  requires :image_id
183
186
  options = {
184
- :image => image_id,
185
187
  :name => name,
186
188
  :zone => zone_id,
187
189
  :user_data => user_data,
@@ -192,6 +194,12 @@ module Fog
192
194
  options.merge!(:cloud_ip => cloud_ip) unless cloud_ip.nil? || cloud_ip == ""
193
195
  options.merge!(:disk_encrypted => disk_encrypted) if disk_encrypted
194
196
 
197
+ if volume_id
198
+ options.merge!(:volumes => [:volume => volume_id])
199
+ else
200
+ options.merge!(:image => image_id)
201
+ end
202
+
195
203
  data = service.create_server(options)
196
204
  merge_attributes(data)
197
205
  true
@@ -0,0 +1,152 @@
1
+ module Fog
2
+ module Brightbox
3
+ class Compute
4
+ class Volume < Fog::Brightbox::Model
5
+ include Fog::Brightbox::Compute::ResourceLocking
6
+
7
+ identity :id
8
+ attribute :url
9
+ attribute :resource_type
10
+
11
+ attribute :name
12
+ attribute :state, :aliases => "status"
13
+
14
+ attribute :description
15
+ attribute :filesystem_label
16
+ attribute :filesystem_type
17
+ attribute :serial
18
+ attribute :size
19
+ attribute :source
20
+ attribute :source_type
21
+ attribute :storage_type
22
+
23
+ attribute :boot
24
+ attribute :delete_with_server
25
+ attribute :encrypted
26
+
27
+ # Times
28
+ attribute :created_at, :type => :time
29
+ attribute :updated_at, :type => :time
30
+ attribute :deleted_at, :type => :time
31
+
32
+ # 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"
36
+
37
+ def attach(server)
38
+ requires :identity
39
+ data = service.attach_volume(identity, server: server.id)
40
+ merge_attributes(data)
41
+ true
42
+ end
43
+
44
+ def attached?
45
+ state == "attached"
46
+ end
47
+
48
+ # @param [Hash] options
49
+ # @option options [Boolean] :delete_with_server Set +true+ the volume will be removed if attached to a server that is deleted
50
+ # @option options [String] :description
51
+ # @option options [String] :name
52
+ # @option options [String] :serial
53
+ #
54
+ # @return [Fog::Compute::Volume] a new model for the copy
55
+ def copy(options = {})
56
+ requires :identity
57
+ data = service.copy_volume(identity, options)
58
+ service.volumes.new(data)
59
+ end
60
+
61
+ def creating?
62
+ state == "creating"
63
+ end
64
+
65
+ def deleted?
66
+ state == "deleted"
67
+ end
68
+
69
+ def deleting?
70
+ state == "deleting"
71
+ end
72
+
73
+ def detach
74
+ requires :identity
75
+ data = service.detach_volume(identity)
76
+ merge_attributes(data)
77
+ true
78
+ end
79
+
80
+ def detached?
81
+ state == "detached"
82
+ end
83
+
84
+ def failed?
85
+ state == "failed"
86
+ end
87
+
88
+ def finished?
89
+ deleted? || failed?
90
+ end
91
+
92
+ def ready?
93
+ attached? || detached?
94
+ end
95
+
96
+ # @param [Hash] options
97
+ # @option options [Integer] :to The new size in MiB to change the volume to
98
+ def resize(options)
99
+ requires :identity
100
+
101
+ # The API requires the old "from" size to avoid acting on stale data
102
+ # We can merge this and if the API rejects the request, the model was out of sync
103
+ options.merge!(:from => size)
104
+
105
+ data = service.resize_volume(identity, options)
106
+ merge_attributes(data)
107
+ true
108
+ end
109
+
110
+ def save
111
+ if persisted?
112
+ options = {
113
+ :delete_with_server => delete_with_server,
114
+ :description => description,
115
+ :name => name,
116
+ :serial => serial
117
+ }.delete_if { |_k, v| v.nil? || v == "" }
118
+
119
+ data = service.update_volume(identity, options)
120
+ else
121
+ raise Fog::Errors::Error.new("'image_id' and 'filesystem_type' are mutually exclusive") if image_id && filesystem_type
122
+ raise Fog::Errors::Error.new("'image_id' or 'filesystem_type' is required") unless image_id || filesystem_type
123
+
124
+ options = {
125
+ :delete_with_server => delete_with_server,
126
+ :description => description,
127
+ :filesystem_label => filesystem_label,
128
+ :filesystem_type => filesystem_type,
129
+ :name => name,
130
+ :serial => serial,
131
+ :size => size
132
+ }.delete_if { |_k, v| v.nil? || v == "" }
133
+
134
+ options.merge!(:image => image_id) unless image_id.nil? || image_id == ""
135
+
136
+ data = service.create_volume(options)
137
+ end
138
+
139
+ merge_attributes(data)
140
+ true
141
+ end
142
+
143
+ def destroy
144
+ requires :identity
145
+ data = service.delete_volume(identity)
146
+ merge_attributes(data)
147
+ true
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,23 @@
1
+ require "fog/brightbox/models/compute/volume"
2
+
3
+ module Fog
4
+ module Brightbox
5
+ class Compute
6
+ class Volumes < Fog::Collection
7
+ model Fog::Brightbox::Compute::Volume
8
+
9
+ def all
10
+ data = service.list_volumes
11
+ load(data)
12
+ end
13
+
14
+ def get(identifier)
15
+ data = service.get_volume(identifier)
16
+ new(data)
17
+ rescue Excon::Errors::NotFound
18
+ nil
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ module Fog
2
+ module Brightbox
3
+ class Compute
4
+ class Real
5
+ # Attach a detached server to a nominated server
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 [String] :server The identifier of the server
11
+ # @option options [Boolean] :boot Set +true+ to attach as boot volume. Only when server is stopped
12
+ #
13
+ # @return [Hash] if successful Hash version of JSON object
14
+ # @return [NilClass] if no options were passed
15
+ #
16
+ def attach_volume(identifier, options)
17
+ return nil if identifier.nil? || identifier == ""
18
+ wrapped_request("post", "/1.0/volumes/#{identifier}/attach", [202], options)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ module Fog
2
+ module Brightbox
3
+ class Compute
4
+ class Real
5
+ # Copy a volume and create a new one
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 copy_volume(identifier, options)
19
+ return nil if identifier.nil? || identifier == ""
20
+ wrapped_request("post", "/1.0/volumes/#{identifier}/copy", [202], options)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ module Fog
2
+ module Brightbox
3
+ class Compute
4
+ class Real
5
+ # Create a new volume
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 create_volume(options)
19
+ return nil if options.empty? || options.nil?
20
+ wrapped_request("post", "/1.0/volumes", [202], options)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ module Fog
2
+ module Brightbox
3
+ class Compute
4
+ class Real
5
+ # Destroy the volume and free up the resources.
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_volume(identifier, options = {})
14
+ return nil if identifier.nil? || identifier == ""
15
+ wrapped_request("delete", "/1.0/volumes/#{identifier}", [202], options)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ module Fog
2
+ module Brightbox
3
+ class Compute
4
+ class Real
5
+ # Detach the volume from its server
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
+ # @return [NilClass] if no options were passed
13
+ #
14
+ def detach_volume(identifier, options = {})
15
+ return nil if identifier.nil? || identifier == ""
16
+ wrapped_request("post", "/1.0/volumes/#{identifier}/detach", [202], options)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ module Fog
2
+ module Brightbox
3
+ class Compute
4
+ class Real
5
+ # Get full details of the volume.
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 get_volume(identifier, options = {})
14
+ return nil if identifier.nil? || identifier == ""
15
+ wrapped_request("get", "/1.0/volumes/#{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
+ # 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.5.0.rc1"
4
4
  end
5
5
  end
@@ -0,0 +1,348 @@
1
+ require "spec_helper"
2
+ require "fog/brightbox/models/compute/volume"
3
+
4
+ describe Fog::Brightbox::Compute::Volume do
5
+ include ModelSetup
6
+ include SupportsResourceLocking
7
+
8
+ subject { service.volumes.new }
9
+
10
+ describe "when state is 'creating'" do
11
+ it do
12
+ subject.state = "creating"
13
+
14
+ assert subject.creating?
15
+ refute subject.attached?
16
+ refute subject.detached?
17
+ refute subject.deleting?
18
+ refute subject.deleted?
19
+ refute subject.failed?
20
+
21
+ refute subject.ready?
22
+ refute subject.finished?
23
+ end
24
+ end
25
+
26
+ describe "when state is 'attached'" do
27
+ it do
28
+ subject.state = "attached"
29
+
30
+ refute subject.creating?
31
+ assert subject.attached?
32
+ refute subject.detached?
33
+ refute subject.deleting?
34
+ refute subject.deleted?
35
+ refute subject.failed?
36
+
37
+ assert subject.ready?
38
+ refute subject.finished?
39
+ end
40
+ end
41
+
42
+ describe "when state is 'detached'" do
43
+ it do
44
+ subject.state = "detached"
45
+
46
+ refute subject.creating?
47
+ refute subject.attached?
48
+ assert subject.detached?
49
+ refute subject.deleting?
50
+ refute subject.deleted?
51
+ refute subject.failed?
52
+
53
+ assert subject.ready?
54
+ refute subject.finished?
55
+ end
56
+ end
57
+
58
+ describe "when state is 'deleting'" do
59
+ it do
60
+ subject.state = "deleting"
61
+
62
+ refute subject.creating?
63
+ refute subject.attached?
64
+ refute subject.detached?
65
+ assert subject.deleting?
66
+ refute subject.deleted?
67
+ refute subject.failed?
68
+
69
+ refute subject.ready?
70
+ refute subject.finished?
71
+ end
72
+ end
73
+
74
+ describe "when state is 'deleted'" do
75
+ it do
76
+ subject.state = "deleted"
77
+
78
+ refute subject.creating?
79
+ refute subject.attached?
80
+ refute subject.detached?
81
+ refute subject.deleting?
82
+ assert subject.deleted?
83
+ refute subject.failed?
84
+
85
+ refute subject.ready?
86
+ assert subject.finished?
87
+ end
88
+ end
89
+
90
+ describe "when state is 'failed'" do
91
+ it do
92
+ subject.state = "failed"
93
+
94
+ refute subject.creating?
95
+ refute subject.attached?
96
+ refute subject.detached?
97
+ refute subject.deleting?
98
+ refute subject.deleted?
99
+ assert subject.failed?
100
+
101
+ refute subject.ready?
102
+ assert subject.finished?
103
+ end
104
+ end
105
+
106
+ describe "#attach" do
107
+ it do
108
+ subject.id = "vol-12345"
109
+ assert subject.persisted?
110
+
111
+ server = service.servers.new
112
+ server.id = "srv-12345"
113
+
114
+ stub_request(:post, "http://localhost/1.0/volumes/vol-12345/attach").
115
+ with(:query => hash_including(:account_id),
116
+ :headers => { "Authorization" => "Bearer FAKECACHEDTOKEN",
117
+ "Content-Type" => "application/json" },
118
+ :body => hash_including(:server => "srv-12345")).
119
+ to_return(:status => 202,
120
+ :body => %q({"id":"vol-12345","status":"attached"}),
121
+ :headers => {})
122
+
123
+ subject.attach(server)
124
+
125
+ assert subject.attached?
126
+ end
127
+ end
128
+
129
+ describe "#collection_name" do
130
+ it "responds 'volumes'" do
131
+ assert_equal "volumes", subject.collection_name
132
+ end
133
+ end
134
+
135
+ describe "#copy" do
136
+ it do
137
+ subject.id = "vol-12345"
138
+ subject.state = "attached"
139
+ subject.delete_with_server = false
140
+
141
+ refute subject.delete_with_server
142
+ assert subject.persisted?
143
+
144
+ stub_request(:post, "http://localhost/1.0/volumes/vol-12345/copy").
145
+ with(:query => hash_including(:account_id),
146
+ :headers => { "Authorization" => "Bearer FAKECACHEDTOKEN",
147
+ "Content-Type" => "application/json" },
148
+ :body => hash_including(:delete_with_server => true)).
149
+ to_return(:status => 202,
150
+ :body => %q({"id":"vol-abcde","delete_with_server":true,"name":"Copy of vol-12345 (Impish Image)","status":"detached"}),
151
+ :headers => {})
152
+
153
+ copy = subject.copy(delete_with_server: true)
154
+
155
+ assert copy.persisted?
156
+ assert_equal "vol-abcde", copy.id
157
+ assert copy.delete_with_server
158
+ assert copy.detached?
159
+ end
160
+ end
161
+
162
+ describe "#detach" do
163
+ it do
164
+ subject.id = "vol-12345"
165
+ subject.state = "attached"
166
+
167
+ assert subject.persisted?
168
+
169
+ stub_request(:post, "http://localhost/1.0/volumes/vol-12345/detach").
170
+ with(:query => hash_including(:account_id),
171
+ :headers => { "Authorization" => "Bearer FAKECACHEDTOKEN",
172
+ "Content-Type" => "application/json" }).
173
+ to_return(:status => 202,
174
+ :body => %q({"id":"vol-12345","status":"detached"}),
175
+ :headers => {})
176
+
177
+ subject.detach
178
+
179
+ assert subject.detached?
180
+ end
181
+ end
182
+
183
+ describe "#destroy" do
184
+ it do
185
+ subject.id = "vol-12345"
186
+ assert subject.persisted?
187
+
188
+ stub_request(:delete, "http://localhost/1.0/volumes/vol-12345").
189
+ with(:query => hash_including(:account_id),
190
+ :headers => { "Authorization" => "Bearer FAKECACHEDTOKEN",
191
+ "Content-Type" => "application/json" }).
192
+ to_return(:status => 202,
193
+ :body => %q({"id":"vol-12345","status":"deleting"}),
194
+ :headers => {})
195
+
196
+ subject.destroy
197
+ assert_equal "deleting", subject.state
198
+ end
199
+ end
200
+
201
+ describe "#ready?" do
202
+ describe "when state is 'creating'" do
203
+ it do
204
+ subject.state = "creating"
205
+
206
+ refute subject.ready?
207
+ end
208
+ end
209
+
210
+ describe "when state is 'attached'" do
211
+ it do
212
+ subject.state = "attached"
213
+
214
+ assert subject.ready?
215
+ end
216
+ end
217
+
218
+ describe "when state is 'detached'" do
219
+ it do
220
+ subject.state = "detached"
221
+
222
+ assert subject.ready?
223
+ end
224
+ end
225
+ end
226
+
227
+ describe "#resize" do
228
+ it do
229
+ subject.id = "vol-12345"
230
+ subject.size = 40_000
231
+
232
+ assert subject.persisted?
233
+
234
+ stub_request(:post, "http://localhost/1.0/volumes/vol-12345/resize").
235
+ with(:query => hash_including(:account_id),
236
+ :headers => { "Authorization" => "Bearer FAKECACHEDTOKEN",
237
+ "Content-Type" => "application/json" },
238
+ :body => hash_including(:from => 40_000, :to => 50_000)).
239
+ to_return(:status => 202,
240
+ :body => %q({"id":"vol-12345","size": 50000}),
241
+ :headers => {})
242
+
243
+ subject.resize(to: 50_000)
244
+
245
+ assert 50_000, subject.size
246
+ end
247
+ end
248
+
249
+ describe "#resource_name" do
250
+ it "responds 'volume'" do
251
+ assert_equal "volume", subject.resource_name
252
+ end
253
+ end
254
+
255
+ describe "#save" do
256
+ describe "when creating" do
257
+ describe "with mutually exclusive arguments" do
258
+ it "raises Fog::Errors::Error" do
259
+ options = {
260
+ filesystem_type: "ext4",
261
+ image_id: "img-12345"
262
+ }
263
+
264
+ @volume = Fog::Brightbox::Compute::Volume.new({ :service => service }.merge(options))
265
+
266
+ assert_raises Fog::Errors::Error do
267
+ @volume.save
268
+ end
269
+ end
270
+ end
271
+
272
+ describe "with filesytem type" do
273
+ it "sends correct JSON" do
274
+ options = {
275
+ description: "An ext4 volume",
276
+ filesystem_type: "ext4"
277
+ }
278
+
279
+ stub_request(:post, "http://localhost/1.0/volumes").
280
+ with(:query => hash_including(:account_id),
281
+ :headers => { "Authorization" => "Bearer FAKECACHEDTOKEN",
282
+ "Content-Type" => "application/json" },
283
+ :body => hash_including(:filesystem_type => "ext4")).
284
+ to_return(:status => 202,
285
+ :body => %q({"id":"vol-12345","image":{"id":"img-blank"}}),
286
+ :headers => {})
287
+
288
+ @volume = Fog::Brightbox::Compute::Volume.new({ :service => service }.merge(options))
289
+ assert @volume.save
290
+ assert_equal @volume.filesystem_type, "ext4"
291
+ assert_equal @volume.image_id, "img-blank"
292
+ assert_equal @volume.description, "An ext4 volume"
293
+ end
294
+ end
295
+
296
+ describe "with image" do
297
+ it "sends correct JSON" do
298
+ options = {
299
+ image_id: "img-12345",
300
+ name: "My Volume"
301
+ }
302
+
303
+ stub_request(:post, "http://localhost/1.0/volumes").
304
+ with(:query => hash_including(:account_id),
305
+ :headers => { "Authorization" => "Bearer FAKECACHEDTOKEN",
306
+ "Content-Type" => "application/json" },
307
+ :body => hash_including(:image => "img-12345")).
308
+ to_return(:status => 202,
309
+ :body => %q({"id":"vol-12345","image":{"id":"img-12345"}}),
310
+ :headers => {})
311
+
312
+
313
+ @volume = Fog::Brightbox::Compute::Volume.new({ :service => service }.merge(options))
314
+ assert @volume.save
315
+ assert_equal @volume.image_id, "img-12345"
316
+ assert_equal @volume.name, "My Volume"
317
+ end
318
+ end
319
+ end
320
+
321
+ describe "when updating" do
322
+ it do
323
+ subject.id = "vol-12345"
324
+
325
+ assert subject.persisted?
326
+
327
+ subject.delete_with_server = true
328
+ subject.description = "Updated description"
329
+ subject.name = "New name"
330
+ subject.serial = "NewSerial"
331
+
332
+ stub_request(:put, "http://localhost/1.0/volumes/vol-12345").
333
+ with(:query => hash_including(:account_id),
334
+ :headers => { "Authorization" => "Bearer FAKECACHEDTOKEN",
335
+ "Content-Type" => "application/json" },
336
+ :body => hash_including(:delete_with_server => true,
337
+ :description => "Updated description",
338
+ :name => "New name",
339
+ :serial => "NewSerial")).
340
+ to_return(:status => 202,
341
+ :body => %q({"id":"vol-12345"}),
342
+ :headers => {})
343
+
344
+ subject.save
345
+ end
346
+ end
347
+ end
348
+ end
@@ -252,6 +252,29 @@ class Brightbox
252
252
  "inviter" => Brightbox::Compute::Formats::Nested::USER
253
253
  }
254
254
 
255
+ VOLUME = {
256
+ "id" => String,
257
+ "resource_type" => String,
258
+ "url" => String,
259
+ "status" => String,
260
+ "name" => Fog::Nullable::String,
261
+ "delete_with_server" => Fog::Boolean,
262
+ "description" => Fog::Nullable::String,
263
+ "boot" => Fog::Boolean,
264
+ "encrypted" => Fog::Boolean,
265
+ "filesystem_label" => Fog::Nullable::String,
266
+ "filesystem_type" => Fog::Nullable::String,
267
+ "locked" => Fog::Boolean,
268
+ "serial" => String,
269
+ "size" => Integer,
270
+ "source" => Fog::Nullable::String,
271
+ "source_type" => String,
272
+ "storage_type" => String,
273
+ "created_at" => String,
274
+ "updated_at" => String,
275
+ "deleted_at" => Fog::Nullable::String
276
+ }
277
+
255
278
  ZONE = {
256
279
  "id" => String,
257
280
  "resource_type" => String,
@@ -482,6 +505,29 @@ class Brightbox
482
505
  "inviter" => Brightbox::Compute::Formats::Nested::USER
483
506
  }
484
507
 
508
+ VOLUME = {
509
+ "id" => String,
510
+ "resource_type" => String,
511
+ "url" => String,
512
+ "status" => String,
513
+ "name" => Fog::Nullable::String,
514
+ "delete_with_server" => Fog::Boolean,
515
+ "description" => Fog::Nullable::String,
516
+ "boot" => Fog::Boolean,
517
+ "encrypted" => Fog::Boolean,
518
+ "filesystem_label" => Fog::Nullable::String,
519
+ "filesystem_type" => Fog::Nullable::String,
520
+ "locked" => Fog::Boolean,
521
+ "serial" => String,
522
+ "size" => Integer,
523
+ "source" => Fog::Nullable::String,
524
+ "source_type" => String,
525
+ "storage_type" => String,
526
+ "created_at" => String,
527
+ "updated_at" => String,
528
+ "deleted_at" => Fog::Nullable::String
529
+ }
530
+
485
531
  ZONE = {
486
532
  "id" => String,
487
533
  "resource_type" => String,
@@ -706,6 +752,7 @@ class Brightbox
706
752
  "snapshots" => [Brightbox::Compute::Formats::Nested::IMAGE],
707
753
  "server_groups" => [Brightbox::Compute::Formats::Nested::SERVER_GROUP],
708
754
  "interfaces" => [Brightbox::Compute::Formats::Nested::INTERFACE],
755
+ "volumes" => [Brightbox::Compute::Formats::Nested::VOLUME],
709
756
  "zone" => Fog::Brightbox::Nullable::Zone,
710
757
  "licence_name" => Fog::Nullable::String,
711
758
  "username" => Fog::Nullable::String,
@@ -763,6 +810,32 @@ class Brightbox
763
810
  "inviter" => Brightbox::Compute::Formats::Nested::USER
764
811
  }
765
812
 
813
+ VOLUME = {
814
+ "id" => String,
815
+ "resource_type" => String,
816
+ "url" => String,
817
+ "status" => String,
818
+ "name" => Fog::Nullable::String,
819
+ "delete_with_server" => Fog::Boolean,
820
+ "description" => Fog::Nullable::String,
821
+ "boot" => Fog::Boolean,
822
+ "encrypted" => Fog::Boolean,
823
+ "filesystem_label" => Fog::Nullable::String,
824
+ "filesystem_type" => Fog::Nullable::String,
825
+ "locked" => Fog::Boolean,
826
+ "serial" => String,
827
+ "size" => Integer,
828
+ "source" => Fog::Nullable::String,
829
+ "source_type" => String,
830
+ "storage_type" => String,
831
+ "created_at" => String,
832
+ "updated_at" => String,
833
+ "deleted_at" => Fog::Nullable::String,
834
+ "account" => Brightbox::Compute::Formats::Nested::ACCOUNT,
835
+ "image" => Fog::Brightbox::Nullable::Image,
836
+ "server" => Fog::Brightbox::Nullable::Server
837
+ }
838
+
766
839
  ZONE = {
767
840
  "id" => String,
768
841
  "resource_type" => String,
@@ -787,6 +860,7 @@ class Brightbox
787
860
  SERVER_GROUPS = [Brightbox::Compute::Formats::Collected::SERVER_GROUP]
788
861
  SERVER_TYPES = [Brightbox::Compute::Formats::Collected::SERVER_TYPE]
789
862
  USERS = [Brightbox::Compute::Formats::Collected::USER]
863
+ VOLUMES = [Brightbox::Compute::Formats::Collected::VOLUME]
790
864
  ZONES = [Brightbox::Compute::Formats::Collected::ZONE]
791
865
  end
792
866
  end
@@ -0,0 +1,57 @@
1
+ Shindo.tests("Fog::Compute[:brightbox] | volume requests", ["brightbox"]) do
2
+ pending if Fog.mocking?
3
+ image_id = Brightbox::Compute::TestSupport.image_id
4
+
5
+ tests("success") do
6
+ create_options = { image: image_id }
7
+
8
+ tests("#create_volume(#{create_options.inspect})") do
9
+ result = Fog::Compute[:brightbox].create_volume(create_options)
10
+ @volume_id = result["id"]
11
+ data_matches_schema(Brightbox::Compute::Formats::Full::VOLUME, :allow_extra_keys => true) { result }
12
+ end
13
+
14
+ tests("#list_volumes") do
15
+ result = Fog::Compute[:brightbox].list_volumes
16
+ data_matches_schema(Brightbox::Compute::Formats::Collection::VOLUMES, :allow_extra_keys => true) { result }
17
+
18
+ test("#{@volume_id} is listed") do
19
+ result.any? do |volume|
20
+ volume["id"] == @volume_id
21
+ end
22
+ end
23
+ end
24
+
25
+ tests("#get_volume('#{@volume_id}')") do
26
+ result = Fog::Compute[:brightbox].get_volume(@volume_id)
27
+ data_matches_schema(Brightbox::Compute::Formats::Full::VOLUME, :allow_extra_keys => true) { result }
28
+ end
29
+
30
+ update_options = {
31
+ name: "New name"
32
+ }
33
+ tests("#update_volume('#{@volume_id}', ...)") do
34
+ result = Fog::Compute[:brightbox].update_volume(@volume_id, update_options)
35
+ data_matches_schema(Brightbox::Compute::Formats::Full::VOLUME, :allow_extra_keys => true) { result }
36
+
37
+ test("name has updated") { result["name"] == "New name" }
38
+ end
39
+
40
+ Fog::Compute[:brightbox].volumes.get(@volume_id).wait_for { ready? }
41
+
42
+ tests("#delete_volume('#{@volume_id}')") do
43
+ result = Fog::Compute[:brightbox].delete_volume(@volume_id)
44
+ data_matches_schema(Brightbox::Compute::Formats::Full::VOLUME, :allow_extra_keys => true) { result }
45
+ end
46
+ end
47
+
48
+ tests("failure") do
49
+ tests("create_volume without options").raises(ArgumentError) do
50
+ Fog::Compute[:brightbox].create_volume
51
+ end
52
+
53
+ tests("get_volume with invalid ID").raises(Excon::Errors::NotFound) do
54
+ Fog::Compute[:brightbox].get_volume("vol-00000")
55
+ end
56
+ end
57
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fog-brightbox
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.2
4
+ version: 1.5.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Thornthwaite
@@ -219,6 +219,8 @@ files:
219
219
  - lib/fog/brightbox/models/compute/user_collaboration.rb
220
220
  - lib/fog/brightbox/models/compute/user_collaborations.rb
221
221
  - lib/fog/brightbox/models/compute/users.rb
222
+ - lib/fog/brightbox/models/compute/volume.rb
223
+ - lib/fog/brightbox/models/compute/volumes.rb
222
224
  - lib/fog/brightbox/models/compute/zone.rb
223
225
  - lib/fog/brightbox/models/compute/zones.rb
224
226
  - lib/fog/brightbox/models/storage/directories.rb
@@ -232,6 +234,8 @@ files:
232
234
  - lib/fog/brightbox/requests/compute/add_nodes_load_balancer.rb
233
235
  - lib/fog/brightbox/requests/compute/add_servers_server_group.rb
234
236
  - lib/fog/brightbox/requests/compute/apply_to_firewall_policy.rb
237
+ - lib/fog/brightbox/requests/compute/attach_volume.rb
238
+ - lib/fog/brightbox/requests/compute/copy_volume.rb
235
239
  - lib/fog/brightbox/requests/compute/create_api_client.rb
236
240
  - lib/fog/brightbox/requests/compute/create_application.rb
237
241
  - lib/fog/brightbox/requests/compute/create_cloud_ip.rb
@@ -243,6 +247,7 @@ files:
243
247
  - lib/fog/brightbox/requests/compute/create_load_balancer.rb
244
248
  - lib/fog/brightbox/requests/compute/create_server.rb
245
249
  - lib/fog/brightbox/requests/compute/create_server_group.rb
250
+ - lib/fog/brightbox/requests/compute/create_volume.rb
246
251
  - lib/fog/brightbox/requests/compute/delete_api_client.rb
247
252
  - lib/fog/brightbox/requests/compute/delete_application.rb
248
253
  - lib/fog/brightbox/requests/compute/delete_cloud_ip.rb
@@ -256,6 +261,8 @@ files:
256
261
  - lib/fog/brightbox/requests/compute/delete_server.rb
257
262
  - lib/fog/brightbox/requests/compute/delete_server_group.rb
258
263
  - lib/fog/brightbox/requests/compute/delete_user_collaboration.rb
264
+ - lib/fog/brightbox/requests/compute/delete_volume.rb
265
+ - lib/fog/brightbox/requests/compute/detach_volume.rb
259
266
  - lib/fog/brightbox/requests/compute/get_account.rb
260
267
  - lib/fog/brightbox/requests/compute/get_api_client.rb
261
268
  - lib/fog/brightbox/requests/compute/get_application.rb
@@ -276,6 +283,7 @@ files:
276
283
  - lib/fog/brightbox/requests/compute/get_server_type.rb
277
284
  - lib/fog/brightbox/requests/compute/get_user.rb
278
285
  - lib/fog/brightbox/requests/compute/get_user_collaboration.rb
286
+ - lib/fog/brightbox/requests/compute/get_volume.rb
279
287
  - lib/fog/brightbox/requests/compute/get_zone.rb
280
288
  - lib/fog/brightbox/requests/compute/list_accounts.rb
281
289
  - lib/fog/brightbox/requests/compute/list_api_clients.rb
@@ -294,12 +302,14 @@ files:
294
302
  - lib/fog/brightbox/requests/compute/list_servers.rb
295
303
  - lib/fog/brightbox/requests/compute/list_user_collaborations.rb
296
304
  - lib/fog/brightbox/requests/compute/list_users.rb
305
+ - lib/fog/brightbox/requests/compute/list_volumes.rb
297
306
  - lib/fog/brightbox/requests/compute/list_zones.rb
298
307
  - lib/fog/brightbox/requests/compute/lock_resource_database_server.rb
299
308
  - lib/fog/brightbox/requests/compute/lock_resource_database_snapshot.rb
300
309
  - lib/fog/brightbox/requests/compute/lock_resource_image.rb
301
310
  - lib/fog/brightbox/requests/compute/lock_resource_load_balancer.rb
302
311
  - lib/fog/brightbox/requests/compute/lock_resource_server.rb
312
+ - lib/fog/brightbox/requests/compute/lock_resource_volume.rb
303
313
  - lib/fog/brightbox/requests/compute/map_cloud_ip.rb
304
314
  - lib/fog/brightbox/requests/compute/move_servers_server_group.rb
305
315
  - lib/fog/brightbox/requests/compute/reboot_server.rb
@@ -315,6 +325,7 @@ files:
315
325
  - lib/fog/brightbox/requests/compute/reset_secret_api_client.rb
316
326
  - lib/fog/brightbox/requests/compute/reset_secret_application.rb
317
327
  - lib/fog/brightbox/requests/compute/reset_server.rb
328
+ - lib/fog/brightbox/requests/compute/resize_volume.rb
318
329
  - lib/fog/brightbox/requests/compute/shutdown_server.rb
319
330
  - lib/fog/brightbox/requests/compute/snapshot_database_server.rb
320
331
  - lib/fog/brightbox/requests/compute/snapshot_server.rb
@@ -325,6 +336,7 @@ files:
325
336
  - lib/fog/brightbox/requests/compute/unlock_resource_image.rb
326
337
  - lib/fog/brightbox/requests/compute/unlock_resource_load_balancer.rb
327
338
  - lib/fog/brightbox/requests/compute/unlock_resource_server.rb
339
+ - lib/fog/brightbox/requests/compute/unlock_resource_volume.rb
328
340
  - lib/fog/brightbox/requests/compute/unmap_cloud_ip.rb
329
341
  - lib/fog/brightbox/requests/compute/update_account.rb
330
342
  - lib/fog/brightbox/requests/compute/update_api_client.rb
@@ -340,6 +352,7 @@ files:
340
352
  - lib/fog/brightbox/requests/compute/update_server.rb
341
353
  - lib/fog/brightbox/requests/compute/update_server_group.rb
342
354
  - lib/fog/brightbox/requests/compute/update_user.rb
355
+ - lib/fog/brightbox/requests/compute/update_volume.rb
343
356
  - lib/fog/brightbox/requests/storage/copy_object.rb
344
357
  - lib/fog/brightbox/requests/storage/delete_container.rb
345
358
  - lib/fog/brightbox/requests/storage/delete_multiple_objects.rb
@@ -398,6 +411,7 @@ files:
398
411
  - spec/fog/compute/brightbox/server_spec.rb
399
412
  - spec/fog/compute/brightbox/user_collaboration_spec.rb
400
413
  - spec/fog/compute/brightbox/user_spec.rb
414
+ - spec/fog/compute/brightbox/volume_spec.rb
401
415
  - spec/fog/compute/brightbox/zone_spec.rb
402
416
  - spec/fog/compute/brightbox_spec.rb
403
417
  - spec/fog/storage/brightbox_spec.rb
@@ -434,6 +448,7 @@ files:
434
448
  - tests/brightbox/requests/compute/server_type_tests.rb
435
449
  - tests/brightbox/requests/compute/user_collaboration_tests.rb
436
450
  - tests/brightbox/requests/compute/user_tests.rb
451
+ - tests/brightbox/requests/compute/volume_tests.rb
437
452
  - tests/brightbox/requests/compute/zone_tests.rb
438
453
  - tests/helper.rb
439
454
  - tests/helpers/collection_helper.rb
@@ -462,9 +477,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
462
477
  version: '2.0'
463
478
  required_rubygems_version: !ruby/object:Gem::Requirement
464
479
  requirements:
465
- - - ">="
480
+ - - ">"
466
481
  - !ruby/object:Gem::Version
467
- version: '0'
482
+ version: 1.3.1
468
483
  requirements: []
469
484
  rubygems_version: 3.0.6
470
485
  signing_key:
@@ -503,6 +518,7 @@ test_files:
503
518
  - spec/fog/compute/brightbox/server_spec.rb
504
519
  - spec/fog/compute/brightbox/user_collaboration_spec.rb
505
520
  - spec/fog/compute/brightbox/user_spec.rb
521
+ - spec/fog/compute/brightbox/volume_spec.rb
506
522
  - spec/fog/compute/brightbox/zone_spec.rb
507
523
  - spec/fog/compute/brightbox_spec.rb
508
524
  - spec/fog/storage/brightbox_spec.rb