aboisvert_aws 3.0.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.
Files changed (78) hide show
  1. data/History.txt +329 -0
  2. data/Manifest.txt +61 -0
  3. data/README.txt +163 -0
  4. data/Rakefile +130 -0
  5. data/lib/acf/right_acf_interface.rb +549 -0
  6. data/lib/acf/right_acf_invalidations.rb +144 -0
  7. data/lib/acf/right_acf_origin_access_identities.rb +230 -0
  8. data/lib/acf/right_acf_streaming_interface.rb +229 -0
  9. data/lib/acw/right_acw_interface.rb +248 -0
  10. data/lib/as/right_as_interface.rb +698 -0
  11. data/lib/awsbase/benchmark_fix.rb +39 -0
  12. data/lib/awsbase/right_awsbase.rb +1343 -0
  13. data/lib/awsbase/support.rb +35 -0
  14. data/lib/awsbase/version.rb +9 -0
  15. data/lib/ec2/right_ec2.rb +541 -0
  16. data/lib/ec2/right_ec2_ebs.rb +481 -0
  17. data/lib/ec2/right_ec2_images.rb +444 -0
  18. data/lib/ec2/right_ec2_instances.rb +788 -0
  19. data/lib/ec2/right_ec2_monitoring.rb +70 -0
  20. data/lib/ec2/right_ec2_placement_groups.rb +108 -0
  21. data/lib/ec2/right_ec2_reserved_instances.rb +184 -0
  22. data/lib/ec2/right_ec2_security_groups.rb +491 -0
  23. data/lib/ec2/right_ec2_spot_instances.rb +422 -0
  24. data/lib/ec2/right_ec2_tags.rb +139 -0
  25. data/lib/ec2/right_ec2_vpc.rb +590 -0
  26. data/lib/ec2/right_ec2_vpc2.rb +381 -0
  27. data/lib/ec2/right_ec2_windows_mobility.rb +84 -0
  28. data/lib/elb/right_elb_interface.rb +573 -0
  29. data/lib/emr/right_emr_interface.rb +727 -0
  30. data/lib/iam/right_iam_access_keys.rb +71 -0
  31. data/lib/iam/right_iam_groups.rb +195 -0
  32. data/lib/iam/right_iam_interface.rb +341 -0
  33. data/lib/iam/right_iam_mfa_devices.rb +67 -0
  34. data/lib/iam/right_iam_users.rb +251 -0
  35. data/lib/rds/right_rds_interface.rb +1384 -0
  36. data/lib/right_aws.rb +86 -0
  37. data/lib/route_53/right_route_53_interface.rb +640 -0
  38. data/lib/s3/right_s3.rb +1138 -0
  39. data/lib/s3/right_s3_interface.rb +1278 -0
  40. data/lib/sdb/active_sdb.rb +1107 -0
  41. data/lib/sdb/right_sdb_interface.rb +762 -0
  42. data/lib/sns/right_sns_interface.rb +286 -0
  43. data/lib/sqs/right_sqs.rb +387 -0
  44. data/lib/sqs/right_sqs_gen2.rb +342 -0
  45. data/lib/sqs/right_sqs_gen2_interface.rb +523 -0
  46. data/lib/sqs/right_sqs_interface.rb +593 -0
  47. data/right_aws.gemspec +90 -0
  48. data/test/README.mdown +39 -0
  49. data/test/acf/test_helper.rb +2 -0
  50. data/test/acf/test_right_acf.rb +138 -0
  51. data/test/awsbase/test_helper.rb +2 -0
  52. data/test/awsbase/test_right_awsbase.rb +11 -0
  53. data/test/ec2/test_helper.rb +2 -0
  54. data/test/ec2/test_right_ec2.rb +107 -0
  55. data/test/elb/test_helper.rb +2 -0
  56. data/test/elb/test_right_elb.rb +43 -0
  57. data/test/http_connection.rb +87 -0
  58. data/test/rds/test_helper.rb +2 -0
  59. data/test/rds/test_right_rds.rb +120 -0
  60. data/test/route_53/fixtures/a_record.xml +18 -0
  61. data/test/route_53/fixtures/alias_record.xml +18 -0
  62. data/test/route_53/test_helper.rb +2 -0
  63. data/test/route_53/test_right_route_53.rb +141 -0
  64. data/test/s3/test_helper.rb +2 -0
  65. data/test/s3/test_right_s3.rb +528 -0
  66. data/test/s3/test_right_s3_stubbed.rb +97 -0
  67. data/test/sdb/test_active_sdb.rb +357 -0
  68. data/test/sdb/test_batch_put_attributes.rb +54 -0
  69. data/test/sdb/test_helper.rb +3 -0
  70. data/test/sdb/test_right_sdb.rb +253 -0
  71. data/test/sns/test_helper.rb +2 -0
  72. data/test/sns/test_right_sns.rb +153 -0
  73. data/test/sqs/test_helper.rb +2 -0
  74. data/test/sqs/test_right_sqs.rb +285 -0
  75. data/test/sqs/test_right_sqs_gen2.rb +264 -0
  76. data/test/test_credentials.rb +37 -0
  77. data/test/ts_right_aws.rb +15 -0
  78. metadata +257 -0
