right_aws_api 0.1.0
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.
- checksums.yaml +7 -0
- data/HISTORY +2 -0
- data/LICENSE +19 -0
- data/README.md +164 -0
- data/Rakefile +38 -0
- data/lib/cloud/aws/as/manager.rb +118 -0
- data/lib/cloud/aws/base/helpers/utils.rb +328 -0
- data/lib/cloud/aws/base/manager.rb +186 -0
- data/lib/cloud/aws/base/parsers/response_error.rb +117 -0
- data/lib/cloud/aws/base/routines/request_signer.rb +80 -0
- data/lib/cloud/aws/cf/manager.rb +171 -0
- data/lib/cloud/aws/cf/routines/request_signer.rb +70 -0
- data/lib/cloud/aws/cf/wrappers/default.rb +213 -0
- data/lib/cloud/aws/cfm/manager.rb +90 -0
- data/lib/cloud/aws/cw/manager.rb +113 -0
- data/lib/cloud/aws/eb/manager.rb +87 -0
- data/lib/cloud/aws/ec/manager.rb +91 -0
- data/lib/cloud/aws/ec2/manager.rb +222 -0
- data/lib/cloud/aws/elb/manager.rb +120 -0
- data/lib/cloud/aws/emr/manager.rb +86 -0
- data/lib/cloud/aws/iam/manager.rb +100 -0
- data/lib/cloud/aws/rds/manager.rb +110 -0
- data/lib/cloud/aws/route53/manager.rb +177 -0
- data/lib/cloud/aws/route53/routines/request_signer.rb +70 -0
- data/lib/cloud/aws/route53/wrappers/default.rb +132 -0
- data/lib/cloud/aws/s3/manager.rb +373 -0
- data/lib/cloud/aws/s3/parsers/response_error.rb +76 -0
- data/lib/cloud/aws/s3/routines/request_signer.rb +243 -0
- data/lib/cloud/aws/s3/wrappers/default.rb +315 -0
- data/lib/cloud/aws/sdb/manager.rb +150 -0
- data/lib/cloud/aws/sns/manager.rb +96 -0
- data/lib/cloud/aws/sqs/manager.rb +335 -0
- data/lib/right_aws_api.rb +45 -0
- data/lib/right_aws_api_version.rb +40 -0
- data/right_aws_api.gemspec +55 -0
- data/spec/describe_calls.rb +92 -0
- metadata +118 -0
@@ -0,0 +1,70 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2013 RightScale, Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# 'Software'), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
18
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
19
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
20
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
21
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
module RightScale
|
25
|
+
module CloudApi
|
26
|
+
module AWS
|
27
|
+
module Route53
|
28
|
+
|
29
|
+
# Route 53 request signer
|
30
|
+
class RequestSigner < CloudApi::Routine
|
31
|
+
|
32
|
+
# Route53 RequestSigner Error
|
33
|
+
class Error < CloudApi::Error
|
34
|
+
end
|
35
|
+
|
36
|
+
# Authenticates a Route53 request
|
37
|
+
#
|
38
|
+
# @return [void]
|
39
|
+
#
|
40
|
+
# @example
|
41
|
+
# # no example
|
42
|
+
#
|
43
|
+
def process
|
44
|
+
# Fix body
|
45
|
+
unless @data[:request][:body]._blank?
|
46
|
+
# Make sure 'content-type' is set if we have a body
|
47
|
+
@data[:request][:headers].set_if_blank('content-type', 'application/xml' )
|
48
|
+
# Fix body if it is a Hash instance
|
49
|
+
if @data[:request][:body].is_a?(Hash)
|
50
|
+
@data[:request][:body] = Utils::contentify_body(@data[:request][:body], @data[:request][:headers]['content-type'])
|
51
|
+
end
|
52
|
+
# Calculate 'content-md5' when possible (some API calls wanna have it set)
|
53
|
+
if @data[:request][:body].is_a?(String)
|
54
|
+
@data[:request][:headers]['content-md5'] = Base64::encode64(Digest::MD5::digest(@data[:request][:body])).strip
|
55
|
+
end
|
56
|
+
end
|
57
|
+
# Set date
|
58
|
+
@data[:request][:headers].set_if_blank('date', Time::now.utc.httpdate)
|
59
|
+
# Sign a request
|
60
|
+
signature = Utils::AWS::sign(@data[:credentials][:aws_secret_access_key], Utils::dearrayify(@data[:request][:headers]['date']))
|
61
|
+
@data[:request][:headers]['x-amzn-authorization'] = "AWS3-HTTPS AWSAccessKeyId=#{@data[:credentials][:aws_access_key_id]},Algorithm=HmacSHA1,Signature=#{signature}"
|
62
|
+
# Set path
|
63
|
+
@data[:request][:path] = Utils::join_urn(@data[:connection][:uri].path, @data[:options][:api_version], @data[:request][:relative_path], @data[:request][:params])
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2013 RightScale, Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# 'Software'), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
18
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
19
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
20
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
21
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
module RightScale
|
25
|
+
module CloudApi
|
26
|
+
module AWS
|
27
|
+
module Route53
|
28
|
+
|
29
|
+
# Route 53 wrapper namespace
|
30
|
+
module Wrapper
|
31
|
+
|
32
|
+
# Default wrapper
|
33
|
+
module DEFAULT
|
34
|
+
|
35
|
+
# Defines QUERY API like methods for the service
|
36
|
+
#
|
37
|
+
# @return [void]
|
38
|
+
#
|
39
|
+
# @example
|
40
|
+
# # no example
|
41
|
+
#
|
42
|
+
def self.extended(base)
|
43
|
+
|
44
|
+
#-----------------
|
45
|
+
# Hosted Zones
|
46
|
+
#-----------------
|
47
|
+
|
48
|
+
|
49
|
+
base.query_api_pattern 'ListHostedZones', :get, 'hostedzone'
|
50
|
+
|
51
|
+
|
52
|
+
base.query_api_pattern 'GetHostedZone', :get, 'hostedzone/{:HostedZoneId}'
|
53
|
+
|
54
|
+
|
55
|
+
base.query_api_pattern 'CreateHostedZones', :post, 'hostedzone',
|
56
|
+
:body => {
|
57
|
+
'CreateHostedZoneRequest' => {
|
58
|
+
'Name' => :Name,
|
59
|
+
'CallerReference' => :CallerReference,
|
60
|
+
'HostedZoneConfig{!remove-if-blank}' => {
|
61
|
+
'Comment' => :Comment
|
62
|
+
}
|
63
|
+
}
|
64
|
+
},
|
65
|
+
:defaults => {
|
66
|
+
:Comment => Utils::NONE
|
67
|
+
}
|
68
|
+
|
69
|
+
|
70
|
+
base.query_api_pattern 'DeleteHostedZone', :delete, 'hostedzone/{:HostedZoneId}'
|
71
|
+
|
72
|
+
|
73
|
+
#----------------------
|
74
|
+
# Resource Record Sets
|
75
|
+
#----------------------
|
76
|
+
|
77
|
+
|
78
|
+
base.query_api_pattern 'ListResourceRecordSets', :get, 'hostedzone/{:HostedZoneId}/rrset'
|
79
|
+
|
80
|
+
|
81
|
+
base.query_api_pattern 'GetChange', :get, 'change/{:ChangeId}'
|
82
|
+
|
83
|
+
|
84
|
+
base.query_api_pattern 'ChangeResourceRecordSets', :post, 'hostedzone/{:HostedZoneId}/rrset',
|
85
|
+
:body => {
|
86
|
+
'ChangeResourceRecordSetsRequest' => {
|
87
|
+
'@xmlns' => 'https://route53.amazonaws.com/doc/2011-05-05/',
|
88
|
+
'ChangeBatch' => {
|
89
|
+
'Comment' => :Comment,
|
90
|
+
'Changes' => {
|
91
|
+
'Change[{:Change}]' => {
|
92
|
+
'Action' => :Action,
|
93
|
+
'ResourceRecordSet' => {
|
94
|
+
'Name' => :Name,
|
95
|
+
'Type' => :Type,
|
96
|
+
'AliasTarget{!remove-if-blank}' => {
|
97
|
+
'HostedZoneId' => :HostedZoneId,
|
98
|
+
'DNSName' => :DNSName
|
99
|
+
},
|
100
|
+
'SetIdentifier' => :SetIdentifier,
|
101
|
+
'Weight' => :Weight,
|
102
|
+
'TTL' => :TTL,
|
103
|
+
'ResourceRecords{!remove-if-blank}' => {
|
104
|
+
'ResourceRecord{!remove-if-blank}' => {
|
105
|
+
'Value' => :ResourceRecord
|
106
|
+
}
|
107
|
+
}
|
108
|
+
}
|
109
|
+
}
|
110
|
+
}
|
111
|
+
}
|
112
|
+
}
|
113
|
+
},
|
114
|
+
:defaults => {
|
115
|
+
:Comment => Utils::NONE,
|
116
|
+
:TTL => Utils::NONE,
|
117
|
+
:DNSName => Utils::NONE,
|
118
|
+
:HostedZoneId => Utils::NONE,
|
119
|
+
:SetIdentifier => Utils::NONE,
|
120
|
+
:Weight => Utils::NONE,
|
121
|
+
:ResourceRecord => Utils::NONE
|
122
|
+
}
|
123
|
+
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,373 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2013 RightScale, Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# 'Software'), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
18
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
19
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
20
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
21
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
require "cloud/aws/base/helpers/utils"
|
25
|
+
require "cloud/aws/s3/parsers/response_error"
|
26
|
+
require "cloud/aws/s3/wrappers/default"
|
27
|
+
require "cloud/aws/s3/routines/request_signer"
|
28
|
+
|
29
|
+
module RightScale
|
30
|
+
module CloudApi
|
31
|
+
module AWS
|
32
|
+
|
33
|
+
# Simple Storage Service namespace
|
34
|
+
#
|
35
|
+
# @api public
|
36
|
+
#
|
37
|
+
module S3
|
38
|
+
|
39
|
+
# Amazon Simple Storage Service (S3) compatible manager (thread safe).
|
40
|
+
#
|
41
|
+
# @example
|
42
|
+
# require "right_aws_api"
|
43
|
+
#
|
44
|
+
# s3 = RightScale::CloudApi::AWS::S3::Manager.new(key, secret, 'https://s3.amazonaws.com')
|
45
|
+
#
|
46
|
+
# @example
|
47
|
+
# # -- Using HTTP verb methods --
|
48
|
+
#
|
49
|
+
# # List all buckets
|
50
|
+
# s3.get
|
51
|
+
#
|
52
|
+
# # List bucket objects
|
53
|
+
# s3.get('devs-us-east')
|
54
|
+
#
|
55
|
+
# # Get bucket ACL
|
56
|
+
# s3.get('devs-us-east', :params => {'acl' => nil} )
|
57
|
+
#
|
58
|
+
# # Put bucket ACL
|
59
|
+
# s3.put('devs-us-east',
|
60
|
+
# :params => {'acl' => nil},
|
61
|
+
# :body => access_control_policy_xml,
|
62
|
+
# :headers => { 'content-type' => 'application/xml' }
|
63
|
+
# )
|
64
|
+
#
|
65
|
+
# # Get bucket Versions
|
66
|
+
# s3.get('devs-us-east', :params => {'version' => nil} )
|
67
|
+
#
|
68
|
+
# # Get object
|
69
|
+
# s3.get('devs-us-east/boot1.jpg')
|
70
|
+
# # Do not parse response if Amazon reports back XML or JSON content-type
|
71
|
+
# s3.get('devs-us-east/boot1.xml', :options => { :raw_response => true})
|
72
|
+
#
|
73
|
+
# # Get object, force set content-type
|
74
|
+
# s3.get('kd-kd-kd-1/boot1.jpg', :params => { 'response-content-type' => 'image/jpeg'})
|
75
|
+
#
|
76
|
+
# # Put object
|
77
|
+
# # Do not forget to provide a proper 'content-type' header because the default
|
78
|
+
# # one is set to 'application/octet-stream'
|
79
|
+
# s3.put('devs-us-east/boot1.jpg',
|
80
|
+
# :body => 'This is my object DATA. WooHoo!!!',
|
81
|
+
# :headers => {'content-type' => 'text/plain'})
|
82
|
+
#
|
83
|
+
#
|
84
|
+
# @example
|
85
|
+
# # A simple example of a multi-thread file download:
|
86
|
+
# threads = []
|
87
|
+
# file_size = 3257230
|
88
|
+
# chunks = 3
|
89
|
+
# chunk_size = file_size / chunks
|
90
|
+
# chunks.times do |i|
|
91
|
+
# from_byte = i * chunk_size
|
92
|
+
# to_byte = from_byte + chunk_size - 1
|
93
|
+
# to_byte += file_size % chunks if i + 1 == chunks
|
94
|
+
# threads << Thread::new {
|
95
|
+
# Thread.current[:my_file] = s3.get('devs-us-east/xxx/boot.jpg', {:headers => {'Range' => "bytes=#{from_byte}-#{to_byte}"}})
|
96
|
+
# }
|
97
|
+
# end
|
98
|
+
# file_body = ''
|
99
|
+
# threads.each do |thread|
|
100
|
+
# thread.join
|
101
|
+
# file_body << thread[:my_file]
|
102
|
+
# end
|
103
|
+
# file_body.size #=> 3257230
|
104
|
+
#
|
105
|
+
#
|
106
|
+
# @example
|
107
|
+
# # Download into IO object
|
108
|
+
# File.open('/tmp/boot.jpg','w') do |file|
|
109
|
+
# s3.get('devs-us-east/kd/boot.jpg') do |chunk|
|
110
|
+
# file.write(chunk)
|
111
|
+
# end
|
112
|
+
# end
|
113
|
+
#
|
114
|
+
#
|
115
|
+
# @example
|
116
|
+
# # -- Using helper methods --
|
117
|
+
#
|
118
|
+
# # List all buckets
|
119
|
+
# s3.ListAllMyBuckets
|
120
|
+
#
|
121
|
+
# # List bucket objects
|
122
|
+
# s3.ListObjects('Bucket' => 'devs-us-east')
|
123
|
+
#
|
124
|
+
# # Get bucket ACL
|
125
|
+
# s3.GetBucketAcl('Bucket' => 'devs-us-east')
|
126
|
+
#
|
127
|
+
# # Get bucket Versions
|
128
|
+
# s3.GetBucketVersions('Bucket' => 'devs-us-east')
|
129
|
+
#
|
130
|
+
# # Get object
|
131
|
+
# s3.GetObject('Bucket' => 'devs-us-east', 'Object' => 'boot1.jpg')
|
132
|
+
#
|
133
|
+
# # Get object, force set content-type
|
134
|
+
# s3.GetObject('Bucket' => 'devs-us-east', 'Object' => 'boot1.jpg',
|
135
|
+
# :params => { 'response-content-type' => 'image/jpeg'})
|
136
|
+
#
|
137
|
+
# # Put object
|
138
|
+
# # P.S. 'content-type' is 'application/octet-stream' by default
|
139
|
+
# s3.PutObject('Bucket' => 'devs-us-east',
|
140
|
+
# 'Object' => 'boot1.jpg',
|
141
|
+
# :body => file_content,
|
142
|
+
# :headers => {'content-type' => 'image/jpeg'})
|
143
|
+
#
|
144
|
+
# @example
|
145
|
+
#
|
146
|
+
# # List all buckets
|
147
|
+
# s3.ListAllMyBuckets #=>
|
148
|
+
# {"ListAllMyBucketsResult"=>
|
149
|
+
# {"Buckets"=>
|
150
|
+
# {"Bucket"=>
|
151
|
+
# [{"Name"=>"CI_right_test",
|
152
|
+
# "CreationDate"=>"2011-05-25T20:46:28.000Z"},
|
153
|
+
# {"Name"=>"CR_right_test",
|
154
|
+
# "CreationDate"=>"2011-06-08T20:46:32.000Z"},
|
155
|
+
# {"Name"=>"DarrylTest",
|
156
|
+
# "CreationDate"=>"2011-06-03T03:43:08.000Z"},
|
157
|
+
# {"Name"=>"RightScalePeter",
|
158
|
+
# "CreationDate"=>"2008-10-28T03:59:20.000Z"}]},
|
159
|
+
# "Owner"=>
|
160
|
+
# {"DisplayName"=>"fghsfg",
|
161
|
+
# "ID"=>"16144ab2929314cc309ffe736daa2b264357476c7fea6efb2c3347ac3ab2792a"},
|
162
|
+
# "@xmlns"=>"http://s3.amazonaws.com/doc/2006-03-01/"}}
|
163
|
+
#
|
164
|
+
# # List bucket objects
|
165
|
+
# s3.ListObjects('Bucket' => 'devs-us-east', 'max-keys' => 3, 'prefix' => 'kd') #=>
|
166
|
+
# {"ListBucketResult"=>
|
167
|
+
# {"MaxKeys"=>"3",
|
168
|
+
# "IsTruncated"=>"false",
|
169
|
+
# "Name"=>"devs-us-east",
|
170
|
+
# "Marker"=>nil,
|
171
|
+
# "Contents"=>
|
172
|
+
# {"LastModified"=>"2010-08-26T12:23:30.000Z",
|
173
|
+
# "StorageClass"=>"STANDARD",
|
174
|
+
# "ETag"=>"\"3c9a2717e34efedb6d6ac007b2acb8df\"",
|
175
|
+
# "Owner"=>
|
176
|
+
# {"DisplayName"=>"thve",
|
177
|
+
# "ID"=>
|
178
|
+
# "16144ab2929314cc309ffe736daa2b264357476c7fea6efb2c3347ac3ab2792a"},
|
179
|
+
# "Size"=>"3257230",
|
180
|
+
# "Key"=>"kd/boot.jpg"},
|
181
|
+
# "@xmlns"=>"http://s3.amazonaws.com/doc/2006-03-01/",
|
182
|
+
# "Prefix"=>"kd"}}
|
183
|
+
#
|
184
|
+
#
|
185
|
+
# @example
|
186
|
+
# # Get
|
187
|
+
# s3.GetBucketCors('Bucket' => 'my-bucket' ) #=>
|
188
|
+
# {"CORSConfiguration"=>
|
189
|
+
# {"@xmlns"=>"http://s3.amazonaws.com/doc/2006-03-01/",
|
190
|
+
# "CORSRule"=>
|
191
|
+
# [{"AllowedOrigin"=>"http://www.example.com",
|
192
|
+
# "AllowedMethod"=>["PUT", "POST"],
|
193
|
+
# "MaxAgeSeconds"=>"2000",
|
194
|
+
# "ExposeHeader"=>"x-amz-server-side-encryption"},
|
195
|
+
# {"AllowedOrigin"=>"*", "AllowedMethod"=>"GET", "MaxAgeSeconds"=>"2001"}]}}
|
196
|
+
#
|
197
|
+
#
|
198
|
+
# @example
|
199
|
+
# # Put
|
200
|
+
# cors_rules = [
|
201
|
+
# {'AllowedOrigin' => 'http://www.example.com',
|
202
|
+
# 'AllowedMethod' => ['PUT', 'POST'],
|
203
|
+
# 'MaxAgeSeconds' => 3000,
|
204
|
+
# 'ExposeHeader' => 'x-amz-server-side-encryption' },
|
205
|
+
# {'AllowedOrigin' => '*',
|
206
|
+
# 'AllowedMethod' => 'GET',
|
207
|
+
# 'MaxAgeSeconds' => 3000 } ]
|
208
|
+
# s3.PutBucketCors('Bucket' => 'kd-ver-test', 'CORSRule' => cors_rules ) #=> ''
|
209
|
+
#
|
210
|
+
# # .. or
|
211
|
+
# body = "<CORSConfiguration><CORSRule><AllowedOrigin>http://www.example.com</AllowedOrigin>"+
|
212
|
+
# "<AllowedMethod>PUT</AllowedMethod><AllowedMethod>POST</AllowedMethod>"+
|
213
|
+
# "<MaxAgeSeconds>3000</MaxAgeSeconds>..</CORSConfiguration>"
|
214
|
+
# s3.PutBucketCors('Bucket' => 'my-bucket', :body => body ) #=> ''
|
215
|
+
#
|
216
|
+
#
|
217
|
+
# @example
|
218
|
+
# # Delete
|
219
|
+
# s3.DeleteBucketCors('Bucket' => 'my-bucket' ) #=> ''
|
220
|
+
#
|
221
|
+
#
|
222
|
+
# @example
|
223
|
+
# # Bucket Tagging
|
224
|
+
# # Get
|
225
|
+
# s3.GetBucketTagging('Bucket' => 'my-bucket' ) #=>
|
226
|
+
# {"Tagging"=> {
|
227
|
+
# "TagSet"=> {
|
228
|
+
# "Tag"=>[
|
229
|
+
# {"Key"=>"Project",
|
230
|
+
# "Value"=>"Project One"},
|
231
|
+
# {"Key"=>"User",
|
232
|
+
# "Value"=>"jsmith"}]}}}
|
233
|
+
#
|
234
|
+
#
|
235
|
+
# @example
|
236
|
+
# # Delete
|
237
|
+
# s3.DeleteBucketTagging('Bucket' => 'my-bucket' ) #=> ''
|
238
|
+
#
|
239
|
+
#
|
240
|
+
# @example
|
241
|
+
# # Put
|
242
|
+
# tagging_rules = [
|
243
|
+
# {"Key"=>"Project",
|
244
|
+
# "Value"=>"Project One"},
|
245
|
+
# {"Key"=>"User",
|
246
|
+
# "Value"=>"jsmith"} ]
|
247
|
+
# s3.PutBucketTagging('Bucket' => 'my-bucket', 'TagSet' => tagging_rules ) #=> ''
|
248
|
+
#
|
249
|
+
#
|
250
|
+
# @example
|
251
|
+
# # Bucket Lifecycle
|
252
|
+
# # Get
|
253
|
+
# s3.GetBucketLifecycle('Bucket' => 'my-bucket' ) #=>
|
254
|
+
# {"LifecycleConfiguration"=> {
|
255
|
+
# "Rule"=>[{
|
256
|
+
# "ID" => "30-day-log-deletion-rule",
|
257
|
+
# "Prefix" => "logs",
|
258
|
+
# "Status" => "Enabled",
|
259
|
+
# "Expiration" => { "Days" => 30 }}]}}
|
260
|
+
#
|
261
|
+
#
|
262
|
+
# @example
|
263
|
+
# # Delete
|
264
|
+
# s3.DeleteBucketLifecycle('Bucket' => 'my-bucket' ) #=> ''
|
265
|
+
#
|
266
|
+
#
|
267
|
+
# @example
|
268
|
+
# # Put
|
269
|
+
# lifecycle_rules = [
|
270
|
+
# { "ID" => "30-day-log-deletion-rule",
|
271
|
+
# "Prefix" => "logs",
|
272
|
+
# "Status" => "Enabled",
|
273
|
+
# "Expiration" => {"Days" => 30}},
|
274
|
+
# {"ID" => "delete-documents-rule",
|
275
|
+
# "Prefix" => "documents",
|
276
|
+
# "Status" => "Enabled",
|
277
|
+
# "Expiration" => { "Days" => 365 }}]
|
278
|
+
# s3.PutBucketLifecycle('Bucket' => 'my-bucket', 'Rule' => lifecycle_rules ) #=> ''
|
279
|
+
#
|
280
|
+
#
|
281
|
+
# @example
|
282
|
+
# # Get a link to ListAllMyBuckets action
|
283
|
+
# s3.ListAllMyBuckets(:options=>{:cloud=>{:link=>true}}) #=>
|
284
|
+
# {"verb" => "get",
|
285
|
+
# "link" => "https://s3.amazonaws.com/?AWSAccessKeyId=0K4QH...G2&Expires=1426111071&Signature=vLMH...3D",
|
286
|
+
# "headers"=> {"host"=>["s3.amazonaws.com"]}}
|
287
|
+
#
|
288
|
+
# # If you need to get a bunch of links you can use with_options helper method:
|
289
|
+
# opts = {:headers => {'expires' => Time.now + 3600}}
|
290
|
+
# s3.with_options(:cloud=>{:link => true}) do
|
291
|
+
# pp s3.GetObject({'Bucket'=>'my-bucket', 'Object'=>'kd/kd0.test', 'versionId'=>"00eYZeb291o4"}, opts)
|
292
|
+
# pp s3.GetObject({'Bucket'=>'my-bucket', 'Object'=>'kd/kd1.test', 'versionId'=>"fafaf1obp1W4"}, opts)
|
293
|
+
# pp s3.GetObject({'Bucket'=>'my-bucket', 'Object'=>'kd/kd2.test', 'versionId'=>"00asdTebp1W4"}, opts)
|
294
|
+
# pp s3.GetObject({'Bucket'=>'my-bucket', 'Object'=>'kd/kd3.test', 'versionId'=>"0lkjreobp1W4"}, opts)
|
295
|
+
# end
|
296
|
+
#
|
297
|
+
#
|
298
|
+
# @see ApiManager
|
299
|
+
# @see Wrapper::DEFAULT.extended Wrapper::DEFAULT.extended (click [View source])
|
300
|
+
# @see http://docs.aws.amazon.com/AmazonS3/latest/API/APIRest.html
|
301
|
+
#
|
302
|
+
class Manager < CloudApi::Manager
|
303
|
+
end
|
304
|
+
|
305
|
+
|
306
|
+
# Amazon Simple Storage Service (S3) compatible manager (thread unsafe).
|
307
|
+
#
|
308
|
+
# @see Manager
|
309
|
+
#
|
310
|
+
class ApiManager < CloudApi::ApiManager
|
311
|
+
|
312
|
+
# S3 Error
|
313
|
+
class Error < CloudApi::Error
|
314
|
+
end
|
315
|
+
|
316
|
+
include Mixin::QueryApiPatterns
|
317
|
+
|
318
|
+
set_routine CloudApi::RetryManager
|
319
|
+
set_routine CloudApi::RequestInitializer
|
320
|
+
set_routine AWS::S3::RequestSigner
|
321
|
+
set_routine CloudApi::RequestGenerator
|
322
|
+
set_routine CloudApi::ConnectionProxy
|
323
|
+
set_routine CloudApi::ResponseAnalyzer
|
324
|
+
set_routine CloudApi::ResponseParser
|
325
|
+
set_routine CloudApi::ResultWrapper
|
326
|
+
|
327
|
+
set :response_error_parser => Parser::AWS::S3::ResponseError
|
328
|
+
|
329
|
+
|
330
|
+
# Constructor
|
331
|
+
#
|
332
|
+
# @param [String] aws_access_key_id
|
333
|
+
# @param [String] aws_secret_access_key
|
334
|
+
# @param [String] endpoint
|
335
|
+
# @param [Hash] options
|
336
|
+
#
|
337
|
+
# @example
|
338
|
+
# # see Manager class
|
339
|
+
#
|
340
|
+
# @see Manager
|
341
|
+
#
|
342
|
+
def initialize(aws_access_key_id, aws_secret_access_key, endpoint, options={})
|
343
|
+
credentials = { :aws_access_key_id => aws_access_key_id,
|
344
|
+
:aws_secret_access_key => aws_secret_access_key }
|
345
|
+
super(credentials, endpoint, options)
|
346
|
+
end
|
347
|
+
|
348
|
+
|
349
|
+
# Makes an API call to AWS::S3 compatible cloud
|
350
|
+
#
|
351
|
+
# @param [String,Symbol] verb 'get' | 'put' | etc
|
352
|
+
# @param [Objects] args
|
353
|
+
#
|
354
|
+
# @return [Object]
|
355
|
+
#
|
356
|
+
# @example
|
357
|
+
# api(verb, opts={})
|
358
|
+
# api(verb, 'bucket', opts={})
|
359
|
+
# # Where opts may have next keys: :options, :headers, :params, :body
|
360
|
+
# api(verb, 'bucket/object', opts={})
|
361
|
+
#
|
362
|
+
def api(verb, *args, &block)
|
363
|
+
relative_path = args.first.is_a?(String) ? args.shift : ''
|
364
|
+
opts = args.shift || {}
|
365
|
+
raise Error::new("Opts must be Hash not #{opts.class.name}") unless opts.is_a?(Hash)
|
366
|
+
process_api_request(verb, relative_path, opts, &block)
|
367
|
+
end
|
368
|
+
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|