devdnsd 1.0.3 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|