diff --git a/pkg/apis/psmdb/v1/psmdb_defaults.go b/pkg/apis/psmdb/v1/psmdb_defaults.go index 4e41f089c..a60dd4087 100644 --- a/pkg/apis/psmdb/v1/psmdb_defaults.go +++ b/pkg/apis/psmdb/v1/psmdb_defaults.go @@ -550,6 +550,13 @@ func (cr *PerconaServerMongoDB) CheckNSetDefaults(ctx context.Context, platform } } + if cr.CompareVersion("1.20.0") < 0 && cr.Spec.Backup.PITR.Enabled { + if len(cr.Spec.Backup.Storages) != 1 { + cr.Spec.Backup.PITR.Enabled = false + log.Info("Point-in-time recovery can be enabled only if one bucket is used in spec.backup.storages") + } + } + if cr.CompareVersion("1.20.0") >= 0 && len(cr.Spec.Backup.Storages) > 1 { main := 0 for _, stg := range cr.Spec.Backup.Storages { diff --git a/pkg/controller/perconaservermongodb/pbm.go b/pkg/controller/perconaservermongodb/pbm.go index 940531b3a..4982db696 100644 --- a/pkg/controller/perconaservermongodb/pbm.go +++ b/pkg/controller/perconaservermongodb/pbm.go @@ -12,6 +12,7 @@ import ( "github.com/pkg/errors" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" + "k8s.io/apimachinery/pkg/types" logf "sigs.k8s.io/controller-runtime/pkg/log" "github.com/percona/percona-backup-mongodb/pbm/config" @@ -188,6 +189,56 @@ func isResyncNeeded(currentCfg *config.Config, newCfg *config.Config) bool { return false } +func (r *ReconcilePerconaServerMongoDB) reconcilePiTRStorageLegacy( + ctx context.Context, + pbm backup.PBM, + cr *psmdbv1.PerconaServerMongoDB, +) error { + log := logf.FromContext(ctx) + + if len(cr.Spec.Backup.Storages) != 1 { + log.Info("Expected exactly one storage for PiTR in legacy version", "configured", len(cr.Spec.Backup.Storages)) + return nil + } + + // if PiTR is enabled user can configure only one storage + var storage psmdbv1.BackupStorageSpec + for name, stg := range cr.Spec.Backup.Storages { + storage = stg + log.Info("Configuring PBM with storage", "storage", name) + break + } + + var secretName string + switch storage.Type { + case psmdbv1.BackupStorageS3: + secretName = storage.S3.CredentialsSecret + case psmdbv1.BackupStorageAzure: + secretName = storage.Azure.CredentialsSecret + } + + if secretName != "" { + exists, err := secretExists(ctx, r.client, types.NamespacedName{Name: secretName, Namespace: cr.Namespace}) + if err != nil { + return errors.Wrap(err, "check storage credentials secret") + } + + if !exists { + log.Error(nil, "Storage credentials secret does not exist", "secret", secretName) + return nil + } + } + + err := pbm.GetNSetConfigLegacy(ctx, r.client, cr, storage) + if err != nil { + return errors.Wrap(err, "set PBM config") + } + + log.Info("Configured PBM storage") + + return nil +} + func (r *ReconcilePerconaServerMongoDB) reconcilePiTRConfig(ctx context.Context, cr *psmdbv1.PerconaServerMongoDB) error { log := logf.FromContext(ctx) @@ -209,10 +260,17 @@ func (r *ReconcilePerconaServerMongoDB) reconcilePiTRConfig(ctx context.Context, return nil } - stgName, _, err := cr.Spec.Backup.MainStorage() - if err != nil { - // no storage found - return nil + var stgName string + for name := range cr.Spec.Backup.Storages { + stgName = name + break + } + if cr.CompareVersion("1.20.0") >= 0 { + stgName, _, err = cr.Spec.Backup.MainStorage() + if err != nil { + // no storage found + return nil + } } if cr.Spec.Backup.PITR.Enabled && !cr.Spec.Backup.PITR.OplogOnly { @@ -236,6 +294,15 @@ func (r *ReconcilePerconaServerMongoDB) reconcilePiTRConfig(ctx context.Context, defer pbm.Close(ctx) if err := enablePiTRIfNeeded(ctx, pbm, cr); err != nil { + if backup.IsErrNoDocuments(err) { + if cr.CompareVersion("1.20.0") < 0 { + if err := r.reconcilePiTRStorageLegacy(ctx, pbm, cr); err != nil { + return errors.Wrap(err, "reconcile pitr storage") + } + } + return nil + } + return errors.Wrap(err, "enable pitr if needed") } diff --git a/pkg/controller/perconaservermongodbbackup/backup.go b/pkg/controller/perconaservermongodbbackup/backup.go index 298fc0c52..789380644 100644 --- a/pkg/controller/perconaservermongodbbackup/backup.go +++ b/pkg/controller/perconaservermongodbbackup/backup.go @@ -64,6 +64,13 @@ func (b *Backup) Start(ctx context.Context, k8sclient client.Client, cluster *ap return status, errors.Errorf("unable to get storage '%s'", cr.Spec.StorageName) } + if cluster.CompareVersion("1.20.0") < 0 { + err := b.pbm.GetNSetConfigLegacy(ctx, k8sclient, cluster, stg) + if err != nil { + return status, errors.Wrapf(err, "set backup config with storage %s", cr.Spec.StorageName) + } + } + name := time.Now().UTC().Format(time.RFC3339) var compLevel *int @@ -83,16 +90,18 @@ func (b *Backup) Start(ctx context.Context, k8sclient client.Client, cluster *ap }, } - mainStgName, _, err := b.spec.MainStorage() - if err != nil { - return status, errors.Wrap(err, "get main storage") - } + if cluster.CompareVersion("1.20.0") >= 0 { + mainStgName, _, err := b.spec.MainStorage() + if err != nil { + return status, errors.Wrap(err, "get main storage") + } - if cr.Spec.StorageName != mainStgName { - cmd.Backup.Profile = cr.Spec.StorageName + if cr.Spec.StorageName != mainStgName { + cmd.Backup.Profile = cr.Spec.StorageName + } } - log.Info("Sending backup command", "backupCmd", cmd) + log.Info("Sending backup command", "backupCmd", cmd, "profile", cmd.Backup.Profile) if err := b.pbm.SendCmd(ctx, cmd); err != nil { return status, err diff --git a/pkg/controller/perconaservermongodbbackup/perconaservermongodbbackup_controller.go b/pkg/controller/perconaservermongodbbackup/perconaservermongodbbackup_controller.go index 5fd321bd8..209a6ea8d 100644 --- a/pkg/controller/perconaservermongodbbackup/perconaservermongodbbackup_controller.go +++ b/pkg/controller/perconaservermongodbbackup/perconaservermongodbbackup_controller.go @@ -460,6 +460,23 @@ func (r *ReconcilePerconaServerMongoDBBackup) deleteBackupFinalizer(ctx context. return nil } + if cluster.CompareVersion("1.20.0") < 0 { + err = b.pbm.DeletePITRChunks(ctx, meta.LastWriteTS) + if err != nil { + return errors.Wrap(err, "failed to delete PITR") + } + log.Info("PiTR chunks deleted", "until", meta.LastWriteTS) + + err = b.pbm.DeleteBackup(ctx, cr.Status.PBMname) + if err != nil { + return errors.Wrap(err, "failed to delete backup") + } + + log.Info("Backup deleted") + + return nil + } + mainStgName, _, err := cluster.Spec.Backup.MainStorage() if err != nil { return errors.Wrap(err, "get main storage") diff --git a/pkg/controller/perconaservermongodbrestore/perconaservermongodbrestore_controller.go b/pkg/controller/perconaservermongodbrestore/perconaservermongodbrestore_controller.go index 7ee08855c..56e8ed108 100644 --- a/pkg/controller/perconaservermongodbrestore/perconaservermongodbrestore_controller.go +++ b/pkg/controller/perconaservermongodbrestore/perconaservermongodbrestore_controller.go @@ -438,6 +438,14 @@ func (r *ReconcilePerconaServerMongoDBRestore) resyncStorage( return errors.Wrap(err, "get backup") } + if cluster.CompareVersion("1.20.0") < 0 { + if err := pbmC.ResyncMainStorageAndWait(ctx); err != nil { + return errors.Wrap(err, "start config resync") + } + + return nil + } + mainStgName, _, err := cluster.Spec.Backup.MainStorage() if err != nil { return errors.Wrap(err, "get main storage") diff --git a/pkg/psmdb/backup/fake/pbm.go b/pkg/psmdb/backup/fake/pbm.go index 41c74ff27..e28eac95a 100644 --- a/pkg/psmdb/backup/fake/pbm.go +++ b/pkg/psmdb/backup/fake/pbm.go @@ -109,6 +109,10 @@ func (p *fakePBM) GetNSetConfig(ctx context.Context, k8sclient client.Client, cl return nil } +func (p *fakePBM) GetNSetConfigLegacy(ctx context.Context, k8sclient client.Client, cluster *api.PerconaServerMongoDB, stg api.BackupStorageSpec) error { + return nil +} + func (p *fakePBM) SetConfigVar(ctx context.Context, key, val string) error { return nil } diff --git a/pkg/psmdb/backup/pbm.go b/pkg/psmdb/backup/pbm.go index a4192fbdc..edb388f94 100644 --- a/pkg/psmdb/backup/pbm.go +++ b/pkg/psmdb/backup/pbm.go @@ -89,6 +89,7 @@ type PBM interface { GetProfile(ctx context.Context, name string) (*config.Config, error) RemoveProfile(ctx context.Context, name string) error GetNSetConfig(ctx context.Context, k8sclient client.Client, cluster *api.PerconaServerMongoDB) error + GetNSetConfigLegacy(ctx context.Context, k8sclient client.Client, cluster *api.PerconaServerMongoDB, stg api.BackupStorageSpec) error SetConfig(ctx context.Context, cfg *config.Config) error SetConfigVar(ctx context.Context, key, val string) error @@ -522,6 +523,26 @@ func (b *pbmC) RemoveProfile(ctx context.Context, name string) error { return config.RemoveProfile(ctx, b.Client, name) } +// GetNSetConfigLegacy sets the PBM config with given storage +func (b *pbmC) GetNSetConfigLegacy(ctx context.Context, k8sclient client.Client, cluster *api.PerconaServerMongoDB, stg api.BackupStorageSpec) error { + log := logf.FromContext(ctx) + + conf, err := GetPBMConfig(ctx, k8sclient, cluster, stg) + if err != nil { + return errors.Wrap(err, "get PBM config") + } + + log.Info("Setting config", "cluster", cluster.Name, "storage", stg) + + if err := config.SetConfig(ctx, b.Client, &conf); err != nil { + return errors.Wrap(err, "write config") + } + + time.Sleep(11 * time.Second) // give time to init new storage + + return nil +} + // GetNSetConfig sets the PBM config with main storage defined in the cluster CR func (b *pbmC) GetNSetConfig(ctx context.Context, k8sclient client.Client, cluster *api.PerconaServerMongoDB) error { log := logf.FromContext(ctx)