diff --git a/helm/db-controller/templates/tests/dbproxy.yaml b/helm/db-controller/templates/tests/dbproxy.yaml index 0f359f3..8151a9e 100644 --- a/helm/db-controller/templates/tests/dbproxy.yaml +++ b/helm/db-controller/templates/tests/dbproxy.yaml @@ -71,6 +71,7 @@ metadata: labels: persistance.atlas.infoblox.com/allow-deletion: enabled {{- include "db-proxy-test.labels" . | nindent 4 }} + persistance.atlas.infoblox.com/allow-deletion: enabled annotations: # ensure this runs on the new db-controller, not the existing one "helm.sh/hook": "test" diff --git a/helm/db-controller/templates/tests/dsnexec.yaml b/helm/db-controller/templates/tests/dsnexec.yaml index a87c394..422e5d8 100644 --- a/helm/db-controller/templates/tests/dsnexec.yaml +++ b/helm/db-controller/templates/tests/dsnexec.yaml @@ -26,7 +26,7 @@ spec: - /bin/sh - -c - | - ls /etc/secrets + test -f /etc/secrets/uri_dsn.txt || { echo "Error: URI file does not exist"; exit 1; } cat /etc/secrets/uri_dsn.txt for i in $(seq 1 10); do echo "Attempt $i: Connecting to PostgreSQL..." diff --git a/helm/db-controller/templates/tests/roleclaim.yaml b/helm/db-controller/templates/tests/roleclaim.yaml index efd6fb1..fac6d7c 100644 --- a/helm/db-controller/templates/tests/roleclaim.yaml +++ b/helm/db-controller/templates/tests/roleclaim.yaml @@ -6,6 +6,7 @@ metadata: labels: persistance.atlas.infoblox.com/allow-deletion: enabled {{- include "db-controller.labels" . | nindent 4 }} + persistance.atlas.infoblox.com/allow-deletion: enabled annotations: "helm.sh/hook": test "helm.sh/hook-weight": "-4" diff --git a/internal/controller/databaseclaim_controller_test.go b/internal/controller/databaseclaim_controller_test.go index bc9da22..86ef5fd 100644 --- a/internal/controller/databaseclaim_controller_test.go +++ b/internal/controller/databaseclaim_controller_test.go @@ -97,7 +97,10 @@ var _ = Describe("DatabaseClaim Controller", func() { Expect(k8sClient.Get(ctx, typeNamespacedName, claim)).To(Succeed()) hostParams, err := hostparams.New(controllerReconciler.Config.Viper, claim) Expect(err).NotTo(HaveOccurred()) + + // postgres-db.t4g.medium-15 credSecretName := fmt.Sprintf("%s-%s-%s", env, resourceName, hostParams.Hash()) + Expect(credSecretName).To(Equal("testenv-test-dbclaim-416e183c")) cleanup := dockerdb.MockRDSCredentials(GinkgoT(), ctx, k8sClient, testDSN, credSecretName) DeferCleanup(cleanup) }) @@ -226,6 +229,42 @@ var _ = Describe("DatabaseClaim Controller", func() { }) + It("Should have DSN and URIDSN keys populated", func() { + By("Reconciling the created resource") + _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{NamespacedName: typeNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + + var claim persistancev1.DatabaseClaim + err = k8sClient.Get(ctx, typeNamespacedName, &claim) + Expect(err).NotTo(HaveOccurred()) + Expect(claim.Status.Error).To(Equal("")) + + By("Checking the user credentials secret") + + secret := &corev1.Secret{} + err = k8sClient.Get(ctx, typeNamespacedSecretName, secret) + Expect(err).NotTo(HaveOccurred()) + + for _, key := range []string{v1.DSNKey, v1.DSNURIKey, "fixme.txt", "uri_fixme.txt"} { + Expect(secret.Data[key]).NotTo(BeNil()) + } + oldKey := secret.Data[v1.DSNKey] + Expect(secret.Data[v1.DSNKey]).To(Equal(secret.Data["fixme.txt"])) + Expect(secret.Data[v1.DSNURIKey]).To(Equal(secret.Data["uri_fixme.txt"])) + // Slow down the test so creds are rotated, 60ns rotation time + By("Rotate passwords and verify credentials are updated") + _, err = controllerReconciler.Reconcile(ctx, reconcile.Request{NamespacedName: typeNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + + err = k8sClient.Get(ctx, typeNamespacedSecretName, secret) + Expect(err).NotTo(HaveOccurred()) + + Expect(secret.Data[v1.DSNKey]).NotTo(Equal(oldKey)) + Expect(secret.Data[v1.DSNKey]).To(Equal(secret.Data["fixme.txt"])) + Expect(secret.Data[v1.DSNURIKey]).To(Equal(secret.Data["uri_fixme.txt"])) + + }) + It("Should succeed with no error status to reconcile CR with DBVersion", func() { By("Updating the DatabaseClaim resource with a DB Version 13.3") resource := &v1.DatabaseClaim{} @@ -307,6 +346,7 @@ var _ = Describe("DatabaseClaim Controller", func() { instanceName := fmt.Sprintf("%s-%s-%s", env, resourceName, hostParams.Hash()) By(fmt.Sprintf("Check dbinstance is created with labels: %s", instanceName)) + Eventually(func() error { return k8sClient.Get(ctx, types.NamespacedName{Name: instanceName}, &instance) }).Should(Succeed()) @@ -332,6 +372,9 @@ var _ = Describe("DatabaseClaim Controller", func() { By("Updating CR with a DB Version") resource := &persistancev1.DatabaseClaim{} + Expect(k8sClient.Get(ctx, typeNamespacedName, resource)).NotTo(HaveOccurred()) + Expect(k8sClient.Update(ctx, resource)).NotTo(HaveOccurred()) + Expect(k8sClient.Get(ctx, typeNamespacedName, resource)).NotTo(HaveOccurred()) Expect(resource.Spec.DBVersion).To(Equal("")) @@ -357,5 +400,36 @@ var _ = Describe("DatabaseClaim Controller", func() { Expect(resource.Status.ActiveDB.ConnectionInfo.Username).To(Equal("postgres_a")) }) + + It("Reconcile rotates the username", func() { + By("Updating CR with a DB Version") + + resource := &persistancev1.DatabaseClaim{} + Expect(k8sClient.Get(ctx, typeNamespacedName, resource)).NotTo(HaveOccurred()) + Expect(resource.Spec.DBVersion).To(Equal("")) + + By("Rotating to UserSuffixA") + _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{NamespacedName: typeNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + Expect(k8sClient.Get(ctx, typeNamespacedName, resource)).NotTo(HaveOccurred()) + Expect(resource.Status.Error).To(Equal("")) + Expect(resource.Status.ActiveDB.ConnectionInfo.Username).To(Equal("postgres_a")) + + By("Rotating to UserSuffixB") + _, err = controllerReconciler.Reconcile(ctx, reconcile.Request{NamespacedName: typeNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + Expect(k8sClient.Get(ctx, typeNamespacedName, resource)).NotTo(HaveOccurred()) + Expect(resource.Status.Error).To(Equal("")) + Expect(resource.Status.ActiveDB.ConnectionInfo.Username).To(Equal("postgres_b")) + + By("Rotating to UserSuffixA") + _, err = controllerReconciler.Reconcile(ctx, reconcile.Request{NamespacedName: typeNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + Expect(k8sClient.Get(ctx, typeNamespacedName, resource)).NotTo(HaveOccurred()) + Expect(resource.Status.Error).To(Equal("")) + Expect(resource.Status.ActiveDB.ConnectionInfo.Username).To(Equal("postgres_a")) + + }) + }) }) diff --git a/internal/webhook/dbproxy.go b/internal/webhook/dbproxy.go index 2aca424..6de1b9b 100644 --- a/internal/webhook/dbproxy.go +++ b/internal/webhook/dbproxy.go @@ -8,6 +8,7 @@ import ( ) var ( + // TODO: align this with the path used in dsnexec.go MountPathProxy = "/dbproxy" VolumeNameProxy = "dbproxydsn" ContainerNameProxy = "dbproxy" diff --git a/internal/webhook/dsnexec.go b/internal/webhook/dsnexec.go index 3418496..de36857 100644 --- a/internal/webhook/dsnexec.go +++ b/internal/webhook/dsnexec.go @@ -78,13 +78,12 @@ func mutatePodExec(ctx context.Context, pod *corev1.Pod, secretName string, dsnE var readinessProbe *corev1.Probe if enableReady { readinessProbe = &corev1.Probe{ - ProbeHandler: corev1.ProbeHandler{ Exec: &corev1.ExecAction{ Command: []string{ "/bin/sh", "-c", - "psql -h localhost -c \"SELECT 1\"", + fmt.Sprintf("psql \"$(cat %s/%s)\" -c \"SELECT 1\"", MountPathExec, SecretKey), }, }, }, @@ -94,9 +93,10 @@ func mutatePodExec(ctx context.Context, pod *corev1.Pod, secretName string, dsnE } } + // FIXME: figure out a liveness probe for dsnexec var livenessProbe *corev1.Probe - - if enableLiveness { + _ = livenessProbe + if false && enableLiveness { livenessProbe = &corev1.Probe{ ProbeHandler: corev1.ProbeHandler{ Exec: &corev1.ExecAction{ @@ -128,9 +128,9 @@ func mutatePodExec(ctx context.Context, pod *corev1.Pod, secretName string, dsnE Value: fmt.Sprintf("%s/%s", MountPathExec, SecretKey), }, }, - // Test connection to upstream database - LivenessProbe: livenessProbe, - // Test connection to pgbouncer + // FIXME: figure out a liveness probe for dsnexec + // LivenessProbe: livenessProbe, + // Test connection to specified database ReadinessProbe: readinessProbe, VolumeMounts: []corev1.VolumeMount{ { diff --git a/internal/webhook/dsnexec_test.go b/internal/webhook/dsnexec_test.go index c05a5ef..07a6310 100644 --- a/internal/webhook/dsnexec_test.go +++ b/internal/webhook/dsnexec_test.go @@ -127,7 +127,8 @@ var _ = Describe("dsnexec defaulting", func() { Expect(sidecar.VolumeMounts[0].MountPath).To(Equal(MountPathExec)) Expect(sidecar.VolumeMounts[0].ReadOnly).To(BeTrue()) Expect(sidecar.ReadinessProbe).ToNot(BeNil()) - Expect(sidecar.LivenessProbe).ToNot(BeNil()) + // FIXME: liveness probes deactivated DEVOPS-30642 + // Expect(sidecar.LivenessProbe).ToNot(BeNil()) }) It("pre-mutated pods are not re-mutated", func() { diff --git a/pkg/databaseclaim/claimstatus.go b/pkg/databaseclaim/claimstatus.go index 5005e61..1e226c5 100644 --- a/pkg/databaseclaim/claimstatus.go +++ b/pkg/databaseclaim/claimstatus.go @@ -223,7 +223,7 @@ func (m *StatusManager) MigrationInProgressStatus(ctx context.Context, dbClaim * return ctrl.Result{Requeue: true}, err } -// ActiveDBSuccessReconcile clears the error status and determines if the DB version is explicitly +// ActiveDBSuccessReconcile clears the error status and determines if the DB version is explicitly // defined. func (m *StatusManager) ActiveDBSuccessReconcile(ctx context.Context, dbClaim *v1.DatabaseClaim) (reconcile.Result, error) { result, err := m.SuccessAndUpdateCondition(ctx, dbClaim)