Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions api/test/v1alpha1/virtualmachine_conversion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2140,5 +2140,102 @@ func TestVirtualMachineConversion(t *testing.T) {
g.Expect(anno).Should(HaveKeyWithValue(vmopv1a1.PauseAnnotation, "true"))
g.Expect(anno).ShouldNot(HaveKey(vmopv1.PauseAnnotation))
})

t.Run("VirtualMachine hub-spoke-hub with VLANs", func(t *testing.T) {
g := NewWithT(t)

// Create a hub VM with VLANs configuration
hub := vmopv1.VirtualMachine{
ObjectMeta: metav1.ObjectMeta{
Name: "test-vm-with-vlans",
Namespace: "default",
},
Spec: vmopv1.VirtualMachineSpec{
ImageName: "ubuntu-2004",
ClassName: "best-effort-small",
Network: &vmopv1.VirtualMachineNetworkSpec{
Interfaces: []vmopv1.VirtualMachineNetworkInterfaceSpec{
{
Name: "vds-interface",
Network: &vmopv1common.PartialObjectRef{
TypeMeta: metav1.TypeMeta{
Kind: "Network",
APIVersion: "netoperator.vmware.com/v1alpha1",
},
Name: "primary",
},
GuestDeviceName: "eth0",
},
{
Name: "vds-interface",
Network: &vmopv1common.PartialObjectRef{
TypeMeta: metav1.TypeMeta{
Kind: "Network",
APIVersion: "netoperator.vmware.com/v1alpha1",
},
Name: "primary",
},
GuestDeviceName: "eth1",
},
{
Name: "vds-interface",
Network: &vmopv1common.PartialObjectRef{
TypeMeta: metav1.TypeMeta{
Kind: "Network",
APIVersion: "netoperator.vmware.com/v1alpha1",
},
Name: "primary",
},
GuestDeviceName: "eth2",
},
},
VLANs: map[string]vmopv1.VirtualMachineNetworkVLANSpec{
"vlan100": {
ID: 100,
Link: "eth1",
},
"vlan200": {
ID: 200,
Link: "eth1",
},
"vlan300": {
ID: 300,
Link: "eth2",
},
},
},
},
}

// Convert hub -> spoke
var spoke vmopv1a1.VirtualMachine
g.Expect(spoke.ConvertFrom(&hub)).To(Succeed())

// Verify hub
g.Expect(spoke.Spec.NetworkInterfaces).ToNot(BeNil())
g.Expect(spoke.Annotations[utilconversion.AnnotationKey]).ToNot(BeEmpty())

// Convert spoke -> hub
var hubAfter vmopv1.VirtualMachine
g.Expect(spoke.ConvertTo(&hubAfter)).To(Succeed())

// Verify hub
g.Expect(hubAfter.Spec.Network).ToNot(BeNil())
g.Expect(hubAfter.Spec.Network.VLANs).To(HaveLen(3))
g.Expect(hubAfter.Spec.Network.VLANs).To(HaveKey("vlan100"))
g.Expect(hubAfter.Spec.Network.VLANs).To(HaveKey("vlan200"))
g.Expect(hubAfter.Spec.Network.VLANs).To(HaveKey("vlan300"))

g.Expect(hubAfter.Spec.Network.VLANs["vlan100"].ID).To(Equal(int64(100)))
g.Expect(hubAfter.Spec.Network.VLANs["vlan100"].Link).To(Equal("eth1"))
g.Expect(hubAfter.Spec.Network.VLANs["vlan200"].ID).To(Equal(int64(200)))
g.Expect(hubAfter.Spec.Network.VLANs["vlan200"].Link).To(Equal("eth1"))
g.Expect(hubAfter.Spec.Network.VLANs["vlan300"].ID).To(Equal(int64(300)))
g.Expect(hubAfter.Spec.Network.VLANs["vlan300"].Link).To(Equal("eth2"))

// Verify full round-trip equality
g.Expect(apiequality.Semantic.DeepEqual(hub.Spec.Network.VLANs, hubAfter.Spec.Network.VLANs)).To(BeTrue(),
cmp.Diff(hub.Spec.Network.VLANs, hubAfter.Spec.Network.VLANs))
})
})
}
102 changes: 102 additions & 0 deletions api/test/v1alpha2/virtualmachine_conversion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -956,4 +956,106 @@ func TestVirtualMachineConversion(t *testing.T) {
g.Expect(anno).ShouldNot(HaveKey(vmopv1.PauseAnnotation))
})
})

