fog-brightbox 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/lib/fog/brightbox.rb +1 -0
  4. data/lib/fog/brightbox/config.rb +102 -2
  5. data/lib/fog/brightbox/core.rb +1 -0
  6. data/lib/fog/brightbox/models/compute/api_client.rb +3 -1
  7. data/lib/fog/brightbox/models/storage/directories.rb +45 -0
  8. data/lib/fog/brightbox/models/storage/directory.rb +53 -0
  9. data/lib/fog/brightbox/models/storage/file.rb +166 -0
  10. data/lib/fog/brightbox/models/storage/files.rb +104 -0
  11. data/lib/fog/brightbox/oauth2.rb +140 -136
  12. data/lib/fog/brightbox/requests/storage/copy_object.rb +27 -0
  13. data/lib/fog/brightbox/requests/storage/delete_container.rb +22 -0
  14. data/lib/fog/brightbox/requests/storage/delete_multiple_objects.rb +67 -0
  15. data/lib/fog/brightbox/requests/storage/delete_object.rb +23 -0
  16. data/lib/fog/brightbox/requests/storage/delete_static_large_object.rb +43 -0
  17. data/lib/fog/brightbox/requests/storage/get_container.rb +44 -0
  18. data/lib/fog/brightbox/requests/storage/get_containers.rb +33 -0
  19. data/lib/fog/brightbox/requests/storage/get_object.rb +29 -0
  20. data/lib/fog/brightbox/requests/storage/get_object_http_url.rb +21 -0
  21. data/lib/fog/brightbox/requests/storage/get_object_https_url.rb +85 -0
  22. data/lib/fog/brightbox/requests/storage/head_container.rb +28 -0
  23. data/lib/fog/brightbox/requests/storage/head_containers.rb +25 -0
  24. data/lib/fog/brightbox/requests/storage/head_object.rb +23 -0
  25. data/lib/fog/brightbox/requests/storage/post_set_meta_temp_url_key.rb +37 -0
  26. data/lib/fog/brightbox/requests/storage/put_container.rb +27 -0
  27. data/lib/fog/brightbox/requests/storage/put_dynamic_obj_manifest.rb +43 -0
  28. data/lib/fog/brightbox/requests/storage/put_object.rb +42 -0
  29. data/lib/fog/brightbox/requests/storage/put_object_manifest.rb +16 -0
  30. data/lib/fog/brightbox/requests/storage/put_static_obj_manifest.rb +57 -0
  31. data/lib/fog/brightbox/storage.rb +166 -0
  32. data/lib/fog/brightbox/storage/authentication_request.rb +52 -0
  33. data/lib/fog/brightbox/storage/config.rb +23 -0
  34. data/lib/fog/brightbox/storage/connection.rb +83 -0
  35. data/lib/fog/brightbox/storage/errors.rb +11 -0
  36. data/lib/fog/brightbox/version.rb +1 -1
  37. data/spec/fog/brightbox/config_spec.rb +62 -1
  38. data/spec/fog/brightbox/storage/authentication_request_spec.rb +77 -0
  39. data/spec/fog/brightbox/storage/config_spec.rb +40 -0
  40. data/spec/fog/brightbox/storage/connection_errors_spec.rb +54 -0
  41. data/spec/fog/brightbox/storage/connection_spec.rb +120 -0
  42. data/spec/fog/storage/brightbox_spec.rb +290 -0
  43. metadata +40 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9c828f450aae49fe5ef940159c7cdaee50804594
4
- data.tar.gz: 6ab4e5663ebb90199b0e01b8d38cf117479c4d27
3
+ metadata.gz: 885f9a5d7a53d8239ab311b2a6fb621b147bfd82
4
+ data.tar.gz: 9bd4bb8e36fc2ee1ff504dec8f795ccf0f0aa6d8
5
5
  SHA512:
