forked from TrueCloudLab/restic
Try to make repo upgrade migration more failsafe
This commit is contained in:
parent
82ed5a3a15
commit
a5f1d318ac
1 changed files with 52 additions and 5 deletions
|
@ -3,6 +3,10 @@ package migrations
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/restic/restic/internal/restic"
|
"github.com/restic/restic/internal/restic"
|
||||||
)
|
)
|
||||||
|
@ -26,17 +30,19 @@ func (*UpgradeRepoV2) Check(ctx context.Context, repo restic.Repository) (bool,
|
||||||
return isV1, nil
|
return isV1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*UpgradeRepoV2) Apply(ctx context.Context, repo restic.Repository) error {
|
func (*UpgradeRepoV2) upgrade(ctx context.Context, repo restic.Repository) error {
|
||||||
cfg := repo.Config()
|
|
||||||
cfg.Version = 2
|
|
||||||
|
|
||||||
h := restic.Handle{Type: restic.ConfigFile}
|
h := restic.Handle{Type: restic.ConfigFile}
|
||||||
|
|
||||||
|
// now remove the original file
|
||||||
err := repo.Backend().Remove(ctx, h)
|
err := repo.Backend().Remove(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("remove old config file failed: %w", err)
|
return fmt.Errorf("remove config failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// upgrade config
|
||||||
|
cfg := repo.Config()
|
||||||
|
cfg.Version = 2
|
||||||
|
|
||||||
_, err = repo.SaveJSONUnpacked(ctx, restic.ConfigFile, cfg)
|
_, err = repo.SaveJSONUnpacked(ctx, restic.ConfigFile, cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("save new config file failed: %w", err)
|
return fmt.Errorf("save new config file failed: %w", err)
|
||||||
|
@ -44,3 +50,44 @@ func (*UpgradeRepoV2) Apply(ctx context.Context, repo restic.Repository) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *UpgradeRepoV2) Apply(ctx context.Context, repo restic.Repository) error {
|
||||||
|
tempdir, err := ioutil.TempDir("", "restic-migrate-upgrade-repo-v2-")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("create temp dir failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
h := restic.Handle{Type: restic.ConfigFile}
|
||||||
|
|
||||||
|
// read raw config file and save it to a temp dir, just in case
|
||||||
|
var rawConfigFile []byte
|
||||||
|
err = repo.Backend().Load(ctx, h, 0, 0, func(rd io.Reader) (err error) {
|
||||||
|
rawConfigFile, err = ioutil.ReadAll(rd)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("load config file failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filepath.Join(tempdir, "config.old"), rawConfigFile, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("write config file backup to %v failed: %w", tempdir, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// run the upgrade
|
||||||
|
err = m.upgrade(ctx, repo)
|
||||||
|
if err != nil {
|
||||||
|
// try contingency methods, reupload the original file
|
||||||
|
_ = repo.Backend().Remove(ctx, h)
|
||||||
|
uploadError := repo.Backend().Save(ctx, h, restic.NewByteReader(rawConfigFile, nil))
|
||||||
|
if uploadError != nil {
|
||||||
|
return fmt.Errorf("error uploading config (%w), re-uploading old config filed failed as well (%v) but there is a backup in %v", err, uploadError, tempdir)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("error uploading config (%w), re-uploadid old config, there is a backup in %v", err, tempdir)
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = os.Remove(backupFileName)
|
||||||
|
_ = os.Remove(tempdir)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue