Skip to content

Commit 6305055

Browse files
jpbetzthockinaaron-prindleyongruilin
committed
Add validators: optional/required/forbidden
Co-authored-by: Tim Hockin <[email protected]> Co-authored-by: Aaron Prindle <[email protected]> Co-authored-by: Yongrui Lin <[email protected]>
1 parent 31f4637 commit 6305055

File tree

4 files changed

+1308
-0
lines changed

4 files changed

+1308
-0
lines changed
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package validate
18+
19+
import (
20+
"context"
21+
22+
"k8s.io/apimachinery/pkg/api/operation"
23+
"k8s.io/apimachinery/pkg/util/validation/field"
24+
)
25+
26+
// RequiredValue verifies that the specified value is not the zero-value for
27+
// its type.
28+
func RequiredValue[T comparable](_ context.Context, _ operation.Operation, fldPath *field.Path, value, _ *T) field.ErrorList {
29+
var zero T
30+
if *value != zero {
31+
return nil
32+
}
33+
return field.ErrorList{field.Required(fldPath, "")}
34+
}
35+
36+
// RequiredPointer verifies that the specified pointer is not nil.
37+
func RequiredPointer[T any](_ context.Context, _ operation.Operation, fldPath *field.Path, value, _ *T) field.ErrorList {
38+
if value != nil {
39+
return nil
40+
}
41+
return field.ErrorList{field.Required(fldPath, "")}
42+
}
43+
44+
// RequiredSlice verifies that the specified slice is not empty.
45+
func RequiredSlice[T any](_ context.Context, _ operation.Operation, fldPath *field.Path, value, _ []T) field.ErrorList {
46+
if len(value) > 0 {
47+
return nil
48+
}
49+
return field.ErrorList{field.Required(fldPath, "")}
50+
}
51+
52+
// RequiredMap verifies that the specified map is not empty.
53+
func RequiredMap[K comparable, T any](_ context.Context, _ operation.Operation, fldPath *field.Path, value, _ map[K]T) field.ErrorList {
54+
if len(value) > 0 {
55+
return nil
56+
}
57+
return field.ErrorList{field.Required(fldPath, "")}
58+
}
59+
60+
// ForbiddenValue verifies that the specified value is the zero-value for its
61+
// type.
62+
func ForbiddenValue[T comparable](_ context.Context, _ operation.Operation, fldPath *field.Path, value, _ *T) field.ErrorList {
63+
var zero T
64+
if *value == zero {
65+
return nil
66+
}
67+
return field.ErrorList{field.Forbidden(fldPath, "")}
68+
}
69+
70+
// ForbiddenPointer verifies that the specified pointer is nil.
71+
func ForbiddenPointer[T any](_ context.Context, _ operation.Operation, fldPath *field.Path, value, _ *T) field.ErrorList {
72+
if value == nil {
73+
return nil
74+
}
75+
return field.ErrorList{field.Forbidden(fldPath, "")}
76+
}
77+
78+
// ForbiddenSlice verifies that the specified slice is empty.
79+
func ForbiddenSlice[T any](_ context.Context, _ operation.Operation, fldPath *field.Path, value, _ []T) field.ErrorList {
80+
if len(value) == 0 {
81+
return nil
82+
}
83+
return field.ErrorList{field.Forbidden(fldPath, "")}
84+
}
85+
86+
// RequiredMap verifies that the specified map is empty.
87+
func ForbiddenMap[K comparable, T any](_ context.Context, _ operation.Operation, fldPath *field.Path, value, _ map[K]T) field.ErrorList {
88+
if len(value) == 0 {
89+
return nil
90+
}
91+
return field.ErrorList{field.Forbidden(fldPath, "")}
92+
}
93+
94+
// OptionalValue verifies that the specified value is not the zero-value for
95+
// its type. This is identical to RequiredValue, but the caller should treat an
96+
// error here as an indication that the optional value was not specified.
97+
func OptionalValue[T comparable](_ context.Context, _ operation.Operation, fldPath *field.Path, value, _ *T) field.ErrorList {
98+
var zero T
99+
if *value != zero {
100+
return nil
101+
}
102+
return field.ErrorList{field.Required(fldPath, "optional value was not specified")}
103+
}
104+
105+
// OptionalPointer verifies that the specified pointer is not nil. This is
106+
// identical to RequiredPointer, but the caller should treat an error here as an
107+
// indication that the optional value was not specified.
108+
func OptionalPointer[T any](_ context.Context, _ operation.Operation, fldPath *field.Path, value, _ *T) field.ErrorList {
109+
if value != nil {
110+
return nil
111+
}
112+
return field.ErrorList{field.Required(fldPath, "optional value was not specified")}
113+
}
114+
115+
// OptionalSlice verifies that the specified slice is not empty. This is
116+
// identical to RequiredSlice, but the caller should treat an error here as an
117+
// indication that the optional value was not specified.
118+
func OptionalSlice[T any](_ context.Context, _ operation.Operation, fldPath *field.Path, value, _ []T) field.ErrorList {
119+
if len(value) > 0 {
120+
return nil
121+
}
122+
return field.ErrorList{field.Required(fldPath, "optional value was not specified")}
123+
}
124+
125+
// OptionalMap verifies that the specified map is not empty. This is identical
126+
// to RequiredMap, but the caller should treat an error here as an indication that
127+
// the optional value was not specified.
128+
func OptionalMap[K comparable, T any](_ context.Context, _ operation.Operation, fldPath *field.Path, value, _ map[K]T) field.ErrorList {
129+
if len(value) > 0 {
130+
return nil
131+
}
132+
return field.ErrorList{field.Required(fldPath, "optional value was not specified")}
133+
}

0 commit comments

Comments
 (0)