Compare commits

...

3 Commits

Author SHA1 Message Date
Jean-Marc ANDRE
888284017e Set backupsession state to NEW 2023-02-07 17:12:43 +01:00
Jean-Marc ANDRE
aba4ae4620 Added sidecar volume mounts 2023-02-07 17:12:17 +01:00
Jean-Marc ANDRE
e22c29f783 Cleanup 2023-02-07 17:11:16 +01:00
5 changed files with 44 additions and 95 deletions

View File

@ -35,8 +35,9 @@ const (
)
type TargetStatus struct {
Name string `json:"name"`
Kind string `json:"kind"`
BackupType `json:"backupType"`
TargetName string `json:"targetName"`
TargetKind `json:"targetKind"`
SessionState `json:"state"`
SnapshotId string `json:"snapshotId"`
StartTime *metav1.Time `json:"startTime"`

View File

@ -1,89 +0,0 @@
/*
Copyright 2023.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)
type SessionState string
const (
New SessionState = "New"
Init SessionState = "Initializing"
Running SessionState = "Running"
Waiting SessionState = "Waiting"
Finalize SessionState = "Finalizing"
Success SessionState = "Success"
Failure SessionState = "Failure"
Deleted SessionState = "Deleted"
)
type TargetStatus struct {
Name string `json:"name"`
Kind string `json:"kind"`
SessionState `json:"state"`
SnapshotId string `json:"snapshotId"`
StartTime *metav1.Time `json:"startTime"`
Duration *metav1.Duration `json:"duration"`
Try int `json:"try"`
}
// BackupSessionSpec defines the desired state of BackupSession
type BackupSessionSpec struct {
Ref corev1.ObjectReference `json:"ref"`
}
// BackupSessionStatus defines the observed state of BackupSession
type BackupSessionStatus struct {
SessionState `json:"state"`
StartTime *metav1.Time `json:"startTime"`
Targets []TargetStatus `json:"target"`
Keep string `json:"keep"`
}
//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
// +kubebuilder:resource:shortName="bs"
// +kubebuilder:printcolumn:name="Ref",type=string,JSONPath=`.spec.ref.name`
// +kubebuilder:printcolumn:name="State",type=string,JSONPath=`.status.state`
// +kubebuilder:printcolumn:name="Started",type=string,format=date-time,JSONPath=`.status.startTime`
// +kubebuilder:printcolumn:name="Keep",type=string,JSONPath=`.status.keep`
// BackupSession is the Schema for the backupsessions API
type BackupSession struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec BackupSessionSpec `json:"spec,omitempty"`
Status BackupSessionStatus `json:"status,omitempty"`
}
//+kubebuilder:object:root=true
// BackupSessionList contains a list of BackupSession
type BackupSessionList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []BackupSession `json:"items"`
}
func init() {
SchemeBuilder.Register(&BackupSession{}, &BackupSessionList{})
}

View File

@ -17,6 +17,7 @@ limitations under the License.
package controllers
import (
"fmt"
appsv1 "k8s.io/api/apps/v1"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
@ -24,6 +25,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"strings"
formolv1alpha1 "github.com/desmo999r/formol/api/v1alpha1"
)
@ -175,17 +177,34 @@ func (r *BackupConfigurationReconciler) AddSidecar(backupConf formolv1alpha1.Bac
// the backupType: Online needs a sidecar container for every single listed 'container'
// if the backupType is something else than Online, the 'container' will still need a sidecar
// if it has 'steps'
addTags := func(podSpec *corev1.PodSpec, target formolv1alpha1.Target) bool {
addTags := func(sideCar *corev1.Container, podSpec *corev1.PodSpec, target formolv1alpha1.Target) bool {
for i, container := range podSpec.Containers {
if container.Name == formolv1alpha1.SIDECARCONTAINER_NAME {
return false
}
for _, targetContainer := range target.Containers {
if targetContainer.Name == container.Name {
// Found a target container. Tag it.
podSpec.Containers[i].Env = append(container.Env, corev1.EnvVar{
Name: formolv1alpha1.TARGETCONTAINER_TAG,
Value: container.Name,
})
// targetContainer.Paths are the paths to backup
// We have to find what volumes are mounted under those paths
// and mount them under a path that exists in the sidecar container
for i, path := range targetContainer.Paths {
vm := corev1.VolumeMount{ReadOnly: true}
for _, volumeMount := range container.VolumeMounts {
var longest int = 0
if strings.HasPrefix(path, volumeMount.MountPath) && len(volumeMount.MountPath) > longest {
longest = len(volumeMount.MountPath)
vm.Name = volumeMount.Name
vm.MountPath = fmt.Sprintf("/backup%d", i)
vm.SubPath = volumeMount.SubPath
}
}
sideCar.VolumeMounts = append(sideCar.VolumeMounts, vm)
}
}
}
}
@ -233,7 +252,7 @@ func (r *BackupConfigurationReconciler) AddSidecar(backupConf formolv1alpha1.Bac
r.Log.Error(err, "cannot get deployment", "Deployment", target.TargetName)
return err
}
if addTags(&deployment.Spec.Template.Spec, target) {
if addTags(&sideCar, &deployment.Spec.Template.Spec, target) {
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 {

View File

@ -18,8 +18,10 @@ package controllers
import (
formolv1alpha1 "github.com/desmo999r/formol/api/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"sigs.k8s.io/controller-runtime/pkg/client"
"time"
)
func (r *BackupSessionReconciler) isBackupOngoing(backupConf formolv1alpha1.BackupConfiguration) bool {
@ -36,10 +38,26 @@ func (r *BackupSessionReconciler) isBackupOngoing(backupConf formolv1alpha1.Back
return len(backupSessionList.Items) > 0
}
func (r *BackupSessionReconciler) startNextTask(backupSession formolv1alpha1.BackupSession, backupConf formolv1alpha1.BackupConfiguration) (formolv1alpha1.TargetStatus, error) {
func (r *BackupSessionReconciler) startNextTask(backupSession formolv1alpha1.BackupSession, backupConf formolv1alpha1.BackupConfiguration) (*formolv1alpha1.TargetStatus, error) {
nextTargetIndex := len(backupSession.Status.Targets)
if nextTargetIndex < len(backupConf.Spec.Targets) {
nextTarget := backupConf.Spec.Targets[nextTargetIndex]
nextTargetStatus := formolv1alpha1.TargetStatus{
BackupType: nextTarget.BackupType,
TargetName: nextTarget.TargetName,
TargetKind: nextTarget.TargetKind,
SessionState: formolv1alpha1.New,
StartTime: &metav1.Time{Time: time.Now()},
Try: 1,
}
switch nextTarget.BackupType {
case formolv1alpha1.JobKind:
r.Log.V(0).Info("Starts a new JobKind task", "target", nextTarget)
case formolv1alpha1.SnapshotKind:
r.Log.V(0).Info("Starts a new SnapshotKind task", "target", nextTarget)
}
return &nextTargetStatus, nil
} else {
return nil, nil
}
return nil, nil
}