RPF-WP-0044-T06: ESO adoption prep, readiness receipts and founder runbook
Source gate passes; predecessor proofs stale/missing smoke; live diff and store baseline blocked on agent cluster read access after CUST-WP-0073. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 527080@bnt-lap001 Assistant-Session: 5a0e864a-67be-4605-a77a-16635f7dd292
This commit is contained in:
parent
8761da9027
commit
fd2f808cd8
4 changed files with 164 additions and 1 deletions
93
docs/runbooks/rpf-wp-0044-t06-eso-adoption.md
Normal file
93
docs/runbooks/rpf-wp-0044-t06-eso-adoption.md
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
# RPF-WP-0044-T06 — adopt external-secrets into Argo (founder runbook)
|
||||
|
||||
Authority: D2 (`89f1058f-33bc-47a8-8a49-0b44d426c67e`). No further founder approval is needed.
|
||||
Highest-risk adoption: ESO serves every ExternalSecret on railiance01. Prep receipt:
|
||||
`docs/evidence/2026-10-21-eso-adoption-prep/prep-receipt.json`.
|
||||
|
||||
## State at preparation (2026-10-21, agent, offline only)
|
||||
|
||||
- Draft `argocd/railiance01/drafts/external-secrets.application.yaml`: chart `0.16.1`,
|
||||
`ServerSideApply=true`, no `automated`, no finalizer, no Force/Replace, and CRD values
|
||||
`crds.annotations: argocd.argoproj.io/sync-options: Prune=false,Delete=false`. The readiness gate
|
||||
passes the source check.
|
||||
- Offline render (render sha256 `55236645…f136f`): 39 objects, made up of 20 CRDs (all 20
|
||||
prune/delete protected), 3 Deployments, 3 ServiceAccounts, 5 ClusterRoles, 2 ClusterRoleBindings,
|
||||
1 Role, 1 RoleBinding, 1 Service, 2 ValidatingWebhookConfigurations and the empty webhook-cert
|
||||
holder (metadata only). **No ClusterSecretStore or ExternalSecret is rendered**, so adoption cannot
|
||||
delete or replace a store. The webhooks declare no `caBundle`, so server-side apply does not take
|
||||
it from the cert-controller. `ignoreDifferences` is added only if the diff below shows drift.
|
||||
- **Not done by the agent:** the fresh live diff, the store baseline and the fresh predecessor proofs.
|
||||
Since the CUST-WP-0073 cutover (2026-10-20) the agent's `ssh railiance01` login (`tegwick`) cannot
|
||||
read the k3s kubeconfig, and the custodian-agent observer role has no CRD, RBAC, webhook or ESO read.
|
||||
Run every `ssh railiance01 "kubectl …"` below through a login that still has cluster-admin read.
|
||||
|
||||
## 1. Pre-check (founder, or agent once read access exists)
|
||||
|
||||
```bash
|
||||
cd ~/railiance-platform && git pull --ff-only
|
||||
D=docs/evidence/2026-10-21-eso-adoption-prep
|
||||
# a) fresh predecessor proofs (gate window is 300 s, so run all three back to back)
|
||||
( cd ~/rapp-issue-core && make -s verify-live VERIFY_ARGS="--expected-revision 186c817b67d3919a64acdddbd3889e539841f946 --expected-source-url ssh://git@forgejo.coulomb.social:30022/coulomb/rapp-issue-core.git --smoke" ) > $D/issue-core-proof.json
|
||||
python3 scripts/workload_adoption_proof.py --live --source-root ~/target-revenue --observation $D/target-revenue-observation.json --receipt $D/target-revenue-proof.json
|
||||
python3 scripts/eso_adoption_readiness.py --draft argocd/railiance01/drafts/external-secrets.application.yaml --issue-core-proof $D/issue-core-proof.json --target-revenue-proof $D/target-revenue-proof.json | tee $D/readiness-r2.json
|
||||
# must print "ready_for_fresh_native_render_diff": true
|
||||
# b) fresh render + client-side diff (T05 method); credential data in diff output is masked by kubectl
|
||||
python3 -c "import yaml;print(yaml.safe_load(open('argocd/railiance01/drafts/external-secrets.application.yaml'))['spec']['source']['helm']['values'])" > /tmp/eso-values.yaml
|
||||
helm template external-secrets external-secrets --repo https://charts.external-secrets.io --version 0.16.1 -n external-secrets -f /tmp/eso-values.yaml > /tmp/eso-render.yaml
|
||||
ssh railiance01 "kubectl diff -f -" < /tmp/eso-render.yaml > $D/client-diff.txt; echo rc=$?
|
||||
# c) store baseline
|
||||
ssh railiance01 "kubectl get clustersecretstores -o custom-columns=NAME:.metadata.name,STATUS:.status.conditions[0].reason --no-headers" | tee $D/store-baseline-before.txt
|
||||
```
|
||||
|
||||
Go only if all of these hold:
|
||||
- the readiness gate is true;
|
||||
- the diff touches CRDs in metadata only (the protective annotation) and changes no CRD `spec`;
|
||||
- nothing is deleted or replaced;
|
||||
- the baseline shows every store `Valid` except `openbao-activity-core` and `openbao-email-connect` (`ValidationFailed`).
|
||||
|
||||
If the diff shows webhook `caBundle` drift, an agent adds `ignoreDifferences` for
|
||||
`ValidatingWebhookConfiguration` `/webhooks/0/clientConfig/caBundle` and `/webhooks/1/clientConfig/caBundle` and re-runs b.
|
||||
|
||||
## 2. Create the Application (an agent, after the gate is green)
|
||||
|
||||
The agent moves the draft to `argocd/railiance01/applications/external-secrets.application.yaml`,
|
||||
commits and pushes, runs `make argocd-pin-drift`, then creates the child only with
|
||||
`ssh railiance01 "kubectl apply --dry-run=server -f -" < <file>` followed by the same command without `--dry-run`.
|
||||
The root also carries other OutOfSync children. Creating the Application syncs nothing.
|
||||
|
||||
## 3. The founder's sync command (one command)
|
||||
|
||||
```bash
|
||||
ssh railiance01 "kubectl -n argocd patch application external-secrets --type merge -p '{\"operation\":{\"initiatedBy\":{\"username\":\"rpf-wp-0044-t06\"},\"sync\":{\"revision\":\"0.16.1\",\"prune\":false,\"syncOptions\":[\"ServerSideApply=true\"],\"syncStrategy\":{\"apply\":{\"force\":false}}}}}'"
|
||||
```
|
||||
|
||||
(Local double quotes; the remote shell receives the JSON inside single quotes. Prune off, force off, SSA.)
|
||||
|
||||
## 4. Post-sync checks
|
||||
|
||||
```bash
|
||||
ssh railiance01 "kubectl -n argocd get application external-secrets -o custom-columns=SYNC:.status.sync.status,HEALTH:.status.health.status,PHASE:.status.operationState.phase,REV:.status.sync.revision"
|
||||
# expect Synced Healthy Succeeded 0.16.1
|
||||
ssh railiance01 "kubectl -n external-secrets get deploy" # 3/3 available, no restarts beyond rollout
|
||||
ssh railiance01 "kubectl get crd -o name | grep -c external-secrets.io" # still 20
|
||||
ssh railiance01 "kubectl get clustersecretstores -o custom-columns=NAME:.metadata.name,STATUS:.status.conditions[0].reason --no-headers" > $D/store-baseline-after.txt
|
||||
diff $D/store-baseline-before.txt $D/store-baseline-after.txt && echo baseline-unchanged
|
||||
# ExternalSecret refresh sample (issue-core): force a refresh and confirm Ready
|
||||
ssh railiance01 "kubectl -n issue-core annotate externalsecret issue-core-runtime force-sync=\$(date +%s) --overwrite && sleep 20 && kubectl -n issue-core get externalsecret issue-core-runtime -o custom-columns=READY:.status.conditions[0].status,REASON:.status.conditions[0].reason"
|
||||
# expect True SecretSynced
|
||||
```
|
||||
|
||||
The agent records these as `docs/evidence/<date>-eso-argocd-adoption.json`, re-runs issue-core
|
||||
`verify-live`, and marks T06 done after the proving period.
|
||||
|
||||
## Rollback (abort owner: railiance-platform)
|
||||
|
||||
Never prune and never delete the Application with cascade. Revert the Application to the previously
|
||||
reviewed chart `0.16.1` values in Git (`git revert <adoption commit>`), re-apply the child, then
|
||||
run the same sync command as above. To stop Argo management without touching workloads, delete only
|
||||
the Application object. It has no finalizer, so no cascade happens, and the CRDs are protected anyway.
|
||||
|
||||
## Separate later step (not part of adoption)
|
||||
|
||||
Retire the stale `pending-upgrade` Helm release record (`sh.helm.release.v1.external-secrets.v*`)
|
||||
under its own reviewed cleanup. ArgoCD does not track it, and it must not be replaced silently.
|
||||
Loading…
Add table
Add a link
Reference in a new issue