-
Notifications
You must be signed in to change notification settings - Fork 4
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
Conversation
There was a problem hiding this 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:
- Make sure every function has a comment above it with proper English.
- Make sure variables and constants that should not be unexported are not exported.
- 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.
- 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. - The
RetryOnConflict
update is repeated a lot, perhaps in case be generalized and reused in a function. - 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. |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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.
internal/controller/status/status.go
Outdated
return nil | ||
} | ||
|
||
// UpdatePvcStatus Update the status of the pvc. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updates*
internal/controller/status/status.go
Outdated
} | ||
return updateErr | ||
}) | ||
//Should be nil |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
internal/controller/status/status.go
Outdated
} | ||
|
||
// getPvcStatus return the Pvc's Phase. | ||
// getPvcStatus return the phase of the pvc |
There was a problem hiding this comment.
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 :)
There was a problem hiding this comment.
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.
} 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. |
There was a problem hiding this comment.
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
if getErr := k8sClient.Get(ctx, types.NamespacedName{Name: nfspvc.Name + "-" + nfspvc.Namespace + "-pv"}, &pv); getErr != nil { | ||
return getErr | ||
} |
There was a problem hiding this comment.
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
internal/controller/sync/sync.go
Outdated
@@ -4,30 +4,26 @@ import ( | |||
"context" | |||
"fmt" | |||
|
|||
statusutils "github.com/dana-team/nfspvc-operator/internal/controller/status" |
There was a problem hiding this comment.
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?
internal/controller/sync/sync.go
Outdated
@@ -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" |
There was a problem hiding this comment.
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?
internal/controller/sync/sync.go
Outdated
// 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" { |
There was a problem hiding this comment.
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
a9340fd
to
66b41f4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some more comments
api/v1alpha1/nfspvc_webhook.go
Outdated
PVCAlreadyExists = "a PVC of this name already exists in the namespace. Please rename your NFSPVC" | ||
InvalidAccessModeError = "forbidden: only the following AccessModes are permitted" |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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.
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())) |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing comment
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing comment
There was a problem hiding this comment.
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
// UpdatePV updates a PV if the nfspvc is updated. | ||
func UpdatePV(ctx context.Context, nfspvc danaiov1alpha1.NfsPvc, k8sClient client.Client, pv corev1.PersistentVolume) error { |
There was a problem hiding this comment.
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.
internal/controller/sync/sync.go
Outdated
return err | ||
} | ||
return nil | ||
if pvc.Status.Phase == corev1.ClaimLost { // if the pvc's phase is 'lost', so probably the associated pv was deleted |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
omers fault
internal/controller/sync/sync.go
Outdated
// DeletePVCBindAnnotation deletes the "bind" annotation from a pvc. | ||
func DeletePVCBindAnnotation(ctx context.Context, nfspvc danaiov1alpha1.NfsPvc, k8sClient client.Client, pvc corev1.PersistentVolumeClaim) error { |
There was a problem hiding this comment.
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?
3b1215c
to
733d930
Compare
There was a problem hiding this 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" |
There was a problem hiding this comment.
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
"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" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the unneeded spaces
if nfspvc.ObjectMeta.DeletionTimestamp != nil { | ||
if controllerutil.ContainsFinalizer(&nfspvc, utils.NfsPvcDeletionFinalizer) { |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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
internal/controller/sync/sync.go
Outdated
"github.com/dana-team/nfspvc-operator/internal/controller/storage" | ||
"github.com/dana-team/nfspvc-operator/internal/controller/utils" |
There was a problem hiding this comment.
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
internal/controller/sync/sync.go
Outdated
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove comment
internal/controller/sync/sync.go
Outdated
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove comment
StorageClassEnv = "STORAGE_CLASS" | ||
ReclaimPolicyEnv = "RECLAIM_POLICY" |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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.
a24d8eb
to
fc2d1b4
Compare
There was a problem hiding this 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) |
There was a problem hiding this comment.
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()) |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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()) |
There was a problem hiding this comment.
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
19a9f27
to
ff9893f
Compare
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/lgtm
/approve
[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 |
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.