Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactored NFSPVC Logic #56

Merged
merged 1 commit into from
May 23, 2024
Merged

refactored NFSPVC Logic #56

merged 1 commit into from
May 23, 2024

Conversation

dvirgilad
Copy link
Contributor

With this pr, several files where separated and refactored in order to improve readability and general code quality.
Also removed usage of deprecated kustomize functionality.

Copy link
Contributor

@mzeevi mzeevi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks better but there are still stuff to do. Some generate notes:

  1. Make sure every function has a comment above it with proper English.
  2. Make sure variables and constants that should not be unexported are not exported.
  3. If a constant is only used in a single package and a single file then it should be a part of this package and not part of different package.
  4. Return errors where needed with fmt.Errorf and add context to the errors where it's suitable. Only add context when it makes things clearer to the reader of the logs.
  5. The RetryOnConflict update is repeated a lot, perhaps in case be generalized and reused in a function.
  6. Go over the functions and think whether you can minimize the scopes, especially in if-else parts.

"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)

// RemoveFinalizer remove the dana finalizer from the nfspvc object.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removes*

return nil
}

// EnsureFinalizer ensures the nfspvc has the finalizer.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// EnsureFinalizer adds a finalizer to the NFSPVC object if such does not exist.

return nil
}

// UpdatePvcStatus Update the status of the pvc.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updates*

}
return updateErr
})
//Should be nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean? I think it can be non-nil if there is an issue with the update, or the default retries number has been reached

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant for this comment to be explanatory. If everything went ok, err = nil but since we return err, the reader might get confused. I will replace this with more indicative logic

}

// getPvcStatus return the Pvc's Phase.
// getPvcStatus return the phase of the pvc
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

returns* Fix the present simple everywhere :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also make sure there's a . at the end of each comment.

