class Fog::Brightbox::Storage::Real

Public Class Methods

new(config) click to toggle source
# File lib/fog/brightbox/storage.rb, line 52
def initialize(config)
  if config.respond_to?(:config_service?) && config.config_service?
    @config = config
  else
    @config = Fog::Brightbox::Config.new(config)
  end
  @config = Fog::Brightbox::Storage::Config.new(@config)

  @temp_url_key = @config.storage_temp_key
end

Public Instance Methods

account() click to toggle source
# File lib/fog/brightbox/storage.rb, line 79
def account
  @config.account
end
authenticate() click to toggle source
# File lib/fog/brightbox/storage.rb, line 115
def authenticate
  if !management_url || needs_to_authenticate?
    response = Fog::Brightbox::Storage::AuthenticationRequest.new(@config).authenticate
    if response.nil?
      return false
    else
      update_config_from_auth_response(response)
    end
  else
    false
  end
end
authentication_url() click to toggle source
# File lib/fog/brightbox/storage.rb, line 67
def authentication_url
  @auth_url ||= URI.parse(@config.storage_url.to_s)
end
change_account(account) click to toggle source
# File lib/fog/brightbox/storage.rb, line 83
def change_account(account)
  @config.change_account(account)
end
connection() click to toggle source
# File lib/fog/brightbox/storage.rb, line 91
def connection
  @connection ||= Fog::Brightbox::Storage::Connection.new(@config)
end
copy_object(source_container_name, source_object_name, target_container_name, target_object_name, options = {}) click to toggle source

Copy object

Parameters

  • source_container_name<~String> - Name of source bucket

  • source_object_name<~String> - Name of source object

  • target_container_name<~String> - Name of bucket to create copy in

  • target_object_name<~String> - Name for new copy of object

  • options<~Hash> - Additional headers

# File lib/fog/brightbox/requests/storage/copy_object.rb, line 13
def copy_object(source_container_name, source_object_name, target_container_name, target_object_name, options = {})
  headers = { "X-Copy-From" => "/#{source_container_name}/#{source_object_name}" }.merge(options)
  request(
            :expects  => 201,
            :headers  => headers,
            :method   => "PUT",
            :path     => "#{Fog::Brightbox::Storage.escape(target_container_name)}/#{Fog::Brightbox::Storage.escape(target_object_name)}"
          )
end
create_temp_url(container, object, expires_at, method, options = {}) click to toggle source

creates a temporary url

@param container [String] Name of container containing object @param object [String] Name of object to get expiring url for @param expires_at [Time] An expiry time for this url @param method [String] The method to use for accessing the object (GET, PUT, HEAD) @param options [Hash] An optional options hash @option options [String] :scheme The scheme to use (http, https) @option options [String] :port A non standard port to use

@return [String] url for object

@raise [ArgumentError] if storage_temp_key is not set in configuration @raise [ArgumentError] if method is not valid

@see docs.rackspace.com/files/api/v1/cf-devguide/content/Create_TempURL-d1a444.html

# File lib/fog/brightbox/storage.rb, line 151
def create_temp_url(container, object, expires_at, method, options = {})
  raise ArgumentError, "Storage must be instantiated with the :brightbox_temp_url_key option" if @config.storage_temp_key.nil?

  # POST not allowed
  allowed_methods = %w(GET PUT HEAD)
  unless allowed_methods.include?(method)
    raise ArgumentError.new("Invalid method '#{method}' specified. Valid methods are: #{allowed_methods.join(", ")}")
  end

  if management_url.nil?
    message = "Storage must be instantiated with the :brightbox_storage_management_url or you must authenticate first"
    raise Fog::Brightbox::Storage::ManagementUrlUnknown, message
  end

  destination_url = management_url.dup
  object_path = destination_url.path

  destination_url.scheme = options[:scheme] if options[:scheme]
  destination_url.port = options[:port] if options[:port]

  object_path_escaped = "#{object_path}/#{Fog::Brightbox::Storage.escape(container)}/#{Fog::Brightbox::Storage.escape(object, "/")}"
  object_path_unescaped = "#{object_path}/#{Fog::Brightbox::Storage.escape(container)}/#{object}"

  expiry_timestamp = expires_at.to_i
  string_to_sign = [method, expiry_timestamp, object_path_unescaped].join("\n")

  hmac = Fog::HMAC.new("sha1", @config.storage_temp_key)
  sig = sig_to_hex(hmac.sign(string_to_sign))

  destination_url.path = object_path_escaped
  destination_url.query = URI.encode_www_form(:temp_url_sig => sig, :temp_url_expires => expiry_timestamp)
  destination_url.to_s
