@@ -18,8 +18,10 @@ import (
18
18
"fmt"
19
19
20
20
awssdkmodel "github.com/aws-controllers-k8s/code-generator/pkg/api"
21
+ simpleschema "github.com/kro-run/kro/pkg/simpleschema"
21
22
22
23
ackmodel "github.com/aws-controllers-k8s/code-generator/pkg/model"
24
+ apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
23
25
)
24
26
25
27
var (
@@ -41,11 +43,11 @@ type customShapeInjector struct {
41
43
// into the list of shapes in the API and update the list of custom shapes in
42
44
// the SDKAPI object.
43
45
func (h * Helper ) InjectCustomShapes (sdkapi * ackmodel.SDKAPI ) error {
44
- err := h .InjectSimpleSchemaShapes (sdkapi )
45
- if err != nil {
46
+ injector := customShapeInjector {sdkapi }
47
+
48
+ if err := injector .injectSimpleSchemaShapes (h .cfg .CustomShapes ); err != nil {
46
49
return err
47
50
}
48
- injector := customShapeInjector {sdkapi }
49
51
50
52
for _ , memberShape := range h .cfg .GetCustomMapFieldMembers () {
51
53
customShape , err := injector .newMap (memberShape )
@@ -68,6 +70,96 @@ func (h *Helper) InjectCustomShapes(sdkapi *ackmodel.SDKAPI) error {
68
70
return nil
69
71
}
70
72
73
+ // injectSimpleSchemaShapes processes custom shapes from the top-level custom_shapes
74
+ // section and injects them into the SDK API model.
75
+ // Only string types are supported - all other types will cause a panic.
76
+ func (i * customShapeInjector ) injectSimpleSchemaShapes (customShapes map [string ]map [string ]interface {}) error {
77
+ if len (customShapes ) == 0 {
78
+ return nil
79
+ }
80
+
81
+ apiShapeNames := i .sdkAPI .API .ShapeNames ()
82
+ for shapeName , fieldsMap := range customShapes {
83
+ // check for duplicates
84
+ for _ , as := range apiShapeNames {
85
+ if as == shapeName {
86
+ return fmt .Errorf ("CustomType name %s already exists in the API" , shapeName )
87
+ }
88
+ }
89
+ schemaObj := convertMapValues (fieldsMap )
90
+ openAPISchema , err := simpleschema .ToOpenAPISpec (schemaObj )
91
+ if err != nil {
92
+ return err
93
+ }
94
+
95
+ // Create and register the base structure shape
96
+ shape , shapeRef := i .newStructureShape (shapeName , openAPISchema )
97
+ i .sdkAPI .API .Shapes [shape .ShapeName ] = shape
98
+ i .sdkAPI .CustomShapes = append (i .sdkAPI .CustomShapes , & ackmodel.CustomShape {
99
+ Shape : shape ,
100
+ ShapeRef : shapeRef ,
101
+ MemberShapeName : nil ,
102
+ ValueShapeName : nil ,
103
+ })
104
+ }
105
+
106
+ return nil
107
+ }
108
+
109
+ // convertMapValues converts a fields map to a schema object for OpenAPI spec generation
110
+ func convertMapValues (fieldsMap map [string ]interface {}) map [string ]interface {} {
111
+ schemaObj := make (map [string ]interface {})
112
+ for fieldName , fieldType := range fieldsMap {
113
+ schemaObj [fieldName ] = fieldType
114
+ }
115
+ return schemaObj
116
+ }
117
+
118
+ // newStructureShape creates a base shape with its member fields
119
+ func (i * customShapeInjector ) newStructureShape (
120
+ shapeName string ,
121
+ openAPISchema * apiextv1.JSONSchemaProps ,
122
+ ) (* awssdkmodel.Shape , * awssdkmodel.ShapeRef ) {
123
+ shape := & awssdkmodel.Shape {
124
+ API : i .sdkAPI .API ,
125
+ ShapeName : shapeName ,
126
+ Type : "structure" ,
127
+ Documentation : "// Custom ACK type for " + shapeName ,
128
+ MemberRefs : make (map [string ]* awssdkmodel.ShapeRef ),
129
+ }
130
+
131
+ properties := openAPISchema .Properties
132
+ for fieldName , propObj := range properties {
133
+ propType := propObj .Type
134
+ if propType != "string" {
135
+ panic (fmt .Sprintf ("Field %s in shape %s has non-string type '%s'" ,
136
+ fieldName , shapeName , propType ))
137
+ }
138
+ addStringFieldToShape (i .sdkAPI , shape , fieldName , shapeName )
139
+ }
140
+
141
+ shapeRef := i .createShapeRefForMember (shape )
142
+ return shape , shapeRef
143
+ }
144
+
145
+ // addStringFieldToShape adds a string field to the parent shape
146
+ func addStringFieldToShape (
147
+ sdkapi * ackmodel.SDKAPI ,
148
+ parentShape * awssdkmodel.Shape ,
149
+ fieldName string ,
150
+ shapeName string ,
151
+ ) {
152
+ injector := customShapeInjector {sdkapi }
153
+ fieldShape := & awssdkmodel.Shape {
154
+ API : sdkapi .API ,
155
+ ShapeName : fieldName ,
156
+ Type : "string" ,
157
+ }
158
+
159
+ sdkapi .API .Shapes [fieldShape .ShapeName ] = fieldShape
160
+ parentShape .MemberRefs [fieldName ] = injector .createShapeRefForMember (fieldShape )
161
+ }
162
+
71
163
// createShapeRefForMember creates a minimal ShapeRef type to encapsulate a
72
164
// shape.
73
165
func (i * customShapeInjector ) createShapeRefForMember (shape * awssdkmodel.Shape ) * awssdkmodel.ShapeRef {
0 commit comments