From fe29d6aee39bd2881da6dd2936e7dd15e0df03eb Mon Sep 17 00:00:00 2001 From: andres-portainer <91705312+andres-portainer@users.noreply.github.com> Date: Mon, 25 Nov 2024 10:10:11 -0300 Subject: [PATCH] feat(backup): reduce the locking time of the offline gate BE-11402 (#157) --- api/backup/backup.go | 65 ++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/api/backup/backup.go b/api/backup/backup.go index b00577470..e2a52101f 100644 --- a/api/backup/backup.go +++ b/api/backup/backup.go @@ -21,6 +21,7 @@ const rwxr__r__ os.FileMode = 0o744 var filesToBackup = []string{ "certs", + "chisel", "compose", "config.json", "custom_templates", @@ -30,40 +31,13 @@ var filesToBackup = []string{ "portainer.key", "portainer.pub", "tls", - "chisel", } // Creates a tar.gz system archive and encrypts it if password is not empty. Returns a path to the archive file. func CreateBackupArchive(password string, gate *offlinegate.OfflineGate, datastore dataservices.DataStore, filestorePath string) (string, error) { - unlock := gate.Lock() - defer unlock() - - backupDirPath := filepath.Join(filestorePath, "backup", time.Now().Format("2006-01-02_15-04-05")) - if err := os.MkdirAll(backupDirPath, rwxr__r__); err != nil { - return "", errors.Wrap(err, "Failed to create backup dir") - } - - { - // new export - exportFilename := path.Join(backupDirPath, fmt.Sprintf("export-%d.json", time.Now().Unix())) - - err := datastore.Export(exportFilename) - if err != nil { - log.Error().Err(err).Str("filename", exportFilename).Msg("failed to export") - } else { - log.Debug().Str("filename", exportFilename).Msg("file exported") - } - } - - if err := backupDb(backupDirPath, datastore); err != nil { - return "", errors.Wrap(err, "Failed to backup database") - } - - for _, filename := range filesToBackup { - err := filesystem.CopyPath(filepath.Join(filestorePath, filename), backupDirPath) - if err != nil { - return "", errors.Wrap(err, "Failed to create backup file") - } + backupDirPath, err := backupDatabaseAndFilesystem(gate, datastore, filestorePath) + if err != nil { + return "", err } archivePath, err := archive.TarGzDir(backupDirPath) @@ -81,6 +55,37 @@ func CreateBackupArchive(password string, gate *offlinegate.OfflineGate, datasto return archivePath, nil } +func backupDatabaseAndFilesystem(gate *offlinegate.OfflineGate, datastore dataservices.DataStore, filestorePath string) (string, error) { + unlock := gate.Lock() + defer unlock() + + backupDirPath := filepath.Join(filestorePath, "backup", time.Now().Format("2006-01-02_15-04-05")) + if err := os.MkdirAll(backupDirPath, rwxr__r__); err != nil { + return "", errors.Wrap(err, "Failed to create backup dir") + } + + // new export + exportFilename := path.Join(backupDirPath, fmt.Sprintf("export-%d.json", time.Now().Unix())) + + if err := datastore.Export(exportFilename); err != nil { + log.Error().Err(err).Str("filename", exportFilename).Msg("failed to export") + } else { + log.Debug().Str("filename", exportFilename).Msg("file exported") + } + + if err := backupDb(backupDirPath, datastore); err != nil { + return "", errors.Wrap(err, "Failed to backup database") + } + + for _, filename := range filesToBackup { + if err := filesystem.CopyPath(filepath.Join(filestorePath, filename), backupDirPath); err != nil { + return "", errors.Wrap(err, "Failed to create backup file") + } + } + + return backupDirPath, nil +} + func backupDb(backupDirPath string, datastore dataservices.DataStore) error { dbFileName := datastore.Connection().GetDatabaseFileName() _, err := datastore.Backup(filepath.Join(backupDirPath, dbFileName))