t.Run("VirtualMachine network VLANs", func(t *testing.T) {
t.Run("VirtualMachine hub-spoke-hub with VLANs preserves VLANs", func(t *testing.T) {
g := NewWithT(t)

// Create a hub VM with VLANs configuration
hub := vmopv1.VirtualMachine{
ObjectMeta: metav1.ObjectMeta{
Name: "test-vm-with-vlans",
Namespace: "default",
},
Spec: vmopv1.VirtualMachineSpec{
ImageName: "ubuntu-2004",
ClassName: "best-effort-small",
Network: &vmopv1.VirtualMachineNetworkSpec{
Interfaces: []vmopv1.VirtualMachineNetworkInterfaceSpec{
{
Name: "eth0",
},
{
Name: "eth1",
},
},
VLANs: map[string]vmopv1.VirtualMachineNetworkVLANSpec{
"vlan100": {
ID: 100,
Link: "eth1",
},
"vlan200": {
ID: 200,
Link: "eth1",
},
},
},
},
}

hubSpokeHub(g, &hub, &vmopv1.VirtualMachine{}, &vmopv1a2.VirtualMachine{})
})

t.Run("VirtualMachine hub-spoke-hub with VLANs verifies round-trip", func(t *testing.T) {
g := NewWithT(t)

hubBefore := vmopv1.VirtualMachine{
ObjectMeta: metav1.ObjectMeta{
Name: "test-vm-with-vlans",
Namespace: "default",
},
Spec: vmopv1.VirtualMachineSpec{
ImageName: "ubuntu-2004",
ClassName: "best-effort-small",
Network: &vmopv1.VirtualMachineNetworkSpec{
Interfaces: []vmopv1.VirtualMachineNetworkInterfaceSpec{
{
Name: "eth0",
},
{
Name: "eth1",
},
},
VLANs: map[string]vmopv1.VirtualMachineNetworkVLANSpec{
"vlan100": {
ID: 100,
Link: "eth1",
},
"vlan200": {
ID: 200,
Link: "eth1",
},
},
},
},
}

// Convert hub -> spoke
var spoke vmopv1a2.VirtualMachine
g.Expect(spoke.ConvertFrom(&hubBefore)).To(Succeed())

// Verify spoke does not have VLANs field (it was removed from v1alpha2)
g.Expect(spoke.Spec.Network).ToNot(BeNil())
g.Expect(spoke.Spec.Network.Interfaces).To(HaveLen(2))

// Convert spoke -> hub
var hubAfter vmopv1.VirtualMachine
g.Expect(spoke.ConvertTo(&hubAfter)).To(Succeed())

// Verify VLANs are restored in hub
g.Expect(hubAfter.Spec.Network).ToNot(BeNil())
g.Expect(hubAfter.Spec.Network.VLANs).To(HaveLen(2))
g.Expect(hubAfter.Spec.Network.VLANs).To(HaveKey("vlan100"))
g.Expect(hubAfter.Spec.Network.VLANs).To(HaveKey("vlan200"))

g.Expect(hubAfter.Spec.Network.VLANs["vlan100"].ID).To(Equal(int64(100)))
g.Expect(hubAfter.Spec.Network.VLANs["vlan100"].Link).To(Equal("eth1"))
g.Expect(hubAfter.Spec.Network.VLANs["vlan200"].ID).To(Equal(int64(200)))
g.Expect(hubAfter.Spec.Network.VLANs["vlan200"].Link).To(Equal("eth1"))

// Verify full round-trip equality
g.Expect(apiequality.Semantic.DeepEqual(hubBefore.Spec.Network.VLANs, hubAfter.Spec.Network.VLANs)).To(BeTrue(),
cmp.Diff(hubBefore.Spec.Network.VLANs, hubAfter.Spec.Network.VLANs))
})
})
}
115 changes: 115 additions & 0 deletions api/test/v1alpha3/virtualmachine_conversion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -741,4 +741,119 @@ func TestVirtualMachineConversion(t *testing.T) {
})
})
})

