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)



110
111
112
# File 'lib/cloudfiles/container.rb', line 110

def bytes
  self.[:bytes]
end

#cdn_available?Boolean

Returns:

  • (Boolean)


441
442
443
# File 'lib/cloudfiles/container.rb', line 441

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


128
129
130
# File 'lib/cloudfiles/container.rb', line 128

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



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/cloudfiles/container.rb', line 56

def 
  return @cdn_metadata if @cdn_metadata
  if cdn_available?
    @cdn_metadata = (
      begin
        response = SwiftClient.head_container(self.connection.cdnurl, self.connection.authtoken, 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,
          :cdn_log => (cdn_enabled and response["x-log-retention"] == "True") ? true : false
        }
      rescue ClientException => e
        raise CloudFiles::Exception::NoSuchContainer, "Container #{@name} does not exist" unless (e.status.to_s =~ /^20/)
      end
    )
  else
    @cdn_metadata = {}
  end
end

#cdn_ssl_urlObject

CDN SSL container URL (if container is public)



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

def cdn_ssl_url
  self.[:cdn_ssl_url]
end

#cdn_streaming_urlObject

CDN Streaming container URL (if container is public)



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

def cdn_streaming_url
  self.[:cdn_streaming_url]
end

#cdn_ttlObject

CDN container TTL (if container is public)



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

def cdn_ttl
  self.[:cdn_ttl]
end

#cdn_urlObject

CDN container URL (if container is public)



140
141
142
# File 'lib/cloudfiles/container.rb', line 140

def cdn_url
  self.[:cdn_url]
end

#container_metadataObject

Retrieves Metadata for the container



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

def 
  @metadata ||= (
    begin
      response = SwiftClient.head_container(self.connection.storageurl, self.connection.authtoken, escaped_name)
      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"]}
    rescue ClientException => e
      raise CloudFiles::Exception::NoSuchContainer, "Container #{@name} does not exist" unless (e.status.to_s =~ /^20/)
    end
  )
end

#countObject

Number of objects in the container



115
116
117
# File 'lib/cloudfiles/container.rb', line 115

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.



307
308
309
# File 'lib/cloudfiles/container.rb', line 307

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


319
320
321
322
323
324
325
326
327
# File 'lib/cloudfiles/container.rb', line 319

def delete_object(objectname)
  begin
    SwiftClient.delete_object(self.connection.storageurl, self.connection.authtoken, escaped_name, objectname)
    true
  rescue ClientException => e
    raise CloudFiles::Exception::NoSuchObject, "Object #{objectname} does not exist" if (e.status.to_s == "404")
    raise CloudFiles::Exception::InvalidResponse, "Invalid response code #{e.status}" unless (e.status.to_s =~ /^20/)
  end
end

#empty?Boolean

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

new_container.empty?
=> true

full_container.empty?
=> false

Returns:

  • (Boolean)


279
280
281
# File 'lib/cloudfiles/container.rb', line 279

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

#escaped_nameObject



445
446
447
# File 'lib/cloudfiles/container.rb', line 445

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”.



176
177
178
179
180
181
182
183
184
# File 'lib/cloudfiles/container.rb', line 176

def log_retention=(value)
  raise Exception::CDNNotAvailable unless cdn_available?
  begin
    SwiftClient.post_container(self.connection.cdnurl, self.connection.authtoken, escaped_name, {"x-log-retention" => value.to_s.capitalize})
    true
  rescue ClientException => e
    raise CloudFiles::Exception::InvalidResponse, "Invalid response code #{e.status}" unless (e.status.to_s == "201" or e.status.to_s == "202")
  end
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


396
397
398
399
400
401
402
403
404
405
406
# File 'lib/cloudfiles/container.rb', line 396

def make_private
  raise Exception::CDNNotAvailable unless cdn_available?
  headers = { "X-CDN-Enabled" => "False" }
  begin
    SwiftClient.post_container(self.connection.cdnurl, self.connection.authtoken, escaped_name, headers)
    refresh
    true
  rescue ClientException => e
    raise CloudFiles::Exception::NoSuchContainer, "Container #{@name} does not exist" unless (e.status.to_s == "201" || e.status.to_s == "202")
  end
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


