Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions components/utilities/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Utilities

Shared Kustomize `Component` helpers for GitOps overlays. Add new utilities as subdirectories
here (each subdirectory should contain a `kustomization.yaml` with `kind: Component`).

| Component | Role |
| --------- | ---- |
| [approve-installplan](./approve-installplan/) | RBAC, `Job`, and Subscription sync-wave patch for Manual OLM InstallPlan approval (OpenStack operator subscription from `architecture` `olm-openstack-subscriptions`). |
27 changes: 27 additions & 0 deletions components/utilities/approve-installplan/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# approve-installplan

Kustomize `Component` that adds:

- `ClusterRole` / `ClusterRoleBinding` so the OpenShift GitOps Argo CD application controller can patch `InstallPlan` objects and read related OpenStack APIs used by the Job script.
- `Job` `approve-openstack-installplan` (sync-wave `1`) that approves a Manual InstallPlan and waits for operator install.
- JSON6902 patch on `Subscription` named `openstack` (sync-wave `0`), matching
[`architecture` `olm-openstack-subscriptions`](https://github.com/openstack-k8s-operators/architecture/tree/main/lib/olm-openstack-subscriptions).

## Usage

List this directory under `components` **after** the overlay that emits the `Subscription` (for
example the remote `lib/olm-openstack-subscriptions/overlays/default` component). If this component
runs first, the Subscription sync-wave patch will not apply.

```yaml
components:
- pin-version
- https://github.com/openstack-k8s-operators/architecture/lib/olm-openstack-subscriptions/overlays/default?ref=COMMIT_SHA
- https://github.com/openstack-k8s-operators/gitops/components/utilities/approve-installplan?ref=v0.1.0
```

Images: `registry.redhat.io/openshift4/ose-tools-rhel9:latest` (Job).

In-tree overlays may reference this component with a local path until a release tag that contains
`components/utilities/approve-installplan` is published; use the HTTPS URL above for reproducible
builds outside the repository.
160 changes: 160 additions & 0 deletions components/utilities/approve-installplan/job.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
---
apiVersion: batch/v1
kind: Job
metadata:
name: approve-openstack-installplan
namespace: openshift-gitops
annotations:
argocd.argoproj.io/sync-wave: "1"
spec:
backoffLimit: 1
template:
spec:
containers:
- name: installplan-approver
image: registry.redhat.io/openshift4/ose-tools-rhel9:latest
env:
- name: OS_OPERATORS_NAMESPACE
value: "openstack-operators"
- name: OS_NAMESPACE
value: "openstack"
- name: RETRIES
value: "30"
- name: DELAY
value: "10"
- name: INSTALL_PLAN_RETRIES
value: "60"
- name: DEBUG
value: "true"
command:
- /bin/bash
- -c
- |
set -eo pipefail
if [ "${DEBUG}" = "true" ]; then
set -x
fi
# --- Configuration with defaults ---
# Namespace where the OpenStack operators are installed.
OS_OPERATORS_NAMESPACE=${OS_OPERATORS_NAMESPACE:-"openstack-operators"}
# Namespace where the OpenStack control plane is deployed and the OpenStackVersion CR exists.
OS_NAMESPACE=${OS_NAMESPACE:-"openstack"}
# Default number of retries for most checks.
RETRIES=${RETRIES:-60}
# Number of retries specifically for waiting for the InstallPlan to complete.
# This is longer because pulling operator images and starting pods can take a significant amount of time.
INSTALL_PLAN_RETRIES=${INSTALL_PLAN_RETRIES:-60}
# Delay in seconds between retries.
DELAY=${DELAY:-10}
# ---

log() {
echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) $@" >&2
}

