diff --git a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddDefaultConfigSettings.java b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddDefaultConfigSettings.java index 07e4d34b2d2..e635c1b9991 100644 --- a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddDefaultConfigSettings.java +++ b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddDefaultConfigSettings.java @@ -16,30 +16,37 @@ package software.amazon.smithy.aws.apigateway.openapi; import java.util.List; +import java.util.logging.Logger; import software.amazon.smithy.model.Model; import software.amazon.smithy.openapi.OpenApiConfig; /** - * Disables OpenAPI and JSON Schema features not supported by API Gateway. + * Sets default config settings for API Gateway. + * + *

By default, this disables OpenAPI and JSON Schema features not + * supported by API Gateway.

* *

API Gateway does not allow characters like "_". API Gateway * doesn't support the "default" trait or `int32` or `int64` "format" * values. */ final class AddDefaultConfigSettings implements ApiGatewayMapper { + private static final Logger LOGGER = Logger.getLogger(AddDefaultConfigSettings.class.getName()); + private static final String DEFAULT_VERSION_MESSAGE = String.format("`apiGatewayDefault` configuration not set for" + + " opeanapi plugin. Assuming %s.", ApiGatewayDefault.VERSION_2023_08_11); + @Override public List getApiTypes() { return null; } @Override - public void updateDefaultSettings(Model model, OpenApiConfig config) { - config.setAlphanumericOnlyRefs(true); - config.getDisableFeatures().add("default"); - config.setDisableDefaultValues(true); - // If the `useIntegerType` config has been set, this assures that - // `int32` and `int64` formats are not set on those integer types. - // See https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-known-issues.html - config.setDisableIntegerFormat(true); + public void updateDefaultSettings(Model model, OpenApiConfig openApiConfig) { + ApiGatewayConfig config = openApiConfig.getExtensions(ApiGatewayConfig.class); + if (config.getApiGatewayDefault() == null) { + LOGGER.warning(DEFAULT_VERSION_MESSAGE); + config.setApiGatewayDefault(ApiGatewayDefault.VERSION_2023_08_11); + } + config.getApiGatewayDefault().setDefaults(openApiConfig); } } diff --git a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/ApiGatewayConfig.java b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/ApiGatewayConfig.java index 6385ba83baf..564dce20637 100644 --- a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/ApiGatewayConfig.java +++ b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/ApiGatewayConfig.java @@ -60,6 +60,7 @@ public enum ApiType { private ApiType apiGatewayType = ApiType.REST; private boolean disableCloudFormationSubstitution; private Set additionalAllowedCorsHeaders = Collections.emptySet(); + private ApiGatewayDefault apiGatewayDefault; /** * @return Returns true if CloudFormation substitutions are disabled. @@ -120,4 +121,12 @@ public Set getAdditionalAllowedCorsHeadersSet() { public void setAdditionalAllowedCorsHeaders(Collection additionalAllowedCorsHeaders) { this.additionalAllowedCorsHeaders = SetUtils.caseInsensitiveCopyOf(additionalAllowedCorsHeaders); } + + public ApiGatewayDefault getApiGatewayDefault() { + return this.apiGatewayDefault; + } + + public void setApiGatewayDefault(ApiGatewayDefault apiGatewayDefault) { + this.apiGatewayDefault = apiGatewayDefault; + } } diff --git a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/ApiGatewayDefault.java b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/ApiGatewayDefault.java new file mode 100644 index 00000000000..7d3fdabdc02 --- /dev/null +++ b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/ApiGatewayDefault.java @@ -0,0 +1,51 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.smithy.aws.apigateway.openapi; + +import software.amazon.smithy.openapi.OpenApiConfig; +import software.amazon.smithy.utils.SetUtils; +import software.amazon.smithy.utils.SmithyUnstableApi; + +public enum ApiGatewayDefault { + VERSION_2023_08_11("2023-08-11") { + @Override + public void setDefaults(OpenApiConfig config) { + config.setAlphanumericOnlyRefs(true); + config.setDisableDefaultValues(true); + config.setDisableIntegerFormat(true); + config.setDisableFeatures(SetUtils.of("default")); + } + }, + DISABLED("disabled") { + @Override + public void setDefaults(OpenApiConfig config) { + } + }; + + private final String version; + + ApiGatewayDefault(String version) { + this.version = version; + } + + @Override + public String toString() { + return version; + } + + @SmithyUnstableApi + public abstract void setDefaults(OpenApiConfig config); +} diff --git a/smithy-aws-apigateway-openapi/src/test/java/software/amazon/smithy/aws/apigateway/openapi/AddDefaultConfigSettingsTest.java b/smithy-aws-apigateway-openapi/src/test/java/software/amazon/smithy/aws/apigateway/openapi/AddDefaultConfigSettingsTest.java index a026afd5ac8..31845538e53 100644 --- a/smithy-aws-apigateway-openapi/src/test/java/software/amazon/smithy/aws/apigateway/openapi/AddDefaultConfigSettingsTest.java +++ b/smithy-aws-apigateway-openapi/src/test/java/software/amazon/smithy/aws/apigateway/openapi/AddDefaultConfigSettingsTest.java @@ -1,13 +1,9 @@ package software.amazon.smithy.aws.apigateway.openapi; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.not; - -import java.util.Optional; import org.junit.jupiter.api.Test; import software.amazon.smithy.model.Model; import software.amazon.smithy.model.node.Node; -import software.amazon.smithy.model.node.NodePointer; +import software.amazon.smithy.model.node.NodeMapper; import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.shapes.ShapeId; import software.amazon.smithy.openapi.OpenApiConfig; @@ -16,38 +12,66 @@ public class AddDefaultConfigSettingsTest { @Test - public void addsDefaultConfigSettings() { + public void defaultsTo2023_08_11() { Model model = Model.assembler() .discoverModels(getClass().getClassLoader()) - .addImport(getClass().getResource("alphanumeric-only.json")) + .addImport(getClass().getResource("default-config-settings.smithy")) .assemble() .unwrap(); OpenApiConfig config = new OpenApiConfig(); config.setService(ShapeId.from("example.smithy#MyService")); + config.setUseIntegerType(true); ObjectNode result = OpenApiConverter.create() .config(config) .convertToNode(model); - // Ensure that Foo_Baz became FooBaz. - NodePointer pointer = NodePointer.parse("/components/schemas/FooBaz"); - assertThat(pointer.getValue(result), not(Optional.empty())); + Node.assertEquals(result, Node.parse(IoUtils.readUtf8Resource(getClass(), "2023-08-11.openapi.json"))); } @Test - public void omitsDefaultTraits() { + public void usesVersion2023_08_11() { Model model = Model.assembler() .discoverModels(getClass().getClassLoader()) - .addImport(getClass().getResource("omits-default-trait.smithy")) + .addImport(getClass().getResource("default-config-settings.smithy")) .assemble() .unwrap(); - OpenApiConfig config = new OpenApiConfig(); - config.setService(ShapeId.from("example.smithy#MyService")); + OpenApiConfig openApiConfig = new OpenApiConfig(); + openApiConfig.setService(ShapeId.from("example.smithy#MyService")); + openApiConfig.setUseIntegerType(true); + + ApiGatewayConfig config = new ApiGatewayConfig(); + NodeMapper mapper = new NodeMapper(); + config.setApiGatewayDefault(ApiGatewayDefault.VERSION_2023_08_11); + openApiConfig.setExtensions(mapper.serialize(config).expectObjectNode()); ObjectNode result = OpenApiConverter.create() - .config(config) + .config(openApiConfig) + .convertToNode(model); + + Node.assertEquals(result, Node.parse(IoUtils.readUtf8Resource(getClass(), "2023-08-11.openapi.json"))); + } + + @Test + public void canDisableDefaults() { + Model model = Model.assembler() + .discoverModels(getClass().getClassLoader()) + .addImport(getClass().getResource("default-config-settings.smithy")) + .assemble() + .unwrap(); + + OpenApiConfig openApiConfig = new OpenApiConfig(); + openApiConfig.setService(ShapeId.from("example.smithy#MyService")); + openApiConfig.setUseIntegerType(true); + + ApiGatewayConfig config = new ApiGatewayConfig(); + NodeMapper mapper = new NodeMapper(); + config.setApiGatewayDefault(ApiGatewayDefault.DISABLED); + openApiConfig.setExtensions(mapper.serialize(config).expectObjectNode()); + ObjectNode result = OpenApiConverter.create() + .config(openApiConfig) .convertToNode(model); - Node.assertEquals(result, Node.parse(IoUtils.readUtf8Resource(getClass(), "omits-default-trait.openapi.json"))); + Node.assertEquals(result, Node.parse(IoUtils.readUtf8Resource(getClass(), "disabled-defaults.openapi.json"))); } } diff --git a/smithy-aws-apigateway-openapi/src/test/java/software/amazon/smithy/aws/apigateway/openapi/AddDefaultRestConfigSettingsTest.java b/smithy-aws-apigateway-openapi/src/test/java/software/amazon/smithy/aws/apigateway/openapi/AddDefaultRestConfigSettingsTest.java index 2cc154db2fd..bd47ad1957a 100644 --- a/smithy-aws-apigateway-openapi/src/test/java/software/amazon/smithy/aws/apigateway/openapi/AddDefaultRestConfigSettingsTest.java +++ b/smithy-aws-apigateway-openapi/src/test/java/software/amazon/smithy/aws/apigateway/openapi/AddDefaultRestConfigSettingsTest.java @@ -1,15 +1,8 @@ package software.amazon.smithy.aws.apigateway.openapi; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.not; - -import java.util.Optional; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import software.amazon.smithy.model.Model; import software.amazon.smithy.model.node.Node; -import software.amazon.smithy.model.node.NodePointer; import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.shapes.ShapeId; import software.amazon.smithy.openapi.OpenApiConfig; diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/omits-default-trait.openapi.json b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/2023-08-11.openapi.json similarity index 88% rename from smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/omits-default-trait.openapi.json rename to smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/2023-08-11.openapi.json index 8cdb9e15cf9..ddca16c5c27 100644 --- a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/omits-default-trait.openapi.json +++ b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/2023-08-11.openapi.json @@ -41,6 +41,9 @@ "BAR" ] }, + "FooBaz": { + "type": "object" + }, "HasDefaultRequestContent": { "type": "object", "properties": { @@ -69,6 +72,12 @@ }, "baz": { "$ref": "#/components/schemas/DefaultEnum" + }, + "withAlphaOnlyRef": { + "$ref": "#/components/schemas/FooBaz" + }, + "anInt": { + "type": "integer" } } } diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/alphanumeric-only.json b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/alphanumeric-only.json deleted file mode 100644 index ee15e1c867d..00000000000 --- a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/alphanumeric-only.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "smithy": "2.0", - "shapes": { - "example.smithy#MyService": { - "type": "service", - "version": "2006-03-01", - "operations": [ - { - "target": "example.smithy#GetPayload" - } - ], - "traits": { - "aws.protocols#restJson1": {}, - "smithy.api#httpBasicAuth": {} - } - }, - "example.smithy#GetPayload": { - "type": "operation", - "output": { - "target": "example.smithy#GetPayloadOutput" - }, - "traits": { - "smithy.api#readonly": {}, - "smithy.api#http": { - "uri": "/test", - "method": "GET" - } - } - }, - "example.smithy#GetPayloadOutput": { - "type": "structure", - "members": { - "foo": { - "target": "example.smithy#Foo_Baz" - } - } - }, - "example.smithy#Foo_Baz": { - "type": "structure", - "members": {} - } - } -} diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/omits-default-trait.smithy b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/default-config-settings.smithy similarity index 86% rename from smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/omits-default-trait.smithy rename to smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/default-config-settings.smithy index cefc45c92ee..2c013ccc4dd 100644 --- a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/omits-default-trait.smithy +++ b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/default-config-settings.smithy @@ -20,6 +20,8 @@ operation HasDefault { foo: String = "" bar: StringList = [] baz: DefaultEnum = "FOO" + withAlphaOnlyRef: Foo_Baz, + anInt: Long } } @@ -31,3 +33,5 @@ enum DefaultEnum { FOO BAR } + +structure Foo_Baz {} diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/disabled-defaults.openapi.json b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/disabled-defaults.openapi.json new file mode 100644 index 00000000000..6c8269d6301 --- /dev/null +++ b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/disabled-defaults.openapi.json @@ -0,0 +1,98 @@ +{ + "openapi": "3.0.2", + "info": { + "title": "MyService", + "version": "2020-07-02" + }, + "paths": { + "/defaults": { + "post": { + "operationId": "HasDefault", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HasDefaultRequestContent" + } + } + } + }, + "responses": { + "200": { + "description": "HasDefault 200 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HasDefaultResponseContent" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "DefaultEnum": { + "type": "string", + "enum": [ + "FOO", + "BAR" + ] + }, + "Foo_Baz": { + "type": "object" + }, + "HasDefaultRequestContent": { + "type": "object", + "properties": { + "foo": { + "type": "string", + "default": "" + }, + "bar": { + "type": "array", + "default": [], + "items": { + "type": "string" + } + } + } + }, + "HasDefaultResponseContent": { + "type": "object", + "properties": { + "foo": { + "type": "string", + "default": "" + }, + "bar": { + "type": "array", + "default": [], + "items": { + "type": "string" + } + }, + "baz": { + "allOf": [ + { + "$ref": "#/components/schemas/DefaultEnum" + }, + { + "default": "FOO" + } + ] + }, + "withAlphaOnlyRef": { + "$ref": "#/components/schemas/Foo_Baz" + }, + "anInt": { + "type": "integer", + "format": "int64" + } + } + } + } + } +}