Skip to content

K8SPG-594 delete custom extensions from installed #967

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 41 commits into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
bdfa932
K8SPG-594 delete custom extensions from installed
nmarukovich Dec 2, 2024
d1c9434
update extensions check
nmarukovich Dec 2, 2024
a265b86
fix checks
nmarukovich Dec 2, 2024
d370c4a
fix checks
nmarukovich Dec 2, 2024
71c00fb
delete unused
nmarukovich Dec 2, 2024
afb1f0c
Merge branch 'main' into K8SPG-594_delete_installed_ext
nmarukovich Dec 2, 2024
6f450e1
Merge branch 'main' into K8SPG-594_delete_installed_ext
nmarukovich Dec 3, 2024
08695c6
fix PR coments
nmarukovich Dec 4, 2024
cf29171
Merge branch 'K8SPG-594_delete_installed_ext' of github.com:percona/p…
nmarukovich Dec 4, 2024
4c6bf22
fix PR comments
nmarukovich Dec 4, 2024
b6a2f72
Merge branch 'main' into K8SPG-594_delete_installed_ext
nmarukovich Dec 6, 2024
f232f36
fix PR
nmarukovich Dec 9, 2024
f3999bd
Merge branch 'K8SPG-594_delete_installed_ext' of github.com:percona/p…
nmarukovich Dec 9, 2024
0a2524a
delete logs
nmarukovich Dec 9, 2024
e174f7b
update conditions
nmarukovich Dec 9, 2024
41e0fb4
Merge branch 'main' into K8SPG-594_delete_installed_ext
nmarukovich Dec 9, 2024
08e178d
Merge branch 'main' into K8SPG-594_delete_installed_ext
nmarukovich Dec 11, 2024
a4c54f2
update annotations adding
nmarukovich Dec 12, 2024
0dc2bbd
Merge branch 'main' into K8SPG-594_delete_installed_ext
hors Dec 12, 2024
fbe03d3
use status instead of annotations
nmarukovich Dec 16, 2024
bf0818c
Merge branch 'K8SPG-594_delete_installed_ext' of github.com:percona/p…
nmarukovich Dec 16, 2024
b6ce78d
fix PR
nmarukovich Dec 17, 2024
bbf10e0
delete unused logs
nmarukovich Dec 17, 2024
061f592
fix PR comments
nmarukovich Dec 18, 2024
a74161a
fix PR comments
nmarukovich Dec 18, 2024
bd04f98
fix PR comments
nmarukovich Dec 18, 2024
f9ea789
fix test
nmarukovich Dec 18, 2024
37b3e4e
fix the test
nmarukovich Dec 19, 2024
eb26df5
Merge branch 'main' into K8SPG-594_delete_installed_ext
nmarukovich Dec 19, 2024
c688307
fix vulnarabilities
nmarukovich Dec 19, 2024
d94deba
fix vulnarabilities
nmarukovich Dec 19, 2024
ed21ea6
update test
nmarukovich Dec 19, 2024
75a3372
fix logging
nmarukovich Dec 19, 2024
4f86a07
fix test
nmarukovich Dec 19, 2024
4f1bac0
fix PR comments
nmarukovich Dec 21, 2024
7128445
Merge branch 'main' into K8SPG-594_delete_installed_ext
nmarukovich Dec 21, 2024
07979c3
rename package with common functions
nmarukovich Jan 2, 2025
a899835
Merge branch 'K8SPG-594_delete_installed_ext' of github.com:percona/p…
nmarukovich Jan 2, 2025
51242e9
Merge branch 'main' into K8SPG-594_delete_installed_ext
hors Jan 2, 2025
05a27e0
fix imports
nmarukovich Jan 3, 2025
10d9c83
Merge branch 'K8SPG-594_delete_installed_ext' of github.com:percona/p…
nmarukovich Jan 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build/postgres-operator/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
12 changes: 12 additions & 0 deletions e2e-tests/tests/custom-extensions/09-assert.yaml
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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}"
81 changes: 78 additions & 3 deletions percona/controller/pgcluster/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"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"
Expand Down Expand Up @@ -241,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)
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")
Expand Down Expand Up @@ -524,17 +528,62 @@ func (r *PGClusterReconciler) handleMonitorUserPassChange(ctx context.Context, c
return nil
}

func (r *PGClusterReconciler) reconcileCustomExtensions(cr *v2.PerconaPGCluster) {
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
return nil
}

extensionKeys := make([]string, 0)
for _, extension := range cr.Spec.Extensions.Custom {
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
// 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{}{}
}

// 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)

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 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(
Expand All @@ -549,6 +598,32 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(cr *v2.PerconaPGCluster)
))
set.VolumeMounts = append(set.VolumeMounts, extensions.ExtensionVolumeMounts(cr.Spec.PostgresVersion)...)
}
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) {
Expand Down
3 changes: 3 additions & 0 deletions percona/naming/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Loading