fix(remote-config): strip server-managed metadata fields from generated YAML - #832
Merged
souravbiswassanto merged 11 commits intoAug 7, 2026
Merged
Conversation
…ed YAML kubectl apply fails with a resource version conflict when the generated config YAML retains resourceVersion, uid, creationTimestamp, and generation fetched from the source cluster. These fields are server-assigned and must not be present in manifests applied to a different cluster. Also remove Labels from the TLS Secret: the cert-manager ownership label (controller.cert-manager.io/fao) must not be propagated to the remote cluster where cert-manager would incorrectly take ownership of the secret. Signed-off-by: souravbiswassanto <saurov@appscode.com>
…e corruption When kubectl apply was previously run with a YAML that contained resourceVersion (from the source cluster), the kubectl.kubernetes.io/ last-applied-configuration annotation stored it. On re-apply with a clean YAML (no resourceVersion), the 3-way merge treats the missing field as 'user wants to delete it' and patches metadata.resourceVersion to empty string, which the API server rejects as invalid value 0. Fix by constructing a minimal AppBinding containing only the connection fields needed by the remote replica, rather than mutating the AppBinding fetched from the source cluster. This keeps the last-applied annotation minimal and idempotent across re-runs, and avoids carrying over source-cluster labels, annotations, appRef, and Stash parameters that are irrelevant on the remote side. Signed-off-by: souravbiswassanto <saurov@appscode.com>
…from scratch Building the AppBinding from scratch drops fields that exist in the source AppBinding spec (appRef, parameters, secretTransforms, and any future additions). Using DeepCopy + clean ObjectMeta is safer: the full spec is preserved while server-managed metadata is discarded. Signed-off-by: souravbiswassanto <saurov@appscode.com>
…ore dereference ClientConfig.Service (*ServiceReference) and Secret (*TypedLocalObjectReference) are optional pointer fields. If the source AppBinding uses clientConfig.url instead of clientConfig.service, or has no secret set, the DeepCopy would carry nil pointers and the subsequent .Name assignments would panic. Signed-off-by: souravbiswassanto <saurov@appscode.com>
Signed-off-by: souravbiswassanto <saurov@appscode.com>
…t name If --auth-secret is provided, the generated auth Secret and the AppBinding's secret reference both use that name. If omitted, the default <dbname>-remote-replica-auth is used as before. Signed-off-by: souravbiswassanto <saurov@appscode.com>
-s is reserved by k8s.io/cli-runtime for --server (the Kubernetes API server address) and is registered as a root persistent flag inherited by all subcommands. Using the same shorthand causes a panic in cobra's mergePersistentFlags. Use the long form --auth-secret only. Signed-off-by: souravbiswassanto <saurov@appscode.com>
generateAuthSecret declared `var buffer []byte` at the top of the function and then redeclared it with `:=` after marshalling the secret, which fails to compile: pkg/remote_replica/postgres.go:261:9: no new variables on left side of := The leading declaration is dead — buffer is not referenced before the `make` call — so remove it and keep the sized allocation. Signed-off-by: Tamal Saha <tamal@appscode.com>
--port (default 5432, also accepted as -d host:port; an explicit --port wins) is written into the generated AppBinding's spec.clientConfig.service.port. Sources behind a load balancer are commonly exposed on non-standard frontend ports; the operator injects this as PRIMARY_PORT into the remote replica containers. --replica-name, when set, appends a ready-to-apply remote replica Postgres manifest to the generated config, sized from the source spec: version, replicas, storage, storageType, standby mode and the postgres container's resources are copied; remoteReplica.sourceRef, the generated auth secret and a disabled write check are added. spec.tls, monitoring, archiver and custom sidecars are deliberately not carried over (the remote cluster has its own issuer), clientAuthMode falls back from cert to md5 for the same reason, and deletionPolicy is forced to Halt so a DR replica's PVCs survive accidental CR deletion. The result is a starting point; a secondary site is often sized differently on purpose. Verified end to end: one command against a live TLS source exposed on port 5434, one kubectl apply on the remote cluster creating secrets, AppBinding and Postgres CR; the replica reached Ready streaming over port 5434 with the copied resources in place. Signed-off-by: Tamal Saha <tamal@appscode.com>
tamalsaha
force-pushed
the
fix/remote-config-strip-server-managed-fields
branch
from
August 7, 2026 12:57
f8e7601 to
13c6173
Compare
souravbiswassanto
force-pushed
the
fix/remote-config-strip-server-managed-fields
branch
from
August 7, 2026 14:10
13c6173 to
c8dc583
Compare
Add --ca-cert/--ca-key (required together: signing needs the CA's private key, ca.crt alone cannot issue anything). When given, the client certificate is generated and signed locally instead of through cert-manager, covering sources whose TLS is not cert-manager-managed. CN is the replication user, validity is clamped to the CA's own expiry, and the emitted kubernetes.io/tls Secret carries ca.crt/tls.crt/tls.key exactly as the operator expects to mount them. Add --client-sans (comma separated DNS names) applied to the generated certificate on both the local-CA and cert-manager paths. Signed-off-by: Tamal Saha <tamal@appscode.com>
souravbiswassanto
marked this pull request as ready for review
August 7, 2026 15:18
souravbiswassanto
deleted the
fix/remote-config-strip-server-managed-fields
branch
August 7, 2026 15:18
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
`kubectl dba remote-config postgres` generates a YAML file from live objects fetched out of the source cluster. Two bugs caused `kubectl apply` to fail on the remote cluster.
Bug 1 — server-managed fields in generated YAML (first error)
The fetched AppBinding and TLS Secret had server-assigned fields baked in:
Applying these to the remote cluster caused two errors:
Bug 2 — 3-way merge corruption of `metadata.resourceVersion` (second error)
Even after clearing `resourceVersion` from the generated YAML, re-applying still failed:
Root cause: `kubectl apply` stores the full desired state in the `kubectl.kubernetes.io/last-applied-configuration` annotation. Because the previous (buggy) YAML contained `resourceVersion: "5735"`, the annotation stored it. When re-applied with the new YAML (no `resourceVersion`), the 3-way merge logic sees:
The API server rejects that as `Invalid value: 0`.
The deeper issue is that the AppBinding was built by mutating the live object fetched from the source cluster, which unavoidably leaked source-cluster metadata into the generated YAML and its last-applied annotation.
Fix
Bug 1 — clear `ResourceVersion`, `UID`, `CreationTimestamp`, and `Labels` from the TLS Secret before marshalling.
Bug 2 — construct the AppBinding from scratch with only the fields the remote cluster needs (connection coordinates, auth/TLS secret refs, DB type/version). This keeps the last-applied annotation minimal and consistent, so no future re-apply can corrupt `metadata.resourceVersion` via the 3-way merge. It also stops carrying over source-cluster labels, annotations, `appRef`, and Stash `parameters` that are irrelevant on the remote side.
Affected files