Skip to content

Commit 925c6b7

Browse files
committed
Use separate observer for root password
If another object is referenced via the connectionDetails for a kube object, it can happen that the kube object can't be deleted, if the referenced object is deleted first. In this specific case, we used to reference the secret that StackGres creates to expose the root password via the connectionDetails of the `cluster` kube object. However that secret is managed by StackGres. So it will be created by StackGres once a sgcluster object is created. This sgcluster object is managed by the `cluster` kube object, which leads to the race condition. It can happen that StackGres is faster with removing the secret than provider-kubernetes in remove the `cluster` kube object. When that happens the `cluster` kube object doesn't get deleted, because provider-kubernetes throws observation warnings. These warnings prevent the deletion of the actual sgcluster object and the wrapping `cluster` kube object.
1 parent acc6d8c commit 925c6b7

File tree

1 file changed

+40
-11
lines changed

1 file changed

+40
-11
lines changed

pkg/comp-functions/functions/vshnpostgres/connection_details.go

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
vshnv1 "github.com/vshn/appcat/v4/apis/vshn/v1"
1212
"github.com/vshn/appcat/v4/pkg/comp-functions/runtime"
1313
corev1 "k8s.io/api/core/v1"
14+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1415
controllerruntime "sigs.k8s.io/controller-runtime"
1516
)
1617

@@ -63,14 +64,19 @@ func AddConnectionDetails(ctx context.Context, comp *vshnv1.VSHNPostgreSQL, svc
6364
return runtime.NewWarningResult("no connection details yet on cluster")
6465
}
6566

67+
rootPw, err := getPGRootPassword(comp, svc)
68+
if err != nil {
69+
return runtime.NewWarningResult("cannot observe root password: " + err.Error())
70+
}
71+
6672
host := fmt.Sprintf("%s.vshn-postgresql-%s.svc.cluster.local", comp.GetName(), comp.GetName())
6773

6874
url := getPostgresURL(cd, host)
6975

7076
svc.SetConnectionDetail(PostgresqlURL, []byte(url))
7177
svc.SetConnectionDetail(PostgresqlDb, []byte(defaultDB))
7278
svc.SetConnectionDetail(PostgresqlPort, []byte(defaultPort))
73-
svc.SetConnectionDetail(PostgresqlPassword, cd[PostgresqlPassword])
79+
svc.SetConnectionDetail(PostgresqlPassword, []byte(rootPw))
7480
svc.SetConnectionDetail(PostgresqlUser, []byte(defaultUser))
7581
svc.SetConnectionDetail(PostgresqlHost, []byte(host))
7682
err = svc.AddObservedConnectionDetails("cluster")
@@ -100,16 +106,6 @@ func addConnectionDetailsToObject(obj *xkubev1.Object, comp *vshnv1.VSHNPostgreS
100106
certSecretName := "tls-certificate"
101107

102108
obj.Spec.ConnectionDetails = []xkubev1.ConnectionDetail{
103-
{
104-
ToConnectionSecretKey: PostgresqlPassword,
105-
ObjectReference: corev1.ObjectReference{
106-
APIVersion: "v1",
107-
Kind: "Secret",
108-
Namespace: comp.GetInstanceNamespace(),
109-
Name: comp.GetName(),
110-
FieldPath: "data.superuser-password",
111-
},
112-
},
113109
{
114110
ToConnectionSecretKey: "ca.crt",
115111
ObjectReference: corev1.ObjectReference{
@@ -154,3 +150,36 @@ func addConnectionDetailsToObject(obj *xkubev1.Object, comp *vshnv1.VSHNPostgreS
154150

155151
return nil
156152
}
153+
154+
// getPGRootPassword will deploy an observer for stackgres' generated secret and return the password for the root user.
155+
// This is necessary, because provider-kubernetes can hang during de-provisioning, if the secret is used as a connectiondetails
156+
// reference. During deletion, if the secret gets removed before the kube-object gets removed, the kube-object will get stuck
157+
// with observation errors, as it can't resolve the connectiondetails anymore. This is a bug in provider-kubernetes itself.
158+
// To avoid this, we deploy a separate observer for that secret and get the value directly that way.
159+
func getPGRootPassword(comp *vshnv1.VSHNPostgreSQL, svc *runtime.ServiceRuntime) (string, error) {
160+
resNameSuffix := "-root-pw-observer"
161+
162+
secret := &corev1.Secret{
163+
ObjectMeta: metav1.ObjectMeta{
164+
Name: comp.GetName(),
165+
Namespace: comp.GetInstanceNamespace(),
166+
},
167+
}
168+
169+
err := svc.SetDesiredKubeObject(secret, comp.GetName()+resNameSuffix, runtime.KubeOptionObserve)
170+
if err != nil {
171+
return "", err
172+
}
173+
174+
err = svc.GetObservedKubeObject(secret, comp.GetName()+resNameSuffix)
175+
if err != nil {
176+
if err == runtime.ErrNotFound {
177+
return "", nil
178+
}
179+
return "", err
180+
}
181+
182+
pw := secret.Data["superuser-password"]
183+
184+
return string(pw), nil
185+
}

0 commit comments

Comments
 (0)