6
- metadata.gz: d7ba85e84d50f9689c9262836196c02629e470613d26cbd403c0319f16cc513bc09d06ca8d7f0e4762cbe2dec4f0dc4212058bb9289e35702c3d27a20e480381
7
- data.tar.gz: 19d9f5dfac3c1825c9bc21749a1baf5ff68c4f0b87a3a210c519dd90837c2e0fcf19a008a6c037ed4ebf106cbbf4d9543873d798abf2a3b29f124a17b1849e9b
6
+ metadata.gz: 0a87b352d2167daedb10f233d6f941c0923b4b0d10d371f5387d283ffd18e4ee7987e3fcfd27350f375331879ee883a4911b85e9f6a32c0b9180567f4e66e614
7
+ data.tar.gz: 8e3758fa7350541363f744096379c0c065ead22f479c911a945ae56d27ed81c0b3676ac3cd3ee8f0d39b27b7c3eceb054ac6103b1feaadf5a1b5b82213547867
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ### 0.4.0 / 2014-08-28
2
+
3
+ Enhancements:
4
+
5
+ * Add Add support for Brightbox Orbit cloud storage service. This adds a
6
+ `storage` service to the Brightbox provider using the standard `fog`
7
+ interfaces.
8
+
1
9
  ### 0.3.0 / 2014-08-12
2
10
 
3
11
  Enhancements:
data/lib/fog/brightbox.rb CHANGED
@@ -1 +1,2 @@
1
1
  require 'fog/brightbox/compute'
2
+ require 'fog/brightbox/storage'
@@ -1,3 +1,5 @@
1
+ require "fog/brightbox/oauth2"
2
+
1
3
  module Fog
2
4
  module Brightbox
3
5
  # The {Fog::Brightbox::Config} class is designed to encapsulate a group of settings for reuse
@@ -49,6 +51,21 @@ module Fog
49
51
  @options = options
50
52
  end
51
53
 
54
+ # @return [OAuth2::CredentialSet]
55
+ def credentials
56
+ @credentials ||= OAuth2::CredentialSet.new(client_id, client_secret, {
57
+ :username => username,
58
+ :password => password,
59
+ :access_token => cached_access_token,
60
+ :refresh_token => cached_refresh_token
61
+ })
62
+ end
63
+
64
+ # @return [Boolean]
65
+ def user_credentials?
66
+ credentials.user_details?
67
+ end
68
+
52
69
  # Can this be used to configure services? Yes, yes it can.
53
70
  #
54
71
  # @return [true]
@@ -71,7 +88,24 @@ module Fog
71
88
  end
72
89
  alias_method :api_url, :compute_url
73
90
 
74
- # @return [String] The configured identifier of the API client or user application.
91
+ def storage_url
92
+ URI.parse(@options[:brightbox_storage_url] || "https://files.gb1.brightbox.com")
93
+ end
94
+
95
+ def storage_management_url
96
+ @storage_management_url ||= if @options.key?(:brightbox_storage_management_url)
97
+ URI.parse(@options[:brightbox_storage_management_url])
98
+ else
99
+ nil
100
+ end
101
+ end
102
+
103
+ # @param [URI] management_url The URI to use for management requests.
104
+ def storage_management_url=(management_url)
105
+ @storage_management_url = management_url
106
+ end
107
+
108
+ # @return [String] The configured identifier of the API client or user application.
75
109
  def client_id
76
110
  @options[:brightbox_client_id]
77
111
  end
@@ -93,7 +127,21 @@ module Fog
93
127
 
94
128
  # @return [String] The configured account identifier to scope API requests by.
95
129
  def account
96
- @options[:brightbox_account]
130
+ @current_account ||= @options[:brightbox_account]
131
+ end
132
+
133
+ # This changes the scoped account from the originally configured one to another.
134
+ #
135
+ # @return [String] The new account identifier used to scope API requests by.
136
+ def change_account(new_account)
137
+ @current_account = new_account
138
+ end
139
+
140
+ # Sets the scoped account back to originally configured one.
141
+ #
142
+ # @return [String] The configured account identifier to scope API requests by.
143
+ def reset_account
144
+ @current_account = @options[:brightbox_account]
97
145
  end
