Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
381a2ee
fix(airgap): repoint default-catalog subscriptions to mirrored catalogs
butler54 Oct 29, 2026
602abe0
fix(airgap): cover reg.kyverno.io in the manual ITMS
butler54 Nov 2, 2026
a93cbec
fix(airgap): pin vault 2.1.2-ubi in the imageset
butler54 Nov 2, 2026
6fbf1e5
docs(airgap): org-prefixed mirror targets need the org in MIRROR_REGI…
butler54 Nov 2, 2026
20febe5
fix(airgap): repoint intel operator subscriptions via the airgap overlay
butler54 Nov 2, 2026
59ed821
fix(airgap): trustee AS collateral backend follows the airgap flag
butler54 Nov 2, 2026
4c4a229
fix(airgap): activate the CoCo workload image overrides via the overlay
butler54 Nov 2, 2026
bec203a
docs(airgap): helmRepoUrl is required for multiSourceConfig in airgap
butler54 Nov 2, 2026
5cb65e3
fix(airgap): set the MCE subscription source via the ACM chart override
butler54 Nov 2, 2026
f4aacd5
fix(airgap): enable application health check for sync-wave gating
butler54 Nov 2, 2026
33650b8
fix(waves): acm app moves to wave 15 — breaks the CRD discovery deadlock
butler54 Nov 2, 2026
c82fc7f
style: trim inline comments to brief pointers
butler54 Nov 2, 2026
48831de
fix(gating): set the ArgoCD application health check on every install…
butler54 Nov 3, 2026
4f2305e
fix(airgap): correct, derive and make re-runnable the subscription re…
butler54 Nov 3, 2026
70e96c6
feat(workloads): charts rewrite their images against the mirror
butler54 Nov 3, 2026
6e3d851
fix(airgap): pin the vault chart to 0.1.11
butler54 Nov 3, 2026
be2d033
docs(airgap): MIRROR_REGISTRY includes the org path — everywhere
butler54 Nov 3, 2026
67e7516
test(airgap): render gate for both connectivity modes
butler54 Nov 3, 2026
344076b
fix(rbac): bootstrap the ArgoCD controller cluster-admin at wave -1
butler54 Nov 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,10 @@ airgap-mirror: ## Mirror content to disconnected registry (requires MIRROR_REGIS
airgap-post-install: ## Post-install bootstrap (after airgap-mirror + labctl apply-mirror-resources)
@scripts/airgap-post-install.sh

.PHONY: airgap-repoint-subs
airgap-repoint-subs: ## Re-run the default-catalog subscription repoint (safety net; safe any time, e.g. after MCH deploys)
@scripts/airgap-post-install.sh --repoint-subs




Expand Down
10 changes: 6 additions & 4 deletions airgap/imageset-config-4.22.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
# ImageSetConfiguration for CoCo Validated Pattern airgap deployment
# Target: MIRROR_REGISTRY_HOST:8443 (mirror-registry — sole airgap target, Phase 25.2)
# Target: a single mirror registry (org-prefixed target for Quay, e.g.
# quay.example:443/mirror — MIRROR_REGISTRY includes the org path)
# OCP: 4.22.17
# Topology: baremetal (full operator set from values-baremetal.yaml)
#
Expand All @@ -10,7 +11,7 @@
# Usage:
# oc-mirror -c airgap/imageset-config-4.22.yaml \
# --workspace file://$HOME/oc-mirror-workspace \
# docker://MIRROR_REGISTRY_HOST:8443 --v2
# docker://<mirror-root-including-org> --v2

