Skip to content

Commit bb996bf

Browse files
committed
Ignore unknown k8s:validation comments tags
1 parent 67ed584 commit bb996bf

File tree

3 files changed

+52
-4
lines changed

3 files changed

+52
-4
lines changed

pkg/generators/markers.go

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ import (
2020
"encoding/json"
2121
"errors"
2222
"fmt"
23+
"reflect"
2324
"regexp"
2425
"strconv"
2526
"strings"
27+
"sync"
2628

2729
"k8s.io/gengo/v2/types"
2830
openapi "k8s.io/kube-openapi/pkg/common"
@@ -61,6 +63,30 @@ func (c *CELTag) Validate() error {
6163
return nil
6264
}
6365

66+
func isKnownTagCommentKey(key string) bool {
67+
split := func(r rune) bool { return r == ':' || r == '[' }
68+
commentTags := strings.FieldsFunc(key, split)
69+
if len(commentTags) == 0 {
70+
return false
71+
}
72+
_, ok := tagKeys()[commentTags[0]]
73+
return ok
74+
}
75+
76+
var tagKeys = sync.OnceValue(func() map[string]struct{} {
77+
result := map[string]struct{}{}
78+
t := reflect.TypeOf(commentTags{})
79+
for i := 0; i < t.NumField(); i++ {
80+
field := t.Field(i)
81+
if jsonTag := field.Tag.Get("json"); jsonTag != "" {
82+
if key, _, _ := strings.Cut(jsonTag, ","); key != "" {
83+
result[key] = struct{}{}
84+
}
85+
}
86+
}
87+
return result
88+
})
89+
6490
// commentTags represents the parsed comment tags for a given type. These types are then used to generate schema validations.
6591
// These only include the newer prefixed tags. The older tags are still supported,
6692
// but are not included in this struct. Comment Tags are transformed into a
@@ -385,12 +411,11 @@ func memberWithJSONName(t *types.Type, key string) *types.Member {
385411
return nil
386412
}
387413

388-
// Parses the given comments into a CommentTags type. Validates the parsed comment tags, and returns the result.
414+
// ParseCommentTags parses the given comments into a CommentTags type. Validates the parsed comment tags, and returns the result.
389415
// Accepts an optional type to validate against, and a prefix to filter out markers not related to validation.
390416
// Accepts a prefix to filter out markers not related to validation.
391417
// Returns any errors encountered while parsing or validating the comment tags.
392418
func ParseCommentTags(t *types.Type, comments []string, prefix string) (*spec.Schema, error) {
393-
394419
markers, err := parseMarkers(comments, prefix)
395420
if err != nil {
396421
return nil, fmt.Errorf("failed to parse marker comments: %w", err)
@@ -610,6 +635,8 @@ func parseMarkers(markerComments []string, prefix string) (map[string]any, error
610635

611636
if len(key) == 0 {
612637
return nil, fmt.Errorf("cannot have empty key for marker comment")
638+
} else if !isKnownTagCommentKey(key) {
639+
continue
613640
} else if _, ok := parseSymbolReference(value, ""); ok {
614641
// Skip ref markers
615642
continue

pkg/generators/markers_test.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"testing"
2020

2121
"github.com/stretchr/testify/require"
22+
2223
"k8s.io/gengo/v2/types"
2324
"k8s.io/kube-openapi/pkg/generators"
2425
"k8s.io/kube-openapi/pkg/validation/spec"
@@ -626,6 +627,7 @@ func TestCommentTags_Validate(t *testing.T) {
626627
comments []string
627628
t *types.Type
628629
errorMessage string
630+
options []generators.ParseCommentTagsOptions
629631
}{
630632
{
631633
name: "invalid minimum type",
@@ -960,11 +962,29 @@ func TestCommentTags_Validate(t *testing.T) {
960962
},
961963
errorMessage: `failed to validate property "name": pattern can only be used on string types`,
962964
},
965+
{
966+
name: "ignore unknown field with unparsable value",
967+
comments: []string{
968+
`+k8s:validation:xyz=a=b`, // a=b is not a valid value
969+
},
970+
t: &types.Type{
971+
Kind: types.Struct,
972+
Name: types.Name{Name: "struct"},
973+
Members: []types.Member{
974+
{
975+
Name: "name",
976+
Type: types.String,
977+
Tags: `json:"name"`,
978+
},
979+
},
980+
},
981+
options: []generators.ParseCommentTagsOptions{generators.IgnoreUnknown()},
982+
},
963983
}
964984

965985
for _, tc := range testCases {
966986
t.Run(tc.name, func(t *testing.T) {
967-
_, err := generators.ParseCommentTags(tc.t, tc.comments, "+k8s:validation:")
987+
_, err := generators.ParseCommentTags(tc.t, tc.comments, "+k8s:validation:", tc.options...)
968988
if tc.errorMessage != "" {
969989
require.Error(t, err)
970990
require.Equal(t, "invalid marker comments: "+tc.errorMessage, err.Error())

pkg/generators/openapi_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/google/go-cmp/cmp"
2828
"golang.org/x/tools/go/packages"
2929
"golang.org/x/tools/go/packages/packagestest"
30+
3031
"k8s.io/gengo/v2/generator"
3132
"k8s.io/gengo/v2/namer"
3233
"k8s.io/gengo/v2/parser"
@@ -2386,7 +2387,7 @@ func TestMarkerComments(t *testing.T) {
23862387
// +k8s:validation:pattern="^foo$[0-9]+"
23872388
StringValue string
23882389
2389-
// +k8s:validation:maxitems=10
2390+
// +k8s:validation:maxItems=10
23902391
// +k8s:validation:minItems=1
23912392
// +k8s:validation:uniqueItems
23922393
ArrayValue []string

0 commit comments

Comments
 (0)