A sidecar ENV keeps the paths to backup. That will do for now but the BackupSession controller in the sidecar should do the job of computing the paths to backup every time it reconciles. In case the paths have changed

This commit is contained in:
Jean-Marc ANDRE 2023-02-18 22:46:15 +01:00
parent c89a522262
commit 1361f62045
5 changed files with 50 additions and 70 deletions

View File

@ -61,11 +61,6 @@ type Target struct {
Retry int `json:"retry"` Retry int `json:"retry"`
} }
type TargetSidecarPath struct {
TargetName string `json:"targetName"`
SidecarPaths []string `json:"sidecarPaths"`
}
type Keep struct { type Keep struct {
Last int32 `json:"last"` Last int32 `json:"last"`
Daily int32 `json:"daily"` Daily int32 `json:"daily"`
@ -91,8 +86,6 @@ type BackupConfigurationStatus struct {
Suspended bool `json:"suspended"` Suspended bool `json:"suspended"`
ActiveCronJob bool `json:"activeCronJob"` ActiveCronJob bool `json:"activeCronJob"`
ActiveSidecar bool `json:"activeSidecar"` ActiveSidecar bool `json:"activeSidecar"`
// +optional
Targets []TargetSidecarPath `json:"targets,omitempty"`
} }
//+kubebuilder:object:root=true //+kubebuilder:object:root=true

View File

@ -10,4 +10,6 @@ const (
// Used by the backupsession controller // Used by the backupsession controller
POD_NAME string = "POD_NAME" POD_NAME string = "POD_NAME"
POD_NAMESPACE string = "POD_NAMESPACE" POD_NAMESPACE string = "POD_NAMESPACE"
// Backup Paths list
BACKUP_PATHS = "BACKUP_PATHS"
) )

View File

