revans_right_aws 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/.gemtest +0 -0
  2. data/History.txt +284 -0
  3. data/Manifest.txt +50 -0
  4. data/README.txt +167 -0
  5. data/Rakefile +110 -0
  6. data/lib/acf/right_acf_interface.rb +485 -0
  7. data/lib/acf/right_acf_origin_access_identities.rb +230 -0
  8. data/lib/acf/right_acf_streaming_interface.rb +236 -0
  9. data/lib/acw/right_acw_interface.rb +249 -0
  10. data/lib/as/right_as_interface.rb +699 -0
  11. data/lib/awsbase/benchmark_fix.rb +39 -0
  12. data/lib/awsbase/right_awsbase.rb +978 -0
  13. data/lib/awsbase/support.rb +115 -0
  14. data/lib/ec2/right_ec2.rb +395 -0
  15. data/lib/ec2/right_ec2_ebs.rb +452 -0
  16. data/lib/ec2/right_ec2_images.rb +373 -0
  17. data/lib/ec2/right_ec2_instances.rb +755 -0
  18. data/lib/ec2/right_ec2_monitoring.rb +70 -0
  19. data/lib/ec2/right_ec2_reserved_instances.rb +170 -0
  20. data/lib/ec2/right_ec2_security_groups.rb +277 -0
  21. data/lib/ec2/right_ec2_spot_instances.rb +399 -0
  22. data/lib/ec2/right_ec2_vpc.rb +571 -0
  23. data/lib/elb/right_elb_interface.rb +496 -0
  24. data/lib/rds/right_rds_interface.rb +998 -0
  25. data/lib/right_aws.rb +83 -0
  26. data/lib/s3/right_s3.rb +1126 -0
  27. data/lib/s3/right_s3_interface.rb +1199 -0
  28. data/lib/sdb/active_sdb.rb +1122 -0
  29. data/lib/sdb/right_sdb_interface.rb +721 -0
  30. data/lib/sqs/right_sqs.rb +388 -0
  31. data/lib/sqs/right_sqs_gen2.rb +343 -0
  32. data/lib/sqs/right_sqs_gen2_interface.rb +524 -0
  33. data/lib/sqs/right_sqs_interface.rb +594 -0
  34. data/test/acf/test_helper.rb +2 -0
  35. data/test/acf/test_right_acf.rb +138 -0
  36. data/test/ec2/test_helper.rb +2 -0
  37. data/test/ec2/test_right_ec2.rb +108 -0
  38. data/test/http_connection.rb +87 -0
  39. data/test/rds/test_helper.rb +2 -0
  40. data/test/rds/test_right_rds.rb +120 -0
  41. data/test/s3/test_helper.rb +2 -0
  42. data/test/s3/test_right_s3.rb +421 -0
  43. data/test/s3/test_right_s3_stubbed.rb +97 -0
  44. data/test/sdb/test_active_sdb.rb +357 -0
  45. data/test/sdb/test_helper.rb +3 -0
  46. data/test/sdb/test_right_sdb.rb +253 -0
  47. data/test/sqs/test_helper.rb +2 -0
  48. data/test/sqs/test_right_sqs.rb +291 -0
  49. data/test/sqs/test_right_sqs_gen2.rb +264 -0
  50. data/test/test_credentials.rb +37 -0
  51. data/test/ts_right_aws.rb +14 -0
  52. metadata +169 -0
