Class: CloudFiles::Container

Inherits:
Object
  • Object
show all
Defined in:
lib/cloudfiles/container.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(connection, name) ⇒ Container

Retrieves an existing CloudFiles::Container object tied to the current CloudFiles::Connection. If the requested container does not exist, it will raise a CloudFiles::Exception::NoSuchContainer Exception.

Will likely not be called directly, instead use connection.container(‘container_name’) to retrieve the object.



16
17
18
19
20
21
22
# File 'lib/cloudfiles/container.rb', line 16

def initialize(connection, name)
  @connection = connection
  @name = name
  # Load the metadata now, so we'll get a CloudFiles::Exception::NoSuchContainer exception should the container
  # not exist.
  self.
end

Instance Attribute Details

#connectionObject (readonly)

The parent CloudFiles::Connection object for this container



10
11
12
# File 'lib/cloudfiles/container.rb', line 10

def connection
  @connection
end

#nameObject (readonly)

Name of the container which corresponds to the instantiated container class



7
8
9
# File 'lib/cloudfiles/container.rb', line 7

def name
  @name
end

Instance Method Details

#bytesObject

Size of the container (in bytes)



101
102
103
# File 'lib/cloudfiles/container.rb', line 101

def bytes
  self.[:bytes]
end

#cdn_available?Boolean

Returns:

  • (Boolean)


425
426
427
# File 'lib/cloudfiles/container.rb', line 425

def cdn_available?
  self.connection.cdn_available?
end

#cdn_enabledObject Also known as: cdn_enabled?, public?

Returns true if the container is public and CDN-enabled. Returns false otherwise.

Aliased as container.public?

public_container.cdn_enabled?
=> true

private_container.public?
=> false


119
120
121
# File 'lib/cloudfiles/container.rb', line 119

def cdn_enabled
  cdn_available? && self.[:cdn_enabled]
end

#cdn_logObject Also known as: log_retention?, cdn_log?

Returns true if log retention is enabled on this container, false otherwise



165
166
167
# File 'lib/cloudfiles/container.rb', line 165

def cdn_log
  self.[:cdn_log]
end

#cdn_metadataObject

Retrieves CDN-Enabled Meta Data



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/cloudfiles/container.rb', line 53

def 
  return @cdn_metadata if @cdn_metadata
  if cdn_available?
    @cdn_metadata = (
      response = self.connection.cdn_request("HEAD", escaped_name)
      cdn_enabled = ((response["x-cdn-enabled"] || "").downcase == "true") ? true : false
      {
        :cdn_enabled => cdn_enabled,
        :cdn_ttl => cdn_enabled ? response["x-ttl"].to_i : nil,
        :cdn_url => cdn_enabled ? response["x-cdn-uri"] : nil,
        :cdn_ssl_url => cdn_enabled ? response["x-cdn-ssl-uri"] : nil,
        :cdn_streaming_url => cdn_enabled ? response["x-cdn-streaming-uri"] : nil,
        :user_agent_acl => response["x-user-agent-acl"],
        :referrer_acl => response["x-referrer-acl"],
        :cdn_log => (cdn_enabled and response["x-log-retention"] == "True") ? true : false
      }
    )
  else
    @cdn_metadata = {}
  end
end

#cdn_ssl_urlObject

CDN Streaming container URL (if container is public)



136
137
138
# File 'lib/cloudfiles/container.rb', line 136

def cdn_ssl_url
  self.[:cdn_ssl_url]
end

#cdn_ttlObject

CDN container TTL (if container is public)



126
127
128
# File 'lib/cloudfiles/container.rb', line 126

def cdn_ttl
  self.[:cdn_ttl]
end

#cdn_urlObject

CDN container URL (if container is public)



131
132
133
# File 'lib/cloudfiles/container.rb', line 131

def cdn_url
  self.[:cdn_url]
end

#container_metadataObject

Retrieves Metadata for the container