98
146
 
99
147
  def connection_options
@@ -109,10 +157,34 @@ module Fog
109
157
  @options[:brightbox_access_token]
110
158
  end
111
159
 
160
+ def latest_access_token
161
+ credentials.access_token
162
+ end
163
+
112
164
  def cached_refresh_token
113
165
  @options[:brightbox_refresh_token]
114
166
  end
115
167
 
168
+ # This is the current, most up to date refresh token.
169
+ def latest_refresh_token
170
+ credentials.refresh_token
171
+ end
172
+
173
+ def must_authenticate?
174
+ !credentials.access_token?
175
+ end
176
+
177
+ # Allows classes sharing to mark the tokens as invalid in response to API status codes.
178
+ def expire_tokens!
179
+ update_tokens(nil)
180
+ end
181
+
182
+ # @param [String] access_token The new access token to use
183
+ # @param [String] refresh_token The new refresh token to use
184
+ def update_tokens(access_token, refresh_token = nil, expires_in = nil)
185
+ credentials.update_tokens(access_token, refresh_token, expires_in)
186
+ end
187
+
116
188
  def managed_tokens?
117
189
  @options.fetch(:brightbox_token_management, true)
118
190
  end
@@ -120,6 +192,34 @@ module Fog
120
192
  def default_image_id
121
193
  @options.fetch(:brightbox_default_image, nil)
122
194
  end
195
+
196
+ def latest_token
197
+ @options[:brightbox_access_token]
198
+ end
199
+
200
+ def service_type
201
+ @options[:brightbox_service_type] || "object-store"
202
+ end
203
+
204
+ def service_name
205
+ @options[:brightbox_service_name]
206
+ end
207
+
208
+ def region
209
+ @options[:brightbox_region]
210
+ end
211
+
212
+ def tenant
213
+ @options[:brightbox_tenant]
214
+ end
215
+
216
+ def storage_connection_options
217
+ @options[:connection_options] || {}
218
+ end
219
+
220
+ def storage_temp_key
221
+ @options[:brightbox_temp_url_key]
222
+ end
123
223
  end
124
224
  end
125
225
  end
@@ -7,5 +7,6 @@ module Fog
7
7
  extend Fog::Provider
8
8
 
9
9
  service(:compute, 'Compute')
10
+ service(:storage, 'Storage')
10
11
  end
11
12
  end
@@ -9,13 +9,15 @@ module Fog
9
9
  attribute :description
10
10
  attribute :secret
11
11
  attribute :revoked_at, :type => :time
12
+ attribute :permissions_group
12
13
  attribute :account_id
13
14
 
14
15
  def save
15
16
  raise Fog::Errors::Error.new('Resaving an existing object may create a duplicate') if persisted?
16
17
  options = {
17
18
  :name => name,
18
- :description => description
19
+ :description => description,
20
+ :permissions_group => permissions_group
19
21
  }.delete_if { |k, v| v.nil? || v == "" }
20
22
  data = service.create_api_client(options)
21
23
  merge_attributes(data)
