From 036f57f3cb6e0b7c2335b54d2acb804378e1f776 Mon Sep 17 00:00:00 2001 From: Antonio Ojea Date: Mon, 2 Jan 2023 14:20:56 +0000 Subject: [PATCH] Add IPAddress API Change-Id: I9cf710f011b58409ab880d3b2e7f841f228ee5ee --- pkg/apis/networking/fuzzer/fuzzer.go | 32 +++++++++ pkg/apis/networking/install/install.go | 2 +- pkg/apis/networking/register.go | 2 + pkg/apis/networking/types.go | 53 +++++++++++++++ .../api/networking/v1alpha1/register.go | 12 +++- .../k8s.io/api/networking/v1alpha1/types.go | 66 +++++++++++++++++++ .../networking/v1alpha1/well_known_labels.go | 33 ++++++++++ 7 files changed, 196 insertions(+), 4 deletions(-) create mode 100644 staging/src/k8s.io/api/networking/v1alpha1/well_known_labels.go diff --git a/pkg/apis/networking/fuzzer/fuzzer.go b/pkg/apis/networking/fuzzer/fuzzer.go index 5406abdcccd..015739c1942 100644 --- a/pkg/apis/networking/fuzzer/fuzzer.go +++ b/pkg/apis/networking/fuzzer/fuzzer.go @@ -17,6 +17,8 @@ limitations under the License. package fuzzer import ( + "net/netip" + fuzz "github.com/google/gofuzz" runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/kubernetes/pkg/apis/networking" @@ -74,5 +76,35 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { } } }, + func(obj *networking.IPAddress, c fuzz.Continue) { + c.FuzzNoCustom(obj) // fuzz self without calling this function again + // length in bytes of the IP Family: IPv4: 4 bytes IPv6: 16 bytes + boolean := []bool{false, true} + is6 := boolean[c.Rand.Intn(2)] + ip := generateRandomIP(is6, c) + obj.Name = ip + }, } } + +func generateRandomIP(is6 bool, c fuzz.Continue) string { + n := 4 + if is6 { + n = 16 + } + bytes := make([]byte, n) + for i := 0; i < n; i++ { + bytes[i] = uint8(c.Rand.Intn(255)) + } + + ip, ok := netip.AddrFromSlice(bytes) + if ok { + return ip.String() + } + // this should not happen but is better to + // return a good IP address than nothing + if is6 { + return "2001:db8::1" + } + return "192.168.1.1" +} diff --git a/pkg/apis/networking/install/install.go b/pkg/apis/networking/install/install.go index c29708f2cb2..2f6abe9c0e8 100644 --- a/pkg/apis/networking/install/install.go +++ b/pkg/apis/networking/install/install.go @@ -23,7 +23,7 @@ import ( utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/networking" - "k8s.io/kubernetes/pkg/apis/networking/v1" + v1 "k8s.io/kubernetes/pkg/apis/networking/v1" "k8s.io/kubernetes/pkg/apis/networking/v1alpha1" "k8s.io/kubernetes/pkg/apis/networking/v1beta1" ) diff --git a/pkg/apis/networking/register.go b/pkg/apis/networking/register.go index 486bf834bfe..570a6a4db3b 100644 --- a/pkg/apis/networking/register.go +++ b/pkg/apis/networking/register.go @@ -54,6 +54,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &IngressClassList{}, &ClusterCIDR{}, &ClusterCIDRList{}, + &IPAddress{}, + &IPAddressList{}, ) return nil } diff --git a/pkg/apis/networking/types.go b/pkg/apis/networking/types.go index 864173b870b..6c9eaa7a484 100644 --- a/pkg/apis/networking/types.go +++ b/pkg/apis/networking/types.go @@ -18,6 +18,7 @@ package networking import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" api "k8s.io/kubernetes/pkg/apis/core" ) @@ -699,3 +700,55 @@ type ClusterCIDRList struct { // items is the list of ClusterCIDRs. Items []ClusterCIDR } + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// IPAddress represents a single IP of a single IP Family. The object is designed to be used by APIs +// that operate on IP addresses. The object is used by the Service core API for allocation of IP addresses. +// An IP address can be represented in different formats, to guarantee the uniqueness of the IP, +// the name of the object is the IP address in canonical format, four decimal digits separated +// by dots suppressing leading zeros for IPv4 and the representation defined by RFC 5952 for IPv6. +// Valid: 192.168.1.5 or 2001:db8::1 or 2001:db8:aaaa:bbbb:cccc:dddd:eeee:1 +// Invalid: 10.01.2.3 or 2001:db8:0:0:0::1 +type IPAddress struct { + metav1.TypeMeta + // +optional + metav1.ObjectMeta + // +optional + Spec IPAddressSpec +} + +// IPAddressSpec describe the attributes in an IP Address, +type IPAddressSpec struct { + // ParentRef references the resource that an IPAddress is attached to. + // An IPAddress must reference a parent object. + // +required + ParentRef *ParentReference +} +type ParentReference struct { + // Group is the group of the object being referenced. + Group string + // Resource is the resource of the object being referenced. + Resource string + // Namespace is the namespace of the object being referenced. + Namespace string + // Name is the name of the object being referenced. + Name string + // UID is the uid of the object being referenced. + // +optional + UID types.UID +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// IPAddressList contains a list of IPAddress. +type IPAddressList struct { + metav1.TypeMeta + // +optional + metav1.ListMeta + + // Items is the list of IPAddress + Items []IPAddress +} diff --git a/staging/src/k8s.io/api/networking/v1alpha1/register.go b/staging/src/k8s.io/api/networking/v1alpha1/register.go index 12c0cf7bd46..8dda6394d47 100644 --- a/staging/src/k8s.io/api/networking/v1alpha1/register.go +++ b/staging/src/k8s.io/api/networking/v1alpha1/register.go @@ -22,12 +22,17 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" ) -// GroupName is the group name use in this package. +// GroupName is the group name used in this package. const GroupName = "networking.k8s.io" -// SchemeGroupVersion is group version used to register these objects. +// SchemeGroupVersion is group version used to register objects in this package. var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} +// Kind takes an unqualified kind and returns a Group qualified GroupKind. +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + // Resource takes an unqualified resource and returns a Group qualified GroupResource. func Resource(resource string) schema.GroupResource { return SchemeGroupVersion.WithResource(resource).GroupResource() @@ -49,8 +54,9 @@ func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &ClusterCIDR{}, &ClusterCIDRList{}, + &IPAddress{}, + &IPAddressList{}, ) - // Add the watch version that applies. metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil } diff --git a/staging/src/k8s.io/api/networking/v1alpha1/types.go b/staging/src/k8s.io/api/networking/v1alpha1/types.go index 2a6e13a379d..52e4a11e8b1 100644 --- a/staging/src/k8s.io/api/networking/v1alpha1/types.go +++ b/staging/src/k8s.io/api/networking/v1alpha1/types.go @@ -19,6 +19,7 @@ package v1alpha1 import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" ) // +genclient @@ -95,3 +96,68 @@ type ClusterCIDRList struct { // items is the list of ClusterCIDRs. Items []ClusterCIDR `json:"items" protobuf:"bytes,2,rep,name=items"` } + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +k8s:prerelease-lifecycle-gen:introduced=1.27 + +// IPAddress represents a single IP of a single IP Family. The object is designed to be used by APIs +// that operate on IP addresses. The object is used by the Service core API for allocation of IP addresses. +// An IP address can be represented in different formats, to guarantee the uniqueness of the IP, +// the name of the object is the IP address in canonical format, four decimal digits separated +// by dots suppressing leading zeros for IPv4 and the representation defined by RFC 5952 for IPv6. +// Valid: 192.168.1.5 or 2001:db8::1 or 2001:db8:aaaa:bbbb:cccc:dddd:eeee:1 +// Invalid: 10.01.2.3 or 2001:db8:0:0:0::1 +type IPAddress struct { + metav1.TypeMeta `json:",inline"` + // Standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + // spec is the desired state of the IPAddress. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status + // +optional + Spec IPAddressSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"` +} + +// IPAddressSpec describe the attributes in an IP Address. +type IPAddressSpec struct { + // ParentRef references the resource that an IPAddress is attached to. + // An IPAddress must reference a parent object. + // +required + ParentRef *ParentReference `json:"parentRef,omitempty" protobuf:"bytes,1,opt,name=parentRef"` +} + +// ParentReference describes a reference to a parent object. +type ParentReference struct { + // Group is the group of the object being referenced. + // +optional + Group string `json:"group,omitempty" protobuf:"bytes,1,opt,name=group"` + // Resource is the resource of the object being referenced. + // +required + Resource string `json:"resource,omitempty" protobuf:"bytes,2,opt,name=resource"` + // Namespace is the namespace of the object being referenced. + // +optional + Namespace string `json:"namespace,omitempty" protobuf:"bytes,3,opt,name=namespace"` + // Name is the name of the object being referenced. + // +required + Name string `json:"name,omitempty" protobuf:"bytes,4,opt,name=name"` + // UID is the uid of the object being referenced. + // +optional + UID types.UID `json:"uid,omitempty" protobuf:"bytes,5,opt,name=uid,casttype=k8s.io/apimachinery/pkg/types.UID"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +k8s:prerelease-lifecycle-gen:introduced=1.27 + +// IPAddressList contains a list of IPAddress. +type IPAddressList struct { + metav1.TypeMeta `json:",inline"` + // Standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + // +optional + metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + // items is the list of IPAddresses. + Items []IPAddress `json:"items" protobuf:"bytes,2,rep,name=items"` +} diff --git a/staging/src/k8s.io/api/networking/v1alpha1/well_known_labels.go b/staging/src/k8s.io/api/networking/v1alpha1/well_known_labels.go new file mode 100644 index 00000000000..5f9c23f708c --- /dev/null +++ b/staging/src/k8s.io/api/networking/v1alpha1/well_known_labels.go @@ -0,0 +1,33 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +const ( + + // TODO: Use IPFamily as field with a field selector,And the value is set based on + // the name at create time and immutable. + // LabelIPAddressFamily is used to indicate the IP family of a Kubernetes IPAddress. + // This label simplify dual-stack client operations allowing to obtain the list of + // IP addresses filtered by family. + LabelIPAddressFamily = "ipaddress.kubernetes.io/ip-family" + // LabelManagedBy is used to indicate the controller or entity that manages + // an IPAddress. This label aims to enable different IPAddress + // objects to be managed by different controllers or entities within the + // same cluster. It is highly recommended to configure this label for all + // IPAddress objects. + LabelManagedBy = "ipaddress.kubernetes.io/managed-by" +)