diff --git a/api/v1/helper.go b/api/v1/helper.go index e5eeaa5883..363006dc5a 100644 --- a/api/v1/helper.go +++ b/api/v1/helper.go @@ -19,6 +19,7 @@ import ( uns "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" intstrutil "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/client-go/kubernetes" + "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" @@ -651,6 +652,7 @@ func (cr *SriovIBNetwork) RenderNetAttDef() (*uns.Unstructured, error) { } else { data.Data["SriovNetworkNamespace"] = cr.Spec.NetworkNamespace } + data.Data["Owner"] = OwnerRefToString(cr) data.Data["SriovCniResourceName"] = os.Getenv("RESOURCE_PREFIX") + "/" + cr.Spec.ResourceName data.Data["StateConfigured"] = true @@ -719,6 +721,7 @@ func (cr *SriovNetwork) RenderNetAttDef() (*uns.Unstructured, error) { } else { data.Data["SriovNetworkNamespace"] = cr.Spec.NetworkNamespace } + data.Data["Owner"] = OwnerRefToString(cr) data.Data["SriovCniResourceName"] = os.Getenv("RESOURCE_PREFIX") + "/" + cr.Spec.ResourceName data.Data["SriovCniVlan"] = cr.Spec.Vlan @@ -837,6 +840,7 @@ func (cr *OVSNetwork) RenderNetAttDef() (*uns.Unstructured, error) { } else { data.Data["NetworkNamespace"] = cr.Spec.NetworkNamespace } + data.Data["Owner"] = OwnerRefToString(cr) data.Data["CniResourceName"] = os.Getenv("RESOURCE_PREFIX") + "/" + cr.Spec.ResourceName if cr.Spec.Capabilities == "" { @@ -994,3 +998,14 @@ func (s *SriovNetworkNodeState) ResetKeepUntilTime() bool { s.SetAnnotations(annotations) return true } + +func OwnerRefToString(cr client.Object) string { + if cr == nil { + return "owner-object-not-found" + } + if cr.GetObjectKind().GroupVersionKind().Empty() { + return "unknown/" + cr.GetNamespace() + "/" + cr.GetName() + } + + return cr.GetObjectKind().GroupVersionKind().GroupKind().String() + "/" + cr.GetNamespace() + "/" + cr.GetName() +} diff --git a/api/v1/helper_test.go b/api/v1/helper_test.go index 06215d067f..cb337d32ae 100644 --- a/api/v1/helper_test.go +++ b/api/v1/helper_test.go @@ -10,6 +10,7 @@ import ( "testing" "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" intstrutil "k8s.io/apimachinery/pkg/util/intstr" @@ -149,6 +150,8 @@ func TestRendering(t *testing.T) { { tname: "simple", network: v1.SriovNetwork{ + TypeMeta: metav1.TypeMeta{APIVersion: v1.GroupVersion.String(), Kind: "SriovNetwork"}, + ObjectMeta: metav1.ObjectMeta{Namespace: "ns", Name: "test"}, Spec: v1.SriovNetworkSpec{ NetworkNamespace: "testnamespace", ResourceName: "testresource", @@ -158,6 +161,8 @@ func TestRendering(t *testing.T) { { tname: "chained", network: v1.SriovNetwork{ + TypeMeta: metav1.TypeMeta{APIVersion: v1.GroupVersion.String(), Kind: "SriovNetwork"}, + ObjectMeta: metav1.ObjectMeta{Namespace: "ns", Name: "test"}, Spec: v1.SriovNetworkSpec{ NetworkNamespace: "testnamespace", ResourceName: "testresource", @@ -194,10 +199,8 @@ func TestRendering(t *testing.T) { if err != nil { t.Fatalf("failed reading .golden: %s", err) } - t.Log(b.String()) - if !bytes.Equal(b.Bytes(), g) { - t.Errorf("bytes do not match .golden file") - } + + assert.Equal(t, string(g), b.String(), "bytes do not match .golden file [%s]", gp) }) } } @@ -210,6 +213,8 @@ func TestIBRendering(t *testing.T) { { tname: "simpleib", network: v1.SriovIBNetwork{ + TypeMeta: metav1.TypeMeta{APIVersion: v1.GroupVersion.String(), Kind: "SriovIBNetwork"}, + ObjectMeta: metav1.ObjectMeta{Namespace: "ns", Name: "test"}, Spec: v1.SriovIBNetworkSpec{ NetworkNamespace: "testnamespace", ResourceName: "testresource", @@ -241,10 +246,8 @@ func TestIBRendering(t *testing.T) { if err != nil { t.Fatalf("failed reading .golden: %s", err) } - t.Log(b.String()) - if !bytes.Equal(b.Bytes(), g) { - t.Errorf("bytes do not match .golden file") - } + + assert.Equal(t, string(g), b.String(), "bytes do not match .golden file [%s]", gp) }) } } @@ -257,9 +260,8 @@ func TestOVSRendering(t *testing.T) { { tname: "simpleovs", network: v1.OVSNetwork{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test", - }, + TypeMeta: metav1.TypeMeta{APIVersion: v1.GroupVersion.String(), Kind: "OVSNetwork"}, + ObjectMeta: metav1.ObjectMeta{Namespace: "ns", Name: "test"}, Spec: v1.OVSNetworkSpec{ NetworkNamespace: "testnamespace", ResourceName: "testresource", @@ -269,9 +271,8 @@ func TestOVSRendering(t *testing.T) { { tname: "chained", network: v1.OVSNetwork{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test", - }, + TypeMeta: metav1.TypeMeta{APIVersion: v1.GroupVersion.String(), Kind: "OVSNetwork"}, + ObjectMeta: metav1.ObjectMeta{Namespace: "ns", Name: "test"}, Spec: v1.OVSNetworkSpec{ NetworkNamespace: "testnamespace", ResourceName: "testresource", @@ -288,9 +289,8 @@ func TestOVSRendering(t *testing.T) { { tname: "complexconf", network: v1.OVSNetwork{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test", - }, + TypeMeta: metav1.TypeMeta{APIVersion: v1.GroupVersion.String(), Kind: "OVSNetwork"}, + ObjectMeta: metav1.ObjectMeta{Namespace: "ns", Name: "test"}, Spec: v1.OVSNetworkSpec{ NetworkNamespace: "testnamespace", ResourceName: "testresource", @@ -334,10 +334,8 @@ func TestOVSRendering(t *testing.T) { if err != nil { t.Fatalf("failed reading .golden: %s", err) } - t.Log(b.String()) - if !bytes.Equal(b.Bytes(), g) { - t.Errorf("bytes do not match .golden file") - } + + assert.Equal(t, string(g), b.String(), "bytes do not match .golden file [%s]", gp) }) } } diff --git a/api/v1/testdata/TestIBRendering/simpleib.golden b/api/v1/testdata/TestIBRendering/simpleib.golden index c88d26c35b..e93fde91a1 100644 --- a/api/v1/testdata/TestIBRendering/simpleib.golden +++ b/api/v1/testdata/TestIBRendering/simpleib.golden @@ -3,12 +3,13 @@ "kind": "NetworkAttachmentDefinition", "metadata": { "annotations": { - "k8s.v1.cni.cncf.io/resourceName": "/testresource" + "k8s.v1.cni.cncf.io/resourceName": "/testresource", + "sriovnetwork.openshift.io/owner-ref": "SriovIBNetwork.sriovnetwork.openshift.io/ns/test" }, - "name": null, + "name": "test", "namespace": "testnamespace" }, "spec": { - "config": "{ \"cniVersion\":\"1.0.0\", \"name\":\"\",\"type\":\"ib-sriov\",\"capabilities\":foo,\"ipam\":{} }" + "config": "{ \"cniVersion\":\"1.0.0\", \"name\":\"test\",\"type\":\"ib-sriov\",\"capabilities\":foo,\"ipam\":{} }" } } diff --git a/api/v1/testdata/TestOVSRendering/chained.golden b/api/v1/testdata/TestOVSRendering/chained.golden index 42024e90ae..9f37afeb21 100644 --- a/api/v1/testdata/TestOVSRendering/chained.golden +++ b/api/v1/testdata/TestOVSRendering/chained.golden @@ -3,7 +3,8 @@ "kind": "NetworkAttachmentDefinition", "metadata": { "annotations": { - "k8s.v1.cni.cncf.io/resourceName": "/testresource" + "k8s.v1.cni.cncf.io/resourceName": "/testresource", + "sriovnetwork.openshift.io/owner-ref": "OVSNetwork.sriovnetwork.openshift.io/ns/test" }, "name": "test", "namespace": "testnamespace" diff --git a/api/v1/testdata/TestOVSRendering/complexconf.golden b/api/v1/testdata/TestOVSRendering/complexconf.golden index 4ead9f3f90..54ee8e4a2f 100644 --- a/api/v1/testdata/TestOVSRendering/complexconf.golden +++ b/api/v1/testdata/TestOVSRendering/complexconf.golden @@ -3,7 +3,8 @@ "kind": "NetworkAttachmentDefinition", "metadata": { "annotations": { - "k8s.v1.cni.cncf.io/resourceName": "/testresource" + "k8s.v1.cni.cncf.io/resourceName": "/testresource", + "sriovnetwork.openshift.io/owner-ref": "OVSNetwork.sriovnetwork.openshift.io/ns/test" }, "name": "test", "namespace": "testnamespace" diff --git a/api/v1/testdata/TestOVSRendering/simpleovs.golden b/api/v1/testdata/TestOVSRendering/simpleovs.golden index ce58ef5978..8357b0e807 100644 --- a/api/v1/testdata/TestOVSRendering/simpleovs.golden +++ b/api/v1/testdata/TestOVSRendering/simpleovs.golden @@ -3,7 +3,8 @@ "kind": "NetworkAttachmentDefinition", "metadata": { "annotations": { - "k8s.v1.cni.cncf.io/resourceName": "/testresource" + "k8s.v1.cni.cncf.io/resourceName": "/testresource", + "sriovnetwork.openshift.io/owner-ref": "OVSNetwork.sriovnetwork.openshift.io/ns/test" }, "name": "test", "namespace": "testnamespace" diff --git a/api/v1/testdata/TestRendering/chained.golden b/api/v1/testdata/TestRendering/chained.golden index 156acf88b4..894185b304 100644 --- a/api/v1/testdata/TestRendering/chained.golden +++ b/api/v1/testdata/TestRendering/chained.golden @@ -3,12 +3,13 @@ "kind": "NetworkAttachmentDefinition", "metadata": { "annotations": { - "k8s.v1.cni.cncf.io/resourceName": "/testresource" + "k8s.v1.cni.cncf.io/resourceName": "/testresource", + "sriovnetwork.openshift.io/owner-ref": "SriovNetwork.sriovnetwork.openshift.io/ns/test" }, - "name": null, + "name": "test", "namespace": "testnamespace" }, "spec": { - "config": "{ \"cniVersion\":\"1.0.0\", \"name\":\"\",\"plugins\": [ {\"type\":\"sriov\",\"vlan\":0,\"vlanQoS\":0,\"ipam\":{} },\n{ \"type\": \"vrf\", \"vrfname\": \"blue\" }\n] }" + "config": "{ \"cniVersion\":\"1.0.0\", \"name\":\"test\",\"plugins\": [ {\"type\":\"sriov\",\"vlan\":0,\"vlanQoS\":0,\"ipam\":{} },\n{ \"type\": \"vrf\", \"vrfname\": \"blue\" }\n] }" } } diff --git a/api/v1/testdata/TestRendering/simple.golden b/api/v1/testdata/TestRendering/simple.golden index 3eb98bbb3c..830be2ed6a 100644 --- a/api/v1/testdata/TestRendering/simple.golden +++ b/api/v1/testdata/TestRendering/simple.golden @@ -3,12 +3,13 @@ "kind": "NetworkAttachmentDefinition", "metadata": { "annotations": { - "k8s.v1.cni.cncf.io/resourceName": "/testresource" + "k8s.v1.cni.cncf.io/resourceName": "/testresource", + "sriovnetwork.openshift.io/owner-ref": "SriovNetwork.sriovnetwork.openshift.io/ns/test" }, - "name": null, + "name": "test", "namespace": "testnamespace" }, "spec": { - "config": "{ \"cniVersion\":\"1.0.0\", \"name\":\"\",\"type\":\"sriov\",\"vlan\":0,\"vlanQoS\":0,\"ipam\":{} }" + "config": "{ \"cniVersion\":\"1.0.0\", \"name\":\"test\",\"type\":\"sriov\",\"vlan\":0,\"vlanQoS\":0,\"ipam\":{} }" } } diff --git a/bindata/manifests/cni-config/ovs/ovs-cni-config.yaml b/bindata/manifests/cni-config/ovs/ovs-cni-config.yaml index 425e2297f1..2f693a64b5 100644 --- a/bindata/manifests/cni-config/ovs/ovs-cni-config.yaml +++ b/bindata/manifests/cni-config/ovs/ovs-cni-config.yaml @@ -5,6 +5,7 @@ metadata: namespace: {{.NetworkNamespace}} annotations: k8s.v1.cni.cncf.io/resourceName: {{.CniResourceName}} + sriovnetwork.openshift.io/owner-ref: {{.Owner}} spec: config: '{ "cniVersion":"1.0.0", diff --git a/bindata/manifests/cni-config/sriov/sriov-cni-config.yaml b/bindata/manifests/cni-config/sriov/sriov-cni-config.yaml index 749e326c75..b3514a9efd 100644 --- a/bindata/manifests/cni-config/sriov/sriov-cni-config.yaml +++ b/bindata/manifests/cni-config/sriov/sriov-cni-config.yaml @@ -5,6 +5,7 @@ metadata: namespace: {{.SriovNetworkNamespace}} annotations: k8s.v1.cni.cncf.io/resourceName: {{.SriovCniResourceName}} + sriovnetwork.openshift.io/owner-ref: {{.Owner}} spec: config: '{ "cniVersion":"1.0.0", diff --git a/controllers/generic_network_controller.go b/controllers/generic_network_controller.go index af2d94e046..f5b60294a0 100644 --- a/controllers/generic_network_controller.go +++ b/controllers/generic_network_controller.go @@ -38,6 +38,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) @@ -189,6 +190,20 @@ func (r *genericNetworkReconciler) Reconcile(ctx context.Context, req ctrl.Reque } } else { reqLogger.Info("NetworkAttachmentDefinition CR already exist") + + foundOwner := found.GetAnnotations()[consts.OwnerRefAnnotation] + expectedOwner := netAttDef.GetAnnotations()[consts.OwnerRefAnnotation] + + // Note for the future: the `foundOwner != ""` condition can be removed to make the operator not touching the NetworkAttachmentDefinition created + // by the user. + if foundOwner != "" && foundOwner != expectedOwner { + reqLogger.Info("A NetworkAttachmentDefinition with the same name already exists and it does not belong to this resource", + "Namespace", netAttDef.Namespace, "Name", netAttDef.Name, + "CurrentOwner", foundOwner, "ExpectedOwner", expectedOwner, + ) + return reconcile.Result{}, nil + } + if !equality.Semantic.DeepEqual(found.Spec, netAttDef.Spec) || !equality.Semantic.DeepEqual(found.GetAnnotations(), netAttDef.GetAnnotations()) { reqLogger.Info("Update NetworkAttachmentDefinition CR", "Namespace", netAttDef.Namespace, "Name", netAttDef.Name) netAttDef.SetResourceVersion(found.GetResourceVersion()) diff --git a/controllers/generic_network_controller_test.go b/controllers/generic_network_controller_test.go new file mode 100644 index 0000000000..ecd247d0e5 --- /dev/null +++ b/controllers/generic_network_controller_test.go @@ -0,0 +1,222 @@ +package controllers + +import ( + "context" + "sync" + "time" + + netattdefv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util" +) + +var _ = Describe("All Network Controllers", Ordered, func() { + var cancel context.CancelFunc + var ctx context.Context + + BeforeAll(func() { + By("Setup controller manager") + k8sManager, err := setupK8sManagerForTest() + Expect(err).ToNot(HaveOccurred()) + + err = (&SriovNetworkReconciler{ + Client: k8sManager.GetClient(), + Scheme: k8sManager.GetScheme(), + }).SetupWithManager(k8sManager) + Expect(err).ToNot(HaveOccurred()) + + err = (&SriovIBNetworkReconciler{ + Client: k8sManager.GetClient(), + Scheme: k8sManager.GetScheme(), + }).SetupWithManager(k8sManager) + Expect(err).ToNot(HaveOccurred()) + + err = (&OVSNetworkReconciler{ + Client: k8sManager.GetClient(), + Scheme: k8sManager.GetScheme(), + }).SetupWithManager(k8sManager) + Expect(err).ToNot(HaveOccurred()) + + ctx, cancel = context.WithCancel(context.Background()) + + wg := sync.WaitGroup{} + wg.Add(1) + go func() { + defer wg.Done() + defer GinkgoRecover() + By("Start controller manager") + err := k8sManager.Start(ctx) + Expect(err).ToNot(HaveOccurred()) + }() + + DeferCleanup(func() { + By("Shutdown controller manager") + cancel() + wg.Wait() + }) + }) + + Context("owner-reference annotations", func() { + AfterEach(func() { + cleanNetworksInNamespace(testNamespace) + cleanNetworksInNamespace("default") + }) + + It("applies to new netattachdef", func() { + cr := sriovnetworkv1.SriovNetwork{ + ObjectMeta: metav1.ObjectMeta{ + Name: "sriovnet-blue", + Namespace: testNamespace, + }, + Spec: sriovnetworkv1.SriovNetworkSpec{ + NetworkNamespace: "default", + }, + } + + err := k8sClient.Create(ctx, &cr) + Expect(err).NotTo(HaveOccurred()) + + netAttDef := &netattdefv1.NetworkAttachmentDefinition{} + err = util.WaitForNamespacedObject(netAttDef, k8sClient, "default", cr.GetName(), util.RetryInterval, util.Timeout) + Expect(err).NotTo(HaveOccurred()) + + Expect(netAttDef.GetAnnotations()).To(HaveKeyWithValue(consts.OwnerRefAnnotation, "SriovNetwork.sriovnetwork.openshift.io/openshift-sriov-network-operator/sriovnet-blue")) + }) + + It("should migrate existing NetAttachDef to have a value for Owner annotation", func() { + netAttachDef := netattdefv1.NetworkAttachmentDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: "netuser", Namespace: "default"}, + Spec: netattdefv1.NetworkAttachmentDefinitionSpec{ + Config: "user created configration, to be overridden", + }, + } + err := k8sClient.Create(ctx, &netAttachDef) + Expect(err).NotTo(HaveOccurred()) + + cr := sriovnetworkv1.SriovNetwork{ + ObjectMeta: metav1.ObjectMeta{Name: "netuser", Namespace: testNamespace}, + Spec: sriovnetworkv1.SriovNetworkSpec{NetworkNamespace: "default"}, + } + err = k8sClient.Create(ctx, &cr) + Expect(err).NotTo(HaveOccurred()) + + Eventually(func(g Gomega) { + netAttDef := &netattdefv1.NetworkAttachmentDefinition{} + err = util.WaitForNamespacedObject(netAttDef, k8sClient, "default", cr.GetName(), util.RetryInterval, util.Timeout) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(netAttDef.GetAnnotations()). + To(HaveKeyWithValue(consts.OwnerRefAnnotation, "SriovNetwork.sriovnetwork.openshift.io/openshift-sriov-network-operator/netuser")) + g.Expect(netAttDef.Spec.Config).To(Equal(generateExpectedNetConfig(&cr))) + }).WithPolling(30 * time.Millisecond).WithTimeout(300 * time.Millisecond).Should(Succeed()) + }) + + Context("does not override the NetAttachDefinition if the Owner annotation does not match", func() { + It("when using different network type with the same name", func() { + cr := sriovnetworkv1.SriovNetwork{ + ObjectMeta: metav1.ObjectMeta{Name: "net1", Namespace: testNamespace}, + Spec: sriovnetworkv1.SriovNetworkSpec{NetworkNamespace: "default"}, + } + err := k8sClient.Create(ctx, &cr) + Expect(err).NotTo(HaveOccurred()) + + netAttDef := &netattdefv1.NetworkAttachmentDefinition{} + err = util.WaitForNamespacedObject(netAttDef, k8sClient, "default", cr.GetName(), util.RetryInterval, util.Timeout) + Expect(err).NotTo(HaveOccurred()) + + cr2 := sriovnetworkv1.SriovIBNetwork{ + ObjectMeta: metav1.ObjectMeta{Name: "net1", Namespace: testNamespace}, + Spec: sriovnetworkv1.SriovIBNetworkSpec{NetworkNamespace: "default"}, + } + err = k8sClient.Create(ctx, &cr2) + Expect(err).NotTo(HaveOccurred()) + + Consistently(func(g Gomega) { + netAttDef := &netattdefv1.NetworkAttachmentDefinition{} + err = util.WaitForNamespacedObject(netAttDef, k8sClient, "default", cr.GetName(), util.RetryInterval, util.Timeout) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(netAttDef.Spec.Config).To(ContainSubstring(`"sriov"`)) + g.Expect(netAttDef.Spec.Config).ToNot(ContainSubstring(`"ib-sriov"`)) + }).WithPolling(30 * time.Millisecond).WithTimeout(300 * time.Millisecond).Should(Succeed()) + }) + + It("when using the same network type with the same name, in different namespaces", func() { + cr := sriovnetworkv1.SriovNetwork{ + ObjectMeta: metav1.ObjectMeta{Name: "net2", Namespace: testNamespace}, + Spec: sriovnetworkv1.SriovNetworkSpec{ + NetworkNamespace: "default", + MinTxRate: ptr.To(42), + }, + } + err := k8sClient.Create(ctx, &cr) + Expect(err).NotTo(HaveOccurred()) + + netAttDef := &netattdefv1.NetworkAttachmentDefinition{} + err = util.WaitForNamespacedObject(netAttDef, k8sClient, "default", cr.GetName(), util.RetryInterval, util.Timeout) + Expect(err).NotTo(HaveOccurred()) + + cr2 := sriovnetworkv1.SriovNetwork{ + ObjectMeta: metav1.ObjectMeta{Name: "net2", Namespace: "default"}, + Spec: sriovnetworkv1.SriovNetworkSpec{ + MinTxRate: ptr.To(84), + }, + } + err = k8sClient.Create(ctx, &cr2) + Expect(err).NotTo(HaveOccurred()) + + Consistently(func(g Gomega) { + netAttDef := &netattdefv1.NetworkAttachmentDefinition{} + err = util.WaitForNamespacedObject(netAttDef, k8sClient, "default", cr.GetName(), util.RetryInterval, util.Timeout) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(netAttDef.Spec.Config).To(ContainSubstring(`"min_tx_rate": 42`)) + g.Expect(netAttDef.Spec.Config).ToNot(ContainSubstring(`"min_tx_rate": 84`)) + }).WithPolling(30 * time.Millisecond).WithTimeout(300 * time.Millisecond).Should(Succeed()) + }) + }) + }) + +}) + +func cleanNetworksInNamespace(namespace string) { + ctx := context.Background() + EventuallyWithOffset(1, func(g Gomega) { + err := k8sClient.DeleteAllOf(ctx, &sriovnetworkv1.SriovNetwork{}, client.InNamespace(namespace)) + g.Expect(err).NotTo(HaveOccurred()) + + err = k8sClient.DeleteAllOf(ctx, &sriovnetworkv1.SriovIBNetwork{}, client.InNamespace(namespace)) + g.Expect(err).NotTo(HaveOccurred()) + + err = k8sClient.DeleteAllOf(ctx, &sriovnetworkv1.OVSNetwork{}, client.InNamespace(namespace)) + g.Expect(err).NotTo(HaveOccurred()) + + k8sClient.DeleteAllOf(ctx, &netattdefv1.NetworkAttachmentDefinition{}, client.InNamespace(namespace)) + g.Expect(err).NotTo(HaveOccurred()) + + sriovNetworks := &sriovnetworkv1.SriovNetworkList{} + err = k8sClient.List(ctx, sriovNetworks, client.InNamespace(namespace)) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(sriovNetworks.Items).To(BeEmpty()) + + sriovIBNetworks := &sriovnetworkv1.SriovIBNetworkList{} + err = k8sClient.List(ctx, sriovIBNetworks, client.InNamespace(namespace)) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(sriovIBNetworks.Items).To(BeEmpty()) + + ovsNetworks := &sriovnetworkv1.OVSNetworkList{} + err = k8sClient.List(ctx, ovsNetworks, client.InNamespace(namespace)) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(ovsNetworks.Items).To(BeEmpty()) + + netAttachDefs := &netattdefv1.NetworkAttachmentDefinitionList{} + err = k8sClient.List(ctx, netAttachDefs, client.InNamespace(namespace)) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(netAttachDefs.Items).To(BeEmpty()) + }).WithPolling(100 * time.Millisecond).WithTimeout(10 * time.Second).Should(Succeed()) +} diff --git a/controllers/sriovnetwork_controller_test.go b/controllers/sriovnetwork_controller_test.go index df146ccea5..191ca7438a 100644 --- a/controllers/sriovnetwork_controller_test.go +++ b/controllers/sriovnetwork_controller_test.go @@ -15,7 +15,6 @@ import ( "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/util/retry" - "sigs.k8s.io/controller-runtime/pkg/client" dynclient "sigs.k8s.io/controller-runtime/pkg/client" . "github.com/onsi/ginkgo/v2" @@ -475,24 +474,3 @@ func generateExpectedNetConfig(cr *sriovnetworkv1.SriovNetwork) string { } return configStr } - -func cleanNetworksInNamespace(namespace string) { - ctx := context.Background() - EventuallyWithOffset(1, func(g Gomega) { - err := k8sClient.DeleteAllOf(ctx, &sriovnetworkv1.SriovNetwork{}, client.InNamespace(namespace)) - g.Expect(err).NotTo(HaveOccurred()) - - k8sClient.DeleteAllOf(ctx, &netattdefv1.NetworkAttachmentDefinition{}, client.InNamespace(namespace)) - g.Expect(err).NotTo(HaveOccurred()) - - sriovNetworks := &sriovnetworkv1.SriovNetworkList{} - err = k8sClient.List(ctx, sriovNetworks, client.InNamespace(namespace)) - g.Expect(err).NotTo(HaveOccurred()) - g.Expect(sriovNetworks.Items).To(BeEmpty()) - - netAttachDefs := &netattdefv1.NetworkAttachmentDefinitionList{} - err = k8sClient.List(ctx, netAttachDefs, client.InNamespace(namespace)) - g.Expect(err).NotTo(HaveOccurred()) - g.Expect(netAttachDefs.Items).To(BeEmpty()) - }).WithPolling(100 * time.Millisecond).WithTimeout(10 * time.Second).Should(Succeed()) -} diff --git a/controllers/suite_test.go b/controllers/suite_test.go index e477142c8d..f278274fe9 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -31,8 +31,10 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" + "k8s.io/utils/ptr" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/config" "sigs.k8s.io/controller-runtime/pkg/envtest" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" @@ -67,6 +69,9 @@ func setupK8sManagerForTest() (manager.Manager, error) { k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{ Scheme: scheme.Scheme, Metrics: server.Options{BindAddress: "0"}, // we don't need metrics server for tests + Controller: config.Controller{ + SkipNameValidation: ptr.To(true), + }, }) if err != nil { diff --git a/pkg/consts/constants.go b/pkg/consts/constants.go index 3b444a34b6..06304fd317 100644 --- a/pkg/consts/constants.go +++ b/pkg/consts/constants.go @@ -97,6 +97,8 @@ const ( MCPPauseAnnotationState = "sriovnetwork.openshift.io/state" MCPPauseAnnotationTime = "sriovnetwork.openshift.io/time" + OwnerRefAnnotation = "sriovnetwork.openshift.io/owner-ref" + // NodeStateKeepUntilAnnotation contains name of the "keep until time" annotation for SriovNetworkNodeState object. // The "keep until time" specifies the earliest time at which the state object can be removed // if the daemon's pod is not found on the node.