aws 2.3.21 → 2.3.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.markdown +5 -4
- data/lib/acf/right_acf_interface.rb +3 -3
- data/lib/ec2/right_ec2.rb +76 -1
- data/lib/s3/right_s3.rb +996 -987
- data/lib/s3/right_s3_interface.rb +60 -56
- data/test/ec2/test_ec2.rb +83 -2
- metadata +27 -33
data/README.markdown
CHANGED
|
@@ -69,9 +69,10 @@ The RightScale AWS gems comprise:
|
|
|
69
69
|
|
|
70
70
|
## THREADING:
|
|
71
71
|
|
|
72
|
-
All
|
|
73
|
-
1. Use a single persistent HTTP connection per process.
|
|
74
|
-
2. Use a persistent HTTP connection per Ruby thread.
|
|
72
|
+
All AWS interfaces offer three threading options:
|
|
73
|
+
1. Use a single persistent HTTP connection per process. :single
|
|
74
|
+
2. Use a persistent HTTP connection per Ruby thread. :per_thread
|
|
75
|
+
3. Open a new connection for each request. :per_request
|
|
75
76
|
|
|
76
77
|
Either way, it doesn't matter how many (for example) Aws::S3 objects you create,
|
|
77
78
|
they all use the same per-program or per-thread
|
|
@@ -91,7 +92,7 @@ Note that due to limitations in the I/O of the Ruby interpreter you
|
|
|
91
92
|
may not get the degree of parallelism you may expect with the multi-threaded setting.
|
|
92
93
|
|
|
93
94
|
By default, EC2/S3/SQS/SDB/ACF interface instances are created in single-threaded mode. Set
|
|
94
|
-
params[:connection_mode] to :
|
|
95
|
+
params[:connection_mode] to :per_thread in the initialization arguments to use
|
|
95
96
|
multithreaded mode.
|
|
96
97
|
|
|
97
98
|
## GETTING STARTED:
|
|
@@ -76,10 +76,10 @@ module Aws
|
|
|
76
76
|
|
|
77
77
|
include AwsBaseInterface
|
|
78
78
|
|
|
79
|
-
API_VERSION = "
|
|
79
|
+
API_VERSION = "2010-08-01"
|
|
80
80
|
DEFAULT_HOST = 'cloudfront.amazonaws.com'
|
|
81
|
-
DEFAULT_PORT =
|
|
82
|
-
DEFAULT_PROTOCOL = '
|
|
81
|
+
DEFAULT_PORT = 443
|
|
82
|
+
DEFAULT_PROTOCOL = 'https'
|
|
83
83
|
DEFAULT_PATH = '/'
|
|
84
84
|
|
|
85
85
|
@@bench = AwsBenchmarkingBlock.new
|
data/lib/ec2/right_ec2.rb
CHANGED
|
@@ -68,7 +68,7 @@ module Aws
|
|
|
68
68
|
include AwsBaseInterface
|
|
69
69
|
|
|
70
70
|
# Amazon EC2 API version being used
|
|
71
|
-
API_VERSION = "
|
|
71
|
+
API_VERSION = "2010-08-31"
|
|
72
72
|
DEFAULT_HOST = "ec2.amazonaws.com"
|
|
73
73
|
DEFAULT_PATH = '/'
|
|
74
74
|
DEFAULT_PROTOCOL = 'https'
|
|
@@ -1252,6 +1252,59 @@ module Aws
|
|
|
1252
1252
|
rescue Exception
|
|
1253
1253
|
on_exception
|
|
1254
1254
|
end
|
|
1255
|
+
|
|
1256
|
+
# Add/replace one tag to a resource
|
|
1257
|
+
# http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference_query_CreateTags.html
|
|
1258
|
+
#
|
|
1259
|
+
# ec2.create_tag('ami-1a2b3c4d', 'webserver') #=> true
|
|
1260
|
+
# ec2.create_tag('i-7f4d3a2b', 'stack', 'Production') #=> true
|
|
1261
|
+
#
|
|
1262
|
+
def create_tag(resource_id, key, value = nil)
|
|
1263
|
+
link = generate_request("CreateTags",
|
|
1264
|
+
"ResourceId.1" => resource_id.to_s,
|
|
1265
|
+
"Tag.1.Key" => key.to_s,
|
|
1266
|
+
"Tag.1.Value" => value.to_s)
|
|
1267
|
+
request_info(link, RightBoolResponseParser.new(:logger => @logger))
|
|
1268
|
+
rescue Exception
|
|
1269
|
+
on_exception
|
|
1270
|
+
end
|
|
1271
|
+
|
|
1272
|
+
# Describe tags
|
|
1273
|
+
# http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference_query_DescribeTags.html
|
|
1274
|
+
#
|
|
1275
|
+
# ec2.describe_tags
|
|
1276
|
+
# ec2.describe_tags(
|
|
1277
|
+
# 'Filter.1.Name' => 'resource-type', 'Filter.1.Value.1' => 'instance',
|
|
1278
|
+
# 'Filter.2.Name' => 'value', 'Filter.2.Value.1' => 'Test', 'Filter.2.Value.2' => 'Production'
|
|
1279
|
+
# )
|
|
1280
|
+
#
|
|
1281
|
+
def describe_tags(filters = {})
|
|
1282
|
+
link = generate_request("DescribeTags", filters)
|
|
1283
|
+
request_info(link, QEc2DescribeTagsParser.new(:logger => @logger))
|
|
1284
|
+
rescue Exception
|
|
1285
|
+
on_exception
|
|
1286
|
+
end
|
|
1287
|
+
|
|
1288
|
+
# Delete one or all tags from a resource
|
|
1289
|
+
# http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference_query_DeleteTags.html
|
|
1290
|
+
#
|
|
1291
|
+
# ec2.delete_tag('i-7f4d3a2b', 'stack') #=> true
|
|
1292
|
+
# ec2.delete_tag('i-7f4d3a2b', 'stack', 'Production') #=> true
|
|
1293
|
+
#
|
|
1294
|
+
# "If you omit Tag.n.Value, we delete the tag regardless of its value. If
|
|
1295
|
+
# you specify this parameter with an empty string as the value, we delete the
|
|
1296
|
+
# key only if its value is an empty string."
|
|
1297
|
+
# http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference_query_DeleteTags.html
|
|
1298
|
+
#
|
|
1299
|
+
def delete_tag(resource_id, key, value = nil)
|
|
1300
|
+
request_args = {"ResourceId.1" => resource_id.to_s, "Tag.1.Key" => key.to_s}
|
|
1301
|
+
request_args["Tag.1.Value"] = value.to_s if value
|
|
1302
|
+
|
|
1303
|
+
link = generate_request("DeleteTags", request_args)
|
|
1304
|
+
request_info(link, RightBoolResponseParser.new(:logger => @logger))
|
|
1305
|
+
rescue Exception
|
|
1306
|
+
on_exception
|
|
1307
|
+
end
|
|
1255
1308
|
|
|
1256
1309
|
#-----------------------------------------------------------------
|
|
1257
1310
|
# PARSERS: Boolean Response Parser
|
|
@@ -1792,6 +1845,28 @@ module Aws
|
|
|
1792
1845
|
end
|
|
1793
1846
|
end
|
|
1794
1847
|
|
|
1848
|
+
#-----------------------------------------------------------------
|
|
1849
|
+
# PARSERS: Tags
|
|
1850
|
+
#-----------------------------------------------------------------
|
|
1851
|
+
|
|
1852
|
+
class QEc2DescribeTagsParser < AwsParser #:nodoc:
|
|
1853
|
+
def tagstart(name, attributes)
|
|
1854
|
+
@tag = {} if name == 'item'
|
|
1855
|
+
end
|
|
1856
|
+
def tagend(name)
|
|
1857
|
+
case name
|
|
1858
|
+
when 'resourceId' then @tag[:aws_resource_id] = @text
|
|
1859
|
+
when 'resourceType' then @tag[:aws_resource_type] = @text
|
|
1860
|
+
when 'key' then @tag[:aws_key] = @text
|
|
1861
|
+
when 'value' then @tag[:aws_value] = @text
|
|
1862
|
+
when 'item' then @result << @tag
|
|
1863
|
+
end
|
|
1864
|
+
end
|
|
1865
|
+
def reset
|
|
1866
|
+
@result = []
|
|
1867
|
+
end
|
|
1868
|
+
end
|
|
1869
|
+
|
|
1795
1870
|
end
|
|
1796
1871
|
|
|
1797
1872
|
end
|
data/lib/s3/right_s3.rb
CHANGED
|
@@ -23,878 +23,886 @@
|
|
|
23
23
|
|
|
24
24
|
module Aws
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
#
|
|
33
|
-
# See examples below for the bucket and buckets methods.
|
|
34
|
-
#
|
|
35
|
-
# Error handling: all operations raise an Aws::AwsError in case
|
|
36
|
-
# of problems. Note that transient errors are automatically retried.
|
|
37
|
-
#
|
|
38
|
-
# It is a good way to use domain naming style getting a name for the buckets.
|
|
39
|
-
# See http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingBucket.html
|
|
40
|
-
# about the naming convention for the buckets. This case they can be accessed using a virtual domains.
|
|
41
|
-
#
|
|
42
|
-
# Let assume you have 3 buckets: 'awesome-bucket', 'awesome_bucket' and 'AWEsomE-bucket'.
|
|
43
|
-
# The first ones objects can be accessed as: http:// awesome-bucket.s3.amazonaws.com/key/object
|
|
44
|
-
#
|
|
45
|
-
# But the rest have to be accessed as:
|
|
46
|
-
# http:// s3.amazonaws.com/awesome_bucket/key/object and http:// s3.amazonaws.com/AWEsomE-bucket/key/object
|
|
47
|
-
#
|
|
48
|
-
# See: http://docs.amazonwebservices.com/AmazonS3/2006-03-01/VirtualHosting.html for better explanation.
|
|
49
|
-
#
|
|
50
|
-
class S3
|
|
51
|
-
attr_reader :interface
|
|
52
|
-
|
|
53
|
-
# Create a new handle to an S3 account. All handles share the same per process or per thread
|
|
54
|
-
# HTTP connection to Amazon S3. Each handle is for a specific account.
|
|
55
|
-
# The +params+ are passed through as-is to Aws::S3Interface.new
|
|
26
|
+
# = Aws::S3 -- RightScale's Amazon S3 interface
|
|
27
|
+
# The Aws::S3 class provides a complete interface to Amazon's Simple
|
|
28
|
+
# Storage Service.
|
|
29
|
+
# For explanations of the semantics
|
|
30
|
+
# of each call, please refer to Amazon's documentation at
|
|
31
|
+
# http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=48
|
|
56
32
|
#
|
|
57
|
-
#
|
|
33
|
+
# See examples below for the bucket and buckets methods.
|
|
58
34
|
#
|
|
59
|
-
#
|
|
60
|
-
#
|
|
61
|
-
# :protocol => 'https' # Amazon service protocol: 'http' or 'https'(default)
|
|
62
|
-
# :multi_thread => true|false # Multi-threaded (connection per each thread): true or false(default)
|
|
63
|
-
# :logger => Logger Object} # Logger instance: logs to STDOUT if omitted }
|
|
64
|
-
def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
|
|
65
|
-
@interface = S3Interface.new(aws_access_key_id, aws_secret_access_key, params)
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def close_connection
|
|
69
|
-
@interface.close_connection
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# Retrieve a list of buckets.
|
|
73
|
-
# Returns an array of Aws::S3::Bucket instances.
|
|
74
|
-
# # Create handle to S3 account
|
|
75
|
-
# s3 = Aws::S3.new(aws_access_key_id, aws_secret_access_key)
|
|
76
|
-
# my_buckets_names = s3.buckets.map{|b| b.name}
|
|
77
|
-
# puts "Buckets on S3: #{my_bucket_names.join(', ')}"
|
|
78
|
-
def buckets
|
|
79
|
-
@interface.list_all_my_buckets.map! do |entry|
|
|
80
|
-
owner = Owner.new(entry[:owner_id], entry[:owner_display_name])
|
|
81
|
-
Bucket.new(self, entry[:name], entry[:creation_date], owner)
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
# Retrieve an individual bucket.
|
|
86
|
-
# If the bucket does not exist and +create+ is set, a new bucket
|
|
87
|
-
# is created on S3. Launching this method with +create+=+true+ may
|
|
88
|
-
# affect on the bucket's ACL if the bucket already exists.
|
|
89
|
-
# Returns a Aws::S3::Bucket instance or +nil+ if the bucket does not exist
|
|
90
|
-
# and +create+ is not set.
|
|
35
|
+
# Error handling: all operations raise an Aws::AwsError in case
|
|
36
|
+
# of problems. Note that transient errors are automatically retried.
|
|
91
37
|
#
|
|
92
|
-
#
|
|
93
|
-
#
|
|
94
|
-
#
|
|
95
|
-
# ...
|
|
96
|
-
# bucket2 = s3.bucket('my_awesome_bucket_2', true)
|
|
97
|
-
# bucket2.keys #=> list of keys
|
|
98
|
-
# # create a bucket at the European location with public read access
|
|
99
|
-
# bucket3 = s3.bucket('my-awesome-bucket-3', true, 'public-read', :location => :eu)
|
|
38
|
+
# It is a good way to use domain naming style getting a name for the buckets.
|
|
39
|
+
# See http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingBucket.html
|
|
40
|
+
# about the naming convention for the buckets. This case they can be accessed using a virtual domains.
|
|
100
41
|
#
|
|
101
|
-
#
|
|
102
|
-
#
|
|
42
|
+
# Let assume you have 3 buckets: 'awesome-bucket', 'awesome_bucket' and 'AWEsomE-bucket'.
|
|
43
|
+
# The first ones objects can be accessed as: http:// awesome-bucket.s3.amazonaws.com/key/object
|
|
103
44
|
#
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
# ...
|
|
130
|
-
# bucket2 = Aws::S3::Bucket.create(s3, 'my_awesome_bucket_2', true)
|
|
131
|
-
# bucket2.keys #=> list of keys
|
|
132
|
-
# # create a bucket at the European location with public read access
|
|
133
|
-
# bucket3 = Aws::S3::Bucket.create(s3,'my-awesome-bucket-3', true, 'public-read', :location => :eu)
|
|
134
|
-
#
|
|
135
|
-
# see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAccessPolicy.html
|
|
136
|
-
# (section: Canned Access Policies)
|
|
137
|
-
#
|
|
138
|
-
def self.create(s3, name, create=false, perms=nil, headers={})
|
|
139
|
-
s3.bucket(name, create, perms, headers)
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
# Create a bucket instance. In normal use this method should
|
|
144
|
-
# not be called directly.
|
|
145
|
-
# Use Aws::S3::Bucket.create or Aws::S3.bucket instead.
|
|
146
|
-
def initialize(s3, name, creation_date=nil, owner=nil)
|
|
147
|
-
@s3 = s3
|
|
148
|
-
@name = name
|
|
149
|
-
@owner = owner
|
|
150
|
-
@creation_date = creation_date
|
|
151
|
-
if @creation_date && !@creation_date.is_a?(Time)
|
|
152
|
-
@creation_date = Time.parse(@creation_date)
|
|
45
|
+
# But the rest have to be accessed as:
|
|
46
|
+
# http:// s3.amazonaws.com/awesome_bucket/key/object and http:// s3.amazonaws.com/AWEsomE-bucket/key/object
|
|
47
|
+
#
|
|
48
|
+
# See: http://docs.amazonwebservices.com/AmazonS3/2006-03-01/VirtualHosting.html for better explanation.
|
|
49
|
+
#
|
|
50
|
+
class S3
|
|
51
|
+
attr_reader :interface
|
|
52
|
+
|
|
53
|
+
# Create a new handle to an S3 account. All handles share the same per process or per thread
|
|
54
|
+
# HTTP connection to Amazon S3. Each handle is for a specific account.
|
|
55
|
+
# The +params+ are passed through as-is to Aws::S3Interface.new
|
|
56
|
+
#
|
|
57
|
+
# Params is a hash:
|
|
58
|
+
#
|
|
59
|
+
# {:server => 's3.amazonaws.com' # Amazon service host: 's3.amazonaws.com'(default)
|
|
60
|
+
# :port => 443 # Amazon service port: 80 or 443(default)
|
|
61
|
+
# :protocol => 'https' # Amazon service protocol: 'http' or 'https'(default)
|
|
62
|
+
# :connection_mode => :default # options are
|
|
63
|
+
# :default (will use best known safe (as in won't need explicit close) option, may change in the future)
|
|
64
|
+
# :per_request (opens and closes a connection on every request)
|
|
65
|
+
# :single (one thread across entire app)
|
|
66
|
+
# :per_thread (one connection per thread)
|
|
67
|
+
# :logger => Logger Object} # Logger instance: logs to STDOUT if omitted }
|
|
68
|
+
def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
|
|
69
|
+
@interface = S3Interface.new(aws_access_key_id, aws_secret_access_key, params)
|
|
153
70
|
end
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
# Return bucket name as a String.
|
|
157
|
-
#
|
|
158
|
-
# bucket = Aws::S3.bucket('my_awesome_bucket')
|
|
159
|
-
# puts bucket #=> 'my_awesome_bucket'
|
|
160
|
-
#
|
|
161
|
-
def to_s
|
|
162
|
-
@name.to_s
|
|
163
|
-
end
|
|
164
|
-
alias_method :full_name, :to_s
|
|
165
71
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
# bucket.public_link #=> 'https://s3.amazonaws.com:443/my_awesome_bucket'
|
|
169
|
-
#
|
|
170
|
-
def public_link
|
|
171
|
-
params = @s3.interface.params
|
|
172
|
-
"#{params[:protocol]}://#{params[:server]}:#{params[:port]}/#{full_name}"
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
# Returns the bucket location
|
|
176
|
-
def location
|
|
177
|
-
@location ||= @s3.interface.bucket_location(@name)
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
# Retrieves the logging configuration for a bucket.
|
|
181
|
-
# Returns a hash of {:enabled, :targetbucket, :targetprefix}
|
|
182
|
-
#
|
|
183
|
-
# bucket.logging_info()
|
|
184
|
-
# => {:enabled=>true, :targetbucket=>"mylogbucket", :targetprefix=>"loggylogs/"}
|
|
185
|
-
def logging_info
|
|
186
|
-
@s3.interface.get_logging_parse(:bucket => @name)
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
# Enables S3 server access logging on a bucket. The target bucket must have been properly configured to receive server
|
|
190
|
-
# access logs.
|
|
191
|
-
# Params:
|
|
192
|
-
# :targetbucket - either the target bucket object or the name of the target bucket
|
|
193
|
-
# :targetprefix - the prefix under which all logs should be stored
|
|
194
|
-
#
|
|
195
|
-
# bucket.enable_logging(:targetbucket=>"mylogbucket", :targetprefix=>"loggylogs/")
|
|
196
|
-
# => true
|
|
197
|
-
def enable_logging(params)
|
|
198
|
-
AwsUtils.mandatory_arguments([:targetbucket, :targetprefix], params)
|
|
199
|
-
AwsUtils.allow_only([:targetbucket, :targetprefix], params)
|
|
200
|
-
xmldoc = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><BucketLoggingStatus xmlns=\"http://doc.s3.amazonaws.com/2006-03-01\"><LoggingEnabled><TargetBucket>#{params[:targetbucket]}</TargetBucket><TargetPrefix>#{params[:targetprefix]}</TargetPrefix></LoggingEnabled></BucketLoggingStatus>"
|
|
201
|
-
@s3.interface.put_logging(:bucket => @name, :xmldoc => xmldoc)
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
# Disables S3 server access logging on a bucket. Takes no arguments.
|
|
205
|
-
def disable_logging
|
|
206
|
-
xmldoc = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><BucketLoggingStatus xmlns=\"http://doc.s3.amazonaws.com/2006-03-01\"></BucketLoggingStatus>"
|
|
207
|
-
@s3.interface.put_logging(:bucket => @name, :xmldoc => xmldoc)
|
|
208
|
-
end
|
|
209
|
-
|
|
210
|
-
# Retrieve a group of keys from Amazon.
|
|
211
|
-
# +options+ is a hash: { 'prefix'=>'', 'marker'=>'', 'max-keys'=>5, 'delimiter'=>'' }).
|
|
212
|
-
# Retrieves meta-headers information if +head+ it +true+.
|
|
213
|
-
# Returns an array of Key instances.
|
|
214
|
-
#
|
|
215
|
-
# bucket.keys #=> # returns all keys from bucket
|
|
216
|
-
# bucket.keys('prefix' => 'logs') #=> # returns all keys that starts with 'logs'
|
|
217
|
-
#
|
|
218
|
-
def keys(options={}, head=false)
|
|
219
|
-
keys_and_service(options, head)[0]
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
# Same as +keys+ method but return an array of [keys, service_data].
|
|
223
|
-
# where +service_data+ is a hash with additional output information.
|
|
224
|
-
#
|
|
225
|
-
# keys, service = bucket.keys_and_service({'max-keys'=> 2, 'prefix' => 'logs'})
|
|
226
|
-
# p keys #=> # 2 keys array
|
|
227
|
-
# p service #=> {"max-keys"=>"2", "prefix"=>"logs", "name"=>"my_awesome_bucket", "marker"=>"", "is_truncated"=>true}
|
|
228
|
-
#
|
|
229
|
-
def keys_and_service(options={}, head=false)
|
|
230
|
-
opt = {}; options.each{ |key, value| opt[key.to_s] = value }
|
|
231
|
-
service_data = {}
|
|
232
|
-
thislist = {}
|
|
233
|
-
list = []
|
|
234
|
-
@s3.interface.incrementally_list_bucket(@name, opt) do |thislist|
|
|
235
|
-
thislist[:contents].each do |entry|
|
|
236
|
-
owner = Owner.new(entry[:owner_id], entry[:owner_display_name])
|
|
237
|
-
key = Key.new(self, entry[:key], nil, {}, {}, entry[:last_modified], entry[:e_tag], entry[:size], entry[:storage_class], owner)
|
|
238
|
-
key.head if head
|
|
239
|
-
list << key
|
|
240
|
-
end
|
|
72
|
+
def close_connection
|
|
73
|
+
@interface.close_connection
|
|
241
74
|
end
|
|
242
|
-
thislist.each_key do |key|
|
|
243
|
-
service_data[key] = thislist[key] unless (key == :contents || key == :common_prefixes)
|
|
244
|
-
end
|
|
245
|
-
[list, service_data]
|
|
246
|
-
end
|
|
247
75
|
|
|
248
|
-
# Retrieve
|
|
249
|
-
#
|
|
250
|
-
#
|
|
251
|
-
#
|
|
252
|
-
#
|
|
253
|
-
#
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
raise 'Key name can not be empty.' if key_name.blank?
|
|
260
|
-
key_instance = nil
|
|
261
|
-
# if this key exists - find it ....
|
|
262
|
-
keys({'prefix'=>key_name}, head).each do |key|
|
|
263
|
-
if key.name == key_name.to_s
|
|
264
|
-
key_instance = key
|
|
265
|
-
break
|
|
266
|
-
end
|
|
76
|
+
# Retrieve a list of buckets.
|
|
77
|
+
# Returns an array of Aws::S3::Bucket instances.
|
|
78
|
+
# # Create handle to S3 account
|
|
79
|
+
# s3 = Aws::S3.new(aws_access_key_id, aws_secret_access_key)
|
|
80
|
+
# my_buckets_names = s3.buckets.map{|b| b.name}
|
|
81
|
+
# puts "Buckets on S3: #{my_bucket_names.join(', ')}"
|
|
82
|
+
def buckets
|
|
83
|
+
@interface.list_all_my_buckets.map! do |entry|
|
|
84
|
+
owner = Owner.new(entry[:owner_id], entry[:owner_display_name])
|
|
85
|
+
Bucket.new(self, entry[:name], entry[:creation_date], owner)
|
|
86
|
+
end
|
|
267
87
|
end
|
|
268
|
-
# .... else this key is unknown
|
|
269
|
-
unless key_instance
|
|
270
|
-
key_instance = Key.create(self, key_name.to_s)
|
|
271
|
-
end
|
|
272
|
-
key_instance
|
|
273
|
-
end
|
|
274
|
-
|
|
275
|
-
# Store object data.
|
|
276
|
-
# The +key+ is a +String+ or Key instance.
|
|
277
|
-
# Returns +true+.
|
|
278
|
-
#
|
|
279
|
-
# bucket.put('logs/today/1.log', 'Olala!') #=> true
|
|
280
|
-
#
|
|
281
|
-
def put(key, data=nil, meta_headers={}, perms=nil, headers={})
|
|
282
|
-
key = Key.create(self, key.to_s, data, meta_headers) unless key.is_a?(Key)
|
|
283
|
-
key.put(data, perms, headers)
|
|
284
|
-
end
|
|
285
|
-
|
|
286
|
-
# Retrieve object data from Amazon.
|
|
287
|
-
# The +key+ is a +String+ or Key.
|
|
288
|
-
# Returns Key instance.
|
|
289
|
-
#
|
|
290
|
-
# key = bucket.get('logs/today/1.log') #=>
|
|
291
|
-
# puts key.data #=> 'sasfasfasdf'
|
|
292
|
-
#
|
|
293
|
-
def get(key, headers={})
|
|
294
|
-
key = Key.create(self, key.to_s) unless key.is_a?(Key)
|
|
295
|
-
key.get(headers)
|
|
296
|
-
end
|
|
297
|
-
|
|
298
|
-
# Rename object. Returns Aws::S3::Key instance.
|
|
299
|
-
#
|
|
300
|
-
# new_key = bucket.rename_key('logs/today/1.log','logs/today/2.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
|
|
301
|
-
# puts key.name #=> 'logs/today/2.log'
|
|
302
|
-
# key.exists? #=> true
|
|
303
|
-
#
|
|
304
|
-
def rename_key(old_key_or_name, new_name)
|
|
305
|
-
old_key_or_name = Key.create(self, old_key_or_name.to_s) unless old_key_or_name.is_a?(Key)
|
|
306
|
-
old_key_or_name.rename(new_name)
|
|
307
|
-
old_key_or_name
|
|
308
|
-
end
|
|
309
|
-
|
|
310
|
-
# Create an object copy. Returns a destination Aws::S3::Key instance.
|
|
311
|
-
#
|
|
312
|
-
# new_key = bucket.copy_key('logs/today/1.log','logs/today/2.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
|
|
313
|
-
# puts key.name #=> 'logs/today/2.log'
|
|
314
|
-
# key.exists? #=> true
|
|
315
|
-
#
|
|
316
|
-
def copy_key(old_key_or_name, new_key_or_name)
|
|
317
|
-
old_key_or_name = Key.create(self, old_key_or_name.to_s) unless old_key_or_name.is_a?(Key)
|
|
318
|
-
old_key_or_name.copy(new_key_or_name)
|
|
319
|
-
end
|
|
320
|
-
|
|
321
|
-
# Move an object to other location. Returns a destination Aws::S3::Key instance.
|
|
322
|
-
#
|
|
323
|
-
# new_key = bucket.copy_key('logs/today/1.log','logs/today/2.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
|
|
324
|
-
# puts key.name #=> 'logs/today/2.log'
|
|
325
|
-
# key.exists? #=> true
|
|
326
|
-
#
|
|
327
|
-
def move_key(old_key_or_name, new_key_or_name)
|
|
328
|
-
old_key_or_name = Key.create(self, old_key_or_name.to_s) unless old_key_or_name.is_a?(Key)
|
|
329
|
-
old_key_or_name.move(new_key_or_name)
|
|
330
|
-
end
|
|
331
|
-
|
|
332
|
-
# Remove all keys from a bucket.
|
|
333
|
-
# Returns +true+.
|
|
334
|
-
#
|
|
335
|
-
# bucket.clear #=> true
|
|
336
|
-
#
|
|
337
|
-
def clear
|
|
338
|
-
@s3.interface.clear_bucket(@name)
|
|
339
|
-
end
|
|
340
88
|
|
|
341
|
-
#
|
|
342
|
-
#
|
|
343
|
-
#
|
|
89
|
+
# Retrieve an individual bucket.
|
|
90
|
+
# If the bucket does not exist and +create+ is set, a new bucket
|
|
91
|
+
# is created on S3. Launching this method with +create+=+true+ may
|
|
92
|
+
# affect on the bucket's ACL if the bucket already exists.
|
|
93
|
+
# Returns a Aws::S3::Bucket instance or +nil+ if the bucket does not exist
|
|
94
|
+
# and +create+ is not set.
|
|
344
95
|
#
|
|
345
|
-
#
|
|
346
|
-
# bucket
|
|
347
|
-
#
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
#
|
|
353
|
-
#
|
|
354
|
-
#
|
|
355
|
-
#
|
|
356
|
-
#
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
Grantee::grantees(self)
|
|
366
|
-
end
|
|
367
|
-
|
|
368
|
-
end
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
class Key
|
|
372
|
-
attr_reader :bucket, :name, :last_modified, :e_tag, :size, :storage_class, :owner
|
|
373
|
-
attr_accessor :headers, :meta_headers
|
|
374
|
-
attr_writer :data
|
|
375
|
-
|
|
376
|
-
# Separate Amazon meta headers from other headers
|
|
377
|
-
def self.split_meta(headers) #:nodoc:
|
|
378
|
-
hash = headers.dup
|
|
379
|
-
meta = {}
|
|
380
|
-
hash.each do |key, value|
|
|
381
|
-
if key[/^#{S3Interface::AMAZON_METADATA_PREFIX}/]
|
|
382
|
-
meta[key.gsub(S3Interface::AMAZON_METADATA_PREFIX,'')] = value
|
|
383
|
-
hash.delete(key)
|
|
384
|
-
end
|
|
385
|
-
end
|
|
386
|
-
[hash, meta]
|
|
387
|
-
end
|
|
388
|
-
|
|
389
|
-
def self.add_meta_prefix(meta_headers, prefix=S3Interface::AMAZON_METADATA_PREFIX)
|
|
390
|
-
meta = {}
|
|
391
|
-
meta_headers.each do |meta_header, value|
|
|
392
|
-
if meta_header[/#{prefix}/]
|
|
393
|
-
meta[meta_header] = value
|
|
394
|
-
else
|
|
395
|
-
meta["#{S3Interface::AMAZON_METADATA_PREFIX}#{meta_header}"] = value
|
|
396
|
-
end
|
|
96
|
+
# s3 = Aws::S3.new(aws_access_key_id, aws_secret_access_key)
|
|
97
|
+
# bucket1 = s3.bucket('my_awesome_bucket_1')
|
|
98
|
+
# bucket1.keys #=> exception here if the bucket does not exists
|
|
99
|
+
# ...
|
|
100
|
+
# bucket2 = s3.bucket('my_awesome_bucket_2', true)
|
|
101
|
+
# bucket2.keys #=> list of keys
|
|
102
|
+
# # create a bucket at the European location with public read access
|
|
103
|
+
# bucket3 = s3.bucket('my-awesome-bucket-3', true, 'public-read', :location => :eu)
|
|
104
|
+
#
|
|
105
|
+
# see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAccessPolicy.html
|
|
106
|
+
# (section: Canned Access Policies)
|
|
107
|
+
#
|
|
108
|
+
def bucket(name, create=false, perms=nil, headers={})
|
|
109
|
+
headers['x-amz-acl'] = perms if perms
|
|
110
|
+
@interface.create_bucket(name, headers) if create
|
|
111
|
+
return Bucket.new(self, name)
|
|
112
|
+
# The old way below was too slow and unnecessary because it retreived all the buckets every time.
|
|
113
|
+
# owner = Owner.new(entry[:owner_id], entry[:owner_display_name])
|
|
114
|
+
# buckets.each { |bucket| return bucket if bucket.name == name }
|
|
115
|
+
# nil
|
|
397
116
|
end
|
|
398
|
-
meta
|
|
399
|
-
end
|
|
400
117
|
|
|
401
118
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
119
|
+
class Bucket
|
|
120
|
+
attr_reader :s3, :name, :owner, :creation_date
|
|
121
|
+
|
|
122
|
+
# Create a Bucket instance.
|
|
123
|
+
# If the bucket does not exist and +create+ is set, a new bucket
|
|
124
|
+
# is created on S3. Launching this method with +create+=+true+ may
|
|
125
|
+
# affect on the bucket's ACL if the bucket already exists.
|
|
126
|
+
# Returns Bucket instance or +nil+ if the bucket does not exist
|
|
127
|
+
# and +create+ is not set.
|
|
128
|
+
#
|
|
129
|
+
# s3 = Aws::S3.new(aws_access_key_id, aws_secret_access_key)
|
|
130
|
+
# ...
|
|
131
|
+
# bucket1 = Aws::S3::Bucket.create(s3, 'my_awesome_bucket_1')
|
|
132
|
+
# bucket1.keys #=> exception here if the bucket does not exists
|
|
133
|
+
# ...
|
|
134
|
+
# bucket2 = Aws::S3::Bucket.create(s3, 'my_awesome_bucket_2', true)
|
|
135
|
+
# bucket2.keys #=> list of keys
|
|
136
|
+
# # create a bucket at the European location with public read access
|
|
137
|
+
# bucket3 = Aws::S3::Bucket.create(s3,'my-awesome-bucket-3', true, 'public-read', :location => :eu)
|
|
138
|
+
#
|
|
139
|
+
# see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAccessPolicy.html
|
|
140
|
+
# (section: Canned Access Policies)
|
|
141
|
+
#
|
|
142
|
+
def self.create(s3, name, create=false, perms=nil, headers={})
|
|
143
|
+
s3.bucket(name, create, perms, headers)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
# Create a bucket instance. In normal use this method should
|
|
148
|
+
# not be called directly.
|
|
149
|
+
# Use Aws::S3::Bucket.create or Aws::S3.bucket instead.
|
|
150
|
+
def initialize(s3, name, creation_date=nil, owner=nil)
|
|
151
|
+
@s3 = s3
|
|
152
|
+
@name = name
|
|
153
|
+
@owner = owner
|
|
154
|
+
@creation_date = creation_date
|
|
155
|
+
if @creation_date && !@creation_date.is_a?(Time)
|
|
156
|
+
@creation_date = Time.parse(@creation_date)
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Return bucket name as a String.
|
|
161
|
+
#
|
|
162
|
+
# bucket = Aws::S3.bucket('my_awesome_bucket')
|
|
163
|
+
# puts bucket #=> 'my_awesome_bucket'
|
|
164
|
+
#
|
|
165
|
+
def to_s
|
|
166
|
+
@name.to_s
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
alias_method :full_name, :to_s
|
|
170
|
+
|
|
171
|
+
# Return a public link to bucket.
|
|
172
|
+
#
|
|
173
|
+
# bucket.public_link #=> 'https://s3.amazonaws.com:443/my_awesome_bucket'
|
|
174
|
+
#
|
|
175
|
+
def public_link
|
|
176
|
+
params = @s3.interface.params
|
|
177
|
+
"#{params[:protocol]}://#{params[:server]}:#{params[:port]}/#{full_name}"
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Returns the bucket location
|
|
181
|
+
def location
|
|
182
|
+
@location ||= @s3.interface.bucket_location(@name)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Retrieves the logging configuration for a bucket.
|
|
186
|
+
# Returns a hash of {:enabled, :targetbucket, :targetprefix}
|
|
187
|
+
#
|
|
188
|
+
# bucket.logging_info()
|
|
189
|
+
# => {:enabled=>true, :targetbucket=>"mylogbucket", :targetprefix=>"loggylogs/"}
|
|
190
|
+
def logging_info
|
|
191
|
+
@s3.interface.get_logging_parse(:bucket => @name)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# Enables S3 server access logging on a bucket. The target bucket must have been properly configured to receive server
|
|
195
|
+
# access logs.
|
|
196
|
+
# Params:
|
|
197
|
+
# :targetbucket - either the target bucket object or the name of the target bucket
|
|
198
|
+
# :targetprefix - the prefix under which all logs should be stored
|
|
199
|
+
#
|
|
200
|
+
# bucket.enable_logging(:targetbucket=>"mylogbucket", :targetprefix=>"loggylogs/")
|
|
201
|
+
# => true
|
|
202
|
+
def enable_logging(params)
|
|
203
|
+
AwsUtils.mandatory_arguments([:targetbucket, :targetprefix], params)
|
|
204
|
+
AwsUtils.allow_only([:targetbucket, :targetprefix], params)
|
|
205
|
+
xmldoc = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><BucketLoggingStatus xmlns=\"http://doc.s3.amazonaws.com/2006-03-01\"><LoggingEnabled><TargetBucket>#{params[:targetbucket]}</TargetBucket><TargetPrefix>#{params[:targetprefix]}</TargetPrefix></LoggingEnabled></BucketLoggingStatus>"
|
|
206
|
+
@s3.interface.put_logging(:bucket => @name, :xmldoc => xmldoc)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# Disables S3 server access logging on a bucket. Takes no arguments.
|
|
210
|
+
def disable_logging
|
|
211
|
+
xmldoc = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><BucketLoggingStatus xmlns=\"http://doc.s3.amazonaws.com/2006-03-01\"></BucketLoggingStatus>"
|
|
212
|
+
@s3.interface.put_logging(:bucket => @name, :xmldoc => xmldoc)
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Retrieve a group of keys from Amazon.
|
|
216
|
+
# +options+ is a hash: { 'prefix'=>'', 'marker'=>'', 'max-keys'=>5, 'delimiter'=>'' }).
|
|
217
|
+
# Retrieves meta-headers information if +head+ it +true+.
|
|
218
|
+
# Returns an array of Key instances.
|
|
219
|
+
#
|
|
220
|
+
# bucket.keys #=> # returns all keys from bucket
|
|
221
|
+
# bucket.keys('prefix' => 'logs') #=> # returns all keys that starts with 'logs'
|
|
222
|
+
#
|
|
223
|
+
def keys(options={}, head=false)
|
|
224
|
+
keys_and_service(options, head)[0]
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
# Same as +keys+ method but return an array of [keys, service_data].
|
|
228
|
+
# where +service_data+ is a hash with additional output information.
|
|
229
|
+
#
|
|
230
|
+
# keys, service = bucket.keys_and_service({'max-keys'=> 2, 'prefix' => 'logs'})
|
|
231
|
+
# p keys #=> # 2 keys array
|
|
232
|
+
# p service #=> {"max-keys"=>"2", "prefix"=>"logs", "name"=>"my_awesome_bucket", "marker"=>"", "is_truncated"=>true}
|
|
233
|
+
#
|
|
234
|
+
def keys_and_service(options={}, head=false)
|
|
235
|
+
opt = {}; options.each { |key, value| opt[key.to_s] = value }
|
|
236
|
+
service_data = {}
|
|
237
|
+
thislist = {}
|
|
238
|
+
list = []
|
|
239
|
+
@s3.interface.incrementally_list_bucket(@name, opt) do |thislist|
|
|
240
|
+
thislist[:contents].each do |entry|
|
|
241
|
+
owner = Owner.new(entry[:owner_id], entry[:owner_display_name])
|
|
242
|
+
key = Key.new(self, entry[:key], nil, {}, {}, entry[:last_modified], entry[:e_tag], entry[:size], entry[:storage_class], owner)
|
|
243
|
+
key.head if head
|
|
244
|
+
list << key
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
thislist.each_key do |key|
|
|
248
|
+
service_data[key] = thislist[key] unless (key == :contents || key == :common_prefixes)
|
|
249
|
+
end
|
|
250
|
+
[list, service_data]
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# Retrieve key information from Amazon.
|
|
254
|
+
# The +key_name+ is a +String+ or Key instance.
|
|
255
|
+
# Retrieves meta-header information if +head+ is +true+.
|
|
256
|
+
# Returns new Key instance.
|
|
257
|
+
#
|
|
258
|
+
# key = bucket.key('logs/today/1.log', true) #=> #<Aws::S3::Key:0xb7b1e240 ... >
|
|
259
|
+
# # is the same as:
|
|
260
|
+
# key = Aws::S3::Key.create(bucket, 'logs/today/1.log')
|
|
261
|
+
# key.head
|
|
262
|
+
#
|
|
263
|
+
def key(key_name, head=false)
|
|
264
|
+
raise 'Key name can not be empty.' if key_name.blank?
|
|
265
|
+
key_instance = nil
|
|
266
|
+
# if this key exists - find it ....
|
|
267
|
+
keys({'prefix'=>key_name}, head).each do |key|
|
|
268
|
+
if key.name == key_name.to_s
|
|
269
|
+
key_instance = key
|
|
270
|
+
break
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
# .... else this key is unknown
|
|
274
|
+
unless key_instance
|
|
275
|
+
key_instance = Key.create(self, key_name.to_s)
|
|
276
|
+
end
|
|
277
|
+
key_instance
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# Store object data.
|
|
281
|
+
# The +key+ is a +String+ or Key instance.
|
|
282
|
+
# Returns +true+.
|
|
283
|
+
#
|
|
284
|
+
# bucket.put('logs/today/1.log', 'Olala!') #=> true
|
|
285
|
+
#
|
|
286
|
+
def put(key, data=nil, meta_headers={}, perms=nil, headers={})
|
|
287
|
+
key = Key.create(self, key.to_s, data, meta_headers) unless key.is_a?(Key)
|
|
288
|
+
key.put(data, perms, headers)
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
# Retrieve object data from Amazon.
|
|
292
|
+
# The +key+ is a +String+ or Key.
|
|
293
|
+
# Returns Key instance.
|
|
294
|
+
#
|
|
295
|
+
# key = bucket.get('logs/today/1.log') #=>
|
|
296
|
+
# puts key.data #=> 'sasfasfasdf'
|
|
297
|
+
#
|
|
298
|
+
def get(key, headers={})
|
|
299
|
+
key = Key.create(self, key.to_s) unless key.is_a?(Key)
|
|
300
|
+
key.get(headers)
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
# Rename object. Returns Aws::S3::Key instance.
|
|
304
|
+
#
|
|
305
|
+
# new_key = bucket.rename_key('logs/today/1.log','logs/today/2.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
|
|
306
|
+
# puts key.name #=> 'logs/today/2.log'
|
|
307
|
+
# key.exists? #=> true
|
|
308
|
+
#
|
|
309
|
+
def rename_key(old_key_or_name, new_name)
|
|
310
|
+
old_key_or_name = Key.create(self, old_key_or_name.to_s) unless old_key_or_name.is_a?(Key)
|
|
311
|
+
old_key_or_name.rename(new_name)
|
|
312
|
+
old_key_or_name
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
# Create an object copy. Returns a destination Aws::S3::Key instance.
|
|
316
|
+
#
|
|
317
|
+
# new_key = bucket.copy_key('logs/today/1.log','logs/today/2.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
|
|
318
|
+
# puts key.name #=> 'logs/today/2.log'
|
|
319
|
+
# key.exists? #=> true
|
|
320
|
+
#
|
|
321
|
+
def copy_key(old_key_or_name, new_key_or_name)
|
|
322
|
+
old_key_or_name = Key.create(self, old_key_or_name.to_s) unless old_key_or_name.is_a?(Key)
|
|
323
|
+
old_key_or_name.copy(new_key_or_name)
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
# Move an object to other location. Returns a destination Aws::S3::Key instance.
|
|
327
|
+
#
|
|
328
|
+
# new_key = bucket.copy_key('logs/today/1.log','logs/today/2.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
|
|
329
|
+
# puts key.name #=> 'logs/today/2.log'
|
|
330
|
+
# key.exists? #=> true
|
|
331
|
+
#
|
|
332
|
+
def move_key(old_key_or_name, new_key_or_name)
|
|
333
|
+
old_key_or_name = Key.create(self, old_key_or_name.to_s) unless old_key_or_name.is_a?(Key)
|
|
334
|
+
old_key_or_name.move(new_key_or_name)
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
# Remove all keys from a bucket.
|
|
338
|
+
# Returns +true+.
|
|
339
|
+
#
|
|
340
|
+
# bucket.clear #=> true
|
|
341
|
+
#
|
|
342
|
+
def clear
|
|
343
|
+
@s3.interface.clear_bucket(@name)
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
# Delete all keys where the 'folder_key' can be interpreted
|
|
347
|
+
# as a 'folder' name.
|
|
348
|
+
# Returns an array of string keys that have been deleted.
|
|
349
|
+
#
|
|
350
|
+
# bucket.keys.map{|key| key.name}.join(', ') #=> 'test, test/2/34, test/3, test1, test1/logs'
|
|
351
|
+
# bucket.delete_folder('test') #=> ['test','test/2/34','test/3']
|
|
352
|
+
#
|
|
353
|
+
def delete_folder(folder, separator='/')
|
|
354
|
+
@s3.interface.delete_folder(@name, folder, separator)
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
# Delete a bucket. Bucket must be empty.
|
|
358
|
+
# If +force+ is set, clears and deletes the bucket.
|
|
359
|
+
# Returns +true+.
|
|
360
|
+
#
|
|
361
|
+
# bucket.delete(true) #=> true
|
|
362
|
+
#
|
|
363
|
+
def delete(force=false)
|
|
364
|
+
force ? @s3.interface.force_delete_bucket(@name) : @s3.interface.delete_bucket(@name)
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
# Return a list of grantees.
|
|
368
|
+
#
|
|
369
|
+
def grantees
|
|
370
|
+
Grantee::grantees(self)
|
|
371
|
+
end
|
|
414
372
|
|
|
415
|
-
# Create a new Key instance, but do not create the actual key.
|
|
416
|
-
# In normal use this method should not be called directly.
|
|
417
|
-
# Use Aws::S3::Key.create or bucket.key() instead.
|
|
418
|
-
#
|
|
419
|
-
def initialize(bucket, name, data=nil, headers={}, meta_headers={},
|
|
420
|
-
last_modified=nil, e_tag=nil, size=nil, storage_class=nil, owner=nil)
|
|
421
|
-
raise 'Bucket must be a Bucket instance.' unless bucket.is_a?(Bucket)
|
|
422
|
-
@bucket = bucket
|
|
423
|
-
@name = name
|
|
424
|
-
@data = data
|
|
425
|
-
@e_tag = e_tag
|
|
426
|
-
@size = size.to_i
|
|
427
|
-
@storage_class = storage_class
|
|
428
|
-
@owner = owner
|
|
429
|
-
@last_modified = last_modified
|
|
430
|
-
if @last_modified && !@last_modified.is_a?(Time)
|
|
431
|
-
@last_modified = Time.parse(@last_modified)
|
|
432
373
|
end
|
|
433
|
-
@headers, @meta_headers = self.class.split_meta(headers)
|
|
434
|
-
@meta_headers.merge!(meta_headers)
|
|
435
|
-
end
|
|
436
|
-
|
|
437
|
-
# Return key name as a String.
|
|
438
|
-
#
|
|
439
|
-
# key = Aws::S3::Key.create(bucket, 'logs/today/1.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
|
|
440
|
-
# puts key #=> 'logs/today/1.log'
|
|
441
|
-
#
|
|
442
|
-
def to_s
|
|
443
|
-
@name.to_s
|
|
444
|
-
end
|
|
445
|
-
|
|
446
|
-
# Return the full S3 path to this key (bucket/key).
|
|
447
|
-
#
|
|
448
|
-
# key.full_name #=> 'my_awesome_bucket/cool_key'
|
|
449
|
-
#
|
|
450
|
-
def full_name(separator='/')
|
|
451
|
-
"#{@bucket.to_s}#{separator}#{@name}"
|
|
452
|
-
end
|
|
453
374
|
|
|
454
|
-
# Return a public link to a key.
|
|
455
|
-
#
|
|
456
|
-
# key.public_link #=> 'https://s3.amazonaws.com:443/my_awesome_bucket/cool_key'
|
|
457
|
-
#
|
|
458
|
-
def public_link
|
|
459
|
-
params = @bucket.s3.interface.params
|
|
460
|
-
"#{params[:protocol]}://#{params[:server]}:#{params[:port]}/#{full_name('/')}"
|
|
461
|
-
end
|
|
462
375
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
376
|
+
class Key
|
|
377
|
+
attr_reader :bucket, :name, :last_modified, :e_tag, :size, :storage_class, :owner
|
|
378
|
+
attr_accessor :headers, :meta_headers
|
|
379
|
+
attr_writer :data
|
|
380
|
+
|
|
381
|
+
# Separate Amazon meta headers from other headers
|
|
382
|
+
def self.split_meta(headers) #:nodoc:
|
|
383
|
+
hash = headers.dup
|
|
384
|
+
meta = {}
|
|
385
|
+
hash.each do |key, value|
|
|
386
|
+
if key[/^#{S3Interface::AMAZON_METADATA_PREFIX}/]
|
|
387
|
+
meta[key.gsub(S3Interface::AMAZON_METADATA_PREFIX, '')] = value
|
|
388
|
+
hash.delete(key)
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
[hash, meta]
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
def self.add_meta_prefix(meta_headers, prefix=S3Interface::AMAZON_METADATA_PREFIX)
|
|
395
|
+
meta = {}
|
|
396
|
+
meta_headers.each do |meta_header, value|
|
|
397
|
+
if meta_header[/#{prefix}/]
|
|
398
|
+
meta[meta_header] = value
|
|
399
|
+
else
|
|
400
|
+
meta["#{S3Interface::AMAZON_METADATA_PREFIX}#{meta_header}"] = value
|
|
401
|
+
end
|
|
402
|
+
end
|
|
403
|
+
meta
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
# Create a new Key instance, but do not create the actual key.
|
|
408
|
+
# The +name+ is a +String+.
|
|
409
|
+
# Returns a new Key instance.
|
|
410
|
+
#
|
|
411
|
+
# key = Aws::S3::Key.create(bucket, 'logs/today/1.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
|
|
412
|
+
# key.exists? #=> true | false
|
|
413
|
+
# key.put('Woohoo!') #=> true
|
|
414
|
+
# key.exists? #=> true
|
|
415
|
+
#
|
|
416
|
+
def self.create(bucket, name, data=nil, meta_headers={})
|
|
417
|
+
new(bucket, name, data, {}, meta_headers)
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
# Create a new Key instance, but do not create the actual key.
|
|
421
|
+
# In normal use this method should not be called directly.
|
|
422
|
+
# Use Aws::S3::Key.create or bucket.key() instead.
|
|
423
|
+
#
|
|
424
|
+
def initialize(bucket, name, data=nil, headers={}, meta_headers={},
|
|
425
|
+
last_modified=nil, e_tag=nil, size=nil, storage_class=nil, owner=nil)
|
|
426
|
+
raise 'Bucket must be a Bucket instance.' unless bucket.is_a?(Bucket)
|
|
427
|
+
@bucket = bucket
|
|
428
|
+
@name = name
|
|
429
|
+
@data = data
|
|
430
|
+
@e_tag = e_tag
|
|
431
|
+
@size = size.to_i
|
|
432
|
+
@storage_class = storage_class
|
|
433
|
+
@owner = owner
|
|
434
|
+
@last_modified = last_modified
|
|
435
|
+
if @last_modified && !@last_modified.is_a?(Time)
|
|
436
|
+
@last_modified = Time.parse(@last_modified)
|
|
437
|
+
end
|
|
438
|
+
@headers, @meta_headers = self.class.split_meta(headers)
|
|
439
|
+
@meta_headers.merge!(meta_headers)
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
# Return key name as a String.
|
|
443
|
+
#
|
|
444
|
+
# key = Aws::S3::Key.create(bucket, 'logs/today/1.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
|
|
445
|
+
# puts key #=> 'logs/today/1.log'
|
|
446
|
+
#
|
|
447
|
+
def to_s
|
|
448
|
+
@name.to_s
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
# Return the full S3 path to this key (bucket/key).
|
|
452
|
+
#
|
|
453
|
+
# key.full_name #=> 'my_awesome_bucket/cool_key'
|
|
454
|
+
#
|
|
455
|
+
def full_name(separator='/')
|
|
456
|
+
"#{@bucket.to_s}#{separator}#{@name}"
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
# Return a public link to a key.
|
|
460
|
+
#
|
|
461
|
+
# key.public_link #=> 'https://s3.amazonaws.com:443/my_awesome_bucket/cool_key'
|
|
462
|
+
#
|
|
463
|
+
def public_link
|
|
464
|
+
params = @bucket.s3.interface.params
|
|
465
|
+
"#{params[:protocol]}://#{params[:server]}:#{params[:port]}/#{full_name('/')}"
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
# Return Key data. Retrieve this data from Amazon if it is the first time call.
|
|
469
|
+
# TODO TRB 6/19/07 What does the above mean? Clarify.
|
|
470
|
+
#
|
|
471
|
+
def data
|
|
472
|
+
get if !@data and exists?
|
|
473
|
+
@data
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
# Retrieve object data and attributes from Amazon.
|
|
477
|
+
# Returns a +String+.
|
|
478
|
+
#
|
|
479
|
+
def get(headers={}, &block)
|
|
480
|
+
response = @bucket.s3.interface.get(@bucket.name, @name, headers, &block)
|
|
481
|
+
@data = response[:object]
|
|
482
|
+
@headers, @meta_headers = self.class.split_meta(response[:headers])
|
|
483
|
+
# refresh(false) Holy moly, this was doing two extra hits to s3 for making 3 hits for every get!!
|
|
484
|
+
@data
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
# Store object data on S3.
|
|
488
|
+
# Parameter +data+ is a +String+ or S3Object instance.
|
|
489
|
+
# Returns +true+.
|
|
490
|
+
#
|
|
491
|
+
# key = Aws::S3::Key.create(bucket, 'logs/today/1.log')
|
|
492
|
+
# key.data = 'Qwerty'
|
|
493
|
+
# key.put #=> true
|
|
494
|
+
# ...
|
|
495
|
+
# key.put('Olala!') #=> true
|
|
496
|
+
#
|
|
497
|
+
def put(data=nil, perms=nil, headers={})
|
|
498
|
+
headers['x-amz-acl'] = perms if perms
|
|
499
|
+
@data = data || @data
|
|
500
|
+
meta = self.class.add_meta_prefix(@meta_headers)
|
|
501
|
+
@bucket.s3.interface.put(@bucket.name, @name, @data, meta.merge(headers))
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
# Rename an object. Returns new object name.
|
|
505
|
+
#
|
|
506
|
+
# key = Aws::S3::Key.create(bucket, 'logs/today/1.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
|
|
507
|
+
# key.rename('logs/today/2.log') #=> 'logs/today/2.log'
|
|
508
|
+
# puts key.name #=> 'logs/today/2.log'
|
|
509
|
+
# key.exists? #=> true
|
|
510
|
+
#
|
|
511
|
+
def rename(new_name)
|
|
512
|
+
@bucket.s3.interface.rename(@bucket.name, @name, new_name)
|
|
513
|
+
@name = new_name
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
# Create an object copy. Returns a destination Aws::S3::Key instance.
|
|
517
|
+
#
|
|
518
|
+
# # Key instance as destination
|
|
519
|
+
# key1 = Aws::S3::Key.create(bucket, 'logs/today/1.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
|
|
520
|
+
# key2 = Aws::S3::Key.create(bucket, 'logs/today/2.log') #=> #<Aws::S3::Key:0xb7b5e240 ... >
|
|
521
|
+
# key1.put('Olala!') #=> true
|
|
522
|
+
# key1.copy(key2) #=> #<Aws::S3::Key:0xb7b5e240 ... >
|
|
523
|
+
# key1.exists? #=> true
|
|
524
|
+
# key2.exists? #=> true
|
|
525
|
+
# puts key2.data #=> 'Olala!'
|
|
526
|
+
#
|
|
527
|
+
# # String as destination
|
|
528
|
+
# key = Aws::S3::Key.create(bucket, 'logs/today/777.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
|
|
529
|
+
# key.put('Olala!') #=> true
|
|
530
|
+
# new_key = key.copy('logs/today/888.log') #=> #<Aws::S3::Key:0xb7b5e240 ... >
|
|
531
|
+
# key.exists? #=> true
|
|
532
|
+
# new_key.exists? #=> true
|
|
533
|
+
#
|
|
534
|
+
def copy(new_key_or_name)
|
|
535
|
+
new_key_or_name = Key.create(@bucket, new_key_or_name.to_s) unless new_key_or_name.is_a?(Key)
|
|
536
|
+
@bucket.s3.interface.copy(@bucket.name, @name, new_key_or_name.bucket.name, new_key_or_name.name)
|
|
537
|
+
new_key_or_name
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
# Move an object to other location. Returns a destination Aws::S3::Key instance.
|
|
541
|
+
#
|
|
542
|
+
# # Key instance as destination
|
|
543
|
+
# key1 = Aws::S3::Key.create(bucket, 'logs/today/1.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
|
|
544
|
+
# key2 = Aws::S3::Key.create(bucket, 'logs/today/2.log') #=> #<Aws::S3::Key:0xb7b5e240 ... >
|
|
545
|
+
# key1.put('Olala!') #=> true
|
|
546
|
+
# key1.move(key2) #=> #<Aws::S3::Key:0xb7b5e240 ... >
|
|
547
|
+
# key1.exists? #=> false
|
|
548
|
+
# key2.exists? #=> true
|
|
549
|
+
# puts key2.data #=> 'Olala!'
|
|
550
|
+
#
|
|
551
|
+
# # String as destination
|
|
552
|
+
# key = Aws::S3::Key.create(bucket, 'logs/today/777.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
|
|
553
|
+
# key.put('Olala!') #=> true
|
|
554
|
+
# new_key = key.move('logs/today/888.log') #=> #<Aws::S3::Key:0xb7b5e240 ... >
|
|
555
|
+
# key.exists? #=> false
|
|
556
|
+
# new_key.exists? #=> true
|
|
557
|
+
#
|
|
558
|
+
def move(new_key_or_name)
|
|
559
|
+
new_key_or_name = Key.create(@bucket, new_key_or_name.to_s) unless new_key_or_name.is_a?(Key)
|
|
560
|
+
@bucket.s3.interface.move(@bucket.name, @name, new_key_or_name.bucket.name, new_key_or_name.name)
|
|
561
|
+
new_key_or_name
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
# Retrieve key info from bucket and update attributes.
|
|
565
|
+
# Refresh meta-headers (by calling +head+ method) if +head+ is set.
|
|
566
|
+
# Returns +true+ if the key exists in bucket and +false+ otherwise.
|
|
567
|
+
#
|
|
568
|
+
# key = Aws::S3::Key.create(bucket, 'logs/today/1.log')
|
|
569
|
+
# key.e_tag #=> nil
|
|
570
|
+
# key.meta_headers #=> {}
|
|
571
|
+
# key.refresh #=> true
|
|
572
|
+
# key.e_tag #=> '12345678901234567890bf11094484b6'
|
|
573
|
+
# key.meta_headers #=> {"family"=>"qwerty", "name"=>"asdfg"}
|
|
574
|
+
#
|
|
575
|
+
def refresh(head=true)
|
|
576
|
+
new_key = @bucket.key(self)
|
|
577
|
+
@last_modified = new_key.last_modified
|
|
578
|
+
@e_tag = new_key.e_tag
|
|
579
|
+
@size = new_key.size
|
|
580
|
+
@storage_class = new_key.storage_class
|
|
581
|
+
@owner = new_key.owner
|
|
582
|
+
if @last_modified
|
|
583
|
+
self.head
|
|
584
|
+
true
|
|
585
|
+
else
|
|
586
|
+
@headers = @meta_headers = {}
|
|
587
|
+
false
|
|
588
|
+
end
|
|
589
|
+
end
|
|
590
|
+
|
|
591
|
+
# Updates headers and meta-headers from S3.
|
|
592
|
+
# Returns +true+.
|
|
593
|
+
#
|
|
594
|
+
# key.meta_headers #=> {"family"=>"qwerty"}
|
|
595
|
+
# key.head #=> true
|
|
596
|
+
# key.meta_headers #=> {"family"=>"qwerty", "name"=>"asdfg"}
|
|
597
|
+
#
|
|
598
|
+
def head
|
|
599
|
+
@headers, @meta_headers = self.class.split_meta(@bucket.s3.interface.head(@bucket, @name))
|
|
600
|
+
true
|
|
601
|
+
end
|
|
602
|
+
|
|
603
|
+
# Reload meta-headers only. Returns meta-headers hash.
|
|
604
|
+
#
|
|
605
|
+
# key.reload_meta #=> {"family"=>"qwerty", "name"=>"asdfg"}
|
|
606
|
+
#
|
|
607
|
+
def reload_meta
|
|
608
|
+
@meta_headers = self.class.split_meta(@bucket.s3.interface.head(@bucket, @name)).last
|
|
609
|
+
end
|
|
610
|
+
|
|
611
|
+
# Replace meta-headers by new hash at S3. Returns new meta-headers hash.
|
|
612
|
+
#
|
|
613
|
+
# key.reload_meta #=> {"family"=>"qwerty", "name"=>"asdfg"}
|
|
614
|
+
# key.save_meta #=> {"family"=>"oops", "race" => "troll"}
|
|
615
|
+
# key.reload_meta #=> {"family"=>"oops", "race" => "troll"}
|
|
616
|
+
#
|
|
617
|
+
def save_meta(meta_headers)
|
|
618
|
+
meta = self.class.add_meta_prefix(meta_headers)
|
|
619
|
+
@bucket.s3.interface.copy(@bucket.name, @name, @bucket.name, @name, :replace, meta)
|
|
620
|
+
@meta_headers = self.class.split_meta(meta)[1]
|
|
621
|
+
end
|
|
622
|
+
|
|
623
|
+
# Check for existence of the key in the given bucket.
|
|
624
|
+
# Returns +true+ or +false+.
|
|
625
|
+
#
|
|
626
|
+
# key = Aws::S3::Key.create(bucket,'logs/today/1.log')
|
|
627
|
+
# key.exists? #=> false
|
|
628
|
+
# key.put('Woohoo!') #=> true
|
|
629
|
+
# key.exists? #=> true
|
|
630
|
+
#
|
|
631
|
+
def exists?
|
|
632
|
+
@bucket.key(self).last_modified ? true : false
|
|
633
|
+
end
|
|
634
|
+
|
|
635
|
+
# Remove key from bucket.
|
|
636
|
+
# Returns +true+.
|
|
637
|
+
#
|
|
638
|
+
# key.delete #=> true
|
|
639
|
+
#
|
|
640
|
+
def delete
|
|
641
|
+
raise 'Key name must be specified.' if @name.blank?
|
|
642
|
+
@bucket.s3.interface.delete(@bucket, @name)
|
|
643
|
+
end
|
|
644
|
+
|
|
645
|
+
# Return a list of grantees.
|
|
646
|
+
#
|
|
647
|
+
def grantees
|
|
648
|
+
Grantee::grantees(self)
|
|
649
|
+
end
|
|
470
650
|
|
|
471
|
-
# Retrieve object data and attributes from Amazon.
|
|
472
|
-
# Returns a +String+.
|
|
473
|
-
#
|
|
474
|
-
def get(headers={}, &block)
|
|
475
|
-
response = @bucket.s3.interface.get(@bucket.name, @name, headers, &block)
|
|
476
|
-
@data = response[:object]
|
|
477
|
-
@headers, @meta_headers = self.class.split_meta(response[:headers])
|
|
478
|
-
refresh(false)
|
|
479
|
-
@data
|
|
480
|
-
end
|
|
481
|
-
|
|
482
|
-
# Store object data on S3.
|
|
483
|
-
# Parameter +data+ is a +String+ or S3Object instance.
|
|
484
|
-
# Returns +true+.
|
|
485
|
-
#
|
|
486
|
-
# key = Aws::S3::Key.create(bucket, 'logs/today/1.log')
|
|
487
|
-
# key.data = 'Qwerty'
|
|
488
|
-
# key.put #=> true
|
|
489
|
-
# ...
|
|
490
|
-
# key.put('Olala!') #=> true
|
|
491
|
-
#
|
|
492
|
-
def put(data=nil, perms=nil, headers={})
|
|
493
|
-
headers['x-amz-acl'] = perms if perms
|
|
494
|
-
@data = data || @data
|
|
495
|
-
meta = self.class.add_meta_prefix(@meta_headers)
|
|
496
|
-
@bucket.s3.interface.put(@bucket.name, @name, @data, meta.merge(headers))
|
|
497
|
-
end
|
|
498
|
-
|
|
499
|
-
# Rename an object. Returns new object name.
|
|
500
|
-
#
|
|
501
|
-
# key = Aws::S3::Key.create(bucket, 'logs/today/1.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
|
|
502
|
-
# key.rename('logs/today/2.log') #=> 'logs/today/2.log'
|
|
503
|
-
# puts key.name #=> 'logs/today/2.log'
|
|
504
|
-
# key.exists? #=> true
|
|
505
|
-
#
|
|
506
|
-
def rename(new_name)
|
|
507
|
-
@bucket.s3.interface.rename(@bucket.name, @name, new_name)
|
|
508
|
-
@name = new_name
|
|
509
|
-
end
|
|
510
|
-
|
|
511
|
-
# Create an object copy. Returns a destination Aws::S3::Key instance.
|
|
512
|
-
#
|
|
513
|
-
# # Key instance as destination
|
|
514
|
-
# key1 = Aws::S3::Key.create(bucket, 'logs/today/1.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
|
|
515
|
-
# key2 = Aws::S3::Key.create(bucket, 'logs/today/2.log') #=> #<Aws::S3::Key:0xb7b5e240 ... >
|
|
516
|
-
# key1.put('Olala!') #=> true
|
|
517
|
-
# key1.copy(key2) #=> #<Aws::S3::Key:0xb7b5e240 ... >
|
|
518
|
-
# key1.exists? #=> true
|
|
519
|
-
# key2.exists? #=> true
|
|
520
|
-
# puts key2.data #=> 'Olala!'
|
|
521
|
-
#
|
|
522
|
-
# # String as destination
|
|
523
|
-
# key = Aws::S3::Key.create(bucket, 'logs/today/777.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
|
|
524
|
-
# key.put('Olala!') #=> true
|
|
525
|
-
# new_key = key.copy('logs/today/888.log') #=> #<Aws::S3::Key:0xb7b5e240 ... >
|
|
526
|
-
# key.exists? #=> true
|
|
527
|
-
# new_key.exists? #=> true
|
|
528
|
-
#
|
|
529
|
-
def copy(new_key_or_name)
|
|
530
|
-
new_key_or_name = Key.create(@bucket, new_key_or_name.to_s) unless new_key_or_name.is_a?(Key)
|
|
531
|
-
@bucket.s3.interface.copy(@bucket.name, @name, new_key_or_name.bucket.name, new_key_or_name.name)
|
|
532
|
-
new_key_or_name
|
|
533
|
-
end
|
|
534
|
-
|
|
535
|
-
# Move an object to other location. Returns a destination Aws::S3::Key instance.
|
|
536
|
-
#
|
|
537
|
-
# # Key instance as destination
|
|
538
|
-
# key1 = Aws::S3::Key.create(bucket, 'logs/today/1.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
|
|
539
|
-
# key2 = Aws::S3::Key.create(bucket, 'logs/today/2.log') #=> #<Aws::S3::Key:0xb7b5e240 ... >
|
|
540
|
-
# key1.put('Olala!') #=> true
|
|
541
|
-
# key1.move(key2) #=> #<Aws::S3::Key:0xb7b5e240 ... >
|
|
542
|
-
# key1.exists? #=> false
|
|
543
|
-
# key2.exists? #=> true
|
|
544
|
-
# puts key2.data #=> 'Olala!'
|
|
545
|
-
#
|
|
546
|
-
# # String as destination
|
|
547
|
-
# key = Aws::S3::Key.create(bucket, 'logs/today/777.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
|
|
548
|
-
# key.put('Olala!') #=> true
|
|
549
|
-
# new_key = key.move('logs/today/888.log') #=> #<Aws::S3::Key:0xb7b5e240 ... >
|
|
550
|
-
# key.exists? #=> false
|
|
551
|
-
# new_key.exists? #=> true
|
|
552
|
-
#
|
|
553
|
-
def move(new_key_or_name)
|
|
554
|
-
new_key_or_name = Key.create(@bucket, new_key_or_name.to_s) unless new_key_or_name.is_a?(Key)
|
|
555
|
-
@bucket.s3.interface.move(@bucket.name, @name, new_key_or_name.bucket.name, new_key_or_name.name)
|
|
556
|
-
new_key_or_name
|
|
557
|
-
end
|
|
558
|
-
|
|
559
|
-
# Retrieve key info from bucket and update attributes.
|
|
560
|
-
# Refresh meta-headers (by calling +head+ method) if +head+ is set.
|
|
561
|
-
# Returns +true+ if the key exists in bucket and +false+ otherwise.
|
|
562
|
-
#
|
|
563
|
-
# key = Aws::S3::Key.create(bucket, 'logs/today/1.log')
|
|
564
|
-
# key.e_tag #=> nil
|
|
565
|
-
# key.meta_headers #=> {}
|
|
566
|
-
# key.refresh #=> true
|
|
567
|
-
# key.e_tag #=> '12345678901234567890bf11094484b6'
|
|
568
|
-
# key.meta_headers #=> {"family"=>"qwerty", "name"=>"asdfg"}
|
|
569
|
-
#
|
|
570
|
-
def refresh(head=true)
|
|
571
|
-
new_key = @bucket.key(self)
|
|
572
|
-
@last_modified = new_key.last_modified
|
|
573
|
-
@e_tag = new_key.e_tag
|
|
574
|
-
@size = new_key.size
|
|
575
|
-
@storage_class = new_key.storage_class
|
|
576
|
-
@owner = new_key.owner
|
|
577
|
-
if @last_modified
|
|
578
|
-
self.head
|
|
579
|
-
true
|
|
580
|
-
else
|
|
581
|
-
@headers = @meta_headers = {}
|
|
582
|
-
false
|
|
583
651
|
end
|
|
584
|
-
end
|
|
585
652
|
|
|
586
|
-
# Updates headers and meta-headers from S3.
|
|
587
|
-
# Returns +true+.
|
|
588
|
-
#
|
|
589
|
-
# key.meta_headers #=> {"family"=>"qwerty"}
|
|
590
|
-
# key.head #=> true
|
|
591
|
-
# key.meta_headers #=> {"family"=>"qwerty", "name"=>"asdfg"}
|
|
592
|
-
#
|
|
593
|
-
def head
|
|
594
|
-
@headers, @meta_headers = self.class.split_meta(@bucket.s3.interface.head(@bucket, @name))
|
|
595
|
-
true
|
|
596
|
-
end
|
|
597
|
-
|
|
598
|
-
# Reload meta-headers only. Returns meta-headers hash.
|
|
599
|
-
#
|
|
600
|
-
# key.reload_meta #=> {"family"=>"qwerty", "name"=>"asdfg"}
|
|
601
|
-
#
|
|
602
|
-
def reload_meta
|
|
603
|
-
@meta_headers = self.class.split_meta(@bucket.s3.interface.head(@bucket, @name)).last
|
|
604
|
-
end
|
|
605
|
-
|
|
606
|
-
# Replace meta-headers by new hash at S3. Returns new meta-headers hash.
|
|
607
|
-
#
|
|
608
|
-
# key.reload_meta #=> {"family"=>"qwerty", "name"=>"asdfg"}
|
|
609
|
-
# key.save_meta #=> {"family"=>"oops", "race" => "troll"}
|
|
610
|
-
# key.reload_meta #=> {"family"=>"oops", "race" => "troll"}
|
|
611
|
-
#
|
|
612
|
-
def save_meta(meta_headers)
|
|
613
|
-
meta = self.class.add_meta_prefix(meta_headers)
|
|
614
|
-
@bucket.s3.interface.copy(@bucket.name, @name, @bucket.name, @name, :replace, meta)
|
|
615
|
-
@meta_headers = self.class.split_meta(meta)[1]
|
|
616
|
-
end
|
|
617
|
-
|
|
618
|
-
# Check for existence of the key in the given bucket.
|
|
619
|
-
# Returns +true+ or +false+.
|
|
620
|
-
#
|
|
621
|
-
# key = Aws::S3::Key.create(bucket,'logs/today/1.log')
|
|
622
|
-
# key.exists? #=> false
|
|
623
|
-
# key.put('Woohoo!') #=> true
|
|
624
|
-
# key.exists? #=> true
|
|
625
|
-
#
|
|
626
|
-
def exists?
|
|
627
|
-
@bucket.key(self).last_modified ? true : false
|
|
628
|
-
end
|
|
629
|
-
|
|
630
|
-
# Remove key from bucket.
|
|
631
|
-
# Returns +true+.
|
|
632
|
-
#
|
|
633
|
-
# key.delete #=> true
|
|
634
|
-
#
|
|
635
|
-
def delete
|
|
636
|
-
raise 'Key name must be specified.' if @name.blank?
|
|
637
|
-
@bucket.s3.interface.delete(@bucket, @name)
|
|
638
|
-
end
|
|
639
|
-
|
|
640
|
-
# Return a list of grantees.
|
|
641
|
-
#
|
|
642
|
-
def grantees
|
|
643
|
-
Grantee::grantees(self)
|
|
644
|
-
end
|
|
645
|
-
|
|
646
|
-
end
|
|
647
653
|
|
|
654
|
+
class Owner
|
|
655
|
+
attr_reader :id, :name
|
|
648
656
|
|
|
649
|
-
|
|
650
|
-
|
|
657
|
+
def initialize(id, name)
|
|
658
|
+
@id = id
|
|
659
|
+
@name = name
|
|
660
|
+
end
|
|
651
661
|
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
# Return Owner name as a +String+.
|
|
658
|
-
def to_s
|
|
659
|
-
@name
|
|
660
|
-
end
|
|
661
|
-
end
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
# There are 2 ways to set permissions for a bucket or key (called a +thing+ below):
|
|
665
|
-
#
|
|
666
|
-
# 1 . Use +perms+ param to set 'Canned Access Policies' when calling the <tt>bucket.create</tt>,
|
|
667
|
-
# <tt>bucket.put</tt> and <tt>key.put</tt> methods.
|
|
668
|
-
# The +perms+ param can take these values: 'private', 'public-read', 'public-read-write' and
|
|
669
|
-
# 'authenticated-read'.
|
|
670
|
-
# (see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAccessPolicy.html).
|
|
671
|
-
#
|
|
672
|
-
# bucket = s3.bucket('bucket_for_kd_test_13', true, 'public-read')
|
|
673
|
-
# key.put('Woohoo!','public-read-write' )
|
|
674
|
-
#
|
|
675
|
-
# 2 . Use Grantee instances (the permission is a +String+ or an +Array+ of: 'READ', 'WRITE',
|
|
676
|
-
# 'READ_ACP', 'WRITE_ACP', 'FULL_CONTROL'):
|
|
677
|
-
#
|
|
678
|
-
# bucket = s3.bucket('my_awesome_bucket', true)
|
|
679
|
-
# grantee1 = Aws::S3::Grantee.new(bucket, 'a123b...223c', FULL_CONTROL, :apply)
|
|
680
|
-
# grantee2 = Aws::S3::Grantee.new(bucket, 'xy3v3...5fhp', [READ, WRITE], :apply)
|
|
681
|
-
#
|
|
682
|
-
# There is only one way to get and to remove permission (via Grantee instances):
|
|
683
|
-
#
|
|
684
|
-
# grantees = bucket.grantees # a list of Grantees that have any access for this bucket
|
|
685
|
-
# grantee1 = Aws::S3::Grantee.new(bucket, 'a123b...223c')
|
|
686
|
-
# grantee1.perms #=> returns a list of perms for this grantee to that bucket
|
|
687
|
-
# ...
|
|
688
|
-
# grantee1.drop # remove all perms for this grantee
|
|
689
|
-
# grantee2.revoke('WRITE') # revoke write access only
|
|
690
|
-
#
|
|
691
|
-
class Grantee
|
|
692
|
-
# A bucket or a key the grantee has an access to.
|
|
693
|
-
attr_reader :thing
|
|
694
|
-
# Grantee Amazon id.
|
|
695
|
-
attr_reader :id
|
|
696
|
-
# Grantee display name.
|
|
697
|
-
attr_reader :name
|
|
698
|
-
# Array of permissions.
|
|
699
|
-
attr_accessor :perms
|
|
700
|
-
|
|
701
|
-
# Retrieve Owner information and a list of Grantee instances that have
|
|
702
|
-
# a access to this thing (bucket or key).
|
|
703
|
-
#
|
|
704
|
-
# bucket = s3.bucket('my_awesome_bucket', true, 'public-read')
|
|
705
|
-
# ...
|
|
706
|
-
# Aws::S3::Grantee.owner_and_grantees(bucket) #=> [owner, grantees]
|
|
707
|
-
#
|
|
708
|
-
def self.owner_and_grantees(thing)
|
|
709
|
-
if thing.is_a?(Bucket)
|
|
710
|
-
bucket, key = thing, ''
|
|
711
|
-
else
|
|
712
|
-
bucket, key = thing.bucket, thing
|
|
662
|
+
# Return Owner name as a +String+.
|
|
663
|
+
def to_s
|
|
664
|
+
@name
|
|
665
|
+
end
|
|
713
666
|
end
|
|
714
|
-
hash = bucket.s3.interface.get_acl_parse(bucket.to_s, key.to_s)
|
|
715
|
-
owner = Owner.new(hash[:owner][:id], hash[:owner][:display_name])
|
|
716
667
|
|
|
717
|
-
grantees = []
|
|
718
|
-
hash[:grantees].each do |id, params|
|
|
719
|
-
grantees << new(thing, id, params[:permissions], nil, params[:display_name])
|
|
720
|
-
end
|
|
721
|
-
[owner, grantees]
|
|
722
|
-
end
|
|
723
668
|
|
|
724
|
-
#
|
|
669
|
+
# There are 2 ways to set permissions for a bucket or key (called a +thing+ below):
|
|
725
670
|
#
|
|
726
|
-
#
|
|
727
|
-
#
|
|
728
|
-
#
|
|
729
|
-
#
|
|
730
|
-
|
|
731
|
-
owner_and_grantees(thing)[1]
|
|
732
|
-
end
|
|
733
|
-
|
|
734
|
-
def self.put_acl(thing, owner, grantees) #:nodoc:
|
|
735
|
-
if thing.is_a?(Bucket)
|
|
736
|
-
bucket, key = thing, ''
|
|
737
|
-
else
|
|
738
|
-
bucket, key = thing.bucket, thing
|
|
739
|
-
end
|
|
740
|
-
body = "<AccessControlPolicy>" +
|
|
741
|
-
"<Owner>" +
|
|
742
|
-
"<ID>#{owner.id}</ID>" +
|
|
743
|
-
"<DisplayName>#{owner.name}</DisplayName>" +
|
|
744
|
-
"</Owner>" +
|
|
745
|
-
"<AccessControlList>" +
|
|
746
|
-
grantees.map{|grantee| grantee.to_xml}.join +
|
|
747
|
-
"</AccessControlList>" +
|
|
748
|
-
"</AccessControlPolicy>"
|
|
749
|
-
bucket.s3.interface.put_acl(bucket.to_s, key.to_s, body)
|
|
750
|
-
end
|
|
751
|
-
|
|
752
|
-
# Create a new Grantee instance.
|
|
753
|
-
# Grantee +id+ must exist on S3. If +action+ == :refresh, then retrieve
|
|
754
|
-
# permissions from S3 and update @perms. If +action+ == :apply, then apply
|
|
755
|
-
# perms to +thing+ at S3. If +action+ == :apply_and_refresh then it performs.
|
|
756
|
-
# both the actions. This is used for the new grantees that had no perms to
|
|
757
|
-
# this thing before. The default action is :refresh.
|
|
671
|
+
# 1 . Use +perms+ param to set 'Canned Access Policies' when calling the <tt>bucket.create</tt>,
|
|
672
|
+
# <tt>bucket.put</tt> and <tt>key.put</tt> methods.
|
|
673
|
+
# The +perms+ param can take these values: 'private', 'public-read', 'public-read-write' and
|
|
674
|
+
# 'authenticated-read'.
|
|
675
|
+
# (see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAccessPolicy.html).
|
|
758
676
|
#
|
|
759
|
-
# bucket = s3.bucket('
|
|
760
|
-
#
|
|
761
|
-
# ...
|
|
762
|
-
# grantee2 = Aws::S3::Grantee.new(bucket, 'abcde...asdf', [FULL_CONTROL, READ], :apply)
|
|
763
|
-
# grantee3 = Aws::S3::Grantee.new(bucket, 'aaaaa...aaaa', 'READ', :apply_and_refresh)
|
|
764
|
-
#
|
|
765
|
-
def initialize(thing, id, perms=[], action=:refresh, name=nil)
|
|
766
|
-
@thing = thing
|
|
767
|
-
@id = id
|
|
768
|
-
@name = name
|
|
769
|
-
@perms = perms.to_a
|
|
770
|
-
case action
|
|
771
|
-
when :apply then apply
|
|
772
|
-
when :refresh then refresh
|
|
773
|
-
when :apply_and_refresh then apply; refresh
|
|
774
|
-
end
|
|
775
|
-
end
|
|
776
|
-
|
|
777
|
-
# Return +true+ if the grantee has any permissions to the thing.
|
|
778
|
-
def exists?
|
|
779
|
-
self.class.grantees(@thing).each do |grantee|
|
|
780
|
-
return true if @id == grantee.id
|
|
781
|
-
end
|
|
782
|
-
false
|
|
783
|
-
end
|
|
784
|
-
|
|
785
|
-
# Return Grantee type (+String+): "Group" or "CanonicalUser".
|
|
786
|
-
def type
|
|
787
|
-
@id[/^http:/] ? "Group" : "CanonicalUser"
|
|
788
|
-
end
|
|
789
|
-
|
|
790
|
-
# Return a name or an id.
|
|
791
|
-
def to_s
|
|
792
|
-
@name || @id
|
|
793
|
-
end
|
|
794
|
-
|
|
795
|
-
# Add permissions for grantee.
|
|
796
|
-
# Permissions: 'READ', 'WRITE', 'READ_ACP', 'WRITE_ACP', 'FULL_CONTROL'.
|
|
797
|
-
# See http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingPermissions.html .
|
|
798
|
-
# Returns +true+.
|
|
677
|
+
# bucket = s3.bucket('bucket_for_kd_test_13', true, 'public-read')
|
|
678
|
+
# key.put('Woohoo!','public-read-write' )
|
|
799
679
|
#
|
|
800
|
-
#
|
|
801
|
-
#
|
|
802
|
-
# grantee.grant(['WRITE_ACP','READ','READ_ACP']) #=> true
|
|
680
|
+
# 2 . Use Grantee instances (the permission is a +String+ or an +Array+ of: 'READ', 'WRITE',
|
|
681
|
+
# 'READ_ACP', 'WRITE_ACP', 'FULL_CONTROL'):
|
|
803
682
|
#
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
@perms += permissions
|
|
808
|
-
@perms.uniq!
|
|
809
|
-
return true if @perms == old_perms
|
|
810
|
-
apply
|
|
811
|
-
end
|
|
812
|
-
|
|
813
|
-
# Revoke permissions for grantee.
|
|
814
|
-
# Permissions: 'READ', 'WRITE', 'READ_ACP', 'WRITE_ACP', 'FULL_CONTROL'
|
|
815
|
-
# See http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingPermissions.html .
|
|
816
|
-
# Default value is 'FULL_CONTROL'.
|
|
817
|
-
# Returns +true+.
|
|
683
|
+
# bucket = s3.bucket('my_awesome_bucket', true)
|
|
684
|
+
# grantee1 = Aws::S3::Grantee.new(bucket, 'a123b...223c', FULL_CONTROL, :apply)
|
|
685
|
+
# grantee2 = Aws::S3::Grantee.new(bucket, 'xy3v3...5fhp', [READ, WRITE], :apply)
|
|
818
686
|
#
|
|
819
|
-
#
|
|
820
|
-
# grantee.revoke('FULL_CONTROL','WRITE') #=> true
|
|
821
|
-
# grantee.revoke(['READ_ACP','WRITE_ACP']) #=> true
|
|
687
|
+
# There is only one way to get and to remove permission (via Grantee instances):
|
|
822
688
|
#
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
689
|
+
# grantees = bucket.grantees # a list of Grantees that have any access for this bucket
|
|
690
|
+
# grantee1 = Aws::S3::Grantee.new(bucket, 'a123b...223c')
|
|
691
|
+
# grantee1.perms #=> returns a list of perms for this grantee to that bucket
|
|
692
|
+
# ...
|
|
693
|
+
# grantee1.drop # remove all perms for this grantee
|
|
694
|
+
# grantee2.revoke('WRITE') # revoke write access only
|
|
695
|
+
#
|
|
696
|
+
class Grantee
|
|
697
|
+
# A bucket or a key the grantee has an access to.
|
|
698
|
+
attr_reader :thing
|
|
699
|
+
# Grantee Amazon id.
|
|
700
|
+
attr_reader :id
|
|
701
|
+
# Grantee display name.
|
|
702
|
+
attr_reader :name
|
|
703
|
+
# Array of permissions.
|
|
704
|
+
attr_accessor :perms
|
|
705
|
+
|
|
706
|
+
# Retrieve Owner information and a list of Grantee instances that have
|
|
707
|
+
# a access to this thing (bucket or key).
|
|
708
|
+
#
|
|
709
|
+
# bucket = s3.bucket('my_awesome_bucket', true, 'public-read')
|
|
710
|
+
# ...
|
|
711
|
+
# Aws::S3::Grantee.owner_and_grantees(bucket) #=> [owner, grantees]
|
|
712
|
+
#
|
|
713
|
+
def self.owner_and_grantees(thing)
|
|
714
|
+
if thing.is_a?(Bucket)
|
|
715
|
+
bucket, key = thing, ''
|
|
716
|
+
else
|
|
717
|
+
bucket, key = thing.bucket, thing
|
|
718
|
+
end
|
|
719
|
+
hash = bucket.s3.interface.get_acl_parse(bucket.to_s, key.to_s)
|
|
720
|
+
owner = Owner.new(hash[:owner][:id], hash[:owner][:display_name])
|
|
721
|
+
|
|
722
|
+
grantees = []
|
|
723
|
+
hash[:grantees].each do |id, params|
|
|
724
|
+
grantees << new(thing, id, params[:permissions], nil, params[:display_name])
|
|
725
|
+
end
|
|
726
|
+
[owner, grantees]
|
|
727
|
+
end
|
|
728
|
+
|
|
729
|
+
# Retrieves a list of Grantees instances that have an access to this thing(bucket or key).
|
|
730
|
+
#
|
|
731
|
+
# bucket = s3.bucket('my_awesome_bucket', true, 'public-read')
|
|
732
|
+
# ...
|
|
733
|
+
# Aws::S3::Grantee.grantees(bucket) #=> grantees
|
|
734
|
+
#
|
|
735
|
+
def self.grantees(thing)
|
|
736
|
+
owner_and_grantees(thing)[1]
|
|
737
|
+
end
|
|
738
|
+
|
|
739
|
+
def self.put_acl(thing, owner, grantees) #:nodoc:
|
|
740
|
+
if thing.is_a?(Bucket)
|
|
741
|
+
bucket, key = thing, ''
|
|
742
|
+
else
|
|
743
|
+
bucket, key = thing.bucket, thing
|
|
744
|
+
end
|
|
745
|
+
body = "<AccessControlPolicy>" +
|
|
746
|
+
"<Owner>" +
|
|
747
|
+
"<ID>#{owner.id}</ID>" +
|
|
748
|
+
"<DisplayName>#{owner.name}</DisplayName>" +
|
|
749
|
+
"</Owner>" +
|
|
750
|
+
"<AccessControlList>" +
|
|
751
|
+
grantees.map { |grantee| grantee.to_xml }.join +
|
|
752
|
+
"</AccessControlList>" +
|
|
753
|
+
"</AccessControlPolicy>"
|
|
754
|
+
bucket.s3.interface.put_acl(bucket.to_s, key.to_s, body)
|
|
755
|
+
end
|
|
756
|
+
|
|
757
|
+
# Create a new Grantee instance.
|
|
758
|
+
# Grantee +id+ must exist on S3. If +action+ == :refresh, then retrieve
|
|
759
|
+
# permissions from S3 and update @perms. If +action+ == :apply, then apply
|
|
760
|
+
# perms to +thing+ at S3. If +action+ == :apply_and_refresh then it performs.
|
|
761
|
+
# both the actions. This is used for the new grantees that had no perms to
|
|
762
|
+
# this thing before. The default action is :refresh.
|
|
763
|
+
#
|
|
764
|
+
# bucket = s3.bucket('my_awesome_bucket', true, 'public-read')
|
|
765
|
+
# grantee1 = Aws::S3::Grantee.new(bucket, 'a123b...223c', FULL_CONTROL)
|
|
766
|
+
# ...
|
|
767
|
+
# grantee2 = Aws::S3::Grantee.new(bucket, 'abcde...asdf', [FULL_CONTROL, READ], :apply)
|
|
768
|
+
# grantee3 = Aws::S3::Grantee.new(bucket, 'aaaaa...aaaa', 'READ', :apply_and_refresh)
|
|
769
|
+
#
|
|
770
|
+
def initialize(thing, id, perms=[], action=:refresh, name=nil)
|
|
771
|
+
@thing = thing
|
|
772
|
+
@id = id
|
|
773
|
+
@name = name
|
|
774
|
+
@perms = perms.to_a
|
|
775
|
+
case action
|
|
776
|
+
when :apply then
|
|
777
|
+
apply
|
|
778
|
+
when :refresh then
|
|
779
|
+
refresh
|
|
780
|
+
when :apply_and_refresh then
|
|
781
|
+
apply; refresh
|
|
782
|
+
end
|
|
783
|
+
end
|
|
784
|
+
|
|
785
|
+
# Return +true+ if the grantee has any permissions to the thing.
|
|
786
|
+
def exists?
|
|
787
|
+
self.class.grantees(@thing).each do |grantee|
|
|
788
|
+
return true if @id == grantee.id
|
|
789
|
+
end
|
|
790
|
+
false
|
|
791
|
+
end
|
|
792
|
+
|
|
793
|
+
# Return Grantee type (+String+): "Group" or "CanonicalUser".
|
|
794
|
+
def type
|
|
795
|
+
@id[/^http:/] ? "Group" : "CanonicalUser"
|
|
796
|
+
end
|
|
797
|
+
|
|
798
|
+
# Return a name or an id.
|
|
799
|
+
def to_s
|
|
800
|
+
@name || @id
|
|
801
|
+
end
|
|
802
|
+
|
|
803
|
+
# Add permissions for grantee.
|
|
804
|
+
# Permissions: 'READ', 'WRITE', 'READ_ACP', 'WRITE_ACP', 'FULL_CONTROL'.
|
|
805
|
+
# See http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingPermissions.html .
|
|
806
|
+
# Returns +true+.
|
|
807
|
+
#
|
|
808
|
+
# grantee.grant('FULL_CONTROL') #=> true
|
|
809
|
+
# grantee.grant('FULL_CONTROL','WRITE','READ') #=> true
|
|
810
|
+
# grantee.grant(['WRITE_ACP','READ','READ_ACP']) #=> true
|
|
811
|
+
#
|
|
812
|
+
def grant(*permissions)
|
|
813
|
+
permissions.flatten!
|
|
814
|
+
old_perms = @perms.dup
|
|
815
|
+
@perms += permissions
|
|
816
|
+
@perms.uniq!
|
|
817
|
+
return true if @perms == old_perms
|
|
818
|
+
apply
|
|
819
|
+
end
|
|
820
|
+
|
|
821
|
+
# Revoke permissions for grantee.
|
|
822
|
+
# Permissions: 'READ', 'WRITE', 'READ_ACP', 'WRITE_ACP', 'FULL_CONTROL'
|
|
823
|
+
# See http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingPermissions.html .
|
|
824
|
+
# Default value is 'FULL_CONTROL'.
|
|
825
|
+
# Returns +true+.
|
|
826
|
+
#
|
|
827
|
+
# grantee.revoke('READ') #=> true
|
|
828
|
+
# grantee.revoke('FULL_CONTROL','WRITE') #=> true
|
|
829
|
+
# grantee.revoke(['READ_ACP','WRITE_ACP']) #=> true
|
|
830
|
+
#
|
|
831
|
+
def revoke(*permissions)
|
|
832
|
+
permissions.flatten!
|
|
833
|
+
old_perms = @perms.dup
|
|
834
|
+
@perms -= permissions
|
|
835
|
+
@perms.uniq!
|
|
836
|
+
return true if @perms == old_perms
|
|
837
|
+
apply
|
|
838
|
+
end
|
|
839
|
+
|
|
840
|
+
# Revoke all permissions for this grantee.
|
|
841
|
+
# Returns +true+.
|
|
842
|
+
#
|
|
843
|
+
# grantee.drop #=> true
|
|
844
|
+
#
|
|
845
|
+
def drop
|
|
846
|
+
@perms = []
|
|
847
|
+
apply
|
|
848
|
+
end
|
|
849
|
+
|
|
850
|
+
# Refresh grantee perms for its +thing+.
|
|
851
|
+
# Returns +true+ if the grantee has perms for this +thing+ or
|
|
852
|
+
# +false+ otherwise, and updates @perms value as a side-effect.
|
|
853
|
+
#
|
|
854
|
+
# grantee.grant('FULL_CONTROL') #=> true
|
|
855
|
+
# grantee.refresh #=> true
|
|
856
|
+
# grantee.drop #=> true
|
|
857
|
+
# grantee.refresh #=> false
|
|
858
|
+
#
|
|
859
|
+
def refresh
|
|
860
|
+
@perms = []
|
|
861
|
+
self.class.grantees(@thing).each do |grantee|
|
|
862
|
+
if @id == grantee.id
|
|
863
|
+
@name = grantee.name
|
|
864
|
+
@perms = grantee.perms
|
|
865
|
+
return true
|
|
866
|
+
end
|
|
867
|
+
end
|
|
868
|
+
false
|
|
869
|
+
end
|
|
870
|
+
|
|
871
|
+
# Apply current grantee @perms to +thing+. This method is called internally by the +grant+
|
|
872
|
+
# and +revoke+ methods. In normal use this method should not
|
|
873
|
+
# be called directly.
|
|
874
|
+
#
|
|
875
|
+
# grantee.perms = ['FULL_CONTROL']
|
|
876
|
+
# grantee.apply #=> true
|
|
877
|
+
#
|
|
878
|
+
def apply
|
|
879
|
+
@perms.uniq!
|
|
880
|
+
owner, grantees = self.class.owner_and_grantees(@thing)
|
|
881
|
+
# walk through all the grantees and replace the data for the current one and ...
|
|
882
|
+
grantees.map! { |grantee| grantee.id == @id ? self : grantee }
|
|
883
|
+
# ... if this grantee is not known - add this bad boy to a list
|
|
884
|
+
grantees << self unless grantees.include?(self)
|
|
885
|
+
# set permissions
|
|
886
|
+
self.class.put_acl(@thing, owner, grantees)
|
|
887
|
+
end
|
|
888
|
+
|
|
889
|
+
def to_xml # :nodoc:
|
|
890
|
+
id_str = @id[/^http/] ? "<URI>#{@id}</URI>" : "<ID>#{@id}</ID>"
|
|
891
|
+
grants = ''
|
|
892
|
+
@perms.each do |perm|
|
|
893
|
+
grants << "<Grant>" +
|
|
894
|
+
"<Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
|
895
|
+
"xsi:type=\"#{type}\">#{id_str}</Grantee>" +
|
|
896
|
+
"<Permission>#{perm}</Permission>" +
|
|
897
|
+
"</Grant>"
|
|
898
|
+
end
|
|
899
|
+
grants
|
|
900
|
+
end
|
|
862
901
|
|
|
863
|
-
# Apply current grantee @perms to +thing+. This method is called internally by the +grant+
|
|
864
|
-
# and +revoke+ methods. In normal use this method should not
|
|
865
|
-
# be called directly.
|
|
866
|
-
#
|
|
867
|
-
# grantee.perms = ['FULL_CONTROL']
|
|
868
|
-
# grantee.apply #=> true
|
|
869
|
-
#
|
|
870
|
-
def apply
|
|
871
|
-
@perms.uniq!
|
|
872
|
-
owner, grantees = self.class.owner_and_grantees(@thing)
|
|
873
|
-
# walk through all the grantees and replace the data for the current one and ...
|
|
874
|
-
grantees.map! { |grantee| grantee.id == @id ? self : grantee }
|
|
875
|
-
# ... if this grantee is not known - add this bad boy to a list
|
|
876
|
-
grantees << self unless grantees.include?(self)
|
|
877
|
-
# set permissions
|
|
878
|
-
self.class.put_acl(@thing, owner, grantees)
|
|
879
|
-
end
|
|
880
|
-
|
|
881
|
-
def to_xml # :nodoc:
|
|
882
|
-
id_str = @id[/^http/] ? "<URI>#{@id}</URI>" : "<ID>#{@id}</ID>"
|
|
883
|
-
grants = ''
|
|
884
|
-
@perms.each do |perm|
|
|
885
|
-
grants << "<Grant>" +
|
|
886
|
-
"<Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
|
887
|
-
"xsi:type=\"#{type}\">#{id_str}</Grantee>" +
|
|
888
|
-
"<Permission>#{perm}</Permission>" +
|
|
889
|
-
"</Grant>"
|
|
890
902
|
end
|
|
891
|
-
grants
|
|
892
|
-
end
|
|
893
903
|
|
|
894
904
|
end
|
|
895
905
|
|
|
896
|
-
end
|
|
897
|
-
|
|
898
906
|
# Aws::S3Generator and Aws::S3Generator::Bucket methods:
|
|
899
907
|
#
|
|
900
908
|
# s3g = Aws::S3Generator.new('1...2', 'nx...Y6') #=> #<Aws::S3Generator:0xb7b5cc94>
|
|
@@ -932,170 +940,171 @@ module Aws
|
|
|
932
940
|
# # Delete key (method 'DELETE'):
|
|
933
941
|
# key.delete #=> https://s3.amazonaws.com:443/my_awesome_bucket/my_cool_key?Signature=x...D&Expires=1180820032&AWSAccessKeyId=1...2
|
|
934
942
|
#
|
|
935
|
-
|
|
936
|
-
|
|
943
|
+
class S3Generator
|
|
944
|
+
attr_reader :interface
|
|
937
945
|
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
# Generate link to list all buckets
|
|
943
|
-
#
|
|
944
|
-
# s3.buckets(1.hour)
|
|
945
|
-
#
|
|
946
|
-
def buckets(expires=nil, headers={})
|
|
947
|
-
@interface.list_all_my_buckets_link(expires, headers)
|
|
948
|
-
end
|
|
949
|
-
|
|
950
|
-
# Create new S3LinkBucket instance and generate link to create it at S3.
|
|
951
|
-
#
|
|
952
|
-
# bucket= s3.bucket('my_owesome_bucket')
|
|
953
|
-
#
|
|
954
|
-
def bucket(name, expires=nil, headers={})
|
|
955
|
-
Bucket.create(self, name.to_s)
|
|
956
|
-
end
|
|
957
|
-
|
|
958
|
-
class Bucket
|
|
959
|
-
attr_reader :s3, :name
|
|
960
|
-
|
|
961
|
-
def to_s
|
|
962
|
-
@name
|
|
963
|
-
end
|
|
964
|
-
alias_method :full_name, :to_s
|
|
965
|
-
|
|
966
|
-
# Return a public link to bucket.
|
|
967
|
-
#
|
|
968
|
-
# bucket.public_link #=> 'https://s3.amazonaws.com:443/my_awesome_bucket'
|
|
969
|
-
#
|
|
970
|
-
def public_link
|
|
971
|
-
params = @s3.interface.params
|
|
972
|
-
"#{params[:protocol]}://#{params[:server]}:#{params[:port]}/#{full_name}"
|
|
973
|
-
end
|
|
974
|
-
|
|
975
|
-
# Create new S3LinkBucket instance and generate creation link for it.
|
|
976
|
-
def self.create(s3, name, expires=nil, headers={})
|
|
977
|
-
new(s3, name.to_s)
|
|
978
|
-
end
|
|
979
|
-
|
|
980
|
-
# Create new S3LinkBucket instance.
|
|
981
|
-
def initialize(s3, name)
|
|
982
|
-
@s3, @name = s3, name.to_s
|
|
983
|
-
end
|
|
984
|
-
|
|
985
|
-
# Return a link to create this bucket.
|
|
986
|
-
#
|
|
987
|
-
def create_link(expires=nil, headers={})
|
|
988
|
-
@s3.interface.create_bucket_link(@name, expires, headers)
|
|
989
|
-
end
|
|
990
|
-
|
|
991
|
-
# Generate link to list keys.
|
|
992
|
-
#
|
|
993
|
-
# bucket.keys
|
|
994
|
-
# bucket.keys('prefix'=>'logs')
|
|
995
|
-
#
|
|
996
|
-
def keys(options=nil, expires=nil, headers={})
|
|
997
|
-
@s3.interface.list_bucket_link(@name, options, expires, headers)
|
|
998
|
-
end
|
|
999
|
-
|
|
1000
|
-
# Return a S3Generator::Key instance.
|
|
1001
|
-
#
|
|
1002
|
-
# bucket.key('my_cool_key').get #=> https://s3.amazonaws.com:443/my_awesome_bucket/my_cool_key?Signature=B...D&Expires=1180820032&AWSAccessKeyId=1...2
|
|
1003
|
-
# bucket.key('my_cool_key').delete #=> https://s3.amazonaws.com:443/my_awesome_bucket/my_cool_key?Signature=B...D&Expires=1180820098&AWSAccessKeyId=1...2
|
|
1004
|
-
#
|
|
1005
|
-
def key(name)
|
|
1006
|
-
Key.new(self, name)
|
|
1007
|
-
end
|
|
1008
|
-
|
|
1009
|
-
# Generates link to PUT key data.
|
|
1010
|
-
#
|
|
1011
|
-
# puts bucket.put('logs/today/1.log', 2.hour)
|
|
1012
|
-
#
|
|
1013
|
-
def put(key, meta_headers={}, expires=nil, headers={})
|
|
1014
|
-
meta = Aws::S3::Key.add_meta_prefix(meta_headers)
|
|
1015
|
-
@s3.interface.put_link(@name, key.to_s, nil, expires, meta.merge(headers))
|
|
1016
|
-
end
|
|
1017
|
-
|
|
1018
|
-
# Generate link to GET key data.
|
|
1019
|
-
#
|
|
1020
|
-
# bucket.get('logs/today/1.log', 1.hour)
|
|
1021
|
-
#
|
|
1022
|
-
def get(key, expires=nil, headers={})
|
|
1023
|
-
@s3.interface.get_link(@name, key.to_s, expires, headers)
|
|
1024
|
-
end
|
|
1025
|
-
|
|
1026
|
-
# Generate link to delete bucket.
|
|
1027
|
-
#
|
|
1028
|
-
# bucket.delete(2.hour)
|
|
1029
|
-
#
|
|
1030
|
-
def delete(expires=nil, headers={})
|
|
1031
|
-
@s3.interface.delete_bucket_link(@name, expires, headers)
|
|
1032
|
-
end
|
|
1033
|
-
end
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
class Key
|
|
1037
|
-
attr_reader :bucket, :name
|
|
1038
|
-
|
|
1039
|
-
def to_s
|
|
1040
|
-
@name
|
|
1041
|
-
end
|
|
946
|
+
def initialize(aws_access_key_id, aws_secret_access_key, params={})
|
|
947
|
+
@interface = S3Interface.new(aws_access_key_id, aws_secret_access_key, params)
|
|
948
|
+
end
|
|
1042
949
|
|
|
1043
|
-
#
|
|
950
|
+
# Generate link to list all buckets
|
|
1044
951
|
#
|
|
1045
|
-
#
|
|
952
|
+
# s3.buckets(1.hour)
|
|
1046
953
|
#
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
954
|
+
def buckets(expires=nil, headers={})
|
|
955
|
+
@interface.list_all_my_buckets_link(expires, headers)
|
|
956
|
+
end
|
|
1050
957
|
|
|
1051
|
-
#
|
|
1052
|
-
#
|
|
1053
|
-
# key.public_link #=> 'https://s3.amazonaws.com:443/my_awesome_bucket/cool_key'
|
|
958
|
+
# Create new S3LinkBucket instance and generate link to create it at S3.
|
|
1054
959
|
#
|
|
1055
|
-
|
|
1056
|
-
params = @bucket.s3.interface.params
|
|
1057
|
-
"#{params[:protocol]}://#{params[:server]}:#{params[:port]}/#{full_name('/')}"
|
|
1058
|
-
end
|
|
1059
|
-
|
|
1060
|
-
def initialize(bucket, name, meta_headers={})
|
|
1061
|
-
@bucket = bucket
|
|
1062
|
-
@name = name.to_s
|
|
1063
|
-
@meta_headers = meta_headers
|
|
1064
|
-
raise 'Key name can not be empty.' if @name.blank?
|
|
1065
|
-
end
|
|
1066
|
-
|
|
1067
|
-
# Generate link to PUT key data.
|
|
960
|
+
# bucket= s3.bucket('my_owesome_bucket')
|
|
1068
961
|
#
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
@bucket.put(@name.to_s, @meta_headers, expires, headers)
|
|
1073
|
-
end
|
|
962
|
+
def bucket(name, expires=nil, headers={})
|
|
963
|
+
Bucket.create(self, name.to_s)
|
|
964
|
+
end
|
|
1074
965
|
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
966
|
+
class Bucket
|
|
967
|
+
attr_reader :s3, :name
|
|
968
|
+
|
|
969
|
+
def to_s
|
|
970
|
+
@name
|
|
971
|
+
end
|
|
972
|
+
|
|
973
|
+
alias_method :full_name, :to_s
|
|
974
|
+
|
|
975
|
+
# Return a public link to bucket.
|
|
976
|
+
#
|
|
977
|
+
# bucket.public_link #=> 'https://s3.amazonaws.com:443/my_awesome_bucket'
|
|
978
|
+
#
|
|
979
|
+
def public_link
|
|
980
|
+
params = @s3.interface.params
|
|
981
|
+
"#{params[:protocol]}://#{params[:server]}:#{params[:port]}/#{full_name}"
|
|
982
|
+
end
|
|
983
|
+
|
|
984
|
+
# Create new S3LinkBucket instance and generate creation link for it.
|
|
985
|
+
def self.create(s3, name, expires=nil, headers={})
|
|
986
|
+
new(s3, name.to_s)
|
|
987
|
+
end
|
|
988
|
+
|
|
989
|
+
# Create new S3LinkBucket instance.
|
|
990
|
+
def initialize(s3, name)
|
|
991
|
+
@s3, @name = s3, name.to_s
|
|
992
|
+
end
|
|
993
|
+
|
|
994
|
+
# Return a link to create this bucket.
|
|
995
|
+
#
|
|
996
|
+
def create_link(expires=nil, headers={})
|
|
997
|
+
@s3.interface.create_bucket_link(@name, expires, headers)
|
|
998
|
+
end
|
|
999
|
+
|
|
1000
|
+
# Generate link to list keys.
|
|
1001
|
+
#
|
|
1002
|
+
# bucket.keys
|
|
1003
|
+
# bucket.keys('prefix'=>'logs')
|
|
1004
|
+
#
|
|
1005
|
+
def keys(options=nil, expires=nil, headers={})
|
|
1006
|
+
@s3.interface.list_bucket_link(@name, options, expires, headers)
|
|
1007
|
+
end
|
|
1008
|
+
|
|
1009
|
+
# Return a S3Generator::Key instance.
|
|
1010
|
+
#
|
|
1011
|
+
# bucket.key('my_cool_key').get #=> https://s3.amazonaws.com:443/my_awesome_bucket/my_cool_key?Signature=B...D&Expires=1180820032&AWSAccessKeyId=1...2
|
|
1012
|
+
# bucket.key('my_cool_key').delete #=> https://s3.amazonaws.com:443/my_awesome_bucket/my_cool_key?Signature=B...D&Expires=1180820098&AWSAccessKeyId=1...2
|
|
1013
|
+
#
|
|
1014
|
+
def key(name)
|
|
1015
|
+
Key.new(self, name)
|
|
1016
|
+
end
|
|
1017
|
+
|
|
1018
|
+
# Generates link to PUT key data.
|
|
1019
|
+
#
|
|
1020
|
+
# puts bucket.put('logs/today/1.log', 2.hour)
|
|
1021
|
+
#
|
|
1022
|
+
def put(key, meta_headers={}, expires=nil, headers={})
|
|
1023
|
+
meta = Aws::S3::Key.add_meta_prefix(meta_headers)
|
|
1024
|
+
@s3.interface.put_link(@name, key.to_s, nil, expires, meta.merge(headers))
|
|
1025
|
+
end
|
|
1026
|
+
|
|
1027
|
+
# Generate link to GET key data.
|
|
1028
|
+
#
|
|
1029
|
+
# bucket.get('logs/today/1.log', 1.hour)
|
|
1030
|
+
#
|
|
1031
|
+
def get(key, expires=nil, headers={})
|
|
1032
|
+
@s3.interface.get_link(@name, key.to_s, expires, headers)
|
|
1033
|
+
end
|
|
1034
|
+
|
|
1035
|
+
# Generate link to delete bucket.
|
|
1036
|
+
#
|
|
1037
|
+
# bucket.delete(2.hour)
|
|
1038
|
+
#
|
|
1039
|
+
def delete(expires=nil, headers={})
|
|
1040
|
+
@s3.interface.delete_bucket_link(@name, expires, headers)
|
|
1041
|
+
end
|
|
1042
|
+
end
|
|
1082
1043
|
|
|
1083
|
-
# Generate link to delete key.
|
|
1084
|
-
#
|
|
1085
|
-
# bucket.delete(2.hour) #=> https://s3.amazonaws.com:443/my_awesome_bucket/logs%2Ftoday%2F1.log?Signature=4...D&Expires=1180820032&AWSAccessKeyId=1...2
|
|
1086
|
-
#
|
|
1087
|
-
def delete(expires=nil, headers={})
|
|
1088
|
-
@bucket.s3.interface.delete_link(@bucket.to_s, @name, expires, headers)
|
|
1089
|
-
end
|
|
1090
1044
|
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1045
|
+
class Key
|
|
1046
|
+
attr_reader :bucket, :name
|
|
1047
|
+
|
|
1048
|
+
def to_s
|
|
1049
|
+
@name
|
|
1050
|
+
end
|
|
1051
|
+
|
|
1052
|
+
# Return a full S# name (bucket/key).
|
|
1053
|
+
#
|
|
1054
|
+
# key.full_name #=> 'my_awesome_bucket/cool_key'
|
|
1055
|
+
#
|
|
1056
|
+
def full_name(separator='/')
|
|
1057
|
+
"#{@bucket.to_s}#{separator}#{@name}"
|
|
1058
|
+
end
|
|
1059
|
+
|
|
1060
|
+
# Return a public link to key.
|
|
1061
|
+
#
|
|
1062
|
+
# key.public_link #=> 'https://s3.amazonaws.com:443/my_awesome_bucket/cool_key'
|
|
1063
|
+
#
|
|
1064
|
+
def public_link
|
|
1065
|
+
params = @bucket.s3.interface.params
|
|
1066
|
+
"#{params[:protocol]}://#{params[:server]}:#{params[:port]}/#{full_name('/')}"
|
|
1067
|
+
end
|
|
1068
|
+
|
|
1069
|
+
def initialize(bucket, name, meta_headers={})
|
|
1070
|
+
@bucket = bucket
|
|
1071
|
+
@name = name.to_s
|
|
1072
|
+
@meta_headers = meta_headers
|
|
1073
|
+
raise 'Key name can not be empty.' if @name.blank?
|
|
1074
|
+
end
|
|
1075
|
+
|
|
1076
|
+
# Generate link to PUT key data.
|
|
1077
|
+
#
|
|
1078
|
+
# puts bucket.put('logs/today/1.log', '123', 2.hour) #=> https://s3.amazonaws.com:443/my_awesome_bucket/logs%2Ftoday%2F1.log?Signature=B...D&Expires=1180820032&AWSAccessKeyId=1...2
|
|
1079
|
+
#
|
|
1080
|
+
def put(expires=nil, headers={})
|
|
1081
|
+
@bucket.put(@name.to_s, @meta_headers, expires, headers)
|
|
1082
|
+
end
|
|
1083
|
+
|
|
1084
|
+
# Generate link to GET key data.
|
|
1085
|
+
#
|
|
1086
|
+
# bucket.get('logs/today/1.log', 1.hour) #=> https://s3.amazonaws.com:443/my_awesome_bucket/logs%2Ftoday%2F1.log?Signature=h...M%3D&Expires=1180820032&AWSAccessKeyId=1...2
|
|
1087
|
+
#
|
|
1088
|
+
def get(expires=nil, headers={})
|
|
1089
|
+
@bucket.s3.interface.get_link(@bucket.to_s, @name, expires, headers)
|
|
1090
|
+
end
|
|
1091
|
+
|
|
1092
|
+
# Generate link to delete key.
|
|
1093
|
+
#
|
|
1094
|
+
# bucket.delete(2.hour) #=> https://s3.amazonaws.com:443/my_awesome_bucket/logs%2Ftoday%2F1.log?Signature=4...D&Expires=1180820032&AWSAccessKeyId=1...2
|
|
1095
|
+
#
|
|
1096
|
+
def delete(expires=nil, headers={})
|
|
1097
|
+
@bucket.s3.interface.delete_link(@bucket.to_s, @name, expires, headers)
|
|
1098
|
+
end
|
|
1099
|
+
|
|
1100
|
+
# Generate link to head key.
|
|
1101
|
+
#
|
|
1102
|
+
# bucket.head(2.hour) #=> https://s3.amazonaws.com:443/my_awesome_bucket/logs%2Ftoday%2F1.log?Signature=4...D&Expires=1180820032&AWSAccessKeyId=1...2
|
|
1103
|
+
#
|
|
1104
|
+
def head(expires=nil, headers={})
|
|
1105
|
+
@bucket.s3.interface.head_link(@bucket.to_s, @name, expires, headers)
|
|
1106
|
+
end
|
|
1107
|
+
end
|
|
1098
1108
|
end
|
|
1099
|
-
end
|
|
1100
1109
|
|
|
1101
1110
|
end
|