Skip to content

ADR-015: Disconnected Install: Complete Container Image Inventory and Resolution - #29

Open
Fortune-Ndlovu wants to merge 30 commits into
redhat-developer:mainfrom
Fortune-Ndlovu:adr/009-disconnected-install-container-image-inventory
Open

Fortune-Ndlovu wants to merge 30 commits into
redhat-developer:mainfrom
Fortune-Ndlovu:adr/009-disconnected-install-container-image-inventory

Conversation

@Fortune-Ndlovu

@Fortune-Ndlovu Fortune-Ndlovu commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

Every container image the operator can inject into a workload it creates must be listed in the CSV's spec.relatedImages and must be overridable through a matching RELATED_IMAGE_* environment variable.

This is the standard Red Hat operator pattern. It generalizes the existing backstage / postgresql substitution to every operator-chosen image.

Images covered

Image Required when Env var
backstage Always RELATED_IMAGE_backstage (existing)
postgresql Local DB enabled RELATED_IMAGE_postgresql (existing)
lightspeed-core Always in 2.1+ (Intelligent Assistant is enabledByDefault: true) RELATED_IMAGE_lightspeed_core
okp intelligent-assistant-okp add-on (opt-in) RELATED_IMAGE_okp
sonataflow psql job orchestrator (opt-in) reuses RELATED_IMAGE_postgresql
ubi10-minimal orchestrator (opt-in) RELATED_IMAGE_ubi_minimal
Tekton git image orchestrator (opt-in) RELATED_IMAGE_tekton_git
plugin-installer OPERATOR_DP_PROCESSING=true (dev preview; GA gate) RELATED_IMAGE_plugin_installer

Feature: https://redhat.atlassian.net/browse/RHDHPLAN-1887

Document Declare→Discover→Mirror→Resolve for Operator relatedImages
and Helm values.yaml as the static image contract for air-gap installs.

Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
Address review feedback by naming owning repos, paths, and planned CI
without implying those files live in rhdh-adr.

Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
@rhdh-qodo-merge

rhdh-qodo-merge Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Qodo Logo

@rhdh-qodo-merge

Copy link
Copy Markdown

PR Summary by Qodo

ADR: Define disconnected image inventories for Operator and Helm

📝 Documentation 🕐 20-40 Minutes

Grey Divider

AI Description

• Defines release-specific static container image inventories for disconnected Operator and Helm
 installs.
• Establishes Declare → Discover → Mirror → Resolve using Operator relatedImages and chart values.
• Identifies owning repositories, planned validation, and separate handling for dynamic plugin
 artifacts.
Diagram

graph TD
  A["Operator profiles"] --> B["Bundle relatedImages"] --> C["Mirror tooling"] --> D["Customer registry"] --> E["Running workloads"]
  F["Helm chart values"] --> G["Mirror guidance"] --> D
  F -->|"image overrides"| E
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Document manual image lists
  • ➕ Avoids immediate changes to Operator tooling and bundle generation.
  • ➖ Lists can drift as flavours and dependencies change.
  • ➖ Leaves no auditable inventory for automation.
2. Scan every bundle manifest
  • ➕ Could discover images omitted from the CSV as a temporary safeguard.
  • ➖ Depends on bundle layout and does not establish one authoritative inventory.

Recommendation: The ADR’s separate, version-bound sources of truth are preferable: relatedImages gives Operator tooling an auditable contract, while Helm can reuse chart values without a duplicate inventory. Keep manifest scanning, if needed, as a transitional check rather than the primary contract.

Files changed (1) +111 / -0

Documentation (1) +111 / -0
009-disconnected-install-container-image-inventory.mdRecord the disconnected static-image inventory decision +111/-0

Record the disconnected static-image inventory decision

• Adds an ADR defining how Operator and Helm installs declare, discover, mirror, and resolve static container images. It identifies implementation repositories and planned CI and documentation work, excludes dynamic plugin artifacts, and records alternatives and trade-offs. This PR documents intent; it does not implement the tooling or inventory changes.

decisions/009-disconnected-install-container-image-inventory.md

@Fortune-Ndlovu Fortune-Ndlovu changed the title ADR: Disconnected install container image inventory (Operator and Helm) ADR-009: Disconnected install container image inventory (Operator and Helm) Sep 30, 2026
Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
@Fortune-Ndlovu

Copy link
Copy Markdown
Member Author

/agentic_review

@rhdh-qodo-merge

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 77baff9

Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>

@gazarenkov gazarenkov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think mirror configuration should be a first class citizen for RHDH Operator.
The best approach I see for the time being is:

  • configure mirrors on operator level (using ConfigMap of known format)
  • if configured make operator apply it

