Compare commits

...

2 Commits

Author SHA1 Message Date
Jean-Marc ANDRE
cfea083594 sharedprocess and local restic repostory 2023-02-21 01:12:47 +01:00
Jean-Marc ANDRE
9f91876dd2 updated the tests 2023-02-21 01:12:43 +01:00
6 changed files with 106 additions and 36 deletions

View File

@ -30,8 +30,6 @@ const (
AWS_SECRET_ACCESS_KEY = "AWS_SECRET_ACCESS_KEY"
)
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
type S3 struct {
Server string `json:"server"`
Bucket string `json:"bucket"`
@ -39,11 +37,15 @@ type S3 struct {
Prefix string `json:"prefix,omitempty"`
}
type Local struct {
Path string `json:"path"`
}
type Backend struct {
// +optional
S3 *S3 `json:"s3,omitempty"`
// +optional
Nfs *string `json:"nfs,omitempty"`
Local *Local `json:"local,omitempty"`
}
// RepoSpec defines the desired state of Repo
@ -96,7 +98,6 @@ func (repo *Repo) GetResticEnv(backupConf BackupConfiguration) []corev1.EnvVar {
for _, key := range []string{
AWS_ACCESS_KEY_ID,
AWS_SECRET_ACCESS_KEY,
RESTIC_PASSWORD,
} {
env = append(env, corev1.EnvVar{
Name: key,
@ -111,6 +112,23 @@ func (repo *Repo) GetResticEnv(backupConf BackupConfiguration) []corev1.EnvVar {
})
}
}
if repo.Spec.Backend.Local != nil {
env = append(env, corev1.EnvVar{
Name: RESTIC_REPOSITORY,
Value: repo.Spec.Backend.Local.Path,
})
}
env = append(env, corev1.EnvVar{
Name: RESTIC_PASSWORD,
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: repo.Spec.RepositorySecrets,
},
Key: RESTIC_PASSWORD,
},
},
})
return env
}

View File

