right_aws 1.9.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. data/History.txt +164 -13
  2. data/Manifest.txt +28 -1
  3. data/README.txt +12 -10
  4. data/Rakefile +56 -29
  5. data/lib/acf/right_acf_interface.rb +343 -172
  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/right_awsbase.rb +755 -115
  12. data/lib/awsbase/support.rb +2 -78
  13. data/lib/awsbase/version.rb +9 -0
  14. data/lib/ec2/right_ec2.rb +274 -1294
  15. data/lib/ec2/right_ec2_ebs.rb +514 -0
  16. data/lib/ec2/right_ec2_images.rb +444 -0
  17. data/lib/ec2/right_ec2_instances.rb +797 -0
  18. data/lib/ec2/right_ec2_monitoring.rb +70 -0
  19. data/lib/ec2/right_ec2_placement_groups.rb +108 -0
  20. data/lib/ec2/right_ec2_reserved_instances.rb +243 -0
  21. data/lib/ec2/right_ec2_security_groups.rb +496 -0
  22. data/lib/ec2/right_ec2_spot_instances.rb +422 -0
  23. data/lib/ec2/right_ec2_tags.rb +139 -0
  24. data/lib/ec2/right_ec2_vpc.rb +598 -0
  25. data/lib/ec2/right_ec2_vpc2.rb +382 -0
  26. data/lib/ec2/right_ec2_windows_mobility.rb +84 -0
  27. data/lib/elb/right_elb_interface.rb +573 -0
  28. data/lib/emr/right_emr_interface.rb +728 -0
  29. data/lib/iam/right_iam_access_keys.rb +71 -0
  30. data/lib/iam/right_iam_groups.rb +195 -0
  31. data/lib/iam/right_iam_interface.rb +341 -0
  32. data/lib/iam/right_iam_mfa_devices.rb +67 -0
  33. data/lib/iam/right_iam_users.rb +251 -0
  34. data/lib/rds/right_rds_interface.rb +1657 -0
  35. data/lib/right_aws.rb +30 -13
  36. data/lib/route_53/right_route_53_interface.rb +641 -0
  37. data/lib/s3/right_s3.rb +108 -41
  38. data/lib/s3/right_s3_interface.rb +349 -118
  39. data/lib/sdb/active_sdb.rb +388 -54
  40. data/lib/sdb/right_sdb_interface.rb +323 -64
  41. data/lib/sns/right_sns_interface.rb +286 -0
  42. data/lib/sqs/right_sqs.rb +1 -2
  43. data/lib/sqs/right_sqs_gen2.rb +73 -17
  44. data/lib/sqs/right_sqs_gen2_interface.rb +146 -73
  45. data/lib/sqs/right_sqs_interface.rb +12 -22
  46. data/right_aws.gemspec +91 -0
  47. data/test/README.mdown +39 -0
  48. data/test/acf/test_right_acf.rb +11 -19
  49. data/test/awsbase/test_helper.rb +2 -0
  50. data/test/awsbase/test_right_awsbase.rb +11 -0
  51. data/test/ec2/test_right_ec2.rb +32 -1
  52. data/test/elb/test_helper.rb +2 -0
  53. data/test/elb/test_right_elb.rb +43 -0
  54. data/test/rds/test_helper.rb +2 -0
  55. data/test/rds/test_right_rds.rb +120 -0
  56. data/test/route_53/fixtures/a_record.xml +18 -0
  57. data/test/route_53/fixtures/alias_record.xml +18 -0
  58. data/test/route_53/test_helper.rb +2 -0
  59. data/test/route_53/test_right_route_53.rb +141 -0
  60. data/test/s3/test_right_s3.rb +176 -42
  61. data/test/s3/test_right_s3_stubbed.rb +6 -4
  62. data/test/sdb/test_active_sdb.rb +120 -19
  63. data/test/sdb/test_batch_put_attributes.rb +54 -0
  64. data/test/sdb/test_right_sdb.rb +71 -16
  65. data/test/sns/test_helper.rb +2 -0
  66. data/test/sns/test_right_sns.rb +153 -0
  67. data/test/sqs/test_right_sqs.rb +0 -6
  68. data/test/sqs/test_right_sqs_gen2.rb +104 -49
  69. data/test/ts_right_aws.rb +1 -0
  70. metadata +181 -22
