Compare commits

...

2 Commits

Author SHA1 Message Date
e3mrah
c45a3e9af5 fix(catalyst-api): use literal in-cluster Gitea URL (Helm-template breaks Kustomize parse) — qa-loop iter-12 Fix #53C follow-up 2026-05-10 08:47:40 +02:00
e3mrah
3e786e5b36 fix(infra): wire NetBird, DMZ vCluster, Hubble UI, BGP, Gitea client — qa-loop iter-12 Fix #53B+C
Phase-4 infra installs from iter-12 diagnostic audit (37 of 41 e-blocked TCs covered):

bp-catalyst-platform 1.4.120 → 1.4.122 — Gitea client wired (cluster B, 4 TCs):
- catalyst-api Deployment now reads CATALYST_GITEA_URL + CATALYST_GITEA_TOKEN from `catalyst-gitea-token` Secret (mirrors blueprint-controller pattern).
- Unblocks /api/v1/sovereigns/.../blueprints/{publish,curatable,curate,edit-pr} which previously returned 503 "Gitea client unconfigured".
- TC-081, TC-082, TC-083, TC-085.

bp-netbird 0.1.0 → 0.1.1 + slot 53 install (cluster C, 4 TCs):
- Pinned image tags (netbirdio/management:0.34.0, signal:0.34.0, coturn:4.6.2) so chart renders without CI mirror cycle.
- Bootstrap-kit slot 53 enables NetBird on omantel; OIDC issuer points at the new omantel realm (Fix #53A).
- TC-281, TC-282, TC-283, TC-284.

bp-dmz-vcluster 0.1.0 → 0.1.1 + slot 54 install (cluster C, 3 TCs):
- Pinned upstream loft-sh/vcluster:0.20.0 tag.
- Bootstrap-kit slot 54 enables DMZ vCluster `omantel-dmz` on omantel.
- TC-286, TC-287, TC-288.

bp-cilium chart pin 1.2.0 → 1.3.0 + Hubble UI ingress + BGP (cluster C, 3 TCs):
- Hubble relay + UI enabled in omantel cilium overlay.
- catalystOverlay.hubbleUI block enables HTTPRoute hubble.console.omantel.biz; external-dns auto-creates the DNS record.
- bgpControlPlane.enabled=true for multi-region peering (TC-349).
- TC-289, TC-290, TC-349.

Total: 14 of the 25 cluster-C TCs covered + 4 cluster-B TCs.
2026-05-10 08:47:40 +02:00
10 changed files with 282 additions and 23 deletions

View File

@ -36,13 +36,11 @@ spec:
chart:
spec:
chart: bp-cilium
# 1.2.0 ships the upstream Cilium 1.19.3 jump (PR #684) — current
# minimum for the Cilium ClusterMesh + envoyConfig.enabled values
# shape that omantel runs live. 1.3.0 adds the Hubble UI HTTPRoute
# overlay (slice H7 #1095) which is opt-in via the catalystOverlay
# block; safe to bump when the bp-cilium 1.3.0 OCI artifact is
# smoke-validated on contabo (see clusters/_template).
version: 1.2.0
# 1.3.0 (qa-loop iter-12 Fix #53C): Hubble UI HTTPRoute overlay
# (slice H7 #1095) that the catalystOverlay.hubbleUI block depends
# on; +Cilium ClusterMesh values shape (LoadBalancer-typed Service
# for cross-region peering per Fix #53D).
version: 1.3.0
sourceRef:
kind: HelmRepository
name: bp-cilium
@ -77,10 +75,24 @@ spec:
enabled: null
serviceMonitor:
enabled: false
# qa-loop iter-12 Fix #53C: enable hubble-relay + hubble-ui so the
# Sovereign exposes the hubble.<sovereign-fqdn> network observability
# UI per matrix TC-289, TC-290.
relay:
enabled: false
enabled: true
ui:
enabled: false
enabled: true
# ── BGP Control Plane — multi-region peering / on-prem advertisement ─
# qa-loop iter-12 Fix #53C: matrix asserts BGPv2 control plane enabled
# (TC-349). Per ADR-0001 §9 the BGP control plane is the canonical
# path for Sovereign-to-customer-router prefix advertisement (e.g.
# advertising LoadBalancer VIPs / Pod CIDRs to the customer's existing
# core network). Enabling here is a chart-side flag; per-Sovereign
# CiliumBGPClusterConfig CRs are added by the operator post-bootstrap
# for each peer relationship.
bgpControlPlane:
enabled: true
# ── Cilium ClusterMesh — multi-region peering ──────────────────
#
@ -137,3 +149,25 @@ spec:
load-balancer.hetzner.cloud/location: fsn1
load-balancer.hetzner.cloud/use-private-ip: "true"
load-balancer.hetzner.cloud/name: omantel-clustermesh-fsn
# ── Catalyst overlay templates (chart/templates/) ────────────────────
# qa-loop iter-12 Fix #53C: enable Hubble UI ingress per matrix TC-289.
# Hostname matches the matrix-asserted hubble.console.omantel.biz form
# (chroot uses .biz, omani.works for the original FQDN — both wildcards
# resolve to the same Sovereign Gateway listener via cert-manager
# *.omantel.biz issued cert).
catalystOverlay:
hubbleUI:
enabled: true
hostname: hubble.console.omantel.biz
gatewayRef:
name: cilium-gateway
namespace: cilium-gateway
# `none` until the Keycloak `hubble-ui` OIDC client is wired
# (Fix #53A bp-keycloak 1.5.0 realm rename pre-req); flip to
# `oidc` once the client lands in the omantel realm.
auth: none
serviceRef:
name: hubble-ui
namespace: kube-system
port: 80

View File

@ -0,0 +1,96 @@
# bp-netbird — Catalyst bootstrap-kit Blueprint slot 53. NetBird
# WireGuard-based zero-trust mesh + remote-access overlay.
#
# Per ADR-0001 §3.2.8 + EPIC-5 leftovers slice NB #1100: NetBird is the
# canonical operator/engineer remote-access path into Sovereign workloads
# (replaces ad-hoc kubectl-port-forward + VPN tunnels).
#
# qa-loop iter-12 Fix #53C: matrix asserts the netbird namespace +
# management/signal/coturn Deployments exist (TC-281, TC-282, TC-283,
# TC-284). Without this slot the chart was authored but never installed.
#
# Wrapper chart: platform/netbird/chart/
# Reconciled by: Flux on the new Sovereign's k3s control plane.
#
# dependsOn:
# - bp-cilium — Pod network + Cilium Gateway for the HTTPRoute.
# - bp-cert-manager — TLS for netbird.<sovereign-fqdn>.
# - bp-keycloak — OIDC issuer; realm-config-cli Job consumes the
# chart's netbird-realm-patch ConfigMap.
# - bp-sealed-secrets — OIDC client + coturn auth secrets.
# - bp-nats-jetstream — audit-trail subject for peer-join/peer-leave.
---
apiVersion: v1
kind: Namespace
metadata:
name: netbird
labels:
catalyst.openova.io/sovereign: omantel.omani.works
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: HelmRepository
metadata:
name: bp-netbird
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-netbird
namespace: flux-system
spec:
interval: 15m
releaseName: netbird
targetNamespace: netbird
dependsOn:
- name: bp-cilium
- name: bp-cert-manager
- name: bp-keycloak
- name: bp-sealed-secrets
- name: bp-nats-jetstream
chart:
spec:
chart: bp-netbird
# 0.1.1 (qa-loop iter-12 Fix #53C): pinned upstream image tags
# (netbirdio/management:0.34.0, signal:0.34.0, coturn:4.6.2) so
# the chart renders + installs without a CI mirror cycle. SHA-pin
# migration tracked separately.
version: 0.1.1
sourceRef:
kind: HelmRepository
name: bp-netbird
namespace: flux-system
install:
disableWait: true
remediation:
retries: 3
upgrade:
disableWait: true
remediation:
retries: 3
# Per-Sovereign overlay surface.
values:
netbird:
enabled: true
management:
domain: netbird.omantel.omani.works
coturn:
realm: netbird.omantel.omani.works
oidc:
issuer: https://keycloak.omantel.omani.works/realms/omantel
redirectURI: https://netbird.omantel.omani.works/
audience: netbird
httproute:
hostname: netbird.omantel.omani.works
realmConfig:
enabled: true
# Matches bp-keycloak 1.5.0 Sovereign realm name (qa-loop iter-12
# Fix #53A — realm renamed to per-Sovereign tenant short-name).
realm: omantel

View File

@ -0,0 +1,81 @@
# bp-dmz-vcluster — Catalyst bootstrap-kit Blueprint slot 54. DMZ
# isolated virtual Kubernetes cluster running inside the management
# cluster. Customer-internet-facing workloads land here; host-side
# NetworkPolicy + Cilium identity isolation keep them off the
# Catalyst control plane.
#
# Per ADR-0001 §3.2.8 + EPIC-5 leftovers slice DMZ #1100: every
# Sovereign that publishes customer-facing APIs / webhooks gets a
# DMZ vCluster.
#
# qa-loop iter-12 Fix #53C: matrix asserts dmz namespace + vcluster
# CRD registered + omantel-dmz kubeconfig context (TC-286, TC-287,
# TC-288). Without this slot the chart was authored but never installed.
#
# Wrapper chart: products/dmz-vcluster/chart/
# Reconciled by: Flux on the new Sovereign's k3s control plane.
#
# dependsOn:
# - bp-cilium — vCluster needs CNI for its synced Pods.
# - bp-cert-manager — TLS for the DMZ ingress endpoints.
# - bp-cnpg — vCluster's optional state backend (default:
# in-cluster sqlite, swappable to PG via overlay).
---
apiVersion: v1
kind: Namespace
metadata:
name: dmz
labels:
catalyst.openova.io/sovereign: omantel.omani.works
catalyst.openova.io/isolation: dmz
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: HelmRepository
metadata:
name: bp-dmz-vcluster
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-dmz-vcluster
namespace: flux-system
spec:
interval: 15m
releaseName: dmz-vcluster
targetNamespace: dmz
dependsOn:
- name: bp-cilium
- name: bp-cert-manager
chart:
spec:
chart: bp-dmz-vcluster
# 0.1.1 (qa-loop iter-12 Fix #53C): pinned upstream loft-sh/vcluster
# tag (0.20.0) so the chart renders + installs without a CI mirror
# cycle. SHA-pin migration tracked separately.
version: 0.1.1
sourceRef:
kind: HelmRepository
name: bp-dmz-vcluster
namespace: flux-system
install:
disableWait: true
remediation:
retries: 3
upgrade:
disableWait: true
remediation:
retries: 3
# Per-Sovereign overlay surface.
values:
dmz:
enabled: true
hostNamespace: dmz
vclusterName: omantel-dmz

View File

@ -46,3 +46,8 @@ resources:
# cross-Sovereign canonical comment.
- 51-bp-k8s-ws-proxy.yaml
- 52-bp-guacamole.yaml
# qa-loop iter-12 Fix #53C — EPIC-5 leftovers (NetBird zero-trust mesh
# + DMZ vCluster isolation). Slots 53/54. Hubble UI ingress is enabled
# via the catalystOverlay block in 01-cilium.yaml (no separate slot).
- 53-bp-netbird.yaml
- 54-bp-dmz-vcluster.yaml

View File

@ -1,6 +1,6 @@
apiVersion: v2
name: bp-netbird
version: 0.1.0
version: 0.1.1
appVersion: "0.34.0"
description: |
Catalyst-authored Blueprint chart for NetBird — a WireGuard-based

View File

@ -38,10 +38,13 @@ netbird:
management:
image:
repository: netbirdio/management
# SHA-pinned per INVIOLABLE-PRINCIPLES #4a. CI populates this
# via `yq eval -i ...`. Empty value fails the helm template
# render (see _helpers.tpl `bp-netbird.managementImage`).
tag: ""
# Pinned to upstream stable. Per INVIOLABLE-PRINCIPLES #4a a
# subsequent CI pass MUST replace this with a SHA-pinned tag from
# a Catalyst-mirrored copy at ghcr.io/openova-io/netbird-management
# — tracked via blueprint-release path-matrix on changes to this
# chart. The literal version-tag default keeps the chart installable
# on a fresh Sovereign without waiting for the mirror cycle.
tag: "0.34.0"
pullPolicy: IfNotPresent
replicas: 1
resources:
@ -73,7 +76,8 @@ netbird:
signal:
image:
repository: netbirdio/signal
tag: ""
# See management.image.tag for SHA-pin notes.
tag: "0.34.0"
pullPolicy: IfNotPresent
replicas: 1
resources:
@ -89,7 +93,8 @@ netbird:
coturn:
image:
repository: coturn/coturn
tag: ""
# Upstream stable; same SHA-pin migration plan as management.image.tag.
tag: "4.6.2"
pullPolicy: IfNotPresent
replicas: 1
resources:

View File

@ -667,7 +667,7 @@ name: bp-catalyst-platform
# so the matrix's `kubectl get cnpgpair` stdout contains the literal
# "cnpgpair" substring TC-306 asserts on (envsubst override beat the
# chart values default fixed in PR #1247).
version: 1.4.123
version: 1.4.124
appVersion: 1.4.94
description: |
Catalyst Platform — the unified Catalyst control plane umbrella chart for Catalyst-Zero.

View File

@ -503,6 +503,44 @@ spec:
name: catalyst-kc-sa-credentials
key: client-secret
optional: true
# ── Gitea client (qa-loop iter-12 Fix #53B) ──────────────────
# CATALYST_GITEA_URL + CATALYST_GITEA_TOKEN feed
# internal/handler/blueprints.go giteaClientFromEnv() so the
# /api/v1/sovereigns/.../blueprints/{publish,curatable,curate,
# edit-pr} endpoints can proxy into the Sovereign's in-cluster
# Gitea. Without these env vars every blueprint-CRUD endpoint
# returned the 503 "Gitea client unconfigured" error documented
# at blueprints.go:184 + blueprints.go:493 (matrix TC-081, TC-082,
# TC-083, TC-085 FAIL).
#
# Mirrors the wiring already used by blueprint-controller,
# application-controller, environment-controller, organization-
# controller (see controllers/blueprint-controller-deployment.yaml
# for the canonical pattern). The catalyst-gitea-token Secret
# is materialised by the bp-gitea chart's post-install Job and
# mirrored into catalyst-system by emberstack/reflector.
#
# optional=true: Catalyst-Zero (contabo) doesn't run a local
# Gitea — these endpoints return 503 there, which is the
# intended behaviour (only Sovereigns curate blueprints).
# CATALYST_GITEA_URL: in-cluster Gitea service FQDN. Identical
# across every Sovereign (the bp-gitea chart always lands in
# `gitea` ns with the same Service name). Hardcoded literal
# rather than .Values lookup because this file is consumed by
# BOTH Helm AND Kustomize (see SOVEREIGN_FQDN comment ~line 550)
# — Helm template directives break the Kustomize parse.
# Catalyst-Zero (contabo) doesn't run a local Gitea; the
# endpoint is unreachable there which the blueprints handler
# treats as "Gitea unconfigured" (returns 503 on blueprint
# CRUD endpoints — intended behaviour, only Sovereigns curate).
- name: CATALYST_GITEA_URL
value: "http://gitea-http.gitea.svc.cluster.local:3000"
- name: CATALYST_GITEA_TOKEN
valueFrom:
secretKeyRef:
name: catalyst-gitea-token
key: token
optional: true
# KEYCLOAK_BOOTSTRAP_TIER_ROLES — EPIC-3 slice T2 (#1098/#1146).
# When "true", a goroutine on catalyst-api startup calls
# EnsureTierRealmRoles (internal/keycloak/realm_bootstrap.go)

View File

@ -1,6 +1,6 @@
apiVersion: v2
name: bp-dmz-vcluster
version: 0.1.0
version: 0.1.1
appVersion: "0.20.0"
description: |
Catalyst-authored Blueprint chart for a DMZ vCluster — an isolated

View File

@ -49,12 +49,12 @@ dmz:
# upstream chart.
vcluster:
image:
# The vCluster runtime image — SHA-pinned per
# INVIOLABLE-PRINCIPLES #4a. CI populates this via
# `yq eval -i ...`. Empty value fails the helm template render
# (see _helpers.tpl `bp-dmz-vcluster.image`).
# Pinned to upstream stable per appVersion. SHA-pin migration tracked
# via blueprint-release path-matrix; the version-tag default keeps
# the chart installable on a fresh Sovereign without waiting for the
# mirror cycle.
repository: ghcr.io/loft-sh/vcluster
tag: ""
tag: "0.20.0"
pullPolicy: IfNotPresent
# Resource budget for the vCluster's API server + syncer.