Comment on lines 65 to 66
} else if !pvDeleted && pvcDeleted { // if only the pvc was deleted successfully, the reconcile function will be triggered again for the pv cleanup.
// if the pv still exists, delete it.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment should not be inline

Comment on lines 183 to 94
if getErr := k8sClient.Get(ctx, types.NamespacedName{Name: nfspvc.Name + "-" + nfspvc.Namespace + "-pv"}, &pv); getErr != nil {
return getErr
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move the naming concatenation to a variable outside this scope so it doesn't need to be recomputed on every retry

@@ -4,30 +4,26 @@ import (
"context"
"fmt"

statusutils "github.com/dana-team/nfspvc-operator/internal/controller/status"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just status with no renaming?

@@ -4,30 +4,26 @@ import (
"context"
"fmt"

statusutils "github.com/dana-team/nfspvc-operator/internal/controller/status"

storageutils "github.com/dana-team/nfspvc-operator/internal/controller/storage"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just storage with no renaming?

// DeletePvcBindAnnotation Deletes the "bind" annotation from a pvc
func DeletePvcBindAnnotation(ctx context.Context, nfspvc danaiov1alpha1.NfsPvc, k8sClient client.Client, pvc corev1.PersistentVolumeClaim) error {
bindStatus, ok := pvc.ObjectMeta.Annotations[utils.PvcBindStatusAnnotation]
if ok && bindStatus == "yes" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change the "yes" to a constant

@dvirgilad dvirgilad force-pushed the dvir-refactor branch 2 times, most recently from a9340fd to 66b41f4 Compare May 21, 2024 14:46
Copy link
Contributor

@mzeevi mzeevi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some more comments

Comment on lines 37 to 38
PVCAlreadyExists = "a PVC of this name already exists in the namespace. Please rename your NFSPVC"
InvalidAccessModeError = "forbidden: only the following AccessModes are permitted"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those don't need to be exported

func RemoveFinalizer(ctx context.Context, nfspvc danaiov1alpha1.NfsPvc, log logr.Logger, k8sClient client.Client) error {
controllerutil.RemoveFinalizer(&nfspvc, utils.NfsPvcDeletionFinalizer)
if err := k8sClient.Update(ctx, &nfspvc); err != nil {
log.Error(err, "unable to remove the finalizer from the NfsPvc - "+nfspvc.Name)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The log message here is kind of redundant since I'd get the same information on the caller when it fails

if !controllerutil.ContainsFinalizer(&nfspvc, utils.NfsPvcDeletionFinalizer) {
controllerutil.AddFinalizer(&nfspvc, utils.NfsPvcDeletionFinalizer)
if err := k8sClient.Update(ctx, &nfspvc); err != nil {
log.Error(err, "unable to add the finalizer to the nfspvc - "+nfspvc.Name)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing here

"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)

// RemoveFinalizer removes the dana finalizer from the nfspvc object.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// RemoveFinalizer removes a finalizer from the nfspvc object.

Comment on lines 85 to 87
if resources.IsFailedCleanUp(err) {
// this means the error is of type *FailedCleanUpError.
logger.Info(fmt.Sprintf("failed to handle NfsPvc deletion: %s, so trying again in a few seconds", err.Error()))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason we are not using errors.Is() instead of creating a new error struct of type FailedCleanUpError? Can't we just use errors.New or fmt.Errorf() to create a new error and check for it here? Mind you we'd have to unwrap the error, so return %w when needed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand this one, skipping for now.

nfsPvcDanaLabel = "nfspvc.dana.io/nfspvc-owner"
)

func PreparePVC(nfspvc danaiov1alpha1.NfsPvc, StorageClass string) corev1.PersistentVolumeClaim {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing comment

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't actually create a new PVC, it just returns a PersistentVolumeClaim object as per given parameters

}
}

func PreparePV(nfspvc danaiov1alpha1.NfsPvc, StorageClass string, ReclaimPolicy string) corev1.PersistentVolume {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing comment

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't actually create a new PV, it just returns a PersistentVolume object as per given parameters

Comment on lines 71 to 75
// UpdatePV updates a PV if the nfspvc is updated.
func UpdatePV(ctx context.Context, nfspvc danaiov1alpha1.NfsPvc, k8sClient client.Client, pv corev1.PersistentVolume) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function makes no conditional on whether the nfspvc is updated or not. This logic is on the caller side.

return err
}
return nil
if pvc.Status.Phase == corev1.ClaimLost { // if the pvc's phase is 'lost', so probably the associated pv was deleted
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use comments like this, always in a new line

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

omers fault

Comment on lines 84 to 85
// DeletePVCBindAnnotation deletes the "bind" annotation from a pvc.
func DeletePVCBindAnnotation(ctx context.Context, nfspvc danaiov1alpha1.NfsPvc, k8sClient client.Client, pvc corev1.PersistentVolumeClaim) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be exported?

@dvirgilad dvirgilad force-pushed the dvir-refactor branch 2 times, most recently from 3b1215c to 733d930 Compare May 22, 2024 14:07
Copy link
Contributor

@mzeevi mzeevi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few more minor things

@@ -18,13 +18,18 @@ package controller

import (
"context"
goerrors "errors"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather you keep this package using the same name and rename the apimachinery errors package as apierrors

Comment on lines 25 to 30
"github.com/dana-team/nfspvc-operator/internal/controller/status"

"github.com/dana-team/nfspvc-operator/internal/controller/resources"

"github.com/dana-team/nfspvc-operator/internal/controller/sync"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the unneeded spaces

Comment on lines 23 to 24
if nfspvc.ObjectMeta.DeletionTimestamp != nil {
if controllerutil.ContainsFinalizer(&nfspvc, utils.NfsPvcDeletionFinalizer) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic should sit on the caller in the Reconciler imo

var FailedCleanupError = goerrors.New("failed nfspvc cleanup")

// HandleDelete ensures the deletion of the nfspvc.
func HandleDelete(ctx context.Context, nfspvc danaiov1alpha1.NfsPvc, k8sClient client.Client) (error, bool) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

error should always be the last returned parameter

return err, false
}
if pvDeleted && pvcDeleted {
return finalizer.Remove(ctx, nfspvc, k8sClient), true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling the finalizer.Remove should be done from the Reconciler code and not from here, I think it'd be clearer

@@ -0,0 +1,99 @@
package storage
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This entire file can move to the resources package I think, no need for its own package

Comment on lines 7 to 8
"github.com/dana-team/nfspvc-operator/internal/controller/storage"
"github.com/dana-team/nfspvc-operator/internal/controller/utils"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file can move to the resources package

func deletePVCBindAnnotation(ctx context.Context, nfspvc danaiov1alpha1.NfsPvc, k8sClient client.Client, pvc corev1.PersistentVolumeClaim) error {
bindStatus, ok := pvc.ObjectMeta.Annotations[pvcBindStatusAnnotation]
if ok && bindStatus == desiredBindStatus {
// Use retry on conflict to update the PVC.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove comment

delete(pvc.ObjectMeta.Annotations, pvcBindStatusAnnotation)
updateErr := k8sClient.Update(ctx, &pvc)
if errors.IsConflict(updateErr) {
// Conflict occurred, let's re-fetch the latest version of PVC and retry the update.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove comment

Comment on lines +12 to +13
StorageClassEnv = "STORAGE_CLASS"
ReclaimPolicyEnv = "RECLAIM_POLICY"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These can be moved to the resources package. We should only have things in common if they are used across packages (or they don't fit anywhere else)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variables are verified in main so I will keep this here.

@dvirgilad dvirgilad force-pushed the dvir-refactor branch 2 times, most recently from a24d8eb to fc2d1b4 Compare May 23, 2024 06:53
Copy link
Contributor

@mzeevi mzeevi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks a lot better, very little remaining

return false, err
}
pvName := nfspvc.Name + "-" + nfspvc.Namespace + "-pv"
return false, fmt.Errorf("the pv %s is not deleted yet, %w", pvName, FailedCleanupError)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For names, use %q instead of %s since it makes it easier to read. Also use : instead of ,:

fmt.Errorf("pv %q has not been deleted yet: %w", pvName, FailedCleanupError)

}
if !pvcDeleted {
if err := deleteResource(ctx, pvc, k8sClient); err != nil {
return fmt.Errorf("failed to delete pvc - %s: %s", nfsPvcName, err.Error())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return fmt.Errorf("failed to delete pvc %q: %v", nfsPvcName, err)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use %w when you need to unwrap the error, and %v when you don't

}
if !pvDeleted {
if err := deleteResource(ctx, pv, k8sClient); err != nil {
return fmt.Errorf("failed to delete pv - %s: %s", pvName, err.Error())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, fix the error messages everywhere

@dvirgilad dvirgilad force-pushed the dvir-refactor branch 2 times, most recently from 19a9f27 to ff9893f Compare May 23, 2024 10:45
With this pr, several files where seperated and refactored in order to improve readability and general code quality
Also removed usage of deprecated kustomize functionality
Copy link
Contributor

@mzeevi mzeevi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm
/approve

Copy link
Contributor

dana-prow-ci bot commented May 23, 2024

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: dvirgilad, mzeevi

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@dana-prow-ci dana-prow-ci bot merged commit 031b784 into main May 23, 2024
3 of 4 checks passed
@dana-prow-ci dana-prow-ci bot deleted the dvir-refactor branch May 23, 2024 10:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants