devdnsd 3.0.7 → 3.0.8

Sign up to get free protection for your applications and to get access to all the features.
data/doc/_index.html CHANGED
@@ -237,7 +237,7 @@
237
237
  </div>
238
238
 
239
239
  <div id="footer">
240
- Generated on Sat Mar 8 11:03:19 2014 by
240
+ Generated on Sat Mar 8 15:25:56 2014 by
241
241
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
242
242
  0.8.7.3 (ruby-2.1.0).
243
243
  </div>
data/doc/file.README.html CHANGED
@@ -105,7 +105,7 @@
105
105
 
106
106
  <h2 id="configuration">Configuration</h2>
107
107
 
108
- <p>By defaults, DevDNSd uses a configuration file in <code>~/.devdnsd_config</code>, but you can change the path using the <code>--config</code> switch.</p>
108
+ <p>By defaults, DevDNSd uses a configuration file in <code>~/.devdnsd/default.conf</code>, but you can change the path using the <code>--config</code> switch.</p>
109
109
 
110
110
  <p>The file is a plain Ruby file with a single <code>config</code> object that supports the following directives.</p>
111
111
 
@@ -166,7 +166,7 @@ This argument is ignored if you pass the block, as it assumes that the second ar
166
166
  </div></div>
167
167
 
168
168
  <div id="footer">
169
- Generated on Sat Mar 8 11:03:19 2014 by
169
+ Generated on Sat Mar 8 15:25:56 2014 by
170
170
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
171
171
  0.8.7.3 (ruby-2.1.0).
172
172
  </div>
data/doc/index.html CHANGED
@@ -105,7 +105,7 @@
105
105
 
106
106
  <h2 id="configuration">Configuration</h2>
107
107
 
108
- <p>By defaults, DevDNSd uses a configuration file in <code>~/.devdnsd_config</code>, but you can change the path using the <code>--config</code> switch.</p>
108
+ <p>By defaults, DevDNSd uses a configuration file in <code>~/.devdnsd/default.conf</code>, but you can change the path using the <code>--config</code> switch.</p>
109
109
 
110
110
  <p>The file is a plain Ruby file with a single <code>config</code> object that supports the following directives.</p>
111
111
 
@@ -166,7 +166,7 @@ This argument is ignored if you pass the block, as it assumes that the second ar
166
166
  </div></div>
167
167
 
168
168
  <div id="footer">
169
- Generated on Sat Mar 8 11:03:19 2014 by
169
+ Generated on Sat Mar 8 15:25:56 2014 by
170
170
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
171
171
  0.8.7.3 (ruby-2.1.0).
172
172
  </div>
@@ -103,7 +103,7 @@
103
103
  </div>
104
104
 
105
105
  <div id="footer">
106
- Generated on Sat Mar 8 11:03:19 2014 by
106
+ Generated on Sat Mar 8 15:25:56 2014 by
107
107
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
108
108
  0.8.7.3 (ruby-2.1.0).
109
109
  </div>
@@ -73,7 +73,7 @@ module DevDNSd
73
73
  # @param command [String] The command to execute.
74
74
  # @return [Boolean] `true` if command succeeded, `false` otherwise.
75
75
  def execute_command(command)
76
- system(command)
76
+ system("#{command} 2&>1 > /dev/null")
77
77
  end
78
78
 
79
79
  # Updates DNS cache.
@@ -81,7 +81,15 @@ module DevDNSd
81
81
  # @return [Boolean] `true` if command succeeded, `false` otherwise.
82
82
  def dns_update
83
83
  @logger.info(i18n.dns_update)
84
- execute_command("dscacheutil -flushcache")
84
+
85
+ script = Tempfile.new("devdnsd-dns-cache-script")
86
+ script.write("dscacheutil -flushcache 2&>1 > /dev/null\n")
87
+ script.write("killall -9 mDNSResponder 2&>1 > /dev/null\n")
88
+ script.write("killall -9 mDNSResponderHelper 2&>1 > /dev/null\n")
89
+ script.close
90
+
91
+ Kernel.system("/usr/bin/osascript -e 'do shell script \"sh #{script.path}\" with administrator privileges' 2&>1 > /dev/null")
92
+ script.unlink
85
93
  end
