Add run hooks commands
This commit is contained in:
parent
7f4ef3c94c
commit
f418bca204
@ -1,7 +1,7 @@
|
|||||||
# Build a small image
|
# Build a small image
|
||||||
FROM arm32v7/alpine:3.12
|
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
|
COPY bin/formolcli /usr/local/bin
|
||||||
|
|
||||||
# Command to run
|
# Command to run
|
||||||
|
|||||||
2
go.mod
2
go.mod
@ -3,7 +3,7 @@ module github.com/desmo999r/formolcli
|
|||||||
go 1.14
|
go 1.14
|
||||||
|
|
||||||
require (
|
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/logr v0.1.0
|
||||||
github.com/go-logr/zapr v0.1.0
|
github.com/go-logr/zapr v0.1.0
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import (
|
|||||||
|
|
||||||
formolv1alpha1 "github.com/desmo999r/formol/api/v1alpha1"
|
formolv1alpha1 "github.com/desmo999r/formol/api/v1alpha1"
|
||||||
"github.com/desmo999r/formolcli/pkg/backup"
|
"github.com/desmo999r/formolcli/pkg/backup"
|
||||||
|
formolcliutils "github.com/desmo999r/formolcli/pkg/utils"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
@ -95,56 +96,29 @@ func (r *BackupSessionReconciler) Reconcile(req ctrl.Request) (ctrl.Result, erro
|
|||||||
return ctrl.Result{}, client.IgnoreNotFound(err)
|
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 {
|
for _, target := range backupConf.Spec.Targets {
|
||||||
switch target.Kind {
|
switch target.Kind {
|
||||||
case "Deployment":
|
case "Deployment":
|
||||||
if target.Name == deploymentName {
|
if target.Name == deploymentName {
|
||||||
for i, status := range backupSession.Status.Targets {
|
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)
|
log.V(0).Info("It's for us!", "target", target)
|
||||||
|
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
|
result := formolv1alpha1.Success
|
||||||
status.StartTime = &metav1.Time{Time: time.Now()}
|
status.StartTime = &metav1.Time{Time: time.Now()}
|
||||||
output, err := backup.BackupPaths(backupSession.Name, target.Paths)
|
output, err := backup.BackupPaths(backupSession.Name, target.Paths)
|
||||||
@ -162,6 +136,11 @@ func (r *BackupSessionReconciler) Reconcile(req ctrl.Request) (ctrl.Result, erro
|
|||||||
log.Error(err, "unable to update backupsession status")
|
log.Error(err, "unable to update backupsession status")
|
||||||
return ctrl.Result{}, err
|
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