Skip to content

Commit

Permalink
Move API conditions and phases into common api file (#130)
Browse files Browse the repository at this point in the history
Signed-off-by: Michal Pryc <[email protected]>
  • Loading branch information
mpryc authored Dec 10, 2024
1 parent 06cf4a2 commit 56afada
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 114 deletions.
52 changes: 52 additions & 0 deletions api/v1alpha1/nonadmin_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
Copyright 2024.
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

// NonAdminPhase is a simple one high-level summary of the lifecycle of a NonAdminBackup or NonAdminRestore.
// +kubebuilder:validation:Enum=New;BackingOff;Created;Deleting
type NonAdminPhase string

const (
// NonAdminPhaseNew - NonAdmin object was accepted by the OpenShift cluster, but it has not yet been processed by the NonAdminController
NonAdminPhaseNew NonAdminPhase = "New"
// NonAdminPhaseBackingOff - Velero object was not created due to NonAdmin object error (configuration or similar)
NonAdminPhaseBackingOff NonAdminPhase = "BackingOff"
// NonAdminPhaseCreated - Velero object was created. The Phase will not have additional information about it.
NonAdminPhaseCreated NonAdminPhase = "Created"
// NonAdminPhaseDeleting - Velero object is pending deletion. The Phase will not have additional information about it.
NonAdminPhaseDeleting NonAdminPhase = "Deleting"
)

// NonAdminCondition are used for more detailed information supporing NonAdminBackupPhase state.
// +kubebuilder:validation:Enum=Accepted;Queued;Deleting
type NonAdminCondition string

// Predefined conditions for NonAdminController objects.
// One NonAdminController object may have multiple conditions.
// It is more granular knowledge of the NonAdminController object and represents the
// array of the conditions through which the NonAdminController has or has not passed
const (
NonAdminConditionAccepted NonAdminCondition = "Accepted"
NonAdminConditionQueued NonAdminCondition = "Queued"
NonAdminConditionDeleting NonAdminCondition = "Deleting"
)

// QueueInfo holds the queue position for a specific operation.
type QueueInfo struct {
// estimatedQueuePosition is the number of operations ahead in the queue (0 if not queued)
EstimatedQueuePosition int `json:"estimatedQueuePosition"`
}
28 changes: 4 additions & 24 deletions api/v1alpha1/nonadminbackup_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

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

const (
// NonAdminPhaseNew - NonAdmin object was accepted by the OpenShift cluster, but it has not yet been processed by the NonAdminController
NonAdminPhaseNew NonAdminPhase = "New"
// NonAdminPhaseBackingOff - Velero object was not created due to NonAdmin object error (configuration or similar)
NonAdminPhaseBackingOff NonAdminPhase = "BackingOff"
// NonAdminPhaseCreated - Velero object was created. The Phase will not have additional information about it.
NonAdminPhaseCreated NonAdminPhase = "Created"
// NonAdminPhaseDeleting - Velero object is pending deletion. The Phase will not have additional information about it.
NonAdminPhaseDeleting NonAdminPhase = "Deleting"
)

// NonAdminBackupSpec defines the desired state of NonAdminBackup
type NonAdminBackupSpec struct {
// BackupSpec defines the specification for a Velero backup.
Expand Down Expand Up @@ -98,6 +83,10 @@ type NonAdminBackupStatus struct {
// +optional
VeleroDeleteBackupRequest *VeleroDeleteBackupRequest `json:"veleroDeleteBackupRequest,omitempty"`

// queueInfo is used to estimate how many backups are scheduled before the given VeleroBackup in the OADP namespace.
// This number is not guaranteed to be accurate, but it should be close. It's inaccurate for cases when
// Velero pod is not running or being restarted after Backup object were created.
// It counts only VeleroBackups that are still subject to be handled by OADP/Velero.
// +optional
QueueInfo *QueueInfo `json:"queueInfo,omitempty"`

Expand All @@ -107,15 +96,6 @@ type NonAdminBackupStatus struct {
Conditions []metav1.Condition `json:"conditions,omitempty"`
}

// QueueInfo holds the queue position for a specific VeleroBackup.
// It is used to estimate how many backups are scheduled before the given VeleroBackup in the OADP namespace.
// This number is not guaranteed to be accurate, but it should be close. It's inaccurate for cases when
// Velero pod is not running or being restarted after Backup object were created.
// It counts only VeleroBackups that are still subject to be handled by OADP/Velero.
type QueueInfo struct {
EstimatedQueuePosition int `json:"estimatedQueuePosition"` // Number of backups ahead in the queue (0 if not queued)
}

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:path=nonadminbackups,shortName=nab
Expand Down
5 changes: 3 additions & 2 deletions config/crd/bases/oadp.openshift.io_nonadminbackups.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -611,13 +611,14 @@ spec:
type: string
queueInfo:
description: |-
QueueInfo holds the queue position for a specific VeleroBackup.
It is used to estimate how many backups are scheduled before the given VeleroBackup in the OADP namespace.
queueInfo is used to estimate how many backups are scheduled before the given VeleroBackup in the OADP namespace.
This number is not guaranteed to be accurate, but it should be close. It's inaccurate for cases when
Velero pod is not running or being restarted after Backup object were created.
It counts only VeleroBackups that are still subject to be handled by OADP/Velero.
properties:
estimatedQueuePosition:
description: estimatedQueuePosition is the number of operations
ahead in the queue (0 if not queued)
type: integer
required:
- estimatedQueuePosition
Expand Down
23 changes: 11 additions & 12 deletions internal/common/constant/constant.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ const (
NarOriginNameAnnotation = v1alpha1.OadpOperatorLabel + "-nar-origin-name"
NarOriginNamespaceAnnotation = v1alpha1.OadpOperatorLabel + "-nar-origin-namespace"

NabFinalizerName = "nonadminbackup.oadp.openshift.io/finalizer"
NonAdminRestoreFinalizerName = "nonadminrestore.oadp.openshift.io/finalizer"
NabFinalizerName = "nonadminbackup.oadp.openshift.io/finalizer"
NarFinalizerName = "nonadminrestore.oadp.openshift.io/finalizer"
)

// Common environment variables for the Non Admin Controller
Expand All @@ -60,16 +60,15 @@ const TrueString = "True"
// NamespaceString defines a constant for the Namespace string
const NamespaceString = "Namespace"

// NameString defines a constant for the Name string
const NameString = "name"

// CurrentPhaseString defines a constant for the Current Phase string
const CurrentPhaseString = "currentPhase"

// UUIDString defines a constant for the UUID string
const UUIDString = "UUID"

// MaximumNacObjectNameLength represents Generated Non Admin Object Name and
// must be below 63 characters, because it's used within object Label Value
const MaximumNacObjectNameLength = validation.DNS1123LabelMaxLength

// Predefined conditions for NonAdmin object.
// One NonAdmin object may have multiple conditions.
// It is more granular knowledge of the NonAdmin object and represents the
// array of the conditions through which the NonAdmin object has or has not passed
const (
NonAdminConditionAccepted = "Accepted"
NonAdminConditionQueued = "Queued"
NonAdminConditionDeleting = "Deleting"
)
2 changes: 1 addition & 1 deletion internal/common/function/function.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ func GetVeleroRestoreByLabel(ctx context.Context, clientInstance client.Client,
case 1:
return &veleroRestoreList.Items[0], nil
default:
return nil, fmt.Errorf("multiple Velero Restore objects found with label %s=%s in namespace '%s'", constant.NabOriginNACUUIDLabel, labelValue, namespace)
return nil, fmt.Errorf("multiple Velero Restore objects found with label %s=%s in namespace '%s'", constant.NarOriginNACUUIDLabel, labelValue, namespace)
}
}

Expand Down
44 changes: 21 additions & 23 deletions internal/controller/nonadminbackup_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ const (
statusUpdateError = "Failed to update NonAdminBackup Status"
findSingleVBError = "Error encountered while retrieving VeleroBackup for NAB during the Delete operation"
findSingleVDBRError = "Error encountered while retrieving DeleteBackupRequest for NAB during the Delete operation"
uuidString = "UUID"
nameString = "name"
)

// +kubebuilder:rbac:groups=oadp.openshift.io,resources=nonadminbackups,verbs=get;list;watch;create;update;patch;delete
Expand Down Expand Up @@ -165,7 +163,7 @@ func (r *NonAdminBackupReconciler) setStatusAndConditionForDeletionAndCallDelete
updatedPhase := updateNonAdminPhase(&nab.Status.Phase, nacv1alpha1.NonAdminPhaseDeleting)
updatedCondition := meta.SetStatusCondition(&nab.Status.Conditions,
metav1.Condition{
Type: string(constant.NonAdminConditionDeleting),
Type: string(nacv1alpha1.NonAdminConditionDeleting),
Status: metav1.ConditionTrue,
Reason: "DeletionPending",
Message: "backup accepted for deletion",
Expand All @@ -182,7 +180,7 @@ func (r *NonAdminBackupReconciler) setStatusAndConditionForDeletionAndCallDelete
logger.V(1).Info("NonAdminBackup status unchanged during deletion")
}
if nab.ObjectMeta.DeletionTimestamp.IsZero() {
logger.V(1).Info("Marking NonAdminBackup for deletion", nameString, nab.Name)
logger.V(1).Info("Marking NonAdminBackup for deletion", constant.NameString, nab.Name)
if err := r.Delete(ctx, nab); err != nil {
logger.Error(err, "Failed to call Delete on the NonAdminBackup object")
return false, err
Expand Down Expand Up @@ -210,7 +208,7 @@ func (r *NonAdminBackupReconciler) setStatusForDirectKubernetesAPIDeletion(ctx c
updatedPhase := updateNonAdminPhase(&nab.Status.Phase, nacv1alpha1.NonAdminPhaseDeleting)
updatedCondition := meta.SetStatusCondition(&nab.Status.Conditions,
metav1.Condition{
Type: string(constant.NonAdminConditionDeleting),
Type: string(nacv1alpha1.NonAdminConditionDeleting),
Status: metav1.ConditionTrue,
Reason: "DeletionPending",
Message: "backup deletion requires setting spec.deleteBackup or spec.forceDeleteBackup to true or finalizer removal",
Expand Down Expand Up @@ -262,19 +260,19 @@ func (r *NonAdminBackupReconciler) createVeleroDeleteBackupRequest(ctx context.C

if err != nil {
// Log error if multiple VeleroBackup objects are found
logger.Error(err, findSingleVBError, uuidString, veleroBackupNACUUID)
logger.Error(err, findSingleVBError, constant.UUIDString, veleroBackupNACUUID)
return false, err
}

if veleroBackup == nil {
logger.V(1).Info("VeleroBackup already deleted", "UUID", veleroBackupNACUUID)
logger.V(1).Info("VeleroBackup already deleted", constant.UUIDString, veleroBackupNACUUID)
return false, nil
}

deleteBackupRequest, err := function.GetVeleroDeleteBackupRequestByLabel(ctx, r.Client, r.OADPNamespace, veleroBackupNACUUID)
if err != nil {
// Log error if multiple DeleteBackupRequest objects are found
logger.Error(err, findSingleVDBRError, uuidString, veleroBackupNACUUID)
logger.Error(err, findSingleVDBRError, constant.UUIDString, veleroBackupNACUUID)
return false, err
}

Expand Down Expand Up @@ -346,32 +344,32 @@ func (r *NonAdminBackupReconciler) deleteVeleroBackupAndDeleteBackupRequestObjec
if err != nil {
// Case where more than one VeleroBackup is found with the same label UUID
// TODO (migi): Determine if all objects with this UUID should be deleted
logger.Error(err, findSingleVBError, uuidString, veleroBackupNACUUID)
logger.Error(err, findSingleVBError, constant.UUIDString, veleroBackupNACUUID)
return false, err
}

if veleroBackup != nil {
if err = r.Delete(ctx, veleroBackup); err != nil {
logger.Error(err, "Failed to delete VeleroBackup", nameString, veleroBackup.Name)
logger.Error(err, "Failed to delete VeleroBackup", constant.NameString, veleroBackup.Name)
return false, err
}
logger.V(1).Info("VeleroBackup deletion initiated", nameString, veleroBackup.Name)
logger.V(1).Info("VeleroBackup deletion initiated", constant.NameString, veleroBackup.Name)
} else {
logger.V(1).Info("VeleroBackup already deleted")
}

deleteBackupRequest, err := function.GetVeleroDeleteBackupRequestByLabel(ctx, r.Client, r.OADPNamespace, veleroBackupNACUUID)
if err != nil {
// Log error if multiple DeleteBackupRequest objects are found
logger.Error(err, findSingleVDBRError, uuidString, veleroBackupNACUUID)
logger.Error(err, findSingleVDBRError, constant.UUIDString, veleroBackupNACUUID)
return false, err
}
if deleteBackupRequest != nil {
if err = r.Delete(ctx, deleteBackupRequest); err != nil {
logger.Error(err, "Failed to delete VeleroDeleteBackupRequest", nameString, deleteBackupRequest.Name)
logger.Error(err, "Failed to delete VeleroDeleteBackupRequest", constant.NameString, deleteBackupRequest.Name)
return false, err
}
logger.V(1).Info("VeleroDeleteBackupRequest deletion initiated", nameString, deleteBackupRequest.Name)
logger.V(1).Info("VeleroDeleteBackupRequest deletion initiated", constant.NameString, deleteBackupRequest.Name)
}
return false, nil // Continue so initNabDeletion can initialize deletion of an NonAdminBackup object
}
Expand Down Expand Up @@ -408,12 +406,12 @@ func (r *NonAdminBackupReconciler) removeNabFinalizerUponVeleroBackupDeletion(ct
if err != nil {
// Case in which more then one VeleroBackup is found with the same label UUID
// TODO (migi): Should we delete all of the objects with such UUID ?
logger.Error(err, findSingleVBError, uuidString, veleroBackupNACUUID)
logger.Error(err, findSingleVBError, constant.UUIDString, veleroBackupNACUUID)
return false, err
}

if veleroBackup != nil {
logger.V(1).Info("Waiting for VeleroBackup to be deleted", nameString, veleroBackupNACUUID)
logger.V(1).Info("Waiting for VeleroBackup to be deleted", constant.NameString, veleroBackupNACUUID)
return true, nil // Requeue
}
}
Expand Down Expand Up @@ -447,7 +445,7 @@ func (r *NonAdminBackupReconciler) removeNabFinalizerUponVeleroBackupDeletion(ct
func (r *NonAdminBackupReconciler) initNabCreate(ctx context.Context, logger logr.Logger, nab *nacv1alpha1.NonAdminBackup) (bool, error) {
// If phase is already set, nothing to do
if nab.Status.Phase != constant.EmptyString {
logger.V(1).Info("NonAdminBackup Phase already initialized", "currentPhase", nab.Status.Phase)
logger.V(1).Info("NonAdminBackup Phase already initialized", constant.CurrentPhaseString, nab.Status.Phase)
return false, nil
}

Expand All @@ -459,7 +457,7 @@ func (r *NonAdminBackupReconciler) initNabCreate(ctx context.Context, logger log
}
logger.V(1).Info("NonAdminBackup Phase set to New")
} else {
logger.V(1).Info("NonAdminBackup Phase update skipped", "currentPhase", nab.Status.Phase)
logger.V(1).Info("NonAdminBackup Phase update skipped", constant.CurrentPhaseString, nab.Status.Phase)
}

return false, nil
Expand All @@ -483,7 +481,7 @@ func (r *NonAdminBackupReconciler) validateSpec(ctx context.Context, logger logr
updatedPhase := updateNonAdminPhase(&nab.Status.Phase, nacv1alpha1.NonAdminPhaseBackingOff)
updatedCondition := meta.SetStatusCondition(&nab.Status.Conditions,
metav1.Condition{
Type: string(constant.NonAdminConditionAccepted),
Type: string(nacv1alpha1.NonAdminConditionAccepted),
Status: metav1.ConditionFalse,
Reason: "InvalidBackupSpec",
Message: err.Error(),
Expand All @@ -504,7 +502,7 @@ func (r *NonAdminBackupReconciler) validateSpec(ctx context.Context, logger logr

updated := meta.SetStatusCondition(&nab.Status.Conditions,
metav1.Condition{
Type: string(constant.NonAdminConditionAccepted),
Type: string(nacv1alpha1.NonAdminConditionAccepted),
Status: metav1.ConditionTrue,
Reason: "BackupAccepted",
Message: "backup accepted",
Expand Down Expand Up @@ -596,12 +594,12 @@ func (r *NonAdminBackupReconciler) createVeleroBackupAndSyncWithNonAdminBackup(c

if err != nil {
// Case in which more then one VeleroBackup is found with the same label UUID
logger.Error(err, findSingleVBError, uuidString, veleroBackupNACUUID)
logger.Error(err, findSingleVBError, constant.UUIDString, veleroBackupNACUUID)
return false, err
}

if veleroBackup == nil {
logger.Info("VeleroBackup with label not found, creating one", uuidString, veleroBackupNACUUID)
logger.Info("VeleroBackup with label not found, creating one", constant.UUIDString, veleroBackupNACUUID)

backupSpec := nab.Spec.BackupSpec.DeepCopy()
backupSpec.IncludedNamespaces = []string{nab.Namespace}
Expand Down Expand Up @@ -659,7 +657,7 @@ func (r *NonAdminBackupReconciler) createVeleroBackupAndSyncWithNonAdminBackup(c

updatedCondition := meta.SetStatusCondition(&nab.Status.Conditions,
metav1.Condition{
Type: string(constant.NonAdminConditionQueued),
Type: string(nacv1alpha1.NonAdminConditionQueued),
Status: metav1.ConditionTrue,
Reason: "BackupScheduled",
Message: "Created Velero Backup object",
Expand Down
Loading

0 comments on commit 56afada

Please sign in to comment.