@@ -20,7 +20,6 @@
20
20
  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
21
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  #
23
-
24
23
  module RightAws
25
24
 
26
25
  # = RightAws::AcfInterface -- RightScale Amazon's CloudFront interface
@@ -39,24 +38,25 @@ module RightAws
39
38
  # [{:status => "Deployed",
40
39
  # :domain_name => "d74zzrxmpmygb.6hops.net",
41
40
  # :aws_id => "E4U91HCJHGXVC",
42
- # :origin => "my-bucket.s3.amazonaws.com",
41
+ # :s3_origin => {:dns_name=>"bucket-for-konstantin-00.s3.amazonaws.com"},
43
42
  # :cnames => ["x1.my-awesome-site.net", "x1.my-awesome-site.net"]
44
43
  # :comment => "My comments",
45
- # :last_modified_time => Wed Sep 10 17:00:04 UTC 2008 }, ..., {...} ]
44
+ # :last_modified_time => "2008-09-10T17:00:04.000Z" }, ..., {...} ]
46
45
  #
47
46
  # distibution = list.first
48
47
  #
49
48
  # 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 }
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
60
  #
61
61
  # config = acf.get_distribution_config(distibution[:aws_id]) #=>
62
62
  # {:enabled => true,
@@ -64,7 +64,7 @@ module RightAws
64
64
  # :e_tag => "E39OHHU1ON65SI",
65
65
  # :cnames => ["web1.my-awesome-site.net", "web2.my-awesome-site.net"]
66
66
  # :comment => "Woo-Hoo!",
67
- # :origin => "my-bucket.s3.amazonaws.com"}
67
+ # :s3_origin => {:dns_name => "my-bucket.s3.amazonaws.com"}}
68
68
  #
69
69
  # config[:comment] = 'Olah-lah!'
70
70
  # config[:enabled] = false
@@ -76,7 +76,7 @@ module RightAws
76
76
 
77
77
  include RightAwsBaseInterface
78
78
 
79
- API_VERSION = "2008-06-30"
79
+ API_VERSION = "2010-11-01"
80
80
  DEFAULT_HOST = 'cloudfront.amazonaws.com'
81
81
  DEFAULT_PORT = 443
82
82
  DEFAULT_PROTOCOL = 'https'
@@ -93,22 +93,22 @@ module RightAws
93
93
  # Create a new handle to a CloudFront account. All handles share the same per process or per thread
94
94
  # HTTP connection to CloudFront. Each handle is for a specific account. The params have the
95
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'
96
97
  # * <tt>:server</tt>: CloudFront service host, default: DEFAULT_HOST
97
98
  # * <tt>:port</tt>: CloudFront service port, default: DEFAULT_PORT
98
99
  # * <tt>:protocol</tt>: 'http' or 'https', default: DEFAULT_PROTOCOL
99
- # * <tt>:multi_thread</tt>: true=HTTP connection per thread, false=per process
100
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
101
  #
103
102
  # acf = RightAws::AcfInterface.new('1E3GDYEOGFJPIT7XXXXXX','hgTHt68JY07JKUY08ftHYtERkjgtfERn57XXXXXX',
104
- # {:multi_thread => true, :logger => Logger.new('/tmp/x.log')}) #=> #<RightAws::AcfInterface::0xb7b3c30c>
103
+ # {:logger => Logger.new('/tmp/x.log')}) #=> #<RightAws::AcfInterface::0xb7b3c30c>
105
104
  #
106
105
  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 },
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
112
  aws_access_key_id || ENV['AWS_ACCESS_KEY_ID'],
113
113
  aws_secret_access_key || ENV['AWS_SECRET_ACCESS_KEY'],
114
114
  params)
@@ -119,15 +119,22 @@ module RightAws
119
119
  #-----------------------------------------------------------------
120
120
 
121
121
  # Generates request hash for REST API.