t.Run("VirtualMachine network VLANs", func(t *testing.T) {
hubSpokeHub := func(g *WithT, hub, hubAfter ctrlconversion.Hub, spoke ctrlconversion.Convertible) {
hubBefore := hub.DeepCopyObject().(ctrlconversion.Hub)

// First convert hub to spoke
dstCopy := spoke.DeepCopyObject().(ctrlconversion.Convertible)
g.Expect(dstCopy.ConvertFrom(hubBefore)).To(Succeed())

// Convert spoke back to hub and check if the resulting hub is equal to the hub before the round trip
g.Expect(dstCopy.ConvertTo(hubAfter)).To(Succeed())

g.Expect(apiequality.Semantic.DeepEqual(hubBefore, hubAfter)).To(BeTrue(), cmp.Diff(hubBefore, hubAfter))
}

t.Run("VirtualMachine hub-spoke-hub with VLANs preserves VLANs", func(t *testing.T) {
g := NewWithT(t)

// Create a hub VM with VLANs configuration
hub := vmopv1.VirtualMachine{
ObjectMeta: metav1.ObjectMeta{
Name: "test-vm-with-vlans",
Namespace: "default",
},
Spec: vmopv1.VirtualMachineSpec{
ImageName: "ubuntu-2004",
ClassName: "best-effort-small",
Network: &vmopv1.VirtualMachineNetworkSpec{
Interfaces: []vmopv1.VirtualMachineNetworkInterfaceSpec{
{
Name: "eth0",
},
{
Name: "eth1",
},
},
VLANs: map[string]vmopv1.VirtualMachineNetworkVLANSpec{
"vlan100": {
ID: 100,
Link: "eth1",
},
"vlan200": {
ID: 200,
Link: "eth1",
},
},
},
},
}

hubSpokeHub(g, &hub, &vmopv1.VirtualMachine{}, &vmopv1a3.VirtualMachine{})
})

t.Run("VirtualMachine hub-spoke-hub with VLANs verifies round-trip", func(t *testing.T) {
g := NewWithT(t)

hubBefore := vmopv1.VirtualMachine{
ObjectMeta: metav1.ObjectMeta{
Name: "test-vm-with-vlans",
Namespace: "default",
},
Spec: vmopv1.VirtualMachineSpec{
ImageName: "ubuntu-2004",
ClassName: "best-effort-small",
Network: &vmopv1.VirtualMachineNetworkSpec{
Interfaces: []vmopv1.VirtualMachineNetworkInterfaceSpec{
{
Name: "eth0",
},
{
Name: "eth1",
},
},
VLANs: map[string]vmopv1.VirtualMachineNetworkVLANSpec{
"vlan100": {
ID: 100,
Link: "eth1",
},
"vlan200": {
ID: 200,
Link: "eth1",
},
},
},
},
}

// Convert hub -> spoke
var spoke vmopv1a3.VirtualMachine
g.Expect(spoke.ConvertFrom(&hubBefore)).To(Succeed())

// Verify spoke does not have VLANs field (it was removed from v1alpha3)
g.Expect(spoke.Spec.Network).ToNot(BeNil())
g.Expect(spoke.Spec.Network.Interfaces).To(HaveLen(2))

// Convert spoke -> hub
var hubAfter vmopv1.VirtualMachine
g.Expect(spoke.ConvertTo(&hubAfter)).To(Succeed())

// Verify VLANs are restored in hub
g.Expect(hubAfter.Spec.Network).ToNot(BeNil())
g.Expect(hubAfter.Spec.Network.VLANs).To(HaveLen(2))
g.Expect(hubAfter.Spec.Network.VLANs).To(HaveKey("vlan100"))
g.Expect(hubAfter.Spec.Network.VLANs).To(HaveKey("vlan200"))

g.Expect(hubAfter.Spec.Network.VLANs["vlan100"].ID).To(Equal(int64(100)))
g.Expect(hubAfter.Spec.Network.VLANs["vlan100"].Link).To(Equal("eth1"))
g.Expect(hubAfter.Spec.Network.VLANs["vlan200"].ID).To(Equal(int64(200)))
g.Expect(hubAfter.Spec.Network.VLANs["vlan200"].Link).To(Equal("eth1"))

// Verify full round-trip equality
g.Expect(apiequality.Semantic.DeepEqual(hubBefore.Spec.Network.VLANs, hubAfter.Spec.Network.VLANs)).To(BeTrue(),
cmp.Diff(hubBefore.Spec.Network.VLANs, hubAfter.Spec.Network.VLANs))
})
})
}
Loading