42
43
44
45
46
47
48
49
50
# File 'lib/cloudfiles/container.rb', line 42

def 
  @metadata ||= (
    response = self.connection.storage_request("HEAD", "#{escaped_name}/")
    raise CloudFiles::Exception::NoSuchContainer, "Container #{@name} does not exist" unless (response.code =~ /^20/)
    resphash = {}
    response.to_hash.select { |k,v| k.match(/^x-container-meta/) }.each { |x| resphash[x[0]] = x[1].to_s }
    {:bytes => response["x-container-bytes-used"].to_i, :count => response["x-container-object-count"].to_i, :metadata => resphash, :container_read => response["x-container-read"], :container_write => response["x-container-write"]}
  )
end

#countObject

Number of objects in the container



106
107
108
# File 'lib/cloudfiles/container.rb', line 106

def count
  self.[:count]
end

#create_object(objectname, make_path = false) ⇒ Object

Creates a new CloudFiles::StorageObject in the current container.

If an object with the specified name exists in the current container, that object will be returned. Otherwise, an empty new object will be returned.

Passing in the optional make_path argument as true will create zero-byte objects to simulate a filesystem path to the object, if an objectname with path separators (“/path/to/myfile.mp3”) is supplied. These path objects can be used in the Container.objects method.



301
302
303
# File 'lib/cloudfiles/container.rb', line 301

def create_object(objectname, make_path = false)
  CloudFiles::StorageObject.new(self, objectname, false, make_path)
end

#delete_object(objectname) ⇒ Object

Removes an CloudFiles::StorageObject from a container. True is returned if the removal is successful. Throws NoSuchObjectException if the object doesn’t exist. Throws InvalidResponseException if the request fails.

container.delete_object('new.txt')
=> true

container.delete_object('nonexistent_file.txt')
=> NoSuchObjectException: Object nonexistent_file.txt does not exist


313
314
315
316
317
318
# File 'lib/cloudfiles/container.rb', line 313

def delete_object(objectname)
  response = self.connection.storage_request("DELETE", "#{escaped_name}/#{CloudFiles.escape objectname}")
  raise CloudFiles::Exception::NoSuchObject, "Object #{objectname} does not exist" if (response.code == "404")
  raise CloudFiles::Exception::InvalidResponse, "Invalid response code #{response.code}" unless (response.code =~ /^20/)
  true
end

#empty?Boolean

Returns true if a container is empty and returns false otherwise.

new_container.empty?
=> true

full_container.empty?
=> false

Returns:

  • (Boolean)


277
278
279
# File 'lib/cloudfiles/container.rb', line 277

def empty?
  return ([:count].to_i == 0)? true : false
end

#escaped_nameObject



429
430
431
# File 'lib/cloudfiles/container.rb', line 429

def escaped_name
  CloudFiles.escape(@name)
end

#log_retention=(value) ⇒ Object

Change the log retention status for this container. Values are true or false.

These logs will be periodically (at unpredictable intervals) compressed and uploaded to a “.CDN_ACCESS_LOGS” container in the form of “container_name.YYYYMMDDHH-XXXX.gz”.



175
176
177
178
179
180
# File 'lib/cloudfiles/container.rb', line 175

def log_retention=(value)
  raise Exception::CDNNotAvailable unless cdn_available?
  response = self.connection.cdn_request("POST", escaped_name, {"x-log-retention" => value.to_s.capitalize})
  raise CloudFiles::Exception::InvalidResponse, "Invalid response code #{response.code}" unless (response.code == "201" or response.code == "202")
  return true
end

#make_privateObject

Makes a container private and returns true upon success. Throws NoSuchContainerException if the container doesn’t exist or if the request fails.

Note that if the container was previously public, it will continue to exist out on the CDN until it expires.

container.make_private
=> true


386
387
388
389
390
391
392
393
# File 'lib/cloudfiles/container.rb', line 386

