Skip to content

feat(register): expose Backend wrapper for registry (KPEP-0001 phase 2)#1

Closed
zachsmith1 wants to merge 2 commits into
masterfrom
kpep-0001/register
Closed

feat(register): expose Backend wrapper for registry (KPEP-0001 phase 2)#1
zachsmith1 wants to merge 2 commits into
masterfrom
kpep-0001/register

Conversation

@zachsmith1

Copy link
Copy Markdown
Contributor

Summary

Phase 2 of KPEP-0001 (pluggable storage backends). Adds a thin `Options` struct that implements `registry.Backend` from `kplane-dev/storage/registry` so the kplane apiserver can register Spanner against a `*registry.Backends` without the apiserver source needing to know anything Spanner-specific.

What's in the package

  • `register.go` — `Options` struct + `NewOptions()` factory. Implements `registry.Backend` (`Name / AddFlags / Validate / Build`):
    • `Name() == "spanner"` (value matched against `--storage-backend`).
    • `AddFlags` binds `--spanner-project`, `--spanner-instance`, `--spanner-database`, `--spanner-emulator-host`.
    • `Validate` requires project/instance/database, only invoked when this backend is selected.
    • `Build` reuses the existing `NewBackendFactory` so the Phase 3 cutover in the apiserver is behavior-preserving — the legacy hardcoded `if opts.SpannerProject != ""` branch and the new registry path produce identical store/broadcaster/watcher behavior.
  • `register_test.go` — unit tests covering interface satisfaction, flag binding, validation matrix, and registry roundtrip.

Two go.mod bumps

This PR pins:

  1. `k8s.io/*` fork replace directives to `v0.0.0-20260616231039-40baaf871491` — the head of kplane-dev/kubernetes#3 (the cherry-picked `DecodeCallback` relocation). Without this bump, `watcher.go`/`store.go` don't compile against any merged fork commit — `storage.WithDecodeCallback` only exists publicly on that PR branch.
  2. `github.com/kplane-dev/storage` to `v0.0.0-20260616225019-c6a9aa30bcf3` — the head of kplane-dev/storage#2 (the registry types).

Once both prerequisite PRs merge, a follow-up bumps these pins to whichever `main` SHAs end up containing them.

Merge chain

This PR is the third link:

  1. kplane-dev/kubernetes#3 — fork: move `DecodeCallback` to `storage` package.
  2. kplane-dev/storage#2 — registry types.
  3. This PR — Spanner `Register()` wrapper.
  4. TBD — `kplane-dev/apiserver` dispatch swap (the cutover).

Test plan

  • `go build ./...` clean (was previously broken at HEAD because `storage.WithDecodeCallback` wasn't on any merged fork commit).
  • `go test -run 'TestOptions|TestAddFlags|TestValidate|TestRegister' ./...` passes against the real published storage branch (no local replace directives in the committed go.mod).
  • Existing emulator-backed store tests still gated on `SPANNER_EMULATOR_HOST` — unchanged behavior.

See KPEP-0001 in kplane-dev/enhancements for the design rationale.

…y (KPEP-0001 phase 2)

Adds register.go: an Options struct that implements registry.Backend so
the kplane apiserver can register Spanner against a *registry.Backends in
its Phase 3 dispatch swap, without the apiserver source needing to know
anything Spanner-specific.

The wrapper is thin: NewOptions() returns an Options whose Build() calls
the existing NewBackendFactory. Identical store/broadcaster/watcher
behavior to the legacy 'if opts.SpannerProject != ""' branch in the
apiserver, so the Phase 3 cutover is behavior-preserving.

Bumps go.mod fork pin to the cherry-pick branch
(kplane-dev/kubernetes#3) so 'storage.WithDecodeCallback' resolves at the
storage package — that's the symbol watcher.go/store.go have been
calling since they were written, but no merged fork commit exposed it
publicly until the cherry-pick.

Also adds the github.com/kplane-dev/storage require (registry/ subpackage)
pinned to the kpep-0001/add-registry branch head. Once both
prerequisite PRs merge, a follow-up bumps these pins to whichever main
SHAs end up containing them.

Tested:
- go build ./... clean (was previously broken at HEAD).
- go test -run 'TestOptions|TestAddFlags|TestValidate|TestRegister'
  ./... passes against the published storage branch.
- Existing emulator-backed store tests still gated on
  SPANNER_EMULATOR_HOST.

See KPEP-0001 in kplane-dev/enhancements for the design rationale, and
the chain:
  - kplane-dev/kubernetes#3  (fork: move DecodeCallback to storage pkg)
  - kplane-dev/storage#2     (registry types)
  - this PR                  (Spanner Register wrapper)
  - kplane-dev/apiserver#?   (TBD: dispatch swap)
…-0001 head

Aligns with the consolidated KPEP-0001 fork branch. Both prerequisite
features (DecodeCallback move + per-cluster allocators) live there; the
former is what unblocks store.go/watcher.go from using
storage.WithDecodeCallback. Apiserver Phase 3 will pin the same fork
SHA.
zachsmith1 added a commit to kplane-dev/storage that referenced this pull request Jun 17, 2026
…P-0001)

Brings the Spanner backend into kplane-dev/storage as the first in-tree
implementation, matching the KPEP-0001 end-state layout:

  kplane-dev/storage/
    registry/                     (added in previous commits)
    decorator.go                  BackendFactory = registry.Factory alias
    backends/
      register.go                 RegisterBuiltin(b) aggregator
      spanner/
        broadcast.go, config.go,
        factory.go, register.go,
        store.go, watcher.go,
        store_test.go, register_test.go

What this collapses:

- Drops the standalone kplane-dev/spanner repo entirely. It existed only
  because BackendFactory needed to be declared somewhere without
  importing kplane-dev/storage (the 'avoid an import cycle' comment in
  the old factory.go). Now that Spanner is a subpackage of
  kplane-dev/storage, it references storage.BackendFactory directly.

- BackendFactory is now a type alias to registry.Factory, so the
  apiserver can pass registry.Backend.Build()'s return value into
  DecoratorConfig without a conversion.

- The aggregator (backends/register.go) is one import + one Register()
  call per backend. Adding postgres or kine in the future means editing
  one file here, not the apiserver.

Tested:
- go test ./registry/... ./backends/... clean.
- Spanner emulator-backed tests pass.
- decorator.go alias compiles cleanly; the BackendFactory hook path in
  StorageWithClusterIdentity is unchanged.

Follow-up: archive kplane-dev/spanner (or leave as a one-release re-export
shim). kplane-dev/spanner#1 will be closed since its work is now here.

See KPEP-0001 in kplane-dev/enhancements for the design.
@zachsmith1

Copy link
Copy Markdown
Contributor Author

Closing. KPEP-0001 collapses kplane-dev/spanner into kplane-dev/storage/backends/spanner/ — see kplane-dev/storage#2 for the migrated source. The standalone repo's BackendFactory duplication ('to avoid an import cycle') goes away when Spanner lives as a subpackage of storage.

@zachsmith1 zachsmith1 closed this Jun 17, 2026
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