122
- def generate_request(method, path, body=nil, headers={}) # :nodoc:
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 = AwsUtils::fix_headers(headers)
123
130
  headers['content-type'] ||= 'text/xml' if body
124
131
  headers['date'] = Time.now.httpdate
125
132
  # Auth
126
133
  signature = AwsUtils::sign(@aws_secret_access_key, headers['date'])
127
134
  headers['Authorization'] = "AWS #{@aws_access_key_id}:#{signature}"
128
135
  # Request
129
- path = "#{@params[:default_service]}/#{API_VERSION}/#{path}"
130
- request = "Net::HTTP::#{method.capitalize}".constantize.new(path)
136
+ path = "#{@params[:service]}#{@params[:api_version]}/#{path}"
137
+ request = "Net::HTTP::#{method.capitalize}".right_constantize.new(path)
131
138
  request.body = body if body
132
139
  # Set request headers
133
140
  headers.each { |key, value| request[key.to_s] = value }
@@ -141,27 +148,13 @@ module RightAws
141
148
  # Sends request to Amazon and parses the response.
142
149
  # Raises AwsError if any banana happened.
143
150
  def request_info(request, parser, &block) # :nodoc:
144
- thread = @params[:multi_thread] ? Thread.current : Thread.main
145
- thread[:acf_connection] ||= Rightscale::HttpConnection.new(:exception => RightAws::AwsError, :logger => @logger)
146
- request_info_impl(thread[:acf_connection], @@bench, request, parser, &block)
151
+ request_info_impl(:acf_connection, @@bench, request, parser, &block)
147
152
  end
148
153
 
149
154
  #-----------------------------------------------------------------
150
155
  # Helpers:
151
156
  #-----------------------------------------------------------------
152
157
 
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
158
  def generate_call_reference # :nodoc:
166
159
  result = Time.now.strftime('%Y%m%d%H%M%S')
167
160
  10.times{ result << rand(10).to_s }
@@ -174,102 +167,287 @@ module RightAws
174
167
  hash
175
168
  end
176
169
 
