Skip to content

OCPBUGS-85585: apply registry overrides to component images in CPO sub-resources#8509

Open
raelga wants to merge 1 commit into
openshift:mainfrom
raelga:raelga/fix-cpo-registry-overrides-init-containers
Open

OCPBUGS-85585: apply registry overrides to component images in CPO sub-resources#8509
raelga wants to merge 1 commit into
openshift:mainfrom
raelga:raelga/fix-cpo-registry-overrides-init-containers

Conversation

@raelga
Copy link
Copy Markdown

@raelga raelga commented May 13, 2026

Summary

CPO does not propagate --registry-overrides to init containers it injects in HCP sub-resources. When CPO creates deployments like capi-provider, it injects availability-prober init containers using the original quay.io image reference instead of the overridden ACR path.

Root cause

In hostedcontrolplane_controller.go:1106, the releaseImageProvider is created with imageprovider.New(releaseImage) which returns component images as-is from the release image stream. The registry overrides available via r.ReleaseProvider.GetRegistryOverrides() are not applied to these component images.

Fix

Add NewWithRegistryOverrides() to the imageprovider package that applies registry overrides to all component images when creating the provider. Use it in the HostedControlPlane reconciler instead of imageprovider.New().

This ensures when CPO calls GetImage("availability-prober") (or any other component), the returned image reference has the registry override applied.

Impact

Without this fix, any ValidatingAdmissionPolicy that restricts container images to approved registries will block CPO init containers, causing HCP cluster creation to hang indefinitely.

Test plan

  • 4 new unit tests covering: overrides match, no overrides, non-matching overrides, multiple overrides
  • Existing imageprovider tests pass
  • E2E with --registry-overrides and a VAP in Deny mode

Related

Summary by CodeRabbit

  • New Features

    • Registry overrides are now applied when reconciling hosted control plane components; image references are remapped using configured registry prefixes and only the first matching prefix is applied.
    • Remapping ignores non-matching prefixes and avoids accidental subdomain-only matches.
  • Tests

    • Added tests validating registry override behavior and edge cases.
    • Updated controller tests to reflect empty registry-overrides in mocked provider.

@openshift-merge-bot
Copy link
Copy Markdown
Contributor

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: LGTM mode

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 13, 2026

📝 Walkthrough

Walkthrough

The controller now constructs the image provider with registry override data by calling imageprovider.NewWithRegistryOverrides(releaseImage, r.ReleaseProvider.GetRegistryOverrides()). The new image provider clones the release’s component image map and rewrites image references by applying the first matching prefix-based registry override per image. Tests were added to verify remapping, non-matching behavior, subdomain non-matches, and precedence when multiple overrides exist; two controller tests were adjusted to mock an empty GetRegistryOverrides() map.

Sequence Diagram(s)

sequenceDiagram
    participant C as Controller
    participant RP as ReleaseProvider
    participant IP as ImageProvider
    participant K as Kubernetes API

    C->>RP: GetReleaseImage()
    C->>RP: GetRegistryOverrides()
    RP-->>C: releaseImage, registryOverrides
    C->>IP: NewWithRegistryOverrides(releaseImage, registryOverrides)
    IP-->>C: SimpleReleaseImageProvider (componentsImages remapped)
    C->>K: Reconcile components using provider (image references)
    K-->>C: Reconciliation status
