From a8f6d77c8da6c5df574048884a54198314cee0ae Mon Sep 17 00:00:00 2001 From: Antonio Ojea Date: Tue, 15 Apr 2025 14:52:14 +0000 Subject: [PATCH] ServiceCIDR and IPAddess Conformance Change-Id: I6ee188cc8c163c312f8a8da9f1277d83e1ea634c --- test/conformance/testdata/conformance.yaml | 21 ++ .../testdata/ineligible_endpoints.yaml | 21 ++ test/e2e/network/service_cidrs.go | 196 ++++++++++++++++++ 3 files changed, 238 insertions(+) diff --git a/test/conformance/testdata/conformance.yaml b/test/conformance/testdata/conformance.yaml index 1514663af86..9550d7d9825 100755 --- a/test/conformance/testdata/conformance.yaml +++ b/test/conformance/testdata/conformance.yaml @@ -1861,6 +1861,27 @@ and 50s for the 90th percentile. release: v1.9 file: test/e2e/network/service_latency.go +- testname: IPAddress API + codename: '[sig-network] ServiceCIDR and IPAddress API should support IPAddress + API operations [Conformance]' + description: ' The networking.k8s.io API group MUST exist in the /apis discovery + document. The networking.k8s.io/v1 API group/version MUST exist in the /apis/networking.k8s.io + discovery document. The ipaddresses resources MUST exist in the /apis/networking.k8s.io/v1 + discovery document. The ipaddresses resource must support create, get, list, watch, + update, patch, delete, and deletecollection.' + release: v1.34 + file: test/e2e/network/service_cidrs.go +- testname: ServiceCIDR API + codename: '[sig-network] ServiceCIDR and IPAddress API should support ServiceCIDR + API operations [Conformance]' + description: ' The networking.k8s.io API group MUST exist in the /apis discovery + document. The networking.k8s.io/v1 API group/version MUST exist in the /apis/networking.k8s.io + discovery document. The servicecidrs resources MUST exist in the /apis/networking.k8s.io/v1 + discovery document. The servicecidrs resource must support create, get, list, + watch, update, patch, delete, and deletecollection. The servicecidrs/status resource + must support update and patch' + release: v1.34 + file: test/e2e/network/service_cidrs.go - testname: Service, change type, ClusterIP to ExternalName codename: '[sig-network] Services should be able to change the type from ClusterIP to ExternalName [Conformance]' diff --git a/test/conformance/testdata/ineligible_endpoints.yaml b/test/conformance/testdata/ineligible_endpoints.yaml index 4e53ed81741..20b3cd3e6e5 100644 --- a/test/conformance/testdata/ineligible_endpoints.yaml +++ b/test/conformance/testdata/ineligible_endpoints.yaml @@ -274,3 +274,24 @@ - endpoint: getStoragemigrationAPIGroup reason: The endpoint is part of a group that has no stable endpoints yet, reporting as a stable endpoint in apisnoop. link: https://github.com/kubernetes/issues/124248 +- endpoint: createNetworkingV1ServiceCIDR + reason: Kubernetes distribution would reasonably not allow this action via the API + link: https://github.com/kubernetes/enhancements/pull/4983#issuecomment-2541699445 +- endpoint: deleteNetworkingV1CollectionServiceCIDR + reason: Kubernetes distribution would reasonably not allow this action via the API + link: https://github.com/kubernetes/enhancements/pull/4983#issuecomment-2541699445 +- endpoint: deleteNetworkingV1ServiceCIDR + reason: Kubernetes distribution would reasonably not allow this action via the API + link: https://github.com/kubernetes/enhancements/pull/4983#issuecomment-2541699445 +- endpoint: patchNetworkingV1ServiceCIDR + reason: Kubernetes distribution would reasonably not allow this action via the API + link: https://github.com/kubernetes/enhancements/pull/4983#issuecomment-2541699445 +- endpoint: patchNetworkingV1ServiceCIDRStatus + reason: Kubernetes distribution would reasonably not allow this action via the API + link: https://github.com/kubernetes/enhancements/pull/4983#issuecomment-2541699445 +- endpoint: replaceNetworkingV1ServiceCIDR + reason: Kubernetes distribution would reasonably not allow this action via the API + link: https://github.com/kubernetes/enhancements/pull/4983#issuecomment-2541699445 +- endpoint: replaceNetworkingV1ServiceCIDRStatus + reason: Kubernetes distribution would reasonably not allow this action via the API + link: https://github.com/kubernetes/enhancements/pull/4983#issuecomment-2541699445 diff --git a/test/e2e/network/service_cidrs.go b/test/e2e/network/service_cidrs.go index 198c678db80..b1b63ba6924 100644 --- a/test/e2e/network/service_cidrs.go +++ b/test/e2e/network/service_cidrs.go @@ -24,9 +24,12 @@ import ( v1 "k8s.io/api/core/v1" networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/util/retry" + "k8s.io/kubernetes/pkg/controlplane/controller/defaultservicecidr" "k8s.io/kubernetes/test/e2e/framework" e2enode "k8s.io/kubernetes/test/e2e/framework/node" e2epod "k8s.io/kubernetes/test/e2e/framework/pod" @@ -142,3 +145,196 @@ func isReady(serviceCIDR *networkingv1.ServiceCIDR) bool { } return false } + +var _ = common.SIGDescribe("ServiceCIDR and IPAddress API", func() { + f := framework.NewDefaultFramework("servicecidr") + f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged + /* + Release: v1.34 + Testname: ServiceCIDR API + Description: + The networking.k8s.io API group MUST exist in the /apis discovery document. + The networking.k8s.io/v1 API group/version MUST exist in the /apis/networking.k8s.io discovery document. + The servicecidrs resources MUST exist in the /apis/networking.k8s.io/v1 discovery document. + The servicecidrs resource must support create, get, list, watch, update, patch, delete, and deletecollection. + The servicecidrs/status resource must support update and patch + */ + + framework.ConformanceIt("should support ServiceCIDR API operations", func(ctx context.Context) { + ginkgo.By("getting") + _, err := f.ClientSet.NetworkingV1().ServiceCIDRs().Get(ctx, defaultservicecidr.DefaultServiceCIDRName, metav1.GetOptions{}) + if err != nil { + framework.Failf("unexpected error getting default ServiceCIDR: %v", err) + } + + ginkgo.By("patching") + patchedServiceCIDR, err := f.ClientSet.NetworkingV1().ServiceCIDRs().Patch(ctx, defaultservicecidr.DefaultServiceCIDRName, types.MergePatchType, []byte(`{"metadata":{"annotations":{"patched":"true"}}}`), metav1.PatchOptions{}) + if err != nil { + framework.Failf("unexpected error patching IPAddress: %v", err) + } + if v, ok := patchedServiceCIDR.Annotations["patched"]; !ok || v != "true" { + framework.Failf("patched object should have the applied annotation") + } + + ginkgo.By("updating") + var cidrToUpdate, updatedCIDR *networkingv1.ServiceCIDR + err = retry.RetryOnConflict(retry.DefaultRetry, func() error { + cidrToUpdate, err = f.ClientSet.NetworkingV1().ServiceCIDRs().Get(ctx, defaultservicecidr.DefaultServiceCIDRName, metav1.GetOptions{}) + if err != nil { + return err + } + cidrToUpdate.Annotations["updated"] = "true" + updatedCIDR, err = f.ClientSet.NetworkingV1().ServiceCIDRs().Update(ctx, cidrToUpdate, metav1.UpdateOptions{}) + return err + }) + if err != nil { + framework.Failf("unexpected error updating IPAddress: %v", err) + } + if v, ok := updatedCIDR.Annotations["updated"]; !ok || v != "true" { + framework.Failf("updated object should have the applied annotation") + } + + ginkgo.By("listing") + list, err := f.ClientSet.NetworkingV1().ServiceCIDRs().List(ctx, metav1.ListOptions{}) + if err != nil { + framework.Failf("unexpected error listing ServiceCIDR: %v", err) + } + if len(list.Items) == 0 { + framework.Failf("expected at list one, the default, ServiceCIDR") + } + + ginkgo.By("watching") + _, err = f.ClientSet.NetworkingV1().ServiceCIDRs().Watch(ctx, metav1.ListOptions{}) + if err != nil { + framework.Failf("unexpected error watching ServiceCIDR: %v", err) + } + + }) + + /* + Release: v1.34 + Testname: IPAddress API + Description: + The networking.k8s.io API group MUST exist in the /apis discovery document. + The networking.k8s.io/v1 API group/version MUST exist in the /apis/networking.k8s.io discovery document. + The ipaddresses resources MUST exist in the /apis/networking.k8s.io/v1 discovery document. + The ipaddresses resource must support create, get, list, watch, update, patch, delete, and deletecollection. + */ + framework.ConformanceIt("should support IPAddress API operations", func(ctx context.Context) { + ip := &networkingv1.IPAddress{ + ObjectMeta: metav1.ObjectMeta{ + Name: "255.255.255.255", + Labels: map[string]string{ + "type": "broadcast", + }, + }, + Spec: networkingv1.IPAddressSpec{ + ParentRef: &networkingv1.ParentReference{ + Group: "mygroup", + Resource: "myresources", + Namespace: "foo", + Name: "bar", + }, + }, + } + + ipv6 := &networkingv1.IPAddress{ + ObjectMeta: metav1.ObjectMeta{ + Name: "fe80::42:1dff:fe84:f9e2", + Labels: map[string]string{ + "type": "link-local", + }, + }, + Spec: networkingv1.IPAddressSpec{ + ParentRef: &networkingv1.ParentReference{ + Group: "mygroup", + Resource: "myresources", + Namespace: "foo", + Name: "bar", + }, + }, + } + + ginkgo.By("creating") + _, err := f.ClientSet.NetworkingV1().IPAddresses().Create(ctx, ip, metav1.CreateOptions{}) + if err != nil { + framework.Failf("unexpected error getting IPAddress: %v", err) + } + _, err = f.ClientSet.NetworkingV1().IPAddresses().Create(ctx, ipv6, metav1.CreateOptions{}) + if err != nil { + framework.Failf("unexpected error getting IPAddress: %v", err) + } + + ginkgo.By("patching") + patchedIP, err := f.ClientSet.NetworkingV1().IPAddresses().Patch(ctx, ip.Name, types.MergePatchType, []byte(`{"metadata":{"annotations":{"patched":"true"}}}`), metav1.PatchOptions{}) + if err != nil { + framework.Failf("unexpected error patching IPAddress: %v", err) + } + if v, ok := patchedIP.Annotations["patched"]; !ok || v != "true" { + framework.Failf("patched object should have the applied annotation") + } + + ginkgo.By("updating") + var ipToUpdate, updatedIP *networkingv1.IPAddress + err = retry.RetryOnConflict(retry.DefaultRetry, func() error { + ipToUpdate, err = f.ClientSet.NetworkingV1().IPAddresses().Get(ctx, ip.Name, metav1.GetOptions{}) + if err != nil { + return err + } + ipToUpdate.Annotations["updated"] = "true" + updatedIP, err = f.ClientSet.NetworkingV1().IPAddresses().Update(ctx, ipToUpdate, metav1.UpdateOptions{}) + return err + }) + if err != nil { + framework.Failf("unexpected error updating IPAddress: %v", err) + } + if v, ok := updatedIP.Annotations["updated"]; !ok || v != "true" { + framework.Failf("updated object should have the applied annotation") + } + + ginkgo.By("getting") + _, err = f.ClientSet.NetworkingV1().IPAddresses().Get(ctx, ip.Name, metav1.GetOptions{}) + if err != nil { + framework.Failf("unexpected error getting IPAddress: %v", err) + } + + ginkgo.By("listing") + list, err := f.ClientSet.NetworkingV1().IPAddresses().List(ctx, metav1.ListOptions{ + LabelSelector: "type=broadcast", + }) + if err != nil { + framework.Failf("unexpected error listing IPAddress: %v", err) + } + if len(list.Items) != 1 { + framework.Failf("expected one IPAddress") + } + + ginkgo.By("watching") + _, err = f.ClientSet.NetworkingV1().IPAddresses().Watch(ctx, metav1.ListOptions{ + LabelSelector: "type=broadcast", + }) + if err != nil { + framework.Failf("unexpected error watching IPAddress: %v", err) + } + ginkgo.By("deleting") + err = f.ClientSet.NetworkingV1().IPAddresses().Delete(ctx, ip.Name, metav1.DeleteOptions{}) + if err != nil { + framework.Failf("unexpected error deleting IPAddress: %v", err) + } + + ginkgo.By("deleting a collection") + err = f.ClientSet.NetworkingV1().IPAddresses().DeleteCollection(ctx, metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: "type=link-local"}) + if err != nil { + framework.Failf("unexpected error deleting IPAddress Collection: %v", err) + } + list, err = f.ClientSet.NetworkingV1().IPAddresses().List(ctx, metav1.ListOptions{ + LabelSelector: "type=link-local", + }) + if err != nil { + framework.Failf("unexpected error listing IPAddress: %v", err) + } + if len(list.Items) > 0 { + framework.Failf("expected 0 IPAddresses") + } + }) +})