170
+ def distribution_config_to_xml(config, xml_wrapper='DistributionConfig') # :nodoc:
171
+ cnames = logging = trusted_signers = s3_origin = custom_origin = default_root_object = ''
172
+ # CNAMES
173
+ unless config[:cnames].right_blank?
174
+ Array(config[:cnames]).each { |cname| cnames += " <CNAME>#{cname}</CNAME>\n" }
175
+ end
176
+ # Logging
177
+ unless config[:logging].right_blank?
178
+ logging = " <Logging>\n" +
179
+ " <Bucket>#{config[:logging][:bucket]}</Bucket>\n" +
180
+ " <Prefix>#{config[:logging][:prefix]}</Prefix>\n" +
181
+ " </Logging>\n"
182
+ end
183
+ unless config[:required_protocols].right_blank?
184
+ required_protocols = " <RequiredProtocols>\n" +
185
+ " <Protocol>#{config[:required_protocols]}</Protocol>\n" +
186
+ " </RequiredProtocols>\n"
187
+ else required_protocols = ""
188
+ end
189
+ # Default Root Object
190
+ unless config[:default_root_object].right_blank?
191
+ default_root_object = " <DefaultRootObject>#{config[:default_root_object]}</DefaultRootObject>\n" unless config[:default_root_object].right_blank?
192
+ end
193
+ # Trusted Signers
194
+ unless config[:trusted_signers].right_blank?
195
+ trusted_signers = " <TrustedSigners>\n"
196
+ Array(config[:trusted_signers]).each do |trusted_signer|
197
+ trusted_signers += if trusted_signer.to_s[/self/i]
198
+ " <Self/>\n"
199
+ else
200
+ " <AwsAccountNumber>#{trusted_signer}</AwsAccountNumber>\n"
201
+ end
202
+ end
203
+ trusted_signers += " </TrustedSigners>\n"
204
+ end
205
+ # S3Origin
206
+ unless config[:s3_origin].right_blank?
207
+ origin_access_identity = ''
208
+ # Origin Access Identity
209
+ unless config[:s3_origin][:origin_access_identity].right_blank?
210
+ origin_access_identity = config[:s3_origin][:origin_access_identity]
211
+ unless origin_access_identity[%r{^origin-access-identity}]
212
+ origin_access_identity = "origin-access-identity/cloudfront/#{origin_access_identity}"
213
+ end
214
+ origin_access_identity = " <OriginAccessIdentity>#{origin_access_identity}</OriginAccessIdentity>\n"
215
+ end
216
+ s3_origin = " <S3Origin>\n" +
217
+ " <DNSName>#{config[:s3_origin][:dns_name]}</DNSName>\n" +
218
+ "#{origin_access_identity}" +
219
+ " </S3Origin>\n"
220
+ end
221
+ # Custom Origin
222
+ unless config[:custom_origin].right_blank?
223
+ http_port = https_port = origin_protocol_policy = ''
224
+ http_port = " <HTTPPort>#{config[:custom_origin][:http_port]}</HTTPPort>\n" unless config[:custom_origin][:http_port].right_blank?
225
+ https_port = " <HTTPSPort>#{config[:custom_origin][:https_port]}</HTTPSPort>" unless config[:custom_origin][:https_port].right_blank?
226
+ origin_protocol_policy = " <OriginProtocolPolicy>#{config[:custom_origin][:origin_protocol_policy]}</OriginProtocolPolicy>\n" unless config[:custom_origin][:origin_protocol_policy].right_blank?
227
+ custom_origin = " <CustomOrigin>\n" +
228
+ " <DNSName>#{config[:custom_origin][:dns_name]}</DNSName>\n" +
229
+ "#{http_port}" +
230
+ "#{https_port}" +
231
+ "#{origin_protocol_policy}" +
232
+ " </CustomOrigin>\n"
233
+ end
234
+ # XML
235
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
236
+ "<#{xml_wrapper} xmlns=\"http://#{@params[:server]}/doc/#{API_VERSION}/\">\n" +
237
+ " <CallerReference>#{config[:caller_reference]}</CallerReference>\n" +
238
+ " <Comment>#{AwsUtils::xml_escape(config[:comment].to_s)}</Comment>\n" +
239
+ " <Enabled>#{config[:enabled]}</Enabled>\n" +
240
+ s3_origin +
241
+ custom_origin +
242
+ default_root_object +
243
+ cnames +
244
+ logging +
245
+ required_protocols +
246
+ trusted_signers +
247
+ "</#{xml_wrapper}>"
248
+ end
249
+
177
250
  #-----------------------------------------------------------------
178
251
  # API Calls:
179
252
  #-----------------------------------------------------------------
180
253
 
181
- # List distributions.
254
+ # List all distributions.
182
255
  # Returns an array of distributions or RightAws::AwsError exception.
183
256
  #
184
257
  # 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 }, ..., {...} ]
258
+ # [{:status=>"Deployed",
259
+ # :domain_name=>"dgmde.6os.net",
260
+ # :comment=>"ONE LINE OF COMMENT",
261
+ # :last_modified_time=>"2009-06-16T16:10:02.210Z",
262
+ # :s3_origin=>{:dns_name=>"example.s3.amazonaws.com"},
263
+ # :aws_id=>"12Q05OOMFN7SYL",
264
+ # :enabled=>true}, ... ]
192
265
  #
193
266
  def list_distributions
