@@ -20,9 +20,11 @@ import (
20
20
"encoding/json"
21
21
"errors"
22
22
"fmt"
23
+ "reflect"
23
24
"regexp"
24
25
"strconv"
25
26
"strings"
27
+ "sync"
26
28
27
29
"k8s.io/gengo/v2/types"
28
30
openapi "k8s.io/kube-openapi/pkg/common"
@@ -61,6 +63,26 @@ func (c *CELTag) Validate() error {
61
63
return nil
62
64
}
63
65
66
+ func isKnownTagCommentKey (key string ) bool {
67
+ commentTag , _ , _ := strings .Cut (key , ":" )
68
+ _ , ok := tagKeys ()[commentTag ]
69
+ return ok
70
+ }
71
+
72
+ var tagKeys = sync .OnceValue (func () map [string ]struct {} {
73
+ result := map [string ]struct {}{}
74
+ t := reflect .TypeOf (commentTags {})
75
+ for i := 0 ; i < t .NumField (); i ++ {
76
+ field := t .Field (i )
77
+ if jsonTag := field .Tag .Get ("json" ); jsonTag != "" {
78
+ if key , _ , _ := strings .Cut (jsonTag , "," ); key != "" {
79
+ result [key ] = struct {}{}
80
+ }
81
+ }
82
+ }
83
+ return result
84
+ })
85
+
64
86
// commentTags represents the parsed comment tags for a given type. These types are then used to generate schema validations.
65
87
// These only include the newer prefixed tags. The older tags are still supported,
66
88
// but are not included in this struct. Comment Tags are transformed into a
@@ -385,13 +407,30 @@ func memberWithJSONName(t *types.Type, key string) *types.Member {
385
407
return nil
386
408
}
387
409
388
- // Parses the given comments into a CommentTags type. Validates the parsed comment tags, and returns the result.
410
+ type commentTagsOptions struct {
411
+ ignoreUnknown bool
412
+ }
413
+
414
+ type ParseCommentTagsOptions func (* commentTagsOptions )
415
+
416
+ // IgnoreUnknown returns a ParseCommentTagsOptions that will ignore unknown comment tags.
417
+ func IgnoreUnknown () ParseCommentTagsOptions {
418
+ return func (o * commentTagsOptions ) {
419
+ o .ignoreUnknown = true
420
+ }
421
+ }
422
+
423
+ // ParseCommentTags parses the given comments into a CommentTags type. Validates the parsed comment tags, and returns the result.
389
424
// Accepts an optional type to validate against, and a prefix to filter out markers not related to validation.
390
425
// Accepts a prefix to filter out markers not related to validation.
391
426
// Returns any errors encountered while parsing or validating the comment tags.
392
- func ParseCommentTags (t * types.Type , comments []string , prefix string ) (* spec.Schema , error ) {
427
+ func ParseCommentTags (t * types.Type , comments []string , prefix string , opts ... ParseCommentTagsOptions ) (* spec.Schema , error ) {
428
+ options := commentTagsOptions {}
429
+ for _ , opt := range opts {
430
+ opt (& options )
431
+ }
393
432
394
- markers , err := parseMarkers (comments , prefix )
433
+ markers , err := parseMarkers (comments , prefix , options . ignoreUnknown )
395
434
if err != nil {
396
435
return nil , fmt .Errorf ("failed to parse marker comments: %w" , err )
397
436
}
@@ -597,7 +636,7 @@ func extractCommentTags(marker string, lines []string) (map[string]string, error
597
636
// Accepts a prefix to filter out markers not related to validation.
598
637
// The prefix is removed from the key in the returned map.
599
638
// Empty keys and invalid values will return errors, refs are currently unsupported and will be skipped.
600
- func parseMarkers (markerComments []string , prefix string ) (map [string ]any , error ) {
639
+ func parseMarkers (markerComments []string , prefix string , ignoreUnknown bool ) (map [string ]any , error ) {
601
640
markers , err := extractCommentTags (prefix , markerComments )
602
641
if err != nil {
603
642
return nil , err
@@ -606,6 +645,9 @@ func parseMarkers(markerComments []string, prefix string) (map[string]any, error
606
645
// Parse the values as JSON
607
646
result := map [string ]any {}
608
647
for key , value := range markers {
648
+ if ignoreUnknown && ! isKnownTagCommentKey (key ) {
649
+ continue
650
+ }
609
651
var unmarshalled interface {}
610
652
611
653
if len (key ) == 0 {
0 commit comments