Add OpenAPI extensions to openapi_gen (Definition Generator)

This commit is contained in:
mbohlool 2017-02-03 16:53:53 -08:00
parent 28aa23e5db
commit 317376de30
3 changed files with 70 additions and 8 deletions

View File

@ -2,3 +2,12 @@
- To generate definition for a specific type or package add "+k8s:openapi-gen=true" tag to the type/package comment lines.
- To exclude a type or a member from a tagged package/type, add "+k8s:openapi-gen=false" tag to the comment lines.
# OpenAPI Extensions
OpenAPI spec can have extensions on types. To define one or more extensions on a type or its member
add "+k8s:openapi-gen=x-kubernetes-$NAME:$VALUE" to the comment lines before type/member. A type/member can
have multiple extensions. The rest of the line in the comment will be used as $VALUE so there is no need to
escape or quote the value string. Extensions can be use to pass more information to client generators or
documentation generators. For example a type my have a friendly name to be displayed in documentation or
being used in a client's fluent interface.

View File

@ -40,15 +40,17 @@ const tagOptional = "optional"
// Known values for the tag.
const (
tagValueTrue = "true"
tagValueFalse = "false"
tagValueTrue = "true"
tagValueFalse = "false"
tagExtensionPrefix = "x-kubernetes-"
)
func getOpenAPITagValue(comments []string) []string {
return types.ExtractCommentTags("+", comments)[tagName]
}
func hasOpenAPITagValue(comments []string, value string) bool {
tagValues := types.ExtractCommentTags("+", comments)[tagName]
if tagValues == nil {
return false
}
tagValues := getOpenAPITagValue(comments)
for _, val := range tagValues {
if val == value {
return true
@ -342,6 +344,33 @@ func (g openAPITypeWriter) generate(t *types.Type) error {
}
g.Do("\"$.$\",", k)
}
g.Do("},\n", nil)
if err := g.generateExtensions(t.CommentLines); err != nil {
return err
}
g.Do("},\n", nil)
}
return nil
}
func (g openAPITypeWriter) generateExtensions(CommentLines []string) error {
tagValues := getOpenAPITagValue(CommentLines)
anyExtension := false
for _, val := range tagValues {
if strings.HasPrefix(val, tagExtensionPrefix) {
if !anyExtension {
g.Do("spec.VendorExtensible: {\nExtensions: spec.Extensions{\n", nil)
anyExtension = true
}
parts := strings.SplitN(val, ":", 2)
if len(parts) != 2 {
return fmt.Errorf("Invalid extension value: %v", val)
}
g.Do("\"$.$\": ", parts[0])
g.Do("\"$.$\",\n", parts[1])
}
}
if anyExtension {
g.Do("},\n},\n", nil)
}
return nil
@ -396,6 +425,9 @@ func (g openAPITypeWriter) generateProperty(m *types.Member) error {
return nil
}
g.Do("\"$.$\": {\n", name)
if err := g.generateExtensions(m.CommentLines); err != nil {
return err
}
g.Do("SchemaProps: spec.SchemaProps{\n", nil)
g.generateDescription(m.CommentLines)
jsonTags := getJsonTags(m)

View File

@ -71,7 +71,8 @@ func TestSimple(t *testing.T) {
package foo
// Blah is a test.
// +k8s:openapi=true
// +k8s:openapi-gen=true
// +k8s:openapi-gen=x-kubernetes-type-tag:type_test
type Blah struct {
// A simple string
String string
@ -107,6 +108,9 @@ type Blah struct {
Float32 float32
// a base64 encoded characters
ByteArray []byte
// a member with an extension
// +k8s:openapi-gen=x-kubernetes-member-tag:member_test
WithExtension string
}
`)
if err != nil {
@ -222,12 +226,29 @@ Type: []string{"string"},
Format: "byte",
},
},
"WithExtension": {
spec.VendorExtensible: {
Extensions: spec.Extensions{
"x-kubernetes-member-tag": "member_test",
},
Required: []string{"String","Int64","Int32","Int16","Int8","Uint","Uint64","Uint32","Uint16","Uint8","Byte","Bool","Float64","Float32","ByteArray"},
},
SchemaProps: spec.SchemaProps{
Description: "a member with an extension",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"String","Int64","Int32","Int16","Int8","Uint","Uint64","Uint32","Uint16","Uint8","Byte","Bool","Float64","Float32","ByteArray","WithExtension"},
},
},
Dependencies: []string{
},
spec.VendorExtensible: {
Extensions: spec.Extensions{
"x-kubernetes-type-tag": "type_test",
},
},
},
`, buffer.String())
}