mirror of
https://github.com/capistrano/capistrano
synced 2023-03-27 23:21:18 -04:00
Add ability to filter tasks to specific servers (host filtering).
This commit adds the ability to control what servers are involved in an task from the command line, or by setting an environment variable. The filter contains a list of servers; these are the only servers that will be involved in the task. For example, if you had three servers defined in your configuration (server1, server2 and server3), you could deploy to only server1 by doing either: cap --hosts server1 production deploy Or: HOSTS=server1 cap production deploy Multiple servers can be specified by separating them with commas: cap --hosts server1,server2 production deploy HOSTS=server1,server2 cap production deploy Host filtering happens after role filtering, and does not change what roles a server will respond to.
This commit is contained in:
parent
7b438780cc
commit
a1d3bfb524
6 changed files with 183 additions and 2 deletions
|
@ -4,6 +4,7 @@ Reverse Chronological Order:
|
|||
|
||||
## master
|
||||
|
||||
* Add ability to filter tasks to specific servers (host filtering). (@andytinycat)
|
||||
* Add a command line option to control role filter (`--roles`) (@andytinycat)
|
||||
|
||||
## `3.1.0` (not released)
|
||||
|
|
|
@ -16,7 +16,7 @@ module Capistrano
|
|||
end
|
||||
|
||||
def sort_options(options)
|
||||
options.push(version, dry_run, roles)
|
||||
options.push(version, roles, dry_run, hostfilter)
|
||||
super
|
||||
end
|
||||
|
||||
|
@ -74,6 +74,16 @@ module Capistrano
|
|||
}
|
||||
]
|
||||
end
|
||||
|
||||
def hostfilter
|
||||
['--hosts HOSTS', '-z',
|
||||
"Filter command to only apply to these hosts (separate multiple hosts with a comma)",
|
||||
lambda { |value|
|
||||
Configuration.env.set(:filter, :hosts => value.split(","))
|
||||
}
|
||||
]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
require 'set'
|
||||
require_relative 'servers/role_filter'
|
||||
require_relative 'servers/host_filter'
|
||||
module Capistrano
|
||||
class Configuration
|
||||
class Servers
|
||||
|
@ -39,7 +40,7 @@ module Capistrano
|
|||
|
||||
def fetch_roles(required, options)
|
||||
filter_roles = RoleFilter.for(required, available_roles)
|
||||
select(servers_with_roles(filter_roles), options)
|
||||
HostFilter.for(select(servers_with_roles(filter_roles), options))
|
||||
end
|
||||
|
||||
def servers_with_roles(roles)
|
||||
|
|
82
lib/capistrano/configuration/servers/host_filter.rb
Normal file
82
lib/capistrano/configuration/servers/host_filter.rb
Normal file
|
@ -0,0 +1,82 @@
|
|||
module Capistrano
|
||||
class Configuration
|
||||
class Servers
|
||||
class HostFilter
|
||||
|
||||
def initialize(available)
|
||||
@available = available
|
||||
end
|
||||
|
||||
def self.for(available)
|
||||
new(available).hosts
|
||||
end
|
||||
|
||||
def hosts
|
||||
if host_filter.any?
|
||||
@available.select { |server| host_filter.include? server.hostname }
|
||||
else
|
||||
@available
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def filter
|
||||
if host_filter.any?
|
||||
host_filter
|
||||
else
|
||||
@available
|
||||
end
|
||||
end
|
||||
|
||||
def host_filter
|
||||
env_filter | configuration_filter
|
||||
end
|
||||
|
||||
def configuration_filter
|
||||
ConfigurationFilter.new.hosts
|
||||
end
|
||||
|
||||
def env_filter
|
||||
EnvFilter.new.hosts
|
||||
end
|
||||
|
||||
class ConfigurationFilter
|
||||
|
||||
def hosts
|
||||
if filter
|
||||
Array(filter.fetch(:hosts, []))
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
def config
|
||||
Configuration.env
|
||||
end
|
||||
|
||||
def filter
|
||||
config.fetch(:filter) || config.fetch(:select)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class EnvFilter
|
||||
|
||||
def hosts
|
||||
if filter
|
||||
filter.split(',')
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
def filter
|
||||
ENV['HOSTS']
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,86 @@
|
|||
require 'spec_helper'
|
||||
|
||||
module Capistrano
|
||||
class Configuration
|
||||
class Servers
|
||||
|
||||
describe HostFilter do
|
||||
let(:host_filter) { HostFilter.new(available) }
|
||||
let(:available) { [ Server.new('server1'), Server.new('server2'), Server.new('server3') ] }
|
||||
|
||||
describe '#new' do
|
||||
it 'takes one array of hostnames' do
|
||||
expect(host_filter)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.for' do
|
||||
|
||||
subject { HostFilter.for(available) }
|
||||
|
||||
context 'without env vars' do
|
||||
|
||||
it 'returns all available hosts' do
|
||||
expect(subject).to eq available
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'with ENV vars' do
|
||||
before do
|
||||
ENV.stubs(:[]).with('HOSTS').returns('server1,server2')
|
||||
end
|
||||
|
||||
it 'returns all required hosts defined in HOSTS' do
|
||||
expect(subject).to eq [Server.new('server1'), Server.new('server2')]
|
||||
end
|
||||
end
|
||||
|
||||
context 'with configuration filters' do
|
||||
before do
|
||||
Configuration.env.set(:filter, hosts: %w{server1 server2})
|
||||
end
|
||||
|
||||
it 'returns all required hosts defined in the filter' do
|
||||
expect(subject).to eq [Server.new('server1'), Server.new('server2')]
|
||||
end
|
||||
|
||||
after do
|
||||
Configuration.env.delete(:filter)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a single configuration filter' do
|
||||
before do
|
||||
Configuration.env.set(:filter, hosts: 'server3')
|
||||
end
|
||||
|
||||
it 'returns all required hosts defined in the filter' do
|
||||
expect(subject).to eq [Server.new('server3')]
|
||||
end
|
||||
|
||||
after do
|
||||
Configuration.env.delete(:filter)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with configuration filters and ENV vars' do
|
||||
before do
|
||||
Configuration.env.set(:filter, hosts: 'server1')
|
||||
ENV.stubs(:[]).with('HOSTS').returns('server3')
|
||||
end
|
||||
|
||||
it 'returns all required hosts defined in the filter' do
|
||||
expect(subject).to eq [Server.new('server1'), Server.new('server3')]
|
||||
end
|
||||
|
||||
after do
|
||||
Configuration.env.delete(:filter)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -179,6 +179,7 @@ module Capistrano
|
|||
|
||||
before do
|
||||
ENV.stubs(:[]).with('ROLES').returns('web,db')
|
||||
ENV.stubs(:[]).with('HOSTS').returns(nil)
|
||||
servers.add_host('1', roles: :app, active: true)
|
||||
servers.add_host('2', roles: :app)
|
||||
servers.add_host('3', roles: :web)
|
||||
|
|
Loading…
Add table
Reference in a new issue