Skip to content

fix: match full RHEL and Rocky product names in OS normalization - #2788

Open
rugggger wants to merge 1 commit into
mainfrom
09-02-fix_match_full_rhel_and_rocky_product_names_in_os_normalization
Open

fix: match full RHEL and Rocky product names in OS normalization#2788
rugggger wants to merge 1 commit into
mainfrom
09-02-fix_match_full_rhel_and_rocky_product_names_in_os_normalization

Conversation

@rugggger

@rugggger rugggger commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

NormalizeOSImageName matched the literal "RHEL", but Kubernetes reports
osImage as "Red Hat Enterprise Linux 9.7 (Plow)", so every RHEL node
normalized to "unknown-os" and its builder containers were named after
it. Rocky had the same gap: "rocky\s*(\d+)" never matched "Rocky Linux
8.10". Widen both patterns and add a table test covering the spellings
Kubernetes actually emits.

Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com

NormalizeOSImageName matched the literal "RHEL", but Kubernetes reports
osImage as "Red Hat Enterprise Linux 9.7 (Plow)", so every RHEL node
normalized to "unknown-os" and its builder containers were named after
it. Rocky had the same gap: "rocky\s*(\d+)" never matched "Rocky Linux
8.10". Widen both patterns and add a table test covering the spellings
Kubernetes actually emits.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

rugggger commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

How to use the Graphite Merge Queue

Add the label main-merge-queue to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has required the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@claude

claude Bot commented Sep 2, 2026

Copy link
Copy Markdown

Claude finished @rugggger's task in 2m 44s —— View job


Claude Code Review

  • Read PR diff (git diff origin/main...HEAD)
  • Review NormalizeOSImageName regex changes
  • Trace the single consumer (getBuilderContainerName) for blast radius
  • Post inline comments + summary
  • Run go test ./internal/drivers/ — blocked, see note below

Summary

The fix is correct and well-scoped. NormalizeOSImageName has exactly one consumer — getBuilderContainerName at internal/controllers/operations/enable_local_drivers_distribution.go:868 — so the change can only affect builder-container naming, nothing about how drivers are actually built or distributed. The new patterns match the spellings Kubernetes emits for RHEL 8/9 and Rocky, and the table test is a real improvement over having none.

Two things worth a look, both raised inline:

