1
0
Fork 0
mirror of https://github.com/capistrano/capistrano synced 2023-03-27 23:21:18 -04:00

When executing multiline commands, escape newlines with a backslash

git-svn-id: http://svn.rubyonrails.org/rails/trunk/switchtower@1975 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
Jamis Buck 2005-08-06 19:35:25 +00:00
parent 936c35fdc1
commit 71e6cc2cb8
5 changed files with 98 additions and 39 deletions

3
CHANGELOG Normal file
View file

@ -0,0 +1,3 @@
*SVN*
* When executing multiline commands, use a backslash to escape the newline

View file

@ -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

View file

@ -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

View file

@ -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
end
def establish_gateway
GatewayConnectionFactory.new
def connect_to(server)
server
end
end
class Command
class GatewayConnectionFactory
def connect_to(server)
server
end
end
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

43
test/command_test.rb Normal file
View file

@ -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