mirror of
https://github.com/kubernetes/kubernetes.git
synced 2026-06-09 08:55:55 -04:00
feat(validation-gen): Add declarative validation support for ClusterRole(v1,v1alpha1,v1beta1)
This commit is contained in:
parent
3f8a5219e2
commit
4e660cc05b
9 changed files with 640 additions and 3 deletions
155
pkg/apis/rbac/v1/zz_generated.validations.go
generated
155
pkg/apis/rbac/v1/zz_generated.validations.go
generated
|
|
@ -22,7 +22,16 @@ limitations under the License.
|
|||
package v1
|
||||
|
||||
import (
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
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"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
field "k8s.io/apimachinery/pkg/util/validation/field"
|
||||
)
|
||||
|
||||
func init() { localSchemeBuilder.Register(RegisterValidations) }
|
||||
|
|
@ -30,5 +39,151 @@ 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 ClusterRole
|
||||
scheme.AddValidationFunc((*rbacv1.ClusterRole)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList {
|
||||
switch op.Request.SubresourcePath() {
|
||||
case "/":
|
||||
return Validate_ClusterRole(ctx, op, nil /* fldPath */, obj.(*rbacv1.ClusterRole), safe.Cast[*rbacv1.ClusterRole](oldObj))
|
||||
}
|
||||
return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))}
|
||||
})
|
||||
// type ClusterRoleList
|
||||
scheme.AddValidationFunc((*rbacv1.ClusterRoleList)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList {
|
||||
switch op.Request.SubresourcePath() {
|
||||
case "/":
|
||||
return Validate_ClusterRoleList(ctx, op, nil /* fldPath */, obj.(*rbacv1.ClusterRoleList), safe.Cast[*rbacv1.ClusterRoleList](oldObj))
|
||||
}
|
||||
return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))}
|
||||
})
|
||||
// type Role
|
||||
scheme.AddValidationFunc((*rbacv1.Role)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList {
|
||||
switch op.Request.SubresourcePath() {
|
||||
case "/":
|
||||
return Validate_Role(ctx, op, nil /* fldPath */, obj.(*rbacv1.Role), safe.Cast[*rbacv1.Role](oldObj))
|
||||
}
|
||||
return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))}
|
||||
})
|
||||
// type RoleList
|
||||
scheme.AddValidationFunc((*rbacv1.RoleList)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList {
|
||||
switch op.Request.SubresourcePath() {
|
||||
case "/":
|
||||
return Validate_RoleList(ctx, op, nil /* fldPath */, obj.(*rbacv1.RoleList), safe.Cast[*rbacv1.RoleList](oldObj))
|
||||
}
|
||||
return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))}
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate_ClusterRole validates an instance of ClusterRole according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_ClusterRole(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *rbacv1.ClusterRole) (errs field.ErrorList) {
|
||||
// field rbacv1.ClusterRole.TypeMeta has no validation
|
||||
// field rbacv1.ClusterRole.ObjectMeta has no validation
|
||||
|
||||
// field rbacv1.ClusterRole.Rules
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj []rbacv1.PolicyRule) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if 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_PolicyRule)...)
|
||||
return
|
||||
}(fldPath.Child("rules"), obj.Rules, safe.Field(oldObj, func(oldObj *rbacv1.ClusterRole) []rbacv1.PolicyRule { return oldObj.Rules }))...)
|
||||
|
||||
// field rbacv1.ClusterRole.AggregationRule has no validation
|
||||
return errs
|
||||
}
|
||||
|
||||
// Validate_ClusterRoleList validates an instance of ClusterRoleList according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_ClusterRoleList(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *rbacv1.ClusterRoleList) (errs field.ErrorList) {
|
||||
// field rbacv1.ClusterRoleList.TypeMeta has no validation
|
||||
// field rbacv1.ClusterRoleList.ListMeta has no validation
|
||||
|
||||
// field rbacv1.ClusterRoleList.Items
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj []rbacv1.ClusterRole) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if 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_ClusterRole)...)
|
||||
return
|
||||
}(fldPath.Child("items"), obj.Items, safe.Field(oldObj, func(oldObj *rbacv1.ClusterRoleList) []rbacv1.ClusterRole { return oldObj.Items }))...)
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
// Validate_PolicyRule validates an instance of PolicyRule according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_PolicyRule(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *rbacv1.PolicyRule) (errs field.ErrorList) {
|
||||
// field rbacv1.PolicyRule.Verbs
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj []string) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
|
||||
return nil
|
||||
}
|
||||
// call field-attached validations
|
||||
earlyReturn := false
|
||||
if e := validate.RequiredSlice(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
|
||||
errs = append(errs, e...)
|
||||
earlyReturn = true
|
||||
}
|
||||
if earlyReturn {
|
||||
return // do not proceed
|
||||
}
|
||||
return
|
||||
}(fldPath.Child("verbs"), obj.Verbs, safe.Field(oldObj, func(oldObj *rbacv1.PolicyRule) []string { return oldObj.Verbs }))...)
|
||||
|
||||
// field rbacv1.PolicyRule.APIGroups has no validation
|
||||
// field rbacv1.PolicyRule.Resources has no validation
|
||||
// field rbacv1.PolicyRule.ResourceNames has no validation
|
||||
// field rbacv1.PolicyRule.NonResourceURLs has no validation
|
||||
return errs
|
||||
}
|
||||
|
||||
// Validate_Role validates an instance of Role according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_Role(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *rbacv1.Role) (errs field.ErrorList) {
|
||||
// field rbacv1.Role.TypeMeta has no validation
|
||||
// field rbacv1.Role.ObjectMeta has no validation
|
||||
|
||||
// field rbacv1.Role.Rules
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj []rbacv1.PolicyRule) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if 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_PolicyRule)...)
|
||||
return
|
||||
}(fldPath.Child("rules"), obj.Rules, safe.Field(oldObj, func(oldObj *rbacv1.Role) []rbacv1.PolicyRule { return oldObj.Rules }))...)
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
// Validate_RoleList validates an instance of RoleList according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_RoleList(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *rbacv1.RoleList) (errs field.ErrorList) {
|
||||
// field rbacv1.RoleList.TypeMeta has no validation
|
||||
// field rbacv1.RoleList.ListMeta has no validation
|
||||
|
||||
// field rbacv1.RoleList.Items
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj []rbacv1.Role) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if 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_Role)...)
|
||||
return
|
||||
}(fldPath.Child("items"), obj.Items, safe.Field(oldObj, func(oldObj *rbacv1.RoleList) []rbacv1.Role { return oldObj.Items }))...)
|
||||
|
||||
return errs
|
||||
}
|
||||
|
|
|
|||
155
pkg/apis/rbac/v1alpha1/zz_generated.validations.go
generated
155
pkg/apis/rbac/v1alpha1/zz_generated.validations.go
generated
|
|
@ -22,7 +22,16 @@ limitations under the License.
|
|||
package v1alpha1
|
||||
|
||||
import (
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
|
||||
rbacv1alpha1 "k8s.io/api/rbac/v1alpha1"
|
||||
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"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
field "k8s.io/apimachinery/pkg/util/validation/field"
|
||||
)
|
||||
|
||||
func init() { localSchemeBuilder.Register(RegisterValidations) }
|
||||
|
|
@ -30,5 +39,151 @@ 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 ClusterRole
|
||||
scheme.AddValidationFunc((*rbacv1alpha1.ClusterRole)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList {
|
||||
switch op.Request.SubresourcePath() {
|
||||
case "/":
|
||||
return Validate_ClusterRole(ctx, op, nil /* fldPath */, obj.(*rbacv1alpha1.ClusterRole), safe.Cast[*rbacv1alpha1.ClusterRole](oldObj))
|
||||
}
|
||||
return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))}
|
||||
})
|
||||
// type ClusterRoleList
|
||||
scheme.AddValidationFunc((*rbacv1alpha1.ClusterRoleList)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList {
|
||||
switch op.Request.SubresourcePath() {
|
||||
case "/":
|
||||
return Validate_ClusterRoleList(ctx, op, nil /* fldPath */, obj.(*rbacv1alpha1.ClusterRoleList), safe.Cast[*rbacv1alpha1.ClusterRoleList](oldObj))
|
||||
}
|
||||
return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))}
|
||||
})
|
||||
// type Role
|
||||
scheme.AddValidationFunc((*rbacv1alpha1.Role)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList {
|
||||
switch op.Request.SubresourcePath() {
|
||||
case "/":
|
||||
return Validate_Role(ctx, op, nil /* fldPath */, obj.(*rbacv1alpha1.Role), safe.Cast[*rbacv1alpha1.Role](oldObj))
|
||||
}
|
||||
return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))}
|
||||
})
|
||||
// type RoleList
|
||||
scheme.AddValidationFunc((*rbacv1alpha1.RoleList)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList {
|
||||
switch op.Request.SubresourcePath() {
|
||||
case "/":
|
||||
return Validate_RoleList(ctx, op, nil /* fldPath */, obj.(*rbacv1alpha1.RoleList), safe.Cast[*rbacv1alpha1.RoleList](oldObj))
|
||||
}
|
||||
return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))}
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate_ClusterRole validates an instance of ClusterRole according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_ClusterRole(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *rbacv1alpha1.ClusterRole) (errs field.ErrorList) {
|
||||
// field rbacv1alpha1.ClusterRole.TypeMeta has no validation
|
||||
// field rbacv1alpha1.ClusterRole.ObjectMeta has no validation
|
||||
|
||||
// field rbacv1alpha1.ClusterRole.Rules
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj []rbacv1alpha1.PolicyRule) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if 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_PolicyRule)...)
|
||||
return
|
||||
}(fldPath.Child("rules"), obj.Rules, safe.Field(oldObj, func(oldObj *rbacv1alpha1.ClusterRole) []rbacv1alpha1.PolicyRule { return oldObj.Rules }))...)
|
||||
|
||||
// field rbacv1alpha1.ClusterRole.AggregationRule has no validation
|
||||
return errs
|
||||
}
|
||||
|
||||
// Validate_ClusterRoleList validates an instance of ClusterRoleList according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_ClusterRoleList(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *rbacv1alpha1.ClusterRoleList) (errs field.ErrorList) {
|
||||
// field rbacv1alpha1.ClusterRoleList.TypeMeta has no validation
|
||||
// field rbacv1alpha1.ClusterRoleList.ListMeta has no validation
|
||||
|
||||
// field rbacv1alpha1.ClusterRoleList.Items
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj []rbacv1alpha1.ClusterRole) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if 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_ClusterRole)...)
|
||||
return
|
||||
}(fldPath.Child("items"), obj.Items, safe.Field(oldObj, func(oldObj *rbacv1alpha1.ClusterRoleList) []rbacv1alpha1.ClusterRole { return oldObj.Items }))...)
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
// Validate_PolicyRule validates an instance of PolicyRule according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_PolicyRule(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *rbacv1alpha1.PolicyRule) (errs field.ErrorList) {
|
||||
// field rbacv1alpha1.PolicyRule.Verbs
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj []string) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
|
||||
return nil
|
||||
}
|
||||
// call field-attached validations
|
||||
earlyReturn := false
|
||||
if e := validate.RequiredSlice(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
|
||||
errs = append(errs, e...)
|
||||
earlyReturn = true
|
||||
}
|
||||
if earlyReturn {
|
||||
return // do not proceed
|
||||
}
|
||||
return
|
||||
}(fldPath.Child("verbs"), obj.Verbs, safe.Field(oldObj, func(oldObj *rbacv1alpha1.PolicyRule) []string { return oldObj.Verbs }))...)
|
||||
|
||||
// field rbacv1alpha1.PolicyRule.APIGroups has no validation
|
||||
// field rbacv1alpha1.PolicyRule.Resources has no validation
|
||||
// field rbacv1alpha1.PolicyRule.ResourceNames has no validation
|
||||
// field rbacv1alpha1.PolicyRule.NonResourceURLs has no validation
|
||||
return errs
|
||||
}
|
||||
|
||||
// Validate_Role validates an instance of Role according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_Role(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *rbacv1alpha1.Role) (errs field.ErrorList) {
|
||||
// field rbacv1alpha1.Role.TypeMeta has no validation
|
||||
// field rbacv1alpha1.Role.ObjectMeta has no validation
|
||||
|
||||
// field rbacv1alpha1.Role.Rules
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj []rbacv1alpha1.PolicyRule) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if 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_PolicyRule)...)
|
||||
return
|
||||
}(fldPath.Child("rules"), obj.Rules, safe.Field(oldObj, func(oldObj *rbacv1alpha1.Role) []rbacv1alpha1.PolicyRule { return oldObj.Rules }))...)
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
// Validate_RoleList validates an instance of RoleList according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_RoleList(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *rbacv1alpha1.RoleList) (errs field.ErrorList) {
|
||||
// field rbacv1alpha1.RoleList.TypeMeta has no validation
|
||||
// field rbacv1alpha1.RoleList.ListMeta has no validation
|
||||
|
||||
// field rbacv1alpha1.RoleList.Items
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj []rbacv1alpha1.Role) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if 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_Role)...)
|
||||
return
|
||||
}(fldPath.Child("items"), obj.Items, safe.Field(oldObj, func(oldObj *rbacv1alpha1.RoleList) []rbacv1alpha1.Role { return oldObj.Items }))...)
|
||||
|
||||
return errs
|
||||
}
|
||||
|
|
|
|||
155
pkg/apis/rbac/v1beta1/zz_generated.validations.go
generated
155
pkg/apis/rbac/v1beta1/zz_generated.validations.go
generated
|
|
@ -22,7 +22,16 @@ limitations under the License.
|
|||
package v1beta1
|
||||
|
||||
import (
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
|
||||
rbacv1beta1 "k8s.io/api/rbac/v1beta1"
|
||||
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"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
field "k8s.io/apimachinery/pkg/util/validation/field"
|
||||
)
|
||||
|
||||
func init() { localSchemeBuilder.Register(RegisterValidations) }
|
||||
|
|
@ -30,5 +39,151 @@ 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 ClusterRole
|
||||
scheme.AddValidationFunc((*rbacv1beta1.ClusterRole)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList {
|
||||
switch op.Request.SubresourcePath() {
|
||||
case "/":
|
||||
return Validate_ClusterRole(ctx, op, nil /* fldPath */, obj.(*rbacv1beta1.ClusterRole), safe.Cast[*rbacv1beta1.ClusterRole](oldObj))
|
||||
}
|
||||
return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))}
|
||||
})
|
||||
// type ClusterRoleList
|
||||
scheme.AddValidationFunc((*rbacv1beta1.ClusterRoleList)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList {
|
||||
switch op.Request.SubresourcePath() {
|
||||
case "/":
|
||||
return Validate_ClusterRoleList(ctx, op, nil /* fldPath */, obj.(*rbacv1beta1.ClusterRoleList), safe.Cast[*rbacv1beta1.ClusterRoleList](oldObj))
|
||||
}
|
||||
return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))}
|
||||
})
|
||||
// type Role
|
||||
scheme.AddValidationFunc((*rbacv1beta1.Role)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList {
|
||||
switch op.Request.SubresourcePath() {
|
||||
case "/":
|
||||
return Validate_Role(ctx, op, nil /* fldPath */, obj.(*rbacv1beta1.Role), safe.Cast[*rbacv1beta1.Role](oldObj))
|
||||
}
|
||||
return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))}
|
||||
})
|
||||
// type RoleList
|
||||
scheme.AddValidationFunc((*rbacv1beta1.RoleList)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList {
|
||||
switch op.Request.SubresourcePath() {
|
||||
case "/":
|
||||
return Validate_RoleList(ctx, op, nil /* fldPath */, obj.(*rbacv1beta1.RoleList), safe.Cast[*rbacv1beta1.RoleList](oldObj))
|
||||
}
|
||||
return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))}
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate_ClusterRole validates an instance of ClusterRole according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_ClusterRole(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *rbacv1beta1.ClusterRole) (errs field.ErrorList) {
|
||||
// field rbacv1beta1.ClusterRole.TypeMeta has no validation
|
||||
// field rbacv1beta1.ClusterRole.ObjectMeta has no validation
|
||||
|
||||
// field rbacv1beta1.ClusterRole.Rules
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj []rbacv1beta1.PolicyRule) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if 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_PolicyRule)...)
|
||||
return
|
||||
}(fldPath.Child("rules"), obj.Rules, safe.Field(oldObj, func(oldObj *rbacv1beta1.ClusterRole) []rbacv1beta1.PolicyRule { return oldObj.Rules }))...)
|
||||
|
||||
// field rbacv1beta1.ClusterRole.AggregationRule has no validation
|
||||
return errs
|
||||
}
|
||||
|
||||
// Validate_ClusterRoleList validates an instance of ClusterRoleList according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_ClusterRoleList(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *rbacv1beta1.ClusterRoleList) (errs field.ErrorList) {
|
||||
// field rbacv1beta1.ClusterRoleList.TypeMeta has no validation
|
||||
// field rbacv1beta1.ClusterRoleList.ListMeta has no validation
|
||||
|
||||
// field rbacv1beta1.ClusterRoleList.Items
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj []rbacv1beta1.ClusterRole) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if 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_ClusterRole)...)
|
||||
return
|
||||
}(fldPath.Child("items"), obj.Items, safe.Field(oldObj, func(oldObj *rbacv1beta1.ClusterRoleList) []rbacv1beta1.ClusterRole { return oldObj.Items }))...)
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
// Validate_PolicyRule validates an instance of PolicyRule according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_PolicyRule(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *rbacv1beta1.PolicyRule) (errs field.ErrorList) {
|
||||
// field rbacv1beta1.PolicyRule.Verbs
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj []string) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
|
||||
return nil
|
||||
}
|
||||
// call field-attached validations
|
||||
earlyReturn := false
|
||||
if e := validate.RequiredSlice(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
|
||||
errs = append(errs, e...)
|
||||
earlyReturn = true
|
||||
}
|
||||
if earlyReturn {
|
||||
return // do not proceed
|
||||
}
|
||||
return
|
||||
}(fldPath.Child("verbs"), obj.Verbs, safe.Field(oldObj, func(oldObj *rbacv1beta1.PolicyRule) []string { return oldObj.Verbs }))...)
|
||||
|
||||
// field rbacv1beta1.PolicyRule.APIGroups has no validation
|
||||
// field rbacv1beta1.PolicyRule.Resources has no validation
|
||||
// field rbacv1beta1.PolicyRule.ResourceNames has no validation
|
||||
// field rbacv1beta1.PolicyRule.NonResourceURLs has no validation
|
||||
return errs
|
||||
}
|
||||
|
||||
// Validate_Role validates an instance of Role according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_Role(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *rbacv1beta1.Role) (errs field.ErrorList) {
|
||||
// field rbacv1beta1.Role.TypeMeta has no validation
|
||||
// field rbacv1beta1.Role.ObjectMeta has no validation
|
||||
|
||||
// field rbacv1beta1.Role.Rules
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj []rbacv1beta1.PolicyRule) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if 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_PolicyRule)...)
|
||||
return
|
||||
}(fldPath.Child("rules"), obj.Rules, safe.Field(oldObj, func(oldObj *rbacv1beta1.Role) []rbacv1beta1.PolicyRule { return oldObj.Rules }))...)
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
// Validate_RoleList validates an instance of RoleList according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_RoleList(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *rbacv1beta1.RoleList) (errs field.ErrorList) {
|
||||
// field rbacv1beta1.RoleList.TypeMeta has no validation
|
||||
// field rbacv1beta1.RoleList.ListMeta has no validation
|
||||
|
||||
// field rbacv1beta1.RoleList.Items
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj []rbacv1beta1.Role) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if 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_Role)...)
|
||||
return
|
||||
}(fldPath.Child("items"), obj.Items, safe.Field(oldObj, func(oldObj *rbacv1beta1.RoleList) []rbacv1beta1.Role { return oldObj.Items }))...)
|
||||
|
||||
return errs
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ func ValidateClusterRoleUpdate(role *rbac.ClusterRole, oldRole *rbac.ClusterRole
|
|||
func ValidatePolicyRule(rule rbac.PolicyRule, isNamespaced bool, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(rule.Verbs) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("verbs"), "verbs must contain at least one value"))
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("verbs"), "verbs must contain at least one value").MarkCoveredByDeclarative())
|
||||
}
|
||||
|
||||
if len(rule.NonResourceURLs) > 0 {
|
||||
|
|
|
|||
150
pkg/registry/rbac/clusterrole/declarative_validation_test.go
Normal file
150
pkg/registry/rbac/clusterrole/declarative_validation_test.go
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
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 clusterrole
|
||||
|
||||
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"
|
||||
rbac "k8s.io/kubernetes/pkg/apis/rbac"
|
||||
)
|
||||
|
||||
var apiVersions = []string{"v1", "v1alpha1", "v1beta1"}
|
||||
|
||||
func TestDeclarativeValidateForDeclarative(t *testing.T) {
|
||||
for _, apiVersion := range apiVersions {
|
||||
testDeclarativeValidateForDeclarative(t, apiVersion)
|
||||
}
|
||||
}
|
||||
|
||||
func testDeclarativeValidateForDeclarative(t *testing.T, apiVersion string) {
|
||||
ctx := genericapirequest.WithRequestInfo(genericapirequest.NewDefaultContext(), &genericapirequest.RequestInfo{
|
||||
APIGroup: "rbac.authorization.k8s.io",
|
||||
APIVersion: apiVersion,
|
||||
})
|
||||
testCases := map[string]struct {
|
||||
input rbac.ClusterRole
|
||||
expectedErrs field.ErrorList
|
||||
}{
|
||||
"missing verbs": {
|
||||
input: rbac.ClusterRole{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test-role"},
|
||||
Rules: []rbac.PolicyRule{
|
||||
{
|
||||
APIGroups: []string{""},
|
||||
Resources: []string{"pods"},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErrs: field.ErrorList{
|
||||
field.Required(field.NewPath("rules").Index(0).Child("verbs"), "must have at least one verb"),
|
||||
},
|
||||
},
|
||||
"valid rule": {
|
||||
input: rbac.ClusterRole{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "valid-role"},
|
||||
Rules: []rbac.PolicyRule{
|
||||
{
|
||||
APIGroups: []string{""},
|
||||
Resources: []string{"pods"},
|
||||
Verbs: []string{"get", "list"},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErrs: field.ErrorList{},
|
||||
},
|
||||
}
|
||||
for k, tc := range testCases {
|
||||
t.Run(k, func(t *testing.T) {
|
||||
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy.Validate, tc.expectedErrs)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateUpdateForDeclarative(t *testing.T) {
|
||||
for _, apiVersion := range apiVersions {
|
||||
testValidateUpdateForDeclarative(t, apiVersion)
|
||||
}
|
||||
}
|
||||
|
||||
func testValidateUpdateForDeclarative(t *testing.T, apiVersion string) {
|
||||
ctx := genericapirequest.WithRequestInfo(genericapirequest.NewDefaultContext(), &genericapirequest.RequestInfo{
|
||||
APIGroup: "rbac.authorization.k8s.io",
|
||||
APIVersion: apiVersion,
|
||||
})
|
||||
testCases := map[string]struct {
|
||||
old rbac.ClusterRole
|
||||
update rbac.ClusterRole
|
||||
expectedErrs field.ErrorList
|
||||
}{
|
||||
"update missing verbs": {
|
||||
old: rbac.ClusterRole{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "role"},
|
||||
Rules: []rbac.PolicyRule{
|
||||
{
|
||||
APIGroups: []string{""},
|
||||
Resources: []string{"pods"},
|
||||
Verbs: []string{"get"},
|
||||
},
|
||||
},
|
||||
},
|
||||
update: rbac.ClusterRole{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "role", ResourceVersion: "1"},
|
||||
Rules: []rbac.PolicyRule{
|
||||
{
|
||||
APIGroups: []string{""},
|
||||
Resources: []string{"pods"},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErrs: field.ErrorList{
|
||||
field.Required(field.NewPath("rules").Index(0).Child("verbs"), "must have at least one verb"),
|
||||
},
|
||||
},
|
||||
"valid update": {
|
||||
old: rbac.ClusterRole{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "role"},
|
||||
Rules: []rbac.PolicyRule{
|
||||
{
|
||||
APIGroups: []string{""},
|
||||
Resources: []string{"pods"},
|
||||
Verbs: []string{"get"},
|
||||
},
|
||||
},
|
||||
},
|
||||
update: rbac.ClusterRole{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "role", ResourceVersion: "1"},
|
||||
Rules: []rbac.PolicyRule{
|
||||
{
|
||||
APIGroups: []string{""},
|
||||
Resources: []string{"pods"},
|
||||
Verbs: []string{"get", "list"},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErrs: field.ErrorList{},
|
||||
},
|
||||
}
|
||||
for k, tc := range testCases {
|
||||
t.Run(k, func(t *testing.T) {
|
||||
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.update, &tc.old, Strategy.ValidateUpdate, tc.expectedErrs)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@ package clusterrole
|
|||
import (
|
||||
"context"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/operation"
|
||||
metav1validation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
|
|
@ -75,7 +76,16 @@ func (strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorLis
|
|||
opts := validation.ClusterRoleValidationOptions{
|
||||
AllowInvalidLabelValueInSelector: false,
|
||||
}
|
||||
return validation.ValidateClusterRole(clusterRole, opts)
|
||||
allErrs := validation.ValidateClusterRole(clusterRole, opts)
|
||||
|
||||
return rest.ValidateDeclarativelyWithMigrationChecks(
|
||||
ctx,
|
||||
legacyscheme.Scheme,
|
||||
clusterRole,
|
||||
nil,
|
||||
allErrs,
|
||||
operation.Create,
|
||||
)
|
||||
}
|
||||
|
||||
// WarningsOnCreate returns warnings for the creation of the given object.
|
||||
|
|
@ -93,7 +103,16 @@ func (strategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) fie
|
|||
opts := validation.ClusterRoleValidationOptions{
|
||||
AllowInvalidLabelValueInSelector: hasInvalidLabelValueInLabelSelector(oldObj),
|
||||
}
|
||||
return validation.ValidateClusterRoleUpdate(newObj, old.(*rbac.ClusterRole), opts)
|
||||
errs := validation.ValidateClusterRoleUpdate(newObj, oldObj, opts)
|
||||
|
||||
return rest.ValidateDeclarativelyWithMigrationChecks(
|
||||
ctx,
|
||||
legacyscheme.Scheme,
|
||||
newObj,
|
||||
oldObj,
|
||||
errs,
|
||||
operation.Update,
|
||||
)
|
||||
}
|
||||
|
||||
// WarningsOnUpdate returns warnings for the given update.
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ const (
|
|||
type PolicyRule struct {
|
||||
// Verbs is a list of Verbs that apply to ALL the ResourceKinds contained in this rule. '*' represents all verbs.
|
||||
// +listType=atomic
|
||||
// +k8s:required
|
||||
Verbs []string `json:"verbs" protobuf:"bytes,1,rep,name=verbs"`
|
||||
|
||||
// APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ const (
|
|||
type PolicyRule struct {
|
||||
// Verbs is a list of Verbs that apply to ALL the ResourceKinds contained in this rule. '*' represents all verbs.
|
||||
// +listType=atomic
|
||||
// +k8s:required
|
||||
Verbs []string `json:"verbs" protobuf:"bytes,1,rep,name=verbs"`
|
||||
|
||||
// APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ const (
|
|||
type PolicyRule struct {
|
||||
// Verbs is a list of Verbs that apply to ALL the ResourceKinds contained in this rule. '*' represents all verbs.
|
||||
// +listType=atomic
|
||||
// +k8s:required
|
||||
Verbs []string `json:"verbs" protobuf:"bytes,1,rep,name=verbs"`
|
||||
|
||||
// APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of
|
||||
|
|
|
|||
Loading…
Reference in a new issue