From f634d35bfb3cee4337321935d578c78af7f5d6cf Mon Sep 17 00:00:00 2001 From: Ram Lavi Date: Sun, 4 Aug 2024 11:50:50 +0300 Subject: [PATCH] network/kubevirt-ipam-controller: Add new net-attach-def resource This resource does not belong to kubevirt-ipam-controller, but is currently piggy-backing this component in order to deploy the primary user-defined-network net-attach-def [0]. This net-attach-def is deployed on default namespace, as this way it will be available to all VMs that need to consume it. Note that for CI, KubevirtIpamController will not be able to deploy without Multus (that deploys the net-attach-def CRD) alongside it, or the net-attach-def deployment will fail, with error: `could not apply (k8s.cni.cncf.io/v1, Kind=NetworkAttachmentDefinition) default/primary-user-defined-network: could not retrieve existing (k8s.cni.cncf.io/v1, Kind=NetworkAttachmentDefinition) default/primary-user-defined-network: no matches for kind "NetworkAttachmentDefinition" in version "k8s.cni.cncf.io/v1"` [0] https://kubevirt.io/user-guide/network/network_binding_plugins/#deployment Signed-off-by: Ram Lavi --- .../004-primary-udn-networkattachdef.yaml | 16 +++++++ go.mod | 2 +- .../bump-kubevirt-ipam-controller.sh | 2 +- pkg/network/kubevirt_ipam_controller_test.go | 45 +++++++++++++++++++ test/check/check.go | 36 +++++++++++++++ test/check/components.go | 12 ++--- test/e2e/workflow/deployment_test.go | 3 +- test/env/env.go | 3 ++ 8 files changed, 111 insertions(+), 8 deletions(-) create mode 100644 data/kubevirt-ipam-controller/004-primary-udn-networkattachdef.yaml create mode 100644 pkg/network/kubevirt_ipam_controller_test.go diff --git a/data/kubevirt-ipam-controller/004-primary-udn-networkattachdef.yaml b/data/kubevirt-ipam-controller/004-primary-udn-networkattachdef.yaml new file mode 100644 index 000000000..0dcda5711 --- /dev/null +++ b/data/kubevirt-ipam-controller/004-primary-udn-networkattachdef.yaml @@ -0,0 +1,16 @@ +--- +apiVersion: "k8s.cni.cncf.io/v1" +kind: NetworkAttachmentDefinition +metadata: + name: primary-user-defined-network + namespace: default +spec: + config: '{ + "cniVersion": "1.0.0", + "name": "primary-user-defined-network", + "plugins": [ + { + "type": "cni-passt-binding-plugin" + } + ] +}' diff --git a/go.mod b/go.mod index 16aeec76d..9ba94b1bb 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/go-git/go-git/v5 v5.11.0 github.com/gobwas/glob v0.2.3 github.com/google/go-github/v32 v32.1.0 + github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.3.0 github.com/kubevirt/monitoring/pkg/metrics/parser v0.0.0-20231024120544-6a3ba1a680b4 github.com/machadovilaca/operator-observability v0.0.19-0.20240326121036-9f2e5a31675f github.com/onsi/ginkgo/v2 v2.11.0 @@ -144,7 +145,6 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.3.0 // indirect github.com/kevinburke/rest v0.0.0-20210506044642-5611499aa33c // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/klauspost/compress v1.16.0 // indirect diff --git a/hack/components/bump-kubevirt-ipam-controller.sh b/hack/components/bump-kubevirt-ipam-controller.sh index ebfac4b77..00d7bb1f8 100755 --- a/hack/components/bump-kubevirt-ipam-controller.sh +++ b/hack/components/bump-kubevirt-ipam-controller.sh @@ -148,7 +148,7 @@ echo 'Adjust kubevirt-ipam-controller to CNAO' echo 'Copy manifests' shopt -s extglob -rm -rf data/kubevirt-ipam-controller/!(002-rbac.yaml) +rm -rf data/kubevirt-ipam-controller/!(002-rbac.yaml|004-primary-udn-networkattachdef.yaml) # CRD crd_manifest="https://raw.githubusercontent.com/k8snetworkplumbingwg/ipamclaims/${IPAMCLAIMS_CRD_VERSION}/artifacts/k8s.cni.cncf.io_ipamclaims.yaml" diff --git a/pkg/network/kubevirt_ipam_controller_test.go b/pkg/network/kubevirt_ipam_controller_test.go new file mode 100644 index 000000000..3811b80a7 --- /dev/null +++ b/pkg/network/kubevirt_ipam_controller_test.go @@ -0,0 +1,45 @@ +package network + +import ( + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + osv1 "github.com/openshift/api/operator/v1" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + + cnao "github.com/kubevirt/cluster-network-addons-operator/pkg/apis/networkaddonsoperator/shared" +) + +var _ = Describe("Testing kubevirt ipam controller", func() { + Context("Render KubevirtIpamController", func() { + conf := &cnao.NetworkAddonsConfigSpec{ImagePullPolicy: v1.PullAlways, Multus: &cnao.Multus{}, KubevirtIpamController: &cnao.KubevirtIpamController{}, PlacementConfiguration: &cnao.PlacementConfiguration{Workloads: &cnao.Placement{}}} + manifestDir := "../../data" + openshiftNetworkConf := &osv1.Network{} + clusterInfo := &ClusterInfo{} + expectedGroupVersionKind := schema.GroupVersionKind{ + Group: "k8s.cni.cncf.io", + Version: "v1", + Kind: "NetworkAttachmentDefinition", + } + const expectedName = "primary-user-defined-network" + + It("should add the primary-udn network-attach-def obj", func() { + objs, err := Render(conf, manifestDir, openshiftNetworkConf, clusterInfo) + Expect(err).NotTo(HaveOccurred()) + Expect(objs).NotTo(BeEmpty()) + + Expect(objs).To(ContainElement( + SatisfyAll( + WithTransform(func(obj *unstructured.Unstructured) string { + return obj.GetName() + }, Equal(expectedName)), + WithTransform(func(obj *unstructured.Unstructured) schema.GroupVersionKind { + return obj.GetObjectKind().GroupVersionKind() + }, Equal(expectedGroupVersionKind)), + ), + )) + }) + }) +}) diff --git a/test/check/check.go b/test/check/check.go index e47f3ab60..e6e971c2c 100644 --- a/test/check/check.go +++ b/test/check/check.go @@ -13,6 +13,7 @@ import ( . "github.com/onsi/gomega" monitoringv1 "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1" + k8snetworkplumbingwgv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" testenv "github.com/kubevirt/cluster-network-addons-operator/test/env" conditionsv1 "github.com/openshift/custom-resource-status/conditions/v1" securityapi "github.com/openshift/origin/pkg/security/apis/security" @@ -346,6 +347,10 @@ func checkForComponent(component *Component) error { errsAppend(checkForPrometheusRule(component.PrometheusRule)) } + if component.NetworkAttachmentDefinition != "" { + errsAppend(checkForNetworkAttachmentDefinition(component.NetworkAttachmentDefinition)) + } + return errsToErr(errs) } @@ -389,6 +394,10 @@ func checkForComponentRemoval(component *Component) error { errsAppend(checkForPrometheusRuleRemoval(component.PrometheusRule)) } + if component.NetworkAttachmentDefinition != "" { + errsAppend(checkForNetworkAttachmentDefinitionRemoval(component.NetworkAttachmentDefinition)) + } + return errsToErr(errs) } @@ -649,6 +658,21 @@ func checkForPrometheusRule(name string) error { return nil } +func checkForNetworkAttachmentDefinition(name string) error { + networkAttachmentDefinition := k8snetworkplumbingwgv1.NetworkAttachmentDefinition{} + err := testenv.Client.Get(context.Background(), types.NamespacedName{Name: name, Namespace: corev1.NamespaceDefault}, &networkAttachmentDefinition) + if err != nil { + return err + } + + err = checkRelationshipLabels(networkAttachmentDefinition.GetLabels(), "NetworkAttachmentDefinition", name) + if err != nil { + return err + } + + return nil +} + func checkRelationshipLabels(labels map[string]string, kind, name string) error { expectedValues := map[string]string{ names.COMPONENT_LABEL_KEY: names.COMPONENT_LABEL_DEFAULT_VALUE, @@ -708,6 +732,14 @@ func checkForPrometheusRuleRemoval(name string) error { return isNotFound("PrometheusRule", name, err) } +func checkForNetworkAttachmentDefinitionRemoval(name string) error { + err := testenv.Client.Get(context.Background(), types.NamespacedName{Name: name, Namespace: corev1.NamespaceDefault}, &k8snetworkplumbingwgv1.NetworkAttachmentDefinition{}) + if isKindNotFound(err) { + return nil + } + return isNotFound("NetworkAttachmentDefinition", name, err) +} + func getMonitoringEndpoint() (*corev1.Endpoints, error) { By("Finding CNAO prometheus endpoint") endpoint := &corev1.Endpoints{} @@ -812,6 +844,10 @@ func isNotSupportedKind(err error) bool { return strings.Contains(err.Error(), "no kind is registered for the type") } +func isKindNotFound(err error) bool { + return strings.Contains(err.Error(), "no matches for kind") +} + func configToYaml(gvk schema.GroupVersionKind) string { config := GetConfig(gvk) manifest, err := yaml.Marshal(config) diff --git a/test/check/components.go b/test/check/components.go index ebd5ee0fd..a87986cb2 100644 --- a/test/check/components.go +++ b/test/check/components.go @@ -20,6 +20,7 @@ type Component struct { Service string ServiceMonitor string PrometheusRule string + NetworkAttachmentDefinition string } var ( @@ -87,11 +88,12 @@ var ( Deployments: []string{"secondary-dns"}, } KubevirtIpamController = Component{ - ComponentName: "KubevirtIpamController", - ClusterRole: "kubevirt-ipam-controller-manager-role", - ClusterRoleBinding: "kubevirt-ipam-controller-manager-rolebinding", - Deployments: []string{"kubevirt-ipam-controller-manager"}, - DaemonSets: []string{"passt-binding-cni"}, + ComponentName: "KubevirtIpamController", + ClusterRole: "kubevirt-ipam-controller-manager-role", + ClusterRoleBinding: "kubevirt-ipam-controller-manager-rolebinding", + Deployments: []string{"kubevirt-ipam-controller-manager"}, + DaemonSets: []string{"passt-binding-cni"}, + NetworkAttachmentDefinition: "primary-user-defined-network", } AllComponents = []Component{ KubeMacPoolComponent, diff --git a/test/e2e/workflow/deployment_test.go b/test/e2e/workflow/deployment_test.go index afeb14e8d..9dda94803 100644 --- a/test/e2e/workflow/deployment_test.go +++ b/test/e2e/workflow/deployment_test.go @@ -91,9 +91,10 @@ var _ = Describe("NetworkAddonsConfig", func() { Entry( KubevirtIpamController.ComponentName, cnao.NetworkAddonsConfigSpec{ + Multus: &cnao.Multus{}, KubevirtIpamController: &cnao.KubevirtIpamController{}, }, - []Component{KubevirtIpamController}, + []Component{MultusComponent, KubevirtIpamController}, ), ) It("should deploy prometheus if NetworkAddonsConfigSpec is not empty", func() { diff --git a/test/env/env.go b/test/env/env.go index b72bb3362..babae5d03 100644 --- a/test/env/env.go +++ b/test/env/env.go @@ -1,6 +1,7 @@ package env import ( + k8snetworkplumbingwgv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" . "github.com/onsi/gomega" monitoringv1 "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1" @@ -39,6 +40,8 @@ func Start() { ExpectWithOffset(1, err).NotTo(HaveOccurred()) err = monitoringv1.AddToScheme(scheme.Scheme) ExpectWithOffset(1, err).NotTo(HaveOccurred()) + err = k8snetworkplumbingwgv1.AddToScheme(scheme.Scheme) + ExpectWithOffset(1, err).NotTo(HaveOccurred()) // +kubebuilder:scaffold:scheme