Skip to content

test(controller): both Reconcile loops are untested — no envtest harness #202

Description

@BryanFRD

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 conditionsReady/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:

  1. Happy path — CR created, Secret materialises with the expected keys
  2. Drift — Secret mutated out-of-band, reconcile restores it
  3. Upstream error — API unreachable, status reflects it and the item is requeued rather than dropped
  4. Deletion — CR removed, managed Secret handled per the intended policy
  5. 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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions