Compare commits

...

2 Commits

Author SHA1 Message Date
Jean-Marc ANDRE
994b792d97 multi arch Dockerfile 2023-03-20 22:15:13 +01:00
Jean-Marc ANDRE
0f8012c22e prepared BackupSession and RestoreSession common code 2023-03-20 22:14:41 +01:00
9 changed files with 140 additions and 107 deletions

View File

@ -1,6 +1,6 @@
# Build a small image
FROM --platform=linux/amd64 alpine:3
RUN apk add --no-cache su-exec restic postgresql-client
RUN apk add --no-cache su-exec restic
COPY ./bin/formolcli /usr/local/bin
# Command to run

8
Dockerfile.arm64 Normal file
View File

@ -0,0 +1,8 @@
# Build a small image
FROM --platform=linux/arm64 alpine:3
RUN apk add --no-cache su-exec restic postgresql-client
COPY ./bin/formolcli /usr/local/bin
# Command to run
ENTRYPOINT ["/usr/local/bin/formolcli"]
CMD ["--help"]

View File

@ -1,51 +0,0 @@
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
package cmd
import (
"fmt"
"github.com/desmo999r/formolcli/backupsession"
"github.com/desmo999r/formolcli/controllers"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
)
var createBackupSessionCmd = &cobra.Command{
Use: "create",
Short: "Create a backupsession",
Run: func(cmd *cobra.Command, args []string) {
name, _ := cmd.Flags().GetString("name")
namespace, _ := cmd.Flags().GetString("namespace")
fmt.Println("create backupsession called")
backupsession.CreateBackupSession(corev1.ObjectReference{
Namespace: namespace,
Name: name,
})
},
}
var startServerCmd = &cobra.Command{
Use: "server",
Short: "Start a BackupSession controller",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("starts backupsession controller")
controllers.StartServer()
},
}
// backupsessionCmd represents the backupsession command
var backupSessionCmd = &cobra.Command{
Use: "backupsession",
Short: "All the BackupSession related commands",
}
func init() {
rootCmd.AddCommand(backupSessionCmd)
backupSessionCmd.AddCommand(createBackupSessionCmd)
backupSessionCmd.AddCommand(startServerCmd)
createBackupSessionCmd.Flags().String("namespace", "", "The namespace of the BackupConfiguration containing the information about the backup.")
createBackupSessionCmd.Flags().String("name", "", "The name of the BackupConfiguration containing the information about the backup.")
createBackupSessionCmd.MarkFlagRequired("namespace")
createBackupSessionCmd.MarkFlagRequired("name")
}

View File

@ -4,11 +4,42 @@ Copyright © 2023 NAME HERE <EMAIL ADDRESS>
package cmd
import (
"os"
"fmt"
"github.com/desmo999r/formolcli/backupsession"
"github.com/desmo999r/formolcli/controllers"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
"os"
)
var createBackupSessionCmd = &cobra.Command{
Use: "create",
Short: "Create a backupsession",
Run: func(cmd *cobra.Command, args []string) {
name, _ := cmd.Flags().GetString("name")
namespace, _ := cmd.Flags().GetString("namespace")
fmt.Println("create backupsession called")
backupsession.CreateBackupSession(corev1.ObjectReference{
Namespace: namespace,
Name: name,
})
},
}
var startServerCmd = &cobra.Command{
Use: "server",
Short: "Start a BackupSession / RestoreSession controller",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("starts backupsession controller")
controllers.StartServer()
},
}
var backupSessionCmd = &cobra.Command{
Use: "backupsession",
Short: "All the BackupSession related commands",
}
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "formolcli",
@ -34,13 +65,11 @@ func Execute() {
}
func init() {
// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.
// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.formolcli.yaml)")
// Cobra also supports local flags, which will only run
// when this action is called directly.
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
rootCmd.AddCommand(backupSessionCmd)
backupSessionCmd.AddCommand(createBackupSessionCmd)
rootCmd.AddCommand(startServerCmd)
createBackupSessionCmd.Flags().String("namespace", "", "The namespace of the BackupConfiguration containing the information about the backup.")
createBackupSessionCmd.Flags().String("name", "", "The name of the BackupConfiguration containing the information about the backup.")
createBackupSessionCmd.MarkFlagRequired("namespace")
createBackupSessionCmd.MarkFlagRequired("name")
}

View File

