route53 0.1.8 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +21 -6
- data/lib/route53.rb +58 -21
- data/lib/route53/cli.rb +27 -12
- data/lib/route53/version.rb +1 -1
- metadata +4 -4
data/README.markdown
CHANGED
@@ -6,7 +6,7 @@ This interface can either be used as a command line tool or as a library from wi
|
|
6
6
|
Costs & Impact
|
7
7
|
--------------
|
8
8
|
|
9
|
-
At the time of this writing Amazon charges $1/zone/month. This includes zones that have been created and deleted and then recreated. The creator of this gem is not responsible for costs incurred while using this interface or unexpected oepration or bugs which may incur a cost for the user. The creator is also not responsible for any downtime incurred or disruption in service from the usage of this tool. DNS can be a tricky thing, be careful and always make sure you have a backup of your zone prior to mucking around with it. (route53 -l example.com.)
|
9
|
+
At the time of this writing Amazon charges $1/zone/month. This includes zones that have been created and deleted and then recreated outside of the normal 12 hour grace period. The creator of this gem is not responsible for costs incurred while using this interface or unexpected oepration or bugs which may incur a cost for the user. The creator is also not responsible for any downtime incurred or disruption in service from the usage of this tool. DNS can be a tricky thing, be careful and always make sure you have a backup of your zone prior to mucking around with it. (route53 -l example.com.)
|
10
10
|
|
11
11
|
Latest Version
|
12
12
|
--------------
|
@@ -43,10 +43,10 @@ The first time you run the gem in command line mode you'll be prompted to setup.
|
|
43
43
|
Please answer the following prompts.
|
44
44
|
Amazon Access Key: []
|
45
45
|
Amazon Secret Key: []
|
46
|
-
Amazon Route 53 API Version: [
|
47
|
-
Amazon Route 53 Endpoint: [https://route53.amazonaws.com/]
|
48
|
-
Default TTL: [3600]
|
49
|
-
Save the configuration file to "~/.route53"?: [Y]
|
46
|
+
Amazon Route 53 API Version: [2011-05-05]
|
47
|
+
Amazon Route 53 Endpoint: [https://route53.amazonaws.com/]
|
48
|
+
Default TTL: [3600]
|
49
|
+
Save the configuration file to "~/.route53"?: [Y]
|
50
50
|
|
51
51
|
Command Line Options
|
52
52
|
--------------------
|
@@ -66,15 +66,19 @@ Command Line Options
|
|
66
66
|
--name [NAME] Specify a name for a record
|
67
67
|
--type [TYPE] Specify a type for a record
|
68
68
|
--ttl [TTL] Specify a TTL for a record
|
69
|
+
--weight [WEIGHT] Specify a Weight for a record
|
70
|
+
--ident [IDENTIFIER] Specify a unique identifier for a record
|
69
71
|
--values [VALUE1],[VALUE2],[VALUE3]
|
70
72
|
Specify one or multiple values for a record
|
73
|
+
--zone-apex-id [ZONE_APEX_ID]
|
74
|
+
Specify a zone apex if for the record
|
71
75
|
-m, --comment [COMMENT] Provide a comment for this operation
|
72
76
|
--no-wait Do not wait for actions to finish syncing.
|
73
77
|
-s, --setup Run the setup ptogram to create your configuration file.
|
74
78
|
-f, --file [CONFIGFILE] Specify a configuration file to use
|
75
79
|
--access [ACCESSKEY] Specify an access key on the command line.
|
76
80
|
--secret [SECRETKEY] Specify a secret key on the command line. WARNING: Not a good idea
|
77
|
-
|
81
|
+
--no-upgrade Do not automatically upgrade the route53 api spec for this version.
|
78
82
|
|
79
83
|
Command Line Usage
|
80
84
|
------------------
|
@@ -100,9 +104,20 @@ Once route53 is installed, started and has been setup you're ready to start. You
|
|
100
104
|
#If updating values for a record, make sure to includ all other values. Otherwise they will be dropped
|
101
105
|
route53 --zone example.com. -g --ttl 600
|
102
106
|
|
107
|
+
#Creating a record that corresponds to an Amazon ELB (zone apex support)
|
108
|
+
route53 --zone example.com. -c --name example. --zone-apex-id Z3DZXE0XXXXXXX --type A --values my-load-balancer-XXXXXXX.us-east-1.elb.amazonaws.com
|
109
|
+
|
110
|
+
#Creating weighted record sets
|
111
|
+
route53 example.com. -c --name www.example.com. --weight 15 --ident "75 percent of traffic to pool1" --type CNAME --values pool1.example.com.
|
112
|
+
route53 example.com. -c --name www.example.com. --weight 5 --ident "25 percent of traffic to pool2" --type CNAME --values pool2.example.com.
|
113
|
+
|
114
|
+
#Creating a wildcard domain
|
115
|
+
route53 example.com. -c --name *.example.com --type CNAME --values pool1.example.com.
|
116
|
+
|
103
117
|
#Deleting a zone - First remove all records except the NS and SOA record. Then delete the zone.
|
104
118
|
route53 --zone example.com. -r
|
105
119
|
route53 -d example.com.
|
120
|
+
|
106
121
|
|
107
122
|
Library Usage
|
108
123
|
-------------
|
data/lib/route53.rb
CHANGED
@@ -19,7 +19,7 @@ module Route53
|
|
19
19
|
attr_reader :endpoint
|
20
20
|
attr_reader :verbose
|
21
21
|
|
22
|
-
def initialize(accesskey,secret,api='
|
22
|
+
def initialize(accesskey,secret,api='2011-05-05',endpoint='https://route53.amazonaws.com/',verbose=false)
|
23
23
|
@accesskey = accesskey
|
24
24
|
@secret = secret
|
25
25
|
@api = api
|
@@ -165,14 +165,23 @@ module Route53
|
|
165
165
|
#puts "Name:"+record.search("Name").first.innerText if @conn.verbose
|
166
166
|
#puts "Type:"+record.search("Type").first.innerText if @conn.verbose
|
167
167
|
#puts "TTL:"+record.search("TTL").first.innerText if @conn.verbose
|
168
|
-
record.search("Value").each do |val|
|
169
|
-
|
170
|
-
end
|
168
|
+
#record.search("Value").each do |val|
|
169
|
+
# #puts "Val:"+val.innerText if @conn.verbose
|
170
|
+
#end
|
171
|
+
zone_apex_records = record.search("HostedZoneId")
|
172
|
+
values = record.search("Value").map { |val| val.innerText }
|
173
|
+
values << record.search("DNSName").first.innerText unless zone_apex_records.empty?
|
174
|
+
weight_records = record.search("Weight")
|
175
|
+
ident_records = record.search("SetIdentifier")
|
171
176
|
dom_records.push(DNSRecord.new(record.search("Name").first.innerText,
|
172
177
|
record.search("Type").first.innerText,
|
173
|
-
record.search("TTL").first.innerText,
|
174
|
-
|
175
|
-
self
|
178
|
+
(record.search("TTL").first.innerText if zone_apex_records.empty?),
|
179
|
+
values,
|
180
|
+
self,
|
181
|
+
(zone_apex_records.first.innerText unless zone_apex_records.empty?),
|
182
|
+
(weight_records.first.innerText unless weight_records.empty?),
|
183
|
+
(ident_records.first.innerText unless ident_records.empty?)
|
184
|
+
))
|
176
185
|
end
|
177
186
|
|
178
187
|
truncated = (zone_file.search("IsTruncated").first.innerText == "true")
|
@@ -230,7 +239,7 @@ module Route53
|
|
230
239
|
|
231
240
|
|
232
241
|
def initialize(resp,conn)
|
233
|
-
@raw_data = resp
|
242
|
+
@raw_data = unescape(resp)
|
234
243
|
if error?
|
235
244
|
$stderr.puts "ERROR: Amazon returned an error for the request."
|
236
245
|
$stderr.puts "ERROR: RAW_XML: "+@raw_data
|
@@ -291,6 +300,10 @@ module Route53
|
|
291
300
|
def to_s
|
292
301
|
return @raw_data
|
293
302
|
end
|
303
|
+
|
304
|
+
def unescape(string)
|
305
|
+
string.gsub(/\\0(\d{2})/) { $1.oct.chr }
|
306
|
+
end
|
294
307
|
end
|
295
308
|
|
296
309
|
class DNSRecord
|
@@ -298,16 +311,22 @@ module Route53
|
|
298
311
|
attr_reader :type
|
299
312
|
attr_reader :ttl
|
300
313
|
attr_reader :values
|
314
|
+
attr_reader :weight
|
315
|
+
attr_reader :ident
|
316
|
+
attr_reader :zone_apex
|
301
317
|
|
302
|
-
def initialize(name,type,ttl,values,zone)
|
318
|
+
def initialize(name,type,ttl,values,zone,zone_apex=nil,weight=nil,ident=nil)
|
303
319
|
@name = name
|
304
320
|
unless @name.end_with?(".")
|
305
321
|
@name += "."
|
306
322
|
end
|
307
|
-
@type = type
|
308
|
-
@ttl = ttl
|
323
|
+
@type = type.upcase
|
324
|
+
@ttl = ttl
|
309
325
|
@values = values
|
310
326
|
@zone = zone
|
327
|
+
@zone_apex = zone_apex
|
328
|
+
@weight = weight
|
329
|
+
@ident = ident
|
311
330
|
end
|
312
331
|
|
313
332
|
def gen_change_xml(xml,action)
|
@@ -316,14 +335,23 @@ module Route53
|
|
316
335
|
change.ResourceRecordSet { |record|
|
317
336
|
record.Name(@name)
|
318
337
|
record.Type(@type)
|
319
|
-
record.
|
320
|
-
record.
|
321
|
-
|
322
|
-
|
323
|
-
|
338
|
+
record.SetIdentifier(@ident) if @ident
|
339
|
+
record.Weight(@weight) if @weight
|
340
|
+
record.TTL(@ttl) unless @zone_apex
|
341
|
+
if @zone_apex
|
342
|
+
record.AliasTarget { |targets|
|
343
|
+
targets.HostedZoneId(@zone_apex)
|
344
|
+
targets.DNSName(@values.first)
|
345
|
+
}
|
346
|
+
else
|
347
|
+
record.ResourceRecords { |resources|
|
348
|
+
@values.each { |val|
|
349
|
+
resources.ResourceRecord { |record|
|
350
|
+
record.Value(val)
|
351
|
+
}
|
324
352
|
}
|
325
353
|
}
|
326
|
-
|
354
|
+
end
|
327
355
|
}
|
328
356
|
}
|
329
357
|
end
|
@@ -337,12 +365,13 @@ module Route53
|
|
337
365
|
end
|
338
366
|
|
339
367
|
#Need to modify to a param hash
|
340
|
-
def update(name,type,ttl,values,comment=nil)
|
368
|
+
def update(name,type,ttl,values,comment=nil, zone_apex = nil)
|
341
369
|
prev = self.clone
|
342
370
|
@name = name unless name.nil?
|
343
371
|
@type = type unless type.nil?
|
344
372
|
@ttl = ttl unless ttl.nil?
|
345
373
|
@values = values unless values.nil?
|
374
|
+
@zone_apex = zone_apex unless zone_apex.nil?
|
346
375
|
@zone.perform_actions([
|
347
376
|
{:action => "DELETE", :record => prev},
|
348
377
|
{:action => "CREATE", :record => self},
|
@@ -351,20 +380,28 @@ module Route53
|
|
351
380
|
|
352
381
|
#Returns the raw array so the developer can update large batches manually
|
353
382
|
#Need to modify to a param hash
|
354
|
-
def update_dirty(name,type,ttl,values)
|
383
|
+
def update_dirty(name,type,ttl,values,zone_apex = nil)
|
355
384
|
prev = self.clone
|
356
385
|
@name = name unless name.nil?
|
357
386
|
@type = type unless type.nil?
|
358
387
|
@ttl = ttl unless ttl.nil?
|
359
388
|
@values = values unless values.nil?
|
389
|
+
@zone_apex = zone_apex unless zone_apex.nil?
|
360
390
|
return [{:action => "DELETE", :record => prev},
|
361
391
|
{:action => "CREATE", :record => self}]
|
362
392
|
end
|
363
393
|
|
364
394
|
def to_s
|
365
|
-
|
395
|
+
if @weight
|
396
|
+
"#{@name} #{@type} #{@ttl} '#{@ident}' #{@weight} #{@values.join(",")}"
|
397
|
+
elsif @zone_apex
|
398
|
+
"#{@name} #{@type} #{@zone_apex} #{@values.join(",")}"
|
399
|
+
else
|
400
|
+
"#{@name} #{@type} #{@ttl} #{@values.join(",")}"
|
401
|
+
end
|
366
402
|
end
|
367
403
|
end
|
404
|
+
|
368
405
|
end
|
369
406
|
|
370
407
|
$messages = { "InvalidClientTokenId" => "You may have a missing or incorrect secret or access key. Please double check your configuration files and amazon account",
|
@@ -373,7 +410,7 @@ end
|
|
373
410
|
"Other" => "It looks like you've run into an unhandled error. Please send a detailed bug report with the entire input and output from the program to support@50projects.com or to https://github.com/pcorliss/ruby_route_53/issues and we'll do out best to help you.",
|
374
411
|
"SignatureDoesNotMatch" => "It looks like your secret key is incorrect or no longer valid. Please check your amazon account information for the proper key.",
|
375
412
|
"HostedZoneNotEmpty" => "You'll need to first delete the contents of this zone. You can do so using the '--remove' option as part of the command line interface.",
|
376
|
-
"InvalidChangeBatch" => "You may have tried to delete a NS or SOA record. This error is safe to ignore if you're just trying to delete all records as part of a zone prior to deleting the zone. Otherwise please file a bug by sending a detailed bug report with the entire input and output from the program to support@50projects.com or to https://github.com/pcorliss/ruby_route_53/issues and we'll do out best to help you.",
|
413
|
+
"InvalidChangeBatch" => "You may have tried to delete a NS or SOA record. This error is safe to ignore if you're just trying to delete all records as part of a zone prior to deleting the zone. Or you may have tried to create a record that already exists. Otherwise please file a bug by sending a detailed bug report with the entire input and output from the program to support@50projects.com or to https://github.com/pcorliss/ruby_route_53/issues and we'll do out best to help you.",
|
377
414
|
"ValidationError" => "Check over your input again to make sure the record to be created is valid. The error message should give you some hints on what went wrong. If you're still having problems please file a bug by sending a detailed bug report with the entire input and output from the program to support@50projects.com or to https://github.com/pcorliss/ruby_route_53/issues and we'll do out best to help you."}
|
378
415
|
|
379
416
|
|
data/lib/route53/cli.rb
CHANGED
@@ -35,7 +35,8 @@ module Route53
|
|
35
35
|
puts "\nFinished at #{DateTime.now}" if @options.verbose
|
36
36
|
|
37
37
|
else
|
38
|
-
|
38
|
+
puts "ERROR: Invalid Options passed. Please run with --help"
|
39
|
+
exit 1
|
39
40
|
end
|
40
41
|
|
41
42
|
end
|
@@ -57,13 +58,17 @@ module Route53
|
|
57
58
|
opts.on('-z', '--zone [ZONE]', String, "Specify a zone to perform an operation on. Either in 'example.com.' or '/hostedzone/XXX' format") { |zone| @options.zone = zone }
|
58
59
|
|
59
60
|
opts.on('-c', '--create', "Create a new record") { @options.create_record = true }
|
61
|
+
|
60
62
|
opts.on('-r', '--remove', String, "Remove a record") { |record| @options.remove_record = true }
|
61
63
|
opts.on('-g', '--change', String, "Change a record") { |record| @options.change_record = true }
|
62
64
|
|
63
65
|
opts.on('--name [NAME]', String, "Specify a name for a record") { |name| @options.name = name }
|
64
66
|
opts.on('--type [TYPE]', String, "Specify a type for a record") { |dnstype| @options.dnstype = dnstype }
|
65
67
|
opts.on('--ttl [TTL]', String, "Specify a TTL for a record") { |ttl| @options.ttl = ttl }
|
68
|
+
opts.on('--weight [WEIGHT]', String, "Specify a Weight for a record") { |weight| @options.weight = weight }
|
69
|
+
opts.on('--ident [IDENTIFIER]', String, "Specify a unique identifier for a record") { |ident| @options.ident = ident }
|
66
70
|
opts.on('--values [VALUE1],[VALUE2],[VALUE3]', Array, "Specify one or multiple values for a record") { |value| @options.values = value }
|
71
|
+
opts.on('--zone-apex-id [ZONE_APEX_ID]', String, "Specify a zone apex if for the record") { |zone_apex| @options.zone_apex = zone_apex }
|
67
72
|
|
68
73
|
opts.on('-m', '--comment [COMMENT]', String, "Provide a comment for this operation") { |comment| @options.comment = comment }
|
69
74
|
|
@@ -74,10 +79,12 @@ module Route53
|
|
74
79
|
opts.on('--access [ACCESSKEY]',String,"Specify an access key on the command line.") { |access| @options.access = access }
|
75
80
|
opts.on('--secret [SECRETKEY]',String,"Specify a secret key on the command line. WARNING: Not a good idea") { |secret| @options.secret = secret }
|
76
81
|
|
82
|
+
opts.on('--no-upgrade',"Do not automatically upgrade the route53 api spec for this version.") { @options.no_upgrade = true }
|
83
|
+
|
77
84
|
opts.parse!(@arguments) rescue return false
|
78
85
|
|
79
86
|
process_options
|
80
|
-
true
|
87
|
+
true
|
81
88
|
end
|
82
89
|
|
83
90
|
# Performs post-parse processing on options
|
@@ -180,7 +187,7 @@ module Route53
|
|
180
187
|
puts "Zone Deleted." unless resp.error?
|
181
188
|
end
|
182
189
|
else
|
183
|
-
$stderr.puts "ERROR: Couldn't Find Record for @options.zone."
|
190
|
+
$stderr.puts "ERROR: Couldn't Find Record for #{@options.zone}."
|
184
191
|
end
|
185
192
|
else
|
186
193
|
required_options("delete zone",["--zone"])
|
@@ -197,7 +204,7 @@ module Route53
|
|
197
204
|
zones.each do |z|
|
198
205
|
puts "Creating Record"
|
199
206
|
@options.ttl = @config['default_ttl'] if @options.ttl.nil?
|
200
|
-
if @options.dnstype == 'TXT'
|
207
|
+
if @options.dnstype.upcase == 'TXT'
|
201
208
|
@options.values = @options.values.map do |val|
|
202
209
|
unless val.start_with?('"') && val.end_with?('"')
|
203
210
|
val = '"' + val unless val.start_with? '"'
|
@@ -206,7 +213,7 @@ module Route53
|
|
206
213
|
val
|
207
214
|
end
|
208
215
|
end
|
209
|
-
record = Route53::DNSRecord.new(@options.name,@options.dnstype,@options.ttl,@options.values,z)
|
216
|
+
record = Route53::DNSRecord.new(@options.name,@options.dnstype,@options.ttl,@options.values,z,@options.zone_apex,@options.weight,@options.ident)
|
210
217
|
puts "Creating Record #{record}"
|
211
218
|
resps.push(record.create)
|
212
219
|
end
|
@@ -215,7 +222,7 @@ module Route53
|
|
215
222
|
puts "Record Created." unless resp.error?
|
216
223
|
end
|
217
224
|
else
|
218
|
-
$stderr.puts "ERROR: Couldn't Find Record for @options.zone."
|
225
|
+
$stderr.puts "ERROR: Couldn't Find Record for #{@options.zone}."
|
219
226
|
end
|
220
227
|
else
|
221
228
|
#$stderr.puts "ERROR: The following arguments are required for a create record operation."
|
@@ -243,11 +250,11 @@ module Route53
|
|
243
250
|
puts "Record Deleted." unless resp.error?
|
244
251
|
end
|
245
252
|
else
|
246
|
-
$stderr.puts "ERROR: Couldn't Find Record for @options.zone of type "+(@options.dnstype.nil? ? "ANY" : @options.dnstype)+"."
|
253
|
+
$stderr.puts "ERROR: Couldn't Find Record for #{@options.zone} of type "+(@options.dnstype.nil? ? "ANY" : @options.dnstype)+"."
|
247
254
|
end
|
248
255
|
end
|
249
256
|
else
|
250
|
-
$stderr.puts "ERROR: Couldn't Find Record for @options.zone."
|
257
|
+
$stderr.puts "ERROR: Couldn't Find Record for #{@options.zone}."
|
251
258
|
end
|
252
259
|
else
|
253
260
|
#$stderr.puts "ERROR: The following arguments are required for a record removal operation."
|
@@ -263,7 +270,7 @@ module Route53
|
|
263
270
|
if zones.size > 0
|
264
271
|
zones.each do |z|
|
265
272
|
records = z.get_records(@options.dnstype.nil? ? "ANY" : @options.dnstype)
|
266
|
-
records = records.select { |rec| rec.name == @options.name } if @options.name
|
273
|
+
records = records.select { |rec| puts "Rec: #{rec.name}"; rec.name == @options.name } if @options.name
|
267
274
|
if records.size > 0
|
268
275
|
if records.size > 1
|
269
276
|
records = record_picker(records,false)
|
@@ -275,11 +282,11 @@ module Route53
|
|
275
282
|
puts "Record Modified." unless resp.error?
|
276
283
|
end
|
277
284
|
else
|
278
|
-
$stderr.puts "ERROR: Couldn't Find Record for @options.
|
285
|
+
$stderr.puts "ERROR: Couldn't Find Record for #{@options.name} of type "+(@options.dnstype.nil? ? "ANY" : @options.dnstype)+"."
|
279
286
|
end
|
280
287
|
end
|
281
288
|
else
|
282
|
-
$stderr.puts "ERROR: Couldn't Find Record for @options.
|
289
|
+
$stderr.puts "ERROR: Couldn't Find Record for #{@options.name}."
|
283
290
|
end
|
284
291
|
else
|
285
292
|
#$stderr.puts "ERROR: The following arguments are required for a record change operation."
|
@@ -304,7 +311,7 @@ module Route53
|
|
304
311
|
new_config = Hash.new
|
305
312
|
new_config['access_key'] = get_input(String,"Amazon Access Key")
|
306
313
|
new_config['secret_key'] = get_input(String,"Amazon Secret Key")
|
307
|
-
new_config['api'] = get_input(String,"Amazon Route 53 API Version","
|
314
|
+
new_config['api'] = get_input(String,"Amazon Route 53 API Version","2011-05-05")
|
308
315
|
new_config['endpoint'] = get_input(String,"Amazon Route 53 Endpoint","https://route53.amazonaws.com/")
|
309
316
|
new_config['default_ttl'] = get_input(String,"Default TTL","3600")
|
310
317
|
if get_input(true.class,"Save the configuration file to \"~/.route53\"?","Y")
|
@@ -406,6 +413,14 @@ module Route53
|
|
406
413
|
unless @config
|
407
414
|
@config = Hash.new
|
408
415
|
end
|
416
|
+
if @config['api'] != '2011-05-05' && !@options.no_upgrade
|
417
|
+
puts "Note: Automatically setting your configuration file to the amazon route 53 api spec this program was written for. You can avoid this by passing --no-upgrade"
|
418
|
+
@config['api'] = '2011-05-05'
|
419
|
+
File.open(@options.file,'w') do |out|
|
420
|
+
YAML.dump(@config,out)
|
421
|
+
end
|
422
|
+
File.chmod(0600,@options.file)
|
423
|
+
end
|
409
424
|
end
|
410
425
|
|
411
426
|
def user_home
|
data/lib/route53/version.rb
CHANGED
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Philip Corliss
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-
|
17
|
+
date: 2011-05-30 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|