@@ -0,0 +1,130 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require "rake/testtask"
5
+ require 'rake/gempackagetask'
6
+ require 'rake/clean'
7
+ $: << File.dirname(__FILE__)
8
+ testglobs = ["test/ts_right_aws.rb"]
9
+
10
+ begin
11
+ require 'bundler'
12
+ rescue LoadError => e
13
+ STDERR.puts("Bundler is not available, some rake tasks will not be defined: #{e.message}")
14
+ else
15
+ Bundler::GemHelper.install_tasks :name => 'right_aws'
16
+ end
17
+
18
+ begin
19
+ require 'rcov/rcovtask'
20
+ rescue LoadError => e
21
+ STDERR.puts("RCov is not available, some rake tasks will not be defined: #{e.message}")
22
+ else
23
+ desc "Analyze code coverage of the unit tests."
24
+ Rcov::RcovTask.new do |t|
25
+ t.test_files = FileList[testglobs]
26
+ #t.verbose = true # uncomment to see the executed command
27
+ end
28
+ end
29
+
30
+ # == Gem == #
31
+
32
+ gemtask = Rake::GemPackageTask.new(Gem::Specification.load("right_aws.gemspec")) do |package|
33
+ package.package_dir = ENV['PACKAGE_DIR'] || 'pkg'
34
+ package.need_zip = true
35
+ package.need_tar = true
36
+ end
37
+
38
+ directory gemtask.package_dir
39
+
40
+ CLEAN.include(gemtask.package_dir)
41
+
42
+ desc "Test just the SQS interface"
43
+ task :testsqs do
44
+ require 'test/test_credentials'
45
+ require 'test/http_connection'
46
+ TestCredentials.get_credentials
47
+ require 'test/sqs/test_right_sqs.rb'
48
+ end
49
+
50
+ desc "Test just the second generation SQS interface"
51
+ task :testsqs2 do
52
+ require 'test/test_credentials'
53
+ require 'test/http_connection'
54
+ TestCredentials.get_credentials
55
+ require 'test/sqs/test_right_sqs_gen2.rb'
56
+ end
57
+
58
+ desc "Test just the S3 interface"
59
+ task :tests3 do
60
+ require 'test/test_credentials'
61
+ require 'test/http_connection'
62
+ TestCredentials.get_credentials
63
+ require 'test/s3/test_right_s3.rb'
64
+ end
65
+
66
+ desc "Test just the S3 interface using local stubs"
67
+ task :tests3local do
68
+ require 'test/test_credentials'
69
+ require 'test/http_connection'
70
+ TestCredentials.get_credentials
71
+ require 'test/s3/test_right_s3_stubbed.rb'
72
+ end
73
+
74
+ desc "Test just the EC2 interface"
75
+ task :testec2 do
76
+ require 'test/test_credentials'
77
+ TestCredentials.get_credentials
78
+ require 'test/ec2/test_right_ec2.rb'
79
+ end
80
+
81
+ desc "Test just the SDB interface"
82
+ task :testsdb do
83
+ require 'test/test_credentials'
84
+ TestCredentials.get_credentials
85
+ require 'test/sdb/test_right_sdb.rb'
86
+ end
87
+
88
+ desc "Test active SDB interface"
89
+ task :testactivesdb do
90
+ require 'test/test_credentials'
91
+ TestCredentials.get_credentials
92
+ require 'test/sdb/test_active_sdb.rb'
93
+ end
94
+
95
+ desc "Test CloudFront interface"
96
+ task :testacf do
97
+ require 'test/test_credentials'
98
+ TestCredentials.get_credentials
99
+ require 'test/acf/test_right_acf.rb'
100
+ end
101
+
102
+ desc "Test RDS interface"
103
+ task :testrds do
104
+ require 'test/test_credentials'
105
+ TestCredentials.get_credentials
106
+ require 'test/rds/test_right_rds.rb'
107
+ end
108
+
109
+ desc "Test just the SNS interface"
110
+ task :testsns do
111
+ require 'test/test_credentials'
112
+ TestCredentials.get_credentials
113
+ require 'test/sns/test_right_sns.rb'
114
+ end
115
+
116
+ desc "Test Route 53 interface"
117
+ task :testroute53 do
118
+ require 'test/test_credentials'
119
+ TestCredentials.get_credentials
120
+ require 'test/route_53/test_right_route_53'
121
+ end
122
+
123
+ desc "Test ELB interface"
124
+ task :testelb do
125
+ require 'test/test_credentials'
126
+ TestCredentials.get_credentials
127
+ require 'test/elb/test_right_elb'
128
+ end
129
+
130
+ # vim: syntax=Ruby
@@ -0,0 +1,549 @@
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
+ # :s3_origin => {:dns_name=>"bucket-for-konstantin-00.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
+ # {:last_modified_time=>"2010-05-19T18:54:38.242Z",
50
+ # :status=>"Deployed",
51
+ # :domain_name=>"dpzl38cuix402.cloudfront.net",
52
+ # :caller_reference=>"201005181943052207677116",
53
+ # :e_tag=>"EJSXFGM5JL8ER",
54
+ # :s3_origin=>
55
+ # {:dns_name=>"bucket-for-konstantin-eu.s3.amazonaws.com",
56
+ # :origin_access_identity=>
57
+ # "origin-access-identity/cloudfront/E3JPJZ80ZBX24G"},
58
+ # :aws_id=>"E5P8HQ3ZAZIXD",
59
+ # :enabled=>false}
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
+ # :s3_origin => {:dns_name => "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 < RightAwsBase
76
+
77
+ include RightAwsBaseInterface
78
+
79
+ API_VERSION = "2010-11-01"
80
+ DEFAULT_HOST = 'cloudfront.amazonaws.com'
81
+ DEFAULT_PORT = 443
82
+ DEFAULT_PROTOCOL = 'https'
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>:endpoint_url</tt> a fully qualified url to Amazon API endpoint (this overwrites: :server, :port, :service, :protocol). Example: 'https://cloudfront.amazonaws.com'
97
+ # * <tt>:server</tt>: CloudFront service host, default: DEFAULT_HOST
98
+ # * <tt>:port</tt>: CloudFront service port, default: DEFAULT_PORT
99
+ # * <tt>:protocol</tt>: 'http' or 'https', default: DEFAULT_PROTOCOL
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.right_blank? }
125
+ unless params.right_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}".right_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 generate_call_reference # :nodoc:
158
+ result = Time.now.strftime('%Y%m%d%H%M%S')
159
+ 10.times{ result << rand(10).to_s }
160
+ result
161
+ end
162
+
163
+ def merge_headers(hash) # :nodoc:
164
+ hash[:location] = @last_response['Location'] if @last_response['Location']
165
+ hash[:e_tag] = @last_response['ETag'] if @last_response['ETag']
166
+ hash
167
+ end
168
+
169
+ def distribution_config_to_xml(config, xml_wrapper='DistributionConfig') # :nodoc:
170
+ cnames = logging = trusted_signers = s3_origin = custom_origin = default_root_object = ''
171
+ # CNAMES
172
+ unless config[:cnames].right_blank?
173
+ Array(config[:cnames]).each { |cname| cnames += " <CNAME>#{cname}</CNAME>\n" }
174
+ end
175
+ # Logging
176
+ unless config[:logging].right_blank?
177
+ logging = " <Logging>\n" +
178
+ " <Bucket>#{config[:logging][:bucket]}</Bucket>\n" +
179
+ " <Prefix>#{config[:logging][:prefix]}</Prefix>\n" +
180
+ " </Logging>\n"
181
+ end
182
+ unless config[:required_protocols].right_blank?
183
+ required_protocols = " <RequiredProtocols>\n" +
184
+ " <Protocol>#{config[:required_protocols]}</Protocol>\n" +
185
+ " </RequiredProtocols>\n"
186
+ else required_protocols = ""
187
+ end
188
+ # Default Root Object
189
+ unless config[:default_root_object].right_blank?
190
+ default_root_object = " <DefaultRootObject>#{config[:default_root_object]}</DefaultRootObject>\n" unless config[:default_root_object].right_blank?
191
+ end
192
+ # Trusted Signers
193
+ unless config[:trusted_signers].right_blank?
194
+ trusted_signers = " <TrustedSigners>\n"
195
+ Array(config[:trusted_signers]).each do |trusted_signer|
196
+ trusted_signers += if trusted_signer.to_s[/self/i]
197
+ " <Self/>\n"
198
+ else
199
+ " <AwsAccountNumber>#{trusted_signer}</AwsAccountNumber>\n"
200
+ end
201
+ end
202
+ trusted_signers += " </TrustedSigners>\n"
203
+ end
204
+ # S3Origin
205
+ unless config[:s3_origin].right_blank?
206
+ origin_access_identity = ''
207
+ # Origin Access Identity
208
+ unless config[:s3_origin][:origin_access_identity].right_blank?
209
+ origin_access_identity = config[:s3_origin][:origin_access_identity]
210
+ unless origin_access_identity[%r{^origin-access-identity}]
211
+ origin_access_identity = "origin-access-identity/cloudfront/#{origin_access_identity}"
212
+ end
213
+ origin_access_identity = " <OriginAccessIdentity>#{origin_access_identity}</OriginAccessIdentity>\n"
214
+ end
215
+ s3_origin = " <S3Origin>\n" +
216
+ " <DNSName>#{config[:s3_origin][:dns_name]}</DNSName>\n" +
217
+ "#{origin_access_identity}" +
218
+ " </S3Origin>\n"
219
+ end
220
+ # Custom Origin
221
+ unless config[:custom_origin].right_blank?
222
+ http_port = https_port = origin_protocol_policy = ''
223
+ http_port = " <HTTPPort>#{config[:custom_origin][:http_port]}</HTTPPort>\n" unless config[:custom_origin][:http_port].right_blank?
224
+ https_port = " <HTTPSPort>#{config[:custom_origin][:https_port]}</HTTPSPort>" unless config[:custom_origin][:https_port].right_blank?
225
+ origin_protocol_policy = " <OriginProtocolPolicy>#{config[:custom_origin][:origin_protocol_policy]}</OriginProtocolPolicy>\n" unless config[:custom_origin][:origin_protocol_policy].right_blank?
226
+ custom_origin = " <CustomOrigin>\n" +
227
+ " <DNSName>#{config[:custom_origin][:dns_name]}</DNSName>\n" +
228
+ "#{http_port}" +
229
+ "#{https_port}" +
230
+ "#{origin_protocol_policy}" +
231
+ " </CustomOrigin>\n"
232
+ end
233
+ # XML
234
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
235
+ "<#{xml_wrapper} xmlns=\"http://#{@params[:server]}/doc/#{API_VERSION}/\">\n" +
236
+ " <CallerReference>#{config[:caller_reference]}</CallerReference>\n" +
237
+ " <Comment>#{AwsUtils::xml_escape(config[:comment].to_s)}</Comment>\n" +
238
+ " <Enabled>#{config[:enabled]}</Enabled>\n" +
239
+ s3_origin +
240
+ custom_origin +
241
+ default_root_object +
242
+ cnames +
243
+ logging +
244
+ required_protocols +
245
+ trusted_signers +
246
+ "</#{xml_wrapper}>"
247
+ end
248
+
249
+ #-----------------------------------------------------------------
250
+ # API Calls:
251
+ #-----------------------------------------------------------------
252
+
253
+ # List all distributions.
254
+ # Returns an array of distributions or RightAws::AwsError exception.
255
+ #
256
+ # acf.list_distributions #=>
257
+ # [{:status=>"Deployed",
258
+ # :domain_name=>"dgmde.6os.net",
259
+ # :comment=>"ONE LINE OF COMMENT",
260
+ # :last_modified_time=>"2009-06-16T16:10:02.210Z",
261
+ # :s3_origin=>{:dns_name=>"example.s3.amazonaws.com"},
262
+ # :aws_id=>"12Q05OOMFN7SYL",
263
+ # :enabled=>true}, ... ]
264
+ #
265
+ def list_distributions
266
+ result = []
267
+ incrementally_list_distributions do |response|
268
+ result += response[:distributions]
269
+ true
270
+ end
271
+ result
272
+ end
273
+
274
+ # Incrementally list distributions.
275
+ #
276
+ # Optional params: +:marker+ and +:max_items+.
277
+ #
278
+ # # get first distribution
279
+ # incrementally_list_distributions(:max_items => 1) #=>
280
+ # {:distributions=>
281
+ # [{:status=>"Deployed",
282
+ # :aws_id=>"E2Q0AOOMFNPSYL",
283
+ # :s3_origin=>{:dns_name=>"example.s3.amazonaws.com"},
284
+ # :domain_name=>"d1s5gmdtmafnre.6hops.net",
285
+ # :comment=>"ONE LINE OF COMMENT",
286
+ # :last_modified_time=>"2008-10-22T19:31:23.000Z",
287
+ # :enabled=>true,
288
+ # :cnames=>[]}],
289
+ # :is_truncated=>true,
290
+ # :max_items=>1,
291
+ # :marker=>"",
292
+ # :next_marker=>"E2Q0AOOMFNPSYL"}
293
+ #
294
+ # # get max 100 distributions (the list will be restricted by a default MaxItems value ==100 )
295
+ # incrementally_list_distributions
296
+ #
297
+ # # list distributions by 10
298
+ # incrementally_list_distributions(:max_items => 10) do |response|
299
+ # puts response.inspect # a list of 10 distributions
300
+ # true # return false if the listing should be broken otherwise use true
301
+ # end
302
+ #
303
+ def incrementally_list_distributions(params={}, &block)
304
+ opts = {}
305
+ opts['MaxItems'] = params[:max_items] if params[:max_items]
306
+ opts['Marker'] = params[:marker] if params[:marker]
307
+ last_response = nil
308
+ loop do
309
+ link = generate_request('GET', 'distribution', opts)
310
+ last_response = request_info(link, AcfDistributionListParser.new(:logger => @logger))
311
+ opts['Marker'] = last_response[:next_marker]
312
+ break unless block && block.call(last_response) && !last_response[:next_marker].right_blank?
313
+ end
314
+ last_response
315
+ end
316
+
317
+ # Create a new distribution.
318
+ # Returns the just created distribution or RightAws::AwsError exception.
319
+ #
320
+ # # S3 Origin
321
+ #
322
+ # config = { :comment => "kd: delete me please",
323
+ # :s3_origin => { :dns_name => "devs-us-east.s3.amazonaws.com",
324
+ # :origin_access_identity => "origin-access-identity/cloudfront/E3JPJZ80ZBX24G"},
325
+ # :enabled => true,
326
+ # :logging => { :prefix => "kd/log/",
327
+ # :bucket => "devs-us-west.s3.amazonaws.com"}}
328
+ # acf.create_distribution(config) #=>
329
+ # { :status=>"InProgress",
330
+ # :enabled=>true,
331
+ # :caller_reference=>"201012071910051044304704",
332
+ # :logging=>{:prefix=>"kd/log/", :bucket=>"devs-us-west.s3.amazonaws.com"},
333
+ # :e_tag=>"ESCTG5WJCFWJK",
334
+ # :location=> "https://cloudfront.amazonaws.com/2010-11-01/distribution/E3KUBANZ7N1B2",
335
+ # :comment=>"kd: delete me please",
336
+ # :domain_name=>"d3stykk6upgs20.cloudfront.net",
337
+ # :aws_id=>"E3KUBANZ7N1B2",
338
+ # :s3_origin=>
339
+ # {:origin_access_identity=>"origin-access-identity/cloudfront/E3JPJZ80ZBX24G",
340
+ # :dns_name=>"devs-us-east.s3.amazonaws.com"},
341
+ # :last_modified_time=>"2010-12-07T16:10:07.087Z",
342
+ # :in_progress_invalidation_batches=>0}
343
+ #
344
+ # # Custom Origin
345
+ #
346
+ # custom_config = { :comment => "kd: delete me please",
347
+ # :custom_origin => { :dns_name => "custom_origin.my-site.com",
348
+ # :http_port => 80,
349
+ # :https_port => 443,
350
+ # :origin_protocol_policy => 'match-viewer' },
351
+ # :enabled => true,
352
+ # :logging => { :prefix => "kd/log/",
353
+ # :bucket => "my-bucket.s3.amazonaws.com"}} #=>
354
+ # { :last_modified_time=>"2010-12-08T14:23:43.522Z",
355
+ # :status=>"InProgress",
356
+ # :custom_origin=>
357
+ # {:http_port=>"80",
358
+ # :https_port=>"443",
359
+ # :origin_protocol_policy=>"match-viewer",
360
+ # :dns_name=>"custom_origin.my-site.com"},
361
+ # :enabled=>true,
362
+ # :caller_reference=>"201012081723428499167245",
363
+ # :in_progress_invalidation_batches=>0,
364
+ # :e_tag=>"E1ZCJ8N5E52KO6",
365
+ # :location=>
366
+ # "https://cloudfront.amazonaws.com/2010-11-01/distribution/EK0AJ4RMNIF2P",
367
+ # :logging=>{:prefix=>"kd/log/", :bucket=>"my-bucket.s3.amazonaws.com"},
368
+ # :domain_name=>"do36k7s2wxklg.cloudfront.net",
369
+ # :comment=>"kd: delete me please",
370
+ # :aws_id=>"EK0AJ4RMNIF2P"}
371
+ #
372
+ def create_distribution(config)
373
+ config[:caller_reference] ||= generate_call_reference
374
+ link = generate_request('POST', 'distribution', {}, distribution_config_to_xml(config))
375
+ merge_headers(request_info(link, AcfDistributionListParser.new(:logger => @logger))[:distributions].first)
376
+ end
377
+ alias_method :create_distribution_by_config, :create_distribution
378
+
379
+ # Get a distribution's information.
380
+ # Returns a distribution's information or RightAws::AwsError exception.
381
+ #
382
+ # acf.get_distribution('E2REJM3VUN5RSI') #=>
383
+ # {:last_modified_time=>"2010-05-19T18:54:38.242Z",
384
+ # :status=>"Deployed",
385
+ # :domain_name=>"dpzl38cuix402.cloudfront.net",
386
+ # :caller_reference=>"201005181943052207677116",
387
+ # :e_tag=>"EJSXFGM5JL8ER",
388
+ # :s3_origin=>
389
+ # {:dns_name=>"bucket-for-konstantin-eu.s3.amazonaws.com",
390
+ # :origin_access_identity=>
391
+ # "origin-access-identity/cloudfront/E3JPJZ80ZBX24G"},
392
+ # :aws_id=>"E5P8HQ3ZAZIXD",
393
+ # :enabled=>false}
394
+ #
395
+ # acf.get_distribution('E2FNSBHNVVF11E') #=>
396
+ # {:e_tag=>"E1Q2DJEPTQOLJD",
397
+ # :status=>"InProgress",
398
+ # :last_modified_time=>"2010-04-17T17:24:25.000Z",
399
+ # :cnames=>["web1.my-awesome-site.net", "web2.my-awesome-site.net"],
400
+ # :aws_id=>"E2FNSBHNVVF11E",
401
+ # :logging=>{:prefix=>"xlog/", :bucket=>"my-bucket.s3.amazonaws.com"},
402
+ # :enabled=>true,
403
+ # :active_trusted_signers=>
404
+ # [{:aws_account_number=>"120288270000",
405
+ # :key_pair_ids=>["APKAJTD5OHNDX0000000", "APKAIK74BJWCL0000000"]},
406
+ # {:aws_account_number=>"self"},
407
+ # {:aws_account_number=>"648772220000"}],
408
+ # :caller_reference=>"201004171154450740700072",
409
+ # :domain_name=>"d1f6lpevremt5m.cloudfront.net",
410
+ # :s3_origin=>
411
+ # {:dns_name=>"bucket-for-konstantin-eu.s3.amazonaws.com",
412
+ # :origin_access_identity=>
413
+ # "origin-access-identity/cloudfront/E3JPJZ80ZBX24G"},
414
+ # :trusted_signers=>["self", "648772220000", "120288270000"]}
415
+ #
416
+ def get_distribution(aws_id)
417
+ link = generate_request('GET', "distribution/#{aws_id}")
418
+ merge_headers(request_info(link, AcfDistributionListParser.new(:logger => @logger))[:distributions].first)
419
+ end
420
+
421
+ # Get a distribution's configuration.
422
+ # Returns a distribution's configuration or RightAws::AwsError exception.
423
+ #
424
+ # acf.get_distribution_config('E2REJM3VUN5RSI') #=>
425
+ # {:caller_reference=>"201005181943052207677116",
426
+ # :e_tag=>"EJSXFGM5JL8ER",
427
+ # :s3_origin=>
428
+ # {:dns_name=>"bucket-for-konstantin-eu.s3.amazonaws.com",
429
+ # :origin_access_identity=>
430
+ # "origin-access-identity/cloudfront/E3JPJZ80ZBX24G"},
431
+ # :enabled=>false}
432
+ #
433
+ # acf.get_distribution_config('E2FNSBHNVVF11E') #=>
434
+ # {:e_tag=>"E1Q2DJEPTQOLJD",
435
+ # :logging=>{:prefix=>"xlog/", :bucket=>"my-bucket.s3.amazonaws.com"},
436
+ # :enabled=>true,
437
+ # :caller_reference=>"201004171154450740700072",
438
+ # :trusted_signers=>["self", "648772220000", "120288270000"],
439
+ # :s3_origin=>
440
+ # {:dns_name=>"bucket-for-konstantin-eu.s3.amazonaws.com",
441
+ # :origin_access_identity=>
442
+ # "origin-access-identity/cloudfront/E3JPJZ80ZBX24G"}}
443
+ #
444
+ def get_distribution_config(aws_id)
445
+ link = generate_request('GET', "distribution/#{aws_id}/config")
446
+ merge_headers(request_info(link, AcfDistributionListParser.new(:logger => @logger))[:distributions].first)
447
+ end
448
+
449
+ # Set a distribution's configuration
450
+ # Returns +true+ on success or RightAws::AwsError exception.
451
+ #
452
+ # config = acf.get_distribution_config('E2REJM3VUN5RSI') #=>
453
+ # {:enabled => true,
454
+ # :caller_reference => "200809102100536497863003",
455
+ # :e_tag => "E39OHHU1ON65SI",
456
+ # :cnames => ["web1.my-awesome-site.net", "web2.my-awesome-site.net"]
457
+ # :comment => "Woo-Hoo!",
458
+ # :s3_origin => { :dns_name => "my-bucket.s3.amazonaws.com"}}
459
+ #
460
+ # config[:comment] = 'Olah-lah!'
461
+ # config[:enabled] = false
462
+ # config[:s3_origin][:origin_access_identity] = "origin-access-identity/cloudfront/E3JPJZ80ZBX24G"
463
+ # # or just
464
+ # # config[:s3_origin][:origin_access_identity] = "E3JPJZ80ZBX24G"
465
+ # config[:trusted_signers] = ['self', '648772220000', '120288270000']
466
+ # config[:logging] = { :bucket => 'my-bucket.s3.amazonaws.com', :prefix => 'xlog/' }
467
+ #
468
+ # acf.set_distribution_config('E2REJM3VUN5RSI', config) #=> true
469
+ #
470
+ def set_distribution_config(aws_id, config)
471
+ link = generate_request('PUT', "distribution/#{aws_id}/config", {}, distribution_config_to_xml(config),
472
+ 'If-Match' => config[:e_tag])
473
+ request_info(link, RightHttp2xxParser.new(:logger => @logger))
474
+ end
475
+
476
+ # Delete a distribution. The enabled distribution cannot be deleted.
477
+ # Returns +true+ on success or RightAws::AwsError exception.
478
+ #
479
+ # acf.delete_distribution('E2REJM3VUN5RSI', 'E39OHHU1ON65SI') #=> true
480
+ #
481
+ def delete_distribution(aws_id, e_tag)
482
+ link = generate_request('DELETE', "distribution/#{aws_id}", {}, nil,
483
+ 'If-Match' => e_tag)
484
+ request_info(link, RightHttp2xxParser.new(:logger => @logger))
485
+ end
486
+
487
+ #-----------------------------------------------------------------
488
+ # PARSERS:
489
+ #-----------------------------------------------------------------
490
+
491
+ class AcfDistributionListParser < RightAWSParser # :nodoc:
492
+ def reset
493
+ @result = { :distributions => [] }
494
+ end
495
+ def tagstart(name, attributes)
496
+ case full_tag_name
497
+ when %r{/Signer$}
498
+ @active_signer = {}
499
+ when %r{(Streaming)?DistributionSummary$},
500
+ %r{^(Streaming)?Distribution$},
501
+ %r{^(Streaming)?DistributionConfig$}
502
+ @distribution = { }
503
+ when %r{/S3Origin$} then @distribution[:s3_origin] = {}
504
+ when %r{/CustomOrigin$} then @distribution[:custom_origin] = {}
505
+ end
506
+ end
507
+ def tagend(name)
508
+ case name
509
+ when 'Marker' then @result[:marker] = @text
510
+ when 'NextMarker' then @result[:next_marker] = @text
511
+ when 'MaxItems' then @result[:max_items] = @text.to_i
512
+ when 'IsTruncated' then @result[:is_truncated] = (@text == 'true')
513
+ when 'Id' then @distribution[:aws_id] = @text
514
+ when 'Status' then @distribution[:status] = @text
515
+ when 'LastModifiedTime' then @distribution[:last_modified_time] = @text
516
+ when 'DomainName' then @distribution[:domain_name] = @text
517
+ when 'Comment' then @distribution[:comment] = AwsUtils::xml_unescape(@text)
518
+ when 'CallerReference' then @distribution[:caller_reference] = @text
519
+ when 'CNAME' then (@distribution[:cnames] ||= []) << @text
520
+ when 'Enabled' then @distribution[:enabled] = (@text == 'true')
521
+ when 'Bucket' then (@distribution[:logging] ||= {})[:bucket] = @text
522
+ when 'Prefix' then (@distribution[:logging] ||= {})[:prefix] = @text
523
+ when 'Protocol' then (@distribution[:required_protocols] ||= {})[:protocol] = @text
524
+ when 'InProgressInvalidationBatches' then @distribution[:in_progress_invalidation_batches] = @text.to_i
525
+ when 'DefaultRootObject' then @distribution[:default_root_object] = @text
526
+ else
527
+ case full_tag_name
528
+ when %r{/S3Origin/DNSName$} then @distribution[:s3_origin][:dns_name] = @text
529
+ when %r{/S3Origin/OriginAccessIdentity$} then @distribution[:s3_origin][:origin_access_identity] = @text
530
+ when %r{/CustomOrigin/DNSName$} then @distribution[:custom_origin][:dns_name] = @text
531
+ when %r{/CustomOrigin/HTTPPort} then @distribution[:custom_origin][:http_port] = @text
532
+ when %r{/CustomOrigin/HTTPSPort$} then @distribution[:custom_origin][:https_port] = @text
533
+ when %r{/CustomOrigin/OriginProtocolPolicy$} then @distribution[:custom_origin][:origin_protocol_policy] = @text
534
+ when %r{/TrustedSigners/Self$} then (@distribution[:trusted_signers] ||= []) << 'self'
535
+ when %r{/TrustedSigners/AwsAccountNumber$} then (@distribution[:trusted_signers] ||= []) << @text
536
+ when %r{/Signer/Self$} then @active_signer[:aws_account_number] = 'self'
537
+ when %r{/Signer/AwsAccountNumber$} then @active_signer[:aws_account_number] = @text
538
+ when %r{/Signer/KeyPairId$} then (@active_signer[:key_pair_ids] ||= []) << @text
539
+ when %r{/Signer$} then (@distribution[:active_trusted_signers] ||= []) << @active_signer
540
+ when %r{(Streaming)?DistributionSummary$},
541
+ %r{^(Streaming)?Distribution$},
542
+ %r{^(Streaming)?DistributionConfig$}
543
+ @result[:distributions] << @distribution
544
+ end
545
+ end
546
+ end
547
+ end
548
+ end
549
+ end