route53 0.1.0 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/bin/route53 +10 -0
- data/lib/route53.rb +46 -32
- data/lib/route53/cli.rb +338 -0
- data/lib/route53/version.rb +1 -1
- data/route53.gemspec +4 -4
- metadata +11 -9
data/.gitignore
CHANGED
data/bin/route53
ADDED
data/lib/route53.rb
CHANGED
@@ -1,29 +1,34 @@
|
|
1
|
+
require 'hmac'
|
2
|
+
require 'hmac-sha2'
|
3
|
+
require 'base64'
|
4
|
+
require 'time'
|
5
|
+
require 'net/http'
|
6
|
+
require 'uri'
|
7
|
+
require 'hpricot'
|
8
|
+
require 'builder'
|
9
|
+
require 'digest/md5'
|
10
|
+
|
1
11
|
module Route53
|
2
|
-
require 'hmac'
|
3
|
-
require 'hmac-sha2'
|
4
|
-
require 'base64'
|
5
|
-
require 'time'
|
6
|
-
require 'net/http'
|
7
|
-
require 'uri'
|
8
|
-
require 'hpricot'
|
9
|
-
require 'builder'
|
10
|
-
require 'digest/md5'
|
11
12
|
|
12
13
|
class Connection
|
13
14
|
attr_reader :base_url
|
14
15
|
attr_reader :api
|
15
16
|
attr_reader :endpoint
|
17
|
+
attr_reader :verbose
|
16
18
|
|
17
|
-
def initialize(accesskey,secret,api='2010-10-01',endpoint='https://route53.amazonaws.com/')
|
19
|
+
def initialize(accesskey,secret,api='2010-10-01',endpoint='https://route53.amazonaws.com/',verbose=false)
|
18
20
|
@accesskey = accesskey
|
19
21
|
@secret = secret
|
20
22
|
@api = api
|
21
23
|
@endpoint = endpoint
|
22
24
|
@base_url = endpoint+@api
|
25
|
+
@verbose = verbose
|
23
26
|
end
|
24
27
|
|
25
28
|
def request(url,type = "GET",data = nil)
|
26
|
-
puts "URL: #{url}"
|
29
|
+
puts "URL: #{url}" if @verbose
|
30
|
+
puts "Type: #{type}" if @verbose
|
31
|
+
puts "Req: #{data}" if type != "GET" && @verbose
|
27
32
|
uri = URI(url)
|
28
33
|
http = Net::HTTP.new(uri.host, uri.port)
|
29
34
|
http.use_ssl = true
|
@@ -36,10 +41,10 @@ module Route53
|
|
36
41
|
'X-Amzn-Authorization' => "AWS3-HTTPS AWSAccessKeyId=#{@accesskey},Algorithm=HmacSHA256,Signature=#{signature}",
|
37
42
|
'Content-Type' => 'text/xml; charset=UTF-8'
|
38
43
|
}
|
39
|
-
resp,
|
40
|
-
puts "Resp:"+resp.to_s
|
41
|
-
#puts "
|
42
|
-
return AWSResponse.new(
|
44
|
+
resp, raw_resp = http.send_request(type,uri.path,data,headers)
|
45
|
+
#puts "Resp:"+resp.to_s if @verbose
|
46
|
+
#puts "XML_RESP:"+raw_resp if @verbose
|
47
|
+
return AWSResponse.new(raw_resp,self)
|
43
48
|
end
|
44
49
|
|
45
50
|
def get_zones(name = nil)
|
@@ -69,12 +74,19 @@ module Route53
|
|
69
74
|
|
70
75
|
def get_date
|
71
76
|
#return Time.now.utc.rfc2822
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
77
|
+
#Cache date for 30 seconds to reduce extra calls
|
78
|
+
if @date_stale.nil? || @date_stale < Time.now - 30
|
79
|
+
uri = URI(@endpoint)
|
80
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
81
|
+
http.use_ssl = true
|
82
|
+
resp = nil
|
83
|
+
puts "Making Date Request" if @verbose
|
84
|
+
http.start { |http| resp = http.head('/date') }
|
85
|
+
@date = resp['Date']
|
86
|
+
@date_stale = Time.now
|
87
|
+
puts "Received Date." if @verbose
|
88
|
+
end
|
89
|
+
return @date
|
78
90
|
end
|
79
91
|
|
80
92
|
end
|
@@ -107,7 +119,7 @@ module Route53
|
|
107
119
|
xml_str = ""
|
108
120
|
xml = Builder::XmlMarkup.new(:target=>xml_str, :indent=>2)
|
109
121
|
xml.instruct!
|
110
|
-
xml.CreateHostedZoneRequest(:xmlns => @endpoint+'doc/'+@api+'/') { |create|
|
122
|
+
xml.CreateHostedZoneRequest(:xmlns => @conn.endpoint+'doc/'+@conn.api+'/') { |create|
|
111
123
|
create.Name(@name)
|
112
124
|
# AWS lists this as required
|
113
125
|
# "unique string that identifies the request and that
|
@@ -118,7 +130,7 @@ module Route53
|
|
118
130
|
conf.Comment(comment)
|
119
131
|
}
|
120
132
|
}
|
121
|
-
puts "XML:\n#{xml_str}"
|
133
|
+
#puts "XML:\n#{xml_str}" if @conn.verbose
|
122
134
|
@conn.request(@conn.base_url + "/hostedzone","POST",xml_str)
|
123
135
|
end
|
124
136
|
|
@@ -133,11 +145,11 @@ module Route53
|
|
133
145
|
|
134
146
|
dom_records = []
|
135
147
|
records.each do |record|
|
136
|
-
puts "Name:"+record.search("Name").first.innerText
|
137
|
-
puts "Type:"+record.search("Type").first.innerText
|
138
|
-
puts "TTL:"+record.search("TTL").first.innerText
|
148
|
+
#puts "Name:"+record.search("Name").first.innerText if @conn.verbose
|
149
|
+
#puts "Type:"+record.search("Type").first.innerText if @conn.verbose
|
150
|
+
#puts "TTL:"+record.search("TTL").first.innerText if @conn.verbose
|
139
151
|
record.search("Value").each do |val|
|
140
|
-
puts "Val:"+val.innerText
|
152
|
+
#puts "Val:"+val.innerText if @conn.verbose
|
141
153
|
end
|
142
154
|
dom_records.push(DNSRecord.new(record.search("Name").first.innerText,
|
143
155
|
record.search("Type").first.innerText,
|
@@ -170,7 +182,7 @@ module Route53
|
|
170
182
|
}
|
171
183
|
}
|
172
184
|
}
|
173
|
-
puts "XML:\n#{xml_str}"
|
185
|
+
#puts "XML:\n#{xml_str}" if @conn.verbose
|
174
186
|
return xml_str
|
175
187
|
end
|
176
188
|
|
@@ -195,6 +207,7 @@ module Route53
|
|
195
207
|
$stderr.puts @raw_data
|
196
208
|
end
|
197
209
|
@conn = conn
|
210
|
+
puts "Raw: #{@raw_data}" if @conn.verbose
|
198
211
|
end
|
199
212
|
|
200
213
|
def error?
|
@@ -202,6 +215,7 @@ module Route53
|
|
202
215
|
end
|
203
216
|
|
204
217
|
def complete?
|
218
|
+
return true if error?
|
205
219
|
if @change_url.nil?
|
206
220
|
change = Hpricot::XML(@raw_data).search("ChangeInfo")
|
207
221
|
if change.size > 0
|
@@ -274,10 +288,10 @@ module Route53
|
|
274
288
|
@type = type unless type.nil?
|
275
289
|
@ttl = ttl unless ttl.nil?
|
276
290
|
@values = values unless values.nil?
|
277
|
-
@zone.perform_actions(
|
278
|
-
|
279
|
-
|
280
|
-
|
291
|
+
@zone.perform_actions([
|
292
|
+
{:action => "DELETE", :record => prev},
|
293
|
+
{:action => "CREATE", :record => self},
|
294
|
+
],comment)
|
281
295
|
end
|
282
296
|
|
283
297
|
#Returns the raw array so the developer can update large batches manually
|
data/lib/route53/cli.rb
ADDED
@@ -0,0 +1,338 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
require 'optparse'
|
4
|
+
require 'ostruct'
|
5
|
+
require 'date'
|
6
|
+
require 'yaml'
|
7
|
+
require 'route53/version'
|
8
|
+
|
9
|
+
module Route53
|
10
|
+
class CLI
|
11
|
+
|
12
|
+
attr_reader :options
|
13
|
+
|
14
|
+
def initialize(arguments, stdin)
|
15
|
+
@arguments = arguments
|
16
|
+
@stdin = stdin
|
17
|
+
|
18
|
+
# Set defaults
|
19
|
+
@options = OpenStruct.new
|
20
|
+
@options.verbose = false
|
21
|
+
@options.quiet = false
|
22
|
+
end
|
23
|
+
|
24
|
+
# Parse options, check arguments, then process the command
|
25
|
+
def run
|
26
|
+
if parsed_options? && arguments_valid?
|
27
|
+
puts "Start at #{DateTime.now}\n\n" if @options.verbose
|
28
|
+
|
29
|
+
output_options if @options.verbose # [Optional]
|
30
|
+
|
31
|
+
process_arguments
|
32
|
+
process_command
|
33
|
+
|
34
|
+
puts "\nFinished at #{DateTime.now}" if @options.verbose
|
35
|
+
|
36
|
+
else
|
37
|
+
#puts "Usage Message"
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
def parsed_options?
|
45
|
+
|
46
|
+
# Specify options
|
47
|
+
opts = OptionParser.new
|
48
|
+
opts.on('-v', '--version', "Print Version Information") { output_version ; exit 0 }
|
49
|
+
opts.on('-h', '--help',"Show this message") { puts opts ; exit 0 }
|
50
|
+
opts.on('-V', '--verbose',"Verbose Output") { @options.verbose = true }
|
51
|
+
#opts.on('-q', '--quiet',"Quiet Output") { @options.quiet = true }
|
52
|
+
|
53
|
+
opts.on('-l', '--list [ZONE]', String, "Receive a list of all zones or specify a zone to view") { |zone| @options.zone = zone; @options.list = true }
|
54
|
+
opts.on('-n', '--new [ZONE]', String, "Create a new Zone") { |zone| @options.zone = zone; @options.new_zone = true }
|
55
|
+
opts.on('-d', '--delete [ZONE]', String, "Delete a Zone") { |zone| @options.zone = zone; @options.delete_zone = true }
|
56
|
+
opts.on('-z', '--zone [ZONE]', String, "Specify a zone to perform an operation on") { |zone| @options.zone = zone }
|
57
|
+
|
58
|
+
opts.on('-c', '--create', "Create a new record") { @options.create_record = true }
|
59
|
+
opts.on('-r', '--remove', String, "Remove a record") { |record| @options.remove_record = true }
|
60
|
+
opts.on('-g', '--change', String, "Change a record") { |record| @options.change_record = true }
|
61
|
+
|
62
|
+
opts.on('--name [NAME]', String, "Specify a name for a record") { |name| @options.name = name }
|
63
|
+
opts.on('--type [TYPE]', String, "Specify a type for a record") { |type| @options.type = type }
|
64
|
+
opts.on('--ttl [TTL]', String, "Specify a TTL for a record") { |ttl| @options.ttl = ttl }
|
65
|
+
opts.on('--values [VALUE1],[VALUE2],[VALUE3]', Array, "Specify one or multiple values for a record") { |value| @options.values = value }
|
66
|
+
|
67
|
+
opts.on('-m', '--comment [COMMENT]', String, "Provide a comment for this operation") { |comment| @options.comment = comment }
|
68
|
+
|
69
|
+
opts.on('--no-wait',"Do not wait for actions to finish syncing.") { @options.nowait = true }
|
70
|
+
opts.on('-s', '--setup',"Run the setup ptogram to create your configuration file.") { @options.setup = true }
|
71
|
+
opts.on('-f', '--file [CONFIGFILE]',String,"Specify a configuration file to use") { |file| @options.file = file }
|
72
|
+
|
73
|
+
opts.on('--access [ACCESSKEY]',String,"Specify an access key on the command line.") { |access| @options.access = access }
|
74
|
+
opts.on('--secret [SECRETKEY]',String,"Specify a secret key on the command line. WARNING: Not a good idea") { |secret| @options.secret = secret }
|
75
|
+
|
76
|
+
opts.parse!(@arguments) rescue return false
|
77
|
+
|
78
|
+
process_options
|
79
|
+
true
|
80
|
+
end
|
81
|
+
|
82
|
+
# Performs post-parse processing on options
|
83
|
+
def process_options
|
84
|
+
@options.verbose = false if @options.quiet
|
85
|
+
@options.file = (user_home+"/.route53") if @options.file.nil?
|
86
|
+
#setup file
|
87
|
+
if @options.setup
|
88
|
+
setup
|
89
|
+
end
|
90
|
+
load_config
|
91
|
+
@config['access_key'] = @options.access unless @options.access.nil?
|
92
|
+
@config['secret_key'] = @options.secret unless @options.secret.nil?
|
93
|
+
end
|
94
|
+
|
95
|
+
def output_options
|
96
|
+
puts "Options:\n"
|
97
|
+
|
98
|
+
@options.marshal_dump.each do |name, val|
|
99
|
+
puts " #{name} = #{val}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def arguments_valid?
|
104
|
+
true #if @arguments.length == 1
|
105
|
+
end
|
106
|
+
|
107
|
+
# Setup the arguments
|
108
|
+
def process_arguments
|
109
|
+
|
110
|
+
|
111
|
+
if @options.new_zone
|
112
|
+
new_zone = Route53::Zone.new(@options.zone,nil,conn)
|
113
|
+
puts "Creating New Zone #{@options.zone}"
|
114
|
+
resp = new_zone.create_zone(@options.comment)
|
115
|
+
if resp.error?
|
116
|
+
$stderr.puts "ERROR: Failed to create new zone."
|
117
|
+
else
|
118
|
+
pending_wait(resp)
|
119
|
+
puts "Zone Created."
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
if @options.delete_zone
|
124
|
+
records = conn.get_zones(@options.zone)
|
125
|
+
if records.size > 0
|
126
|
+
if records.size > 1
|
127
|
+
records = record_picker(records)
|
128
|
+
end
|
129
|
+
records.each do |r|
|
130
|
+
puts "Deleting Zone #{r.name}"
|
131
|
+
resp = r.delete_zone
|
132
|
+
pending_wait(resp)
|
133
|
+
puts "Zone Deleted." unless resp.error?
|
134
|
+
end
|
135
|
+
else
|
136
|
+
$stderr.puts "ERROR: Couldn't Find Record for @options.zone."
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
if @options.create_record
|
141
|
+
zones = conn.get_zones(@options.zone)
|
142
|
+
if zones.size > 0
|
143
|
+
resps = []
|
144
|
+
zones.each do |z|
|
145
|
+
puts "Creating Record"
|
146
|
+
record = Route53::DNSRecord.new(@options.name,@options.type,@options.ttl,@options.values,z)
|
147
|
+
puts "Creating Record #{record}"
|
148
|
+
resps.push(record.create)
|
149
|
+
end
|
150
|
+
resps.each do |resp|
|
151
|
+
pending_wait(resp)
|
152
|
+
puts "Record Created." unless resp.error?
|
153
|
+
end
|
154
|
+
else
|
155
|
+
$stderr.puts "ERROR: Couldn't Find Record for @options.zone."
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
if @options.remove_record
|
161
|
+
zones = conn.get_zones(@options.zone)
|
162
|
+
if zones.size > 0
|
163
|
+
zones.each do |z|
|
164
|
+
records = z.get_records(@options.type.nil? ? "ANY" : @options.type)
|
165
|
+
if records.size > 0
|
166
|
+
if records.size > 1
|
167
|
+
records = record_picker(records)
|
168
|
+
end
|
169
|
+
records.each do |r|
|
170
|
+
puts "Deleting Record #{r.name}"
|
171
|
+
resp = r.delete
|
172
|
+
pending_wait(resp)
|
173
|
+
puts "Record Deleted." unless resp.error?
|
174
|
+
end
|
175
|
+
else
|
176
|
+
$stderr.puts "ERROR: Couldn't Find Record for @options.zone of type "+(@options.type.nil? ? "ANY" : @options.type)+"."
|
177
|
+
end
|
178
|
+
end
|
179
|
+
else
|
180
|
+
$stderr.puts "ERROR: Couldn't Find Record for @options.zone."
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
if @options.change_record
|
185
|
+
zones = conn.get_zones(@options.zone)
|
186
|
+
if zones.size > 0
|
187
|
+
zones.each do |z|
|
188
|
+
records = z.get_records(@options.type.nil? ? "ANY" : @options.type)
|
189
|
+
if records.size > 0
|
190
|
+
if records.size > 1
|
191
|
+
records = record_picker(records,false)
|
192
|
+
end
|
193
|
+
records.each do |r|
|
194
|
+
puts "Modifying Record #{r.name}"
|
195
|
+
resp = r.update(@options.name,@options.type,@options.ttl,@options.values,comment=nil)
|
196
|
+
pending_wait(resp)
|
197
|
+
puts "Record Modified." unless resp.error?
|
198
|
+
end
|
199
|
+
else
|
200
|
+
$stderr.puts "ERROR: Couldn't Find Record for @options.zone of type "+(@options.type.nil? ? "ANY" : @options.type)+"."
|
201
|
+
end
|
202
|
+
end
|
203
|
+
else
|
204
|
+
$stderr.puts "ERROR: Couldn't Find Record for @options.zone."
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
if @options.list || @options.zone.nil?
|
209
|
+
zones = conn.get_zones(@options.zone)
|
210
|
+
zones.each do |z|
|
211
|
+
puts z
|
212
|
+
if @options.zone
|
213
|
+
records = z.get_records(@options.type.nil? ? "ANY" : @options.type)
|
214
|
+
records.each do |r|
|
215
|
+
puts r
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def setup
|
223
|
+
puts "You've either elected to run the setup or a configuration file could not be found."
|
224
|
+
puts "Please answer the following prompts."
|
225
|
+
new_config = Hash.new
|
226
|
+
new_config['access_key'] = get_input(String,"Amazon Access Key",)
|
227
|
+
new_config['secret_key'] = get_input(String,"Amazon Secret Key")
|
228
|
+
new_config['api'] = get_input(String,"Amazon Route 53 API Version","2010-10-01")
|
229
|
+
new_config['endpoint'] = get_input(String,"Amazon Route 53 Endpoint","https://route53.amazonaws.com/")
|
230
|
+
if get_input(true.class,"Save the configuration file to \"~/.route53\"?","Y")
|
231
|
+
File.open(@options.file,'w') do |out|
|
232
|
+
YAML.dump(new_config,out)
|
233
|
+
end
|
234
|
+
load_config
|
235
|
+
else
|
236
|
+
puts "Not Saving File. Dumping Config instead."
|
237
|
+
puts YAML.dump(new_config)
|
238
|
+
exit 0
|
239
|
+
end
|
240
|
+
|
241
|
+
end
|
242
|
+
|
243
|
+
def get_input(type,description,default = nil)
|
244
|
+
print "#{description}: [#{default}] "
|
245
|
+
STDOUT.flush
|
246
|
+
selection = gets
|
247
|
+
selection.chomp!
|
248
|
+
if selection == ""
|
249
|
+
selection = default
|
250
|
+
end
|
251
|
+
if type == true.class
|
252
|
+
selection = (selection == 'Y')
|
253
|
+
end
|
254
|
+
return selection
|
255
|
+
end
|
256
|
+
|
257
|
+
def record_picker(records,allowall = true)
|
258
|
+
puts "Please select the record to perform the action on."
|
259
|
+
records.each_with_index do |r,i|
|
260
|
+
puts "[#{i}] #{r}"
|
261
|
+
end
|
262
|
+
puts "[#{records.size}] All" if allowall
|
263
|
+
puts "[#{records.size+1}] None"
|
264
|
+
print "Make a selection: [#{records.size+1}] "
|
265
|
+
STDOUT.flush
|
266
|
+
selection = gets
|
267
|
+
selection.chomp!
|
268
|
+
if selection == ""
|
269
|
+
selection = records.size+1
|
270
|
+
elsif selection != "0" && selection.to_i == 0
|
271
|
+
$stderr.puts "a Invalid selection: #{selection}"
|
272
|
+
exit 1
|
273
|
+
end
|
274
|
+
selection = selection.to_i
|
275
|
+
puts "Received #{selection}"
|
276
|
+
if selection == records.size && allowall
|
277
|
+
return records
|
278
|
+
elsif selection == records.size + 1
|
279
|
+
return []
|
280
|
+
elsif records[selection]
|
281
|
+
return [records[selection]]
|
282
|
+
else
|
283
|
+
$stderr.puts "Invalid selection: #{selection}"
|
284
|
+
exit 1
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def pending_wait(resp)
|
289
|
+
while !@options.nowait && resp.pending?
|
290
|
+
print '.'
|
291
|
+
sleep 1
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
def output_version
|
296
|
+
puts "Ruby route53 interface version #{Route53::VERSION}"
|
297
|
+
puts "Written by Philip Corliss (pcorliss@50projects.com)"
|
298
|
+
puts "https://github.com/pcorliss/ruby_route_53"
|
299
|
+
end
|
300
|
+
|
301
|
+
def process_command
|
302
|
+
|
303
|
+
end
|
304
|
+
|
305
|
+
def process_standard_input
|
306
|
+
input = @stdin.read
|
307
|
+
#@stdin.each do |line|
|
308
|
+
#
|
309
|
+
#end
|
310
|
+
end
|
311
|
+
|
312
|
+
def conn
|
313
|
+
if @conn.nil?
|
314
|
+
@conn = Route53::Connection.new(@config['access_key'],@config['secret_key'],@config['api'],@config['endpoint'],@options.verbose)
|
315
|
+
end
|
316
|
+
return @conn
|
317
|
+
end
|
318
|
+
|
319
|
+
def load_config
|
320
|
+
unless File.exists?(@options.file)
|
321
|
+
setup
|
322
|
+
end
|
323
|
+
@config = YAML.load_file(@options.file)
|
324
|
+
unless @config
|
325
|
+
@config = Hash.new
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
def user_home
|
330
|
+
homes = ["HOME", "HOMEPATH"]
|
331
|
+
realHome = homes.detect {|h| ENV[h] != nil}
|
332
|
+
if not realHome
|
333
|
+
$stderr.puts "Could not find home directory"
|
334
|
+
end
|
335
|
+
return ENV[realHome]
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
data/lib/route53/version.rb
CHANGED
data/route53.gemspec
CHANGED
@@ -13,10 +13,10 @@ Gem::Specification.new do |s|
|
|
13
13
|
|
14
14
|
s.required_rubygems_version = ">= 1.3.6"
|
15
15
|
|
16
|
-
s.
|
17
|
-
s.
|
18
|
-
s.
|
19
|
-
s.
|
16
|
+
s.add_dependency "bundler", ">= 1.0.0"
|
17
|
+
s.add_dependency "ruby-hmac"
|
18
|
+
s.add_dependency "hpricot"
|
19
|
+
s.add_dependency "builder"
|
20
20
|
|
21
21
|
s.files = `git ls-files`.split("\n")
|
22
22
|
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 2
|
9
|
+
version: 0.1.2
|
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: 2010-12-
|
17
|
+
date: 2010-12-09 00:00:00 -06:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -30,7 +30,7 @@ dependencies:
|
|
30
30
|
- 0
|
31
31
|
- 0
|
32
32
|
version: 1.0.0
|
33
|
-
type: :
|
33
|
+
type: :runtime
|
34
34
|
version_requirements: *id001
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: ruby-hmac
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
segments:
|
44
44
|
- 0
|
45
45
|
version: "0"
|
46
|
-
type: :
|
46
|
+
type: :runtime
|
47
47
|
version_requirements: *id002
|
48
48
|
- !ruby/object:Gem::Dependency
|
49
49
|
name: hpricot
|
@@ -56,7 +56,7 @@ dependencies:
|
|
56
56
|
segments:
|
57
57
|
- 0
|
58
58
|
version: "0"
|
59
|
-
type: :
|
59
|
+
type: :runtime
|
60
60
|
version_requirements: *id003
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
name: builder
|
@@ -69,12 +69,12 @@ dependencies:
|
|
69
69
|
segments:
|
70
70
|
- 0
|
71
71
|
version: "0"
|
72
|
-
type: :
|
72
|
+
type: :runtime
|
73
73
|
version_requirements: *id004
|
74
74
|
description: Provides CRUD and list operations for records and zones as part of Amazon's Route 53 service.
|
75
75
|
email: pcorlis@50projects.com
|
76
|
-
executables:
|
77
|
-
|
76
|
+
executables:
|
77
|
+
- route53
|
78
78
|
extensions: []
|
79
79
|
|
80
80
|
extra_rdoc_files: []
|
@@ -85,7 +85,9 @@ files:
|
|
85
85
|
- Gemfile.lock
|
86
86
|
- README.markdown
|
87
87
|
- Rakefile
|
88
|
+
- bin/route53
|
88
89
|
- lib/route53.rb
|
90
|
+
- lib/route53/cli.rb
|
89
91
|
- lib/route53/version.rb
|
90
92
|
- route53.gemspec
|
91
93
|
has_rdoc: true
|