From bdfa932aa75a8c11eff10e232f475b70e4c85b1a Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Mon, 2 Dec 2024 11:49:00 +0100 Subject: [PATCH 01/26] K8SPG-594 delete custom extensions from installed --- .../tests/custom-extensions/09-assert.yaml | 12 +++ .../09-check-installed-extensions.yaml | 13 +++ percona/controller/pgcluster/controller.go | 100 +++++++++++++++++- percona/extensions/uninstall.go | 32 +++++- 4 files changed, 152 insertions(+), 5 deletions(-) create mode 100644 e2e-tests/tests/custom-extensions/09-assert.yaml create mode 100644 e2e-tests/tests/custom-extensions/09-check-installed-extensions.yaml diff --git a/e2e-tests/tests/custom-extensions/09-assert.yaml b/e2e-tests/tests/custom-extensions/09-assert.yaml new file mode 100644 index 0000000000..248fb9f19e --- /dev/null +++ b/e2e-tests/tests/custom-extensions/09-assert.yaml @@ -0,0 +1,12 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 30 +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: 10-check-extensions +data: + data: |2- + pg_stat_monitor + pgaudit diff --git a/e2e-tests/tests/custom-extensions/09-check-installed-extensions.yaml b/e2e-tests/tests/custom-extensions/09-check-installed-extensions.yaml new file mode 100644 index 0000000000..7cbb0f581a --- /dev/null +++ b/e2e-tests/tests/custom-extensions/09-check-installed-extensions.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + data=$(kubectl -n ${NAMESPACE} exec $(get_client_pod) -- psql -v ON_ERROR_STOP=1 -t -q postgres://postgres:$(get_psql_user_pass custom-extensions-pguser-postgres)@$(get_psql_user_host custom-extensions-pguser-postgres) -c "\c postgres" -c "select name from pg_extensions order by name") + + kubectl create configmap -n "${NAMESPACE}" 10-check-extensions --from-literal=data="${data}" diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index 1d5d1dac92..ad7e40c6eb 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -4,6 +4,7 @@ import ( "context" "crypto/md5" "fmt" + "github.com/percona/percona-postgresql-operator/internal/postgres" "reflect" "strings" "time" @@ -241,7 +242,7 @@ func (r *PGClusterReconciler) Reconcile(ctx context.Context, request reconcile.R return reconcile.Result{}, errors.Wrap(err, "failed to handle monitor user password change") } - r.reconcileCustomExtensions(cr) + r.reconcileCustomExtensions(cr, ctx) if err := r.reconcileScheduledBackups(ctx, cr); err != nil { return reconcile.Result{}, errors.Wrap(err, "reconcile scheduled backups") @@ -524,9 +525,9 @@ func (r *PGClusterReconciler) handleMonitorUserPassChange(ctx context.Context, c return nil } -func (r *PGClusterReconciler) reconcileCustomExtensions(cr *v2.PerconaPGCluster) { +func (r *PGClusterReconciler) reconcileCustomExtensions(cr *v2.PerconaPGCluster, ctx context.Context) error { if cr.Spec.Extensions.Storage.Secret == nil { - return + return nil } extensionKeys := make([]string, 0) @@ -535,6 +536,54 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(cr *v2.PerconaPGCluster) extensionKeys = append(extensionKeys, key) } + if cr.CompareVersion("2.6.0") >= 0 { + var extensionKeysForDeletion []string + var extensionsKeysAnnotations []string + + if cr.Spec.Metadata.Annotations != nil { + if val, ok := cr.Spec.Metadata.Annotations["custom_extensions_list"]; ok && val != "" { + extensionsKeysAnnotations = strings.Split(val, ",") + } + } + + for i := range extensionsKeysAnnotations { + extensionsKeysAnnotations[i] = strings.TrimSpace(extensionsKeysAnnotations[i]) + } + annotationExtensionsMap := make(map[string]struct{}) + + crExtensionsMap := make(map[string]struct{}) + // extensions added to annotations + for _, ext := range extensionsKeysAnnotations { + annotationExtensionsMap[ext] = struct{}{} + } + + // Populate crExtensionsMap and simultaneously check for missing entries in extensionsKeysAnnotations + for _, ext := range extensionKeys { + crExtensionsMap[ext] = struct{}{} + + // If an object exists in crExtensions but not in extensionsKeysAnnotations + if _, exists := annotationExtensionsMap[ext]; !exists { + extensionsKeysAnnotations = append(extensionsKeysAnnotations, ext) + } + } + cr.Spec.Metadata.Annotations["custom_extensions_list"] = strings.Join(extensionsKeysAnnotations, ", ") + + // Check for missing entries in crExtensions + for _, ext := range extensionsKeysAnnotations { + // If an object exists in extensionsKeysAnnotations but not in crExtensions, the extension should be deleted. + if _, exists := crExtensionsMap[ext]; !exists { + extensionKeysForDeletion = append(extensionKeysForDeletion, ext) + } + } + if len(extensionKeysForDeletion) > 0 { + var exec postgres.Executor + err := extensions.DisableCustomExtensionsInPostgreSQL(ctx, extensionKeysForDeletion, exec) + if err != nil { + return errors.Wrap(err, "custom extension deletion") + } + } + } + for i := 0; i < len(cr.Spec.InstanceSets); i++ { set := &cr.Spec.InstanceSets[i] set.InitContainers = append(set.InitContainers, extensions.ExtensionRelocatorContainer( @@ -549,6 +598,7 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(cr *v2.PerconaPGCluster) )) set.VolumeMounts = append(set.VolumeMounts, extensions.ExtensionVolumeMounts(cr.Spec.PostgresVersion)...) } + return nil } func isBackupRunning(ctx context.Context, cl client.Reader, cr *v2.PerconaPGCluster) (bool, error) { @@ -659,3 +709,47 @@ func (r *PGClusterReconciler) ensureFinalizers(ctx context.Context, cr *v2.Perco return nil } + +//func DisableCustomExtentionsInPostgreSQL(ctx context.Context, crExtensions []string, exec postgres.Executor) error { +// log := logging.FromContext(ctx) +// +// stdout, stderr, err := exec.ExecInAllDatabases(ctx, +// `SELECT extname FROM pg_extension;`, +// map[string]string{ +// "ON_ERROR_STOP": "on", // Abort if any command fails. +// "QUIET": "on", // Do not print successful commands to stdout. +// }) +// if err != nil { +// log.Error(err, "Error executing query: %v, stderr: %s", stderr) +// return err +// } +// +// pgExtensions := strings.Split(strings.TrimSpace(stdout), "\n") +// fmt.Printf("Installed extensions: %v\n", pgExtensions) +// +// crExtensionMap := make(map[string]bool) +// for _, ext := range crExtensions { +// crExtensionMap[ext] = true +// } +// +// for _, extensionName := range pgExtensions { +// if !crExtensionMap[extensionName] { +// sqlCommand := fmt.Sprintf( +// `SET client_min_messages = WARNING; DROP EXTENSION IF EXISTS %s;`, +// extensionName, +// ) +// +// stdout, stderr, err := exec.ExecInAllDatabases(ctx, +// sqlCommand, +// map[string]string{ +// "ON_ERROR_STOP": "on", // Abort when any one command fails. +// "QUIET": "on", // Do not print successful commands to stdout. +// }, +// ) +// log.V(1).Info("disabled %s", extensionName, "stdout", stdout, "stderr", stderr) +// +// return err +// } +// } +// return nil +//} diff --git a/percona/extensions/uninstall.go b/percona/extensions/uninstall.go index f7df15cee8..82e64c207b 100644 --- a/percona/extensions/uninstall.go +++ b/percona/extensions/uninstall.go @@ -3,11 +3,14 @@ package extensions import ( "archive/tar" "compress/gzip" + "context" + "fmt" + "github.com/percona/percona-postgresql-operator/internal/logging" + "github.com/percona/percona-postgresql-operator/internal/postgres" + "github.com/pkg/errors" "io" "log" "os" - - "github.com/pkg/errors" ) func Uninstall(archivePath string) error { @@ -42,3 +45,28 @@ func Uninstall(archivePath string) error { return nil } + +func DisableCustomExtensionsInPostgreSQL(ctx context.Context, customExtensionsForDeletion []string, exec postgres.Executor) error { + log := logging.FromContext(ctx) + + for _, extensionName := range customExtensionsForDeletion { + + sqlCommand := fmt.Sprintf( + `SET client_min_messages = WARNING; DROP EXTENSION IF EXISTS %s;`, + extensionName, + ) + + stdout, stderr, err := exec.ExecInAllDatabases(ctx, + sqlCommand, + map[string]string{ + "ON_ERROR_STOP": "on", // Abort when any one command fails. + "QUIET": "on", // Do not print successful commands to stdout. + }, + ) + log.V(1).Info("disabled %s", extensionName, "stdout", stdout, "stderr", stderr) + + return errors.Wrap(err, "custom extension deletion") + + } + return nil +} From d1c94349e4ea948f27f9b30364a7b11161b8e0d2 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Mon, 2 Dec 2024 12:36:40 +0100 Subject: [PATCH 02/26] update extensions check --- percona/controller/pgcluster/controller.go | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index ad7e40c6eb..06bb574349 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -557,17 +557,6 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(cr *v2.PerconaPGCluster, annotationExtensionsMap[ext] = struct{}{} } - // Populate crExtensionsMap and simultaneously check for missing entries in extensionsKeysAnnotations - for _, ext := range extensionKeys { - crExtensionsMap[ext] = struct{}{} - - // If an object exists in crExtensions but not in extensionsKeysAnnotations - if _, exists := annotationExtensionsMap[ext]; !exists { - extensionsKeysAnnotations = append(extensionsKeysAnnotations, ext) - } - } - cr.Spec.Metadata.Annotations["custom_extensions_list"] = strings.Join(extensionsKeysAnnotations, ", ") - // Check for missing entries in crExtensions for _, ext := range extensionsKeysAnnotations { // If an object exists in extensionsKeysAnnotations but not in crExtensions, the extension should be deleted. @@ -575,6 +564,7 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(cr *v2.PerconaPGCluster, extensionKeysForDeletion = append(extensionKeysForDeletion, ext) } } + if len(extensionKeysForDeletion) > 0 { var exec postgres.Executor err := extensions.DisableCustomExtensionsInPostgreSQL(ctx, extensionKeysForDeletion, exec) @@ -582,6 +572,9 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(cr *v2.PerconaPGCluster, return errors.Wrap(err, "custom extension deletion") } } + + cr.Spec.Metadata.Annotations["custom_extensions_list"] = strings.Join(extensionKeys, ", ") + } for i := 0; i < len(cr.Spec.InstanceSets); i++ { From a265b8669b25645124b91ba9674e823ee89d77c7 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Mon, 2 Dec 2024 15:17:30 +0100 Subject: [PATCH 03/26] fix checks --- percona/extensions/uninstall.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/percona/extensions/uninstall.go b/percona/extensions/uninstall.go index 82e64c207b..bc9ed7f4bf 100644 --- a/percona/extensions/uninstall.go +++ b/percona/extensions/uninstall.go @@ -5,12 +5,14 @@ import ( "compress/gzip" "context" "fmt" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/pkg/errors" "io" "log" "os" + + "github.com/pkg/errors" + + "github.com/percona/percona-postgresql-operator/internal/logging" + "github.com/percona/percona-postgresql-operator/internal/postgres" ) func Uninstall(archivePath string) error { @@ -63,7 +65,7 @@ func DisableCustomExtensionsInPostgreSQL(ctx context.Context, customExtensionsFo "QUIET": "on", // Do not print successful commands to stdout. }, ) - log.V(1).Info("disabled %s", extensionName, "stdout", stdout, "stderr", stderr) + log.V(1).Info("disabled", "extensionName", extensionName, "stdout", stdout, "stderr", stderr) return errors.Wrap(err, "custom extension deletion") From d370c4a2ec86ab0ad60d4d9bbe1625785fd848d4 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Mon, 2 Dec 2024 15:33:31 +0100 Subject: [PATCH 04/26] fix checks --- percona/controller/pgcluster/controller.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index 06bb574349..66a2bf709a 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -4,11 +4,12 @@ import ( "context" "crypto/md5" "fmt" - "github.com/percona/percona-postgresql-operator/internal/postgres" "reflect" "strings" "time" + "github.com/percona/percona-postgresql-operator/internal/postgres" + "github.com/pkg/errors" "go.opentelemetry.io/otel/trace" batchv1 "k8s.io/api/batch/v1" @@ -242,7 +243,9 @@ func (r *PGClusterReconciler) Reconcile(ctx context.Context, request reconcile.R return reconcile.Result{}, errors.Wrap(err, "failed to handle monitor user password change") } - r.reconcileCustomExtensions(cr, ctx) + if err := r.reconcileCustomExtensions(ctx, cr); err != nil { + return reconcile.Result{}, errors.Wrap(err, "reconcile custom extensions") + } if err := r.reconcileScheduledBackups(ctx, cr); err != nil { return reconcile.Result{}, errors.Wrap(err, "reconcile scheduled backups") @@ -525,7 +528,7 @@ func (r *PGClusterReconciler) handleMonitorUserPassChange(ctx context.Context, c return nil } -func (r *PGClusterReconciler) reconcileCustomExtensions(cr *v2.PerconaPGCluster, ctx context.Context) error { +func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr *v2.PerconaPGCluster) error { if cr.Spec.Extensions.Storage.Secret == nil { return nil } From 71c00fbb4c87676b428612b22a6968a75cbc190a Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Mon, 2 Dec 2024 17:55:06 +0100 Subject: [PATCH 05/26] delete unused --- percona/controller/pgcluster/controller.go | 44 ---------------------- 1 file changed, 44 deletions(-) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index 66a2bf709a..d65055e64c 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -705,47 +705,3 @@ func (r *PGClusterReconciler) ensureFinalizers(ctx context.Context, cr *v2.Perco return nil } - -//func DisableCustomExtentionsInPostgreSQL(ctx context.Context, crExtensions []string, exec postgres.Executor) error { -// log := logging.FromContext(ctx) -// -// stdout, stderr, err := exec.ExecInAllDatabases(ctx, -// `SELECT extname FROM pg_extension;`, -// map[string]string{ -// "ON_ERROR_STOP": "on", // Abort if any command fails. -// "QUIET": "on", // Do not print successful commands to stdout. -// }) -// if err != nil { -// log.Error(err, "Error executing query: %v, stderr: %s", stderr) -// return err -// } -// -// pgExtensions := strings.Split(strings.TrimSpace(stdout), "\n") -// fmt.Printf("Installed extensions: %v\n", pgExtensions) -// -// crExtensionMap := make(map[string]bool) -// for _, ext := range crExtensions { -// crExtensionMap[ext] = true -// } -// -// for _, extensionName := range pgExtensions { -// if !crExtensionMap[extensionName] { -// sqlCommand := fmt.Sprintf( -// `SET client_min_messages = WARNING; DROP EXTENSION IF EXISTS %s;`, -// extensionName, -// ) -// -// stdout, stderr, err := exec.ExecInAllDatabases(ctx, -// sqlCommand, -// map[string]string{ -// "ON_ERROR_STOP": "on", // Abort when any one command fails. -// "QUIET": "on", // Do not print successful commands to stdout. -// }, -// ) -// log.V(1).Info("disabled %s", extensionName, "stdout", stdout, "stderr", stderr) -// -// return err -// } -// } -// return nil -//} From 08695c65ea8128fbc18f3b67b96697e7f2447217 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Wed, 4 Dec 2024 16:04:16 +0100 Subject: [PATCH 06/26] fix PR coments --- percona/controller/pgcluster/controller.go | 38 +++++++++------------- percona/naming/annotations.go | 3 ++ 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index d65055e64c..6a5abf69c1 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -540,43 +540,37 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr } if cr.CompareVersion("2.6.0") >= 0 { - var extensionKeysForDeletion []string - var extensionsKeysAnnotations []string + // custom extensions to be removed + var removedExtension []string + // list of installed custom extensions + var installedExtensions []string - if cr.Spec.Metadata.Annotations != nil { - if val, ok := cr.Spec.Metadata.Annotations["custom_extensions_list"]; ok && val != "" { - extensionsKeysAnnotations = strings.Split(val, ",") - } - } - - for i := range extensionsKeysAnnotations { - extensionsKeysAnnotations[i] = strings.TrimSpace(extensionsKeysAnnotations[i]) + if val, ok := cr.Spec.Metadata.Annotations[pNaming.AnnotationClusterCustomExtensions]; ok && val != "" { + installedExtensions = strings.Split(val, ",") } - annotationExtensionsMap := make(map[string]struct{}) - crExtensionsMap := make(map[string]struct{}) - // extensions added to annotations - for _, ext := range extensionsKeysAnnotations { - annotationExtensionsMap[ext] = struct{}{} + crExtensions := make(map[string]struct{}) + for _, ext := range installedExtensions { + crExtensions[ext] = struct{}{} } // Check for missing entries in crExtensions - for _, ext := range extensionsKeysAnnotations { - // If an object exists in extensionsKeysAnnotations but not in crExtensions, the extension should be deleted. - if _, exists := crExtensionsMap[ext]; !exists { - extensionKeysForDeletion = append(extensionKeysForDeletion, ext) + for _, ext := range installedExtensions { + // If an object exists in installedExtensions but not in crExtensions, the extension should be deleted. + if _, exists := crExtensions[ext]; !exists { + removedExtension = append(removedExtension, ext) } } - if len(extensionKeysForDeletion) > 0 { + if len(removedExtension) > 0 { var exec postgres.Executor - err := extensions.DisableCustomExtensionsInPostgreSQL(ctx, extensionKeysForDeletion, exec) + err := extensions.DisableCustomExtensionsInPostgreSQL(ctx, removedExtension, exec) if err != nil { return errors.Wrap(err, "custom extension deletion") } } - cr.Spec.Metadata.Annotations["custom_extensions_list"] = strings.Join(extensionKeys, ", ") + cr.Spec.Metadata.Annotations[pNaming.AnnotationClusterCustomExtensions] = strings.Join(extensionKeys, ",") } diff --git a/percona/naming/annotations.go b/percona/naming/annotations.go index 0a861e606d..8c04c4ef16 100644 --- a/percona/naming/annotations.go +++ b/percona/naming/annotations.go @@ -46,6 +46,9 @@ const ( // AnnotationClusterBootstrapRestore is the annotation that is added to PerconaPGRestore to // indicate that it is a cluster bootstrap restore. AnnotationClusterBootstrapRestore = AnnotationPrefix + "cluster-bootstrap-restore" + + //AnnotationClusterCustomExtension is annotation that added to pg cluster to handle the list of custom extensions. + AnnotationClusterCustomExtensions = AnnotationPrefix + "custom_extensions" ) func ToCrunchyAnnotation(annotation string) string { From 4c6bf22784889204dce2a9c8be2d6abc9417ed41 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Wed, 4 Dec 2024 17:53:46 +0100 Subject: [PATCH 07/26] fix PR comments --- percona/controller/pgcluster/controller.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index 6a5abf69c1..afe8d2425a 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -550,7 +550,7 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr } crExtensions := make(map[string]struct{}) - for _, ext := range installedExtensions { + for _, ext := range extensionKeys { crExtensions[ext] = struct{}{} } From f232f3695ece48928c4c5832ab0528bfe32863bd Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Mon, 9 Dec 2024 15:34:04 +0100 Subject: [PATCH 08/26] fix PR --- build/postgres-operator/Dockerfile | 2 +- percona/controller/pgcluster/controller.go | 38 ++++++++++++++++++++-- percona/extensions/uninstall.go | 30 ----------------- 3 files changed, 37 insertions(+), 33 deletions(-) diff --git a/build/postgres-operator/Dockerfile b/build/postgres-operator/Dockerfile index 93597cc638..b6c48b0cd2 100644 --- a/build/postgres-operator/Dockerfile +++ b/build/postgres-operator/Dockerfile @@ -11,7 +11,7 @@ ARG GO_LDFLAGS ARG GOOS=linux ARG TARGETARCH ARG OPERATOR_CGO_ENABLED=1 -ARG EXTENSION_INSTALLER_CGO_ENABLED=0 +ARG EXTENSION_INSTALLER_CGO_ENABLED=1 ARG TARGETPLATFORM ARG BUILDPLATFORM diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index afe8d2425a..d4fd4a33cf 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -549,11 +549,15 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr installedExtensions = strings.Split(val, ",") } + fmt.Sprintf("Before getting crExtensions") + crExtensions := make(map[string]struct{}) for _, ext := range extensionKeys { crExtensions[ext] = struct{}{} } + fmt.Sprintf("After getting crExtensions") + // Check for missing entries in crExtensions for _, ext := range installedExtensions { // If an object exists in installedExtensions but not in crExtensions, the extension should be deleted. @@ -561,17 +565,22 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr removedExtension = append(removedExtension, ext) } } + fmt.Sprintf("After getting crExtensions %v", removedExtension) if len(removedExtension) > 0 { + fmt.Sprintf("Before remove extension check") var exec postgres.Executor - err := extensions.DisableCustomExtensionsInPostgreSQL(ctx, removedExtension, exec) + fmt.Sprintf("After executor") + err := DisableCustomExtensionsInPostgreSQL(ctx, removedExtension, exec) if err != nil { return errors.Wrap(err, "custom extension deletion") } } - + fmt.Sprintf("After remove extension check") cr.Spec.Metadata.Annotations[pNaming.AnnotationClusterCustomExtensions] = strings.Join(extensionKeys, ",") + fmt.Sprintf("After annotations update") + } for i := 0; i < len(cr.Spec.InstanceSets); i++ { @@ -591,6 +600,31 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr return nil } +func DisableCustomExtensionsInPostgreSQL(ctx context.Context, customExtensionsForDeletion []string, exec postgres.Executor) error { + log := logging.FromContext(ctx) + + for _, extensionName := range customExtensionsForDeletion { + + sqlCommand := fmt.Sprintf( + `SET client_min_messages = WARNING; DROP EXTENSION IF EXISTS %s;`, + extensionName, + ) + + stdout, stderr, err := exec.ExecInAllDatabases(ctx, + sqlCommand, + map[string]string{ + "ON_ERROR_STOP": "on", // Abort when any one command fails. + "QUIET": "on", // Do not print successful commands to stdout. + }, + ) + log.V(1).Info("disabled", "extensionName", extensionName, "stdout", stdout, "stderr", stderr) + + return errors.Wrap(err, "custom extension deletion") + + } + return nil +} + func isBackupRunning(ctx context.Context, cl client.Reader, cr *v2.PerconaPGCluster) (bool, error) { jobList := &batchv1.JobList{} selector := labels.SelectorFromSet(map[string]string{ diff --git a/percona/extensions/uninstall.go b/percona/extensions/uninstall.go index bc9ed7f4bf..f7df15cee8 100644 --- a/percona/extensions/uninstall.go +++ b/percona/extensions/uninstall.go @@ -3,16 +3,11 @@ package extensions import ( "archive/tar" "compress/gzip" - "context" - "fmt" "io" "log" "os" "github.com/pkg/errors" - - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/postgres" ) func Uninstall(archivePath string) error { @@ -47,28 +42,3 @@ func Uninstall(archivePath string) error { return nil } - -func DisableCustomExtensionsInPostgreSQL(ctx context.Context, customExtensionsForDeletion []string, exec postgres.Executor) error { - log := logging.FromContext(ctx) - - for _, extensionName := range customExtensionsForDeletion { - - sqlCommand := fmt.Sprintf( - `SET client_min_messages = WARNING; DROP EXTENSION IF EXISTS %s;`, - extensionName, - ) - - stdout, stderr, err := exec.ExecInAllDatabases(ctx, - sqlCommand, - map[string]string{ - "ON_ERROR_STOP": "on", // Abort when any one command fails. - "QUIET": "on", // Do not print successful commands to stdout. - }, - ) - log.V(1).Info("disabled", "extensionName", extensionName, "stdout", stdout, "stderr", stderr) - - return errors.Wrap(err, "custom extension deletion") - - } - return nil -} From 0a2524ab6f87b8dc98260e11163169b324a5a049 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Mon, 9 Dec 2024 15:37:18 +0100 Subject: [PATCH 09/26] delete logs --- percona/controller/pgcluster/controller.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index d4fd4a33cf..a99b5a6d50 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -548,16 +548,11 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr if val, ok := cr.Spec.Metadata.Annotations[pNaming.AnnotationClusterCustomExtensions]; ok && val != "" { installedExtensions = strings.Split(val, ",") } - - fmt.Sprintf("Before getting crExtensions") - crExtensions := make(map[string]struct{}) for _, ext := range extensionKeys { crExtensions[ext] = struct{}{} } - fmt.Sprintf("After getting crExtensions") - // Check for missing entries in crExtensions for _, ext := range installedExtensions { // If an object exists in installedExtensions but not in crExtensions, the extension should be deleted. @@ -565,22 +560,16 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr removedExtension = append(removedExtension, ext) } } - fmt.Sprintf("After getting crExtensions %v", removedExtension) if len(removedExtension) > 0 { - fmt.Sprintf("Before remove extension check") var exec postgres.Executor - fmt.Sprintf("After executor") err := DisableCustomExtensionsInPostgreSQL(ctx, removedExtension, exec) if err != nil { return errors.Wrap(err, "custom extension deletion") } } - fmt.Sprintf("After remove extension check") cr.Spec.Metadata.Annotations[pNaming.AnnotationClusterCustomExtensions] = strings.Join(extensionKeys, ",") - fmt.Sprintf("After annotations update") - } for i := 0; i < len(cr.Spec.InstanceSets); i++ { From e174f7b9b9df22f3288d10f6f0e607197bf2d72a Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Mon, 9 Dec 2024 18:29:51 +0100 Subject: [PATCH 10/26] update conditions --- percona/controller/pgcluster/controller.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index a99b5a6d50..932cd11329 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -544,10 +544,14 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr var removedExtension []string // list of installed custom extensions var installedExtensions []string - - if val, ok := cr.Spec.Metadata.Annotations[pNaming.AnnotationClusterCustomExtensions]; ok && val != "" { - installedExtensions = strings.Split(val, ",") + if cr.Spec.Metadata != nil && cr.Spec.Metadata.Annotations != nil { + if val, ok := cr.Spec.Metadata.Annotations[pNaming.AnnotationClusterCustomExtensions]; ok && val != "" { + installedExtensions = strings.Split(val, ",") + } + } else { + return errors.Wrap(nil, "custom extension don't use") } + crExtensions := make(map[string]struct{}) for _, ext := range extensionKeys { crExtensions[ext] = struct{}{} @@ -563,6 +567,9 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr if len(removedExtension) > 0 { var exec postgres.Executor + if exec == nil { + return errors.New("executor is nil") + } err := DisableCustomExtensionsInPostgreSQL(ctx, removedExtension, exec) if err != nil { return errors.Wrap(err, "custom extension deletion") From a4c54f2945fcb4a52c8ebd6aae0c2e8fdd52a182 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Thu, 12 Dec 2024 14:02:13 +0100 Subject: [PATCH 11/26] update annotations adding --- percona/controller/pgcluster/controller.go | 53 ++++++++++++---------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index 932cd11329..78a6daa865 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -529,6 +529,7 @@ func (r *PGClusterReconciler) handleMonitorUserPassChange(ctx context.Context, c } func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr *v2.PerconaPGCluster) error { + log := logging.FromContext(ctx).WithValues("cluster", cr.Name, "namespace", cr.Namespace) if cr.Spec.Extensions.Storage.Secret == nil { return nil } @@ -538,7 +539,7 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr key := extensions.GetExtensionKey(cr.Spec.PostgresVersion, extension.Name, extension.Version) extensionKeys = append(extensionKeys, key) } - + log.Info("List of extension keys", "extensionKeys", extensionKeys) if cr.CompareVersion("2.6.0") >= 0 { // custom extensions to be removed var removedExtension []string @@ -548,37 +549,41 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr if val, ok := cr.Spec.Metadata.Annotations[pNaming.AnnotationClusterCustomExtensions]; ok && val != "" { installedExtensions = strings.Split(val, ",") } - } else { - return errors.Wrap(nil, "custom extension don't use") - } + crExtensions := make(map[string]struct{}) + for _, ext := range extensionKeys { + crExtensions[ext] = struct{}{} + } - crExtensions := make(map[string]struct{}) - for _, ext := range extensionKeys { - crExtensions[ext] = struct{}{} - } + // Check for missing entries in crExtensions + for _, ext := range installedExtensions { + log.Info("Test extensions installedExt") + // If an object exists in installedExtensions but not in crExtensions, the extension should be deleted. + if _, exists := crExtensions[ext]; !exists { + removedExtension = append(removedExtension, strings.Split(ext, "-")[0]) + } + } + log.Info("Test extensions installedExt", "removedExtension", removedExtension) - // Check for missing entries in crExtensions - for _, ext := range installedExtensions { - // If an object exists in installedExtensions but not in crExtensions, the extension should be deleted. - if _, exists := crExtensions[ext]; !exists { - removedExtension = append(removedExtension, ext) + if len(removedExtension) > 0 { + var exec postgres.Executor + if exec == nil { + return errors.New("executor is nil") + } + err := DisableCustomExtensionsInPostgreSQL(ctx, removedExtension, exec) + if err != nil { + return errors.Wrap(err, "custom extension deletion") + } } } + if cr.Spec.Metadata == nil { + cr.Spec.Metadata = new(v1beta1.Metadata) + } - if len(removedExtension) > 0 { - var exec postgres.Executor - if exec == nil { - return errors.New("executor is nil") - } - err := DisableCustomExtensionsInPostgreSQL(ctx, removedExtension, exec) - if err != nil { - return errors.Wrap(err, "custom extension deletion") - } + if cr.Spec.Metadata.Annotations == nil { + cr.Spec.Metadata.Annotations = make(map[string]string) } cr.Spec.Metadata.Annotations[pNaming.AnnotationClusterCustomExtensions] = strings.Join(extensionKeys, ",") - } - for i := 0; i < len(cr.Spec.InstanceSets); i++ { set := &cr.Spec.InstanceSets[i] set.InitContainers = append(set.InitContainers, extensions.ExtensionRelocatorContainer( From fbe03d370a15710b00e9b052aad462c2ef66141f Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Mon, 16 Dec 2024 09:38:40 +0100 Subject: [PATCH 12/26] use status instead of annotations --- .../pgv2.percona.com_perconapgclusters.yaml | 4 ++ .../pgv2.percona.com_perconapgclusters.yaml | 4 ++ deploy/bundle.yaml | 4 ++ deploy/crd.yaml | 4 ++ deploy/cw-bundle.yaml | 4 ++ percona/controller/pgcluster/controller.go | 58 ++++++++----------- percona/controller/pgcluster/status.go | 8 ++- percona/naming/annotations.go | 3 - .../v2/perconapgcluster_types.go | 4 ++ .../v2/zz_generated.deepcopy.go | 5 ++ 10 files changed, 59 insertions(+), 39 deletions(-) diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index 7a6c7f7ad0..8528b8d18c 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -17384,6 +17384,10 @@ spec: properties: host: type: string + installedCustomExtensions: + items: + type: string + type: array pgbouncer: properties: ready: diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index b97a1cdedb..5ae7583760 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -17790,6 +17790,10 @@ spec: properties: host: type: string + installedCustomExtensions: + items: + type: string + type: array pgbouncer: properties: ready: diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index b5004710e8..fc6bf156f0 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -18083,6 +18083,10 @@ spec: properties: host: type: string + installedCustomExtensions: + items: + type: string + type: array pgbouncer: properties: ready: diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 581367b96d..d0d3ac7a89 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -18083,6 +18083,10 @@ spec: properties: host: type: string + installedCustomExtensions: + items: + type: string + type: array pgbouncer: properties: ready: diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index b80c54851d..f37839c59b 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -18083,6 +18083,10 @@ spec: properties: host: type: string + installedCustomExtensions: + items: + type: string + type: array pgbouncer: properties: ready: diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index 78a6daa865..3936b35235 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -529,61 +529,49 @@ func (r *PGClusterReconciler) handleMonitorUserPassChange(ctx context.Context, c } func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr *v2.PerconaPGCluster) error { - log := logging.FromContext(ctx).WithValues("cluster", cr.Name, "namespace", cr.Namespace) if cr.Spec.Extensions.Storage.Secret == nil { return nil } extensionKeys := make([]string, 0) + extensionNames := make([]string, 0) + for _, extension := range cr.Spec.Extensions.Custom { key := extensions.GetExtensionKey(cr.Spec.PostgresVersion, extension.Name, extension.Version) extensionKeys = append(extensionKeys, key) + extensionNames = append(extensionNames, extension.Name) } - log.Info("List of extension keys", "extensionKeys", extensionKeys) + if cr.CompareVersion("2.6.0") >= 0 { // custom extensions to be removed var removedExtension []string // list of installed custom extensions var installedExtensions []string - if cr.Spec.Metadata != nil && cr.Spec.Metadata.Annotations != nil { - if val, ok := cr.Spec.Metadata.Annotations[pNaming.AnnotationClusterCustomExtensions]; ok && val != "" { - installedExtensions = strings.Split(val, ",") - } - crExtensions := make(map[string]struct{}) - for _, ext := range extensionKeys { - crExtensions[ext] = struct{}{} + installedExtensions = cr.Status.InstalledCustomExtensions + crExtensions := make(map[string]struct{}) + for _, ext := range extensionNames { + crExtensions[ext] = struct{}{} + } + // Check for missing entries in crExtensions + for _, ext := range installedExtensions { + // If an object exists in installedExtensions but not in crExtensions, the extension should be deleted. + if _, exists := crExtensions[ext]; !exists { + removedExtension = append(removedExtension, ext) } + } - // Check for missing entries in crExtensions - for _, ext := range installedExtensions { - log.Info("Test extensions installedExt") - // If an object exists in installedExtensions but not in crExtensions, the extension should be deleted. - if _, exists := crExtensions[ext]; !exists { - removedExtension = append(removedExtension, strings.Split(ext, "-")[0]) - } + if len(removedExtension) > 0 { + var exec postgres.Executor + if exec == nil { + return errors.New("executor is nil") } - log.Info("Test extensions installedExt", "removedExtension", removedExtension) - - if len(removedExtension) > 0 { - var exec postgres.Executor - if exec == nil { - return errors.New("executor is nil") - } - err := DisableCustomExtensionsInPostgreSQL(ctx, removedExtension, exec) - if err != nil { - return errors.Wrap(err, "custom extension deletion") - } + err := DisableCustomExtensionsInPostgreSQL(ctx, removedExtension, exec) + if err != nil { + return errors.Wrap(err, "custom extension deletion") } } - if cr.Spec.Metadata == nil { - cr.Spec.Metadata = new(v1beta1.Metadata) - } - - if cr.Spec.Metadata.Annotations == nil { - cr.Spec.Metadata.Annotations = make(map[string]string) - } - cr.Spec.Metadata.Annotations[pNaming.AnnotationClusterCustomExtensions] = strings.Join(extensionKeys, ",") } + for i := 0; i < len(cr.Spec.InstanceSets); i++ { set := &cr.Spec.InstanceSets[i] set.InitContainers = append(set.InitContainers, extensions.ExtensionRelocatorContainer( diff --git a/percona/controller/pgcluster/status.go b/percona/controller/pgcluster/status.go index 477fe2a604..cc1ce40964 100644 --- a/percona/controller/pgcluster/status.go +++ b/percona/controller/pgcluster/status.go @@ -2,7 +2,6 @@ package pgcluster import ( "context" - "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" @@ -78,6 +77,11 @@ func (r *PGClusterReconciler) updateStatus(ctx context.Context, cr *v2.PerconaPG return errors.Wrap(err, "get app host") } + installedCustomExtensions := make([]string, 0) + for _, extension := range cr.Spec.Extensions.Custom { + installedCustomExtensions = append(installedCustomExtensions, extension.Name) + } + var size, ready int32 ss := make([]v2.PostgresInstanceSetStatus, 0, len(status.InstanceSets)) for _, is := range status.InstanceSets { @@ -111,6 +115,8 @@ func (r *PGClusterReconciler) updateStatus(ctx context.Context, cr *v2.PerconaPG Ready: status.Proxy.PGBouncer.ReadyReplicas, }, Host: host, + + InstalledCustomExtensions: installedCustomExtensions, } cluster.Status.State = r.getState(cr, &cluster.Status, status) diff --git a/percona/naming/annotations.go b/percona/naming/annotations.go index 8c04c4ef16..0a861e606d 100644 --- a/percona/naming/annotations.go +++ b/percona/naming/annotations.go @@ -46,9 +46,6 @@ const ( // AnnotationClusterBootstrapRestore is the annotation that is added to PerconaPGRestore to // indicate that it is a cluster bootstrap restore. AnnotationClusterBootstrapRestore = AnnotationPrefix + "cluster-bootstrap-restore" - - //AnnotationClusterCustomExtension is annotation that added to pg cluster to handle the list of custom extensions. - AnnotationClusterCustomExtensions = AnnotationPrefix + "custom_extensions" ) func ToCrunchyAnnotation(annotation string) string { diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index b7f063ebf6..d2a9340099 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -393,6 +393,10 @@ type PerconaPGClusterStatus struct { // +optional // +operator-sdk:csv:customresourcedefinitions:type=status Host string `json:"host"` + + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=status + InstalledCustomExtensions []string `json:"installedCustomExtensions"` } type Backups struct { diff --git a/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go b/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go index 2b4951b9cc..857869fcc5 100644 --- a/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go +++ b/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go @@ -747,6 +747,11 @@ func (in *PerconaPGClusterStatus) DeepCopyInto(out *PerconaPGClusterStatus) { *out = *in in.Postgres.DeepCopyInto(&out.Postgres) out.PGBouncer = in.PGBouncer + if in.InstalledCustomExtensions != nil { + in, out := &in.InstalledCustomExtensions, &out.InstalledCustomExtensions + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PerconaPGClusterStatus. From b6ce78d697efb8af7902074d528b4e406142e9f6 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Tue, 17 Dec 2024 19:04:43 +0100 Subject: [PATCH 13/26] fix PR --- percona/controller/pgcluster/controller.go | 78 +++++++++++++++++++--- 1 file changed, 68 insertions(+), 10 deletions(-) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index 3936b35235..6d19d9a043 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -4,6 +4,8 @@ import ( "context" "crypto/md5" "fmt" + "github.com/percona/percona-postgresql-operator/internal/controller/runtime" + "io" "reflect" "strings" "time" @@ -51,8 +53,12 @@ const ( // Reconciler holds resources for the PerconaPGCluster reconciler type PGClusterReconciler struct { - Client client.Client - Owner client.FieldOwner + Client client.Client + Owner client.FieldOwner + PodExec func( + ctx context.Context, namespace, pod, container string, + stdin io.Reader, stdout, stderr io.Writer, command ...string, + ) error Recorder record.EventRecorder Tracer trace.Tracer Platform string @@ -67,6 +73,13 @@ type PGClusterReconciler struct { // SetupWithManager adds the PerconaPGCluster controller to the provided runtime manager func (r *PGClusterReconciler) SetupWithManager(mgr manager.Manager) error { + if r.PodExec == nil { + var err error + r.PodExec, err = runtime.NewPodExecutor(mgr.GetConfig()) + if err != nil { + return err + } + } if err := r.CrunchyController.Watch(source.Kind(mgr.GetCache(), &corev1.Secret{}, r.watchSecrets())); err != nil { return errors.Wrap(err, "unable to watch secrets") } @@ -243,7 +256,7 @@ func (r *PGClusterReconciler) Reconcile(ctx context.Context, request reconcile.R return reconcile.Result{}, errors.Wrap(err, "failed to handle monitor user password change") } - if err := r.reconcileCustomExtensions(ctx, cr); err != nil { + if err := r.reconcileCustomExtensions(ctx, cr, postgresCluster); err != nil { return reconcile.Result{}, errors.Wrap(err, "reconcile custom extensions") } @@ -528,7 +541,13 @@ func (r *PGClusterReconciler) handleMonitorUserPassChange(ctx context.Context, c return nil } -func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr *v2.PerconaPGCluster) error { +func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr *v2.PerconaPGCluster, postgresCluster *v1beta1.PostgresCluster) error { + log := logging.FromContext(ctx).WithValues("cluster", cr.Name, "namespace", cr.Namespace) + + if err := r.Client.Get(ctx, client.ObjectKeyFromObject(postgresCluster), postgresCluster); err != nil { + return errors.Wrap(err, "get PostgresCluster") + } + if cr.Spec.Extensions.Storage.Secret == nil { return nil } @@ -559,15 +578,27 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr removedExtension = append(removedExtension, ext) } } + log.Info("Extension to delete", "removedExtension", removedExtension) if len(removedExtension) > 0 { - var exec postgres.Executor - if exec == nil { - return errors.New("executor is nil") + + log.Info("Try to delete extension") + action := func(ctx context.Context, exec postgres.Executor) error { + return errors.WithStack(DisableCustomExtensionsInPostgreSQL(ctx, exec, removedExtension)) + } + //pod := getWritableInstance(ctx, postgresCluster) + + primary, err := getPrimaryPod(ctx, r.Client, cr) + + if primary == nil { + return errors.New("Pod is nil") } - err := DisableCustomExtensionsInPostgreSQL(ctx, removedExtension, exec) + + err = action(ctx, func(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer, command ...string) error { + return r.PodExec(ctx, primary.Namespace, primary.Name, naming.ContainerDatabase, stdin, stdout, stderr, command...) + }) if err != nil { - return errors.Wrap(err, "custom extension deletion") + return errors.Wrap(err, "deletion extension from installed") } } } @@ -589,7 +620,7 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr return nil } -func DisableCustomExtensionsInPostgreSQL(ctx context.Context, customExtensionsForDeletion []string, exec postgres.Executor) error { +func DisableCustomExtensionsInPostgreSQL(ctx context.Context, exec postgres.Executor, customExtensionsForDeletion []string) error { log := logging.FromContext(ctx) for _, extensionName := range customExtensionsForDeletion { @@ -599,6 +630,8 @@ func DisableCustomExtensionsInPostgreSQL(ctx context.Context, customExtensionsFo extensionName, ) + log.Info("sqlCommand", "command", sqlCommand) + stdout, stderr, err := exec.ExecInAllDatabases(ctx, sqlCommand, map[string]string{ @@ -606,6 +639,7 @@ func DisableCustomExtensionsInPostgreSQL(ctx context.Context, customExtensionsFo "QUIET": "on", // Do not print successful commands to stdout. }, ) + log.V(1).Info("disabled", "extensionName", extensionName, "stdout", stdout, "stderr", stderr) return errors.Wrap(err, "custom extension deletion") @@ -722,3 +756,27 @@ func (r *PGClusterReconciler) ensureFinalizers(ctx context.Context, cr *v2.Perco return nil } + +func getPrimaryPod(ctx context.Context, cli client.Client, cr *v2.PerconaPGCluster) (*corev1.Pod, error) { + podList := &corev1.PodList{} + err := cli.List(ctx, podList, &client.ListOptions{ + Namespace: cr.Namespace, + LabelSelector: labels.SelectorFromSet(map[string]string{ + "app.kubernetes.io/instance": cr.Name, + "postgres-operator.crunchydata.com/role": "master", + }), + }) + if err != nil { + return nil, err + } + + if len(podList.Items) == 0 { + return nil, errors.New("no primary pod found") + } + + if len(podList.Items) > 1 { + return nil, errors.New("multiple primary pods found") + } + + return &podList.Items[0], nil +} From bbf10e08e39e41b3d25793e9a953c0aa45b6b92f Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Tue, 17 Dec 2024 19:07:34 +0100 Subject: [PATCH 14/26] delete unused logs --- percona/controller/pgcluster/controller.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index 6d19d9a043..db14a76f2f 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -582,11 +582,9 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr if len(removedExtension) > 0 { - log.Info("Try to delete extension") action := func(ctx context.Context, exec postgres.Executor) error { return errors.WithStack(DisableCustomExtensionsInPostgreSQL(ctx, exec, removedExtension)) } - //pod := getWritableInstance(ctx, postgresCluster) primary, err := getPrimaryPod(ctx, r.Client, cr) @@ -630,8 +628,6 @@ func DisableCustomExtensionsInPostgreSQL(ctx context.Context, exec postgres.Exec extensionName, ) - log.Info("sqlCommand", "command", sqlCommand) - stdout, stderr, err := exec.ExecInAllDatabases(ctx, sqlCommand, map[string]string{ From 061f592d5b10c50aca25188a310874c3c833f167 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Wed, 18 Dec 2024 12:50:38 +0100 Subject: [PATCH 15/26] fix PR comments --- percona/controller/pgcluster/controller.go | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index db14a76f2f..bbff4bd609 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -256,7 +256,7 @@ func (r *PGClusterReconciler) Reconcile(ctx context.Context, request reconcile.R return reconcile.Result{}, errors.Wrap(err, "failed to handle monitor user password change") } - if err := r.reconcileCustomExtensions(ctx, cr, postgresCluster); err != nil { + if err := r.reconcileCustomExtensions(ctx, cr); err != nil { return reconcile.Result{}, errors.Wrap(err, "reconcile custom extensions") } @@ -541,13 +541,9 @@ func (r *PGClusterReconciler) handleMonitorUserPassChange(ctx context.Context, c return nil } -func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr *v2.PerconaPGCluster, postgresCluster *v1beta1.PostgresCluster) error { +func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr *v2.PerconaPGCluster) error { log := logging.FromContext(ctx).WithValues("cluster", cr.Name, "namespace", cr.Namespace) - if err := r.Client.Get(ctx, client.ObjectKeyFromObject(postgresCluster), postgresCluster); err != nil { - return errors.Wrap(err, "get PostgresCluster") - } - if cr.Spec.Extensions.Storage.Secret == nil { return nil } @@ -574,7 +570,7 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr // Check for missing entries in crExtensions for _, ext := range installedExtensions { // If an object exists in installedExtensions but not in crExtensions, the extension should be deleted. - if _, exists := crExtensions[ext]; !exists { + if _, ok := crExtensions[ext]; !ok { removedExtension = append(removedExtension, ext) } } @@ -583,7 +579,7 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr if len(removedExtension) > 0 { action := func(ctx context.Context, exec postgres.Executor) error { - return errors.WithStack(DisableCustomExtensionsInPostgreSQL(ctx, exec, removedExtension)) + return errors.WithStack(DisableCustomExtensionsInDb(ctx, exec, removedExtension)) } primary, err := getPrimaryPod(ctx, r.Client, cr) @@ -618,7 +614,7 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr return nil } -func DisableCustomExtensionsInPostgreSQL(ctx context.Context, exec postgres.Executor, customExtensionsForDeletion []string) error { +func DisableCustomExtensionsInDb(ctx context.Context, exec postgres.Executor, customExtensionsForDeletion []string) error { log := logging.FromContext(ctx) for _, extensionName := range customExtensionsForDeletion { From a74161a19b0a7e4cf2c0dc78e74578f3195e1e89 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Wed, 18 Dec 2024 15:29:05 +0100 Subject: [PATCH 16/26] fix PR comments --- percona/controller/pgcluster/controller.go | 60 +++++----------------- percona/controller/pgcluster/status.go | 3 +- percona/postgres/common.go | 36 +++++++++++++ percona/watcher/wal.go | 31 ++--------- 4 files changed, 54 insertions(+), 76 deletions(-) create mode 100644 percona/postgres/common.go diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index bbff4bd609..b54455e01d 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -4,14 +4,11 @@ import ( "context" "crypto/md5" "fmt" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" "io" "reflect" "strings" "time" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/pkg/errors" "go.opentelemetry.io/otel/trace" batchv1 "k8s.io/api/batch/v1" @@ -33,13 +30,16 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/source" + "github.com/percona/percona-postgresql-operator/internal/controller/runtime" "github.com/percona/percona-postgresql-operator/internal/logging" "github.com/percona/percona-postgresql-operator/internal/naming" + "github.com/percona/percona-postgresql-operator/internal/postgres" perconaController "github.com/percona/percona-postgresql-operator/percona/controller" "github.com/percona/percona-postgresql-operator/percona/extensions" "github.com/percona/percona-postgresql-operator/percona/k8s" pNaming "github.com/percona/percona-postgresql-operator/percona/naming" "github.com/percona/percona-postgresql-operator/percona/pmm" + common "github.com/percona/percona-postgresql-operator/percona/postgres" "github.com/percona/percona-postgresql-operator/percona/utils/registry" "github.com/percona/percona-postgresql-operator/percona/watcher" v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" @@ -542,8 +542,6 @@ func (r *PGClusterReconciler) handleMonitorUserPassChange(ctx context.Context, c } func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr *v2.PerconaPGCluster) error { - log := logging.FromContext(ctx).WithValues("cluster", cr.Name, "namespace", cr.Namespace) - if cr.Spec.Extensions.Storage.Secret == nil { return nil } @@ -558,15 +556,13 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr } if cr.CompareVersion("2.6.0") >= 0 { - // custom extensions to be removed var removedExtension []string - // list of installed custom extensions - var installedExtensions []string - installedExtensions = cr.Status.InstalledCustomExtensions + installedExtensions := cr.Status.InstalledCustomExtensions crExtensions := make(map[string]struct{}) for _, ext := range extensionNames { crExtensions[ext] = struct{}{} } + // Check for missing entries in crExtensions for _, ext := range installedExtensions { // If an object exists in installedExtensions but not in crExtensions, the extension should be deleted. @@ -574,21 +570,19 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr removedExtension = append(removedExtension, ext) } } - log.Info("Extension to delete", "removedExtension", removedExtension) if len(removedExtension) > 0 { - action := func(ctx context.Context, exec postgres.Executor) error { - return errors.WithStack(DisableCustomExtensionsInDb(ctx, exec, removedExtension)) + disabled := func(ctx context.Context, exec postgres.Executor) error { + return errors.WithStack(disableCustomExtensionsInDB(ctx, exec, removedExtension)) } - primary, err := getPrimaryPod(ctx, r.Client, cr) - - if primary == nil { - return errors.New("Pod is nil") + primary, err := common.GetPrimaryPod(ctx, r.Client, cr) + if err != nil { + return errors.New("primary pod not found") } - err = action(ctx, func(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer, command ...string) error { + err = disabled(ctx, func(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer, command ...string) error { return r.PodExec(ctx, primary.Namespace, primary.Name, naming.ContainerDatabase, stdin, stdout, stderr, command...) }) if err != nil { @@ -614,16 +608,14 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr return nil } -func DisableCustomExtensionsInDb(ctx context.Context, exec postgres.Executor, customExtensionsForDeletion []string) error { +func disableCustomExtensionsInDB(ctx context.Context, exec postgres.Executor, customExtensionsForDeletion []string) error { log := logging.FromContext(ctx) for _, extensionName := range customExtensionsForDeletion { - sqlCommand := fmt.Sprintf( `SET client_min_messages = WARNING; DROP EXTENSION IF EXISTS %s;`, extensionName, ) - stdout, stderr, err := exec.ExecInAllDatabases(ctx, sqlCommand, map[string]string{ @@ -632,11 +624,11 @@ func DisableCustomExtensionsInDb(ctx context.Context, exec postgres.Executor, cu }, ) - log.V(1).Info("disabled", "extensionName", extensionName, "stdout", stdout, "stderr", stderr) + log.V(1).Info("extension was disabled ", "extensionName", extensionName) return errors.Wrap(err, "custom extension deletion") - } + return nil } @@ -748,27 +740,3 @@ func (r *PGClusterReconciler) ensureFinalizers(ctx context.Context, cr *v2.Perco return nil } - -func getPrimaryPod(ctx context.Context, cli client.Client, cr *v2.PerconaPGCluster) (*corev1.Pod, error) { - podList := &corev1.PodList{} - err := cli.List(ctx, podList, &client.ListOptions{ - Namespace: cr.Namespace, - LabelSelector: labels.SelectorFromSet(map[string]string{ - "app.kubernetes.io/instance": cr.Name, - "postgres-operator.crunchydata.com/role": "master", - }), - }) - if err != nil { - return nil, err - } - - if len(podList.Items) == 0 { - return nil, errors.New("no primary pod found") - } - - if len(podList.Items) > 1 { - return nil, errors.New("multiple primary pods found") - } - - return &podList.Items[0], nil -} diff --git a/percona/controller/pgcluster/status.go b/percona/controller/pgcluster/status.go index cc1ce40964..30123abd6a 100644 --- a/percona/controller/pgcluster/status.go +++ b/percona/controller/pgcluster/status.go @@ -114,8 +114,7 @@ func (r *PGClusterReconciler) updateStatus(ctx context.Context, cr *v2.PerconaPG Size: status.Proxy.PGBouncer.Replicas, Ready: status.Proxy.PGBouncer.ReadyReplicas, }, - Host: host, - + Host: host, InstalledCustomExtensions: installedCustomExtensions, } diff --git a/percona/postgres/common.go b/percona/postgres/common.go new file mode 100644 index 0000000000..a5e1120e7d --- /dev/null +++ b/percona/postgres/common.go @@ -0,0 +1,36 @@ +package postgres + +import ( + "context" + + "github.com/pkg/errors" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/labels" + "sigs.k8s.io/controller-runtime/pkg/client" + + v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" +) + +func GetPrimaryPod(ctx context.Context, cli client.Client, cr *v2.PerconaPGCluster) (*corev1.Pod, error) { + podList := &corev1.PodList{} + err := cli.List(ctx, podList, &client.ListOptions{ + Namespace: cr.Namespace, + LabelSelector: labels.SelectorFromSet(map[string]string{ + "app.kubernetes.io/instance": cr.Name, + "postgres-operator.crunchydata.com/role": "master", + }), + }) + if err != nil { + return nil, err + } + + if len(podList.Items) == 0 { + return nil, errors.New("no primary pod found") + } + + if len(podList.Items) > 1 { + return nil, errors.New("multiple primary pods found") + } + + return &podList.Items[0], nil +} diff --git a/percona/watcher/wal.go b/percona/watcher/wal.go index 65787d1b3b..3542036ffd 100644 --- a/percona/watcher/wal.go +++ b/percona/watcher/wal.go @@ -7,16 +7,15 @@ import ( "time" "github.com/pkg/errors" - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" - "k8s.io/apimachinery/pkg/labels" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" "github.com/percona/percona-postgresql-operator/internal/logging" "github.com/percona/percona-postgresql-operator/percona/clientcmd" "github.com/percona/percona-postgresql-operator/percona/pgbackrest" + common "github.com/percona/percona-postgresql-operator/percona/postgres" pgv2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" ) @@ -153,7 +152,7 @@ func getLatestBackup(ctx context.Context, cli client.Client, cr *pgv2.PerconaPGC func GetLatestCommitTimestamp(ctx context.Context, cli client.Client, execCli *clientcmd.Client, cr *pgv2.PerconaPGCluster, backup *pgv2.PerconaPGBackup) (*metav1.Time, error) { log := logging.FromContext(ctx) - primary, err := getPrimaryPod(ctx, cli, cr) + primary, err := common.GetPrimaryPod(ctx, cli, cr) if err != nil { return nil, PrimaryPodNotFound } @@ -188,32 +187,8 @@ func GetLatestCommitTimestamp(ctx context.Context, cli client.Client, execCli *c return &commitTsMeta, nil } -func getPrimaryPod(ctx context.Context, cli client.Client, cr *pgv2.PerconaPGCluster) (*corev1.Pod, error) { - podList := &corev1.PodList{} - err := cli.List(ctx, podList, &client.ListOptions{ - Namespace: cr.Namespace, - LabelSelector: labels.SelectorFromSet(map[string]string{ - "app.kubernetes.io/instance": cr.Name, - "postgres-operator.crunchydata.com/role": "master", - }), - }) - if err != nil { - return nil, err - } - - if len(podList.Items) == 0 { - return nil, errors.New("no primary pod found") - } - - if len(podList.Items) > 1 { - return nil, errors.New("multiple primary pods found") - } - - return &podList.Items[0], nil -} - func getBackupStartTimestamp(ctx context.Context, cli client.Client, cr *pgv2.PerconaPGCluster, backup *pgv2.PerconaPGBackup) (time.Time, error) { - primary, err := getPrimaryPod(ctx, cli, cr) + primary, err := common.GetPrimaryPod(ctx, cli, cr) if err != nil { return time.Time{}, PrimaryPodNotFound } From bd04f98cd95e5dd9caf6956f128b2a8f9090ef5c Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Wed, 18 Dec 2024 15:32:48 +0100 Subject: [PATCH 17/26] fix PR comments --- percona/controller/pgcluster/controller.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index b54455e01d..c1ed7d72d0 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -616,7 +616,7 @@ func disableCustomExtensionsInDB(ctx context.Context, exec postgres.Executor, cu `SET client_min_messages = WARNING; DROP EXTENSION IF EXISTS %s;`, extensionName, ) - stdout, stderr, err := exec.ExecInAllDatabases(ctx, + _, _, err := exec.ExecInAllDatabases(ctx, sqlCommand, map[string]string{ "ON_ERROR_STOP": "on", // Abort when any one command fails. From f9ea7892aa3335ecdb79a6ff2cbbd65f0784853a Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Wed, 18 Dec 2024 18:09:43 +0100 Subject: [PATCH 18/26] fix test --- .../tests/custom-extensions/09-check-installed-extensions.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/tests/custom-extensions/09-check-installed-extensions.yaml b/e2e-tests/tests/custom-extensions/09-check-installed-extensions.yaml index 7cbb0f581a..c8ef72f247 100644 --- a/e2e-tests/tests/custom-extensions/09-check-installed-extensions.yaml +++ b/e2e-tests/tests/custom-extensions/09-check-installed-extensions.yaml @@ -8,6 +8,6 @@ commands: source ../../functions - data=$(kubectl -n ${NAMESPACE} exec $(get_client_pod) -- psql -v ON_ERROR_STOP=1 -t -q postgres://postgres:$(get_psql_user_pass custom-extensions-pguser-postgres)@$(get_psql_user_host custom-extensions-pguser-postgres) -c "\c postgres" -c "select name from pg_extensions order by name") + data=$(kubectl -n ${NAMESPACE} exec $(get_client_pod) -- psql -v ON_ERROR_STOP=1 -t -q postgres://postgres:$(get_psql_user_pass custom-extensions-pguser-postgres)@$(get_psql_user_host custom-extensions-pguser-postgres) -c "\c postgres" -c "select name from pg_extensions order by extname") kubectl create configmap -n "${NAMESPACE}" 10-check-extensions --from-literal=data="${data}" From 37b3e4ec4b19cb42580bd48910d542cb5bac738a Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Thu, 19 Dec 2024 09:51:07 +0100 Subject: [PATCH 19/26] fix the test --- .../tests/custom-extensions/09-check-installed-extensions.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/tests/custom-extensions/09-check-installed-extensions.yaml b/e2e-tests/tests/custom-extensions/09-check-installed-extensions.yaml index c8ef72f247..4bc3a92fd2 100644 --- a/e2e-tests/tests/custom-extensions/09-check-installed-extensions.yaml +++ b/e2e-tests/tests/custom-extensions/09-check-installed-extensions.yaml @@ -8,6 +8,6 @@ commands: source ../../functions - data=$(kubectl -n ${NAMESPACE} exec $(get_client_pod) -- psql -v ON_ERROR_STOP=1 -t -q postgres://postgres:$(get_psql_user_pass custom-extensions-pguser-postgres)@$(get_psql_user_host custom-extensions-pguser-postgres) -c "\c postgres" -c "select name from pg_extensions order by extname") + data=$(kubectl -n ${NAMESPACE} exec $(get_client_pod) -- psql -v ON_ERROR_STOP=1 -t -q postgres://postgres:$(get_psql_user_pass custom-extensions-pguser-postgres)@$(get_psql_user_host custom-extensions-pguser-postgres) -c "\c postgres" -c "select extname from pg_extensions order by extname") kubectl create configmap -n "${NAMESPACE}" 10-check-extensions --from-literal=data="${data}" From c688307102d7823c40c10b85e14328bbb6473b5d Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Thu, 19 Dec 2024 10:37:38 +0100 Subject: [PATCH 20/26] fix vulnarabilities --- go.mod | 4 ++-- go.sum | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index ca34d23a04..848ae099d2 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( go.opentelemetry.io/otel/sdk v1.32.0 go.opentelemetry.io/otel/trace v1.32.0 go.uber.org/zap v1.27.0 - golang.org/x/crypto v0.30.0 + golang.org/x/crypto v0.31.0 google.golang.org/grpc v1.68.1 gotest.tools/v3 v3.5.1 k8s.io/api v0.31.3 @@ -110,7 +110,7 @@ require ( go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect - golang.org/x/net v0.30.0 // indirect + golang.org/x/net v0.33.0 // indirect golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/sys v0.28.0 // indirect diff --git a/go.sum b/go.sum index 8cfce5cd88..b1fc33cf13 100644 --- a/go.sum +++ b/go.sum @@ -267,6 +267,7 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= @@ -289,6 +290,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= From ed21ea6fef7aeb9fb66b95a38a39f48b42fd710a Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Thu, 19 Dec 2024 13:04:29 +0100 Subject: [PATCH 21/26] update test --- e2e-tests/tests/custom-extensions/09-assert.yaml | 2 +- .../custom-extensions/09-check-installed-extensions.yaml | 2 +- percona/controller/pgcluster/controller.go | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/e2e-tests/tests/custom-extensions/09-assert.yaml b/e2e-tests/tests/custom-extensions/09-assert.yaml index 248fb9f19e..edd94c0f88 100644 --- a/e2e-tests/tests/custom-extensions/09-assert.yaml +++ b/e2e-tests/tests/custom-extensions/09-assert.yaml @@ -5,7 +5,7 @@ timeout: 30 kind: ConfigMap apiVersion: v1 metadata: - name: 10-check-extensions + name: 11-check-extensions data: data: |2- pg_stat_monitor diff --git a/e2e-tests/tests/custom-extensions/09-check-installed-extensions.yaml b/e2e-tests/tests/custom-extensions/09-check-installed-extensions.yaml index 4bc3a92fd2..a029f4836c 100644 --- a/e2e-tests/tests/custom-extensions/09-check-installed-extensions.yaml +++ b/e2e-tests/tests/custom-extensions/09-check-installed-extensions.yaml @@ -10,4 +10,4 @@ commands: data=$(kubectl -n ${NAMESPACE} exec $(get_client_pod) -- psql -v ON_ERROR_STOP=1 -t -q postgres://postgres:$(get_psql_user_pass custom-extensions-pguser-postgres)@$(get_psql_user_host custom-extensions-pguser-postgres) -c "\c postgres" -c "select extname from pg_extensions order by extname") - kubectl create configmap -n "${NAMESPACE}" 10-check-extensions --from-literal=data="${data}" + kubectl create configmap -n "${NAMESPACE}" 11-check-extensions --from-literal=data="${data}" diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index c1ed7d72d0..73fa8cfed4 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -616,7 +616,7 @@ func disableCustomExtensionsInDB(ctx context.Context, exec postgres.Executor, cu `SET client_min_messages = WARNING; DROP EXTENSION IF EXISTS %s;`, extensionName, ) - _, _, err := exec.ExecInAllDatabases(ctx, + _, stderr, err := exec.ExecInAllDatabases(ctx, sqlCommand, map[string]string{ "ON_ERROR_STOP": "on", // Abort when any one command fails. @@ -626,7 +626,7 @@ func disableCustomExtensionsInDB(ctx context.Context, exec postgres.Executor, cu log.V(1).Info("extension was disabled ", "extensionName", extensionName) - return errors.Wrap(err, "custom extension deletion") + return errors.Wrapf(err, "custom extension deletion", "stderr: %s", stderr) } return nil From 75a337281841694efe058dd27f76f71f0c47fd0f Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Thu, 19 Dec 2024 13:43:22 +0100 Subject: [PATCH 22/26] fix logging --- percona/controller/pgcluster/controller.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index 73fa8cfed4..c1ed7d72d0 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -616,7 +616,7 @@ func disableCustomExtensionsInDB(ctx context.Context, exec postgres.Executor, cu `SET client_min_messages = WARNING; DROP EXTENSION IF EXISTS %s;`, extensionName, ) - _, stderr, err := exec.ExecInAllDatabases(ctx, + _, _, err := exec.ExecInAllDatabases(ctx, sqlCommand, map[string]string{ "ON_ERROR_STOP": "on", // Abort when any one command fails. @@ -626,7 +626,7 @@ func disableCustomExtensionsInDB(ctx context.Context, exec postgres.Executor, cu log.V(1).Info("extension was disabled ", "extensionName", extensionName) - return errors.Wrapf(err, "custom extension deletion", "stderr: %s", stderr) + return errors.Wrap(err, "custom extension deletion") } return nil From 4f86a07c554c9622505f9664b8decd3ac008d40e Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Thu, 19 Dec 2024 14:55:30 +0100 Subject: [PATCH 23/26] fix test --- .../tests/custom-extensions/09-check-installed-extensions.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/tests/custom-extensions/09-check-installed-extensions.yaml b/e2e-tests/tests/custom-extensions/09-check-installed-extensions.yaml index a029f4836c..fa5607a324 100644 --- a/e2e-tests/tests/custom-extensions/09-check-installed-extensions.yaml +++ b/e2e-tests/tests/custom-extensions/09-check-installed-extensions.yaml @@ -8,6 +8,6 @@ commands: source ../../functions - data=$(kubectl -n ${NAMESPACE} exec $(get_client_pod) -- psql -v ON_ERROR_STOP=1 -t -q postgres://postgres:$(get_psql_user_pass custom-extensions-pguser-postgres)@$(get_psql_user_host custom-extensions-pguser-postgres) -c "\c postgres" -c "select extname from pg_extensions order by extname") + data=$(kubectl -n ${NAMESPACE} exec $(get_client_pod) -- psql -v ON_ERROR_STOP=1 -t -q postgres://postgres:$(get_psql_user_pass custom-extensions-pguser-postgres)@$(get_psql_user_host custom-extensions-pguser-postgres) -c "\c postgres" -c "select extname from pg_extension order by extname") kubectl create configmap -n "${NAMESPACE}" 11-check-extensions --from-literal=data="${data}" From 4f1bac07352cefcba78bab3ddc04bf356edfa516 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Sat, 21 Dec 2024 22:50:09 +0100 Subject: [PATCH 24/26] fix PR comments --- e2e-tests/tests/custom-extensions/09-assert.yaml | 1 + percona/controller/pgcluster/controller.go | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/e2e-tests/tests/custom-extensions/09-assert.yaml b/e2e-tests/tests/custom-extensions/09-assert.yaml index edd94c0f88..1217de376b 100644 --- a/e2e-tests/tests/custom-extensions/09-assert.yaml +++ b/e2e-tests/tests/custom-extensions/09-assert.yaml @@ -10,3 +10,4 @@ data: data: |2- pg_stat_monitor pgaudit + plpgsql diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index c1ed7d72d0..53f175cfde 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -572,8 +572,7 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr } if len(removedExtension) > 0 { - - disabled := func(ctx context.Context, exec postgres.Executor) error { + disable := func(ctx context.Context, exec postgres.Executor) error { return errors.WithStack(disableCustomExtensionsInDB(ctx, exec, removedExtension)) } @@ -582,7 +581,7 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr return errors.New("primary pod not found") } - err = disabled(ctx, func(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer, command ...string) error { + err = disable(ctx, func(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer, command ...string) error { return r.PodExec(ctx, primary.Namespace, primary.Name, naming.ContainerDatabase, stdin, stdout, stderr, command...) }) if err != nil { From 07979c3ad09137e98edcccfc568d5fa30295d2ba Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Thu, 2 Jan 2025 10:52:04 +0100 Subject: [PATCH 25/26] rename package with common functions --- percona/controller/pgcluster/controller.go | 4 ++-- percona/postgres/common.go | 2 +- percona/watcher/wal.go | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index 53f175cfde..c6709f4718 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -39,7 +39,7 @@ import ( "github.com/percona/percona-postgresql-operator/percona/k8s" pNaming "github.com/percona/percona-postgresql-operator/percona/naming" "github.com/percona/percona-postgresql-operator/percona/pmm" - common "github.com/percona/percona-postgresql-operator/percona/postgres" + "github.com/percona/percona-postgresql-operator/percona/postgres" "github.com/percona/percona-postgresql-operator/percona/utils/registry" "github.com/percona/percona-postgresql-operator/percona/watcher" v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" @@ -576,7 +576,7 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr return errors.WithStack(disableCustomExtensionsInDB(ctx, exec, removedExtension)) } - primary, err := common.GetPrimaryPod(ctx, r.Client, cr) + primary, err := perconaPG.GetPrimaryPod(ctx, r.Client, cr) if err != nil { return errors.New("primary pod not found") } diff --git a/percona/postgres/common.go b/percona/postgres/common.go index a5e1120e7d..9997e05bdd 100644 --- a/percona/postgres/common.go +++ b/percona/postgres/common.go @@ -1,4 +1,4 @@ -package postgres +package perconaPG import ( "context" diff --git a/percona/watcher/wal.go b/percona/watcher/wal.go index 3542036ffd..6342f3fe83 100644 --- a/percona/watcher/wal.go +++ b/percona/watcher/wal.go @@ -15,7 +15,7 @@ import ( "github.com/percona/percona-postgresql-operator/internal/logging" "github.com/percona/percona-postgresql-operator/percona/clientcmd" "github.com/percona/percona-postgresql-operator/percona/pgbackrest" - common "github.com/percona/percona-postgresql-operator/percona/postgres" + "github.com/percona/percona-postgresql-operator/percona/postgres" pgv2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" ) @@ -152,7 +152,7 @@ func getLatestBackup(ctx context.Context, cli client.Client, cr *pgv2.PerconaPGC func GetLatestCommitTimestamp(ctx context.Context, cli client.Client, execCli *clientcmd.Client, cr *pgv2.PerconaPGCluster, backup *pgv2.PerconaPGBackup) (*metav1.Time, error) { log := logging.FromContext(ctx) - primary, err := common.GetPrimaryPod(ctx, cli, cr) + primary, err := perconaPG.GetPrimaryPod(ctx, cli, cr) if err != nil { return nil, PrimaryPodNotFound } @@ -188,7 +188,7 @@ func GetLatestCommitTimestamp(ctx context.Context, cli client.Client, execCli *c } func getBackupStartTimestamp(ctx context.Context, cli client.Client, cr *pgv2.PerconaPGCluster, backup *pgv2.PerconaPGBackup) (time.Time, error) { - primary, err := common.GetPrimaryPod(ctx, cli, cr) + primary, err := perconaPG.GetPrimaryPod(ctx, cli, cr) if err != nil { return time.Time{}, PrimaryPodNotFound } From 05a27e0644b8146327e9f6c846f47b421f526f1b Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Fri, 3 Jan 2025 09:42:00 +0100 Subject: [PATCH 26/26] fix imports --- percona/controller/pgcluster/controller.go | 2 +- percona/watcher/wal.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index c6709f4718..0539f00e81 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -39,7 +39,7 @@ import ( "github.com/percona/percona-postgresql-operator/percona/k8s" pNaming "github.com/percona/percona-postgresql-operator/percona/naming" "github.com/percona/percona-postgresql-operator/percona/pmm" - "github.com/percona/percona-postgresql-operator/percona/postgres" + perconaPG "github.com/percona/percona-postgresql-operator/percona/postgres" "github.com/percona/percona-postgresql-operator/percona/utils/registry" "github.com/percona/percona-postgresql-operator/percona/watcher" v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" diff --git a/percona/watcher/wal.go b/percona/watcher/wal.go index 6342f3fe83..797172a5fc 100644 --- a/percona/watcher/wal.go +++ b/percona/watcher/wal.go @@ -15,7 +15,7 @@ import ( "github.com/percona/percona-postgresql-operator/internal/logging" "github.com/percona/percona-postgresql-operator/percona/clientcmd" "github.com/percona/percona-postgresql-operator/percona/pgbackrest" - "github.com/percona/percona-postgresql-operator/percona/postgres" + perconaPG "github.com/percona/percona-postgresql-operator/percona/postgres" pgv2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" )