diff options
Diffstat (limited to 'switchtower')
-rw-r--r-- | switchtower/CHANGELOG | 3 | ||||
-rw-r--r-- | switchtower/lib/switchtower/actor.rb | 38 | ||||
-rw-r--r-- | switchtower/lib/switchtower/command.rb | 2 | ||||
-rw-r--r-- | switchtower/test/actor_test.rb | 47 | ||||
-rw-r--r-- | switchtower/test/command_test.rb | 43 |
5 files changed, 96 insertions, 37 deletions
diff --git a/switchtower/CHANGELOG b/switchtower/CHANGELOG new file mode 100644 index 0000000000..e8681cfaeb --- /dev/null +++ b/switchtower/CHANGELOG @@ -0,0 +1,3 @@ +*SVN* + +* When executing multiline commands, use a backslash to escape the newline diff --git a/switchtower/lib/switchtower/actor.rb b/switchtower/lib/switchtower/actor.rb index cbaf8463e1..db25ca99c2 100644 --- a/switchtower/lib/switchtower/actor.rb +++ b/switchtower/lib/switchtower/actor.rb @@ -12,6 +12,27 @@ module SwitchTower # new actor via Configuration#actor. class Actor + # An adaptor for making the Net::SSH interface look and act like that of the + # Gateway class. + class DefaultConnectionFactory #:nodoc: + def initialize(config) + @config= config + end + + def connect_to(server) + Net::SSH.start(server, :username => @config.user, + :password => @config.password) + end + end + + class <<self + attr_accessor :connection_factory + attr_accessor :command_factory + end + + self.connection_factory = DefaultConnectionFactory + self.command_factory = Command + # The configuration instance associated with this actor. attr_reader :configuration @@ -37,19 +58,6 @@ module SwitchTower # A struct for representing a single instance of an invoked task. TaskCallFrame = Struct.new(:name, :rollback) - # An adaptor for making the Net::SSH interface look and act like that of the - # Gateway class. - class DefaultConnectionFactory #:nodoc: - def initialize(config) - @config= config - end - - def connect_to(server) - Net::SSH.start(server, :username => @config.user, - :password => @config.password) - end - end - # Represents the definition of a single task. class Task #:nodoc: attr_reader :name, :options @@ -88,7 +96,7 @@ module SwitchTower @tasks = {} @task_call_frames = [] @sessions = {} - @factory = DefaultConnectionFactory.new(configuration) + @factory = self.class.connection_factory.new(configuration) end # Define a new task for this actor. The block will be invoked when this @@ -134,7 +142,7 @@ module SwitchTower establish_connections(servers) # execute the command on each server in parallel - command = Command.new(servers, cmd, block, options, self) + command = self.class.command_factory.new(servers, cmd, block, options, self) command.process! # raises an exception if command fails on any server end end diff --git a/switchtower/lib/switchtower/command.rb b/switchtower/lib/switchtower/command.rb index 910c97cb45..807958fd76 100644 --- a/switchtower/lib/switchtower/command.rb +++ b/switchtower/lib/switchtower/command.rb @@ -7,7 +7,7 @@ module SwitchTower def initialize(servers, command, callback, options, actor) #:nodoc: @servers = servers - @command = command + @command = command.gsub(/\r?\n/, "\\\n") @callback = callback @options = options @actor = actor diff --git a/switchtower/test/actor_test.rb b/switchtower/test/actor_test.rb index bc33750b83..ed657ee26e 100644 --- a/switchtower/test/actor_test.rb +++ b/switchtower/test/actor_test.rb @@ -5,28 +5,24 @@ require 'test/unit' require 'switchtower/actor' require 'switchtower/logger' -module SwitchTower - class Actor - attr_reader :factory +class ActorTest < Test::Unit::TestCase - class DefaultConnectionFactory - def connect_to(server) - server - end + class TestingConnectionFactory + def initialize(config) end - class GatewayConnectionFactory - def connect_to(server) - server - end + def connect_to(server) + server end + end - def establish_gateway - GatewayConnectionFactory.new + class GatewayConnectionFactory + def connect_to(server) + server end end - class Command + class TestingCommand def self.invoked! @invoked = true end @@ -46,9 +42,18 @@ module SwitchTower self.class.invoked! end end -end -class ActorTest < Test::Unit::TestCase + class TestActor < SwitchTower::Actor + attr_reader :factory + + self.connection_factory = TestingConnectionFactory + self.command_factory = TestingCommand + + def establish_gateway + GatewayConnectionFactory.new + end + end + class MockConfiguration Role = Struct.new(:host, :options) @@ -79,8 +84,8 @@ class ActorTest < Test::Unit::TestCase end def setup - SwitchTower::Command.reset! - @actor = SwitchTower::Actor.new(MockConfiguration.new) + TestingCommand.reset! + @actor = TestActor.new(MockConfiguration.new) end def test_define_task_creates_method @@ -203,7 +208,7 @@ class ActorTest < Test::Unit::TestCase end @actor.foo - assert_instance_of SwitchTower::Actor::GatewayConnectionFactory, @actor.factory + assert_instance_of GatewayConnectionFactory, @actor.factory end def test_run_when_not_pretend @@ -213,7 +218,7 @@ class ActorTest < Test::Unit::TestCase @actor.configuration.pretend = false @actor.foo - assert SwitchTower::Command.invoked? + assert TestingCommand.invoked? end def test_run_when_pretend @@ -223,7 +228,7 @@ class ActorTest < Test::Unit::TestCase @actor.configuration.pretend = true @actor.foo - assert !SwitchTower::Command.invoked? + assert !TestingCommand.invoked? end def test_task_before_hook diff --git a/switchtower/test/command_test.rb b/switchtower/test/command_test.rb new file mode 100644 index 0000000000..7005ba0f2d --- /dev/null +++ b/switchtower/test/command_test.rb @@ -0,0 +1,43 @@ +$:.unshift File.dirname(__FILE__) + "/../lib" + +require 'stringio' +require 'test/unit' +require 'switchtower/command' + +class CommandTest < Test::Unit::TestCase + class MockSession + def open_channel + { :closed => true, :status => 0 } + end + end + + class MockActor + attr_reader :sessions + + def initialize + @sessions = Hash.new { |h,k| h[k] = MockSession.new } + end + end + + def setup + @actor = MockActor.new + end + + def test_command_executes_on_all_servers + command = SwitchTower::Command.new(%w(server1 server2 server3), + "hello", nil, {}, @actor) + assert_equal %w(server1 server2 server3), @actor.sessions.keys.sort + end + + def test_command_with_newlines + command = SwitchTower::Command.new(%w(server1), "hello\nworld", nil, {}, + @actor) + assert_equal "hello\\\nworld", command.command + end + + def test_command_with_windows_newlines + command = SwitchTower::Command.new(%w(server1), "hello\r\nworld", nil, {}, + @actor) + assert_equal "hello\\\nworld", command.command + end +end |