Skip to content

Commit

Permalink
Remove PV of OVA provider server
Browse files Browse the repository at this point in the history
The way the PV for a pod that serves as an NFS server for an OVA
provider is created doesn't allow its deletion by a CSI driver and
therefore we need to take care of its cleanup when the OVA provider is
deleted.

Here, we add a finalizer to OVA providers to prevent their deletion
until we delete their PV.

Signed-off-by: Arik Hadas <[email protected]>
  • Loading branch information
ahadas committed Feb 13, 2024
1 parent c8257c8 commit 59ed0ef
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 7 deletions.
2 changes: 2 additions & 0 deletions pkg/apis/forklift/v1beta1/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ const (
ESXI = "esxi"
)

const OvaProviderFinalizer = "forklift/ova-provider"

// Defines the desired state of Provider.
type ProviderSpec struct {
// Provider type.
Expand Down
2 changes: 2 additions & 0 deletions pkg/controller/provider/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,12 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/api/errors",
"//vendor/k8s.io/apimachinery/pkg/api/resource",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:meta",
"//vendor/k8s.io/apimachinery/pkg/labels",
"//vendor/k8s.io/apimachinery/pkg/util/intstr",
"//vendor/k8s.io/apiserver/pkg/storage/names",
"//vendor/sigs.k8s.io/controller-runtime/pkg/client",
"//vendor/sigs.k8s.io/controller-runtime/pkg/controller",
"//vendor/sigs.k8s.io/controller-runtime/pkg/controller/controllerutil",
"//vendor/sigs.k8s.io/controller-runtime/pkg/event",
"//vendor/sigs.k8s.io/controller-runtime/pkg/handler",
"//vendor/sigs.k8s.io/controller-runtime/pkg/manager",
Expand Down
26 changes: 26 additions & 0 deletions pkg/controller/provider/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@ import (
appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
k8serr "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apiserver/pkg/storage/names"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
k8sutil "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
Expand Down Expand Up @@ -234,6 +236,30 @@ func (r Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (r
}
}

if provider.DeletionTimestamp != nil && k8sutil.ContainsFinalizer(provider, api.OvaProviderFinalizer) {
labelSelector := labels.SelectorFromSet(labels.Set{
"subapp": "ova-server",
"app": "forklift",
"provider": provider.Name,
})
pvList := &v1.PersistentVolumeList{}
if err = r.Client.List(context.TODO(), pvList, &client.ListOptions{LabelSelector: labelSelector}); err != nil {
r.Log.Error(err, "Failed to list PVs for OVA provider", "provider", provider)
} else {
for _, pv := range pvList.Items {
if err = r.Client.Delete(context.TODO(), &pv); err != nil {
r.Log.Error(err, "Failed to delete PV", "PV", pv)
return
}
}
clonedProvider := provider.DeepCopy()
k8sutil.RemoveFinalizer(provider, api.OvaProviderFinalizer)
if err := r.Patch(context.TODO(), provider, client.MergeFrom(clonedProvider)); err != nil {
r.Log.Error(err, "Failed to remove finalizer", "provider", provider)
}
}
}

// Begin staging conditions.
provider.Status.Phase = Staging
provider.Status.BeginStagingConditions()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/api/errors",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:meta",
"//vendor/sigs.k8s.io/controller-runtime/pkg/client",
"//vendor/sigs.k8s.io/controller-runtime/pkg/controller/controllerutil",
],
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/konveyor/forklift-controller/pkg/forklift-api/webhooks/util"
admissionv1 "k8s.io/api/admission/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
k8sutil "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)

type ProviderMutator struct {
Expand All @@ -25,9 +26,25 @@ func (mutator *ProviderMutator) Mutate(ar *admissionv1.AdmissionReview) *admissi
}

specChanged := mutator.setSdkEndpointIfNeeded()
metadataChanged := mutator.ar.Request.Operation == admissionv1.Create && mutator.setFinalizers()

var patches []util.PatchOperation
if specChanged {
patches := mutator.patchPayload()
patches = append(patches, util.PatchOperation{
Op: "replace",
Path: "/spec",
Value: mutator.provider.Spec,
})
}
if metadataChanged {
patches = append(patches, util.PatchOperation{
Op: "replace",
Path: "/metadata",
Value: mutator.provider.ObjectMeta,
})
}

if len(patches) > 0 {
patchBytes, err := util.GeneratePatchPayload(patches...)
if err != nil {
log.Error(err, "mutating webhook error, failed to generate payload for patch request")
Expand Down Expand Up @@ -62,10 +79,10 @@ func (mutator *ProviderMutator) setSdkEndpointIfNeeded() bool {
return providerChanged
}

func (mutator *ProviderMutator) patchPayload() []util.PatchOperation {
return []util.PatchOperation{{
Op: "replace",
Path: "/spec",
Value: mutator.provider.Spec,
}}
func (mutator *ProviderMutator) setFinalizers() bool {
var changed bool
if mutator.provider.Type() == api.Ova {
changed = k8sutil.AddFinalizer(&(mutator.provider), api.OvaProviderFinalizer)
}
return changed
}

0 comments on commit 59ed0ef

Please sign in to comment.