network: migrate CIDR validation to DV

Co-authored-by: Abhishek Srivastava <abhishek@asrivas.me>
This commit is contained in:
darshansreenivas 2025-12-10 21:26:49 -08:00
parent 1c24a05ce1
commit bc17031d19
9 changed files with 555 additions and 5 deletions

View file

@ -47,9 +47,43 @@ func RegisterValidations(scheme *runtime.Scheme) error {
}
return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))}
})
// type NetworkPolicy
scheme.AddValidationFunc((*networkingv1.NetworkPolicy)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList {
switch op.Request.SubresourcePath() {
case "/":
return Validate_NetworkPolicy(ctx, op, nil /* fldPath */, obj.(*networkingv1.NetworkPolicy), safe.Cast[*networkingv1.NetworkPolicy](oldObj))
}
return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))}
})
return nil
}
// Validate_IPBlock validates an instance of IPBlock according
// to declarative validation rules in the API schema.
func Validate_IPBlock(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *networkingv1.IPBlock) (errs field.ErrorList) {
// field networkingv1.IPBlock.CIDR
errs = append(errs,
func(fldPath *field.Path, obj, oldObj *string, oldValueCorrelated bool) (errs field.ErrorList) {
// don't revalidate unchanged data
if oldValueCorrelated && op.Type == operation.Update && (obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj)) {
return nil
}
// call field-attached validations
earlyReturn := false
if e := validate.RequiredValue(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
errs = append(errs, e...)
earlyReturn = true
}
if earlyReturn {
return // do not proceed
}
return
}(fldPath.Child("cidr"), &obj.CIDR, safe.Field(oldObj, func(oldObj *networkingv1.IPBlock) *string { return &oldObj.CIDR }), oldObj != nil)...)
// field networkingv1.IPBlock.Except has no validation
return errs
}
// Validate_IngressClass validates an instance of IngressClass according
// to declarative validation rules in the API schema.
func Validate_IngressClass(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *networkingv1.IngressClass) (errs field.ErrorList) {
@ -148,3 +182,132 @@ func Validate_IngressClassSpec(ctx context.Context, op operation.Operation, fldP
return errs
}
// Validate_NetworkPolicy validates an instance of NetworkPolicy according
// to declarative validation rules in the API schema.
func Validate_NetworkPolicy(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *networkingv1.NetworkPolicy) (errs field.ErrorList) {
// field networkingv1.NetworkPolicy.TypeMeta has no validation
// field networkingv1.NetworkPolicy.ObjectMeta has no validation
// field networkingv1.NetworkPolicy.Spec
errs = append(errs,
func(fldPath *field.Path, obj, oldObj *networkingv1.NetworkPolicySpec, oldValueCorrelated bool) (errs field.ErrorList) {
// don't revalidate unchanged data
if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
return nil
}
// call the type's validation function
errs = append(errs, Validate_NetworkPolicySpec(ctx, op, fldPath, obj, oldObj)...)
return
}(fldPath.Child("spec"), &obj.Spec, safe.Field(oldObj, func(oldObj *networkingv1.NetworkPolicy) *networkingv1.NetworkPolicySpec { return &oldObj.Spec }), oldObj != nil)...)
return errs
}
// Validate_NetworkPolicyEgressRule validates an instance of NetworkPolicyEgressRule according
// to declarative validation rules in the API schema.
func Validate_NetworkPolicyEgressRule(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *networkingv1.NetworkPolicyEgressRule) (errs field.ErrorList) {
// field networkingv1.NetworkPolicyEgressRule.Ports has no validation
// field networkingv1.NetworkPolicyEgressRule.To
errs = append(errs,
func(fldPath *field.Path, obj, oldObj []networkingv1.NetworkPolicyPeer, oldValueCorrelated bool) (errs field.ErrorList) {
// don't revalidate unchanged data
if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
return nil
}
// iterate the list and call the type's validation function
errs = append(errs, validate.EachSliceVal(ctx, op, fldPath, obj, oldObj, nil, nil, Validate_NetworkPolicyPeer)...)
return
}(fldPath.Child("to"), obj.To, safe.Field(oldObj, func(oldObj *networkingv1.NetworkPolicyEgressRule) []networkingv1.NetworkPolicyPeer { return oldObj.To }), oldObj != nil)...)
return errs
}
// Validate_NetworkPolicyIngressRule validates an instance of NetworkPolicyIngressRule according
// to declarative validation rules in the API schema.
func Validate_NetworkPolicyIngressRule(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *networkingv1.NetworkPolicyIngressRule) (errs field.ErrorList) {
// field networkingv1.NetworkPolicyIngressRule.Ports has no validation
// field networkingv1.NetworkPolicyIngressRule.From
errs = append(errs,
func(fldPath *field.Path, obj, oldObj []networkingv1.NetworkPolicyPeer, oldValueCorrelated bool) (errs field.ErrorList) {
// don't revalidate unchanged data
if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
return nil
}
// iterate the list and call the type's validation function
errs = append(errs, validate.EachSliceVal(ctx, op, fldPath, obj, oldObj, nil, nil, Validate_NetworkPolicyPeer)...)
return
}(fldPath.Child("from"), obj.From, safe.Field(oldObj, func(oldObj *networkingv1.NetworkPolicyIngressRule) []networkingv1.NetworkPolicyPeer {
return oldObj.From
}), oldObj != nil)...)
return errs
}
// Validate_NetworkPolicyPeer validates an instance of NetworkPolicyPeer according
// to declarative validation rules in the API schema.
func Validate_NetworkPolicyPeer(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *networkingv1.NetworkPolicyPeer) (errs field.ErrorList) {
// field networkingv1.NetworkPolicyPeer.PodSelector has no validation
// field networkingv1.NetworkPolicyPeer.NamespaceSelector has no validation
// field networkingv1.NetworkPolicyPeer.IPBlock
errs = append(errs,
func(fldPath *field.Path, obj, oldObj *networkingv1.IPBlock, oldValueCorrelated bool) (errs field.ErrorList) {
// don't revalidate unchanged data
if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
return nil
}
// call field-attached validations
earlyReturn := false
if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
earlyReturn = true
}
if earlyReturn {
return // do not proceed
}
// call the type's validation function
errs = append(errs, Validate_IPBlock(ctx, op, fldPath, obj, oldObj)...)
return
}(fldPath.Child("ipBlock"), obj.IPBlock, safe.Field(oldObj, func(oldObj *networkingv1.NetworkPolicyPeer) *networkingv1.IPBlock { return oldObj.IPBlock }), oldObj != nil)...)
return errs
}
// Validate_NetworkPolicySpec validates an instance of NetworkPolicySpec according
// to declarative validation rules in the API schema.
func Validate_NetworkPolicySpec(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *networkingv1.NetworkPolicySpec) (errs field.ErrorList) {
// field networkingv1.NetworkPolicySpec.PodSelector has no validation
// field networkingv1.NetworkPolicySpec.Ingress
errs = append(errs,
func(fldPath *field.Path, obj, oldObj []networkingv1.NetworkPolicyIngressRule, oldValueCorrelated bool) (errs field.ErrorList) {
// don't revalidate unchanged data
if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
return nil
}
// iterate the list and call the type's validation function
errs = append(errs, validate.EachSliceVal(ctx, op, fldPath, obj, oldObj, nil, nil, Validate_NetworkPolicyIngressRule)...)
return
}(fldPath.Child("ingress"), obj.Ingress, safe.Field(oldObj, func(oldObj *networkingv1.NetworkPolicySpec) []networkingv1.NetworkPolicyIngressRule {
return oldObj.Ingress
}), oldObj != nil)...)
// field networkingv1.NetworkPolicySpec.Egress
errs = append(errs,
func(fldPath *field.Path, obj, oldObj []networkingv1.NetworkPolicyEgressRule, oldValueCorrelated bool) (errs field.ErrorList) {
// don't revalidate unchanged data
if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
return nil
}
// iterate the list and call the type's validation function
errs = append(errs, validate.EachSliceVal(ctx, op, fldPath, obj, oldObj, nil, nil, Validate_NetworkPolicyEgressRule)...)
return
}(fldPath.Child("egress"), obj.Egress, safe.Field(oldObj, func(oldObj *networkingv1.NetworkPolicySpec) []networkingv1.NetworkPolicyEgressRule {
return oldObj.Egress
}), oldObj != nil)...)
// field networkingv1.NetworkPolicySpec.PolicyTypes has no validation
return errs
}