1. RHEL 7 still falls through (inline) — RHEL 7's PRETTY_NAME is Red Hat Enterprise Linux Server 7.9 (Maipo). The Server token between Linux and the version means \s*(\d+) doesn't match, so RHEL 7 nodes keep normalizing to unknown-os — the exact bug this PR fixes for 8/9. An explicit (?:\s+server)? handles it without the risk a permissive [^\d]* would carry (that would map RHEL CoreOS's Red Hat Enterprise Linux CoreOS 414.92... to rhel414).

2. Test table nits (inline) — name duplicates input verbatim in all nine cases; missing coverage for the Rocky codename spelling, a two-digit major (rhel10, the only case exercising %02s non-trivially), and the no-space RHEL9 form.

Upgrade note (not a defect, worth release-noting)

On clusters with RHEL/Rocky nodes, the builder container name changes from <policy>-<suffix>-<hash>-unknown-os-<kernel> to ...-rhel09-<kernel>. CleanupOldBuilderContainers (enable_local_drivers_distribution.go:735-767) deletes anything not in the current desired set, so this is self-healing rather than a leak — but it does mean a one-time driver rebuild on operator upgrade for those clusters, during which WaitForBuilders reports incomplete progress. Worth confirming that window is acceptable (drivers already distributed to nodes should be unaffected, but the policy will not report complete until the new builders finish).

Secondary effect of the same rename: unknown-os (10 chars) → rhel09 (6 chars) shifts the 63-char truncation point at lines 885-887, so long kernel strings truncate differently too. No correctness issue, just part of the same one-time rename.

Minor observations

  • fmt.Sprintf("rhel%02s", m[1]) (line 46) — zero-padding a string with %02s works in Go and go vet accepts it, but it's an unusual idiom. Pre-existing, not introduced here.
  • GetBuilderImageForNode (line 57) still matches on the raw string with strings.Contains(osImage, "Ubuntu 24.04") rather than going through the normalizer. It's correct today since Ubuntu's spelling is stable, but it's the same category of brittleness. Out of scope for this PR.
  • AlmaLinux, CentOS Stream, SLES and Amazon Linux all still land on unknown-os. Fine if unsupported; a follow-up if not.

No security or performance concerns — both regexes are compiled once at package init, and neither introduces backtracking risk (Go's RE2 is linear-time regardless).

Note on verification

I could not execute go test ./internal/drivers/ or a standalone regex probe in this environment — both go invocations were denied by the tool permission policy. The regex analysis above is from reading the patterns, not from running them. Adding Bash(go test:*) to --allowedTools would let me verify the table empirically next time.
Branch

ubuntuRe = regexp.MustCompile(`(?i)ubuntu\s+(\d+)\.(\d+)`)
rhelRe = regexp.MustCompile(`(?i)rhel\s*(\d+)`)
rockyRe = regexp.MustCompile(`(?i)rocky\s*(\d+)`)
rhelRe = regexp.MustCompile(`(?i)(?:rhel|red\s+hat\s+enterprise\s+linux)\s*(\d+)`)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same class of gap remains for RHEL 7, which reports PRETTY_NAME="Red Hat Enterprise Linux Server 7.9 (Maipo)" — the word Server sits between Linux and the version, so \s*(\d+) fails and the node still normalizes to unknown-os. ("Server" was dropped in RHEL 8+, which is why 8/9 work.)

Worth handling explicitly rather than with a permissive [^\d]*: RHEL CoreOS reports Red Hat Enterprise Linux CoreOS 414.92.202310170514-0, and a greedy skip would turn that into rhel414. Leaving CoreOS at unknown-os is the safer behavior.

Suggested change
rhelRe = regexp.MustCompile(`(?i)(?:rhel|red\s+hat\s+enterprise\s+linux)\s*(\d+)`)
rhelRe = regexp.MustCompile(`(?i)(?:rhel|red\s+hat\s+enterprise\s+linux(?:\s+server)?)\s*(\d+)`)

If RHEL 7 is outside the supported matrix, feel free to skip — but then it'd be good to say so in the doc comment.

Comment on lines +41 to +52
tests := []struct {
name string
input string
want string
}{
{"Ubuntu 22.04.5 LTS", "Ubuntu 22.04.5 LTS", "ubuntu-22-04"},
{"Ubuntu 24.04.3 LTS", "Ubuntu 24.04.3 LTS", "ubuntu-24"},
{"Ubuntu 24.04.4 LTS", "Ubuntu 24.04.4 LTS", "ubuntu-24"},
{"RHEL 9.4", "RHEL 9.4", "rhel09"},
{"Red Hat Enterprise Linux 9.7 (Plow)", "Red Hat Enterprise Linux 9.7 (Plow)", "rhel09"},
{"Red Hat Enterprise Linux 8.10", "Red Hat Enterprise Linux 8.10", "rhel08"},
{"Rocky Linux 8.10", "Rocky Linux 8.10", "rocky08"},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

name is character-for-character identical to input in all nine cases, so it's pure duplication — dropping the field and using t.Run(tt.input, ...) gives the same subtest names (empty string becomes #00-style, or keep a name only where it adds something).

Coverage gaps worth adding while the table is here:

  • "Rocky Linux 9.6 (Blue Onyx)" — the codename-suffixed spelling for Rocky, mirroring the (Plow) case you added for RHEL.
  • "RHEL 10.0" / "Red Hat Enterprise Linux 10.0" — the only case that exercises %02s with a two-digit major (rhel10, not rhel010).
  • "RHEL9" with no space — \s* allows it, so it's worth pinning as intended rather than accidental.

@graphite-app

graphite-app Bot commented Sep 2, 2026

Copy link
Copy Markdown

Graphite Automations

"Add anton/matt/sergey/kristina as reviwers on operator PRs" took an action on this PR • (09/02/26)

3 reviewers were added to this PR based on Anton Bykov's automation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant