# bp-guacamole — Catalyst bootstrap-kit Blueprint slot 52 (exec
# fan-out, post-W2.K4). Apache Guacamole HTML5 remote-desktop gateway.
# Brokers
# SSH / RDP / VNC sessions AND kubectl-exec sessions through one
# browser-accessible surface. Sessions are authenticated via Keycloak
# SSO, recorded to SeaweedFS for compliance, and reach Pods via the
# per-node bp-k8s-ws-proxy DaemonSet.
#
# Per ADR-0001 §11: ONE Guacamole per Sovereign — no Manara-style
# multi-cluster fan-out (Sovereigns stay self-sufficient).
#
# Wrapper chart: platform/guacamole/chart/
# Catalyst-curated values: platform/guacamole/chart/values.yaml
# Reconciled by: Flux on the new Sovereign's k3s control plane.
#
# dependsOn:
#   - bp-cilium                — Pod network + Gateway API for the
#                                operator-facing HTTPRoute.
#   - bp-cert-manager          — TLS for guacamole.<sovereign-fqdn>
#                                via the Cilium Gateway listener.
#   - bp-keycloak              — OIDC issuer + realm-config Job that
#                                consumes the chart's realm-patch
#                                ConfigMap.
#   - bp-sealed-secrets        — OIDC client-secret SealedSecret.
#   - bp-seaweedfs             — RWX-capable PVC for session recordings.
#   - bp-k8s-ws-proxy          — exec tunnelling onto the local-node
#                                kube-apiserver via the DaemonSet.
#
# qa-loop iter-7 Fix #39 (closes the gap surfaced by Fix #36):
# bp-guacamole was previously chart-only, no CI workflow + no
# bootstrap-kit slot, so TC-228/TC-230/TC-245/TC-246 stayed FAIL
# with "deployment NotFound". The CI workflow
# .github/workflows/build-bp-guacamole.yaml mirrors the upstream
# Apache Guacamole images to GHCR, bumps Chart.yaml, dispatches
# blueprint-release; this slot installs the resulting OCI artifact
# on every Sovereign.
#
# install/upgrade.disableWait: true — readiness signalled via Flux
# dependsOn, never via spec.timeout watchdogs.

---
apiVersion: v1
kind: Namespace
metadata:
  name: guacamole
  labels:
    catalyst.openova.io/sovereign: ${SOVEREIGN_FQDN}
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: HelmRepository
metadata:
  name: bp-guacamole
  namespace: flux-system
spec:
  type: oci
  interval: 15m
  url: oci://ghcr.io/openova-io
  secretRef:
    name: ghcr-pull
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: bp-guacamole
  namespace: flux-system
  labels:
    catalyst.openova.io/slot: "52"
