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

Merge pull request #383 from mpapis/feature/improved_command_logging_for_parallel

Improve parallel commands logging
This commit is contained in:
Lee Hambley 2013-04-02 10:46:52 -07:00
commit 7b585024c2
5 changed files with 60 additions and 31 deletions

View file

@ -17,7 +17,7 @@ module Capistrano
include Enumerable include Enumerable
class Branch class Branch
attr_accessor :command, :callback attr_accessor :command, :callback, :condition
attr_reader :options attr_reader :options
def initialize(command, options, callback) def initialize(command, options, callback)
@ -43,14 +43,17 @@ module Capistrano
true true
end end
def to_s def to_s(parallel=false)
if parallel && @condition
"#{condition.inspect} :: #{command.inspect}"
else
command.inspect command.inspect
end end
end end
end
class ConditionBranch < Branch class ConditionBranch < Branch
attr_accessor :configuration attr_accessor :configuration
attr_accessor :condition
class Evaluator class Evaluator
attr_reader :configuration, :condition, :server attr_reader :configuration, :condition, :server
@ -89,9 +92,12 @@ module Capistrano
def match(server) def match(server)
Evaluator.new(configuration, condition, server).result Evaluator.new(configuration, condition, server).result
end end
end
def to_s class ElseBranch < Branch
"#{condition.inspect} :: #{command.inspect}" def initialize(command, options, callback)
@condition = "else"
super(command, options, callback)
end end
end end
@ -106,7 +112,7 @@ module Capistrano
end end
def else(command, &block) def else(command, &block)
@fallback = Branch.new(command, {}, block) @fallback = ElseBranch.new(command, {}, block)
end end
def branches_for(server) def branches_for(server)

View file

@ -159,12 +159,26 @@ module Capistrano
# use, but should instead be called indirectly, via #run or #parallel, # use, but should instead be called indirectly, via #run or #parallel,
# or #invoke_command. # or #invoke_command.
def run_tree(tree, options={}) #:nodoc: def run_tree(tree, options={}) #:nodoc:
if tree.branches.empty? && tree.fallback options = add_default_command_options(options)
logger.debug "executing #{tree.fallback}" unless options[:silent]
elsif tree.branches.any? if tree.branches.any? || tree.fallback
_, servers = filter_servers(options)
branches = servers.map{|server| tree.branches_for(server)}.compact
case branches.size
when 0
branches = tree.branches.dup + [tree.fallback]
case branches.size
when 1
logger.debug "no servers for #{branches.first}"
else
logger.debug "no servers for commands"
branches.each{ |branch| logger.trace "-> #{branch.to_s(true)}" }
end
when 1
logger.debug "executing #{branches.first}" unless options[:silent]
else
logger.debug "executing multiple commands in parallel" logger.debug "executing multiple commands in parallel"
tree.each do |branch| branches.each{ |branch| logger.trace "-> #{branch.to_s(true)}" }
logger.trace "-> #{branch}"
end end
else else
raise ArgumentError, "attempt to execute without specifying a command" raise ArgumentError, "attempt to execute without specifying a command"
@ -172,8 +186,6 @@ module Capistrano
return if dry_run || (debug && continue_execution(tree) == false) return if dry_run || (debug && continue_execution(tree) == false)
options = add_default_command_options(options)
tree.each do |branch| tree.each do |branch|
if branch.command.include?(sudo) if branch.command.include?(sudo)
branch.callback = sudo_behavior_callback(branch.callback) branch.callback = sudo_behavior_callback(branch.callback)

View file

@ -147,37 +147,43 @@ module Capistrano
end end
end end
# Determines the set of servers within the current task's scope and # Determines the set of servers within the current task's scope
# establishes connections to them, and then yields that list of def filter_servers(options={})
# servers.
def execute_on_servers(options={})
raise ArgumentError, "expected a block" unless block_given?
if task = current_task if task = current_task
servers = find_servers_for_task(task, options) servers = find_servers_for_task(task, options)
if servers.empty? if servers.empty?
if ENV['HOSTFILTER'] || task.options.merge(options)[:on_no_matching_servers] == :continue if ENV['HOSTFILTER'] || task.options.merge(options)[:on_no_matching_servers] == :continue
logger.info "skipping `#{task.fully_qualified_name}' because no servers matched" logger.info "skipping `#{task.fully_qualified_name}' because no servers matched"
return
else else
unless dry_run
raise Capistrano::NoMatchingServersError, "`#{task.fully_qualified_name}' is only run for servers matching #{task.options.inspect}, but no servers matched" raise Capistrano::NoMatchingServersError, "`#{task.fully_qualified_name}' is only run for servers matching #{task.options.inspect}, but no servers matched"
end end
end end
end
if task.continue_on_error? if task.continue_on_error?
servers.delete_if { |s| has_failed?(s) } servers.delete_if { |s| has_failed?(s) }
return if servers.empty?
end end
else else
servers = find_servers(options) servers = find_servers(options)
if servers.empty? if servers.empty? && !dry_run
raise Capistrano::NoMatchingServersError, "no servers found to match #{options.inspect}" if options[:on_no_matching_servers] != :continue raise Capistrano::NoMatchingServersError, "no servers found to match #{options.inspect}" if options[:on_no_matching_servers] != :continue
return
end end
end end
servers = [servers.first] if options[:once] servers = [servers.first] if options[:once]
[task, servers.compact]
end
# Determines the set of servers within the current task's scope and
# establishes connections to them, and then yields that list of
# servers.
def execute_on_servers(options={})
raise ArgumentError, "expected a block" unless block_given?
task, servers = filter_servers(options)
return if servers.empty?
logger.trace "servers: #{servers.map { |s| s.host }.inspect}" logger.trace "servers: #{servers.map { |s| s.host }.inspect}"
max_hosts = (options[:max_hosts] || (task && task.max_hosts) || servers.size).to_i max_hosts = (options[:max_hosts] || (task && task.max_hosts) || servers.size).to_i

View file

@ -27,6 +27,10 @@ class ConfigurationActionsInvocationTest < Test::Unit::TestCase
@options.fetch(*args) @options.fetch(*args)
end end
def filter_servers(options = {})
[nil, @servers]
end
def execute_on_servers(options = {}) def execute_on_servers(options = {})
yield @servers yield @servers
end end

View file

@ -5,6 +5,7 @@ class ConfigurationConnectionsTest < Test::Unit::TestCase
class MockConfig class MockConfig
attr_reader :original_initialize_called attr_reader :original_initialize_called
attr_reader :values attr_reader :values
attr_reader :dry_run
attr_accessor :current_task attr_accessor :current_task
def initialize def initialize