chore: review

Signed-off-by: Leonardo Cecchi <leonardo.cecchi@enterprisedb.com>
This commit is contained in:
Leonardo Cecchi 2024-10-04 09:20:18 +02:00
parent d11fabd2d3
commit 2e30634ec8
7 changed files with 94 additions and 35 deletions

View File

@ -0,0 +1,12 @@
apiVersion: postgresql.cnpg.io/v1
kind: Backup
metadata:
name: backup-example
spec:
method: plugin
cluster:
name: cluster-example
pluginConfiguration:
name: barman-cloud.cloudnative-pg.io

View File

@ -2,31 +2,46 @@ package instance
import ( import (
"context" "context"
"fmt"
"os" "os"
"strconv" "strconv"
"time"
barmanBackup "github.com/cloudnative-pg/barman-cloud/pkg/backup" barmanBackup "github.com/cloudnative-pg/barman-cloud/pkg/backup"
barmanCapabilities "github.com/cloudnative-pg/barman-cloud/pkg/capabilities" barmanCapabilities "github.com/cloudnative-pg/barman-cloud/pkg/capabilities"
barmanCredentials "github.com/cloudnative-pg/barman-cloud/pkg/credentials" barmanCredentials "github.com/cloudnative-pg/barman-cloud/pkg/credentials"
"github.com/cloudnative-pg/cloudnative-pg/pkg/postgres" "github.com/cloudnative-pg/cloudnative-pg/pkg/postgres"
"github.com/cloudnative-pg/cnpg-i-machinery/pkg/pluginhelper/decoder" "github.com/cloudnative-pg/cloudnative-pg/pkg/utils"
"github.com/cloudnative-pg/cnpg-i/pkg/backup" "github.com/cloudnative-pg/cnpg-i/pkg/backup"
"github.com/cloudnative-pg/machinery/pkg/fileutils" "github.com/cloudnative-pg/machinery/pkg/fileutils"
"github.com/cloudnative-pg/machinery/pkg/log" "github.com/cloudnative-pg/machinery/pkg/log"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
barmancloudv1 "github.com/cloudnative-pg/plugin-barman-cloud/api/v1"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/metadata" "github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/metadata"
) )
// BackupServiceImplementation is the implementation // BackupServiceImplementation is the implementation
// of the Backup CNPG capability // of the Backup CNPG capability
type BackupServiceImplementation struct { type BackupServiceImplementation struct {
Client client.Client BarmanObjectKey client.ObjectKey
InstanceName string ClusterObjectKey client.ObjectKey
Client client.Client
InstanceName string
backup.UnimplementedBackupServer backup.UnimplementedBackupServer
} }
// This is an implementation of the barman executor
// that always instruct the barman library to use the
// "--name" option for backups. We don't support old
// Barman versions that do not implement that option.
type barmanCloudExecutor struct{}
func (barmanCloudExecutor) ShouldForceLegacyBackup() bool {
return false
}
// GetCapabilities implements the BackupService interface // GetCapabilities implements the BackupService interface
func (b BackupServiceImplementation) GetCapabilities( func (b BackupServiceImplementation) GetCapabilities(
_ context.Context, _ *backup.BackupCapabilitiesRequest, _ context.Context, _ *backup.BackupCapabilitiesRequest,
@ -47,15 +62,12 @@ func (b BackupServiceImplementation) GetCapabilities(
// Backup implements the Backup interface // Backup implements the Backup interface
func (b BackupServiceImplementation) Backup( func (b BackupServiceImplementation) Backup(
ctx context.Context, ctx context.Context,
req *backup.BackupRequest, _ *backup.BackupRequest,
) (*backup.BackupResult, error) { ) (*backup.BackupResult, error) {
contextLogger := log.FromContext(ctx) contextLogger := log.FromContext(ctx)
backupObj, err := decoder.DecodeBackup(req.BackupDefinition)
if err != nil { var objectStore barmancloudv1.ObjectStore
return nil, err if err := b.Client.Get(ctx, b.BarmanObjectKey, &objectStore); err != nil {
}
cluster, err := decoder.DecodeClusterJSON(req.ClusterDefinition)
if err != nil {
return nil, err return nil, err
} }
@ -69,33 +81,43 @@ func (b BackupServiceImplementation) Backup(
return nil, err return nil, err
} }
backupCmd := barmanBackup.NewBackupCommand( backupCmd := barmanBackup.NewBackupCommand(
cluster.Spec.Backup.BarmanObjectStore, &objectStore.Spec.Configuration,
capabilities, capabilities,
) )
env := os.Environ()
env, err = barmanCredentials.EnvSetBackupCloudCredentials( // We need to connect to PostgreSQL and to do that we need
// PGHOST (and the like) to be available
osEnvironment := os.Environ()
caBundleEnvironment := getRestoreCABundleEnv(&objectStore.Spec.Configuration)
env, err := barmanCredentials.EnvSetBackupCloudCredentials(
ctx, ctx,
b.Client, b.Client,
cluster.Namespace, objectStore.Namespace,
cluster.Spec.Backup.BarmanObjectStore, &objectStore.Spec.Configuration,
env) mergeEnv(osEnvironment, caBundleEnvironment))
if err != nil { if err != nil {
return nil, err return nil, err
} }
backupName := fmt.Sprintf("backup-%v", utils.ToCompactISO8601(time.Now()))
if err = backupCmd.Take( if err = backupCmd.Take(
ctx, ctx,
backupObj.Status.BackupName, backupName,
backupObj.Status.ServerName, b.InstanceName,
env, env,
cluster, barmanCloudExecutor{},
postgres.BackupTemporaryDirectory, postgres.BackupTemporaryDirectory,
); err != nil { ); err != nil {
return nil, err return nil, err
} }
executedBackupInfo, err := backupCmd.GetExecutedBackupInfo( executedBackupInfo, err := backupCmd.GetExecutedBackupInfo(
ctx, backupObj.Status.BackupName, backupObj.Status.ServerName, cluster, env) ctx,
backupName,
b.InstanceName,
barmanCloudExecutor{},
env)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -36,8 +36,10 @@ func (c *CNPGI) Start(ctx context.Context) error {
PGWALPath: c.PGWALPath, PGWALPath: c.PGWALPath,
}) })
backup.RegisterBackupServer(server, BackupServiceImplementation{ backup.RegisterBackupServer(server, BackupServiceImplementation{
Client: c.Client, Client: c.Client,
InstanceName: c.InstanceName, BarmanObjectKey: c.BarmanObjectKey,
ClusterObjectKey: c.ClusterObjectKey,
InstanceName: c.InstanceName,
}) })
return nil return nil
} }

