Skip to content

Commit d074c6c

Browse files
committed
Ensure that UDN updates update NAD annotations correctly
With b05875b we introduced copying the UDN annotations to the NAD, except for internal annotations (k8s.ovn.org). However, this patch missed doing this on update events. Signed-off-by: Tim Rozet <[email protected]>
1 parent 72d1776 commit d074c6c

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

go-controller/pkg/clustermanager/userdefinednetwork/controller_helper.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"reflect"
7+
"strings"
78

89
netv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1"
910

@@ -76,12 +77,24 @@ func (c *Controller) updateNAD(obj client.Object, namespace string) (*netv1.Netw
7677
return nil, fmt.Errorf("foreign NetworkAttachmentDefinition with the desired name already exist [%s/%s]", nadCopy.Namespace, nadCopy.Name)
7778
}
7879

79-
if reflect.DeepEqual(nadCopy.Spec.Config, desiredNAD.Spec.Config) && reflect.DeepEqual(nadCopy.ObjectMeta.Labels, desiredNAD.ObjectMeta.Labels) {
80+
// NAD update path, need to merge internal (k8s.ovn.org) current annotations with desired
81+
for k, v := range nadCopy.Annotations {
82+
if strings.HasPrefix(k, types.OvnK8sPrefix) {
83+
if desiredNAD.Annotations == nil {
84+
desiredNAD.Annotations = make(map[string]string)
85+
}
86+
desiredNAD.Annotations[k] = v
87+
}
88+
}
89+
90+
if reflect.DeepEqual(nadCopy.Spec.Config, desiredNAD.Spec.Config) && reflect.DeepEqual(nadCopy.ObjectMeta.Labels, desiredNAD.ObjectMeta.Labels) &&
91+
reflect.DeepEqual(desiredNAD.Annotations, nadCopy.Annotations) {
8092
return nadCopy, nil
8193
}
8294

8395
nadCopy.Spec.Config = desiredNAD.Spec.Config
8496
nadCopy.ObjectMeta.Labels = desiredNAD.ObjectMeta.Labels
97+
nadCopy.Annotations = desiredNAD.Annotations
8598
updatedNAD, err := c.nadClient.K8sCniCncfIoV1().NetworkAttachmentDefinitions(nadCopy.Namespace).Update(context.Background(), nadCopy, metav1.UpdateOptions{})
8699
if err != nil {
87100
return nil, fmt.Errorf("failed to update NetworkAttachmentDefinition: %w", err)

go-controller/pkg/clustermanager/userdefinednetwork/controller_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,63 @@ var _ = Describe("User Defined Network Controller", func() {
445445
}
446446
})
447447

448+
It("should update NAD annotations and preserve internal OVNK annotations on UDN update", func() {
449+
testNamespaces := []string{"red", "blue"}
450+
var objs []runtime.Object
451+
for _, nsName := range testNamespaces {
452+
objs = append(objs, testNamespace(nsName))
453+
}
454+
cudn := testClusterUDN("test", testNamespaces...)
455+
cudn.Spec.Network = udnv1.NetworkSpec{Topology: udnv1.NetworkTopologyLayer2, Layer2: &udnv1.Layer2Config{
456+
Subnets: udnv1.DualStackCIDRs{"10.10.10.0/24"},
457+
}}
458+
cudn.Annotations = map[string]string{"foo": "bar"}
459+
460+
objs = append(objs, cudn)
461+
networkName := ovntypes.CUDNPrefix + cudn.Name
462+
expectedNsNADs := map[string]*netv1.NetworkAttachmentDefinition{}
463+
for _, nsName := range testNamespaces {
464+
nad := testClusterUdnNAD(cudn.Name, nsName)
465+
nadName := nsName + "/" + cudn.Name
466+
nad.Spec.Config = `{"cniVersion":"1.0.0","name":"` + networkName + `","netAttachDefName":"` + nadName + `","role":"","subnets":"10.10.10.0/24","topology":"layer2","type":"ovn-k8s-cni-overlay"}`
467+
nad.Annotations = map[string]string{
468+
"foo": "bar",
469+
ovntypes.OvnNetworkNameAnnotation: networkName,
470+
ovntypes.OvnNetworkIDAnnotation: "6",
471+
}
472+
expectedNsNADs[nsName] = nad.DeepCopy()
473+
objs = append(objs, nad)
474+
}
475+
476+
c = newTestController(template.RenderNetAttachDefManifest, objs...)
477+
Expect(c.Run()).To(Succeed())
478+
479+
By("updating CUDN with a new annotation")
480+
cudn, err := cs.UserDefinedNetworkClient.K8sV1().ClusterUserDefinedNetworks().Get(context.Background(), cudn.Name, metav1.GetOptions{})
481+
Expect(err).NotTo(HaveOccurred())
482+
updatedCUDN := cudn.DeepCopy()
483+
updatedCUDN.Annotations = map[string]string{"foo2": "bar2"}
484+
_, err = cs.UserDefinedNetworkClient.K8sV1().ClusterUserDefinedNetworks().Update(context.Background(), updatedCUDN, metav1.UpdateOptions{})
485+
Expect(err).NotTo(HaveOccurred())
486+
487+
for testNamespace, expectedNAD := range expectedNsNADs {
488+
expectedNAD.Annotations = map[string]string{
489+
"foo2": "bar2",
490+
ovntypes.OvnNetworkNameAnnotation: networkName,
491+
ovntypes.OvnNetworkIDAnnotation: "6",
492+
}
493+
494+
Eventually(func(g Gomega) {
495+
actualNAD, err := cs.NetworkAttchDefClient.K8sCniCncfIoV1().
496+
NetworkAttachmentDefinitions(testNamespace).
497+
Get(context.Background(), cudn.Name, metav1.GetOptions{})
498+
g.Expect(err).NotTo(HaveOccurred())
499+
g.Expect(actualNAD).To(Equal(expectedNAD), "NAD should exist, have updated "+
500+
"annotations, and preserve internal annotations")
501+
}).Should(Succeed())
502+
}
503+
})
504+
448505
When("CR exist, and few connected & disconnected namespaces", func() {
449506
const (
450507
cudnName = "global-network"

0 commit comments

Comments
 (0)