86
94
 
87
95
  # Checks if we are running on MacOS X.
@@ -160,6 +168,8 @@ module DevDNSd
160
168
  # @return [Boolean] `true` if operation succeeded, `false` otherwise.
161
169
  def manage_installation(launch_agent, resolver_path, first_operation, second_operation, third_operation)
162
170
  rv = check_agent_available
171
+
172
+ logger.warn(replace_markers(i18n.admin_privileges_warning))
163
173
  rv = send(first_operation, launch_agent, resolver_path) if rv
164
174
  rv = send(second_operation, launch_agent, resolver_path) if rv
165
175
  rv = send(third_operation, launch_agent, resolver_path) if rv
@@ -203,33 +213,36 @@ module DevDNSd
203
213
  # @return [Boolean] `true` if operation succeeded, `false` otherwise.
204
214
  def create_resolver(_, resolver_path)
205
215
  begin
206
- logger.info(i18n.resolver_creating(resolver_path))
216
+ logger.info(replace_markers(i18n.resolver_creating(resolver_path)))
207
217
 
208
- ::File.open(resolver_path, "w") {|f|
209
- f.write("nameserver 127.0.0.1\n")
210
- f.write("port #{@config.port}")
211
- f.flush
212
- }
218
+ script = Tempfile.new("devdnsd-install-script")
219
+ script.write("mkdir -p '#{File.dirname(resolver_path)}'\n")
220
+ script.write("rm -rf '#{resolver_path}'\n")
221
+ script.write("echo 'nameserver 127.0.0.1\\nport #{@config.port}' >> '#{resolver_path}'")
222
+ script.close
213
223
 
224
+ Kernel.system("/usr/bin/osascript -e 'do shell script \"sh #{script.path}\" with administrator privileges' 2&>1 > /dev/null")
225
+ script.unlink
214
226
  true
215
- rescue
227
+ rescue Exception
216
228
  logger.error(i18n.resolver_creating_error)
217
229
  false
218
230
  end
219
231
  end
220
232
 
221
- # Writes a OSX resolver.
222
- #
223
- # @param resolver_path [String] The resolver path.
224
- def write_resolver(resolver_path)
225
- end
226
-
227
233
  # Deletes a OSX resolver.
228
234
  #
229
235
  # @param resolver_path [String] The resolver path.
230
236
  # @return [Boolean] `true` if operation succeeded, `false` otherwise.
231
237
  def delete_resolver(_, resolver_path)
232
- delete_file(resolver_path, :resolver_deleting, :resolver_deleting_error)
238
+ begin
239
+ logger.info(i18n.resolver_deleting(resolver_path))
240
+ Kernel.system("/usr/bin/osascript -e 'do shell script \"rm #{resolver_path}\" with administrator privileges' 2&>1 > /dev/null")
241
+ true
242
+ rescue Exception
243
+ logger.warn(i18n.resolver_deleting_error)
244
+ false
245
+ end
233
246
  end
234
247
 
235
248
  # Creates a OSX system agent.
@@ -238,7 +251,7 @@ module DevDNSd
238
251
  # @return [Boolean] `true` if operation succeeded, `false` otherwise.
239
252
  def create_agent(launch_agent, _)
240
253
  begin
241
- logger.info(i18n.agent_creating(launch_agent))
254
+ logger.info(replace_markers(i18n.agent_creating(launch_agent)))
242
255
  program, args = prepare_agent
243
256
 
