cmeiklejohn-aws 2.3.8

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown ADDED
@@ -0,0 +1,186 @@
1
+ # Appoxy AWS Library
2
+
3
+ A Ruby gem for all Amazon Web Services.
4
+
5
+ Brought to you by: [![Appoxy](http://www.simpledeployr.com/images/global/appoxy-small.png)](http://www.appoxy.com)
6
+
7
+ ## Discussion Group
8
+
9
+ http://groups.google.com/group/ruby-aws
10
+
11
+ ## Issue Tracker
12
+
13
+ http://appoxy.lighthouseapp.com/projects/38441-aws/overview
14
+
15
+ ## Documentation
16
+
17
+ http://rdoc.info/projects/appoxy/aws
18
+
19
+ ## Appoxy Amazon Web Services Ruby Gems
20
+
21
+ Published by Appoxy LLC, under the MIT License. Special thanks to RightScale from which this project is forked.
22
+
23
+ ## INSTALL:
24
+
25
+ THEN (you should have http://gemcutter.org in your sources and it MUST be above rubyforge.org):
26
+
27
+ gem install aws
28
+
29
+
30
+ ## DESCRIPTION:
31
+
32
+ The RightScale AWS gems have been designed to provide a robust, fast, and secure interface to Amazon EC2, EBS, S3, SQS, SDB, and CloudFront.
33
+ These gems have been used in production by RightScale since late 2006 and are being maintained to track enhancements made by Amazon.
34
+ The RightScale AWS gems comprise:
35
+
36
+ - Aws::Ec2 -- interface to Amazon EC2 (Elastic Compute Cloud) and the associated EBS (Elastic Block Store)
37
+ - Aws::S3 and Aws::S3Interface -- interface to Amazon S3 (Simple Storage Service)
38
+ - Aws::Sqs and Aws::SqsInterface -- interface to Amazon SQS (Simple Queue Service)
39
+ - Aws::SdbInterface and Aws::ActiveSdb -- interface to Amazon SDB (SimpleDB)
40
+ - Aws::AcfInterface -- interface to Amazon CloudFront, a content distribution service
41
+ - Aws::ElbInterface -- interface to Amazon Load Balancing service
42
+ - Aws::MonInterface -- interface to Amazon CloudWatch monitoring service
43
+
44
+
45
+ ## FEATURES:
46
+
47
+ - Full programmmatic access to EC2, EBS, S3, SQS, SDB, ELB, and CloudFront.
48
+ - Complete error handling: all operations check for errors and report complete
49
+ error information by raising an AwsError.
50
+ - Persistent HTTP connections with robust network-level retry layer using
51
+ RightHttpConnection). This includes socket timeouts and retries.
52
+ - Robust HTTP-level retry layer. Certain (user-adjustable) HTTP errors returned
53
+ by Amazon's services are classified as temporary errors.
54
+ These errors are automaticallly retried using exponentially increasing intervals.
55
+ The number of retries is user-configurable.
56
+ - Fast REXML-based parsing of responses (as fast as a pure Ruby solution allows).
57
+ - Uses libxml (if available) for faster response parsing.
58
+ - Support for large S3 list operations. Buckets and key subfolders containing
59
+ many (> 1000) keys are listed in entirety. Operations based on list (like
60
+ bucket clear) work on arbitrary numbers of keys.
61
+ - Support for streaming GETs from S3, and streaming PUTs to S3 if the data source is a file.
62
+ - Support for single-threaded usage, multithreaded usage, as well as usage with multiple
63
+ AWS accounts.
64
+ - Support for both first- and second-generation SQS (API versions 2007-05-01
65
+ and 2008-01-01). These versions of SQS are not compatible.
66
+ - Support for signature versions 0, 1 and 2 on all services.
67
+ - Interoperability with any cloud running Eucalyptus (http://eucalyptus.cs.ucsb.edu)
68
+ - Test suite (requires AWS account to do "live" testing).
69
+
70
+ ## THREADING:
71
+
72
+ All RightScale AWS interfaces offer two threading options:
73
+ 1. Use a single persistent HTTP connection per process.
74
+ 2. Use a persistent HTTP connection per Ruby thread.
75
+
76
+ Either way, it doesn't matter how many (for example) Aws::S3 objects you create,
77
+ they all use the same per-program or per-thread
78
+ connection. The purpose of sharing the connection is to keep a single
79
+ persistent HTTP connection open to avoid paying connection
80
+ overhead on every request. However, if you have multiple concurrent
81
+ threads, you may want or need an HTTP connection per thread to enable
82
+ concurrent requests to AWS. The way this plays out in practice is:
83
+ 1. If you have a non-multithreaded Ruby program, use the non-multithreaded setting.
84
+ 2. If you have a multi-threaded Ruby program, use the multithreaded setting to enable
85
+ concurrent requests to S3 (or SQS, or SDB, or EC2).
86
+ 3. For running under Mongrel/Rails, use the non-multithreaded setting even though
87
+ mongrel is multithreaded. This is because only one Rails handler is invoked at
88
+ time (i.e. it acts like a single-threaded program)
89
+
90
+ Note that due to limitations in the I/O of the Ruby interpreter you
91
+ may not get the degree of parallelism you may expect with the multi-threaded setting.
92
+
93
+ By default, EC2/S3/SQS/SDB/ACF interface instances are created in single-threaded mode. Set
94
+ params[:connection_mode] to :multi_thread in the initialization arguments to use
95
+ multithreaded mode.
96
+
97
+ ## GETTING STARTED:
98
+
99
+ * For EC2 read Aws::Ec2 and consult the Amazon EC2 API documentation at
100
+ http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=87
101
+ * For S3 read Aws::S3 and consult the Amazon S3 API documentation at
102
+ http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=48
103
+ * For SQS read Aws::Sqs and consult the Amazon SQS API documentation at
104
+ http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=31
105
+
106
+ Amazon's Migration Guide for moving from first to second generation SQS is
107
+ avalable at:
108
+ http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1148
109
+ * For SDB read Aws::SdbInterface, Aws::ActiveSdb, and consult the Amazon SDB API documentation at
110
+ http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=141
111
+ * For CloudFront (ACF) read Aws::AcfInterface and consult the Amazon CloudFront API documentation at
112
+ http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=213
113
+
114
+ ## KNOWN ISSUES:
115
+
116
+ - 7/08: A user has reported that uploads of large files on Windows may be broken on some
117
+ Win platforms due to a buggy File.lstat.size. Use the following monkey-patch at your own risk,
118
+ as it has been proven to break Rails 2.0 on Windows:
119
+
120
+ require 'win32/file'
121
+ class File
122
+ def lstat
123
+ self.stat
124
+ end
125
+ end
126
+
127
+
128
+ - Attempting to use the Gibberish plugin (used by the Beast forum app)
129
+ will break right_aws as well as lots of other code. Gibberish
130
+ changes the semantics of core Ruby (specifically, the String class) and thus presents a reliability
131
+ problem for most Ruby programs.
132
+
133
+ - 2/11/08: If you use Aws in conjunction with attachment_fu, the
134
+ right_aws gem must be included (using the require statement) AFTER
135
+ attachment_fu. If right_aws is loaded before attachment_fu, you'll
136
+ encounter errors similar to:
137
+
138
+ s3.amazonaws.com temporarily unavailable: (wrong number of arguments (5 for 4))
139
+
140
+ or
141
+
142
+ 'incompatible Net::HTTP monkey-patch'
143
+
144
+ This is due to a conflict between the right_http_connection gem and another
145
+ gem required by attachment_fu. It may be possible to require right_aws (and
146
+ thus right_http_connection) in the .after_initialize method of the config object in
147
+ environment.rb (check the docs for Rails::Configuration.after_initialize).
148
+
149
+ - 8/07: Amazon has changed the semantics of the SQS service. A
150
+ new queue may not be created within 60 seconds of the destruction of any
151
+ older queue with the same name. Certain methods of Aws::Sqs and
152
+ Aws::SqsInterface will fail with the message:
153
+ "AWS.SimpleQueueService.QueueDeletedRecently: You must wait 60 seconds after deleting a queue before you can create another with the same name."
154
+
155
+ ## REQUIREMENTS:
156
+
157
+ Aws requires REXML and the right_http_connection gem.
158
+ If libxml and its Ruby bindings (distributed in the libxml-ruby gem) are
159
+ present, Aws can be configured to use them:
160
+ Aws::AwsParser.xml_lib = 'libxml'
161
+ Any error with the libxml installation will result in Aws failing-safe to
162
+ REXML parsing.
163
+
164
+
165
+ == LICENSE:
166
+
167
+ Copyright (c) 2007-2009 RightScale, Inc.
168
+
169
+ Permission is hereby granted, free of charge, to any person obtaining
170
+ a copy of this software and associated documentation files (the
171
+ 'Software'), to deal in the Software without restriction, including
172
+ without limitation the rights to use, copy, modify, merge, publish,
173
+ distribute, sublicense, and/or sell copies of the Software, and to
174
+ permit persons to whom the Software is furnished to do so, subject to
175
+ the following conditions:
176
+
177
+ The above copyright notice and this permission notice shall be
178
+ included in all copies or substantial portions of the Software.
179
+
180
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
181
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
182
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
183
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
184
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
185
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
186
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,379 @@
1
+ #
2
+ # Copyright (c) 2008 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
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+
24
+ module Aws
25
+
26
+ # = Aws::AcfInterface -- RightScale Amazon's CloudFront interface
27
+ # The AcfInterface class provides a complete interface to Amazon's
28
+ # CloudFront service.
29
+ #
30
+ # For explanations of the semantics of each call, please refer to
31
+ # Amazon's documentation at
32
+ # http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=211
33
+ #
34
+ # Example:
35
+ #
36
+ # acf = Aws::AcfInterface.new('1E3GDYEOGFJPIT7XXXXXX','hgTHt68JY07JKUY08ftHYtERkjgtfERn57XXXXXX')
37
+ #
38
+ # list = acf.list_distributions #=>
39
+ # [{:status => "Deployed",
40
+ # :domain_name => "d74zzrxmpmygb.6hops.net",
41
+ # :aws_id => "E4U91HCJHGXVC",
42
+ # :origin => "my-bucket.s3.amazonaws.com",
43
+ # :cnames => ["x1.my-awesome-site.net", "x1.my-awesome-site.net"]
44
+ # :comment => "My comments",
45
+ # :last_modified_time => Wed Sep 10 17:00:04 UTC 2008 }, ..., {...} ]
46
+ #
47
+ # distibution = list.first
48
+ #
49
+ # info = acf.get_distribution(distibution[:aws_id]) #=>
50
+ # {:enabled => true,
51
+ # :caller_reference => "200809102100536497863003",
52
+ # :e_tag => "E39OHHU1ON65SI",
53
+ # :status => "Deployed",
54
+ # :domain_name => "d3dxv71tbbt6cd.6hops.net",
55
+ # :cnames => ["web1.my-awesome-site.net", "web2.my-awesome-site.net"]
56
+ # :aws_id => "E2REJM3VUN5RSI",
57
+ # :comment => "Woo-Hoo!",
58
+ # :origin => "my-bucket.s3.amazonaws.com",
59
+ # :last_modified_time => Wed Sep 10 17:00:54 UTC 2008 }
60
+ #
61
+ # config = acf.get_distribution_config(distibution[:aws_id]) #=>
62
+ # {:enabled => true,
63
+ # :caller_reference => "200809102100536497863003",
64
+ # :e_tag => "E39OHHU1ON65SI",
65
+ # :cnames => ["web1.my-awesome-site.net", "web2.my-awesome-site.net"]
66
+ # :comment => "Woo-Hoo!",
67
+ # :origin => "my-bucket.s3.amazonaws.com"}
68
+ #
69
+ # config[:comment] = 'Olah-lah!'
70
+ # config[:enabled] = false
71
+ # config[:cnames] << "web3.my-awesome-site.net"
72
+ #
73
+ # acf.set_distribution_config(distibution[:aws_id], config) #=> true
74
+ #
75
+ class AcfInterface < AwsBase
76
+
77
+ include AwsBaseInterface
78
+
79
+ API_VERSION = "2008-06-30"
80
+ DEFAULT_HOST = 'cloudfront.amazonaws.com'
81
+ DEFAULT_PORT = 80
82
+ DEFAULT_PROTOCOL = 'http'
83
+ DEFAULT_PATH = '/'
84
+
85
+ @@bench = AwsBenchmarkingBlock.new
86
+ def self.bench_xml
87
+ @@bench.xml
88
+ end
89
+ def self.bench_service
90
+ @@bench.service
91
+ end
92
+
93
+ # Create a new handle to a CloudFront account. All handles share the same per process or per thread
94
+ # HTTP connection to CloudFront. Each handle is for a specific account. The params have the
95
+ # following options:
96
+ # * <tt>:server</tt>: CloudFront service host, default: DEFAULT_HOST
97
+ # * <tt>:port</tt>: CloudFront service port, default: DEFAULT_PORT
98
+ # * <tt>:protocol</tt>: 'http' or 'https', default: DEFAULT_PROTOCOL
99
+ # * <tt>:multi_thread</tt>: true=HTTP connection per thread, false=per process
100
+ # * <tt>:logger</tt>: for log messages, default: RAILS_DEFAULT_LOGGER else STDOUT
101
+ # * <tt>:cache</tt>: true/false: caching for list_distributions method, default: false.
102
+ #
103
+ # acf = Aws::AcfInterface.new('1E3GDYEOGFJPIT7XXXXXX','hgTHt68JY07JKUY08ftHYtERkjgtfERn57XXXXXX',
104
+ # {:multi_thread => true, :logger => Logger.new('/tmp/x.log')}) #=> #<Aws::AcfInterface::0xb7b3c30c>
105
+ #
106
+ def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
107
+ init({ :name => 'ACF',
108
+ :default_host => ENV['ACF_URL'] ? URI.parse(ENV['ACF_URL']).host : DEFAULT_HOST,
109
+ :default_port => ENV['ACF_URL'] ? URI.parse(ENV['ACF_URL']).port : DEFAULT_PORT,
110
+ :default_service => ENV['ACF_URL'] ? URI.parse(ENV['ACF_URL']).path : DEFAULT_PATH,
111
+ :default_protocol => ENV['ACF_URL'] ? URI.parse(ENV['ACF_URL']).scheme : DEFAULT_PROTOCOL },
112
+ aws_access_key_id || ENV['AWS_ACCESS_KEY_ID'],
113
+ aws_secret_access_key || ENV['AWS_SECRET_ACCESS_KEY'],
114
+ params)
115
+ end
116
+
117
+ #-----------------------------------------------------------------
118
+ # Requests
119
+ #-----------------------------------------------------------------
120
+
121
+ # Generates request hash for REST API.
122
+ def generate_request(method, path, body=nil, headers={}) # :nodoc:
123
+ headers['content-type'] ||= 'text/xml' if body
124
+ headers['date'] = Time.now.httpdate
125
+ # Auth
126
+ signature = AwsUtils::sign(@aws_secret_access_key, headers['date'])
127
+ headers['Authorization'] = "AWS #{@aws_access_key_id}:#{signature}"
128
+ # Request
129
+ path = "#{@params[:default_service]}/#{API_VERSION}/#{path}"
130
+ request = "Net::HTTP::#{method.capitalize}".constantize.new(path)
131
+ request.body = body if body
132
+ # Set request headers
133
+ headers.each { |key, value| request[key.to_s] = value }
134
+ # prepare output hash
135
+ { :request => request,
136
+ :server => @params[:server],
137
+ :port => @params[:port],
138
+ :protocol => @params[:protocol] }
139
+ end
140
+
141
+ # Sends request to Amazon and parses the response.
142
+ # Raises AwsError if any banana happened.
143
+ def request_info(request, parser, &block) # :nodoc:
144
+ thread = @params[:multi_thread] ? Thread.current : Thread.main
145
+ thread[:acf_connection] ||= Aws::HttpConnection.new(:exception => Aws::AwsError, :logger => @logger)
146
+ request_info_impl(thread[:acf_connection], @@bench, request, parser, &block)
147
+ end
148
+
149
+ #-----------------------------------------------------------------
150
+ # Helpers:
151
+ #-----------------------------------------------------------------
152
+
153
+ def self.escape(text) # :nodoc:
154
+ REXML::Text::normalize(text)
155
+ end
156
+
157
+ def self.unescape(text) # :nodoc:
158
+ REXML::Text::unnormalize(text)
159
+ end
160
+
161
+ def xmlns # :nodoc:
162
+ %Q{"http://#{@params[:server]}/doc/#{API_VERSION}/"}
163
+ end
164
+
165
+ def generate_call_reference # :nodoc:
166
+ result = Time.now.strftime('%Y%m%d%H%M%S')
167
+ 10.times{ result << rand(10).to_s }
168
+ result
169
+ end
170
+
171
+ def merge_headers(hash) # :nodoc:
172
+ hash[:location] = @last_response['Location'] if @last_response['Location']
173
+ hash[:e_tag] = @last_response['ETag'] if @last_response['ETag']
174
+ hash
175
+ end
176
+
177
+ #-----------------------------------------------------------------
178
+ # API Calls:
179
+ #-----------------------------------------------------------------
180
+
181
+ # List distributions.
182
+ # Returns an array of distributions or Aws::AwsError exception.
183
+ #
184
+ # acf.list_distributions #=>
185
+ # [{:status => "Deployed",
186
+ # :domain_name => "d74zzrxmpmygb.6hops.net",
187
+ # :aws_id => "E4U91HCJHGXVC",
188
+ # :cnames => ["web1.my-awesome-site.net", "web2.my-awesome-site.net"]
189
+ # :origin => "my-bucket.s3.amazonaws.com",
190
+ # :comment => "My comments",
191
+ # :last_modified_time => Wed Sep 10 17:00:04 UTC 2008 }, ..., {...} ]
192
+ #
193
+ def list_distributions
194
+ request_hash = generate_request('GET', 'distribution')
195
+ request_cache_or_info :list_distributions, request_hash, AcfDistributionListParser, @@bench
196
+ end
197
+
198
+ # Create a new distribution.
199
+ # Returns the just created distribution or Aws::AwsError exception.
200
+ #
201
+ # acf.create_distribution('bucket-for-k-dzreyev.s3.amazonaws.com', 'Woo-Hoo!', true, ['web1.my-awesome-site.net'] ) #=>
202
+ # {:comment => "Woo-Hoo!",
203
+ # :enabled => true,
204
+ # :location => "https://cloudfront.amazonaws.com/2008-06-30/distribution/E2REJM3VUN5RSI",
205
+ # :status => "InProgress",
206
+ # :aws_id => "E2REJM3VUN5RSI",
207
+ # :domain_name => "d3dxv71tbbt6cd.6hops.net",
208
+ # :origin => "my-bucket.s3.amazonaws.com",
209
+ # :cnames => ["web1.my-awesome-site.net"]
210
+ # :last_modified_time => Wed Sep 10 17:00:54 UTC 2008,
211
+ # :caller_reference => "200809102100536497863003"}
212
+ #
213
+ def create_distribution(origin, comment='', enabled=true, cnames=[], caller_reference=nil)
214
+ # join CNAMES
215
+ cnames_str = ''
216
+ unless cnames.blank?
217
+ cnames.to_a.each { |cname| cnames_str += "\n <CNAME>#{cname}</CNAME>" }
218
+ end
219
+ # reference
220
+ caller_reference ||= generate_call_reference
221
+ body = <<-EOXML
222
+ <?xml version="1.0" encoding="UTF-8"?>
223
+ <DistributionConfig xmlns=#{xmlns}>
224
+ <Origin>#{origin}</Origin>
225
+ <CallerReference>#{caller_reference}</CallerReference>
226
+ #{cnames_str.lstrip}
227
+ <Comment>#{AcfInterface::escape(comment.to_s)}</Comment>
228
+ <Enabled>#{enabled}</Enabled>
229
+ </DistributionConfig>
230
+ EOXML
231
+ request_hash = generate_request('POST', 'distribution', body.strip)
232
+ merge_headers(request_info(request_hash, AcfDistributionParser.new))
233
+ end
234
+
235
+ # Get a distribution's information.
236
+ # Returns a distribution's information or Aws::AwsError exception.
237
+ #
238
+ # acf.get_distribution('E2REJM3VUN5RSI') #=>
239
+ # {:enabled => true,
240
+ # :caller_reference => "200809102100536497863003",
241
+ # :e_tag => "E39OHHU1ON65SI",
242
+ # :status => "Deployed",
243
+ # :domain_name => "d3dxv71tbbt6cd.6hops.net",
244
+ # :cnames => ["web1.my-awesome-site.net", "web2.my-awesome-site.net"]
245
+ # :aws_id => "E2REJM3VUN5RSI",
246
+ # :comment => "Woo-Hoo!",
247
+ # :origin => "my-bucket.s3.amazonaws.com",
248
+ # :last_modified_time => Wed Sep 10 17:00:54 UTC 2008 }
249
+ #
250
+ def get_distribution(aws_id)
251
+ request_hash = generate_request('GET', "distribution/#{aws_id}")
252
+ merge_headers(request_info(request_hash, AcfDistributionParser.new))
253
+ end
254
+
255
+ # Get a distribution's configuration.
256
+ # Returns a distribution's configuration or Aws::AwsError exception.
257
+ #
258
+ # acf.get_distribution_config('E2REJM3VUN5RSI') #=>
259
+ # {:enabled => true,
260
+ # :caller_reference => "200809102100536497863003",
261
+ # :e_tag => "E39OHHU1ON65SI",
262
+ # :cnames => ["web1.my-awesome-site.net", "web2.my-awesome-site.net"]
263
+ # :comment => "Woo-Hoo!",
264
+ # :origin => "my-bucket.s3.amazonaws.com"}
265
+ #
266
+ def get_distribution_config(aws_id)
267
+ request_hash = generate_request('GET', "distribution/#{aws_id}/config")
268
+ merge_headers(request_info(request_hash, AcfDistributionConfigParser.new))
269
+ end
270
+
271
+ # Set a distribution's configuration
272
+ # (the :origin and the :caller_reference cannot be changed).
273
+ # Returns +true+ on success or Aws::AwsError exception.
274
+ #
275
+ # config = acf.get_distribution_config('E2REJM3VUN5RSI') #=>
276
+ # {:enabled => true,
277
+ # :caller_reference => "200809102100536497863003",
278
+ # :e_tag => "E39OHHU1ON65SI",
279
+ # :cnames => ["web1.my-awesome-site.net", "web2.my-awesome-site.net"]
280
+ # :comment => "Woo-Hoo!",
281
+ # :origin => "my-bucket.s3.amazonaws.com"}
282
+ # config[:comment] = 'Olah-lah!'
283
+ # config[:enabled] = false
284
+ # acf.set_distribution_config('E2REJM3VUN5RSI', config) #=> true
285
+ #
286
+ def set_distribution_config(aws_id, config)
287
+ # join CNAMES
288
+ cnames_str = ''
289
+ unless config[:cnames].blank?
290
+ config[:cnames].to_a.each { |cname| cnames_str += "\n <CNAME>#{cname}</CNAME>" }
291
+ end
292
+ # format request's XML body
293
+ body = <<-EOXML
294
+ <?xml version="1.0" encoding="UTF-8"?>
295
+ <DistributionConfig xmlns=#{xmlns}>
296
+ <Origin>#{config[:origin]}</Origin>
297
+ <CallerReference>#{config[:caller_reference]}</CallerReference>
298
+ #{cnames_str.lstrip}
299
+ <Comment>#{AcfInterface::escape(config[:comment].to_s)}</Comment>
300
+ <Enabled>#{config[:enabled]}</Enabled>
301
+ </DistributionConfig>
302
+ EOXML
303
+ request_hash = generate_request('PUT', "distribution/#{aws_id}/config", body.strip,
304
+ 'If-Match' => config[:e_tag])
305
+ request_info(request_hash, RightHttp2xxParser.new)
306
+ end
307
+
308
+ # Delete a distribution. The enabled distribution cannot be deleted.
309
+ # Returns +true+ on success or Aws::AwsError exception.
310
+ #
311
+ # acf.delete_distribution('E2REJM3VUN5RSI', 'E39OHHU1ON65SI') #=> true
312
+ #
313
+ def delete_distribution(aws_id, e_tag)
314
+ request_hash = generate_request('DELETE', "distribution/#{aws_id}", nil,
315
+ 'If-Match' => e_tag)
316
+ request_info(request_hash, RightHttp2xxParser.new)
317
+ end
318
+
319
+ #-----------------------------------------------------------------
320
+ # PARSERS:
321
+ #-----------------------------------------------------------------
322
+
323
+ class AcfDistributionListParser < AwsParser # :nodoc:
324
+ def reset
325
+ @result = []
326
+ end
327
+ def tagstart(name, attributes)
328
+ @distribution = { :cnames => [] } if name == 'DistributionSummary'
329
+ end
330
+ def tagend(name)
331
+ case name
332
+ when 'Id' then @distribution[:aws_id] = @text
333
+ when 'Status' then @distribution[:status] = @text
334
+ when 'LastModifiedTime' then @distribution[:last_modified_time] = Time.parse(@text)
335
+ when 'DomainName' then @distribution[:domain_name] = @text
336
+ when 'Origin' then @distribution[:origin] = @text
337
+ when 'Comment' then @distribution[:comment] = AcfInterface::unescape(@text)
338
+ when 'CNAME' then @distribution[:cnames] << @text
339
+ when 'DistributionSummary' then @result << @distribution
340
+ end
341
+ end
342
+ end
343
+
344
+ class AcfDistributionParser < AwsParser # :nodoc:
345
+ def reset
346
+ @result = { :cnames => [] }
347
+ end
348
+ def tagend(name)
349
+ case name
350
+ when 'Id' then @result[:aws_id] = @text
351
+ when 'Status' then @result[:status] = @text
352
+ when 'LastModifiedTime' then @result[:last_modified_time] = Time.parse(@text)
353
+ when 'DomainName' then @result[:domain_name] = @text
354
+ when 'Origin' then @result[:origin] = @text
355
+ when 'CallerReference' then @result[:caller_reference] = @text
356
+ when 'Comment' then @result[:comment] = AcfInterface::unescape(@text)
357
+ when 'Enabled' then @result[:enabled] = @text == 'true' ? true : false
358
+ when 'CNAME' then @result[:cnames] << @text
359
+ end
360
+ end
361
+ end
362
+
363
+ class AcfDistributionConfigParser < AwsParser # :nodoc:
364
+ def reset
365
+ @result = { :cnames => [] }
366
+ end
367
+ def tagend(name)
368
+ case name
369
+ when 'Origin' then @result[:origin] = @text
370
+ when 'CallerReference' then @result[:caller_reference] = @text
371
+ when 'Comment' then @result[:comment] = AcfInterface::unescape(@text)
372
+ when 'Enabled' then @result[:enabled] = @text == 'true' ? true : false
373
+ when 'CNAME' then @result[:cnames] << @text
374
+ end
375
+ end
376
+ end
377
+
378
+ end
379
+ end
data/lib/aws.rb ADDED
@@ -0,0 +1,30 @@
1
+
2
+ require 'benchmark'
3
+ require 'net/https'
4
+ require 'uri'
5
+ require 'time'
6
+ require "cgi"
7
+ require "base64"
8
+ require "rexml/document"
9
+ require "openssl"
10
+ require "digest/sha1"
11
+
12
+ require 'rubygems'
13
+ require 'right_http_connection'
14
+
15
+ $:.unshift(File.dirname(__FILE__))
16
+ require 'awsbase/benchmark_fix'
17
+ require 'awsbase/support'
18
+ require 'awsbase/right_awsbase'
19
+ require 'awsbase/aws_response_array'
20
+ require 'ec2/right_ec2'
21
+ require 'ec2/right_mon_interface'
22
+ require 's3/right_s3_interface'
23
+ require 's3/right_s3'
24
+ require 'sqs/right_sqs_interface'
25
+ require 'sqs/right_sqs'
26
+ require 'sdb/right_sdb_interface'
27
+ require 'acf/right_acf_interface'
28
+ require 'elb/elb_interface'
29
+ require 'rds/rds'
30
+
@@ -0,0 +1,30 @@
1
+ module Aws
2
+
3
+ # This class is a special array to hold a bit of extra information about a response like:
4
+ # <ResponseMetadata>
5
+ # <RequestId>4f1fae46-bf3d-11de-a88b-7b5b3d23b3a7</RequestId>
6
+ # </ResponseMetadata>
7
+ #
8
+ # Which can be accessed directly from the array using array.response_metadata
9
+ #
10
+ class AwsResponseArray < Array
11
+
12
+ attr_accessor :response_metadata
13
+
14
+ def initialize(response_metadata)
15
+ @response_metadata = response_metadata
16
+ end
17
+
18
+ end
19
+
20
+ # Used when pulling out a single response object
21
+ class AwsResponseObjectHash < Hash
22
+
23
+ attr_accessor :response_metadata
24
+
25
+ def initialize(response_metadata)
26
+ @response_metadata = response_metadata
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,39 @@
1
+ #
2
+ # Copyright (c) 2007-2008 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
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+ #
24
+
25
+
26
+ # A hack because there's a bug in add! in Benchmark::Tms
27
+ module Benchmark #:nodoc:
28
+ class Tms #:nodoc:
29
+ def add!(&blk)
30
+ t = Benchmark::measure(&blk)
31
+ @utime = utime + t.utime
32
+ @stime = stime + t.stime
33
+ @cutime = cutime + t.cutime
34
+ @cstime = cstime + t.cstime
35
+ @real = real + t.real
36
+ self
37
+ end
38
+ end
39
+ end