Skip to content

Commit

Permalink
Fix potential VM validation webhook NPE for Spec.Network
Browse files Browse the repository at this point in the history
If the VM Spec.Network was changed to/from nil, the validation webhook
would NPE. I think the stems from late in v1a2 we decided to make most
of the top level Spec/Status fields pointers and this was just missed.

Add a few basic update tests for VM Spec.Network.
  • Loading branch information
Bryan Venteicher committed Dec 13, 2024
1 parent 32a7325 commit ac3ac59
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1230,8 +1230,13 @@ func (v validator) validateImmutableNetwork(ctx *pkgctx.WebhookRequestContext, v

p := field.NewPath("spec", "network")

oldInterfaces := oldVM.Spec.Network.Interfaces
newInterfaces := vm.Spec.Network.Interfaces
var oldInterfaces, newInterfaces []vmopv1.VirtualMachineNetworkInterfaceSpec
if oldNetwork != nil {
oldInterfaces = oldNetwork.Interfaces
}
if newNetwork != nil {
newInterfaces = newNetwork.Interfaces
}

if len(oldInterfaces) != len(newInterfaces) {
return append(allErrs, field.Forbidden(p.Child("interfaces"), "network interfaces cannot be added or removed"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3148,7 +3148,7 @@ func unitTestsValidateUpdate() {
},
),

Entry("alow changing image for privileged users when FSS_WCP_VMSERVICE_INCREMENTAL_RESTORE is enabled, and Registered annotation is present",
Entry("allow changing image for privileged users when FSS_WCP_VMSERVICE_INCREMENTAL_RESTORE is enabled, and Registered annotation is present",
testParams{
setup: func(ctx *unitValidatingWebhookContext) {
pkgcfg.SetContext(ctx, func(config *pkgcfg.Config) {
Expand Down Expand Up @@ -3687,7 +3687,7 @@ func unitTestsValidateUpdate() {
},
),

Entry("alow removing CD-ROM when VM is powered off",
Entry("allow removing CD-ROM when VM is powered off",
testParams{
setup: func(ctx *unitValidatingWebhookContext) {
ctx.vm.Spec.Cdrom = []vmopv1.VirtualMachineCdromSpec{}
Expand Down Expand Up @@ -4014,6 +4014,98 @@ func unitTestsValidateUpdate() {
),
)
})

Context("Network", func() {

DescribeTable("network update", doTest,
Entry("allow Network go from nil to not-nil",
testParams{
setup: func(ctx *unitValidatingWebhookContext) {
ctx.oldVM.Spec.Network = nil
ctx.vm.Spec.Network = &vmopv1.VirtualMachineNetworkSpec{}
},
expectAllowed: true,
},
),
Entry("allow Network go from not-nil to nil",
testParams{
setup: func(ctx *unitValidatingWebhookContext) {
ctx.oldVM.Spec.Network = &vmopv1.VirtualMachineNetworkSpec{}
ctx.vm.Spec.Network = nil
},
expectAllowed: true,
},
),
Entry("disallow adding Network Interface",
testParams{
setup: func(ctx *unitValidatingWebhookContext) {
ctx.oldVM.Spec.Network = &vmopv1.VirtualMachineNetworkSpec{
Interfaces: []vmopv1.VirtualMachineNetworkInterfaceSpec{
{
Name: "eth0",
},
},
}
ctx.vm.Spec.Network = &vmopv1.VirtualMachineNetworkSpec{
Interfaces: []vmopv1.VirtualMachineNetworkInterfaceSpec{
{
Name: "eth0",
},
{
Name: "eth1",
},
},
}
},
validate: doValidateWithMsg(`spec.network.interfaces: Forbidden: network interfaces cannot be added or removed`),
},
),
Entry("disallow Network Interface Name change",
testParams{
setup: func(ctx *unitValidatingWebhookContext) {
ctx.oldVM.Spec.Network = &vmopv1.VirtualMachineNetworkSpec{
Interfaces: []vmopv1.VirtualMachineNetworkInterfaceSpec{
{
Name: "eth0",
},
},
}
ctx.vm.Spec.Network = &vmopv1.VirtualMachineNetworkSpec{
Interfaces: []vmopv1.VirtualMachineNetworkInterfaceSpec{
{
Name: "eth1",
},
},
}
},
validate: doValidateWithMsg(`spec.network.interfaces[0].name: Forbidden: field is immutable`),
},
),
Entry("disallow Network Interface Network ref change",
testParams{
setup: func(ctx *unitValidatingWebhookContext) {
ctx.oldVM.Spec.Network = &vmopv1.VirtualMachineNetworkSpec{
Interfaces: []vmopv1.VirtualMachineNetworkInterfaceSpec{
{
Name: "eth0",
Network: &common.PartialObjectRef{Name: "net1"},
},
},
}
ctx.vm.Spec.Network = &vmopv1.VirtualMachineNetworkSpec{
Interfaces: []vmopv1.VirtualMachineNetworkInterfaceSpec{
{
Name: "eth0",
Network: &common.PartialObjectRef{Name: "net99"},
},
},
}
},
validate: doValidateWithMsg(`spec.network.interfaces[0].network: Forbidden: field is immutable`),
},
),
)
})
}

func unitTestsValidateDelete() {
Expand Down

0 comments on commit ac3ac59

Please sign in to comment.