def make_private
  raise Exception::CDNNotAvailable unless cdn_available?
  headers = { "X-CDN-Enabled" => "False" }
  response = self.connection.cdn_request("POST", escaped_name, headers)
  raise CloudFiles::Exception::NoSuchContainer, "Container #{@name} does not exist" unless (response.code == "201" || response.code == "202")
  refresh
  true
end

#make_public(options = {:ttl => 86400}) ⇒ Object

Makes a container publicly available via the Cloud Files CDN and returns true upon success. Throws NoSuchContainerException if the container doesn’t exist or if the request fails.

Takes an optional hash of options, including:

:ttl, which is the CDN cache TTL in seconds (default 86400 seconds or 1 day, minimum 3600 or 1 hour, maximum 259200 or 3 days)

:user_agent_acl, a Perl-compatible regular expression limiting access to this container to user agents matching the given regular expression

:referrer_acl, a Perl-compatible regular expression limiting access to this container to HTTP referral URLs matching the given regular expression

container.make_public(:ttl => 8900, :user_agent_acl => "/Mozilla/", :referrer_acl => "/^http://rackspace.com")
=> true


333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
# File 'lib/cloudfiles/container.rb', line 333

def make_public(options = {:ttl => 86400})
  raise Exception::CDNNotAvailable unless cdn_available?
  if options.is_a?(Fixnum)
    print "DEPRECATED: make_public takes a hash of options now, instead of a TTL number"
    ttl = options
    options = {:ttl => ttl}
  end

  response = self.connection.cdn_request("PUT", escaped_name)
  raise CloudFiles::Exception::NoSuchContainer, "Container #{@name} does not exist" unless (response.code == "201" || response.code == "202")

  headers = { "X-TTL" => options[:ttl].to_s , "X-CDN-Enabled" => "True" }
  headers["X-User-Agent-ACL"] = options[:user_agent_acl] if options[:user_agent_acl]
  headers["X-Referrer-ACL"] = options[:referrer_acl] if options[:referrer_acl]
  response = post_with_headers(headers)
  raise CloudFiles::Exception::NoSuchContainer, "Container #{@name} does not exist" unless (response.code == "201" || response.code == "202")
  refresh
  true
end

#metadataObject

Returns the container’s metadata as a nicely formatted hash, stripping off the X-Meta-Object- prefix that the system prepends to the key name.

object.metadata
=> {"ruby"=>"cool", "foo"=>"bar"}


80
81
82
83
84
# File 'lib/cloudfiles/container.rb', line 80

def 
  metahash = {}
  self.[:metadata].each{ |key, value| metahash[key.gsub(/x-container-meta-/, '').gsub(/%20/, ' ')] = URI.decode(value).gsub(/\+\-/, ' ') }
  metahash
end

#object(objectname) ⇒ Object Also known as: get_object

Returns the CloudFiles::StorageObject for the named object. Refer to the CloudFiles::StorageObject class for available methods. If the object exists, it will be returned. If the object does not exist, a NoSuchObjectException will be thrown.

object = container.object('test.txt')
object.data
=> "This is test data"

object = container.object('newfile.txt')
=> NoSuchObjectException: Object newfile.txt does not exist


192
193
194
195
# File 'lib/cloudfiles/container.rb', line 192

def object(objectname)
  o = CloudFiles::StorageObject.new(self, objectname, true)
  return o
end

#object_exists?(objectname) ⇒ Boolean

Returns true if object exists and returns false otherwise.

container.object_exists?('goodfile.txt')
=> true

container.object_exists?('badfile.txt')
=> false

Returns:

  • (Boolean)


288
289
290
291
# File 'lib/cloudfiles/container.rb', line 288

def object_exists?(objectname)
  response = self.connection.storage_request("HEAD", "#{escaped_name}/#{CloudFiles.escape objectname}")
  return (response.code =~ /^20/)? true : false
end

#objects(params = {}) ⇒ Object Also known as: list_objects