194
- request_hash = generate_request('GET', 'distribution')
195
- request_cache_or_info :list_distributions, request_hash, AcfDistributionListParser, @@bench
267
+ result = []
268
+ incrementally_list_distributions do |response|
269
+ result += response[:distributions]
270
+ true
271
+ end
272
+ result
273
+ end
274
+
275
+ # Incrementally list distributions.
276
+ #
277
+ # Optional params: +:marker+ and +:max_items+.
278
+ #
279
+ # # get first distribution
280
+ # incrementally_list_distributions(:max_items => 1) #=>
281
+ # {:distributions=>
282
+ # [{:status=>"Deployed",
283
+ # :aws_id=>"E2Q0AOOMFNPSYL",
284
+ # :s3_origin=>{:dns_name=>"example.s3.amazonaws.com"},
285
+ # :domain_name=>"d1s5gmdtmafnre.6hops.net",
286
+ # :comment=>"ONE LINE OF COMMENT",
287
+ # :last_modified_time=>"2008-10-22T19:31:23.000Z",
288
+ # :enabled=>true,
289
+ # :cnames=>[]}],
290
+ # :is_truncated=>true,
291
+ # :max_items=>1,
292
+ # :marker=>"",
293
+ # :next_marker=>"E2Q0AOOMFNPSYL"}
294
+ #
295
+ # # get max 100 distributions (the list will be restricted by a default MaxItems value ==100 )
296
+ # incrementally_list_distributions
297
+ #
298
+ # # list distributions by 10
299
+ # incrementally_list_distributions(:max_items => 10) do |response|
300
+ # puts response.inspect # a list of 10 distributions
301
+ # true # return false if the listing should be broken otherwise use true
302
+ # end
303
+ #
304
+ def incrementally_list_distributions(params={}, &block)
305
+ opts = {}
306
+ opts['MaxItems'] = params[:max_items] if params[:max_items]
307
+ opts['Marker'] = params[:marker] if params[:marker]
308
+ last_response = nil
309
+ loop do
310
+ link = generate_request('GET', 'distribution', opts)
311
+ last_response = request_info(link, AcfDistributionListParser.new(:logger => @logger))
312
+ opts['Marker'] = last_response[:next_marker]
313
+ break unless block && block.call(last_response) && !last_response[:next_marker].right_blank?
314
+ end
315
+ last_response
196
316
  end
197
317
 
198
318
  # Create a new distribution.
199
319
  # Returns the just created distribution or RightAws::AwsError exception.
200
320
  #
201
- # acf.create_distribution('bucket-for-k-dzreyev.s3.amazonaws.com', 'Woo-Hoo!', ['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"}
321
+ # # S3 Origin
212
322
  #
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))
323
+ # config = { :comment => "kd: delete me please",
324
+ # :s3_origin => { :dns_name => "devs-us-east.s3.amazonaws.com",
325
+ # :origin_access_identity => "origin-access-identity/cloudfront/E3JPJZ80ZBX24G"},
326
+ # :enabled => true,
327
+ # :logging => { :prefix => "kd/log/",
328
+ # :bucket => "devs-us-west.s3.amazonaws.com"}}
329
+ # acf.create_distribution(config) #=>
330
+ # { :status=>"InProgress",
331
+ # :enabled=>true,
332
+ # :caller_reference=>"201012071910051044304704",
333
+ # :logging=>{:prefix=>"kd/log/", :bucket=>"devs-us-west.s3.amazonaws.com"},
334
+ # :e_tag=>"ESCTG5WJCFWJK",
335
+ # :location=> "https://cloudfront.amazonaws.com/2010-11-01/distribution/E3KUBANZ7N1B2",
336
+ # :comment=>"kd: delete me please",
337
+ # :domain_name=>"d3stykk6upgs20.cloudfront.net",
338
+ # :aws_id=>"E3KUBANZ7N1B2",
339
+ # :s3_origin=>
340
+ # {:origin_access_identity=>"origin-access-identity/cloudfront/E3JPJZ80ZBX24G",
341
+ # :dns_name=>"devs-us-east.s3.amazonaws.com"},
342
+ # :last_modified_time=>"2010-12-07T16:10:07.087Z",
343
+ # :in_progress_invalidation_batches=>0}
344
+ #
345
+ # # Custom Origin
346
+ #
347
+ # custom_config = { :comment => "kd: delete me please",
348
+ # :custom_origin => { :dns_name => "custom_origin.my-site.com",
349
+ # :http_port => 80,
350
+ # :https_port => 443,
351
+ # :origin_protocol_policy => 'match-viewer' },
352
+ # :enabled => true,
353
+ # :logging => { :prefix => "kd/log/",
354
+ # :bucket => "my-bucket.s3.amazonaws.com"}} #=>
355
+ # { :last_modified_time=>"2010-12-08T14:23:43.522Z",
356
+ # :status=>"InProgress",
357
+ # :custom_origin=>
358
+ # {:http_port=>"80",
359
+ # :https_port=>"443",
360
+ # :origin_protocol_policy=>"match-viewer",
361
+ # :dns_name=>"custom_origin.my-site.com"},
362
+ # :enabled=>true,
363
+ # :caller_reference=>"201012081723428499167245",
364
+ # :in_progress_invalidation_batches=>0,
365
+ # :e_tag=>"E1ZCJ8N5E52KO6",
366
+ # :location=>
367
+ # "https://cloudfront.amazonaws.com/2010-11-01/distribution/EK0AJ4RMNIF2P",
368
+ # :logging=>{:prefix=>"kd/log/", :bucket=>"my-bucket.s3.amazonaws.com"},
369
+ # :domain_name=>"do36k7s2wxklg.cloudfront.net",
370
+ # :comment=>"kd: delete me please",
371
+ # :aws_id=>"EK0AJ4RMNIF2P"}
372
+ #
373
+ def create_distribution(config)
374
+ config[:caller_reference] ||= generate_call_reference
375
+ link = generate_request('POST', 'distribution', {}, distribution_config_to_xml(config))
376
+ merge_headers(request_info(link, AcfDistributionListParser.new(:logger => @logger))[:distributions].first)
233
377
  end
