Skip to content

Commit

Permalink
Delete Velero Backup when user sets the deleteVeleroBackup
Browse files Browse the repository at this point in the history
Enhancement which will delete original VeleroBackup when
the user sets the deleteVeleroBackup witin NonAdminBackup Spec.

Fixes Issue migtools#58

Signed-off-by: Michal Pryc <[email protected]>
  • Loading branch information
mpryc committed May 20, 2024
1 parent 914e498 commit 3db9cc3
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 4 deletions.
8 changes: 7 additions & 1 deletion api/v1alpha1/nonadminbackup_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
)

// NonAdminBackupPhase is a simple one high-level summary of the lifecycle of an NonAdminBackup.
// +kubebuilder:validation:Enum=New;BackingOff;Created
// +kubebuilder:validation:Enum=New;BackingOff;Created;Deleted
type NonAdminBackupPhase string

const (
Expand All @@ -32,13 +32,19 @@ const (
NonAdminBackupPhaseBackingOff NonAdminBackupPhase = "BackingOff"
// NonAdminBackupPhaseCreated - Velero Backup was created. The Phase will not have additional informations about the Backup.
NonAdminBackupPhaseCreated NonAdminBackupPhase = "Created"
// NonAdminBackupPhaseDeleted - Velero Backup was deleted.
NonAdminBackupPhaseDeleted NonAdminBackupPhase = "Deleted"
)

// NonAdminBackupSpec defines the desired state of NonAdminBackup
type NonAdminBackupSpec struct {
// BackupSpec defines the specification for a Velero backup.
BackupSpec *velerov1api.BackupSpec `json:"backupSpec,omitempty"`

// DeleteVeleroBackup tells the controller to remove created Velero Backup.
// +optional
DeleteVeleroBackup *bool `json:"deleteVeleroBackup,omitempty"`

// NonAdminBackup log level (use debug for the most logging, leave unset for default)
// +optional
// +kubebuilder:validation:Enum=trace;debug;info;warning;error;fatal;panic
Expand Down
1 change: 1 addition & 0 deletions api/v1alpha1/nonadmincontroller_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ type NonAdminCondition string
const (
NonAdminConditionAccepted NonAdminCondition = "Accepted"
NonAdminConditionQueued NonAdminCondition = "Queued"
NonAdminConditionDeletion NonAdminCondition = "Deletion"
)
5 changes: 5 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions config/crd/bases/nac.oadp.openshift.io_nonadminbackups.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,10 @@ spec:
type: string
type: array
type: object
deleteVeleroBackup:
description: DeleteVeleroBackup tells the controller to remove created
Velero Backup.
type: boolean
logLevel:
description: NonAdminBackup log level (use debug for the most logging,
leave unset for default)
Expand Down Expand Up @@ -597,6 +601,7 @@ spec:
- New
- BackingOff
- Created
- Deleted
type: string
veleroBackupName:
description: VeleroBackupName references the VeleroBackup object by
Expand Down
9 changes: 7 additions & 2 deletions docs/design/nab_status_update.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ The `phase` is a simple one high-level summary of the lifecycle of an NonAdminBa

It is always a one well defined value, that is intended to be a comprehensive state of a NonAdminBackup.

Those are are the possible values for phase:
Those are the possible values for phase:

| **Value** | **Description** |
|-----------|--------------------------------|
| New | *NonAdminBackup resource was accepted by the OpenShift cluster, but it has not yet been processed by the NonAdminController* |
| BackingOff | Velero *Backup* object was not created due to NonAdminBackup error (configuration or similar) |
| Created | Velero *Backup* was created. The Phase will not have additional informations about the *Backup* run |
| Deleted | Velero *Backup* was deleted by the controller |

### Conditions

Expand All @@ -28,6 +29,7 @@ The `conditions` is also a part of the NonAdminBackup's `status` field. One NAB
|-----------|--------------------------------|
| Accepted | The Backup object was accepted by the reconcile loop, but the Velero Backup may have not yet been created |
| Queued | The Velero Backup was created succesfully. At this stage errors may still occur either from the Velero not accepting backup or during backup procedure. |
| Deletion | The Velero Backup object was accepted by the reconcile loop for deletion |

The `condition` data is also accomapied with the following:

Expand Down Expand Up @@ -99,12 +101,15 @@ graph
START[Phase: New] -- NAC config OK --> ACCEPTED[Non Admin Backup Accepted]
START -- NAC config NOT OK --> ERROR[Phase: BackingOff]
ACCEPTED -- Create Velero Backup --> CREATED[Phase: Created]
CREATED -- Velero Backup deletion request --> DELETED[Phase: Deleted]
DELETED -- Deleted --> COND_DELETED{Conditions:\nDeletion:True}
DELETED -- Unable to delete --> COND_NOT_DELETED{Conditions:\nDeletion:False}
ACCEPTED -.-> COND_ACCEPTED{Conditions:\nAccepted: True\n}
CREATED -.-> COND_QUEUED{Conditions:\nAccepted: True\nQueued: True\n}
ERROR -.-> COND_ERROR{Conditions:\nAccepted: False}
classDef conditions fill:#ccc,stroke:#ccc,stroke-width:2px;
class COND_ACCEPTED,COND_QUEUED,COND_ERROR conditions;
class COND_ACCEPTED,COND_QUEUED,COND_ERROR,COND_DELETED,COND_NOT_DELETED conditions;
classDef phases fill:#777,stroke:#ccc,stroke-width:2px;
class START,CREATED,ERROR phases;
Expand Down
24 changes: 24 additions & 0 deletions internal/common/function/function.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (

"github.com/go-logr/logr"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
Expand Down Expand Up @@ -280,6 +281,29 @@ func CheckVeleroBackupLabels(backup *velerov1api.Backup) bool {
return exists && value == constant.ManagedByLabelValue
}

// DeleteVeleroBackup deletes Velero Backup object based on the NonAdminBackup object name and namespace
func DeleteVeleroBackup(ctx context.Context, r client.Client, logger logr.Logger, nab *nacv1alpha1.NonAdminBackup) (bool, error) {
veleroBackupName := GenerateVeleroBackupName(nab.Namespace, nab.Name)

logger.V(1).Info(fmt.Sprintf("Attempting to delete VeleroBackup: %s", veleroBackupName))
veleroBackup := velerov1api.Backup{}

err := r.Get(ctx, types.NamespacedName{Name: veleroBackupName, Namespace: constant.OadpNamespace}, &veleroBackup)

if err == nil {
err = r.Delete(ctx, &veleroBackup)
if err != nil {
logger.V(1).Info(fmt.Sprintf("Error deleting VeleroBackup: %s", veleroBackupName))
return false, err
}
} else if apierrors.IsNotFound(err) {
return false, nil
}

logger.V(1).Info(fmt.Sprintf("Deleted VeleroBackup: %s", veleroBackupName))
return true, nil
}

// TODO not used

// GetNonAdminBackupFromVeleroBackup return referenced NonAdminBackup object from Velero Backup object, if no error occurs
Expand Down
56 changes: 55 additions & 1 deletion internal/controller/nonadminbackup_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,13 @@ func (r *NonAdminBackupReconciler) Reconcile(ctx context.Context, req ctrl.Reque
return ctrl.Result{}, err
}

reconcileExit, reconcileErr := r.DeleteVeleroBackup(ctx, rLog, &nab)
if reconcileExit && reconcileErr != nil {
return ctrl.Result{}, reconcile.TerminalError(reconcileErr)
} else if reconcileExit {
return ctrl.Result{}, nil
}

reconcileExit, reconcileRequeue, reconcileErr := r.InitNonAdminBackup(ctx, rLog, &nab)
if reconcileRequeue {
return ctrl.Result{Requeue: true, RequeueAfter: requeueTimeSeconds * time.Second}, reconcileErr
Expand Down Expand Up @@ -118,6 +125,53 @@ func (r *NonAdminBackupReconciler) Reconcile(ctx context.Context, req ctrl.Reque
return ctrl.Result{}, nil
}

// DeleteVeleroBackup deletes original Velero Backup object when the deleteVeleroBackup Spec is set to true
//
// Parameters:
//
// ctx: Context for the request.
// logrLogger: Logger instance for logging messages.
// nab: Pointer to the NonAdminBackup object.
func (r *NonAdminBackupReconciler) DeleteVeleroBackup(ctx context.Context, logrLogger logr.Logger, nab *nacv1alpha1.NonAdminBackup) (exitReconcile bool, errorReconcile error) {
rLog := log.FromContext(ctx)
logger := logrLogger.WithValues("DeleteVeleroBackup", nab.Namespace)

// Delete Velero Backup if the deleteVeleroBackup was set to true
if nab.Spec.DeleteVeleroBackup != nil && *nab.Spec.DeleteVeleroBackup {
if nab.Status.Phase == nacv1alpha1.NonAdminBackupPhaseDeleted {
// No change, no need to update
return true, nil
}

deleted, deleteErr := function.DeleteVeleroBackup(ctx, r.Client, rLog, nab)
if deleteErr != nil {
return true, deleteErr
}

deletedMsg := "Velero Backup deleted"
deletedCondition := metav1.ConditionTrue

if !deleted {
deletedCondition = metav1.ConditionFalse
deletedMsg = "Unable to find origin Velero Backup"
}

_, errUpdateCondition := function.UpdateNonAdminBackupCondition(ctx, r.Client, logger, nab, nacv1alpha1.NonAdminConditionDeletion, deletedCondition, "BackupDeleted", deletedMsg)
if errUpdateCondition != nil {
logger.Error(errUpdateCondition, "Unable to set Deletion Condition: True", nameField, nab.Name, constant.NameSpaceString, nab.Namespace)
return true, errUpdateCondition
}
_, errUpdatePhase := function.UpdateNonAdminPhase(ctx, r.Client, logger, nab, nacv1alpha1.NonAdminBackupPhaseDeleted)

if errUpdatePhase != nil {
logger.Error(errUpdatePhase, "Unable to set NonAdminBackup Phase: Deleted", nameField, nab.Name, constant.NameSpaceString, nab.Namespace)
return true, errUpdatePhase
}
}

return false, nil
}

// InitNonAdminBackup sets the New Phase on a NonAdminBackup object if it is not already set.
//
// Parameters:
Expand Down Expand Up @@ -201,7 +255,7 @@ func (r *NonAdminBackupReconciler) ValidateVeleroBackupSpec(ctx context.Context,
return true, false, err
}

updatedStatus, errUpdateStatus := function.UpdateNonAdminBackupCondition(ctx, r.Client, logger, nab, nacv1alpha1.NonAdminConditionAccepted, metav1.ConditionTrue, "BackupAccepted", "backup accepted")
updatedStatus, errUpdateStatus := function.UpdateNonAdminBackupCondition(ctx, r.Client, logger, nab, nacv1alpha1.NonAdminConditionAccepted, metav1.ConditionTrue, "BackupAccepted", "Backup accepted")
if errUpdateStatus != nil {
logger.Error(errUpdateStatus, "Unable to set BackupAccepted Condition: True", nameField, nab.Name, constant.NameSpaceString, nab.Namespace)
return true, false, errUpdateStatus
Expand Down

0 comments on commit 3db9cc3

Please sign in to comment.