342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
# File 'lib/cloudfiles/container.rb', line 342

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

  begin
    SwiftClient.put_container(self.connection.cdnurl, self.connection.authtoken, escaped_name)
  rescue ClientException => e
    raise CloudFiles::Exception::NoSuchContainer, "Container #{@name} does not exist" unless (e.status.to_s == "201" || e.status.to_s == "202")
  end
  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]

  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"}


85
86
87
88
89
# File 'lib/cloudfiles/container.rb', line 85

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


196
197
198
199
# File 'lib/cloudfiles/container.rb', line 196

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)


290
291
292
293
294
295
296
297
# File 'lib/cloudfiles/container.rb', line 290

def object_exists?(objectname)
  begin
    response = SwiftClient.head_object(self.connection.storageurl, self.connection.authtoken, escaped_name, objectname)
    true
  rescue ClientException => e
    false
  end
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.



220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'lib/cloudfiles/container.rb', line 220

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
  begin
    response = SwiftClient.get_container(self.connection.storageurl, self.connection.authtoken, escaped_name, params[:marker], params[:limit], params[:prefix], params[:delimiter])
    return response[1].collect{|o| o['name']}
  rescue ClientException => e
    raise CloudFiles::Exception::InvalidResponse, "Invalid response code #{e.status}" unless (e.status.to_s == "200")
  end
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"}
   }


255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/cloudfiles/container.rb', line 255

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
  begin 
    response = SwiftClient.get_container(self.connection.storageurl, self.connection.authtoken, escaped_name, params[:marker], params[:limit], params[:prefix], params[:delimiter])
    return Hash[*response[1].collect{|o| [o['name'],{ :bytes => o["bytes"], :hash => o["hash"], :content_type => o["content_type"], :last_modified => DateTime.parse(o["last_modified"])}] }.flatten]
  rescue ClientException => e
    raise CloudFiles::Exception::InvalidResponse, "Invalid response code #{e.status}" unless (e.status.to_s == "200")
  end
end

#post_with_headers(headers = {}) ⇒ Object



381
382
383
384
385
386
387
# File 'lib/cloudfiles/container.rb', line 381

def post_with_headers(headers = {})
  begin
    SwiftClient.post_container(cdn_enabled? ? self.connection.cdnurl : self.connection.storageurl, self.connection.authtoken, escaped_name, headers)
  rescue ClientException => e
    raise CloudFiles::Exception::NoSuchContainer, "Container #{@name} does not exist (response code: #{e.status.to_s})" unless (e.status.to_s =~ /^20/)
  end
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


425
426
427
428
429
430
431
432
433
434
435
# File 'lib/cloudfiles/container.rb', line 425

def purge_from_cdn(email=nil)
  raise Exception::CDNNotAvailable unless cdn_available?
  headers = {}
  headers = {"X-Purge-Email" => email} if email
  begin
    SwiftClient.delete_container(self.connection.cdnurl, self.connection.authtoken, escaped_name, headers)
    true
  rescue ClientException => e
    raise CloudFiles::Exception::Connection, "Error Unable to Purge Container: #{@name}" unless (e.status.to_s > "200" && e.status.to_s < "299")
  end
end

#read_aclObject

used by openstack swift



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

def read_acl
  self.[:container_read]
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.



96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/cloudfiles/container.rb', line 96

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

#set_read_acl(read_string) ⇒ Object

Only to be used with openstack swift



374
375
376
377
378
379
# File 'lib/cloudfiles/container.rb', line 374

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



366
367
368
369
370
371
# File 'lib/cloudfiles/container.rb', line 366

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

#to_sObject

:nodoc:



437
438
439
# File 'lib/cloudfiles/container.rb', line 437

def to_s # :nodoc:
  @name
end

#write_aclObject

used by openstack swift



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

def write_acl
  self.[:container_write]
end