end
delete_container(name) click to toggle source

Delete an existing container

Parameters

  • name<~String> - Name of container to delete

# File lib/fog/brightbox/requests/storage/delete_container.rb, line 10
def delete_container(name)
  request(
    :expects  => 204,
    :method   => "DELETE",
    :path     => Fog::Brightbox::Storage.escape(name)
  )
end
delete_multiple_objects(container, object_names, options = {}) click to toggle source

Deletes multiple objects or containers with a single request.

To delete objects from a single container, container may be provided and object_names should be an Array of object names within the container.

To delete objects from multiple containers or delete containers, container should be nil and all object_names should be prefixed with a container name.

Containers must be empty when deleted. object_names are processed in the order given, so objects within a container should be listed first to empty the container.

Up to 10,000 objects may be deleted in a single request. The server will respond with +200 OK+ for all requests. response.body must be inspected for actual results.

@example Delete objects from a container

object_names = ['object', 'another/object']
conn.delete_multiple_objects('my_container', object_names)

@example Delete objects from multiple containers

object_names = ['container_a/object', 'container_b/object']
conn.delete_multiple_objects(nil, object_names)

@example Delete a container and all it's objects

object_names = ['my_container/object_a', 'my_container/object_b', 'my_container']
conn.delete_multiple_objects(nil, object_names)

@param container [String,nil] Name of container. @param object_names [Array<String>] Object names to be deleted. @param options [Hash] Additional request headers.

@return [Excon::Response]

* body [Hash] - Results of the operation.
  * "Number Not Found" [Integer] - Number of missing objects or containers.
  * "Response Status" [String] - Response code for the subrequest of the last failed operation.
  * "Errors" [Array<object_name, response_status>]
    * object_name [String] - Object that generated an error when the delete was attempted.
    * response_status [String] - Response status from the subrequest for object_name.
  * "Number Deleted" [Integer] - Number of objects or containers deleted.
  * "Response Body" [String] - Response body for "Response Status".
# File lib/fog/brightbox/requests/storage/delete_multiple_objects.rb, line 45
def delete_multiple_objects(container, object_names, options = {})
  body = object_names.map do |name|
    object_name = container ? "#{ container }/#{ name }" : name
    URI.encode(object_name)
  end.join("\n")

  response = request({
                       :expects  => 200,
                       :method   => "DELETE",
                       :headers  => options.merge("Content-Type" => "text/plain",
                                                  "Accept" => "application/json"),
                       :body     => body,
                       :query    => { "bulk-delete" => true }
                     }, false)
  response.body = Fog::JSON.decode(response.body)
  response
end
delete_object(container, object) click to toggle source

Delete an existing object

Parameters

  • container<~String> - Name of container to delete

  • object<~String> - Name of object to delete

# File lib/fog/brightbox/requests/storage/delete_object.rb, line 11
def delete_object(container, object)
  request(
    :expects  => 204,
    :method   => "DELETE",
    :path     => "#{Fog::Brightbox::Storage.escape(container)}/#{Fog::Brightbox::Storage.escape(object)}"
  )
end
delete_static_large_object(container, object, options = {}) click to toggle source

Delete a static large object.

Deletes the SLO manifest object and all segments that it references. The server will respond with +200 OK+ for all requests. response.body must be inspected for actual results.

@param container [String] Name of container. @param object [String] Name of the SLO manifest object. @param options [Hash] Additional request headers.