@ -145,13 +145,6 @@ func (in *BackupConfigurationStatus) DeepCopyInto(out *BackupConfigurationStatus
in, out := &in.LastBackupTime, &out.LastBackupTime in, out := &in.LastBackupTime, &out.LastBackupTime
*out = (*in).DeepCopy() *out = (*in).DeepCopy()
} }
if in.Targets != nil {
in, out := &in.Targets, &out.Targets
*out = make([]TargetSidecarPath, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
} }
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupConfigurationStatus. // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupConfigurationStatus.
@ -617,26 +610,6 @@ func (in *TargetContainer) DeepCopy() *TargetContainer {
return out return out
} }
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TargetSidecarPath) DeepCopyInto(out *TargetSidecarPath) {
*out = *in
if in.SidecarPaths != nil {
in, out := &in.SidecarPaths, &out.SidecarPaths
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetSidecarPath.
func (in *TargetSidecarPath) DeepCopy() *TargetSidecarPath {
if in == nil {
return nil
}
out := new(TargetSidecarPath)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TargetStatus) DeepCopyInto(out *TargetStatus) { func (in *TargetStatus) DeepCopyInto(out *TargetStatus) {
*out = *in *out = *in

View File

@ -97,15 +97,9 @@ func (r *BackupConfigurationReconciler) Reconcile(ctx context.Context, req ctrl.
switch target.BackupType { switch target.BackupType {
case formolv1alpha1.OnlineKind: case formolv1alpha1.OnlineKind:
// TODO: add a sidecar to the pod with the target.Containers[].Paths mounted // TODO: add a sidecar to the pod with the target.Containers[].Paths mounted
if sidecarPaths, err := r.addOnlineSidecar(backupConf, target); err != nil { if err := r.addOnlineSidecar(backupConf, target); err != nil {
r.Log.Error(err, "unable to add online sidecar") r.Log.Error(err, "unable to add online sidecar")
return ctrl.Result{}, err return ctrl.Result{}, err
} else if len(sidecarPaths) > 0 {
backupConf.Status.Targets = append(backupConf.Status.Targets,
formolv1alpha1.TargetSidecarPath{
TargetName: target.TargetName,
SidecarPaths: sidecarPaths,
})
} }
backupConf.Status.ActiveSidecar = true backupConf.Status.ActiveSidecar = true
case formolv1alpha1.JobKind: case formolv1alpha1.JobKind:

View File

@ -24,9 +24,11 @@ import (
rbacv1 "k8s.io/api/rbac/v1" rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"os"
"path/filepath" "path/filepath"
ctrl "sigs.k8s.io/controller-runtime" ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"strings"
formolv1alpha1 "github.com/desmo999r/formol/api/v1alpha1" formolv1alpha1 "github.com/desmo999r/formol/api/v1alpha1"
) )
@ -178,13 +180,18 @@ func (r *BackupConfigurationReconciler) DeleteSidecar(backupConf formolv1alpha1.
return nil return nil
} }
func (r *BackupConfigurationReconciler) addOnlineSidecar(backupConf formolv1alpha1.BackupConfiguration, target formolv1alpha1.Target) (sidecarPaths []string, err error) { func hasSidecar(podSpec *corev1.PodSpec) bool {
addTags := func(sideCar *corev1.Container, podSpec *corev1.PodSpec, target formolv1alpha1.Target) ([]string, bool) { for _, container := range podSpec.Containers {
var sidecarPaths []string if container.Name == formolv1alpha1.SIDECARCONTAINER_NAME {
return true
}
}
return false
}
func (r *BackupConfigurationReconciler) addOnlineSidecar(backupConf formolv1alpha1.BackupConfiguration, target formolv1alpha1.Target) (err error) {
addTags := func(podSpec *corev1.PodSpec, target formolv1alpha1.Target) (sidecarPaths []string, vms []corev1.VolumeMount) {
for i, container := range podSpec.Containers { for i, container := range podSpec.Containers {
if container.Name == formolv1alpha1.SIDECARCONTAINER_NAME {
return sidecarPaths, false
}
for _, targetContainer := range target.Containers { for _, targetContainer := range target.Containers {
if targetContainer.Name == container.Name { if targetContainer.Name == container.Name {
// Found a target container. Tag it. // Found a target container. Tag it.
@ -209,13 +216,13 @@ func (r *BackupConfigurationReconciler) addOnlineSidecar(backupConf formolv1alph
sidecarPath = filepath.Join(vm.MountPath, rel) sidecarPath = filepath.Join(vm.MountPath, rel)
} }
} }
sideCar.VolumeMounts = append(sideCar.VolumeMounts, vm) vms = append(vms, vm)
sidecarPaths = append(sidecarPaths, sidecarPath) sidecarPaths = append(sidecarPaths, sidecarPath)
} }
} }
} }
} }
return sidecarPaths, true return
} }
repo := formolv1alpha1.Repo{} repo := formolv1alpha1.Repo{}
@ -224,11 +231,11 @@ func (r *BackupConfigurationReconciler) addOnlineSidecar(backupConf formolv1alph
Name: backupConf.Spec.Repository, Name: backupConf.Spec.Repository,
}, &repo); err != nil { }, &repo); err != nil {
r.Log.Error(err, "unable to get Repo") r.Log.Error(err, "unable to get Repo")
return return err
} }
r.Log.V(1).Info("Got Repository", "repo", repo) r.Log.V(1).Info("Got Repository", "repo", repo)
env := repo.GetResticEnv(backupConf) env := repo.GetResticEnv(backupConf)
sideCar := corev1.Container{ sidecar := corev1.Container{
Name: formolv1alpha1.SIDECARCONTAINER_NAME, Name: formolv1alpha1.SIDECARCONTAINER_NAME,
Image: backupConf.Spec.Image, Image: backupConf.Spec.Image,
Args: []string{"backupsession", "server"}, Args: []string{"backupsession", "server"},
@ -247,33 +254,44 @@ func (r *BackupConfigurationReconciler) addOnlineSidecar(backupConf formolv1alph
}), }),
VolumeMounts: []corev1.VolumeMount{}, VolumeMounts: []corev1.VolumeMount{},
} }
var targetObject client.Object
var targetPodSpec *corev1.PodSpec
switch target.TargetKind { switch target.TargetKind {
case formolv1alpha1.Deployment: case formolv1alpha1.Deployment:
deployment := &appsv1.Deployment{} deployment := appsv1.Deployment{}
if err = r.Get(r.Context, client.ObjectKey{ if err = r.Get(r.Context, client.ObjectKey{
Namespace: backupConf.Namespace, Namespace: backupConf.Namespace,
Name: target.TargetName, Name: target.TargetName,
}, deployment); err != nil { }, &deployment); err != nil {
r.Log.Error(err, "cannot get deployment", "Deployment", target.TargetName) r.Log.Error(err, "cannot get deployment", "Deployment", target.TargetName)
return return
} }
if paths, add := addTags(&sideCar, &deployment.Spec.Template.Spec, target); add == true { targetObject = &deployment
sidecarPaths = paths targetPodSpec = &deployment.Spec.Template.Spec
if err = r.createRBACSidecar(corev1.ServiceAccount{ }
ObjectMeta: metav1.ObjectMeta{ if !hasSidecar(targetPodSpec) {
Namespace: deployment.Namespace, if err = r.createRBACSidecar(corev1.ServiceAccount{
Name: deployment.Spec.Template.Spec.ServiceAccountName, ObjectMeta: metav1.ObjectMeta{
}, Namespace: backupConf.Namespace,
}); err != nil { Name: targetPodSpec.ServiceAccountName,
r.Log.Error(err, "unable to create RBAC for the sidecar container") },
return }); err != nil {
} r.Log.Error(err, "unable to create RBAC for the sidecar container")
deployment.Spec.Template.Spec.Containers = append(deployment.Spec.Template.Spec.Containers, sideCar) return
r.Log.V(1).Info("Updating deployment", "deployment", deployment, "containers", deployment.Spec.Template.Spec.Containers) }
if err = r.Update(r.Context, deployment); err != nil { sidecarPaths, vms := addTags(targetPodSpec, target)
r.Log.Error(err, "cannot update deployment", "Deployment", deployment) sidecar.VolumeMounts = vms
return sidecar.Env = append(sidecar.Env, corev1.EnvVar{
} Name: formolv1alpha1.BACKUP_PATHS,
Value: strings.Join(sidecarPaths, string(os.PathListSeparator)),
})
// The sidecar definition is complete. Add it to the targetObject
targetPodSpec.Containers = append(targetPodSpec.Containers, sidecar)
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)
return
} }
} }