104 lines
2.3 KiB
Go
104 lines
2.3 KiB
Go
|
package backup
|
||
|
|
||
|
import (
|
||
|
"crypto/sha256"
|
||
|
"github.com/pkg/errors"
|
||
|
"github.com/pterodactyl/wings/api"
|
||
|
"github.com/pterodactyl/wings/config"
|
||
|
"go.uber.org/zap"
|
||
|
"io"
|
||
|
"os"
|
||
|
"path"
|
||
|
)
|
||
|
|
||
|
type Backup struct {
|
||
|
// The UUID of this backup object. This must line up with a backup from
|
||
|
// the panel instance.
|
||
|
Uuid string `json:"uuid"`
|
||
|
|
||
|
// An array of files to ignore when generating this backup. This should be
|
||
|
// compatible with a standard .gitignore structure.
|
||
|
IgnoredFiles []string `json:"ignored_files"`
|
||
|
}
|
||
|
|
||
|
type ArchiveDetails struct {
|
||
|
Checksum string `json:"checksum"`
|
||
|
Size int64 `json:"size"`
|
||
|
}
|
||
|
|
||
|
// Returns a request object.
|
||
|
func (ad *ArchiveDetails) ToRequest(successful bool) api.BackupRequest {
|
||
|
return api.BackupRequest{
|
||
|
Checksum: ad.Checksum,
|
||
|
Size: ad.Size,
|
||
|
Successful: successful,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Returns the path for this specific backup.
|
||
|
func (b *Backup) Path() string {
|
||
|
return path.Join(config.Get().System.BackupDirectory, b.Uuid+".tar.gz")
|
||
|
}
|
||
|
|
||
|
// Returns the SHA256 checksum of a backup.
|
||
|
func (b *Backup) Checksum() ([]byte, error) {
|
||
|
h := sha256.New()
|
||
|
|
||
|
f, err := os.Open(b.Path())
|
||
|
if err != nil {
|
||
|
return []byte{}, errors.WithStack(err)
|
||
|
}
|
||
|
defer f.Close()
|
||
|
|
||
|
if _, err := io.Copy(h, f); err != nil {
|
||
|
return []byte{}, errors.WithStack(err)
|
||
|
}
|
||
|
|
||
|
return h.Sum(nil), nil
|
||
|
}
|
||
|
|
||
|
// Removes a backup from the system.
|
||
|
func (b *Backup) Remove() error {
|
||
|
return os.Remove(b.Path())
|
||
|
}
|
||
|
|
||
|
// Notifies the panel of a backup's state and returns an error if one is encountered
|
||
|
// while performing this action.
|
||
|
func (b *Backup) NotifyPanel(ad *ArchiveDetails, successful bool) error {
|
||
|
r := api.NewRequester()
|
||
|
|
||
|
rerr, err := r.SendBackupStatus(b.Uuid, ad.ToRequest(successful))
|
||
|
if rerr != nil || err != nil {
|
||
|
if err != nil {
|
||
|
zap.S().Errorw(
|
||
|
"failed to notify panel of backup status due to internal code error",
|
||
|
zap.String("backup", b.Uuid),
|
||
|
zap.Error(err),
|
||
|
)
|
||
|
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
zap.S().Warnw(rerr.String(), zap.String("backup", b.Uuid))
|
||
|
|
||
|
return errors.New(rerr.String())
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Ensures that the local backup destination for files exists.
|
||
|
func (b *Backup) ensureLocalBackupLocation() error {
|
||
|
d := config.Get().System.BackupDirectory
|
||
|
|
||
|
if _, err := os.Stat(d); err != nil {
|
||
|
if !os.IsNotExist(err) {
|
||
|
return errors.WithStack(err)
|
||
|
}
|
||
|
|
||
|
return os.MkdirAll(d, 0700)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|