Skip to content

Commit 48a6e9c

Browse files
IfSentientkonsalex
andauthored
[codegen] Support non-string selectable fields of types (#825)
Support non-string selectable fields of types `int` (including `int32` and `int64`), `bool`, and `time.Time`. Field type determination is a bit messy for now. Previously, codegen created non-compiling go code for the `_schema_gen.go` file for a kind if a selectable field type was not a string. This behavior is supported in CRDs, so should also be supported in the API server code created in `_schema_gen.go` for the field. This PR adds a slightly-guesstimating-way of determining the type of each field in the selectable field list, and then formatting that type to a string in the resultant go code. Resolves #809 --------- Co-authored-by: Costa Alexoglou <konsalexee@gmail.com>
1 parent 3ca4ff8 commit 48a6e9c

File tree

3 files changed

+40
-9
lines changed

3 files changed

+40
-9
lines changed

codegen/jennies/schema.go

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ func (s *SchemaGenerator) Generate(kind codegen.Kind) (codejen.Files, error) {
7777
return files, nil
7878
}
7979

80-
func (*SchemaGenerator) getSelectableFields(ver *codegen.KindVersion) ([]templates.SchemaMetadataSeletableField, error) {
81-
fields := make([]templates.SchemaMetadataSeletableField, 0)
80+
func (*SchemaGenerator) getSelectableFields(ver *codegen.KindVersion) ([]templates.SchemaMetadataSelectableField, error) {
81+
fields := make([]templates.SchemaMetadataSelectableField, 0)
8282
if len(ver.SelectableFields) == 0 {
8383
return fields, nil
8484
}
@@ -101,14 +101,24 @@ func (*SchemaGenerator) getSelectableFields(ver *codegen.KindVersion) ([]templat
101101
if val := ver.Schema.LookupPath(cue.MakePath(path...).Optional()); val.Err() == nil {
102102
// Simplest way to check if it's an optional field is to try to look it up as non-optional, then try optional
103103
if lookup := val.LookupPath(cue.MakePath(cue.Str(field))); lookup.Exists() {
104-
fields = append(fields, templates.SchemaMetadataSeletableField{
104+
typ, err := getCUEValueKindString(val, cue.MakePath(cue.Str(field)))
105+
if err != nil {
106+
return nil, fmt.Errorf("invalid selectable field '%s': %w", s, err)
107+
}
108+
fields = append(fields, templates.SchemaMetadataSelectableField{
105109
Field: s,
106110
Optional: false,
111+
Type: typ,
107112
})
108113
} else if optional := val.LookupPath(cue.MakePath(cue.Str(field).Optional())); optional.Exists() {
109-
fields = append(fields, templates.SchemaMetadataSeletableField{
114+
typ, err := getCUEValueKindString(val, cue.MakePath(cue.Str(field).Optional()))
115+
if err != nil {
116+
return nil, fmt.Errorf("invalid selectable field '%s': %w", s, err)
117+
}
118+
fields = append(fields, templates.SchemaMetadataSelectableField{
110119
Field: s,
111120
Optional: true,
121+
Type: typ,
112122
})
113123
} else {
114124
return nil, fmt.Errorf("invalid selectable field path: %s", fieldPath)
@@ -117,3 +127,19 @@ func (*SchemaGenerator) getSelectableFields(ver *codegen.KindVersion) ([]templat
117127
}
118128
return fields, nil
119129
}
130+
131+
func getCUEValueKindString(v cue.Value, path cue.Path) (string, error) {
132+
// This is a kind of messy way of guessing type without having to actually parse the AST
133+
roughType := CUEValueToString(v.LookupPath(path))
134+
switch {
135+
case strings.Contains(roughType, "time.Time"):
136+
return "time", nil
137+
case strings.Contains(roughType, "string"):
138+
return "string", nil
139+
case strings.Contains(roughType, "bool"):
140+
return "bool", nil
141+
case strings.Contains(roughType, "int"):
142+
return "int", nil
143+
}
144+
return "", fmt.Errorf("unsupported type %s, supported types are string, bool, int and time.Time", v.Kind())
145+
}

codegen/templates/schema.tmpl

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,13 @@ var (
2222
}{{ if .Optional }}
2323
if cast.{{$root.ToObjectPath .Field}} == nil {
2424
return "", nil
25-
}
26-
return *cast.{{$root.ToObjectPath .Field}}, nil{{ else }}
27-
return cast.{{$root.ToObjectPath .Field}}, nil{{ end }}
25+
}{{ if eq .Type "string" }}
26+
return *cast.{{$root.ToObjectPath .Field}}, nil{{ else if eq .Type "int" }}
27+
return fmt.Sprintf("%d", *cast.{{$root.ToObjectPath .Field}}), nil{{ else }}
28+
return fmt.Sprintf("%v", *cast.{{$root.ToObjectPath .Field}}), nil{{ end }}{{ else }}{{ if eq .Type "string" }}
29+
return cast.{{$root.ToObjectPath .Field}}, nil{{ else if eq .Type "int" }}
30+
return fmt.Sprintf("%d", cast.{{$root.ToObjectPath .Field}}), nil{{ else }}
31+
return fmt.Sprintf("%v", cast.{{$root.ToObjectPath .Field}}), nil{{ end }}{{ end }}
2832
},
2933
},
3034
{{ end }} }){{ end }})

codegen/templates/templates.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,14 @@ type SchemaMetadata struct {
122122
Kind string
123123
Plural string
124124
Scope string
125-
SelectableFields []SchemaMetadataSeletableField
125+
SelectableFields []SchemaMetadataSelectableField
126126
FuncPrefix string
127127
}
128128

129-
type SchemaMetadataSeletableField struct {
129+
type SchemaMetadataSelectableField struct {
130130
Field string
131131
Optional bool
132+
Type string
132133
}
133134

134135
func (SchemaMetadata) ToObjectPath(s string) string {

0 commit comments

Comments
 (0)