apiVersion: mirror.openshift.io/v2alpha1
kind: ImageSetConfiguration
Expand Down Expand Up @@ -113,7 +114,8 @@ mirror:
# NFD operand — worker/master/gc DaemonSets use this tag, NOT the operator digest.
- name: registry.redhat.io/openshift4/ose-node-feature-discovery-rhel9:v4.22
# Vault — Red Hat certified UBI image from registry.connect.redhat.com
- name: registry.connect.redhat.com/hashicorp/vault:1.21.4-ubi
# (hashicorp-vault chart 0.1.11 deploys vault:2.1.2-ubi by default)
- name: registry.connect.redhat.com/hashicorp/vault:2.1.2-ubi

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Bug: the imageset pins vault 2.1.2-ubi and drops 1.21.4-ubi, but the chart is a range (chartVersion: "~0.1.10"). If 0.1.10 is the chart version resolved (or mirrored), it deploys vault:1.21.4-ubi, which is no longer mirrored, and vault gets ImagePullBackOff. A future 0.1.12 that bumps the image breaks the same way. Pin chartVersion: 0.1.11 to match, or keep both tags in the imageset.

# Kyverno (Helm chart, not OLM — images from ghcr.io)
- name: ghcr.io/kyverno/kyverno:v1.17.2
- name: ghcr.io/kyverno/kyvernopre:v1.17.2
Expand All @@ -125,7 +127,7 @@ mirror:
# --- VP Helm OCI charts ---
- name: quay.io/validatedpatterns/clustergroup:0.9.58
- name: quay.io/validatedpatterns/acm:0.1.27
# values pin ~0.1.10 resolves the newest 0.1.x — mirror that, not the floor
# values pin 0.1.11 exactly (chart 0.1.11 deploys vault:2.1.2-ubi)
- name: quay.io/validatedpatterns/hashicorp-vault:0.1.11
- name: quay.io/validatedpatterns/openshift-external-secrets:0.0.4
- name: quay.io/validatedpatterns/trustee:0.10.2
Expand Down
7 changes: 7 additions & 0 deletions airgap/itms-manual-mirrors.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Org-prefixed mirror targets: MIRROR_REGISTRY must include the org path

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Contradictory guidance on the mirror format. This new comment says MIRROR_REGISTRY must include the org path (for example quay.example:443/mirror). But airgap-post-install.sh documents and validates it as "registry host:port (e.g. MIRROR_REGISTRY_HOST:8443)", and the placeholder in this file and in the overlay is MIRROR_REGISTRY_HOST:8443 with no org. Users following the script's own help text get the 404s this comment warns about. Align the script help text, the error message, and the placeholders.

# (e.g. quay.example:443/mirror) — the same value scripts/airgap-post-install.sh
# requires — or every tag-based operand pull 404s.
apiVersion: config.openshift.io/v1
kind: ImageTagMirrorSet
metadata:
Expand All @@ -14,3 +17,7 @@ spec:
- MIRROR_REGISTRY_HOST:8443/hashicorp
# NOTE: quay.io/community-operator-pipeline-prod removed — oc-mirror 4.22
# generates ITMS for it in itms-oc-mirror.yaml automatically.
# Kyverno chart images: the chart pulls from reg.kyverno.io, not ghcr.io.
- source: reg.kyverno.io
mirrors:
- MIRROR_REGISTRY_HOST:8443
31 changes: 31 additions & 0 deletions charts/coco-supported/hello-openshift/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,34 @@ Determine runtime class name from global config.
{{- define "hello-openshift.runtimeClassName" -}}
{{- .Values.global.coco.runtimeClassName -}}
{{- end }}