244
257
  ::File.open(launch_agent, "w") {|f|
@@ -305,6 +318,14 @@ module DevDNSd
305
318
  false
306
319
  end
307
320
  end
321
+
322
+ # Replaces markers in a log message.
323
+ #
324
+ # @param message [String] The message to process.
325
+ # @return [String] The processed message.
326
+ def replace_markers(message)
327
+ @command.application.console.replace_markers(message)
328
+ end
308
329
  end
309
330
 
310
331
  # Methods to handle interfaces aliases.
@@ -464,7 +485,7 @@ module DevDNSd
464
485
  log_management(:run, prefix, type, locale.removing, locale.adding, address, config)
465
486
  rv = execute_command(command)
466
487
  labels = (type == :remove ? [locale.remove, locale.from] : [locale.add, locale.to])
467
- @logger.error(@command.application.console.replace_markers(locale.general_error(labels[0], address, labels[1], config.interface))) if !rv
488
+ @logger.error(replace_markers(locale.general_error(labels[0], address, labels[1], config.interface))) if !rv
468
489
  rv
469
490
  end
470
491
 
@@ -480,7 +501,7 @@ module DevDNSd
480
501
  def log_management(message, prefix, type, remove_label, add_label, address, config)
481
502
  locale = i18n
482
503
  labels = (type == :remove ? [remove_label, locale.from] : [add_label, locale.to])
483
- @logger.info(@command.application.console.replace_markers(i18n.send(message, prefix, labels[0], address, labels[1], config.interface)))
504
+ @logger.info(replace_markers(i18n.send(message, prefix, labels[0], address, labels[1], config.interface)))
484
505
  end
485
506
  end
486
507
 
@@ -624,7 +645,7 @@ module DevDNSd
624
645
  options = @command.application.get_options.reject {|_, v| v.nil? }
625
646
 
626
647
  # Setup logger
627
- @logger = Bovem::Logger.create(Bovem::Logger.get_real_file(options["log_file"]) || Bovem::Logger.default_file, Logger::INFO)
648
+ create_logger(options)
628
649
 
629
650
  # Open configuration
630
651
  read_configuration(options)
@@ -687,18 +708,59 @@ module DevDNSd
687
708
  end
688
709
 
689
710
  private
711
+ # Creates a logger.
712
+ #
713
+ # @param options [Hash] The configuration to use.
714
+ def create_logger(options)
715
+ warn_failure = false
716
+ orig_file = file = Bovem::Logger.get_real_file(options["log_file"]) || Bovem::Logger.default_file
717
+
718
+ if file.is_a?(String) then
719
+ file = File.absolute_path(File.expand_path(file))
720
+
721
+ begin
722
+ FileUtils.mkdir_p(File.dirname(file))
723
+ @logger = Bovem::Logger.create(file, Logger::INFO)
724
+ rescue
725
+ file = $stdout
726
+ warn_failure = true
727
+ end
728
+ end
729
+
730
+ @logger = Bovem::Logger.create(file, Logger::INFO)
731
+ @logger.warn(replace_markers(i18n.logging_failed(orig_file))) if @logger && warn_failure
732
+ @logger
733
+ end
734
+
690
735
  # Reads configuration.
691
736
  #
692
737
  # @param options [Hash] The configuration to read.
693
738
  def read_configuration(options)
739
+ path = ::File.absolute_path(File.expand_path(options["configuration"]))
740
+
694
741
  begin
695
- @config = DevDNSd::Configuration.new(options["configuration"], options, @logger)
742
+ @config = DevDNSd::Configuration.new(path, options, @logger)
743
+ ensure_directory_for(@config.log_file) if @config.log_file.is_a?(String)
744
+ ensure_directory_for(@config.pid_file)
745
+
696
746
  @logger = nil
697
747
  @logger = get_logger
698
748
  rescue Bovem::Errors::InvalidConfiguration => e
699
- logger = Bovem::Logger.create("STDERR")
749
+ logger = Bovem::Logger.create($stderr)
700
750
  logger.fatal(e.message)
701
- logger.warn(@command.application.console.replace_markers(i18n.application_create_config(options["configuration"])))
751
+ logger.warn(replace_markers(i18n.application_create_config(path)))
752
+ raise ::SystemExit
753
+ end
754
+ end
755
+
756
+ # Creates a folder for a file.
757
+ #
758
+ # @param [String] The path of the file.
759
+ def ensure_directory_for(path)
760
+ begin
761
+ FileUtils.mkdir_p(File.dirname(path))
762
+ rescue
763
+ @logger.warn(replace_markers(i18n.invalid_directory(File.dirname(path))))
702
764
  raise ::SystemExit
703
765
  end
704
766
  end
@@ -19,11 +19,11 @@ module DevDNSd
19
19
  # The TLD to manage. Default: `dev`.
20
20
  property :tld, default: "dev"
21
21
 
22
- # The PID file to use. Default: `/var/run/devdnsd.pid`.
23
- property :pid_file, default: "/var/log/devdnsd.pid"
22
+ # The PID file to use. Default: `~/.devdnsd/daemon.pid`.
23
+ property :pid_file, default: "~/.devdnsd/daemon.pid"
24
24
 
25
- # The file to log to. Default: `/var/log/devdnsd.log`.
26
- property :log_file, default: "/var/log/devdnsd.log"
25
+ # The file to log to. Default: `/var/log/daemon.log`.
26
+ property :log_file, default: "~/.devdnsd/daemon.log"
27
27
 
28
28
  # The minimum severity to log. Default: `Logger::INFO`.
29
29
  property :log_level, default: Logger::INFO
@@ -65,8 +65,13 @@ module DevDNSd
65
65
  super(file, overrides, logger)
66
66
 
67
67
  # Make sure some arguments are of correct type
68
- self.log_file = $stdout if log_file == "STDOUT"
69
- self.log_file = $stderr if log_file == "STDERR"
68
+ self.log_file = case log_file
69
+ when "STDOUT" then $stdout
70
+ when "STDERR" then $stderr
71
+ else File.absolute_path(File.expand_path(log_file))
72
+ end
73
+
74
+ self.pid_file = File.absolute_path(File.expand_path(pid_file))
70
75
  self.port = port.to_integer
71
76
  self.log_level = log_level.to_integer
72
77
 
@@ -16,7 +16,7 @@ module DevDNSd
16
16
  MINOR = 0
17
17
 
18
18
  # The patch version.
19
- PATCH = 7
19
+ PATCH = 8
20
20
 
21
21
  # The current version number of DevDNSd.
22
22
  STRING = [MAJOR, MINOR, PATCH].compact.join(".")
data/lib/devdnsd.rb CHANGED
@@ -12,6 +12,7 @@ require "mustache"
12
12
  require "ipaddr"
13
13
  require "fiber"
14
14
  require "plist"
15
+ require "tempfile"
15
16
 
16
17
  Lazier.load!(:object)
17
18
 
data/locales/en.yml CHANGED
@@ -17,6 +17,7 @@
17
17
  reply: "Reply is %1 with type %2."
18
18
  no_reply: "No reply found."
19
19
  no_agent: "Install DevDNSd as a local resolver is only available on MacOSX."
20
+ admin_privileges_warning: "Basing on your setup, the system might ask you up to twice to grant {mark=bright}osascript{/mark} application admin privileges."
20
21
  resolver_creating: "Creating the resolver in {mark=bright}%1{/mark} ..."
21
22
  resolver_creating_error: "Cannot create the resolver file."
22
23
  resolver_deleting: "Deleting the resolver %1 ..."
@@ -29,7 +30,8 @@
29
30
  agent_loading_error: "Cannot load the launch agent."
30
31
  agent_unloading: "Unloading the launch agent %1 ..."
31
32
  agent_unloading_error: "Cannot unload the launch agent."
32
- logging_failed: "Cannot log to {mark=bright}%1{/mark}. Exiting..."
33
+ logging_failed: "Cannot log to {mark=bright}%1{/mark}. Logging to terminal..."
34
+ invalid_directory: "Cannot write on directory {mark=bright}%1{/mark}. Exiting..."
33
35
  application_description: "A small DNS server to enable local domain resolution."
34
36
  application_help_configuration: "The configuration file to use. Default is \"~/.devdnsd_config\"."
35
37
  application_help_tld: "The TLD to handle. Default is \"dev\"."
data/locales/it.yml CHANGED
@@ -17,6 +17,7 @@
17
17
  reply: "La risposta è %1 con tipo %2."
18
18
  no_reply: "Nessuna risposta trovata."
19
19
  no_agent: "Installare DevDNSd come resolver locale è disponibile solo su MacOSX."
20
+ 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."
20
21
  resolver_creating: "Creo il resolver in {mark=bright}%1{/mark} ..."
21
22
  resolver_creating_error: "Impossible creare il file del resolver."
22
23
  resolver_deleting: "Cancello resolver %1 ..."
@@ -29,7 +30,8 @@
29
30
  agent_loading_error: "Impossibile avviare il launch agent."
30
31
  agent_unloading: "Fermo il launch agent %1 ..."
31
32
  agent_unloading_error: "Impossible fermare il launch agent."
32
- logging_failed: "Impossibile eseguire il logging in {mark=bright}%1{/mark}. Esco..."
33
+ logging_failed: "Impossibile eseguire il logging in {mark=bright}%1{/mark}. Eseguo il logging nel terminale..."
34
+ invalid_directory: "Impossibile scrivere sulla directory {mark=bright}%1{/mark}. Esco..."
33
35
  application_description: "Un piccolo server DNS per abilitare la risoluzione di domini locali."
34
36
  application_help_configuration: "Il file di configurazione da usare. Il valore predefinito è \"~/.devdnsd_config\"."
35
37
  application_help_tld: "Il TLD da gestiere. Il valore predefinito è \"dev\"."
@@ -17,7 +17,7 @@ describe DevDNSd::Application do
17
17
  option :configuration, [], {default: overrides["configuration"] || "/dev/null"}
18
18
  option :tld, [], {default: overrides["tld"] || "dev"}
19
19
  option :port, [], {type: Integer, default: overrides["port"] || 7771}
20
- option :pid_file, [:P, "pid-file"], {type: String, default: "/var/run/devdnsd.pid"}
20
+ option :pid_file, [:P, "pid-file"], {type: String, default: overrides["pid_file"] || "/var/run/devdnsd.pid"}
21
21
  option :log_file, [:l, "log-file"], {default: overrides["log_file"] || "/dev/null"}
22
22
  option :log_level, [:L, "log-level"], {type: Integer, default: overrides["log_level"] || 1}
23
23
  }, :en)