378
+ alias_method :create_distribution_by_config, :create_distribution
234
379
 
235
380
  # Get a distribution's information.
236
381
  # Returns a distribution's information or RightAws::AwsError exception.
237
382
  #
238
383
  # 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 }
384
+ # {:last_modified_time=>"2010-05-19T18:54:38.242Z",
385
+ # :status=>"Deployed",
386
+ # :domain_name=>"dpzl38cuix402.cloudfront.net",
387
+ # :caller_reference=>"201005181943052207677116",
388
+ # :e_tag=>"EJSXFGM5JL8ER",
389
+ # :s3_origin=>
390
+ # {:dns_name=>"bucket-for-konstantin-eu.s3.amazonaws.com",
391
+ # :origin_access_identity=>
392
+ # "origin-access-identity/cloudfront/E3JPJZ80ZBX24G"},
393
+ # :aws_id=>"E5P8HQ3ZAZIXD",
394
+ # :enabled=>false}
395
+ #
396
+ # acf.get_distribution('E2FNSBHNVVF11E') #=>
397
+ # {:e_tag=>"E1Q2DJEPTQOLJD",
398
+ # :status=>"InProgress",
399
+ # :last_modified_time=>"2010-04-17T17:24:25.000Z",
400
+ # :cnames=>["web1.my-awesome-site.net", "web2.my-awesome-site.net"],
401
+ # :aws_id=>"E2FNSBHNVVF11E",
402
+ # :logging=>{:prefix=>"xlog/", :bucket=>"my-bucket.s3.amazonaws.com"},
403
+ # :enabled=>true,
404
+ # :active_trusted_signers=>
405
+ # [{:aws_account_number=>"120288270000",
406
+ # :key_pair_ids=>["APKAJTD5OHNDX0000000", "APKAIK74BJWCL0000000"]},
407
+ # {:aws_account_number=>"self"},
408
+ # {:aws_account_number=>"648772220000"}],
409
+ # :caller_reference=>"201004171154450740700072",
410
+ # :domain_name=>"d1f6lpevremt5m.cloudfront.net",
411
+ # :s3_origin=>
412
+ # {:dns_name=>"bucket-for-konstantin-eu.s3.amazonaws.com",
413
+ # :origin_access_identity=>
414
+ # "origin-access-identity/cloudfront/E3JPJZ80ZBX24G"},
415
+ # :trusted_signers=>["self", "648772220000", "120288270000"]}
249
416
  #
250
417
  def get_distribution(aws_id)
251
- request_hash = generate_request('GET', "distribution/#{aws_id}")
252
- merge_headers(request_info(request_hash, AcfDistributionParser.new))
418
+ link = generate_request('GET', "distribution/#{aws_id}")
419
+ merge_headers(request_info(link, AcfDistributionListParser.new(:logger => @logger))[:distributions].first)
253
420
  end
254
421
 
255
422
  # Get a distribution's configuration.
256
423
  # Returns a distribution's configuration or RightAws::AwsError exception.
