devdnsd 3.1.2 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -2
- data/.rubocop.yml +82 -0
- data/.travis-gemfile +4 -10
- data/.travis.yml +11 -5
- data/CHANGELOG.md +11 -0
- data/Gemfile +9 -8
- data/README.md +4 -5
- data/Rakefile +22 -6
- data/bin/devdnsd +42 -36
- data/config/devdnsd_config.sample +11 -11
- data/devdnsd.gemspec +7 -6
- data/doc/DevDNSd.html +6 -6
- data/doc/DevDNSd/{ApplicationMethods/Aliases.html → Aliases.html} +96 -100
- data/doc/DevDNSd/Application.html +2170 -1084
- data/doc/DevDNSd/Configuration.html +63 -33
- data/doc/DevDNSd/Errors.html +3 -3
- data/doc/DevDNSd/Errors/InvalidRule.html +3 -3
- data/doc/DevDNSd/{ApplicationMethods/System.html → OSX.html} +116 -489
- data/doc/DevDNSd/Rule.html +448 -749
- data/doc/DevDNSd/{ApplicationMethods/Server.html → Server.html} +77 -73
- data/doc/DevDNSd/System.html +895 -0
- data/doc/DevDNSd/Version.html +6 -6
- data/doc/_index.html +28 -27
- data/doc/class_list.html +6 -2
- data/doc/file.README.html +8 -9
- data/doc/file_list.html +5 -1
- data/doc/frames.html +1 -1
- data/doc/index.html +8 -9
- data/doc/js/full_list.js +4 -1
- data/doc/method_list.html +106 -84
- data/doc/top-level-namespace.html +3 -3
- data/lib/devdnsd.rb +10 -8
- data/lib/devdnsd/aliases.rb +171 -0
- data/lib/devdnsd/application.rb +93 -704
- data/lib/devdnsd/configuration.rb +20 -11
- data/lib/devdnsd/errors.rb +1 -1
- data/lib/devdnsd/osx.rb +217 -0
- data/lib/devdnsd/rule.rb +65 -94
- data/lib/devdnsd/server.rb +118 -0
- data/lib/devdnsd/system.rb +102 -0
- data/lib/devdnsd/version.rb +3 -3
- data/locales/en.yml +17 -16
- data/locales/it.yml +17 -16
- data/spec/devdnsd/application_spec.rb +188 -184
- data/spec/devdnsd/configuration_spec.rb +2 -2
- data/spec/devdnsd/rule_spec.rb +33 -34
- data/spec/resolver_helper.rb +10 -27
- data/spec/spec_helper.rb +21 -7
- metadata +36 -21
- data/doc/DevDNSd/ApplicationMethods.html +0 -125
- data/doc/DevDNSd/ApplicationMethods/System/ClassMethods.html +0 -538
- data/spec/coverage_helper.rb +0 -20
@@ -0,0 +1,118 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the devdnsd gem. Copyright (C) 2013 and above Shogun <shogun@cowtech.it>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
# A small DNS server to enable local .dev domain resolution.
|
8
|
+
module DevDNSd
|
9
|
+
# Methods to process requests.
|
10
|
+
module Server
|
11
|
+
# Starts the DNS server.
|
12
|
+
#
|
13
|
+
# @return [Object] The result of stop callbacks.
|
14
|
+
def perform_server
|
15
|
+
application = self
|
16
|
+
|
17
|
+
@server = RubyDNS.run_server(server_options) do
|
18
|
+
self.logger = application.logger
|
19
|
+
|
20
|
+
match(/.+/, DevDNSd::Application::ANY_CLASSES) do |transaction, match_data|
|
21
|
+
# During debugging, wrap the inside of the block with a begin rescue and PRINT the exception because RubyDNS hides it.
|
22
|
+
application.config.rules.each { |rule| application.process_rule_in_classes(rule, match_data, transaction) }
|
23
|
+
end
|
24
|
+
|
25
|
+
# Default DNS handler and event handlers
|
26
|
+
otherwise { |transaction| transaction.failure!(:NXDomain) }
|
27
|
+
on(:start) { application.on_start }
|
28
|
+
on(:stop) { application.on_stop }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
alias_method :startup, :perform_server
|
33
|
+
|
34
|
+
# Processes a DNS rule.
|
35
|
+
#
|
36
|
+
# @param rule [Rule] The rule to process.
|
37
|
+
# @param type [Symbol] The type of the query.
|
38
|
+
# @param match_data [MatchData|nil] If the rule pattern was a Regexp, then this holds the match data, otherwise `nil` is passed.
|
39
|
+
# @param transaction [RubyDNS::Transaction] The current DNS transaction (http://rubydoc.info/gems/rubydns/RubyDNS/Transaction).
|
40
|
+
def process_rule(rule, type, match_data, transaction)
|
41
|
+
reply, type = perform_process_rule(rule, type, match_data, transaction)
|
42
|
+
logger.debug(reply ? i18n.reply(reply, type) : i18n.no_reply)
|
43
|
+
|
44
|
+
if reply
|
45
|
+
transaction.respond!(*finalize_reply(reply, rule, type))
|
46
|
+
else
|
47
|
+
reply.is_a?(FalseClass) ? false : nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Processes a rule against a set of DNS resource classes.
|
52
|
+
#
|
53
|
+
# @param rule [Rule] The rule to process.
|
54
|
+
# @param match_data [MatchData|nil] If the rule pattern was a Regexp, then this holds the match data, otherwise `nil` is passed.
|
55
|
+
# @param transaction [RubyDNS::Transaction] The current DNS transaction (http://rubydoc.info/gems/rubydns/RubyDNS/Transaction).
|
56
|
+
def process_rule_in_classes(rule, match_data, transaction)
|
57
|
+
# Get the subset of handled class that is valid for the rule
|
58
|
+
resource_classes = DevDNSd::Application::ANY_CLASSES & rule.resource_class.ensure_array
|
59
|
+
resource_classes &= [transaction.resource_class] if transaction.resource_class != DevDNSd::Application::ANY_REQUEST
|
60
|
+
|
61
|
+
if resource_classes.present?
|
62
|
+
resource_classes.each do |resource_class| # Now for every class
|
63
|
+
matches = rule.match_host(match_data[0])
|
64
|
+
process_rule(rule, resource_class, rule.regexp? ? matches : nil, transaction) if matches
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
# :nodoc:
|
72
|
+
def server_options
|
73
|
+
{asynchronous: !@config.foreground, listen: build_listen_interfaces}
|
74
|
+
end
|
75
|
+
|
76
|
+
# :nodoc:
|
77
|
+
def build_listen_interfaces
|
78
|
+
port = @config.port.to_integer
|
79
|
+
@config.bind_addresses.ensure_array { |address| [:udp, address, port] } + @config.bind_addresses.ensure_array { |address| [:tcp, address, port] }
|
80
|
+
end
|
81
|
+
|
82
|
+
# :nodoc:
|
83
|
+
def perform_process_rule(rule, type, match_data, transaction)
|
84
|
+
type = DevDNSd::Rule.resource_class_to_symbol(type)
|
85
|
+
reply = execute_rule(transaction, rule, type, match_data)
|
86
|
+
|
87
|
+
logger.debug(i18n.match(rule.match, type))
|
88
|
+
[reply, type]
|
89
|
+
end
|
90
|
+
|
91
|
+
# :nodoc:
|
92
|
+
def execute_rule(transaction, rule, type, match_data)
|
93
|
+
reply = rule.block ? rule.block.call(match_data, type, transaction) : rule.reply
|
94
|
+
reply = match_data[0].gsub(rule.match, reply.gsub("$", "\\")) if rule.match.is_a?(::Regexp) && reply && match_data && match_data[0]
|
95
|
+
reply
|
96
|
+
end
|
97
|
+
|
98
|
+
# :nodoc:
|
99
|
+
def finalize_reply(reply, rule, type)
|
100
|
+
rv = []
|
101
|
+
rv << rule.options.delete(:priority).to_integer(10) if type == :MX
|
102
|
+
rv << ([:A, :AAAA].include?(type) ? reply : Resolv::DNS::Name.create(reply))
|
103
|
+
rv << prepare_reply_options(rule, type)
|
104
|
+
rv
|
105
|
+
end
|
106
|
+
|
107
|
+
# :nodoc:
|
108
|
+
def prepare_reply_options(rule, type)
|
109
|
+
rule.options.merge({resource_class: DevDNSd::Rule.symbol_to_resource_class(type, @locale), ttl: validate_ttl(rule.options.delete(:ttl))})
|
110
|
+
end
|
111
|
+
|
112
|
+
# :nodoc:
|
113
|
+
def validate_ttl(current, default = 300)
|
114
|
+
current = current.to_integer
|
115
|
+
current > 0 ? current : default
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the devdnsd gem. Copyright (C) 2013 and above Shogun <shogun@cowtech.it>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
# A small DNS server to enable local .dev domain resolution.
|
8
|
+
module DevDNSd
|
9
|
+
# System management methods.
|
10
|
+
module System
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
# Returns the name of the daemon.
|
14
|
+
#
|
15
|
+
# @return [String] The name of the daemon.
|
16
|
+
def daemon_name
|
17
|
+
config ? File.basename(config.pid_file, ".pid") : "devdnsd"
|
18
|
+
end
|
19
|
+
|
20
|
+
alias_method :name, :daemon_name
|
21
|
+
|
22
|
+
# Returns the standard location of the PID file.
|
23
|
+
#
|
24
|
+
# @return [String] The standard location of the PID file.
|
25
|
+
def working_directory
|
26
|
+
config ? File.dirname(config.pid_file) : Dir.pwd
|
27
|
+
end
|
28
|
+
alias_method :runtime_directory, :working_directory
|
29
|
+
|
30
|
+
# Returns the complete path of the PID file.
|
31
|
+
#
|
32
|
+
# @return [String] The complete path of the PID file.
|
33
|
+
def process_file_path
|
34
|
+
config ? config.pid_file : Dir.pwd + "devdnsd.pid"
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns the complete path of the log file.
|
38
|
+
#
|
39
|
+
# @return [String] The complete path of the log file.
|
40
|
+
def log_file_path
|
41
|
+
config.log_file
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns the standard location of the log file.
|
45
|
+
#
|
46
|
+
# @return [String] The standard location of the log file.
|
47
|
+
def log_directory
|
48
|
+
File.dirname(config.log_file)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Starts the server in background.
|
52
|
+
#
|
53
|
+
# @return [Boolean] `true` if action succeeded, `false` otherwise.
|
54
|
+
def action_start
|
55
|
+
logger.info(i18n.starting)
|
56
|
+
|
57
|
+
prepare_start
|
58
|
+
|
59
|
+
@config.foreground ? perform_server : self.class.start
|
60
|
+
true
|
61
|
+
end
|
62
|
+
|
63
|
+
# Stops the server in background.
|
64
|
+
#
|
65
|
+
# @return [Boolean] `true` if action succeeded, `false` otherwise.
|
66
|
+
def action_stop
|
67
|
+
self.class.stop
|
68
|
+
true
|
69
|
+
end
|
70
|
+
|
71
|
+
# Restarts the server in background.
|
72
|
+
#
|
73
|
+
# @return [Boolean] `true` if action succeeded, `false` otherwise.
|
74
|
+
def action_restart
|
75
|
+
action_stop
|
76
|
+
action_start
|
77
|
+
true
|
78
|
+
end
|
79
|
+
|
80
|
+
# Shows the status of the server
|
81
|
+
#
|
82
|
+
# @return [Boolean] `true` if action succeeded, `false` otherwise.
|
83
|
+
def action_status
|
84
|
+
status = self.class.status
|
85
|
+
status = :crashed if status == :unknown && self.class.crashed?
|
86
|
+
|
87
|
+
log_status(self.class.controller.pid, status)
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
# :nodoc:
|
93
|
+
def prepare_start
|
94
|
+
if !Process.respond_to?(:fork)
|
95
|
+
logger.warn(i18n.no_fork)
|
96
|
+
@config.foreground = true
|
97
|
+
elsif @command.options[:foreground].value
|
98
|
+
@config.foreground = true
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
data/lib/devdnsd/version.rb
CHANGED
@@ -10,13 +10,13 @@ module DevDNSd
|
|
10
10
|
# @see http://semver.org
|
11
11
|
module Version
|
12
12
|
# The major version.
|
13
|
-
MAJOR =
|
13
|
+
MAJOR = 4
|
14
14
|
|
15
15
|
# The minor version.
|
16
|
-
MINOR =
|
16
|
+
MINOR = 0
|
17
17
|
|
18
18
|
# The patch version.
|
19
|
-
PATCH =
|
19
|
+
PATCH = 0
|
20
20
|
|
21
21
|
# The current version number of DevDNSd.
|
22
22
|
STRING = [MAJOR, MINOR, PATCH].compact.join(".")
|
data/locales/en.yml
CHANGED
@@ -5,33 +5,34 @@
|
|
5
5
|
#
|
6
6
|
|
7
7
|
---
|
8
|
+
en:
|
8
9
|
devdnsd:
|
9
10
|
rule_invalid_call: "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."
|
10
11
|
rule_invalid_options: "You can only use hashs for options."
|
11
|
-
rule_invalid_resource: "Invalid resource class %
|
12
|
+
rule_invalid_resource: "Invalid resource class %s."
|
12
13
|
dns_update: "Flushing DNS cache and resolvers ..."
|
13
14
|
no_jruby: "DevDNSd is not available on JRuby."
|
14
15
|
no_fork: "Forking is not available for this platform. Running in foreground ..."
|
15
16
|
starting: "Starting DevDNSd ..."
|
16
|
-
match: "Found match on %
|
17
|
-
reply: "Reply is %
|
17
|
+
match: "Found match on %s with type %s."
|
18
|
+
reply: "Reply is %s with type %s."
|
18
19
|
no_reply: "No reply found."
|
19
20
|
no_agent: "Install DevDNSd as a local resolver is only available on MacOSX."
|
20
21
|
admin_privileges_warning: "Basing on your setup, the system might ask you up to twice to grant {mark=bright}osascript{/mark} application admin privileges."
|
21
|
-
resolver_creating: "Creating the resolver in {mark=bright}%
|
22
|
+
resolver_creating: "Creating the resolver in {mark=bright}%s{/mark} ..."
|
22
23
|
resolver_creating_error: "Cannot create the resolver file."
|
23
|
-
resolver_deleting: "Deleting the resolver %
|
24
|
+
resolver_deleting: "Deleting the resolver %s ..."
|
24
25
|
resolver_deleting_error: "Cannot delete the resolver file."
|
25
|
-
agent_creating: "Creating the launch agent in {mark=bright}%
|
26
|
+
agent_creating: "Creating the launch agent in {mark=bright}%s{/mark} ..."
|
26
27
|
agent_creating_error: "Cannot create the launch agent."
|
27
|
-
agent_deleting: "Deleting the launch agent %
|
28
|
+
agent_deleting: "Deleting the launch agent %s ..."
|
28
29
|
agent_deleting_error: "Cannot delete the launch agent."
|
29
|
-
agent_loading: "Loading the launch agent %
|
30
|
+
agent_loading: "Loading the launch agent %s ..."
|
30
31
|
agent_loading_error: "Cannot load the launch agent."
|
31
|
-
agent_unloading: "Unloading the launch agent %
|
32
|
+
agent_unloading: "Unloading the launch agent %s ..."
|
32
33
|
agent_unloading_error: "Cannot unload the launch agent."
|
33
|
-
logging_failed: "Cannot log to {mark=bright}%
|
34
|
-
invalid_directory: "Cannot write on directory {mark=bright}%
|
34
|
+
logging_failed: "Cannot log to {mark=bright}%s{/mark}. Logging to terminal..."
|
35
|
+
invalid_directory: "Cannot write on directory {mark=bright}%s{/mark}. Exiting..."
|
35
36
|
application_description: "A small DNS server to enable local domain resolution."
|
36
37
|
application_help_configuration: "The configuration file to use. Default is \"~/.devdnsd_config\"."
|
37
38
|
application_help_tld: "The TLD to handle. Default is \"dev\"."
|
@@ -56,7 +57,7 @@
|
|
56
57
|
application_meta_addresses: "ADDRESSES"
|
57
58
|
application_meta_aliases: "ALIASES"
|
58
59
|
application_meta_command: "COMMAND"
|
59
|
-
application_create_config: "To execute devdnsd, please create the file {mark=bright}%
|
60
|
+
application_create_config: "To execute devdnsd, please create the file {mark=bright}%s{/mark}. An empty file is sufficient."
|
60
61
|
command_start: "Starts the server."
|
61
62
|
command_stop: "Stops the server."
|
62
63
|
command_restart: "Restarts the server."
|
@@ -67,7 +68,7 @@
|
|
67
68
|
command_aliases: "Adds or removes aliases to network interfaces."
|
68
69
|
command_add: "Adds aliases."
|
69
70
|
command_remove: "Removes aliases."
|
70
|
-
status_running: "The server is running with process ID {mark=bright}%
|
71
|
+
status_running: "The server is running with process ID {mark=bright}%s{/mark}."
|
71
72
|
status_stopped: "The server is stopped."
|
72
73
|
status_crashed: "The server crashed. See the log for more information."
|
73
74
|
status_unknown: "The server status is unknown."
|
@@ -77,8 +78,8 @@
|
|
77
78
|
add: "add"
|
78
79
|
to: "to "
|
79
80
|
from: "from "
|
80
|
-
general_error: "Cannot {mark=bright}%
|
81
|
+
general_error: "Cannot {mark=bright}%s{/mark} address {mark=bright}%s{/mark} %sinterface {mark=bright}%s{/mark}."
|
81
82
|
add_empty: "No valid addresses to add to the interface found."
|
82
83
|
remove_empty: "No valid addresses to remove from the interface found."
|
83
|
-
run: "%
|
84
|
-
dry_run: "%
|
84
|
+
run: "%s {mark=bright}%s{/mark} address {mark=bright}%s{/mark} %sinterface {mark=bright}%s{/mark}..."
|
85
|
+
dry_run: "%s I will {mark=bright}%s{/mark} address {mark=bright}%s{/mark} %sinterface {mark=bright}%s{/mark}..."
|
data/locales/it.yml
CHANGED
@@ -5,33 +5,34 @@
|
|
5
5
|
#
|
6
6
|
|
7
7
|
---
|
8
|
+
it:
|
8
9
|
devdnsd:
|
9
10
|
rule_invalid_call: "Devi specificare almeno una regola e un host (anche tramite un blocco). Opzionalmente puoi aggiungere un tipo di record (default: A) e le opzioni."
|
10
11
|
rule_invalid_options: "Puoi usare solo hash per le opzioni."
|
11
|
-
rule_invalid_resource: "Classe di risorsa %
|
12
|
+
rule_invalid_resource: "Classe di risorsa %s non valida."
|
12
13
|
no_jruby: "DevDNSd non è disponibile per JRuby."
|
13
14
|
no_fork: "Il forking non è disponibile per questa piattaforma. Eseguo foreground ..."
|
14
15
|
dns_update: "Cancello la cache dei DNS e dei resolver ..."
|
15
16
|
starting: "Avvio DevDNSd ..."
|
16
|
-
match: "Trovata corrispondenza per %
|
17
|
-
reply: "La risposta è %
|
17
|
+
match: "Trovata corrispondenza per %s con tipo %s."
|
18
|
+
reply: "La risposta è %s con tipo %s."
|
18
19
|
no_reply: "Nessuna risposta trovata."
|
19
20
|
no_agent: "Installare DevDNSd come resolver locale è disponibile solo su MacOSX."
|
20
21
|
admin_privileges_warning: "In base alla tua configurazione, il sistema potrebbe chiederti fino a due volte di garantire all'applicazione {mark=bright}osascript{/mark} i privilegi di amministratore."
|
21
|
-
resolver_creating: "Creo il resolver in {mark=bright}%
|
22
|
+
resolver_creating: "Creo il resolver in {mark=bright}%s{/mark} ..."
|
22
23
|
resolver_creating_error: "Impossible creare il file del resolver."
|
23
|
-
resolver_deleting: "Cancello resolver %
|
24
|
+
resolver_deleting: "Cancello resolver %s ..."
|
24
25
|
resolver_deleting_error: "Impossibile cancellare il file del resolver."
|
25
|
-
agent_creating: "Creo il launch agent in {mark=bright}%
|
26
|
+
agent_creating: "Creo il launch agent in {mark=bright}%s{/mark} ..."
|
26
27
|
agent_creating_error: "Impossibile creare il launch agent."
|
27
|
-
agent_deleting: "Cancello il launch agent %
|
28
|
+
agent_deleting: "Cancello il launch agent %s ..."
|
28
29
|
agent_deleting_error: "Impossibile cancellare launch agent."
|
29
|
-
agent_loading: "Avvio il launch agent %
|
30
|
+
agent_loading: "Avvio il launch agent %s ..."
|
30
31
|
agent_loading_error: "Impossibile avviare il launch agent."
|
31
|
-
agent_unloading: "Fermo il launch agent %
|
32
|
+
agent_unloading: "Fermo il launch agent %s ..."
|
32
33
|
agent_unloading_error: "Impossible fermare il launch agent."
|
33
|
-
logging_failed: "Impossibile eseguire il logging in {mark=bright}%
|
34
|
-
invalid_directory: "Impossibile scrivere sulla directory {mark=bright}%
|
34
|
+
logging_failed: "Impossibile eseguire il logging in {mark=bright}%s{/mark}. Eseguo il logging nel terminale..."
|
35
|
+
invalid_directory: "Impossibile scrivere sulla directory {mark=bright}%s{/mark}. Esco..."
|
35
36
|
application_description: "Un piccolo server DNS per abilitare la risoluzione di domini locali."
|
36
37
|
application_help_configuration: "Il file di configurazione da usare. Il valore predefinito è \"~/.devdnsd_config\"."
|
37
38
|
application_help_tld: "Il TLD da gestiere. Il valore predefinito è \"dev\"."
|
@@ -57,7 +58,7 @@
|
|
57
58
|
application_meta_addresses: "INDIRIZZI"
|
58
59
|
application_meta_aliases: "ALIAS"
|
59
60
|
application_meta_command: "COMANDO"
|
60
|
-
application_create_config: "Per eseguire devdnsd, per favore crea il file {mark=bright}%
|
61
|
+
application_create_config: "Per eseguire devdnsd, per favore crea il file {mark=bright}%s{/mark}. Un file vuoto è sufficiente."
|
61
62
|
command_start: "Avvia server."
|
62
63
|
command_stop: "Ferma il server."
|
63
64
|
command_restart: "Riavvia server."
|
@@ -68,7 +69,7 @@
|
|
68
69
|
command_aliases: "Aggiunge or rimuove indirizzi dalle interfacce di rete."
|
69
70
|
command_add: "Aggiungi indirizzi"
|
70
71
|
command_remove: "Rimuovi indirizzi."
|
71
|
-
status_running: "Il server è in esecuzione con ID processo {mark=bright}%
|
72
|
+
status_running: "Il server è in esecuzione con ID processo {mark=bright}%s{/mark}."
|
72
73
|
status_stopped: "Il server è stato fermato."
|
73
74
|
status_crashed: "Il server è terminato con errori. Guarda il log per maggiori informazioni."
|
74
75
|
status_unknown: "Lo status del server è sconosciuto."
|
@@ -78,8 +79,8 @@
|
|
78
79
|
add: "aggiungere"
|
79
80
|
to: "all'"
|
80
81
|
from: "dall'"
|
81
|
-
general_error: "Impossibile {mark=bright}%
|
82
|
+
general_error: "Impossibile {mark=bright}%s{/mark} l'indirizzo {mark=bright}%s{/mark} %sinterfaccia {mark=bright}%s{/mark}."
|
82
83
|
add_empty: "Nessun indirizzo valido da aggiungere all'interfaccia trovato."
|
83
84
|
remove_empty: "Nessun indirizzo valido da rimuovere dall'interfaccia trovato."
|
84
|
-
run: "%
|
85
|
-
dry_run: "%
|
85
|
+
run: "%s {mark=bright}%s{/mark} l'indirizzo {mark=bright}%s{/mark} %sinterfaccia {mark=bright}%s{/mark}..."
|
86
|
+
dry_run: "%s Sto per {mark=bright}%s{/mark} l'indirizzo {mark=bright}%s{/mark} %sinterfaccia {mark=bright}%s{/mark}..."
|
@@ -10,6 +10,7 @@ describe DevDNSd::Application do
|
|
10
10
|
before(:each) do
|
11
11
|
allow(Bovem::Logger).to receive(:default_file).and_return("/dev/null")
|
12
12
|
allow(DevDNSd::Application).to receive(:instance).and_return(application)
|
13
|
+
allow(Kernel).to receive(:exit)
|
13
14
|
end
|
14
15
|
|
15
16
|
def create_application(overrides = {})
|
@@ -24,7 +25,7 @@ describe DevDNSd::Application do
|
|
24
25
|
end
|
25
26
|
|
26
27
|
let(:log_file) { "/tmp/devdnsd-test-log-#{Time.now.strftime("%Y%m%d-%H%M%S")}" }
|
27
|
-
let(:application){ create_application({"log_file" => log_file}) }
|
28
|
+
let(:application){ create_application({"log_file" => log_file, "configuration" => "/dev/null"}) }
|
28
29
|
let(:executable) { ::Pathname.new(::File.dirname((__FILE__))) + "../../bin/devdnsd" }
|
29
30
|
let(:sample_config) { ::Pathname.new(::File.dirname((__FILE__))) + "../../config/devdnsd_config.sample" }
|
30
31
|
let(:resolver_path) { "/tmp/devdnsd-test-resolver-#{Time.now.strftime("%Y%m%d-%H%M%S")}" }
|
@@ -37,7 +38,7 @@ describe DevDNSd::Application do
|
|
37
38
|
|
38
39
|
it "should fallback logger to STDOUT" do
|
39
40
|
allow_any_instance_of(DevDNSd::Application).to receive(:read_configuration)
|
40
|
-
expect(Bovem::Logger).to receive(:create).with($stdout, Logger::INFO)
|
41
|
+
expect(Bovem::Logger).to receive(:create).with($stdout, level: Logger::INFO)
|
41
42
|
create_application({"log_file" => "/invalid/logger"})
|
42
43
|
end
|
43
44
|
|
@@ -53,14 +54,16 @@ describe DevDNSd::Application do
|
|
53
54
|
file.write("config.port = ")
|
54
55
|
file.close
|
55
56
|
|
56
|
-
|
57
|
+
expect_any_instance_of(DevDNSd::Application).to receive(:shutdown).and_call_original
|
58
|
+
create_application({"configuration" => file.path, "log_file" => log_file})
|
57
59
|
::File.unlink(path)
|
58
60
|
end
|
59
61
|
|
60
62
|
it "should abort when the log file is invalid" do
|
61
63
|
allow_any_instance_of(Bovem::Logger).to receive(:fatal)
|
62
64
|
allow_any_instance_of(Bovem::Logger).to receive(:warn)
|
63
|
-
|
65
|
+
expect_any_instance_of(DevDNSd::Application).to receive(:shutdown).and_call_original
|
66
|
+
create_application({"pid_file" => "/invalid/pid", "log_file" => "/dev/null"})
|
64
67
|
end
|
65
68
|
end
|
66
69
|
|
@@ -73,13 +76,13 @@ describe DevDNSd::Application do
|
|
73
76
|
|
74
77
|
describe ".quit" do
|
75
78
|
it "should quit the application" do
|
76
|
-
allow(
|
77
|
-
expect(EM).to receive(:stop)
|
79
|
+
allow(application).to receive(:instance).and_call_original
|
78
80
|
DevDNSd::Application.quit
|
79
81
|
end
|
80
82
|
|
81
|
-
it "should
|
82
|
-
allow(
|
83
|
+
it "should return with error code 1 in case of errors" do
|
84
|
+
allow(application).to receive(:shutdown).and_raise(RuntimeError)
|
85
|
+
expect(Kernel).to receive(:exit).with(1)
|
83
86
|
expect { DevDNSd::Application.quit }.not_to raise_error
|
84
87
|
end
|
85
88
|
end
|
@@ -126,153 +129,138 @@ describe DevDNSd::Application do
|
|
126
129
|
end
|
127
130
|
end
|
128
131
|
|
129
|
-
describe "
|
132
|
+
describe "#process_file_path" do
|
130
133
|
let(:application){ create_application({"log_file" => log_file, "configuration" => sample_config}) }
|
131
134
|
|
132
135
|
it "returns the default file" do
|
133
|
-
expect(DevDNSd::Application.process_file_path).to eq("/var/run/devdnsd.pid")
|
136
|
+
expect(DevDNSd::Application.instance.process_file_path).to eq("/var/run/devdnsd.pid")
|
134
137
|
end
|
135
138
|
|
136
139
|
it "return the set file" do
|
137
140
|
DevDNSd::Application.instance.config.pid_file = "/this/is/a/daemon.pid"
|
138
|
-
expect(DevDNSd::Application.process_file_path).to eq("/this/is/a/daemon.pid")
|
141
|
+
expect(DevDNSd::Application.instance.process_file_path).to eq("/this/is/a/daemon.pid")
|
139
142
|
end
|
140
143
|
end
|
141
144
|
|
142
|
-
describe "
|
145
|
+
describe "#log_file_path" do
|
143
146
|
let(:application){ create_application({"log_file" => log_file, "configuration" => sample_config}) }
|
144
147
|
|
145
148
|
it "returns the default file" do
|
146
|
-
expect(DevDNSd::Application.log_file_path).to eq(log_file)
|
149
|
+
expect(DevDNSd::Application.instance.log_file_path).to eq(log_file)
|
147
150
|
end
|
148
151
|
|
149
152
|
it "return the set file" do
|
150
153
|
DevDNSd::Application.instance.config.log_file = "/this/is/a/daemon.log"
|
151
|
-
expect(DevDNSd::Application.log_file_path).to eq("/this/is/a/daemon.log")
|
154
|
+
expect(DevDNSd::Application.instance.log_file_path).to eq("/this/is/a/daemon.log")
|
152
155
|
end
|
153
156
|
end
|
154
157
|
|
155
|
-
describe "
|
158
|
+
describe "#working_directory" do
|
156
159
|
let(:application){ create_application({"log_file" => log_file, "configuration" => sample_config}) }
|
157
160
|
|
158
161
|
it "returns the default path" do
|
159
|
-
expect(DevDNSd::Application.working_directory).to eq("/var/run")
|
162
|
+
expect(DevDNSd::Application.instance.working_directory).to eq("/var/run")
|
160
163
|
end
|
161
164
|
|
162
165
|
it "return the set path basing on the PID file" do
|
163
166
|
DevDNSd::Application.instance.config.pid_file = "/this/is/a/daemon.pid"
|
164
|
-
expect(DevDNSd::Application.working_directory).to eq("/this/is/a")
|
167
|
+
expect(DevDNSd::Application.instance.working_directory).to eq("/this/is/a")
|
165
168
|
end
|
166
169
|
end
|
167
170
|
|
168
|
-
describe "
|
171
|
+
describe "#log_directory" do
|
169
172
|
let(:application){ create_application({"log_file" => log_file, "configuration" => sample_config}) }
|
170
173
|
|
171
174
|
it "returns the default path" do
|
172
|
-
expect(DevDNSd::Application.log_directory).to eq(File.dirname(log_file))
|
175
|
+
expect(DevDNSd::Application.instance.log_directory).to eq(File.dirname(log_file))
|
173
176
|
end
|
174
177
|
|
175
178
|
it "return the set path basing on the PID file" do
|
176
179
|
DevDNSd::Application.instance.config.log_file = "/this/is/a/daemon.log"
|
177
|
-
expect(DevDNSd::Application.log_directory).to eq("/this/is/a")
|
180
|
+
expect(DevDNSd::Application.instance.log_directory).to eq("/this/is/a")
|
178
181
|
end
|
179
182
|
end
|
180
183
|
|
181
|
-
describe "
|
184
|
+
describe "#daemon_name" do
|
182
185
|
let(:application){ create_application({"log_file" => log_file, "configuration" => sample_config}) }
|
183
186
|
|
184
187
|
it "returns the default name" do
|
185
|
-
expect(DevDNSd::Application.daemon_name).to eq("devdnsd")
|
188
|
+
expect(DevDNSd::Application.instance.daemon_name).to eq("devdnsd")
|
186
189
|
end
|
187
190
|
|
188
191
|
it "return the set name basing on the PID file" do
|
189
192
|
DevDNSd::Application.instance.config.pid_file = "/this/is/a/daemon.pid"
|
190
|
-
expect(DevDNSd::Application.daemon_name).to eq("daemon")
|
193
|
+
expect(DevDNSd::Application.instance.daemon_name).to eq("daemon")
|
191
194
|
end
|
192
195
|
end
|
193
196
|
|
194
197
|
describe "#perform_server" do
|
195
|
-
let(:application){ create_application({"log_file" => log_file, "configuration" => sample_config, "port" => 60771}) }
|
196
|
-
|
197
|
-
def test_resolve(host = "match_1.dev", type = "ANY", nameserver = "127.0.0.1", port = 60771, logger = nil)
|
198
|
-
result = nil
|
199
|
-
|
200
|
-
EM.run do
|
201
|
-
EM.add_timer(0.01) { application.perform_server }
|
202
|
-
EM.add_timer(0.1) {
|
203
|
-
Fiber.new {
|
204
|
-
result = devdnsd_resolv(host, type, nameserver, port, logger)
|
205
|
-
EM.stop
|
206
|
-
}.resume
|
207
|
-
}
|
208
|
-
end
|
209
|
-
|
210
|
-
result
|
211
|
-
end
|
198
|
+
let(:application) { create_application({"log_file" => log_file, "configuration" => sample_config, "port" => 60771}) }
|
212
199
|
|
213
|
-
it "should
|
214
|
-
expect(RubyDNS).to receive(:run_server)
|
200
|
+
it "should free resources correctly" do
|
215
201
|
application.perform_server
|
202
|
+
application.shutdown
|
203
|
+
application.perform_server
|
204
|
+
application.shutdown
|
216
205
|
end
|
217
206
|
|
218
207
|
it "should setup callbacks" do
|
219
208
|
expect_any_instance_of(RubyDNS::RuleBasedServer).to receive(:on).with(:start)
|
220
209
|
expect_any_instance_of(RubyDNS::RuleBasedServer).to receive(:on).with(:stop)
|
221
|
-
|
222
|
-
|
223
|
-
EM.add_timer(0.01) { application.perform_server }
|
224
|
-
EM.add_timer(0.2) { DevDNSd::Application.quit }
|
225
|
-
end
|
226
|
-
end
|
227
|
-
|
228
|
-
it "should iterate the rules" do
|
229
|
-
test_resolve do
|
230
|
-
expect(application.config.rules).to receive(:each).at_least(1)
|
231
|
-
application.perform_server
|
232
|
-
end
|
233
|
-
end
|
234
|
-
|
235
|
-
it "should call process_rule" do
|
236
|
-
test_resolve do
|
237
|
-
expect(application).to receive(:process_rule).at_least(1)
|
238
|
-
application.perform_server
|
239
|
-
end
|
210
|
+
application.perform_server
|
211
|
+
application.shutdown
|
240
212
|
end
|
241
213
|
|
242
|
-
|
243
|
-
test_resolve
|
244
|
-
|
245
|
-
expect { application.perform_server }.to raise_exception
|
214
|
+
describe "using rules" do
|
215
|
+
def test_resolve(host = "match_1.dev", type = "ANY", nameserver = "127.0.0.1", port = 60771, logger = nil)
|
216
|
+
devdnsd_resolv(host, type, nameserver, port, logger)
|
246
217
|
end
|
247
|
-
end
|
248
218
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
expect(test_resolve("match_4.dev")).to eq(["cowtech.it", :CNAME])
|
219
|
+
around(:each) do |example|
|
220
|
+
app = application
|
221
|
+
app.perform_server
|
222
|
+
example.call
|
223
|
+
app.shutdown
|
255
224
|
end
|
256
225
|
|
257
|
-
it "
|
258
|
-
expect(
|
259
|
-
|
260
|
-
expect(test_resolve("match_6_33.dev")).to eq(["10.0.6.33", :PTR])
|
261
|
-
expect(test_resolve("match_6_44.dev")).to eq(["10.0.6.44", :PTR])
|
262
|
-
expect(test_resolve("match_7_55.dev")).to eq(["10.0.7.55", :A])
|
263
|
-
expect(test_resolve("match_7_66.dev")).to eq(["10.0.7.66", :A])
|
264
|
-
expect(test_resolve("match_8_77.dev")).to eq(["10.0.8.77", :PTR])
|
265
|
-
expect(test_resolve("match_8_88.dev")).to eq(["10.0.8.88", :PTR])
|
226
|
+
it "should iterate the rules" do
|
227
|
+
expect(application.config.rules).to receive(:each).at_least(1)
|
228
|
+
test_resolve
|
266
229
|
end
|
267
230
|
|
268
|
-
it "
|
269
|
-
|
270
|
-
|
231
|
+
it "should call process_rule" do
|
232
|
+
expect_any_instance_of(DevDNSd::Application).to receive(:process_rule).at_least(1)
|
233
|
+
test_resolve
|
271
234
|
end
|
272
235
|
|
273
|
-
|
274
|
-
|
275
|
-
|
236
|
+
describe "should correctly resolve hostnames" do
|
237
|
+
it "basing on a exact pattern" do
|
238
|
+
expect(test_resolve("match_1.dev")).to eq(["10.0.1.1", :A])
|
239
|
+
expect(test_resolve("match_2.dev")).to eq(["10.0.2.1", :MX])
|
240
|
+
expect(test_resolve("match_3.dev")).to eq(["10.0.3.1", :A])
|
241
|
+
expect(test_resolve("match_4.dev")).to eq(["cowtech.it", :CNAME])
|
242
|
+
end
|
243
|
+
|
244
|
+
it "basing on a regexp pattern" do
|
245
|
+
expect(test_resolve("match_5_11.dev")).to eq(["ns.cowtech.it", :NS])
|
246
|
+
expect(test_resolve("match_5_22.dev")).to eq(["ns.cowtech.it", :NS])
|
247
|
+
expect(test_resolve("match_6_33.dev")).to eq(["10.0.6.33", :PTR])
|
248
|
+
expect(test_resolve("match_6_44.dev")).to eq(["10.0.6.44", :PTR])
|
249
|
+
expect(test_resolve("match_7_55.dev")).to eq(["10.0.7.55", :A])
|
250
|
+
expect(test_resolve("match_7_66.dev")).to eq(["10.0.7.66", :A])
|
251
|
+
expect(test_resolve("match_8_77.dev")).to eq(["10.0.8.77", :PTR])
|
252
|
+
expect(test_resolve("match_8_88.dev")).to eq(["10.0.8.88", :PTR])
|
253
|
+
end
|
254
|
+
|
255
|
+
it "and return multiple or only relevant answsers" do
|
256
|
+
expect(test_resolve("match_10.dev")).to eq([["10.0.10.1", :A], ["10.0.10.2", :MX]])
|
257
|
+
expect(test_resolve("match_10.dev", "MX")).to eq(["10.0.10.2", :MX])
|
258
|
+
end
|
259
|
+
|
260
|
+
it "and reject invalid matches (with or without rules)" do
|
261
|
+
expect(test_resolve("match_9.dev")).to eq([])
|
262
|
+
expect(test_resolve("invalid.dev")).to eq([])
|
263
|
+
end
|
276
264
|
end
|
277
265
|
end
|
278
266
|
end
|
@@ -295,51 +283,51 @@ describe DevDNSd::Application do
|
|
295
283
|
|
296
284
|
it "should match a valid string request" do
|
297
285
|
rule = application.config.rules[0]
|
298
|
-
expect(application.process_rule(rule, rule.resource_class, nil, transaction)).to
|
286
|
+
expect(application.process_rule(rule, rule.resource_class, nil, transaction)).to be_truthy
|
299
287
|
end
|
300
288
|
|
301
289
|
it "should match a valid string request with specific type" do
|
302
290
|
rule = application.config.rules[1]
|
303
|
-
expect(application.process_rule(rule, rule.resource_class, nil, transaction)).to
|
291
|
+
expect(application.process_rule(rule, rule.resource_class, nil, transaction)).to be_truthy
|
304
292
|
end
|
305
293
|
|
306
294
|
it "should match a valid string request with a block" do
|
307
295
|
rule = application.config.rules[2]
|
308
|
-
expect(application.process_rule(rule, rule.resource_class, nil, transaction)).to
|
296
|
+
expect(application.process_rule(rule, rule.resource_class, nil, transaction)).to be_truthy
|
309
297
|
end
|
310
298
|
|
311
299
|
it "should match a valid string request with a block" do
|
312
300
|
rule = application.config.rules[3]
|
313
|
-
expect(application.process_rule(rule, rule.resource_class, nil, transaction)).to
|
301
|
+
expect(application.process_rule(rule, rule.resource_class, nil, transaction)).to be_truthy
|
314
302
|
end
|
315
303
|
|
316
304
|
it "should match a valid regexp request" do
|
317
305
|
rule = application.config.rules[4]
|
318
306
|
mo = rule.match_host("match_5_12.dev")
|
319
|
-
expect(application.process_rule(rule, rule.resource_class, mo, transaction)).to
|
307
|
+
expect(application.process_rule(rule, rule.resource_class, mo, transaction)).to be_truthy
|
320
308
|
end
|
321
309
|
|
322
310
|
it "should match a valid regexp request with specific type" do
|
323
311
|
rule = application.config.rules[5]
|
324
312
|
mo = rule.match_host("match_6_34.dev")
|
325
|
-
expect(application.process_rule(rule, rule.resource_class, mo, transaction)).to
|
313
|
+
expect(application.process_rule(rule, rule.resource_class, mo, transaction)).to be_truthy
|
326
314
|
end
|
327
315
|
|
328
316
|
it "should match a valid regexp request with a block" do
|
329
317
|
rule = application.config.rules[6]
|
330
318
|
mo = rule.match_host("match_7_56.dev")
|
331
|
-
expect(application.process_rule(rule, rule.resource_class, mo, transaction)).to
|
319
|
+
expect(application.process_rule(rule, rule.resource_class, mo, transaction)).to be_truthy
|
332
320
|
end
|
333
321
|
|
334
322
|
it "should match a valid regexp request with a block and specific type" do
|
335
323
|
rule = application.config.rules[7]
|
336
324
|
mo = rule.match_host("match_8_78.dev")
|
337
|
-
expect(application.process_rule(rule, rule.resource_class, mo, transaction)).to
|
325
|
+
expect(application.process_rule(rule, rule.resource_class, mo, transaction)).to be_truthy
|
338
326
|
end
|
339
327
|
|
340
328
|
it "should return false for a false block" do
|
341
329
|
rule = application.config.rules[8]
|
342
|
-
expect(application.process_rule(rule, rule.resource_class, nil, transaction)).to
|
330
|
+
expect(application.process_rule(rule, rule.resource_class, nil, transaction)).to be_falsey
|
343
331
|
end
|
344
332
|
|
345
333
|
it "should return nil for a nil reply" do
|
@@ -356,12 +344,12 @@ describe DevDNSd::Application do
|
|
356
344
|
end
|
357
345
|
end
|
358
346
|
|
359
|
-
describe "#
|
347
|
+
describe "#osx?" do
|
360
348
|
it "should return the correct information" do
|
361
349
|
stub_const("RbConfig::CONFIG", {"host_os" => "darwin foo"})
|
362
|
-
expect(application.
|
350
|
+
expect(application.osx?).to be_truthy
|
363
351
|
stub_const("RbConfig::CONFIG", {"host_os" => "another"})
|
364
|
-
expect(application.
|
352
|
+
expect(application.osx?).to be_falsey
|
365
353
|
end
|
366
354
|
end
|
367
355
|
|
@@ -387,22 +375,22 @@ describe DevDNSd::Application do
|
|
387
375
|
|
388
376
|
describe "#manage_aliases" do
|
389
377
|
it "should override configuration" do
|
390
|
-
|
378
|
+
expect_any_instance_of(DevDNSd::Application).to receive(:manage_address)
|
391
379
|
application.manage_aliases(:add, "MESSAGE", {aliases: 10})
|
392
380
|
expect(application.config.aliases).to eq(10)
|
393
381
|
end
|
394
382
|
|
395
383
|
it "should log an error if no interfaces are found" do
|
396
|
-
|
384
|
+
expect_any_instance_of(DevDNSd::Application).to receive(:compute_addresses).and_return([])
|
397
385
|
expect(application.logger).to receive(:error).with("MESSAGE")
|
398
|
-
expect(application.manage_aliases(:add, "MESSAGE", {aliases: 10})).to
|
386
|
+
expect(application.manage_aliases(:add, "MESSAGE", {aliases: 10})).to be_falsey
|
399
387
|
end
|
400
388
|
|
401
389
|
it "should call #manage_address for each address" do
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
expect(application.manage_aliases("OPERATION", "MESSAGE", {aliases: 3, dry_run: "DRY_RUN"})).to
|
390
|
+
expect_any_instance_of(DevDNSd::Application).to receive(:manage_address).with("OPERATION", IPAddr.new("10.0.0.1"), "DRY_RUN").and_return(true)
|
391
|
+
expect_any_instance_of(DevDNSd::Application).to receive(:manage_address).with("OPERATION", IPAddr.new("10.0.0.2"), "DRY_RUN").and_return(true)
|
392
|
+
expect_any_instance_of(DevDNSd::Application).to receive(:manage_address).with("OPERATION", IPAddr.new("10.0.0.3"), "DRY_RUN").and_return(true)
|
393
|
+
expect(application.manage_aliases("OPERATION", "MESSAGE", {aliases: 3, dry_run: "DRY_RUN"})).to be_truthy
|
406
394
|
end
|
407
395
|
end
|
408
396
|
|
@@ -416,24 +404,24 @@ describe DevDNSd::Application do
|
|
416
404
|
end
|
417
405
|
|
418
406
|
it "should call the right system command" do
|
419
|
-
|
407
|
+
expect_any_instance_of(DevDNSd::Application).to receive(:execute_command).with("sudo ifconfig lo0 alias 10.0.0.3 > /dev/null 2>&1")
|
420
408
|
application.manage_address(:add, "10.0.0.3")
|
421
409
|
|
422
|
-
|
410
|
+
expect_any_instance_of(DevDNSd::Application).to receive(:execute_command).with("sudo ifconfig lo0 -alias 10.0.0.3 > /dev/null 2>&1")
|
423
411
|
application.manage_address(:remove, "10.0.0.3")
|
424
412
|
end
|
425
413
|
|
426
414
|
it "should return true if the command succeded" do
|
427
415
|
application.config.add_command = "echo {{interface}}"
|
428
|
-
expect(application.manage_address(:add, "10.0.0.3")).to
|
416
|
+
expect(application.manage_address(:add, "10.0.0.3")).to be_truthy
|
429
417
|
end
|
430
418
|
|
431
419
|
it "should return false if the command failed" do
|
432
|
-
expect(application.manage_address(:add, "10.0.0.256")).to
|
420
|
+
expect(application.manage_address(:add, "10.0.0.256")).to be_falsey
|
433
421
|
end
|
434
422
|
|
435
423
|
it "should respect dry-run mode" do
|
436
|
-
|
424
|
+
expect_any_instance_of(DevDNSd::Application).not_to receive(:execute_command)
|
437
425
|
expect(application.logger).to receive(:info).with(/.+.*3.*\/.*5.*.+ I will .*add.* address .*10.0.0.3.* to interface .*lo0.*/)
|
438
426
|
expect(application.logger).to receive(:info).with(/.+.*3.*\/.*5.*.+ I will .*remove.* address .*10.0.0.3.* from interface .*lo0.*/)
|
439
427
|
|
@@ -491,39 +479,39 @@ describe DevDNSd::Application do
|
|
491
479
|
end
|
492
480
|
end
|
493
481
|
|
494
|
-
describe "#
|
482
|
+
describe "#ipv4?" do
|
495
483
|
it "correctly detects valid IPv4 address" do
|
496
|
-
expect(application.
|
497
|
-
expect(application.
|
498
|
-
expect(application.
|
484
|
+
expect(application.ipv4?("10.0.0.1")).to be_truthy
|
485
|
+
expect(application.ipv4?("255.0.0.1")).to be_truthy
|
486
|
+
expect(application.ipv4?("192.168.0.1")).to be_truthy
|
499
487
|
end
|
500
488
|
|
501
489
|
it "rejects other values" do
|
502
|
-
expect(application.
|
503
|
-
expect(application.
|
504
|
-
expect(application.
|
505
|
-
expect(application.
|
506
|
-
expect(application.
|
490
|
+
expect(application.ipv4?("10.0.0.256")).to be_falsey
|
491
|
+
expect(application.ipv4?("10.0.0.-1")).to be_falsey
|
492
|
+
expect(application.ipv4?("::1")).to be_falsey
|
493
|
+
expect(application.ipv4?("INVALID")).to be_falsey
|
494
|
+
expect(application.ipv4?(nil)).to be_falsey
|
507
495
|
end
|
508
496
|
end
|
509
497
|
|
510
|
-
describe "#
|
498
|
+
describe "#ipv6?" do
|
511
499
|
it "correctly detects valid IPv4 address" do
|
512
|
-
expect(application.
|
513
|
-
expect(application.
|
514
|
-
expect(application.
|
515
|
-
expect(application.
|
516
|
-
expect(application.
|
517
|
-
expect(application.
|
518
|
-
expect(application.
|
519
|
-
expect(application.
|
500
|
+
expect(application.ipv6?("2001:0db8:0000:0000:0000:1428:57ab")).to be_truthy
|
501
|
+
expect(application.ipv6?("2001:0db8:0:000:00:1428:57ab")).to be_truthy
|
502
|
+
expect(application.ipv6?("2001:0db8:0::1428:57ab")).to be_truthy
|
503
|
+
expect(application.ipv6?("2001::")).to be_truthy
|
504
|
+
expect(application.ipv6?("::1")).to be_truthy
|
505
|
+
expect(application.ipv6?("::2:1")).to be_truthy
|
506
|
+
expect(application.ipv6?("2011::10.0.0.1")).to be_truthy
|
507
|
+
expect(application.ipv6?("2011::0:10.0.0.1")).to be_truthy
|
520
508
|
end
|
521
509
|
|
522
510
|
it "rejects other values" do
|
523
|
-
expect(application.
|
524
|
-
expect(application.
|
525
|
-
expect(application.
|
526
|
-
expect(application.
|
511
|
+
expect(application.ipv6?("::H")).to be_falsey
|
512
|
+
expect(application.ipv6?("192.168.0.256")).to be_falsey
|
513
|
+
expect(application.ipv6?("INVALID")).to be_falsey
|
514
|
+
expect(application.ipv6?(nil)).to be_falsey
|
527
515
|
end
|
528
516
|
end
|
529
517
|
|
@@ -534,7 +522,7 @@ describe DevDNSd::Application do
|
|
534
522
|
option :foreground, [:n, "foreground"], {default: true}
|
535
523
|
})
|
536
524
|
|
537
|
-
|
525
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:perform_server)
|
538
526
|
application.action_start
|
539
527
|
end
|
540
528
|
|
@@ -544,7 +532,7 @@ describe DevDNSd::Application do
|
|
544
532
|
option :foreground, [:n, "foreground"], {default: false}
|
545
533
|
})
|
546
534
|
|
547
|
-
expect(::
|
535
|
+
expect(::DevDNSd::Application).to receive(:start)
|
548
536
|
application.action_start
|
549
537
|
end
|
550
538
|
|
@@ -552,48 +540,48 @@ describe DevDNSd::Application do
|
|
552
540
|
application.config.foreground = false
|
553
541
|
|
554
542
|
allow(Process).to receive(:respond_to?).and_return(false)
|
555
|
-
|
543
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:perform_server)
|
556
544
|
expect(application.logger).to receive(:warn)
|
557
545
|
|
558
546
|
application.action_start
|
559
|
-
expect(application.config.foreground).to
|
547
|
+
expect(application.config.foreground).to be_truthy
|
560
548
|
end
|
561
549
|
end
|
562
550
|
|
563
551
|
describe "#action_stop" do
|
564
552
|
it "should stop the daemon" do
|
565
|
-
expect(::
|
553
|
+
expect(::DevDNSd::Application).to receive(:stop)
|
566
554
|
application.action_stop
|
567
555
|
end
|
568
556
|
end
|
569
557
|
|
570
558
|
describe "#action_restart" do
|
571
559
|
it "should stop and restart the server" do
|
572
|
-
|
573
|
-
|
560
|
+
expect_any_instance_of(DevDNSd::Application).to receive(:action_stop)
|
561
|
+
expect_any_instance_of(DevDNSd::Application).to receive(:action_start)
|
574
562
|
application.action_restart
|
575
563
|
end
|
576
564
|
end
|
577
565
|
|
578
566
|
describe "#action_status" do
|
579
567
|
it "should get the status of the daemon when running" do
|
580
|
-
expect(
|
581
|
-
expect(
|
568
|
+
expect(Process::Daemon::ProcessFile).to receive(:status).and_return(:running)
|
569
|
+
expect(DevDNSd::Application.controller).to receive(:pid).and_return(123)
|
582
570
|
|
583
|
-
expect(application.logger).to receive(:info).with("The server is running with process ID
|
571
|
+
expect(application.logger).to receive(:info).with("The server is running with process ID \e[1m123\e[0m.")
|
584
572
|
application.action_status
|
585
573
|
end
|
586
574
|
|
587
575
|
it "should get the status of the daemon when stopped" do
|
588
|
-
expect(
|
589
|
-
expect(
|
576
|
+
expect(Process::Daemon::ProcessFile).to receive(:status).and_return(:stopped)
|
577
|
+
expect(DevDNSd::Application.controller).to receive(:pid).and_return(123)
|
590
578
|
|
591
579
|
expect(application.logger).to receive(:info).with("The server is stopped.")
|
592
580
|
application.action_status
|
593
581
|
end
|
594
582
|
|
595
583
|
it "should get the status of the daemon when crashed" do
|
596
|
-
expect(
|
584
|
+
expect(Process::Daemon::ProcessFile).to receive(:status).and_return(:unknown)
|
597
585
|
expect(application.class).to receive(:crashed?).and_return(true)
|
598
586
|
|
599
587
|
expect(application.logger).to receive(:info).with("The server crashed. See the log for more information.")
|
@@ -601,7 +589,7 @@ describe DevDNSd::Application do
|
|
601
589
|
end
|
602
590
|
|
603
591
|
it "should get the status of the daemon when unknown" do
|
604
|
-
expect(
|
592
|
+
expect(Process::Daemon::ProcessFile).to receive(:status).and_return(:unknown)
|
605
593
|
expect(application.class).to receive(:crashed?).and_return(false)
|
606
594
|
|
607
595
|
expect(application.logger).to receive(:info).with("The server status is unknown.")
|
@@ -611,46 +599,46 @@ describe DevDNSd::Application do
|
|
611
599
|
|
612
600
|
describe "#action_install" do
|
613
601
|
before(:each) do
|
614
|
-
allow(application).to receive(:
|
602
|
+
allow(application).to receive(:osx?).and_return(true)
|
615
603
|
allow(application).to receive(:execute_command)
|
616
604
|
expect(Kernel).to receive(:system).at_least(1)
|
617
605
|
end
|
618
606
|
|
619
607
|
it "should create the resolver" do
|
620
|
-
|
621
|
-
|
608
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:resolver_path).and_return(resolver_path)
|
609
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:launch_agent_path).and_return(launch_agent_path)
|
622
610
|
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
623
611
|
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
624
612
|
|
625
|
-
|
613
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:create_resolver) {|_, path| FileUtils.touch(path) }
|
626
614
|
application.action_install
|
627
|
-
expect(::File.exists?(resolver_path)).to
|
615
|
+
expect(::File.exists?(resolver_path)).to be_truthy
|
628
616
|
|
629
617
|
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
630
618
|
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
631
619
|
end
|
632
620
|
|
633
621
|
it "should create the agent" do
|
634
|
-
|
635
|
-
|
622
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:resolver_path).and_return(resolver_path)
|
623
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:launch_agent_path).and_return(launch_agent_path)
|
636
624
|
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
637
625
|
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
638
626
|
|
639
|
-
|
627
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:resolver_path).and_return(resolver_path)
|
640
628
|
application.action_install
|
641
|
-
expect(::File.exists?(application.launch_agent_path)).to
|
629
|
+
expect(::File.exists?(application.launch_agent_path)).to be_truthy
|
642
630
|
|
643
631
|
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
644
632
|
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
645
633
|
end
|
646
634
|
|
647
635
|
it "should update the DNS cache" do
|
648
|
-
|
649
|
-
|
636
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:resolver_path).and_return(resolver_path)
|
637
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:launch_agent_path).and_return(launch_agent_path)
|
650
638
|
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
651
639
|
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
652
640
|
|
653
|
-
|
641
|
+
expect_any_instance_of(DevDNSd::Application).to receive(:dns_update)
|
654
642
|
application.action_install
|
655
643
|
|
656
644
|
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
@@ -658,13 +646,13 @@ describe DevDNSd::Application do
|
|
658
646
|
end
|
659
647
|
|
660
648
|
it "should not create an invalid resolver" do
|
661
|
-
|
662
|
-
|
649
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:resolver_path).and_return("/invalid/resolver")
|
650
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:launch_agent_path).and_return("/invalid/agent")
|
663
651
|
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
664
652
|
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
665
653
|
|
666
|
-
|
667
|
-
expect_any_instance_of(
|
654
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:create_agent).and_return(true)
|
655
|
+
expect_any_instance_of(Bovem::I18n).to receive(:resolver_creating).and_raise(ArgumentError)
|
668
656
|
expect(application.logger).to receive(:error).with("Cannot create the resolver file.")
|
669
657
|
application.action_install
|
670
658
|
|
@@ -673,8 +661,8 @@ describe DevDNSd::Application do
|
|
673
661
|
end
|
674
662
|
|
675
663
|
it "should not create an invalid agent" do
|
676
|
-
|
677
|
-
|
664
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:resolver_path).and_return(resolver_path)
|
665
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:launch_agent_path).and_return("/invalid/agent")
|
678
666
|
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
679
667
|
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
680
668
|
|
@@ -690,11 +678,12 @@ describe DevDNSd::Application do
|
|
690
678
|
command =~ /^launchctl/ ? raise(StandardError) : true
|
691
679
|
end
|
692
680
|
|
693
|
-
|
694
|
-
|
681
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:resolver_path).and_return(resolver_path)
|
682
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:launch_agent_path).and_return(launch_agent_path)
|
695
683
|
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
696
684
|
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
697
685
|
|
686
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:create_agent).and_return(true)
|
698
687
|
expect(application.logger).to receive(:error).with("Cannot load the launch agent.")
|
699
688
|
application.action_install
|
700
689
|
|
@@ -703,41 +692,41 @@ describe DevDNSd::Application do
|
|
703
692
|
end
|
704
693
|
|
705
694
|
it "should raise an exception if not running on OSX" do
|
706
|
-
|
695
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:osx?).and_return(false)
|
707
696
|
expect(application.logger).to receive(:fatal).with("Install DevDNSd as a local resolver is only available on MacOSX.")
|
708
|
-
expect(application.action_install).to
|
697
|
+
expect(application.action_install).to be_falsey
|
709
698
|
end
|
710
699
|
end
|
711
700
|
|
712
701
|
describe "#action_uninstall" do
|
713
702
|
before(:each) do
|
714
|
-
allow(application).to receive(:
|
703
|
+
allow(application).to receive(:osx?).and_return(true)
|
715
704
|
allow(application).to receive(:execute_command)
|
716
705
|
expect(Kernel).to receive(:system).at_least(1)
|
717
706
|
end
|
718
707
|
|
719
708
|
it "should remove the resolver" do
|
720
|
-
|
721
|
-
|
709
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:resolver_path).and_return(resolver_path)
|
710
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:launch_agent_path).and_return(launch_agent_path)
|
722
711
|
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
723
712
|
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
724
713
|
|
725
714
|
application.action_install
|
726
715
|
application.action_uninstall
|
727
|
-
expect(::File.exists?(resolver_path)).to
|
716
|
+
expect(::File.exists?(resolver_path)).to be_falsey
|
728
717
|
|
729
718
|
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
730
719
|
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
731
720
|
end
|
732
721
|
|
733
722
|
it "should not remove an invalid resolver" do
|
734
|
-
|
735
|
-
|
723
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:resolver_path).and_return("/invalid/resolver")
|
724
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:launch_agent_path).and_return("/invalid/agent")
|
736
725
|
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
737
726
|
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
738
727
|
|
739
728
|
allow(application).to receive(:unload_agent).and_return(true)
|
740
|
-
expect_any_instance_of(
|
729
|
+
expect_any_instance_of(Bovem::I18n).to receive(:resolver_deleting).and_raise(ArgumentError)
|
741
730
|
expect(application.logger).to receive(:warn)
|
742
731
|
expect(application.logger).to receive(:warn).with("Cannot delete the resolver file.")
|
743
732
|
|
@@ -748,15 +737,30 @@ describe DevDNSd::Application do
|
|
748
737
|
end
|
749
738
|
|
750
739
|
it "should remove the agent" do
|
751
|
-
|
752
|
-
|
740
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:resolver_path).and_return(resolver_path)
|
741
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:launch_agent_path).and_return(launch_agent_path)
|
742
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
743
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
744
|
+
|
745
|
+
allow(Bovem::Logger).to receive(:default_file).and_return($stdout)
|
746
|
+
application.action_install
|
747
|
+
application.action_uninstall
|
748
|
+
expect(::File.exists?(application.launch_agent_path)).to be_falsey
|
749
|
+
|
750
|
+
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
751
|
+
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
752
|
+
end
|
753
|
+
|
754
|
+
it "should not fail if the agent cannot be removed" do
|
755
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:resolver_path).and_return(resolver_path)
|
756
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:launch_agent_path).and_return(launch_agent_path)
|
753
757
|
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
754
758
|
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
755
759
|
|
760
|
+
allow(File).to receive(:delete).and_raise(RuntimeError)
|
756
761
|
allow(Bovem::Logger).to receive(:default_file).and_return($stdout)
|
757
762
|
application.action_install
|
758
763
|
application.action_uninstall
|
759
|
-
expect(::File.exists?(application.launch_agent_path)).to be_false
|
760
764
|
|
761
765
|
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
762
766
|
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
@@ -807,7 +811,7 @@ describe DevDNSd::Application do
|
|
807
811
|
::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
|
808
812
|
|
809
813
|
application.action_install
|
810
|
-
|
814
|
+
expect_any_instance_of(DevDNSd::Application).to receive(:dns_update)
|
811
815
|
application.action_uninstall
|
812
816
|
|
813
817
|
::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
|
@@ -815,22 +819,22 @@ describe DevDNSd::Application do
|
|
815
819
|
end
|
816
820
|
|
817
821
|
it "should raise an exception if not running on OSX" do
|
818
|
-
|
822
|
+
allow_any_instance_of(DevDNSd::Application).to receive(:osx?).and_return(false)
|
819
823
|
expect(application.logger).to receive(:fatal).with("Install DevDNSd as a local resolver is only available on MacOSX.")
|
820
|
-
expect(application.action_uninstall).to
|
824
|
+
expect(application.action_uninstall).to be_falsey
|
821
825
|
end
|
822
826
|
end
|
823
827
|
|
824
828
|
describe "#action_add" do
|
825
829
|
it "should #manage_aliases" do
|
826
|
-
|
830
|
+
expect_any_instance_of(DevDNSd::Application).to receive(:manage_aliases).with(:add, "No valid addresses to add to the interface found.", {a: 1})
|
827
831
|
application.action_add({a: 1})
|
828
832
|
end
|
829
833
|
end
|
830
834
|
|
831
835
|
describe "#action_remove" do
|
832
836
|
it "should #manage_aliases" do
|
833
|
-
|
837
|
+
expect_any_instance_of(DevDNSd::Application).to receive(:manage_aliases).with(:remove, "No valid addresses to remove from the interface found.", {a: 1})
|
834
838
|
application.action_remove({a: 1})
|
835
839
|
end
|
836
840
|
end
|