@@ -35,6 +35,12 @@ describe DevDNSd::Application do
35
35
  expect(application.logger).not_to be_nil
36
36
  end
37
37
 
38
+ it "should fallback logger to STDOUT" do
39
+ allow_any_instance_of(DevDNSd::Application).to receive(:read_configuration)
40
+ expect(Bovem::Logger).to receive(:create).with($stdout, Logger::INFO)
41
+ create_application({"log_file" => "/invalid/logger"})
42
+ end
43
+
38
44
  it "should setup the configuration" do
39
45
  expect(application.config).not_to be_nil
40
46
  end
@@ -50,6 +56,12 @@ describe DevDNSd::Application do
50
56
  expect { create_application({"configuration" => file.path, "log_file" => log_file}) }.to raise_error(::SystemExit)
51
57
  ::File.unlink(path)
52
58
  end
59
+
60
+ it "should abort when the log file is invalid" do
61
+ allow_any_instance_of(Bovem::Logger).to receive(:fatal)
62
+ allow_any_instance_of(Bovem::Logger).to receive(:warn)
63
+ expect { create_application({"pid_file" => "/invalid/pid", "log_file" => log_file}) }.to raise_error(::SystemExit)
64
+ end
53
65
  end
54
66
 
55
67
  describe ".run" do