@ -12,49 +12,6 @@ import (
"strings"
)
const (
RESTIC_EXEC = "/usr/bin/restic"
)
func (r *BackupSessionReconciler) setResticEnv(backupConf formolv1alpha1.BackupConfiguration) error {
repo := formolv1alpha1.Repo{}
if err := r.Get(r.Context, client.ObjectKey{
Namespace: backupConf.Namespace,
Name: backupConf.Spec.Repository,
}, &repo); err != nil {
r.Log.Error(err, "unable to get repo")
return err
}
if repo.Spec.Backend.S3 != nil {
os.Setenv(formolv1alpha1.RESTIC_REPOSITORY, fmt.Sprintf("s3:http://%s/%s/%s-%s",
repo.Spec.Backend.S3.Server,
repo.Spec.Backend.S3.Bucket,
strings.ToUpper(backupConf.Namespace),
strings.ToLower(backupConf.Name)))
data := r.getSecretData(repo.Spec.RepositorySecrets)
os.Setenv(formolv1alpha1.AWS_SECRET_ACCESS_KEY, string(data[formolv1alpha1.AWS_SECRET_ACCESS_KEY]))
os.Setenv(formolv1alpha1.AWS_ACCESS_KEY_ID, string(data[formolv1alpha1.AWS_ACCESS_KEY_ID]))
os.Setenv(formolv1alpha1.RESTIC_PASSWORD, string(data[formolv1alpha1.RESTIC_PASSWORD]))
}
return nil
}
func (r *BackupSessionReconciler) checkRepo() error {
r.Log.V(0).Info("Checking repo")
if err := exec.Command(RESTIC_EXEC, "unlock").Run(); err != nil {
r.Log.Error(err, "unable to unlock repo", "repo", os.Getenv(formolv1alpha1.RESTIC_REPOSITORY))
}
output, err := exec.Command(RESTIC_EXEC, "check").CombinedOutput()
if err != nil {
r.Log.V(0).Info("Initializing new repo")
output, err = exec.Command(RESTIC_EXEC, "init").CombinedOutput()
if err != nil {
r.Log.Error(err, "something went wrong during repo init", "output", output)
}
}
return err
}
type BackupResult struct {
SnapshotId string
Duration float64

View File

@ -0,0 +1,37 @@
package controllers
import (
"context"
formolv1alpha1 "github.com/desmo999r/formol/api/v1alpha1"
"k8s.io/apimachinery/pkg/api/errors"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/log"
)
type RestoreSessionReconciler struct {
Session
}
func (r *RestoreSessionReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
r.Log = log.FromContext(ctx)
r.Context = ctx
restoreSession := formolv1alpha1.RestoreSession{}
err := r.Get(r.Context, req.NamespacedName, &restoreSession)
if err != nil {
if errors.IsNotFound(err) {
return ctrl.Result{}, nil
}
return ctrl.Result{}, err
}
switch restoreSession.Status.SessionState {
case formolv1alpha1.New:
}
return ctrl.Result{}, nil
}
func (r *RestoreSessionReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&formolv1alpha1.RestoreSession{}).
Complete(r)
}

View File

@ -37,6 +37,16 @@ func StartServer() {
setupLog.Error(err, "unable to create manager")
os.Exit(1)
}
if err = (&RestoreSessionReconciler{
Session: Session{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
},
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "RestoreSession")
os.Exit(1)
}
if err = (&BackupSessionReconciler{
Session: Session{
Client: mgr.GetClient(),

View File

@ -27,6 +27,49 @@ type Session struct {
Namespace string
}
const (
RESTIC_EXEC = "/usr/bin/restic"
)
func (s Session) setResticEnv(backupConf formolv1alpha1.BackupConfiguration) error {
repo := formolv1alpha1.Repo{}
if err := s.Get(r.Context, client.ObjectKey{
Namespace: backupConf.Namespace,
Name: backupConf.Spec.Repository,
}, &repo); err != nil {
s.Log.Error(err, "unable to get repo")
return err
}
if repo.Spec.Backend.S3 != nil {
os.Setenv(formolv1alpha1.RESTIC_REPOSITORY, fmt.Sprintf("s3:http://%s/%s/%s-%s",
repo.Spec.Backend.S3.Server,
repo.Spec.Backend.S3.Bucket,
strings.ToUpper(backupConf.Namespace),
strings.ToLower(backupConf.Name)))
data := s.getSecretData(repo.Spec.RepositorySecrets)
os.Setenv(formolv1alpha1.AWS_SECRET_ACCESS_KEY, string(data[formolv1alpha1.AWS_SECRET_ACCESS_KEY]))
os.Setenv(formolv1alpha1.AWS_ACCESS_KEY_ID, string(data[formolv1alpha1.AWS_ACCESS_KEY_ID]))
os.Setenv(formolv1alpha1.RESTIC_PASSWORD, string(data[formolv1alpha1.RESTIC_PASSWORD]))
}
return nil
}
func (s Session) checkRepo() error {
s.Log.V(0).Info("Checking repo")
if err := exec.Command(RESTIC_EXEC, "unlock").Run(); err != nil {
s.Log.Error(err, "unable to unlock repo", "repo", os.Getenv(formolv1alpha1.RESTIC_REPOSITORY))
}
output, err := exec.Command(RESTIC_EXEC, "check").CombinedOutput()
if err != nil {
s.Log.V(0).Info("Initializing new repo")
output, err = exec.Command(RESTIC_EXEC, "init").CombinedOutput()
if err != nil {
s.Log.Error(err, "something went wrong during repo init", "output", output)
}
}
return err
}
func (s Session) getSecretData(name string) map[string][]byte {
secret := corev1.Secret{}
namespace := os.Getenv(formolv1alpha1.POD_NAMESPACE)

2
formol

@ -1 +1 @@
Subproject commit 19d74cda40b40eaea1d633f30400abd46d898f7a
Subproject commit 3486ad2efe7bcf40990212299a87aaa70f88965f