@@ -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"
|
||||
}
|
||||
|
@@ -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"
|
||||
)
|
||||
|
@@ -54,6 +54,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
&IngressClassList{},
|
||||
&ClusterCIDR{},
|
||||
&ClusterCIDRList{},
|
||||
&IPAddress{},
|
||||
&IPAddressList{},
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
@@ -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
|
||||
}
|
||||
|
137
pkg/apis/networking/v1alpha1/zz_generated.conversion.go
generated
137
pkg/apis/networking/v1alpha1/zz_generated.conversion.go
generated
@@ -28,6 +28,7 @@ import (
|
||||
v1alpha1 "k8s.io/api/networking/v1alpha1"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
core "k8s.io/kubernetes/pkg/apis/core"
|
||||
networking "k8s.io/kubernetes/pkg/apis/networking"
|
||||
)
|
||||
@@ -69,6 +70,46 @@ func RegisterConversions(s *runtime.Scheme) error {
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*v1alpha1.IPAddress)(nil), (*networking.IPAddress)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_IPAddress_To_networking_IPAddress(a.(*v1alpha1.IPAddress), b.(*networking.IPAddress), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*networking.IPAddress)(nil), (*v1alpha1.IPAddress)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_networking_IPAddress_To_v1alpha1_IPAddress(a.(*networking.IPAddress), b.(*v1alpha1.IPAddress), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*v1alpha1.IPAddressList)(nil), (*networking.IPAddressList)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_IPAddressList_To_networking_IPAddressList(a.(*v1alpha1.IPAddressList), b.(*networking.IPAddressList), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*networking.IPAddressList)(nil), (*v1alpha1.IPAddressList)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_networking_IPAddressList_To_v1alpha1_IPAddressList(a.(*networking.IPAddressList), b.(*v1alpha1.IPAddressList), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*v1alpha1.IPAddressSpec)(nil), (*networking.IPAddressSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_IPAddressSpec_To_networking_IPAddressSpec(a.(*v1alpha1.IPAddressSpec), b.(*networking.IPAddressSpec), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*networking.IPAddressSpec)(nil), (*v1alpha1.IPAddressSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_networking_IPAddressSpec_To_v1alpha1_IPAddressSpec(a.(*networking.IPAddressSpec), b.(*v1alpha1.IPAddressSpec), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*v1alpha1.ParentReference)(nil), (*networking.ParentReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_ParentReference_To_networking_ParentReference(a.(*v1alpha1.ParentReference), b.(*networking.ParentReference), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*networking.ParentReference)(nil), (*v1alpha1.ParentReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_networking_ParentReference_To_v1alpha1_ParentReference(a.(*networking.ParentReference), b.(*v1alpha1.ParentReference), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -145,3 +186,99 @@ func autoConvert_networking_ClusterCIDRSpec_To_v1alpha1_ClusterCIDRSpec(in *netw
|
||||
func Convert_networking_ClusterCIDRSpec_To_v1alpha1_ClusterCIDRSpec(in *networking.ClusterCIDRSpec, out *v1alpha1.ClusterCIDRSpec, s conversion.Scope) error {
|
||||
return autoConvert_networking_ClusterCIDRSpec_To_v1alpha1_ClusterCIDRSpec(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_IPAddress_To_networking_IPAddress(in *v1alpha1.IPAddress, out *networking.IPAddress, s conversion.Scope) error {
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
if err := Convert_v1alpha1_IPAddressSpec_To_networking_IPAddressSpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_IPAddress_To_networking_IPAddress is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_IPAddress_To_networking_IPAddress(in *v1alpha1.IPAddress, out *networking.IPAddress, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_IPAddress_To_networking_IPAddress(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_networking_IPAddress_To_v1alpha1_IPAddress(in *networking.IPAddress, out *v1alpha1.IPAddress, s conversion.Scope) error {
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
if err := Convert_networking_IPAddressSpec_To_v1alpha1_IPAddressSpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_networking_IPAddress_To_v1alpha1_IPAddress is an autogenerated conversion function.
|
||||
func Convert_networking_IPAddress_To_v1alpha1_IPAddress(in *networking.IPAddress, out *v1alpha1.IPAddress, s conversion.Scope) error {
|
||||
return autoConvert_networking_IPAddress_To_v1alpha1_IPAddress(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_IPAddressList_To_networking_IPAddressList(in *v1alpha1.IPAddressList, out *networking.IPAddressList, s conversion.Scope) error {
|
||||
out.ListMeta = in.ListMeta
|
||||
out.Items = *(*[]networking.IPAddress)(unsafe.Pointer(&in.Items))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_IPAddressList_To_networking_IPAddressList is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_IPAddressList_To_networking_IPAddressList(in *v1alpha1.IPAddressList, out *networking.IPAddressList, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_IPAddressList_To_networking_IPAddressList(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_networking_IPAddressList_To_v1alpha1_IPAddressList(in *networking.IPAddressList, out *v1alpha1.IPAddressList, s conversion.Scope) error {
|
||||
out.ListMeta = in.ListMeta
|
||||
out.Items = *(*[]v1alpha1.IPAddress)(unsafe.Pointer(&in.Items))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_networking_IPAddressList_To_v1alpha1_IPAddressList is an autogenerated conversion function.
|
||||
func Convert_networking_IPAddressList_To_v1alpha1_IPAddressList(in *networking.IPAddressList, out *v1alpha1.IPAddressList, s conversion.Scope) error {
|
||||
return autoConvert_networking_IPAddressList_To_v1alpha1_IPAddressList(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_IPAddressSpec_To_networking_IPAddressSpec(in *v1alpha1.IPAddressSpec, out *networking.IPAddressSpec, s conversion.Scope) error {
|
||||
out.ParentRef = (*networking.ParentReference)(unsafe.Pointer(in.ParentRef))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_IPAddressSpec_To_networking_IPAddressSpec is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_IPAddressSpec_To_networking_IPAddressSpec(in *v1alpha1.IPAddressSpec, out *networking.IPAddressSpec, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_IPAddressSpec_To_networking_IPAddressSpec(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_networking_IPAddressSpec_To_v1alpha1_IPAddressSpec(in *networking.IPAddressSpec, out *v1alpha1.IPAddressSpec, s conversion.Scope) error {
|
||||
out.ParentRef = (*v1alpha1.ParentReference)(unsafe.Pointer(in.ParentRef))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_networking_IPAddressSpec_To_v1alpha1_IPAddressSpec is an autogenerated conversion function.
|
||||
func Convert_networking_IPAddressSpec_To_v1alpha1_IPAddressSpec(in *networking.IPAddressSpec, out *v1alpha1.IPAddressSpec, s conversion.Scope) error {
|
||||
return autoConvert_networking_IPAddressSpec_To_v1alpha1_IPAddressSpec(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_ParentReference_To_networking_ParentReference(in *v1alpha1.ParentReference, out *networking.ParentReference, s conversion.Scope) error {
|
||||
out.Group = in.Group
|
||||
out.Resource = in.Resource
|
||||
out.Namespace = in.Namespace
|
||||
out.Name = in.Name
|
||||
out.UID = types.UID(in.UID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_ParentReference_To_networking_ParentReference is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_ParentReference_To_networking_ParentReference(in *v1alpha1.ParentReference, out *networking.ParentReference, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_ParentReference_To_networking_ParentReference(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_networking_ParentReference_To_v1alpha1_ParentReference(in *networking.ParentReference, out *v1alpha1.ParentReference, s conversion.Scope) error {
|
||||
out.Group = in.Group
|
||||
out.Resource = in.Resource
|
||||
out.Namespace = in.Namespace
|
||||
out.Name = in.Name
|
||||
out.UID = types.UID(in.UID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_networking_ParentReference_To_v1alpha1_ParentReference is an autogenerated conversion function.
|
||||
func Convert_networking_ParentReference_To_v1alpha1_ParentReference(in *networking.ParentReference, out *v1alpha1.ParentReference, s conversion.Scope) error {
|
||||
return autoConvert_networking_ParentReference_To_v1alpha1_ParentReference(in, out, s)
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@ package validation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"strings"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
@@ -741,3 +742,77 @@ func validateClusterCIDRUpdateSpec(update, old *networking.ClusterCIDRSpec, fldP
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateIPAddressName validates that the name is the decimal representation of an IP address.
|
||||
// IPAddress does not support generating names, prefix is not considered.
|
||||
func ValidateIPAddressName(name string, prefix bool) []string {
|
||||
var errs []string
|
||||
ip, err := netip.ParseAddr(name)
|
||||
if err != nil {
|
||||
errs = append(errs, err.Error())
|
||||
} else if ip.String() != name {
|
||||
errs = append(errs, "not a valid ip in canonical format")
|
||||
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
func ValidateIPAddress(ipAddress *networking.IPAddress) field.ErrorList {
|
||||
allErrs := apivalidation.ValidateObjectMeta(&ipAddress.ObjectMeta, false, ValidateIPAddressName, field.NewPath("metadata"))
|
||||
errs := validateIPAddressParentReference(ipAddress.Spec.ParentRef, field.NewPath("spec"))
|
||||
allErrs = append(allErrs, errs...)
|
||||
return allErrs
|
||||
|
||||
}
|
||||
|
||||
// validateIPAddressParentReference ensures that the IPAddress ParenteReference exists and is valid.
|
||||
func validateIPAddressParentReference(params *networking.ParentReference, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if params == nil {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("parentRef"), ""))
|
||||
return allErrs
|
||||
}
|
||||
|
||||
fldPath = fldPath.Child("parentRef")
|
||||
// group is required but the Core group used by Services is the empty value, so it can not be enforced
|
||||
if params.Group != "" {
|
||||
for _, msg := range validation.IsDNS1123Subdomain(params.Group) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("group"), params.Group, msg))
|
||||
}
|
||||
}
|
||||
|
||||
// resource is required
|
||||
if params.Resource == "" {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("resource"), ""))
|
||||
} else {
|
||||
for _, msg := range pathvalidation.IsValidPathSegmentName(params.Resource) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("resource"), params.Resource, msg))
|
||||
}
|
||||
}
|
||||
|
||||
// name is required
|
||||
if params.Name == "" {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("name"), ""))
|
||||
} else {
|
||||
for _, msg := range pathvalidation.IsValidPathSegmentName(params.Name) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), params.Name, msg))
|
||||
}
|
||||
}
|
||||
|
||||
// namespace is optional
|
||||
if params.Namespace != "" {
|
||||
for _, msg := range pathvalidation.IsValidPathSegmentName(params.Namespace) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("namespace"), params.Namespace, msg))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateIPAddressUpdate tests if an update to an IPAddress is valid.
|
||||
func ValidateIPAddressUpdate(update, old *networking.IPAddress) field.ErrorList {
|
||||
var allErrs field.ErrorList
|
||||
allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&update.ObjectMeta, &old.ObjectMeta, field.NewPath("metadata"))...)
|
||||
allErrs = append(allErrs, apivalidation.ValidateImmutableField(update.Spec.ParentRef, old.Spec.ParentRef, field.NewPath("spec").Child("parentRef"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
@@ -2195,3 +2195,215 @@ func TestValidateClusterConfigUpdate(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateIPAddress(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
expectedErrors int
|
||||
ipAddress *networking.IPAddress
|
||||
}{
|
||||
"empty-ipaddress-bad-name": {
|
||||
expectedErrors: 1,
|
||||
ipAddress: &networking.IPAddress{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-name",
|
||||
},
|
||||
Spec: networking.IPAddressSpec{
|
||||
ParentRef: &networking.ParentReference{
|
||||
Group: "",
|
||||
Resource: "services",
|
||||
Name: "foo",
|
||||
Namespace: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"empty-ipaddress-bad-name-no-parent-reference": {
|
||||
expectedErrors: 2,
|
||||
ipAddress: &networking.IPAddress{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-name",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
"good-ipaddress": {
|
||||
expectedErrors: 0,
|
||||
ipAddress: &networking.IPAddress{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "192.168.1.1",
|
||||
},
|
||||
Spec: networking.IPAddressSpec{
|
||||
ParentRef: &networking.ParentReference{
|
||||
Group: "",
|
||||
Resource: "services",
|
||||
Name: "foo",
|
||||
Namespace: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"good-ipaddress-gateway": {
|
||||
expectedErrors: 0,
|
||||
ipAddress: &networking.IPAddress{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "192.168.1.1",
|
||||
},
|
||||
Spec: networking.IPAddressSpec{
|
||||
ParentRef: &networking.ParentReference{
|
||||
Group: "gateway.networking.k8s.io",
|
||||
Resource: "gateway",
|
||||
Name: "foo",
|
||||
Namespace: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"good-ipv6address": {
|
||||
expectedErrors: 0,
|
||||
ipAddress: &networking.IPAddress{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "2001:4860:4860::8888",
|
||||
},
|
||||
Spec: networking.IPAddressSpec{
|
||||
ParentRef: &networking.ParentReference{
|
||||
Group: "",
|
||||
Resource: "services",
|
||||
Name: "foo",
|
||||
Namespace: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"non-canonica-ipv6address": {
|
||||
expectedErrors: 1,
|
||||
ipAddress: &networking.IPAddress{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "2001:4860:4860:0::8888",
|
||||
},
|
||||
Spec: networking.IPAddressSpec{
|
||||
ParentRef: &networking.ParentReference{
|
||||
Group: "",
|
||||
Resource: "services",
|
||||
Name: "foo",
|
||||
Namespace: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"missing-ipaddress-reference": {
|
||||
expectedErrors: 1,
|
||||
ipAddress: &networking.IPAddress{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "192.168.1.1",
|
||||
},
|
||||
},
|
||||
},
|
||||
"wrong-ipaddress-reference": {
|
||||
expectedErrors: 1,
|
||||
ipAddress: &networking.IPAddress{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "192.168.1.1",
|
||||
},
|
||||
Spec: networking.IPAddressSpec{
|
||||
ParentRef: &networking.ParentReference{
|
||||
Group: "custom.resource.com",
|
||||
Resource: "services",
|
||||
Name: "foo$%&",
|
||||
Namespace: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"wrong-ipaddress-reference-multiple-errors": {
|
||||
expectedErrors: 4,
|
||||
ipAddress: &networking.IPAddress{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "192.168.1.1",
|
||||
},
|
||||
Spec: networking.IPAddressSpec{
|
||||
ParentRef: &networking.ParentReference{
|
||||
Group: ".cust@m.resource.com",
|
||||
Resource: "",
|
||||
Name: "",
|
||||
Namespace: "bar$$$$$%@",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, testCase := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
errs := ValidateIPAddress(testCase.ipAddress)
|
||||
if len(errs) != testCase.expectedErrors {
|
||||
t.Errorf("Expected %d errors, got %d errors: %v", testCase.expectedErrors, len(errs), errs)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateIPAddressUpdate(t *testing.T) {
|
||||
old := &networking.IPAddress{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "192.168.1.1",
|
||||
ResourceVersion: "1",
|
||||
},
|
||||
Spec: networking.IPAddressSpec{
|
||||
ParentRef: &networking.ParentReference{
|
||||
Group: "custom.resource.com",
|
||||
Resource: "services",
|
||||
Name: "foo",
|
||||
Namespace: "bar",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
new func(svc *networking.IPAddress) *networking.IPAddress
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
name: "Successful update, no changes",
|
||||
new: func(old *networking.IPAddress) *networking.IPAddress {
|
||||
out := old.DeepCopy()
|
||||
return out
|
||||
},
|
||||
expectErr: false,
|
||||
},
|
||||
|
||||
{
|
||||
name: "Failed update, update spec.ParentRef",
|
||||
new: func(svc *networking.IPAddress) *networking.IPAddress {
|
||||
out := svc.DeepCopy()
|
||||
out.Spec.ParentRef = &networking.ParentReference{
|
||||
Group: "custom.resource.com",
|
||||
Resource: "Gateway",
|
||||
Name: "foo",
|
||||
Namespace: "bar",
|
||||
}
|
||||
|
||||
return out
|
||||
}, expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "Failed update, delete spec.ParentRef",
|
||||
new: func(svc *networking.IPAddress) *networking.IPAddress {
|
||||
out := svc.DeepCopy()
|
||||
out.Spec.ParentRef = nil
|
||||
return out
|
||||
}, expectErr: true,
|
||||
},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
err := ValidateIPAddressUpdate(testCase.new(old), old)
|
||||
if !testCase.expectErr && err != nil {
|
||||
t.Errorf("ValidateIPAddressUpdate must be successful for test '%s', got %v", testCase.name, err)
|
||||
}
|
||||
if testCase.expectErr && err == nil {
|
||||
t.Errorf("ValidateIPAddressUpdate must return error for test: %s, but got nil", testCase.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
97
pkg/apis/networking/zz_generated.deepcopy.go
generated
97
pkg/apis/networking/zz_generated.deepcopy.go
generated
@@ -154,6 +154,87 @@ func (in *HTTPIngressRuleValue) DeepCopy() *HTTPIngressRuleValue {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *IPAddress) DeepCopyInto(out *IPAddress) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPAddress.
|
||||
func (in *IPAddress) DeepCopy() *IPAddress {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(IPAddress)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *IPAddress) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *IPAddressList) DeepCopyInto(out *IPAddressList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]IPAddress, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPAddressList.
|
||||
func (in *IPAddressList) DeepCopy() *IPAddressList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(IPAddressList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *IPAddressList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *IPAddressSpec) DeepCopyInto(out *IPAddressSpec) {
|
||||
*out = *in
|
||||
if in.ParentRef != nil {
|
||||
in, out := &in.ParentRef, &out.ParentRef
|
||||
*out = new(ParentReference)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPAddressSpec.
|
||||
func (in *IPAddressSpec) DeepCopy() *IPAddressSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(IPAddressSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *IPBlock) DeepCopyInto(out *IPBlock) {
|
||||
*out = *in
|
||||
@@ -816,6 +897,22 @@ func (in *NetworkPolicyStatus) DeepCopy() *NetworkPolicyStatus {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ParentReference) DeepCopyInto(out *ParentReference) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ParentReference.
|
||||
func (in *ParentReference) DeepCopy() *ParentReference {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ParentReference)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ServiceBackendPort) DeepCopyInto(out *ServiceBackendPort) {
|
||||
*out = *in
|
||||
|
Reference in New Issue
Block a user