@return [Excon::Response]

* body [Hash] - Results of the operation.
  * "Number Not Found" [Integer] - Number of missing segments.
  * "Response Status" [String] - Response code for the subrequest of the last failed operation.
  * "Errors" [Array<object_name, response_status>]
    * object_name [String] - Object that generated an error when the delete was attempted.
    * response_status [String] - Response status from the subrequest for object_name.
  * "Number Deleted" [Integer] - Number of segments deleted.
  * "Response Body" [String] - Response body for Response Status.

@see docs.brightbox.org/api/brightbox-object-storage/1.0/content/static-large-objects.html

# File lib/fog/brightbox/requests/storage/delete_static_large_object.rb, line 26
def delete_static_large_object(container, object, options = {})
  response = request({
                       :expects  => 200,
                       :method   => "DELETE",
                       :headers  => options.merge("Content-Type" => "text/plain",
                                                  "Accept" => "application/json"),
                       :path     => "#{Fog::Brightbox::Storage.escape(container)}/#{Fog::Brightbox::Storage.escape(object)}",
                       :query    => { "multipart-manifest" => "delete" }
                     }, false)
  response.body = Fog::JSON.decode(response.body)
  response
end
extract_account_from_url(url) click to toggle source

@param [URI] url A URI object to extract the account from @return [String] The account

# File lib/fog/brightbox/storage.rb, line 130
def extract_account_from_url(url)
  url.path.split("/")[2]
end
get_container(container, options = {}) click to toggle source

Get details for container and total bytes stored

Parameters

  • container<~String> - Name of container to retrieve info for

  • options<~String>:

    • 'limit'<~String> - Maximum number of objects to return

    • 'marker'<~String> - Only return objects whose name is greater than marker

    • 'prefix'<~String> - Limits results to those starting with prefix

    • 'path'<~String> - Return objects nested in the pseudo path

Returns

  • response<~Excon::Response>:

    • headers<~Hash>:

      • 'X-Account-Container-Count'<~String> - Count of containers

      • 'X-Account-Bytes-Used'<~String> - Bytes used

    • body<~Array>:

      • 'bytes'<~Integer> - Number of bytes used by container

      • 'count'<~Integer> - Number of items in container

      • 'name'<~String> - Name of container

      • item<~Hash>:

        • 'bytes'<~String> - Size of object

        • 'content_type'<~String> Content-Type of object

        • 'hash'<~String> - Hash of object (etag?)

        • 'last_modified'<~String> - Last modified timestamp

        • 'name'<~String> - Name of object

# File lib/fog/brightbox/requests/storage/get_container.rb, line 30
def get_container(container, options = {})
  options = options.reject { |_key, value| value.nil? }
  request(
    :expects  => 200,
    :method   => "GET",
    :path     => Fog::Brightbox::Storage.escape(container),
    :query    => { "format" => "json" }.merge!(options)
  )
end
get_containers(options = {}) click to toggle source

List existing storage containers

Parameters

  • options<~Hash>:

    • 'limit'<~Integer> - Upper limit to number of results returned

    • 'marker'<~String> - Only return objects with name greater than this value

Returns

  • response<~Excon::Response>:

    • body<~Array>:

      • container<~Hash>:

        • 'bytes'<~Integer>: - Number of bytes used by container

        • 'count'<~Integer>: - Number of items in container

        • 'name'<~String>: - Name of container

# File lib/fog/brightbox/requests/storage/get_containers.rb, line 19
def get_containers(options = {})
  options = options.reject { |_key, value| value.nil? }
  request(
    :expects  => [200, 204],
    :method   => "GET",
    :path     => "",
    :query    => { "format" => "json" }.merge!(options)
  )
end
get_object(container, object, &block) click to toggle source

Get details for object

Parameters

  • container<~String> - Name of container to look in

  • object<~String> - Name of object to look for

