right_aws_api 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 164b81b2c4e7845571d6616ce59b22a3baa7788a
4
- data.tar.gz: e7cbd22f3857d650a026b29699e22cc9718d1821
3
+ metadata.gz: 64f50bf6419f2dab98f45aaf99cdba9cb1239e4f
4
+ data.tar.gz: 02dcede70b66b401f4a2fb1227881623da8a2979
5
5
  SHA512:
6
- metadata.gz: 4b970d6a9794c29953c16e63018f7a97522476f66a7357ea5be7e0bd6d3d110b880615d86531a45a70b7ebe41d96d3bf18697074d2a7fc5844b1fc16caf51089
7
- data.tar.gz: d0846816165f048ebfa43d026d144c03c35158f4006c750a7d0c14117a1f50d4031a3d46422b34321935d182e074f121bc426e84be043b3ba76371ed03b59ffa
6
+ metadata.gz: 8624a2807021be070b88d46783d923df81961ddd802517e61eb74eb2358d28d995c03fe57df35a4ef711c76e39e67de8ed8c954ed66f14725315201ebc644c55
7
+ data.tar.gz: 5464bb232f2fa074ec5a26d8fd04df4c19fd3a7b71ff026ab14d273f791ba9a6ce0e333326d4c8fbf5b73cbd780252b85b140e7566314ccda47530c7454a3a3c
data/HISTORY CHANGED
@@ -1,11 +1,13 @@
1
- == 2015-01-16
2
- - v0.2.2
3
- Added an ability to not use DNS like buckets in AWS S3
4
- Some minor bugs were fixed in singature V4
1
+ == current
5
2
 
6
- == 2014-10-30
7
- - v0.2.1
8
- Added support for AWS v4 signature and make it the default
3
+ == 2015-01-16, v0.2.3
4
+ - Added an ability to not use DNS like buckets in AWS S3
5
+ - Added support for S3 folders creation
9
6
 
10
- == 2013-06-28
11
- - pre-release candidate created
7
+ == 2015-01-16, v0.2.2
8
+ - Some minor bugs were fixed in singature V4
9
+
10
+ == 2014-10-30, v0.2.1
11
+ - Added support for AWS v4 signature and make it the default
12
+
13
+ == 2013-06-28, pre-release
data/README.md CHANGED
@@ -66,6 +66,8 @@ call and you know what params it accepts - just call the method with those param
66
66
  ```ruby
67
67
  require "right_aws_api"
68
68
 
69
+ ec2 = RightScale::CloudApi::AWS::EC2::Manager.new(key, secret, endpoint)
70
+
69
71
  # Get a list of your instances
70
72
  ec2.DescribeInstances
71
73
 
@@ -156,6 +158,110 @@ call and you know what params it accepts - just call the method with those param
156
158
  sqs.DeleteQueue('myCoolQueue')
157
159
  ```
158
160
 
