37baabe134
* EE-384: add endpoint to set auto backup (#224) * EE-383: add endpoint to fetch backup settings (#231) * add get backup settings handler * add api docs desc * EE-382: restore from s3 (#233) * EE-381: add GET backup status handler (#234) * EE-385: Add S3 backup execute handler (#237) * add s3 backup execute handler * refactories inside `./api/backup/backup_scheduler.go` and `./api/backup/backup_scheduler.go` * fix tests * EE-375: added backup to S3 form * EE-376: added restore from S3 form * EE-377: Update Home screen to display last backup run status * update backup service with back end endpoints. * restart admin monitor during s3 restores * use go 1.13 * go 1.13 compatibility * EE-375: added cron-validator lib * EE-375: using enum to compare form types * EE-375: validate cron rule field * try fix windows build * EE-375 EE-376 backup and restore forms validation changes * fix(autobackup): update autobackup settings validation rules (#260) * fix(autobackup): automate backup to s3 fe update (#261) * EE-292: fixed typo in property. * EE-292: updated auto backup front end validation. * EE-292: updated lib to validate cron rule in front end * fix dependencies * bumped libcompose version Co-authored-by: Hui <arris_li@hotmail.com> Co-authored-by: Felix Han <felix.han@portainer.io> Co-authored-by: fhanportainer <79428273+fhanportainer@users.noreply.github.com>
69 lines
1.4 KiB
Go
69 lines
1.4 KiB
Go
package backup
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
func copyPath(path string, toDir string) error {
|
|
info, err := os.Stat(path)
|
|
if err != nil && errors.Is(err, os.ErrNotExist) {
|
|
// skip copy if file does not exist
|
|
return nil
|
|
}
|
|
|
|
if !info.IsDir() {
|
|
destination := filepath.Join(toDir, info.Name())
|
|
return copyFile(path, destination)
|
|
}
|
|
|
|
return copyDir(path, toDir)
|
|
}
|
|
|
|
func copyDir(fromDir, toDir string) error {
|
|
cleanedSourcePath := filepath.Clean(fromDir)
|
|
parentDirectory := filepath.Dir(cleanedSourcePath)
|
|
err := filepath.Walk(cleanedSourcePath, func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
destination := filepath.Join(toDir, strings.TrimPrefix(path, parentDirectory))
|
|
if info.IsDir() {
|
|
return nil // skip directory creations
|
|
}
|
|
|
|
if info.Mode()&os.ModeSymlink != 0 { // entry is a symlink
|
|
return nil // don't copy symlinks
|
|
}
|
|
|
|
return copyFile(path, destination)
|
|
})
|
|
|
|
return err
|
|
}
|
|
|
|
// copies regular a file from src to dst
|
|
func copyFile(src, dst string) error {
|
|
from, err := os.Open(src)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer from.Close()
|
|
|
|
// has to include 'execute' bit, otherwise fails. MkdirAll follows `mkdir -m` restrictions
|
|
if err := os.MkdirAll(filepath.Dir(dst), 0744); err != nil {
|
|
return err
|
|
}
|
|
to, err := os.Create(dst)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer to.Close()
|
|
|
|
_, err = io.Copy(to, from)
|
|
return err
|
|
}
|