@@ -0,0 +1,45 @@
1
+ require 'fog/core/collection'
2
+ require 'fog/brightbox/models/storage/directory'
3
+
4
+ module Fog
5
+ module Storage
6
+ class Brightbox
7
+
8
+ class Directories < Fog::Collection
9
+
10
+ model Fog::Storage::Brightbox::Directory
11
+
12
+ HEADER_ATTRIBUTES = [
13
+ 'X-Container-Bytes-Used', 'X-Container-Object-Count', 'X-Container-Read',
14
+ 'X-Container-Write'
15
+ ]
16
+
17
+ def all
18
+ data = service.get_containers.body
19
+ load(data)
20
+ end
21
+
22
+ def get(key, options = {})
23
+ data = service.get_container(key, options)
24
+ directory = new(:key => key)
25
+ for key, value in data.headers
26
+ if HEADER_ATTRIBUTES.include?(key)
27
+ directory.merge_attributes(key => value)
28
+ end
29
+ end
30
+ directory.files.merge_attributes(options)
31
+ directory.files.instance_variable_set(:@loaded, true)
32
+
33
+ data.body.each do |file|
34
+ directory.files << directory.files.new(file)
35
+ end
36
+ directory
37
+ rescue Fog::Storage::Brightbox::NotFound
38
+ nil
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,53 @@
1
+ require "fog/core/model"
2
+ require "fog/brightbox/models/storage/files"
3
+
4
+ module Fog
5
+ module Storage
6
+ class Brightbox
7
+ class Directory < Fog::Model
8
+ identity :key, :aliases => "name"
9
+
10
+ attribute :bytes, :aliases => "X-Container-Bytes-Used"
11
+ attribute :count, :aliases => "X-Container-Object-Count"
12
+ attribute :read_permissions, :aliases => "X-Container-Read"
13
+ attribute :write_permissions, :aliases => "X-Container-Write"
14
+
15
+ def destroy
16
+ requires :key
17
+ service.delete_container(key)
18
+ true
19
+ rescue Excon::Errors::NotFound
20
+ false
21
+ end
22
+
23
+ def files
24
+ @files ||= begin
25
+ Fog::Storage::Brightbox::Files.new(
26
+ :directory => self,
27
+ :service => service
28
+ )
29
+ end
30
+ end
31
+
32
+ def public=(new_public)
33
+ @public = new_public
34
+ end
35
+
36
+ def public_url
37
+ #raise NotImplementedError
38
+ ""
39
+ end
40
+
41
+ def save
42
+ requires :key
43
+ options = {
44
+ 'read_permissions' => read_permissions,
45
+ 'write_permissions' => write_permissions
46
+ }
47
+ service.put_container(key, options)
48
+ true
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,166 @@
1
+ require 'fog/core/model'
2
+
3
+ module Fog
4
+ module Storage
5
+ class Brightbox
6
+
7
+ class File < Fog::Model
8
+
9
+ identity :key, :aliases => 'name'
10
+
11
+ attribute :content_length, :aliases => ['bytes', 'Content-Length'], :type => :integer
12
+ attribute :content_type, :aliases => ['content_type', 'Content-Type']
13
+ attribute :content_disposition, :aliases => ['content_disposition', 'Content-Disposition']
14
+ attribute :etag, :aliases => ['hash', 'Etag']
15
+ attribute :last_modified, :aliases => ['last_modified', 'Last-Modified'], :type => :time
16
+ attribute :access_control_allow_origin, :aliases => ['Access-Control-Allow-Origin']
17
+ attribute :origin, :aliases => ['Origin']
18
+
19
+ def body
20
+ attributes[:body] ||= if last_modified
21
+ collection.get(identity).body
22
+ else
23
+ ''
24
+ end
25
+ end
26
+
27
+ def body=(new_body)
28
+ attributes[:body] = new_body
29
+ end
30
+
31
+ def directory
32
+ @directory
33
+ end
34
+
35
+ def copy(target_directory_key, target_file_key, options={})
36
+ requires :directory, :key
37
+ options['Content-Type'] ||= content_type if content_type
38
+ options['Access-Control-Allow-Origin'] ||= access_control_allow_origin if access_control_allow_origin
39
+ options['Origin'] ||= origin if origin
40
+ service.copy_object(directory.key, key, target_directory_key, target_file_key, options)
41
+ target_directory = service.directories.new(:key => target_directory_key)
42
+ target_directory.files.get(target_file_key)
43
+ end
44
+
45
+ def destroy
46
+ requires :directory, :key
47
+ service.delete_object(directory.key, key)
48
+ true
49
+ end
50
+
51
+ def metadata
52
+ @metadata ||= headers_to_metadata
53
+ end
54
+
55
+ def owner=(new_owner)
56
+ if new_owner
57
+ attributes[:owner] = {
58
+ :display_name => new_owner['DisplayName'],
59
+ :id => new_owner['ID']
60
+ }
61
+ end
62
+ end
63
+
64
+ def public=(new_public)
65
+ new_public
66
+ end
67
+
68
+ # Get a url for file.
69
+ #
70
+ # required attributes: key
71
+ #
72
+ # @param expires [String] number of seconds (since 1970-01-01 00:00) before url expires
73
+ # @param options [Hash]
74
+ # @return [String] url
75
+ #
76
+ def url(expires, options = {})
77
+ requires :directory, :key
78
+ self.service.create_temp_url(directory.key, key, expires, "GET", options)
79
+ end
80
+
81
+ def public_url
82
+ requires :key
83
+ self.collection.get_url(self.key)
84
+ end
85
+
86
+
87
+ def save(options = {})
88
+ requires :body, :directory, :key
89
+ options['Content-Type'] = content_type if content_type
90
+ options['Content-Disposition'] = content_disposition if content_disposition
91
+ options['Access-Control-Allow-Origin'] = access_control_allow_origin if access_control_allow_origin
92
+ options['Origin'] = origin if origin
93
+ options.merge!(metadata_to_headers)
94
+
95
+ data = service.put_object(directory.key, key, body, options)
96
+ update_attributes_from(data)
97
+ refresh_metadata
98
+
99
+ self.content_length = Fog::Storage.get_body_size(body)
100
+ self.content_type ||= Fog::Storage.get_content_type(body)
101
+ true
102
+ end
103
+
104
+ private
105
+
106
+ def directory=(new_directory)
107
+ @directory = new_directory
108
+ end
109
+
110
+ def refresh_metadata
111
+ metadata.reject! {|k, v| v.nil? }
112
+ end
113
+
114
+ def headers_to_metadata
115
+ key_map = key_mapping
116
+ Hash[metadata_attributes.map {|k, v| [key_map[k], v] }]
117
+ end
118
+
119
+ def key_mapping
120
+ key_map = metadata_attributes
121
+ key_map.each_pair {|k, v| key_map[k] = header_to_key(k)}
122
+ end
123
+
124
+ def header_to_key(opt)
125
+ opt.gsub(metadata_prefix, '').split('-').map {|k| k[0, 1].downcase + k[1..-1]}.join('_').to_sym
126
+ end
127
+
128
+ def metadata_to_headers
129
+ header_map = header_mapping
130
+ Hash[metadata.map {|k, v| [header_map[k], v] }]
131
+ end
132
+
133
+ def header_mapping
134
+ header_map = metadata.dup
135
+ header_map.each_pair {|k, v| header_map[k] = key_to_header(k)}
136
+ end
137
+
138
+ def key_to_header(key)
139
+ metadata_prefix + key.to_s.split(/[-_]/).map(&:capitalize).join('-')
140
+ end
141
+
142
+ def metadata_attributes
143
+ if last_modified
144
+ headers = service.head_object(directory.key, self.key).headers
145
+ headers.reject! {|k, v| !metadata_attribute?(k)}
146
+ else
147
+ {}
148
+ end
149
+ end
150
+
151
+ def metadata_attribute?(key)
152
+ key.to_s =~ /^#{metadata_prefix}/
153
+ end
154
+
155
+ def metadata_prefix
156
+ "X-Object-Meta-"
157
+ end
158
+
159
+ def update_attributes_from(data)
160
+ merge_attributes(data.headers.reject {|key, value| ['Content-Length', 'Content-Type'].include?(key)})
161
+ end
162
+ end
163
+
164
+ end
165
+ end
166
+ end