snapshots #10
@ -17,7 +17,10 @@ limitations under the License.
|
|||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
// +kubebuilder:validation:Enum=Deployment;StatefulSet;Pod
|
// +kubebuilder:validation:Enum=Deployment;StatefulSet;Pod
|
||||||
@ -38,6 +41,22 @@ const (
|
|||||||
JobKind BackupType = "Job"
|
JobKind BackupType = "Job"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func GetTargetObjects(kind TargetKind) (targetObject client.Object, targetPodSpec *corev1.PodSpec) {
|
||||||
|
switch kind {
|
||||||
|
case Deployment:
|
||||||
|
deployment := appsv1.Deployment{}
|
||||||
|
targetObject = &deployment
|
||||||
|
targetPodSpec = &deployment.Spec.Template.Spec
|
||||||
|
|
||||||
|
case StatefulSet:
|
||||||
|
statefulSet := appsv1.StatefulSet{}
|
||||||
|
targetObject = &statefulSet
|
||||||
|
targetPodSpec = &statefulSet.Spec.Template.Spec
|
||||||
|
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
BACKUP_PREFIX_PATH = `backup`
|
BACKUP_PREFIX_PATH = `backup`
|
||||||
FORMOL_SHARED_VOLUME = `formol-shared`
|
FORMOL_SHARED_VOLUME = `formol-shared`
|
||||||
|
|||||||
@ -18,7 +18,6 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
appsv1 "k8s.io/api/apps/v1"
|
|
||||||
batchv1 "k8s.io/api/batch/v1"
|
batchv1 "k8s.io/api/batch/v1"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
rbacv1 "k8s.io/api/rbac/v1"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
@ -130,36 +129,6 @@ func (r *BackupConfigurationReconciler) AddCronJob(backupConf formolv1alpha1.Bac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *BackupConfigurationReconciler) getTargetObjects(kind formolv1alpha1.TargetKind, namespace string, name string) (targetObject client.Object, targetPodSpec *corev1.PodSpec, err error) {
|
|
||||||
switch kind {
|
|
||||||
case formolv1alpha1.Deployment:
|
|
||||||
deployment := appsv1.Deployment{}
|
|
||||||
if err = r.Get(r.Context, client.ObjectKey{
|
|
||||||
Namespace: namespace,
|
|
||||||
Name: name,
|
|
||||||
}, &deployment); err != nil {
|
|
||||||
r.Log.Error(err, "cannot get deployment", "Deployment", name)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
targetObject = &deployment
|
|
||||||
targetPodSpec = &deployment.Spec.Template.Spec
|
|
||||||
|
|
||||||
case formolv1alpha1.StatefulSet:
|
|
||||||
statefulSet := appsv1.StatefulSet{}
|
|
||||||
if err = r.Get(r.Context, client.ObjectKey{
|
|
||||||
Namespace: namespace,
|
|
||||||
Name: name,
|
|
||||||
}, &statefulSet); err != nil {
|
|
||||||
r.Log.Error(err, "cannot get StatefulSet", "StatefulSet", name)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
targetObject = &statefulSet
|
|
||||||
targetPodSpec = &statefulSet.Spec.Template.Spec
|
|
||||||
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *BackupConfigurationReconciler) DeleteSidecar(backupConf formolv1alpha1.BackupConfiguration) error {
|
func (r *BackupConfigurationReconciler) DeleteSidecar(backupConf formolv1alpha1.BackupConfiguration) error {
|
||||||
removeTags := func(podSpec *corev1.PodSpec, target formolv1alpha1.Target) {
|
removeTags := func(podSpec *corev1.PodSpec, target formolv1alpha1.Target) {
|
||||||
for i, container := range podSpec.Containers {
|
for i, container := range podSpec.Containers {
|
||||||
@ -190,9 +159,12 @@ func (r *BackupConfigurationReconciler) DeleteSidecar(backupConf formolv1alpha1.
|
|||||||
}
|
}
|
||||||
r.Log.V(1).Info("Got Repository", "repo", repo)
|
r.Log.V(1).Info("Got Repository", "repo", repo)
|
||||||
for _, target := range backupConf.Spec.Targets {
|
for _, target := range backupConf.Spec.Targets {
|
||||||
targetObject, targetPodSpec, err := r.getTargetObjects(target.TargetKind, backupConf.Namespace, target.TargetName)
|
targetObject, targetPodSpec := formolv1alpha1.GetTargetObjects(target.TargetKind)
|
||||||
if err != nil {
|
if err := r.Get(r.Context, client.ObjectKey{
|
||||||
r.Log.Error(err, "unable to get target objects")
|
Namespace: backupConf.Namespace,
|
||||||
|
Name: target.TargetName,
|
||||||
|
}, targetObject); err != nil {
|
||||||
|
r.Log.Error(err, "cannot get target", "target", target.TargetName)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
restoreContainers := []corev1.Container{}
|
restoreContainers := []corev1.Container{}
|
||||||
@ -225,7 +197,7 @@ func (r *BackupConfigurationReconciler) DeleteSidecar(backupConf formolv1alpha1.
|
|||||||
}
|
}
|
||||||
targetPodSpec.Volumes = restoreVolumes
|
targetPodSpec.Volumes = restoreVolumes
|
||||||
removeTags(targetPodSpec, target)
|
removeTags(targetPodSpec, target)
|
||||||
if err = r.Update(r.Context, targetObject); err != nil {
|
if err := r.Update(r.Context, targetObject); err != nil {
|
||||||
r.Log.Error(err, "unable to remove sidecar", "targetObject", targetObject)
|
r.Log.Error(err, "unable to remove sidecar", "targetObject", targetObject)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -275,9 +247,12 @@ func (r *BackupConfigurationReconciler) addSidecar(backupConf formolv1alpha1.Bac
|
|||||||
Privileged: func() *bool { b := true; return &b }(),
|
Privileged: func() *bool { b := true; return &b }(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
targetObject, targetPodSpec, err := r.getTargetObjects(target.TargetKind, backupConf.Namespace, target.TargetName)
|
targetObject, targetPodSpec := formolv1alpha1.GetTargetObjects(target.TargetKind)
|
||||||
if err != nil {
|
if err := r.Get(r.Context, client.ObjectKey{
|
||||||
r.Log.Error(err, "unable to get target objects")
|
Namespace: backupConf.Namespace,
|
||||||
|
Name: target.TargetName,
|
||||||
|
}, targetObject); err != nil {
|
||||||
|
r.Log.Error(err, "cannot get target", "target", target.TargetName)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !hasSidecar(targetPodSpec) {
|
if !hasSidecar(targetPodSpec) {
|
||||||
|
|||||||
@ -65,7 +65,33 @@ func (r *RestoreSessionReconciler) Reconcile(ctx context.Context, req ctrl.Reque
|
|||||||
var newSessionState formolv1alpha1.SessionState
|
var newSessionState formolv1alpha1.SessionState
|
||||||
switch restoreSession.Status.SessionState {
|
switch restoreSession.Status.SessionState {
|
||||||
case formolv1alpha1.New:
|
case formolv1alpha1.New:
|
||||||
newSessionState = r.initRestore(&restoreSession, backupConf)
|
// Go through the Targets and create the corresponding TargetStatus. Move to Initializing.
|
||||||
|
if r.isBackupOngoing(backupConf) {
|
||||||
|
r.Log.V(0).Info("there is an ongoing backup. Let's reschedule this operation")
|
||||||
|
return ctrl.Result{
|
||||||
|
RequeueAfter: 30 * time.Second,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
restoreSession.Status.Targets = r.initSession(backupConf)
|
||||||
|
newSessionState = formolv1alpha1.Initializing
|
||||||
|
case formolv1alpha1.Initializing:
|
||||||
|
// Wait for all the Targets to be in the Initialized state then move them to Running and move to Running myself.
|
||||||
|
// if one of the Target fails to initialize, move it back to New state and decrement Try.
|
||||||
|
// if try reaches 0, move all the Targets to Finalize and move myself to Failure.
|
||||||
|
newSessionState = r.checkInitialized(restoreSession.Status.Targets, backupConf)
|
||||||
|
case formolv1alpha1.Running:
|
||||||
|
// Wait for all the target to be in Waiting state then move them to the Finalize state. Move myself to Finalize.
|
||||||
|
// if one of the Target fails the backup, move it back to Running state and decrement Try.
|
||||||
|
// if try reaches 0, move all the Targets to Finalize and move myself to Failure.
|
||||||
|
newSessionState = r.checkWaiting(restoreSession.Status.Targets, backupConf)
|
||||||
|
case formolv1alpha1.Finalize:
|
||||||
|
// Check the TargetStatus of all the Targets. If they are all Success then move myself to Success.
|
||||||
|
// if one of the Target fails to Finalize, move it back to Finalize state and decrement Try.
|
||||||
|
// if try reaches 0, move myself to Success because the backup was a Success even if the Finalize failed.
|
||||||
|
if newSessionState = r.checkSuccess(restoreSession.Status.Targets, backupConf); newSessionState == formolv1alpha1.Failure {
|
||||||
|
r.Log.V(0).Info("One of the target did not manage to Finalize but the backup is still a Success")
|
||||||
|
newSessionState = formolv1alpha1.Success
|
||||||
|
}
|
||||||
case "":
|
case "":
|
||||||
newSessionState = formolv1alpha1.New
|
newSessionState = formolv1alpha1.New
|
||||||
restoreSession.Status.StartTime = &metav1.Time{Time: time.Now()}
|
restoreSession.Status.StartTime = &metav1.Time{Time: time.Now()}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user