From c344bc40b2d6ac5c0711992a54909bb4270c1d76 Mon Sep 17 00:00:00 2001 From: Lee Hambley Date: Tue, 28 May 2013 12:43:05 +0200 Subject: [PATCH] Enable filtering server list when querying. This patch makes it possible to do something like: server 'example.com', some_property: true on(:all, filter: :some_property) do |h| # ... end This is the shorthand syntax which checks the host properties for anything truthy matching the key name given. Symbols and strings are supported here. If a more complex match should be made, then a continuation can be given in the place of the smybol: server 'example.com', some_property: true on(:all, filter: lambda { |h| h.properties.some_property }) do |h| # ... end The keys `filter` and `select` are aliases of one another. Either may be used interchangably. An execption is raised if the filter removes all matching servers. --- lib/capistrano/configuration.rb | 15 +++++++++++++-- spec/lib/capistrano/dsl/env_spec.rb | 29 ++++++++++++++++++++++++++--- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/lib/capistrano/configuration.rb b/lib/capistrano/configuration.rb index d5254e67..37adb06c 100644 --- a/lib/capistrano/configuration.rb +++ b/lib/capistrano/configuration.rb @@ -37,8 +37,19 @@ module Capistrano servers.add_host(name, properties) end - def roles_for(names) - servers.fetch_roles(names) + def roles_for(names, options = {}) + servers.fetch_roles(names).tap do |list| + if filter = options.delete(:filter) || options.delete(:select) + if filter.respond_to?(:call) + list.select!(&filter) + else + list.select! { |s| s.properties.send(filter) } + end + if list.empty? + raise "Your filter #{filter} would remove all matching servers!" + end + end + end end def primary(role) diff --git a/spec/lib/capistrano/dsl/env_spec.rb b/spec/lib/capistrano/dsl/env_spec.rb index 60a86f4e..5822b686 100644 --- a/spec/lib/capistrano/dsl/env_spec.rb +++ b/spec/lib/capistrano/dsl/env_spec.rb @@ -39,12 +39,35 @@ module Capistrano describe '#roles' do - before do + let(:env) { Configuration.env } + before do + env.server('example.com', roles: :app, active: true) + env.server('example.org', roles: :app) end - it 'can filter hosts by properties on the host object' do - 1+1 + it 'raises if the filter would remove all matching hosts' do + pending + env.server('example.org', active: true) + lambda do + env.roles_for(:app, filter: lambda { |s| !s.properties.active }) + end.should raise_error + end + + it 'can filter hosts by properties on the host object using symbol as shorthand' do + env.roles_for(:app, filter: :active).length.should == 1 + end + + it 'can select hosts by properties on the host object using symbol as shorthand' do + env.roles_for(:app, select: :active).length.should == 1 + end + + it 'can filter hosts by properties on the host using a regular proc' do + env.roles_for(:app, filter: lambda { |h| h.properties.active } ).length.should == 1 + end + + it 'can select hosts by properties on the host using a regular proc' do + env.roles_for(:app, select: lambda { |h| h.properties.active } ).length.should == 1 end end