161
+ ### Options
162
+
163
+ There is a way to provide extra options when you instantiate a new manager:
164
+
165
+ ```ruby
166
+ options = { :key => value }
167
+ ec2 = RightScale::CloudApi::AWS::EC2::Manager.new(key, secret, endpoint, options)
168
+ sqs = RightScale::CloudApi::AWS::SQS::Manager.new(key, secret, account_number, endpoint, options)
169
+ s3 = RightScale::CloudApi::AWS::S3::Manager::new(key, secret, endpoint, options)
170
+ etc
171
+ ```
172
+
173
+ The options allow you to tweak the managers behavoir. Here is a list of the options that make sense for AWS services:
174
+
175
+ Name | Type | Default | Description
176
+ -------------------------| --------| ----------------------------|--------------
177
+ :abort_on_timeout | Boolean | false | When set to +true+ the gem does not perform a retry call when there is a connection timeout. This may help you to deal with request idempotence issue. Lets say you make a create call and you get back a timeout. It is possible that AWS created a new resource but just failed to report it properly. It is better to stop here rather than keep retrying creating more and more resources.
178
+ :api_version | String | see service Manager | The required cloud API version if it is different from the default one.
179
+ :cache | Boolean | false | Cache cloud responses when possible so that we don't parse them again if cloud response does not change (see cloud specific ApiManager definition).
180
+ :cloud | Hash | {} | A set of cloud or service specific options. There is an only option for AWS S3 so far: :no_dns_buckets => false/true.
181
+ :connection_open_timeout | Integer | up to NetHttpPersistent gem | Connection open timeout (in seconds).
182
+ :connection_read_timeout | Integer | up to NetHttpPersistent gem | Connection read timeout (in seconds).
183
+ :connection_retry_count | Integer | 3 | Max number of establish connection retry attempts before it gives up.
184
+ :connection_retry_delay | Float | 0.5 | Initial retry backoff delay in seconds. The value is doubled on every retry attempt.
185
+ :connection_verify_mode | Integer | OpenSSL::SSL::VERIFY_PEER | Try OpenSSL::SSL::VERIFY_NONE is there is an SSL sertificate issue with th eremote end. This may happen when working with DNS-line S3 buckets.
186
+ :headers | Hash | {} | A set of request headers to be added to every API request.
187
+ :logger | Logger | -> STDOUT | Current logger. When nil is given it logs to '/dev/nul'.
188
+ :log_filter_patterns | Array | see DEFAULT_LOG_FILTERS | A set of log filters that define what to log (see {RightScale::CloudApi::CloudApiLogger}).
189
+ :params | Hash | {} | A set of URL params to be added to every API request.
190
+ :raw_response | Boolean | false | By default the gem parses all XML and JSON responses and returns them as ruby Hashes. Sometimes it is not what one would want (Amazon S3 GetObject for example). Setting this option to +true+ forces the gem to return the body of the response as it is.
191
+
192
+ For more options see https://github.com/rightscale/right_cloud_api_base/blob/master/lib/base/api_manager.rb
193
+
194
+ ### Response
195
+
196
+ It is easy to get the last HTTP request and response data:
197
+
198
+ ```ruby
199
+ s3.PutObject('Bucket' => 'a.b.c.d.1.com', 'Object' => '13', :body => 'hahaha') #=> ''
200
+
201
+ s3.request.verb # => 'put'
202
+ s3.request.path # => '/13'
203
+ s3.request.headers # =>
204
+ {
205
+ "content-type" => ["binary/octet-stream"],
206
+ "content-length" => [6],
207
+ "content-md5" => ["EBpuyfk4iF3wpE8gRY0utA=="],
208
+ "x-amz-content-sha256" => ["23453452345234523452345"],
209
+ "x-amz-date" => ["20150123T225348Z"],
210
+ "x-amz-expires" => [3600],
211
+ "host" => ["a.b.c.d.1.com.s3.amazonaws.com"],
212
+ "authorization" => ["AWS4-HMAC-SHA256 Credential=000/20150123/us-east-1/s3/aws4_request, SignedHeaders=content-length;content-md5;content-type;host;x-amz-content-sha256;x-amz-date;x-amz-expires, Signature=111"]}
213
+ s3.request.body #=> "hahaha"
214
+
215
+ s3.response.code #=> '200'
216
+ s3.response.headers #=>
217
+ {
218
+ "x-amz-id-2" => ["wB/XOQ+dfgdfgdfgwgfdg"],
219
+ "x-amz-request-id" => ["FEC7DEE7C51ACAB3"],
220
+ "date" => ["Fri, 23 Jan 2015 22:53:49 GMT"],
221
+ "etag" => ["\"101a6ec9f938885df0a44f20458d2eb4\""],
222
+ "content-length" => ["0"],
223
+ "server" => ["AmazonS3"]}
224
+ s3.response.body #=> ''
225
+
226
+ ```
227
+
228
+ Furthermore every response value may return its HTTP response code and HTTP headers through 'metadata' method:
229
+
230
+ ```ruby
231
+ response1 = s3.GetObject('Bucket' => 'a.b.c.d.1.com', 'Object' => '13')
232
+ response2 = s3.GetObject('Bucket' => 'a.b.c.d.1.com', 'Object' => '14')
233
+
234
+ response1 #=> "hahaha"
235
+ response1.metadata #=>
236
+ { :code => '200',
237
+ :headers =>
238
+ {"x-amz-id-2" => ["sdasfdasd="],
239
+ "x-amz-request-id" => ["B2AB70B2D081BF2B"],
240
+ "date" => ["Fri, 23 Jan 2015 23:02:36 GMT"],
241
+ "last-modified" => ["Fri, 23 Jan 2015 22:53:49 GMT"],
242
+ "etag" => ["\"2345435234523452345324\""],
243
+ "accept-ranges" => ["bytes"],
244
+ "content-type" => ["binary/octet-stream"],
245
+ "content-length" => ["6"],
246
+ "server" => ["AmazonS3"]}}
247
+
248
+ response2 #=> "hohohohoho"
249
+ response2.metadata #=>
250
+ { :code => '200',
251
+ :headers =>
252
+ {"x-amz-id-2" => ["asdasdf="],
253
+ "x-amz-request-id" => ["50DBC360C934C548"],
254
+ "date" => ["Fri, 23 Jan 2015 23:02:36 GMT"],
255
+ "last-modified" => ["Fri, 23 Jan 2015 23:01:55 GMT"],
256
+ "etag" => ["\"2345345243523452345234\""],
257
+ "accept-ranges" => ["bytes"],
258
+ "content-type" => ["binary/octet-stream"],
259
+ "content-length" => ["10"],
260
+ "server" => ["AmazonS3"]}}
261
+ ```
262
+
263
+
264
+
159
265
  ## Dependencies