@@ -339,8 +351,8 @@ describe DevDNSd::Application do
339
351
 
340
352
  describe "#dns_update" do
341
353
  it "should update the DNS cache" do
342
- allow(application).to receive(:execute_command).and_return("EXECUTED")
343
- expect(application.dns_update).to eq("EXECUTED")
354
+ allow(Kernel).to receive(:system).and_return("EXECUTED")
355
+ application.dns_update
344
356
  end
345
357
  end
346
358
 
@@ -559,6 +571,7 @@ describe DevDNSd::Application do
559
571
  before(:each) do
560
572
  allow(application).to receive(:is_osx?).and_return(true)
561
573
  allow(application).to receive(:execute_command)
574
+ expect(Kernel).to receive(:system).at_least(1)
562
575
  end
563
576
 
564
577
  it "should create the resolver" do
@@ -567,6 +580,7 @@ describe DevDNSd::Application do
567
580
  ::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
568
581
  ::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
569
582
 
583
+ allow(application).to receive(:create_resolver) {|_, path| FileUtils.touch(path) }
570
584
  application.action_install
571
585
  expect(::File.exists?(resolver_path)).to be_true
572
586
 
@@ -607,6 +621,8 @@ describe DevDNSd::Application do
607
621
  ::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
608
622
  ::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