257
424
  #
258
425
  # 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"}
426
+ # {:caller_reference=>"201005181943052207677116",
427
+ # :e_tag=>"EJSXFGM5JL8ER",
428
+ # :s3_origin=>
429
+ # {:dns_name=>"bucket-for-konstantin-eu.s3.amazonaws.com",
430
+ # :origin_access_identity=>
431
+ # "origin-access-identity/cloudfront/E3JPJZ80ZBX24G"},
432
+ # :enabled=>false}
433
+ #
434
+ # acf.get_distribution_config('E2FNSBHNVVF11E') #=>
435
+ # {:e_tag=>"E1Q2DJEPTQOLJD",
436
+ # :logging=>{:prefix=>"xlog/", :bucket=>"my-bucket.s3.amazonaws.com"},
437
+ # :enabled=>true,
438
+ # :caller_reference=>"201004171154450740700072",
439
+ # :trusted_signers=>["self", "648772220000", "120288270000"],
440
+ # :s3_origin=>
441
+ # {:dns_name=>"bucket-for-konstantin-eu.s3.amazonaws.com",
442
+ # :origin_access_identity=>
443
+ # "origin-access-identity/cloudfront/E3JPJZ80ZBX24G"}}
265
444
  #
266
445
  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))
446
+ link = generate_request('GET', "distribution/#{aws_id}/config")
447
+ merge_headers(request_info(link, AcfDistributionListParser.new(:logger => @logger))[:distributions].first)
269
448
  end
270
449
 
271
450
  # Set a distribution's configuration
272
- # (the :origin and the :caller_reference cannot be changed).
273
451
  # Returns +true+ on success or RightAws::AwsError exception.
274
452
  #
275
453
  # config = acf.get_distribution_config('E2REJM3VUN5RSI') #=>
@@ -278,31 +456,22 @@ module RightAws
278
456
  # :e_tag => "E39OHHU1ON65SI",
279
457
  # :cnames => ["web1.my-awesome-site.net", "web2.my-awesome-site.net"]
280
458
  # :comment => "Woo-Hoo!",
281
- # :origin => "my-bucket.s3.amazonaws.com"}
282
- # config[:comment] = 'Olah-lah!'
283
- # config[:enabled] = false
459
+ # :s3_origin => { :dns_name => "my-bucket.s3.amazonaws.com"}}
460
+ #
461
+ # config[:comment] = 'Olah-lah!'
462
+ # config[:enabled] = false
463
+ # config[:s3_origin][:origin_access_identity] = "origin-access-identity/cloudfront/E3JPJZ80ZBX24G"
464
+ # # or just
465
+ # # config[:s3_origin][:origin_access_identity] = "E3JPJZ80ZBX24G"
466
+ # config[:trusted_signers] = ['self', '648772220000', '120288270000']
467
+ # config[:logging] = { :bucket => 'my-bucket.s3.amazonaws.com', :prefix => 'xlog/' }
468
+ #
284
469
  # acf.set_distribution_config('E2REJM3VUN5RSI', config) #=> true
285
470
  #
286
471
  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)
472
+ link = generate_request('PUT', "distribution/#{aws_id}/config", {}, distribution_config_to_xml(config),
473
+ 'If-Match' => config[:e_tag])
474
+ request_info(link, RightHttp2xxParser.new(:logger => @logger))
306
475
  end
307
476
 
308
477
  # Delete a distribution. The enabled distribution cannot be deleted.
@@ -311,9 +480,9 @@ module RightAws
311
480
  # acf.delete_distribution('E2REJM3VUN5RSI', 'E39OHHU1ON65SI') #=> true
312
481
  #
313
482
  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)
483
+ link = generate_request('DELETE', "distribution/#{aws_id}", {}, nil,
484
+ 'If-Match' => e_tag)
485
+ request_info(link, RightHttp2xxParser.new(:logger => @logger))
317
486
  end
318
487
 
319
488
  #-----------------------------------------------------------------
@@ -322,58 +491,60 @@ module RightAws
322
491
 
323
492
  class AcfDistributionListParser < RightAWSParser # :nodoc:
