s3 0.3.2 → 0.3.4
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/Gemfile.lock +2 -5
- data/lib/s3/bucket.rb +1 -1
- data/lib/s3/service.rb +2 -2
- data/lib/s3/signature.rb +78 -34
- data/lib/s3/version.rb +1 -1
- data/s3.gemspec +1 -2
- data/test/signature_test.rb +62 -0
- metadata +13 -27
- data/bin/s3 +0 -187
data/Gemfile.lock
CHANGED
@@ -1,19 +1,17 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
s3 (0.3.
|
4
|
+
s3 (0.3.3)
|
5
5
|
proxies
|
6
|
-
trollop
|
7
6
|
|
8
7
|
GEM
|
9
8
|
remote: http://rubygems.org/
|
10
9
|
specs:
|
11
10
|
mocha (0.9.8)
|
12
11
|
rake
|
13
|
-
proxies (0.
|
12
|
+
proxies (0.2.1)
|
14
13
|
rake (0.8.7)
|
15
14
|
test-unit (2.1.1)
|
16
|
-
trollop (1.16.2)
|
17
15
|
|
18
16
|
PLATFORMS
|
19
17
|
ruby
|
@@ -24,4 +22,3 @@ DEPENDENCIES
|
|
24
22
|
proxies
|
25
23
|
s3!
|
26
24
|
test-unit (>= 2.0)
|
27
|
-
trollop
|
data/lib/s3/bucket.rb
CHANGED
@@ -85,7 +85,7 @@ module S3
|
|
85
85
|
# Returns the objects in the bucket and caches the result (see
|
86
86
|
# #reload method).
|
87
87
|
def objects
|
88
|
-
|
88
|
+
Proxy.new(lambda { list_bucket }, :owner => self, :extend => ObjectsExtension)
|
89
89
|
end
|
90
90
|
|
91
91
|
def inspect #:nodoc:
|
data/lib/s3/service.rb
CHANGED
@@ -28,7 +28,7 @@ module S3
|
|
28
28
|
@use_ssl = options.fetch(:use_ssl, false)
|
29
29
|
@timeout = options.fetch(:timeout, 60)
|
30
30
|
@debug = options.fetch(:debug, false)
|
31
|
-
|
31
|
+
|
32
32
|
raise ArgumentError, "Missing proxy settings. Must specify at least :host." if options[:proxy] && !options[:proxy][:host]
|
33
33
|
@proxy = options.fetch(:proxy, nil)
|
34
34
|
end
|
@@ -36,7 +36,7 @@ module S3
|
|
36
36
|
# Returns all buckets in the service and caches the result (see
|
37
37
|
# +reload+)
|
38
38
|
def buckets
|
39
|
-
|
39
|
+
Proxy.new(lambda { list_all_my_buckets}, :owner => self, :extend => BucketsExtension)
|
40
40
|
end
|
41
41
|
|
42
42
|
# Returns "http://" or "https://", depends on <tt>:use_ssl</tt>
|
data/lib/s3/signature.rb
CHANGED
@@ -23,64 +23,108 @@ module S3
|
|
23
23
|
# Generated signature string for given hostname and request
|
24
24
|
def self.generate(options)
|
25
25
|
request = options[:request]
|
26
|
-
host = options[:host]
|
27
26
|
access_key_id = options[:access_key_id]
|
28
|
-
secret_access_key = options[:secret_access_key]
|
29
|
-
|
30
|
-
http_verb = request.method
|
31
|
-
content_md5 = request["content-md5"] || ""
|
32
|
-
content_type = request["content-type"] || ""
|
33
|
-
date = request["x-amz-date"].nil? ? request["date"] : ""
|
34
|
-
canonicalized_resource = canonicalized_resource(host, request)
|
35
|
-
canonicalized_amz_headers = canonicalized_amz_headers(request)
|
36
27
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
string_to_sign << content_md5
|
41
|
-
string_to_sign << "\n"
|
42
|
-
string_to_sign << content_type
|
43
|
-
string_to_sign << "\n"
|
44
|
-
string_to_sign << date
|
45
|
-
string_to_sign << "\n"
|
46
|
-
string_to_sign << canonicalized_amz_headers
|
47
|
-
string_to_sign << canonicalized_resource
|
28
|
+
options.merge!(:headers => request,
|
29
|
+
:method => request.method,
|
30
|
+
:resource => request.path)
|
48
31
|
|
49
|
-
|
50
|
-
hmac = OpenSSL::HMAC.digest(digest, secret_access_key, string_to_sign)
|
51
|
-
base64 = Base64.encode64(hmac)
|
52
|
-
signature = base64.chomp
|
32
|
+
signature = canonicalized_signature(options)
|
53
33
|
|
54
34
|
"AWS #{access_key_id}:#{signature}"
|
55
35
|
end
|
56
36
|
|
57
|
-
# Generates temporary URL for given resource
|
37
|
+
# Generates temporary URL signature for given resource
|
58
38
|
#
|
59
39
|
# ==== Options
|
60
40
|
# * <tt>:bucket</tt> - Bucket in which the resource resides
|
61
41
|
# * <tt>:resource</tt> - Path to the resouce you want to create
|
62
|
-
# a
|
42
|
+
# a temporary link to
|
63
43
|
# * <tt>:secret_access_key</tt> - Secret access key
|
64
|
-
# * <tt>:
|
44
|
+
# * <tt>:expires_at</tt> - Unix time stamp of when the resouce
|
65
45
|
# link will expire
|
46
|
+
# * <tt>:method</tt> - HTTP request method you want to use on
|
47
|
+
# the resource, defaults to GET
|
48
|
+
# * <tt>:headers</tt> - Any additional HTTP headers you intend
|
49
|
+
# to use when requesting the resource
|
66
50
|
def self.generate_temporary_url_signature(options)
|
67
51
|
bucket = options[:bucket]
|
68
52
|
resource = options[:resource]
|
69
53
|
secret_access_key = options[:secret_access_key]
|
70
54
|
expires = options[:expires_at]
|
71
55
|
|
72
|
-
|
56
|
+
headers = options[:headers] || {}
|
57
|
+
headers.merge!('date' => expires.to_i.to_s)
|
73
58
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
signature =
|
59
|
+
options.merge!(:resource => "/#{bucket}/#{resource}",
|
60
|
+
:method => options[:method] || :get,
|
61
|
+
:headers => headers)
|
62
|
+
signature = canonicalized_signature(options)
|
78
63
|
|
79
64
|
CGI.escape(signature)
|
80
65
|
end
|
81
66
|
|
67
|
+
# Generates temporary URL for given resource
|
68
|
+
#
|
69
|
+
# ==== Options
|
70
|
+
# * <tt>:bucket</tt> - Bucket in which the resource resides
|
71
|
+
# * <tt>:resource</tt> - Path to the resouce you want to create
|
72
|
+
# a temporary link to
|
73
|
+
# * <tt>:access_key</tt> - Access key
|
74
|
+
# * <tt>:secret_access_key</tt> - Secret access key
|
75
|
+
# * <tt>:expires_at</tt> - Unix time stamp of when the resouce
|
76
|
+
# link will expire
|
77
|
+
# * <tt>:method</tt> - HTTP request method you want to use on
|
78
|
+
# the resource, defaults to GET
|
79
|
+
# * <tt>:headers</tt> - Any additional HTTP headers you intend
|
80
|
+
# to use when requesting the resource
|
81
|
+
def self.generate_temporary_url(options)
|
82
|
+
bucket = options[:bucket]
|
83
|
+
resource = options[:resource]
|
84
|
+
access_key = options[:access_key]
|
85
|
+
expires = options[:expires_at].to_i
|
86
|
+
signature = generate_temporary_url_signature(options)
|
87
|
+
|
88
|
+
url = "http://#{S3::HOST}/#{bucket}/#{resource}"
|
89
|
+
url << "?AWSAccessKeyId=#{access_key}"
|
90
|
+
url << "&Expires=#{expires}"
|
91
|
+
url << "&Signature=#{signature}"
|
92
|
+
end
|
93
|
+
|
82
94
|
private
|
83
95
|
|
96
|
+
def self.canonicalized_signature(options)
|
97
|
+
headers = options[:headers] || {}
|
98
|
+
host = options[:host] || ""
|
99
|
+
resource = options[:resource]
|
100
|
+
access_key_id = options[:access_key_id]
|
101
|
+
secret_access_key = options[:secret_access_key]
|
102
|
+
|
103
|
+
http_verb = options[:method].to_s.upcase
|
104
|
+
content_md5 = headers["content-md5"] || ""
|
105
|
+
content_type = headers["content-type"] || ""
|
106
|
+
date = headers["x-amz-date"].nil? ? headers["date"] : ""
|
107
|
+
canonicalized_resource = canonicalized_resource(host, resource)
|
108
|
+
canonicalized_amz_headers = canonicalized_amz_headers(headers)
|
109
|
+
|
110
|
+
string_to_sign = ""
|
111
|
+
string_to_sign << http_verb
|
112
|
+
string_to_sign << "\n"
|
113
|
+
string_to_sign << content_md5
|
114
|
+
string_to_sign << "\n"
|
115
|
+
string_to_sign << content_type
|
116
|
+
string_to_sign << "\n"
|
117
|
+
string_to_sign << date
|
118
|
+
string_to_sign << "\n"
|
119
|
+
string_to_sign << canonicalized_amz_headers
|
120
|
+
string_to_sign << canonicalized_resource
|
121
|
+
|
122
|
+
digest = OpenSSL::Digest::Digest.new('sha1')
|
123
|
+
hmac = OpenSSL::HMAC.digest(digest, secret_access_key, string_to_sign)
|
124
|
+
base64 = Base64.encode64(hmac)
|
125
|
+
base64.chomp
|
126
|
+
end
|
127
|
+
|
84
128
|
# Helper method for extracting header fields from Net::HTTPRequest
|
85
129
|
# and preparing them for singing in #generate method
|
86
130
|
#
|
@@ -157,7 +201,7 @@ module S3
|
|
157
201
|
#
|
158
202
|
# ==== Returns
|
159
203
|
# String containing extracted canonicalized resource
|
160
|
-
def self.canonicalized_resource(host,
|
204
|
+
def self.canonicalized_resource(host, resource)
|
161
205
|
# 1. Start with the empty string ("").
|
162
206
|
string = ""
|
163
207
|
|
@@ -172,7 +216,7 @@ module S3
|
|
172
216
|
|
173
217
|
# 3. Append the path part of the un-decoded HTTP Request-URI,
|
174
218
|
# up-to but not including the query string.
|
175
|
-
uri = URI.parse(
|
219
|
+
uri = URI.parse(resource)
|
176
220
|
string << uri.path
|
177
221
|
|
178
222
|
# 4. If the request addresses a sub-resource, like ?location,
|
data/lib/s3/version.rb
CHANGED
data/s3.gemspec
CHANGED
@@ -9,13 +9,12 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.authors = ["Jakub Kuźma"]
|
10
10
|
s.email = ["qoobaa@gmail.com"]
|
11
11
|
s.homepage = "http://jah.pl/projects/s3.html"
|
12
|
-
s.summary = "Library for accessing S3 objects and buckets
|
12
|
+
s.summary = "Library for accessing S3 objects and buckets"
|
13
13
|
s.description = "S3 library provides access to Amazon's Simple Storage Service. It supports both: European and US buckets through REST API."
|
14
14
|
|
15
15
|
s.required_rubygems_version = ">= 1.3.6"
|
16
16
|
s.rubyforge_project = "s3"
|
17
17
|
|
18
|
-
s.add_dependency "trollop"
|
19
18
|
s.add_dependency "proxies"
|
20
19
|
s.add_development_dependency "test-unit", ">= 2.0"
|
21
20
|
s.add_development_dependency "mocha"
|
data/test/signature_test.rb
CHANGED
@@ -140,4 +140,66 @@ class SignatureTest < Test::Unit::TestCase
|
|
140
140
|
expected = "AWS 0PN5J17HBGZHT7JJ3X82:dxhSBHoI6eVSPcXJqEghlUzZMnY="
|
141
141
|
assert_equal expected, actual
|
142
142
|
end
|
143
|
+
|
144
|
+
test "temporary signature for object get" do
|
145
|
+
actual = S3::Signature.generate_temporary_url_signature(
|
146
|
+
:bucket => "johnsmith",
|
147
|
+
:resource => "photos/puppy.jpg",
|
148
|
+
:secret_access_key => "uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o",
|
149
|
+
:expires_at => 1175046589
|
150
|
+
)
|
151
|
+
expected = "gs6xNznrLJ4Bd%2B1y9pcy2HOSVeg%3D"
|
152
|
+
assert_equal expected, actual
|
153
|
+
end
|
154
|
+
|
155
|
+
test "temporary signature for object post" do
|
156
|
+
actual = S3::Signature.generate_temporary_url_signature(
|
157
|
+
:bucket => "johnsmith",
|
158
|
+
:resource => "photos/puppy.jpg",
|
159
|
+
:secret_access_key => "uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o",
|
160
|
+
:expires_at => 1175046589,
|
161
|
+
:method => :post
|
162
|
+
)
|
163
|
+
expected = "duIzwO2KTEMIlbSYbFFS86Wj0LI%3D"
|
164
|
+
assert_equal expected, actual
|
165
|
+
end
|
166
|
+
|
167
|
+
test "temporary signature for object put with headers" do
|
168
|
+
actual = S3::Signature.generate_temporary_url_signature(
|
169
|
+
:bucket => "johnsmith",
|
170
|
+
:resource => "photos/puppy.jpg",
|
171
|
+
:secret_access_key => "uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o",
|
172
|
+
:expires_at => 1175046589,
|
173
|
+
:method => :put,
|
174
|
+
:headers => {'x-amz-acl' => 'public-read'}
|
175
|
+
)
|
176
|
+
expected = "SDMxjIkOKIVR47nWfJ57UNPXxFM%3D"
|
177
|
+
assert_equal expected, actual
|
178
|
+
end
|
179
|
+
|
180
|
+
test "temporary signature for object delete" do
|
181
|
+
actual = S3::Signature.generate_temporary_url_signature(
|
182
|
+
:bucket => "johnsmith",
|
183
|
+
:resource => "photos/puppy.jpg",
|
184
|
+
:secret_access_key => "uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o",
|
185
|
+
:expires_at => 1175046589,
|
186
|
+
:method => :delete
|
187
|
+
)
|
188
|
+
expected = "5Vg7A4HxgS6tVCYzBx%2BkMR8sztY%3D"
|
189
|
+
assert_equal expected, actual
|
190
|
+
end
|
191
|
+
|
192
|
+
test "temporary url for object put with headers" do
|
193
|
+
actual = S3::Signature.generate_temporary_url(
|
194
|
+
:bucket => "johnsmith",
|
195
|
+
:resource => "photos/puppy.jpg",
|
196
|
+
:access_key => '0PN5J17HBGZHT7JJ3X82',
|
197
|
+
:secret_access_key => "uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o",
|
198
|
+
:expires_at => 1175046589,
|
199
|
+
:method => :put,
|
200
|
+
:headers => {'x-amz-acl' => 'public-read'}
|
201
|
+
)
|
202
|
+
expected = "http://s3.amazonaws.com/johnsmith/photos/puppy.jpg?AWSAccessKeyId=0PN5J17HBGZHT7JJ3X82&Expires=1175046589&Signature=SDMxjIkOKIVR47nWfJ57UNPXxFM%3D"
|
203
|
+
assert_equal expected, actual
|
204
|
+
end
|
143
205
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 3
|
8
|
-
-
|
9
|
-
version: 0.3.
|
8
|
+
- 4
|
9
|
+
version: 0.3.4
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- "Jakub Ku\xC5\xBAma"
|
@@ -14,11 +14,11 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-09-
|
17
|
+
date: 2010-09-25 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
|
-
name:
|
21
|
+
name: proxies
|
22
22
|
prerelease: false
|
23
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
24
|
none: false
|
@@ -30,23 +30,10 @@ dependencies:
|
|
30
30
|
version: "0"
|
31
31
|
type: :runtime
|
32
32
|
version_requirements: *id001
|
33
|
-
- !ruby/object:Gem::Dependency
|
34
|
-
name: proxies
|
35
|
-
prerelease: false
|
36
|
-
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
-
none: false
|
38
|
-
requirements:
|
39
|
-
- - ">="
|
40
|
-
- !ruby/object:Gem::Version
|
41
|
-
segments:
|
42
|
-
- 0
|
43
|
-
version: "0"
|
44
|
-
type: :runtime
|
45
|
-
version_requirements: *id002
|
46
33
|
- !ruby/object:Gem::Dependency
|
47
34
|
name: test-unit
|
48
35
|
prerelease: false
|
49
|
-
requirement: &
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
50
37
|
none: false
|
51
38
|
requirements:
|
52
39
|
- - ">="
|
@@ -56,11 +43,11 @@ dependencies:
|
|
56
43
|
- 0
|
57
44
|
version: "2.0"
|
58
45
|
type: :development
|
59
|
-
version_requirements: *
|
46
|
+
version_requirements: *id002
|
60
47
|
- !ruby/object:Gem::Dependency
|
61
48
|
name: mocha
|
62
49
|
prerelease: false
|
63
|
-
requirement: &
|
50
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
64
51
|
none: false
|
65
52
|
requirements:
|
66
53
|
- - ">="
|
@@ -69,11 +56,11 @@ dependencies:
|
|
69
56
|
- 0
|
70
57
|
version: "0"
|
71
58
|
type: :development
|
72
|
-
version_requirements: *
|
59
|
+
version_requirements: *id003
|
73
60
|
- !ruby/object:Gem::Dependency
|
74
61
|
name: bundler
|
75
62
|
prerelease: false
|
76
|
-
requirement: &
|
63
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
77
64
|
none: false
|
78
65
|
requirements:
|
79
66
|
- - ">="
|
@@ -84,12 +71,12 @@ dependencies:
|
|
84
71
|
- 0
|
85
72
|
version: 1.0.0
|
86
73
|
type: :development
|
87
|
-
version_requirements: *
|
74
|
+
version_requirements: *id004
|
88
75
|
description: "S3 library provides access to Amazon's Simple Storage Service. It supports both: European and US buckets through REST API."
|
89
76
|
email:
|
90
77
|
- qoobaa@gmail.com
|
91
|
-
executables:
|
92
|
-
|
78
|
+
executables: []
|
79
|
+
|
93
80
|
extensions: []
|
94
81
|
|
95
82
|
extra_rdoc_files: []
|
@@ -101,7 +88,6 @@ files:
|
|
101
88
|
- LICENSE
|
102
89
|
- README.rdoc
|
103
90
|
- Rakefile
|
104
|
-
- bin/s3
|
105
91
|
- extra/s3_attachment_fu.rb
|
106
92
|
- extra/s3_paperclip.rb
|
107
93
|
- lib/s3.rb
|
@@ -155,6 +141,6 @@ rubyforge_project: s3
|
|
155
141
|
rubygems_version: 1.3.7
|
156
142
|
signing_key:
|
157
143
|
specification_version: 3
|
158
|
-
summary: Library for accessing S3 objects and buckets
|
144
|
+
summary: Library for accessing S3 objects and buckets
|
159
145
|
test_files: []
|
160
146
|
|
data/bin/s3
DELETED
@@ -1,187 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
$: << File.expand_path(File.dirname(__FILE__) + "/../lib")
|
4
|
-
|
5
|
-
require "trollop"
|
6
|
-
require "s3"
|
7
|
-
|
8
|
-
# HELPER METHODS
|
9
|
-
|
10
|
-
include S3
|
11
|
-
|
12
|
-
def list_buckets(service)
|
13
|
-
service.buckets.each do |bucket|
|
14
|
-
puts bucket.name
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def create_bucket(service, name, location)
|
19
|
-
service.buckets.build(name).save(location)
|
20
|
-
end
|
21
|
-
|
22
|
-
def destroy_bucket(service, name)
|
23
|
-
service.buckets.find(name).destroy
|
24
|
-
end
|
25
|
-
|
26
|
-
def show_bucket(service, name, options = {})
|
27
|
-
service.buckets.find(name).objects.find_all.each do |object|
|
28
|
-
puts "#{name}/#{object.key}"
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def list_objects(service)
|
33
|
-
service.buckets.each do |bucket|
|
34
|
-
bucket.objects.each do |object|
|
35
|
-
puts "#{bucket.name}/#{object.key}"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def create_object(service, name, file_name, options = {})
|
41
|
-
bucket_name, object_name = name.split("/", 2)
|
42
|
-
object = service.buckets.find(bucket_name).objects.build(object_name)
|
43
|
-
object.content_type = options[:type]
|
44
|
-
object.content_encoding = options[:encoding]
|
45
|
-
object.content_disposition = options[:disposition]
|
46
|
-
object.acl = options[:acl]
|
47
|
-
object.content = File.new(file_name)
|
48
|
-
object.save
|
49
|
-
end
|
50
|
-
|
51
|
-
def destroy_object(service, name)
|
52
|
-
bucket_name, object_name = name.split("/", 2)
|
53
|
-
object = service.buckets.find(bucket_name).objects.find(object_name)
|
54
|
-
object.destroy
|
55
|
-
end
|
56
|
-
|
57
|
-
def show_object(service, name, file_name = nil)
|
58
|
-
bucket_name, object_name = name.split("/", 2)
|
59
|
-
object = service.buckets.find(bucket_name).objects.find_first(object_name)
|
60
|
-
puts " object: #{object.name}/#{object.key}"
|
61
|
-
puts " content type: #{object.content_type}"
|
62
|
-
puts " size: #{object.size}"
|
63
|
-
puts " etag: #{object.etag}"
|
64
|
-
puts " last modified: #{object.last_modified}"
|
65
|
-
if file_name
|
66
|
-
if file_name == "-"
|
67
|
-
puts object.content
|
68
|
-
else
|
69
|
-
File.open(file_name, "wb") do |file|
|
70
|
-
file.write(object.content)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
# COMMAND LINE PARSER
|
77
|
-
|
78
|
-
ACCESS_KEY_ID = ENV["ACCESS_KEY_ID"]
|
79
|
-
SECRET_ACCESS_KEY = ENV["SECRET_ACCESS_KEY"]
|
80
|
-
COMMANDS = %w(bucket object)
|
81
|
-
BUCKET_SUBCOMMANDS = %w(add remove show)
|
82
|
-
OBJECT_SUBCOMMANDS = %w(add remove show)
|
83
|
-
|
84
|
-
global_options = Trollop::options do
|
85
|
-
banner "s3 command line tool"
|
86
|
-
opt :access_key_id, "Your access key id to AWS", :type => :string, :default => ACCESS_KEY_ID
|
87
|
-
opt :secret_access_key, "Your secret access key to AWS", :type => :string, :default => SECRET_ACCESS_KEY
|
88
|
-
opt :debug, "Debug mode", :type => :flag, :default => false
|
89
|
-
stop_on COMMANDS
|
90
|
-
end
|
91
|
-
|
92
|
-
Trollop::die "No access key id given" unless global_options[:access_key_id]
|
93
|
-
Trollop::die "No secret access key given" unless global_options[:secret_access_key]
|
94
|
-
|
95
|
-
service = Service.new(:access_key_id => global_options[:access_key_id],
|
96
|
-
:secret_access_key => global_options[:secret_access_key],
|
97
|
-
:debug => global_options[:debug])
|
98
|
-
|
99
|
-
command = ARGV.shift
|
100
|
-
|
101
|
-
begin
|
102
|
-
case command
|
103
|
-
when "bucket"
|
104
|
-
command_options = Trollop::options do
|
105
|
-
banner "manage buckets"
|
106
|
-
stop_on BUCKET_SUBCOMMANDS
|
107
|
-
end
|
108
|
-
subcommand = ARGV.shift
|
109
|
-
case subcommand
|
110
|
-
when "add"
|
111
|
-
subcommand_options = Trollop::options do
|
112
|
-
banner "add bucket"
|
113
|
-
opt :location, "Location of the bucket - EU or US", :default => "US", :type => :string
|
114
|
-
end
|
115
|
-
name = ARGV.shift
|
116
|
-
Trollop::die "Bucket has not been added because of unknown error" unless create_bucket(service, name, subcommand_options[:location])
|
117
|
-
when "remove"
|
118
|
-
subcommand_options = Trollop::options do
|
119
|
-
banner "remove bucket"
|
120
|
-
end
|
121
|
-
name = ARGV.shift
|
122
|
-
Trollop::die "Bucket name must be given" if name.nil? or name.empty?
|
123
|
-
Trollop::die "Bucket has not been removed because of unknown error" unless destroy_bucket(service, name)
|
124
|
-
when "show"
|
125
|
-
subcommand_options = Trollop::options do
|
126
|
-
banner "show bucket"
|
127
|
-
opt :prefix, "Limits the response to keys which begin with the indicated prefix", :type => :string
|
128
|
-
opt :marker, "Indicates where in the bucket to begin listing", :type => :string
|
129
|
-
opt :max_keys, "The maximum number of keys you'd like to see", :type => :integer
|
130
|
-
opt :delimiter, "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", :type => :string
|
131
|
-
end
|
132
|
-
name = ARGV.shift
|
133
|
-
Trollop::die "Bucket name must be given" if name.nil? or name.empty?
|
134
|
-
show_bucket(service, name, subcommand_options)
|
135
|
-
when nil
|
136
|
-
list_buckets(service)
|
137
|
-
else
|
138
|
-
Trollop::die "Unknown subcommand: #{subcommand.inspect}"
|
139
|
-
end
|
140
|
-
when "object"
|
141
|
-
command_options = Trollop::options do
|
142
|
-
banner "manage objects"
|
143
|
-
stop_on OBJECT_SUBCOMMANDS
|
144
|
-
end
|
145
|
-
subcommand = ARGV.shift
|
146
|
-
case subcommand
|
147
|
-
when "add"
|
148
|
-
subcommand_options = Trollop::options do
|
149
|
-
banner "object add s3_object_name local_file_name"
|
150
|
-
opt :type, "A standard MIME type describing the format of the contents", :default => "binary/octet-stream"
|
151
|
-
opt :disposition, "Specifies presentational information for the object", :type => :string
|
152
|
-
opt :encoding, "Specifies what content encodings have been applied to the object and thus what decoding mechanisms must be applied in order to obtain the media-type referenced by the Content-Type header field", :type => :string
|
153
|
-
opt :acl, "The canned ACL to apply to the object. Options include private, public-read, public-read-write, and authenticated-read", :type => :string
|
154
|
-
end
|
155
|
-
name = ARGV.shift
|
156
|
-
Trollop::die "No object name given" if name.nil? or name.empty?
|
157
|
-
file_name = ARGV.shift
|
158
|
-
Trollop::die "No file name given" if file_name.nil? or file_name.empty?
|
159
|
-
Trollop::die "Object has not been added because of unknown error" unless create_object(service, name, file_name, subcommand_options)
|
160
|
-
when "remove"
|
161
|
-
subcommand_options = Trollop::options do
|
162
|
-
banner "object remove s3_object_name"
|
163
|
-
end
|
164
|
-
name = ARGV.shift
|
165
|
-
Trollop::die "No object name given" if name.nil? or name.empty?
|
166
|
-
Trollop::die "Object has not been removed because of unknown error" unless destroy_object(service, name)
|
167
|
-
when "show"
|
168
|
-
subcommand_options = Trollop::options do
|
169
|
-
banner "object show s3_object_name optional_file_name"
|
170
|
-
end
|
171
|
-
name = ARGV.shift
|
172
|
-
Trollop::die "No object name given" if name.nil? or name.empty?
|
173
|
-
file_name = ARGV.shift
|
174
|
-
show_object(service, name, file_name)
|
175
|
-
when nil
|
176
|
-
list_objects(service)
|
177
|
-
else
|
178
|
-
Trollop::die "Unknown subcommand: #{subcommand.inspect}"
|
179
|
-
end
|
180
|
-
when nil
|
181
|
-
Trollop::die "No command given"
|
182
|
-
else
|
183
|
-
Trollop::die "Unknown command #{command.inspect}"
|
184
|
-
end
|
185
|
-
rescue Error::ResponseError => e
|
186
|
-
Trollop::die e.message.sub(/\.+\Z/, "")
|
187
|
-
end
|