Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
10 changes: 10 additions & 0 deletions integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,16 @@ func TestOpenAPIGeneration(t *testing.T) {
},
wantFiles: []string{"test10/openapiv3.yaml"},
},
{
name: "Test enum with x-enumNames",
id: "test11",
perPackage: false,
genOpts: "yaml=true,single_file=true,use_int_enums=true,enum_names_extensions=x-enumNames;x-enum-values",
inputFiles: map[string][]string{
"test11": {"./testdata/test11/enums.proto"},
},
wantFiles: []string{"test11/openapiv3.yaml"},
},
}

for _, tc := range testcases {
Expand Down
18 changes: 18 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,12 @@ func generate(request pluginpb.CodeGeneratorRequest) (*pluginpb.CodeGeneratorRes
includeDescription := true
multilineDescription := false
enumAsIntOrString := false
enumAsInt := false
protoOneof := false
intNative := false
disableKubeMarkers := false

var enumNamesExtensions []string
var messagesWithEmptySchema []string
var ignoredKubeMarkerSubstrings []string

Expand Down Expand Up @@ -119,6 +121,20 @@ func generate(request pluginpb.CodeGeneratorRequest) (*pluginpb.CodeGeneratorRes
default:
return nil, fmt.Errorf("unknown value '%s' for enum_as_int_or_string", v)
}
} else if k == "use_int_enums" {
switch strings.ToLower(v) {
case "true":
enumAsInt = true
case "false":
enumAsInt = false
default:
return nil, fmt.Errorf("unknown value '%s' for enum_as_int", v)
}
} else if k == "enum_names_extensions" {
enumNamesExtensions = strings.Split(v, ";")
if len(enumNamesExtensions) == 0 {
return nil, fmt.Errorf("cant use '%s' as enum_names_extensions, provide a semicolon separated list", v)
}
} else if k == "proto_oneof" {
switch strings.ToLower(v) {
case "true":
Expand Down Expand Up @@ -185,6 +201,8 @@ func generate(request pluginpb.CodeGeneratorRequest) (*pluginpb.CodeGeneratorRes
useRef,
descriptionConfiguration,
enumAsIntOrString,
enumAsInt,
enumNamesExtensions,
messagesWithEmptySchema,
protoOneof,
intNative,
Expand Down
33 changes: 33 additions & 0 deletions openapiGenerator.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ type openapiGenerator struct {
// we need to support this since some controllers marshal enums as integers and others as strings
enumAsIntOrString bool

enumsAsInt bool

enumNamesExtensions []string

// @solo.io customizations to define schemas for certain messages
customSchemasByMessageName map[string]openapi3.Schema

Expand Down Expand Up @@ -138,6 +142,8 @@ func newOpenAPIGenerator(
useRef bool,
descriptionConfiguration *DescriptionConfiguration,
enumAsIntOrString bool,
enumAsInt bool,
enumNamesExtensions []string,
messagesWithEmptySchema []string,
protoOneof bool,
intNative bool,
Expand All @@ -156,6 +162,8 @@ func newOpenAPIGenerator(
useRef: useRef,
descriptionConfiguration: descriptionConfiguration,
enumAsIntOrString: enumAsIntOrString,
enumsAsInt: enumAsInt,
enumNamesExtensions: enumNamesExtensions,
customSchemasByMessageName: buildCustomSchemasByMessageName(messagesWithEmptySchema),
protoOneof: protoOneof,
intNative: intNative,
Expand Down Expand Up @@ -569,6 +577,14 @@ func (g *openapiGenerator) generateEnum(enum *protomodel.EnumDescriptor, allSche
}

func (g *openapiGenerator) generateEnumSchema(enum *protomodel.EnumDescriptor) *openapi3.Schema {
if !g.enumsAsInt {
g.generateStringEnum(enum)
}

return g.generateIntEnum(enum)
}

func (g *openapiGenerator) generateStringEnum(enum *protomodel.EnumDescriptor) *openapi3.Schema {
/**
The out of the box solution created an enum like:
enum:
Expand Down Expand Up @@ -599,6 +615,23 @@ func (g *openapiGenerator) generateEnumSchema(enum *protomodel.EnumDescriptor) *
o.Enum = append(o.Enum, v.GetName())
}
o.Type = &openapi3.Types{openapi3.TypeString}
return o
}

func (g *openapiGenerator) generateIntEnum(enum *protomodel.EnumDescriptor) *openapi3.Schema {
o := openapi3.NewIntegerSchema()
o.Description = g.generateDescription(enum)

values := enum.GetValue()
var names []string
for _, v := range values {
o.Enum = append(o.Enum, v.GetNumber())
names = append(names, v.GetName())
}
o.Extensions = make(map[string]interface{})
for _, extensionName := range g.enumNamesExtensions {
o.Extensions[extensionName] = names
}

return o
}
Expand Down
35 changes: 35 additions & 0 deletions testdata/golden/test11/openapiv3.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
components:
schemas:
test11.AnotherEnum:
enum:
- 0
- 1
- 2
type: integer
x-enum-values:
- ANOTHER_UNSPECIFIED
- ANOTHER_SOME_NAME
- ANOTHER_ANOTHER_NAME
x-enumNames:
- ANOTHER_UNSPECIFIED
- ANOTHER_SOME_NAME
- ANOTHER_ANOTHER_NAME
test11.MyProtoEnum:
enum:
- 0
- 1
- 2
type: integer
x-enum-values:
- MY_PROTO_UNSPECIFIED
- MY_PROTO_SOME_NAME
- MY_PROTO_ANOTHER_NAME
x-enumNames:
- MY_PROTO_UNSPECIFIED
- MY_PROTO_SOME_NAME
- MY_PROTO_ANOTHER_NAME
info:
title: OpenAPI Spec for Solo APIs.
version: ""
openapi: 3.0.1
paths: null
15 changes: 15 additions & 0 deletions testdata/test11/enums.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
syntax = "proto3";

package test11;

enum MyProtoEnum {
MY_PROTO_UNSPECIFIED = 0;
MY_PROTO_SOME_NAME = 1;
MY_PROTO_ANOTHER_NAME = 2;
}

enum AnotherEnum {
ANOTHER_UNSPECIFIED = 0;
ANOTHER_SOME_NAME = 1;
ANOTHER_ANOTHER_NAME = 2;
}