@@ -17,142 +17,13 @@ limitations under the License.
17
17
package validations
18
18
19
19
import (
20
- "bufio"
21
- "fmt"
22
- "io/ioutil"
23
- "net/http"
24
- "os"
25
20
"regexp"
26
21
"sort"
27
22
"strings"
28
23
29
- "sigs. k8s.io/yaml "
24
+ "k8s.io/enhancements/pkg/kepval/util "
30
25
)
31
26
32
- type KeyMustBeSpecified struct {
33
- key interface {}
34
- }
35
-
36
- func (k * KeyMustBeSpecified ) Error () string {
37
- return fmt .Sprintf ("missing key %[1]v" , k .key )
38
- }
39
-
40
- type KeyMustBeString struct {
41
- key interface {}
42
- }
43
-
44
- func (k * KeyMustBeString ) Error () string {
45
- return fmt .Sprintf ("key %[1]v must be a string but it is a %[1]T" , k .key )
46
- }
47
-
48
- type ValueMustBeString struct {
49
- key string
50
- value interface {}
51
- }
52
-
53
- func (v * ValueMustBeString ) Error () string {
54
- return fmt .Sprintf ("%q must be a string but it is a %T: %v" , v .key , v .value , v .value )
55
- }
56
-
57
- type ValueMustBeOneOf struct {
58
- key string
59
- value string
60
- values []string
61
- }
62
-
63
- func (v * ValueMustBeOneOf ) Error () string {
64
- return fmt .Sprintf ("%q must be one of (%s) but it is a %T: %v" , v .key , strings .Join (v .values , "," ), v .value , v .value )
65
- }
66
-
67
- type ValueMustBeListOfStrings struct {
68
- key string
69
- value interface {}
70
- }
71
-
72
- func (v * ValueMustBeListOfStrings ) Error () string {
73
- return fmt .Sprintf ("%q must be a list of strings: %v" , v .key , v .value )
74
- }
75
-
76
- type MustHaveOneValue struct {
77
- key string
78
- }
79
-
80
- func (m * MustHaveOneValue ) Error () string {
81
- return fmt .Sprintf ("%q must have a value" , m .key )
82
- }
83
-
84
- type MustHaveAtLeastOneValue struct {
85
- key string
86
- }
87
-
88
- func (m * MustHaveAtLeastOneValue ) Error () string {
89
- return fmt .Sprintf ("%q must have at least one value" , m .key )
90
- }
91
-
92
- var (
93
- listGroups []string
94
- prrApprovers []string
95
- )
96
-
97
- func Sigs () []string {
98
- return listGroups
99
- }
100
-
101
- func init () {
102
- resp , err := http .Get ("https://raw.githubusercontent.com/kubernetes/community/master/sigs.yaml" )
103
- if err != nil {
104
- fmt .Fprintf (os .Stderr , "unable to fetch list of sigs: %v\n " , err )
105
- os .Exit (1 )
106
- }
107
- defer resp .Body .Close ()
108
- if resp .StatusCode != http .StatusOK {
109
- fmt .Fprintf (os .Stderr , "invalid status code when fetching list of sigs: %d\n " , resp .StatusCode )
110
- os .Exit (1 )
111
- }
112
- re := regexp .MustCompile (`- dir: (.*)$` )
113
-
114
- scanner := bufio .NewScanner (resp .Body )
115
- for scanner .Scan () {
116
- match := re .FindStringSubmatch (scanner .Text ())
117
- if len (match ) > 0 {
118
- listGroups = append (listGroups , match [1 ])
119
- }
120
- }
121
- if err := scanner .Err (); err != nil {
122
- fmt .Fprintf (os .Stderr , "unable to scan list of sigs: %v\n " , err )
123
- os .Exit (1 )
124
- }
125
- sort .Strings (listGroups )
126
-
127
- resp , err = http .Get ("https://raw.githubusercontent.com/kubernetes/enhancements/master/OWNERS_ALIASES" )
128
- if err != nil {
129
- fmt .Fprintf (os .Stderr , "unable to fetch list of aliases: %v\n " , err )
130
- os .Exit (1 )
131
- }
132
- defer resp .Body .Close ()
133
- if resp .StatusCode != http .StatusOK {
134
- fmt .Fprintf (os .Stderr , "invalid status code when fetching list of aliases: %d\n " , resp .StatusCode )
135
- os .Exit (1 )
136
- }
137
-
138
- body , err := ioutil .ReadAll (resp .Body )
139
- if err != nil {
140
- fmt .Fprintf (os .Stderr , "unable to read aliases content: %v\n " , err )
141
- os .Exit (1 )
142
- }
143
- config := & struct {
144
- Data map [string ][]string `json:"aliases,omitempty"`
145
- }{}
146
- if err := yaml .Unmarshal (body , config ); err != nil {
147
- fmt .Fprintf (os .Stderr , "unable to read parse aliases content: %v\n " , err )
148
- os .Exit (1 )
149
- }
150
- for _ , approver := range config .Data ["prod-readiness-approvers" ] {
151
- prrApprovers = append (prrApprovers , approver )
152
- }
153
- sort .Strings (listGroups )
154
- }
155
-
156
27
var (
157
28
mandatoryKeys = []string {"title" , "owning-sig" }
158
29
statuses = []string {"provisional" , "implementable" , "implemented" , "deferred" , "rejected" , "withdrawn" , "replaced" }
@@ -164,15 +35,18 @@ var (
164
35
func ValidateStructure (parsed map [interface {}]interface {}) error {
165
36
for _ , key := range mandatoryKeys {
166
37
if _ , found := parsed [key ]; ! found {
167
- return & KeyMustBeSpecified { key }
38
+ return util . NewKeyMustBeSpecified ( key )
168
39
}
169
40
}
170
41
42
+ listGroups := util .Groups ()
43
+ prrApprovers := util .PRRApprovers ()
44
+
171
45
for key , value := range parsed {
172
46
// First off the key has to be a string. fact.
173
47
k , ok := key .(string )
174
48
if ! ok {
175
- return & KeyMustBeString { k }
49
+ return util . NewKeyMustBeString ( k )
176
50
}
177
51
empty := value == nil
178
52
@@ -181,30 +55,30 @@ func ValidateStructure(parsed map[interface{}]interface{}) error {
181
55
case "status" :
182
56
switch v := value .(type ) {
183
57
case []interface {}:
184
- return & ValueMustBeString { k , v }
58
+ return util . NewValueMustBeString ( k , v )
185
59
}
186
60
v , _ := value .(string )
187
61
if ! reStatus .Match ([]byte (v )) {
188
- return & ValueMustBeOneOf { k , v , statuses }
62
+ return util . NewValueMustBeOneOf ( k , v , statuses )
189
63
}
190
64
case "stage" :
191
65
switch v := value .(type ) {
192
66
case []interface {}:
193
- return & ValueMustBeString { k , v }
67
+ return util . NewValueMustBeString ( k , v )
194
68
}
195
69
v , _ := value .(string )
196
70
if ! reStages .Match ([]byte (v )) {
197
- return & ValueMustBeOneOf { k , v , stages }
71
+ return util . NewValueMustBeOneOf ( k , v , stages )
198
72
}
199
73
case "owning-sig" :
200
74
switch v := value .(type ) {
201
75
case []interface {}:
202
- return & ValueMustBeString { k , v }
76
+ return util . NewValueMustBeString ( k , v )
203
77
}
204
78
v , _ := value .(string )
205
79
index := sort .SearchStrings (listGroups , v )
206
80
if index >= len (listGroups ) || listGroups [index ] != v {
207
- return & ValueMustBeOneOf { k , v , listGroups }
81
+ return util . NewValueMustBeOneOf ( k , v , listGroups )
208
82
}
209
83
// optional strings
210
84
case "editor" :
@@ -215,14 +89,14 @@ func ValidateStructure(parsed map[interface{}]interface{}) error {
215
89
case "title" , "creation-date" , "last-updated" :
216
90
switch v := value .(type ) {
217
91
case []interface {}:
218
- return & ValueMustBeString { k , v }
92
+ return util . NewValueMustBeString ( k , v )
219
93
}
220
94
v , ok := value .(string )
221
95
if ok && v == "" {
222
- return & MustHaveOneValue { k }
96
+ return util . NewMustHaveOneValue ( k )
223
97
}
224
98
if ! ok {
225
- return & ValueMustBeString { k , v }
99
+ return util . NewValueMustBeString ( k , v )
226
100
}
227
101
// These are optional lists, so skip if there is no value
228
102
case "participating-sigs" , "replaces" , "superseded-by" , "see-also" :
@@ -243,19 +117,19 @@ func ValidateStructure(parsed map[interface{}]interface{}) error {
243
117
switch values := value .(type ) {
244
118
case []interface {}:
245
119
if len (values ) == 0 {
246
- return & MustHaveAtLeastOneValue { k }
120
+ return util . NewMustHaveAtLeastOneValue ( k )
247
121
}
248
122
if strings .ToLower (k ) == "participating-sigs" {
249
123
for _ , value := range values {
250
124
v := value .(string )
251
125
index := sort .SearchStrings (listGroups , v )
252
126
if index >= len (listGroups ) || listGroups [index ] != v {
253
- return & ValueMustBeOneOf { k , v , listGroups }
127
+ return util . NewValueMustBeOneOf ( k , v , listGroups )
254
128
}
255
129
}
256
130
}
257
131
case interface {}:
258
- return & ValueMustBeListOfStrings { k , values }
132
+ return util . NewValueMustBeListOfStrings ( k , values )
259
133
}
260
134
case "prr-approvers" :
261
135
switch values := value .(type ) {
@@ -271,11 +145,11 @@ func ValidateStructure(parsed map[interface{}]interface{}) error {
271
145
272
146
index := sort .SearchStrings (prrApprovers , v )
273
147
if index >= len (prrApprovers ) || prrApprovers [index ] != v {
274
- return & ValueMustBeOneOf { k , v , prrApprovers }
148
+ return util . NewValueMustBeOneOf ( k , v , prrApprovers )
275
149
}
276
150
}
277
151
case interface {}:
278
- return & ValueMustBeListOfStrings { k , values }
152
+ return util . NewValueMustBeListOfStrings ( k , values )
279
153
}
280
154
}
281
155
}
0 commit comments