Class: Awsum::S3

Inherits:
Object show all
Includes:
Requestable
Defined in:
lib/awsum/s3.rb,
lib/awsum/s3/bucket.rb,
lib/awsum/s3/object.rb,
lib/awsum/s3/headers.rb,
lib/awsum/s3/parsers/bucket_parser.rb

Overview

Handles all interaction with Amazon S3

– TODO: Change this to S3

Getting Started

Create an Awsum::Ec2 object and begin calling methods on it.

require 'rubygems'
require 'awsum'
ec2 = Awsum::Ec2.new('your access id', 'your secret key')
images = ec2.my_images
...

All calls to EC2 can be done directly in this class, or through a more object oriented way through the various returned classes

Examples

ec2.image('ami-ABCDEF').run

ec2.instance('i-123456789').volumes.each do |vol|
  vol.create_snapsot
end

ec2.regions.each do |region|
  region.use
    images.each do |img|
      puts "#{img.id} - #{region.name}"
    end
  end
end

Errors

All methods will raise an Awsum::Error if an error is returned from Amazon

Missing Methods

If you need any of this functionality, please consider getting involved and help complete this library.

Defined Under Namespace

Classes: Bucket, BucketParser, Headers, Object, ObjectParser

Instance Method Summary collapse

Constructor Details

#initialize(access_key = nil, secret_key = nil) ⇒ S3

Create an new S3 instance

The access_key and secret_key are both required to do any meaningful work.

If you want to get these keys from environment variables, you can do that in your code as follows:

