Skip to content

Commit

Permalink
webhook: add StorageClass validator
Browse files Browse the repository at this point in the history
    - To ensure the VG status is active

Signed-off-by: Vicente Cheng <vicente.cheng@suse.com>
  • Loading branch information
Vicente-Cheng committed Oct 24, 2024
1 parent c494fe0 commit 14dd63c
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 2 deletions.
5 changes: 5 additions & 0 deletions cmd/node-disk-manager-webhook/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ import (
ctldisk "github.com/harvester/node-disk-manager/pkg/generated/controllers/harvesterhci.io"
ctldiskv1 "github.com/harvester/node-disk-manager/pkg/generated/controllers/harvesterhci.io/v1beta1"
"github.com/harvester/node-disk-manager/pkg/webhook/blockdevice"
"github.com/harvester/node-disk-manager/pkg/webhook/storageclass"
)

const webhookName = "harvester-node-disk-manager-webhook"

type resourceCaches struct {
bdCache ctldiskv1.BlockDeviceCache
lvmVGCache ctldiskv1.LVMVolumeGroupCache
storageClassCache ctlstoragev1.StorageClassCache
pvCache ctlcorev1.PersistentVolumeCache
}
Expand Down Expand Up @@ -116,8 +118,10 @@ func runWebhookServer(ctx context.Context, cfg *rest.Config, options *config.Opt
}

bdValidator := blockdevice.NewBlockdeviceValidator(resourceCaches.bdCache, resourceCaches.storageClassCache, resourceCaches.pvCache)
scValidator := storageclass.NewStorageClassValidator(resourceCaches.lvmVGCache)
var validators = []admission.Validator{
bdValidator,
scValidator,
}

if err := webhookServer.RegisterMutators(mutators...); err != nil {
Expand Down Expand Up @@ -155,6 +159,7 @@ func newCaches(ctx context.Context, cfg *rest.Config, threadiness int) (*resourc
starters = append(starters, disks, storageFactory, coreFactory)
resourceCaches := &resourceCaches{
bdCache: disks.Harvesterhci().V1beta1().BlockDevice().Cache(),
lvmVGCache: disks.Harvesterhci().V1beta1().LVMVolumeGroup().Cache(),
storageClassCache: storageFactory.Storage().V1().StorageClass().Cache(),
pvCache: coreFactory.Core().V1().PersistentVolume().Cache(),
}
Expand Down
4 changes: 2 additions & 2 deletions deploy/charts/harvester-node-disk-manager/templates/rbac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ rules:
verbs: [ "get", "watch", "list" ]
- apiGroups: [ "storage.k8s.io" ]
resources: [ "storageclasses" ]
verbs: [ "get", "watch", "list" ]
verbs: [ "*" ]
- apiGroups: [ "harvesterhci.io" ]
resources: [ "blockdevices" ]
resources: [ "blockdevices", "lvmvolumegroups", "lvmvolumegroups/status" ]
verbs: [ "*" ]
- apiGroups: [ "apiregistration.k8s.io" ]
resources: [ "apiservices" ]
Expand Down
68 changes: 68 additions & 0 deletions pkg/webhook/storageclass/validator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package storageclass

import (
"fmt"

werror "github.com/harvester/webhook/pkg/error"
"github.com/harvester/webhook/pkg/server/admission"
admissionregv1 "k8s.io/api/admissionregistration/v1"
storagev1 "k8s.io/api/storage/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"

diskv1 "github.com/harvester/node-disk-manager/pkg/apis/harvesterhci.io/v1beta1"
ctldiskv1 "github.com/harvester/node-disk-manager/pkg/generated/controllers/harvesterhci.io/v1beta1"
"github.com/harvester/node-disk-manager/pkg/utils"
)

type Validator struct {
admission.DefaultValidator

lvmVGCache ctldiskv1.LVMVolumeGroupCache
}

func NewStorageClassValidator(lvmVGCache ctldiskv1.LVMVolumeGroupCache) *Validator {
return &Validator{
lvmVGCache: lvmVGCache,
}
}

func (v *Validator) Create(_ *admission.Request, newObj runtime.Object) error {
sc := newObj.(*storagev1.StorageClass)
return v.validateVGStatus(sc)
}

func (v *Validator) validateVGStatus(sc *storagev1.StorageClass) error {
if sc.Provisioner != utils.LVMCSIDriver {
return nil
}
vgs, err := v.lvmVGCache.List(utils.HarvesterNS, labels.Everything())
if err != nil {
return err
}
targetVGName := sc.Parameters["vgName"]

for _, vg := range vgs {
if vg.Spec.VgName != targetVGName {
continue
}
if vg.Status == nil || vg.Status.Status != diskv1.VGStatusActive {
errMsg := fmt.Sprintf("VG %s is not ready", vg.Spec.VgName)
return werror.NewBadRequest(errMsg)
}
}
return nil
}

func (v *Validator) Resource() admission.Resource {
return admission.Resource{
Names: []string{"storageclasses"},
Scope: admissionregv1.ClusterScope,
APIGroup: storagev1.SchemeGroupVersion.Group,
APIVersion: storagev1.SchemeGroupVersion.Version,
ObjectType: &storagev1.StorageClass{},
OperationTypes: []admissionregv1.OperationType{
admissionregv1.Create,
},
}
}

0 comments on commit 14dd63c

Please sign in to comment.