Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 8924

Show
Ignore:
Timestamp:
02/22/08 04:07:16 (7 months ago)
Author:
minam
Message:

Add support for :max_hosts option in task definition or run() (closes #10264)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • tools/capistrano/CHANGELOG

    r8923 r8924  
    11*SVN* 
     2 
     3* Add support for :max_hosts option in task definition or run() [Rob Holland <rob@inversepath.com>] 
    24 
    35* Distributed git support for better operability with remote_cache strategy [voidlock] 
  • tools/capistrano/lib/capistrano/configuration/connections.rb

    r7205 r8924  
     1 
     2require 'enumerator' 
    13require 'capistrano/gateway' 
    24require 'capistrano/ssh' 
     
    9698      end 
    9799 
     100      # Destroys sessions for each server in the list. 
     101      def teardown_connections_to(servers) 
     102        servers.each do |server| 
     103           @sessions[server].close 
     104           @sessions.delete(server) 
     105         end 
     106      end 
     107 
    98108      # Determines the set of servers within the current task's scope and 
    99109      # establishes connections to them, and then yields that list of 
     
    121131        logger.trace "servers: #{servers.map { |s| s.host }.inspect}" 
    122132 
    123         # establish connections to those servers, as necessary 
    124         begin 
    125           establish_connections_to(servers) 
    126         rescue ConnectionError => error 
    127           raise error unless task && task.continue_on_error? 
    128           error.hosts.each do |h| 
    129             servers.delete(h) 
    130             failed!(h) 
     133        max_hosts = (options[:max_hosts] || (task && task.max_hosts) || servers.size).to_i 
     134        is_subset = max_hosts < servers.size 
     135 
     136        # establish connections to those servers in groups of max_hosts, as necessary 
     137        servers.each_slice(max_hosts) do |servers_slice| 
     138          begin 
     139            establish_connections_to(servers_slice) 
     140          rescue ConnectionError => error 
     141            raise error unless task && task.continue_on_error? 
     142            error.hosts.each do |h| 
     143              servers_slice.delete(h) 
     144              failed!(h) 
     145            end 
    131146          end 
    132         end 
    133147 
    134         begin 
    135           yield servers 
    136         rescue RemoteError => error 
    137           raise error unless task && task.continue_on_error? 
    138           error.hosts.each { |h| failed!(h) } 
     148          begin 
     149            yield servers_slice 
     150          rescue RemoteError => error 
     151            raise error unless task && task.continue_on_error? 
     152            error.hosts.each { |h| failed!(h) } 
     153          end 
     154 
     155          # if dealing with a subset (e.g., :max_hosts is less than the 
     156          # number of servers available) teardown the subset of connections 
     157          # that were just made, so that we can make room for the next subset. 
     158          teardown_connections_to(servers_slice) if is_subset 
    139159        end 
    140160      end 
  • tools/capistrano/lib/capistrano/task_definition.rb

    r7205 r8924  
    44  # Represents the definition of a single task. 
    55  class TaskDefinition 
    6     attr_reader :name, :namespace, :options, :body, :desc, :on_error 
     6    attr_reader :name, :namespace, :options, :body, :desc, :on_error, :max_hosts 
    77 
    88    def initialize(name, namespace, options={}, &block) 
     
    1010      @desc = @options.delete(:desc) 
    1111      @on_error = options.delete(:on_error) 
     12      @max_hosts = options[:max_hosts] && options[:max_hosts].to_i 
    1213      @body = block or raise ArgumentError, "a task requires a block" 
    1314      @servers = nil 
  • tools/capistrano/test/configuration/connections_test.rb

    r7373 r8924  
    218218    @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns(list) 
    219219    Capistrano::SSH.expects(:connect).times(2).raises(Exception).then.returns(:success) 
    220     @config.expects(:failed!).with(server("cap1")) 
    221220    @config.execute_on_servers do |servers| 
    222221      assert_equal %w(cap2), servers.map { |s| s.host } 
     
    261260    end 
    262261  end 
    263  
     262   
    264263  def test_connect_should_establish_connections_to_all_servers_in_scope 
    265264    assert @config.sessions.empty? 
     
    270269    assert_equal %w(cap1 cap2 cap3), @config.sessions.keys.sort.map { |s| s.host } 
    271270  end 
    272  
     271   
     272  def test_execute_on_servers_should_only_run_on_tasks_max_hosts_hosts_at_once 
     273    cap1 = server("cap1") 
     274    cap2 = server("cap2") 
     275    connection1 = mock() 
     276    connection2 = mock() 
     277    connection1.expects(:close) 
     278    connection2.expects(:close) 
     279    @config.current_task = mock_task(:max_hosts => 1) 
     280    @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([cap1, cap2]) 
     281    Capistrano::SSH.expects(:connect).times(2).returns(connection1).then.returns(connection2) 
     282    block_called = 0 
     283    @config.execute_on_servers do |servers| 
     284      block_called += 1 
     285      assert_equal 1, servers.size 
     286    end 
     287    assert_equal 2, block_called 
     288  end 
     289   
     290  def test_execute_on_servers_should_only_run_on_max_hosts_hosts_at_once 
     291    cap1 = server("cap1") 
     292    cap2 = server("cap2") 
     293    connection1 = mock() 
     294    connection2 = mock() 
     295    connection1.expects(:close) 
     296    connection2.expects(:close) 
     297    @config.current_task = mock_task(:max_hosts => 1) 
     298    @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([cap1, cap2]) 
     299    Capistrano::SSH.expects(:connect).times(2).returns(connection1).then.returns(connection2) 
     300    block_called = 0 
     301    @config.execute_on_servers do |servers| 
     302      block_called += 1 
     303      assert_equal 1, servers.size 
     304    end 
     305    assert_equal 2, block_called 
     306  end 
     307   
    273308  def test_connect_should_honor_once_option 
    274309    assert @config.sessions.empty? 
     
    284319    def mock_task(options={}) 
    285320      continue_on_error = options[:on_error] == :continue 
    286       stub("task", :fully_qualified_name => "name", :options => options, :continue_on_error? => continue_on_error) 
     321      stub("task", 
     322        :fully_qualified_name => "name", 
     323        :options => options, 
     324        :continue_on_error? => continue_on_error, 
     325        :max_hosts => options[:max_hosts] 
     326      ) 
    287327    end 
    288328end