View file

@ -246,7 +246,7 @@ func ValidateNetworkPolicyUpdate(update, old *networking.NetworkPolicy, opts Net
func ValidateIPBlock(ipb *networking.IPBlock, fldPath *field.Path, opts NetworkPolicyValidationOptions) field.ErrorList {
allErrs := field.ErrorList{}
if ipb.CIDR == "" {
allErrs = append(allErrs, field.Required(fldPath.Child("cidr"), ""))
allErrs = append(allErrs, field.Required(fldPath.Child("cidr"), "").MarkCoveredByDeclarative())
return allErrs
}
allErrs = append(allErrs, apivalidation.IsValidCIDRForLegacyField(fldPath.Child("cidr"), ipb.CIDR, opts.AllowCIDRsEvenIfInvalid)...)

View file

@ -0,0 +1,214 @@
/*
Copyright 2025 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 networkpolicy
import (
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/validation/field"
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
apitesting "k8s.io/kubernetes/pkg/api/testing"
networking "k8s.io/kubernetes/pkg/apis/networking"
)
var apiVersions = []string{"v1"}
func TestDeclarativeValidateIPBlockCIDR(t *testing.T) {
for _, apiVersion := range apiVersions {
t.Run(apiVersion, func(t *testing.T) {
ctx := genericapirequest.WithRequestInfo(
genericapirequest.NewDefaultContext(),
&genericapirequest.RequestInfo{
APIGroup: "networking.k8s.io",
APIVersion: apiVersion,
Resource: "networkpolicies",
IsResourceRequest: true,
Verb: "create",
},
)
testCases := map[string]struct {
input networking.NetworkPolicy
expectedErrs field.ErrorList
}{
"valid ingress rule with CIDR": {
input: mkValidNetworkPolicy("ingress"),
},
"valid egress rule with CIDR": {
input: mkValidNetworkPolicy("egress"),
},
"ingress rule rejects empty CIDR in ipBlock": {
input: mkValidNetworkPolicy("ingress", tweakIngressFromIPBlock("")),
expectedErrs: field.ErrorList{
field.Required(
field.NewPath("spec", "ingress").Index(0).Child("from").Index(0).Child("ipBlock", "cidr"),
"",
),
},
},
"egress rule rejects empty CIDR in ipBlock": {
input: mkValidNetworkPolicy("egress", tweakEgressToIPBlock("")),
expectedErrs: field.ErrorList{
field.Required(
field.NewPath("spec", "egress").Index(0).Child("to").Index(0).Child("ipBlock", "cidr"),
"",
),
},
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
apitesting.VerifyValidationEquivalence(
t,
ctx,
&tc.input,
Strategy.Validate,
tc.expectedErrs,
)
})
}
})
}
}
func TestDeclarativeValidateIPBlockCIDRUpdate(t *testing.T) {
for _, apiVersion := range apiVersions {
t.Run(apiVersion, func(t *testing.T) {
testCases := map[string]struct {
oldObj networking.NetworkPolicy
updateObj networking.NetworkPolicy
expectedErrs field.ErrorList
}{
"valid update ingress rule with CIDR": {
oldObj: mkValidNetworkPolicy("ingress"),
updateObj: mkValidNetworkPolicy("ingress", tweakIngressFromIPBlock("10.0.0.0/8")),
},
"valid update egress rule with CIDR": {
oldObj: mkValidNetworkPolicy("egress"),
updateObj: mkValidNetworkPolicy("egress", tweakEgressToIPBlock("10.0.0.0/8")),
},
"update ingress rule rejects empty CIDR in ipBlock": {
oldObj: mkValidNetworkPolicy("ingress"),
updateObj: mkValidNetworkPolicy("ingress", tweakIngressFromIPBlock("")),
expectedErrs: field.ErrorList{
field.Required(
field.NewPath("spec", "ingress").Index(0).Child("from").Index(0).Child("ipBlock", "cidr"),
"",
),
},
},
"update egress rule rejects empty CIDR in ipBlock": {
oldObj: mkValidNetworkPolicy("egress"),
updateObj: mkValidNetworkPolicy("egress", tweakEgressToIPBlock("")),
expectedErrs: field.ErrorList{
field.Required(
field.NewPath("spec", "egress").Index(0).Child("to").Index(0).Child("ipBlock", "cidr"),
"",
),
},
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
ctx := genericapirequest.WithRequestInfo(
genericapirequest.NewDefaultContext(),
&genericapirequest.RequestInfo{
APIPrefix: "apis",
APIGroup: "networking.k8s.io",
APIVersion: apiVersion,
Resource: "networkpolicies",
Name: "valid-network-policy",
IsResourceRequest: true,
Verb: "update",
},
)
apitesting.VerifyUpdateValidationEquivalence(
t,
ctx,
&tc.updateObj,
&tc.oldObj,
Strategy.ValidateUpdate,
tc.expectedErrs,
)
})
}
})
}
}
func tweakIngressFromIPBlock(cidr string) func(obj *networking.NetworkPolicy) {
return func(obj *networking.NetworkPolicy) {
obj.Spec.Ingress[0].From[0].IPBlock.CIDR = cidr
}
}
func tweakEgressToIPBlock(cidr string) func(obj *networking.NetworkPolicy) {
return func(obj *networking.NetworkPolicy) {
obj.Spec.Egress[0].To[0].IPBlock.CIDR = cidr
}
}
func mkValidNetworkPolicy(ruleType string, tweaks ...func(obj *networking.NetworkPolicy)) networking.NetworkPolicy {
obj := networking.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "valid-network-policy",
Namespace: "default",
},
Spec: networking.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{},
},
}
switch ruleType {
case "ingress":
obj.Spec.Ingress = []networking.NetworkPolicyIngressRule{
{
From: []networking.NetworkPolicyPeer{
{
IPBlock: &networking.IPBlock{
CIDR: "192.168.1.0/24",
},
},
},
},
}
case "egress":
obj.Spec.Egress = []networking.NetworkPolicyEgressRule{
{
To: []networking.NetworkPolicyPeer{
{
IPBlock: &networking.IPBlock{
CIDR: "192.168.1.0/24",
},
},
},
},
}
}
obj.ResourceVersion = "1"
for _, tweak := range tweaks {
tweak(&obj)
}
return obj
}

View file

@ -18,6 +18,8 @@ package networkpolicy
import (
"context"
"k8s.io/apimachinery/pkg/api/operation"
"k8s.io/apiserver/pkg/registry/rest"
"reflect"
"k8s.io/apimachinery/pkg/runtime"
@ -66,7 +68,9 @@ func (networkPolicyStrategy) PrepareForUpdate(ctx context.Context, obj, old runt
func (networkPolicyStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
networkPolicy := obj.(*networking.NetworkPolicy)
ops := validation.ValidationOptionsForNetworking(networkPolicy, nil)
return validation.ValidateNetworkPolicy(networkPolicy, ops)
allErrs := validation.ValidateNetworkPolicy(networkPolicy, ops)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, networkPolicy, nil, allErrs, operation.Create)
}
// WarningsOnCreate returns warnings for the creation of the given object.
@ -85,9 +89,8 @@ func (networkPolicyStrategy) AllowCreateOnUpdate() bool {
// ValidateUpdate is the default update validation for an end user.
func (networkPolicyStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
opts := validation.ValidationOptionsForNetworking(obj.(*networking.NetworkPolicy), old.(*networking.NetworkPolicy))
validationErrorList := validation.ValidateNetworkPolicy(obj.(*networking.NetworkPolicy), opts)
updateErrorList := validation.ValidateNetworkPolicyUpdate(obj.(*networking.NetworkPolicy), old.(*networking.NetworkPolicy), opts)
return append(validationErrorList, updateErrorList...)
allErrs := validation.ValidateNetworkPolicyUpdate(obj.(*networking.NetworkPolicy), old.(*networking.NetworkPolicy), opts)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, obj, old, allErrs, operation.Update)
}
// WarningsOnUpdate returns warnings for the given update.

View file

@ -428,6 +428,8 @@ message HTTPIngressRuleValue {
message IPBlock {
// CIDR is a string representing the IP Block
// Valid examples are "192.168.1.0/24" or "2001:db8::/64"
// +required
// +k8s:required
optional string cidr = 1;
// Except is a slice of CIDRs that should not be included within an IP Block
@ -746,6 +748,7 @@ message NetworkPolicyPeer {
// IPBlock defines policy on a particular IPBlock. If this field is set then
// neither of the other fields can be.
// +optional
// +k8s:optional
optional IPBlock ipBlock = 3;
}

View file

@ -1209,6 +1209,8 @@ type NetworkPolicyPort struct {
type IPBlock struct {
// CIDR is a string representing the IP Block
// Valid examples are "192.168.1.0/24" or "2001:db8::/64"
// +required
// +k8s:required
CIDR string `json:"cidr" protobuf:"bytes,1,name=cidr"`
// Except is a slice of CIDRs that should not be included within an IP Block
// Valid examples are "192.168.1.0/24" or "2001:db8::/64"
@ -1241,6 +1243,7 @@ type NetworkPolicyPeer struct {
// IPBlock defines policy on a particular IPBlock. If this field is set then
// neither of the other fields can be.
// +optional
// +k8s:optional
IPBlock *IPBlock `json:"ipBlock,omitempty" protobuf:"bytes,3,rep,name=ipBlock"`
}

View file

@ -25,6 +25,7 @@ import (
context "context"
fmt "fmt"
equality "k8s.io/apimachinery/pkg/api/equality"
operation "k8s.io/apimachinery/pkg/api/operation"
safe "k8s.io/apimachinery/pkg/api/safe"
validate "k8s.io/apimachinery/pkg/api/validate"
@ -37,6 +38,14 @@ func init() { localSchemeBuilder.Register(RegisterValidations) }
// RegisterValidations adds validation functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterValidations(scheme *runtime.Scheme) error {
// type NetworkPolicy
scheme.AddValidationFunc((*NetworkPolicy)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList {
switch op.Request.SubresourcePath() {
case "/":
return Validate_NetworkPolicy(ctx, op, nil /* fldPath */, obj.(*NetworkPolicy), safe.Cast[*NetworkPolicy](oldObj))
}
return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))}
})
// type Scale
scheme.AddValidationFunc((*Scale)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList {
switch op.Request.SubresourcePath() {
@ -48,6 +57,155 @@ func RegisterValidations(scheme *runtime.Scheme) error {
return nil
}
// Validate_IPBlock validates an instance of IPBlock according
// to declarative validation rules in the API schema.
func Validate_IPBlock(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *IPBlock) (errs field.ErrorList) {
// field IPBlock.CIDR
errs = append(errs,
func(fldPath *field.Path, obj, oldObj *string, oldValueCorrelated bool) (errs field.ErrorList) {
// don't revalidate unchanged data
if oldValueCorrelated && op.Type == operation.Update && (obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj)) {
return nil
}
// call field-attached validations
earlyReturn := false
if e := validate.RequiredValue(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
errs = append(errs, e...)
earlyReturn = true
}
if earlyReturn {
return // do not proceed
}
return
}(fldPath.Child("cidr"), &obj.CIDR, safe.Field(oldObj, func(oldObj *IPBlock) *string { return &oldObj.CIDR }), oldObj != nil)...)
// field IPBlock.Except has no validation
return errs
}
// Validate_NetworkPolicy validates an instance of NetworkPolicy according
// to declarative validation rules in the API schema.
func Validate_NetworkPolicy(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *NetworkPolicy) (errs field.ErrorList) {
// field NetworkPolicy.TypeMeta has no validation
// field NetworkPolicy.ObjectMeta has no validation
// field NetworkPolicy.Spec
errs = append(errs,
func(fldPath *field.Path, obj, oldObj *NetworkPolicySpec, oldValueCorrelated bool) (errs field.ErrorList) {
// don't revalidate unchanged data
if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
return nil
}
// call the type's validation function
errs = append(errs, Validate_NetworkPolicySpec(ctx, op, fldPath, obj, oldObj)...)
return
}(fldPath.Child("spec"), &obj.Spec, safe.Field(oldObj, func(oldObj *NetworkPolicy) *NetworkPolicySpec { return &oldObj.Spec }), oldObj != nil)...)
return errs
}
// Validate_NetworkPolicyEgressRule validates an instance of NetworkPolicyEgressRule according
// to declarative validation rules in the API schema.
func Validate_NetworkPolicyEgressRule(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *NetworkPolicyEgressRule) (errs field.ErrorList) {
// field NetworkPolicyEgressRule.Ports has no validation
// field NetworkPolicyEgressRule.To
errs = append(errs,
func(fldPath *field.Path, obj, oldObj []NetworkPolicyPeer, oldValueCorrelated bool) (errs field.ErrorList) {
// don't revalidate unchanged data
if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
return nil
}
// iterate the list and call the type's validation function
errs = append(errs, validate.EachSliceVal(ctx, op, fldPath, obj, oldObj, nil, nil, Validate_NetworkPolicyPeer)...)
return
}(fldPath.Child("to"), obj.To, safe.Field(oldObj, func(oldObj *NetworkPolicyEgressRule) []NetworkPolicyPeer { return oldObj.To }), oldObj != nil)...)
return errs
}
// Validate_NetworkPolicyIngressRule validates an instance of NetworkPolicyIngressRule according
// to declarative validation rules in the API schema.
func Validate_NetworkPolicyIngressRule(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *NetworkPolicyIngressRule) (errs field.ErrorList) {
// field NetworkPolicyIngressRule.Ports has no validation
// field NetworkPolicyIngressRule.From
errs = append(errs,
func(fldPath *field.Path, obj, oldObj []NetworkPolicyPeer, oldValueCorrelated bool) (errs field.ErrorList) {
// don't revalidate unchanged data
if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
return nil
}
// iterate the list and call the type's validation function
errs = append(errs, validate.EachSliceVal(ctx, op, fldPath, obj, oldObj, nil, nil, Validate_NetworkPolicyPeer)...)
return
}(fldPath.Child("from"), obj.From, safe.Field(oldObj, func(oldObj *NetworkPolicyIngressRule) []NetworkPolicyPeer { return oldObj.From }), oldObj != nil)...)
return errs
}
// Validate_NetworkPolicyPeer validates an instance of NetworkPolicyPeer according
// to declarative validation rules in the API schema.
func Validate_NetworkPolicyPeer(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *NetworkPolicyPeer) (errs field.ErrorList) {
// field NetworkPolicyPeer.PodSelector has no validation
// field NetworkPolicyPeer.NamespaceSelector has no validation
// field NetworkPolicyPeer.IPBlock
errs = append(errs,
func(fldPath *field.Path, obj, oldObj *IPBlock, oldValueCorrelated bool) (errs field.ErrorList) {
// don't revalidate unchanged data
if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
return nil
}
// call field-attached validations
earlyReturn := false
if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
earlyReturn = true
}
if earlyReturn {
return // do not proceed
}
// call the type's validation function
errs = append(errs, Validate_IPBlock(ctx, op, fldPath, obj, oldObj)...)
return
}(fldPath.Child("ipBlock"), obj.IPBlock, safe.Field(oldObj, func(oldObj *NetworkPolicyPeer) *IPBlock { return oldObj.IPBlock }), oldObj != nil)...)
return errs
}
// Validate_NetworkPolicySpec validates an instance of NetworkPolicySpec according
// to declarative validation rules in the API schema.
func Validate_NetworkPolicySpec(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *NetworkPolicySpec) (errs field.ErrorList) {
// field NetworkPolicySpec.PodSelector has no validation
// field NetworkPolicySpec.Ingress
errs = append(errs,
func(fldPath *field.Path, obj, oldObj []NetworkPolicyIngressRule, oldValueCorrelated bool) (errs field.ErrorList) {
// don't revalidate unchanged data
if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
return nil
}
// iterate the list and call the type's validation function
errs = append(errs, validate.EachSliceVal(ctx, op, fldPath, obj, oldObj, nil, nil, Validate_NetworkPolicyIngressRule)...)
return
}(fldPath.Child("ingress"), obj.Ingress, safe.Field(oldObj, func(oldObj *NetworkPolicySpec) []NetworkPolicyIngressRule { return oldObj.Ingress }), oldObj != nil)...)
// field NetworkPolicySpec.Egress
errs = append(errs,
func(fldPath *field.Path, obj, oldObj []NetworkPolicyEgressRule, oldValueCorrelated bool) (errs field.ErrorList) {
// don't revalidate unchanged data
if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
return nil
}
// iterate the list and call the type's validation function
errs = append(errs, validate.EachSliceVal(ctx, op, fldPath, obj, oldObj, nil, nil, Validate_NetworkPolicyEgressRule)...)
return
}(fldPath.Child("egress"), obj.Egress, safe.Field(oldObj, func(oldObj *NetworkPolicySpec) []NetworkPolicyEgressRule { return oldObj.Egress }), oldObj != nil)...)
// field NetworkPolicySpec.PolicyTypes has no validation
return errs
}
// Validate_Scale validates an instance of Scale according
// to declarative validation rules in the API schema.
func Validate_Scale(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *Scale) (errs field.ErrorList) {

View file

@ -116,6 +116,8 @@ message IPAddressSpec {
message IPBlock {
// cidr is a string representing the IPBlock
// Valid examples are "192.168.1.0/24" or "2001:db8::/64"
// +required
// +k8s:required
optional string cidr = 1;
// except is a slice of CIDRs that should not be included within an IPBlock
@ -511,6 +513,7 @@ message NetworkPolicyPeer {
// ipBlock defines policy on a particular IPBlock. If this field is set then
// neither of the other fields can be.
// +optional
// +k8s:optional
optional IPBlock ipBlock = 3;
}

View file

@ -178,6 +178,8 @@ type NetworkPolicyPort struct {
type IPBlock struct {
// cidr is a string representing the IPBlock
// Valid examples are "192.168.1.0/24" or "2001:db8::/64"
// +required
// +k8s:required
CIDR string `json:"cidr" protobuf:"bytes,1,name=cidr"`
// except is a slice of CIDRs that should not be included within an IPBlock
@ -212,6 +214,7 @@ type NetworkPolicyPeer struct {
// ipBlock defines policy on a particular IPBlock. If this field is set then
// neither of the other fields can be.
// +optional
// +k8s:optional
IPBlock *IPBlock `json:"ipBlock,omitempty" protobuf:"bytes,3,rep,name=ipBlock"`
}