Skip to content

Fix grain PCRE/glob matching against dict-valued grains#69690

Open
ggiesen wants to merge 2 commits into
saltstack:3006.xfrom
ggiesen:fix-35567-grain-pcre-dict
Open

Fix grain PCRE/glob matching against dict-valued grains#69690
ggiesen wants to merge 2 commits into
saltstack:3006.xfrom
ggiesen:fix-35567-grain-pcre-dict

Conversation

@ggiesen

@ggiesen ggiesen commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

subdict_match in salt/utils/data.py only applied regex/fnmatch to list members and to literal dict keys, so a PCRE/glob pattern like 'roles:(roleA|roleB|roleC)' matched a list-valued grain but returned False for the equivalent dict-valued grain (issue #35567, reproduced against 3006.x). The fix adds a key scan in _dict_match using the existing _match() helper so dict keys are matched consistently with list members. Verified the new unit test fails on unpatched code (stashed the source fix -> FAIL) and passes with the fix; existing subdict_match tests still pass. Note: pytest hangs unless the pytest-salt-factories plugins are disabled via -p no:..., which is why the test command lists them.

What issues does this PR fix or reference?

Fixes #35567

Previous Behavior

See #35567.

New Behavior

Fix grain PCRE/glob matching against dict-valued grains. Validated by a unit test proven to fail on unpatched 3006.x and pass with the fix (confirmed by adversarial review).

Merge requirements satisfied?

  • Tests written/updated
  • Changelog

Commits signed with GPG?

No

subdict_match only applied regex/fnmatch patterns to list members and to
literal dict keys, so a pattern like 'roles:(roleA|roleB|roleC)' matched a
list-valued grain but not the equivalent dict-valued grain. Scan dict keys
with the same _match() helper used for list members so key matching is
consistent.

Fixes saltstack#35567
The PR's existing test already exercises subdict_match directly with
regex_match=True (the exact flag grain_pcre_match passes) and the plain
glob shape grain_match passes. This adds the inverse guard: the new
key-matching branch runs for every caller, so exact_match=True (the
shape pillar_exact_match and the minions cache check pass) must keep
glob/regex metacharacters literal, a non-matching glob must not match,
and a key-only match must not satisfy a deeper expression whose lower
levels do not match. All inverse assertions hold with and without the
fix applied.
@dwoz dwoz added the test:full Run the full test suite label Jul 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test:full Run the full test suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants