Skip to content

cue/cmd: import crd for importing Kubernetes CustomResourceDefinitions #2701

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 21 commits into
base: master
Choose a base branch
from
Draft
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
more
justenstall committed Nov 20, 2023
commit 5cc67007f1e4088b58ee536ced2d571ba1b93a30
136 changes: 69 additions & 67 deletions encoding/crd/decode.go
Original file line number Diff line number Diff line change
@@ -514,6 +514,70 @@ func xKubernetesAttributes(path []cue.Selector, prop v1.JSONSchemaProps) []struc
return extensions
}

// Preserves Kubernetes OpenAPI extensions in an attribute for each field utilizing them
func mapAttributes(val cue.Value, prop v1.JSONSchemaProps) cue.Value {
attr := xk8sattr(*val.Context(), prop)
if attr != nil {
_, p := val.ReferencePath()
fmt.Println(p.String() + ": " + attr.Text)
node := val.Source()
switch x := node.(type) {
case *ast.StructLit:
x.Elts = append(x.Elts, attr)
case *ast.Field:
x.Attrs = append(x.Attrs, attr)
case *ast.File:
x.Decls = append(x.Decls, attr)
default:
// fmt.Println(attrPath)
// fmt.Printf("extendedVal: %v\n\n", extendedVal)
// fmt.Println(reflect.TypeOf(node))
// fmt.Printf("node: %v\n", node)
}
}

for name := range prop.Properties {
// Recursively add subextensions for each property
nextPath := cue.MakePath(cue.Str(name))
nextVal := mapAttributes(val.LookupPath(nextPath), prop.Properties[name])
val = val.FillPath(nextPath, nextVal)
}

// TODO: array does not work right, see https://github.com/istio/istio/blob/0d5f530188dfe571bf0d8f515618ba99a0dc3e6c/manifests/charts/base/crds/crd-all.gen.yaml#L188
if prop.Type == "array" {
if len(prop.Items.JSONSchemas) > 0 {
iter, err := val.List()
if err != nil {
fmt.Println(err)
}
// Iterate each schema in list and add attribute for that list index
for i := range prop.Items.JSONSchemas {
// Add attribute to the item at index i
if !iter.Next() {
break
}
nextVal := iter.Value()
val = val.FillPath(nextVal.Path(), mapAttributes(nextVal, prop.Items.JSONSchemas[i]))
}
} else {
// if val.Allows(cue.AnyIndex) {
anyIndex := cue.MakePath(cue.AnyIndex)
nextVal := mapAttributes(val.LookupPath(anyIndex), *prop.Items.Schema)
val = val.FillPath(anyIndex, nextVal)
// } else {
// fmt.Println("here")
// }

// Add attribute to the pattern constraint
// // Recursively add subextensions for each property
// subExts := xKubernetesAttributes(append(path, cue.AnyIndex), *prop.Items.Schema)
// extensions = append(extensions, subExts...)
}
}

return val
}

// TODO: use internal.Attr if it can support writing attributes
type attr struct {
name string
@@ -528,16 +592,6 @@ func (a attr) String() string {
return fmt.Sprintf("@%s(%s)", a.name, strings.Join(fields, ", "))
}

func addAttr(field ast.Label, a attr) *ast.Field {
return &ast.Field{
Label: field,
Value: ast.NewIdent("_"),
Attrs: []*ast.Attribute{
{Text: a.String()},
},
}
}

type keyval struct {
key string
val string
@@ -550,8 +604,7 @@ func (kv keyval) String() string {
return kv.key
}

// Preserves Kubernetes OpenAPI extensions in an attribute for each field utilizing them
func mapAttributes(val cue.Value, prop v1.JSONSchemaProps) cue.Value {
func xk8sattr(ctx cue.Context, prop v1.JSONSchemaProps) *ast.Attribute {
a := attr{
name: "crd",
fields: []keyval{},
@@ -576,7 +629,7 @@ func mapAttributes(val cue.Value, prop v1.JSONSchemaProps) cue.Value {
}

if len(prop.XListMapKeys) > 0 {
appendField(XListMapKeys, fmt.Sprint(val.Context().Encode(prop.XListMapKeys)))
appendField(XListMapKeys, fmt.Sprint(ctx.Encode(prop.XListMapKeys)))
}

if prop.XListType != nil {
@@ -588,63 +641,12 @@ func mapAttributes(val cue.Value, prop v1.JSONSchemaProps) cue.Value {
}

if len(prop.XValidations) > 0 {
appendField(XValidations, fmt.Sprint(val.Context().Encode(prop.XValidations)))
appendField(XValidations, fmt.Sprint(ctx.Encode(prop.XValidations)))
}

if len(a.fields) > 0 {
attr := &ast.Attribute{Text: a.String()}
node := val.Source()
switch x := node.(type) {
case *ast.StructLit:
x.Elts = append(x.Elts, attr)
case *ast.Field:
x.Attrs = append(x.Attrs, attr)
case *ast.File:
x.Decls = append(x.Decls, attr)
default:
// fmt.Println(attrPath)
// fmt.Printf("extendedVal: %v\n\n", extendedVal)
// fmt.Println(reflect.TypeOf(node))
// fmt.Printf("node: %v\n", node)
}
return &ast.Attribute{Text: a.String()}
}

for name := range prop.Properties {
// Recursively add subextensions for each property
nextPath := cue.MakePath(cue.Str(name))
nextVal := mapAttributes(val.LookupPath(nextPath), prop.Properties[name])
val = val.FillPath(nextPath, nextVal)
}

// TODO: array does not work right, see https://github.com/istio/istio/blob/0d5f530188dfe571bf0d8f515618ba99a0dc3e6c/manifests/charts/base/crds/crd-all.gen.yaml#L188
if prop.Type == "array" {
if len(prop.Items.JSONSchemas) > 0 {
iter, err := val.List()
if err != nil {
fmt.Println(err)
}
// Iterate each schema in list and add attribute for that list index
for i := range prop.Items.JSONSchemas {
// Add attribute to the item at index i
if !iter.Next() {
break
}
nextVal := iter.Value()
val = val.FillPath(nextVal.Path(), mapAttributes(nextVal, prop.Items.JSONSchemas[i]))
}
} else {
if val.Allows(cue.AnyIndex) {
anyIndex := cue.MakePath(cue.AnyIndex)
nextVal := mapAttributes(val.LookupPath(anyIndex), *prop.Items.Schema)
val = val.FillPath(anyIndex, nextVal)
}

// Add attribute to the pattern constraint
// // Recursively add subextensions for each property
// subExts := xKubernetesAttributes(append(path, cue.AnyIndex), *prop.Items.Schema)
// extensions = append(extensions, subExts...)
}
}

return val
return nil
}