# File lib/fog/brightbox/requests/storage/get_object.rb, line 11
def get_object(container, object, &block)
  params = {
    :expects  => 200,
    :method   => "GET",
    :path     => "#{Fog::Brightbox::Storage.escape(container)}/#{Fog::Brightbox::Storage.escape(object)}"
  }

  if block_given?
    params[:response_block] = block
  end

  request(params, false)
end
get_object_http_url(container, object, expires, options = {}) click to toggle source

Get an expiring object http url

Parameters

  • container<~String> - Name of container containing object

  • object<~String> - Name of object to get expiring url for

  • expires<~Time> - An expiry time for this url

Returns

  • response<~Excon::Response>:

    • body<~String> - url for object

# File lib/fog/brightbox/requests/storage/get_object_http_url.rb, line 15
def get_object_http_url(container, object, expires, options = {})
  create_temp_url(container, object, expires, "GET", options.merge(:scheme => "http"))
end
get_object_https_url(container, object, expires, options = {}) click to toggle source

Get an expiring object https url from Cloud Files

Parameters

  • container<~String> - Name of container containing object

  • object<~String> - Name of object to get expiring url for

  • expires<~Time> - An expiry time for this url

Returns

  • response<~Excon::Response>:

    • body<~String> - url for object

# File lib/fog/brightbox/requests/storage/get_object_https_url.rb, line 15
def get_object_https_url(container, object, expires, options = {})
  create_temp_url(container, object, expires, "GET", options.merge(:scheme => "https"))
end
head_container(container) click to toggle source

List number of objects and total bytes stored

Parameters

  • container<~String> - Name of container to retrieve info for

Returns

  • response<~Excon::Response>:

    • headers<~Hash>:

      • 'X-Container-Object-Count'<~String> - Count of containers

      • 'X-Container-Bytes-Used'<~String> - Bytes used

# File lib/fog/brightbox/requests/storage/head_container.rb, line 15
def head_container(container)
  request(
    :expects  => 204,
    :method   => "HEAD",
    :path     => Fog::Brightbox::Storage.escape(container),
    :query    => { "format" => "json" }
  )
end
head_containers() click to toggle source

List number of containers and total bytes stored

Returns

  • response<~Excon::Response>:

    • headers<~Hash>:

      • 'X-Account-Container-Count'<~String> - Count of containers

      • 'X-Account-Bytes-Used'<~String> - Bytes used

# File lib/fog/brightbox/requests/storage/head_containers.rb, line 12
def head_containers
  request(
    :expects  => 204,
    :method   => "HEAD",
    :path     => "",
    :query    => { "format" => "json" }
  )
end
head_object(container, object) click to toggle source

Get headers for object

Parameters

  • container<~String> - Name of container to look in

  • object<~String> - Name of object to look for

# File lib/fog/brightbox/requests/storage/head_object.rb, line 11
def head_object(container, object)
  request({
            :expects  => 200,
            :method   => "HEAD",
            :path     => "#{Fog::Brightbox::Storage.escape(container)}/#{Fog::Brightbox::Storage.escape(object)}"
          }, false)
end
management_url() click to toggle source
# File lib/fog/brightbox/storage.rb, line 71
def management_url
  @config.storage_management_url
end
needs_to_authenticate?() click to toggle source
# File lib/fog/brightbox/storage.rb, line 63
def needs_to_authenticate?
  @config.must_authenticate?
end
post_set_meta_temp_url_key(key) click to toggle source

Set the account wide Temp URL Key. This is a secret key that's used to generate signed expiring URLs.

Once the key has been set with this request you should create new Storage objects with the :brightbox_temp_url_key option then use the get_object_https_url method to generate expiring URLs.

*** CAUTION *** changing this secret key will invalidate any expiring URLS generated with old keys.

Parameters

  • key<~String> - The new Temp URL Key

Returns

  • response<~Excon::Response>

See Also

docs.rackspace.com/files/api/v1/cf-devguide/content/Set_Account_Metadata-d1a4460.html

# File lib/fog/brightbox/requests/storage/post_set_meta_temp_url_key.rb, line 23
def post_set_meta_temp_url_key(key)
  request(
    :expects  => [201, 202, 204],
    :method   => "POST",
    :headers  => { "X-Account-Meta-Temp-Url-Key" => key }
  )
