Skip to content

Commit

Permalink
Only add a prefix to enum types if conflicting types have different v…
Browse files Browse the repository at this point in the history
…alues (#157)

* Only add a prefix to enum types if conflicting types have different values.

* Add test

* update
  • Loading branch information
praneetloke authored May 25, 2024
1 parent 26f400a commit 9c4d314
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 6 deletions.
2 changes: 1 addition & 1 deletion pkg/multiple_paths_using_same_refs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
// spec are sometimes processed should not add/remove such a type
// based on which request is processed first.
func TestMultiplePathsUsingSameRef(t *testing.T) {
mustReadTestOpenAPIDoc(t, filepath.Join("testdata", "multiple_paths_using_same_refs.yml"))
mustReadTestOpenAPIDoc(t, filepath.Join("testdata", "multiple_paths_using_same_refs_openapi.yml"))

openAPICtx := &OpenAPIContext{
Doc: *testOpenAPIDoc,
Expand Down
16 changes: 11 additions & 5 deletions pkg/openapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -1401,9 +1401,6 @@ func (ctx *resourceContext) genEnumType(enumName string, propSchema openapi3.Sch
}

typName := ToPascalCase(enumName)
if !strings.HasPrefix(typName, ctx.resourceName) {
typName = ctx.resourceName + enumName
}
tok := fmt.Sprintf("%s:%s:%s", ctx.pkg.Name, ctx.mod, typName)

enumSpec := &pschema.ComplexTypeSpec{
Expand Down Expand Up @@ -1437,8 +1434,17 @@ func (ctx *resourceContext) genEnumType(enumName string, propSchema openapi3.Sch
}

if !same {
msg := fmt.Sprintf("duplicate enum %q: %+v vs. %+v", tok, enumSpec.Enum, other.Enum)
return nil, &duplicateEnumError{msg: msg}
// If the values are not the same and the type
// is not already prefixed with the resource name,
// we'll just use a unique name for it.
if !strings.HasPrefix(typName, ctx.resourceName) {
typName = ctx.resourceName + enumName
tok = fmt.Sprintf("%s:%s:%s", ctx.pkg.Name, ctx.mod, typName)
referencedTypeName = fmt.Sprintf("#/types/%s", tok)
} else {
msg := fmt.Sprintf("duplicate enum %q: %+v vs. %+v", tok, enumSpec.Enum, other.Enum)
return nil, &duplicateEnumError{msg: msg}
}
}

return &pschema.TypeSpec{
Expand Down
42 changes: 42 additions & 0 deletions pkg/prefix_enum_type_on_collision_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package pkg

import (
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
)

// TestGenEnumType tests that schemas that have conflicting
// enums are legal. This is because they can have the
// same enum names but with different values as inline
// enums instead of refs.
func TestGenEnumType(t *testing.T) {
mustReadTestOpenAPIDoc(t, filepath.Join("testdata", "prefix_enum_type_on_collision_openapi.yml"))

openAPICtx := &OpenAPIContext{
Doc: *testOpenAPIDoc,
Pkg: &testPulumiPkg,
}

csharpNamespaces := map[string]string{
"": "Provider",
}

_, _, err := openAPICtx.GatherResourcesFromAPI(csharpNamespaces)
assert.Nil(t, err)

resourceSpec, ok := testPulumiPkg.Resources["fake-package:resource/v2:SomeResource"]
assert.Truef(t, ok, "Expected to find a resource called SomeResource: %v", testPulumiPkg.Resources)

// Due to the ordering of the paths, the type that has an enum prop point to a ref
// would be encountered first and therefore would not have any collision.
assert.Equal(t, "#/types/fake-package:resource/v2:EnumProp", resourceSpec.InputProperties["enumProp"].Ref)

resourceSpec2, ok := testPulumiPkg.Resources["fake-package:resource/v2:SomeOtherResource"]
assert.Truef(t, ok, "Expected to find a resource called SomeOtherResource: %v", testPulumiPkg.Resources)

// When the next operation is encountered, the enum_prop property having an inline
// schema with different values should be renamed with the prefix of the resource.
assert.Equal(t, "#/types/fake-package:resource/v2:SomeOtherResourceEnumProp", resourceSpec2.InputProperties["enumProp"].Ref)
}
77 changes: 77 additions & 0 deletions pkg/testdata/prefix_enum_type_on_collision_openapi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
openapi: 3.1.0
info:
title: Fake API
version: "2.0"
servers:
- url: https://api.fake.com
description: production

components:
schemas:
an_enum_type:
type: string
enum:
- a
- b
- c
a_string_prop:
type: string
request_object_type:
type: object
properties:
simple_prop:
$ref: "#/components/schemas/a_string_prop"
# This prop has a ref to a shared enum type.
enum_prop:
$ref: "#/components/schemas/an_enum_type"
request_object_type2:
type: object
properties:
simple_prop:
$ref: "#/components/schemas/a_string_prop"
# Whereas this prop, also called `enum_prop`
# has an inline schema def.
enum_prop:
type: string
enum:
- d
- e
- f
response_object_type:
type: object
properties:
another_prop:
$ref: "#/components/schemas/a_string_prop"

paths:
/v2/resource/someResource:
post:
operationId: create_some_resource
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/request_object_type"
responses:
"200":
description: The response will be a JSON object with a key called `action`.
content:
application/json:
schema:
$ref: "#/components/schemas/response_object_type"

/v2/resource/someOtherResource:
post:
operationId: create_some_other_resource
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/request_object_type2"
responses:
"200":
description: The response will be a JSON object with a key called `action`.
content:
application/json:
schema:
$ref: "#/components/schemas/response_object_type"

0 comments on commit 9c4d314

Please sign in to comment.