route53 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +97 -89
- data/lib/route53.rb +48 -40
- data/lib/route53/cli.rb +61 -60
- data/lib/route53/version.rb +1 -1
- metadata +73 -45
data/README.markdown
CHANGED
@@ -18,24 +18,30 @@ Installation
|
|
18
18
|
|
19
19
|
Installing the Gem
|
20
20
|
|
21
|
-
|
21
|
+
```bash
|
22
|
+
sudo gem install route53
|
23
|
+
```
|
22
24
|
|
23
25
|
Ubuntu with precompiled dependencies
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
```bash
|
28
|
+
sudo apt-get update
|
29
|
+
sudo apt-get install ruby rubygems libopenssl-ruby libhmac-ruby libbuilder-ruby libhpricot-ruby
|
30
|
+
sudo gem install route53 --ignore-dependencies
|
31
|
+
/var/lib/gems/1.X/gems/route53-W.Y.Z/bin/route53
|
32
|
+
|
33
|
+
#When working with the library and using this method you may need to require the library manually
|
34
|
+
require '/var/lib/gems/1.X/gems/route53-W.Y.Z/lib/route53'
|
35
|
+
```
|
32
36
|
|
33
37
|
Ubuntu with building dependencies
|
34
38
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
+
```bash
|
40
|
+
sudo apt-get update
|
41
|
+
sudo apt-get install ruby rubygems ruby-dev build-essential libopenssl-ruby
|
42
|
+
sudo gem install route53
|
43
|
+
/var/lib/gems/1.X/bin/route53
|
44
|
+
```
|
39
45
|
|
40
46
|
The first time you run the gem in command line mode you'll be prompted to setup. You'll want to have your Amazon access and secret key ready.
|
41
47
|
|
@@ -85,89 +91,91 @@ Command Line Usage
|
|
85
91
|
|
86
92
|
Once route53 is installed, started and has been setup you're ready to start. You can use the following examples to get started.
|
87
93
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
94
|
+
```bash
|
95
|
+
#Creating a new zone
|
96
|
+
route53 -n example.com.
|
97
|
+
|
98
|
+
#List Operations
|
99
|
+
route53 -l #Get all zones for this account
|
100
|
+
route53 -l example.com. #Get all records for this account within the zone example.com.
|
101
|
+
|
102
|
+
#Create a new record within our newly created zone.
|
103
|
+
route53 --zone example.com. -c --name foo.example.com. --type CNAME --ttl 3600 --values example.com.
|
104
|
+
|
105
|
+
#New MX Record for a Google Apps hosted domain
|
106
|
+
route53 --zone example.com. -c --name example.com. --type MX --ttl 3600 \
|
107
|
+
--values "10 ASPMX.L.GOOGLE.com.","20 ALT1.ASPMX.L.GOOGLE.com.","30 ALT2.ASPMX.L.GOOGLE.com.","40 ASPMX2.GOOGLEMAIL.com.","50 ASPMX3.GOOGLEMAIL.com."
|
108
|
+
|
109
|
+
#Update the TTL of a record (Leave values nil to leave them alone)
|
110
|
+
#You'll be prompted to select the record from a list.
|
111
|
+
#If updating values for a record, make sure to includ all other values. Otherwise they will be dropped
|
112
|
+
route53 --zone example.com. -g --ttl 600
|
113
|
+
|
114
|
+
#Creating a record that corresponds to an Amazon ELB (zone apex support)
|
115
|
+
route53 --zone example.com. -c --name example. --zone-apex-id Z3DZXE0XXXXXXX --type A --values my-load-balancer-XXXXXXX.us-east-1.elb.amazonaws.com
|
116
|
+
|
117
|
+
#Creating weighted record sets
|
118
|
+
route53 example.com. -c --name www.example.com. --weight 15 --ident "75 percent of traffic to pool1" --type CNAME --values pool1.example.com.
|
119
|
+
route53 example.com. -c --name www.example.com. --weight 5 --ident "25 percent of traffic to pool2" --type CNAME --values pool2.example.com.
|
120
|
+
|
121
|
+
#Creating a wildcard domain
|
122
|
+
route53 example.com. -c --name *.example.com --type CNAME --values pool1.example.com.
|
123
|
+
|
124
|
+
#Deleting a zone - First remove all records except the NS and SOA record. Then delete the zone.
|
125
|
+
route53 --zone example.com. -r
|
126
|
+
route53 -d example.com.
|
127
|
+
```
|
121
128
|
|
122
129
|
Library Usage
|
123
130
|
-------------
|
124
131
|
|
125
132
|
If you're using this as a library for your own ruby project you can load it and perform operations by using the following examples.
|
126
133
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
134
|
+
```ruby
|
135
|
+
require 'route53'
|
136
|
+
|
137
|
+
#Creating a Connection object
|
138
|
+
conn = Route53::Connection.new(my_access_key,my_secret_key) #opens connection
|
139
|
+
|
140
|
+
#Creating a new zone and working with responses
|
141
|
+
new_zone = Route53::Zone.new("example.com.",nil,conn) #Create a new zone "example.com."
|
142
|
+
resp = new_zone.create_zone #Creates a new zone
|
143
|
+
exit 1 if resp.error? #Exit if there was an error. The AWSResponse Class automatically prints out error messages to STDERR.
|
144
|
+
while resp.pending? #Waits for response to sync on Amazon's servers.
|
145
|
+
sleep 1 #If you'll be performing operations on this newly created zone you'll probably want to wait.
|
146
|
+
end
|
147
|
+
|
148
|
+
#List Operations
|
149
|
+
zones = conn.get_zones #Requests list of all zones for this account
|
150
|
+
records = zones.first.get_records #Gets list of all records for a specific zone
|
151
|
+
|
152
|
+
#Create a new record within our newly created zone.
|
153
|
+
new_record = Route53::DNSRecord.new("foo.example.com.","CNAME","3600",["example.com."],new_zone)
|
154
|
+
resp = new_record.create
|
155
|
+
|
156
|
+
#New MX Record for a Google Apps hosted domain
|
157
|
+
new_mx_record = Route53::DNSRecord.new("example.com.","MX","3600",
|
158
|
+
["10 ASPMX.L.GOOGLE.com.",
|
159
|
+
"20 ALT1.ASPMX.L.GOOGLE.com.",
|
160
|
+
"30 ALT2.ASPMX.L.GOOGLE.com.",
|
161
|
+
"40 ASPMX2.GOOGLEMAIL.com.",
|
162
|
+
"50 ASPMX3.GOOGLEMAIL.com."],
|
163
|
+
new_zone)
|
164
|
+
resp = new_mx_record.create
|
165
|
+
|
166
|
+
#Update the TTL of a record (Leave values nil to leave them alone)
|
167
|
+
#If updating values for a record, make sure to includ all other values. Otherwise they will be dropped
|
168
|
+
resp = new_record.update(nil,nil,"600",nil)
|
169
|
+
|
170
|
+
#Deleting a zone
|
171
|
+
#A zone can't be deleted until all of it's records have been deleted (Except for 1 NS record and 1 SOA record)
|
172
|
+
new_zone.get_records.each do |record|
|
173
|
+
unless record.type == 'NS' || record.type == 'SOA'
|
174
|
+
record.delete
|
175
|
+
end
|
176
|
+
end
|
177
|
+
new_zone.delete_zone
|
178
|
+
```
|
171
179
|
|
172
180
|
Requirements
|
173
181
|
------------
|
data/lib/route53.rb
CHANGED
@@ -12,22 +12,23 @@ require 'builder'
|
|
12
12
|
require 'digest/md5'
|
13
13
|
|
14
14
|
module Route53
|
15
|
-
|
15
|
+
|
16
16
|
class Connection
|
17
17
|
attr_reader :base_url
|
18
18
|
attr_reader :api
|
19
19
|
attr_reader :endpoint
|
20
20
|
attr_reader :verbose
|
21
|
-
|
22
|
-
def initialize(accesskey,secret,api='
|
21
|
+
|
22
|
+
def initialize(accesskey,secret,api='2012-12-12',endpoint='https://route53.amazonaws.com/',verbose=false,ssl_no_verify=false)
|
23
23
|
@accesskey = accesskey
|
24
24
|
@secret = secret
|
25
25
|
@api = api
|
26
26
|
@endpoint = endpoint
|
27
27
|
@base_url = endpoint+@api
|
28
28
|
@verbose = verbose
|
29
|
+
@ssl_no_verify = ssl_no_verify
|
29
30
|
end
|
30
|
-
|
31
|
+
|
31
32
|
def request(url,type = "GET",data = nil)
|
32
33
|
puts "URL: #{url}" if @verbose
|
33
34
|
puts "Type: #{type}" if @verbose
|
@@ -35,7 +36,7 @@ module Route53
|
|
35
36
|
uri = URI(url)
|
36
37
|
http = Net::HTTP.new(uri.host, uri.port)
|
37
38
|
http.use_ssl = true if uri.scheme == "https"
|
38
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if RUBY_VERSION.start_with?("1.8")
|
39
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if RUBY_VERSION.start_with?("1.8") or @ssl_no_verify
|
39
40
|
time = get_date
|
40
41
|
hmac = HMAC::SHA256.new(@secret)
|
41
42
|
hmac.update(time)
|
@@ -50,7 +51,7 @@ module Route53
|
|
50
51
|
#puts "RespBody: #{resp.body}" if @verbose
|
51
52
|
return AWSResponse.new(resp.body,self)
|
52
53
|
end
|
53
|
-
|
54
|
+
|
54
55
|
def get_zones(name = nil)
|
55
56
|
truncated = true
|
56
57
|
query = []
|
@@ -75,7 +76,7 @@ module Route53
|
|
75
76
|
end
|
76
77
|
unless name.nil? || name.start_with?("/hostedzone/")
|
77
78
|
name_arr = name.split('.')
|
78
|
-
(0 ... name_arr.size).each do |i|
|
79
|
+
(0 ... name_arr.size).each do |i|
|
79
80
|
search_domain = name_arr.last(name_arr.size-i).join('.')+"."
|
80
81
|
zone_select = zones.select { |z| z.name == search_domain }
|
81
82
|
return zone_select
|
@@ -84,7 +85,7 @@ module Route53
|
|
84
85
|
end
|
85
86
|
return zones
|
86
87
|
end
|
87
|
-
|
88
|
+
|
88
89
|
def get_date
|
89
90
|
#return Time.now.utc.rfc2822
|
90
91
|
#Cache date for 30 seconds to reduce extra calls
|
@@ -92,7 +93,7 @@ module Route53
|
|
92
93
|
uri = URI(@endpoint)
|
93
94
|
http = Net::HTTP.new(uri.host, uri.port)
|
94
95
|
http.use_ssl = true if uri.scheme == "https"
|
95
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if RUBY_VERSION.start_with?("1.8")
|
96
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if RUBY_VERSION.start_with?("1.8") or @ssl_no_verify
|
96
97
|
resp = nil
|
97
98
|
puts "Making Date Request" if @verbose
|
98
99
|
http.start { |http| resp = http.head('/date') }
|
@@ -102,16 +103,16 @@ module Route53
|
|
102
103
|
end
|
103
104
|
return @date
|
104
105
|
end
|
105
|
-
|
106
|
+
|
106
107
|
end
|
107
|
-
|
108
|
-
|
108
|
+
|
109
|
+
|
109
110
|
class Zone
|
110
111
|
attr_reader :host_url
|
111
112
|
attr_reader :name
|
112
113
|
attr_reader :records
|
113
114
|
attr_reader :conn
|
114
|
-
|
115
|
+
|
115
116
|
def initialize(name,host_url,conn)
|
116
117
|
@name = name
|
117
118
|
unless @name.end_with?(".")
|
@@ -120,11 +121,18 @@ module Route53
|
|
120
121
|
@host_url = host_url
|
121
122
|
@conn = conn
|
122
123
|
end
|
123
|
-
|
124
|
+
|
125
|
+
def nameservers
|
126
|
+
return @nameservers if @nameservers
|
127
|
+
response = Hpricot::XML(@conn.request(@conn.base_url + @host_url).to_s)
|
128
|
+
@nameservers = response.search("NameServer").map(&:innerText)
|
129
|
+
@nameservers
|
130
|
+
end
|
131
|
+
|
124
132
|
def delete_zone
|
125
133
|
@conn.request(@conn.base_url + @host_url,"DELETE")
|
126
134
|
end
|
127
|
-
|
135
|
+
|
128
136
|
def create_zone(comment = nil)
|
129
137
|
xml_str = ""
|
130
138
|
xml = Builder::XmlMarkup.new(:target=>xml_str, :indent=>2)
|
@@ -132,7 +140,7 @@ module Route53
|
|
132
140
|
xml.CreateHostedZoneRequest(:xmlns => @conn.endpoint+'doc/'+@conn.api+'/') { |create|
|
133
141
|
create.Name(@name)
|
134
142
|
# AWS lists this as required
|
135
|
-
# "unique string that identifies the request and that
|
143
|
+
# "unique string that identifies the request and that
|
136
144
|
# allows failed CreateHostedZone requests to be retried without the risk of executing the operation twice."
|
137
145
|
# Just going to pass a random string instead.
|
138
146
|
create.CallerReference(rand(2**32).to_s(16))
|
@@ -146,10 +154,10 @@ module Route53
|
|
146
154
|
@host_url = resp_xml.search("HostedZone").first.search("Id").first.innerText
|
147
155
|
return resp
|
148
156
|
end
|
149
|
-
|
157
|
+
|
150
158
|
def get_records(type="ANY")
|
151
159
|
return nil if host_url.nil?
|
152
|
-
|
160
|
+
|
153
161
|
truncated = true
|
154
162
|
query = []
|
155
163
|
dom_records = []
|
@@ -183,7 +191,7 @@ module Route53
|
|
183
191
|
(ident_records.first.innerText unless ident_records.empty?)
|
184
192
|
))
|
185
193
|
end
|
186
|
-
|
194
|
+
|
187
195
|
truncated = (zone_file.search("IsTruncated").first.innerText == "true")
|
188
196
|
if truncated
|
189
197
|
next_name = zone_file.search("NextRecordName").first.innerText
|
@@ -197,7 +205,7 @@ module Route53
|
|
197
205
|
end
|
198
206
|
return dom_records
|
199
207
|
end
|
200
|
-
|
208
|
+
|
201
209
|
#When deleting a record an optional value is available to specify just a single value within a recordset like an MX record
|
202
210
|
#Takes an array of [:action => , :record => ] where action is either CREATE or DELETE and record is a DNSRecord
|
203
211
|
def gen_change_xml(change_list,comment=nil)
|
@@ -219,25 +227,25 @@ module Route53
|
|
219
227
|
#puts "XML:\n#{xml_str}" if @conn.verbose
|
220
228
|
return xml_str
|
221
229
|
end
|
222
|
-
|
230
|
+
|
223
231
|
#For modifying multiple or single records within a single transaction
|
224
232
|
def perform_actions(change_list,comment=nil)
|
225
233
|
xml_str = gen_change_xml(change_list,comment)
|
226
234
|
@conn.request(@conn.base_url + @host_url+"/rrset","POST",xml_str)
|
227
235
|
end
|
228
236
|
|
229
|
-
|
237
|
+
|
230
238
|
def to_s
|
231
239
|
return "#{@name} #{@host_url}"
|
232
240
|
end
|
233
241
|
end
|
234
|
-
|
242
|
+
|
235
243
|
class AWSResponse
|
236
244
|
attr_reader :raw_data
|
237
|
-
|
245
|
+
|
238
246
|
#I wanted to put this in a seprate file but ruby's method of determinign the root of the gem is a pain in the butt and I was in a hurry. Sorry. -PC
|
239
247
|
|
240
|
-
|
248
|
+
|
241
249
|
def initialize(resp,conn)
|
242
250
|
@raw_data = unescape(resp)
|
243
251
|
if error?
|
@@ -252,18 +260,18 @@ module Route53
|
|
252
260
|
@created = Time.now
|
253
261
|
puts "Raw: #{@raw_data}" if @conn.verbose
|
254
262
|
end
|
255
|
-
|
263
|
+
|
256
264
|
def error?
|
257
265
|
return Hpricot::XML(@raw_data).search("ErrorResponse").size > 0
|
258
266
|
end
|
259
|
-
|
267
|
+
|
260
268
|
def error_message
|
261
269
|
xml = Hpricot::XML(@raw_data)
|
262
270
|
msg_code = xml.search("Code")
|
263
271
|
msg_text = xml.search("Message")
|
264
272
|
return (msg_code.size > 0 ? msg_code.first.inner_text : "") + (msg_text.size > 0 ? ': ' + msg_text.first.innerText : "")
|
265
273
|
end
|
266
|
-
|
274
|
+
|
267
275
|
def helpful_message
|
268
276
|
xml = Hpricot::XML(@raw_data)
|
269
277
|
msg_code = xml.search("Code").first.innerText
|
@@ -291,21 +299,21 @@ module Route53
|
|
291
299
|
end
|
292
300
|
return @complete
|
293
301
|
end
|
294
|
-
|
302
|
+
|
295
303
|
def pending?
|
296
304
|
#Return opposite of complete via XOR
|
297
305
|
return complete? ^ true
|
298
306
|
end
|
299
|
-
|
307
|
+
|
300
308
|
def to_s
|
301
309
|
return @raw_data
|
302
310
|
end
|
303
|
-
|
311
|
+
|
304
312
|
def unescape(string)
|
305
313
|
string.gsub(/\\0(\d{2})/) { $1.oct.chr }
|
306
314
|
end
|
307
315
|
end
|
308
|
-
|
316
|
+
|
309
317
|
class DNSRecord
|
310
318
|
attr_reader :name
|
311
319
|
attr_reader :type
|
@@ -314,7 +322,7 @@ module Route53
|
|
314
322
|
attr_reader :weight
|
315
323
|
attr_reader :ident
|
316
324
|
attr_reader :zone_apex
|
317
|
-
|
325
|
+
|
318
326
|
def initialize(name,type,ttl,values,zone,zone_apex=nil,weight=nil,ident=nil)
|
319
327
|
@name = name
|
320
328
|
unless @name.end_with?(".")
|
@@ -328,7 +336,7 @@ module Route53
|
|
328
336
|
@weight = weight
|
329
337
|
@ident = ident
|
330
338
|
end
|
331
|
-
|
339
|
+
|
332
340
|
def gen_change_xml(xml,action)
|
333
341
|
xml.Change { |change|
|
334
342
|
change.Action(action.upcase)
|
@@ -355,15 +363,15 @@ module Route53
|
|
355
363
|
}
|
356
364
|
}
|
357
365
|
end
|
358
|
-
|
366
|
+
|
359
367
|
def delete(comment=nil)
|
360
368
|
@zone.perform_actions([{:action => "DELETE", :record => self}],comment)
|
361
369
|
end
|
362
|
-
|
370
|
+
|
363
371
|
def create(comment=nil)
|
364
372
|
@zone.perform_actions([{:action => "CREATE", :record => self}],comment)
|
365
373
|
end
|
366
|
-
|
374
|
+
|
367
375
|
#Need to modify to a param hash
|
368
376
|
def update(name,type,ttl,values,comment=nil, zone_apex = nil)
|
369
377
|
prev = self.clone
|
@@ -377,7 +385,7 @@ module Route53
|
|
377
385
|
{:action => "CREATE", :record => self},
|
378
386
|
],comment)
|
379
387
|
end
|
380
|
-
|
388
|
+
|
381
389
|
#Returns the raw array so the developer can update large batches manually
|
382
390
|
#Need to modify to a param hash
|
383
391
|
def update_dirty(name,type,ttl,values,zone_apex = nil)
|
@@ -390,7 +398,7 @@ module Route53
|
|
390
398
|
return [{:action => "DELETE", :record => prev},
|
391
399
|
{:action => "CREATE", :record => self}]
|
392
400
|
end
|
393
|
-
|
401
|
+
|
394
402
|
def to_s
|
395
403
|
if @weight
|
396
404
|
"#{@name} #{@type} #{@ttl} '#{@ident}' #{@weight} #{@values.join(",")}"
|
@@ -412,5 +420,5 @@ end
|
|
412
420
|
"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.",
|
413
421
|
"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.",
|
414
422
|
"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."}
|
415
|
-
|
423
|
+
|
416
424
|
|
data/lib/route53/cli.rb
CHANGED
@@ -7,13 +7,13 @@ require 'yaml'
|
|
7
7
|
|
8
8
|
module Route53
|
9
9
|
class CLI
|
10
|
-
|
10
|
+
|
11
11
|
attr_reader :options
|
12
12
|
|
13
13
|
def initialize(arguments, stdin)
|
14
14
|
@arguments = arguments
|
15
15
|
@stdin = stdin
|
16
|
-
|
16
|
+
|
17
17
|
# Set defaults
|
18
18
|
@options = OpenStruct.new
|
19
19
|
@options.verbose = false
|
@@ -21,47 +21,47 @@ module Route53
|
|
21
21
|
end
|
22
22
|
|
23
23
|
#Skeleton obtained from http://blog.toddwerth.com/entries/show/5 and modified
|
24
|
-
|
24
|
+
|
25
25
|
# Parse options, check arguments, then process the command
|
26
26
|
def run
|
27
|
-
if parsed_options? && arguments_valid?
|
27
|
+
if parsed_options? && arguments_valid?
|
28
28
|
puts "Start at #{DateTime.now}\n\n" if @options.verbose
|
29
|
-
|
29
|
+
|
30
30
|
output_options if @options.verbose # [Optional]
|
31
|
-
|
32
|
-
process_arguments
|
31
|
+
|
32
|
+
process_arguments
|
33
33
|
process_command
|
34
|
-
|
34
|
+
|
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
39
|
exit 1
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
protected
|
45
|
-
|
45
|
+
|
46
46
|
def parsed_options?
|
47
|
-
|
47
|
+
|
48
48
|
# Specify options
|
49
|
-
opts = OptionParser.new
|
49
|
+
opts = OptionParser.new
|
50
50
|
opts.on('-v', '--version', "Print Version Information") { output_version ; exit 0 }
|
51
51
|
opts.on('-h', '--help',"Show this message") { puts opts ; exit 0 }
|
52
|
-
opts.on('-V', '--verbose',"Verbose Output") { @options.verbose = true }
|
52
|
+
opts.on('-V', '--verbose',"Verbose Output") { @options.verbose = true }
|
53
53
|
#opts.on('-q', '--quiet',"Quiet Output") { @options.quiet = true }
|
54
|
-
|
54
|
+
|
55
55
|
opts.on('-l', '--list [ZONE]', String, "Receive a list of all zones or specify a zone to view") { |zone| @options.zone = zone unless zone.nil?; @options.list = true }
|
56
56
|
opts.on('-n', '--new [ZONE]', String, "Create a new Zone") { |zone| @options.zone = zone unless zone.nil?; @options.new_zone = true }
|
57
57
|
opts.on('-d', '--delete [ZONE]', String, "Delete a Zone") { |zone| @options.zone = zone unless zone.nil?; @options.delete_zone = true }
|
58
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 }
|
59
|
-
|
59
|
+
|
60
60
|
opts.on('-c', '--create', "Create a new record") { @options.create_record = true }
|
61
|
-
|
61
|
+
|
62
62
|
opts.on('-r', '--remove', String, "Remove a record") { |record| @options.remove_record = true }
|
63
63
|
opts.on('-g', '--change', String, "Change a record") { |record| @options.change_record = true }
|
64
|
-
|
64
|
+
|
65
65
|
opts.on('--name [NAME]', String, "Specify a name for a record") { |name| @options.name = name }
|
66
66
|
opts.on('--type [TYPE]', String, "Specify a type for a record") { |dnstype| @options.dnstype = dnstype }
|
67
67
|
opts.on('--ttl [TTL]', String, "Specify a TTL for a record") { |ttl| @options.ttl = ttl }
|
@@ -69,20 +69,21 @@ module Route53
|
|
69
69
|
opts.on('--ident [IDENTIFIER]', String, "Specify a unique identifier for a record") { |ident| @options.ident = ident }
|
70
70
|
opts.on('--values [VALUE1],[VALUE2],[VALUE3]', Array, "Specify one or multiple values for a record") { |value| @options.values = value }
|
71
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 }
|
72
|
-
|
72
|
+
|
73
73
|
opts.on('-m', '--comment [COMMENT]', String, "Provide a comment for this operation") { |comment| @options.comment = comment }
|
74
|
-
|
74
|
+
|
75
75
|
opts.on('--no-wait',"Do not wait for actions to finish syncing.") { @options.nowait = true }
|
76
76
|
opts.on('-s', '--setup',"Run the setup ptogram to create your configuration file.") { @options.setup = true }
|
77
77
|
opts.on('-f', '--file [CONFIGFILE]',String,"Specify a configuration file to use") { |file| @options.file = file }
|
78
|
-
|
78
|
+
|
79
79
|
opts.on('--access [ACCESSKEY]',String,"Specify an access key on the command line.") { |access| @options.access = access }
|
80
80
|
opts.on('--secret [SECRETKEY]',String,"Specify a secret key on the command line. WARNING: Not a good idea") { |secret| @options.secret = secret }
|
81
|
-
|
81
|
+
|
82
82
|
opts.on('--no-upgrade',"Do not automatically upgrade the route53 api spec for this version.") { @options.no_upgrade = true }
|
83
|
-
|
83
|
+
opts.on('-k', '--ssl_no_verify',"set none to ssl veryfy mode ") { @options.ssl_no_verify = true }
|
84
|
+
|
84
85
|
opts.parse!(@arguments) rescue return false
|
85
|
-
|
86
|
+
|
86
87
|
process_options
|
87
88
|
true
|
88
89
|
end
|
@@ -98,17 +99,17 @@ module Route53
|
|
98
99
|
load_config
|
99
100
|
@config['access_key'] = @options.access unless @options.access.nil?
|
100
101
|
@config['secret_key'] = @options.secret unless @options.secret.nil?
|
101
|
-
|
102
|
-
|
102
|
+
|
103
|
+
|
103
104
|
required_options("",["--access-key"]) if @config['access_key'].nil? || @config['access_key'] == ""
|
104
105
|
required_options("",["--secret_key"]) if @config['secret_key'].nil? || @config['secret_key'] == ""
|
105
|
-
|
106
|
+
|
106
107
|
end
|
107
|
-
|
108
|
+
|
108
109
|
def output_options
|
109
110
|
puts "Options:\n"
|
110
|
-
|
111
|
-
@options.marshal_dump.each do |name, val|
|
111
|
+
|
112
|
+
@options.marshal_dump.each do |name, val|
|
112
113
|
puts " #{name} = #{val}"
|
113
114
|
end
|
114
115
|
end
|
@@ -122,7 +123,7 @@ module Route53
|
|
122
123
|
return false
|
123
124
|
end
|
124
125
|
end
|
125
|
-
|
126
|
+
|
126
127
|
# Setup the arguments
|
127
128
|
def process_arguments
|
128
129
|
if @options.new_zone
|
@@ -131,7 +132,7 @@ module Route53
|
|
131
132
|
delete_zone
|
132
133
|
elsif @options.create_record
|
133
134
|
create_record
|
134
|
-
elsif @options.remove_record
|
135
|
+
elsif @options.remove_record
|
135
136
|
remove_record
|
136
137
|
elsif @options.change_record
|
137
138
|
change_record
|
@@ -139,7 +140,7 @@ module Route53
|
|
139
140
|
list
|
140
141
|
end
|
141
142
|
end
|
142
|
-
|
143
|
+
|
143
144
|
def list
|
144
145
|
zones = conn.get_zones(@options.zone)
|
145
146
|
unless zones.nil?
|
@@ -156,7 +157,7 @@ module Route53
|
|
156
157
|
$stderr.puts "ERROR: No Records found for #{@options.zone}"
|
157
158
|
end
|
158
159
|
end
|
159
|
-
|
160
|
+
|
160
161
|
def new_zone
|
161
162
|
if @options.zone
|
162
163
|
new_zone = Route53::Zone.new(@options.zone,nil,conn)
|
@@ -172,7 +173,7 @@ module Route53
|
|
172
173
|
required_options("new zone",["--zone"])
|
173
174
|
end
|
174
175
|
end
|
175
|
-
|
176
|
+
|
176
177
|
def delete_zone
|
177
178
|
if @options.zone
|
178
179
|
records = conn.get_zones(@options.zone)
|
@@ -180,7 +181,7 @@ module Route53
|
|
180
181
|
if records.size > 1
|
181
182
|
records = record_picker(records)
|
182
183
|
end
|
183
|
-
records.each do |r|
|
184
|
+
records.each do |r|
|
184
185
|
puts "Deleting Zone #{r.name}"
|
185
186
|
resp = r.delete_zone
|
186
187
|
pending_wait(resp)
|
@@ -193,10 +194,10 @@ module Route53
|
|
193
194
|
required_options("delete zone",["--zone"])
|
194
195
|
end
|
195
196
|
end
|
196
|
-
|
197
|
+
|
197
198
|
def create_record
|
198
|
-
if @options.zone && @options.name &&
|
199
|
-
@options.dnstype && @options.values &&
|
199
|
+
if @options.zone && @options.name &&
|
200
|
+
@options.dnstype && @options.values &&
|
200
201
|
(@options.ttl || @config['default_ttl'])
|
201
202
|
zones = conn.get_zones(@options.zone)
|
202
203
|
if zones.size > 0
|
@@ -231,7 +232,7 @@ module Route53
|
|
231
232
|
required_options("create record",["--zone","--name","--type","--ttl","--values"])
|
232
233
|
end
|
233
234
|
end
|
234
|
-
|
235
|
+
|
235
236
|
def remove_record
|
236
237
|
if @options.zone
|
237
238
|
zones = conn.get_zones(@options.zone)
|
@@ -243,7 +244,7 @@ module Route53
|
|
243
244
|
if records.size > 1
|
244
245
|
records = record_picker(records)
|
245
246
|
end
|
246
|
-
records.each do |r|
|
247
|
+
records.each do |r|
|
247
248
|
puts "Deleting Record #{r.name}"
|
248
249
|
resp = r.delete
|
249
250
|
pending_wait(resp)
|
@@ -263,7 +264,7 @@ module Route53
|
|
263
264
|
required_options("record removal",["--zone"])
|
264
265
|
end
|
265
266
|
end
|
266
|
-
|
267
|
+
|
267
268
|
def change_record
|
268
269
|
if @options.zone && (@options.name || @options.dnstype || @options.ttl || @options.values)
|
269
270
|
zones = conn.get_zones(@options.zone)
|
@@ -275,7 +276,7 @@ module Route53
|
|
275
276
|
if records.size > 1
|
276
277
|
records = record_picker(records,false)
|
277
278
|
end
|
278
|
-
records.each do |r|
|
279
|
+
records.each do |r|
|
279
280
|
puts "Modifying Record #{r.name}"
|
280
281
|
resp = r.update(@options.name,@options.dnstype,@options.ttl,@options.values,comment=nil)
|
281
282
|
pending_wait(resp)
|
@@ -295,7 +296,7 @@ module Route53
|
|
295
296
|
required_options("record change",["--zone"],["--name","--type","--ttl","--values"])
|
296
297
|
end
|
297
298
|
end
|
298
|
-
|
299
|
+
|
299
300
|
def required_options(operation,required = [],at_least_one = [],optional = [])
|
300
301
|
operation == "" ? operation += " " : operation = " "+operation+" "
|
301
302
|
$stderr.puts "ERROR: The following arguments are required for a#{operation}operation."
|
@@ -304,7 +305,7 @@ module Route53
|
|
304
305
|
$stderr.puts "ERROR: #{optional.join(", ")}are optional." if optional.size > 0
|
305
306
|
exit 1
|
306
307
|
end
|
307
|
-
|
308
|
+
|
308
309
|
def setup
|
309
310
|
puts "You've either elected to run the setup or a configuration file could not be found."
|
310
311
|
puts "Please answer the following prompts."
|
@@ -325,9 +326,9 @@ module Route53
|
|
325
326
|
puts YAML.dump(new_config)
|
326
327
|
exit 0
|
327
328
|
end
|
328
|
-
|
329
|
+
|
329
330
|
end
|
330
|
-
|
331
|
+
|
331
332
|
def get_input(inputtype,description,default = nil)
|
332
333
|
print "#{description}: [#{default}] "
|
333
334
|
STDOUT.flush
|
@@ -341,7 +342,7 @@ module Route53
|
|
341
342
|
end
|
342
343
|
return selection
|
343
344
|
end
|
344
|
-
|
345
|
+
|
345
346
|
def record_picker(records,allowall = true)
|
346
347
|
puts "Please select the record to perform the action on."
|
347
348
|
records.each_with_index do |r,i|
|
@@ -371,40 +372,40 @@ module Route53
|
|
371
372
|
exit 1
|
372
373
|
end
|
373
374
|
end
|
374
|
-
|
375
|
+
|
375
376
|
def pending_wait(resp)
|
376
377
|
while !@options.nowait && resp.pending?
|
377
378
|
print '.'
|
378
|
-
|
379
|
+
|
379
380
|
STDOUT.flush
|
380
381
|
sleep 1
|
381
382
|
end
|
382
383
|
end
|
383
|
-
|
384
|
+
|
384
385
|
def output_version
|
385
386
|
puts "Ruby route53 interface version #{Route53::VERSION}"
|
386
387
|
puts "Written by Philip Corliss (pcorliss@50projects.com)"
|
387
388
|
puts "https://github.com/pcorliss/ruby_route_53"
|
388
389
|
end
|
389
|
-
|
390
|
+
|
390
391
|
def process_command
|
391
392
|
|
392
393
|
end
|
393
394
|
|
394
395
|
def process_standard_input
|
395
|
-
input = @stdin.read
|
396
|
-
#@stdin.each do |line|
|
397
|
-
#
|
396
|
+
input = @stdin.read
|
397
|
+
#@stdin.each do |line|
|
398
|
+
#
|
398
399
|
#end
|
399
400
|
end
|
400
|
-
|
401
|
+
|
401
402
|
def conn
|
402
403
|
if @conn.nil?
|
403
|
-
@conn = Route53::Connection.new(@config['access_key'],@config['secret_key'],@config['api'],@config['endpoint'],@options.verbose)
|
404
|
+
@conn = Route53::Connection.new(@config['access_key'],@config['secret_key'],@config['api'],@config['endpoint'],@options.verbose,@options.ssl_no_verify)
|
404
405
|
end
|
405
406
|
return @conn
|
406
407
|
end
|
407
|
-
|
408
|
+
|
408
409
|
def load_config
|
409
410
|
unless File.exists?(@options.file)
|
410
411
|
setup
|
@@ -422,7 +423,7 @@ module Route53
|
|
422
423
|
File.chmod(0600,@options.file)
|
423
424
|
end
|
424
425
|
end
|
425
|
-
|
426
|
+
|
426
427
|
def user_home
|
427
428
|
homes = ["HOME", "HOMEPATH"]
|
428
429
|
realHome = homes.detect {|h| ENV[h] != nil}
|
data/lib/route53/version.rb
CHANGED
metadata
CHANGED
@@ -1,57 +1,73 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: route53
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 19
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
- 2
|
10
|
+
version: 0.2.2
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Philip Corliss
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
|
18
|
+
date: 2013-11-21 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
15
21
|
name: ruby-hmac
|
16
|
-
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
17
24
|
none: false
|
18
|
-
requirements:
|
19
|
-
- -
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
22
32
|
type: :runtime
|
23
|
-
|
24
|
-
|
25
|
-
- !ruby/object:Gem::Dependency
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
26
35
|
name: hpricot
|
27
|
-
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
28
38
|
none: false
|
29
|
-
requirements:
|
30
|
-
- -
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 3
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
version: "0"
|
33
46
|
type: :runtime
|
34
|
-
|
35
|
-
|
36
|
-
- !ruby/object:Gem::Dependency
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
37
49
|
name: builder
|
38
|
-
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
39
52
|
none: false
|
40
|
-
requirements:
|
41
|
-
- -
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
44
60
|
type: :runtime
|
45
|
-
|
46
|
-
|
47
|
-
description: Provides CRUD and list operations for records and zones as part of Amazon's
|
48
|
-
Route 53 service.
|
61
|
+
version_requirements: *id003
|
62
|
+
description: Provides CRUD and list operations for records and zones as part of Amazon's Route 53 service.
|
49
63
|
email: pcorlis@50projects.com
|
50
|
-
executables:
|
64
|
+
executables:
|
51
65
|
- route53
|
52
66
|
extensions: []
|
67
|
+
|
53
68
|
extra_rdoc_files: []
|
54
|
-
|
69
|
+
|
70
|
+
files:
|
55
71
|
- .gitignore
|
56
72
|
- LICENSE
|
57
73
|
- README.markdown
|
@@ -62,26 +78,38 @@ files:
|
|
62
78
|
- route53.gemspec
|
63
79
|
homepage: http://github.com/pcorliss/ruby_route_53
|
64
80
|
licenses: []
|
81
|
+
|
65
82
|
post_install_message:
|
66
83
|
rdoc_options: []
|
67
|
-
|
84
|
+
|
85
|
+
require_paths:
|
68
86
|
- lib
|
69
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
88
|
none: false
|
71
|
-
requirements:
|
72
|
-
- -
|
73
|
-
- !ruby/object:Gem::Version
|
74
|
-
|
75
|
-
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
hash: 3
|
93
|
+
segments:
|
94
|
+
- 0
|
95
|
+
version: "0"
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
97
|
none: false
|
77
|
-
requirements:
|
78
|
-
- -
|
79
|
-
- !ruby/object:Gem::Version
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
hash: 17
|
102
|
+
segments:
|
103
|
+
- 1
|
104
|
+
- 3
|
105
|
+
- 5
|
80
106
|
version: 1.3.5
|
81
107
|
requirements: []
|
108
|
+
|
82
109
|
rubyforge_project:
|
83
|
-
rubygems_version: 1.8.
|
110
|
+
rubygems_version: 1.8.25
|
84
111
|
signing_key:
|
85
112
|
specification_version: 3
|
86
113
|
summary: Library for Amazon's Route 53 service
|
87
114
|
test_files: []
|
115
|
+
|