end
put_container(name, options = {}) click to toggle source

Create a new container

Parameters

  • name<~String> - Name for container, should be < 256 bytes and must not contain '/'

# File lib/fog/brightbox/requests/storage/put_container.rb, line 10
def put_container(name, options = {})
  headers = options[:headers] || {}
  headers["X-Container-Read"] ||= options.delete(:read_permissions)
  headers["X-Container-Write"] ||= options.delete(:write_permissions)

  request(
    :expects  => [201, 202],
    :method   => "PUT",
    :path     => Fog::Brightbox::Storage.escape(name),
    :headers  => headers
  )
end
put_dynamic_obj_manifest(container, object, options = {}) click to toggle source

Create a new dynamic large object manifest

Creates an object with a X-Object-Manifest header that specifies the common prefix (“<container>/<prefix>”) for all uploaded segments. Retrieving the manifest object streams all segments matching this prefix. Segments must sort in the order they should be concatenated. Note that any future objects stored in the container along with the segments that match the prefix will be included when retrieving the manifest object.

All segments must be stored in the same container, but may be in a different container than the manifest object. The default X-Object-Manifest header is set to “container/object”, but may be overridden in options to specify the prefix and/or the container where segments were stored. If overridden, names should be CGI escaped (excluding spaces) if needed (see {Fog::Brightbox::Storage.escape}).

@param container [String] Name for container where object will be stored. Should be < 256 bytes and must not contain '/' @param object [String] Name for manifest object. @param options [Hash] Config headers for object. @option options [String] 'X-Object-Manifest' (“container/object”) “<container>/<prefix>” for segment objects.

@raise [Fog::Brightbox::Storage::NotFound] HTTP 404 @raise [Excon::Errors::BadRequest] HTTP 400 @raise [Excon::Errors::Unauthorized] HTTP 401 @raise [Excon::Errors::HTTPStatusError]

@see docs.brightbox.org/api/brightbox-object-storage/1.0/content/dynamic-large-object-creation.html

# File lib/fog/brightbox/requests/storage/put_dynamic_obj_manifest.rb, line 28
def put_dynamic_obj_manifest(container, object, options = {})
  path = "#{Fog::Brightbox::Storage.escape(container)}/#{Fog::Brightbox::Storage.escape(object)}"
  headers = { "X-Object-Manifest" => path }.merge(options)
  request(
    :expects  => 201,
    :headers  => headers,
    :method   => "PUT",
    :path     => path
  )
end
put_object(container, object, data, options = {}, &block) click to toggle source

Create a new object

When passed a block, it will make a chunked request, calling the block for chunks until it returns an empty string. In this case the data parameter is ignored.

Parameters

  • container<~String> - Name for container, should be < 256 bytes and must not contain '/'

  • object<~String> - Name for object

  • data<~String|File> - data to upload

  • options<~Hash> - config headers for object. Defaults to {}.

  • block<~Proc> - chunker

# File lib/fog/brightbox/requests/storage/put_object.rb, line 18
def put_object(container, object, data, options = {}, &block)
  if block_given?
    params = { :request_block => block }
    headers = options
  else
    data = Fog::Storage.parse_data(data)
    headers = data[:headers].merge!(options)
    params = { :body => data[:body] }
  end

  params.merge!(
    :expects    => 201,
    :idempotent => !params[:request_block],
    :headers    => headers,
    :method     => "PUT",
    :path       => "#{Fog::Brightbox::Storage.escape(container)}/#{Fog::Brightbox::Storage.escape(object)}"
  )

  request(params)
end
put_object_manifest(container, object, options = {}) click to toggle source

Create a new dynamic large object manifest

