@@ -35,29 +35,11 @@ import (
35
35
// Some special types with predefined schemas.
36
36
// This is to catch cases where solo apis contain recursive definitions
37
37
// Normally these would result in stack-overflow errors when generating the open api schema
38
- // The imperfect solution, is to just genrate an empty object for these types
38
+ // The imperfect solution, is to just generate an empty object for these types
39
39
var specialSoloTypes = map [string ]openapi3.Schema {
40
- "core.solo.io.Status" : {
41
- Type : openapi3 .TypeObject ,
42
- Properties : make (map [string ]* openapi3.SchemaRef ),
43
- ExtensionProps : openapi3.ExtensionProps {
44
- Extensions : map [string ]interface {}{
45
- "x-kubernetes-preserve-unknown-fields" : true ,
46
- },
47
- },
48
- },
49
40
"core.solo.io.Metadata" : {
50
41
Type : openapi3 .TypeObject ,
51
42
},
52
- "ratelimit.api.solo.io.Descriptor" : {
53
- Type : openapi3 .TypeObject ,
54
- Properties : make (map [string ]* openapi3.SchemaRef ),
55
- ExtensionProps : openapi3.ExtensionProps {
56
- Extensions : map [string ]interface {}{
57
- "x-kubernetes-preserve-unknown-fields" : true ,
58
- },
59
- },
60
- },
61
43
"google.protobuf.ListValue" : * openapi3 .NewArraySchema ().WithItems (openapi3 .NewObjectSchema ()),
62
44
"google.protobuf.Struct" : {
63
45
Type : openapi3 .TypeObject ,
@@ -116,31 +98,68 @@ type openapiGenerator struct {
116
98
// @solo.io customization to support enum validation schemas with int or string values
117
99
// we need to support this since some controllers marshal enums as integers and others as strings
118
100
enumAsIntOrString bool
101
+
102
+ // @solo.io customizations to define schemas for certain messages
103
+ customSchemasByMessageName map [string ]openapi3.Schema
119
104
}
120
105
121
106
type DescriptionConfiguration struct {
122
107
// Whether or not to include a description in the generated open api schema
123
108
IncludeDescriptionInSchema bool
124
-
125
- // The maximum number of characters to include in a description
126
- // If IncludeDescriptionsInSchema is set to false, this will be ignored
127
- // A 0 value will be interpreted as "include all characters"
128
- // Default: 0
129
- MaxDescriptionCharacters int
130
109
}
131
110
132
- func newOpenAPIGenerator (model * protomodel.Model , perFile bool , singleFile bool , yaml bool , useRef bool , descriptionConfiguration * DescriptionConfiguration , enumAsIntOrString bool ) * openapiGenerator {
111
+ func newOpenAPIGenerator (
112
+ model * protomodel.Model ,
113
+ perFile bool ,
114
+ singleFile bool ,
115
+ yaml bool ,
116
+ useRef bool ,
117
+ descriptionConfiguration * DescriptionConfiguration ,
118
+ enumAsIntOrString bool ,
119
+ messagesWithEmptySchema []string ,
120
+ ) * openapiGenerator {
133
121
return & openapiGenerator {
134
- model : model ,
135
- perFile : perFile ,
136
- singleFile : singleFile ,
137
- yaml : yaml ,
138
- useRef : useRef ,
139
- descriptionConfiguration : descriptionConfiguration ,
140
- enumAsIntOrString : enumAsIntOrString ,
122
+ model : model ,
123
+ perFile : perFile ,
124
+ singleFile : singleFile ,
125
+ yaml : yaml ,
126
+ useRef : useRef ,
127
+ descriptionConfiguration : descriptionConfiguration ,
128
+ enumAsIntOrString : enumAsIntOrString ,
129
+ customSchemasByMessageName : buildCustomSchemasByMessageName (messagesWithEmptySchema ),
141
130
}
142
131
}
143
132
133
+ // buildCustomSchemasByMessageName name returns a mapping of message name to a pre-defined openapi schema
134
+ // It includes:
135
+ // 1. `specialSoloTypes`, a set of pre-defined schemas
136
+ // 2. `messagesWithEmptySchema`, a list of messages that are injected at runtime that should contain
137
+ // and empty schema which accepts and preserves all fields
138
+ func buildCustomSchemasByMessageName (messagesWithEmptySchema []string ) map [string ]openapi3.Schema {
139
+ schemasByMessageName := make (map [string ]openapi3.Schema )
140
+
141
+ // Initialize the hard-coded values
142
+ for name , schema := range specialSoloTypes {
143
+ schemasByMessageName [name ] = schema
144
+ }
145
+
146
+ // Add the messages that were injected at runtime
147
+ for _ , messageName := range messagesWithEmptySchema {
148
+ emptyMessage := openapi3.Schema {
149
+ Type : openapi3 .TypeObject ,
150
+ Properties : make (map [string ]* openapi3.SchemaRef ),
151
+ ExtensionProps : openapi3.ExtensionProps {
152
+ Extensions : map [string ]interface {}{
153
+ "x-kubernetes-preserve-unknown-fields" : true ,
154
+ },
155
+ },
156
+ }
157
+ schemasByMessageName [messageName ] = emptyMessage
158
+ }
159
+
160
+ return schemasByMessageName
161
+ }
162
+
144
163
func (g * openapiGenerator ) generateOutput (filesToGen map [* protomodel.FileDescriptor ]bool ) (* plugin.CodeGeneratorResponse , error ) {
145
164
response := plugin.CodeGeneratorResponse {}
146
165
@@ -438,13 +457,7 @@ func (g *openapiGenerator) generateDescription(desc protomodel.CoreDesc) string
438
457
return ""
439
458
}
440
459
441
- fullDescription := strings .Join (strings .Fields (t ), " " )
442
- maxCharacters := g .descriptionConfiguration .MaxDescriptionCharacters
443
- if maxCharacters > 0 && len (fullDescription ) > maxCharacters {
444
- // return the first [maxCharacters] characters, including an ellipsis to mark that it has been truncated
445
- return fmt .Sprintf ("%s..." , fullDescription [0 :maxCharacters ])
446
- }
447
- return fullDescription
460
+ return strings .Join (strings .Fields (t ), " " )
448
461
}
449
462
450
463
func (g * openapiGenerator ) fieldType (field * protomodel.FieldDescriptor ) * openapi3.Schema {
@@ -474,7 +487,7 @@ func (g *openapiGenerator) fieldType(field *protomodel.FieldDescriptor) *openapi
474
487
475
488
case descriptor .FieldDescriptorProto_TYPE_MESSAGE :
476
489
msg := field .FieldType .(* protomodel.MessageDescriptor )
477
- if soloSchema , ok := specialSoloTypes [g .absoluteName (msg )]; ok {
490
+ if soloSchema , ok := g . customSchemasByMessageName [g .absoluteName (msg )]; ok {
478
491
// Allow for defining special Solo types
479
492
schema = g .generateSoloMessageSchema (msg , & soloSchema )
480
493
} else if msg .GetOptions ().GetMapEntry () {
0 commit comments