It is already applied for dynamic plugins (see https://redhat.atlassian.net/browse/RHIDP-15003) and we can pretty easily extend it for others, such as: plugin related sidecars or pod resources and even for backstage and postgre images as well.

This way our disconnected env related instruction would be as easy as:

  • mirror images locally with oc-mirror oe skopeo etc. (we can consider some tool for forming list of images based on catalog, default-config manifests as well)
  • create mirror configMap before start operator (or restart it)

This way mirroring will be applied dynamically, on reconciliation with no additional actions.

WDYT?

@Fortune-Ndlovu

Copy link
Copy Markdown
Member Author

Hey @gazarenkov ,

You're absolutely right, mirror configuration should be a first-class citizen. I've revised the ADR to adopt your ConfigMap-based approach instead of extending spec.relatedImages.

Here's what changed: The operator already does runtime mirror resolution for plugin packages via the plugin-registry-mirror ConfigMap. Users create one ConfigMap with their mirror mappings, and the operator reads it during reconciliation and rewrites the package URLs. This ADR now extends that same mechanism to container images.

The flow works like this: Users create the ConfigMap once with all their registry mappings (plugins + containers). The operator loads it at startup, then during each Backstage reconciliation, it applies those mirror mappings to both plugin OCI packages (already working) and container image references in Deployments/StatefulSets (new). The pods end up with already-resolved registry paths, no IDMS/ITMS needed.

This keeps everything dynamic (ConfigMap changes apply on next reconciliation), works everywhere the operator runs (including Rosa HCP where IDMS/ITMS are blocked), and solves the optional feature problem users only mirror what they actually enable.

cc: @rm3l

@Fortune-Ndlovu Fortune-Ndlovu changed the title ADR-009: Disconnected install container image inventory (Operator and Helm) ADR-009: Extend ConfigMap mirror resolution to container images Oct 21, 2026
Rename from "container-image-inventory" to "mirror-resolution" to
reflect the actual decision: runtime mirror resolution via ConfigMap,
not static inventory listing in CSV spec.relatedImages.

Major changes based on team feedback:

Decision:
- Switch from spec.relatedImages to ConfigMap-based runtime resolution
- Extend existing plugin mirror mechanism to container images
- Manual-first documentation with scripts as optional automation

Technical approach:
- Apply mirror mappings during reconciliation (addToModel phase)
- Reuse existing plugin-registry-mirror ConfigMap
- One ConfigMap for plugins + containers

Documentation deliverables:
- Flip all air-gap docs from script-first to manual-first
- Add Orchestrator air-gap for vanilla Kubernetes
- Show transparent yq/skopeo commands, then link to scripts

Rationale:
- No CSV maintenance burden
- Only mirror what you enable (OKP is 10+ GB, optional)
- Works on platforms where IDMS/ITMS blocked (Rosa HCP)
- Enterprise-friendly transparent manual steps

Addresses feedback:
- Gennady: Use ConfigMap-based resolution (like plugins)
- Armel: Don't force mirroring of huge optional images

Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
@Fortune-Ndlovu
Fortune-Ndlovu force-pushed the adr/009-disconnected-install-container-image-inventory branch from 404d99f to 44d7821 Compare October 21, 2026 10:46
@Fortune-Ndlovu Fortune-Ndlovu changed the title ADR-009: Extend ConfigMap mirror resolution to container images ADR-009: Extend ConfigMap mirror resolution to container images (Airgap) Oct 21, 2026
@Fortune-Ndlovu Fortune-Ndlovu changed the title ADR-009: Extend ConfigMap mirror resolution to container images (Airgap) ADR-009: Disconnected Install: Extend ConfigMap mirror resolution to container images Oct 21, 2026
@Fortune-Ndlovu

Copy link
Copy Markdown
Member Author

/agentic_review

…gMap)

Revise based on review feedback from rm3l and gazarenkov:

- Adopt spec.relatedImages + RELATED_IMAGE_* env vars as Layer 1
  (standard RH operator pattern, enables oc-mirror + Conforma)
- Retain ConfigMap mirror resolution as Layer 2
  (runtime resolution for Rosa HCP, vanilla K8s)
- Both layers are complementary, not competing
- Add glossary for readers unfamiliar with OLM/air-gap terminology
- Document two resolution paths: standard OpenShift vs ConfigMap
- Reference OCPSTRAT-3755 for future optional image classification
- Reference RHDHSUPP-417 for oc-mirror customer expectations
- Include examples of other RH operators using spec.relatedImages
- Fix: remove local file path reference
- Fix: correct restart behavior claims (both mechanisms need restarts)
- Fix: reword IDMS/ITMS format claim (inspired by, not compatible with)
- Fix: remove Orchestrator vanilla K8s scope (OpenShift-only supported)

Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
@Fortune-Ndlovu Fortune-Ndlovu changed the title ADR-009: Disconnected Install: Extend ConfigMap mirror resolution to container images ADR-009: Disconnected Install: Dual-Layer Mirror Strategy (spec.relatedImages + ConfigMap) Oct 30, 2026
…ainers

Align with RHDH Install Cabal decisions (Nov 2, 2026):

Decision:
- Use spec.relatedImages + RELATED_IMAGE_* env vars only
- Drop ConfigMap mirror resolution for container images
  (reinvents IDMS, unnecessary given env var overrides work
  on all platforms including Rosa HCP and vanilla K8s)
