From c89a5222625eb4851a04bc3b1d18c5b11bb1faad Mon Sep 17 00:00:00 2001 From: Jean-Marc ANDRE Date: Thu, 16 Feb 2023 21:40:22 +0100 Subject: [PATCH] added BackupConfiguration.Status.Targets struct to hold the paths to be backed up in the sidecar container --- api/v1alpha1/backupconfiguration_types.go | 9 ++++ api/v1alpha1/zz_generated.deepcopy.go | 27 ++++++++++++ controllers/backupconfiguration_controller.go | 8 +++- .../backupconfiguration_controller_helpers.go | 42 +++++++++++-------- 4 files changed, 67 insertions(+), 19 deletions(-) diff --git a/api/v1alpha1/backupconfiguration_types.go b/api/v1alpha1/backupconfiguration_types.go index 3a7d9f1..aff1486 100644 --- a/api/v1alpha1/backupconfiguration_types.go +++ b/api/v1alpha1/backupconfiguration_types.go @@ -38,6 +38,8 @@ const ( JobKind BackupType = "Job" ) +const BACKUP_PREFIX_PATH = `backup` + type Step struct { Name string `json:"name"` // +optional @@ -59,6 +61,11 @@ type Target struct { Retry int `json:"retry"` } +type TargetSidecarPath struct { + TargetName string `json:"targetName"` + SidecarPaths []string `json:"sidecarPaths"` +} + type Keep struct { Last int32 `json:"last"` Daily int32 `json:"daily"` @@ -84,6 +91,8 @@ type BackupConfigurationStatus struct { Suspended bool `json:"suspended"` ActiveCronJob bool `json:"activeCronJob"` ActiveSidecar bool `json:"activeSidecar"` + // +optional + Targets []TargetSidecarPath `json:"targets,omitempty"` } //+kubebuilder:object:root=true diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 3cd2fac..1cef863 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -145,6 +145,13 @@ func (in *BackupConfigurationStatus) DeepCopyInto(out *BackupConfigurationStatus in, out := &in.LastBackupTime, &out.LastBackupTime *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. @@ -610,6 +617,26 @@ func (in *TargetContainer) DeepCopy() *TargetContainer { 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. func (in *TargetStatus) DeepCopyInto(out *TargetStatus) { *out = *in diff --git a/controllers/backupconfiguration_controller.go b/controllers/backupconfiguration_controller.go index 600c213..792d94c 100644 --- a/controllers/backupconfiguration_controller.go +++ b/controllers/backupconfiguration_controller.go @@ -97,9 +97,15 @@ func (r *BackupConfigurationReconciler) Reconcile(ctx context.Context, req ctrl. switch target.BackupType { case formolv1alpha1.OnlineKind: // TODO: add a sidecar to the pod with the target.Containers[].Paths mounted - if err := r.AddOnlineSidecar(backupConf, target); err != nil { + if sidecarPaths, err := r.addOnlineSidecar(backupConf, target); err != nil { r.Log.Error(err, "unable to add online sidecar") 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 case formolv1alpha1.JobKind: diff --git a/controllers/backupconfiguration_controller_helpers.go b/controllers/backupconfiguration_controller_helpers.go index cd9c333..26c0f9e 100644 --- a/controllers/backupconfiguration_controller_helpers.go +++ b/controllers/backupconfiguration_controller_helpers.go @@ -24,9 +24,9 @@ import ( rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "path/filepath" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" - "strings" formolv1alpha1 "github.com/desmo999r/formol/api/v1alpha1" ) @@ -178,11 +178,12 @@ func (r *BackupConfigurationReconciler) DeleteSidecar(backupConf formolv1alpha1. return nil } -func (r *BackupConfigurationReconciler) AddOnlineSidecar(backupConf formolv1alpha1.BackupConfiguration, target formolv1alpha1.Target) error { - addTags := func(sideCar *corev1.Container, podSpec *corev1.PodSpec, target formolv1alpha1.Target) bool { +func (r *BackupConfigurationReconciler) addOnlineSidecar(backupConf formolv1alpha1.BackupConfiguration, target formolv1alpha1.Target) (sidecarPaths []string, err error) { + addTags := func(sideCar *corev1.Container, podSpec *corev1.PodSpec, target formolv1alpha1.Target) ([]string, bool) { + var sidecarPaths []string for i, container := range podSpec.Containers { if container.Name == formolv1alpha1.SIDECARCONTAINER_NAME { - return false + return sidecarPaths, false } for _, targetContainer := range target.Containers { if targetContainer.Name == container.Name { @@ -196,30 +197,34 @@ func (r *BackupConfigurationReconciler) AddOnlineSidecar(backupConf formolv1alph // and mount them under a path that exists in the sidecar container for i, path := range targetContainer.Paths { vm := corev1.VolumeMount{ReadOnly: true} + var longest int = 0 + var sidecarPath string for _, volumeMount := range container.VolumeMounts { - var longest int = 0 - if strings.HasPrefix(path, volumeMount.MountPath) && len(volumeMount.MountPath) > longest { + // if strings.HasPrefix(path, volumeMount.MountPath) && len(volumeMount.MountPath) > longest { + if rel, err := filepath.Rel(volumeMount.MountPath, path); err == nil && len(volumeMount.MountPath) > longest { longest = len(volumeMount.MountPath) vm.Name = volumeMount.Name - vm.MountPath = fmt.Sprintf("/backup%d", i) + vm.MountPath = fmt.Sprintf("/%s%d", formolv1alpha1.BACKUP_PREFIX_PATH, i) vm.SubPath = volumeMount.SubPath + sidecarPath = filepath.Join(vm.MountPath, rel) } } sideCar.VolumeMounts = append(sideCar.VolumeMounts, vm) + sidecarPaths = append(sidecarPaths, sidecarPath) } } } } - return true + return sidecarPaths, true } repo := formolv1alpha1.Repo{} - if err := r.Get(r.Context, client.ObjectKey{ + 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 + return } r.Log.V(1).Info("Got Repository", "repo", repo) env := repo.GetResticEnv(backupConf) @@ -245,33 +250,34 @@ func (r *BackupConfigurationReconciler) AddOnlineSidecar(backupConf formolv1alph switch target.TargetKind { case formolv1alpha1.Deployment: deployment := &appsv1.Deployment{} - if err := r.Get(r.Context, client.ObjectKey{ + if err = r.Get(r.Context, client.ObjectKey{ Namespace: backupConf.Namespace, Name: target.TargetName, }, deployment); err != nil { r.Log.Error(err, "cannot get deployment", "Deployment", target.TargetName) - return err + return } - if addTags(&sideCar, &deployment.Spec.Template.Spec, target) { - if err := r.createRBACSidecar(corev1.ServiceAccount{ + if paths, add := addTags(&sideCar, &deployment.Spec.Template.Spec, target); add == true { + sidecarPaths = paths + if err = r.createRBACSidecar(corev1.ServiceAccount{ ObjectMeta: metav1.ObjectMeta{ Namespace: deployment.Namespace, Name: deployment.Spec.Template.Spec.ServiceAccountName, }, }); err != nil { r.Log.Error(err, "unable to create RBAC for the sidecar container") - return err + return } deployment.Spec.Template.Spec.Containers = append(deployment.Spec.Template.Spec.Containers, sideCar) r.Log.V(1).Info("Updating deployment", "deployment", deployment, "containers", deployment.Spec.Template.Spec.Containers) - if err := r.Update(r.Context, deployment); err != nil { + if err = r.Update(r.Context, deployment); err != nil { r.Log.Error(err, "cannot update deployment", "Deployment", deployment) - return err + return } } } - return nil + return } func (r *BackupConfigurationReconciler) createRBACSidecar(sa corev1.ServiceAccount) error {