find_and_approve_installplan() {
log "Waiting for unapproved InstallPlan..."
for i in $(seq 1 $RETRIES); do
install_plan_name=$(oc get installplan -n $OS_OPERATORS_NAMESPACE -o json | jq -r '.items[] | select(.spec.approval=="Manual" and .spec.approved==false) | .metadata.name' | head -n1) || true
[ -n "$install_plan_name" ] && break
log "Attempt $i/$RETRIES: No InstallPlan found, retrying..."
sleep $DELAY
done

if [ -z "$install_plan_name" ]; then
log "Error: No manual InstallPlan found to approve within the time limit."
exit 1
fi

log "Found InstallPlan: $install_plan_name, approving..."
oc patch installplan $install_plan_name -n $OS_OPERATORS_NAMESPACE --type merge -p '{"spec":{"approved":true}}' >&2
echo "$install_plan_name"
}

wait_for_installplan_completion() {
local install_plan_name=$1
for i in $(seq 1 $INSTALL_PLAN_RETRIES); do
phase=$(oc get installplan $install_plan_name -n $OS_OPERATORS_NAMESPACE -o jsonpath='{.status.phase}')
if [ "$phase" == "Complete" ]; then
log "InstallPlan completed successfully."
return 0
fi
if [ $i -eq $INSTALL_PLAN_RETRIES ]; then
log "Error: InstallPlan did not complete in time."
exit 1
fi
log "Attempt $i/$INSTALL_PLAN_RETRIES: Status is $phase, retrying..."
sleep $DELAY
done
}

wait_for_crd() {
log "Waiting for OpenStack CRD to become available..."
for i in $(seq 1 $RETRIES); do
if oc get crd openstacks.operator.openstack.org -o jsonpath='{.status.conditions[?(@.type=="Established")].status}' | grep -q True; then
log "OpenStack CRD is Established."
return 0
fi
if [ $i -eq $RETRIES ]; then
log "Error: OpenStack CRD did not become Established in time."
exit 1
fi
log "Attempt $i/$RETRIES: CRD not Established, retrying..."
sleep $DELAY
done
}

wait_for_new_version() {
log "Waiting for a new OpenStack version to become available..."

local deployed_version=""
for i in $(seq 1 $RETRIES); do
# There should be only one openstackversion CR
deployed_version=$(oc get openstackversion -n $OS_NAMESPACE -o jsonpath='{.items[0].status.deployedVersion}' 2>/dev/null) || true
if [ -n "$deployed_version" ]; then
log "Current deployed version is: $deployed_version"
break
fi
if [ $i -eq $RETRIES ]; then
log "Error: Could not get current deployed version in time."
exit 1
fi
log "Attempt $i/$RETRIES: Waiting for OpenStackVersion resource to get deployedVersion. Retrying..."
sleep $DELAY
done

for i in $(seq 1 $RETRIES); do
available_version=$(oc get openstackversion -n $OS_NAMESPACE -o jsonpath='{.items[0].status.availableVersion}' 2>/dev/null) || true
if [ -n "$available_version" ] && [ "$available_version" != "$deployed_version" ]; then
log "New available version found: $available_version"
return 0
fi
if [ $i -eq $RETRIES ]; then
log "Error: New version did not become available in time."
exit 1
fi
log "Attempt $i/$RETRIES: No new version available yet. Current available is '$available_version'. Retrying..."
sleep $DELAY
done
}

# --- Main execution ---
log "Starting install_plan_approval"
install_plan_name=$(find_and_approve_installplan)

log "Waiting for InstallPlan '$install_plan_name' to complete..."

wait_for_installplan_completion "$install_plan_name"

log "Checking if this is an initial installation or an update..."
if oc get openstack openstack -n $OS_OPERATORS_NAMESPACE; then
log "OpenStack CR 'openstack' exists. This is an update."
wait_for_new_version
else
log "OpenStack CR 'openstack' does not exist. This is an initial installation."
wait_for_crd
fi