{{/*
Render a workload container image for the CoCo test workloads.

CoCo guest VMs pull their images directly — there is no IDMS/ITMS inside the
CVM, so a registry.redhat.io/ubi9/... reference cannot be redirected at pull
time. In airgap mode (global.airgap: true) the image is rewritten against
global.mirrorRegistry using the oc-mirror source-path convention: the registry
hostname is stripped and the mirror root prefixed, e.g.

registry.redhat.io/ubi9/httpd-24@sha256:...
→ quay.example:443/mirror/ubi9/httpd-24@sha256:...

The mirror root must include the org path for Quay targets (it is the same
value oc-mirror was pointed at). Rendering fails fast when airgap mode is on
and the mirror is unset or still a placeholder — a missing value here would
otherwise surface as ImagePullBackOff inside the CVM minutes later.
*/}}
{{- define "hello-openshift.image" -}}
{{- $image := .image -}}
{{- if .root.Values.global.airgap -}}
{{- $mirror := .root.Values.global.mirrorRegistry | default "" -}}
{{- if or (not $mirror) (contains "MIRROR_REGISTRY_HOST" $mirror) -}}
{{- fail "global.mirrorRegistry must be set to the mirror root (e.g. quay.example:443/mirror) when global.airgap is true" -}}
{{- end -}}
{{- $path := regexReplaceAll "^[a-zA-Z0-9.-]+(:[0-9]+)?/(.*)$" $image "${2}" -}}
{{- printf "%s/%s" $mirror $path -}}
{{- else -}}
{{- $image -}}
{{- end -}}
{{- end -}}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ spec:
runtimeClassName: {{ include "hello-openshift.runtimeClassName" . }}
containers:
- name: hello-openshift
image: {{ .Values.image }}
image: {{ include "hello-openshift.image" (dict "root" $ "image" .Values.image) }}
ports:
- containerPort: 8080
volumeMounts:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ spec:
runtimeClassName: {{ include "hello-openshift.runtimeClassName" . }}
containers:
- name: hello-openshift
image: {{ .Values.image }}
image: {{ include "hello-openshift.image" (dict "root" $ "image" .Values.image) }}
ports:
- containerPort: 8080
volumeMounts:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ spec:
spec:
containers:
- name: hello-openshift
image: {{ .Values.image }}
image: {{ include "hello-openshift.image" (dict "root" $ "image" .Values.image) }}
ports:
- containerPort: 8080
volumeMounts:
Expand Down
6 changes: 6 additions & 0 deletions charts/coco-supported/hello-openshift/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,9 @@ runtimeClassName: ""
# Global values used by this chart (overridden by values-global.yaml)
global:
clusterPlatform: "" # Cluster platform: "Azure" or "AWS" - determines runtime class
# Airgap mode comes from values-global.yaml (global.airgap); the default here
# is connected so standalone chart rendering uses upstream registries.
airgap: false
# Mirror root (org-prefixed for Quay targets) — required when airgap is true.
# The workload charts rewrite their images against it; see _helpers.tpl.
mirrorRegistry: ""
30 changes: 30 additions & 0 deletions charts/coco-supported/kbs-access-curl/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{{/*
Render a workload container image for the CoCo test workloads.

CoCo guest VMs pull their images directly — there is no IDMS/ITMS inside the
CVM, so a registry.redhat.io/ubi9/... reference cannot be redirected at pull
time. In airgap mode (global.airgap: true) the image is rewritten against
global.mirrorRegistry using the oc-mirror source-path convention: the registry
hostname is stripped and the mirror root prefixed, e.g.

registry.redhat.io/ubi9/httpd-24@sha256:...
→ quay.example:443/mirror/ubi9/httpd-24@sha256:...

The mirror root must include the org path for Quay targets (it is the same
value oc-mirror was pointed at). Rendering fails fast when airgap mode is on
and the mirror is unset or still a placeholder — a missing value here would
otherwise surface as ImagePullBackOff inside the CVM minutes later.
*/}}
{{- define "kbs-access-curl.image" -}}
{{- $image := .image -}}
{{- if .root.Values.global.airgap -}}
{{- $mirror := .root.Values.global.mirrorRegistry | default "" -}}
{{- if or (not $mirror) (contains "MIRROR_REGISTRY_HOST" $mirror) -}}
{{- fail "global.mirrorRegistry must be set to the mirror root (e.g. quay.example:443/mirror) when global.airgap is true" -}}
{{- end -}}
{{- $path := regexReplaceAll "^[a-zA-Z0-9.-]+(:[0-9]+)?/(.*)$" $image "${2}" -}}
{{- printf "%s/%s" $mirror $path -}}
{{- else -}}
{{- $image -}}
{{- end -}}
{{- end -}}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ spec:
runAsUser: 0
containers:
- name: httpd
image: {{ .Values.image }}
image: {{ include "kbs-access-curl.image" (dict "root" $ "image" .Values.image) }}
ports:
- containerPort: 8080
securityContext:
Expand All @@ -50,7 +50,7 @@ spec:
readOnly: true
initContainers:
- name: curl
image: {{ .Values.initImage }}
image: {{ include "kbs-access-curl.image" (dict "root" $ "image" .Values.initImage) }}
command: ['sh', '-c', 'curl -s http://127.0.0.1:8006/cdh/resource/default/kbsres1/key3 > /var/www/html/secret.txt']
securityContext:
privileged: true
Expand Down
6 changes: 6 additions & 0 deletions charts/coco-supported/kbs-access-curl/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ defaultMemory: ""
runtimeClassName: ""
global:
clusterPlatform: "" # Cluster platform: "Azure", "AWS", etc. - determines runtime class
# Airgap mode comes from values-global.yaml (global.airgap); the default here
# is connected so standalone chart rendering uses upstream registries.
airgap: false
# Mirror root (org-prefixed for Quay targets) — required when airgap is true.
# The workload charts rewrite their images against it; see _helpers.tpl.
mirrorRegistry: ""
30 changes: 30 additions & 0 deletions charts/coco-supported/kbs-access-sealed/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{{/*
Render a workload container image for the CoCo test workloads.

CoCo guest VMs pull their images directly — there is no IDMS/ITMS inside the
CVM, so a registry.redhat.io/ubi9/... reference cannot be redirected at pull
time. In airgap mode (global.airgap: true) the image is rewritten against
global.mirrorRegistry using the oc-mirror source-path convention: the registry
hostname is stripped and the mirror root prefixed, e.g.

registry.redhat.io/ubi9/httpd-24@sha256:...
→ quay.example:443/mirror/ubi9/httpd-24@sha256:...

The mirror root must include the org path for Quay targets (it is the same
value oc-mirror was pointed at). Rendering fails fast when airgap mode is on
and the mirror is unset or still a placeholder — a missing value here would
otherwise surface as ImagePullBackOff inside the CVM minutes later.
*/}}
{{- define "kbs-access-sealed.image" -}}
{{- $image := .image -}}
{{- if .root.Values.global.airgap -}}
{{- $mirror := .root.Values.global.mirrorRegistry | default "" -}}
{{- if or (not $mirror) (contains "MIRROR_REGISTRY_HOST" $mirror) -}}
{{- fail "global.mirrorRegistry must be set to the mirror root (e.g. quay.example:443/mirror) when global.airgap is true" -}}
{{- end -}}
{{- $path := regexReplaceAll "^[a-zA-Z0-9.-]+(:[0-9]+)?/(.*)$" $image "${2}" -}}
{{- printf "%s/%s" $mirror $path -}}
{{- else -}}
{{- $image -}}
{{- end -}}
{{- end -}}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ spec:
runtimeClassName: {{ .Values.global.coco.runtimeClassName }}
containers:
- name: httpd
image: {{ .Values.image }}
image: {{ include "kbs-access-sealed.image" (dict "root" $ "image" .Values.image) }}
ports:
- containerPort: 8080
protocol: TCP
Expand Down
9 changes: 9 additions & 0 deletions charts/coco-supported/kbs-access-sealed/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,12 @@
# Override via values-global.yaml or values-baremetal.yaml

