Skip to content

feat(configread): local ConfigReadService for config-server cache backend - #476

Open
steiler wants to merge 9 commits into
sensitivefrom
config-server-cache-backend
Open

feat(configread): local ConfigReadService for config-server cache backend#476
steiler wants to merge 9 commits into
sensitivefrom
config-server-cache-backend

Conversation

@steiler

@steiler steiler commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds a config_read.ConfigReadService gRPC server (pkg/sdc/configread) exposing last-applied config reads (Get/List) backed by TargetSnapshot, threaded through the controller's KeyRing.
  • This is the config-server-side counterpart consumed by data-server's new config-server-backed cache.Client (see paired PR below), which calls this service instead of talking to the local/dragonfly cache directly.
  • Pins github.com/sdcio/sdc-protos to the pushed config-server-cache-backend commit (a8f3da0) instead of a local path replace, so CI can resolve the module.

Pairs-with: sdcio/data-server#471
Pairs-with: sdcio/integration-tests#113

Test plan

  • go build ./...
  • go test ./...
  • golangci-lint run ./... (no new issues introduced by this branch)
  • Integration tests currently don't exercise this path end-to-end — no Robot scenario configures data-server's Cache.Type: config-server yet. Follow-up needed in sdcio/integration-tests.

Note on integration-tests dependency

integration-tests's data-server-controller StatefulSet was already hanging in ContainerCreating on every sensitive-based run since commit 83d07f8 ("added ENV keyring and removed keyring secret") — that commit moved config-server's config-keyring Secret sample into artifacts/in/, which kform excludes from the generated deploy manifest, so the Secret volume the StatefulSet mounts can never be satisfied. This is pre-existing on sensitive (see #441) and unrelated to this PR's changes, but it blocks integration-tests here too. The Pairs-with: sdcio/integration-tests#113 line above pulls in a fix that provisions a CI-only placeholder Secret directly in integration-tests' deploy flow (the correct place, since config-server intentionally stopped shipping a default key to force real deployments to bring their own).

Made with Cursor

steiler and others added 7 commits August 12, 2026 10:19
Implements ticket 07 of the config-server-cache-backend effort: a unary,
localhost-bound gRPC server (pkg/sdc/configread) that serves Get-by-name/
List-by-target reads over Config joined with SensitiveConfig, backed
entirely by the colocated controller's existing watch-synced informer
cache (mgr.GetClient()) — no new watch, store, or trust boundary. Wired
into cmd/controller/main.go as a manager.Runnable alongside the other
runnables.

Exports targetmanager.ParseSensitivePaths (was private) so the new server
reuses the existing keyless-XPath parsing instead of duplicating it.

Pins github.com/sdcio/sdc-protos to the sibling ../sdc-protos checkout via
a temporary go.mod replace, mirroring data-server's existing pin, since
ticket 01's config_read package isn't tagged upstream yet.

Co-authored-by: Cursor <cursoragent@cursor.com>
configread.Server will need to decrypt TargetSnapshot entries in
upcoming tickets; NewServer now requires a KeyRing and errors out
immediately if one isn't provided, instead of letting a misconfigured
server start and fail lazily on the first Get/List call.

Co-authored-by: Cursor <cursoragent@cursor.com>
…sitiveConfigSpec

Adds the shared mapping function Get/List will use to serve TargetSnapshot-backed
last-applied config instead of live Config/SensitiveConfig, with unit tests
covering the sensitive-path round trip and the decrypt/unmarshal failure modes.

Co-authored-by: Cursor <cursoragent@cursor.com>
Get now serves the last-applied value from TargetSnapshot.Spec.Configs
instead of joining live Config + SensitiveConfig, closing the
live-vs-applied conflation that caused data-server's diff to silently
drop updates and deletions. Deletes the now-dead belongsToTarget guard:
looking the TargetSnapshot up by {target namespace, target name} makes
the lookup key the target's identity, so there's nothing left to
re-check.

Co-authored-by: Cursor <cursoragent@cursor.com>
…read

List now serves every last-applied intent for a target straight from its
TargetSnapshot.Spec.Configs instead of label-matching over live Config +
joined SensitiveConfig, closing the last live-vs-applied read path in
configread. A missing TargetSnapshot returns an empty list (parity with
Cache.Type: local for a target that's never transacted); a decrypt/
unmarshal failure on any one entry fails the whole call with Internal
rather than silently omitting it. Deletes the now-dead toConfigEntry,
getSensitiveConfig, and isOrphan helpers.

Co-authored-by: Cursor <cursoragent@cursor.com>
CI can't resolve `replace github.com/sdcio/sdc-protos => ../sdc-protos`
since no sibling checkout exists on the runner. sdcio/sdc-protos@a8f3da0
(config-server-cache-backend) is now pushed, so pin go.mod to it via a
real pseudo-version instead of the placeholder one and the local path
replace.

Also fix two errcheck findings on unchecked Close() calls, uncovered
now that lint can actually resolve the module.

Co-authored-by: Cursor <cursoragent@cursor.com>
Rebasing onto sensitive picked up the ENV-based keyring rework, which
dropped keyring.NewFromSecret in favor of NewFromFile/NewFromBytes.
Update the test helper accordingly; it no longer needs a fake Secret
wrapper.

Co-authored-by: Cursor <cursoragent@cursor.com>
@steiler
steiler force-pushed the config-server-cache-backend branch from cd42f6b to cf9aeed Compare August 12, 2026 08:24
steiler and others added 2 commits August 12, 2026 10:30
Pre-existing errcheck failure on the sensitive branch itself (Go
Checks has been red there since the ENV-keyring rework landed);
fixing it here so this branch's own CI is green.

Co-authored-by: Cursor <cursoragent@cursor.com>
…a-server-controller StatefulSet

The co-located controller+data-server StatefulSet template
(statefulset-data-server.yaml, used whenever LOCAL_DATASERVER=true —
e.g. integration-tests) only mounted the config-keyring Secret into
the data-server container. The controller container never got it,
so keyring.Load() in cmd/controller/main.go always saw "no keyring
mounted" there, even when the Secret exists and is correctly mounted
into the sibling container.

This silently broke any keyring-requiring reconciler in this topology
(targetconfig's SetupWithManager unconditionally calls
RequireKeyRing, and ENABLE_TARGETCONFIG=true is set here) well before
this PR — main.go now also fails fast constructing the config-read
server, surfacing it as a controller crash loop
("cannot construct config-read server: KeyRing is nil").

The standalone controller Deployment (deployment-controller.yaml)
already mounts the keyring correctly into its controller container;
this mirrors that.

Co-authored-by: Cursor <cursoragent@cursor.com>
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