From 1ac68a8b1af80fc2916d82ea22ae6250276c82a7 Mon Sep 17 00:00:00 2001 From: souravbiswassanto Date: Thu, 18 Jun 2026 17:29:34 +0600 Subject: [PATCH 1/7] fix(remote-config): strip server-managed metadata fields from generated 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 --- pkg/remote_replica/mysql.go | 8 ++++++++ pkg/remote_replica/postgres.go | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/pkg/remote_replica/mysql.go b/pkg/remote_replica/mysql.go index 18abeae47..1320c0e8e 100644 --- a/pkg/remote_replica/mysql.go +++ b/pkg/remote_replica/mysql.go @@ -147,6 +147,10 @@ func generateMySQLConfig(f cmdutil.Factory, userName string, password string, dn apb.Kind = AppcatKind apb.Spec.ClientConfig.Service.Name = dns apb.Spec.Secret.Name = authSecretName + apb.ResourceVersion = "" + apb.UID = "" + apb.CreationTimestamp = metav1.Time{} + apb.Generation = 0 apb.Annotations = nil apb.ManagedFields = nil apb.OwnerReferences = nil @@ -185,7 +189,11 @@ func generateMySQLTlsSecret(userName string, apb *appApi.AppBinding, ns string, } tlsSecret.APIVersion = ApiversionV1 tlsSecret.Kind = KindSecret + tlsSecret.ResourceVersion = "" + tlsSecret.UID = "" + tlsSecret.CreationTimestamp = metav1.Time{} tlsSecret.Annotations = nil + tlsSecret.Labels = nil tlsSecret.ManagedFields = nil tlsSecretYaml, err := yaml.Marshal(tlsSecret) if err != nil { diff --git a/pkg/remote_replica/postgres.go b/pkg/remote_replica/postgres.go index 06095badc..231cc4a01 100644 --- a/pkg/remote_replica/postgres.go +++ b/pkg/remote_replica/postgres.go @@ -143,6 +143,10 @@ func generateConfig(f cmdutil.Factory, userName string, password string, dns str apb.Kind = AppcatKind apb.Spec.ClientConfig.Service.Name = dns apb.Spec.Secret.Name = authSecretName + apb.ResourceVersion = "" + apb.UID = "" + apb.CreationTimestamp = metav1.Time{} + apb.Generation = 0 apb.Annotations = nil apb.ManagedFields = nil apb.OwnerReferences = nil @@ -181,7 +185,11 @@ func generateTlsSecret(userName string, apb *appApi.AppBinding, ns string, opts } tlsSecret.APIVersion = "v1" tlsSecret.Kind = "Secret" + tlsSecret.ResourceVersion = "" + tlsSecret.UID = "" + tlsSecret.CreationTimestamp = metav1.Time{} tlsSecret.Annotations = nil + tlsSecret.Labels = nil tlsSecret.ManagedFields = nil tlsSecretYaml, err := yaml.Marshal(tlsSecret) if err != nil { From 3fe33169132212b6408e230e09f20e03d0015d43 Mon Sep 17 00:00:00 2001 From: souravbiswassanto Date: Thu, 18 Jun 2026 18:55:03 +0600 Subject: [PATCH 2/7] fix(remote-config): build AppBinding from scratch to avoid 3-way merge 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 --- pkg/remote_replica/mysql.go | 58 ++++++++++++++++++++++++---------- pkg/remote_replica/postgres.go | 58 ++++++++++++++++++++++++---------- 2 files changed, 84 insertions(+), 32 deletions(-) diff --git a/pkg/remote_replica/mysql.go b/pkg/remote_replica/mysql.go index 1320c0e8e..ede80e79c 100644 --- a/pkg/remote_replica/mysql.go +++ b/pkg/remote_replica/mysql.go @@ -133,29 +133,55 @@ func generateMySQLConfig(f cmdutil.Factory, userName string, password string, dn } buffer = append(buffer, authBuff...) - // generate secret + var tlsSecretName string if apb.Spec.TLSSecret != nil { - tlsBuff, tlsSecretName, err := generateMySQLTlsSecret(userName, apb, ns, opts) + var tlsBuff []byte + tlsBuff, tlsSecretName, err = generateMySQLTlsSecret(userName, apb, ns, opts) if err != nil { return nil, fmt.Errorf("failed to generate tls secret %v", err) } buffer = append(buffer, tlsBuff...) - apb.Spec.TLSSecret.Name = tlsSecretName } - apb.APIVersion = AppcatApiVersion - apb.Kind = AppcatKind - apb.Spec.ClientConfig.Service.Name = dns - apb.Spec.Secret.Name = authSecretName - apb.ResourceVersion = "" - apb.UID = "" - apb.CreationTimestamp = metav1.Time{} - apb.Generation = 0 - apb.Annotations = nil - apb.ManagedFields = nil - apb.OwnerReferences = nil - - appbindingYaml, err := yaml.Marshal(apb) + // Build a minimal AppBinding from scratch so that no server-managed fields + // (resourceVersion, uid, generation), source-cluster labels, or unrelated + // parameters (e.g. Stash addon config) are carried over. This makes + // repeated kubectl apply idempotent: the last-applied annotation stays + // clean and the 3-way merge never tries to remove metadata.resourceVersion. + remoteApb := &appApi.AppBinding{ + TypeMeta: metav1.TypeMeta{ + APIVersion: AppcatApiVersion, + Kind: AppcatKind, + }, + ObjectMeta: metav1.ObjectMeta{ + Name: apb.Name, + Namespace: ns, + }, + Spec: appApi.AppBindingSpec{ + Type: apb.Spec.Type, + Version: apb.Spec.Version, + ClientConfig: appApi.ClientConfig{ + CABundle: apb.Spec.ClientConfig.CABundle, + Service: &appApi.ServiceReference{ + Scheme: apb.Spec.ClientConfig.Service.Scheme, + Name: dns, + Port: apb.Spec.ClientConfig.Service.Port, + Path: apb.Spec.ClientConfig.Service.Path, + Query: apb.Spec.ClientConfig.Service.Query, + }, + }, + Secret: &appApi.TypedLocalObjectReference{ + Name: authSecretName, + }, + }, + } + if tlsSecretName != "" { + remoteApb.Spec.TLSSecret = &appApi.TypedLocalObjectReference{ + Name: tlsSecretName, + } + } + + appbindingYaml, err := yaml.Marshal(remoteApb) if err != nil { return nil, fmt.Errorf("failed to marshal appbind yaml %v", err) } diff --git a/pkg/remote_replica/postgres.go b/pkg/remote_replica/postgres.go index 231cc4a01..5ccc06ae4 100644 --- a/pkg/remote_replica/postgres.go +++ b/pkg/remote_replica/postgres.go @@ -129,29 +129,55 @@ func generateConfig(f cmdutil.Factory, userName string, password string, dns str } buffer = append(buffer, authBuff...) - // generate secret + var tlsSecretName string if apb.Spec.TLSSecret != nil { - tlsBuff, tlsSecretName, err := generateTlsSecret(userName, apb, ns, opts) + var tlsBuff []byte + tlsBuff, tlsSecretName, err = generateTlsSecret(userName, apb, ns, opts) if err != nil { return nil, fmt.Errorf("failed to generate tls secret %v", err) } buffer = append(buffer, tlsBuff...) - apb.Spec.TLSSecret.Name = tlsSecretName } - apb.APIVersion = AppcatApiVersion - apb.Kind = AppcatKind - apb.Spec.ClientConfig.Service.Name = dns - apb.Spec.Secret.Name = authSecretName - apb.ResourceVersion = "" - apb.UID = "" - apb.CreationTimestamp = metav1.Time{} - apb.Generation = 0 - apb.Annotations = nil - apb.ManagedFields = nil - apb.OwnerReferences = nil - - appbindingYaml, err := yaml.Marshal(apb) + // Build a minimal AppBinding from scratch so that no server-managed fields + // (resourceVersion, uid, generation), source-cluster labels, or unrelated + // parameters (e.g. Stash addon config) are carried over. This makes + // repeated kubectl apply idempotent: the last-applied annotation stays + // clean and the 3-way merge never tries to remove metadata.resourceVersion. + remoteApb := &appApi.AppBinding{ + TypeMeta: metav1.TypeMeta{ + APIVersion: AppcatApiVersion, + Kind: AppcatKind, + }, + ObjectMeta: metav1.ObjectMeta{ + Name: apb.Name, + Namespace: ns, + }, + Spec: appApi.AppBindingSpec{ + Type: apb.Spec.Type, + Version: apb.Spec.Version, + ClientConfig: appApi.ClientConfig{ + CABundle: apb.Spec.ClientConfig.CABundle, + Service: &appApi.ServiceReference{ + Scheme: apb.Spec.ClientConfig.Service.Scheme, + Name: dns, + Port: apb.Spec.ClientConfig.Service.Port, + Path: apb.Spec.ClientConfig.Service.Path, + Query: apb.Spec.ClientConfig.Service.Query, + }, + }, + Secret: &appApi.TypedLocalObjectReference{ + Name: authSecretName, + }, + }, + } + if tlsSecretName != "" { + remoteApb.Spec.TLSSecret = &appApi.TypedLocalObjectReference{ + Name: tlsSecretName, + } + } + + appbindingYaml, err := yaml.Marshal(remoteApb) if err != nil { return nil, fmt.Errorf("failed to marshal appbind yaml %v", err) } From 57ea8795569d285d98894d154ef5bf63020d3cc1 Mon Sep 17 00:00:00 2001 From: souravbiswassanto Date: Thu, 18 Jun 2026 18:59:16 +0600 Subject: [PATCH 3/7] refactor(remote-config): use DeepCopy instead of building AppBinding 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 --- pkg/remote_replica/mysql.go | 53 ++++++++++++---------------------- pkg/remote_replica/postgres.go | 53 ++++++++++++---------------------- 2 files changed, 38 insertions(+), 68 deletions(-) diff --git a/pkg/remote_replica/mysql.go b/pkg/remote_replica/mysql.go index ede80e79c..b87a472f7 100644 --- a/pkg/remote_replica/mysql.go +++ b/pkg/remote_replica/mysql.go @@ -143,42 +143,27 @@ func generateMySQLConfig(f cmdutil.Factory, userName string, password string, dn buffer = append(buffer, tlsBuff...) } - // Build a minimal AppBinding from scratch so that no server-managed fields - // (resourceVersion, uid, generation), source-cluster labels, or unrelated - // parameters (e.g. Stash addon config) are carried over. This makes - // repeated kubectl apply idempotent: the last-applied annotation stays - // clean and the 3-way merge never tries to remove metadata.resourceVersion. - remoteApb := &appApi.AppBinding{ - TypeMeta: metav1.TypeMeta{ - APIVersion: AppcatApiVersion, - Kind: AppcatKind, - }, - ObjectMeta: metav1.ObjectMeta{ - Name: apb.Name, - Namespace: ns, - }, - Spec: appApi.AppBindingSpec{ - Type: apb.Spec.Type, - Version: apb.Spec.Version, - ClientConfig: appApi.ClientConfig{ - CABundle: apb.Spec.ClientConfig.CABundle, - Service: &appApi.ServiceReference{ - Scheme: apb.Spec.ClientConfig.Service.Scheme, - Name: dns, - Port: apb.Spec.ClientConfig.Service.Port, - Path: apb.Spec.ClientConfig.Service.Path, - Query: apb.Spec.ClientConfig.Service.Query, - }, - }, - Secret: &appApi.TypedLocalObjectReference{ - Name: authSecretName, - }, - }, + // Deep-copy the source AppBinding and replace only the ObjectMeta with a + // clean one. This preserves all spec fields (appRef, parameters, type, + // version, clientConfig, etc.) so nothing is silently dropped, while + // ensuring server-managed metadata (resourceVersion, uid, generation, + // labels, annotations) never leaks into the generated YAML. A clean + // ObjectMeta means the last-applied annotation stays minimal, so + // repeated kubectl apply is idempotent and the 3-way merge never tries + // to remove metadata.resourceVersion. + remoteApb := apb.DeepCopy() + remoteApb.TypeMeta = metav1.TypeMeta{ + APIVersion: AppcatApiVersion, + Kind: AppcatKind, } + remoteApb.ObjectMeta = metav1.ObjectMeta{ + Name: apb.Name, + Namespace: ns, + } + remoteApb.Spec.ClientConfig.Service.Name = dns + remoteApb.Spec.Secret.Name = authSecretName if tlsSecretName != "" { - remoteApb.Spec.TLSSecret = &appApi.TypedLocalObjectReference{ - Name: tlsSecretName, - } + remoteApb.Spec.TLSSecret.Name = tlsSecretName } appbindingYaml, err := yaml.Marshal(remoteApb) diff --git a/pkg/remote_replica/postgres.go b/pkg/remote_replica/postgres.go index 5ccc06ae4..4cf56c641 100644 --- a/pkg/remote_replica/postgres.go +++ b/pkg/remote_replica/postgres.go @@ -139,42 +139,27 @@ func generateConfig(f cmdutil.Factory, userName string, password string, dns str buffer = append(buffer, tlsBuff...) } - // Build a minimal AppBinding from scratch so that no server-managed fields - // (resourceVersion, uid, generation), source-cluster labels, or unrelated - // parameters (e.g. Stash addon config) are carried over. This makes - // repeated kubectl apply idempotent: the last-applied annotation stays - // clean and the 3-way merge never tries to remove metadata.resourceVersion. - remoteApb := &appApi.AppBinding{ - TypeMeta: metav1.TypeMeta{ - APIVersion: AppcatApiVersion, - Kind: AppcatKind, - }, - ObjectMeta: metav1.ObjectMeta{ - Name: apb.Name, - Namespace: ns, - }, - Spec: appApi.AppBindingSpec{ - Type: apb.Spec.Type, - Version: apb.Spec.Version, - ClientConfig: appApi.ClientConfig{ - CABundle: apb.Spec.ClientConfig.CABundle, - Service: &appApi.ServiceReference{ - Scheme: apb.Spec.ClientConfig.Service.Scheme, - Name: dns, - Port: apb.Spec.ClientConfig.Service.Port, - Path: apb.Spec.ClientConfig.Service.Path, - Query: apb.Spec.ClientConfig.Service.Query, - }, - }, - Secret: &appApi.TypedLocalObjectReference{ - Name: authSecretName, - }, - }, + // Deep-copy the source AppBinding and replace only the ObjectMeta with a + // clean one. This preserves all spec fields (appRef, parameters, type, + // version, clientConfig, etc.) so nothing is silently dropped, while + // ensuring server-managed metadata (resourceVersion, uid, generation, + // labels, annotations) never leaks into the generated YAML. A clean + // ObjectMeta means the last-applied annotation stays minimal, so + // repeated kubectl apply is idempotent and the 3-way merge never tries + // to remove metadata.resourceVersion. + remoteApb := apb.DeepCopy() + remoteApb.TypeMeta = metav1.TypeMeta{ + APIVersion: AppcatApiVersion, + Kind: AppcatKind, } + remoteApb.ObjectMeta = metav1.ObjectMeta{ + Name: apb.Name, + Namespace: ns, + } + remoteApb.Spec.ClientConfig.Service.Name = dns + remoteApb.Spec.Secret.Name = authSecretName if tlsSecretName != "" { - remoteApb.Spec.TLSSecret = &appApi.TypedLocalObjectReference{ - Name: tlsSecretName, - } + remoteApb.Spec.TLSSecret.Name = tlsSecretName } appbindingYaml, err := yaml.Marshal(remoteApb) From 53482b04b7529143b40fdd74bdd0794fd4cf79c7 Mon Sep 17 00:00:00 2001 From: souravbiswassanto Date: Thu, 18 Jun 2026 19:07:26 +0600 Subject: [PATCH 4/7] fix(remote-config): guard against nil Service and Secret pointers before 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 --- pkg/remote_replica/mysql.go | 9 +++++++++ pkg/remote_replica/postgres.go | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/pkg/remote_replica/mysql.go b/pkg/remote_replica/mysql.go index b87a472f7..1c6ba1af1 100644 --- a/pkg/remote_replica/mysql.go +++ b/pkg/remote_replica/mysql.go @@ -160,9 +160,18 @@ func generateMySQLConfig(f cmdutil.Factory, userName string, password string, dn Name: apb.Name, Namespace: ns, } + if remoteApb.Spec.ClientConfig.Service == nil { + remoteApb.Spec.ClientConfig.Service = &appApi.ServiceReference{} + } remoteApb.Spec.ClientConfig.Service.Name = dns + if remoteApb.Spec.Secret == nil { + remoteApb.Spec.Secret = &appApi.TypedLocalObjectReference{} + } remoteApb.Spec.Secret.Name = authSecretName if tlsSecretName != "" { + if remoteApb.Spec.TLSSecret == nil { + remoteApb.Spec.TLSSecret = &appApi.TypedLocalObjectReference{} + } remoteApb.Spec.TLSSecret.Name = tlsSecretName } diff --git a/pkg/remote_replica/postgres.go b/pkg/remote_replica/postgres.go index 4cf56c641..292463dc2 100644 --- a/pkg/remote_replica/postgres.go +++ b/pkg/remote_replica/postgres.go @@ -156,9 +156,18 @@ func generateConfig(f cmdutil.Factory, userName string, password string, dns str Name: apb.Name, Namespace: ns, } + if remoteApb.Spec.ClientConfig.Service == nil { + remoteApb.Spec.ClientConfig.Service = &appApi.ServiceReference{} + } remoteApb.Spec.ClientConfig.Service.Name = dns + if remoteApb.Spec.Secret == nil { + remoteApb.Spec.Secret = &appApi.TypedLocalObjectReference{} + } remoteApb.Spec.Secret.Name = authSecretName if tlsSecretName != "" { + if remoteApb.Spec.TLSSecret == nil { + remoteApb.Spec.TLSSecret = &appApi.TypedLocalObjectReference{} + } remoteApb.Spec.TLSSecret.Name = tlsSecretName } From 5937b4dea1216f14ebd8b0b42254051870f26c78 Mon Sep 17 00:00:00 2001 From: souravbiswassanto Date: Wed, 24 Jun 2026 12:29:26 +0600 Subject: [PATCH 5/7] remove mysql changes Signed-off-by: souravbiswassanto --- pkg/remote_replica/mysql.go | 50 ++++++++----------------------------- 1 file changed, 11 insertions(+), 39 deletions(-) diff --git a/pkg/remote_replica/mysql.go b/pkg/remote_replica/mysql.go index 1c6ba1af1..18abeae47 100644 --- a/pkg/remote_replica/mysql.go +++ b/pkg/remote_replica/mysql.go @@ -133,49 +133,25 @@ func generateMySQLConfig(f cmdutil.Factory, userName string, password string, dn } buffer = append(buffer, authBuff...) - var tlsSecretName string + // generate secret if apb.Spec.TLSSecret != nil { - var tlsBuff []byte - tlsBuff, tlsSecretName, err = generateMySQLTlsSecret(userName, apb, ns, opts) + tlsBuff, tlsSecretName, err := generateMySQLTlsSecret(userName, apb, ns, opts) if err != nil { return nil, fmt.Errorf("failed to generate tls secret %v", err) } buffer = append(buffer, tlsBuff...) + apb.Spec.TLSSecret.Name = tlsSecretName } - // Deep-copy the source AppBinding and replace only the ObjectMeta with a - // clean one. This preserves all spec fields (appRef, parameters, type, - // version, clientConfig, etc.) so nothing is silently dropped, while - // ensuring server-managed metadata (resourceVersion, uid, generation, - // labels, annotations) never leaks into the generated YAML. A clean - // ObjectMeta means the last-applied annotation stays minimal, so - // repeated kubectl apply is idempotent and the 3-way merge never tries - // to remove metadata.resourceVersion. - remoteApb := apb.DeepCopy() - remoteApb.TypeMeta = metav1.TypeMeta{ - APIVersion: AppcatApiVersion, - Kind: AppcatKind, - } - remoteApb.ObjectMeta = metav1.ObjectMeta{ - Name: apb.Name, - Namespace: ns, - } - if remoteApb.Spec.ClientConfig.Service == nil { - remoteApb.Spec.ClientConfig.Service = &appApi.ServiceReference{} - } - remoteApb.Spec.ClientConfig.Service.Name = dns - if remoteApb.Spec.Secret == nil { - remoteApb.Spec.Secret = &appApi.TypedLocalObjectReference{} - } - remoteApb.Spec.Secret.Name = authSecretName - if tlsSecretName != "" { - if remoteApb.Spec.TLSSecret == nil { - remoteApb.Spec.TLSSecret = &appApi.TypedLocalObjectReference{} - } - remoteApb.Spec.TLSSecret.Name = tlsSecretName - } + apb.APIVersion = AppcatApiVersion + apb.Kind = AppcatKind + apb.Spec.ClientConfig.Service.Name = dns + apb.Spec.Secret.Name = authSecretName + apb.Annotations = nil + apb.ManagedFields = nil + apb.OwnerReferences = nil - appbindingYaml, err := yaml.Marshal(remoteApb) + appbindingYaml, err := yaml.Marshal(apb) if err != nil { return nil, fmt.Errorf("failed to marshal appbind yaml %v", err) } @@ -209,11 +185,7 @@ func generateMySQLTlsSecret(userName string, apb *appApi.AppBinding, ns string, } tlsSecret.APIVersion = ApiversionV1 tlsSecret.Kind = KindSecret - tlsSecret.ResourceVersion = "" - tlsSecret.UID = "" - tlsSecret.CreationTimestamp = metav1.Time{} tlsSecret.Annotations = nil - tlsSecret.Labels = nil tlsSecret.ManagedFields = nil tlsSecretYaml, err := yaml.Marshal(tlsSecret) if err != nil { From 107c9f4ed74a75cd239ba167f1c34bb930058fe2 Mon Sep 17 00:00:00 2001 From: souravbiswassanto Date: Wed, 24 Jun 2026 14:41:46 +0600 Subject: [PATCH 6/7] feat(remote-config): add -s/--auth-secret flag to override auth secret name If --auth-secret is provided, the generated auth Secret and the AppBinding's secret reference both use that name. If omitted, the default -remote-replica-auth is used as before. Signed-off-by: souravbiswassanto --- pkg/remote_replica/postgres.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/pkg/remote_replica/postgres.go b/pkg/remote_replica/postgres.go index 292463dc2..01f098b79 100644 --- a/pkg/remote_replica/postgres.go +++ b/pkg/remote_replica/postgres.go @@ -52,7 +52,7 @@ import ( ) func PostgreSQlAPP(f cmdutil.Factory) *cobra.Command { - var userName, password, dns, ns string + var userName, password, dns, ns, authSecretName string var yes bool cmd := cobra.Command{ @@ -70,7 +70,7 @@ func PostgreSQlAPP(f cmdutil.Factory) *cobra.Command { } var buffer []byte - buffer, err := generateConfig(f, userName, password, dns, ns, args[0]) + buffer, err := generateConfig(f, userName, password, dns, ns, authSecretName, args[0]) if err != nil { log.Fatal(err) } @@ -107,10 +107,11 @@ func PostgreSQlAPP(f cmdutil.Factory) *cobra.Command { log.Fatal(err) } cmd.PersistentFlags().BoolVarP(&yes, "yes", "y", false, "permission for alter password for the remote replica") + cmd.PersistentFlags().StringVarP(&authSecretName, "auth-secret", "s", "", "name for the auth secret on the remote cluster (default: -remote-replica-auth)") return &cmd } -func generateConfig(f cmdutil.Factory, userName string, password string, dns string, ns string, dbname string) ([]byte, error) { +func generateConfig(f cmdutil.Factory, userName string, password string, dns string, ns string, authSecretName string, dbname string) ([]byte, error) { var buffer []byte opts, err := common.NewPostgresOpts(f, dbname, ns) if err != nil { @@ -123,7 +124,7 @@ func generateConfig(f cmdutil.Factory, userName string, password string, dns str return nil, fmt.Errorf("failed to get appbinding %v", err) } - authBuff, authSecretName, err := generateAuthSecret(userName, password, ns, opts) + authBuff, authSecretName, err := generateAuthSecret(userName, password, ns, authSecretName, opts) if err != nil { return nil, fmt.Errorf("failed to generate auth secret ,%v", err) } @@ -222,7 +223,7 @@ func generateTlsSecret(userName string, apb *appApi.AppBinding, ns string, opts return buffer, tlsSecret.Name, nil } -func generateAuthSecret(userName string, password string, ns string, opts *common.PostgresOpts) ([]byte, string, error) { +func generateAuthSecret(userName string, password string, ns string, secretName string, opts *common.PostgresOpts) ([]byte, string, error) { var buffer []byte if userName != opts.Username { // generate user if not present @@ -233,6 +234,9 @@ func generateAuthSecret(userName string, password string, ns string, opts *commo } else { password = opts.Pass } + if secretName == "" { + secretName = fmt.Sprintf("%s-remote-replica-auth", opts.DB.Name) + } // generate auth secret AuthSecret := core.Secret{ TypeMeta: metav1.TypeMeta{ @@ -240,7 +244,7 @@ func generateAuthSecret(userName string, password string, ns string, opts *commo APIVersion: ApiversionV1, }, ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-remote-replica-auth", opts.DB.Name), + Name: secretName, Namespace: ns, }, StringData: map[string]string{ From d817ea01823df6020e1f5f9d9a2e72505e6500ad Mon Sep 17 00:00:00 2001 From: souravbiswassanto Date: Wed, 24 Jun 2026 15:41:04 +0600 Subject: [PATCH 7/7] fix(remote-config): drop -s shorthand from --auth-secret flag -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 --- pkg/remote_replica/postgres.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/remote_replica/postgres.go b/pkg/remote_replica/postgres.go index 01f098b79..aeb5cd882 100644 --- a/pkg/remote_replica/postgres.go +++ b/pkg/remote_replica/postgres.go @@ -107,7 +107,7 @@ func PostgreSQlAPP(f cmdutil.Factory) *cobra.Command { log.Fatal(err) } cmd.PersistentFlags().BoolVarP(&yes, "yes", "y", false, "permission for alter password for the remote replica") - cmd.PersistentFlags().StringVarP(&authSecretName, "auth-secret", "s", "", "name for the auth secret on the remote cluster (default: -remote-replica-auth)") + cmd.PersistentFlags().StringVar(&authSecretName, "auth-secret", "", "name for the auth secret on the remote cluster (default: -remote-replica-auth)") return &cmd }