image: registry.redhat.io/ubi9/httpd-24@sha256:68a91ff691092f455fea682330c499588747231c16516cd4f35aff821e6847f2

global:
clusterPlatform: "" # Cluster platform: "Azure", "AWS", etc. - determines runtime class
# Airgap mode comes from values-global.yaml (global.airgap); the default here
# is connected so standalone chart rendering uses upstream registries.
airgap: false
# Mirror root (org-prefixed for Quay targets) — required when airgap is true.
# The workload charts rewrite their images against it; see _helpers.tpl.
mirrorRegistry: ""
33 changes: 24 additions & 9 deletions overrides/values-baremetal-airgap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,37 @@
# The connected default (global.airgap: false) loads the inert
# values-baremetal-connected.yaml instead.
#
# SCOPE: this overlay applies when ArgoCD renders the clustergroup chart —
# i.e. to the clusterGroup OLM subscriptions (ESO, CNV, LVMS, trustee,
# cert-manager, intel-*, ACM, NFD) and the chart values below.
# SCOPE — this overlay reaches the ROOT clustergroup render: the
# patterns-operator resolves clusterGroup.sharedValueFiles itself when it
# builds the root Application (internal/controller/argo.go,
# commonApplicationSourceHelm → getSharedValueFiles), in addition to the
# chart forwarding them to child Applications. So the clusterGroup
# subscriptions and the app overrides below are all in scope.
#
# It does NOT reach the bootstrap operators: the openshift-gitops-operator
# and patterns-operator subscriptions are created by the patterns-operator
# BEFORE ArgoCD renders with this overlay. For airgap, their sources must
# be set directly in values-global.yaml:
# main.gitops.operatorSource: cs-redhat-operator-index-v4-22
# main.patternsOperator.source: cs-community-operator-index-v4-22
#
# LIST WARNING: Helm replaces lists when merging — an `overrides:` list here
# would drop any entry added to the same app in values-baremetal.yaml. This
# overlay therefore sets ONLY scalars (map values). Mode-dependent list
# entries (e.g. acm.mce_operator.source) are tpl-conditionals in the base
# file instead.
global:
# Mirrored catalog for the Argo-rendered OLM subscriptions (oc-mirror output)
# Mirrored catalog for the Argo-rendered OLM subscriptions (oc-mirror output).
# The names track the operator index tags in airgap/imageset-config-<minor>.yaml
# (e.g. redhat/redhat-operator-index:v4.22 → cs-redhat-operator-index-v4-22 for
# global.clusterVersion 4.22); scripts/airgap-post-install.sh step 3e fails fast
# if any catalog referenced here is missing from the cluster.
catalogSource: cs-redhat-operator-index-v4-22
catalogSourceNamespace: openshift-marketplace
# Trustee: flip platform collateral to the offline file backend.
# Collect with `make collect-dcap-collateral` before deploy.
kbs:
tdx:
collateralService: "file:///opt/confidential-containers/attestation-service/tdx/platform_collaterals.json"
# Connected default: the certified-operators catalog, disabled in airgap.
clusterGroup:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Possible bug: the clusterGroup.subscriptions and clusterGroup.applications.*.overrides in this overlay may never reach the chart that renders them. The overlay is loaded through clusterGroup.sharedValueFiles. clustergroup 0.9.58 (templates/plumbing/applications.yaml) adds sharedValueFiles only to the valueFiles of child Applications. The root clustergroup Application, built by patterns-operator, uses values-global, values-, values-*, and extraValueFiles. That root app is the one that renders Subscription objects and runs tpl on overrides. If that is right, with global.airgap: true the intel subscriptions stay on certified-operators, acm.mce_operator.source is never set, and the CoCo workloads keep their connected images. Please confirm this with a real render of the root app (for example make preview-all). If it doesn't apply, load the overlay through global.extraValueFiles or the Pattern CR's extraValueFiles.

subscriptions:
intel-device-plugins:
source: cs-certified-operator-index-v4-22
intel-tdx-dcap:
source: cs-certified-operator-index-v4-22
Loading
Loading