From 760b47ba05f8744c34e7bba1e4d6b16c343ff078 Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Wed, 3 Oct 2007 22:08:05 -0700 Subject: [PATCH] convert drb to use unix socket --- History.txt | 1 + Manifest.txt | 6 +-- bin/god | 4 +- lib/god.rb | 13 ++----- lib/god/reporter.rb | 25 ------------- lib/god/server.rb | 49 ------------------------ lib/god/socket.rb | 60 ++++++++++++++++++++++++++++++ test/configs/child_events/child_events.god | 4 -- test/test_god.rb | 12 +++--- test/test_hub.rb | 2 +- test/test_reporter.rb | 18 --------- test/{test_server.rb => test_socket.rb} | 26 +++---------- 12 files changed, 81 insertions(+), 139 deletions(-) delete mode 100644 lib/god/reporter.rb delete mode 100644 lib/god/server.rb create mode 100644 lib/god/socket.rb delete mode 100644 test/test_reporter.rb rename test/{test_server.rb => test_socket.rb} (51%) diff --git a/History.txt b/History.txt index f7c661d..f3f96bd 100644 --- a/History.txt +++ b/History.txt @@ -7,6 +7,7 @@ * Add Tasks (a generalization of Watches) to do non-process related tasks * Add example init.d file in GOD_INSTALL_DIR/init/god [scott becker] * Add human readable info to conditions (and make low level log lines debug) + * Switch DRb to use a unix domain socket for security reasons * Minor Enchancements * Allow EventConditions to do transition overloading * Report errors during god startup instead of failing silently diff --git a/Manifest.txt b/Manifest.txt index 17a48c1..b997314 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -38,8 +38,7 @@ lib/god/logger.rb lib/god/metric.rb lib/god/process.rb lib/god/registry.rb -lib/god/reporter.rb -lib/god/server.rb +lib/god/socket.rb lib/god/sugar.rb lib/god/system/process.rb lib/god/task.rb @@ -84,8 +83,7 @@ test/test_logger.rb test/test_metric.rb test/test_process.rb test/test_registry.rb -test/test_reporter.rb -test/test_server.rb +test/test_socket.rb test/test_sugar.rb test/test_system_process.rb test/test_task.rb diff --git a/bin/god b/bin/god index 208e4c7..b0d9cd9 100755 --- a/bin/god +++ b/bin/god @@ -92,9 +92,9 @@ begin # a command was specified - # connect to remote drb + # connect to drb unix socket DRb.start_service - server = DRbObject.new nil, "druby://127.0.0.1:#{options[:port]}" + server = DRbObject.new(nil, God::Socket.socket(options[:port])) begin server.ping diff --git a/lib/god.rb b/lib/god.rb index 05ffe43..4bef751 100644 --- a/lib/god.rb +++ b/lib/god.rb @@ -36,8 +36,7 @@ require 'god/conditions/http_response_code' require 'god/contact' require 'god/contacts/email' -require 'god/reporter' -require 'god/server' +require 'god/socket' require 'god/timer' require 'god/hub' @@ -103,8 +102,6 @@ end class Module def safe_attr_accessor(*args) args.each do |arg| - # instance_variable_set(('@' + arg.to_s).intern, 'foo') - define_method((arg.to_s + "=").intern) do |other| if !self.running && self.inited abort "God.#{arg} must be set before any Tasks are defined" @@ -154,15 +151,11 @@ module God end self.host = nil + self.port = nil self.allow = nil self.log_buffer_size = nil self.pid_file_directory = nil - # deprecated - def self.init - yield self if block_given? - end - def self.internal_init # only do this once return if self.inited @@ -446,7 +439,7 @@ module God self.validater # instantiate server - self.server = Server.new(self.host, self.port, self.allow) + self.server = Socket.new(self.port) # start event handler system EventHandler.start if EventHandler.loaded? diff --git a/lib/god/reporter.rb b/lib/god/reporter.rb deleted file mode 100644 index e57f9c7..0000000 --- a/lib/god/reporter.rb +++ /dev/null @@ -1,25 +0,0 @@ -require 'drb' - -module God - - class Reporter - def initialize(host = nil, port = nil) - @host = host - @port = port || 7777 - @service = nil - end - - def method_missing(*args, &block) - service.send(*args, &block) - end - - private - - def service - return @service if @service - DRb.start_service - @service = DRbObject.new(nil, "druby://#{@host}:#{@port}") - end - end - -end diff --git a/lib/god/server.rb b/lib/god/server.rb deleted file mode 100644 index 2558b78..0000000 --- a/lib/god/server.rb +++ /dev/null @@ -1,49 +0,0 @@ -require 'drb' -require 'drb/acl' - -# The God::Server oversees the DRb server which dishes out info on this God daemon. - -module God - - class Server - attr_reader :host, :port - - def initialize(host = nil, port = nil, allow = []) - @host = host - @port = port - @acl = %w{deny all} + allow.inject([]) { |acc, a| acc + ['allow', a] } - start - end - - def ping - true - end - - def method_missing(*args, &block) - God.send(*args, &block) - end - - private - - def start - acl = ACL.new(@acl) - DRb.install_acl(acl) - - begin - @drb ||= DRb.start_service("druby://#{@host}:#{@port}", self) - LOG.log(nil, :info, "Started on #{DRb.uri}") - rescue Errno::EADDRINUSE - DRb.start_service - server = DRbObject.new nil, "druby://127.0.0.1:#{@port}" - - begin - server.ping - abort "Address #{@host}:#{@port} already in use by another instance of god" - rescue - abort "Address #{@host}:#{@port} already in use by a non-god process" - end - end - end - end - -end diff --git a/lib/god/socket.rb b/lib/god/socket.rb new file mode 100644 index 0000000..ac144e9 --- /dev/null +++ b/lib/god/socket.rb @@ -0,0 +1,60 @@ +require 'drb' + +# The God::Server oversees the DRb server which dishes out info on this God daemon. + +module God + + class Socket + attr_reader :port + + def self.socket_file(port) + "/tmp/god.#{port}.sock" + end + + def self.socket(port) + "drbunix://#{self.socket_file(port)}" + end + + def socket_file + self.class.socket_file(@port) + end + + def socket + self.class.socket(@port) + end + + def initialize(port = nil) + @port = port + start + end + + def ping + true + end + + def method_missing(*args, &block) + God.send(*args, &block) + end + + private + + def start + begin + @drb ||= DRb.start_service(self.socket, self) + LOG.log(nil, :info, "Started on #{DRb.uri}") + rescue Errno::EADDRINUSE + DRb.start_service + server = DRbObject.new(nil, self.socket) + + begin + server.ping + abort "Socket #{self.socket} already in use by another instance of god" + rescue + File.delete(self.socket_file) rescue nil + @drb ||= DRb.start_service(self.socket, self) + end + end + end + end + +end diff --git a/test/configs/child_events/child_events.god b/test/configs/child_events/child_events.god index 67bfb50..0e6a791 100644 --- a/test/configs/child_events/child_events.god +++ b/test/configs/child_events/child_events.god @@ -1,7 +1,3 @@ -God.init do |god| - god.host = '127.0.0.1' -end - God.watch do |w| w.name = "child-events" w.interval = 5.seconds diff --git a/test/test_god.rb b/test/test_god.rb index 9cd7da0..687a312 100644 --- a/test/test_god.rb +++ b/test/test_god.rb @@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/helper' class TestGod < Test::Unit::TestCase def setup - Server.stubs(:new).returns(true) + God::Socket.stubs(:new).returns(true) God.stubs(:setup).returns(true) God.stubs(:validater).returns(true) God.reset @@ -21,11 +21,11 @@ class TestGod < Test::Unit::TestCase # init - def test_init_should_abort_if_called_after_watch + def test_pid_file_directory_should_abort_if_called_after_watch God.watch { |w| w.name = 'foo'; w.start = 'bar' } assert_abort do - God.init { |g| g.pid_file_directory = 'foo' } + God.pid_file_directory = 'foo' end end @@ -37,8 +37,8 @@ class TestGod < Test::Unit::TestCase end def test_pid_file_directory_equals_should_set - God.init God.pid_file_directory = '/foo' + God.internal_init assert_equal '/foo', God.pid_file_directory end @@ -454,7 +454,7 @@ class TestGod < Test::Unit::TestCase # start def test_start_should_kick_off_a_server_instance - Server.expects(:new).returns(true) + God::Socket.expects(:new).returns(true) God.start end @@ -509,7 +509,7 @@ end class TestGodOther < Test::Unit::TestCase def setup - Server.stubs(:new).returns(true) + God::Socket.stubs(:new).returns(true) God.internal_init God.reset end diff --git a/test/test_hub.rb b/test/test_hub.rb index 1b4f127..3ba4de6 100644 --- a/test/test_hub.rb +++ b/test/test_hub.rb @@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/helper' class TestHub < Test::Unit::TestCase def setup - Server.stubs(:new).returns(true) + God::Socket.stubs(:new).returns(true) God.reset God.watch do |w| diff --git a/test/test_reporter.rb b/test/test_reporter.rb deleted file mode 100644 index 7bd8266..0000000 --- a/test/test_reporter.rb +++ /dev/null @@ -1,18 +0,0 @@ -require File.dirname(__FILE__) + '/helper' - -class TestReporter < Test::Unit::TestCase - - def test_should_create_a_drb_object - DRb.expects(:start_service) - DRbObject.expects(:new).with(nil, "druby://host:port").returns(stub(:anything => true)) - - Reporter.new('host', 'port').anything - end - - def test_should_forward_unknown_methods_to_drb_object - Reporter.any_instance.expects(:service).returns(mock(:something_fake => true)) - - reporter = Reporter.new('host', 'port') - reporter.something_fake - end -end diff --git a/test/test_server.rb b/test/test_socket.rb similarity index 51% rename from test/test_server.rb rename to test/test_socket.rb index e413274..8ae4219 100644 --- a/test/test_server.rb +++ b/test/test_socket.rb @@ -1,6 +1,6 @@ require File.dirname(__FILE__) + '/helper' -class TestServer < Test::Unit::TestCase +class TestSocket < Test::Unit::TestCase def setup silence_warnings do Object.const_set(:DRb, stub_everything) @@ -10,46 +10,32 @@ class TestServer < Test::Unit::TestCase def test_should_start_a_drb_server DRb.expects(:start_service) no_stdout do - Server.new + God::Socket.new end end def test_should_use_supplied_port_and_host - DRb.expects(:start_service).with { |uri, object| uri == "druby://host:port" && object.is_a?(Server) } + DRb.expects(:start_service).with { |uri, object| uri == "drbunix:///tmp/god.9999.sock" && object.is_a?(God::Socket) } no_stdout do - server = Server.new('host', 'port') + server = God::Socket.new(9999) end end def test_should_forward_foreign_method_calls_to_god server = nil no_stdout do - server = Server.new + server = God::Socket.new end God.expects(:send).with(:something_random) server.something_random end - def test_should_install_deny_all_by_default - ACL.expects(:new).with(%w{deny all}) - no_stdout do - Server.new - end - end - - def test_should_install_pass_through_acl - ACL.expects(:new).with(%w{deny all allow 127.0.0.1 allow 0.0.0.0}) - no_stdout do - Server.new(nil, 17165, %w{127.0.0.1 0.0.0.0}) - end - end - # ping def test_ping_should_return_true server = nil no_stdout do - server = Server.new + server = God::Socket.new end assert server.ping end -- 2.11.4.GIT