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,67 @@
1
+ module Fog
2
+ module Storage
3
+ class Brightbox
4
+ class Real
5
+
6
+ # Deletes multiple objects or containers with a single request.
7
+ #
8
+ # To delete objects from a single container, +container+ may be provided
9
+ # and +object_names+ should be an Array of object names within the container.
10
+ #
11
+ # To delete objects from multiple containers or delete containers,
12
+ # +container+ should be +nil+ and all +object_names+ should be prefixed with a container name.
13
+ #
14
+ # Containers must be empty when deleted. +object_names+ are processed in the order given,
15
+ # so objects within a container should be listed first to empty the container.
16
+ #
17
+ # Up to 10,000 objects may be deleted in a single request.
18
+ # The server will respond with +200 OK+ for all requests.
19
+ # +response.body+ must be inspected for actual results.
20
+ #
21
+ # @example Delete objects from a container
22
+ # object_names = ['object', 'another/object']
23
+ # conn.delete_multiple_objects('my_container', object_names)
24
+ #
25
+ # @example Delete objects from multiple containers
26
+ # object_names = ['container_a/object', 'container_b/object']
27
+ # conn.delete_multiple_objects(nil, object_names)
28
+ #
29
+ # @example Delete a container and all it's objects
30
+ # object_names = ['my_container/object_a', 'my_container/object_b', 'my_container']
31
+ # conn.delete_multiple_objects(nil, object_names)
32
+ #
33
+ # @param container [String,nil] Name of container.
34
+ # @param object_names [Array<String>] Object names to be deleted.
35
+ # @param options [Hash] Additional request headers.
36
+ #
37
+ # @return [Excon::Response]
38
+ # * body [Hash] - Results of the operation.
39
+ # * "Number Not Found" [Integer] - Number of missing objects or containers.
40
+ # * "Response Status" [String] - Response code for the subrequest of the last failed operation.
41
+ # * "Errors" [Array<object_name, response_status>]
42
+ # * object_name [String] - Object that generated an error when the delete was attempted.
43
+ # * response_status [String] - Response status from the subrequest for object_name.
44
+ # * "Number Deleted" [Integer] - Number of objects or containers deleted.
45
+ # * "Response Body" [String] - Response body for "Response Status".
46
+ def delete_multiple_objects(container, object_names, options = {})
47
+ body = object_names.map do |name|
48
+ object_name = container ? "#{ container }/#{ name }" : name
49
+ URI.encode(object_name)
50
+ end.join("\n")
51
+
52
+ response = request({
53
+ :expects => 200,
54
+ :method => 'DELETE',
55
+ :headers => options.merge('Content-Type' => 'text/plain',
56
+ 'Accept' => 'application/json'),
57
+ :body => body,
58
+ :query => { 'bulk-delete' => true }
59
+ }, false)
60
+ response.body = Fog::JSON.decode(response.body)
61
+ response
62
+ end
63
+
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,23 @@
1
+ module Fog
2
+ module Storage
3
+ class Brightbox
4
+ class Real
5
+
6
+ # Delete an existing object
7
+ #
8
+ # ==== Parameters
9
+ # * container<~String> - Name of container to delete
10
+ # * object<~String> - Name of object to delete
11
+ #
12
+ def delete_object(container, object)
13
+ request(
14
+ :expects => 204,
15
+ :method => 'DELETE',
16
+ :path => "#{Fog::Storage::Brightbox.escape(container)}/#{Fog::Storage::Brightbox.escape(object)}"
17
+ )
18
+ end
19
+
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,43 @@
1
+ module Fog
2
+ module Storage
3
+ class Brightbox
4
+ class Real
5
+
6
+ # Delete a static large object.
7
+ #
8
+ # Deletes the SLO manifest +object+ and all segments that it references.
9
+ # The server will respond with +200 OK+ for all requests.
10
+ # +response.body+ must be inspected for actual results.
11
+ #
12
+ # @param container [String] Name of container.
13
+ # @param object [String] Name of the SLO manifest object.
14
+ # @param options [Hash] Additional request headers.
15
+ #
16
+ # @return [Excon::Response]
17
+ # * body [Hash] - Results of the operation.
18
+ # * "Number Not Found" [Integer] - Number of missing segments.
19
+ # * "Response Status" [String] - Response code for the subrequest of the last failed operation.
20
+ # * "Errors" [Array<object_name, response_status>]
21
+ # * object_name [String] - Object that generated an error when the delete was attempted.
22
+ # * response_status [String] - Response status from the subrequest for object_name.
23
+ # * "Number Deleted" [Integer] - Number of segments deleted.
24
+ # * "Response Body" [String] - Response body for Response Status.
25
+ #
26
+ # @see http://docs.brightbox.org/api/brightbox-object-storage/1.0/content/static-large-objects.html
27
+ def delete_static_large_object(container, object, options = {})
28
+ response = request({
29
+ :expects => 200,
30
+ :method => 'DELETE',
31
+ :headers => options.merge('Content-Type' => 'text/plain',
32
+ 'Accept' => 'application/json'),
33
+ :path => "#{Fog::Storage::Brightbox.escape(container)}/#{Fog::Storage::Brightbox.escape(object)}",
34
+ :query => { 'multipart-manifest' => 'delete' }
35
+ }, false)
36
+ response.body = Fog::JSON.decode(response.body)
37
+ response
38
+ end
39
+
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,44 @@
1
+ module Fog
2
+ module Storage
3
+ class Brightbox
4
+ class Real
5
+
6
+ # Get details for container and total bytes stored
7
+ #
8
+ # ==== Parameters
9
+ # * container<~String> - Name of container to retrieve info for
10
+ # * options<~String>:
11
+ # * 'limit'<~String> - Maximum number of objects to return
12
+ # * 'marker'<~String> - Only return objects whose name is greater than marker
13
+ # * 'prefix'<~String> - Limits results to those starting with prefix
14
+ # * 'path'<~String> - Return objects nested in the pseudo path
15
+ #
16
+ # ==== Returns
17
+ # * response<~Excon::Response>:
18
+ # * headers<~Hash>:
19
+ # * 'X-Account-Container-Count'<~String> - Count of containers
20
+ # * 'X-Account-Bytes-Used'<~String> - Bytes used
21
+ # * body<~Array>:
22
+ # * 'bytes'<~Integer> - Number of bytes used by container
23
+ # * 'count'<~Integer> - Number of items in container
24
+ # * 'name'<~String> - Name of container
25
+ # * item<~Hash>:
26
+ # * 'bytes'<~String> - Size of object
27
+ # * 'content_type'<~String> Content-Type of object
28
+ # * 'hash'<~String> - Hash of object (etag?)
29
+ # * 'last_modified'<~String> - Last modified timestamp
30
+ # * 'name'<~String> - Name of object
31
+ def get_container(container, options = {})
32
+ options = options.reject {|key, value| value.nil?}
33
+ request(
34
+ :expects => 200,
35
+ :method => 'GET',
36
+ :path => Fog::Storage::Brightbox.escape(container),
37
+ :query => {'format' => 'json'}.merge!(options)
38
+ )
39
+ end
40
+
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,33 @@
1
+ module Fog
2
+ module Storage
3
+ class Brightbox
4
+ class Real
5
+
6
+ # List existing storage containers
7
+ #
8
+ # ==== Parameters
9
+ # * options<~Hash>:
10
+ # * 'limit'<~Integer> - Upper limit to number of results returned
11
+ # * 'marker'<~String> - Only return objects with name greater than this value
12
+ #
13
+ # ==== Returns
14
+ # * response<~Excon::Response>:
15
+ # * body<~Array>:
16
+ # * container<~Hash>:
17
+ # * 'bytes'<~Integer>: - Number of bytes used by container
18
+ # * 'count'<~Integer>: - Number of items in container
19
+ # * 'name'<~String>: - Name of container
20
+ def get_containers(options = {})
21
+ options = options.reject {|key, value| value.nil?}
22
+ request(
23
+ :expects => [200, 204],
24
+ :method => 'GET',
25
+ :path => '',
26
+ :query => {'format' => 'json'}.merge!(options)
27
+ )
28
+ end
29
+
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,29 @@
1
+ module Fog
2
+ module Storage
3
+ class Brightbox
4
+ class Real
5
+
6
+ # Get details for object
7
+ #
8
+ # ==== Parameters
9
+ # * container<~String> - Name of container to look in
10
+ # * object<~String> - Name of object to look for
11
+ #
12
+ def get_object(container, object, &block)
13
+ params = {
14
+ :expects => 200,
15
+ :method => 'GET',
16
+ :path => "#{Fog::Storage::Brightbox.escape(container)}/#{Fog::Storage::Brightbox.escape(object)}"
17
+ }
18
+
19
+ if block_given?
20
+ params[:response_block] = block
21
+ end
22
+
23
+ request(params, false)
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,21 @@
1
+ module Fog
2
+ module Storage
3
+ class Brightbox
4
+ class Real
5
+ # Get an expiring object http url
6
+ #
7
+ # ==== Parameters
8
+ # * container<~String> - Name of container containing object
9
+ # * object<~String> - Name of object to get expiring url for
10
+ # * expires<~Time> - An expiry time for this url
11
+ #
12
+ # ==== Returns
13
+ # * response<~Excon::Response>:
14
+ # * body<~String> - url for object
15
+ def get_object_http_url(container, object, expires, options = {})
16
+ create_temp_url(container, object, expires, "GET", options.merge(:scheme => "http"))
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,85 @@
1
+ module Fog
2
+ module Storage
3
+ class Brightbox
4
+
5
+ class Real
6
+
7
+ # Get an expiring object https url from Cloud Files
8
+ #
9
+ # ==== Parameters
10
+ # * container<~String> - Name of container containing object
11
+ # * object<~String> - Name of object to get expiring url for
12
+ # * expires<~Time> - An expiry time for this url
13
+ #
14
+ # ==== Returns
15
+ # * response<~Excon::Response>:
16
+ # * body<~String> - url for object
17
+ def get_object_https_url(container, object, expires, options = {})
18
+ create_temp_url(container, object, expires, "GET", options.merge(:scheme => "https"))
19
+ end
20
+
21
+ # creates a temporary url
22
+ #
23
+ # ==== Parameters
24
+ # * container<~String> - Name of container containing object
25
+ # * object<~String> - Name of object to get expiring url for
26
+ # * expires<~Time> - An expiry time for this url
27
+ # * method<~String> - The method to use for accessing the object (GET, PUT, HEAD)
28
+ # * scheme<~String> - The scheme to use (http, https)
29
+ # * options<~Hash> - An optional options hash
30
+ #
31
+ # ==== Returns
32
+ # * response<~Excon::Response>:
33
+ # * body<~String> - url for object
34
+ #
35
+ # ==== See Also
36
+ # http://docs.rackspace.com/files/api/v1/cf-devguide/content/Create_TempURL-d1a444.html
37
+ def create_temp_url(container, object, expires, method, options = {})
38
+ raise ArgumentError, "Insufficient parameters specified." unless (container && object && expires && method)
39
+ raise ArgumentError, "Storage must be instantiated with the :brightbox_temp_url_key option" if @brightbox_temp_url_key.nil?
40
+
41
+ scheme = options[:scheme] || @scheme
42
+
43
+ # POST not allowed
44
+ allowed_methods = %w{GET PUT HEAD}
45
+ unless allowed_methods.include?(method)
46
+ raise ArgumentError.new("Invalid method '#{method}' specified. Valid methods are: #{allowed_methods.join(', ')}")
47
+ end
48
+
49
+
50
+ expires = expires.to_i
51
+ object_path_escaped = "#{@path}/#{Fog::Storage::Brightbox.escape(container)}/#{Fog::Storage::Brightbox.escape(object,"/")}"
52
+ object_path_unescaped = "#{@path}/#{Fog::Storage::Brightbox.escape(container)}/#{object}"
53
+ string_to_sign = "#{method}\n#{expires}\n#{object_path_unescaped}"
54
+
55
+ hmac = Fog::HMAC.new('sha1', @brightbox_temp_url_key)
56
+ sig = sig_to_hex(hmac.sign(string_to_sign))
57
+
58
+ temp_url_options = {
59
+ :scheme => scheme,
60
+ :host => @host,
61
+ :port => @port,
62
+ :path => object_path_escaped,
63
+ :query => URI.encode_www_form(
64
+ :temp_url_sig => sig,
65
+ :temp_url_expires => expires
66
+ )
67
+ }
68
+ URI::Generic.build(temp_url_options).to_s
69
+ end
70
+
71
+ private
72
+
73
+ def sig_to_hex(str)
74
+ str.unpack("C*").map { |c|
75
+ c.to_s(16)
76
+ }.map { |h|
77
+ h.size == 1 ? "0#{h}" : h
78
+ }.join
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,28 @@
1
+ module Fog
2
+ module Storage
3
+ class Brightbox
4
+ class Real
5
+
6
+ # List number of objects and total bytes stored
7
+ #
8
+ # ==== Parameters
9
+ # * container<~String> - Name of container to retrieve info for
10
+ #
11
+ # ==== Returns
12
+ # * response<~Excon::Response>:
13
+ # * headers<~Hash>:
14
+ # * 'X-Container-Object-Count'<~String> - Count of containers
15
+ # * 'X-Container-Bytes-Used'<~String> - Bytes used
16
+ def head_container(container)
17
+ request(
18
+ :expects => 204,
19
+ :method => 'HEAD',
20
+ :path => Fog::Storage::Brightbox.escape(container),
21
+ :query => {'format' => 'json'}
22
+ )
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ module Fog
2
+ module Storage
3
+ class Brightbox
4
+ class Real
5
+
6
+ # List number of containers and total bytes stored
7
+ #
8
+ # ==== Returns
9
+ # * response<~Excon::Response>:
10
+ # * headers<~Hash>:
11
+ # * 'X-Account-Container-Count'<~String> - Count of containers
12
+ # * 'X-Account-Bytes-Used'<~String> - Bytes used
13
+ def head_containers
14
+ request(
15
+ :expects => 204,
16
+ :method => 'HEAD',
17
+ :path => '',
18
+ :query => {'format' => 'json'}
19
+ )
20
+ end
21
+
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,23 @@
1
+ module Fog
2
+ module Storage
3
+ class Brightbox
4
+ class Real
5
+
6
+ # Get headers for object
7
+ #
8
+ # ==== Parameters
9
+ # * container<~String> - Name of container to look in
10
+ # * object<~String> - Name of object to look for
11
+ #
12
+ def head_object(container, object)
13
+ request({
14
+ :expects => 200,
15
+ :method => 'HEAD',
16
+ :path => "#{Fog::Storage::Brightbox.escape(container)}/#{Fog::Storage::Brightbox.escape(object)}"
17
+ }, false)
18
+ end
19
+
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,37 @@
1
+ module Fog
2
+ module Storage
3
+ class Brightbox
4
+
5
+ class Real
6
+
7
+ # Set the account wide Temp URL Key. This is a secret key that's
8
+ # used to generate signed expiring URLs.
9
+ #
10
+ # Once the key has been set with this request you should create new
11
+ # Storage objects with the :brightbox_temp_url_key option then use
12
+ # the get_object_https_url method to generate expiring URLs.
13
+ #
14
+ # *** CAUTION *** changing this secret key will invalidate any expiring
15
+ # URLS generated with old keys.
16
+ #
17
+ # ==== Parameters
18
+ # * key<~String> - The new Temp URL Key
19
+ #
20
+ # ==== Returns
21
+ # * response<~Excon::Response>
22
+ #
23
+ # ==== See Also
24
+ # http://docs.rackspace.com/files/api/v1/cf-devguide/content/Set_Account_Metadata-d1a4460.html
25
+ def post_set_meta_temp_url_key(key)
26
+ request(
27
+ :expects => [201, 202, 204],
28
+ :method => 'POST',
29
+ :headers => {'X-Account-Meta-Temp-Url-Key' => key}
30
+ )
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+ end
37
+ end