609
623
 
624
+ allow(application).to receive(:create_agent).and_return(true)
625
+ expect_any_instance_of(R18n::Translation).to receive(:resolver_creating).and_raise(ArgumentError)
610
626
  expect(application.logger).to receive(:error).with("Cannot create the resolver file.")
611
627
  application.action_install
612
628
 
@@ -655,6 +671,7 @@ describe DevDNSd::Application do
655
671
  before(:each) do
656
672
  allow(application).to receive(:is_osx?).and_return(true)
657
673
  allow(application).to receive(:execute_command)
674
+ expect(Kernel).to receive(:system).at_least(1)
658
675
  end
659
676
 
660
677
  it "should remove the resolver" do
@@ -671,6 +688,23 @@ describe DevDNSd::Application do
671
688
  ::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
672
689
  end
673
690
 
691
+ it "should not remove an invalid resolver" do
692
+ allow(application).to receive(:resolver_path).and_return("/invalid/resolver")
693
+ allow(application).to receive(:launch_agent_path).and_return("/invalid/agent")
694
+ ::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
695
+ ::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
696
+
697
+ allow(application).to receive(:unload_agent).and_return(true)
698
+ expect_any_instance_of(R18n::Translation).to receive(:resolver_deleting).and_raise(ArgumentError)
699
+ expect(application.logger).to receive(:warn)
700
+ expect(application.logger).to receive(:warn).with("Cannot delete the resolver file.")
701
+
702
+ application.action_uninstall
703
+
704
+ ::File.unlink(application.resolver_path) if ::File.exists?(application.resolver_path)
705
+ ::File.unlink(application.launch_agent_path) if ::File.exists?(application.launch_agent_path)
706
+ end
707
+
674
708
  it "should remove the agent" do
675
709
  allow(application).to receive(:resolver_path).and_return(resolver_path)
676
710
  allow(application).to receive(:launch_agent_path).and_return(launch_agent_path)
@@ -14,11 +14,16 @@ describe DevDNSd::Configuration do
14
14
  expect(config.address).to eq("0.0.0.0")
15
15
  expect(config.port).to eq(7771)
16
16
  expect(config.tld).to eq("dev")
17
- expect(config.log_file).to eq("/var/log/devdnsd.log")
17
+ expect(config.log_file).to eq(File.absolute_path(File.expand_path("~/.devdnsd/daemon.log")))
18
18
  expect(config.log_level).to eq(::Logger::INFO)
19
19
  expect(config.rules.count).to eq(1)
20
20
  expect(config.foreground).to eq(false)
21
21
  end
22
+
23
+ it "should log to standard output or standard error" do
24
+ expect(DevDNSd::Configuration.new(nil, log_file: "STDOUT").log_file).to eq($stdout)
25
+ expect(DevDNSd::Configuration.new(nil, log_file: "STDERR").log_file).to eq($stderr)
26
+ end
22
27
  end
23
28
 
24
29
  describe "#add_rule" do
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: 3.0.7
4
+ version: 3.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shogun
@@ -82,6 +82,7 @@ files:
82
82
  - ".travis-gemfile"
83
83
  - ".travis.yml"
84
84
  - ".yardopts"
85
+ - '1'
85
86
  - CHANGELOG.md
86
87
  - Gemfile
87
88
  - README.md