diff --git a/lib/bolt/inventory/inventory.rb b/lib/bolt/inventory/inventory.rb index 54d67b387..8500cc4ca 100644 --- a/lib/bolt/inventory/inventory.rb +++ b/lib/bolt/inventory/inventory.rb @@ -14,6 +14,10 @@ class Inventory EXTENDED_TARGET_REGEX = /[[:space:],]+(?=[^\]}]*(?:[\[{]|$))/.freeze TARGET_REGEX = /[[:space:],]+/.freeze + # Pattern which looks for indicators that glob-based target name matching + # should be used. + GLOB_MATCH_REGEX = /[*?\[\]{}]/.freeze + class WildcardError < Bolt::Error def initialize(target) super("Found 0 targets matching wildcard pattern #{target}", 'bolt.inventory/wildcard-error') @@ -125,12 +129,18 @@ def match_wildcard?(wildcard, target_name, ext_glob: false) # If target is a group name, expand it to the members of that group. # Else match against groups and targets in inventory by name or alias. - # If a wildcard string, error if no matches are found. + # Attempt exact matches for groups, targets, and aliases first for speed. + # If no exact match and the string contains wildcard characters, then try + # for a wildcard match and error if no matches are found. # Else fall back to [target] if no matches are found. def resolve_name(target, ext_glob: false) if (group = group_lookup[target]) group.all_targets.to_a - else + elsif @targets.key?(target) + [target] + elsif (real_target = groups.target_aliases[target]) + [real_target] + elsif GLOB_MATCH_REGEX.match?(target) targets = [] # Find groups that match the glob @@ -147,12 +157,11 @@ def resolve_name(target, ext_glob: false) .select { |tgt_alias, _| match_wildcard?(target, tgt_alias, ext_glob: ext_glob) } .values - if targets.empty? - raise(WildcardError, target) if target.include?('*') - [target] - else - targets.uniq - end + raise(WildcardError, target) if targets.empty? + + targets.uniq + else + [target] end end private :resolve_name