Skip to content

Commit

Permalink
Deduplicate code in volume mutator
Browse files Browse the repository at this point in the history
  • Loading branch information
ejweber committed Jul 13, 2023
1 parent 19969c6 commit e669b80
Showing 1 changed file with 54 additions and 95 deletions.
149 changes: 54 additions & 95 deletions webhook/resources/volume/mutator.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,28 +48,11 @@ func (v *volumeMutator) Create(request *admission.Request, newObj runtime.Object
volume := newObj.(*longhorn.Volume)
var patchOps admission.PatchOps

var err error
if patchOps, err = mutate(newObj); err != nil {
return nil, err
}

name := util.AutoCorrectName(volume.Name, datastore.NameMaximumLength)
if name != volume.Name {
patchOps = append(patchOps, fmt.Sprintf(`{"op": "replace", "path": "/metadata/name", "value": "%s"}`, name))
}

if volume.Spec.ReplicaAutoBalance == "" {
patchOps = append(patchOps, `{"op": "replace", "path": "/spec/replicaAutoBalance", "value": "ignored"}`)
}

if volume.Spec.DiskSelector == nil {
patchOps = append(patchOps, `{"op": "replace", "path": "/spec/diskSelector", "value": []}`)
}

if volume.Spec.NodeSelector == nil {
patchOps = append(patchOps, `{"op": "replace", "path": "/spec/nodeSelector", "value": []}`)
}

if volume.Spec.NumberOfReplicas == 0 {
numberOfReplicas, err := v.getDefaultReplicaCount()
if err != nil {
Expand All @@ -87,28 +70,6 @@ func (v *volumeMutator) Create(request *admission.Request, newObj runtime.Object
return nil, werror.NewInvalidError(err.Error(), "")
}
patchOps = append(patchOps, fmt.Sprintf(`{"op": "replace", "path": "/spec/dataLocality", "value": "%s"}`, defaultDataLocality))
} else if volume.Spec.DataLocality == longhorn.DataLocalityStrictLocal {
patchOps = append(patchOps, `{"op": "replace", "path": "/spec/revisionCounterDisabled", "value": true}`)
}

if string(volume.Spec.SnapshotDataIntegrity) == "" {
patchOps = append(patchOps, fmt.Sprintf(`{"op": "replace", "path": "/spec/snapshotDataIntegrity", "value": "%s"}`, longhorn.SnapshotDataIntegrityIgnored))
}

if string(volume.Spec.RestoreVolumeRecurringJob) == "" {
patchOps = append(patchOps, fmt.Sprintf(`{"op": "replace", "path": "/spec/restoreVolumeRecurringJob", "value": "%s"}`, longhorn.RestoreVolumeRecurringJobDefault))
}

if volume.Spec.UnmapMarkSnapChainRemoved == "" {
patchOps = append(patchOps, fmt.Sprintf(`{"op": "replace", "path": "/spec/unmapMarkSnapChainRemoved", "value": "%s"}`, longhorn.UnmapMarkSnapChainRemovedIgnored))
}

if string(volume.Spec.ReplicaSoftAntiAffinity) == "" {
patchOps = append(patchOps, fmt.Sprintf(`{"op": "replace", "path": "/spec/replicaSoftAntiAffinity", "value": "%s"}`, longhorn.ReplicaSoftAntiAffinityDefault))
}

if string(volume.Spec.ReplicaZoneSoftAntiAffinity) == "" {
patchOps = append(patchOps, fmt.Sprintf(`{"op": "replace", "path": "/spec/replicaZoneSoftAntiAffinity", "value": "%s"}`, longhorn.ReplicaZoneSoftAntiAffinityDefault))
}

if string(volume.Spec.AccessMode) == "" {
Expand All @@ -131,11 +92,7 @@ func (v *volumeMutator) Create(request *admission.Request, newObj runtime.Object
patchOps = append(patchOps, fmt.Sprintf(`{"op": "replace", "path": "/spec/accessMode", "value": "%s"}`, string(accessModeFromBackup)))
}

labels := volume.Labels
if labels == nil {
labels = map[string]string{}
}

moreLabels := map[string]string{}
size := volume.Spec.Size
if volume.Spec.FromBackup != "" {
bName, bvName, _, err := backupstore.DecodeBackupURL(volume.Spec.FromBackup)
Expand Down Expand Up @@ -188,21 +145,9 @@ func (v *volumeMutator) Create(request *admission.Request, newObj runtime.Object
return nil, werror.NewInvalidError(fmt.Sprintf("get invalid size for volume %v: %v", backup.Status.VolumeSize, err), "")
}

labels[types.LonghornLabelBackupVolume] = bvName
}

labelsForVolumesFollowsGlobalSettings := datastore.GetLabelsForVolumesFollowsGlobalSettings(volume)
for k, v := range labelsForVolumesFollowsGlobalSettings {
labels[k] = v
moreLabels[types.LonghornLabelBackupVolume] = bvName
}

patchOp, err := common.GetLonghornLabelsPatchOp(volume, labels, types.SettingsRelatedToVolume)
if err != nil {
err := errors.Wrapf(err, "failed to get label patch for volume %v", volume.Name)
return nil, werror.NewInvalidError(err.Error(), "")
}
patchOps = append(patchOps, patchOp)

newSize := util.RoundUpSize(size)
if newSize != size {
logrus.Infof("Rounding up the volume spec size from %d to %d in the create mutator", size, newSize)
Expand All @@ -223,10 +168,6 @@ func (v *volumeMutator) Create(request *admission.Request, newObj runtime.Object
patchOps = append(patchOps, fmt.Sprintf(`{"op": "replace", "path": "/spec/backupCompressionMethod", "value": "%s"}`, defaultCompressionMethod))
}

if string(volume.Spec.BackendStoreDriver) == "" {
patchOps = append(patchOps, fmt.Sprintf(`{"op": "replace", "path": "/spec/backendStoreDriver", "value": "%s"}`, longhorn.BackendStoreDriverTypeV1))
}

// TODO: Remove the mutations below after they are implemented for SPDK volumes
if volume.Spec.BackendStoreDriver == longhorn.BackendStoreDriverTypeV2 {
if volume.Spec.Encrypted {
Expand Down Expand Up @@ -257,44 +198,79 @@ func (v *volumeMutator) Create(request *admission.Request, newObj runtime.Object
if string(volume.Spec.OfflineReplicaRebuilding) == "" {
patchOps = append(patchOps, fmt.Sprintf(`{"op": "replace", "path": "/spec/offlineReplicaRebuilding", "value": "%s"}`, longhorn.OfflineReplicaRebuildingIgnored))
}
} else {
// Always mutate the offlineReplicaRebuilding to disabled for non-SPDK volumes
patchOps = append(patchOps, fmt.Sprintf(`{"op": "replace", "path": "/spec/offlineReplicaRebuilding", "value": "%s"}`, longhorn.OfflineReplicaRebuildingDisabled))
}

var patchOpsInCommon admission.PatchOps
var err error
if patchOpsInCommon, err = mutate(newObj, nil); err != nil {
return nil, err
}
patchOps = append(patchOps, patchOpsInCommon...)

return patchOps, nil
}

func (v *volumeMutator) Update(request *admission.Request, oldObj runtime.Object, newObj runtime.Object) (admission.PatchOps, error) {
volume := newObj.(*longhorn.Volume)
var patchOps admission.PatchOps

if volume.Spec.AccessMode == "" {
patchOps = append(patchOps, `{"op": "replace", "path": "/spec/accessMode", "value": "rwo"}`)
}

size := util.RoundUpSize(volume.Spec.Size)
if size != volume.Spec.Size {
logrus.Infof("Rounding up the requested volume spec size from %d to %d in the update mutator", volume.Spec.Size, size)
patchOps = append(patchOps, fmt.Sprintf(`{"op": "replace", "path": "/spec/size", "value": "%s"}`, strconv.FormatInt(size, 10)))
}

if string(volume.Spec.BackupCompressionMethod) == "" {
patchOps = append(patchOps, fmt.Sprintf(`{"op": "replace", "path": "/spec/backupCompressionMethod", "value": "%s"}`, longhorn.BackupCompressionMethodGzip))
}

var patchOpsInCommon admission.PatchOps
var err error
if patchOps, err = mutate(newObj); err != nil {
if patchOpsInCommon, err = mutate(newObj, nil); err != nil {
return nil, err
}
patchOps = append(patchOps, patchOpsInCommon...)

return patchOps, nil
}

// mutate contains functionality shared by Create and Update.
// Unlike mutate for other resources, this mutate takes a moreLabels map, as Create may want to add some.
func mutate(newObj runtime.Object, moreLabels map[string]string) (admission.PatchOps, error) {
volume := newObj.(*longhorn.Volume)
var patchOps admission.PatchOps

patchOp, err := common.GetLonghornFinalizerPatchOpIfNeeded(volume)
if err != nil {
err := errors.Wrapf(err, "failed to get finalizer patch for volume %v", volume.Name)
return nil, werror.NewInvalidError(err.Error(), "")
}
if patchOp != "" {
patchOps = append(patchOps, patchOp)
}

if volume.Spec.ReplicaAutoBalance == "" {
patchOps = append(patchOps, `{"op": "replace", "path": "/spec/replicaAutoBalance", "value": "ignored"}`)
}
if volume.Spec.AccessMode == "" {
patchOps = append(patchOps, `{"op": "replace", "path": "/spec/accessMode", "value": "rwo"}`)
}
if volume.Spec.DiskSelector == nil {
patchOps = append(patchOps, `{"op": "replace", "path": "/spec/diskSelector", "value": []}`)
}
if volume.Spec.NodeSelector == nil {
patchOps = append(patchOps, `{"op": "replace", "path": "/spec/nodeSelector", "value": []}`)
}
if volume.Spec.UnmapMarkSnapChainRemoved == "" {
patchOps = append(patchOps, fmt.Sprintf(`{"op": "replace", "path": "/spec/unmapMarkSnapChainRemoved", "value": "%s"}`, longhorn.UnmapMarkSnapChainRemovedIgnored))
}
if string(volume.Spec.SnapshotDataIntegrity) == "" {
patchOps = append(patchOps, fmt.Sprintf(`{"op": "replace", "path": "/spec/snapshotDataIntegrity", "value": "%s"}`, longhorn.SnapshotDataIntegrityIgnored))
}
if string(volume.Spec.RestoreVolumeRecurringJob) == "" {
patchOps = append(patchOps, fmt.Sprintf(`{"op": "replace", "path": "/spec/restoreVolumeRecurringJob", "value": "%s"}`, longhorn.RestoreVolumeRecurringJobDefault))
}
if volume.Spec.UnmapMarkSnapChainRemoved == "" {
patchOps = append(patchOps, fmt.Sprintf(`{"op": "replace", "path": "/spec/unmapMarkSnapChainRemoved", "value": "%s"}`, longhorn.UnmapMarkSnapChainRemovedIgnored))
}
if string(volume.Spec.ReplicaSoftAntiAffinity) == "" {
patchOps = append(patchOps, fmt.Sprintf(`{"op": "replace", "path": "/spec/replicaSoftAntiAffinity", "value": "%s"}`, longhorn.ReplicaSoftAntiAffinityDefault))
}
Expand All @@ -304,10 +280,9 @@ func (v *volumeMutator) Update(request *admission.Request, oldObj runtime.Object
if string(volume.Spec.BackendStoreDriver) == "" {
patchOps = append(patchOps, fmt.Sprintf(`{"op": "replace", "path": "/spec/backendStoreDriver", "value": "%s"}`, longhorn.BackendStoreDriverTypeV1))
}
if string(volume.Spec.BackupCompressionMethod) == "" {
patchOps = append(patchOps, fmt.Sprintf(`{"op": "replace", "path": "/spec/backupCompressionMethod", "value": "%s"}`, longhorn.BackupCompressionMethodGzip))
}
if string(volume.Spec.OfflineReplicaRebuilding) == "" {
if string(volume.Spec.OfflineReplicaRebuilding) == "" &&
volume.Spec.BackendStoreDriver != longhorn.BackendStoreDriverTypeV2 {
// Always mutate the offlineReplicaRebuilding to disabled for non-SPDK volumes
patchOps = append(patchOps, fmt.Sprintf(`{"op": "replace", "path": "/spec/offlineReplicaRebuilding", "value": "%s"}`, longhorn.OfflineReplicaRebuildingDisabled))
}

Expand All @@ -325,13 +300,14 @@ func (v *volumeMutator) Update(request *admission.Request, oldObj runtime.Object
if labels == nil {
labels = map[string]string{}
}

for k, v := range moreLabels {
labels[k] = v
}
labelsForVolumesFollowsGlobalSettings := datastore.GetLabelsForVolumesFollowsGlobalSettings(volume)
for k, v := range labelsForVolumesFollowsGlobalSettings {
labels[k] = v
}

patchOp, err := common.GetLonghornLabelsPatchOp(volume, labels, types.SettingsRelatedToVolume)
patchOp, err = common.GetLonghornLabelsPatchOp(volume, labels, types.SettingsRelatedToVolume)
if err != nil {
err := errors.Wrapf(err, "failed to get label patch for volume %v", volume.Name)
return nil, werror.NewInvalidError(err.Error(), "")
Expand All @@ -341,23 +317,6 @@ func (v *volumeMutator) Update(request *admission.Request, oldObj runtime.Object
return patchOps, nil
}

// mutate contains functionality shared by Create and Update.
func mutate(newObj runtime.Object) (admission.PatchOps, error) {
volume := newObj.(*longhorn.Volume)
var patchOps admission.PatchOps

patchOp, err := common.GetLonghornFinalizerPatchOpIfNeeded(volume)
if err != nil {
err := errors.Wrapf(err, "failed to get finalizer patch for volume %v", volume.Name)
return nil, werror.NewInvalidError(err.Error(), "")
}
if patchOp != "" {
patchOps = append(patchOps, patchOp)
}

return patchOps, nil
}

func (v *volumeMutator) getDefaultReplicaCount() (int, error) {
c, err := v.ds.GetSettingAsInt(types.SettingNameDefaultReplicaCount)
if err != nil {
Expand Down

0 comments on commit e669b80

Please sign in to comment.