Gathers a list of all available objects in the current container and returns an array of object names.

container = cf.container("My Container")
container.objects                     #=> [ "cat", "dog", "donkey", "monkeydir", "monkeydir/capuchin"]

Pass a limit argument to limit the list to a number of objects:

container.objects(:limit => 1)                  #=> [ "cat" ]

Pass an marker with or without a limit to start the list at a certain object:

container.objects(:limit => 1, :marker => 'dog')                #=> [ "donkey" ]

Pass a prefix to search for objects that start with a certain string:

container.objects(:prefix => "do")       #=> [ "dog", "donkey" ]

Only search within a certain pseudo-filesystem path:

container.objects(:path => 'monkeydir')     #=> ["monkeydir/capuchin"]

Only grab “virtual directories”, based on a single-character delimiter (no “directory” objects required):

container.objects(:delimiter => '/')      #=> ["monkeydir"]

All arguments to this method are optional.

Returns an empty array if no object exist in the container. Throws an InvalidResponseException if the request fails.



216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/cloudfiles/container.rb', line 216

def objects(params = {})
  params[:marker] ||= params[:offset] unless params[:offset].nil?
  query = []
  params.each do |param, value|
    if [:limit, :marker, :prefix, :path, :delimiter].include? param
      query << "#{param}=#{CloudFiles.escape(value.to_s)}"
    end
  end
  response = self.connection.storage_request("GET", "#{escaped_name}?#{query.join '&'}")
  return [] if (response.code == "204")
  raise CloudFiles::Exception::InvalidResponse, "Invalid response code #{response.code}" unless (response.code == "200")
  return CloudFiles.lines(response.body)
end

#objects_detail(params = {}) ⇒ Object Also known as: list_objects_info

Retrieves a list of all objects in the current container along with their size in bytes, hash, and content_type. If no objects exist, an empty hash is returned. Throws an InvalidResponseException if the request fails. Takes a parameter hash as an argument, in the same form as the objects method.

Accepts the same options as objects to limit the returned set.

Returns a hash in the same format as the containers_detail from the CloudFiles class.

container.objects_detail
=> {"test.txt"=>{:content_type=>"application/octet-stream",
                 :hash=>"e2a6fcb4771aa3509f6b27b6a97da55b",
                 :last_modified=>Mon Jan 19 10:43:36 -0600 2009,
                 :bytes=>"16"},
    "new.txt"=>{:content_type=>"application/octet-stream",
                :hash=>"0aa820d91aed05d2ef291d324e47bc96",
                :last_modified=>Wed Jan 28 10:16:26 -0600 2009,
                :bytes=>"22"}
   }


249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'lib/cloudfiles/container.rb', line 249

def objects_detail(params = {})
  params[:marker] ||= params[:offset] unless params[:offset].nil?
  query = ["format=xml"]
  params.each do |param, value|
    if [:limit, :marker, :prefix, :path, :delimiter].include? param
      query << "#{param}=#{CloudFiles.escape(value.to_s)}"
    end
  end
  response = self.connection.storage_request("GET", "#{escaped_name}?#{query.join '&'}")
  return {} if (response.code == "204")
  raise CloudFiles::Exception::InvalidResponse, "Invalid response code #{response.code}" unless (response.code == "200")
  doc = REXML::Document.new(response.body)
  detailhash = {}
  doc.elements.each("container/object") { |o|
    detailhash[o.elements["name"].text] = { :bytes => o.elements["bytes"].text, :hash => o.elements["hash"].text, :content_type => o.elements["content_type"].text, :last_modified => DateTime.parse(o.elements["last_modified"].text) }
  }
  doc = nil
  return detailhash
end

#post_with_headers(headers = {}) ⇒ Object



369
370
371
372
373
374
375
376
377
# File 'lib/cloudfiles/container.rb', line 369