This is an alias for {#put_dynamic_obj_manifest} for backward compatibility.

# File lib/fog/brightbox/requests/storage/put_object_manifest.rb, line 8
def put_object_manifest(container, object, options = {})
  put_dynamic_obj_manifest(container, object, options)
end
put_static_obj_manifest(container, object, segments, options = {}) click to toggle source

Create a new static large object manifest.

A static large object is similar to a dynamic large object. Whereas a GET for a dynamic large object manifest will stream segments based on the manifest's X-Object-Manifest object name prefix, a static large object manifest streams segments which are defined by the user within the manifest. Information about each segment is provided in segments as an Array of Hash objects, ordered in the sequence which the segments should be streamed.

When the SLO manifest is received, each segment's etag and size_bytes will be verified. The etag for each segment is returned in the response to {#put_object}, but may also be calculated. e.g. +Digest::MD5.hexdigest(segment_data)+

The maximum number of segments for a static large object is 1000, and all segments (except the last) must be at least 1 MiB in size. Unlike a dynamic large object, segments are not required to be in the same container.

@example

segments = [
  { :path => 'segments_container/first_segment',
    :etag => 'md5 for first_segment',
    :size_bytes => 'byte size of first_segment' },
  { :path => 'segments_container/second_segment',
    :etag => 'md5 for second_segment',
    :size_bytes => 'byte size of second_segment' }
]
put_static_obj_manifest('my_container', 'my_large_object', segments)

@param container [String] Name for container where object will be stored.

Should be < 256 bytes and must not contain '/'

@param object [String] Name for manifest object. @param segments [Array<Hash>] Segment data for the object. @param options [Hash] Config headers for object.

@raise [Fog::Brightbox::Storage::NotFound] HTTP 404 @raise [Excon::Errors::BadRequest] HTTP 400 @raise [Excon::Errors::Unauthorized] HTTP 401 @raise [Excon::Errors::HTTPStatusError]

@see docs.brightbox.org/api/brightbox-object-storage/1.0/content/static-large-objects.html

# File lib/fog/brightbox/requests/storage/put_static_obj_manifest.rb, line 42
def put_static_obj_manifest(container, object, segments, options = {})
  request(
    :expects  => 201,
    :method   => "PUT",
    :headers  => options,
    :body     => Fog::JSON.encode(segments),
    :path     => "#{Fog::Brightbox::Storage.escape(container)}/#{Fog::Brightbox::Storage.escape(object)}",
    :query    => { "multipart-manifest" => "put" }
  )
end
reload() click to toggle source
# File lib/fog/brightbox/storage.rb, line 75
def reload
  @connection.reset
end
request(params, parse_json = true) click to toggle source
# File lib/fog/brightbox/storage.rb, line 95
def request(params, parse_json = true)
  authenticate if @config.must_authenticate?
  connection.request(params, parse_json)
rescue Fog::Brightbox::Storage::AuthenticationRequired => error
  if @config.managed_tokens?
    @config.expire_tokens!
    authenticate
    retry
  else # bad credentials
    raise error
  end
rescue Excon::Errors::HTTPStatusError => error
  raise case error
        when Excon::Errors::NotFound
          Fog::Brightbox::Storage::NotFound.slurp(error)
        else
          error
        end
end
reset_account_name() click to toggle source
# File lib/fog/brightbox/storage.rb, line 87
def reset_account_name
  @config.reset_account
end

Private Instance Methods

sig_to_hex(str) click to toggle source
# File lib/fog/brightbox/storage.rb, line 187
def sig_to_hex(str)
  str.unpack("C*").map { |c|
    c.to_s(16)
  }.map { |h|
    h.size == 1 ? "0#{h}" : h
  }.join
end
update_config_from_auth_response(response) click to toggle source
# File lib/fog/brightbox/storage.rb, line 195
def update_config_from_auth_response(response)
  @config.update_tokens(response.access_token)

  # Only update the management URL if not set
  return true if management_url && account

  unless management_url
    new_management_url = response.management_url
    if new_management_url && new_management_url != management_url.to_s
      @config.storage_management_url = URI.parse(new_management_url)
    end
  end

  unless account
    # Extract the account ID sent by the server
    change_account(extract_account_from_url(@config.storage_management_url))
  end
  true
end