View File

@ -124,9 +124,8 @@ func (w WALServiceImplementation) Restore(
contextLogger := log.FromContext(ctx) contextLogger := log.FromContext(ctx)
startTime := time.Now() startTime := time.Now()
var cluster *cnpgv1.Cluster var cluster cnpgv1.Cluster
if err := w.Client.Get(ctx, w.ClusterObjectKey, &cluster); err != nil {
if err := w.Client.Get(ctx, w.ClusterObjectKey, cluster); err != nil {
return nil, err return nil, err
} }
@ -152,7 +151,7 @@ func (w WALServiceImplementation) Restore(
if err != nil { if err != nil {
return nil, fmt.Errorf("while getting recover credentials: %w", err) return nil, fmt.Errorf("while getting recover credentials: %w", err)
} }
mergeEnv(env, credentialsEnv) env = mergeEnv(env, credentialsEnv)
options, err := barmanCommand.CloudWalRestoreOptions(ctx, barmanConfiguration, objectStore.Name) options, err := barmanCommand.CloudWalRestoreOptions(ctx, barmanConfiguration, objectStore.Name)
if err != nil { if err != nil {
@ -178,7 +177,7 @@ func (w WALServiceImplementation) Restore(
} }
// We skip this step if streaming connection is not available // We skip this step if streaming connection is not available
if isStreamingAvailable(cluster, w.InstanceName) { if isStreamingAvailable(&cluster, w.InstanceName) {
if err := checkEndOfWALStreamFlag(walRestorer); err != nil { if err := checkEndOfWALStreamFlag(walRestorer); err != nil {
return nil, err return nil, err
} }
@ -213,7 +212,7 @@ func (w WALServiceImplementation) Restore(
// We skip this step if streaming connection is not available // We skip this step if streaming connection is not available
endOfWALStream := isEndOfWALStream(walStatus) endOfWALStream := isEndOfWALStream(walStatus)
if isStreamingAvailable(cluster, w.InstanceName) && endOfWALStream { if isStreamingAvailable(&cluster, w.InstanceName) && endOfWALStream {
contextLogger.Info( contextLogger.Info(
"Set end-of-wal-stream flag as one of the WAL files to be prefetched was not found") "Set end-of-wal-stream flag as one of the WAL files to be prefetched was not found")
@ -262,18 +261,29 @@ func (w WALServiceImplementation) SetFirstRequired(
} }
// mergeEnv merges all the values inside incomingEnv into env. // mergeEnv merges all the values inside incomingEnv into env.
func mergeEnv(env []string, incomingEnv []string) { func mergeEnv(env []string, incomingEnv []string) []string {
result := make([]string, len(env), len(env)+len(incomingEnv))
copy(result, env)
for _, incomingItem := range incomingEnv { for _, incomingItem := range incomingEnv {
incomingKV := strings.SplitAfterN(incomingItem, "=", 2) incomingKV := strings.SplitAfterN(incomingItem, "=", 2)
if len(incomingKV) != 2 { if len(incomingKV) != 2 {
continue continue
} }
for idx, item := range env {
found := false
for idx, item := range result {
if strings.HasPrefix(item, incomingKV[0]) { if strings.HasPrefix(item, incomingKV[0]) {
env[idx] = incomingItem result[idx] = incomingItem
found = true
} }
} }
if !found {
result = append(result, incomingItem)
}
} }
return result
} }
// TODO: refactor. // TODO: refactor.

9
scripts/cleanup.sh Executable file
View File

@ -0,0 +1,9 @@
#!/usr/bin/env bash
set -eu
cd "$(dirname "$0")/.." || exit
kubectl delete clusters --all
kubectl delete backups --all
kubectl exec -ti mc -- mc rm -r --force minio/backups

0
docs/minio/minio-delete.sh → scripts/minio-delete.sh Normal file → Executable file
View File

View File

@ -8,15 +8,19 @@ if [ -f .env ]; then
source .env source .env
fi fi
MYTMPDIR="$(mktemp -d)"
trap 'rm -rf -- "$MYTMPDIR"' EXIT
current_context=$(kubectl config view --raw -o json | jq -r '."current-context"' | sed "s/kind-//") current_context=$(kubectl config view --raw -o json | jq -r '."current-context"' | sed "s/kind-//")
operator_image=$(KIND_CLUSTER_NAME="$current_context" KO_DOCKER_REPO=kind.local ko build -BP ./cmd/operator) operator_image=$(KIND_CLUSTER_NAME="$current_context" KO_DOCKER_REPO=kind.local ko build -BP ./cmd/operator)
instance_image=$(KIND_CLUSTER_NAME="$current_context" KO_DOCKER_REPO=kind.local KO_DEFAULTBASEIMAGE="ghcr.io/cloudnative-pg/postgresql:17.0" ko build -BP ./cmd/instance) instance_image=$(KIND_CLUSTER_NAME="$current_context" KO_DOCKER_REPO=kind.local KO_DEFAULTBASEIMAGE="ghcr.io/cloudnative-pg/postgresql:17.0" ko build -BP ./cmd/instance)
# Now we deploy the plugin inside the `cnpg-system` workspace
( (
cd kubernetes; cp -r kubernetes config "$MYTMPDIR"
cd "$MYTMPDIR/kubernetes"
kustomize edit set image "plugin-barman-cloud=$operator_image" kustomize edit set image "plugin-barman-cloud=$operator_image"
kustomize edit set secret plugin-barman-cloud "--from-literal=SIDECAR_IMAGE=$instance_image" kustomize edit set secret plugin-barman-cloud "--from-literal=SIDECAR_IMAGE=$instance_image"
kubectl apply -k .
) )
# Now we deploy the plugin inside the `cnpg-system` workspace
kubectl apply -k kubernetes/