Merge pull request #583 from basecamp/wildcard-filters

Add wildcards to roles and hosts filters
This commit is contained in:
Donal McBreen
2023-11-14 08:19:02 +00:00
committed by GitHub
4 changed files with 44 additions and 4 deletions

View File

@@ -14,8 +14,8 @@ module Kamal::Cli
class_option :version, desc: "Run commands against a specific app version" class_option :version, desc: "Run commands against a specific app version"
class_option :primary, type: :boolean, aliases: "-p", desc: "Run commands only on primary host instead of all" class_option :primary, type: :boolean, aliases: "-p", desc: "Run commands only on primary host instead of all"
class_option :hosts, aliases: "-h", desc: "Run commands on these hosts instead of all (separate by comma)" class_option :hosts, aliases: "-h", desc: "Run commands on these hosts instead of all (separate by comma, supports wildcards with *)"
class_option :roles, aliases: "-r", desc: "Run commands on these roles instead of all (separate by comma)" class_option :roles, aliases: "-r", desc: "Run commands on these roles instead of all (separate by comma, supports wildcards with *)"
class_option :config_file, aliases: "-c", default: "config/deploy.yml", desc: "Path to config file" class_option :config_file, aliases: "-c", default: "config/deploy.yml", desc: "Path to config file"
class_option :destination, aliases: "-d", desc: "Specify destination to be used for config file (staging -> deploy.staging.yml)" class_option :destination, aliases: "-d", desc: "Specify destination to be used for config file (staging -> deploy.staging.yml)"

View File

@@ -28,11 +28,11 @@ class Kamal::Commander
end end
def specific_roles=(role_names) def specific_roles=(role_names)
@specific_roles = config.roles.select { |r| role_names.include?(r.name) } if role_names.present? @specific_roles = Kamal::Utils.filter_specific_items(role_names, config.roles) if role_names.present?
end end
def specific_hosts=(hosts) def specific_hosts=(hosts)
@specific_hosts = config.all_hosts & hosts if hosts.present? @specific_hosts = Kamal::Utils.filter_specific_items(hosts, config.all_hosts) if hosts.present?
end end
def primary_host def primary_host

View File

@@ -58,4 +58,20 @@ module Kamal::Utils
.gsub(/`/, '\\\\`') .gsub(/`/, '\\\\`')
.gsub(DOLLAR_SIGN_WITHOUT_SHELL_EXPANSION_REGEX, '\$') .gsub(DOLLAR_SIGN_WITHOUT_SHELL_EXPANSION_REGEX, '\$')
end end
# Apply a list of host or role filters, including wildcard matches
def filter_specific_items(filters, items)
matches = []
Array(filters).select do |filter|
matches += Array(items).select do |item|
# Only allow * for a wildcard
pattern = Regexp.escape(filter).gsub('\*', '.*')
# items are roles or hosts
(item.respond_to?(:name) ? item.name : item).match(/^#{pattern}$/)
end
end
matches
end
end end

View File

@@ -14,6 +14,18 @@ class CommanderTest < ActiveSupport::TestCase
@kamal.specific_hosts = [ "1.1.1.1", "1.1.1.2" ] @kamal.specific_hosts = [ "1.1.1.1", "1.1.1.2" ]
assert_equal [ "1.1.1.1", "1.1.1.2" ], @kamal.hosts assert_equal [ "1.1.1.1", "1.1.1.2" ], @kamal.hosts
@kamal.specific_hosts = [ "1.1.1.1*" ]
assert_equal [ "1.1.1.1" ], @kamal.hosts
@kamal.specific_hosts = [ "1.1.1.*", "*.1.2.*" ]
assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], @kamal.hosts
@kamal.specific_hosts = [ "*" ]
assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], @kamal.hosts
@kamal.specific_hosts = [ "*miss" ]
assert_equal [], @kamal.hosts
end end
test "filtering hosts by filtering roles" do test "filtering hosts by filtering roles" do
@@ -28,6 +40,18 @@ class CommanderTest < ActiveSupport::TestCase
@kamal.specific_roles = [ "workers" ] @kamal.specific_roles = [ "workers" ]
assert_equal [ "workers" ], @kamal.roles.map(&:name) assert_equal [ "workers" ], @kamal.roles.map(&:name)
@kamal.specific_roles = [ "w*" ]
assert_equal [ "web", "workers" ], @kamal.roles.map(&:name)
@kamal.specific_roles = [ "we*", "*orkers" ]
assert_equal [ "web", "workers" ], @kamal.roles.map(&:name)
@kamal.specific_roles = [ "*" ]
assert_equal [ "web", "workers" ], @kamal.roles.map(&:name)
@kamal.specific_roles = [ "*miss" ]
assert_equal [], @kamal.roles.map(&:name)
end end
test "filtering roles by filtering hosts" do test "filtering roles by filtering hosts" do