Add run hooks commands
This commit is contained in:
parent
7f4ef3c94c
commit
f418bca204
@ -1,7 +1,7 @@
|
||||
# Build a small image
|
||||
FROM arm32v7/alpine:3.12
|
||||
|
||||
RUN apk add --no-cache restic postgresql-client
|
||||
RUN apk add --no-cache su-exec restic postgresql-client
|
||||
COPY bin/formolcli /usr/local/bin
|
||||
|
||||
# Command to run
|
||||
|
||||
2
go.mod
2
go.mod
@ -3,7 +3,7 @@ module github.com/desmo999r/formolcli
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/desmo999r/formol v0.7.0
|
||||
github.com/desmo999r/formol v0.7.1
|
||||
github.com/go-logr/logr v0.1.0
|
||||
github.com/go-logr/zapr v0.1.0
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
|
||||
@ -15,6 +15,7 @@ import (
|
||||
|
||||
formolv1alpha1 "github.com/desmo999r/formol/api/v1alpha1"
|
||||
"github.com/desmo999r/formolcli/pkg/backup"
|
||||
formolcliutils "github.com/desmo999r/formolcli/pkg/utils"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
@ -95,72 +96,50 @@ func (r *BackupSessionReconciler) Reconcile(req ctrl.Request) (ctrl.Result, erro
|
||||
return ctrl.Result{}, client.IgnoreNotFound(err)
|
||||
}
|
||||
|
||||
// Found the BackupConfiguration.
|
||||
// backupDeployment := func(target formolv1alpha1.Target) error {
|
||||
// //backupSession.Status.BackupSessionState = formolv1alpha1.Running
|
||||
// //if err := r.Client.Status().Update(ctx, backupSession); err != nil {
|
||||
// // log.Error(err, "unable to update status", "backupsession", backupSession)
|
||||
// // return err
|
||||
// //}
|
||||
// // Preparing for backup
|
||||
// c := make(chan []byte)
|
||||
//
|
||||
// go func() {
|
||||
// for msg := range c {
|
||||
// var dat map[string]interface{}
|
||||
// if err := json.Unmarshal(msg, &dat); err != nil {
|
||||
// log.Error(err, "unable to unmarshal json", "msg", msg)
|
||||
// continue
|
||||
// }
|
||||
// log.V(1).Info("message on stdout", "stdout", dat)
|
||||
// //if message_type, ok := dat["message_type"]; ok && message_type == "summary" {
|
||||
// // backupSession.Status.SnapshotId = dat["snapshot_id"].(string)
|
||||
// // backupSession.Status.Duration = &metav1.Duration{Duration: time.Duration(dat["total_duration"].(float64)*1000) * time.Millisecond}
|
||||
// //}
|
||||
// }
|
||||
// }()
|
||||
// //result := formolv1alpha1.Failure
|
||||
// defer func() {
|
||||
// close(c)
|
||||
// //backupSession.Status.BackupSessionState = result
|
||||
// //if err := r.Status().Update(ctx, backupSession); err != nil {
|
||||
// // log.Error(err, "unable to update status")
|
||||
// //}
|
||||
// }()
|
||||
// // do the backup
|
||||
// //backupSession.Status.StartTime = &metav1.Time{Time: time.Now()}
|
||||
// if err := backup.BackupPaths(backupSession.Name, target.Paths, c); err != nil {
|
||||
// log.Error(err, "unable to backup deployment")
|
||||
// return err
|
||||
// }
|
||||
// //result = formolv1alpha1.Success
|
||||
//
|
||||
// return nil
|
||||
// }
|
||||
|
||||
for _, target := range backupConf.Spec.Targets {
|
||||
switch target.Kind {
|
||||
case "Deployment":
|
||||
if target.Name == deploymentName {
|
||||
for i, status := range backupSession.Status.Targets {
|
||||
if status.Name == target.Name && status.BackupState == formolv1alpha1.New {
|
||||
if status.Name == target.Name {
|
||||
log.V(0).Info("It's for us!", "target", target)
|
||||
result := formolv1alpha1.Success
|
||||
status.StartTime = &metav1.Time{Time: time.Now()}
|
||||
output, err := backup.BackupPaths(backupSession.Name, target.Paths)
|
||||
if err != nil {
|
||||
log.Error(err, "unable to backup deployment", "output", string(output))
|
||||
result = formolv1alpha1.Failure
|
||||
} else {
|
||||
snapshotId, duration := backup.GetBackupResults(output)
|
||||
backupSession.Status.Targets[i].SnapshotId = snapshotId
|
||||
backupSession.Status.Targets[i].Duration = &metav1.Duration{Duration: duration}
|
||||
}
|
||||
backupSession.Status.Targets[i].BackupState = result
|
||||
log.V(1).Info("current backupSession status", "status", backupSession.Status)
|
||||
if err := r.Status().Update(ctx, backupSession); err != nil {
|
||||
log.Error(err, "unable to update backupsession status")
|
||||
return ctrl.Result{}, err
|
||||
switch status.BackupState {
|
||||
case formolv1alpha1.New:
|
||||
// TODO: Run beforeBackup
|
||||
log.V(0).Info("New session, run the beforeBackup hooks if any")
|
||||
result := formolv1alpha1.Running
|
||||
if err := formolcliutils.RunBeforeBackup(target); err != nil {
|
||||
result = formolv1alpha1.Failure
|
||||
}
|
||||
backupSession.Status.Targets[i].BackupState = result
|
||||
log.V(1).Info("current backupSession status", "status", backupSession.Status)
|
||||
if err := r.Status().Update(ctx, backupSession); err != nil {
|
||||
log.Error(err, "unable to update backupsession status")
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
case formolv1alpha1.Running:
|
||||
log.V(0).Info("Running session. Do the backup")
|
||||
result := formolv1alpha1.Success
|
||||
status.StartTime = &metav1.Time{Time: time.Now()}
|
||||
output, err := backup.BackupPaths(backupSession.Name, target.Paths)
|
||||
if err != nil {
|
||||
log.Error(err, "unable to backup deployment", "output", string(output))
|
||||
result = formolv1alpha1.Failure
|
||||
} else {
|
||||
snapshotId, duration := backup.GetBackupResults(output)
|
||||
backupSession.Status.Targets[i].SnapshotId = snapshotId
|
||||
backupSession.Status.Targets[i].Duration = &metav1.Duration{Duration: duration}
|
||||
}
|
||||
backupSession.Status.Targets[i].BackupState = result
|
||||
log.V(1).Info("current backupSession status", "status", backupSession.Status)
|
||||
if err := r.Status().Update(ctx, backupSession); err != nil {
|
||||
log.Error(err, "unable to update backupsession status")
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
case formolv1alpha1.Success, formolv1alpha1.Failure:
|
||||
// I decided not to flag the backup as a failure if the AfterBackup command fail. But maybe I'm wrong
|
||||
log.V(0).Info("Backup is over, run the afterBackup hooks if any")
|
||||
formolcliutils.RunAfterBackup(target)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
88
pkg/utils/root.go
Normal file
88
pkg/utils/root.go
Normal file
@ -0,0 +1,88 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
formolv1alpha1 "github.com/desmo999r/formol/api/v1alpha1"
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/go-logr/zapr"
|
||||
"go.uber.org/zap"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var logger logr.Logger
|
||||
|
||||
func init() {
|
||||
zapLog, _ := zap.NewDevelopment()
|
||||
logger = zapr.NewLogger(zapLog)
|
||||
}
|
||||
|
||||
func runHook(hooks []formolv1alpha1.Hook, label string) error {
|
||||
log := logger.WithName(label)
|
||||
log.V(0).Info("Run commands")
|
||||
for _, hook := range hooks {
|
||||
err := RunChroot(hook.Cmd, hook.Args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Run(runCmd string, args []string) error {
|
||||
log := logger.WithValues("Run", runCmd, "Args", args)
|
||||
cmd := exec.Command(runCmd, args...)
|
||||
output, err := cmd.CombinedOutput()
|
||||
log.V(1).Info("result", "output", string(output))
|
||||
if err != nil {
|
||||
log.Error(err, "something went wrong")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func RunChroot(runCmd string, args ...string) error {
|
||||
log := logger.WithValues("RunChroot", runCmd, "Args", args)
|
||||
root := regexp.MustCompile(`/proc/[0-9]+/root`)
|
||||
pid := strconv.Itoa(os.Getpid())
|
||||
skip := false
|
||||
if err := filepath.Walk("/proc", func(path string, info os.FileInfo, err error) error {
|
||||
if skip {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if info.IsDir() && (info.Name() == "1" || info.Name() == pid) {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
if root.MatchString(path) {
|
||||
if _, err := filepath.EvalSymlinks(path); err != nil {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
cmd := exec.Command("chroot", append([]string{path, runCmd}, args...)...)
|
||||
output, err := cmd.CombinedOutput()
|
||||
log.V(0).Info("result", "output", string(output))
|
||||
if err != nil {
|
||||
log.Error(err, "something went wrong")
|
||||
return err
|
||||
}
|
||||
skip = true
|
||||
return filepath.SkipDir
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func RunBeforeBackup(target formolv1alpha1.Target) error {
|
||||
return runHook(target.BeforeBackup, "runBeforeBackup")
|
||||
}
|
||||
|
||||
func RunAfterBackup(target formolv1alpha1.Target) error {
|
||||
return runHook(target.AfterBackup, "runAfterBackup")
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user