def post_with_headers(headers = {})
  if cdn_enabled?
    response = self.connection.cdn_request("POST", escaped_name, headers)
  else
    response = self.connection.storage_request("POST", escaped_name, headers)
  end
  raise CloudFiles::Exception::NoSuchContainer, "Container #{@name} does not exist (response code: #{response.code})" unless (response.code =~ /^20/)
  response
end

#purge_from_cdn(email = nil) ⇒ Object

Purges CDN Edge Cache for all objects inside of this container

:email, An valid email address or comma seperated

list of emails to be notified once purge is complete .

 container.purge_from_cdn
 => true

or 

 container.purge_from_cdn("[email protected]")
 => true

or

 container.purge_from_cdn("[email protected], [email protected]")
 => true


412
413
414
415
416
417
418
419
# File 'lib/cloudfiles/container.rb', line 412

def purge_from_cdn(email=nil)
  raise Exception::CDNNotAvailable unless cdn_available?
  headers = {}
  headers = {"X-Purge-Email" => email} if email
  response = self.connection.cdn_request("DELETE", escaped_name, headers)
  raise CloudFiles::Exception::Connection, "Error Unable to Purge Container: #{@name}" unless (response.code > "200" && response.code < "299")
  true
end

#read_aclObject

used by openstack swift



155
156
157
# File 'lib/cloudfiles/container.rb', line 155

def read_acl
  self.[:container_read]
end

#referrer_aclObject

The container ACL on the site Referrer



150
151
152
# File 'lib/cloudfiles/container.rb', line 150

def referrer_acl
  self.[:referrer_acl]
end

#refreshObject Also known as: populate

Refreshes data about the container and populates class variables. Items are otherwise loaded in a lazy loaded fashion.

container.count
=> 2
[Upload new file to the container]
container.count
=> 2
container.populate
container.count
=> 3


35
36
37
38
# File 'lib/cloudfiles/container.rb', line 35

def refresh
  @metadata = @cdn_metadata = nil
  true
end

#set_metadata(metadatahash) ⇒ Object

Sets the metadata for an object. By passing a hash as an argument, you can set the metadata for an object. New calls to set metadata are additive. To remove metadata, set the value of the key to nil.

Throws NoSuchObjectException if the container doesn’t exist. Throws InvalidResponseException if the request fails.



91
92
93
94
95
96
97
98
# File 'lib/cloudfiles/container.rb', line 91

def (metadatahash)
  headers = {}
  metadatahash.each{ |key, value| headers['X-Container-Meta-' + CloudFiles.escape(key.to_s.capitalize)] = value.to_s }
  response = self.connection.storage_request("POST", escaped_name, headers)
  raise CloudFiles::Exception::NoSuchObject, "Container #{@name} does not exist" if (response.code == "404")
  raise CloudFiles::Exception::InvalidResponse, "Invalid response code #{response.code}" unless (response.code =~ /^20/)
  true
end

#set_read_acl(read_string) ⇒ Object

Only to be used with openstack swift



362
363
364
365
366
367
# File 'lib/cloudfiles/container.rb', line 362

def set_read_acl(read_string)
  refresh
  headers = {"X-Container-Read" => read_string}
  post_with_headers(headers)
  true
end

#set_write_acl(write_string) ⇒ Object

Only to be used with openstack swift



354
355
356
357
358
359
# File 'lib/cloudfiles/container.rb', line 354

def set_write_acl(write_string)
  refresh
  headers = {"X-Container-Write" => write_string}
  post_with_headers(headers)
  true
end

#to_sObject

:nodoc:



421
422
423
# File 'lib/cloudfiles/container.rb', line 421

def to_s # :nodoc:
  @name
end

#user_agent_aclObject

The container ACL on the User Agent



145
146
147
# File 'lib/cloudfiles/container.rb', line 145

def user_agent_acl
  self.[:user_agent_acl]
end

#write_aclObject

used by openstack swift



160
161
162
# File 'lib/cloudfiles/container.rb', line 160

def write_acl
  self.[:container_write]
end