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

Merge pull request #810 from forward3d/host_filter

Add ability to filter tasks to specific servers (host filtering).
This commit is contained in:
Tom Clements 2013-12-20 05:58:09 -08:00
commit 20fec69f99
6 changed files with 183 additions and 2 deletions

View file

@ -4,6 +4,7 @@ Reverse Chronological Order:
## master ## master
* Add ability to filter tasks to specific servers (host filtering). (@andytinycat)
* Add a command line option to control role filter (`--roles`) (@andytinycat) * Add a command line option to control role filter (`--roles`) (@andytinycat)
* Use an SCM object with a pluggable strategy * Use an SCM object with a pluggable strategy

View file

@ -16,7 +16,7 @@ module Capistrano
end end
def sort_options(options) def sort_options(options)
options.push(version, dry_run, roles) options.push(version, roles, dry_run, hostfilter)
super super
end end
@ -74,6 +74,16 @@ module Capistrano
} }
] ]
end 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
end end

View file

@ -1,5 +1,6 @@
require 'set' require 'set'
require_relative 'servers/role_filter' require_relative 'servers/role_filter'
require_relative 'servers/host_filter'
module Capistrano module Capistrano
class Configuration class Configuration
class Servers class Servers
@ -39,7 +40,7 @@ module Capistrano
def fetch_roles(required, options) def fetch_roles(required, options)
filter_roles = RoleFilter.for(required, available_roles) filter_roles = RoleFilter.for(required, available_roles)
select(servers_with_roles(filter_roles), options) HostFilter.for(select(servers_with_roles(filter_roles), options))
end end
def servers_with_roles(roles) def servers_with_roles(roles)

View 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

View file

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

View file

@ -179,6 +179,7 @@ module Capistrano
before do before do
ENV.stubs(:[]).with('ROLES').returns('web,db') ENV.stubs(:[]).with('ROLES').returns('web,db')
ENV.stubs(:[]).with('HOSTS').returns(nil)
servers.add_host('1', roles: :app, active: true) servers.add_host('1', roles: :app, active: true)
servers.add_host('2', roles: :app) servers.add_host('2', roles: :app)
servers.add_host('3', roles: :web) servers.add_host('3', roles: :web)