`#!/usr/bin/env bash

Render the cert-manager and Google CAS issuer charts to plain YAML under

addons/, which Config Sync then reconciles.

WHY RENDER AHEAD OF TIME rather than letting Config Sync inflate the charts:

the fleet API's config_sync accepts only git and oci sources - there is no

Helm source type - and Kustomize helm-inflation would make the in-cluster

hydration controller authenticate to our private Artifact Registry. Rendering

here keeps registry auth on this side of the fence and makes a chart bump show

up as a reviewable YAML diff instead of an opaque version string.

The rendered output IS COMMITTED. Re-run this only when bumping a chart version

or editing render/values-*.yaml, then review the diff and commit it.

helm runs as a CONTAINER so nothing needs installing beyond docker - same

approach as 3-artifact-registry/mirror.sh.

set -euo pipefail
cd "$(dirname "$0")"

REGISTRY=asia-south1-docker.pkg.dev
OCI="${REGISTRY}/project_id/shared-docker"

helm comes from OUR mirror, not Docker Hub. Mirrored by

fast/stages/3-artifact-registry/mirror.sh, for the same reasons the charts and

cert-manager images are: no external registry on the path, no Docker Hub pull

limits, and an air-gapped build host can still render.

This is an AUTHORING-time dependency only. Nothing in the cluster pulls it -

Config Sync reconciles the committed output under manifests/ - so it never

appears on the deploy path.

HELM_IMAGE="${OCI}/alpine-helm:3.16.2"
NAMESPACE=cert-manager

Chart versions. These are the mirrored versions in shared-docker/charts - bump

the mirror (3-artifact-registry/mirror.sh) before bumping these.

CERT_MANAGER_VERSION=v1.21.0
CAS_ISSUER_VERSION=v0.11.0

TOKEN="$(gcloud auth print-access-token)" || { echo "run: gcloud auth login" >&2; exit 1; }

Pull the helm image using a THROWAWAY docker config rather than

gcloud auth configure-docker, so this leaves the operator's ~/.docker

untouched and needs no one-time host setup.

WORK="$(mktemp -d)"; trap 'rm -rf "${WORK}"' EXIT; chmod 700 "${WORK}"
export DOCKER_CONFIG="${WORK}/docker"; mkdir -p "${DOCKER_CONFIG}"
cat > "${DOCKER_CONFIG}/config.json" <<JSON
{"auths":{"${REGISTRY}":{"username":"oauth2accesstoken","password":"${TOKEN}"}}}
JSON
chmod 600 "${DOCKER_CONFIG}/config.json"

if ! docker pull -q "${HELM_IMAGE}" >/dev/null 2>&1; then
echo "ERROR: cannot pull ${HELM_IMAGE}" >&2
echo " mirror it first: fast/stages/3-artifact-registry/mirror.sh" >&2
exit 1
fi

Values come from FILES, not --set. --set needs dots escaped inside the key

(serviceAccount.annotations."iam.gke.io/...") and those backslashes do not

survive being interpolated into the container's sh -c, which silently

produced an empty render. Files also make the values reviewable in git.

Files this script OWNS and overwrites. Anything under manifests/ not listed

here is hand-written - notably the GoogleCASClusterIssuer, which lives beside

the chart output but is not produced by it.

declare -a GENERATED=()

render() { # release chart version values-file outfile
local release=$1 chart=$2 version=$3 values=$4 out=$5
printf 'rendering %-32s %-8s -> %s\n' "${chart}" "${version}" "${out}"
mkdir -p "$(dirname "${out}")"
docker run --rm --entrypoint /bin/sh \
-e HOME=/tmp -e TOKEN="${TOKEN}" \
-v "${PWD}/${values}:/values.yaml:ro" \
"${HELM_IMAGE}" -c "
set -e
helm registry login ${REGISTRY} -u oauth2accesstoken -p \"\$TOKEN\" >/dev/null 2>&1
helm template ${release} oci://${OCI}/charts/${chart} \
--version ${version} --namespace ${NAMESPACE} --values /values.yaml
" > "${out}.tmp"
# Fail loudly rather than committing an empty file - the silent-empty-render
# above is exactly what this guards against.
if [[ ! -s "${out}.tmp" ]] || ! grep -q '^kind:' "${out}.tmp"; then
echo "ERROR: render produced no objects for ${chart}" >&2
rm -f "${out}.tmp"; exit 1
fi
mv "${out}.tmp" "${out}"
GENERATED+=("${out}")
}

helm template does NOT emit the release namespace - create_namespace on the old

helm_release did that - so Config Sync has to be told about it explicitly.

mkdir -p manifests/addons/cert-manager
GENERATED+=(manifests/addons/cert-manager/namespace.yaml)
cat > manifests/addons/cert-manager/namespace.yaml <<YAML

helm template does not render the release namespace (create_namespace on the

retired helm_release did), so it is declared here for Config Sync.

apiVersion: v1
kind: Namespace
metadata:
name: ${NAMESPACE}
YAML

render cert-manager cert-manager "${CERT_MANAGER_VERSION}" \
render/values-cert-manager.yaml manifests/addons/cert-manager/cert-manager.yaml

render cert-manager-google-cas-issuer cert-manager-google-cas-issuer \
"${CAS_ISSUER_VERSION}" render/values-cas-issuer.yaml \
manifests/addons/cas-issuer/cas-issuer.yaml

echo
echo "generated by this script (do not hand-edit):"
for f in "${GENERATED[@]}"; do
printf ' %-52s %3s objects\n' "$f" "$(grep -c '^kind:' "$f")"
done
echo
echo "hand-written (left alone):"
for f in $(find manifests -name '*.yaml' | sort); do
printf '%s\n' "${GENERATED[@]}" | grep -qxF "$f" || echo " $f"
done
echo
echo "Config Sync reconciles from the GIT BRANCH, so nothing takes effect until"
echo "this is committed and pushed:"
echo " git diff --stat manifests/"
echo " git add -A manifests/ render/ && git commit && git push"
`