diff --git a/lib/fog/rackspace/models/storage/account.rb b/lib/fog/rackspace/models/storage/account.rb index c98fac8f4..2316ac250 100644 --- a/lib/fog/rackspace/models/storage/account.rb +++ b/lib/fog/rackspace/models/storage/account.rb @@ -4,16 +4,34 @@ module Fog module Storage class Rackspace class Account < Fog::Model + # @see http://docs.rackspace.com/files/api/v1/cf-devguide/content/View_Account_Info-d1e11995.html + + # @!attribute [rw] meta_temp_url_key is used to generate temporary access to files + # @return [String] The temporary URL key + # @see http://docs.rackspace.com/files/api/v1/cf-devguide/content/Create_TempURL-d1a444.html attribute :meta_temp_url_key, :aliases => 'X-Account-Meta-Temp-Url-Key' + + # @!attribute [r] container_count + # @return [Integer] The number of containers in account attribute :container_count, :aliases => 'X-Account-Container-Count', :type => :integer + + # @!attribute [r] bytes_used + # @return [Integer] The total number of bytes used by the account attribute :bytes_used, :aliases => 'X-Account-Bytes-Used', :type => :integer + + # @!attribute [r] object_count + # @return [Integer] The total number of objects in the account attribute :object_count, :aliases => 'X-Account-Object-Count', :type => :integer + # Saves account settings (meta_temp_url_key) + # @return [Boolean] returns true if successfully updated def save service.post_set_meta_temp_url_key meta_temp_url_key true end + # Reload account with latest data from Cloud Files + # @return [Fog::Storage::Rackspace::Account] returns itself def reload response = service.head_containers merge_attributes response.headers diff --git a/lib/fog/rackspace/models/storage/directories.rb b/lib/fog/rackspace/models/storage/directories.rb index f36ebca3d..dedf2607d 100644 --- a/lib/fog/rackspace/models/storage/directories.rb +++ b/lib/fog/rackspace/models/storage/directories.rb @@ -9,15 +9,25 @@ module Fog model Fog::Storage::Rackspace::Directory + # Returns list of directories + # @return [Array] Retrieves a list directories. + # @note Fog's current implementation only returns 10,000 directories + # @see http://docs.rackspace.com/files/api/v1/cf-devguide/content/View_List_of_Containers-d1e1100.html def all data = service.get_containers.body load(data) end - # Supply the :cdn_cname option to use the Rackspace CDN CNAME functionality on the public_url. + # Retrieves directory + # @param [String] key of directory + # @param options [Hash]: + # @option options [String] cdn_cname CDN CNAME used when calling Directory#public_url + # @return [Fog::Storage::Rackspace:Directory] + # @example + # fog.directories.get('video', :cdn_cname => 'http://cdn.lunenburg.org').files.first.public_url # - # > fog.directories.get('video', :cdn_cname => 'http://cdn.lunenburg.org').files.first.public_url - # => 'http://cdn.lunenburg.org/hayley-dancing.mov' + # @see Directory#public_url + # @see http://docs.rackspace.com/files/api/v1/cf-devguide/content/View-Container_Info-d1e1285.html def get(key, options = {}) data = service.get_container(key, options) directory = new(:key => key, :cdn_cname => options[:cdn_cname]) diff --git a/lib/fog/rackspace/models/storage/directory.rb b/lib/fog/rackspace/models/storage/directory.rb index d0065cb78..d4ca21071 100644 --- a/lib/fog/rackspace/models/storage/directory.rb +++ b/lib/fog/rackspace/models/storage/directory.rb @@ -8,14 +8,35 @@ module Fog class Directory < Fog::Model + # @!attribute [r] key + # @return [String] The name of the directory identity :key, :aliases => 'name' + # @!attribute [r] bytes + # @return [Integer] The number of bytes used by the directory attribute :bytes, :aliases => 'X-Container-Bytes-Used', :type => :integer + + # @!attribute [r] count + # @return [Integer] The number of objects in the directory attribute :count, :aliases => 'X-Container-Object-Count', :type => :integer + + # @!attribute [rw] cdn_name + # @return [String] The CDN CNAME to be used instead of the default CDN directory URI. The CDN CNAME will need to be setup setup in DNS and + # point to the default CDN directory URI. + # @note This value does not persist and will need to be specified each time a directory is created or retrieved + # @see Directories#get attribute :cdn_cname - attr_writer :public, :public_url + # @!attribute [w] public + # Required for compatibility with other Fog providers. Not Used. + attr_writer :public + # @!attribute [w] public_url + # Required for compatibility with other Fog providers. Not Used. + attr_writer :public_url + + # Set directory metadata + # @param [Hash,Fog::Storage::Rackspace::Metadata] hash contains key value pairs def metadata=(hash) if hash.is_a? Fog::Storage::Rackspace::Metadata attributes[:metadata] = hash @@ -25,6 +46,8 @@ module Fog attributes[:metadata] end + # Retrieve directory metadata + # @return [Fog::Storage::Rackspace::Metadata] metadata key value pairs. def metadata unless attributes[:metadata] response = service.head_container(key) @@ -33,6 +56,10 @@ module Fog attributes[:metadata] end + # Destroy the directory and remove it from CDN + # @return [Boolean] returns true if directory was deleted + # @note Directory must be empty before it is destroyed. + # @see http://docs.rackspace.com/files/api/v1/cf-devguide/content/Delete_Container-d1e1765.html def destroy requires :key service.delete_container(key) @@ -42,6 +69,8 @@ module Fog false end + # Returns collection of files in directory + # @return [Fog::Storage::Rackspace::Files] collection of files in directory def files @files ||= begin Fog::Storage::Rackspace::Files.new( @@ -51,6 +80,8 @@ module Fog end end + # Is directory published to CDN + # @return [Boolean] return true if published to CDN def public? if @public.nil? @public ||= (key && public_url) ? true : false @@ -58,6 +89,8 @@ module Fog @public end + # Reload directory with latest data from Cloud Files + # @return [Fog::Storage::Rackspace::Directory] returns itself def reload @public = nil @urls = nil @@ -65,23 +98,42 @@ module Fog super end - def public_url + # Returns the public url for the directory. + # If the directory has not been published to the CDN, this method will return nil as it is not publically accessable. This method will return the approprate + # url in the following order: + # + # 1. If the service used to access this directory was created with the option :rackspace_cdn_ssl => true, this method will return the SSL-secured URL. + # 2. If the cdn_cname attribute is populated this method will return the cname. + # 3. return the default CDN url. + # + # @return [String] public url for directory + def public_url return nil if urls.empty? - return urls[:ssl_uri] if service.ssl? + return urls[:ssl_uri] if service.ssl? cdn_cname || urls[:uri] end + # URL used to stream video to iOS devices. Cloud Files will auto convert to the approprate format. + # @return [String] iOS URL + # @see http://docs.rackspace.com/files/api/v1/cf-devguide/content/iOS-Streaming-d1f3725.html def ios_url urls[:ios_uri] end + # URL used to stream resources + # @return [String] streaming url + # @see http://docs.rackspace.com/files/api/v1/cf-devguide/content/Streaming-CDN-Enabled_Containers-d1f3721.html def streaming_url urls[:streaming_uri] end + # Create or update directory and associated metadata + # @return [Boolean] returns true if directory was saved + # @note If public attribute is true, directory will be CDN enabled + # @see http://docs.rackspace.com/files/api/v1/cf-devguide/content/Create_Container-d1e1694.html def save requires :key - create_container + create_or_update_container raise Fog::Storage::Rackspace::Error.new("Directory can not be set as :public without a CDN provided") if public? && !cdn_enabled? @urls = service.cdn.publish_container(self, public?) true @@ -99,7 +151,7 @@ module Fog @urls ||= service.cdn.urls(self) end - def create_container + def create_or_update_container headers = attributes[:metadata].nil? ? {} : metadata.to_headers service.put_container(key, headers) end diff --git a/lib/fog/rackspace/models/storage/file.rb b/lib/fog/rackspace/models/storage/file.rb index c07c86bad..a1ff67499 100644 --- a/lib/fog/rackspace/models/storage/file.rb +++ b/lib/fog/rackspace/models/storage/file.rb @@ -6,20 +6,52 @@ module Fog class File < Fog::Model + # @!attribute [r] key + # @return [String] The name of the file identity :key, :aliases => 'name' + # @!attribute [r] content_length + # @return [Integer] The content length of the file attribute :content_length, :aliases => ['bytes', 'Content-Length'], :type => :integer + + # @!attribute [rw] content_type + # @return [String] The MIME Media Type of the file + # @see http://www.iana.org/assignments/media-types attribute :content_type, :aliases => ['content_type', 'Content-Type'] + + # @!attribute [rw] etag + # The MD5 checksum of file. If included file creation request, will ensure integrity of the file. + # @return [String] MD5 checksum of file. attribute :etag, :aliases => ['hash', 'Etag'] + + # @!attribute [r] last_modified + # The last time the file was modified + # @return [Time] The last time the file was modified attribute :last_modified, :aliases => ['last_modified', 'Last-Modified'], :type => :time + + # @!attribute [rw] access_control_allow_origin + # A space delimited list of URLs allowed to make Cross Origin Requests. Format is http://www.example.com. An asterisk (*) allows all. + # @return [String] string containing a list of space delimited URLs + # @see http://docs.rackspace.com/files/api/v1/cf-devguide/content/CORS_Container_Header-d1e1300.html attribute :access_control_allow_origin, :aliases => ['Access-Control-Allow-Origin'] - attribute :origin, :aliases => ['Origin'] - attr_writer :public + # @!attribute [rw] origin + # @return [String] The origin is the URI of the object's host. + # @see http://docs.rackspace.com/files/api/v1/cf-devguide/content/CORS_Container_Header-d1e1300.html + attribute :origin, :aliases => ['Origin'] + # @!attribute [r] directory + # @return [Fog::Storage::Rackspace::Directory] directory containing file attr_accessor :directory + + # @!attribute [w] public + # @note Required for compatibility with other Fog providers. Not Used. attr_writer :public + # Returns the body/contents of file + # @example Retrieve and download contents of Cloud Files object to file system + # file_object = directory.files.get('germany.jpg') + # File.open('germany.jpg', 'w') {|f| f.write(file_object.body) } def body attributes[:body] ||= if last_modified collection.get(identity).body @@ -28,10 +60,17 @@ module Fog end end + # Sets the body/contents of file + # @param [String,File] new_body contents of file def body=(new_body) attributes[:body] = new_body end + # Copy file to another directory or directory + # @param [String] target_directory_key + # @param [String] target_file_key + # @param options [Hash] used to pass in file attributes + # @see http://docs.rackspace.com/files/api/v1/cf-devguide/content/Copy_Object-d1e2241.html def copy(target_directory_key, target_file_key, options={}) requires :directory, :key options['Content-Type'] ||= content_type if content_type @@ -42,12 +81,18 @@ module Fog target_directory.files.get(target_file_key) end + # Destroy the file + # @return [Boolean] returns true if file is destroyed + # @note Directory must be empty before destroying directory + # @see http://docs.rackspace.com/files/api/v1/cf-devguide/content/Delete_Object-d1e2264.html def destroy requires :directory, :key service.delete_object(directory.key, key) true end + # Set file metadata + # @param [Hash,Fog::Storage::Rackspace::Metadata] hash contains key value pairs def metadata=(hash) if hash.is_a? Fog::Storage::Rackspace::Metadata attributes[:metadata] = hash @@ -57,10 +102,13 @@ module Fog attributes[:metadata] end + # File metadata + # @return [Fog::Storage::Rackspace::Metadata] metadata key value pairs. def metadata attributes[:metadata] ||= Fog::Storage::Rackspace::Metadata.new(self) end + # Required for compatibility with other Fog providers. Not Used. def owner=(new_owner) if new_owner attributes[:owner] = { @@ -70,22 +118,42 @@ module Fog end end + # Is file published to CDN + # @return [Boolean] return true if published to CDN def public? directory.public? end + # Returns the public url for the file. + # If the file has not been published to the CDN, this method will return nil as it is not publically accessable. This method will return the approprate + # url in the following order: + # + # 1. If the service used to access this file was created with the option :rackspace_cdn_ssl => true, this method will return the SSL-secured URL. + # 2. If the directory's cdn_cname attribute is populated this method will return the cname. + # 3. return the default CDN url. + # + # @return [String] public url for file def public_url Files::file_url directory.public_url, key end + # URL used to stream video to iOS devices without needing to convert your video + # @return [String] iOS URL + # @see http://docs.rackspace.com/files/api/v1/cf-devguide/content/iOS-Streaming-d1f3725.html def ios_url Files::file_url directory.ios_url, key end + # URL used to stream resources + # return [String] streaming url + # @see http://docs.rackspace.com/files/api/v1/cf-devguide/content/Streaming-CDN-Enabled_Containers-d1f3721.html def streaming_url Files::file_url directory.streaming_url, key end + # Immediately purge file from the CDN network + # @note You may only PURGE up to 25 objects per day. Any attempt to purge more than this will result in a 498 status code error (Rate Limited). + # @see http://docs.rackspace.com/files/api/v1/cf-devguide/content/Purge_CDN-Enabled_Objects-d1e3858.html def purge_from_cdn if public? service.cdn.purge(self) @@ -94,6 +162,9 @@ module Fog end end + # Create or updates file and associated metadata + # @param options [Hash] additional parameters to pass to Cloud Files + # @see http://docs.rackspace.com/files/api/v1/cf-devguide/content/Create_Update_Object-d1e1965.html def save(options = {}) requires :body, :directory, :key options['Content-Type'] = content_type if content_type diff --git a/lib/fog/rackspace/models/storage/files.rb b/lib/fog/rackspace/models/storage/files.rb index 4c875d1cf..9ce90013d 100644 --- a/lib/fog/rackspace/models/storage/files.rb +++ b/lib/fog/rackspace/models/storage/files.rb @@ -7,14 +7,35 @@ module Fog class Files < Fog::Collection + # @!attribute [rw] directory + # @return [String] The name of the directory + # @note Methods in this class require this attribute to be set attribute :directory + + # @!attribute [rw] limit + # @return [Integer] For an integer value n, limits the number of results to at most n values. + # @see http://docs.rackspace.com/files/api/v1/cf-devguide/content/List_Large_Number_of_Objects-d1e1521.html attribute :limit + + # @!attribute [rw] marker + # @return [String] Given a string value x, return object names greater in value than the specified marker. + # @see http://docs.rackspace.com/files/api/v1/cf-devguide/content/List_Large_Number_of_Objects-d1e1521.html attribute :marker + + # @!attribute [rw] path + # @return [String] For a string value x, return the object names nested in the pseudo path. + # Equivalent to setting delimiter to '/' and prefix to the path with a '/' on the end. attribute :path + + # @!attribute [rw] prefix + # @return [String] For a string value x, causes the results to be limited to object names beginning with the substring x. attribute :prefix model Fog::Storage::Rackspace::File + # Returns list of files + # @return [Array] Retrieves a list files. + # @see http://docs.rackspace.com/files/api/v1/cf-devguide/content/List_Objects-d1e1284.html def all(options = {}) requires :directory options = { @@ -35,6 +56,10 @@ module Fog end end + # Calls block for each file in the directory + # @yieldparam [[Fog::Storage::Rackspace::File] + # @return [Fog::Storage::Rackspace::Directory] returns itself + # @note This method retrieves files in pages. Page size is defined by the limit attribute alias :each_file_this_page :each def each if !block_given? @@ -52,6 +77,24 @@ module Fog end end + # Retrieves file + # @param [String] key of file + # @yield get yields to block after chunk of data has been received (Optional) + # @yieldparam [String] data + # @yieldparam [Integer] remaining + # @yieldparam [Integer] content_length + # @return [Fog::Storage::Rackspace:File] + # @note If a block is provided, the body attribute will be empty. By default Chunk size is 1 MB. This value can be changed by passing the parameter :chunk_size + # into the :connection_options hash in the service constructor. + # @example Download an image from Cloud Files and save it to file + # + # File.open('download.jpg', 'w') do | f | + # my_directory.files.get("europe.jpg") do |data, remaing, content_length| + # f.syswrite data + # end + # end + # + # @see http://docs.rackspace.com/files/api/v1/cf-devguide/content/Retrieve_Object-d1e1856.html def get(key, &block) requires :directory data = service.get_object(directory.key, key, &block) @@ -67,6 +110,10 @@ module Fog nil end + # Returns the public_url for the given object key + # @param key of the object + # @return [String] url for object + # @see Directory#public_url def get_url(key) requires :directory if self.directory.public_url @@ -74,6 +121,10 @@ module Fog end end + # View directory detail without loading file contents + # @param key - key of the object + # @param options Required for compatibility with other Fog providers. Not Used. + # @return [Fog::Storage::Rackspace::File] def head(key, options = {}) requires :directory data = service.head_object(directory.key, key) @@ -85,11 +136,18 @@ module Fog nil end + # Create a new file object + # @param [Hash] attributes of object + # @return [Fog::Storage::Rackspace::File] def new(attributes = {}) requires :directory super({ :directory => directory }.merge!(attributes)) end + # Returns an escaped object url + # @param [String] path of the url + # @param [String] key of the object + # @return [String] escaped file url def self.file_url(path, key) return nil unless path "#{path}/#{Fog::Rackspace.escape(key, '/')}" diff --git a/lib/fog/rackspace/models/storage/metadata.rb b/lib/fog/rackspace/models/storage/metadata.rb index f6b06eeee..9857938bb 100644 --- a/lib/fog/rackspace/models/storage/metadata.rb +++ b/lib/fog/rackspace/models/storage/metadata.rb @@ -20,20 +20,36 @@ module Fog CONTAINER_KEY_REGEX = /^#{CONTAINER_META_PREFIX}(.*)/ OBJECT_KEY_REGEX = /^#{OBJECT_META_PREFIX}(.*)/ + + # @!attribute [rw] data + # @return [Hash] underlying data store for metadata class + attr_reader :data + + # @!attribute [rw] parent + # @return [Fog::Storage::Rackspace::Directory,Fog::Storage::Rackspace::File] the parent object of the metadata + attr_reader :parent - attr_reader :data, :parent - + # Initialize + # @param [Fog::Storage::Rackspace::Directory,Fog::Storage::Rackspace::File] parent object of the metadata + # @param [Hash] hash containing initial metadata values def initialize(parent, hash={}) @data = hash || {} @deleted_hash = {} @parent = parent end - + + + # Delete key value pair from metadata + # @param [String] key to be deleted + # @return [Object] returns value for key + # @note Metadata must be deleted using this method in order to properly remove it from Cloud Files def delete(key) data.delete(key) @deleted_hash[key] = nil end - + + # Returns metadata in a format expected by Cloud Files + # @return [Hash] Metadata in a format expected by Cloud Files def to_headers headers = {} h = data.merge(@deleted_hash) @@ -45,6 +61,9 @@ module Fog headers end + # Creates metadata object from Cloud File Headers + # @param [Fog::Storage::Rackspace::Directory,Fog::Storage::Rackspace::File] parent object of the metadata + # @param [Hash] headers Cloud File headers def self.from_headers(parent, headers) metadata = Metadata.new(parent) headers.each_pair do |k, v| @@ -55,10 +74,14 @@ module Fog metadata end + # Returns true if method is implemented by Metadata class + # @param [Symbol] method_sym + # @param [Boolean] include_private def respond_to?(method_sym, include_private = false) super(method_sym, include_private) || data.respond_to?(method_sym, include_private) end - + + # Invoked by Ruby when obj is sent a message it cannot handle. def method_missing(method, *args, &block) data.send(method, *args, &block) end diff --git a/lib/fog/rackspace/storage.rb b/lib/fog/rackspace/storage.rb index 072c3c83a..52b661fb2 100644 --- a/lib/fog/rackspace/storage.rb +++ b/lib/fog/rackspace/storage.rb @@ -100,15 +100,21 @@ module Fog @connection = Fog::Connection.new("#{@scheme}://#{@host}:#{@port}", @persistent, @connection_options) end + # Return Account Details + # @return [Fog::Storage::Rackspace::Account] account details object def account account = Fog::Storage::Rackspace::Account.new(:service => self) account.reload end + # Using SSL? + # @return [Boolean] return true if service is returning SSL-Secured URLs in public_url methods + # @see Directory#public_url def ssl? !rackspace_cdn_ssl.nil? end + # Resets presistent service connections def reload @connection.reset end