fix(bp-external-secrets): split ClusterSecretStore into bp-external-secrets-stores chart (resolves CRD ordering, closes #331)
bp-external-secrets@1.0.0 deadlocked on first install on otech.omani.works: Helm install failed for release external-secrets-system/external-secrets with chart bp-external-secrets@1.0.0: failed post-install: unable to build kubernetes object for deleting hook bp-external-secrets/templates/clustersecretstore-vault-region1.yaml: resource mapping not found for name: "vault-region1" namespace: "" no matches for kind "ClusterSecretStore" in version "external-secrets.io/v1beta1" Root cause: Helm's `helm.sh/hook-delete-policy: before-hook-creation` ran a kubectl-style lookup of the existing ClusterSecretStore CR before the upstream `external-secrets` subchart's CRDs finished registration. The in-line ClusterSecretStore template (templates/clustersecretstore-vault- region1.yaml) and the upstream subchart's CRDs co-installed in the same release; admission ordering wasn't deterministic enough to make the post-install hook safe. Fix — same pattern as PR #247 (bp-crossplane@1.1.3 ↔ bp-crossplane-claims@1.0.0): split the chart into controller + stores. Flux dependsOn orders them. - bp-external-secrets@1.1.0 — controller-only (just upstream subchart + NetworkPolicy + ServiceMonitor toggle). CRDs register here. - bp-external-secrets-stores@1.0.0 (NEW) — the default ClusterSecretStore CR; depends on bp-external-secrets being Ready. No Helm hooks needed: by the time this chart's HelmRelease starts, Flux has already verified bp-external-secrets is Ready=True and therefore the CRDs are registered. Files: NEW: platform/external-secrets-stores/blueprint.yaml (1.0.0) NEW: platform/external-secrets-stores/chart/Chart.yaml (1.0.0; no upstream subchart, annotation `catalyst.openova.io/no-upstream: "true"`) NEW: platform/external-secrets-stores/chart/values.yaml (clusterSecretStore.* knobs moved from controller chart) MOVED: platform/external-secrets/chart/templates/clustersecretstore-vault-region1.yaml → platform/external-secrets-stores/chart/templates/clustersecretstore-vault-region1.yaml (Helm hook annotations removed — Flux dependsOn now handles ordering) TOUCHED: platform/external-secrets/chart/Chart.yaml (1.0.0 → 1.1.0; description note appended) TOUCHED: platform/external-secrets/blueprint.yaml (1.0.0 → 1.1.0) TOUCHED: platform/external-secrets/chart/values.yaml (clusterSecretStore block removed; pointer comment added) NEW: clusters/_template/bootstrap-kit/15a-external-secrets-stores.yaml (Flux HelmRelease, dependsOn: [bp-external-secrets, bp-openbao]) TOUCHED: clusters/_template/bootstrap-kit/15-external-secrets.yaml (chart version 1.0.0 → 1.1.0) TOUCHED: clusters/_template/bootstrap-kit/kustomization.yaml (slot 15a inserted after 15) Out of scope for this PR (separate tickets): - blueprint-release.yaml CI fan-out: verify the path-matrix picks up the new platform/external-secrets-stores/ directory automatically; if not, add the directory to the matrix in a follow-up. - Per-Sovereign cluster directory edits (#257 will delete those). - Phase 0 minimum trim (#310 will renumber slots; this PR uses 15a as a non-disruptive sub-slot insertion that works with both the current 35-slot kustomization and the eventual 15-slot canonical layout — when #310 renumbers, 15 + 15a become 08 + 09 in the canonical order). Refs: #331 (this issue), #247 (pattern reference — bp-crossplane split), #310 (Phase 0 trim — companion). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4f80be232a
commit
dc4155c675
@ -57,7 +57,7 @@ spec:
|
||||
chart:
|
||||
spec:
|
||||
chart: bp-external-secrets
|
||||
version: 1.0.0
|
||||
version: 1.1.0
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: bp-external-secrets
|
||||
|
||||
@ -0,0 +1,65 @@
|
||||
# bp-external-secrets-stores — Catalyst bootstrap-kit Blueprint, slot 15a
|
||||
# (sub-slot of 15, follows bp-external-secrets controller).
|
||||
#
|
||||
# Owns the default ClusterSecretStore CR(s) wiring ESO to bp-openbao.
|
||||
# Split from bp-external-secrets@1.0.0 (issue #331) to resolve the
|
||||
# CRD-ordering deadlock — Helm's `before-hook-creation` delete policy on
|
||||
# the in-line ClusterSecretStore hook ran a kubectl-style lookup of the
|
||||
# CR before the upstream chart's CRDs finished registering, deadlocking
|
||||
# the install with `no matches for kind ClusterSecretStore` (incident on
|
||||
# otech.omani.works 2026-04-30).
|
||||
#
|
||||
# Mirrors the bp-crossplane (controller) ↔ bp-crossplane-claims (CRs)
|
||||
# split shape from PR #247.
|
||||
#
|
||||
# Wrapper chart: platform/external-secrets-stores/chart/
|
||||
# Catalyst-curated values: platform/external-secrets-stores/chart/values.yaml
|
||||
# Reconciled by: Flux on the new Sovereign's k3s control plane.
|
||||
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1beta2
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: bp-external-secrets-stores
|
||||
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-external-secrets-stores
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 15m
|
||||
releaseName: external-secrets-stores
|
||||
targetNamespace: external-secrets-system
|
||||
# Order — Flux will not start install until bp-external-secrets reaches
|
||||
# Ready=True (which means: upstream ESO controller running AND CRDs
|
||||
# registered) AND bp-openbao reaches Ready (the secret backend the
|
||||
# ClusterSecretStore points at).
|
||||
dependsOn:
|
||||
- name: bp-external-secrets
|
||||
- name: bp-openbao
|
||||
chart:
|
||||
spec:
|
||||
chart: bp-external-secrets-stores
|
||||
version: 1.0.0
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: bp-external-secrets-stores
|
||||
namespace: flux-system
|
||||
# Event-driven install per docs/INVIOLABLE-PRINCIPLES.md #3 (Flux
|
||||
# dependsOn is the gate, not Helm timeout).
|
||||
install:
|
||||
disableWait: true
|
||||
remediation:
|
||||
retries: 3
|
||||
upgrade:
|
||||
disableWait: true
|
||||
remediation:
|
||||
retries: 3
|
||||
@ -20,6 +20,7 @@ resources:
|
||||
- 13-bp-catalyst-platform.yaml
|
||||
- 14-crossplane-claims.yaml
|
||||
- 15-external-secrets.yaml
|
||||
- 15a-external-secrets-stores.yaml
|
||||
- 16-cnpg.yaml
|
||||
- 17-valkey.yaml
|
||||
- 18-seaweedfs.yaml
|
||||
|
||||
47
platform/external-secrets-stores/blueprint.yaml
Normal file
47
platform/external-secrets-stores/blueprint.yaml
Normal file
@ -0,0 +1,47 @@
|
||||
apiVersion: catalyst.openova.io/v1alpha1
|
||||
kind: Blueprint
|
||||
metadata:
|
||||
name: bp-external-secrets-stores
|
||||
labels:
|
||||
catalyst.openova.io/section: pts-3-3-security-and-policy
|
||||
spec:
|
||||
version: 1.0.0
|
||||
card:
|
||||
title: External Secrets — Stores
|
||||
summary: |
|
||||
Default ClusterSecretStore CR(s) wiring the bp-external-secrets
|
||||
controller to bp-openbao. Split from bp-external-secrets@1.0.0 (#331)
|
||||
to resolve CRD-ordering deadlock — the CR cannot live in the same
|
||||
Helm release as the operator that registers its CRD; Flux dependsOn
|
||||
orders the two charts so this one applies after the controller is
|
||||
Ready and CRDs are guaranteed registered.
|
||||
|
||||
Mirrors the bp-crossplane-claims pattern (PR #247).
|
||||
icon: external-secrets.svg
|
||||
category: security
|
||||
visibility: unlisted
|
||||
configSchema:
|
||||
type: object
|
||||
properties:
|
||||
clusterSecretStore:
|
||||
type: object
|
||||
properties:
|
||||
enabled:
|
||||
type: boolean
|
||||
default: true
|
||||
name:
|
||||
type: string
|
||||
default: vault-region1
|
||||
server:
|
||||
type: string
|
||||
default: "http://openbao.openbao.svc.cluster.local:8200"
|
||||
path:
|
||||
type: string
|
||||
default: secret
|
||||
version:
|
||||
type: string
|
||||
enum: [v1, v2]
|
||||
default: v2
|
||||
dependsOn:
|
||||
- bp-external-secrets
|
||||
- bp-openbao
|
||||
29
platform/external-secrets-stores/chart/Chart.yaml
Normal file
29
platform/external-secrets-stores/chart/Chart.yaml
Normal file
@ -0,0 +1,29 @@
|
||||
apiVersion: v2
|
||||
name: bp-external-secrets-stores
|
||||
version: 1.0.0
|
||||
description: |
|
||||
Catalyst-curated Blueprint chart for the default ESO ClusterSecretStore(s)
|
||||
that wire each Sovereign's bp-external-secrets controller to its bp-openbao
|
||||
backend. Split from bp-external-secrets@1.0.0 (issue #331) to resolve
|
||||
CRD-ordering deadlock: the ClusterSecretStore CR must be applied AFTER ESO's
|
||||
CRDs are registered AND the controller is Ready, which Helm's
|
||||
`before-hook-creation` delete policy can't guarantee within a single
|
||||
HelmRelease (the policy's lookup runs before the upstream chart's CRDs
|
||||
finish registration → "no matches for kind ClusterSecretStore" — see
|
||||
bp-external-secrets@1.0.0 incident on otech.omani.works 2026-04-30).
|
||||
|
||||
Mirrors the bp-crossplane / bp-crossplane-claims split shape (PR #247):
|
||||
controller chart owns the operator + CRDs, separate stores chart owns the
|
||||
CRs, Flux dependsOn orders them.
|
||||
|
||||
Keeps zero upstream subchart deps — the chart is pure Catalyst templates
|
||||
applying CRs against the upstream-registered CRDs.
|
||||
type: application
|
||||
keywords: [catalyst, blueprint, external-secrets, eso, openbao, secrets, clustersecretstore]
|
||||
maintainers:
|
||||
- name: OpenOva Catalyst
|
||||
email: catalyst@openova.io
|
||||
|
||||
annotations:
|
||||
catalyst.openova.io/no-upstream: "true"
|
||||
catalyst.openova.io/depends-on: "bp-external-secrets,bp-openbao"
|
||||
@ -50,10 +50,6 @@ apiVersion: external-secrets.io/v1beta1
|
||||
kind: ClusterSecretStore
|
||||
metadata:
|
||||
name: {{ $name | quote }}
|
||||
annotations:
|
||||
"helm.sh/hook": post-install,post-upgrade
|
||||
"helm.sh/hook-weight": "5"
|
||||
"helm.sh/hook-delete-policy": before-hook-creation
|
||||
labels:
|
||||
catalyst.openova.io/component: external-secrets
|
||||
catalyst.openova.io/secret-backend: openbao
|
||||
25
platform/external-secrets-stores/chart/values.yaml
Normal file
25
platform/external-secrets-stores/chart/values.yaml
Normal file
@ -0,0 +1,25 @@
|
||||
# Catalyst-curated values overlay for bp-external-secrets-stores.
|
||||
#
|
||||
# This chart owns the ClusterSecretStore CR(s) that the bp-external-secrets
|
||||
# controller chart can no longer ship in-line (CRD-ordering deadlock; see
|
||||
# Chart.yaml). All knobs that previously lived under
|
||||
# `clusterSecretStore:` in bp-external-secrets/values.yaml move here
|
||||
# unchanged — cluster overlays in clusters/<sovereign>/ that previously
|
||||
# overrode `clusterSecretStore.*` continue to work via the same key path,
|
||||
# they just target this chart now.
|
||||
#
|
||||
# Per docs/INVIOLABLE-PRINCIPLES.md #4 (never hardcode) every operationally
|
||||
# meaningful value flows from this file; cluster overlays may set
|
||||
# `clusterSecretStore.*` without rebuilding the Blueprint OCI artifact.
|
||||
|
||||
clusterSecretStore:
|
||||
enabled: true
|
||||
name: vault-region1
|
||||
server: "http://openbao.openbao.svc.cluster.local:8200"
|
||||
path: secret
|
||||
version: v2
|
||||
kubernetesAuth:
|
||||
mountPath: kubernetes
|
||||
role: external-secrets
|
||||
serviceAccountName: external-secrets
|
||||
serviceAccountNamespace: external-secrets-system
|
||||
@ -5,7 +5,7 @@ metadata:
|
||||
labels:
|
||||
catalyst.openova.io/section: pts-3-3-security-and-policy
|
||||
spec:
|
||||
version: 1.0.0
|
||||
version: 1.1.0
|
||||
card:
|
||||
title: External Secrets Operator
|
||||
summary: |
|
||||
|
||||
@ -1,15 +1,20 @@
|
||||
apiVersion: v2
|
||||
name: bp-external-secrets
|
||||
version: 1.0.0
|
||||
version: 1.1.0
|
||||
description: |
|
||||
Catalyst-curated Blueprint umbrella chart for External Secrets Operator
|
||||
(ESO). Depends on the upstream `external-secrets` chart as a Helm
|
||||
subchart so `helm dependency build` pulls the upstream payload into
|
||||
this artifact; the Catalyst overlay templates in templates/ (default
|
||||
ClusterSecretStore wired to bp-openbao, NetworkPolicy guard,
|
||||
ServiceMonitor toggle) sit alongside the upstream subchart and Helm
|
||||
renders both at install time. Catalyst-curated values flow into the
|
||||
upstream subchart under the `external-secrets:` key in values.yaml.
|
||||
(ESO) — controller-only as of 1.1.0. Depends on the upstream
|
||||
`external-secrets` chart as a Helm subchart so `helm dependency build`
|
||||
pulls the upstream payload into this artifact.
|
||||
|
||||
1.1.0 (issue #331): the default ClusterSecretStore CR was extracted
|
||||
into a separate chart `bp-external-secrets-stores@1.0.0`. Reason:
|
||||
Helm's `before-hook-creation` delete policy on the ClusterSecretStore
|
||||
hook ran a kubectl-style lookup of the CR before the upstream chart's
|
||||
CRDs finished registration, deadlocking the install on first
|
||||
reconcile with `no matches for kind ClusterSecretStore` (incident on
|
||||
otech.omani.works 2026-04-30). Mirrors the bp-crossplane@1.1.3 ↔
|
||||
bp-crossplane-claims@1.0.0 split shipped in PR #247.
|
||||
type: application
|
||||
keywords: [catalyst, blueprint, external-secrets, eso, openbao, secrets]
|
||||
maintainers:
|
||||
|
||||
@ -90,38 +90,9 @@ external-secrets:
|
||||
service:
|
||||
enabled: false
|
||||
|
||||
# ─── Catalyst-managed default ClusterSecretStore (templates/clustersecretstore-vault-region1.yaml) ──
|
||||
# The Catalyst-curated wrapper renders ONE default ClusterSecretStore
|
||||
# (`vault-region1`) wired to the in-cluster bp-openbao service. Cluster
|
||||
# overlays MAY:
|
||||
# - Set `clusterSecretStore.enabled: false` to disable the default and
|
||||
# author their own ClusterSecretStore CRs (e.g. multi-region with
|
||||
# explicit primary/replica).
|
||||
# - Override `clusterSecretStore.server` to point at an external OpenBao
|
||||
# FQDN when ESO is reading from a different region's primary.
|
||||
#
|
||||
# Per docs/INVIOLABLE-PRINCIPLES.md #4 ("never hardcode") all knobs are
|
||||
# runtime-configurable; cluster overlays in clusters/<sovereign>/ may
|
||||
# override without rebuilding the Blueprint OCI artifact.
|
||||
clusterSecretStore:
|
||||
# Render the default `vault-region1` ClusterSecretStore.
|
||||
enabled: true
|
||||
# ClusterSecretStore name — matches platform/external-secrets/blueprint.yaml.
|
||||
name: vault-region1
|
||||
# In-cluster OpenBao endpoint. Cluster overlays override to the external
|
||||
# FQDN (https://openbao.<location-code>.<sovereign-domain>) when ESO is
|
||||
# reading from a different region's primary.
|
||||
server: "http://openbao.openbao.svc.cluster.local:8200"
|
||||
# KV mount path inside OpenBao (default per platform/openbao/README.md).
|
||||
path: secret
|
||||
# KV engine version (v2 = versioned KV, the OpenBao default).
|
||||
version: v2
|
||||
kubernetesAuth:
|
||||
# Auth mount inside OpenBao for the Kubernetes auth method.
|
||||
mountPath: kubernetes
|
||||
# OpenBao role granted to the ESO ServiceAccount.
|
||||
role: external-secrets
|
||||
# ServiceAccount that ESO uses to authenticate against OpenBao.
|
||||
# Must match external-secrets.serviceAccount.name + targetNamespace.
|
||||
serviceAccountName: external-secrets
|
||||
serviceAccountNamespace: external-secrets-system
|
||||
# ─── ClusterSecretStore values ──────────────────────────────────────────
|
||||
# As of bp-external-secrets@1.1.0 (issue #331) the default
|
||||
# ClusterSecretStore CR moved into bp-external-secrets-stores@1.0.0 to
|
||||
# resolve a CRD-ordering deadlock. Set
|
||||
# `platform/external-secrets-stores/chart/values.yaml::clusterSecretStore.*`
|
||||
# instead — the same key path; only the chart owning the CR changed.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user