The operator's supporting logic is well tested — but the two Reconcile loops, which are the part that actually writes Kubernetes Secrets, have no tests at all.
Current state
Tested (and tested properly — these are good tests):
| File |
Coverage |
internal/controller/token_broker_test.go |
8 tests: token-secret ref, whitespace handling, OIDC happy path, cache, refresh-before-expiry, exchange error, both-auth-modes rejection |
internal/controller/transforms_test.go |
8 tests: prefix, suffix, rename, rename collision, base64 decode selected/all |
internal/controller/metrics_test.go |
collectors, reconcile observation, sync errors, readiness |
internal/ferrvault/client_test.go |
API client |
api/ferrvault/v1alpha1/ferrvaultconnection_types_test.go |
type validation |
Untested:
| Lines |
File |
| 221 |
internal/controller/ferrvaultsecret_controller.go |
| 208 |
internal/controller/ferrvaultconnection_controller.go |
| 133 |
internal/controller/ferrvaultsecret_sync.go |
There is no suite_test.go and no envtest harness — the Makefile notes it was deliberately deferred ("We'll add codegen, envtest, ...").
Why the reconcilers specifically
The tested pieces are pure functions with easy seams, which is exactly why they got tested. The reconcilers hold the behaviour that is hard to reason about and expensive to get wrong:
- Drift correction — a Secret edited by hand in the cluster should be restored on the next reconcile
- Requeue and backoff — an unreachable FerrVault API should back off, not hot-loop against the cluster or the SaaS
- Status conditions —
Ready/Synced must reflect reality, since that is what operators and dashboards act on
- Deletion — what happens to the managed Secret when the
FerrVaultSecret is deleted, and whether a finalizer is honoured
- Partial failure — one key failing to resolve should not silently write a half-populated Secret
Each of those is a way to leak, drop or stale-serve a secret in a customer's cluster, and none of them is currently guarded.
Suggested scope
Add the standard kubebuilder envtest harness (suite_test.go + setup-envtest wired into the existing test: target) and cover, per controller:
- Happy path — CR created, Secret materialises with the expected keys
- Drift — Secret mutated out-of-band, reconcile restores it
- Upstream error — API unreachable, status reflects it and the item is requeued rather than dropped
- Deletion — CR removed, managed Secret handled per the intended policy
- Transform integration — confirm the already-tested transforms are actually applied through the sync path
This does not need to reach the polish level of the existing unit tests to be worth a lot; the first two cases alone cover most of what would break in production.
Acceptance
make test runs an envtest suite covering both reconcilers
- Removing the drift-correction branch from the controller makes a test fail
The operator's supporting logic is well tested — but the two Reconcile loops, which are the part that actually writes Kubernetes Secrets, have no tests at all.
Current state
Tested (and tested properly — these are good tests):
internal/controller/token_broker_test.gointernal/controller/transforms_test.gointernal/controller/metrics_test.gointernal/ferrvault/client_test.goapi/ferrvault/v1alpha1/ferrvaultconnection_types_test.goUntested:
internal/controller/ferrvaultsecret_controller.gointernal/controller/ferrvaultconnection_controller.gointernal/controller/ferrvaultsecret_sync.goThere is no
suite_test.goand no envtest harness — the Makefile notes it was deliberately deferred ("We'll add codegen, envtest, ...").Why the reconcilers specifically
The tested pieces are pure functions with easy seams, which is exactly why they got tested. The reconcilers hold the behaviour that is hard to reason about and expensive to get wrong:
Ready/Syncedmust reflect reality, since that is what operators and dashboards act onFerrVaultSecretis deleted, and whether a finalizer is honouredEach of those is a way to leak, drop or stale-serve a secret in a customer's cluster, and none of them is currently guarded.
Suggested scope
Add the standard kubebuilder envtest harness (
suite_test.go+setup-envtestwired into the existingtest:target) and cover, per controller:This does not need to reach the polish level of the existing unit tests to be worth a lot; the first two cases alone cover most of what would break in production.
Acceptance
make testruns an envtest suite covering both reconcilers