log "Job completed successfully."
restartPolicy: Never
serviceAccountName: openshift-gitops-argocd-application-controller
16 changes: 16 additions & 0 deletions components/utilities/approve-installplan/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
# Apply this component after the Subscription exists in the build (e.g. after
# openstack-k8s-operators/architecture lib/olm-openstack-subscriptions).
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component
resources:
- job.yaml
- rbac.yaml
patches:
- target:
kind: Subscription
name: openstack
patch: |-
- op: add
path: /metadata/annotations/argocd.argoproj.io~1sync-wave
value: "0"
51 changes: 51 additions & 0 deletions components/utilities/approve-installplan/rbac.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
# ClusterRole and binding so the OpenShift GitOps Argo CD application controller
# can approve OLM InstallPlans and read resources used by the approval Job.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: installplan-approver-role
rules:
- apiGroups:
- operators.coreos.com
resources:
- installplans
verbs:
- get
- list
- patch
- apiGroups:
- operator.openstack.org
resources:
- openstacks
verbs:
- get
- list
- apiGroups:
- core.openstack.org
resources:
- openstackversions
verbs:
- get
- list
- patch
- apiGroups:
- apiextensions.k8s.io
resources:
- customresourcedefinitions
verbs:
- get
- list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: installplan-approver-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: installplan-approver-role
subjects:
- kind: ServiceAccount
name: openshift-gitops-argocd-application-controller
namespace: openshift-gitops
2 changes: 1 addition & 1 deletion example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ where the overlay includes `components/argocd/annotations`).

| Directory | Role |
| --------- | ---- |
| [openstack-operator](./openstack-operator/) | Foundational OpenStack operators, namespaces, subscription, install-plan approval (placeholder until a component exists). |
| [openstack-operator](./openstack-operator/) | Foundational OpenStack operators: CDN catalog + pinned CSV, OLM subscription from `architecture` `olm-openstack-subscriptions`, InstallPlan approval Job, RBAC. |
| [openstack-operator-cr](./openstack-operator-cr/) | Main OpenStack custom resource (placeholder until a component exists). |
| [openstack-networks](./openstack-networks/) | Underlying networks: NNCP, NAD, NetConfig, MetalLB pools / advertisements, etc. |
| [openstack-controlplane](./openstack-controlplane/) | `OpenStackControlPlane` and optional watcher service (networking is a separate overlay). |
Expand Down
55 changes: 49 additions & 6 deletions example/openstack-operator/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,53 @@
# openstack-operator

Placeholder overlay for the **openstack-operator** application described in the root
`README.md` (*Application responsibilities and content*).
Sample Kustomize overlay for the **openstack-operator** application described in the repository root
`README.md` under *Application responsibilities and content*.

