Skip to content

Commit dea649c

Browse files
committed
fix webhook validation
1 parent 2923991 commit dea649c

File tree

8 files changed

+47
-52
lines changed

8 files changed

+47
-52
lines changed

api/v1alpha1/lvmcluster_test.go

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -496,38 +496,44 @@ var _ = Describe("webhook acceptance tests", func() {
496496
Expect(k8sClient.Delete(ctx, resource)).To(Succeed())
497497
})
498498

499-
It("device paths cannot be removed from device class in update", func(ctx SpecContext) {
499+
It("device paths can be removed but at least one device must remain", func(ctx SpecContext) {
500500
resource := defaultLVMClusterInUniqueNamespace(ctx)
501-
resource.Spec.Storage.DeviceClasses[0].DeviceSelector = &DeviceSelector{Paths: []DevicePath{"/dev/newpath"}}
501+
resource.Spec.Storage.DeviceClasses[0].DeviceSelector = &DeviceSelector{
502+
Paths: []DevicePath{"/dev/path1", "/dev/path2"},
503+
OptionalPaths: []DevicePath{"/dev/optional1"},
504+
}
502505
Expect(k8sClient.Create(ctx, resource)).To(Succeed())
503506

507+
// Should succeed - removing some devices but keeping at least one
504508
updated := resource.DeepCopy()
505-
updated.Spec.Storage.DeviceClasses[0].DeviceSelector.Paths = []DevicePath{"/dev/otherpath"}
509+
updated.Spec.Storage.DeviceClasses[0].DeviceSelector.Paths = []DevicePath{"/dev/path1"}
510+
updated.Spec.Storage.DeviceClasses[0].DeviceSelector.OptionalPaths = []DevicePath{}
511+
Expect(k8sClient.Update(ctx, updated)).To(Succeed())
506512

507-
err := k8sClient.Update(ctx, updated)
513+
// Should fail - removing all devices
514+
updated2 := resource.DeepCopy()
515+
updated2.Spec.Storage.DeviceClasses[0].DeviceSelector.Paths = []DevicePath{}
516+
updated2.Spec.Storage.DeviceClasses[0].DeviceSelector.OptionalPaths = []DevicePath{}
517+
err := k8sClient.Update(ctx, updated2)
508518
Expect(err).To(HaveOccurred())
509519
Expect(err).To(Satisfy(k8serrors.IsForbidden))
510-
statusError := &k8serrors.StatusError{}
511-
Expect(errors.As(err, &statusError)).To(BeTrue())
512-
Expect(statusError.Status().Message).To(ContainSubstring("required device paths were deleted from the LVMCluster"))
513520

514521
Expect(k8sClient.Delete(ctx, resource)).To(Succeed())
515522
})
516523

517-
It("optional device paths cannot be removed from device class in update", func(ctx SpecContext) {
524+
It("cannot add devices if none were initially specified", func(ctx SpecContext) {
518525
resource := defaultLVMClusterInUniqueNamespace(ctx)
519-
resource.Spec.Storage.DeviceClasses[0].DeviceSelector = &DeviceSelector{OptionalPaths: []DevicePath{"/dev/newpath"}}
526+
resource.Spec.Storage.DeviceClasses[0].DeviceSelector = nil
520527
Expect(k8sClient.Create(ctx, resource)).To(Succeed())
521528

529+
// Should fail - trying to add devices when none were initially specified
522530
updated := resource.DeepCopy()
523-
updated.Spec.Storage.DeviceClasses[0].DeviceSelector.OptionalPaths = []DevicePath{"/dev/otherpath"}
524-
531+
updated.Spec.Storage.DeviceClasses[0].DeviceSelector = &DeviceSelector{
532+
Paths: []DevicePath{"/dev/newpath"},
533+
}
525534
err := k8sClient.Update(ctx, updated)
526535
Expect(err).To(HaveOccurred())
527536
Expect(err).To(Satisfy(k8serrors.IsForbidden))
528-
statusError := &k8serrors.StatusError{}
529-
Expect(errors.As(err, &statusError)).To(BeTrue())
530-
Expect(statusError.Status().Message).To(ContainSubstring("optional device paths were deleted from the LVMCluster"))
531537

532538
Expect(k8sClient.Delete(ctx, resource)).To(Succeed())
533539
})

api/v1alpha1/lvmcluster_webhook.go

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -250,17 +250,12 @@ func (v *lvmClusterValidator) ValidateUpdate(_ context.Context, old, new runtime
250250
return warnings, ErrForceWipeOptionCannotBeChanged
251251
}
252252

253-
// Make sure a device path list was not added
254-
if len(oldDevices) == 0 && len(newDevices) > 0 {
255-
return warnings, ErrDevicePathsCannotBeAddedInUpdate
256-
}
257-
258-
// Make sure an optionalPaths list was not added
259-
if len(oldOptionalDevices) == 0 && len(newOptionalDevices) > 0 {
260-
return warnings, ErrDevicePathsCannotBeAddedInUpdate
261-
}
262-
263-
if len(newOptionalDevices)+len(newDevices) == 0 {
253+
// If originally no devices were specified, prevent adding any devices
254+
if len(oldDevices) == 0 && len(oldOptionalDevices) == 0 {
255+
if len(newDevices) > 0 || len(newOptionalDevices) > 0 {
256+
return warnings, ErrDevicePathsCannotBeAddedInUpdate
257+
}
258+
} else if len(newDevices)+len(newOptionalDevices) == 0 {
264259
return warnings, ErrDevicesCantBeEmpty
265260
}
266261

@@ -288,25 +283,6 @@ func validateDeviceClassesStillExist(old, new []DeviceClass) error {
288283
return nil
289284
}
290285

291-
func validateDevicePathsStillExist(old, new []DevicePath) error {
292-
deviceMap := make(map[DevicePath]struct{})
293-
294-
for _, device := range old {
295-
deviceMap[device] = struct{}{}
296-
}
297-
298-
for _, device := range new {
299-
delete(deviceMap, device)
300-
}
301-
302-
// if any old device is removed now
303-
if len(deviceMap) != 0 {
304-
return fmt.Errorf("devices can not be removed from the LVMCluster once added oldDevices:%s, newDevices:%s", old, new)
305-
}
306-
307-
return nil
308-
}
309-
310286
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
311287
func (v *lvmClusterValidator) ValidateDelete(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
312288
l := obj.(*LVMCluster)

bundle/manifests/lvms-operator.clusterserviceversion.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,17 @@ spec:
615615
- create
616616
- patch
617617
- update
618+
- apiGroups:
619+
- ""
620+
resources:
621+
- configmaps
622+
verbs:
623+
- create
624+
- get
625+
- list
626+
- patch
627+
- update
628+
- watch
618629
serviceAccountName: vg-manager
619630
strategy: deployment
620631
installModes:

catalog/lvms-operator/v0.0.1.yaml

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

config/manager/kustomization.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ generatorOptions:
1111

1212
images:
1313
- name: controller
14-
newName: quay.io/bzamalut/lvms
14+
newName: quay.io/lvms_dev/lvms-operator
1515
newTag: latest

internal/controllers/vgmanager/controller.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,10 @@ func (r *Reconciler) reconcile(
170170
removedDevices, err := r.deleteRemovedDevices(ctx, volumeGroup, vgs, resolver)
171171
if err != nil {
172172
r.WarningEvent(ctx, volumeGroup, EventReasonErrorDeviceRemovalFailed, err)
173-
r.setVolumeGroupFailedStatus(ctx, volumeGroup, vgs, FilteredBlockDevices{}, err)
173+
_, errStatus := r.setVolumeGroupFailedStatus(ctx, volumeGroup, vgs, FilteredBlockDevices{}, err)
174+
if errStatus != nil {
175+
logger.Error(err, "failed to set status to failed")
176+
}
174177
return ctrl.Result{RequeueAfter: 5 * time.Second}, fmt.Errorf("failed to check if device was removed: %w", err)
175178
}
176179

internal/controllers/vgmanager/device_removal_transaction.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,9 @@ type DeviceRemovalTransaction struct {
3838
}
3939

4040
type deviceOperation struct {
41-
devicePath string
42-
originalPath string // The user-provided path (symlink) corresponding to devicePath
43-
phase operationPhase
44-
rollback func(ctx context.Context) error
41+
devicePath string
42+
phase operationPhase
43+
rollback func(ctx context.Context) error
4544
}
4645

4746
type operationPhase int

internal/controllers/vgmanager/device_removal_validation.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,4 @@ func (r *Reconciler) validateDeviceRemoval(ctx context.Context, devicePath, vgNa
5050

5151
logger.V(1).Info("device validated for safe removal")
5252
return nil
53-
}
53+
}

0 commit comments

Comments
 (0)