160
266
 
161
267
  This gem depends on a base gem which is shared across all RightScale cloud libraries:
@@ -38,13 +38,35 @@ module RightScale
38
38
 
39
39
  # Amazon Simple Storage Service (S3) compatible manager (thread safe).
40
40
  #
41
+ # There are 2 ways of using S3 API manager: _HTTP verb calls_ or _helper methods_
42
+ #
43
+ # ### HTTP verbs
44
+ #
45
+ # The manager supports following HTTP verbs: get, post, put, head and delete,
46
+ # and all of them share the same syntax:
47
+ #
48
+ # ```ruby
49
+ # s3.post(path, :params => Hash, :headers => Hash, :body => 'foo-bar', :options => Hash)
50
+ # ```
51
+ #
52
+ # ### Helper methods
53
+ #
54
+ # Eventhough the _HTTP verbs_ are powerfull they are not too handy.
55
+ # If you like to call API actions by their name you may find our helper methods usefull.
56
+ #
57
+ # In most cases these methods use the same names and they take the same parameters
58
+ # that Amazon uses in their docs.
59
+ #
60
+ # You can find use case examples for both the verbs and the methods below.
61
+ # The helper method definitions can be found here: https://github.com/rightscale/right_aws_api/blob/master/lib/cloud/aws/s3/wrappers/default.rb
62
+ #
41
63
  # @example
42
64
  # require "right_aws_api"
43
65
  #
44
66
  # s3 = RightScale::CloudApi::AWS::S3::Manager.new(key, secret, 'https://s3.amazonaws.com')
45
67
  #
46
68
  # @example
47
- # # -- Using HTTP verb methods --
69
+ # # -- Using HTTP verbs --
48
70
  #
49
71
  # # List all buckets
50
72
  # s3.get
@@ -75,11 +97,13 @@ module RightScale
75
97
  #
76
98
  # # Put object
77
99
  # # Do not forget to provide a proper 'content-type' header because the default
78
- # # one is set to 'application/octet-stream'
100
+ # # one is set to 'binary/octet-stream'
79
101
  # s3.put('devs-us-east/boot1.jpg',
80
102
  # :body => 'This is my object DATA. WooHoo!!!',
81
103
  # :headers => {'content-type' => 'text/plain'})
82
104
  #
105
+ # # Create a folder
106
+ # s3.put('devs-us-east/logs/')
83
107
  #
84
108
  # @example
85
109
  # # A simple example of a multi-thread file download:
@@ -111,7 +135,6 @@ module RightScale
111
135
  # end
112
136
  # end
113
137
  #
114
- #
115
138
  # @example
116
139
  # # -- Using helper methods --
117
140
  #
@@ -135,12 +158,15 @@ module RightScale
135
158
  # :params => { 'response-content-type' => 'image/jpeg'})
136
159
  #
137
160
  # # Put object
138
- # # P.S. 'content-type' is 'application/octet-stream' by default
161
+ # # P.S. 'content-type' is 'binary/octet-stream' by default
139
162
  # s3.PutObject('Bucket' => 'devs-us-east',
140
163
  # 'Object' => 'boot1.jpg',
141
164
  # :body => file_content,
142
165
  # :headers => {'content-type' => 'image/jpeg'})
143
166
  #
167
+ # # Create a folder
168
+ # s3.PutObject('Bucket' => 'devs-us-east', 'Object' => 'logs/', :body => '')
169
+ #
144
170
  # @example
145
171
  #
146
172
  # # List all buckets
@@ -152,9 +178,9 @@ module RightScale
152
178
  # "CreationDate"=>"2011-05-25T20:46:28.000Z"},
153
179
  # {"Name"=>"CR_right_test",
154
180
  # "CreationDate"=>"2011-06-08T20:46:32.000Z"},
155
- # {"Name"=>"DarrylTest",
181
+ # {"Name"=>"DarrylTest",
156
182
  # "CreationDate"=>"2011-06-03T03:43:08.000Z"},
157
- # {"Name"=>"RightScalePeter",
183
+ # {"Name"=>"RightScalePeter",
158
184
  # "CreationDate"=>"2008-10-28T03:59:20.000Z"}]},
159
185
  # "Owner"=>
160
186
  # {"DisplayName"=>"fghsfg",
@@ -120,8 +120,12 @@ module RightScale
120
120
  # Amazon wants them to be escaped before we sign the request.
