Skip to content
Open
66 changes: 49 additions & 17 deletions pkg/remote_replica/postgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand All @@ -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)
}
Expand Down Expand Up @@ -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().StringVar(&authSecretName, "auth-secret", "", "name for the auth secret on the remote cluster (default: <dbname>-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 {
Expand All @@ -123,31 +124,55 @@ 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)
}
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.Annotations = nil
apb.ManagedFields = nil
apb.OwnerReferences = nil
// 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
}

appbindingYaml, err := yaml.Marshal(apb)
appbindingYaml, err := yaml.Marshal(remoteApb)
if err != nil {
return nil, fmt.Errorf("failed to marshal appbind yaml %v", err)
}
Expand Down Expand Up @@ -181,7 +206,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 {
Expand All @@ -194,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
Expand All @@ -205,14 +234,17 @@ 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{
Kind: KindSecret,
APIVersion: ApiversionV1,
},
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-remote-replica-auth", opts.DB.Name),
Name: secretName,
Namespace: ns,
},
StringData: map[string]string{
Expand Down
Loading