324
493
  def reset
325
- @result = []
494
+ @result = { :distributions => [] }
326
495
  end
327
496
  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 < RightAWSParser # :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
497
+ case full_tag_name
498
+ when %r{/Signer$}
499
+ @active_signer = {}
500
+ when %r{(Streaming)?DistributionSummary$},
501
+ %r{^(Streaming)?Distribution$},
502
+ %r{^(Streaming)?DistributionConfig$}
503
+ @distribution = { }
504
+ when %r{/S3Origin$} then @distribution[:s3_origin] = {}
505
+ when %r{/CustomOrigin$} then @distribution[:custom_origin] = {}
359
506
  end
360
507
  end
361
- end
362
-
363
- class AcfDistributionConfigParser < RightAWSParser # :nodoc:
364
- def reset
365
- @result = { :cnames => [] }
366
- end
367
508
  def tagend(name)
368
509
  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
510
+ when 'Marker' then @result[:marker] = @text
511
+ when 'NextMarker' then @result[:next_marker] = @text
512
+ when 'MaxItems' then @result[:max_items] = @text.to_i
513
+ when 'IsTruncated' then @result[:is_truncated] = (@text == 'true')
514
+ when 'Id' then @distribution[:aws_id] = @text
515
+ when 'Status' then @distribution[:status] = @text
516
+ when 'LastModifiedTime' then @distribution[:last_modified_time] = @text
517
+ when 'DomainName' then @distribution[:domain_name] = @text
518
+ when 'Comment' then @distribution[:comment] = AwsUtils::xml_unescape(@text)
519
+ when 'CallerReference' then @distribution[:caller_reference] = @text
520
+ when 'CNAME' then (@distribution[:cnames] ||= []) << @text
521
+ when 'Enabled' then @distribution[:enabled] = (@text == 'true')
522
+ when 'Bucket' then (@distribution[:logging] ||= {})[:bucket] = @text
523
+ when 'Prefix' then (@distribution[:logging] ||= {})[:prefix] = @text
524
+ when 'Protocol' then (@distribution[:required_protocols] ||= {})[:protocol] = @text
525
+ when 'InProgressInvalidationBatches' then @distribution[:in_progress_invalidation_batches] = @text.to_i
526
+ when 'DefaultRootObject' then @distribution[:default_root_object] = @text
527
+ else
528
+ case full_tag_name
529
+ when %r{/S3Origin/DNSName$} then @distribution[:s3_origin][:dns_name] = @text
530
+ when %r{/S3Origin/OriginAccessIdentity$} then @distribution[:s3_origin][:origin_access_identity] = @text
531
+ when %r{/CustomOrigin/DNSName$} then @distribution[:custom_origin][:dns_name] = @text
532
+ when %r{/CustomOrigin/HTTPPort} then @distribution[:custom_origin][:http_port] = @text
533
+ when %r{/CustomOrigin/HTTPSPort$} then @distribution[:custom_origin][:https_port] = @text
534
+ when %r{/CustomOrigin/OriginProtocolPolicy$} then @distribution[:custom_origin][:origin_protocol_policy] = @text
535
+ when %r{/TrustedSigners/Self$} then (@distribution[:trusted_signers] ||= []) << 'self'
536
+ when %r{/TrustedSigners/AwsAccountNumber$} then (@distribution[:trusted_signers] ||= []) << @text
537
+ when %r{/Signer/Self$} then @active_signer[:aws_account_number] = 'self'
538
+ when %r{/Signer/AwsAccountNumber$} then @active_signer[:aws_account_number] = @text
539
+ when %r{/Signer/KeyPairId$} then (@active_signer[:key_pair_ids] ||= []) << @text
540
+ when %r{/Signer$} then (@distribution[:active_trusted_signers] ||= []) << @active_signer
541
+ when %r{(Streaming)?DistributionSummary$},
542
+ %r{^(Streaming)?Distribution$},
543
+ %r{^(Streaming)?DistributionConfig$}
544
+ @result[:distributions] << @distribution
545
+ end
374
546
  end
375
547
  end
376
548
  end
377
-
378
549
  end
379
550
  end