fix(hermes): give the source override the shape External Secrets 2.12.0 accepts #399
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/eso-source-ref"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What was wrong
Both instances of the agent carry an ExternalSecret that renders their
.env: most values come from Vault, one entry reads the generated key of the API server back through the store of the namespace, and that override was written flat:The API server refuses the object, and with it the whole rollout of the instances:
spec.data[].sourceRefis aStoreSourceRef: it takes exactly one ofstoreRefandgeneratorRef, and the kind and the name live insidestoreRef. Written flat the object carries two properties the schema does not declare, so theenvKustomization of both namespaces stays NotReady,hermeswaits on it, and the merged work of #397 and #398 does not reach the cluster at all — the file manager that now runs in the pod of the agent is waiting for the same chain.What this fixes
kubernetes/apps/{grachevko,grachevaeu}/hermes/env/app/externalsecret-managed-env.yaml— the single-entry override takes the shape of the deployed version:with the rule written next to it, because the flat form is the one that reads as correct.
Verified
security/external-secrets):SourceRef *StoreSourceRef, andStoreSourceRef{ SecretStoreRefjson:"storeRef"; *GeneratorRefjson:"generatorRef"}with+kubebuilder:validation:MaxProperties=1/MinProperties=1(apis/externalsecrets/v1/externalsecret_types.go).spec.data[].sourceRefdeclaresproperties: [storeRef, generatorRef],maxProperties: 1,minProperties: 1;storeRefdeclareskind(SecretStore or ClusterSecretStore, default SecretStore) andname. The old shape fails the check on both counts, the new shape passes.flate test all— the two failures it reports are the unreachablenetwork/k8s-gatewaychart source (codeberg answers 503), untouched by this change.dataFrom[].sourceRef.generatorRefin alexandrie, tg-ws-proxy, forgejo and pocket-id.After the merge
Both chains resume by themselves (the
envKustomization stops failing the dry run); to pull the revision in without waiting for the source poll:flux reconcile source git flux-system, thenflux reconcile kustomization env -n grachevkoand-n grachevaeu.Rollback
Reverting returns the object to the shape the API server rejects: both namespaces stay blocked exactly as they are now. The state before the merge is the broken one, so there is nothing to roll back to — the way out is forward, or by removing the single-entry override entirely (the API key then has to arrive another way).
Both instances carry an ExternalSecret whose single entry reads the generated key of the API server back through the store of this namespace. The override of the source was written as `sourceRef.kind` plus `sourceRef.name`, and the API server refuses that object: ExternalSecret/grachevko/hermes-managed-env dry-run failed: failed to create typed patch object (external-secrets.io/v1, Kind=ExternalSecret): .spec.data[0].sourceRef.kind: field not declared in schema The field is not declared because `spec.data[].sourceRef` is a StoreSourceRef: it takes exactly one of `storeRef` and `generatorRef`, and the kind and the name live inside `storeRef` (the CRD of the deployed version says maxProperties: 1, minProperties: 1, properties: [storeRef, generatorRef]; the type is StoreSourceRef in apis/externalsecrets/v1/externalsecret_types.go of v2.12.0). Written flat, the object carries two undeclared properties, the Kustomization that renders it never becomes Ready, and the chain behind it - `env`, then `hermes` in both namespaces - does not start: the merged rollout of the instances is blocked entirely, and the file manager that now runs in the pod of the agent waits for the same chain. Neither check of the pull request pipeline covers this class: `flate test all` reports the object as fine, and the `Flux Local` render passes too, because neither validates custom resources against the CRD schemas of the versions we deploy. Two issues are open for that gap (the schema check and the admission-rule check); this commit only makes the object acceptable. Verified against the primary sources of the deployed version: the Go types of v2.12.0 (`SourceRef *StoreSourceRef`, StoreSourceRef{storeRef, generatorRef}, kubebuilder MaxProperties=1) and the CRD schema of v2.12.0 taken from the chart's bundle - `spec.data[].sourceRef` declares [storeRef, generatorRef] with maxProperties 1, so the old shape fails on the undeclared `kind` and on the count, while the new shape passes. The same shape is already in use in this repository, in `dataFrom[].sourceRef.generatorRef` of alexandrie, tg-ws-proxy, forgejo and pocket-id. After the merge: the two namespaces' `secrets -> env -> hermes` chains resume on their own (the `env` Kustomization stops failing on the dry run). To pull it in without waiting for the source poll: `flux reconcile source git flux-system` followed by `flux reconcile kustomization env -n grachevko` (and the same for grachevaeu).Failed to update PR description
PR Reviewer Guide 🔍
Here are some key observations to aid the review process:
PR Code Suggestions ✨
No code suggestions found for the PR.
77a3a3067857792fc93fThe explanation of `spec.data[].sourceRef` and of the flat form the API server refuses was copied verbatim into both instances. In this pair a fact is written once, in the same file of the neighbouring instance, and the other file points at it: the header of the grachevko manifest already does exactly that for the rest of the mechanism, so the long form stays in grachevaeu and the grachevko copy is a two-line pointer. Nothing else changes: the nesting of the override is `sourceRef: { storeRef: { kind, name } }` in both files. The review of the previous revision read `storeRef` as a sibling of `sourceRef` from the diff, which does not reproduce: the rendered object of the Kustomization carries nothing beside `sourceRef` in the entry, and the two `kind`/`name` columns sit two levels deeper.The two
Possible Bugfindings of the last review do not reproduceBoth read the added
storeRefas a sibling ofsourceRef. In the file the columns aresourceRef(6 spaces) ->storeRef(8) ->kind/name(10), and the object this Kustomization renders carries nothing besidesourceRefin the entry:That render is what Flux sends to the API server, and it is exactly the shape the schema declares (
spec.data[].sourceRef=StoreSourceRef,maxProperties: 1, properties[storeRef, generatorRef]). The flat reading comes from the diff context, not from the file - the same class as the ConfigMap nesting finding in #398.The third finding is right and is fixed in
b7c77b4The explanation was copied verbatim into both instances, which the rule of this repository forbids: a fact is stated once, where it is not obvious from the code. The long form stays in
grachevaeuand thegrachevkocopy is a two-line pointer - the header of that file already does this for the rest of the mechanism.