Skip to content

feat(secret): adopt first-class secret base types for K8S::Core::Secret - #66

Merged
JeroenSoeters merged 3 commits into
mainfrom
secret-base-type-adoption
Aug 8, 2026
Merged

feat(secret): adopt first-class secret base types for K8S::Core::Secret#66
JeroenSoeters merged 3 commits into
mainfrom
secret-base-type-adoption

Conversation

@JeroenSoeters

Copy link
Copy Markdown
Contributor

What

Adopts the formae first-class secret base types for K8S::Core::Secret, so a Secret's value can be sourced as a formae secret — resolved live at the plugin-call boundary — instead of only its .name metadata. A Secret is map-shaped, so its value is referenced by key:

password = mySecret.res.secretValue.at("admin-password")

Changes

  • Schema (schema/pkl-main/core/Secret.pkl): SecretResolvable extends formae.MapSecretResolvable (value property decodedData); Secret extends formae.Secret. A new write-only decodedData field typed (Mapping<String,String> | formae.SecretValue) marks the value opaque, so the agent hashes it at rest and excludes it from drift detection. Regenerated the per-version schema trees. Bumps the schema dependency and minFormaeVersion to 0.89.0.
  • Go Read-enrichment (pkg/resources/core/secret.go): Read (and Create/Update/Status live state) attach the base64-decoded payload as a read-only decodedData map. It is kept separate from data — which round-trips as base64 — so decoding never causes perpetual drift. client-go returns Secret.Data already decoded, so no second decode.
  • Examples: lgtm-observability/*.pkl now source the Grafana target's admin password from the managed lgtm-grafana-admin Secret via secret.res.secretValue.at("admin-password"), instead of requiring a GRAFANA_AUTH env var at agent start.

Testing

  • Unit test for the decode enrichment; assertions added to the Secret CRUD integration lifecycle (run against a live cluster). The integration harness gains a KUBE_CONTEXT override.
  • A cross-plugin end-to-end test (in the formae repo) proves the headline: a native Kubernetes Secret supplies a Grafana target's basic-auth credentials via .at(), resolved live with no GRAFANA_AUTH in the agent's environment — the Grafana Folder is created, the Secret's decoded value is hashed at rest, and destroy cleans up. Verified live against a kind cluster + Grafana.

Requires / notes

  • formae >= 0.89.0 — the secret base types (formae.MapSecretResolvable, formae.Secret) and the resolution engine live there; minFormaeVersion is bumped accordingly. Merge/publish is gated on the 0.89.0 release.
  • The Grafana target username/password support (formae-plugin-grafana) is required for the lgtm example's credential sourcing.
  • The lgtm example also needs fix(examples): set pod template labels on lgtm workloads #65 (pod template labels) to apply end-to-end.

Extend K8S::Core::Secret to the first-class secret base types so its value
can be sourced as a formae secret. SecretResolvable now extends
formae.MapSecretResolvable (value property "decodedData"); consumers
reference a key with secret.res.secretValue.at("key"). The new write-only
decodedData field is typed with formae.SecretValue so the agent hashes it at
rest and excludes it from drift detection.

Bump the schema dependency and minFormaeVersion to 0.89.0 and regenerate the
per-version schema trees.
Attach the decoded secret data as a read-only decodedData map on the live
state (Create/Read/Update/Status) so secret.res.secretValue.at("key")
resolves. client-go returns Secret.Data already base64-decoded, and the field
is kept separate from data (which round-trips as base64) to avoid perpetual
drift.

Add a unit test for the decode enrichment and assert it in the Secret CRUD
integration lifecycle. The integration harness gains a KUBE_CONTEXT override so
it can run against any local cluster.
The lgtm-observability examples now source the Grafana Target's basic-auth
password live from the managed lgtm-grafana-admin Secret via
secret.res.secretValue.at("admin-password"), instead of requiring a
GRAFANA_AUTH env var at agent start. lgtm.allResources exposes the admin Secret
as grafanaAdminSecret (only its .res resolvable, so no duplicate resource is
created). Bump the examples' formae schema dependency to 0.89.0 for the
map-secret base types.
@JeroenSoeters
JeroenSoeters merged commit 2097645 into main Aug 8, 2026
10 of 56 checks passed
@JeroenSoeters
JeroenSoeters deleted the secret-base-type-adoption branch August 10, 2026 02:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant