44package openapi
55
66import (
7+ "encoding/json"
78 "fmt"
89 "sync"
910
@@ -18,49 +19,89 @@ func NewFoundryFromSpecV3(spec []byte) (Foundry, error) {
1819 if err != nil {
1920 return nil , err
2021 }
21- return & foapiv3 {doc : oapi3 }, nil
22+ f := & foapiv3 {doc : oapi3 }
23+
24+ err = f .buildGvkIndex ()
25+ if err != nil {
26+ return nil , fmt .Errorf ("failed to build GVK index when creating new foundry: %w" , err )
27+ }
28+
29+ return f , nil
2230}
2331
24- func SchemaToSpec (key string , crschema map [string ]interface {}) map [string ]interface {} {
25- schema := make (map [string ]interface {})
32+ func CRDSchemaToSpec (gvk schema.GroupVersionKind , crschema map [string ]any ) map [string ]any {
33+
34+ schema := make (map [string ]any )
2635 for k , v := range crschema {
2736 schema [k ] = v
2837 }
29- return map [string ]interface {}{
38+ schema ["x-kubernetes-group-version-kind" ] = []map [string ]any {
39+ {
40+ "group" : gvk .Group ,
41+ "version" : gvk .Version ,
42+ "kind" : gvk .Kind ,
43+ },
44+ }
45+ return map [string ]any {
3046 "openapi" : "3.0" ,
31- "info" : map [string ]interface {} {
47+ "info" : map [string ]any {
3248 "title" : "CRD schema wrapper" ,
3349 "version" : "1.0.0" ,
3450 },
35- "paths" : map [string ]interface {} {},
36- "components" : map [string ]interface {} {
37- "schemas" : map [string ]interface {} {
38- key : schema ,
51+ "paths" : map [string ]any {},
52+ "components" : map [string ]any {
53+ "schemas" : map [string ]any {
54+ "crd-schema" : schema ,
3955 },
4056 },
4157 }
4258}
4359
4460type foapiv3 struct {
4561 doc * openapi3.T
46- gate sync.Mutex
47- typeCache sync.Map
62+ gkvIndex sync.Map
4863}
4964
50- func (f * foapiv3 ) GetTypeByGVK (_ schema.GroupVersionKind ) (tftypes.Type , map [string ]string , error ) {
51- f .gate .Lock ()
52- defer f .gate .Unlock ()
53-
65+ func (f * foapiv3 ) GetTypeByGVK (gvk schema.GroupVersionKind ) (tftypes.Type , map [string ]string , error ) {
5466 var hints map [string ]string = make (map [string ]string )
55- ap := tftypes.AttributePath {}
5667
57- sref := f .doc .Components .Schemas ["" ]
68+ // the ID string that OpenAPI uses to identify the resource
69+ // e.g. "io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"
70+ id , ok := f .gkvIndex .Load (gvk )
71+ if ! ok {
72+ return nil , nil , fmt .Errorf ("resource not found in OpenAPI index" )
73+ }
5874
75+ sref := f .doc .Components .Schemas [id .(string )]
5976 sch , err := resolveSchemaRef (sref , f .doc .Components .Schemas )
6077 if err != nil {
61- return nil , hints , fmt .Errorf ("failed to resolve schema: %s " , err )
78+ return nil , hints , fmt .Errorf ("failed to resolve schema: %w " , err )
6279 }
6380
64- tftype , err := getTypeFromSchema (sch , 50 , & ( f . typeCache ), f . doc .Components .Schemas , ap , hints )
81+ tftype , err := getTypeFromSchema (sch , 50 , f . doc .Components .Schemas , tftypes. AttributePath {} , hints )
6582 return tftype , hints , err
6683}
84+
85+ // buildGvkIndex builds the reverse lookup index that associates each GVK
86+ // to its corresponding string key in the swagger.Definitions map
87+ func (f * foapiv3 ) buildGvkIndex () error {
88+ for did , dRef := range f .doc .Components .Schemas {
89+ def , err := resolveSchemaRef (dRef , f .doc .Components .Schemas )
90+ if err != nil {
91+ return err
92+ }
93+ ex , ok := def .Extensions ["x-kubernetes-group-version-kind" ]
94+ if ! ok {
95+ continue
96+ }
97+ gvk := []schema.GroupVersionKind {}
98+ err = json .Unmarshal (([]byte )(ex .(json.RawMessage )), & gvk )
99+ if err != nil {
100+ return fmt .Errorf ("failed to unmarshall GVK from OpenAPI schema extention: %w" , err )
101+ }
102+ for i := range gvk {
103+ f .gkvIndex .Store (gvk [i ], did )
104+ }
105+ }
106+ return nil
107+ }
0 commit comments