@@ -0,0 +1,110 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require "rake/testtask"
6
+ require 'rcov/rcovtask'
7
+ $: << File.dirname(__FILE__)
8
+ require 'lib/right_aws.rb'
9
+
10
+ testglobs = ["test/ts_right_aws.rb"]
11
+
12
+
13
+ # Suppress Hoe's self-inclusion as a dependency for our Gem. This also keeps
14
+ # Rake & rubyforge out of the dependency list. Users must manually install
15
+ # these gems to run tests, etc.
16
+ class Hoe
17
+ def extra_deps
18
+ @extra_deps.reject do |x|
19
+ Array(x).first == 'hoe'
20
+ end
21
+ end
22
+ end
23
+
24
+ Hoe.new('revans_right_aws', RightAws::VERSION::STRING) do |p|
25
+ p.rubyforge_name = 'revans_rightaws'
26
+ p.author = 'RightScale, Inc.'
27
+ p.email = 'support@rightscale.com'
28
+ p.summary = 'Interface classes for the Amazon EC2, SQS, and S3 Web Services'
29
+ p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
30
+ p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
31
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
32
+ p.remote_rdoc_dir = "/right_aws_gem_doc"
33
+ p.extra_deps = [['right_http_connection','>= 1.2.1']]
34
+ p.test_globs = testglobs
35
+ end
36
+
37
+ desc "Analyze code coverage of the unit tests."
38
+ Rcov::RcovTask.new do |t|
39
+ t.test_files = FileList[testglobs]
40
+ #t.verbose = true # uncomment to see the executed command
41
+ end
42
+
43
+ desc "Test just the SQS interface"
44
+ task :testsqs do
45
+ require 'test/test_credentials'
46
+ require 'test/http_connection'
47
+ TestCredentials.get_credentials
48
+ require 'test/sqs/test_right_sqs.rb'
49
+ end
50
+
51
+ desc "Test just the second generation SQS interface"
52
+ task :testsqs2 do
53
+ require 'test/test_credentials'
54
+ require 'test/http_connection'
55
+ TestCredentials.get_credentials
56
+ require 'test/sqs/test_right_sqs_gen2.rb'
57
+ end
58
+
59
+ desc "Test just the S3 interface"
60
+ task :tests3 do
61
+ require 'test/test_credentials'
62
+ require 'test/http_connection'
63
+ TestCredentials.get_credentials
64
+ require 'test/s3/test_right_s3.rb'
65
+ end
66
+
67
+ desc "Test just the S3 interface using local stubs"
68
+ task :tests3local do
69
+ require 'test/test_credentials'
70
+ require 'test/http_connection'
71
+ TestCredentials.get_credentials
72
+ require 'test/s3/test_right_s3_stubbed.rb'
73
+ end
74
+
75
+ desc "Test just the EC2 interface"
76
+ task :testec2 do
77
+ require 'test/test_credentials'
78
+ TestCredentials.get_credentials
79
+ require 'test/ec2/test_right_ec2.rb'
80
+ end
81
+
82
+ desc "Test just the SDB interface"
83
+ task :testsdb do
84
+ require 'test/test_credentials'
85
+ TestCredentials.get_credentials
86
+ require 'test/sdb/test_right_sdb.rb'
87
+ end
88
+
89
+ desc "Test active SDB interface"
90
+ task :testactivesdb do
91
+ require 'test/test_credentials'
92
+ TestCredentials.get_credentials
93
+ require 'test/sdb/test_active_sdb.rb'
94
+ end
95
+
96
+ desc "Test CloudFront interface"
97
+ task :testacf do
98
+ require 'test/test_credentials'
99
+ TestCredentials.get_credentials
100
+ require 'test/acf/test_right_acf.rb'
101
+ end
102
+
103
+ desc "Test RDS interface"
104
+ task :testrds do
105
+ require 'test/test_credentials'
106
+ TestCredentials.get_credentials
107
+ require 'test/rds/test_right_rds.rb'
108
+ end
109
+
110
+ # vim: syntax=Ruby
@@ -0,0 +1,485 @@
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
+ module RightAws
24
+
25
+ # = RightAws::AcfInterface -- RightScale Amazon's CloudFront interface
26
+ # The AcfInterface class provides a complete interface to Amazon's
27
+ # CloudFront service.
28
+ #
29
+ # For explanations of the semantics of each call, please refer to
30
+ # Amazon's documentation at
31
+ # http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=211
32
+ #
33
+ # Example:
34
+ #
35
+ # acf = RightAws::AcfInterface.new('1E3GDYEOGFJPIT7XXXXXX','hgTHt68JY07JKUY08ftHYtERkjgtfERn57XXXXXX')
36
+ #
37
+ # list = acf.list_distributions #=>
38
+ # [{:status => "Deployed",
39
+ # :domain_name => "d74zzrxmpmygb.6hops.net",
40
+ # :aws_id => "E4U91HCJHGXVC",
41
+ # :origin => "my-bucket.s3.amazonaws.com",
42
+ # :cnames => ["x1.my-awesome-site.net", "x1.my-awesome-site.net"]
43
+ # :comment => "My comments",
44
+ # :last_modified_time => "2008-09-10T17:00:04.000Z" }, ..., {...} ]
45
+ #
46
+ # distibution = list.first
47
+ #
48
+ # info = acf.get_distribution(distibution[:aws_id]) #=>
49
+ # {:enabled => true,
50
+ # :caller_reference => "200809102100536497863003",
51
+ # :e_tag => "E39OHHU1ON65SI",
52
+ # :status => "Deployed",
53
+ # :domain_name => "d3dxv71tbbt6cd.6hops.net",
54
+ # :cnames => ["web1.my-awesome-site.net", "web2.my-awesome-site.net"]
55
+ # :aws_id => "E2REJM3VUN5RSI",
56
+ # :comment => "Woo-Hoo!",
57
+ # :origin => "my-bucket.s3.amazonaws.com",
58
+ # :last_modified_time => "2008-09-10T17:00:54.000Z" }
59
+ #
60
+ # config = acf.get_distribution_config(distibution[:aws_id]) #=>
61
+ # {:enabled => true,
62
+ # :caller_reference => "200809102100536497863003",
63
+ # :e_tag => "E39OHHU1ON65SI",
64
+ # :cnames => ["web1.my-awesome-site.net", "web2.my-awesome-site.net"]
65
+ # :comment => "Woo-Hoo!",
66
+ # :origin => "my-bucket.s3.amazonaws.com"}
67
+ #
68
+ # config[:comment] = 'Olah-lah!'
69
+ # config[:enabled] = false
70
+ # config[:cnames] << "web3.my-awesome-site.net"
71
+ #
72
+ # acf.set_distribution_config(distibution[:aws_id], config) #=> true
73
+ #
74
+ class AcfInterface < RightAwsBase
75
+
76
+ include RightAwsBaseInterface
77
+
78
+ API_VERSION = "2010-03-01"
79
+ DEFAULT_HOST = 'cloudfront.amazonaws.com'
80
+ DEFAULT_PORT = 443
81
+ DEFAULT_PROTOCOL = 'https'
82
+ DEFAULT_PATH = '/'
83
+
84
+ @@bench = AwsBenchmarkingBlock.new
85
+ def self.bench_xml
86
+ @@bench.xml
87
+ end
88
+ def self.bench_service
89
+ @@bench.service
90
+ end
91
+
92
+ # Create a new handle to a CloudFront account. All handles share the same per process or per thread
93
+ # HTTP connection to CloudFront. Each handle is for a specific account. The params have the
94
+ # following options:
95
+ # * <tt>:endpoint_url</tt> a fully qualified url to Amazon API endpoint (this overwrites: :server, :port, :service, :protocol). Example: 'https://cloudfront.amazonaws.com'
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
+ #
102
+ # acf = RightAws::AcfInterface.new('1E3GDYEOGFJPIT7XXXXXX','hgTHt68JY07JKUY08ftHYtERkjgtfERn57XXXXXX',
103
+ # {:logger => Logger.new('/tmp/x.log')}) #=> #<RightAws::AcfInterface::0xb7b3c30c>
104
+ #
105
+ def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
106
+ init({ :name => 'ACF',
107
+ :default_host => ENV['ACF_URL'] ? URI.parse(ENV['ACF_URL']).host : DEFAULT_HOST,
108
+ :default_port => ENV['ACF_URL'] ? URI.parse(ENV['ACF_URL']).port : DEFAULT_PORT,
109
+ :default_service => ENV['ACF_URL'] ? URI.parse(ENV['ACF_URL']).path : DEFAULT_PATH,
110
+ :default_protocol => ENV['ACF_URL'] ? URI.parse(ENV['ACF_URL']).scheme : DEFAULT_PROTOCOL,
111
+ :default_api_version => ENV['ACF_API_VERSION'] || API_VERSION },
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, params={}, body=nil, headers={}) # :nodoc:
123
+ # Params
124
+ params.delete_if{ |key, val| val.blank? }
125
+ unless params.blank?
126
+ path += "?" + params.to_a.collect{ |key,val| "#{AwsUtils::amz_escape(key)}=#{AwsUtils::amz_escape(val.to_s)}" }.join("&")
127
+ end
128
+ # Headers
129
+ headers['content-type'] ||= 'text/xml' if body
130
+ headers['date'] = Time.now.httpdate
131
+ # Auth
132
+ signature = AwsUtils::sign(@aws_secret_access_key, headers['date'])
133
+ headers['Authorization'] = "AWS #{@aws_access_key_id}:#{signature}"
134
+ # Request
135
+ path = "#{@params[:service]}#{@params[:api_version]}/#{path}"
136
+ request = "Net::HTTP::#{method.capitalize}".constantize.new(path)
137
+ request.body = body if body
138
+ # Set request headers
139
+ headers.each { |key, value| request[key.to_s] = value }
140
+ # prepare output hash
141
+ { :request => request,
142
+ :server => @params[:server],
143
+ :port => @params[:port],
144
+ :protocol => @params[:protocol] }
145
+ end
146
+
147
+ # Sends request to Amazon and parses the response.
148
+ # Raises AwsError if any banana happened.
149
+ def request_info(request, parser, &block) # :nodoc:
150
+ request_info_impl(:acf_connection, @@bench, request, parser, &block)
151
+ end
152
+
153
+ #-----------------------------------------------------------------
154
+ # Helpers:
155
+ #-----------------------------------------------------------------
156
+
157
+ def self.escape(text) # :nodoc:
158
+ REXML::Text::normalize(text)
159
+ end
160
+
161
+ def self.unescape(text) # :nodoc:
162
+ REXML::Text::unnormalize(text)
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
+ def distribution_config_to_xml(config, xml_wrapper='DistributionConfig') # :nodoc:
178
+ cnames = ''
179
+ logging = ''
180
+ origin_access_identity = ''
181
+ trusted_signers = ''
182
+ # CNAMES
183
+ unless config[:cnames].blank?
184
+ Array(config[:cnames]).each { |cname| cnames += " <CNAME>#{cname}</CNAME>\n" }
185
+ end
186
+ # Logging
187
+ unless config[:logging].blank?
188
+ logging = " <Logging>\n" +
189
+ " <Bucket>#{config[:logging][:bucket]}</Bucket>\n" +
190
+ " <Prefix>#{config[:logging][:prefix]}</Prefix>\n" +
191
+ " </Logging>\n"
192
+ end
193
+ # Origin Access Identity
194
+ unless config[:origin_access_identity].blank?
195
+ origin_access_identity = config[:origin_access_identity]
196
+ unless origin_access_identity[%r{^origin-access-identity}]
197
+ origin_access_identity = "origin-access-identity/cloudfront/#{origin_access_identity}"
198
+ end
199
+ origin_access_identity = " <OriginAccessIdentity>#{origin_access_identity}</OriginAccessIdentity>\n"
200
+ end
201
+ # Trusted Signers
202
+ unless config[:trusted_signers].blank?
203
+ trusted_signers = " <TrustedSigners>\n"
204
+ Array(config[:trusted_signers]).each do |trusted_signer|
205
+ trusted_signers += if trusted_signer.to_s[/self/i]
206
+ " <Self/>\n"
207
+ else
208
+ " <AwsAccountNumber>#{trusted_signer}</AwsAccountNumber>\n"
209
+ end
210
+ end
211
+ trusted_signers += " </TrustedSigners>\n"
212
+ end
213
+
214
+ # XML
215
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
216
+ "<#{xml_wrapper} xmlns=\"http://#{@params[:server]}/doc/#{API_VERSION}/\">\n" +
217
+ " <Origin>#{config[:origin]}</Origin>\n" +
218
+ " <CallerReference>#{config[:caller_reference]}</CallerReference>\n" +
219
+ " <Comment>#{AcfInterface::escape(config[:comment].to_s)}</Comment>\n" +
220
+ " <Enabled>#{config[:enabled]}</Enabled>\n" +
221
+ cnames +
222
+ logging +
223
+ origin_access_identity +
224
+ trusted_signers +
225
+ "</#{xml_wrapper}>"
226
+ end
227
+
228
+ #-----------------------------------------------------------------
229
+ # API Calls:
230
+ #-----------------------------------------------------------------
231
+
232
+ # List all distributions.
233
+ # Returns an array of distributions or RightAws::AwsError exception.
234
+ #
235
+ # acf.list_distributions #=>
236
+ # [{:status => "Deployed",
237
+ # :domain_name => "d74zzrxmpmygb.6hops.net",
238
+ # :aws_id => "E4U91HCJHGXVC",
239
+ # :cnames => ["web1.my-awesome-site.net", "web2.my-awesome-site.net"]
240
+ # :origin => "my-bucket.s3.amazonaws.com",
241
+ # :comment => "My comments",
242
+ # :last_modified_time => Wed Sep 10 17:00:04 UTC 2008 }, ..., {...} ]
243
+ #
244
+ def list_distributions
245
+ result = []
246
+ incrementally_list_distributions do |response|
247
+ result += response[:distributions]
248
+ true
249
+ end
250
+ result
251
+ end
252
+
253
+ # Incrementally list distributions.
254
+ #
255
+ # Optional params: +:marker+ and +:max_items+.
256
+ #
257
+ # # get first distribution
258
+ # incrementally_list_distributions(:max_items => 1) #=>
259
+ # {:distributions=>
260
+ # [{:status=>"Deployed",
261
+ # :aws_id=>"E2Q0AOOMFNPSYL",
262
+ # :origin=>"my-bucket.s3.amazonaws.com",
263
+ # :domain_name=>"d1s5gmdtmafnre.6hops.net",
264
+ # :comment=>"ONE LINE OF COMMENT",
265
+ # :last_modified_time=>"2008-10-22T19:31:23.000Z",
266
+ # :enabled=>true,
267
+ # :cnames=>[]}],
268
+ # :is_truncated=>true,
269
+ # :max_items=>1,
270
+ # :marker=>"",
271
+ # :next_marker=>"E2Q0AOOMFNPSYL"}
272
+ #
273
+ # # get max 100 distributions (the list will be restricted by a default MaxItems value ==100 )
274
+ # incrementally_list_distributions
275
+ #
276
+ # # list distributions by 10
277
+ # incrementally_list_distributions(:max_items => 10) do |response|
278
+ # puts response.inspect # a list of 10 distributions
279
+ # true # return false if the listing should be broken otherwise use true
280
+ # end
281
+ #
282
+ def incrementally_list_distributions(params={}, &block)
283
+ opts = {}
284
+ opts['MaxItems'] = params[:max_items] if params[:max_items]
285
+ opts['Marker'] = params[:marker] if params[:marker]
286
+ last_response = nil
287
+ loop do
288
+ link = generate_request('GET', 'distribution', opts)
289
+ last_response = request_info(link, AcfDistributionListParser.new(:logger => @logger))
290
+ opts['Marker'] = last_response[:next_marker]
291
+ break unless block && block.call(last_response) && !last_response[:next_marker].blank?
292
+ end
293
+ last_response
294
+ end
295
+
296
+ # Create a new distribution.
297
+ # Returns the just created distribution or RightAws::AwsError exception.
298
+ #
299
+ # acf.create_distribution('my-bucket.s3.amazonaws.com', 'Woo-Hoo!', true, ['web1.my-awesome-site.net'], nil,
300
+ # { :prefix=>"log/", :bucket=>"my-logs.s3.amazonaws.com" } ) #=>
301
+ # {:comment => "Woo-Hoo!",
302
+ # :enabled => true,
303
+ # :location => "https://cloudfront.amazonaws.com/2008-06-30/distribution/E2REJM3VUN5RSI",
304
+ # :status => "InProgress",
305
+ # :aws_id => "E2REJM3VUN5RSI",
306
+ # :domain_name => "d3dxv71tbbt6cd.6hops.net",
307
+ # :origin => "my-bucket.s3.amazonaws.com",
308
+ # :cnames => ["web1.my-awesome-site.net"],
309
+ # :logging => { :prefix => "log/",
310
+ # :bucket => "my-logs.s3.amazonaws.com"},
311
+ # :last_modified_time => "2008-10-22T19:31:23.000Z",
312
+ # :caller_reference => "200809102100536497863003"}
313
+ #
314
+ def create_distribution(origin, comment='', enabled=true, cnames=[], caller_reference=nil, logging={})
315
+ config = { :origin => origin,
316
+ :comment => comment,
317
+ :enabled => enabled,
318
+ :cnames => Array(cnames),
319
+ :caller_reference => caller_reference }
320
+ config[:logging] = logging unless logging.blank?
321
+ create_distribution_by_config(config)
322
+ end
323
+
324
+ def create_distribution_by_config(config)
325
+ config[:caller_reference] ||= generate_call_reference
326
+ link = generate_request('POST', 'distribution', {}, distribution_config_to_xml(config))
327
+ merge_headers(request_info(link, AcfDistributionListParser.new(:logger => @logger))[:distributions].first)
328
+ end
329
+
330
+ # Get a distribution's information.
331
+ # Returns a distribution's information or RightAws::AwsError exception.
332
+ #
333
+ # acf.get_distribution('E2REJM3VUN5RSI') #=>
334
+ # {:enabled => true,
335
+ # :caller_reference => "200809102100536497863003",
336
+ # :e_tag => "E39OHHU1ON65SI",
337
+ # :status => "Deployed",
338
+ # :domain_name => "d3dxv71tbbt6cd.6hops.net",
339
+ # :cnames => ["web1.my-awesome-site.net", "web2.my-awesome-site.net"]
340
+ # :aws_id => "E2REJM3VUN5RSI",
341
+ # :comment => "Woo-Hoo!",
342
+ # :origin => "my-bucket.s3.amazonaws.com",
343
+ # :last_modified_time => "2008-09-10T17:00:54.000Z" }
344
+ #
345
+ # acf.get_distribution('E2FNSBHNVVF11E') #=>
346
+ # {:e_tag=>"E1Q2DJEPTQOLJD",
347
+ # :status=>"InProgress",
348
+ # :last_modified_time=>"2010-04-17T17:24:25.000Z",
349
+ # :cnames=>["web1.my-awesome-site.net", "web2.my-awesome-site.net"],
350
+ # :aws_id=>"E2FNSBHNVVF11E",
351
+ # :logging=>{:prefix=>"xlog/", :bucket=>"my-bucket.s3.amazonaws.com"},
352
+ # :enabled=>true,
353
+ # :active_trusted_signers=>
354
+ # [{:aws_account_number=>"120288270000",
355
+ # :key_pair_ids=>["APKAJTD5OHNDX0000000", "APKAIK74BJWCL0000000"]},
356
+ # {:aws_account_number=>"self"},
357
+ # {:aws_account_number=>"648772220000"}],
358
+ # :caller_reference=>"201004171154450740700072",
359
+ # :domain_name=>"d1f6lpevremt5m.cloudfront.net",
360
+ # :origin_access_identity=>"origin-access-identity/cloudfront/E3JPJZ80ZBX24G",
361
+ # :trusted_signers=>["self", "648772220000", "120288270000"],
362
+ # :origin=>"my-bucket.s3.amazonaws.com"}
363
+ #
364
+ def get_distribution(aws_id)
365
+ link = generate_request('GET', "distribution/#{aws_id}")
366
+ merge_headers(request_info(link, AcfDistributionListParser.new(:logger => @logger))[:distributions].first)
367
+ end
368
+
369
+ # Get a distribution's configuration.
370
+ # Returns a distribution's configuration or RightAws::AwsError exception.
371
+ #
372
+ # acf.get_distribution_config('E2REJM3VUN5RSI') #=>
373
+ # {:enabled => true,
374
+ # :caller_reference => "200809102100536497863003",
375
+ # :e_tag => "E39OHHU1ON65SI",
376
+ # :cnames => ["web1.my-awesome-site.net", "web2.my-awesome-site.net"]
377
+ # :comment => "Woo-Hoo!",
378
+ # :origin => "my-bucket.s3.amazonaws.com"}
379
+ #
380
+ # acf.get_distribution_config('E2FNSBHNVVF11E') #=>
381
+ # {:e_tag=>"E1Q2DJEPTQOLJD",
382
+ # :logging=>{:prefix=>"xlog/", :bucket=>"my-bucket.s3.amazonaws.com"},
383
+ # :enabled=>true,
384
+ # :caller_reference=>"201004171154450740700072",
385
+ # :origin_access_identity=>"origin-access-identity/cloudfront/E3JPJZ80ZBX24G",
386
+ # :trusted_signers=>["self", "648772220000", "120288270000"],
387
+ # :origin=>"my-bucket.s3.amazonaws.com"}
388
+ #
389
+ def get_distribution_config(aws_id)
390
+ link = generate_request('GET', "distribution/#{aws_id}/config")
391
+ merge_headers(request_info(link, AcfDistributionListParser.new(:logger => @logger))[:distributions].first)
392
+ end
393
+
394
+ # Set a distribution's configuration
395
+ # (the :origin and the :caller_reference cannot be changed).
396
+ # Returns +true+ on success or RightAws::AwsError exception.
397
+ #
398
+ # config = acf.get_distribution_config('E2REJM3VUN5RSI') #=>
399
+ # {:enabled => true,
400
+ # :caller_reference => "200809102100536497863003",
401
+ # :e_tag => "E39OHHU1ON65SI",
402
+ # :cnames => ["web1.my-awesome-site.net", "web2.my-awesome-site.net"]
403
+ # :comment => "Woo-Hoo!",
404
+ # :origin => "my-bucket.s3.amazonaws.com"}
405
+ #
406
+ # config[:comment] = 'Olah-lah!'
407
+ # config[:enabled] = false
408
+ # config[:origin_access_identity] = "origin-access-identity/cloudfront/E3JPJZ80ZBX24G"
409
+ # # or just
410
+ # # config[:origin_access_identity] = "E3JPJZ80ZBX24G"
411
+ # config[:trusted_signers] = ['self', '648772220000', '120288270000']
412
+ # config[:logging] = { :bucket => 'my-bucket.s3.amazonaws.com', :prefix => 'xlog/' }
413
+ #
414
+ # acf.set_distribution_config('E2REJM3VUN5RSI', config) #=> true
415
+ #
416
+ def set_distribution_config(aws_id, config)
417
+ link = generate_request('PUT', "distribution/#{aws_id}/config", {}, distribution_config_to_xml(config),
418
+ 'If-Match' => config[:e_tag])
419
+ request_info(link, RightHttp2xxParser.new(:logger => @logger))
420
+ end
421
+
422
+ # Delete a distribution. The enabled distribution cannot be deleted.
423
+ # Returns +true+ on success or RightAws::AwsError exception.
424
+ #
425
+ # acf.delete_distribution('E2REJM3VUN5RSI', 'E39OHHU1ON65SI') #=> true
426
+ #
427
+ def delete_distribution(aws_id, e_tag)
428
+ link = generate_request('DELETE', "distribution/#{aws_id}", {}, nil,
429
+ 'If-Match' => e_tag)
430
+ request_info(link, RightHttp2xxParser.new(:logger => @logger))
431
+ end
432
+
433
+ #-----------------------------------------------------------------
434
+ # PARSERS:
435
+ #-----------------------------------------------------------------
436
+
437
+ class AcfDistributionListParser < RightAWSParser # :nodoc:
438
+ def reset
439
+ @result = { :distributions => [] }
440
+ end
441
+ def tagstart(name, attributes)
442
+ case full_tag_name
443
+ when %r{/Signer$}
444
+ @active_signer = {}
445
+ when %r{(Streaming)?DistributionSummary$},
446
+ %r{^(Streaming)?Distribution$},
447
+ %r{^(Streaming)?DistributionConfig$}
448
+ @distribution = { }
449
+ end
450
+ end
451
+ def tagend(name)
452
+ case name
453
+ when 'Marker' then @result[:marker] = @text
454
+ when 'NextMarker' then @result[:next_marker] = @text
455
+ when 'MaxItems' then @result[:max_items] = @text.to_i
456
+ when 'IsTruncated' then @result[:is_truncated] = (@text == 'true')
457
+ when 'Id' then @distribution[:aws_id] = @text
458
+ when 'Status' then @distribution[:status] = @text
459
+ when 'LastModifiedTime' then @distribution[:last_modified_time] = @text
460
+ when 'DomainName' then @distribution[:domain_name] = @text
461
+ when 'Origin' then @distribution[:origin] = @text
462
+ when 'Comment' then @distribution[:comment] = AcfInterface::unescape(@text)
463
+ when 'CallerReference' then @distribution[:caller_reference] = @text
464
+ when 'CNAME' then (@distribution[:cnames] ||= []) << @text
465
+ when 'Enabled' then @distribution[:enabled] = (@text == 'true')
466
+ when 'Bucket' then (@distribution[:logging] ||= {})[:bucket] = @text
467
+ when 'Prefix' then (@distribution[:logging] ||= {})[:prefix] = @text
468
+ when 'OriginAccessIdentity' then @distribution[:origin_access_identity] = @text
469
+ end
470
+ case full_tag_name
471
+ when %r{/TrustedSigners/Self$} then (@distribution[:trusted_signers] ||= []) << 'self'
472
+ when %r{/TrustedSigners/AwsAccountNumber$} then (@distribution[:trusted_signers] ||= []) << @text
473
+ when %r{/Signer/Self$} then @active_signer[:aws_account_number] = 'self'
474
+ when %r{/Signer/AwsAccountNumber$} then @active_signer[:aws_account_number] = @text
475
+ when %r{/Signer/KeyPairId$} then (@active_signer[:key_pair_ids] ||= []) << @text
476
+ when %r{/Signer$} then (@distribution[:active_trusted_signers] ||= []) << @active_signer
477
+ when %r{(Streaming)?DistributionSummary$},
478
+ %r{^(Streaming)?Distribution$},
479
+ %r{^(Streaming)?DistributionConfig$}
480
+ @result[:distributions] << @distribution
481
+ end
482
+ end
483
+ end
484
+ end
485
+ end