spec:
  interval: 15m
  releaseName: guacamole
  # Lands in catalyst-system to be co-located with the catalyst-api +
  # k8s-ws-proxy + the rest of the Catalyst control-plane stack. The
  # chart's NetworkPolicies allow cross-namespace egress to keycloak
  # / seaweedfs / nats-jetstream regardless of where it lands.
  targetNamespace: catalyst-system
  dependsOn:
    - name: bp-cilium
    - name: bp-cert-manager
    - name: bp-keycloak
    - name: bp-sealed-secrets
    - name: bp-seaweedfs
    - name: bp-k8s-ws-proxy
  chart:
    spec:
      chart: bp-guacamole
      # 0.1.9 (qa-loop iter-11 Fix #45 Cluster-A): adds the
      # storageClass-migration pre-install/pre-upgrade hook that
      # unwedges Sovereigns where the existing `guacamole-recordings`
      # PVC is bound to a different storageClass than the chart-desired
      # one (live failure on omantel iter-11: PVC bound to local-path,
      # chart wanted seaweedfs-storage, K8s rejected the immutable-spec
      # patch with `cannot patch ... PersistentVolumeClaim ... is
      # invalid: spec: Forbidden: spec is immutable after creation`).
      # 0.1.15 (Fix #158): migrationImage bumped to
      # bitnamilegacy/kubectl:1.30.7 (was 1.29.3); template fallback no
      # longer references bitnami/kubectl (deleted from Docker Hub 2025-08).
      # 0.1.19 (2026-05-12): chart-bump mirror chain caught up — tests/
      # render.sh expect_total realigned from 15 → 19 (Fix #125's
      # bootstrap Job for guacamole-oidc Secret added 4 resources: 1 Job
      # + 1 ServiceAccount + 1 Role + 1 RoleBinding). Prior to the test
      # fix, every Build bp-guacamole run published images but the
      # Blueprint Release dispatched on the bump commit failed render.sh
      # → 0.1.13–0.1.18 were never published to GHCR → bootstrap-kit
      # HRs wedged at "ghcr.io/openova-io/bp-guacamole:0.1.17: not found".
      # 0.1.21 (Refs TBD-G4 / C5-009, 2026-05-18): pulls in PR #1684
      # (guacamole-deployment.yaml mount /home/guacamole instead of
      # /home/guacamole/.guacamole). The official Apache Guacamole
      # image entrypoint runs `rm -rf $GUACAMOLE_HOME` before
      # repopulating the directory on every start; when the emptyDir
      # was mounted directly at /home/guacamole/.guacamole the path
      # was a mount point and `rm` failed with `Read-only file
      # system`, crash-looping the webapp before Tomcat ever booted
      # (observed on t22, 16 restarts). Mounting the parent dir
      # makes .guacamole a regular subdirectory the entrypoint can
      # freely rm and recreate.
      # 0.1.22 (Refs TBD-G6 / C12-004, 2026-05-18): pulls in PR #1692
      # (values default guacamole.httproute.parentRef.namespace
      # gateway-system -> kube-system). The
      # catalyst-system/guacamole-server HTTPRoute on t22 went
      # Accepted=False because gateway-system/cilium-gateway does not
      # exist on any Sovereign — the canonical gateway is
      # kube-system/cilium-gateway installed by 01-cilium.yaml and
      # used by every other Sovereign HTTPRoute.
      # 0.1.23 (Refs TBD-G4 phase 2 / C12-005, 2026-05-18): pulls in
      # PR #1699 (liveness + readiness probe paths flipped from `/`
      # to `/guacamole/`). The Apache Guacamole webapp deploys under
      # Tomcat's context path /guacamole/, not /, so probing `/`
      # made kubelet restart the Pod every ~60s and the kube-system
      # Cilium gateway returned 503 to the public hostname because
      # the Endpoint was never Ready (observed on t22, 5 restarts).
      # 0.1.25 (catch-up for Blueprint Release workflow outage,
      # 2026-05-18 21:04Z → 22:07Z): chart published 0.1.24 → 0.1.25
      # during the YAML scanner break introduced by PR #1858 and fixed
      # by PR #1866. Auto-bump-pin step didn't fire during the outage.
      # Refs #1864.
      version: 0.1.26
      sourceRef:
        kind: HelmRepository
        name: bp-guacamole
        namespace: flux-system
  install:
    timeout: 15m
    disableWait: true
    remediation:
      retries: 3
  upgrade:
    timeout: 15m
    disableWait: true
    remediation:
      retries: 3
  # Per-Sovereign overlay surface. The Sovereign's FQDN is interpolated
  # at Flux apply time via the bootstrap-kit Kustomization's
  # postBuild.substitute env hook (see clusters/_template/README.md +
  # infra/hetzner/cloudinit-control-plane.tftpl) — `${SOVEREIGN_FQDN}`
  # below is replaced with the concrete sovereign FQDN before the HR
  # bytes land in the cluster.
  values:
    guacamole:
      # Default-OFF gate flipped ON by the bootstrap-kit slot. Operator
      # opts out per-Sovereign by removing this slot from
      # clusters/<sovereign>/bootstrap-kit/kustomization.yaml.
      enabled: true
      httproute:
        # Resolved from the per-Sovereign Kustomize overlay's
        # SOVEREIGN_FQDN env var, which envsubst materializes when the
        # bootstrap-kit Kustomization renders.
        hostname: guacamole.${SOVEREIGN_FQDN}
      oidc:
        # Same SOVEREIGN_FQDN substitution. The realm name (`catalyst`)
        # matches bp-keycloak's realm-config-cli default.
        issuer: https://keycloak.${SOVEREIGN_FQDN}/realms/catalyst
      recordings:
        # SeaweedFS-CSI is the canonical RWX storageClass for
        # multi-pod session-recording workloads on Sovereigns; see
        # platform/seaweedfs/chart values.yaml for the StorageClass
        # name. Per-Sovereign overlay can override for non-SeaweedFS
        # backends (e.g. hcloud-volumes single-node fallback).
        storageClass: seaweedfs-storage