s3 = Awsum::S3.new(ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY'])


53
54
55
56
# File 'lib/awsum/s3.rb', line 53

def initialize(access_key = nil, secret_key = nil)
  @access_key = access_key
  @secret_key = secret_key
end

Instance Method Details

#bucket(name) ⇒ Object



65
66
67
# File 'lib/awsum/s3.rb', line 65

def bucket(name)
  Bucket.new(self, name)
end

#bucketsObject

List all the Bucket(s)



59
60
61
62
63
# File 'lib/awsum/s3.rb', line 59

def buckets
  response = send_s3_request
  parser = Awsum::S3::BucketParser.new(self)
  parser.parse(response.body)
end

#copy_object(source_bucket_name, source_key, destination_bucket_name = nil, destination_key = nil, headers = nil, meta_headers = nil) ⇒ Object

Copy the contents of an Object to another key and/or bucket

Parameters

  • source_bucket_name - The name of the Bucket from which to copy

  • source_key - The name of the Key from which to copy

  • destination_bucket_name - The name of the Bucket to which to copy (Can be nil if copying within the same bucket, or updating header data of existing Key)

  • destination_key - The name of the Key to which to copy (Can be nil if copying to a new bucket with same key, or updating header data of existing Key)

  • headers - If not nil, the headers are replaced with this information

  • meta_headers - If not nil, the meta headers are replaced with this information

– TODO: Need to handle copy-if-… headers

Raises:

  • (ArgumentError)


184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/awsum/s3.rb', line 184

def copy_object(source_bucket_name, source_key, destination_bucket_name = nil, destination_key= nil, headers = nil, meta_headers = nil)
  raise ArgumentError.new('You must include one of destination_bucket_name, destination_key or headers to be replaced') if destination_bucket_name.nil? && destination_key.nil? && headers.nil? && meta_headers.nil?

  headers = {
      'x-amz-copy-source' => "/#{source_bucket_name}/#{source_key}",
      'x-amz-metadata-directive' => (((destination_bucket_name.nil? && destination_key.nil?) || !(headers.nil? || meta_headers.nil?)) ? 'REPLACE' : 'COPY')
    }.merge(headers||{})
  meta_headers.each do |k,v|
    headers[k =~ /^x-amz-meta-/i ? k : "x-amz-meta-#{k}"] = v
  end unless meta_headers.nil?

  destination_bucket_name ||= source_bucket_name
  destination_key ||= source_key

  response = send_s3_request('PUT', :bucket => destination_bucket_name, :key => destination_key, :headers => headers, :data => nil)
  if response.is_a?(Net::HTTPSuccess)
    #Check for delayed error (See http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTObjectCOPY.html#RESTObjectCOPY_Response)
    response_body = response.body
    if response_body =~ /<Error>/i
      raise Awsum::Error.new(response)
    else
      true
    end
  end
end

#create_bucket(bucket_name, location = :default) ⇒ Object

Create a new Bucket

Parameters

  • bucket_name - The name of the new bucket

  • location (optional) - Can be :default, :us or :eu

Raises:

  • (ArgumentError)


74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/awsum/s3.rb', line 74

def create_bucket(bucket_name, location = :default)
  raise ArgumentError.new('Bucket name cannot be in an ip address style') if bucket_name =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/
  raise ArgumentError.new('Bucket name can only have lowercase letters, numbers, periods (.), underscores (_) and dashes (-)') unless bucket_name =~ /^[\w\d][-a-z\d._]+[a-z\d._]$/
  raise ArgumentError.new('Bucket name cannot contain a dash (-) next to a period (.)') if bucket_name =~ /\.-|-\./
  raise ArgumentError.new('Bucket name must be between 3 and 63 characters') if bucket_name.size < 3 || bucket_name.size > 63

  data = nil
  if location == :eu
    data = '<CreateBucketConfiguration><LocationConstraint>EU</LocationConstraint></CreateBucketConfiguration>'
  end

  response = send_s3_request('PUT', :bucket => bucket_name, :data => data)
  response.is_a?(Net::HTTPSuccess)
end

#create_object(bucket_name, key, data, headers = {}, meta_headers = {}, acl = :private) ⇒ Object

Create a new Object in the specified Bucket

Parameters

  • bucket_name - The name of the Bucket in which to store the Key

  • key - The name/path of the Key to store

  • data - The data to be stored in this Object

  • headers - Standard HTTP headers to be sent along

  • meta_headers - Meta headers to be stored along with the key

  • acl - A canned access policy, can be one of :private, :public_read, :public_read_write or :authenticated_read



124
125
126
127
128
129
130
131
132
133
# File 'lib/awsum/s3.rb', line 124

def create_object(bucket_name, key, data, headers = {}, meta_headers = {}, acl = :private)
  headers = headers.dup
  meta_headers.each do |k,v|
    headers[k =~ /^x-amz-meta-/i ? k : "x-amz-meta-#{k}"] = v
  end
  headers['x-amz-acl'] = acl.to_s.gsub(/_/, '-')

  response = send_s3_request('PUT', :bucket => bucket_name, :key => key, :headers => headers, :data => data)
  response.is_a?(Net::HTTPSuccess)
end

#delete_bucket(bucket_name) ⇒ Object



89
90
91
92
# File 'lib/awsum/s3.rb', line 89

def delete_bucket(bucket_name)
  response = send_s3_request('DELETE', :bucket => bucket_name)
  response.is_a?(Net::HTTPSuccess)
end

#delete_object(bucket_name, key) ⇒ Object

Deletes an Object from a Bucket



167
168
169
170
# File 'lib/awsum/s3.rb', line 167

def delete_object(bucket_name, key)
  response = send_s3_request('DELETE', :bucket => bucket_name, :key => key)
  response.is_a?(Net::HTTPSuccess)
end

#hostObject

The host to make all requests against



212
213
214
# File 'lib/awsum/s3.rb', line 212

def host
  @host ||= 's3.amazonaws.com'
end

#host=(host) ⇒ Object



216
217
218
# File 'lib/awsum/s3.rb', line 216

def host=(host)
  @host = host
end

#keys(bucket_name, options = {}) ⇒ Object

List the Key(s) of a Bucket

Parameters

  • bucket_name - The name of the bucket to search for keys

Options

  • :prefix - Limits the response to keys which begin with the indicated prefix. You can use prefixes to separate a bucket into different sets of keys in a way similar to how a file system uses folders.

  • :marker - Indicates where in the bucket to begin listing. The list will only include keys that occur lexicographically after marker. This is convenient for pagination: To get the next page of results use the last key of the current page as the marker.

  • :max_keys - The maximum number of keys you’d like to see in the response body. The server might return fewer than this many keys, but will not return more.

  • :delimeter - Causes keys that contain the same string between the prefix and the first occurrence of the delimiter to be rolled up into a single result element in the CommonPrefixes collection. These rolled-up keys are not returned elsewhere in the response.



103
104
105
106
107
108
109
110
111
112
113
# File 'lib/awsum/s3.rb', line 103

def keys(bucket_name, options = {})
  paramters = {}
  paramters['prefix'] = options[:prefix] if options[:prefix]
  paramters['marker'] = options[:marker] if options[:marker]
  paramters['max_keys'] = options[:max_keys] if options[:max_keys]
  paramters['prefix'] = options[:prefix] if options[:prefix]

  response = send_s3_request('GET', :bucket => bucket_name, :paramters => paramters)
  parser = Awsum::S3::ObjectParser.new(self)
  parser.parse(response.body)
end

#object_data(bucket_name, key, &block) ⇒ Object

Retrieve the data stored for the specified Object

You can get the data as a single call or add a block to retrieve the data in chunks

Examples

data = s3.object_data('test-bucket', 'key')

or

s3.object_data('test-bucket', 'key') do |chunk|
  # handle chunk
  puts chunk
end


155
156
157
158
159
160
161
162
163
164
# File 'lib/awsum/s3.rb', line 155

def object_data(bucket_name, key, &block)
  send_s3_request('GET', :bucket => bucket_name, :key => key) do |response|
    if block_given?
      response.read_body &block
      return true
    else
      return response.body
    end
  end
end

#object_headers(bucket_name, key) ⇒ Object

Retrieve the headers for this Object

All header methods map directly to the Net::HTTPHeader module



138
139
140
141
# File 'lib/awsum/s3.rb', line 138

def object_headers(bucket_name, key)
  response = send_s3_request('HEAD', :bucket => bucket_name, :key => key)
  Headers.new(response)
end