@@ -59,8 +59,8 @@ This script streamlines testing IIB images by configuring an OpenShift or Kubern
5959as a catalog source. On OLM v0, a CatalogSource is created in 'openshift-marketplace' (OpenShift) or 'olm' (Kubernetes). On OLM v1,
6060a ClusterCatalog is created (cluster-scoped); when --install-operator is also provided, a ClusterExtension, ServiceAccount, and
6161ClusterRoleBinding are created in the '${NAMESPACE_SUBSCRIPTION} ' namespace. By default, the OLM version is auto-detected based on
62- the presence of the ClusterExtension CRD. The default catalog/resource name is 'operatorName-channelName' (eg., rhdh-fast),
63- or 'brew-registry-stage' when using -- catalog-source with a brew IIB override
62+ the presence of the ClusterExtension CRD. When installing an operator, the script waits for readiness before exiting successfully.
63+ The default catalog/resource name is 'operatorName-channelName' (eg., rhdh-fast).
6464
6565If IIB installation fails, see https://docs.engineering.redhat.com/display/CFC/Test and
6666follow steps in section 'Adding Brew Pull Secret'
@@ -156,6 +156,107 @@ function resolve_olm_version() {
156156 fi
157157}
158158
159+ # On failure, print ClusterCatalog / ClusterExtension status so CI logs show why Serving/Installed never became True.
160+ function dump_olm_v1_diagnostics() {
161+ local catalog_name=" ${1:- } "
162+ local extension_name=" ${2:- } "
163+
164+ errorf " ===== OLM v1 diagnostics ====="
165+ [[ -n " ${catalog_name} " ]] && invoke_cluster_cli describe clustercatalog " ${catalog_name} " 2>&1 || true
166+ if [[ -n " ${extension_name} " ]]; then
167+ invoke_cluster_cli describe clusterextension " ${extension_name} " 2>&1 || true
168+ invoke_cluster_cli get clusterextension " ${extension_name} " -o jsonpath=' {.status.conditions}' 2>&1 || true
169+ echo
170+ fi
171+ errorf " ===== end OLM v1 diagnostics ====="
172+ }
173+
174+ # OLM v1 catalogd authenticates via openshift-config/pull-secret (--global-pull-secret),
175+ # not ClusterCatalog pullSecret fields or image-puller alone.
176+ function prepare_olm_v1_secrets() {
177+ set -euo pipefail
178+
179+ local catalogd_ns=" $1 "
180+ local controller_ns=" $2 "
181+ local image_namespace=" ${3:- rhdh} "
182+
183+ if [[ " ${IS_OPENSHIFT} " != " true" ]]; then
184+ return 0
185+ fi
186+
187+ local internal_registry_url=" image-registry.openshift-image-registry.svc:5000"
188+ # External route is optional; ClusterCatalog pulls via the internal svc URL.
189+ local external_registry_url
190+ external_registry_url=$( oc get route default-route -n openshift-image-registry --template=' {{ .spec.host }}' 2> /dev/null || true)
191+
192+ local token
193+ token=$( oc whoami -t)
194+ # macOS base64 has no -w0; Linux does. Strip newlines for both.
195+ local internal_auth
196+ internal_auth=$( echo -n " kubeadmin:${token} " | base64 | tr -d ' \n' )
197+
198+ local existing_pull_secret
199+ existing_pull_secret=$( oc get secret pull-secret -n openshift-config -o jsonpath=' {.data.\.dockerconfigjson}' | base64 -d)
200+
201+ local merged
202+ merged=$( echo " ${existing_pull_secret} " | jq \
203+ --arg url " ${internal_registry_url} " \
204+ --arg auth " ${internal_auth} " \
205+ ' .auths[$url] = {auth: $auth}' )
206+ if [[ -n " ${external_registry_url} " ]]; then
207+ merged=$( echo " ${merged} " | jq \
208+ --arg url " ${external_registry_url} " \
209+ --arg auth " ${internal_auth} " \
210+ ' .auths[$url] = {auth: $auth}' )
211+ else
212+ warnf " OpenShift registry default-route not found; merged credentials for ${internal_registry_url} only"
213+ fi
214+
215+ echo " ${merged} " | oc set data secret/pull-secret -n openshift-config --from-file=.dockerconfigjson=/dev/stdin >&2
216+ infof " Merged internal registry credentials into global pull secret (openshift-config/pull-secret)"
217+
218+ # Namespace-scoped secrets for the operator/installer SA (marketplace secrets already created by ocp_install).
219+ if ! invoke_cluster_cli get namespace " ${NAMESPACE_SUBSCRIPTION} " & > /dev/null; then
220+ invoke_cluster_cli create namespace " ${NAMESPACE_SUBSCRIPTION} " >&2
221+ fi
222+ invoke_cluster_cli -n " ${NAMESPACE_SUBSCRIPTION} " delete secret internal-reg-auth-for-rhdh --ignore-not-found >&2
223+ invoke_cluster_cli -n " ${NAMESPACE_SUBSCRIPTION} " create secret docker-registry internal-reg-auth-for-rhdh \
224+ --docker-server=" ${internal_registry_url} " \
225+ --docker-username=kubeadmin \
226+ --docker-password=" ${token} " \
227+ --docker-email=" admin@internal-registry.example.com" >&2
228+ if [[ -n " ${external_registry_url} " ]]; then
229+ invoke_cluster_cli -n " ${NAMESPACE_SUBSCRIPTION} " delete secret internal-reg-ext-auth-for-rhdh --ignore-not-found >&2
230+ invoke_cluster_cli -n " ${NAMESPACE_SUBSCRIPTION} " create secret docker-registry internal-reg-ext-auth-for-rhdh \
231+ --docker-server=" ${external_registry_url} " \
232+ --docker-username=kubeadmin \
233+ --docker-password=" ${token} " \
234+ --docker-email=" admin@internal-registry-ext.example.com" >&2
235+ fi
236+
237+ local catalogd_sa
238+ catalogd_sa=$( invoke_cluster_cli get deployment -n " ${catalogd_ns} " -l ' app.kubernetes.io/name=catalogd' \
239+ -o jsonpath=' {.items[0].spec.template.spec.serviceAccountName}' 2> /dev/null || true)
240+ catalogd_sa=" ${catalogd_sa:- catalogd-controller-manager} "
241+
242+ local controller_sa
243+ controller_sa=$( invoke_cluster_cli get deployment -n " ${controller_ns} " -l ' app.kubernetes.io/name=operator-controller' \
244+ -o jsonpath=' {.items[0].spec.template.spec.serviceAccountName}' 2> /dev/null || true)
245+ controller_sa=" ${controller_sa:- operator-controller-controller-manager} "
246+
247+ # Image project for the rebuilt IIB (created by ocp_install); ensure it exists before grants.
248+ if ! oc get namespace " ${image_namespace} " & > /dev/null; then
249+ oc create namespace " ${image_namespace} " >&2
250+ fi
251+
252+ debugf " Granting image-puller in namespace '${image_namespace} ' to OLM v1 service accounts"
253+ if ! oc policy add-role-to-user system:image-puller " system:serviceaccount:${catalogd_ns} :${catalogd_sa} " -n " ${image_namespace} " || \
254+ ! oc policy add-role-to-user system:image-puller " system:serviceaccount:${controller_ns} :${controller_sa} " -n " ${image_namespace} " ; then
255+ errorf " Failed to grant image-puller to OLM v1 controller SAs in namespace ${image_namespace} "
256+ return 1
257+ fi
258+ }
259+
159260function render_iib() {
160261 set -euo pipefail
161262
@@ -1008,12 +1109,18 @@ if [[ "${RESOLVED_OLM_VERSION}" == "v1" ]]; then
10081109 fi
10091110 debugf " Using operator-controller namespace: ${NAMESPACE_OLM_CONTROLLER} "
10101111
1011- # Grant image-puller access to OLM v1 controller SAs so they can pull images from the internal registry
1012- if [[ " ${IS_OPENSHIFT} " = " true" ]]; then
1013- oc policy add-role-to-user system:image-puller " system:serviceaccount:${NAMESPACE_CATALOGD} :catalogd-controller-manager" -n rhdh ||
1014- warnf " Failed to grant image-puller to catalogd SA; catalog image pulls from internal registry may fail"
1015- oc policy add-role-to-user system:image-puller " system:serviceaccount:${NAMESPACE_OLM_CONTROLLER} :operator-controller-controller-manager" -n rhdh ||
1016- warnf " Failed to grant image-puller to operator-controller SA; operator image pulls from internal registry may fail"
1112+ # OpenShift IIB is rebuilt into the internal registry under <project>/iib:...
1113+ # (ocp_install uses "rhdh"). Derive the project from the image ref instead of
1114+ # assuming the RHDH app deploy namespace (e.g. showcase).
1115+ IMAGE_NAMESPACE=" rhdh"
1116+ if [[ " ${newIIBImage} " =~ ^image-registry\. openshift-image-registry\. svc:5000/([^/]+)/ ]]; then
1117+ IMAGE_NAMESPACE=" ${BASH_REMATCH[1]} "
1118+ fi
1119+ debugf " Using image namespace for OLM v1 puller grants: ${IMAGE_NAMESPACE} "
1120+
1121+ if ! prepare_olm_v1_secrets " ${NAMESPACE_CATALOGD} " " ${NAMESPACE_OLM_CONTROLLER} " " ${IMAGE_NAMESPACE} " ; then
1122+ dump_olm_v1_diagnostics " ${CATALOGSOURCE_NAME} "
1123+ exit 1
10171124 fi
10181125
10191126 # Delete existing ClusterCatalog to force re-index
@@ -1023,16 +1130,25 @@ if [[ "${RESOLVED_OLM_VERSION}" == "v1" ]]; then
10231130kind: ClusterCatalog
10241131metadata:
10251132 name: ${CATALOGSOURCE_NAME}
1133+ labels:
1134+ olm.operatorframework.io/metadata.name: ${CATALOGSOURCE_NAME}
10261135spec:
10271136 source:
10281137 type: Image
10291138 image:
10301139 ref: ${newIIBImage}
10311140" > " $TMPDIR " /ClusterCatalog.yml && invoke_cluster_cli apply -f " $TMPDIR " /ClusterCatalog.yml
10321141
1142+ infof " Waiting for ClusterCatalog/${CATALOGSOURCE_NAME} Serving (timeout 300s)..."
1143+ if ! invoke_cluster_cli wait " clustercatalog/${CATALOGSOURCE_NAME} " --for=condition=Serving --timeout=300s; then
1144+ errorf " ClusterCatalog/${CATALOGSOURCE_NAME} did not become Serving within 300s (check openshift-config/pull-secret and image-puller RBAC if on OpenShift)"
1145+ dump_olm_v1_diagnostics " ${CATALOGSOURCE_NAME} "
1146+ exit 1
1147+ fi
1148+
10331149 if [[ -z " ${TO_INSTALL} " ]]; then
10341150 echo
1035- echo " Done. ClusterCatalog '${CATALOGSOURCE_NAME} ' created ."
1151+ echo " Done. ClusterCatalog '${CATALOGSOURCE_NAME} ' is Serving ."
10361152 echo " To install the operator, create a ClusterExtension, ServiceAccount, and ClusterRoleBinding."
10371153 exit 0
10381154 fi
@@ -1070,10 +1186,12 @@ subjects:
10701186 namespace: ${NAMESPACE_SUBSCRIPTION}
10711187" > " $TMPDIR " /ClusterRoleBinding.yml && invoke_cluster_cli apply -f " $TMPDIR " /ClusterRoleBinding.yml
10721188
1073- # Grant installer SA image-puller access so it can pull operator images from the internal registry
10741189 if [[ " ${IS_OPENSHIFT} " = " true" ]]; then
1075- oc policy add-role-to-user system:image-puller " system:serviceaccount:${NAMESPACE_SUBSCRIPTION} :${SA_NAME} " -n rhdh ||
1076- warnf " Failed to grant image-puller to installer SA '${SA_NAME} '; operator image pulls from internal registry may fail"
1190+ if ! oc policy add-role-to-user system:image-puller " system:serviceaccount:${NAMESPACE_SUBSCRIPTION} :${SA_NAME} " -n " ${IMAGE_NAMESPACE} " ; then
1191+ errorf " Failed to grant image-puller to installer SA '${SA_NAME} ' in namespace ${IMAGE_NAMESPACE} "
1192+ dump_olm_v1_diagnostics " ${CATALOGSOURCE_NAME} " " ${OPERATOR_NAME_TO_INSTALL} "
1193+ exit 1
1194+ fi
10771195 fi
10781196
10791197 # Create ClusterExtension
@@ -1094,13 +1212,34 @@ spec:
10941212 selector:
10951213 matchLabels:
10961214 olm.operatorframework.io/metadata.name: ${CATALOGSOURCE_NAME}
1215+ install:
1216+ preflight:
1217+ crdUpgradeSafety:
1218+ enforcement: None
10971219" > " $TMPDIR " /ClusterExtension.yml && invoke_cluster_cli apply -f " $TMPDIR " /ClusterExtension.yml
10981220
1221+ infof " Waiting for ClusterExtension/${OPERATOR_NAME_TO_INSTALL} Installed (timeout 300s)..."
1222+ if ! invoke_cluster_cli wait " clusterextension/${OPERATOR_NAME_TO_INSTALL} " --for=condition=Installed --timeout=300s; then
1223+ errorf " ClusterExtension/${OPERATOR_NAME_TO_INSTALL} did not become Installed within 300s"
1224+ dump_olm_v1_diagnostics " ${CATALOGSOURCE_NAME} " " ${OPERATOR_NAME_TO_INSTALL} "
1225+ exit 1
1226+ fi
1227+
1228+ # When installing RHDH, wait until the Backstage CRD is Established (not merely present).
1229+ if [[ " ${OPERATOR_NAME_IN_CS} " == " rhdh" || " ${OPERATOR_NAME_TO_INSTALL} " == " rhdh" ]]; then
1230+ infof " Waiting for CRD backstages.rhdh.redhat.com Established (timeout 300s)..."
1231+ if ! invoke_cluster_cli wait --for=condition=Established crd/backstages.rhdh.redhat.com --timeout=300s; then
1232+ errorf " CRD backstages.rhdh.redhat.com was not Established within 300s"
1233+ dump_olm_v1_diagnostics " ${CATALOGSOURCE_NAME} " " ${OPERATOR_NAME_TO_INSTALL} "
1234+ exit 1
1235+ fi
1236+ fi
1237+
10991238 # Post-install output
11001239 CLUSTER_ROUTER_BASE=$( invoke_cluster_cli get ingress.config.openshift.io/cluster ' -o=jsonpath={.spec.domain}' 2> /dev/null || true)
11011240
11021241 echo "
1103- Done. ClusterExtension '${OPERATOR_NAME_TO_INSTALL} ' created via OLM v1.
1242+ Done. ClusterExtension '${OPERATOR_NAME_TO_INSTALL} ' is Installed via OLM v1.
11041243
11051244To create an RHDH instance:
11061245${CR_EXAMPLE}
0 commit comments