Compare commits
2 Commits
d4231768d7
...
994b792d97
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
994b792d97 | ||
|
|
0f8012c22e |
@ -1,6 +1,6 @@
|
|||||||
# Build a small image
|
# Build a small image
|
||||||
FROM --platform=linux/amd64 alpine:3
|
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
|
COPY ./bin/formolcli /usr/local/bin
|
||||||
|
|
||||||
# Command to run
|
# Command to run
|
||||||
|
|||||||
8
Dockerfile.arm64
Normal file
8
Dockerfile.arm64
Normal 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"]
|
||||||
@ -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")
|
|
||||||
}
|
|
||||||
51
cmd/root.go
51
cmd/root.go
@ -4,11 +4,42 @@ Copyright © 2023 NAME HERE <EMAIL ADDRESS>
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"fmt"
|
||||||
|
"github.com/desmo999r/formolcli/backupsession"
|
||||||
|
"github.com/desmo999r/formolcli/controllers"
|
||||||
"github.com/spf13/cobra"
|
"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
|
// rootCmd represents the base command when called without any subcommands
|
||||||
var rootCmd = &cobra.Command{
|
var rootCmd = &cobra.Command{
|
||||||
Use: "formolcli",
|
Use: "formolcli",
|
||||||
@ -34,13 +65,11 @@ func Execute() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// Here you will define your flags and configuration settings.
|
rootCmd.AddCommand(backupSessionCmd)
|
||||||
// Cobra supports persistent flags, which, if defined here,
|
backupSessionCmd.AddCommand(createBackupSessionCmd)
|
||||||
// will be global for your application.
|
rootCmd.AddCommand(startServerCmd)
|
||||||
|
createBackupSessionCmd.Flags().String("namespace", "", "The namespace of the BackupConfiguration containing the information about the backup.")
|
||||||
// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.formolcli.yaml)")
|
createBackupSessionCmd.Flags().String("name", "", "The name of the BackupConfiguration containing the information about the backup.")
|
||||||
|
createBackupSessionCmd.MarkFlagRequired("namespace")
|
||||||
// Cobra also supports local flags, which will only run
|
createBackupSessionCmd.MarkFlagRequired("name")
|
||||||
// when this action is called directly.
|
|
||||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,49 +12,6 @@ import (
|
|||||||
"strings"
|
"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 {
|
type BackupResult struct {
|
||||||
SnapshotId string
|
SnapshotId string
|
||||||
Duration float64
|
Duration float64
|
||||||
|
|||||||
37
controllers/restoresession_controller.go
Normal file
37
controllers/restoresession_controller.go
Normal 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)
|
||||||
|
}
|
||||||
@ -37,6 +37,16 @@ func StartServer() {
|
|||||||
setupLog.Error(err, "unable to create manager")
|
setupLog.Error(err, "unable to create manager")
|
||||||
os.Exit(1)
|
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{
|
if err = (&BackupSessionReconciler{
|
||||||
Session: Session{
|
Session: Session{
|
||||||
Client: mgr.GetClient(),
|
Client: mgr.GetClient(),
|
||||||
|
|||||||
@ -27,6 +27,49 @@ type Session struct {
|
|||||||
Namespace string
|
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 {
|
func (s Session) getSecretData(name string) map[string][]byte {
|
||||||
secret := corev1.Secret{}
|
secret := corev1.Secret{}
|
||||||
namespace := os.Getenv(formolv1alpha1.POD_NAMESPACE)
|
namespace := os.Getenv(formolv1alpha1.POD_NAMESPACE)
|
||||||
|
|||||||
2
formol
2
formol
@ -1 +1 @@
|
|||||||
Subproject commit 19d74cda40b40eaea1d633f30400abd46d898f7a
|
Subproject commit 3486ad2efe7bcf40990212299a87aaa70f88965f
|
||||||
Loading…
Reference in New Issue
Block a user