@ -34,9 +34,9 @@ func (in *Backend) DeepCopyInto(out *Backend) {
*out = new(S3)
**out = **in
}
if in.Nfs != nil {
in, out := &in.Nfs, &out.Nfs
*out = new(string)
if in.Local != nil {
in, out := &in.Local, &out.Local
*out = new(Local)
**out = **in
}
}
@ -347,6 +347,21 @@ func (in *Keep) DeepCopy() *Keep {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Local) DeepCopyInto(out *Local) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Local.
func (in *Local) DeepCopy() *Local {
if in == nil {
return nil
}
out := new(Local)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Repo) DeepCopyInto(out *Repo) {
*out = *in

View File

@ -150,30 +150,54 @@ func (r *BackupConfigurationReconciler) DeleteSidecar(backupConf formolv1alpha1.
}
}
}
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
}
r.Log.V(1).Info("Got Repository", "repo", repo)
for _, target := range backupConf.Spec.Targets {
var targetObject client.Object
var targetPodSpec *corev1.PodSpec
switch target.TargetKind {
case formolv1alpha1.Deployment:
deployment := &appsv1.Deployment{}
deployment := appsv1.Deployment{}
if err := r.Get(r.Context, client.ObjectKey{
Namespace: backupConf.Namespace,
Name: target.TargetName,
}, deployment); err != nil {
}, &deployment); err != nil {
r.Log.Error(err, "cannot get deployment", "Deployment", target.TargetName)
return err
}
restoreContainers := []corev1.Container{}
for _, container := range deployment.Spec.Template.Spec.Containers {
if container.Name == formolv1alpha1.SIDECARCONTAINER_NAME {
targetObject = &deployment
targetPodSpec = &deployment.Spec.Template.Spec
}
restoreContainers := []corev1.Container{}
for _, container := range targetPodSpec.Containers {
if container.Name == formolv1alpha1.SIDECARCONTAINER_NAME {
continue
}
restoreContainers = append(restoreContainers, container)
}
targetPodSpec.Containers = restoreContainers
if repo.Spec.Backend.Local != nil {
restoreVolumes := []corev1.Volume{}
for _, volume := range targetPodSpec.Volumes {
if volume.Name == "restic-local-repo" {
continue
}
restoreContainers = append(restoreContainers, container)
}
deployment.Spec.Template.Spec.Containers = restoreContainers
removeTags(&deployment.Spec.Template.Spec, target)
if err := r.Update(r.Context, deployment); err != nil {
r.Log.Error(err, "unable to update deployment", "deployment", deployment)
return err
restoreVolumes = append(restoreVolumes, volume)
}
targetPodSpec.Volumes = restoreVolumes
}
removeTags(targetPodSpec, target)
if err := r.Update(r.Context, targetObject); err != nil {
r.Log.Error(err, "unable to remove sidecar", "targetObject", targetObject)
return err
}
}
@ -280,14 +304,28 @@ func (r *BackupConfigurationReconciler) addOnlineSidecar(backupConf formolv1alph
return
}
sidecarPaths, vms := addTags(targetPodSpec, target)
sidecar.VolumeMounts = vms
sidecar.Env = append(sidecar.Env, corev1.EnvVar{
Name: formolv1alpha1.BACKUP_PATHS,
Value: strings.Join(sidecarPaths, string(os.PathListSeparator)),
})
if repo.Spec.Backend.Local != nil {
sidecar.VolumeMounts = append(vms, corev1.VolumeMount{
Name: "restic-local-repo",
MountPath: "/repo",
})
targetPodSpec.Volumes = append(targetPodSpec.Volumes, corev1.Volume{
Name: "restic-local-repo",
VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{},
},
})
} else {
sidecar.VolumeMounts = vms
}
// The sidecar definition is complete. Add it to the targetObject
targetPodSpec.Containers = append(targetPodSpec.Containers, sidecar)
targetPodSpec.ShareProcessNamespace = func() *bool { b := true; return &b }()
r.Log.V(1).Info("Adding sidecar", "targetObject", targetObject, "sidecar", sidecar)
if err = r.Update(r.Context, targetObject); err != nil {
r.Log.Error(err, "unable to add sidecar", "targetObject", targetObject)
@ -333,7 +371,7 @@ func (r *BackupConfigurationReconciler) createRBACSidecar(sa corev1.ServiceAccou
rbacv1.PolicyRule{
Verbs: []string{"get", "list", "watch"},
APIGroups: []string{"formol.desmojim.fr"},
Resources: []string{"backupsessions", "backupconfigurations"},
Resources: []string{"backupsessions", "backupconfigurations", "functions", "repos"},
},
rbacv1.PolicyRule{
Verbs: []string{"get", "list", "watch", "create", "update", "patch", "delete"},

View File

@ -74,11 +74,12 @@ data:
apiVersion: formol.desmojim.fr/v1alpha1
kind: Repo
metadata:
name: repo-empty
name: repo-local
namespace: demo
spec:
backend:
nfs: "toto"
local:
path: /repo
repositorySecrets: secret-minio
---
apiVersion: formol.desmojim.fr/v1alpha1
@ -162,7 +163,7 @@ metadata:
namespace: demo
spec:
name: maintenance-off
command: ["/bin/bash", "-c", "echo $(date +%Y/%m/%d-%H:%M:%S) maintenance-off >> /data/logs.txt"]
command: ["/bin/sh", "-c", "echo $(date +%Y/%m/%d-%H:%M:%S) maintenance-off >> /data/logs.txt"]
---
apiVersion: formol.desmojim.fr/v1alpha1
kind: Function
@ -171,4 +172,4 @@ metadata:
namespace: demo
spec:
name: maintenance-on
command: ["/bin/bash", "-c", "echo $(date +%Y/%m/%d-%H:%M:%S) maintenance-on >> /data/logs.txt"]
command: ["/bin/sh", "-c", "echo $(date +%Y/%m/%d-%H:%M:%S) maintenance-on >> /data/logs.txt"]

View File

@ -2,27 +2,27 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
name: apache-deployment
namespace: demo
labels:
app: nginx
app: apache
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nginx
app: apache
template:
metadata:
labels:
app: nginx
app: apache
spec:
imagePullSecrets:
- name: regcred
containers:
- name: nginx
image: docker.io/nginx:1.23.3
- name: apache
image: docker.io/httpd:alpine3.17
ports:
- containerPort: 80
volumeMounts:

View File

@ -7,7 +7,7 @@ metadata:
spec:
suspend: true
image: desmo999r/formolcli:latest
repository: repo-minio
repository: repo-local
schedule: "15 * * * *"
keep:
last: 5
@ -18,13 +18,11 @@ spec:
targets:
- backupType: Online
targetKind: Deployment
targetName: nginx-deployment
targetName: apache-deployment
containers:
- name: nginx
- name: apache
steps:
- name: maintenance-on
- name: with-env
- name: with-envfrom
- name: maintenance-off
finalize: true
paths: