devdnsd 1.0.3 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.DS_Store +0 -0
- data/.travis.yml +3 -0
- data/Gemfile.lock +1 -1
- data/lib/devdnsd/application.rb +23 -21
- data/lib/devdnsd/configuration.rb +6 -6
- data/lib/devdnsd/errors.rb +2 -2
- data/lib/devdnsd/logger.rb +9 -3
- data/lib/devdnsd/rule.rb +4 -4
- data/lib/devdnsd/version.rb +2 -2
- data/spec/devdnsd/application_spec.rb +224 -212
- data/spec/devdnsd/configuration_spec.rb +4 -4
- data/spec/devdnsd/logger_spec.rb +17 -13
- metadata +4 -4
data/.DS_Store
CHANGED
Binary file
|
data/.travis.yml
CHANGED
data/Gemfile.lock
CHANGED
data/lib/devdnsd/application.rb
CHANGED
@@ -52,8 +52,8 @@ module DevDNSd
|
|
52
52
|
@logger = self.get_logger
|
53
53
|
|
54
54
|
rescue DevDNSd::Errors::InvalidConfiguration, DevDNSd::Errors::InvalidRule => e
|
55
|
-
@logger.fatal(e.message)
|
56
|
-
raise SystemExit
|
55
|
+
@logger ? @logger.fatal(e.message) : DevDNSd::Logger.create("STDERR").fatal("Cannot log to #{config.log_file}. Exiting...")
|
56
|
+
raise ::SystemExit
|
57
57
|
end
|
58
58
|
|
59
59
|
self
|
@@ -64,7 +64,7 @@ module DevDNSd
|
|
64
64
|
#
|
65
65
|
# @return [Boolean] `true` if the current platform is MacOS X, `false` otherwise.
|
66
66
|
def is_osx?
|
67
|
-
Config::CONFIG['host_os'] =~ /^darwin/
|
67
|
+
::Config::CONFIG['host_os'] =~ /^darwin/
|
68
68
|
end
|
69
69
|
|
70
70
|
# Gets the current logger of the application.
|
@@ -112,23 +112,24 @@ module DevDNSd
|
|
112
112
|
# @return [Object] The result of stop callbacks.
|
113
113
|
def perform_server
|
114
114
|
RubyDNS::run_server(:listen => [[:udp, @config.address, @config.port.to_integer]]) do
|
115
|
-
self.logger = Application.instance.logger
|
115
|
+
self.logger = DevDNSd::Application.instance.logger
|
116
116
|
|
117
|
-
match(/.+/, Application::
|
117
|
+
match(/.+/, DevDNSd::Application::ANY_CLASSES) do |match_data, transaction|
|
118
118
|
transaction.append_question!
|
119
119
|
|
120
|
-
Application.instance.config.rules.each do |rule|
|
120
|
+
DevDNSd::Application.instance.config.rules.each do |rule|
|
121
121
|
begin
|
122
122
|
# Get the subset of handled class that is valid for the rule
|
123
|
-
resource_classes = Application::ANY_CLASSES & rule.resource_class.ensure_array
|
123
|
+
resource_classes = DevDNSd::Application::ANY_CLASSES & rule.resource_class.ensure_array
|
124
|
+
resource_classes = resource_classes & [transaction.resource_class] if transaction.resource_class != DevDNSd::Application::ANY_REQUEST
|
124
125
|
|
125
126
|
if resource_classes.present? then
|
126
127
|
resource_classes.each do |resource_class| # Now for every class
|
127
128
|
matches = rule.match_host(match_data[0])
|
128
|
-
Application.instance.process_rule(rule, resource_class, rule.is_regexp? ? matches : nil, transaction) if matches
|
129
|
+
DevDNSd::Application.instance.process_rule(rule, resource_class, rule.is_regexp? ? matches : nil, transaction) if matches
|
129
130
|
end
|
130
131
|
end
|
131
|
-
rescue Exception => e
|
132
|
+
rescue ::Exception => e
|
132
133
|
raise e
|
133
134
|
end
|
134
135
|
end
|
@@ -141,11 +142,11 @@ module DevDNSd
|
|
141
142
|
|
142
143
|
# Attach event handlers
|
143
144
|
self.on(:start) do
|
144
|
-
Application.instance.on_start
|
145
|
+
DevDNSd::Application.instance.on_start
|
145
146
|
end
|
146
147
|
|
147
148
|
self.on(:stop) do
|
148
|
-
Application.instance.on_stop
|
149
|
+
DevDNSd::Application.instance.on_stop
|
149
150
|
end
|
150
151
|
end
|
151
152
|
end
|
@@ -158,10 +159,10 @@ module DevDNSd
|
|
158
159
|
# @param transaction [Transaction] The current DNS transaction (http://rubydoc.info/gems/rubydns/RubyDNS/Transaction).
|
159
160
|
# @return A reply for the request if matched, otherwise `false` or `nil`.
|
160
161
|
def process_rule(rule, type, match_data, transaction)
|
161
|
-
is_regex = rule.match.is_a?(Regexp)
|
162
|
+
is_regex = rule.match.is_a?(::Regexp)
|
162
163
|
type = DevDNSd::Rule.resource_class_to_symbol(type)
|
163
164
|
|
164
|
-
Application.instance.logger.debug("Found match on #{rule.match} with type #{type}.")
|
165
|
+
DevDNSd::Application.instance.logger.debug("Found match on #{rule.match} with type #{type}.")
|
165
166
|
|
166
167
|
if !rule.block.nil? then
|
167
168
|
reply = rule.block.call(match_data, type, transaction)
|
@@ -173,7 +174,7 @@ module DevDNSd
|
|
173
174
|
reply = match_data[0].gsub(rule.match, reply.gsub("$", "\\"))
|
174
175
|
end
|
175
176
|
|
176
|
-
Application.instance.logger.debug(reply ? "Reply is #{reply} with type #{type}." : "No reply found.")
|
177
|
+
DevDNSd::Application.instance.logger.debug(reply ? "Reply is #{reply} with type #{type}." : "No reply found.")
|
177
178
|
|
178
179
|
if reply then
|
179
180
|
options = rule.options
|
@@ -261,8 +262,8 @@ module DevDNSd
|
|
261
262
|
|
262
263
|
args = $ARGV ? $ARGV[0, $ARGV.length - 1] : ["A"]
|
263
264
|
|
264
|
-
plist = {"KeepAlive" => true, "Label" => "it.cowtech.devdnsd", "Program" => (Pathname.new(Dir.pwd) + $0).to_s, "ProgramArguments" => args, "RunAtLoad" => true}
|
265
|
-
File.open(launch_agent, "w") {|f|
|
265
|
+
plist = {"KeepAlive" => true, "Label" => "it.cowtech.devdnsd", "Program" => (::Pathname.new(Dir.pwd) + $0).to_s, "ProgramArguments" => args, "RunAtLoad" => true}
|
266
|
+
::File.open(launch_agent, "w") {|f|
|
266
267
|
f.write(plist.to_json)
|
267
268
|
f.flush
|
268
269
|
}
|
@@ -302,7 +303,7 @@ module DevDNSd
|
|
302
303
|
# Remove the resolver
|
303
304
|
begin
|
304
305
|
logger.info("Deleting the resolver #{resolver_file} ...")
|
305
|
-
File.delete(resolver_file)
|
306
|
+
::File.delete(resolver_file)
|
306
307
|
rescue => e
|
307
308
|
logger.warn("Cannot delete the resolver file.")
|
308
309
|
return false
|
@@ -318,7 +319,7 @@ module DevDNSd
|
|
318
319
|
# Delete the launch agent.
|
319
320
|
begin
|
320
321
|
logger.info("Deleting the launch agent #{launch_agent} ...")
|
321
|
-
File.delete(launch_agent)
|
322
|
+
::File.delete(launch_agent)
|
322
323
|
rescue => e
|
323
324
|
logger.warn("Cannot delete the launch agent.")
|
324
325
|
return false
|
@@ -345,10 +346,11 @@ module DevDNSd
|
|
345
346
|
# @param globals [Hash] Global options.
|
346
347
|
# @param locals [Hash] Local command options.
|
347
348
|
# @param args [Array] Extra arguments.
|
349
|
+
# @param force [Boolean] If to force recreation of the instance.
|
348
350
|
# @return [Application] The unique (singleton) instance of the application.
|
349
351
|
def self.instance(globals = {}, locals = {}, args = [], force = false)
|
350
|
-
|
351
|
-
|
352
|
+
@instance = nil if force
|
353
|
+
@instance ||= DevDNSd::Application.new(globals, locals, args)
|
352
354
|
end
|
353
355
|
|
354
356
|
# Runs the application in foreground.
|
@@ -360,7 +362,7 @@ module DevDNSd
|
|
360
362
|
|
361
363
|
# Stops the application.
|
362
364
|
def self.quit
|
363
|
-
EventMachine.stop
|
365
|
+
::EventMachine.stop
|
364
366
|
end
|
365
367
|
end
|
366
368
|
end
|
@@ -45,29 +45,29 @@ module DevDNSd
|
|
45
45
|
@port = 7771
|
46
46
|
@tld = "dev"
|
47
47
|
@log_file = "/var/log/devdnsd.log"
|
48
|
-
@log_level = Logger::INFO
|
48
|
+
@log_level = ::Logger::INFO
|
49
49
|
@rules = []
|
50
50
|
@foreground = false
|
51
51
|
|
52
52
|
if file.present?
|
53
53
|
begin
|
54
54
|
# Open the file
|
55
|
-
path = Pathname.new(file).realpath
|
55
|
+
path = ::Pathname.new(file).realpath
|
56
56
|
application.logger.info("Using configuration file #{path}.") if application
|
57
57
|
self.tap do |config|
|
58
|
-
eval(File.read(path))
|
58
|
+
eval(::File.read(path))
|
59
59
|
end
|
60
60
|
|
61
61
|
@log_file = $stdout if @log_file == "STDOUT"
|
62
62
|
@log_file = $stderr if @log_file == "STDERR"
|
63
|
-
rescue Errno::ENOENT, LoadError
|
64
|
-
rescue Exception => e
|
63
|
+
rescue ::Errno::ENOENT, ::LoadError
|
64
|
+
rescue ::Exception => e
|
65
65
|
raise DevDNSd::Errors::InvalidConfiguration.new("Config file #{file} is not valid.")
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
69
|
# Apply overrides
|
70
|
-
if overrides.is_a?(Hash) then
|
70
|
+
if overrides.is_a?(::Hash) then
|
71
71
|
overrides.each_pair do |k, v|
|
72
72
|
self.send("#{k}=", v) if self.respond_to?("#{k}=") && !v.nil?
|
73
73
|
end
|
data/lib/devdnsd/errors.rb
CHANGED
@@ -8,11 +8,11 @@ module DevDNSd
|
|
8
8
|
# Exceptions for {DevDNSd DevDNSd}.
|
9
9
|
module Errors
|
10
10
|
# This exception is raised if a {Rule Rule} is invalid.
|
11
|
-
class InvalidRule < ArgumentError
|
11
|
+
class InvalidRule < ::ArgumentError
|
12
12
|
end
|
13
13
|
|
14
14
|
# This exception is raised if a {Configuration Configuration} is invalid.
|
15
|
-
class InvalidConfiguration < ArgumentError
|
15
|
+
class InvalidConfiguration < ::ArgumentError
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
data/lib/devdnsd/logger.rb
CHANGED
@@ -32,7 +32,13 @@ module DevDNSd
|
|
32
32
|
# @return [Logger] The new logger.
|
33
33
|
def self.create(file = nil, level = Logger::INFO, formatter = nil)
|
34
34
|
file ||= self.default_file
|
35
|
-
|
35
|
+
|
36
|
+
begin
|
37
|
+
rv = self.new(self.get_real_file(file))
|
38
|
+
rescue
|
39
|
+
raise DevDNSd::Errors::InvalidConfiguration
|
40
|
+
end
|
41
|
+
|
36
42
|
rv.level = level.to_i
|
37
43
|
rv.formatter = formatter || self.default_formatter
|
38
44
|
rv
|
@@ -59,7 +65,7 @@ module DevDNSd
|
|
59
65
|
# The default formatter for logging.
|
60
66
|
# @return [Proc] The default formatter for logging.
|
61
67
|
def self.default_formatter
|
62
|
-
@default_formatter ||= Proc.new {|severity, datetime, progname, msg|
|
68
|
+
@default_formatter ||= ::Proc.new {|severity, datetime, progname, msg|
|
63
69
|
color = case severity
|
64
70
|
when "DEBUG" then :cyan
|
65
71
|
when "INFO" then :green
|
@@ -78,7 +84,7 @@ module DevDNSd
|
|
78
84
|
# The log time of the first logger. This allows to show a `T+0.1234` information into the log.
|
79
85
|
# @return [Time] The log time of the first logger.
|
80
86
|
def self.start_time
|
81
|
-
@start_time ||= Time.now
|
87
|
+
@start_time ||= ::Time.now
|
82
88
|
end
|
83
89
|
end
|
84
90
|
end
|
data/lib/devdnsd/rule.rb
CHANGED
@@ -46,7 +46,7 @@ module DevDNSd
|
|
46
46
|
@block = block
|
47
47
|
|
48
48
|
raise(DevDNSd::Errors::InvalidRule.new("You must specify at least a rule and a host (also via a block). Optionally you can add a record type (default: A) and the options.")) if @reply.blank? && @block.nil?
|
49
|
-
raise(DevDNSd::Errors::InvalidRule.new("You can only use hashs for options.")) if !@options.is_a?(Hash)
|
49
|
+
raise(DevDNSd::Errors::InvalidRule.new("You can only use hashs for options.")) if !@options.is_a?(::Hash)
|
50
50
|
end
|
51
51
|
|
52
52
|
# Returns the resource class(es) for the current rule.
|
@@ -61,7 +61,7 @@ module DevDNSd
|
|
61
61
|
#
|
62
62
|
# @return [Boolean] `true` if the rule is a Regexp, `false` otherwise.
|
63
63
|
def is_regexp?
|
64
|
-
self.match.is_a?(Regexp)
|
64
|
+
self.match.is_a?(::Regexp)
|
65
65
|
end
|
66
66
|
|
67
67
|
# Checks if the rule is a regexp.
|
@@ -88,7 +88,7 @@ module DevDNSd
|
|
88
88
|
# @param block [Proc] An optional block to compute the reply instead of using the `reply_or_type` parameter. In this case `reply_or_type` is used for the type of the request and `type` is ignored.
|
89
89
|
def self.create(match, reply_or_type = nil, type = nil, options = {}, &block)
|
90
90
|
raise(DevDNSd::Errors::InvalidRule.new("You must specify at least a rule and a host (also via a block). Optionally you can add a record type (default: A) and the options.")) if reply_or_type.blank? && block.nil?
|
91
|
-
raise(DevDNSd::Errors::InvalidRule.new("You can only use hashs for options.")) if !options.is_a?(Hash)
|
91
|
+
raise(DevDNSd::Errors::InvalidRule.new("You can only use hashs for options.")) if !options.is_a?(::Hash)
|
92
92
|
|
93
93
|
rv = self.new(match)
|
94
94
|
rv.options = options
|
@@ -122,7 +122,7 @@ module DevDNSd
|
|
122
122
|
|
123
123
|
begin
|
124
124
|
"Resolv::DNS::Resource::IN::#{symbol}".constantize
|
125
|
-
rescue NameError
|
125
|
+
rescue ::NameError
|
126
126
|
raise(DevDNSd::Errors::InvalidRule.new("Invalid resource class #{symbol}."))
|
127
127
|
end
|
128
128
|
end
|
data/lib/devdnsd/version.rb
CHANGED
@@ -11,12 +11,12 @@ describe DevDNSd::Application do
|
|
11
11
|
DevDNSd::Logger.stub(:default_file).and_return("/dev/null")
|
12
12
|
end
|
13
13
|
|
14
|
-
let(:log_file) { "/tmp/devdnsd-test-log-#{Time.now.strftime("%Y%m%d-%H
|
15
|
-
let(:application){
|
16
|
-
let(:executable) { Pathname.new(File.dirname((__FILE__))) + "../../bin/devdnsd" }
|
17
|
-
let(:sample_config) { Pathname.new(File.dirname((__FILE__))) + "../../config/devdnsd_config.sample" }
|
18
|
-
let(:resolver_path) { "/tmp/devdnsd-test-resolver-#{Time.now.strftime("%Y%m%d-%H
|
19
|
-
let(:launch_agent_path) { "/tmp/devdnsd-test-agent-#{Time.now.strftime("%Y%m%d-%H
|
14
|
+
let(:log_file) { "/tmp/devdnsd-test-log-#{Time.now.strftime("%Y%m%d-%H%M%S")}" }
|
15
|
+
let(:application){ DevDNSd::Application.instance({:log_file => log_file}, {}, {}, true) }
|
16
|
+
let(:executable) { ::Pathname.new(::File.dirname((__FILE__))) + "../../bin/devdnsd" }
|
17
|
+
let(:sample_config) { ::Pathname.new(::File.dirname((__FILE__))) + "../../config/devdnsd_config.sample" }
|
18
|
+
let(:resolver_path) { "/tmp/devdnsd-test-resolver-#{Time.now.strftime("%Y%m%d-%H%M%S")}" }
|
19
|
+
let(:launch_agent_path) { "/tmp/devdnsd-test-agent-#{Time.now.strftime("%Y%m%d-%H%M%S")}" }
|
20
20
|
|
21
21
|
describe "#initialize" do
|
22
22
|
it("should setup the logger") do application.logger.should_not be_nil end
|
@@ -24,122 +24,130 @@ describe DevDNSd::Application do
|
|
24
24
|
|
25
25
|
it("should abort with an invalid configuration") do
|
26
26
|
path = "/tmp/devdnsd-test-#{Time.now.strftime("%Y%m%d-%H:%M:%S")}"
|
27
|
-
file = File.new(path, "w")
|
27
|
+
file = ::File.new(path, "w")
|
28
28
|
file.write("config.port = ")
|
29
29
|
file.close
|
30
30
|
|
31
|
-
expect { DevDNSd::Application.new({:config => file.path, :log_file => log_file}) }.to raise_error(SystemExit)
|
32
|
-
File.unlink(path)
|
31
|
+
expect { DevDNSd::Application.new({:config => file.path, :log_file => log_file}) }.to raise_error(::SystemExit)
|
32
|
+
::File.unlink(path)
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
36
|
describe ".run" do
|
37
37
|
it "should run the server" do
|
38
38
|
application.should_receive(:perform_server)
|
39
|
-
|
40
|
-
Thread.start {
|
41
|
-
devdnsd_resolv("match.dev")
|
42
|
-
DevDNSd::Application.quit
|
43
|
-
}
|
44
|
-
|
45
39
|
DevDNSd::Application.run
|
46
40
|
end
|
47
41
|
end
|
48
42
|
|
43
|
+
describe ".quit" do
|
44
|
+
it "should quit the application" do
|
45
|
+
::EventMachine.should_receive(:stop)
|
46
|
+
DevDNSd::Application.quit
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
49
50
|
describe "#perform_server" do
|
51
|
+
let(:application){ DevDNSd::Application.instance({:log_file => log_file, :config => sample_config}, {}, {}, true) }
|
52
|
+
|
50
53
|
before(:each) do
|
51
54
|
DevDNSd::Logger.stub(:default_file).and_return($stdout)
|
52
|
-
end
|
53
55
|
|
54
|
-
it "should run the server" do
|
55
56
|
class DevDNSd::Application
|
56
57
|
def on_start
|
57
|
-
|
58
|
-
devdnsd_resolv("match.dev")
|
59
|
-
DevDNSd::Application.quit
|
60
|
-
end
|
58
|
+
Thread.main[:resolver].wakeup if Thread.main[:resolver].try(:alive?)
|
61
59
|
end
|
62
60
|
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_resolve(host = "match_1.dev", type = "ANY", nameserver = "127.0.0.1", port = 7771, logger = nil)
|
64
|
+
host ||= "match.dev"
|
65
|
+
|
66
|
+
Thread.current[:resolver] = Thread.start {
|
67
|
+
Thread.stop
|
68
|
+
Thread.main[:result] = devdnsd_resolv(host, type, nameserver, port, logger)
|
69
|
+
}
|
70
|
+
|
71
|
+
Thread.current[:server] = Thread.start {
|
72
|
+
sleep(0.1)
|
73
|
+
|
74
|
+
if block_given? then
|
75
|
+
yield
|
76
|
+
else
|
77
|
+
application.perform_server
|
78
|
+
end
|
79
|
+
}
|
80
|
+
|
81
|
+
Thread.current[:resolver].join
|
82
|
+
Thread.kill(Thread.current[:server])
|
83
|
+
Thread.main[:running] = false
|
84
|
+
Thread.main[:result]
|
85
|
+
end
|
63
86
|
|
87
|
+
it "should run the server" do
|
64
88
|
RubyDNS.should_receive(:run_server)
|
65
|
-
|
89
|
+
application.perform_server
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should stop the server" do
|
93
|
+
application.should_receive(:on_stop)
|
94
|
+
|
95
|
+
Thread.new {
|
96
|
+
sleep(1)
|
97
|
+
application.class.quit
|
98
|
+
}
|
99
|
+
|
100
|
+
application.perform_server
|
66
101
|
end
|
67
102
|
|
68
103
|
it "should iterate the rules" do
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
devdnsd_resolv("match.dev")
|
73
|
-
DevDNSd::Application.quit
|
74
|
-
end
|
75
|
-
end
|
104
|
+
test_resolve do
|
105
|
+
application.config.rules.should_receive(:each).at_least(1)
|
106
|
+
application.perform_server
|
76
107
|
end
|
77
|
-
|
78
|
-
DevDNSd::Application.instance.config.rules.should_receive(:each).at_least(1)
|
79
|
-
DevDNSd::Application.instance.perform_server
|
80
108
|
end
|
81
109
|
|
82
110
|
it "should call process_rule" do
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
devdnsd_resolv("match.dev")
|
87
|
-
DevDNSd::Application.quit
|
88
|
-
end
|
89
|
-
end
|
111
|
+
test_resolve do
|
112
|
+
application.should_receive(:process_rule).at_least(1)
|
113
|
+
application.perform_server
|
90
114
|
end
|
91
|
-
|
92
|
-
DevDNSd::Application.instance.should_receive(:process_rule).at_least(1)
|
93
|
-
DevDNSd::Application.instance.perform_server
|
94
115
|
end
|
95
116
|
|
96
117
|
it "should complain about wrong rules" do
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
devdnsd_resolv("invalid.dev")
|
101
|
-
DevDNSd::Application.quit
|
102
|
-
end
|
103
|
-
end
|
118
|
+
test_resolve do
|
119
|
+
application.stub(:process_rule).and_raise(::Exception)
|
120
|
+
expect { application.perform_server }.to raise_exception
|
104
121
|
end
|
105
|
-
|
106
|
-
DevDNSd::Application.instance.stub(:process_rule).and_raise(Exception)
|
107
|
-
expect { DevDNSd::Application.instance.perform_server }.to raise_exception
|
108
122
|
end
|
109
123
|
|
110
124
|
describe "should correctly resolve hostnames" do
|
111
|
-
before(:all) do
|
112
|
-
system("ruby \"#{executable}\" -L 0 -l /dev/null -c \"#{sample_config}\" start > /dev/null 2>&1")
|
113
|
-
end
|
114
|
-
|
115
|
-
after(:all) do
|
116
|
-
system("ruby \"#{executable}\" -L 0 -l /dev/null stop > /dev/null 2>&1")
|
117
|
-
end
|
118
|
-
|
119
125
|
it "basing on a exact pattern" do
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
126
|
+
test_resolve("match_1.dev").should == ["10.0.1.1", :A]
|
127
|
+
test_resolve("match_2.dev").should == ["10.0.2.1", :MX]
|
128
|
+
test_resolve("match_3.dev").should == ["10.0.3.1", :A]
|
129
|
+
test_resolve("match_4.dev").should == ["10.0.4.1", :CNAME]
|
124
130
|
end
|
125
131
|
|
126
132
|
it "basing on a regexp pattern" do
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
133
|
+
test_resolve("match_5_11.dev").should == ["10.0.5.11", :A]
|
134
|
+
test_resolve("match_5_22.dev").should == ["10.0.5.22", :A]
|
135
|
+
test_resolve("match_6_33.dev").should == ["10.0.6.33", :PTR]
|
136
|
+
test_resolve("match_6_44.dev").should == ["10.0.6.44", :PTR]
|
137
|
+
test_resolve("match_7_55.dev").should == ["10.0.7.55", :A]
|
138
|
+
test_resolve("match_7_66.dev").should == ["10.0.7.66", :A]
|
139
|
+
test_resolve("match_8_77.dev").should == ["10.0.8.77", :PTR]
|
140
|
+
test_resolve("match_8_88.dev").should == ["10.0.8.88", :PTR]
|
136
141
|
end
|
137
142
|
|
138
|
-
it "and return multiple
|
143
|
+
it "and return multiple or only relevant answsers" do
|
144
|
+
test_resolve("match_10.dev").should == [["10.0.10.1", :A], ["10.0.10.2", :MX]]
|
145
|
+
test_resolve("match_10.dev", "MX").should == ["10.0.10.2", :MX]
|
146
|
+
end
|
139
147
|
|
140
148
|
it "and reject invalid matches (with or without rules)" do
|
141
|
-
|
142
|
-
|
149
|
+
test_resolve("match_9.dev").should be_nil
|
150
|
+
test_resolve("invalid.dev").should be_nil
|
143
151
|
end
|
144
152
|
end
|
145
153
|
end
|
@@ -157,7 +165,7 @@ describe DevDNSd::Application do
|
|
157
165
|
end
|
158
166
|
end
|
159
167
|
|
160
|
-
let(:application){ DevDNSd::Application.
|
168
|
+
let(:application){ DevDNSd::Application.instance({:log_file => log_file, :config => sample_config}, {}, {}, true) }
|
161
169
|
let(:transaction){ FakeTransaction.new }
|
162
170
|
|
163
171
|
it "should match a valid string request" do
|
@@ -180,7 +188,6 @@ describe DevDNSd::Application do
|
|
180
188
|
application.process_rule(rule, rule.resource_class, nil, transaction).should be_true
|
181
189
|
end
|
182
190
|
|
183
|
-
|
184
191
|
it "should match a valid regexp request" do
|
185
192
|
rule = application.config.rules[4]
|
186
193
|
mo = rule.match_host("match_5_12.dev")
|
@@ -229,115 +236,118 @@ describe DevDNSd::Application do
|
|
229
236
|
it "should return the resolver file basing on the argument" do application.resolver_path("foo").should == "/etc/resolver/foo" end
|
230
237
|
end
|
231
238
|
|
232
|
-
describe "launch_agent_path" do
|
239
|
+
describe "#launch_agent_path" do
|
233
240
|
it "should return the agent file with a default name" do application.launch_agent_path.should == ENV["HOME"] + "/Library/LaunchAgents/it.cowtech.devdnsd.plist" end
|
234
241
|
it "should return the agent file with a specified name" do application.launch_agent_path("foo").should == ENV["HOME"] + "/Library/LaunchAgents/foo.plist" end
|
235
242
|
end
|
236
243
|
|
237
244
|
describe "#action_start" do
|
238
245
|
it "should call perform_server in foreground" do
|
239
|
-
DevDNSd::Application.instance({}, {:foreground => true}, [], true)
|
246
|
+
application = DevDNSd::Application.instance({:log_file => log_file}, {:foreground => true}, [], true)
|
247
|
+
application.should_receive(:perform_server)
|
240
248
|
application.action_start
|
241
249
|
end
|
242
250
|
|
243
251
|
it "should start the daemon" do
|
244
|
-
DevDNSd::Application.instance({:log_file => log_file}, {}, [], true)
|
245
|
-
RExec::Daemon::Controller.should_receive(:start)
|
252
|
+
application = DevDNSd::Application.instance({:log_file => log_file}, {}, [], true)
|
253
|
+
::RExec::Daemon::Controller.should_receive(:start)
|
246
254
|
application.action_start
|
247
255
|
end
|
248
256
|
end
|
249
257
|
|
250
258
|
describe "#action_stop" do
|
251
259
|
it "should stop the daemon" do
|
252
|
-
RExec::Daemon::Controller.should_receive(:stop)
|
260
|
+
::RExec::Daemon::Controller.should_receive(:stop)
|
253
261
|
application.action_stop
|
254
262
|
end
|
255
263
|
end
|
256
264
|
|
257
265
|
describe "#action_install" do
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
266
|
+
if ::Config::CONFIG['host_os'] =~ /^darwin/ then
|
267
|
+
it "should create the resolver" do
|
268
|
+
application.stub(:resolver_path).and_return(resolver_path)
|
269
|
+
application.stub(:launch_agent_path).and_return(launch_agent_path)
|
270
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
271
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
272
|
+
|
273
|
+
application.action_install
|
274
|
+
::File.exists?(resolver_path).should be_true
|
275
|
+
|
276
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
277
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
278
|
+
end
|
270
279
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
280
|
+
it "should create the agent" do
|
281
|
+
application.stub(:resolver_path).and_return(resolver_path)
|
282
|
+
application.stub(:launch_agent_path).and_return(launch_agent_path)
|
283
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
284
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
276
285
|
|
277
|
-
|
278
|
-
|
279
|
-
|
286
|
+
application.stub(:resolver_path).and_return(resolver_path)
|
287
|
+
application.action_install
|
288
|
+
::File.exists?(application.launch_agent_path).should be_true
|
280
289
|
|
281
|
-
|
282
|
-
|
283
|
-
|
290
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
291
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
292
|
+
end
|
284
293
|
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
294
|
+
it "should update the DNS cache" do
|
295
|
+
application.stub(:resolver_path).and_return(resolver_path)
|
296
|
+
application.stub(:launch_agent_path).and_return(launch_agent_path)
|
297
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
298
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
290
299
|
|
291
|
-
|
292
|
-
|
300
|
+
application.should_receive(:dns_update)
|
301
|
+
application.action_install
|
293
302
|
|
294
|
-
|
295
|
-
|
296
|
-
|
303
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
304
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
305
|
+
end
|
297
306
|
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
307
|
+
it "should not create and invalid logger" do
|
308
|
+
application.stub(:resolver_path).and_return("/invalid/resolver")
|
309
|
+
application.stub(:launch_agent_path).and_return("/invalid/agent")
|
310
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
311
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
303
312
|
|
304
|
-
|
305
|
-
|
313
|
+
application.get_logger.should_receive(:error).with("Cannot create the resolver file.")
|
314
|
+
application.action_install
|
306
315
|
|
307
|
-
|
308
|
-
|
309
|
-
|
316
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
317
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
318
|
+
end
|
310
319
|
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
320
|
+
it "should not create and invalid agent" do
|
321
|
+
application.stub(:resolver_path).and_return(resolver_path)
|
322
|
+
application.stub(:launch_agent_path).and_return("/invalid/agent")
|
323
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
324
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
316
325
|
|
317
|
-
|
318
|
-
|
326
|
+
application.get_logger.should_receive(:error).with("Cannot create the launch agent.")
|
327
|
+
application.action_install
|
319
328
|
|
320
|
-
|
321
|
-
|
322
|
-
|
329
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
330
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
331
|
+
end
|
323
332
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
333
|
+
it "should not load an invalid agent" do
|
334
|
+
class DevDNSd::Application
|
335
|
+
def execute_command(command)
|
336
|
+
command =~ /^launchctl/ ? raise(StandardError) : system(command)
|
337
|
+
end
|
328
338
|
end
|
329
|
-
end
|
330
339
|
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
340
|
+
application.stub(:resolver_path).and_return(resolver_path)
|
341
|
+
application.stub(:launch_agent_path).and_return(launch_agent_path)
|
342
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
343
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
335
344
|
|
336
|
-
|
337
|
-
|
345
|
+
application.get_logger.should_receive(:error).with("Cannot load the launch agent.")
|
346
|
+
application.action_install
|
338
347
|
|
339
|
-
|
340
|
-
|
348
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
349
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
350
|
+
end
|
341
351
|
end
|
342
352
|
|
343
353
|
it "should raise an exception if not running on OSX" do
|
@@ -348,84 +358,86 @@ describe DevDNSd::Application do
|
|
348
358
|
end
|
349
359
|
|
350
360
|
describe "#action_uninstall" do
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
361
|
+
if ::Config::CONFIG['host_os'] =~ /^darwin/ then
|
362
|
+
it "should remove the resolver" do
|
363
|
+
application.stub(:resolver_path).and_return(resolver_path)
|
364
|
+
application.stub(:launch_agent_path).and_return(launch_agent_path)
|
365
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
366
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
367
|
+
|
368
|
+
application.action_install
|
369
|
+
application.action_uninstall
|
370
|
+
::File.exists?(resolver_path).should be_false
|
371
|
+
|
372
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
373
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
374
|
+
end
|
364
375
|
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
376
|
+
it "should remove the agent" do
|
377
|
+
application.stub(:resolver_path).and_return(resolver_path)
|
378
|
+
application.stub(:launch_agent_path).and_return(launch_agent_path)
|
379
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
380
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
370
381
|
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
382
|
+
DevDNSd::Logger.stub(:default_file).and_return($stdout)
|
383
|
+
application.action_install
|
384
|
+
application.action_uninstall
|
385
|
+
::File.exists?(application.launch_agent_path).should be_false
|
375
386
|
|
376
|
-
|
377
|
-
|
378
|
-
|
387
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
388
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
389
|
+
end
|
379
390
|
|
380
|
-
|
381
|
-
|
382
|
-
|
391
|
+
it "should not load delete an invalid resolver" do
|
392
|
+
application.stub(:resolver_path).and_return("/invalid/resolver")
|
393
|
+
application.stub(:launch_agent_path).and_return("/invalid/agent")
|
383
394
|
|
384
|
-
|
385
|
-
|
386
|
-
|
395
|
+
application.action_install
|
396
|
+
application.get_logger.should_receive(:warn).at_least(1)
|
397
|
+
application.action_uninstall
|
387
398
|
|
388
|
-
|
389
|
-
|
390
|
-
|
399
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
400
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
401
|
+
end
|
391
402
|
|
392
|
-
|
393
|
-
|
394
|
-
|
403
|
+
it "should not delete an invalid agent" do
|
404
|
+
application.stub(:resolver_path).and_return(resolver_path)
|
405
|
+
application.stub(:launch_agent_path).and_return("/invalid/agent")
|
395
406
|
|
396
|
-
|
397
|
-
|
398
|
-
|
407
|
+
application.action_install
|
408
|
+
application.get_logger.should_receive(:warn).at_least(1)
|
409
|
+
application.action_uninstall
|
399
410
|
|
400
|
-
|
401
|
-
|
402
|
-
|
411
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
412
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
413
|
+
end
|
403
414
|
|
404
|
-
|
405
|
-
|
406
|
-
|
415
|
+
it "should not load delete invalid agent" do
|
416
|
+
application.stub(:resolver_path).and_return(resolver_path)
|
417
|
+
application.stub(:launch_agent_path).and_return("/invalid/agent")
|
407
418
|
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
419
|
+
application.action_install
|
420
|
+
application.stub(:execute_command).and_raise(StandardError)
|
421
|
+
application.get_logger.should_receive(:warn).at_least(1)
|
422
|
+
application.action_uninstall
|
412
423
|
|
413
|
-
|
414
|
-
|
415
|
-
|
424
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
425
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
426
|
+
end
|
416
427
|
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
428
|
+
it "should update the DNS cache" do
|
429
|
+
application.stub(:resolver_path).and_return(resolver_path)
|
430
|
+
application.stub(:launch_agent_path).and_return(launch_agent_path)
|
431
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
432
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
422
433
|
|
423
|
-
|
424
|
-
|
425
|
-
|
434
|
+
application.action_install
|
435
|
+
application.should_receive(:dns_update)
|
436
|
+
application.action_uninstall
|
426
437
|
|
427
|
-
|
428
|
-
|
438
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
439
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
440
|
+
end
|
429
441
|
end
|
430
442
|
|
431
443
|
it "should raise an exception if not running on OSX" do
|
@@ -29,13 +29,13 @@ describe DevDNSd::Configuration do
|
|
29
29
|
config.port.should == 7771
|
30
30
|
config.tld.should == "dev"
|
31
31
|
config.log_file.should == "/var/log/devdnsd.log"
|
32
|
-
config.log_level.should == Logger::INFO
|
32
|
+
config.log_level.should == ::Logger::INFO
|
33
33
|
config.rules.count.should == 1
|
34
34
|
config.foreground.should == false
|
35
35
|
end
|
36
36
|
|
37
37
|
it "reads a valid configuration file" do
|
38
|
-
file = Tempfile.new('devdnsd-test')
|
38
|
+
file = ::Tempfile.new('devdnsd-test')
|
39
39
|
file.write("config.port = 7772")
|
40
40
|
file.close
|
41
41
|
|
@@ -45,7 +45,7 @@ describe DevDNSd::Configuration do
|
|
45
45
|
end
|
46
46
|
|
47
47
|
it "reject an invalid configuration" do
|
48
|
-
file = Tempfile.new('devdnsd-test')
|
48
|
+
file = ::Tempfile.new('devdnsd-test')
|
49
49
|
file.write("config.port = ")
|
50
50
|
file.close
|
51
51
|
|
@@ -54,7 +54,7 @@ describe DevDNSd::Configuration do
|
|
54
54
|
end
|
55
55
|
|
56
56
|
it "allows overrides" do
|
57
|
-
file = Tempfile.new('devdnsd-test')
|
57
|
+
file = ::Tempfile.new('devdnsd-test')
|
58
58
|
file.write("config.port = 7772")
|
59
59
|
file.close
|
60
60
|
|
data/spec/devdnsd/logger_spec.rb
CHANGED
@@ -15,28 +15,32 @@ describe DevDNSd::Logger do
|
|
15
15
|
it("should create a new default logger") do
|
16
16
|
logger = DevDNSd::Logger.create
|
17
17
|
logger.device.should == DevDNSd::Logger.default_file
|
18
|
-
logger.level.should == Logger::INFO
|
18
|
+
logger.level.should == ::Logger::INFO
|
19
19
|
logger.formatter.should == DevDNSd::Logger.default_formatter
|
20
20
|
end
|
21
21
|
|
22
22
|
it("should create a logger with a custom file and level") do
|
23
|
-
logger = DevDNSd::Logger.create("/dev/null", Logger::WARN)
|
23
|
+
logger = DevDNSd::Logger.create("/dev/null", ::Logger::WARN)
|
24
24
|
logger.device.should == "/dev/null"
|
25
|
-
logger.level.should == Logger::WARN
|
25
|
+
logger.level.should == ::Logger::WARN
|
26
26
|
logger.formatter.should == DevDNSd::Logger.default_formatter
|
27
27
|
end
|
28
28
|
|
29
29
|
it("should create a logger with a custom formatter") do
|
30
30
|
formatter = Proc.new {|severity, datetime, progname, msg| msg }
|
31
|
-
logger = DevDNSd::Logger.create("/dev/null", Logger::WARN, formatter)
|
31
|
+
logger = DevDNSd::Logger.create("/dev/null", ::Logger::WARN, formatter)
|
32
32
|
logger.device.should == "/dev/null"
|
33
|
-
logger.level.should == Logger::WARN
|
33
|
+
logger.level.should == ::Logger::WARN
|
34
34
|
logger.formatter.should == formatter
|
35
35
|
end
|
36
|
+
|
37
|
+
it("should raise exceptions for invalid files") do
|
38
|
+
expect { DevDNSd::Logger.create("/invalid/file") }.to raise_error(DevDNSd::Errors::InvalidConfiguration)
|
39
|
+
end
|
36
40
|
end
|
37
41
|
|
38
42
|
describe ".default_formatter" do
|
39
|
-
let(:output) { StringIO.new }
|
43
|
+
let(:output) { ::StringIO.new }
|
40
44
|
let(:logger) { DevDNSd::Logger.create(output, Logger::DEBUG) }
|
41
45
|
|
42
46
|
def get_last_line(buffer)
|
@@ -45,32 +49,32 @@ describe DevDNSd::Logger do
|
|
45
49
|
|
46
50
|
it "should correctly format a DEBUG message" do
|
47
51
|
logger.debug("Message.")
|
48
|
-
get_last_line(output).should == "[#{Time.now.strftime("%Y/%b/%d %H:%M:%S")}] DEBUG: Message."
|
52
|
+
get_last_line(output).should == "[#{::Time.now.strftime("%Y/%b/%d %H:%M:%S")}] DEBUG: Message."
|
49
53
|
end
|
50
54
|
|
51
55
|
it "should correctly format a INFO message" do
|
52
56
|
logger.info("Message.")
|
53
|
-
get_last_line(output).should == "[#{Time.now.strftime("%Y/%b/%d %H:%M:%S")}] INFO: Message."
|
57
|
+
get_last_line(output).should == "[#{::Time.now.strftime("%Y/%b/%d %H:%M:%S")}] INFO: Message."
|
54
58
|
end
|
55
59
|
|
56
60
|
it "should correctly format a WARN message" do
|
57
61
|
logger.warn("Message.")
|
58
|
-
get_last_line(output).should == "[#{Time.now.strftime("%Y/%b/%d %H:%M:%S")}] WARN: Message."
|
62
|
+
get_last_line(output).should == "[#{::Time.now.strftime("%Y/%b/%d %H:%M:%S")}] WARN: Message."
|
59
63
|
end
|
60
64
|
|
61
65
|
it "should correctly format a ERROR message" do
|
62
66
|
logger.error("Message.")
|
63
|
-
get_last_line(output).should == "[#{Time.now.strftime("%Y/%b/%d %H:%M:%S")}] ERROR: Message."
|
67
|
+
get_last_line(output).should == "[#{::Time.now.strftime("%Y/%b/%d %H:%M:%S")}] ERROR: Message."
|
64
68
|
end
|
65
69
|
|
66
70
|
it "should correctly format a FATAL message" do
|
67
71
|
logger.fatal("Message.")
|
68
|
-
get_last_line(output).should == "[#{Time.now.strftime("%Y/%b/%d %H:%M:%S")}] FATAL: Message."
|
72
|
+
get_last_line(output).should == "[#{::Time.now.strftime("%Y/%b/%d %H:%M:%S")}] FATAL: Message."
|
69
73
|
end
|
70
74
|
|
71
75
|
it "should correctly format a INVALID message" do
|
72
|
-
logger.log(Logger::UNKNOWN, "Message.")
|
73
|
-
get_last_line(output).should == "[#{Time.now.strftime("%Y/%b/%d %H:%M:%S")}] ANY: Message."
|
76
|
+
logger.log(::Logger::UNKNOWN, "Message.")
|
77
|
+
get_last_line(output).should == "[#{::Time.now.strftime("%Y/%b/%d %H:%M:%S")}] ANY: Message."
|
74
78
|
end
|
75
79
|
end
|
76
80
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devdnsd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rubydns
|
@@ -266,7 +266,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
266
266
|
version: '0'
|
267
267
|
segments:
|
268
268
|
- 0
|
269
|
-
hash:
|
269
|
+
hash: 97728399073097527
|
270
270
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
271
271
|
none: false
|
272
272
|
requirements:
|
@@ -275,7 +275,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
275
275
|
version: '0'
|
276
276
|
segments:
|
277
277
|
- 0
|
278
|
-
hash:
|
278
|
+
hash: 97728399073097527
|
279
279
|
requirements: []
|
280
280
|
rubyforge_project: devdnsd
|
281
281
|
rubygems_version: 1.8.24
|