Skip to content

Commit

Permalink
Add support for wildcard matches with '*' on roles and hosts.
Browse files Browse the repository at this point in the history
eg:
  --roles=*_chicago,*_tokyo
  --hosts=app-*

Useful for targeted deploys.
  • Loading branch information
mdkent committed Nov 14, 2023
1 parent 8a85840 commit 7137850
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 2 deletions.
4 changes: 2 additions & 2 deletions lib/kamal/commander.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ def specific_primary!
end

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

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

def primary_host
Expand Down
16 changes: 16 additions & 0 deletions lib/kamal/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,20 @@ def escape_shell_value(value)
.gsub(/`/, '\\\\`')
.gsub(DOLLAR_SIGN_WITHOUT_SHELL_EXPANSION_REGEX, '\$')
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
24 changes: 24 additions & 0 deletions test/commander_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ class CommanderTest < ActiveSupport::TestCase

@kamal.specific_hosts = [ "1.1.1.1", "1.1.1.2" ]
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

test "filtering hosts by filtering roles" do
Expand All @@ -28,6 +40,18 @@ class CommanderTest < ActiveSupport::TestCase

@kamal.specific_roles = [ "workers" ]
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

test "filtering roles by filtering hosts" do
Expand Down

0 comments on commit 7137850

Please sign in to comment.