- Only 2 images to add: lightspeed-core and okp
  (RAG init container removed in RHDH 2.1)
- OKP included by default despite 10+ GB size
  (monitor OCPSTRAT-3755 for future optional classification)

Platform workflows:
- OpenShift: oc-mirror + IDMS (standard)
- Rosa HCP: oc-mirror + Subscription/ClusterExtension env var override
- Vanilla K8s: extract from spec.relatedImages, mirror with own
  tooling, set RELATED_IMAGE_* env vars

Script deprecation:
- prepare-restricted-environment.sh deprecated in 2.2
- Removed from docs and repo in 2.3
- Optionally migrated to rhdh-core for internal E2E

Orchestrator:
- Leave current docs as-is
- Plugin ConfigMap resolution is dev preview in 2.1
- OSL operator images are OSL's responsibility

Downstream:
- sync-midstream.sh needs staleness checks for 2 new entries
- E2E tests need updates

Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
@Fortune-Ndlovu Fortune-Ndlovu changed the title ADR-009: Disconnected Install: Dual-Layer Mirror Strategy (spec.relatedImages + ConfigMap) ADR-009: Disconnected Install: Extend spec.relatedImages to all operator-managed container images Nov 2, 2026
Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
- Clarify that OLM does not rewrite RELATED_IMAGE_* env vars; images
  are pulled transparently via IDMS/ITMS on the nodes
- Show extracting the CSV from the bundle image before reading
  spec.relatedImages, drop `yq eval`, and keep related image names
  so users can map them to RELATED_IMAGE_* env vars
- Acknowledge that excluding a single relatedImage via
  ImageSetConfiguration is not possible today; depends on OCPSTRAT-3755
- Note that prepare-restricted-environment.sh already sources images
  from spec.relatedImages and RELATED_IMAGE_* env vars, so no script
  change is needed
- Reword the script deprecation claim to avoid overstating evidence

Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
Rewrites the disconnected-install ADR so it covers every image the
operator can inject, not just RHDH and PostgreSQL.

- Renumber from 009 to 011 (009 and 010 are taken upstream).
- List all operator-deployable images in spec.relatedImages and give
  each a RELATED_IMAGE_* env var: backstage, postgresql, lightspeed-core,
  okp, sonataflow psql (reuses postgresql), ubi10-minimal, tekton git,
  and plugin-installer.
- Define a generic {{ relatedImage "name" "fallback" }} template helper
  so flavours and plugin-deps resolve images at render time. Rejected
  post-render substitution because Tekton Task steps are not pod specs.
- Add plugin-installer now (inert until OPERATOR_DP_PROCESSING=true)
  and document that oc-mirror cannot skip optional images until
  OCPSTRAT-3755.
- Correct the OLM v1 override path: ClusterExtension.spec.config is a
  bundle-schema-validated inline object, not config.env; RHDH exposes
  no schema for RELATED_IMAGE_* today, so this is a tracked gap.
- Document downstream work (replaceUpstreamImages.sh, sync-midstream.sh),
  Conforma/trusted-registry risks, contributor docs, and the script
  lifecycle without a hard removal date.
- Address rm3l's review threads and remove the "as Armel noted" text.
@Fortune-Ndlovu Fortune-Ndlovu changed the title ADR-009: Disconnected Install: Extend spec.relatedImages to all operator-managed container images ADR-011: Disconnected Install: Complete Container Image Inventory and Resolution Nov 6, 2026
@Fortune-Ndlovu

Copy link
Copy Markdown
Member Author

/agentic_review

- Refresh Lightspeed to 0.7.3 and OKP to 1.3.0-1793303796 to match
  rhdh-operator main/release-2.1 and rhdh-chart; replace the stale
  drift claim with the current sync state.
- Replace the sha256 placeholder with the real Tekton git digest and
  pin ubi10-minimal to a tag instead of a bare reference.
- Clarify that plugin-installer is runtime-inert but not
  mirroring-inert, since oc-mirror copies every relatedImages entry.
- Scope the contract and CI guard to config/profile/rhdh/** and mark
  the bare config/profile/backstage.io profile as out of scope.
- Note that downstream scripts live in the internal dist-git repo, not
  the public redhat-developer/rhdh GitHub repo.
- Reject untagged related images in the CI guard.
- Use the repo's "# ADR:" title convention.
- Renumber from 011 to 015 to avoid collision with open PR redhat-developer#15
- Make relatedImage FuncMap registration and env-var fallback explicit
- Extend CI guard to Tekton defaults and Go-injected images
- Correct Tekton trigger, release-2.1 pin, Helm path, and OLM v1 guidance
@Fortune-Ndlovu Fortune-Ndlovu changed the title ADR-011: Disconnected Install: Complete Container Image Inventory and Resolution ADR-015: Disconnected Install: Complete Container Image Inventory and Resolution Nov 6, 2026

@gazarenkov gazarenkov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I see it as a (obvious :) ) workaround to improve experience with OLM before new operator processing come to GA and we can benefit dynamic mechanism consistent with RHDH as a platform for dynamic plugins.

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.

3 participants