aboisvert_aws 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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,86 @@
1
+ #
2
+ # Copyright (c) 2007-2011 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+
24
+ require 'benchmark'
25
+ require 'net/https'
26
+ require 'uri'
27
+ require 'time'
28
+ require "cgi"
29
+ require "base64"
30
+ require "rexml/document"
31
+ require "openssl"
32
+ require "digest/sha1"
33
+
34
+ require 'rubygems'
35
+ require 'right_http_connection'
36
+
37
+ $:.unshift(File.dirname(__FILE__))
38
+ require 'awsbase/version'
39
+ require 'awsbase/support'
40
+ require 'awsbase/benchmark_fix'
41
+ require 'awsbase/right_awsbase'
42
+ require 'ec2/right_ec2'
43
+ require 'ec2/right_ec2_images'
44
+ require 'ec2/right_ec2_instances'
45
+ require 'ec2/right_ec2_security_groups'
46
+ require 'ec2/right_ec2_spot_instances'
47
+ require 'ec2/right_ec2_ebs'
48
+ require 'ec2/right_ec2_reserved_instances'
49
+ require 'ec2/right_ec2_vpc'
50
+ require 'ec2/right_ec2_vpc2'
51
+ require 'ec2/right_ec2_monitoring'
52
+ require 'ec2/right_ec2_placement_groups'
53
+ require 'ec2/right_ec2_windows_mobility'
54
+ require 'ec2/right_ec2_tags'
55
+ require 'elb/right_elb_interface'
56
+ require 'emr/right_emr_interface'
57
+ require 'acw/right_acw_interface'
58
+ require 'as/right_as_interface'
59
+ require 's3/right_s3_interface'
60
+ require 's3/right_s3'
61
+ require 'sqs/right_sqs_interface'
62
+ require 'sqs/right_sqs'
63
+ require 'sqs/right_sqs_gen2_interface'
64
+ require 'sqs/right_sqs_gen2'
65
+ require 'sdb/right_sdb_interface'
66
+ require 'acf/right_acf_interface'
67
+ require 'acf/right_acf_streaming_interface'
68
+ require 'acf/right_acf_origin_access_identities'
69
+ require 'acf/right_acf_invalidations'
70
+ require 'rds/right_rds_interface'
71
+ require 'iam/right_iam_interface'
72
+ require 'iam/right_iam_groups'
73
+ require 'iam/right_iam_users'
74
+ require 'iam/right_iam_access_keys'
75
+ require 'iam/right_iam_mfa_devices'
76
+ require 'route_53/right_route_53_interface'
77
+ require 'sns/right_sns_interface'
78
+
79
+ #-
80
+
81
+ # We also want everything available in the Rightscale namespace for backward
82
+ # compatibility reasons.
83
+ module Rightscale #:nodoc:
84
+ include RightAws
85
+ extend RightAws
86
+ end
@@ -0,0 +1,640 @@
1
+ # Copyright (c) 2007-2011 RightScale Inc
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+ #
22
+
23
+ module RightAws
24
+
25
+ # = RightAws::Route53Interface -- Amazon Route 53 web service interface.
26
+ #
27
+ # The RightAws::Route53Interface class provides a complete interface to Amazon Route 53: a web
28
+ # service that enables you to manage your DNS service.
29
+ #
30
+ # For explanations of the semantics of each call, please refer to Amazon's documentation at
31
+ # http://aws.amazon.com/documentation/route53/
32
+ #
33
+ # Examples:
34
+ #
35
+ # # Create Route53 handler
36
+ # r53 = RightAws::Route53Interface.new(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
37
+ #
38
+ # #------------------------
39
+ # # Create Hosted Zone
40
+ # #------------------------
41
+ #
42
+ # hosted_zone_config = {
43
+ # :name => 'my-awesome-site.com.',
44
+ # :config => {
45
+ # :comment => 'My test site!'
46
+ # }
47
+ # }
48
+ # r53.create_hosted_zone(hosted_zone_config) #=>
49
+ # {:name_servers=>
50
+ # ["ns-1115.awsdns-11.org",
51
+ # "ns-696.awsdns-23.net",
52
+ # "ns-1963.awsdns-53.co.uk",
53
+ # "ns-362.awsdns-45.com"],
54
+ # :aws_id=>"/hostedzone/Z1K6NCF0EB26FB",
55
+ # :caller_reference=>"1295424990-710392-gqMuw-KcY8F-LFlrB-SQhp9",
56
+ # :config=>{:comment=>"My test site!"},
57
+ # :change_info=>
58
+ # {:status=>"PENDING",
59
+ # :aws_id=>"/change/C23QGMT8XTCAJY",
60
+ # :submitted_at=>"2011-01-19T08:16:31.046Z"},
61
+ # :name=>"my-awesome-site.com."}
62
+ #
63
+ # # List Hosted Zones
64
+ # r53.list_hosted_zones #=> []
65
+ # [{:aws_id=>"/hostedzone/Z1K6NCF0EB26FB",
66
+ # :caller_reference=>"1295424990-710392-gqMuw-KcY8F-LFlrB-SQhp9",
67
+ # :config=>{:comment=>"My test site!"},
68
+ # :name=>"my-awesome-site.com."}]
69
+ #
70
+ # #--------------------------------
71
+ # # Manage DNS Records and Changes
72
+ # #--------------------------------
73
+ #
74
+ # # Create DNS Records
75
+ # resource_record_sets = [ { :name => 'www1.my-awesome-site.com.',
76
+ # :type => 'NS',
77
+ # :ttl => 600,
78
+ # :resource_records => 'www.mysite.com' },
79
+ # { :name => 'www2.my-awesome-site.com.',
80
+ # :type => 'A',
81
+ # :ttl => 600,
82
+ # :resource_records => ['10.0.0.1'] } ]
83
+ # r53.create_resource_record_sets("/hostedzone/Z1K6NCF0EB26FB", resource_record_sets, 'my first set of records') #=>
84
+ # { :status=>"PENDING",
85
+ # :aws_id=>"/change/C2C6IGNRTKA0AY",
86
+ # :submitted_at=>"2011-01-19T08:29:26.160Z" }
87
+ #
88
+ # # Delete DNS records
89
+ # r53.delete_resource_record_sets("/hostedzone/Z1K6NCF0EB26FB", resource_record_sets, 'I dont need them any more') #=>
90
+ # { :status=>"PENDING",
91
+ # :aws_id=>"/change/C1CYJ10EZBFLO7",
92
+ # :submitted_at=>"2011-01-19T08:26:41.220Z" }
93
+ #
94
+ # # Create or delete DNS records (:action key must be provided):
95
+ # resource_record_sets = [ { :action => :create,
96
+ # :name => 'www1.my-awesome-site.com.',
97
+ # :type => 'NS',
98
+ # :ttl => 600,
99
+ # :resource_records => 'www.mysite.com' },
100
+ # { :action => :delete,
101
+ # :name => 'www2.my-awesome-site.com.',
102
+ # :type => 'A',
103
+ # :ttl => 600,
104
+ # :resource_records => ['10.0.0.1'] } ]
105
+ # r53.change_resource_record_sets("/hostedzone/Z1K6NCF0EB26FB", resource_record_sets, 'do change records')
106
+ # { :status=>"PENDING",
107
+ # :aws_id=>"/change/C2PWXVECN794LK",
108
+ # :submitted_at=>"2011-01-19T08:31:33.301Z" }
109
+ #
110
+ # # List DNS Records
111
+ # r53.list_resource_record_sets("/hostedzone/Z1K6NCF0EB26FB") #=>
112
+ # [{:type=>"NS",
113
+ # :ttl=>172800,
114
+ # :resource_records=>
115
+ # ["ns-1115.awsdns-11.org.",
116
+ # "ns-696.awsdns-23.net.",
117
+ # "ns-1963.awsdns-53.co.uk.",
118
+ # "ns-362.awsdns-45.com."],
119
+ # :name=>"my-awesome-site.com."},
120
+ # {:type=>"SOA",
121
+ # :ttl=>900,
122
+ # :resource_records=>
123
+ # ["ns-1115.awsdns-11.org. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 86400"],
124
+ # :name=>"my-awesome-site.com."},
125
+ # {:type=>"NS",
126
+ # :ttl=>600,
127
+ # :resource_records=>["www.mysite.com"],
128
+ # :name=>"www1.my-awesome-site.com."}]
129
+ #
130
+ # # Get Change info
131
+ # r53.get_change("/change/C2C6IGNRTKA0AY")
132
+ # {:status=>"INSYNC",
133
+ # :aws_id=>"/change/C2C6IGNRTKA0AY",
134
+ # :submitted_at=>"2011-01-19T08:29:26.160Z"}
135
+ #
136
+ # #------------------------
137
+ # # Delete Hosted Zone
138
+ # #------------------------
139
+ #
140
+ # # Get a list of DNS records I have created (the first 2 records were added by Amazon and cannot be deleted)
141
+ # resource_record_sets = r53.list_resource_record_sets("/hostedzone/Z1K6NCF0EB26FB")
142
+ # resource_record_sets.shift
143
+ # resource_record_sets.shift
144
+ #
145
+ # # Delete them all
146
+ # delete_resource_record_sets("/hostedzone/Z1K6NCF0EB26FB", resource_record_sets, 'kill all records I have created') #=>
147
+ # { :status=>"PENDING",
148
+ # :aws_id=>"/change/C6NCO8Z50MHXV",
149
+ # :submitted_at=>"2011-01-19T08:46:37.307Z" }
150
+ #
151
+ # # Delete Hosted Zone
152
+ # r53.delete_hosted_zone("/hostedzone/Z1K6NCF0EB26FB") #=>
153
+ # { :status=>"PENDING",
154
+ # :aws_id=>"/change/C3OJ31D4V5P2LU",
155
+ # :submitted_at=>"2011-01-19T08:46:37.530Z" }
156
+ #
157
+ class Route53Interface < RightAwsBase
158
+
159
+ include RightAwsBaseInterface
160
+
161
+ API_VERSION = "2011-05-05"
162
+ DEFAULT_HOST = "route53.amazonaws.com"
163
+ DEFAULT_PATH = '/'
164
+ DEFAULT_PROTOCOL = 'https'
165
+ DEFAULT_PORT = 443
166
+
167
+ @@bench = AwsBenchmarkingBlock.new
168
+ def self.bench_xml
169
+ @@bench.xml
170
+ end
171
+ def self.bench_service
172
+ @@bench.service
173
+ end
174
+
175
+ # Create a new handle to an Route53 account. All handles share the same per process or per thread
176
+ # HTTP connection to Amazon Route53. Each handle is for a specific account. The params have the
177
+ # following options:
178
+ # * <tt>:endpoint_url</tt> a fully qualified url to Amazon API endpoint (this overwrites: :server, :port, :service, :protocol).
179
+ # * <tt>:server</tt>: Route53 service host, default: DEFAULT_HOST
180
+ # * <tt>:port</tt>: Route53 service port, default: DEFAULT_PORT
181
+ # * <tt>:protocol</tt>: 'http' or 'https', default: DEFAULT_PROTOCOL
182
+ # * <tt>:logger</tt>: for log messages, default: RAILS_DEFAULT_LOGGER else STDOUT
183
+ # * <tt>:signature_version</tt>: The signature version : '0','1' or '2'(default)
184
+ #
185
+ def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
186
+ init({ :name => 'ROUTE_53',
187
+ :default_host => ENV['ROUTE_53_URL'] ? URI.parse(ENV['ROUTE_53_URL']).host : DEFAULT_HOST,
188
+ :default_port => ENV['ROUTE_53_URL'] ? URI.parse(ENV['ROUTE_53_URL']).port : DEFAULT_PORT,
189
+ :default_service => ENV['ROUTE_53_URL'] ? URI.parse(ENV['ROUTE_53_URL']).path : DEFAULT_PATH,
190
+ :default_protocol => ENV['ROUTE_53_URL'] ? URI.parse(ENV['ROUTE_53_URL']).scheme : DEFAULT_PROTOCOL,
191
+ :default_api_version => ENV['ROUTE_53_API_VERSION'] || API_VERSION },
192
+ aws_access_key_id || ENV['AWS_ACCESS_KEY_ID'] ,
193
+ aws_secret_access_key|| ENV['AWS_SECRET_ACCESS_KEY'],
194
+ params)
195
+ end
196
+
197
+ #-----------------------------------------------------------------
198
+ # Requests
199
+ #-----------------------------------------------------------------
200
+
201
+ # Generates request hash for REST API.
202
+ def generate_request(method, path, params={}, body=nil, headers={}) # :nodoc:
203
+ # Params
204
+ params.delete_if{ |key, val| val.right_blank? }
205
+ unless params.right_blank?
206
+ path += "?" + params.to_a.collect{ |key,val| "#{AwsUtils::amz_escape(key)}=#{AwsUtils::amz_escape(val.to_s)}" }.join("&")
207
+ end
208
+ # Headers
209
+ headers['content-type'] ||= 'text/xml' if body
210
+ headers['date'] = Time.now.httpdate
211
+ # Auth
212
+ signature = AwsUtils::sign(@aws_secret_access_key, headers['date'])
213
+ headers['X-Amzn-Authorization'] = "AWS3-HTTPS AWSAccessKeyId=#{@aws_access_key_id},Algorithm=HmacSHA1,Signature=#{signature}"
214
+ # Request
215
+ path = "#{@params[:service]}#{@params[:api_version]}/#{path}"
216
+ request = "Net::HTTP::#{method.capitalize}".right_constantize.new(path)
217
+ request.body = body if body
218
+ # Set request headers
219
+ headers.each { |key, value| request[key.to_s] = value }
220
+ # prepare output hash
221
+ { :request => request,
222
+ :server => @params[:server],
223
+ :port => @params[:port],
224
+ :protocol => @params[:protocol] }
225
+ end
226
+
227
+ # Sends request to Amazon and parses the response.
228
+ # Raises AwsError if any banana happened.
229
+ def request_info(request, parser, &block) # :nodoc:
230
+ request_info_impl(:acf_connection, @@bench, request, parser, &block)
231
+ end
232
+
233
+ def incrementally_list_hosted_zones(path, parser, params={}, &block) # :nodoc:
234
+ opts = {}
235
+ opts['MaxItems'] = params[:max_items] if params[:max_items]
236
+ opts['Marker'] = params[:marker] if params[:marker]
237
+ last_response = nil
238
+ loop do
239
+ link = generate_request('GET', path, opts)
240
+ last_response = request_info(link, parser.new(:logger => @logger))
241
+ opts['Marker'] = last_response[:next_marker]
242
+ break unless block && block.call(last_response) && !last_response[:next_marker].right_blank?
243
+ end
244
+ last_response
245
+ end
246
+
247
+ def incrementally_list_resource_records(path, parser, params={}, &block) # :nodoc:
248
+ opts = {}
249
+ opts[:maxitems] = params.delete(:max_items) if params[:max_items]
250
+ last_response = nil
251
+ loop do
252
+ link = generate_request('GET', path, opts)
253
+ last_response = request_info(link, parser.new(:logger => @logger))
254
+ opts[:maxitems] = last_response[:max_items]
255
+ opts[:name] = last_response[:next_record_name]
256
+ opts[:type] = last_response[:next_record_type]
257
+ break unless block && block.call(last_response) && last_response[:is_truncated]
258
+ end
259
+ last_response
260
+ end
261
+
262
+ def expand_hosted_zone_id(aws_id) # :nodoc:
263
+ aws_id[%r{^/hostedzone/}] ? aws_id : "/hostedzone/#{aws_id}"
264
+ end
265
+
266
+ def expand_change_id(aws_id) # :nodoc:
267
+ aws_id[%r{^/change/}] ? aws_id : "/change/#{aws_id}"
268
+ end
269
+
270
+ def hosted_zone_config_to_xml(config) # :nodoc:
271
+ config[:caller_reference] ||= AwsUtils::generate_call_reference
272
+ hosted_zone_config = ''
273
+ unless config[:config].right_blank?
274
+ hosted_zone_config = " <HostedZoneConfig>\n" +
275
+ " <Comment>#{AwsUtils::xml_escape config[:config][:comment]}</Comment>\n" +
276
+ " </HostedZoneConfig>\n"
277
+ end
278
+ # XML
279
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
280
+ "<CreateHostedZoneRequest xmlns=\"https://#{@params[:server]}/doc/#{API_VERSION}/\">\n" +
281
+ " <Name>#{config[:name]}</Name>\n" +
282
+ " <CallerReference>#{config[:caller_reference]}</CallerReference>\n" +
283
+ hosted_zone_config +
284
+ "</CreateHostedZoneRequest>\n"
285
+ end
286
+
287
+ def resource_record_sets_to_xml(resource_record_changes, comment) # :nodoc:
288
+ # Comment
289
+ xml_comment = comment.right_blank? ? '' : " <Comment>#{AwsUtils::xml_escape(comment)}</Comment>\n"
290
+ # Changes
291
+ xml_changes = ''
292
+ resource_record_changes.each do |change|
293
+ xml_resource_records = Array(change[:resource_records]).map{|record| " <ResourceRecord><Value>#{AwsUtils::xml_escape(record)}</Value></ResourceRecord>\n" }.join('')
294
+ xml_changes += " <Change>\n" +
295
+ " <Action>#{AwsUtils::xml_escape(change[:action].to_s.upcase)}</Action>\n" +
296
+ " <ResourceRecordSet>\n" +
297
+ " <Name>#{AwsUtils::xml_escape(change[:name])}</Name>\n" +
298
+ " <Type>#{AwsUtils::xml_escape(change[:type].to_s.upcase)}</Type>\n"
299
+ if change[:alias_target]
300
+ alias_target = change[:alias_target]
301
+ xml_changes +=
302
+ " <AliasTarget>\n" +
303
+ " <HostedZoneId>#{AwsUtils::xml_escape(alias_target[:hosted_zone_id].to_s)}</HostedZoneId>\n" +
304
+ " <DNSName>#{AwsUtils::xml_escape(alias_target[:dns_name].to_s)}</DNSName>\n" +
305
+ " </AliasTarget>\n"
306
+ else
307
+ xml_changes +=
308
+ " <TTL>#{AwsUtils::xml_escape(change[:ttl].to_s)}</TTL>\n" +
309
+ " <ResourceRecords>\n" +
310
+ xml_resource_records +
311
+ " </ResourceRecords>\n"
312
+ end
313
+ xml_changes +=
314
+ " </ResourceRecordSet>\n" +
315
+ " </Change>\n"
316
+ end
317
+ # XML
318
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
319
+ "<ChangeResourceRecordSetsRequest xmlns=\"https://#{@params[:server]}/doc/#{API_VERSION}/\">\n" +
320
+ " <ChangeBatch>\n" +
321
+ xml_comment +
322
+ " <Changes>\n" +
323
+ xml_changes +
324
+ " </Changes>\n" +
325
+ " </ChangeBatch>\n" +
326
+ "</ChangeResourceRecordSetsRequest>\n"
327
+ end
328
+
329
+
330
+ #-----------------------------------------------------------------
331
+ # Hosted Zones
332
+ #-----------------------------------------------------------------
333
+
334
+ # List your hosted zones.
335
+ #
336
+ # r53.list_hosted_zones #=>
337
+ # [{:config=>{:comment=>"KD1, description"},
338
+ # :aws_id=>"/hostedzone/Z2P714ENJN23PN",
339
+ # :caller_reference=>"1295424990-710392-gqMuw-KcY8F-LFlrB-SQhp9",
340
+ # :name=>"patch-island.com."},
341
+ # {:config=>{:comment=>"My awesome site!"},
342
+ # :aws_id=>"/hostedzone/ZWEC7PPVACGQ4",
343
+ # :caller_reference=>"1295422234-657482-hfkeo-JFKid-Ldfle-Sdrty",
344
+ # :name=>"mysite.patch-island.com."}, ...]
345
+ #
346
+ # PS: http://docs.amazonwebservices.com/Route53/latest/APIReference/API_ListHostedZones.html
347
+ #
348
+ def list_hosted_zones
349
+ result = []
350
+ incrementally_list_hosted_zones('hostedzone', ListHostedZonesParser) do |response|
351
+ result += response[:items]
352
+ true
353
+ end
354
+ result
355
+ end
356
+
357
+ # Create new hosted zone
358
+ #
359
+ # config = {
360
+ # :name => 'mysite.patch-island.com.',
361
+ # :config => {
362
+ # :comment => 'My awesome site!'
363
+ # }
364
+ # }
365
+ # r53.create_hosted_zone(config) #=>
366
+ # {:config=>{:comment=>"My awesome site!"},
367
+ # :change_info=>
368
+ # {:status=>"PENDING",
369
+ # :aws_id=>"/change/C2NOTVGL7IOFFF",
370
+ # :submitted_at=>"2011-01-18T15:34:18.086Z"},
371
+ # :aws_id=>"/hostedzone/ZWEC7PPVACGQ4",
372
+ # :caller_reference=>"1295365357-227168-NfZ4P-VGHWi-Yq0p7-nuN6q",
373
+ # :name_servers=>
374
+ # ["ns-794.awsdns-35.net",
375
+ # "ns-459.awsdns-57.com",
376
+ # "ns-1537.awsdns-00.co.uk",
377
+ # "ns-1165.awsdns-17.org"],
378
+ # :name=>"mysite.patch-island.com."}
379
+ #
380
+ # PS: http://docs.amazonwebservices.com/Route53/latest/APIReference/index.html?API_CreateHostedZone.html
381
+ #
382
+ def create_hosted_zone(config)
383
+ config[:caller_reference] ||= AwsUtils::generate_unique_token
384
+ link = generate_request('POST', 'hostedzone', {}, hosted_zone_config_to_xml(config))
385
+ request_info(link, GetHostedZoneParser.new(:logger => @logger))
386
+ end
387
+
388
+ # Get your hosted zone.
389
+ #
390
+ # r53.get_hosted_zone("ZWEC7PPVACGQ4") #=>
391
+ # {:config=>{:comment=>"My awesome site!"},
392
+ # :aws_id=>"/hostedzone/ZWEC7PPVACGQ4",
393
+ # :caller_reference=>"1295422234-657482-hfkeo-JFKid-Ldfle-Sdrty",
394
+ # :name_servers=>
395
+ # ["ns-794.awsdns-35.net",
396
+ # "ns-459.awsdns-57.com",
397
+ # "ns-1537.awsdns-00.co.uk",
398
+ # "ns-1165.awsdns-17.org"],
399
+ # :name=>"mysite.patch-island.com."}
400
+ #
401
+ # PS: http://docs.amazonwebservices.com/Route53/latest/APIReference/API_GetHostedZone.html
402
+ #
403
+ def get_hosted_zone(hosted_zone_aws_id)
404
+ link = generate_request('GET', expand_hosted_zone_id(hosted_zone_aws_id))
405
+ request_info(link, GetHostedZoneParser.new(:logger => @logger))
406
+ end
407
+
408
+ # Delete hosted zone.
409
+ #
410
+ # r53.delete_hosted_zone("/hostedzone/Z2P714ENJN23PN") #=>
411
+ # {:status=>"PENDING",
412
+ # :submitted_at=>"2011-01-18T15:45:45.060Z",
413
+ # :aws_id=>"/change/C1PN1SDWZKPTAC"}
414
+ #
415
+ # PS: http://docs.amazonwebservices.com/Route53/latest/APIReference/API_DeleteHostedZone.html
416
+ #
417
+ def delete_hosted_zone(hosted_zone_aws_id)
418
+ link = generate_request('DELETE', expand_hosted_zone_id(hosted_zone_aws_id))
419
+ request_info(link, GetChangeParser.new(:logger => @logger))
420
+ end
421
+
422
+ #-----------------------------------------------------------------
423
+ # Resource Records Set
424
+ #-----------------------------------------------------------------
425
+
426
+ # List your resource record sets.
427
+ # Options: :type, :name, :max_items
428
+ #
429
+ # r53.list_resource_record_sets("/hostedzone/ZWEC7PPVACGQ4") #=>
430
+ # [{:type=>"NS",
431
+ # :ttl=>172800,
432
+ # :name=>"mysite.patch-island.com.",
433
+ # :resource_records=>
434
+ # ["ns-459.awsdns-57.com.",
435
+ # "ns-794.awsdns-35.net.",
436
+ # "ns-1165.awsdns-17.org.",
437
+ # "ns-1537.awsdns-00.co.uk."]},
438
+ # {:type=>"SOA",
439
+ # :ttl=>900,
440
+ # :name=>"mysite.patch-island.com.",
441
+ # :resource_records=>
442
+ # ["ns-794.awsdns-35.net. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 86400"]},
443
+ # {:type=>"NS",
444
+ # :ttl=>600,
445
+ # :resource_records=>["xxx.mysite.com"],
446
+ # :name=>"m1.mysite.patch-island.com."}]
447
+ #
448
+ # PS: http://docs.amazonwebservices.com/Route53/latest/APIReference/API_ListResourceRecordSets.html
449
+ #
450
+ def list_resource_record_sets(hosted_zone_aws_id, options={})
451
+ options = options.dup
452
+ result = []
453
+ incrementally_list_resource_records("#{expand_hosted_zone_id(hosted_zone_aws_id)}/rrset", ListResourceRecordSetsParser, options) do |response|
454
+ result += response[:items]
455
+ true
456
+ end
457
+ result
458
+ end
459
+
460
+ # Create or delete DNS records.
461
+ #
462
+ # resource_record_sets = [{ :action => :create,
463
+ # :name => 'm3.mysite.patch-island.com',
464
+ # :type => 'NS',
465
+ # :ttl => 600,
466
+ # :resource_records => 'xxx.mysite.com' },
467
+ # { :action => :delete,
468
+ # :name => 'm2.mysite.patch-island.com',
469
+ # :type => 'A',
470
+ # :ttl => 600,
471
+ # :resource_records => ['10.0.0.1'] }]
472
+ # r53.change_resource_record_sets("/hostedzone/Z1K6NCF0EB26FB", resource_record_sets, 'KD: Comment#1') #=>
473
+ # {:status=>"PENDING",
474
+ # :submitted_at=>"2011-01-18T20:21:56.828Z",
475
+ # :aws_id=>"/change/C394PNLM1B2P08"}
476
+ #
477
+ # PS: resource_record_sets must have an :action key set (== :create or :delete)
478
+ # PPS: http://docs.amazonwebservices.com/Route53/latest/APIReference/API_ChangeResourceRecordSets.html
479
+ #
480
+ def change_resource_record_sets(hosted_zone_aws_id, resource_record_sets, comment = '')
481
+ link = generate_request('POST', "#{expand_hosted_zone_id(hosted_zone_aws_id)}/rrset", {}, resource_record_sets_to_xml(resource_record_sets, comment))
482
+ request_info(link, GetChangeParser.new(:logger => @logger))
483
+ end
484
+
485
+ # Create DNS records.
486
+ #
487
+ # resource_record_sets = [{ :name => 'm3.mysite.patch-island.com',
488
+ # :type => 'NS',
489
+ # :ttl => 600,
490
+ # :resource_records => 'xxx.mysite.com' },
491
+ # { :name => 'm2.mysite.patch-island.com',
492
+ # :type => 'A',
493
+ # :ttl => 600,
494
+ # :resource_records => ['10.0.0.1'] }]
495
+ # r53.create_resource_record_sets("/hostedzone/Z1K6NCF0EB26FB", resource_record_sets, 'KD: Comment#1') #=>
496
+ # {:status=>"PENDING",
497
+ # :submitted_at=>"2011-01-18T20:21:56.828Z",
498
+ # :aws_id=>"/change/C394PNLM1B2P08"}
499
+ #
500
+ # PS: http://docs.amazonwebservices.com/Route53/latest/APIReference/API_ChangeResourceRecordSets.html
501
+ #
502
+ def create_resource_record_sets(hosted_zone_aws_id, resource_record_sets, comment = '')
503
+ resource_record_sets.each{|rrs| rrs[:action] = :create}
504
+ change_resource_record_sets(hosted_zone_aws_id, resource_record_sets, comment)
505
+ end
506
+
507
+ # Delete DNS records.
508
+ #
509
+ # resource_record_sets = [{ :name => 'm3.mysite.patch-island.com',
510
+ # :type => 'NS',
511
+ # :ttl => 600,
512
+ # :resource_records => 'xxx.mysite.com' },
513
+ # { :name => 'm2.mysite.patch-island.com',
514
+ # :type => 'A',
515
+ # :ttl => 600,
516
+ # :resource_records => ['10.0.0.1'] }]
517
+ # r53.create_resource_record_sets("/hostedzone/Z1K6NCF0EB26FB", resource_record_sets, 'KD: Comment#1') #=>
518
+ # {:status=>"PENDING",
519
+ # :submitted_at=>"2011-01-18T20:21:56.828Z",
520
+ # :aws_id=>"/change/C394PNLM1B2P08"}
521
+ #
522
+ # PS: http://docs.amazonwebservices.com/Route53/latest/APIReference/API_ChangeResourceRecordSets.html
523
+ #
524
+ def delete_resource_record_sets(hosted_zone_aws_id, resource_record_sets, comment = '')
525
+ resource_record_sets.each{|rrs| rrs[:action] = :delete}
526
+ change_resource_record_sets(hosted_zone_aws_id, resource_record_sets, comment)
527
+ end
528
+
529
+
530
+ # Get the current state of a change request.
531
+ #
532
+ # r53.get_change("/change/C1PN1SDWZKPTAC") #=>
533
+ # {:status=>"INSYNC",
534
+ # :aws_id=>"/change/C1PN1SDWZKPTAC",
535
+ # :submitted_at=>"2011-01-18T15:45:45.060Z"}
536
+ #
537
+ # PS: http://docs.amazonwebservices.com/Route53/latest/APIReference/API_GetChange.html
538
+ #
539
+ def get_change(change_aws_id)
540
+ link = generate_request('GET', expand_change_id(change_aws_id))
541
+ request_info(link, GetChangeParser.new(:logger => @logger))
542
+ end
543
+
544
+ #-----------------------------------------------------------------
545
+ # Hosted Zones
546
+ #-----------------------------------------------------------------
547
+
548
+ class ListHostedZonesParser < RightAWSParser # :nodoc:
549
+ def reset
550
+ @result = { :items => [] }
551
+ end
552
+ def tagstart(name, attributes)
553
+ case name
554
+ when 'HostedZone' then @item = { :config => {} }
555
+ end
556
+ end
557
+ def tagend(name)
558
+ case name
559
+ when 'IsTruncated' then @result[:is_truncated] = @text == 'true'
560
+ when 'NextMarker' then @result[:next_marker] = @text
561
+ when 'MaxItems' then @result[:max_items] = @text.to_i
562
+ when 'Id' then @item[:aws_id] = @text
563
+ when 'Name' then @item[:name] = @text
564
+ when 'CallerReference' then @item[:caller_reference] = @text
565
+ when 'HostedZone' then @result[:items] << @item
566
+ else
567
+ case full_tag_name
568
+ when %r{/Config/Comment$} then @item[:config][:comment] = @text
569
+ end
570
+ end
571
+ end
572
+ end
573
+
574
+ class GetHostedZoneParser < RightAWSParser # :nodoc:
575
+ def reset
576
+ @result = {}
577
+ end
578
+ def tagend(name)
579
+ case full_tag_name
580
+ when %r{/HostedZone/Id} then @result[:aws_id] = @text
581
+ when %r{/HostedZone/Name} then @result[:name] = @text
582
+ when %r{/HostedZone/CallerReference} then @result[:caller_reference] = @text
583
+ when %r{/Config/Comment$} then (@result[:config] ||= {})[:comment] = AwsUtils::xml_unescape(@text)
584
+ when %r{/ChangeInfo/Id$} then (@result[:change_info] ||= {})[:aws_id] = @text
585
+ when %r{/ChangeInfo/Status$} then (@result[:change_info] ||= {})[:status] = @text
586
+ when %r{/ChangeInfo/SubmittedAt$} then (@result[:change_info] ||= {})[:submitted_at] = @text
587
+ when %r{/DelegationSet/NameServers/NameServer$} then (@result[:name_servers] ||= []) << @text
588
+ end
589
+ end
590
+ end
591
+
592
+ #-----------------------------------------------------------------
593
+ # Resource Records Set
594
+ #-----------------------------------------------------------------
595
+
596
+ class ListResourceRecordSetsParser < RightAWSParser # :nodoc:
597
+ def reset
598
+ @result = { :items => [] }
599
+ end
600
+ def tagstart(name, attributes)
601
+ case name
602
+ when 'ResourceRecordSet' then @item = {}
603
+ end
604
+ end
605
+ def tagend(name)
606
+ case name
607
+ when 'IsTruncated' then @result[:is_truncated] = @text == 'true'
608
+ when 'NextRecordName' then @result[:next_record_name] = @text
609
+ when 'NextRecordType' then @result[:next_record_type] = @text
610
+ when 'MaxItems' then @result[:max_items] = @text.to_i
611
+ when 'Type' then @item[:type] = @text
612
+ when 'Name' then @item[:name] = @text
613
+ when 'TTL' then @item[:ttl] = @text.to_i
614
+ when 'ResourceRecordSet' then @result[:items] << @item
615
+ else
616
+ case full_tag_name
617
+ when %r{/ResourceRecord/Value} then (@item[:resource_records] ||= []) << @text
618
+ when %r{/AliasTarget/DNSName} then (@item[:alias_target] ||= {})[:dns_name] = @text
619
+ when %r{/AliasTarget/HostedZoneId} then (@item[:alias_target] ||= {})[:hosted_zone_id] = @text
620
+ end
621
+ end
622
+ end
623
+ end
624
+
625
+ class GetChangeParser < RightAWSParser # :nodoc:
626
+ def reset
627
+ @result = { }
628
+ end
629
+ def tagend(name)
630
+ case name
631
+ when 'Id' then @result[:aws_id] = @text
632
+ when 'Status' then @result[:status] = @text
633
+ when 'SubmittedAt' then @result[:submitted_at] = @text
634
+ end
635
+ end
636
+ end
637
+
638
+ end
639
+
640
+ end