There is no matching component under `components/rhoso/` yet. Replace this directory's
`kustomization.yaml` with real `components` / `resources` when a slice is added.
It installs the OpenStack operator from the **Red Hat Operator Hub** (`redhat-operators` catalog):
namespaces, `OperatorGroup`, `CatalogSource`, `Subscription` with a pinned `startingCSV`, Manual
InstallPlan approval, a post-sync `Job` that approves the InstallPlan, and RBAC for the OpenShift
GitOps application controller. The OLM manifests are composed from the
[`openstack-k8s-operators/architecture`](https://github.com/openstack-k8s-operators/architecture)
`lib/olm-openstack-subscriptions` component; local pieces supply CDN catalog settings and the CSV
pin.

Upstream context: Red Hat documentation *Installing and preparing the OpenStack
operator* (namespaces, subscription, install-plan approval job).
See Red Hat documentation:
[Installing and preparing the OpenStack operator](https://docs.redhat.com/en/documentation/red_hat_openstack_services_on_openshift/18.0/html/deploying_red_hat_openstack_services_on_openshift/assembly_installing-and-preparing-the-openstack-operator).

## Layout

| Path | Role |
| ---- | ---- |
| `catalog/values.yaml` | `ConfigMap` `olm-values` (channel, `redhat-operators`, index image, Manual approval) |
| `pin-version/` | Adds `data.openstack-operator-version` for `spec.startingCSV` |
| Remote component | `architecture` `olm-openstack-subscriptions/overlays/default` (pinned git ref in `kustomization.yaml`) |
| [approve-installplan](https://github.com/openstack-k8s-operators/gitops/tree/v0.1.0/components/utilities/approve-installplan) (`?ref=v0.1.0`) | Shared utility: RBAC, InstallPlan approval `Job`, Subscription sync-wave |

Component order in `kustomization.yaml` matters: the version pin runs before the remote OLM
component; the approval `Component` runs after it so the Subscription exists when the sync-wave patch
is applied.

## Render

From the repository root (network access is required the first time to fetch the remote component):

```bash
kustomize build example/openstack-operator
```

## Tunables

- **`registry.redhat.io/redhat/redhat-operator-index` tag** in `catalog/values.yaml` (`openstack-operator-image`):
use an index tag that matches your OpenShift cluster version (for example `v4.18` on OpenShift 4.18).
- **`openstack-operator.v1.0.16`** in `pin-version/patch.yaml`: adjust the CSV string when you target
a different RHOSO release available in the catalog.
- **Remote `architecture` git ref** in `kustomization.yaml`: pinned to a commit SHA for reproducible
builds; bump when you intentionally adopt newer `lib/olm-openstack-subscriptions` behavior.

Clusters must be able to pull images from `registry.redhat.io` (pull secret / global pull secret).

## Related

- [`components/utilities/`](../../components/utilities/) for shared helper components (including InstallPlan approval).
- `openstack-operator-cr` example: main `OpenStack` CR (separate overlay).
- `example/dependencies` for other OLM-related dependencies (MetalLB, NMState, cert-manager, etc.).
6 changes: 6 additions & 0 deletions example/openstack-operator/catalog/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- values.yaml
18 changes: 18 additions & 0 deletions example/openstack-operator/catalog/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# local-config: referenced, but not emitted by kustomize
---
apiVersion: v1
kind: ConfigMap
metadata:
name: olm-values
annotations:
config.kubernetes.io/local-config: 'true'
data:
openstack-operator-subscription-namespace: "openstack-operators"
openstack-operator-channel: "stable-v1.0"
openstack-operator-installplanapproval: "Manual"
# --- CatalogSource Settings ---
openstack-operator-catalog-source: "redhat-operators"
openstack-catalog-namespace: "openshift-marketplace"
openstack-operator-image: "registry.redhat.io/redhat/redhat-operator-index:v4.18"
openstack-operator-display-name: "Red Hat Operators"
openstack-operator-publisher: "Red Hat"
19 changes: 11 additions & 8 deletions example/openstack-operator/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources: []
resources:
- catalog

# No gitops component yet for this slice. See README.md.
# Future: add components (remote refs and local paths), for example:
# components:
# - https://github.com/openstack-k8s-operators/gitops/components/argocd/annotations?ref=TAG
# - https://github.com/openstack-k8s-operators/gitops/components/rhoso/...?ref=TAG
# Local paths (for "kustomize build" testing):
# - ../../components/argocd/annotations
# pin-version must run before the remote OLM component (olm-values feeds replacements).
# approve-installplan must run after the remote component so the Subscription exists for the sync-wave patch.
components:
- pin-version
- https://github.com/openstack-k8s-operators/architecture/lib/olm-openstack-subscriptions/overlays/default?ref=7da5f2e1dc2bfce99e269b0017783679ca405d8c
# TODO: replace the local path with a git HTTPS URI, e.g.
# https://github.com/openstack-k8s-operators/gitops/components/utilities/approve-installplan?ref=v0.1.0
# once that tag includes this component (same pattern as other example overlays).
- ../../components/utilities/approve-installplan
9 changes: 9 additions & 0 deletions example/openstack-operator/pin-version/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
# Patches olm-values with a pinned ClusterServiceVersion for spec.startingCSV on the Subscription.
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component
patches:
- path: patch.yaml
target:
kind: ConfigMap
name: olm-values
Loading
Loading