121
121
  # P.S. but do not escape "/" (signature v4 does not like this)
122
122
  #
123
- object = $2.to_s.split('/').map{|i| Utils::AWS::amz_escape(i)}.join('/')
124
- [ $1, object ]
123
+ new_bucket = $1
124
+ pre_object = $2.to_s
125
+ object = pre_object.split('/').map{|i| Utils::AWS::amz_escape(i)}.join('/')
126
+ # Preserve '/' if it is the last symbol of the object because it is an operation on a folder
127
+ object += '/' if object.length > 0 && pre_object[/\/$/]
128
+ [ new_bucket, object ]
125
129
  end
126
130
 
127
131
 
@@ -183,7 +187,7 @@ module RightScale
183
187
  # So we need to include it into our signature to avoid the error below:
184
188
  # 'The request signature we calculated does not match the signature you provided.
185
189
  # Check your key and signing method.'
186
- headers.set_if_blank('content-type', 'application/octet-stream')
190
+ headers.set_if_blank('content-type', 'binary/octet-stream')
187
191
  headers
188
192
  end
189
193
 
@@ -210,10 +214,15 @@ module RightScale
210
214
  # @return [Boolean]
211
215
  #
212
216
  def is_dns_bucket?(bucket)
213
- return false if @data[:options][:cloud][:no_dns_buckets]
217
+ return false if no_dns_buckets?
214
218
  Utils::AWS::is_dns_bucket?(bucket)
215
219
  end
216
220
 
221
+
222
+ def no_dns_buckets?
223
+ !!@data[:options][:cloud][:no_dns_buckets]
224
+ end
225
+
217
226
  end
218
227
  end
219
228
  end
@@ -253,7 +253,7 @@ module RightScale
253
253
 
254
254
  base.query_api_pattern 'PutObject', :put, '{:Bucket}/{:Object}',
255
255
  :body => Utils::MUST_BE_SET,
256
- :headers => { 'content-type' => 'application/octet-stream' }
256
+ :headers => { 'content-type' => 'binary/octet-stream' }
257
257
 
258
258
 
259
259
  base.query_api_pattern 'PutObjectAcl', :put, '{:Bucket}/{:Object}',
@@ -286,7 +286,7 @@ module RightScale
286
286
  base.query_api_pattern 'UploadPart', :post, '{:Bucket}/{:Object}',
287
287
  :params => { 'partNumber' => :PartNumber,
288
288
  'uploadId' => :UploadId },
289
- :headers => { 'content-type' => 'application/octet-stream' }
289
+ :headers => { 'content-type' => 'binary/octet-stream' }
290
290
 
291
291
 
292
292
  base.query_api_pattern 'UploadPartCopy', :put, '{:DestinationBucket}/{:DestinationObject}',
@@ -33,7 +33,7 @@ module RightScale
33
33
  # Gem version namespace
34
34
  module VERSION
35
35
  # Current version
36
- STRING = '0.2.2'
36
+ STRING = '0.2.3'
37
37
  end
38
38
  end
39
39
  end
@@ -37,6 +37,10 @@ describe RightScale::CloudApi::AWS::S3::RequestSigner do
37
37
 
38
38
 
39
39
  context '#compute_host' do
40
+ before :each do
41
+ allow(subject).to receive(:no_dns_buckets?).and_return(false)
42
+ end
43
+
40
44
  context 'DNS bucket' do
41
45
  before :each do
42
46
  bucket = 'foo-bar-bucket'
@@ -88,9 +92,9 @@ describe RightScale::CloudApi::AWS::S3::RequestSigner do
88
92
  end
89
93
 
90
94
  context 'content-type' do
91
- it 'defaults content-type to application/octet-stream' do
95
+ it 'defaults content-type to binary/octet-stream' do
92
96
  result = subject.compute_headers!(@headers, @body, @host)
93
- expectation = ['application/octet-stream']
97
+ expectation = ['binary/octet-stream']
94
98
  expect(result['content-type']).to eq(expectation)
95
99
  end
96
100
  end
@@ -101,6 +105,7 @@ describe RightScale::CloudApi::AWS::S3::RequestSigner do
101
105
  before :each do
102
106
  @path = 'foo-bar'
103
107
  @object = 'foo%2Fbar%2F%D0%B1%D0%B0%D0%BD%D0%B0%D0%BD%D0%B0.jpg'
108
+ allow(subject).to receive(:no_dns_buckets?).and_return(false)
104
109
  end
105
110
 
106
111
  it 'works for DNS bucket' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: right_aws_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - RightScale, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-17 00:00:00.000000000 Z
11
+ date: 2015-02-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: right_cloud_api_base