fog-brightbox 0.3.0 → 0.4.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 (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
@@ -0,0 +1,104 @@
1
+ require 'fog/core/collection'
2
+ require 'fog/brightbox/models/storage/file'
3
+
4
+ module Fog
5
+ module Storage
6
+ class Brightbox
7
+
8
+ class Files < Fog::Collection
9
+
10
+ attribute :directory
11
+ attribute :limit
12
+ attribute :marker
13
+ attribute :path
14
+ attribute :prefix
15
+
16
+ model Fog::Storage::Brightbox::File
17
+
18
+ def all(options = {})
19
+ requires :directory
20
+ options = {
21
+ 'limit' => limit,
22
+ 'marker' => marker,
23
+ 'path' => path,
24
+ 'prefix' => prefix
25
+ }.merge!(options)
26
+ merge_attributes(options)
27
+ parent = directory.collection.get(
28
+ directory.key,
29
+ options
30
+ )
31
+ if parent
32
+ load(parent.files.map {|file| file.attributes})
33
+ else
34
+ nil
35
+ end
36
+ end
37
+
38
+ alias :each_file_this_page :each
39
+ def each
40
+ if !block_given?
41
+ self
42
+ else
43
+ subset = dup.all
44
+
45
+ subset.each_file_this_page {|f| yield f}
46
+ while subset.length == (subset.limit || 10000)
47
+ subset = subset.all(:marker => subset.last.key)
48
+ subset.each_file_this_page {|f| yield f}
49
+ end
50
+
51
+ self
52
+ end
53
+ end
54
+
55
+ def get(key, &block)
56
+ requires :directory
57
+ data = service.get_object(directory.key, key, &block)
58
+ file_data = data.headers.merge({
59
+ :body => data.body,
60
+ :key => key
61
+ })
62
+ new(file_data)
63
+ rescue Fog::Storage::Brightbox::NotFound
64
+ nil
65
+ end
66
+
67
+ def get_url(key)
68
+ requires :directory
69
+ if self.directory.public_url
70
+ "#{self.directory.public_url}/#{Fog::Storage::Brightbox.escape(key, '/')}"
71
+ end
72
+ end
73
+
74
+ def get_http_url(key, expires, options = {})
75
+ requires :directory
76
+ service.get_object_http_url(directory.key, key, expires, options)
77
+ end
78
+
79
+ def get_https_url(key, expires, options = {})
80
+ requires :directory
81
+ service.get_object_https_url(directory.key, key, expires, options)
82
+ end
83
+
84
+ def head(key, options = {})
85
+ requires :directory
86
+ data = service.head_object(directory.key, key)
87
+ file_data = data.headers.merge({
88
+ :key => key
89
+ })
90
+ new(file_data)
91
+ rescue Fog::Storage::Brightbox::NotFound
92
+ nil
93
+ end
94
+
95
+ def new(attributes = {})
96
+ requires :directory
97
+ super({ :directory => directory }.merge!(attributes))
98
+ end
99
+
100
+ end
101
+
102
+ end
103
+ end
104
+ end
@@ -3,164 +3,168 @@
3
3
  #
4
4
  # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-10
5
5
  #
6
- module Fog::Brightbox::OAuth2
7
-
8
- # This builds the simplest form of requesting an access token
9
- # based on the arguments passed in
10
- #
11
- # @param [Fog::Core::Connection] connection
12
- # @param [CredentialSet] credentials
13
- #
14
- # @return [Excon::Response]
15
- def request_access_token(connection, credentials)
16
- token_strategy = credentials.best_grant_strategy
17
-
18
- header_content = "#{credentials.client_id}:#{credentials.client_secret}"
19
- encoded_credentials = Base64.encode64(header_content).chomp
20
-
21
- connection.request(
22
- :path => "/token",
23
- :expects => 200,
24
- :headers => {
25
- 'Authorization' => "Basic #{encoded_credentials}",
26
- 'Content-Type' => 'application/json'
27
- },
28
- :method => 'POST',
29
- :body => Fog::JSON.encode(token_strategy.authorization_body_data)
30
- )
31
- end
6
+ module Fog
7
+ module Brightbox
8
+ module OAuth2
32
9
 
33
- # Encapsulates credentials required to request access tokens from the
34
- # Brightbox authorisation servers
35
- #
36
- # @todo Interface to update certain credentials (after password change)
37
- #
38
- class CredentialSet
39
- attr_reader :client_id, :client_secret, :username, :password
40
- attr_reader :access_token, :refresh_token, :expires_in
10
+ # This builds the simplest form of requesting an access token
11
+ # based on the arguments passed in
41
12
  #
42
- # @param [String] client_id
43
- # @param [String] client_secret
44
- # @param [Hash] options
45
- # @option options [String] :username
46
- # @option options [String] :password
13
+ # @param [Fog::Core::Connection] connection
14
+ # @param [CredentialSet] credentials
47
15
  #
48
- def initialize(client_id, client_secret, options = {})
49
- @client_id = client_id
50
- @client_secret = client_secret
51
- @username = options[:username]
52
- @password = options[:password]
53
- @access_token = options[:access_token]
54
- @refresh_token = options[:refresh_token]
55
- @expires_in = options[:expires_in]
16
+ # @return [Excon::Response]
17
+ def request_access_token(connection, credentials)
18
+ token_strategy = credentials.best_grant_strategy
19
+
20
+ header_content = "#{credentials.client_id}:#{credentials.client_secret}"
21
+ encoded_credentials = Base64.encode64(header_content).chomp
22
+
23
+ connection.request(
24
+ :path => "/token",
25
+ :expects => 200,
26
+ :headers => {
27
+ 'Authorization' => "Basic #{encoded_credentials}",
28
+ 'Content-Type' => 'application/json'
29
+ },
30
+ :method => 'POST',
31
+ :body => Fog::JSON.encode(token_strategy.authorization_body_data)
32
+ )
56
33
  end
57
34
 
58
- # Returns true if user details are available
59
- # @return [Boolean]
60
- def user_details?
61
- !!(@username && @password)
62
- end
35
+ # Encapsulates credentials required to request access tokens from the
36
+ # Brightbox authorisation servers
37
+ #
38
+ # @todo Interface to update certain credentials (after password change)
39
+ #
40
+ class CredentialSet
41
+ attr_reader :client_id, :client_secret, :username, :password
42
+ attr_reader :access_token, :refresh_token, :expires_in
43
+ #
44
+ # @param [String] client_id
45
+ # @param [String] client_secret
46
+ # @param [Hash] options
47
+ # @option options [String] :username
48
+ # @option options [String] :password
49
+ #
50
+ def initialize(client_id, client_secret, options = {})
51
+ @client_id = client_id
52
+ @client_secret = client_secret
53
+ @username = options[:username]
54
+ @password = options[:password]
55
+ @access_token = options[:access_token]
56
+ @refresh_token = options[:refresh_token]
57
+ @expires_in = options[:expires_in]
58
+ end
63
59
 
64
- # Is an access token available for these credentials?
65
- def access_token?
66
- !!@access_token
67
- end
60
+ # Returns true if user details are available
61
+ # @return [Boolean]
62
+ def user_details?
63
+ !!(@username && @password)
64
+ end
68
65
 
69
- # Is a refresh token available for these credentials?
70
- def refresh_token?
71
- !!@refresh_token
72
- end
66
+ # Is an access token available for these credentials?
67
+ def access_token?
68
+ !!@access_token
69
+ end
73
70
 
74
- # Updates the credentials with newer tokens
75
- def update_tokens(access_token, refresh_token = nil, expires_in = nil)
76
- @access_token = access_token
77
- @refresh_token = refresh_token
78
- @expires_in = expires_in
71
+ # Is a refresh token available for these credentials?
72
+ def refresh_token?
73
+ !!@refresh_token
74
+ end
75
+
76
+ # Updates the credentials with newer tokens
77
+ def update_tokens(access_token, refresh_token = nil, expires_in = nil)
78
+ @access_token = access_token
79
+ @refresh_token = refresh_token
80
+ @expires_in = expires_in
81
+ end
82
+
83
+ # Based on available credentials returns the best strategy
84
+ #
85
+ # @todo Add a means to dictate which should or shouldn't be used
86
+ #
87
+ def best_grant_strategy
88
+ if refresh_token?
89
+ RefreshTokenStrategy.new(self)
90
+ elsif user_details?
91
+ UserCredentialsStrategy.new(self)
92
+ else
93
+ ClientCredentialsStrategy.new(self)
94
+ end
95
+ end
79
96
  end
80
97
 
81
- # Based on available credentials returns the best strategy
98
+ # This strategy class is the basis for OAuth2 grant types
99
+ #
100
+ # @abstract Need to implement {#authorization_body_data} to return a
101
+ # Hash matching the expected parameter form for the OAuth request
82
102
  #
83
- # @todo Add a means to dictate which should or shouldn't be used
103
+ # @todo Strategies should be able to validate if credentials are suitable
104
+ # so just client credentials cannot be used with user strategies
84
105
  #
85
- def best_grant_strategy
86
- if refresh_token?
87
- RefreshTokenStrategy.new(self)
88
- elsif user_details?
89
- UserCredentialsStrategy.new(self)
90
- else
91
- ClientCredentialsStrategy.new(self)
106
+ class GrantTypeStrategy
107
+ def initialize(credentials)
108
+ @credentials = credentials
92
109
  end
93
- end
94
- end
95
110
 
96
- # This strategy class is the basis for OAuth2 grant types
97
- #
98
- # @abstract Need to implement {#authorization_body_data} to return a
99
- # Hash matching the expected parameter form for the OAuth request
100
- #
101
- # @todo Strategies should be able to validate if credentials are suitable
102
- # so just client credentials cannot be used with user strategies
103
- #
104
- class GrantTypeStrategy
105
- def initialize(credentials)
106
- @credentials = credentials
111
+ def authorization_body_data
112
+ raise "Not implemented"
113
+ end
107
114
  end
108
115
 
109
- def authorization_body_data
110
- raise "Not implemented"
116
+ # This implements client based authentication/authorization
117
+ # based on the existing trust relationship using the `none`
118
+ # grant type.
119
+ #
120
+ class ClientCredentialsStrategy < GrantTypeStrategy
121
+ def authorization_body_data
122
+ {
123
+ "grant_type" => "none",
124
+ "client_id" => @credentials.client_id
125
+ }
126
+ end
111
127
  end
112
- end
113
128
 
114
- # This implements client based authentication/authorization
115
- # based on the existing trust relationship using the `none`
116
- # grant type.
117
- #
118
- class ClientCredentialsStrategy < GrantTypeStrategy
119
- def authorization_body_data
120
- {
121
- "grant_type" => "none",
122
- "client_id" => @credentials.client_id
123
- }
129
+ # This passes user details through so the returned token
130
+ # carries the privileges of the user not account limited
131
+ # by the client
132
+ #
133
+ class UserCredentialsStrategy < GrantTypeStrategy
134
+ def authorization_body_data
135
+ {
136
+ "grant_type" => "password",
137
+ "client_id" => @credentials.client_id,
138
+ "username" => @credentials.username,
139
+ "password" => @credentials.password
140
+ }
141
+ end
124
142
  end
125
- end
126
143
 
127
- # This passes user details through so the returned token
128
- # carries the privileges of the user not account limited
129
- # by the client
130
- #
131
- class UserCredentialsStrategy < GrantTypeStrategy
132
- def authorization_body_data
133
- {
134
- "grant_type" => "password",
135
- "client_id" => @credentials.client_id,
136
- "username" => @credentials.username,
137
- "password" => @credentials.password
138
- }
139
- end
140
- end
141
-
142
- # This strategy attempts to use a refresh_token gained during an earlier
143
- # request to reuse the credentials given originally
144
- #
145
- class RefreshTokenStrategy < GrantTypeStrategy
146
- def authorization_body_data
147
- {
148
- "grant_type" => "refresh_token",
149
- "client_id" => @credentials.client_id,
150
- "refresh_token" => @credentials.refresh_token
151
- }
144
+ # This strategy attempts to use a refresh_token gained during an earlier
145
+ # request to reuse the credentials given originally
146
+ #
147
+ class RefreshTokenStrategy < GrantTypeStrategy
148
+ def authorization_body_data
149
+ {
150
+ "grant_type" => "refresh_token",
151
+ "client_id" => @credentials.client_id,
152
+ "refresh_token" => @credentials.refresh_token
153
+ }
154
+ end
152
155
  end
153
- end
154
156
 
155
- private
157
+ private
156
158
 
157
- # This updates the current credentials if passed a valid response
158
- #
159
- # @param [CredentialSet] credentials Credentials to update
160
- # @param [Excon::Response] response Response object to parse value from
161
- #
162
- def update_credentials_from_response(credentials, response)
163
- response_data = Fog::JSON.decode(response.body)
164
- credentials.update_tokens(response_data["access_token"], response_data["refresh_token"], response_data["expires_in"])
159
+ # This updates the current credentials if passed a valid response
160
+ #
161
+ # @param [CredentialSet] credentials Credentials to update
162
+ # @param [Excon::Response] response Response object to parse value from
163
+ #
164
+ def update_credentials_from_response(credentials, response)
165
+ response_data = Fog::JSON.decode(response.body)
166
+ credentials.update_tokens(response_data["access_token"], response_data["refresh_token"], response_data["expires_in"])
167
+ end
165
168
  end
166
169
  end
170
+ end
@@ -0,0 +1,27 @@
1
+ module Fog
2
+ module Storage
3
+ class Brightbox
4
+ class Real
5
+
6
+ # Copy object
7
+ #
8
+ # ==== Parameters
9
+ # * source_container_name<~String> - Name of source bucket
10
+ # * source_object_name<~String> - Name of source object
11
+ # * target_container_name<~String> - Name of bucket to create copy in
12
+ # * target_object_name<~String> - Name for new copy of object
13
+ # * options<~Hash> - Additional headers
14
+ def copy_object(source_container_name, source_object_name, target_container_name, target_object_name, options={})
15
+ headers = { 'X-Copy-From' => "/#{source_container_name}/#{source_object_name}" }.merge(options)
16
+ request({
17
+ :expects => 201,
18
+ :headers => headers,
19
+ :method => 'PUT',
20
+ :path => "#{Fog::Storage::Brightbox.escape(target_container_name)}/#{Fog::Storage::Brightbox.escape(target_object_name)}"
21
+ })
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,22 @@
1
+ module Fog
2
+ module Storage
3
+ class Brightbox
4
+ class Real
5
+
6
+ # Delete an existing container
7
+ #
8
+ # ==== Parameters
9
+ # * name<~String> - Name of container to delete
10
+ #
11
+ def delete_container(name)
12
+ request(
13
+ :expects => 204,
14
+ :method => 'DELETE',
15
+ :path => Fog::Storage::Brightbox.escape(name)
16
+ )
17
+ end
18
+
19
+ end
20
+ end
21
+ end
22
+ end