Loading

Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Stable And Deterministic Test Names ❌ Error TestEventHandling uses dynamic test name with createdObject.GetName() which changes between runs, violating stable naming requirement. Replace dynamic GetName() with static format. Use t.Run(fmt.Sprintf("%T", createdObject), ...) or fully static string instead of including GetName().
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Test Structure And Quality ❓ Inconclusive Custom check specifies Ginkgo test review (Describe/It/BeforeEach), but PR uses standard Go testing with t.Run() subtests. Check applicability unclear. If check applies to all tests: tests show good practices (single responsibility, proper setup) but lack assertion messages with explanations for failures. If Ginkgo-only: check inapplicable to this PR.
✅ Passed checks (9 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Microshift Test Compatibility ✅ Passed PR adds only standard Go unit tests (testing.T + Gomega), not Ginkgo e2e tests. Custom check for Ginkgo e2e tests is not applicable.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No Ginkgo e2e tests added. Tests are regular Go unit tests (testing.T) in imageprovider_test.go and hostedcontrolplane_controller_test.go. SNO compatibility check not applicable.
Topology-Aware Scheduling Compatibility ✅ Passed No scheduling constraints introduced. Changes are purely for image registry overrides applied to component images, with no scheduling, affinity, or topology implications.
Ote Binary Stdout Contract ✅ Passed No process-level stdout writes found. All changes are in reconciliation methods, helper functions, or test functions. No klog, fmt.Print calls, or suite-level code that could corrupt OTE JSON.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No Ginkgo e2e tests are added in this PR. The PR adds standard Go unit tests using testing.T that only mock image provider data with no IPv4 assumptions or external connectivity requirements.
Title check ✅ Passed The title clearly and concisely summarizes the main change: applying registry overrides to component images in CPO sub-resources, which is the primary objective of the PR.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented May 13, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: raelga
Once this PR has been reviewed and has the lgtm label, please assign muraee for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci Bot requested review from devguyio and muraee May 13, 2026 22:04
@openshift-ci openshift-ci Bot added area/control-plane-operator Indicates the PR includes changes for the control plane operator - in an OCP release and removed do-not-merge/needs-area labels May 13, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@control-plane-operator/controllers/hostedcontrolplane/imageprovider/imageprovider_test.go`:
- Around line 200-277: Add a unit test covering the registry-prefix edge case
where an override key like "quay.io" should not match a hostname subdomain
"quay.io.example.com": add a new t.Run in imageprovider_test.go that constructs
a release image with a component image
"quay.io.example.com/namespace/image:tag", supplies an overrides map containing
"quay.io" -> "mirror.example.com", calls NewWithRegistryOverrides(releaseImage,
overrides) and asserts provider.GetImage("component") remains the original
"quay.io.example.com/namespace/image:tag". This ensures the matching logic used
by NewWithRegistryOverrides/GetImage treats registry keys as exact registry
hostnames (not substrings) and prevents incorrect remapping of subdomains.

In
`@control-plane-operator/controllers/hostedcontrolplane/imageprovider/imageprovider.go`:
- Line 70: The map returned by releaseImage.ComponentImages() (assigned to
images) is being modified directly, which can mutate the releaseImage internal
state; clone that map into a new map[string]string (copying all key/value pairs)
before performing any modifications in imageprovider.go (where images is
used/updated) so all changes occur on the cloned map and the original
releaseImage remains unmodified.
- Around line 74-76: The prefix check using strings.HasPrefix(image, source) can
match partial hostnames; update the condition in the loop that sets images[key]
so it only treats source as a match when it equals the registry component
exactly or is followed by a '/' (e.g. use a predicate like image == source or
strings.HasPrefix(image, source+"/") instead of plain HasPrefix). Modify the if
that currently reads strings.HasPrefix(image, source) to this stricter check
before performing images[key] = strings.Replace(image, source, target, 1) so
only full registry hosts are replaced.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: d098d99a-9102-4bfb-b08a-fda47dfc0431

📥 Commits

Reviewing files that changed from the base of the PR and between 674d92a and 196dae0.

📒 Files selected for processing (3)
  • control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller.go
  • control-plane-operator/controllers/hostedcontrolplane/imageprovider/imageprovider.go
  • control-plane-operator/controllers/hostedcontrolplane/imageprovider/imageprovider_test.go

@raelga
Copy link
Copy Markdown
Author

raelga commented May 13, 2026

/area control-plane-operator

@codecov
Copy link
Copy Markdown

codecov Bot commented May 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 40.01%. Comparing base (674d92a) to head (6f542db).
⚠️ Report is 6 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8509      +/-   ##
==========================================
+ Coverage   40.00%   40.01%   +0.01%     
==========================================
  Files         751      751              
  Lines       92838    92880      +42     
==========================================
+ Hits        37137    37164      +27     
- Misses      53014    53024      +10     
- Partials     2687     2692       +5     
Files with missing lines Coverage Δ
...ostedcontrolplane/hostedcontrolplane_controller.go 45.30% <100.00%> (ø)
.../hostedcontrolplane/imageprovider/imageprovider.go 85.36% <100.00%> (+10.36%) ⬆️

... and 1 file with indirect coverage changes

Flag Coverage Δ
cmd-support 34.09% <ø> (ø)
cpo-hostedcontrolplane 40.63% <100.00%> (+0.06%) ⬆️
cpo-other 40.14% <ø> (ø)
hypershift-operator 50.52% <ø> (-0.02%) ⬇️
other 31.54% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
control-plane-operator/controllers/hostedcontrolplane/imageprovider/imageprovider_test.go (1)

200-294: ⚡ Quick win

Add test case for registry port number handling.

The test suite comprehensively covers main scenarios, including the subdomain non-match case. All tests follow best practices with proper "When ... should ..." naming, gomega assertions, and parallel execution.

One scenario not currently tested: registry hostnames with explicit port numbers. The implementation handles this correctly as long as the override key includes the port (e.g., "registry.example.com:5000": "mirror.example.com" will successfully match registry.example.com:5000/namespace/image). Consider adding a test to document this expected behavior:

t.Run("When registry has port number, override matching includes the port", func(t *testing.T) {
	t.Parallel()
	g := NewWithT(t)

	releaseImage := newTestReleaseImage(map[string]string{
		"component": "registry.example.com:5000/namespace/image:tag",
	})
	overrides := map[string]string{
		"registry.example.com:5000": "mirror.example.com",
	}

	provider := NewWithRegistryOverrides(releaseImage, overrides)

	g.Expect(provider.GetImage("component")).To(Equal(
		"mirror.example.com/namespace/image:tag"))
})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@control-plane-operator/controllers/hostedcontrolplane/imageprovider/imageprovider_test.go`
around lines 200 - 294, Add a test case to TestNewWithRegistryOverrides that
verifies registry hostnames with ports are matched when the override key
includes the port: create a subtest using newTestReleaseImage with an image like
"registry.example.com:5000/namespace/image:tag", supply overrides map with key
"registry.example.com:5000" and value "mirror.example.com", construct provider
via NewWithRegistryOverrides and assert provider.GetImage("component") returns
"mirror.example.com/namespace/image:tag".
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@control-plane-operator/controllers/hostedcontrolplane/imageprovider/imageprovider_test.go`:
- Around line 200-294: Add a test case to TestNewWithRegistryOverrides that
verifies registry hostnames with ports are matched when the override key
includes the port: create a subtest using newTestReleaseImage with an image like
"registry.example.com:5000/namespace/image:tag", supply overrides map with key
"registry.example.com:5000" and value "mirror.example.com", construct provider
via NewWithRegistryOverrides and assert provider.GetImage("component") returns
"mirror.example.com/namespace/image:tag".

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 451a24c9-3b71-43db-a6dc-02b6393dbd55

📥 Commits

Reviewing files that changed from the base of the PR and between 196dae0 and 8fd79a4.

📒 Files selected for processing (2)
  • control-plane-operator/controllers/hostedcontrolplane/imageprovider/imageprovider.go
  • control-plane-operator/controllers/hostedcontrolplane/imageprovider/imageprovider_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • control-plane-operator/controllers/hostedcontrolplane/imageprovider/imageprovider.go

@raelga raelga force-pushed the raelga/fix-cpo-registry-overrides-init-containers branch from b0ada44 to 009bb28 Compare May 14, 2026 11:40
When CPO creates sub-resources (e.g. capi-provider deployments), it
injects init containers like availability-prober using image references
from the release image. These references were not being remapped by
--registry-overrides, causing the init containers to reference the
original registry (e.g. quay.io) instead of the override target.

Add NewWithRegistryOverrides to the imageprovider package that clones
the component images map and applies registry overrides using safe
prefix matching (source+"/") to prevent subdomain false matches. Use
it when creating the releaseImageProvider in the HostedControlPlane
reconciler.

Bug: https://redhat.atlassian.net/browse/OCPBUGS-85585
@raelga raelga force-pushed the raelga/fix-cpo-registry-overrides-init-containers branch from 009bb28 to 6f542db Compare May 14, 2026 11:41
@jparrill
Copy link
Copy Markdown
Contributor

/retitle OCPBUGS-85585: apply registry overrides to component images in CPO sub-resources

@openshift-ci openshift-ci Bot changed the title fix: apply registry overrides to component images in CPO sub-resources (OCPBUGS-85585) OCPBUGS-85585: apply registry overrides to component images in CPO sub-resources May 14, 2026
@openshift-ci-robot openshift-ci-robot added jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. labels May 14, 2026
@openshift-ci-robot
Copy link
Copy Markdown

@raelga: This pull request references Jira Issue OCPBUGS-85585, which is invalid:

  • expected the bug to target the "5.0.0" version, but no target version was set

Comment /jira refresh to re-evaluate validity if changes to the Jira bug are made, or edit the title of this pull request to link to a different bug.

The bug has been updated to refer to the pull request using the external bug tracker.

Details

In response to this:

Summary

CPO does not propagate --registry-overrides to init containers it injects in HCP sub-resources. When CPO creates deployments like capi-provider, it injects availability-prober init containers using the original quay.io image reference instead of the overridden ACR path.

Root cause

In hostedcontrolplane_controller.go:1106, the releaseImageProvider is created with imageprovider.New(releaseImage) which returns component images as-is from the release image stream. The registry overrides available via r.ReleaseProvider.GetRegistryOverrides() are not applied to these component images.

Fix

Add NewWithRegistryOverrides() to the imageprovider package that applies registry overrides to all component images when creating the provider. Use it in the HostedControlPlane reconciler instead of imageprovider.New().

This ensures when CPO calls GetImage("availability-prober") (or any other component), the returned image reference has the registry override applied.

Impact

Without this fix, any ValidatingAdmissionPolicy that restricts container images to approved registries will block CPO init containers, causing HCP cluster creation to hang indefinitely.

Test plan

  • 4 new unit tests covering: overrides match, no overrides, non-matching overrides, multiple overrides
  • Existing imageprovider tests pass
  • E2E with --registry-overrides and a VAP in Deny mode

Related

Summary by CodeRabbit

  • New Features

  • Registry overrides are now applied when reconciling hosted control plane components; image references are remapped using configured registry prefixes and only the first matching prefix is applied.

  • Remapping ignores non-matching prefixes and avoids accidental subdomain-only matches.

  • Tests

  • Added tests validating registry override behavior and edge cases.

  • Updated controller tests to reflect empty registry-overrides in mocked provider.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@jparrill
Copy link
Copy Markdown
Contributor

/jira refresh

@openshift-ci-robot openshift-ci-robot added jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. and removed jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. labels May 14, 2026
@openshift-ci-robot
Copy link
Copy Markdown

@jparrill: This pull request references Jira Issue OCPBUGS-85585, which is valid. The bug has been moved to the POST state.

3 validation(s) were run on this bug
  • bug is open, matching expected state (open)
  • bug target version (5.0.0) matches configured target version for branch (5.0.0)
  • bug is in the state New, which is one of the valid states (NEW, ASSIGNED, POST)
Details

In response to this:

/jira refresh

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

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

Labels

area/control-plane-operator Indicates the PR includes changes for the control plane operator - in an OCP release jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants