diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml index cf12f067b26..010bd74af22 100644 --- a/config/checkstyle/suppressions.xml +++ b/config/checkstyle/suppressions.xml @@ -20,4 +20,5 @@ + diff --git a/config/spotbugs/filter.xml b/config/spotbugs/filter.xml index 2bd6c0a0911..f03490ad81a 100644 --- a/config/spotbugs/filter.xml +++ b/config/spotbugs/filter.xml @@ -86,4 +86,10 @@ + + + + + + diff --git a/docs/source/guides/building-models/build-config.rst b/docs/source/guides/building-models/build-config.rst index 7d0e4257b7b..b551dea638c 100644 --- a/docs/source/guides/building-models/build-config.rst +++ b/docs/source/guides/building-models/build-config.rst @@ -437,54 +437,6 @@ orphaned shapes. This transformer does not remove shapes from the prelude. -.. _includeAuth-transform: - -includeAuth ------------ - -Removes authentication schemes from shapes that do not match one of the -given arguments (a list of authentication schemes). - -.. tabs:: - - .. code-tab:: json - - { - "version": "1.0", - "projections": { - "exampleProjection": { - "transforms": [ - {"name": "includeAuth", "args": ["aws.v4", "http-basic"]} - ] - } - } - } - - -.. _includeProtocols-transform: - -includeProtocols ----------------- - -Removes protocols from service shapes that do not match one of the given -arguments (a list of protocol names). - -.. tabs:: - - .. code-tab:: json - - { - "version": "1.0", - "projections": { - "exampleProjection": { - "transforms": [ - {"name": "includeProtocols", "args": ["aws.rest-json"]} - ] - } - } - } - - .. _includeTags-transform: includeTags diff --git a/docs/source/guides/converting-to-openapi.rst b/docs/source/guides/converting-to-openapi.rst index 66c61cc397b..62ca6dae34a 100644 --- a/docs/source/guides/converting-to-openapi.rst +++ b/docs/source/guides/converting-to-openapi.rst @@ -114,7 +114,7 @@ The Smithy Gradle plugin relies on a ``smithy-build.json`` file found at the root of a project to define the actual process of building the OpenAPI specification. The following example defines a ``smithy-build.json`` file that builds an OpenAPI specification from a service for the -``smithy.example#Weather`` service using the ``aws.rest-json-1.1`` protocol: +``smithy.example#Weather`` service using the ``aws.protocols#restJson1`` protocol: .. code-block:: json :caption: smithy-build.json @@ -125,7 +125,7 @@ that builds an OpenAPI specification from a service for the "plugins": { "openapi": { "service": "smithy.example#Weather", - "protocol": "aws.rest-json-1.1" + "protocol": "aws.protocols#restJson1" } } } @@ -155,14 +155,18 @@ service (string) **Required**. The Smithy service :ref:`shape ID ` to convert. protocol (string) - The protocol name to use when converting Smithy to OpenAPI (for example, - ``aws.rest-json-1.1``. + The protocol shape ID to use when converting Smithy to OpenAPI (for + example, ``aws.protocols#restJson1``). Smithy will try to match the provided protocol name with an implementation of ``software.amazon.smithy.openapi.fromsmithy.OpenApiProtocol`` registered with a service provider implementation of ``software.amazon.smithy.openapi.fromsmithy.CoreExtension``. + .. important:: + + This property is required if a service supports multiple protocols. + openapi.tags (boolean) Whether or not to include Smithy :ref:`tags ` in the result. @@ -197,8 +201,8 @@ openapi.keepUnusedComponents (boolean) created specification. openapi.aws.jsonContentType (string) - Sets the media-type to associate with the JSON payload of ``aws.json-*`` - and ``aws.rest-json-*`` protocols + Sets a custom media-type to associate with the JSON payload of + JSON-based protocols. openapi.forbidGreedyLabels (boolean) Set to true to forbid greedy URI labels. By default, greedy labels will @@ -485,9 +489,6 @@ Other traits that influence API Gateway ``aws.api#service`` TODO -``protocols`` - TODO - ``aws.apigateway#apiKeySource`` Specifies the source of the caller identifier that will be used to throttle API methods that require a key. This trait is converted into @@ -532,7 +533,7 @@ Next, you need to create and configure an ``OpenApiConverter``: OpenApiConverter converter = OpenApiConverter.create(); // Add any necessary settings... - converter.putSetting(OpenApiConstants.PROTOCOL, "aws.rest-json-1.1"); + converter.putSetting(OpenApiConstants.PROTOCOL, "aws.protocols#restJson1"); // Create a shape ID that points to the service. ShapeId serviceShapeId = ShapeId.from("smithy.example#Weather"); diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst index 4b37e2b0730..7bc3e75399c 100644 --- a/docs/source/quickstart.rst +++ b/docs/source/quickstart.rst @@ -67,7 +67,7 @@ Smithy supports the following types: * - timestamp - An instant in time with no UTC offset or timezone. The serialization of a timestamp is determined by a - :ref:`protocol `. + :ref:`protocol `. * - :ref:`document ` - An untyped JSON-like value. * - :ref:`list` @@ -137,9 +137,9 @@ weather service. tools to make them easier to use by other tooling. Smithy is a *protocol agnostic* IDL, meaning the model defines the interface of -the API but not its serialization. A :ref:`protocol ` defines -how clients and servers communicate and how messages are passed back and forth. -:ref:`Traits ` can be used to influence how a protocol serializes +the API but not its serialization. A :ref:`protocol ` +defines how clients and servers communicate and how messages are passed back and +forth. :ref:`Traits ` can be used to influence how a protocol serializes shapes. diff --git a/docs/source/spec/amazon-apigateway.rst b/docs/source/spec/amazon-apigateway.rst index a0ce0688e1a..9739a67ec89 100644 --- a/docs/source/spec/amazon-apigateway.rst +++ b/docs/source/spec/amazon-apigateway.rst @@ -108,9 +108,10 @@ An *authorizer* definition is an object that supports the following properties: - Description * - scheme - ``string`` - - **Required**. A Smithy authentication scheme name that identifies how - a client authenticates. This value MUST reference one of the ``auth`` - schemes of the :ref:`protocols-trait` attached to the service. + - **Required**. A Smithy authentication scheme shape ID that identifies + how a client authenticates. This value MUST reference one of the + :ref:`authentication schemes ` attached to the + service. * - type - ``string`` - The type of the authorizer. If specifying information beyond the @@ -122,7 +123,8 @@ An *authorizer* definition is an object that supports the following properties: - ``string`` - The ``authType`` of the authorizer. This value is used in APIGateway exports as ``x-amazon-apigateway-authtype``. This value is set to - ``custom`` by default, or ``awsSigv4`` if your scheme is ``aws.v4``. + ``custom`` by default, or ``awsSigv4`` if your scheme is + :ref:`aws.auth#sigv4 `. * - uri - ``string`` - Specifies the authorizer's Uniform Resource Identifier @@ -182,42 +184,33 @@ An *authorizer* definition is an object that supports the following properties: API Gateway will cache authorizer responses. If this field is not set, the default value is 300. The maximum value is 3600, or 1 hour. -.. - TODO: Add IDL example +.. tabs:: -.. code-block:: json + .. code-tab:: smithy - { - "smithy": "0.5.0", - "shapes": { - "ns.foo#Weather": { - "type": "service", - "version": "2018-03-17", - "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json", - "auth": [ - "aws.v4" - ] - } - ], - "aws.apigateway#authorizer": "arbitrary-name", - "aws.apigateway#authorizers": { - "arbitrary-name": { - "scheme": "aws.v4", - "type": "request", - "uri": "arn:foo:baz", - "credentials": "arn:foo:bar", - "identitySource": "mapping.expression", - "identityValidationExpression": "[A-Z]+", - "resultTtlInSeconds": 100 - } - } - } - } + namespace ns.foo + + use aws.apigateway#authorizer + use aws.apigateway#authorizers + use aws.auth#sigv4 + use aws.protocols#restJson1 + + @restJson1 + @sigv4(name: "weather") + @authorizer("arbitrary-name") + @authorizers( + "arbitrary-name": { + scheme: sigv4, + type: "request", + uri: "arn:foo:baz", + credentials: "arn:foo:bar", + identitySource: "mapping.expression", + identityValidationExpression: "[A-Z]+", + resultTtlInSeconds: 100 + }) + service Weather { + version: "2018-03-17" } - } .. note:: @@ -434,14 +427,10 @@ operation within the service. "type": "service", "version": "2018-03-17", "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json", - "auth": [ - "aws.v4" - ] - } - ], + "aws.protocols#restJson1": true, + "aws.auth#sigv4": { + "name": "weather" + }, "aws.apigateway#integration": { "type": "aws", "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:012345678901:function:HelloWorld/invocations", diff --git a/docs/source/spec/aws-auth.rst b/docs/source/spec/aws-auth.rst new file mode 100644 index 00000000000..7530c76b9e8 --- /dev/null +++ b/docs/source/spec/aws-auth.rst @@ -0,0 +1,125 @@ +.. _aws-authentication: + +========================= +AWS Authentication Traits +========================= + +This document defines AWS authentication schemes. + +.. contents:: Table of contents + :depth: 2 + :local: + :backlinks: none + + +.. _aws.auth#sigv4-trait: + +``aws.auth#sigv4`` trait +======================== + +Trait summary + The ``aws.auth#sigv4`` trait adds support for `AWS signature version 4`_ + to a service. +Trait selector + ``service`` +Trait value + An ``object`` that supports the following properties: + + .. list-table:: + :header-rows: 1 + :widths: 10 20 70 + + * - Property + - Type + - Description + * - name + - ``string`` + - **Required**. The signature version 4 service signing name to use + in the `credential scope`_ when signing requests. This value + SHOULD match the ``arnNamespace`` property of the + :ref:`aws.api#service-trait`. + +.. tabs:: + + .. code-tab:: smithy + + namespace aws.fooBaz + + use aws.api#service + use aws.auth#sigv4 + use aws.protocols#restJson1 + + @service(sdkId: "Some Value") + @sigv4(name: "foobaz") + @restJson1 + service FooBaz { + version: "2018-03-17", + } + + .. code-tab:: json + + { + "smithy": "0.5.0", + "shapes": { + "aws.fooBaz#FooBaz": { + "type": "service", + "version": "2018-03-17", + "traits": { + "aws.protocols#restJson1": true, + "aws.api#service": { + "sdkId": "Some Value" + }, + "aws.auth#sigv4": { + "name": "foobaz" + } + } + } + } + } + + +.. _aws.auth#cognitoUserPools-trait: + +aws.auth#cognitoUserPools +========================= + +Trait summary + The ``aws.auth#cognitoUserPools`` trait adds support for + `Amazon Cognito User Pools`_ to a service. +Trait selector + ``service`` +Trait value + An ``object`` that supports the following properties: + + .. list-table:: + :header-rows: 1 + :widths: 10 20 70 + + * - Property + - Type + - Description + * - providerArns + - ``[string]`` + - **Required**. A list of the Amazon Cognito user pool ARNs. Each + element is of this format: ``arn:aws:cognito-idp:{region}:{account_id}:userpool/{user_pool_id}``. + +.. code-block:: smithy + + namespace aws.fooBaz + + use aws.api#service + use aws.auth#cognitoUserPools + use aws.protocols#restJson1 + + @service(sdkId: "Some Value") + @cognitoUserPools( + providerArns: ["arn:aws:cognito-idp:us-east-1:123:userpool/123"]) + @restJson1 + service FooBaz { + version: "2018-03-17", + } + + +.. _AWS signature version 4: https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html +.. _credential scope: https://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html +.. _Amazon Cognito User Pools: https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html diff --git a/docs/source/spec/aws-core.rst b/docs/source/spec/aws-core.rst index c06e7861330..165657e51c9 100644 --- a/docs/source/spec/aws-core.rst +++ b/docs/source/spec/aws-core.rst @@ -1309,64 +1309,6 @@ Clients SHOULD use an LRU cache implementation with an initial cache limit of Clients SHOULD scope the cache globally or to a specific client instance. -.. _aws-authentication: - --------------- -Authentication --------------- - - -.. _aws.v4-auth: - -``aws.v4`` Authentication -========================= - -The ``aws.v4`` authentication scheme is used to indicate that a service -supports `AWS signature version 4`_. This authentication scheme does not -require any configuration settings. The service name used in the -signature version 4 credential scope defaults to the resolved value of the -``aws.api#service`` trait :ref:`service-arn-namespace` property (that is, -if the value is explicitly defined, then use it, otherwise use the name of -the service converted to lowercase characters). - -.. tabs:: - - .. code-tab:: smithy - - namespace aws.fooBaz - - use aws.api#service - - @service(sdkId: "Some Value") - @protocols([{name: "aws.rest-json", auth: ["aws.v4"]}]) - service FooBaz { - version: "2018-03-17", - } - - .. code-tab:: json - - { - "smithy": "0.5.0", - "shapes": { - "aws.fooBaz#FooBaz": { - "type": "service", - "version": "2018-03-17", - "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json", - "auth": [ - "aws.v4" - ] - } - ], - "aws.api#service": { - "sdkId": "Some Value" - } - } - } - } - } -------- Appendix diff --git a/docs/source/spec/aws-json-protocols.rst b/docs/source/spec/aws-json-protocols.rst new file mode 100644 index 00000000000..070cba2c630 --- /dev/null +++ b/docs/source/spec/aws-json-protocols.rst @@ -0,0 +1,105 @@ +.. _aws-json-protocols: + +================== +AWS JSON protocols +================== + +This specification defines the ``aws.protocols#awsJson1_0`` and +``aws.protocols#awsJson1_1`` protocols. + +.. contents:: Table of contents + :depth: 2 + :local: + :backlinks: none + + +.. _aws.protocols#awsJson1_0-trait: + +---------------------------------- +``aws.protocols#awsJson1_0`` trait +---------------------------------- + +Summary + Adds support for an HTTP protocol that sends POST requests and + responses with JSON documents. +Trait selector + ``service`` +Value type + Annotation trait. +See + `Protocol tests `_ + +.. tabs:: + + .. code-tab:: smithy + + namespace smithy.example + + use aws.protocols#awsJson1_0 + + @awsJson1_0 + service MyService { + version: "2020-02-05" + } + + .. code-tab:: json + + { + "smithy": "0.5.0", + "shapes": { + "smithy.example#MyService": { + "type": "service", + "version": "2020-02-05", + "traits": { + "aws.protocols#awsJson1_0": true + } + } + } + } + +*TODO: Add specifications, protocol examples, etc.* + + +.. _aws.protocols#awsJson1_1-trait: + +---------------------------------- +``aws.protocols#awsJson1_1`` trait +---------------------------------- + +Summary + Adds support for an HTTP protocol that sends POST requests and + responses with JSON documents. +Trait selector + ``service`` +Value type + Annotation trait. + +.. tabs:: + + .. code-tab:: smithy + + namespace smithy.example + + use aws.protocols#awsJson1_1 + + @awsJson1_1 + service MyService { + version: "2020-02-05" + } + + .. code-tab:: json + + { + "smithy": "0.5.0", + "shapes": { + "smithy.example#MyService": { + "type": "service", + "version": "2020-02-05", + "traits": { + "aws.protocols#awsJson1_1": true + } + } + } + } + +*TODO: Add specifications, protocol examples, etc.* diff --git a/docs/source/spec/aws-query-protocol.rst b/docs/source/spec/aws-query-protocol.rst new file mode 100644 index 00000000000..f5621c93c1e --- /dev/null +++ b/docs/source/spec/aws-query-protocol.rst @@ -0,0 +1,105 @@ +.. _aws-query-protocol: + +================== +AWS query protocol +================== + +This specification defines the ``aws.protocols#awsQuery`` protocol. + +.. contents:: Table of contents + :depth: 2 + :local: + :backlinks: none + + +.. _aws.protocols#awsQuery-trait: + +-------------------------------- +``aws.protocols#awsQuery`` trait +-------------------------------- + +Summary + Adds support for an HTTP protocol that sends requests in the query + string and responses in XML documents. +Trait selector + ``service`` +Value type + Annotation trait. +See + `Protocol tests `_ + +.. tabs:: + + .. code-tab:: smithy + + namespace smithy.example + + use aws.protocols#awsQuery + + @awsQuery + service MyService { + version: "2020-02-05" + } + + .. code-tab:: json + + { + "smithy": "0.5.0", + "shapes": { + "smithy.example#MyService": { + "type": "service", + "version": "2020-02-05", + "traits": { + "aws.protocols#awsQuery": true + } + } + } + } + +*TODO: Add specifications, protocol examples, etc.* + + +.. _aws.protocols#ec2Query-trait: + +-------------------------------- +``aws.protocols#ec2Query`` trait +-------------------------------- + +Summary + Adds support for an HTTP protocol that sends request in the query + string and responses in XML documents. This protocol is an + Amazon EC2-specific extension of the ``awsQuery`` protocol. +Trait selector + ``service`` +Value type + Annotation trait. + +.. tabs:: + + .. code-tab:: smithy + + namespace smithy.example + + use aws.protocols#ec2Query + + @ec2Query + service MyService { + version: "2020-02-05" + } + + .. code-tab:: json + + { + "smithy": "0.5.0", + "shapes": { + "smithy.example#MyService": { + "type": "service", + "version": "2020-02-05", + "traits": { + "aws.protocols#ec2Query": true + } + } + } + } + +*TODO: Add specifications, protocol examples, etc.* diff --git a/docs/source/spec/aws-restjson1-protocol.rst b/docs/source/spec/aws-restjson1-protocol.rst new file mode 100644 index 00000000000..aba5daf7635 --- /dev/null +++ b/docs/source/spec/aws-restjson1-protocol.rst @@ -0,0 +1,59 @@ +.. _aws-restjson1-protocol: + +====================== +AWS restJson1 protocol +====================== + +This specification defines the ``aws.protocols#restJson1`` protocol. + +.. contents:: Table of contents + :depth: 2 + :local: + :backlinks: none + + +.. _aws.protocols#restJson1-trait: + +--------------------------------- +``aws.protocols#restJson1`` trait +--------------------------------- + +Summary + Adds support for an HTTP-based protocol that sends JSON requests and + responses with configurable HTTP bindings. +Trait selector + ``service`` +Value type + Annotation trait. +See + `Protocol tests `_ + +.. tabs:: + + .. code-tab:: smithy + + namespace smithy.example + + use aws.protocols#restJson1 + + @restJson1 + service MyService { + version: "2020-02-05" + } + + .. code-tab:: json + + { + "smithy": "0.5.0", + "shapes": { + "smithy.example#MyService": { + "type": "service", + "version": "2020-02-05", + "traits": { + "aws.protocols#restJson1": true + } + } + } + } + +*TODO: Add specifications, protocol examples, etc.* diff --git a/docs/source/spec/aws-restxml-protocol.rst b/docs/source/spec/aws-restxml-protocol.rst new file mode 100644 index 00000000000..09c089dc614 --- /dev/null +++ b/docs/source/spec/aws-restxml-protocol.rst @@ -0,0 +1,59 @@ +.. _aws-restxml-protocol: + +==================== +AWS restXml protocol +==================== + +This specification defines the ``aws.protocols#restXml`` protocol. + +.. contents:: Table of contents + :depth: 2 + :local: + :backlinks: none + + +.. _aws.protocols#restXml-trait: + +------------------------------- +``aws.protocols#restXml`` trait +------------------------------- + +Summary + Adds support for an HTTP-based protocol that sends XML requests and + responses. +Trait selector + ``service`` +Value type + Annotation trait. +See + `Protocol tests `_ + +.. tabs:: + + .. code-tab:: smithy + + namespace smithy.example + + use aws.protocols#restXml + + @restXml + service MyService { + version: "2020-02-05" + } + + .. code-tab:: json + + { + "smithy": "0.5.0", + "shapes": { + "smithy.example#MyService": { + "type": "service", + "version": "2020-02-05", + "traits": { + "aws.protocols#restXml": true + } + } + } + } + +*TODO: Add specifications, protocol examples, etc.* diff --git a/docs/source/spec/core.rst b/docs/source/spec/core.rst index e8510e6928a..2b9fc5a72f3 100644 --- a/docs/source/spec/core.rst +++ b/docs/source/spec/core.rst @@ -219,7 +219,7 @@ or shape references. * - timestamp - Represents an instant in time with no UTC offset or timezone. The serialization of a timestamp is determined by a - :ref:`protocol `. + :ref:`protocol `. * - document - **Unstable** Represents an untyped JSON-like value that can take on one of the following types: null, boolean, string, byte, short, @@ -314,7 +314,7 @@ Timestamp serialization format ------------------------------ By default, the serialization format of a timestamp is implicitly determined by -the :ref:`protocol ` of a service; however, the serialization +the :ref:`protocol ` of a service; however, the serialization format can be explicitly configured to override the default format used by the protocol by applying the :ref:`timestampFormat-trait` to a timestamp shape or a member that targets a timestamp. @@ -344,8 +344,7 @@ double, an array of these types, or a map of these types where the key is a string. Not all protocols support document types, and the serialization format of a -document type is protocol-specific. All JSON protocols SHOULD support document -types and they SHOULD serialize document types inline as normal JSON values. +document type is protocol-specific. .. warning:: @@ -4658,72 +4657,54 @@ match for the name of the resource identifier. Protocol traits =============== -Serialization and protocols traits define how data is transferred over +Serialization and protocol traits define how data is transferred over the wire. -.. _protocols-trait: +.. _protocolDefinition-trait: -``protocols`` trait -------------------- +``protocolDefinition`` trait +---------------------------- Summary - Defines the protocols supported by a service. + A meta-trait that marks a trait as a protocol definition trait. Traits + that are marked with this trait are applied to service shapes to + define the protocols supported by a service. A client MUST understand + at least one of the protocols in order to successfully communicate + with the service. Trait selector - ``service`` + ``[trait|trait]`` Value type - ``array`` of protocol ``object`` + Annotation trait. Smithy is protocol agnostic, which means it focuses on the interfaces and abstractions that are provided to end-users rather than how the data is sent over the wire. In Smithy, a *protocol* is a named set of rules that defines -the syntax and semantics of how a client and server communicate. A protocol -name defines both the application protocol of a service and the serialization -formats used in messages. These serialization formats MAY be influenced by -payload serialization traits like :ref:`jsonName-trait` and -:ref:`xmlAttribute-trait`. - -The ``protocols`` trait of a service defines a priority ordered list of -protocols supported by the service and the authentication schemes that each -protocol supports. A client MUST understand at least one of the protocols in -order to successfully communicate with the service. - -The value of the ``protocols`` trait is an array of protocol objects. Each -protocol object supports the following key-value pairs: - -.. list-table:: - :header-rows: 1 - :widths: 10 10 80 - - * - Property - - Type - - Description - * - name - - ``string`` - - **Required**. The name of the protocol. The name MUST be unique across - the entire list and MUST match the following regular expression: - ``^[a-z][a-z0-9\-.+]*$``. - * - auth - - ``List`` - - A priority ordered list of authentication schemes supported by this - protocol. Each value MUST match the following regular expression: - ``^[a-z][a-z0-9\-.+]*$``. - * - tags - - ``List`` - - Attaches a list of tags that allow the protocol to be categorized and - grouped. +the syntax and semantics of how a client and server communicate. This +includes the application layer protocol of a service (for example, HTTP) +and the serialization formats used in messages (for example, JSON). Traits +MAY be used to influence how messages are serialized (for example, +:ref:`jsonName-trait` and :ref:`xmlAttribute-trait`). -The following example defines a service that supports both the -"smithy.example" protocol and the "aws.mqtt" protocols. The -"aws.mqtt" protocol is defined with an optional list of tags. +The following example defines a service that supports both the hypothetical +``jsonExample`` and ``xmlExample`` protocols. .. tabs:: .. code-tab:: smithy - @protocols([ - {name: "smithy.example", auth: ["http-basic"]}, - {name: "aws.mqtt", auth: ["x.509"], tags: ["internal"]}]) + /// An example JSON protocol. + @protocolDefinition + @trait(selector: "service") + structure jsonExample {} + + /// An example XML protocol. + @protocolDefinition + @trait(selector: "service") + structure xmlExample {} + + @jsonExample + @xmlExample service WeatherService { version: "2017-02-11", } @@ -4737,261 +4718,49 @@ The following example defines a service that supports both the "type": "service", "version": "2017-02-11", "traits": { - "smithy.api#protocols": [ - { - "name": "smithy.example", - "auth": [ - "http-basic" - ] - }, - { - "name": "aws.mqtt", - "auth": [ - "x.509" - ], - "tags": [ - "internal" - ] - } - ] + "smithy.example#jsonExample": true, + "smithy.example#xmlExample": true } - } - } - } - -An operation bound to a service is expected to support every listed ``auth`` -scheme of every protocol unless the operation or the service is annotated -with the :ref:`auth-trait`. - - -Built-in auth schemes -````````````````````` - -Smithy defines the following built-in authentication schemes that can be -used with the ``protocols`` trait. - -.. list-table:: - :header-rows: 1 - :widths: 20 80 - - * - Scheme - - Description - * - http-basic - - HTTP Basic Authentication as defined in :rfc:`2617`. - * - http-digest - - HTTP Digest Authentication as defined in :rfc:`2617`. - * - http-bearer - - HTTP Bearer Authentication as defined in :rfc:`6750`. - * - http-x-api-key - - An HTTP-specific authentication scheme that sends an arbitrary - API key in the "X-Api-Key" HTTP header. - * - none - - Indicates that the API can be called without authentication. - -Custom authentication schemes MAY be referenced in Smithy models and -SHOULD utilize some kind of prefix to prevent collisions with other -custom schemes (for example, "aws.v4" is preferred over just "v4"). - - -.. _auth-trait: - -``auth`` trait --------------- - -Summary - Defines the priority ordered authentication schemes supported by a service - or operation. When applied to a service, it defines the default - authentication schemes of every operation in the service. When applied - to an operation, it defines the list of all authentication schemes - supported by the operation, overriding any ``auth`` trait specified - on a service. -Trait selector - ``:test(service, operation)`` - - *Service or operation shapes* -Value type - This trait contains a priority ordered list of string values that - reference authentication schemes defined on a service shape. - -The ``auth`` trait is used to explicitly define which authentication schemes -defined by the :ref:`protocols-trait` of a service are supported by an -operation. - -Operations that are not annotated with the ``auth`` trait inherit the ``auth`` -trait of the service they are bound to, and if the service is not annotated -with the ``auth`` trait, then the operation is expected to support each of -the authentication schemes defined by all of the protocols of the service. -Each entry in the ``auth`` trait MUST map to a corresponding ``auth`` -property in the ``protocols`` trait of a service with the exception of the -"none" auth scheme which can be used without defining it in a protocol. - -When connecting to a service using a specific protocol, only the intersection -of the ``auth`` schemes listed in the selected protocol and the ``auth`` -schemes defined in the resolved ``auth`` trait are eligible for the client -to use. - -The following example defines two operations: - -* OperationA defines an explicit list of the authentication schemes it - supports using the ``auth`` trait. -* OperationB does is not annotated with the ``auth`` trait, so the schemes - supported by this operation inherit from the ``protocols`` trait defined - on the service. - -.. tabs:: - - .. code-tab:: smithy - - @protocols([{name: "smithy.example", auth: ["http-basic", "http-digest"]}]) - // Every operation by default should support http-basic and http-digest. - @auth(["http-basic", "http-digest"]) - service AuthenticatedService { - version: "2017-02-11", - operations: [OperationA, OperationB] - } - - // This operation is configured to either be unauthenticated - // or to use http-basic. It is not expected to support http-digest. - @auth(["none", "http-basic"]) - operation OperationA {} - - // This operation defines no auth, so it is expected to support the auth - // defined on the service: http-basic and http-digest. - operation OperationB {} - - .. code-tab:: json - - { - "smithy": "0.5.0", - "shapes": { - "smithy.example#AuthenticatedService": { - "type": "service", - "version": "2017-02-11", - "operations": [ - { - "target": "smithy.example#OperationA" - }, - { - "target": "smithy.example#OperationB" - } - ], + }, + "smithy.example#jsonExample": { + "type": "structure", "traits": { - "smithy.api#protocols": [ - { - "name": "smithy.example", - "auth": [ - "http-basic", - "http-digest" - ] - } - ] + "smithy.api#documentation": "An example JSON protocol." + "smithy.api#protocolDefinition": true, + "smithy.api#trait": { + "selector": "service" + } } }, - "smithy.example#OperationA": { - "type": "operation", + "smithy.example#xmlExample": { + "type": "structure", "traits": { - "smithy.api#auth": [ - "none", - "http-basic" - ] + "smithy.api#documentation": "An example JSON protocol." + "smithy.api#protocolDefinition": true, + "smithy.api#trait": { + "selector": "service" + } } - }, - "smithy.example#OperationB": { - "type": "operation" } } } -The following ``auth`` trait is invalid because it uses an ``auth`` trait -scheme that is not supported by any of the ``protocols`` of the service: +Because protocol definitions are just specialized shapes, they can also +support configuration settings. .. code-block:: smithy - @protocols([{name: "smithy.example", auth: ["http-basic"]}]) - @auth(["http-digest"]) // <-- Invalid! - service InvalidExample { - version: "2017-02-11" + @protocolDefinition + @trait(selector: "service") + structure configurableExample { + @required + version: String } -The following example demonstrates how a service that supports multiple -protocols can define different authentication schemes for each protocol. - -.. tabs:: - - .. code-tab:: smithy - - @protocols([ - {name: "example.foo", auth: ["http-basic", "http-digest"]}, - {name: "example.baz", auth: ["x.509"]}]) - @auth(["http-basic", "x.509"]) - service AuthenticatedService { - version: "2017-02-11", - operations: [OperationA, OperationB] - } - - @auth(["http-digest", "x.509"]) - operation OperationA {} - - operation OperationB {} - - .. code-tab:: json - - { - "smithy": "0.5.0", - "shapes": { - "smithy.example#AuthenticatedService": { - "type": "service", - "version": "2017-02-11", - "operations": [ - { - "target": "smithy.example#OperationA" - }, - { - "target": "smithy.example#OperationB" - } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "example.foo", - "auth": [ - "http-basic", - "http-digest" - ] - }, - { - "name": "example.baz", - "auth": [ - "x.509" - ] - } - ] - } - }, - "smithy.example#OperationA": { - "type": "operation", - "traits": { - "smithy.api#auth": [ - "http-digest", - "x.509" - ] - } - }, - "smithy.example#OperationB": { - "type": "operation" - } - } - } - -When connecting to the above service over the "example.foo" protocol: - -* ``OperationA`` supports the "http-digest" authentication scheme. -* ``OperationB`` supports the "http-basic" and "http-digest" authentication - schemes. - -When connecting to the above service over the "example.baz" protocol, -both ``OperationA`` and ``OperationB`` support only the x.509 authentication -scheme. + @configurableExample(version: "1.0") + service WeatherService { + version: "2017-02-11", + } .. _jsonName-trait: @@ -5106,9 +4875,10 @@ Value type ``string`` value The serialization format of a timestamp shape is normally dictated by the -:ref:`protocol ` of a service. In order to interoperate with -other web services or frameworks, it is sometimes necessary to use a specific -serialization format that differs from the protocol. +:ref:`protocol ` of a service. In order to +interoperate with other web services or frameworks, it is sometimes +necessary to use a specific serialization format that differs from the +protocol. Smithy defines the following built-in timestamp formats: @@ -5134,13 +4904,366 @@ Smithy defines the following built-in timestamp formats: .. important:: This trait SHOULD NOT be used unless the intended serialization format of - a timestmap differs from the default protocol format. Using this trait too + a timestamp differs from the default protocol format. Using this trait too liberally can cause other tooling to improperly interpret the timestamp. See :ref:`timestamp-serialization-format` for information on how to determine the serialization format of a timestamp. +.. _authentication-traits: + +Authentication traits +===================== + +.. _authDefinition-trait: + +``authDefinition`` trait +------------------------ + +Summary + A meta-trait that marks a trait as an authentication scheme. Traits + that are marked with this trait are applied to service shapes to + indicate how a client can authenticate with the service. +Trait selector + ``[trait|trait]`` +Value type + Annotation trait. + +Every operation in the closure of a service is expected to support the +authentication schemes applied to a service unless the service or operation +is marked with the :ref:`auth-trait`, which is used to change the set of +supported authentication schemes. + +The following example defines a service that supports both ``httpBasicAuth`` +and the hypothetical ``fooExample`` authentication scheme. + +.. tabs:: + + .. code-tab:: smithy + + namespace smithy.example + + @authDefinition + @trait(selector: "service") + structure fooExample {} + + @fooExample + @httpBasicAuth + service WeatherService { + version: "2017-02-11", + } + + .. code-tab:: json + + { + "smithy": "0.5.0", + "shapes": { + "smithy.example#WeatherService": { + "type": "service", + "version": "2017-02-11", + "traits": { + "smithy.example#fooExample": {}, + "smithy.api#httpBasicAuth": {} + } + }, + "smithy.example#fooExample": { + "type": "structure", + "traits": { + "smithy.api#authDefinition": true, + "smithy.api#trait": { + "selector": "service" + } + } + } + } + } + +Because authentication scheme definitions are just specialized shapes, they +can also support configuration settings. + +.. code-block:: smithy + + namespace smithy.example + + @authDefinition + @trait(selector: "service") + structure algorithmAuth { + algorithm: AlgorithmAuthAlgorithm, + } + + @private + @enum("SHA-2": {}) + string AlgorithmAuthAlgorithm + + @algorithmAuth(algorithm: "SHA-2") + service WeatherService { + version: "2017-02-11", + } + + +.. _httpBasicAuth-trait: + +``httpBasicAuth`` trait +----------------------- + +Summary + Indicates that a service supports HTTP Basic Authentication as + defined in :rfc:`2617`. +Trait selector + ``service`` +Value type + Annotation trait. + +.. code-block:: smithy + + @httpBasicAuth + service WeatherService { + version: "2017-02-11", + } + + +.. _httpDigestAuth-trait: + +``httpDigestAuth`` trait +------------------------ + +Summary + Indicates that a service supports HTTP Digest Authentication as defined + in :rfc:`2617`. +Trait selector + ``service`` +Value type + Annotation trait. + +.. code-block:: smithy + + @httpDigestAuth + service WeatherService { + version: "2017-02-11", + } + + +.. _httpBearerAuth-trait: + +``httpBearerAuth`` trait +------------------------ + +Summary + Indicates that a service supports HTTP Bearer Authentication as defined + in :rfc:`6750`. +Trait selector + ``service`` +Value type + Annotation trait. + +.. code-block:: smithy + + @httpBearerAuth + service WeatherService { + version: "2017-02-11", + } + + +.. _httpApiKeyAuth-trait: + +``httpApiKeyAuth`` trait +------------------------ + +Summary + Indicates that a service supports HTTP-specific authentication using an + API key sent in a header or query string parameter. +Trait selector + ``service`` +Value type + Object + +The ``httpApiKeyAuth`` trait is an object that supports the following +properties: + +.. list-table:: + :header-rows: 1 + :widths: 10 10 80 + + * - Property + - Type + - Description + * - name + - ``string`` + - **Required**. Defines the name of the HTTP header or query string + parameter that contains the API key. + * - in + - ``string`` + - **Required**. Defines the location of where the key is serialized. + This value can be set to ``header`` or ``query``. + +The following example defines a service that accepts an API key in the "X-Api-Key" +HTTP header: + +.. code-block:: smithy + + @httpApiKeyAuth(name: "X-Api-Key", in: "header") + service WeatherService { + version: "2017-02-11", + } + + +.. _optionalAuth-trait: + +``optionalAuth`` trait +---------------------- + +Summary + Indicates that an operation MAY be invoked without authentication, + regardless of any authentication traits applied to the operation. +Trait selector + ``operation`` +Value type + Annotation trait. + +The following example defines a service that uses HTTP digest authentication, +and bound to the service is an operation that supports unauthenticated access. + +.. code-block:: smithy + + @httpDigestAuth + service WeatherService { + version: "2017-02-11", + operations: [PingServer] + } + + @optionalAuth + operation PingServer {} + +The following example defines an operation that does not support +*any* authentication. This kind of operation does not require the +``optionalAuth`` trait. + +.. code-block:: smithy + + @auth([]) + operation SomeUnauthenticatedOperation {} + + +.. _auth-trait: + +``auth`` trait +-------------- + +Summary + Defines the priority ordered authentication schemes supported by a service + or operation. When applied to a service, it defines the default + authentication schemes of every operation in the service. When applied + to an operation, it defines the list of all authentication schemes + supported by the operation, overriding any ``auth`` trait specified + on a service. +Trait selector + ``:test(service, operation)`` + + *Service or operation shapes* +Value type + This trait contains a priority ordered list of unique string values that + reference authentication scheme shape IDs defined on a service + shape. + +Operations that are not annotated with the ``auth`` trait inherit the ``auth`` +trait of the service they are bound to, and if the service is not annotated +with the ``auth`` trait, then the operation is expected to support each of +the :ref:`authentication scheme traits ` applied to the +service. Each entry in the ``auth`` trait is a shape ID that MUST refer to an +authentication scheme trait applied to the service in which it is bound. + +The following example defines two operations: + +* OperationA defines an explicit list of the authentication schemes it + supports using the ``auth`` trait. +* OperationB is not annotated with the ``auth`` trait, so the schemes + supported by this operation inherit all of the authentication schemes + applied to the service. + +.. tabs:: + + .. code-tab:: smithy + + @httpBasicAuth + @httpDigestAuth + @auth([httpBasicAuth]) + service AuthenticatedService { + version: "2017-02-11", + operations: [OperationA, OperationB] + } + + // This operation is configured to only support httpDigestAuth. + // It is not expected to support httpBasicAuth. + @auth([httpDigestAuth]) + operation OperationA {} + + // This operation defines no auth trait, so it is expected to + // support the effective authentication schemes of the service: + // httpBasicAuth and httpDigestAuth. + operation OperationB {} + + .. code-tab:: json + + { + "smithy": "0.5.0", + "shapes": { + "smithy.example#AuthenticatedService": { + "type": "service", + "version": "2017-02-11", + "operations": [ + { + "target": "smithy.example#OperationA" + }, + { + "target": "smithy.example#OperationB" + } + ], + "traits": { + "smithy.api#httpBasicAuth": true, + "smithy.api#httpDigestAuth": true, + "smithy.api#auth": [ + "smithy.api#httpBasicAuth" + ] + } + }, + "smithy.example#OperationA": { + "type": "operation", + "traits": { + "smithy.api#auth": [ + "smithy.api#httpDigestAuth" + ] + } + }, + "smithy.example#OperationB": { + "type": "operation" + } + } + } + +The following ``auth`` trait is invalid because it references an +authentication scheme trait that is not applied to the service: + +.. code-block:: smithy + + @httpDigestAuth + @auth([httpBasicAuth]) // <-- Invalid! + service InvalidExample { + version: "2017-02-11" + } + +The following operation ``auth`` trait is invalid because it references an +authentication scheme trait that is not applied to the service: + +.. code-block:: smithy + + @httpDigestAuth + @auth([httpBasicAuth]) // <-- Invalid! + service InvalidExample { + version: "2017-02-11" + } + + .. _documentation-traits: Documentation traits diff --git a/docs/source/spec/event-streams.rst b/docs/source/spec/event-streams.rst index 9977f247432..414134f6b51 100644 --- a/docs/source/spec/event-streams.rst +++ b/docs/source/spec/event-streams.rst @@ -7,8 +7,8 @@ Event stream specification An event stream is an abstraction that allows multiple messages to be sent asynchronously between a client and server. Event streams support both duplex and simplex streaming. The serialization format and framing of messages sent -over event streams is defined by the :ref:`protocol ` of a -service. +over event streams is defined by the :ref:`protocol ` +of a service. An operation can send an event stream as part of its input or output. An event stream is formed when an input or output member of an operation is diff --git a/docs/source/spec/http-protocol-compliance-tests.rst b/docs/source/spec/http-protocol-compliance-tests.rst index 8dd288b8562..c6cd2bc47f3 100644 --- a/docs/source/spec/http-protocol-compliance-tests.rst +++ b/docs/source/spec/http-protocol-compliance-tests.rst @@ -91,10 +91,11 @@ that support the following properties: ``id`` MUST match Smithy's :token:`identifier` ABNF. No two ``httpRequestTests`` test cases can share the same ID. * - protocol - - ``string`` - - **Required**. The name of the :ref:`protocol ` to - test. Because Smithy services can support multiple protocols, each - test MUST specify which protocol is under test. + - shape ID + - **Required**. A shape ID that targets a shape marked with the + :ref:`protocolDefinition-trait`. Because Smithy services can support + multiple protocols, each test MUST specify which protocol is under + test. * - method - ``string`` - **Required**. The expected serialized HTTP request method. @@ -103,10 +104,11 @@ that support the following properties: - **Required**. The request-target of the HTTP request, not including the query string (for example, "/foo/bar"). * - authScheme - - ``string`` - - The optional :ref:`authentication scheme ` to assume. - It's possible that specific authentication schemes might influence - the serialization logic of an HTTP request. + - shape ID + - A shape ID that specifies the optional authentication scheme to + assume. It's possible that specific authentication schemes might + influence the serialization logic of an HTTP request. The targeted + shape MUST be marked with the :ref:`authDefinition-trait` trait. * - queryParams - ``[string]`` - A list of the expected serialized query string parameters. @@ -212,7 +214,7 @@ that uses :ref:`HTTP binding traits `. @httpRequestTests([ { id: "say_hello", - protocol: "example", + protocol: exampleProtocol, params: { "greeting": "Hi", "name": "Teddy", @@ -263,7 +265,7 @@ that uses :ref:`HTTP binding traits `. "smithy.test#httpRequestTests": [ { "id": "say_hello", - "protocol": "example", + "protocol": "smithy.example#exampleProtocol", "method": "POST", "uri": "/", "headers": { @@ -337,17 +339,19 @@ that support the following properties: ``httpResponseTests`` test cases can share the same ID. * - protocol - ``string`` - - **Required**. The name of the :ref:`protocol ` to - test. Because Smithy services can support multiple protocols, each - test MUST specify which protocol is under test. + - **Required**. A shape ID that targets a shape marked with the + :ref:`protocolDefinition-trait` trait. Because Smithy services can + support multiple protocols, each test MUST specify which protocol is + under test. * - code - ``integer`` - **Required**. The expected HTTP response status code. * - authScheme - - ``string`` - - The optional :ref:`authentication scheme ` to assume. - It's possible that specific authentication schemes might influence - the serialization logic of an HTTP response. + - shape ID + - A shape ID that specifies the optional authentication scheme to + assume. It's possible that specific authentication schemes might + influence the serialization logic of an HTTP response. The targeted + shape MUST be marked with the :ref:`authDefinition-trait` trait. * - headers - ``Map`` - A map of expected HTTP headers. Each key represents a header field @@ -411,7 +415,7 @@ that uses :ref:`HTTP binding traits `. @httpResponseTests([ { id: "say_goodbye", - protocol: "example", + protocol: exampleProtocol, params: {farewell: "Bye"}, code: 200, headers: { @@ -448,7 +452,7 @@ that uses :ref:`HTTP binding traits `. "smithy.test#httpResponseTests": [ { "id": "say_goodbye", - "protocol": "example", + "protocol": "smithy.example#exampleProtocol", "headers": { "Content-Length": "0", "X-Farewell": "Bye" @@ -500,7 +504,7 @@ that uses :ref:`HTTP binding traits `. @httpResponseTests([ { id: "invalid_greeting", - protocol: "example", + protocol: exampleProtocol, params: {foo: "baz", message: "Hi"}, code: 400, headers: {"X-Foo": "baz"}, @@ -539,7 +543,7 @@ that uses :ref:`HTTP binding traits `. "smithy.test#httpResponseTests": [ { "id": "invalid_greeting", - "protocol": "example", + "protocol": "smithy.example#exampleProtocol", "body": "{\"message\": \"Hi\"}", "bodyMediaType": "application/json", "headers": { diff --git a/docs/source/spec/http.rst b/docs/source/spec/http.rst index 78d4fe47540..4af68d21f68 100644 --- a/docs/source/spec/http.rst +++ b/docs/source/spec/http.rst @@ -534,8 +534,8 @@ Various HTTP headers are highly discouraged for the ``httpHeader`` and * - Header - Reason * - Authorization - - This header is controlled by the :ref:`protocols-trait` and - :ref:`auth-trait`. + - This header should be populated by + :ref:`authentication traits `. * - Connection - This is controlled at a lower level by the HTTP client or server. * - Content-Length @@ -548,7 +548,8 @@ Various HTTP headers are highly discouraged for the ``httpHeader`` and * - Max-Forwards - This is controlled at a lower level by the HTTP client. * - Proxy-Authenticate - - Use the :ref:`protocols-trait` of a service. + - This header should be populated by + :ref:`authentication traits `. * - Server - The Server header is controlled by the HTTP server, not the model. * - TE @@ -562,7 +563,8 @@ Various HTTP headers are highly discouraged for the ``httpHeader`` and * - User-Agent - Setting a User-Agent is the responsibility of an HTTP client. * - WWW-Authenticate - - Use the :ref:`protocols-trait` of a service. + - This header should be populated by + :ref:`authentication traits `. * - X-Forwarded-For - X-Forwarded-For is an implementation detail of HTTP that does not need to be modeled. @@ -682,8 +684,8 @@ Serialization rules: #. When a string or blob member is referenced, the raw value is serialized as the body of the message. #. When a :ref:`structure` or :ref:`union` is targeted, the shape value - is serialized as a :ref:`protocol-specific ` document that - is sent as the body of the message. + is serialized as a :ref:`protocol-specific ` + document that is sent as the body of the message. .. _httpPrefixHeaders-trait: diff --git a/docs/source/spec/index.rst b/docs/source/spec/index.rst index 98f15355468..123cf93dc75 100644 --- a/docs/source/spec/index.rst +++ b/docs/source/spec/index.rst @@ -83,8 +83,13 @@ AWS specifications :maxdepth: 1 aws-core + aws-auth aws-iam amazon-apigateway + aws-restjson1-protocol + aws-json-protocols + aws-restxml-protocol + aws-query-protocol AWS-specific specifications are defined below. @@ -93,7 +98,17 @@ AWS-specific specifications are defined below. * - :doc:`aws-core` - Defines core traits used to integrate Smithy models with AWS. + * - :doc:`aws-auth` + - Defines AWS authentication schemes. * - :doc:`aws-iam` - Defines AWS IAM traits. * - :doc:`amazon-apigateway` - Defines Amazon API Gateway integrations. + * - :doc:`aws-restjson1-protocol` + - Defines the AWS restJson1 protocol. + * - :doc:`aws-json-protocols` + - Defines the AWS JSON 1.0 and 1.1 protocols. + * - :doc:`aws-restxml-protocol` + - Defines the AWS restXml protocol. + * - :doc:`aws-query-protocol` + - Defines the AWS query protocol. diff --git a/docs/source/spec/validation.rst b/docs/source/spec/validation.rst index 005c47d32eb..3be42708b39 100644 --- a/docs/source/spec/validation.rst +++ b/docs/source/spec/validation.rst @@ -556,98 +556,6 @@ Default severity Best practice validators ======================== -.. _DeprecatedAuthSchemes: - -DeprecatedAuthSchemes ---------------------- - -Validates that :ref:`auth schemes ` used are not in the -configured set of deprecated schemes. A validation event is emitted when one -of the deprecated auth schemes is found on a service shape. - -Rationale - As a service evolves, its authentication schemes might too. This validator - can be used to inform consumers of a Smithy model that the auth scheme - listed should be considered deprecated. - -Default Severity - ``WARNING`` - -Configuration - .. list-table:: - :header-rows: 1 - :widths: 20 20 60 - - * - Property - - Type - - Description - * - schemes - - [ ``string`` ] - - **Required**. A list of deprecated auth scheme names. - * - reason - - ``string`` - - A reason to display for why these auth schemes are deprecated. - -Example: - -.. code-block:: smithy - - metadata validators = [{ - id: "DeprecateFooScheme" - name: "DeprecatedAuthSchemes", - configuration: { - schemes: ["foo"], - reason: "Please migrate to the foo2 scheme.", - } - }] - - -.. _DeprecatedProtocols: - -DeprecatedProtocols -------------------- - -Validates that :ref:`protocols ` used are not in the -configured set of deprecated protocols. A validation event is emitted when one -of the deprecated protocols is found on a service shape. - -Rationale - As a service evolves, its protocols might too. This validator can be used - to inform consumers of a Smithy model that the protocol listed should be - considered deprecated. - -Default Severity - ``WARNING`` - -Configuration - .. list-table:: - :header-rows: 1 - :widths: 20 20 60 - - * - Property - - Type - - Description - * - protocols - - [ ``string`` ] - - **Required**. A list of deprecated protocol names. - * - reason - - ``string`` - - A reason to display for why these protocols are deprecated. - -Example: - -.. code-block:: smithy - - metadata validators = [{ - id: "DeprecateFooProtocol" - name: "DeprecatedProtocols", - configuration: { - protocols: ["foo"], - reason: "Please migrate to the bar protocol.", - } - }] - - .. _InputOutputStructureReuse: InputOutputStructureReuse diff --git a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddApiKeySource.java b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddApiKeySource.java index a4704d2312e..120ada05994 100644 --- a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddApiKeySource.java +++ b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddApiKeySource.java @@ -17,6 +17,7 @@ import java.util.logging.Logger; import software.amazon.smithy.aws.traits.apigateway.ApiKeySourceTrait; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.fromsmithy.Context; import software.amazon.smithy.openapi.fromsmithy.OpenApiMapper; import software.amazon.smithy.openapi.model.OpenApi; @@ -26,7 +27,7 @@ final class AddApiKeySource implements OpenApiMapper { private static final Logger LOGGER = Logger.getLogger(AddApiKeySource.class.getName()); @Override - public OpenApi after(Context context, OpenApi openApi) { + public OpenApi after(Context context, OpenApi openApi) { return context.getService().getTrait(ApiKeySourceTrait.class) .map(trait -> { LOGGER.fine(() -> String.format( diff --git a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddAuthorizers.java b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddAuthorizers.java index 1e38ca684b0..036fef7fc8e 100644 --- a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddAuthorizers.java +++ b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddAuthorizers.java @@ -26,6 +26,8 @@ import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.shapes.ServiceShape; import software.amazon.smithy.model.shapes.Shape; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.fromsmithy.Context; import software.amazon.smithy.openapi.fromsmithy.OpenApiMapper; import software.amazon.smithy.openapi.fromsmithy.SecuritySchemeConverter; @@ -58,14 +60,14 @@ final class AddAuthorizers implements OpenApiMapper { @Override public Map> updateSecurity( - Context context, + Context context, Shape shape, - SecuritySchemeConverter converter, + SecuritySchemeConverter converter, Map> requirement ) { // Only modify requirements that exactly match the updated scheme. if (requirement.size() != 1 - || !requirement.keySet().iterator().next().equals(converter.getAuthSchemeName())) { + || !requirement.keySet().iterator().next().equals(converter.getAuthSchemeId().toString())) { return requirement; } @@ -80,41 +82,29 @@ public Map> updateSecurity( } @Override - public OpenApi after(Context context, OpenApi openapi) { + public OpenApi after(Context context, OpenApi openapi) { return context.getService().getTrait(AuthorizersTrait.class) .map(authorizers -> addComputedAuthorizers(context, openapi, authorizers)) .orElse(openapi); } - private OpenApi addComputedAuthorizers(Context context, OpenApi openApi, AuthorizersTrait trait) { + private OpenApi addComputedAuthorizers( + Context context, + OpenApi openApi, + AuthorizersTrait trait + ) { OpenApi.Builder builder = openApi.toBuilder(); ComponentsObject.Builder components = openApi.getComponents().toBuilder(); for (Map.Entry entry : trait.getAllAuthorizers().entrySet()) { - String scheme = entry.getValue().getScheme(); - for (SecuritySchemeConverter converter : context.getSecuritySchemeConverters()) { - AuthorizerDefinition authorizer = entry.getValue(); - if (converter.getAuthSchemeName().equals(scheme)) { - SecurityScheme createdScheme = converter.createSecurityScheme(context); - SecurityScheme.Builder schemeBuilder = createdScheme.toBuilder(); - schemeBuilder.putExtension(CLIENT_EXTENSION_NAME, authorizer.getAuthType()); - - ObjectNode authorizerNode = Node.objectNodeBuilder() - .withOptionalMember("type", authorizer.getType().map(Node::from)) - .withOptionalMember("authorizerUri", authorizer.getUri().map(Node::from)) - .withOptionalMember("authorizerCredentials", authorizer.getCredentials().map(Node::from)) - .withOptionalMember("identityValidationExpression", - authorizer.getIdentityValidationExpression().map(Node::from)) - .withOptionalMember("identitySource", authorizer.getIdentitySource().map(Node::from)) - .withOptionalMember("authorizerResultTtlInSeconds", - authorizer.getResultTtlInSeconds().map(Node::from)) - .build(); - if (authorizerNode.size() != 0) { - schemeBuilder.putExtension(EXTENSION_NAME, authorizerNode); - } + String authorizerName = entry.getKey(); + AuthorizerDefinition authorizer = entry.getValue(); + ShapeId scheme = entry.getValue().getScheme(); - LOGGER.fine(() -> String.format("Adding the `%s` OpenAPI security scheme", entry.getKey())); - components.putSecurityScheme(entry.getKey(), schemeBuilder.build()); + for (SecuritySchemeConverter converter : context.getSecuritySchemeConverters()) { + if (isAuthConverterMatched(context, converter, scheme)) { + SecurityScheme updatedScheme = convertAuthScheme(context, converter, authorizer, authorizerName); + components.putSecurityScheme(authorizerName, updatedScheme); break; } } @@ -123,4 +113,42 @@ private OpenApi addComputedAuthorizers(Context context, OpenApi openApi, Authori builder.components(components.build()); return builder.build(); } + + private boolean isAuthConverterMatched( + Context context, + SecuritySchemeConverter converter, + ShapeId scheme + ) { + return converter.getAuthSchemeId().equals(scheme) + && context.getService().hasTrait(converter.getAuthSchemeType()); + } + + private SecurityScheme convertAuthScheme( + Context context, + SecuritySchemeConverter converter, + AuthorizerDefinition authorizer, + String authorizerName + ) { + T authTrait = context.getService().expectTrait(converter.getAuthSchemeType()); + SecurityScheme createdScheme = converter.createSecurityScheme(context, authTrait); + SecurityScheme.Builder schemeBuilder = createdScheme.toBuilder(); + schemeBuilder.putExtension(CLIENT_EXTENSION_NAME, authorizer.getAuthType()); + + ObjectNode authorizerNode = Node.objectNodeBuilder() + .withOptionalMember("type", authorizer.getType().map(Node::from)) + .withOptionalMember("authorizerUri", authorizer.getUri().map(Node::from)) + .withOptionalMember("authorizerCredentials", authorizer.getCredentials().map(Node::from)) + .withOptionalMember("identityValidationExpression", + authorizer.getIdentityValidationExpression().map(Node::from)) + .withOptionalMember("identitySource", authorizer.getIdentitySource().map(Node::from)) + .withOptionalMember("authorizerResultTtlInSeconds", + authorizer.getResultTtlInSeconds().map(Node::from)) + .build(); + if (authorizerNode.size() != 0) { + schemeBuilder.putExtension(EXTENSION_NAME, authorizerNode); + } + + LOGGER.fine(() -> String.format("Adding the `%s` OpenAPI security scheme", authorizerName)); + return schemeBuilder.build(); + } } diff --git a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddBinaryTypes.java b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddBinaryTypes.java index 28f4f2e8eed..8a9ab31480b 100644 --- a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddBinaryTypes.java +++ b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddBinaryTypes.java @@ -28,6 +28,7 @@ import software.amazon.smithy.model.node.ArrayNode; import software.amazon.smithy.model.node.Node; import software.amazon.smithy.model.traits.MediaTypeTrait; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.fromsmithy.Context; import software.amazon.smithy.openapi.fromsmithy.OpenApiMapper; import software.amazon.smithy.openapi.model.OpenApi; @@ -46,7 +47,7 @@ final class AddBinaryTypes implements OpenApiMapper { private static final String DEFAULT_BINARY_TYPE = "application/octet-stream"; @Override - public OpenApi after(Context context, OpenApi openApi) { + public OpenApi after(Context context, OpenApi openApi) { List binaryTypes = supportedMediaTypes(context).sorted().collect(Collectors.toList()); if (!binaryTypes.isEmpty()) { @@ -62,7 +63,7 @@ public OpenApi after(Context context, OpenApi openApi) { return openApi; } - private Stream supportedMediaTypes(Context context) { + private Stream supportedMediaTypes(Context context) { Model model = context.getModel(); HttpBindingIndex httpBindingIndex = context.getModel().getKnowledge(HttpBindingIndex.class); TopDownIndex topDownIndex = context.getModel().getKnowledge(TopDownIndex.class); diff --git a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddCorsPreflightIntegration.java b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddCorsPreflightIntegration.java index 2194fbe09d8..aaf4e69a6c1 100644 --- a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddCorsPreflightIntegration.java +++ b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddCorsPreflightIntegration.java @@ -31,6 +31,7 @@ import software.amazon.smithy.jsonschema.Schema; import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.traits.CorsTrait; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.OpenApiException; import software.amazon.smithy.openapi.fromsmithy.Context; import software.amazon.smithy.openapi.fromsmithy.OpenApiMapper; @@ -69,14 +70,14 @@ final class AddCorsPreflightIntegration implements OpenApiMapper { private static final String PREFLIGHT_SUCCESS = "{\"statusCode\":200}"; @Override - public PathItem updatePathItem(Context context, String path, PathItem pathItem) { + public PathItem updatePathItem(Context context, String path, PathItem pathItem) { return context.getService().getTrait(CorsTrait.class) .map(corsTrait -> addPreflightIntegration(context, path, pathItem, corsTrait)) .orElse(pathItem); } private static PathItem addPreflightIntegration( - Context context, String path, PathItem pathItem, CorsTrait corsTrait) { + Context context, String path, PathItem pathItem, CorsTrait corsTrait) { // Filter out any path for which an OPTIONS handler has already been defined if (pathItem.getOptions().isPresent()) { LOGGER.fine(() -> path + " already defines an OPTIONS request, so no need to generate CORS-preflight"); @@ -91,7 +92,7 @@ private static PathItem addPreflightIntegration( } private static Map deduceCorsHeaders( - Context context, String path, PathItem pathItem, CorsTrait corsTrait) { + Context context, String path, PathItem pathItem, CorsTrait corsTrait) { Map corsHeaders = new HashMap<>(); corsHeaders.put(CorsHeader.MAX_AGE, String.valueOf(corsTrait.getMaxAge())); corsHeaders.put(CorsHeader.ALLOW_ORIGIN, corsTrait.getOrigin()); @@ -109,7 +110,7 @@ private static Map deduceCorsHeaders( headerNames.addAll(findAllHeaders(path, pathItem)); // Add all headers generated by security schemes. - for (SecuritySchemeConverter converter : context.getSecuritySchemeConverters()) { + for (SecuritySchemeConverter converter : context.getSecuritySchemeConverters()) { headerNames.addAll(converter.getAuthRequestHeaders()); } diff --git a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddCorsResponseHeaders.java b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddCorsResponseHeaders.java index 7c47d9af154..9a7d02bc8ca 100644 --- a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddCorsResponseHeaders.java +++ b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddCorsResponseHeaders.java @@ -21,6 +21,7 @@ import software.amazon.smithy.jsonschema.Schema; import software.amazon.smithy.model.shapes.OperationShape; import software.amazon.smithy.model.traits.CorsTrait; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.fromsmithy.Context; import software.amazon.smithy.openapi.fromsmithy.OpenApiMapper; import software.amazon.smithy.openapi.model.ParameterObject; @@ -42,14 +43,22 @@ final class AddCorsResponseHeaders implements OpenApiMapper { @Override public ResponseObject updateResponse( - Context context, String status, OperationShape shape, ResponseObject response) { + Context context, + String status, + OperationShape shape, + ResponseObject response + ) { return context.getService().getTrait(CorsTrait.class) .map(corsTrait -> addCorsHeadersToResponse(context, shape, response, corsTrait)) .orElse(response); } private ResponseObject addCorsHeadersToResponse( - Context context, OperationShape operation, ResponseObject response, CorsTrait corsTrait) { + Context context, + OperationShape operation, + ResponseObject response, + CorsTrait corsTrait + ) { // Determine which headers have been added to the response. List headers = new ArrayList<>(); headers.add(CorsHeader.ALLOW_ORIGIN.toString()); diff --git a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddCorsToGatewayResponses.java b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddCorsToGatewayResponses.java index 3ac8315c1ff..3628fea078f 100644 --- a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddCorsToGatewayResponses.java +++ b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddCorsToGatewayResponses.java @@ -24,6 +24,7 @@ import software.amazon.smithy.model.node.Node; import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.traits.CorsTrait; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.fromsmithy.Context; import software.amazon.smithy.openapi.fromsmithy.OpenApiMapper; import software.amazon.smithy.openapi.model.OpenApi; @@ -64,13 +65,13 @@ final class AddCorsToGatewayResponses implements OpenApiMapper { private static final String RESPONSE_PARAMETERS_KEY = "responseParameters"; @Override - public OpenApi after(Context context, OpenApi openapi) { + public OpenApi after(Context context, OpenApi openapi) { return context.getService().getTrait(CorsTrait.class) .map(corsTrait -> updateModel(context, openapi, corsTrait)) .orElse(openapi); } - private OpenApi updateModel(Context context, OpenApi openapi, CorsTrait corsTrait) { + private OpenApi updateModel(Context context, OpenApi openapi, CorsTrait corsTrait) { // Update the existing gateway responses if present, or inject a default one if not. Node extension = openapi.getExtension(GATEWAY_RESPONSES_EXTENSION) .map(node -> node.expectObjectNode(GATEWAY_RESPONSES_EXTENSION + " must be an object")) @@ -82,12 +83,16 @@ private OpenApi updateModel(Context context, OpenApi openapi, CorsTrait corsTrai .build(); } - private Node updateGatewayResponses(Context context, CorsTrait trait) { + private Node updateGatewayResponses(Context context, CorsTrait trait) { LOGGER.fine(() -> "Injecting default API Gateway responses for " + context.getService().getId()); return updateGatewayResponses(context, trait, DEFAULT_GATEWAY_RESPONSES); } - private Node updateGatewayResponses(Context context, CorsTrait trait, ObjectNode gatewayResponses) { + private Node updateGatewayResponses( + Context context, + CorsTrait trait, + ObjectNode gatewayResponses + ) { Map corsHeaders = new HashMap<>(); corsHeaders.put(CorsHeader.ALLOW_ORIGIN, trait.getOrigin()); diff --git a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddIntegrations.java b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddIntegrations.java index 2639258b9fc..bd5629c1a2c 100644 --- a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddIntegrations.java +++ b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddIntegrations.java @@ -54,7 +54,11 @@ final class AddIntegrations implements OpenApiMapper { private static final String RESPONSE_PARAMETERS_KEY = "responseParameters"; @Override - public OperationObject updateOperation(Context context, OperationShape shape, OperationObject operation) { + public OperationObject updateOperation( + Context context, + OperationShape shape, + OperationObject operation + ) { IntegrationTraitIndex index = context.getModel().getKnowledge(IntegrationTraitIndex.class); return index.getIntegrationTrait(context.getService(), shape) .map(trait -> operation.toBuilder() @@ -66,7 +70,11 @@ public OperationObject updateOperation(Context context, OperationShape shape, Op }); } - private ObjectNode createIntegration(Context context, OperationShape shape, Trait integration) { + private ObjectNode createIntegration( + Context context, + OperationShape shape, + Trait integration + ) { ObjectNode integrationObject = getIntegrationAsObject(context, shape, integration); return context.getService().getTrait(CorsTrait.class) .map(cors -> { @@ -76,7 +84,11 @@ private ObjectNode createIntegration(Context context, OperationShape shape, Trai .orElse(integrationObject); } - private static ObjectNode getIntegrationAsObject(Context context, OperationShape shape, Trait integration) { + private static ObjectNode getIntegrationAsObject( + Context context, + OperationShape shape, + Trait integration + ) { if (integration instanceof MockIntegrationTrait) { return integration.toNode().expectObjectNode().withMember("type", Node.from("mock")); } else if (integration instanceof IntegrationTrait) { @@ -87,7 +99,11 @@ private static ObjectNode getIntegrationAsObject(Context context, OperationShape } private ObjectNode updateIntegrationWithCors( - Context context, OperationShape shape, ObjectNode integrationNode, CorsTrait cors) { + Context context, + OperationShape shape, + ObjectNode integrationNode, + CorsTrait cors + ) { ObjectNode responses = integrationNode.getObjectMember(RESPONSES_KEY).orElse(Node.objectNode()); // Always include a "default" response that has the same HTTP response code. @@ -119,7 +135,11 @@ private ObjectNode updateIntegrationWithCors( } private ObjectNode updateIntegrationResponse( - OperationShape shape, Map corsHeaders, Set deduced, ObjectNode response) { + OperationShape shape, + Map corsHeaders, + Set deduced, + ObjectNode response + ) { Map responseHeaders = new HashMap<>(corsHeaders); ObjectNode responseParams = response.getObjectMember(RESPONSE_PARAMETERS_KEY).orElseGet(Node::objectNode); diff --git a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddRequestValidators.java b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddRequestValidators.java index 9770fcda39c..95cf9ef7481 100644 --- a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddRequestValidators.java +++ b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddRequestValidators.java @@ -22,6 +22,7 @@ import software.amazon.smithy.model.node.Node; import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.shapes.OperationShape; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.fromsmithy.Context; import software.amazon.smithy.openapi.fromsmithy.OpenApiMapper; import software.amazon.smithy.openapi.model.OpenApi; @@ -56,7 +57,11 @@ final class AddRequestValidators implements OpenApiMapper { ); @Override - public OperationObject updateOperation(Context context, OperationShape shape, OperationObject operation) { + public OperationObject updateOperation( + Context context, + OperationShape shape, + OperationObject operation + ) { return shape.getTrait(RequestValidatorTrait.class) .map(RequestValidatorTrait::getValue) .map(value -> operation.toBuilder().putExtension(REQUEST_VALIDATOR, value).build()) @@ -64,7 +69,7 @@ public OperationObject updateOperation(Context context, OperationShape shape, Op } @Override - public OpenApi after(Context context, OpenApi openapi) { + public OpenApi after(Context context, OpenApi openapi) { // Find each known request validator on operation shapes. Set validators = context.getModel().shapes(OperationShape.class) .flatMap(shape -> OptionalUtils.stream(shape.getTrait(RequestValidatorTrait.class))) diff --git a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/ApiGatewayExtension.java b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/ApiGatewayExtension.java index ea5172948e7..87b75a3a0e8 100644 --- a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/ApiGatewayExtension.java +++ b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/ApiGatewayExtension.java @@ -16,6 +16,7 @@ package software.amazon.smithy.aws.apigateway.openapi; import java.util.List; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.fromsmithy.OpenApiMapper; import software.amazon.smithy.openapi.fromsmithy.SecuritySchemeConverter; import software.amazon.smithy.openapi.fromsmithy.Smithy2OpenApiExtension; @@ -38,7 +39,9 @@ public List getOpenApiMappers() { } @Override - public List getSecuritySchemeConverters() { - return ListUtils.of(new CognitoUserPoolsConverter()); + public List> getSecuritySchemeConverters() { + return ListUtils.of( + new CognitoUserPoolsConverter() + ); } } diff --git a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/CloudFormationSubstitution.java b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/CloudFormationSubstitution.java index 59adb891181..cfec3b5b6fe 100644 --- a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/CloudFormationSubstitution.java +++ b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/CloudFormationSubstitution.java @@ -32,6 +32,7 @@ import software.amazon.smithy.model.node.NodeVisitor; import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.node.StringNode; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.OpenApiConstants; import software.amazon.smithy.openapi.fromsmithy.Context; import software.amazon.smithy.openapi.fromsmithy.OpenApiMapper; @@ -67,7 +68,7 @@ public byte getOrder() { } @Override - public ObjectNode updateNode(Context context, OpenApi openapi, ObjectNode node) { + public ObjectNode updateNode(Context context, OpenApi openapi, ObjectNode node) { if (!context.getConfig().getBooleanMemberOrDefault(ApiGatewayConstants.DISABLE_CLOUDFORMATION_SUBSTITUTION)) { return node.accept(new CloudFormationFnSubInjector(PATHS)).expectObjectNode(); } diff --git a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/CognitoUserPoolsConverter.java b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/CognitoUserPoolsConverter.java index a20f44ff717..97d0b535699 100644 --- a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/CognitoUserPoolsConverter.java +++ b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/CognitoUserPoolsConverter.java @@ -16,10 +16,10 @@ package software.amazon.smithy.aws.apigateway.openapi; import java.util.Set; -import software.amazon.smithy.aws.traits.CognitoUserPoolsSettingsTrait; +import software.amazon.smithy.aws.traits.auth.CognitoUserPoolsTrait; import software.amazon.smithy.model.node.ArrayNode; import software.amazon.smithy.model.node.Node; -import software.amazon.smithy.openapi.OpenApiException; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.fromsmithy.Context; import software.amazon.smithy.openapi.fromsmithy.SecuritySchemeConverter; import software.amazon.smithy.openapi.model.SecurityScheme; @@ -28,32 +28,24 @@ /** * An authentication scheme converter that adds Cognito User Pool based * authentication ({@code cognito_user_pools} to an OpenAPI model when the - * {@code aws.cognito-user-pools} authentication scheme is found on + * {@code aws.auth#cognitoUserPools} authentication scheme is found on * a service shape. * * @see Integrate a REST API with a User Pool */ -final class CognitoUserPoolsConverter implements SecuritySchemeConverter { - private static final String SCHEME = "aws.cognito-user-pools"; +final class CognitoUserPoolsConverter implements SecuritySchemeConverter { private static final String AUTH_HEADER = "Authorization"; private static final Set REQUEST_HEADERS = SetUtils.of(AUTH_HEADER); private static final String AUTH_TYPE = "cognito_user_pools"; private static final String PROVIDER_ARNS_PROPERTY = "providerARNs"; @Override - public String getAuthSchemeName() { - return SCHEME; + public Class getAuthSchemeType() { + return CognitoUserPoolsTrait.class; } @Override - public SecurityScheme createSecurityScheme(Context context) { - // Providers are provided in a required trait. - CognitoUserPoolsSettingsTrait providers = context.getService() - .getTrait(CognitoUserPoolsSettingsTrait.class) - .orElseThrow(() -> new OpenApiException(String.format( - "Missing required `%s` trait for the `%s` authentication scheme of `%s`.", - CognitoUserPoolsSettingsTrait.ID, SCHEME, context.getService().getId()))); - + public SecurityScheme createSecurityScheme(Context context, CognitoUserPoolsTrait trait) { return SecurityScheme.builder() .type("apiKey") .description("Amazon Cognito User Pools authentication") @@ -63,7 +55,7 @@ public SecurityScheme createSecurityScheme(Context context) { .putExtension("x-amazon-apigateway-authorizer", Node.objectNode() .withMember("type", Node.from(AUTH_TYPE)) .withMember(PROVIDER_ARNS_PROPERTY, - providers.getProviderArns().stream().map(Node::from).collect(ArrayNode.collect()))) + trait.getProviderArns().stream().map(Node::from).collect(ArrayNode.collect()))) .build(); } diff --git a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/CorsHeader.java b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/CorsHeader.java index 796bcd7cebb..759ecd011c7 100644 --- a/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/CorsHeader.java +++ b/smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/CorsHeader.java @@ -19,6 +19,7 @@ import java.util.TreeSet; import software.amazon.smithy.model.shapes.OperationShape; import software.amazon.smithy.model.traits.CorsTrait; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.fromsmithy.Context; import software.amazon.smithy.openapi.fromsmithy.SecuritySchemeConverter; @@ -42,13 +43,17 @@ public String toString() { return headerName; } - static Set deduceOperationHeaders(Context context, OperationShape shape, CorsTrait cors) { + static Set deduceOperationHeaders( + Context context, + OperationShape shape, + CorsTrait cors + ) { // The deduced response headers of an operation consist of any headers // returned by security schemes, any headers returned by the protocol, // and any headers explicitly modeled on the operation. Set result = new TreeSet<>(cors.getAdditionalExposedHeaders()); result.addAll(context.getOpenApiProtocol().getProtocolResponseHeaders(context, shape)); - for (SecuritySchemeConverter converter : context.getSecuritySchemeConverters()) { + for (SecuritySchemeConverter converter : context.getSecuritySchemeConverters()) { result.addAll(converter.getAuthResponseHeaders()); } diff --git a/smithy-aws-apigateway-openapi/src/test/java/software/amazon/smithy/aws/apigateway/openapi/CognitoUserPoolsConverterTest.java b/smithy-aws-apigateway-openapi/src/test/java/software/amazon/smithy/aws/apigateway/openapi/CognitoUserPoolsConverterTest.java index 5971c40434c..ccfad7d9e2d 100644 --- a/smithy-aws-apigateway-openapi/src/test/java/software/amazon/smithy/aws/apigateway/openapi/CognitoUserPoolsConverterTest.java +++ b/smithy-aws-apigateway-openapi/src/test/java/software/amazon/smithy/aws/apigateway/openapi/CognitoUserPoolsConverterTest.java @@ -5,7 +5,7 @@ import software.amazon.smithy.model.Model; import software.amazon.smithy.model.node.Node; import software.amazon.smithy.model.shapes.ShapeId; -import software.amazon.smithy.openapi.OpenApiException; +import software.amazon.smithy.model.validation.ValidatedResultException; import software.amazon.smithy.openapi.fromsmithy.OpenApiConverter; import software.amazon.smithy.openapi.model.OpenApi; import software.amazon.smithy.utils.IoUtils; @@ -27,7 +27,7 @@ public void addsAwsV4() { @Test public void requiresProviderArns() { - Exception thrown = Assertions.assertThrows(OpenApiException.class, () -> { + Assertions.assertThrows(ValidatedResultException.class, () -> { Model model = Model.assembler(getClass().getClassLoader()) .discoverModels(getClass().getClassLoader()) .addImport(getClass().getResource("invalid-cognito-user-pools-security.json")) @@ -35,7 +35,5 @@ public void requiresProviderArns() { .unwrap(); OpenApiConverter.create().convert(model, ShapeId.from("smithy.example#Service")); }); - - Assertions.assertTrue(thrown.getMessage().contains("Missing required")); } } diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/api-key-source.json b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/api-key-source.json index 99bcb7468f5..46ce79e7beb 100644 --- a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/api-key-source.json +++ b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/api-key-source.json @@ -10,11 +10,7 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json" - } - ], + "aws.protocols#restJson1": {}, "aws.apigateway#apiKeySource": "HEADER" } }, diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/authorizers.json b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/authorizers.json index 5d9c6982a0d..f9d03ee805e 100644 --- a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/authorizers.json +++ b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/authorizers.json @@ -5,18 +5,14 @@ "type": "service", "version": "2018-03-17", "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json", - "auth": [ - "aws.v4" - ] - } - ], + "aws.protocols#restJson1": {}, + "aws.auth#sigv4": { + "name": "someservice" + }, "aws.apigateway#authorizer": "sigv4", "aws.apigateway#authorizers": { "sigv4": { - "scheme": "aws.v4", + "scheme": "aws.auth#sigv4", "type": "request", "uri": "arn:foo:baz", "credentials": "arn:foo:bar", diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/basic-authorizers.json b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/basic-authorizers.json index e170e6f6f41..c85bf0af3f3 100644 --- a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/basic-authorizers.json +++ b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/basic-authorizers.json @@ -5,18 +5,14 @@ "type": "service", "version": "2018-03-17", "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json", - "auth": [ - "aws.v4" - ] - } - ], + "aws.protocols#restJson1": {}, + "aws.auth#sigv4": { + "name": "someservice" + }, "aws.apigateway#authorizer": "sigv4", "aws.apigateway#authorizers": { "sigv4": { - "scheme": "aws.v4" + "scheme": "aws.auth#sigv4" } } } diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/binary-types.json b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/binary-types.json index a07841dff8b..c769241d6cc 100644 --- a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/binary-types.json +++ b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/binary-types.json @@ -13,11 +13,7 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json" - } - ] + "aws.protocols#restJson1": {} } }, "example.smithy#MyOperation": { diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cloudformation-substitutions.json b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cloudformation-substitutions.json index 282eb78dc5c..e809f3d14aa 100644 --- a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cloudformation-substitutions.json +++ b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cloudformation-substitutions.json @@ -10,15 +10,8 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json", - "auth": [ - "aws.cognito-user-pools" - ] - } - ], - "aws.api#cognitoUserPoolsSettings": { + "aws.protocols#restJson1": {}, + "aws.auth#cognitoUserPools": { "providerArns": [ "arn:aws:cognito-idp:${AWS::Region}:${AWS::AccountId}:userpool/user_pool_id", "arn:aws:cognito-idp:${AWS::Region}:${AWS::AccountId}:userpool/other_user_pool_id" diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cognito-user-pools-security.json b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cognito-user-pools-security.json index a2324f87449..501276afdb3 100644 --- a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cognito-user-pools-security.json +++ b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cognito-user-pools-security.json @@ -10,15 +10,8 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json", - "auth": [ - "aws.cognito-user-pools" - ] - } - ], - "aws.api#cognitoUserPoolsSettings": { + "aws.protocols#restJson1": {}, + "aws.auth#cognitoUserPools": { "providerArns": [ "arn:foo:baz" ] diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cognito-user-pools-security.openapi.json b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cognito-user-pools-security.openapi.json index 60eae3fad7b..16920387f88 100644 --- a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cognito-user-pools-security.openapi.json +++ b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cognito-user-pools-security.openapi.json @@ -18,7 +18,7 @@ }, "components": { "securitySchemes": { - "aws.cognito-user-pools": { + "aws.auth#cognitoUserPools": { "type": "apiKey", "description": "Amazon Cognito User Pools authentication", "name": "Authorization", @@ -35,7 +35,7 @@ }, "security": [ { - "aws.cognito-user-pools": [ ] + "aws.auth#cognitoUserPools": [ ] } ] } diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cors-explicit-options.json b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cors-explicit-options.json index ffe2dbac755..7a089e71e45 100644 --- a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cors-explicit-options.json +++ b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cors-explicit-options.json @@ -13,14 +13,8 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json-1.1", - "auth": [ - "http-basic" - ] - } - ], + "aws.protocols#restJson1": {}, + "smithy.api#httpBasicAuth": {}, "smithy.api#cors": { "origin": "https://foo.com" } diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cors-explicit-options.openapi.json b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cors-explicit-options.openapi.json index ecb6ff710aa..0d66c2f94b4 100644 --- a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cors-explicit-options.openapi.json +++ b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cors-explicit-options.openapi.json @@ -73,7 +73,7 @@ }, "components": { "securitySchemes": { - "http-basic": { + "smithy.api#httpBasicAuth": { "type": "http", "description": "HTTP Basic authentication", "scheme": "Basic" @@ -82,7 +82,7 @@ }, "security": [ { - "http-basic": [ ] + "smithy.api#httpBasicAuth": [ ] } ], "x-amazon-apigateway-gateway-responses": { diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cors-model.json b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cors-model.json index bc2187f4cd7..f02057090b6 100644 --- a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cors-model.json +++ b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cors-model.json @@ -10,15 +10,11 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json-1.1", - "auth": [ - "aws.v4", - "http-basic" - ] - } - ], + "aws.protocols#restJson1": {}, + "smithy.api#httpBasicAuth": {}, + "aws.auth#sigv4": { + "name": "myservice" + }, "smithy.api#cors": { "origin": "https://www.example.com", "maxAge": 86400, diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cors-model.openapi.json b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cors-model.openapi.json index 7b04f290464..0953f510491 100644 --- a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cors-model.openapi.json +++ b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cors-model.openapi.json @@ -384,14 +384,14 @@ } }, "securitySchemes": { - "aws.v4": { + "aws.auth#sigv4": { "type": "apiKey", "description": "AWS Signature Version 4 authentication", "name": "Authorization", "in": "header", "x-amazon-apigateway-authtype": "awsSigv4" }, - "http-basic": { + "smithy.api#httpBasicAuth": { "type": "http", "description": "HTTP Basic authentication", "scheme": "Basic" @@ -400,10 +400,10 @@ }, "security": [ { - "aws.v4": [ ] + "smithy.api#httpBasicAuth": [ ] }, { - "http-basic": [ ] + "aws.auth#sigv4": [ ] } ], "x-amazon-apigateway-gateway-responses": { diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cors-with-custom-gateway-response-headers.openapi.json b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cors-with-custom-gateway-response-headers.openapi.json index a79fdd10b8f..d8f9c8f8696 100644 --- a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cors-with-custom-gateway-response-headers.openapi.json +++ b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/cors-with-custom-gateway-response-headers.openapi.json @@ -73,7 +73,7 @@ }, "components": { "securitySchemes": { - "http-basic": { + "smithy.api#httpBasicAuth": { "type": "http", "description": "HTTP Basic authentication", "scheme": "Basic" @@ -82,7 +82,7 @@ }, "security": [ { - "http-basic": [ ] + "smithy.api#httpBasicAuth": [ ] } ], "x-amazon-apigateway-gateway-responses": { diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/custom-auth-type-authorizer.json b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/custom-auth-type-authorizer.json index f31ed87721b..60aa50b1be4 100644 --- a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/custom-auth-type-authorizer.json +++ b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/custom-auth-type-authorizer.json @@ -5,18 +5,14 @@ "type": "service", "version": "2018-03-17", "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json", - "auth": [ - "aws.v4" - ] - } - ], + "aws.protocols#restJson1": {}, + "aws.auth#sigv4": { + "name": "someservice" + }, "aws.apigateway#authorizer": "sigv4", "aws.apigateway#authorizers": { "sigv4": { - "scheme": "aws.v4", + "scheme": "aws.auth#sigv4", "customAuthType": "myCustomType" } } diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/integrations-without-credentials.json b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/integrations-without-credentials.json index 9bcefbfd33c..004b864906a 100644 --- a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/integrations-without-credentials.json +++ b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/integrations-without-credentials.json @@ -13,11 +13,7 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json" - } - ], + "aws.protocols#restJson1": {}, "aws.api#service": { "sdkId": "Some Value" }, diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/integrations.json b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/integrations.json index b05611873d1..ee396ab6e78 100644 --- a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/integrations.json +++ b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/integrations.json @@ -13,11 +13,7 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json" - } - ], + "aws.protocols#restJson1": {}, "aws.api#service": { "sdkId": "Some Value" }, diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/invalid-cognito-user-pools-security.json b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/invalid-cognito-user-pools-security.json index d407f6cfb6b..89ba80f9bf9 100644 --- a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/invalid-cognito-user-pools-security.json +++ b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/invalid-cognito-user-pools-security.json @@ -10,14 +10,8 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json", - "auth": [ - "aws.cognito-user-pools" - ] - } - ] + "aws.protocols#restJson1": {}, + "aws.auth#cognitoUserPools": {} } }, "smithy.example#Operation1": { diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/request-validators.json b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/request-validators.json index ba59e4c5617..546c8e556cc 100644 --- a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/request-validators.json +++ b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/request-validators.json @@ -13,11 +13,7 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json" - } - ], + "aws.protocols#restJson1": {}, "aws.apigateway#requestValidator": "full" } }, diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/substitution-not-performed.json b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/substitution-not-performed.json index 400135d0514..f0c060aec2e 100644 --- a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/substitution-not-performed.json +++ b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/substitution-not-performed.json @@ -18,7 +18,7 @@ }, "components": { "securitySchemes": { - "aws.cognito-user-pools": { + "aws.auth#cognitoUserPools": { "type": "apiKey", "description": "Amazon Cognito User Pools authentication", "name": "Authorization", @@ -36,7 +36,7 @@ }, "security": [ { - "aws.cognito-user-pools": [ ] + "aws.auth#cognitoUserPools": [ ] } ] } diff --git a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/substitution-performed.json b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/substitution-performed.json index e23c353b459..0502934f22b 100644 --- a/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/substitution-performed.json +++ b/smithy-aws-apigateway-openapi/src/test/resources/software/amazon/smithy/aws/apigateway/openapi/substitution-performed.json @@ -18,7 +18,7 @@ }, "components": { "securitySchemes": { - "aws.cognito-user-pools": { + "aws.auth#cognitoUserPools": { "type": "apiKey", "description": "Amazon Cognito User Pools authentication", "name": "Authorization", @@ -36,7 +36,7 @@ }, "security": [ { - "aws.cognito-user-pools": [ ] + "aws.auth#cognitoUserPools": [ ] } ] } diff --git a/smithy-aws-protocol-tests/model/json-rpc-1-1/main.json b/smithy-aws-protocol-tests/model/awsJson1_1/main.json similarity index 84% rename from smithy-aws-protocol-tests/model/json-rpc-1-1/main.json rename to smithy-aws-protocol-tests/model/awsJson1_1/main.json index 8fbb24d3ed1..19441196136 100644 --- a/smithy-aws-protocol-tests/model/json-rpc-1-1/main.json +++ b/smithy-aws-protocol-tests/model/awsJson1_1/main.json @@ -1,51 +1,48 @@ { "smithy": "0.5.0", "shapes": { - "aws.protocols.tests.json#JsonProtocol": { + "aws.protocoltests.json#JsonProtocol": { "type": "service", "version": "2018-01-01", "operations": [ { - "target": "aws.protocols.tests.json#EmptyOperation" + "target": "aws.protocoltests.json#EmptyOperation" }, { - "target": "aws.protocols.tests.json#KitchenSinkOperation" + "target": "aws.protocoltests.json#KitchenSinkOperation" }, { - "target": "aws.protocols.tests.json#OperationWithOptionalInputOutput" + "target": "aws.protocoltests.json#OperationWithOptionalInputOutput" } ], "traits": { "aws.api#service": { "sdkId": "Json Protocol" }, - "smithy.api#protocols": [ - { - "name": "aws.json-1.1", - "auth": ["aws.v4"] - } - ], - "smithy.api#auth": ["aws.v4"], + "aws.protocols#awsJson1_1": {}, + "aws.auth#sigv4": { + "name": "foo" + }, "smithy.api#title": "Sample Json 1.1 Protocol Service" } }, - "aws.protocols.tests.json#Blob": { + "aws.protocoltests.json#Blob": { "type": "blob" }, - "aws.protocols.tests.json#Boolean": { + "aws.protocoltests.json#Boolean": { "type": "boolean" }, - "aws.protocols.tests.json#Double": { + "aws.protocoltests.json#Double": { "type": "double" }, - "aws.protocols.tests.json#EmptyOperation": { + "aws.protocoltests.json#EmptyOperation": { "type": "operation", "traits": { "smithy.test#httpRequestTests": [ { "id": "sends_requests_to_slash", "documentation": "Sends requests to /", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": {} @@ -53,7 +50,7 @@ { "id": "includes_x_amz_target_and_content_type", "documentation": "Includes X-Amz-Target header and Content-Type", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": {}, @@ -67,7 +64,7 @@ { "id": "handles_empty_output_shape", "documentation": "Handles empty output shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "headers": { "Content-Type": "application/x-amz-json-1.1" @@ -80,27 +77,27 @@ ] } }, - "aws.protocols.tests.json#EmptyStruct": { + "aws.protocoltests.json#EmptyStruct": { "type": "structure", "members": {} }, - "aws.protocols.tests.json#ErrorWithMembers": { + "aws.protocoltests.json#ErrorWithMembers": { "type": "structure", "members": { "Code": { "target": "smithy.api#String" }, "ComplexData": { - "target": "aws.protocols.tests.json#KitchenSink" + "target": "aws.protocoltests.json#KitchenSink" }, "IntegerField": { "target": "smithy.api#Integer" }, "ListField": { - "target": "aws.protocols.tests.json#ListOfStrings" + "target": "aws.protocoltests.json#ListOfStrings" }, "MapField": { - "target": "aws.protocols.tests.json#MapOfStrings" + "target": "aws.protocoltests.json#MapOfStrings" }, "Message": { "target": "smithy.api#String" @@ -116,26 +113,26 @@ "smithy.api#error": "client" } }, - "aws.protocols.tests.json#ErrorWithoutMembers": { + "aws.protocoltests.json#ErrorWithoutMembers": { "type": "structure", "members": {}, "traits": { "smithy.api#error": "server" } }, - "aws.protocols.tests.json#Float": { + "aws.protocoltests.json#Float": { "type": "float" }, - "aws.protocols.tests.json#Integer": { + "aws.protocoltests.json#Integer": { "type": "integer" }, - "aws.protocols.tests.json#JsonValue": { + "aws.protocoltests.json#JsonValue": { "type": "string", "traits": { "smithy.api#mediaType": "application/json" } }, - "aws.protocols.tests.json#KitchenSink": { + "aws.protocoltests.json#KitchenSink": { "type": "structure", "members": { "Blob": { @@ -148,7 +145,7 @@ "target": "smithy.api#Double" }, "EmptyStruct": { - "target": "aws.protocols.tests.json#EmptyStruct" + "target": "aws.protocoltests.json#EmptyStruct" }, "Float": { "target": "smithy.api#Float" @@ -169,52 +166,52 @@ } }, "JsonValue": { - "target": "aws.protocols.tests.json#JsonValue" + "target": "aws.protocoltests.json#JsonValue" }, "ListOfLists": { - "target": "aws.protocols.tests.json#ListOfListOfStrings" + "target": "aws.protocoltests.json#ListOfListOfStrings" }, "ListOfMapsOfStrings": { - "target": "aws.protocols.tests.json#ListOfMapsOfStrings" + "target": "aws.protocoltests.json#ListOfMapsOfStrings" }, "ListOfStrings": { - "target": "aws.protocols.tests.json#ListOfStrings" + "target": "aws.protocoltests.json#ListOfStrings" }, "ListOfStructs": { - "target": "aws.protocols.tests.json#ListOfStructs" + "target": "aws.protocoltests.json#ListOfStructs" }, "Long": { "target": "smithy.api#Long" }, "MapOfListsOfStrings": { - "target": "aws.protocols.tests.json#MapOfListsOfStrings" + "target": "aws.protocoltests.json#MapOfListsOfStrings" }, "MapOfMaps": { - "target": "aws.protocols.tests.json#MapOfMapOfStrings" + "target": "aws.protocoltests.json#MapOfMapOfStrings" }, "MapOfStrings": { - "target": "aws.protocols.tests.json#MapOfStrings" + "target": "aws.protocoltests.json#MapOfStrings" }, "MapOfStructs": { - "target": "aws.protocols.tests.json#MapOfStructs" + "target": "aws.protocoltests.json#MapOfStructs" }, "RecursiveList": { - "target": "aws.protocols.tests.json#ListOfKitchenSinks" + "target": "aws.protocoltests.json#ListOfKitchenSinks" }, "RecursiveMap": { - "target": "aws.protocols.tests.json#MapOfKitchenSinks" + "target": "aws.protocoltests.json#MapOfKitchenSinks" }, "RecursiveStruct": { - "target": "aws.protocols.tests.json#KitchenSink" + "target": "aws.protocoltests.json#KitchenSink" }, "SimpleStruct": { - "target": "aws.protocols.tests.json#SimpleStruct" + "target": "aws.protocoltests.json#SimpleStruct" }, "String": { "target": "smithy.api#String" }, "StructWithLocationName": { - "target": "aws.protocols.tests.json#StructWithLocationName" + "target": "aws.protocoltests.json#StructWithLocationName" }, "Timestamp": { "target": "smithy.api#Timestamp" @@ -227,20 +224,20 @@ } } }, - "aws.protocols.tests.json#KitchenSinkOperation": { + "aws.protocoltests.json#KitchenSinkOperation": { "type": "operation", "input": { - "target": "aws.protocols.tests.json#KitchenSink" + "target": "aws.protocoltests.json#KitchenSink" }, "output": { - "target": "aws.protocols.tests.json#KitchenSink" + "target": "aws.protocoltests.json#KitchenSink" }, "errors": [ { - "target": "aws.protocols.tests.json#ErrorWithMembers" + "target": "aws.protocoltests.json#ErrorWithMembers" }, { - "target": "aws.protocols.tests.json#ErrorWithoutMembers" + "target": "aws.protocoltests.json#ErrorWithoutMembers" } ], "traits": { @@ -248,7 +245,7 @@ { "id": "serializes_string_shapes", "documentation": "Serializes string shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -260,7 +257,7 @@ { "id": "serializes_string_shapes_with_jsonvalue_trait", "documentation": "Serializes string shapes with jsonvalue trait", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -272,7 +269,7 @@ { "id": "serializes_integer_shapes", "documentation": "Serializes integer shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -284,7 +281,7 @@ { "id": "serializes_long_shapes", "documentation": "Serializes long shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -296,7 +293,7 @@ { "id": "serializes_float_shapes", "documentation": "Serializes float shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -308,7 +305,7 @@ { "id": "serializes_double_shapes", "documentation": "Serializes double shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -320,7 +317,7 @@ { "id": "serializes_blob_shapes", "documentation": "Serializes blob shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -332,7 +329,7 @@ { "id": "serializes_boolean_shapes_true", "documentation": "Serializes boolean shapes (true)", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -344,7 +341,7 @@ { "id": "serializes_boolean_shapes_false", "documentation": "Serializes boolean shapes (false)", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -356,7 +353,7 @@ { "id": "serializes_timestamp_shapes", "documentation": "Serializes timestamp shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -368,7 +365,7 @@ { "id": "serializes_timestamp_shapes_with_iso8601_timestampformat", "documentation": "Serializes timestamp shapes with iso8601 timestampFormat", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -380,7 +377,7 @@ { "id": "serializes_timestamp_shapes_with_httpdate_timestampformat", "documentation": "Serializes timestamp shapes with httpdate timestampFormat", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -392,7 +389,7 @@ { "id": "serializes_timestamp_shapes_with_unixtimestamp_timestampformat", "documentation": "Serializes timestamp shapes with unixTimestamp timestampFormat", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -404,7 +401,7 @@ { "id": "serializes_list_shapes", "documentation": "Serializes list shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -420,7 +417,7 @@ { "id": "serializes_empty_list_shapes", "documentation": "Serializes empty list shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -432,7 +429,7 @@ { "id": "serializes_list_of_map_shapes", "documentation": "Serializes list of map shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -454,7 +451,7 @@ { "id": "serializes_list_of_structure_shapes", "documentation": "Serializes list of structure shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -476,7 +473,7 @@ { "id": "serializes_list_of_recursive_structure_shapes", "documentation": "Serializes list of recursive structure shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -500,7 +497,7 @@ { "id": "serializes_map_shapes", "documentation": "Serializes map shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -515,7 +512,7 @@ { "id": "serializes_empty_map_shapes", "documentation": "Serializes empty map shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -527,7 +524,7 @@ { "id": "serializes_map_of_list_shapes", "documentation": "Serializes map of list shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -548,7 +545,7 @@ { "id": "serializes_map_of_structure_shapes", "documentation": "Serializes map of structure shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -567,7 +564,7 @@ { "id": "serializes_map_of_recursive_structure_shapes", "documentation": "Serializes map of recursive structure shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -591,7 +588,7 @@ { "id": "serializes_structure_shapes", "documentation": "Serializes structure shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -605,7 +602,7 @@ { "id": "serializes_structure_members_with_locationname_traits", "documentation": "Serializes structure members with locationName traits", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -619,7 +616,7 @@ { "id": "serializes_empty_structure_shapes", "documentation": "Serializes empty structure shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -631,7 +628,7 @@ { "id": "serializes_structure_which_have_no_members", "documentation": "Serializes structure which have no members", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -643,7 +640,7 @@ { "id": "serializes_recursive_structure_shapes", "documentation": "Serializes recursive structure shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -675,7 +672,7 @@ { "id": "parses_operations_with_empty_json_bodies", "documentation": "Parses operations with empty JSON bodies", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "bodyMediaType": "application/json", "body": "{}", @@ -684,7 +681,7 @@ { "id": "parses_string_shapes", "documentation": "Parses string shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "bodyMediaType": "application/json", "body": "{\"String\":\"string-value\"}", @@ -695,7 +692,7 @@ { "id": "parses_integer_shapes", "documentation": "Parses integer shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "bodyMediaType": "application/json", "body": "{\"Integer\":1234}", @@ -706,7 +703,7 @@ { "id": "parses_long_shapes", "documentation": "Parses long shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "bodyMediaType": "application/json", "body": "{\"Long\":1234567890123456789}", @@ -717,7 +714,7 @@ { "id": "parses_float_shapes", "documentation": "Parses float shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "bodyMediaType": "application/json", "body": "{\"Float\":1234.5}", @@ -728,7 +725,7 @@ { "id": "parses_double_shapes", "documentation": "Parses double shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "bodyMediaType": "application/json", "body": "{\"Double\":123456789.12345679}", @@ -739,7 +736,7 @@ { "id": "parses_boolean_shapes_true", "documentation": "Parses boolean shapes (true)", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "bodyMediaType": "application/json", "body": "{\"Boolean\":true}", @@ -750,7 +747,7 @@ { "id": "parses_boolean_false", "documentation": "Parses boolean (false)", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "bodyMediaType": "application/json", "body": "{\"Boolean\":false}", @@ -761,7 +758,7 @@ { "id": "parses_blob_shapes", "documentation": "Parses blob shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "bodyMediaType": "application/json", "body": "{\"Blob\":\"YmluYXJ5LXZhbHVl\"}", @@ -772,7 +769,7 @@ { "id": "parses_timestamp_shapes", "documentation": "Parses timestamp shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "bodyMediaType": "application/json", "body": "{\"Timestamp\":946845296}", @@ -783,7 +780,7 @@ { "id": "parses_iso8601_timestamps", "documentation": "Parses iso8601 timestamps", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "bodyMediaType": "application/json", "body": "{\"Timestamp\":\"2000-01-02T20:34:56.000Z\"}", @@ -794,7 +791,7 @@ { "id": "parses_httpdate_timestamps", "documentation": "Parses httpdate timestamps", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "bodyMediaType": "application/json", "body": "{\"Timestamp\":\"Sun, 02 Jan 2000 20:34:56.000 GMT\"}", @@ -805,7 +802,7 @@ { "id": "parses_list_shapes", "documentation": "Parses list shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "bodyMediaType": "application/json", "body": "{\"ListOfStrings\":[\"abc\",\"mno\",\"xyz\"]}", @@ -820,7 +817,7 @@ { "id": "parses_list_of_map_shapes", "documentation": "Parses list of map shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "bodyMediaType": "application/json", "body": "{\"ListOfMapsOfStrings\":[{\"size\":\"large\"},{\"color\":\"red\"}]}", @@ -838,7 +835,7 @@ { "id": "parses_list_of_list_shapes", "documentation": "Parses list of list shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "bodyMediaType": "application/json", "body": "{\"ListOfLists\":[[\"abc\",\"mno\",\"xyz\"],[\"hjk\",\"qrs\",\"tuv\"]]}", @@ -860,7 +857,7 @@ { "id": "parses_list_of_structure_shapes", "documentation": "Parses list of structure shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "bodyMediaType": "application/json", "body": "{\"ListOfStructs\":[{\"Value\":\"value-1\"},{\"Value\":\"value-2\"}]}", @@ -878,7 +875,7 @@ { "id": "parses_list_of_recursive_structure_shapes", "documentation": "Parses list of recursive structure shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "bodyMediaType": "application/json", "body": "{\"RecursiveList\":[{\"RecursiveList\":[{\"RecursiveList\":[{\"String\":\"value\"}]}]}]}", @@ -901,7 +898,7 @@ { "id": "parses_map_shapes", "documentation": "Parses map shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "bodyMediaType": "application/json", "body": "{\"MapOfStrings\":{\"size\":\"large\",\"color\":\"red\"}}", @@ -915,7 +912,7 @@ { "id": "parses_map_of_list_shapes", "documentation": "Parses map of list shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "bodyMediaType": "application/json", "body": "{\"MapOfListsOfStrings\":{\"sizes\":[\"large\",\"small\"],\"colors\":[\"red\",\"green\"]}}", @@ -935,7 +932,7 @@ { "id": "parses_map_of_map_shapes", "documentation": "Parses map of map shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "bodyMediaType": "application/json", "body": "{\"MapOfMaps\":{\"sizes\":{\"large\":\"L\",\"medium\":\"M\"},\"colors\":{\"red\":\"R\",\"blue\":\"B\"}}}", @@ -955,7 +952,7 @@ { "id": "parses_map_of_structure_shapes", "documentation": "Parses map of structure shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "bodyMediaType": "application/json", "body": "{\"MapOfStructs\":{\"size\":{\"Value\":\"small\"},\"color\":{\"Value\":\"red\"}}}", @@ -973,7 +970,7 @@ { "id": "parses_map_of_recursive_structure_shapes", "documentation": "Parses map of recursive structure shapes", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "bodyMediaType": "application/json", "body": "{\"RecursiveMap\":{\"key-1\":{\"RecursiveMap\":{\"key-2\":{\"RecursiveMap\":{\"key-3\":{\"String\":\"value\"}}}}}}}", @@ -996,7 +993,7 @@ { "id": "parses_the_request_id_from_the_response", "documentation": "Parses the request id from the response", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "code": 200, "headers": { "X-Amzn-Requestid": "amazon-uniq-request-id" @@ -1005,67 +1002,67 @@ ] } }, - "aws.protocols.tests.json#ListOfKitchenSinks": { + "aws.protocoltests.json#ListOfKitchenSinks": { "type": "list", "member": { - "target": "aws.protocols.tests.json#KitchenSink" + "target": "aws.protocoltests.json#KitchenSink" } }, - "aws.protocols.tests.json#ListOfListOfStrings": { + "aws.protocoltests.json#ListOfListOfStrings": { "type": "list", "member": { - "target": "aws.protocols.tests.json#ListOfStrings" + "target": "aws.protocoltests.json#ListOfStrings" } }, - "aws.protocols.tests.json#ListOfMapsOfStrings": { + "aws.protocoltests.json#ListOfMapsOfStrings": { "type": "list", "member": { - "target": "aws.protocols.tests.json#MapOfStrings" + "target": "aws.protocoltests.json#MapOfStrings" } }, - "aws.protocols.tests.json#ListOfStrings": { + "aws.protocoltests.json#ListOfStrings": { "type": "list", "member": { "target": "smithy.api#String" } }, - "aws.protocols.tests.json#ListOfStructs": { + "aws.protocoltests.json#ListOfStructs": { "type": "list", "member": { - "target": "aws.protocols.tests.json#SimpleStruct" + "target": "aws.protocoltests.json#SimpleStruct" } }, - "aws.protocols.tests.json#Long": { + "aws.protocoltests.json#Long": { "type": "long" }, - "aws.protocols.tests.json#MapOfKitchenSinks": { + "aws.protocoltests.json#MapOfKitchenSinks": { "type": "map", "key": { "target": "smithy.api#String" }, "value": { - "target": "aws.protocols.tests.json#KitchenSink" + "target": "aws.protocoltests.json#KitchenSink" } }, - "aws.protocols.tests.json#MapOfListsOfStrings": { + "aws.protocoltests.json#MapOfListsOfStrings": { "type": "map", "key": { "target": "smithy.api#String" }, "value": { - "target": "aws.protocols.tests.json#ListOfStrings" + "target": "aws.protocoltests.json#ListOfStrings" } }, - "aws.protocols.tests.json#MapOfMapOfStrings": { + "aws.protocoltests.json#MapOfMapOfStrings": { "type": "map", "key": { "target": "smithy.api#String" }, "value": { - "target": "aws.protocols.tests.json#MapOfStrings" + "target": "aws.protocoltests.json#MapOfStrings" } }, - "aws.protocols.tests.json#MapOfStrings": { + "aws.protocoltests.json#MapOfStrings": { "type": "map", "key": { "target": "smithy.api#String" @@ -1074,29 +1071,29 @@ "target": "smithy.api#String" } }, - "aws.protocols.tests.json#MapOfStructs": { + "aws.protocoltests.json#MapOfStructs": { "type": "map", "key": { "target": "smithy.api#String" }, "value": { - "target": "aws.protocols.tests.json#SimpleStruct" + "target": "aws.protocoltests.json#SimpleStruct" } }, - "aws.protocols.tests.json#OperationWithOptionalInputOutput": { + "aws.protocoltests.json#OperationWithOptionalInputOutput": { "type": "operation", "input": { - "target": "aws.protocols.tests.json#SimpleStruct" + "target": "aws.protocoltests.json#SimpleStruct" }, "output": { - "target": "aws.protocols.tests.json#SimpleStruct" + "target": "aws.protocoltests.json#SimpleStruct" }, "traits": { "smithy.test#httpRequestTests": [ { "id": "can_call_operation_with_no_input_or_output", "documentation": "Can call operations with no input or output", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "headers": { @@ -1109,7 +1106,7 @@ { "id": "can_call_operation_with_optional_input", "documentation": "Can invoke operations with optional input", - "protocol": "aws.json-1.1", + "protocol": "aws.protocols#awsJson1_1", "method": "POST", "uri": "/", "params": { @@ -1126,7 +1123,7 @@ ] } }, - "aws.protocols.tests.json#SimpleStruct": { + "aws.protocoltests.json#SimpleStruct": { "type": "structure", "members": { "Value": { @@ -1134,10 +1131,10 @@ } } }, - "aws.protocols.tests.json#String": { + "aws.protocoltests.json#String": { "type": "string" }, - "aws.protocols.tests.json#StructWithLocationName": { + "aws.protocoltests.json#StructWithLocationName": { "type": "structure", "members": { "Value": { @@ -1148,7 +1145,7 @@ } } }, - "aws.protocols.tests.json#Timestamp": { + "aws.protocoltests.json#Timestamp": { "type": "timestamp" } } diff --git a/smithy-aws-protocol-tests/model/query/empty-input-output.smithy b/smithy-aws-protocol-tests/model/awsQuery/empty-input-output.smithy similarity index 93% rename from smithy-aws-protocol-tests/model/query/empty-input-output.smithy rename to smithy-aws-protocol-tests/model/awsQuery/empty-input-output.smithy index 62bf737caea..cf1311fa0bd 100644 --- a/smithy-aws-protocol-tests/model/query/empty-input-output.smithy +++ b/smithy-aws-protocol-tests/model/awsQuery/empty-input-output.smithy @@ -3,8 +3,9 @@ $version: "0.5.0" -namespace aws.protocols.tests.query +namespace aws.protocoltests.query +use aws.protocols#awsQuery use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -18,7 +19,7 @@ apply NoInputAndNoOutput @httpRequestTests([ { id: "QueryNoInputAndNoOutput", documentation: "No input serializes no additional query params", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -35,7 +36,7 @@ apply NoInputAndNoOutput @httpResponseTests([ { id: "QueryNoInputAndNoOutput", documentation: "Empty output. Note that no assertion is made on the output body itself.", - protocol: "aws.query", + protocol: awsQuery, code: 200, } ]) @@ -52,7 +53,7 @@ apply NoInputAndOutput @httpRequestTests([ { id: "QueryNoInputAndOutput", documentation: "No input serializes no payload", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -69,7 +70,7 @@ apply NoInputAndOutput @httpResponseTests([ { id: "QueryNoInputAndOutput", documentation: "Empty output", - protocol: "aws.query", + protocol: awsQuery, code: 200, } ]) @@ -89,7 +90,7 @@ apply EmptyInputAndEmptyOutput @httpRequestTests([ { id: "QueryEmptyInputAndEmptyOutput", documentation: "Empty input serializes no extra query params", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -106,7 +107,7 @@ apply EmptyInputAndEmptyOutput @httpResponseTests([ { id: "QueryEmptyInputAndEmptyOutput", documentation: "Empty output", - protocol: "aws.query", + protocol: awsQuery, code: 200, }, ]) diff --git a/smithy-aws-protocol-tests/model/query/input-lists.smithy b/smithy-aws-protocol-tests/model/awsQuery/input-lists.smithy similarity index 91% rename from smithy-aws-protocol-tests/model/query/input-lists.smithy rename to smithy-aws-protocol-tests/model/awsQuery/input-lists.smithy index bdaa095b88e..62521310612 100644 --- a/smithy-aws-protocol-tests/model/query/input-lists.smithy +++ b/smithy-aws-protocol-tests/model/awsQuery/input-lists.smithy @@ -2,12 +2,13 @@ $version: "0.5.0" -namespace aws.protocols.tests.query +namespace aws.protocoltests.query -use aws.protocols.tests.shared#EpochSeconds -use aws.protocols.tests.shared#FooEnum -use aws.protocols.tests.shared#GreetingList -use aws.protocols.tests.shared#StringList +use aws.protocols#awsQuery +use aws.protocoltests.shared#EpochSeconds +use aws.protocoltests.shared#FooEnum +use aws.protocoltests.shared#GreetingList +use aws.protocoltests.shared#StringList use smithy.test#httpRequestTests /// This test serializes simple and complex lists. @@ -19,7 +20,7 @@ apply QueryLists @httpRequestTests([ { id: "QueryLists", documentation: "Serializes query lists", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -49,7 +50,7 @@ apply QueryLists @httpRequestTests([ { id: "EmptyQueryLists", documentation: "Does not serialize empty query lists", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -66,7 +67,7 @@ apply QueryLists @httpRequestTests([ { id: "FlattenedQueryLists", documentation: "Flattens query lists by repeating the member name and removing the member element", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -85,7 +86,7 @@ apply QueryLists @httpRequestTests([ { id: "QueryListArgWithXmlNameMember", documentation: "Changes the member of lists using xmlName trait", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -104,7 +105,7 @@ apply QueryLists @httpRequestTests([ { id: "QueryFlattenedListArgWithXmlName", documentation: "Changes the name of flattened lists using xmlName trait on the structure member", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { diff --git a/smithy-aws-protocol-tests/model/query/input-maps.smithy b/smithy-aws-protocol-tests/model/awsQuery/input-maps.smithy similarity index 93% rename from smithy-aws-protocol-tests/model/query/input-maps.smithy rename to smithy-aws-protocol-tests/model/awsQuery/input-maps.smithy index abf2374f57a..4abc3c7ce15 100644 --- a/smithy-aws-protocol-tests/model/query/input-maps.smithy +++ b/smithy-aws-protocol-tests/model/awsQuery/input-maps.smithy @@ -2,11 +2,12 @@ $version: "0.5.0" -namespace aws.protocols.tests.query +namespace aws.protocoltests.query -use aws.protocols.tests.shared#GreetingStruct -use aws.protocols.tests.shared#StringList -use aws.protocols.tests.shared#StringMap +use aws.protocols#awsQuery +use aws.protocoltests.shared#GreetingStruct +use aws.protocoltests.shared#StringList +use aws.protocoltests.shared#StringMap use smithy.test#httpRequestTests /// This test serializes simple and complex maps. @@ -18,7 +19,7 @@ apply QueryMaps @httpRequestTests([ { id: "QuerySimpleQueryMaps", documentation: "Serializes query maps", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -42,7 +43,7 @@ apply QueryMaps @httpRequestTests([ { id: "QuerySimpleQueryMapsWithXmlName", documentation: "Serializes query maps and uses xmlName", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -63,7 +64,7 @@ apply QueryMaps @httpRequestTests([ { id: "QueryComplexQueryMaps", documentation: "Serializes complex query maps", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -91,7 +92,7 @@ apply QueryMaps @httpRequestTests([ { id: "QueryEmptyQueryMaps", documentation: "Does not serialize empty query maps", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -108,7 +109,7 @@ apply QueryMaps @httpRequestTests([ { id: "QueryQueryMapWithMemberXmlName", documentation: "Serializes query maps where the member has an xmlName trait", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -132,7 +133,7 @@ apply QueryMaps @httpRequestTests([ { id: "QueryFlattenedQueryMaps", documentation: "Serializes flattened query maps", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -156,7 +157,7 @@ apply QueryMaps @httpRequestTests([ { id: "QueryFlattenedQueryMapsWithXmlName", documentation: "Serializes flattened query maps that use an xmlName", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -180,7 +181,7 @@ apply QueryMaps @httpRequestTests([ { id: "QueryQueryMapOfLists", documentation: "Serializes query map of lists", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { diff --git a/smithy-aws-protocol-tests/model/query/input.smithy b/smithy-aws-protocol-tests/model/awsQuery/input.smithy similarity index 94% rename from smithy-aws-protocol-tests/model/query/input.smithy rename to smithy-aws-protocol-tests/model/awsQuery/input.smithy index d86913c6ffc..56b3f805521 100644 --- a/smithy-aws-protocol-tests/model/query/input.smithy +++ b/smithy-aws-protocol-tests/model/awsQuery/input.smithy @@ -2,10 +2,11 @@ $version: "0.5.0" -namespace aws.protocols.tests.query +namespace aws.protocoltests.query -use aws.protocols.tests.shared#EpochSeconds -use aws.protocols.tests.shared#FooEnum +use aws.protocols#awsQuery +use aws.protocoltests.shared#EpochSeconds +use aws.protocoltests.shared#FooEnum use smithy.test#httpRequestTests /// This test serializes strings, numbers, and boolean values. @@ -17,7 +18,7 @@ apply SimpleInputParams @httpRequestTests([ { id: "QuerySimpleInputParamsStrings", documentation: "Serializes strings", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -37,7 +38,7 @@ apply SimpleInputParams @httpRequestTests([ { id: "QuerySimpleInputParamsStringAndBooleanTrue", documentation: "Serializes booleans that are true", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -57,7 +58,7 @@ apply SimpleInputParams @httpRequestTests([ { id: "QuerySimpleInputParamsStringsAndBooleanFalse", documentation: "Serializes booleans that are false", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -75,7 +76,7 @@ apply SimpleInputParams @httpRequestTests([ { id: "QuerySimpleInputParamsInteger", documentation: "Serializes integers", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -93,7 +94,7 @@ apply SimpleInputParams @httpRequestTests([ { id: "QuerySimpleInputParamsFloat", documentation: "Serializes floats", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -111,7 +112,7 @@ apply SimpleInputParams @httpRequestTests([ { id: "QuerySimpleInputParamsBlob", documentation: "Blobs are base64 encoded in the query string", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -129,7 +130,7 @@ apply SimpleInputParams @httpRequestTests([ { id: "QueryEnums", documentation: "Serializes enums in the query string", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -169,7 +170,7 @@ apply QueryTimestamps @httpRequestTests([ { id: "QueryTimestampsInput", documentation: "Serializes timestamps", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -213,7 +214,7 @@ apply NestedStructures @httpRequestTests([ { id: "NestedStructures", documentation: "Serializes nested structures using dots", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -258,7 +259,7 @@ apply QueryIdempotencyTokenAutoFill @httpRequestTests([ { id: "QueryProtocolIdempotencyTokenAutoFill", documentation: "Automatically adds idempotency token when not set", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { @@ -273,7 +274,7 @@ apply QueryIdempotencyTokenAutoFill @httpRequestTests([ { id: "QueryProtocolIdempotencyTokenAutoFillIsSet", documentation: "Uses the given idempotency token as-is", - protocol: "aws.query", + protocol: awsQuery, method: "POST", uri: "/", headers: { diff --git a/smithy-aws-protocol-tests/model/query/main.smithy b/smithy-aws-protocol-tests/model/awsQuery/main.smithy similarity index 93% rename from smithy-aws-protocol-tests/model/query/main.smithy rename to smithy-aws-protocol-tests/model/awsQuery/main.smithy index 32dfef0b5a0..6d9274e5756 100644 --- a/smithy-aws-protocol-tests/model/query/main.smithy +++ b/smithy-aws-protocol-tests/model/awsQuery/main.smithy @@ -1,12 +1,13 @@ $version: "0.5.0" -namespace aws.protocols.tests.query +namespace aws.protocoltests.query +use aws.protocols#awsQuery use smithy.test#httpRequestTests use smithy.test#httpResponseTests /// A query service that sends query requests and XML responses. -@protocols([{"name": "aws.query"}]) +@awsQuery @xmlNamespace(uri: "https://example.com/") service AwsQuery { version: "2020-01-08", diff --git a/smithy-aws-protocol-tests/model/query/xml-errors.smithy b/smithy-aws-protocol-tests/model/awsQuery/xml-errors.smithy similarity index 96% rename from smithy-aws-protocol-tests/model/query/xml-errors.smithy rename to smithy-aws-protocol-tests/model/awsQuery/xml-errors.smithy index c2b130157af..c2c3c87ce01 100644 --- a/smithy-aws-protocol-tests/model/query/xml-errors.smithy +++ b/smithy-aws-protocol-tests/model/awsQuery/xml-errors.smithy @@ -25,8 +25,9 @@ $version: "0.5.0" -namespace aws.protocols.tests.query +namespace aws.protocoltests.query +use aws.protocols#awsQuery use smithy.test#httpResponseTests /// This operation has three possible return values: @@ -43,7 +44,7 @@ apply GreetingWithErrors @httpResponseTests([ { id: "QueryGreetingWithErrors", documentation: "Ensures that operations with errors successfully know how to deserialize the successful response", - protocol: "aws.query", + protocol: awsQuery, code: 200, headers: { "Content-Type": "text/xml" @@ -76,7 +77,7 @@ apply InvalidGreeting @httpResponseTests([ { id: "QueryInvalidGreetingError", documentation: "Parses simple XML errors", - protocol: "aws.query", + protocol: awsQuery, params: { Message: "Hi" }, @@ -109,7 +110,7 @@ structure ComplexError { apply ComplexError @httpResponseTests([ { id: "QueryComplexError", - protocol: "aws.query", + protocol: awsQuery, params: { TopLevel: "Top level", Nested: { diff --git a/smithy-aws-protocol-tests/model/query/xml-lists.smithy b/smithy-aws-protocol-tests/model/awsQuery/xml-lists.smithy similarity index 92% rename from smithy-aws-protocol-tests/model/query/xml-lists.smithy rename to smithy-aws-protocol-tests/model/awsQuery/xml-lists.smithy index cb2d8b00874..0ca2b6d787a 100644 --- a/smithy-aws-protocol-tests/model/query/xml-lists.smithy +++ b/smithy-aws-protocol-tests/model/awsQuery/xml-lists.smithy @@ -2,15 +2,16 @@ $version: "0.5.0" -namespace aws.protocols.tests.query - -use aws.protocols.tests.shared#BooleanList -use aws.protocols.tests.shared#FooEnumList -use aws.protocols.tests.shared#IntegerList -use aws.protocols.tests.shared#NestedStringList -use aws.protocols.tests.shared#StringList -use aws.protocols.tests.shared#StringSet -use aws.protocols.tests.shared#TimestampList +namespace aws.protocoltests.query + +use aws.protocols#awsQuery +use aws.protocoltests.shared#BooleanList +use aws.protocoltests.shared#FooEnumList +use aws.protocoltests.shared#IntegerList +use aws.protocoltests.shared#NestedStringList +use aws.protocoltests.shared#StringList +use aws.protocoltests.shared#StringSet +use aws.protocoltests.shared#TimestampList use smithy.test#httpResponseTests /// This test case serializes XML lists for the following cases for both @@ -31,7 +32,7 @@ apply XmlLists @httpResponseTests([ { id: "QueryXmlLists", documentation: "Serializes XML lists", - protocol: "aws.query", + protocol: awsQuery, code: 200, body: """ diff --git a/smithy-aws-protocol-tests/model/query/xml-maps.smithy b/smithy-aws-protocol-tests/model/awsQuery/xml-maps.smithy similarity index 95% rename from smithy-aws-protocol-tests/model/query/xml-maps.smithy rename to smithy-aws-protocol-tests/model/awsQuery/xml-maps.smithy index c9ba9c3aa9a..ce449f6bb57 100644 --- a/smithy-aws-protocol-tests/model/query/xml-maps.smithy +++ b/smithy-aws-protocol-tests/model/awsQuery/xml-maps.smithy @@ -2,10 +2,11 @@ $version: "0.5.0" -namespace aws.protocols.tests.query +namespace aws.protocoltests.query -use aws.protocols.tests.shared#FooEnumMap -use aws.protocols.tests.shared#GreetingStruct +use aws.protocols#awsQuery +use aws.protocoltests.shared#FooEnumMap +use aws.protocoltests.shared#GreetingStruct use smithy.test#httpResponseTests /// The example tests basic map serialization. @@ -17,7 +18,7 @@ apply XmlMaps @httpResponseTests([ { id: "QueryXmlMaps", documentation: "Serializes XML maps", - protocol: "aws.query", + protocol: awsQuery, code: 200, body: """ @@ -74,7 +75,7 @@ apply XmlMapsXmlName @httpResponseTests([ { id: "QueryQueryXmlMapsXmlName", documentation: "Serializes XML lists", - protocol: "aws.query", + protocol: awsQuery, code: 200, body: """ @@ -134,7 +135,7 @@ apply FlattenedXmlMap @httpResponseTests([ { id: "QueryQueryFlattenedXmlMap", documentation: "Serializes flattened XML maps in responses", - protocol: "aws.query", + protocol: awsQuery, code: 200, body: """ @@ -176,7 +177,7 @@ apply FlattenedXmlMapWithXmlName @httpResponseTests([ { id: "QueryQueryFlattenedXmlMapWithXmlName", documentation: "Serializes flattened XML maps in responses that have xmlName on members", - protocol: "aws.query", + protocol: awsQuery, code: 200, body: """ diff --git a/smithy-aws-protocol-tests/model/query/xml-structs.smithy b/smithy-aws-protocol-tests/model/awsQuery/xml-structs.smithy similarity index 96% rename from smithy-aws-protocol-tests/model/query/xml-structs.smithy rename to smithy-aws-protocol-tests/model/awsQuery/xml-structs.smithy index 44eb34972a8..d14d7bc8a72 100644 --- a/smithy-aws-protocol-tests/model/query/xml-structs.smithy +++ b/smithy-aws-protocol-tests/model/awsQuery/xml-structs.smithy @@ -2,12 +2,13 @@ $version: "0.5.0" -namespace aws.protocols.tests.query +namespace aws.protocoltests.query -use aws.protocols.tests.shared#FooEnum -use aws.protocols.tests.shared#FooEnumList -use aws.protocols.tests.shared#FooEnumSet -use aws.protocols.tests.shared#FooEnumMap +use aws.protocols#awsQuery +use aws.protocoltests.shared#FooEnum +use aws.protocoltests.shared#FooEnumList +use aws.protocoltests.shared#FooEnumSet +use aws.protocoltests.shared#FooEnumMap use smithy.test#httpResponseTests // This example serializes simple scalar types in the top level XML document. @@ -20,7 +21,7 @@ apply SimpleScalarXmlProperties @httpResponseTests([ { id: "QuerySimpleScalarProperties", documentation: "Serializes simple scalar properties", - protocol: "aws.query", + protocol: awsQuery, code: 200, body: """ @@ -81,7 +82,7 @@ apply XmlBlobs @httpResponseTests([ { id: "QueryXmlBlobs", documentation: "Blobs are base64 encoded", - protocol: "aws.query", + protocol: awsQuery, code: 200, body: """ @@ -115,7 +116,7 @@ apply XmlTimestamps @httpResponseTests([ { id: "QueryXmlTimestamps", documentation: "Tests how normal timestamps are serialized", - protocol: "aws.query", + protocol: awsQuery, code: 200, body: """ @@ -135,7 +136,7 @@ apply XmlTimestamps @httpResponseTests([ { id: "QueryXmlTimestampsWithDateTimeFormat", documentation: "Ensures that the timestampFormat of date-time works like normal timestamps", - protocol: "aws.query", + protocol: awsQuery, code: 200, body: """ @@ -155,7 +156,7 @@ apply XmlTimestamps @httpResponseTests([ { id: "QueryXmlTimestampsWithEpochSecondsFormat", documentation: "Ensures that the timestampFormat of epoch-seconds works", - protocol: "aws.query", + protocol: awsQuery, code: 200, body: """ @@ -175,7 +176,7 @@ apply XmlTimestamps @httpResponseTests([ { id: "QueryXmlTimestampsWithHttpDateFormat", documentation: "Ensures that the timestampFormat of http-date works", - protocol: "aws.query", + protocol: awsQuery, code: 200, body: """ @@ -216,7 +217,7 @@ apply XmlEnums @httpResponseTests([ { id: "QueryXmlEnums", documentation: "Serializes simple scalar properties", - protocol: "aws.query", + protocol: awsQuery, code: 200, body: """ @@ -281,7 +282,7 @@ apply RecursiveXmlShapes @httpResponseTests([ { id: "QueryRecursiveShapes", documentation: "Serializes recursive structures", - protocol: "aws.query", + protocol: awsQuery, code: 200, body: """ @@ -345,7 +346,7 @@ apply XmlNamespaces @httpResponseTests([ { id: "QueryXmlNamespaces", documentation: "Serializes XML namespaces", - protocol: "aws.query", + protocol: awsQuery, code: 200, body: """ @@ -410,7 +411,7 @@ apply IgnoresWrappingXmlName @httpResponseTests([ { id: "QueryIgnoresWrappingXmlName", documentation: "The xmlName trait on the output structure is ignored in AWS Query", - protocol: "aws.query", + protocol: awsQuery, code: 200, body: """ diff --git a/smithy-aws-protocol-tests/model/ec2-query/empty-input-output.smithy b/smithy-aws-protocol-tests/model/ec2Query/empty-input-output.smithy similarity index 94% rename from smithy-aws-protocol-tests/model/ec2-query/empty-input-output.smithy rename to smithy-aws-protocol-tests/model/ec2Query/empty-input-output.smithy index 0399992effe..de0b0ba5b08 100644 --- a/smithy-aws-protocol-tests/model/ec2-query/empty-input-output.smithy +++ b/smithy-aws-protocol-tests/model/ec2Query/empty-input-output.smithy @@ -3,8 +3,9 @@ $version: "0.5.0" -namespace aws.protocols.tests.ec2 +namespace aws.protocoltests.ec2 +use aws.protocols#ec2Query use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -20,7 +21,7 @@ apply NoInputAndOutput @httpRequestTests([ { id: "Ec2QueryNoInputAndOutput", documentation: "No input serializes no payload", - protocol: "aws.ec2", + protocol: ec2Query, method: "POST", uri: "/", headers: { @@ -37,7 +38,7 @@ apply NoInputAndOutput @httpResponseTests([ { id: "Ec2QueryNoInputAndOutput", documentation: "Empty output", - protocol: "aws.ec2", + protocol: ec2Query, code: 200, headers: { "Content-Type": "text/xml;charset=UTF-8" @@ -66,7 +67,7 @@ apply EmptyInputAndEmptyOutput @httpRequestTests([ { id: "Ec2QueryEmptyInputAndEmptyOutput", documentation: "Empty input serializes no extra query params", - protocol: "aws.ec2", + protocol: ec2Query, method: "POST", uri: "/", headers: { @@ -83,7 +84,7 @@ apply EmptyInputAndEmptyOutput @httpResponseTests([ { id: "Ec2QueryEmptyInputAndEmptyOutput", documentation: "Empty output", - protocol: "aws.ec2", + protocol: ec2Query, code: 200, headers: { "Content-Type": "text/xml;charset=UTF-8" diff --git a/smithy-aws-protocol-tests/model/ec2-query/input-lists.smithy b/smithy-aws-protocol-tests/model/ec2Query/input-lists.smithy similarity index 90% rename from smithy-aws-protocol-tests/model/ec2-query/input-lists.smithy rename to smithy-aws-protocol-tests/model/ec2Query/input-lists.smithy index 43b4bb63d1f..ffb29746472 100644 --- a/smithy-aws-protocol-tests/model/ec2-query/input-lists.smithy +++ b/smithy-aws-protocol-tests/model/ec2Query/input-lists.smithy @@ -2,12 +2,13 @@ $version: "0.5.0" -namespace aws.protocols.tests.ec2 +namespace aws.protocoltests.ec2 -use aws.protocols.tests.shared#EpochSeconds -use aws.protocols.tests.shared#FooEnum -use aws.protocols.tests.shared#GreetingList -use aws.protocols.tests.shared#StringList +use aws.protocols#ec2Query +use aws.protocoltests.shared#EpochSeconds +use aws.protocoltests.shared#FooEnum +use aws.protocoltests.shared#GreetingList +use aws.protocoltests.shared#StringList use smithy.test#httpRequestTests /// This test serializes simple and complex lists. @@ -19,7 +20,7 @@ apply QueryLists @httpRequestTests([ { id: "Ec2Lists", documentation: "Serializes query lists. All EC2 lists are flattened.", - protocol: "aws.ec2", + protocol: ec2Query, method: "POST", uri: "/", headers: { @@ -49,7 +50,7 @@ apply QueryLists @httpRequestTests([ { id: "Ec2EmptyQueryLists", documentation: "Does not serialize empty query lists", - protocol: "aws.ec2", + protocol: ec2Query, method: "POST", uri: "/", headers: { @@ -66,7 +67,7 @@ apply QueryLists @httpRequestTests([ { id: "Ec2ListArgWithXmlNameMember", documentation: "An xmlName trait in the member of a list has no effect on the list serialization.", - protocol: "aws.ec2", + protocol: ec2Query, method: "POST", uri: "/", headers: { @@ -85,7 +86,7 @@ apply QueryLists @httpRequestTests([ { id: "Ec2ListMemberWithXmlName", documentation: "Changes the name of the list using the xmlName trait", - protocol: "aws.ec2", + protocol: ec2Query, method: "POST", uri: "/", headers: { diff --git a/smithy-aws-protocol-tests/model/ec2-query/input.smithy b/smithy-aws-protocol-tests/model/ec2Query/input.smithy similarity index 94% rename from smithy-aws-protocol-tests/model/ec2-query/input.smithy rename to smithy-aws-protocol-tests/model/ec2Query/input.smithy index a583f3ee7e7..ab3eca18428 100644 --- a/smithy-aws-protocol-tests/model/ec2-query/input.smithy +++ b/smithy-aws-protocol-tests/model/ec2Query/input.smithy @@ -2,11 +2,12 @@ $version: "0.5.0" -namespace aws.protocols.tests.ec2 +namespace aws.protocoltests.ec2 use aws.api#ec2QueryName -use aws.protocols.tests.shared#EpochSeconds -use aws.protocols.tests.shared#FooEnum +use aws.protocols#ec2Query +use aws.protocoltests.shared#EpochSeconds +use aws.protocoltests.shared#FooEnum use smithy.test#httpRequestTests /// This test serializes strings, numbers, and boolean values. @@ -18,7 +19,7 @@ apply SimpleInputParams @httpRequestTests([ { id: "Ec2SimpleInputParamsStrings", documentation: "Serializes strings", - protocol: "aws.ec2", + protocol: ec2Query, method: "POST", uri: "/", headers: { @@ -38,7 +39,7 @@ apply SimpleInputParams @httpRequestTests([ { id: "Ec2SimpleInputParamsStringAndBooleanTrue", documentation: "Serializes booleans that are true", - protocol: "aws.ec2", + protocol: ec2Query, method: "POST", uri: "/", headers: { @@ -58,7 +59,7 @@ apply SimpleInputParams @httpRequestTests([ { id: "Ec2SimpleInputParamsStringsAndBooleanFalse", documentation: "Serializes booleans that are false", - protocol: "aws.ec2", + protocol: ec2Query, method: "POST", uri: "/", headers: { @@ -76,7 +77,7 @@ apply SimpleInputParams @httpRequestTests([ { id: "Ec2SimpleInputParamsInteger", documentation: "Serializes integers", - protocol: "aws.ec2", + protocol: ec2Query, method: "POST", uri: "/", headers: { @@ -94,7 +95,7 @@ apply SimpleInputParams @httpRequestTests([ { id: "Ec2SimpleInputParamsFloat", documentation: "Serializes floats", - protocol: "aws.ec2", + protocol: ec2Query, method: "POST", uri: "/", headers: { @@ -112,7 +113,7 @@ apply SimpleInputParams @httpRequestTests([ { id: "Ec2SimpleInputParamsBlob", documentation: "Blobs are base64 encoded in the query string", - protocol: "aws.ec2", + protocol: ec2Query, method: "POST", uri: "/", headers: { @@ -130,7 +131,7 @@ apply SimpleInputParams @httpRequestTests([ { id: "Ec2Enums", documentation: "Serializes enums in the query string", - protocol: "aws.ec2", + protocol: ec2Query, method: "POST", uri: "/", headers: { @@ -148,7 +149,7 @@ apply SimpleInputParams @httpRequestTests([ { id: "Ec2Query", documentation: "Serializes query using ec2QueryName trait.", - protocol: "aws.ec2", + protocol: ec2Query, method: "POST", uri: "/", headers: { @@ -166,7 +167,7 @@ apply SimpleInputParams @httpRequestTests([ { id: "Ec2QueryIsPreferred", documentation: "ec2QueryName trait is preferred over xmlName.", - protocol: "aws.ec2", + protocol: ec2Query, method: "POST", uri: "/", headers: { @@ -184,7 +185,7 @@ apply SimpleInputParams @httpRequestTests([ { id: "Ec2XmlNameIsUppercased", documentation: "xmlName is used with the ec2 protocol, but the first character is uppercased", - protocol: "aws.ec2", + protocol: ec2Query, method: "POST", uri: "/", headers: { @@ -234,7 +235,7 @@ apply QueryTimestamps @httpRequestTests([ { id: "Ec2TimestampsInput", documentation: "Serializes timestamps", - protocol: "aws.ec2", + protocol: ec2Query, method: "POST", uri: "/", headers: { @@ -278,7 +279,7 @@ apply NestedStructures @httpRequestTests([ { id: "Ec2NestedStructures", documentation: "Serializes nested structures using dots", - protocol: "aws.ec2", + protocol: ec2Query, method: "POST", uri: "/", headers: { @@ -323,7 +324,7 @@ apply QueryIdempotencyTokenAutoFill @httpRequestTests([ { id: "Ec2ProtocolIdempotencyTokenAutoFill", documentation: "Automatically adds idempotency token when not set", - protocol: "aws.ec2", + protocol: ec2Query, method: "POST", uri: "/", headers: { @@ -338,7 +339,7 @@ apply QueryIdempotencyTokenAutoFill @httpRequestTests([ { id: "Ec2ProtocolIdempotencyTokenAutoFillIsSet", documentation: "Uses the given idempotency token as-is", - protocol: "aws.ec2", + protocol: ec2Query, method: "POST", uri: "/", headers: { diff --git a/smithy-aws-protocol-tests/model/ec2-query/main.smithy b/smithy-aws-protocol-tests/model/ec2Query/main.smithy similarity index 96% rename from smithy-aws-protocol-tests/model/ec2-query/main.smithy rename to smithy-aws-protocol-tests/model/ec2Query/main.smithy index 8cc362bd48c..7f8f6daf461 100644 --- a/smithy-aws-protocol-tests/model/ec2-query/main.smithy +++ b/smithy-aws-protocol-tests/model/ec2Query/main.smithy @@ -26,13 +26,14 @@ $version: "0.5.0" -namespace aws.protocols.tests.ec2 +namespace aws.protocoltests.ec2 +use aws.protocols#ec2Query use smithy.test#httpRequestTests use smithy.test#httpResponseTests /// An EC2 query service that sends query requests and XML responses. -@protocols([{"name": "aws.ec2"}]) +@ec2Query @xmlNamespace(uri: "https://example.com/") service AwsEc2 { version: "2020-01-08", diff --git a/smithy-aws-protocol-tests/model/ec2-query/xml-errors.smithy b/smithy-aws-protocol-tests/model/ec2Query/xml-errors.smithy similarity index 96% rename from smithy-aws-protocol-tests/model/ec2-query/xml-errors.smithy rename to smithy-aws-protocol-tests/model/ec2Query/xml-errors.smithy index bbe60561bf6..6817bb56ea2 100644 --- a/smithy-aws-protocol-tests/model/ec2-query/xml-errors.smithy +++ b/smithy-aws-protocol-tests/model/ec2Query/xml-errors.smithy @@ -20,8 +20,9 @@ $version: "0.5.0" -namespace aws.protocols.tests.ec2 +namespace aws.protocoltests.ec2 +use aws.protocols#ec2Query use smithy.test#httpResponseTests /// This operation has three possible return values: @@ -38,7 +39,7 @@ apply GreetingWithErrors @httpResponseTests([ { id: "Ec2GreetingWithErrors", documentation: "Ensures that operations with errors successfully know how to deserialize the successful response", - protocol: "aws.ec2", + protocol: ec2Query, code: 200, headers: { "Content-Type": "text/xml;charset=UTF-8" @@ -70,7 +71,7 @@ apply InvalidGreeting @httpResponseTests([ { id: "Ec2InvalidGreetingError", documentation: "Parses simple XML errors", - protocol: "aws.ec2", + protocol: ec2Query, code: 400, headers: { "Content-Type": "text/xml;charset=UTF-8" @@ -104,7 +105,7 @@ structure ComplexError { apply ComplexError @httpResponseTests([ { id: "Ec2ComplexError", - protocol: "aws.ec2", + protocol: ec2Query, params: { TopLevel: "Top level", Nested: { diff --git a/smithy-aws-protocol-tests/model/ec2-query/xml-lists.smithy b/smithy-aws-protocol-tests/model/ec2Query/xml-lists.smithy similarity index 92% rename from smithy-aws-protocol-tests/model/ec2-query/xml-lists.smithy rename to smithy-aws-protocol-tests/model/ec2Query/xml-lists.smithy index 5bac8533b6e..0348072f3ab 100644 --- a/smithy-aws-protocol-tests/model/ec2-query/xml-lists.smithy +++ b/smithy-aws-protocol-tests/model/ec2Query/xml-lists.smithy @@ -2,15 +2,16 @@ $version: "0.5.0" -namespace aws.protocols.tests.ec2 - -use aws.protocols.tests.shared#BooleanList -use aws.protocols.tests.shared#FooEnumList -use aws.protocols.tests.shared#IntegerList -use aws.protocols.tests.shared#NestedStringList -use aws.protocols.tests.shared#StringList -use aws.protocols.tests.shared#StringSet -use aws.protocols.tests.shared#TimestampList +namespace aws.protocoltests.ec2 + +use aws.protocols#ec2Query +use aws.protocoltests.shared#BooleanList +use aws.protocoltests.shared#FooEnumList +use aws.protocoltests.shared#IntegerList +use aws.protocoltests.shared#NestedStringList +use aws.protocoltests.shared#StringList +use aws.protocoltests.shared#StringSet +use aws.protocoltests.shared#TimestampList use smithy.test#httpResponseTests /// This test case serializes XML lists for the following cases for both @@ -31,7 +32,7 @@ apply XmlLists @httpResponseTests([ { id: "Ec2XmlLists", documentation: "Serializes XML lists", - protocol: "aws.ec2", + protocol: ec2Query, code: 200, body: """ diff --git a/smithy-aws-protocol-tests/model/ec2-query/xml-structs.smithy b/smithy-aws-protocol-tests/model/ec2Query/xml-structs.smithy similarity index 96% rename from smithy-aws-protocol-tests/model/ec2-query/xml-structs.smithy rename to smithy-aws-protocol-tests/model/ec2Query/xml-structs.smithy index acc91822005..c3aad98752c 100644 --- a/smithy-aws-protocol-tests/model/ec2-query/xml-structs.smithy +++ b/smithy-aws-protocol-tests/model/ec2Query/xml-structs.smithy @@ -2,13 +2,14 @@ $version: "0.5.0" -namespace aws.protocols.tests.ec2 +namespace aws.protocoltests.ec2 use aws.api#ec2QueryName -use aws.protocols.tests.shared#FooEnum -use aws.protocols.tests.shared#FooEnumList -use aws.protocols.tests.shared#FooEnumSet -use aws.protocols.tests.shared#FooEnumMap +use aws.protocols#ec2Query +use aws.protocoltests.shared#FooEnum +use aws.protocoltests.shared#FooEnumList +use aws.protocoltests.shared#FooEnumSet +use aws.protocoltests.shared#FooEnumMap use smithy.test#httpResponseTests // This example serializes simple scalar types in the top level XML document. @@ -21,7 +22,7 @@ apply SimpleScalarXmlProperties @httpResponseTests([ { id: "Ec2SimpleScalarProperties", documentation: "Serializes simple scalar properties", - protocol: "aws.ec2", + protocol: ec2Query, code: 200, body: """ @@ -84,7 +85,7 @@ apply XmlBlobs @httpResponseTests([ { id: "Ec2XmlBlobs", documentation: "Blobs are base64 encoded", - protocol: "aws.ec2", + protocol: ec2Query, code: 200, body: """ @@ -117,7 +118,7 @@ apply XmlTimestamps @httpResponseTests([ { id: "Ec2XmlTimestamps", documentation: "Tests how normal timestamps are serialized", - protocol: "aws.ec2", + protocol: ec2Query, code: 200, body: """ @@ -136,7 +137,7 @@ apply XmlTimestamps @httpResponseTests([ { id: "Ec2XmlTimestampsWithDateTimeFormat", documentation: "Ensures that the timestampFormat of date-time works like normal timestamps", - protocol: "aws.ec2", + protocol: ec2Query, code: 200, body: """ @@ -155,7 +156,7 @@ apply XmlTimestamps @httpResponseTests([ { id: "Ec2XmlTimestampsWithEpochSecondsFormat", documentation: "Ensures that the timestampFormat of epoch-seconds works", - protocol: "aws.ec2", + protocol: ec2Query, code: 200, body: """ @@ -174,7 +175,7 @@ apply XmlTimestamps @httpResponseTests([ { id: "Ec2XmlTimestampsWithHttpDateFormat", documentation: "Ensures that the timestampFormat of http-date works", - protocol: "aws.ec2", + protocol: ec2Query, code: 200, body: """ @@ -214,7 +215,7 @@ apply XmlEnums @httpResponseTests([ { id: "Ec2XmlEnums", documentation: "Serializes simple scalar properties", - protocol: "aws.ec2", + protocol: ec2Query, code: 200, body: """ @@ -278,7 +279,7 @@ apply RecursiveXmlShapes @httpResponseTests([ { id: "Ec2RecursiveShapes", documentation: "Serializes recursive structures", - protocol: "aws.ec2", + protocol: ec2Query, code: 200, body: """ @@ -341,7 +342,7 @@ apply XmlNamespaces @httpResponseTests([ { id: "Ec2XmlNamespaces", documentation: "Serializes XML namespaces", - protocol: "aws.ec2", + protocol: ec2Query, code: 200, body: """ @@ -404,7 +405,7 @@ apply IgnoresWrappingXmlName @httpResponseTests([ { id: "Ec2IgnoresWrappingXmlName", documentation: "The xmlName trait on the output structure is ignored in the ec2 protocol", - protocol: "aws.ec2", + protocol: ec2Query, code: 200, body: """ diff --git a/smithy-aws-protocol-tests/model/rest-json/empty-input-output.smithy b/smithy-aws-protocol-tests/model/restJson1/empty-input-output.smithy similarity index 91% rename from smithy-aws-protocol-tests/model/rest-json/empty-input-output.smithy rename to smithy-aws-protocol-tests/model/restJson1/empty-input-output.smithy index 0bb532dd38f..e16c364e236 100644 --- a/smithy-aws-protocol-tests/model/rest-json/empty-input-output.smithy +++ b/smithy-aws-protocol-tests/model/restJson1/empty-input-output.smithy @@ -5,8 +5,9 @@ $version: "0.5.0" -namespace aws.protocols.tests.restjson +namespace aws.protocoltests.restjson +use aws.protocols#restJson1 use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -20,7 +21,7 @@ apply NoInputAndNoOutput @httpRequestTests([ { id: "RestJsonNoInputAndNoOutput", documentation: "No input serializes no payload", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "POST", uri: "/NoInputAndOutput" } @@ -30,7 +31,7 @@ apply NoInputAndNoOutput @httpResponseTests([ { id: "RestJsonNoInputAndNoOutput", documentation: "No output serializes no payload", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200 } ]) @@ -48,7 +49,7 @@ apply NoInputAndOutput @httpRequestTests([ { id: "RestJsonNoInputAndOutput", documentation: "No input serializes no payload", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "POST", uri: "/NoInputAndOutput" } @@ -58,7 +59,7 @@ apply NoInputAndOutput @httpResponseTests([ { id: "RestJsonNoInputAndOutput", documentation: "Empty output serializes no payload", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200 } ]) @@ -79,7 +80,7 @@ apply EmptyInputAndEmptyOutput @httpRequestTests([ { id: "RestJsonEmptyInputAndEmptyOutput", documentation: "Empty input serializes no payload", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "POST", uri: "/EmptyInputAndEmptyOutput", body: "{}", @@ -91,7 +92,7 @@ apply EmptyInputAndEmptyOutput @httpResponseTests([ { id: "RestJsonEmptyInputAndEmptyOutput", documentation: "Empty output serializes no payload", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, body: "{}", bodyMediaType: "application/json" diff --git a/smithy-aws-protocol-tests/model/rest-xml/endpoint-host-trait.smithy b/smithy-aws-protocol-tests/model/restJson1/endpoint-host-trait.smithy similarity index 80% rename from smithy-aws-protocol-tests/model/rest-xml/endpoint-host-trait.smithy rename to smithy-aws-protocol-tests/model/restJson1/endpoint-host-trait.smithy index bce723721f6..b09614bbac7 100644 --- a/smithy-aws-protocol-tests/model/rest-xml/endpoint-host-trait.smithy +++ b/smithy-aws-protocol-tests/model/restJson1/endpoint-host-trait.smithy @@ -3,8 +3,9 @@ $version: "0.5.0" -namespace aws.protocols.tests.restxml +namespace aws.protocoltests.restjson +use aws.protocols#restJson1 use smithy.test#httpRequestTests use smithy.test#httpResponseTests diff --git a/smithy-aws-protocol-tests/model/rest-json/errors.smithy b/smithy-aws-protocol-tests/model/restJson1/errors.smithy similarity index 89% rename from smithy-aws-protocol-tests/model/rest-json/errors.smithy rename to smithy-aws-protocol-tests/model/restJson1/errors.smithy index 25bf2cb8a25..c1f46c7e0a8 100644 --- a/smithy-aws-protocol-tests/model/rest-json/errors.smithy +++ b/smithy-aws-protocol-tests/model/restJson1/errors.smithy @@ -2,8 +2,9 @@ $version: "0.5.0" -namespace aws.protocols.tests.restjson +namespace aws.protocoltests.restjson +use aws.protocols#restJson1 use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -28,7 +29,7 @@ apply GreetingWithErrors @httpResponseTests([ { id: "RestJsonGreetingWithErrors", documentation: "Ensures that operations with errors successfully know how to deserialize the successful response", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, body: """ { @@ -61,7 +62,7 @@ apply InvalidGreeting @httpResponseTests([ { id: "RestJsonInvalidGreetingError", documentation: "Parses simple JSON errors", - protocol: "aws.rest-json-1.1", + protocol: restJson1, params: { Message: "Hi" }, @@ -96,7 +97,7 @@ apply ComplexError @httpResponseTests([ { id: "RestJsonComplexErrorWithNoMessage", documentation: "Serializes a complex error with no message member", - protocol: "aws.rest-json-1.1", + protocol: restJson1, params: { Header: "Header", TopLevel: "Top level", @@ -121,7 +122,7 @@ apply ComplexError @httpResponseTests([ }, { id: "RestJsonEmptyComplexErrorWithNoMessage", - protocol: "aws.rest-json-1.1", + protocol: restJson1, params: {}, code: 403, headers: { @@ -148,7 +149,7 @@ apply FooError @httpResponseTests([ { id: "RestJsonFooErrorUsingXAmznErrorType", documentation: "Serializes the X-Amzn-ErrorType header. For an example service, see Amazon EKS.", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 500, headers: { "X-Amzn-Errortype": "FooError", @@ -162,7 +163,7 @@ apply FooError @httpResponseTests([ is to be interpreted as 'ValidationException'. For an example service see Amazon Polly.""", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 500, headers: { "X-Amzn-Errortype": "FooError:http://internal.amazon.com/coral/com.amazon.coral.validate/", @@ -173,10 +174,10 @@ apply FooError @httpResponseTests([ documentation: """ X-Amzn-Errortype might contain a URL and a namespace. Client should extract only the shape \ name. This is a pathalogical case that might not actually happen in any deployed AWS service.""", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 500, headers: { - "X-Amzn-Errortype": "aws.protocols.tests.restjson#FooError:http://internal.amazon.com/coral/com.amazon.coral.validate/", + "X-Amzn-Errortype": "aws.protocoltests.restjson#FooError:http://internal.amazon.com/coral/com.amazon.coral.validate/", }, }, { @@ -187,7 +188,7 @@ apply FooError @httpResponseTests([ must first check for the X-Amzn-Errortype and then check for a top-level 'code' property. For example service see Amazon S3 Glacier.""", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 500, headers: { "Content-Type": "application/json" @@ -203,14 +204,14 @@ apply FooError @httpResponseTests([ documentation: """ Some services serialize errors using code, and it might contain a namespace. \ Clients should just take the last part of the string after '#'.""", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 500, headers: { "Content-Type": "application/json" }, body: """ { - "code": "aws.protocols.tests.restjson#FooError" + "code": "aws.protocoltests.restjson#FooError" }""", bodyMediaType: "application/json", }, @@ -220,21 +221,21 @@ apply FooError @httpResponseTests([ Some services serialize errors using code, and it might contain a namespace. It also might \ contain a URI. Clients should just take the last part of the string after '#' and before ":". \ This is a pathalogical case that might not occur in any deployed AWS service.""", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 500, headers: { "Content-Type": "application/json" }, body: """ { - "code": "aws.protocols.tests.restjson#FooError:http://internal.amazon.com/coral/com.amazon.coral.validate/" + "code": "aws.protocoltests.restjson#FooError:http://internal.amazon.com/coral/com.amazon.coral.validate/" }""", bodyMediaType: "application/json", }, { id: "RestJsonFooErrorWithDunderType", documentation: "Some services serialize errors using __type.", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 500, headers: { "Content-Type": "application/json" @@ -250,14 +251,14 @@ apply FooError @httpResponseTests([ documentation: """ Some services serialize errors using __type, and it might contain a namespace. \ Clients should just take the last part of the string after '#'.""", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 500, headers: { "Content-Type": "application/json" }, body: """ { - "__type": "aws.protocols.tests.restjson#FooError" + "__type": "aws.protocoltests.restjson#FooError" }""", bodyMediaType: "application/json", }, @@ -267,14 +268,14 @@ apply FooError @httpResponseTests([ Some services serialize errors using __type, and it might contain a namespace. It also might \ contain a URI. Clients should just take the last part of the string after '#' and before ":". \ This is a pathalogical case that might not occur in any deployed AWS service.""", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 500, headers: { "Content-Type": "application/json" }, body: """ { - "__type": "aws.protocols.tests.restjson#FooError:http://internal.amazon.com/coral/com.amazon.coral.validate/" + "__type": "aws.protocoltests.restjson#FooError:http://internal.amazon.com/coral/com.amazon.coral.validate/" }""", bodyMediaType: "application/json", } diff --git a/smithy-aws-protocol-tests/model/rest-json/http-headers.smithy b/smithy-aws-protocol-tests/model/restJson1/http-headers.smithy similarity index 91% rename from smithy-aws-protocol-tests/model/rest-json/http-headers.smithy rename to smithy-aws-protocol-tests/model/restJson1/http-headers.smithy index 05273862a08..b18f11c4df6 100644 --- a/smithy-aws-protocol-tests/model/rest-json/http-headers.smithy +++ b/smithy-aws-protocol-tests/model/restJson1/http-headers.smithy @@ -3,17 +3,18 @@ $version: "0.5.0" -namespace aws.protocols.tests.restjson - -use aws.protocols.tests.shared#BooleanList -use aws.protocols.tests.shared#EpochSeconds -use aws.protocols.tests.shared#FooEnum -use aws.protocols.tests.shared#FooEnumList -use aws.protocols.tests.shared#HttpDate -use aws.protocols.tests.shared#IntegerList -use aws.protocols.tests.shared#StringList -use aws.protocols.tests.shared#StringSet -use aws.protocols.tests.shared#TimestampList +namespace aws.protocoltests.restjson + +use aws.protocols#restJson1 +use aws.protocoltests.shared#BooleanList +use aws.protocoltests.shared#EpochSeconds +use aws.protocoltests.shared#FooEnum +use aws.protocoltests.shared#FooEnumList +use aws.protocoltests.shared#HttpDate +use aws.protocoltests.shared#IntegerList +use aws.protocoltests.shared#StringList +use aws.protocoltests.shared#StringSet +use aws.protocoltests.shared#TimestampList use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -29,7 +30,7 @@ apply InputAndOutputWithHeaders @httpRequestTests([ { id: "RestJsonInputAndOutputWithStringHeaders", documentation: "Tests requests with string header bindings", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "POST", uri: "/InputAndOutputWithHeaders", headers: { @@ -47,7 +48,7 @@ apply InputAndOutputWithHeaders @httpRequestTests([ { id: "RestJsonInputAndOutputWithNumericHeaders", documentation: "Tests requests with numeric header bindings", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "POST", uri: "/InputAndOutputWithHeaders", headers: { @@ -73,7 +74,7 @@ apply InputAndOutputWithHeaders @httpRequestTests([ { id: "RestJsonInputAndOutputWithBooleanHeaders", documentation: "Tests requests with boolean header bindings", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "POST", uri: "/InputAndOutputWithHeaders", headers: { @@ -91,7 +92,7 @@ apply InputAndOutputWithHeaders @httpRequestTests([ { id: "RestJsonInputAndOutputWithTimestampHeaders", documentation: "Tests requests with timestamp header bindings", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "POST", uri: "/InputAndOutputWithHeaders", headers: { @@ -105,7 +106,7 @@ apply InputAndOutputWithHeaders @httpRequestTests([ { id: "RestJsonInputAndOutputWithEnumHeaders", documentation: "Tests requests with enum header bindings", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "POST", uri: "/InputAndOutputWithHeaders", headers: { @@ -124,7 +125,7 @@ apply InputAndOutputWithHeaders @httpResponseTests([ { id: "RestJsonInputAndOutputWithStringHeaders", documentation: "Tests responses with string header bindings", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, headers: { "X-String": "Hello", @@ -141,7 +142,7 @@ apply InputAndOutputWithHeaders @httpResponseTests([ { id: "RestJsonInputAndOutputWithNumericHeaders", documentation: "Tests responses with numeric header bindings", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, headers: { "X-Byte": "1", @@ -166,7 +167,7 @@ apply InputAndOutputWithHeaders @httpResponseTests([ { id: "RestJsonInputAndOutputWithBooleanHeaders", documentation: "Tests responses with boolean header bindings", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, headers: { "X-Boolean1": "true", @@ -183,7 +184,7 @@ apply InputAndOutputWithHeaders @httpResponseTests([ { id: "RestJsonInputAndOutputWithTimestampHeaders", documentation: "Tests responses with timestamp header bindings", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, headers: { "X-HeaderTimestampList": "Mon, 16 Dec 2019 23:48:18 GMT, Mon, 16 Dec 2019 23:48:18 GMT" @@ -196,7 +197,7 @@ apply InputAndOutputWithHeaders @httpResponseTests([ { id: "RestJsonInputAndOutputWithEnumHeaders", documentation: "Tests responses with enum header bindings", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, headers: { "X-Enum": "Foo", @@ -272,7 +273,7 @@ apply NullAndEmptyHeaders @httpRequestTests([ { id: "RestJsonNullAndEmptyHeaders", documentation: "Do not send null values, empty strings, or empty lists over the wire in headers", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "GET", uri: "/NullAndEmptyHeaders", forbidHeaders: ["X-A", "X-B", "X-C"], @@ -289,7 +290,7 @@ apply NullAndEmptyHeaders @httpResponseTests([ { id: "RestJsonNullAndEmptyHeaders", documentation: "Do not send null or empty headers", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, forbidHeaders: ["X-A", "X-B", "X-C"], body: "", @@ -323,7 +324,7 @@ apply TimestampFormatHeaders @httpRequestTests([ { id: "RestJsonTimestampFormatHeaders", documentation: "Tests how timestamp request headers are serialized", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "POST", uri: "/TimestampFormatHeaders", headers: { @@ -352,7 +353,7 @@ apply TimestampFormatHeaders @httpResponseTests([ { id: "RestJsonTimestampFormatHeaders", documentation: "Tests how timestamp response headers are serialized", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, headers: { "X-memberEpochSeconds": "1576540098", diff --git a/smithy-aws-protocol-tests/model/rest-json/http-labels.smithy b/smithy-aws-protocol-tests/model/restJson1/http-labels.smithy similarity index 94% rename from smithy-aws-protocol-tests/model/rest-json/http-labels.smithy rename to smithy-aws-protocol-tests/model/restJson1/http-labels.smithy index 474c3a0e276..f8f11e50b02 100644 --- a/smithy-aws-protocol-tests/model/rest-json/http-labels.smithy +++ b/smithy-aws-protocol-tests/model/restJson1/http-labels.smithy @@ -3,10 +3,11 @@ $version: "0.5.0" -namespace aws.protocols.tests.restjson +namespace aws.protocoltests.restjson -use aws.protocols.tests.shared#EpochSeconds -use aws.protocols.tests.shared#HttpDate +use aws.protocols#restJson1 +use aws.protocoltests.shared#EpochSeconds +use aws.protocoltests.shared#HttpDate use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -22,7 +23,7 @@ apply HttpRequestWithLabels @httpRequestTests([ { id: "RestJsonInputWithHeadersAndAllParams", documentation: "Sends a GET request that uses URI label bindings", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "GET", uri: "/HttpRequestWithLabels/string/1/2/3/4.0/5.0/true/2019-12-16T23%3A48%3A18Z", body: "", @@ -87,7 +88,7 @@ apply HttpRequestWithLabelsAndTimestampFormat @httpRequestTests([ { id: "RestJsonHttpRequestWithLabelsAndTimestampFormat", documentation: "Serializes different timestamp formats in URI labels", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "GET", uri: """ /HttpRequestWithLabelsAndTimestampFormat\ @@ -155,7 +156,7 @@ apply HttpRequestWithGreedyLabelInPath @httpRequestTests([ { id: "RestJsonHttpRequestWithGreedyLabelInPath", documentation: "Serializes greedy labels and normal labels", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "GET", uri: "/HttpRequestWithGreedyLabelInPath/foo/hello/baz/there/guy", body: "", diff --git a/smithy-aws-protocol-tests/model/rest-json/http-payload.smithy b/smithy-aws-protocol-tests/model/restJson1/http-payload.smithy similarity index 93% rename from smithy-aws-protocol-tests/model/rest-json/http-payload.smithy rename to smithy-aws-protocol-tests/model/restJson1/http-payload.smithy index 116d76bcc34..de9e1f3d8d0 100644 --- a/smithy-aws-protocol-tests/model/rest-json/http-payload.smithy +++ b/smithy-aws-protocol-tests/model/restJson1/http-payload.smithy @@ -3,9 +3,10 @@ $version: "0.5.0" -namespace aws.protocols.tests.restjson +namespace aws.protocoltests.restjson -use aws.protocols.tests.shared#TextPlainBlob +use aws.protocols#restJson1 +use aws.protocoltests.shared#TextPlainBlob use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -23,7 +24,7 @@ apply HttpPayloadTraits @httpRequestTests([ { id: "RestJsonHttpPayloadTraitsWithBlob", documentation: "Serializes a blob in the HTTP payload", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "POST", uri: "/HttpPayloadTraits", body: "blobby blob blob", @@ -38,7 +39,7 @@ apply HttpPayloadTraits @httpRequestTests([ { id: "RestJsonHttpPayloadTraitsWithNoBlobBody", documentation: "Serializes an empty blob in the HTTP payload", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "POST", uri: "/HttpPayloadTraits", body: "", @@ -55,7 +56,7 @@ apply HttpPayloadTraits @httpResponseTests([ { id: "RestJsonHttpPayloadTraitsWithBlob", documentation: "Serializes a blob in the HTTP payload", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, body: "blobby blob blob", headers: { @@ -69,7 +70,7 @@ apply HttpPayloadTraits @httpResponseTests([ { id: "RestJsonHttpPayloadTraitsWithNoBlobBody", documentation: "Serializes an empty blob in the HTTP payload", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, body: "", headers: { @@ -101,7 +102,7 @@ apply HttpPayloadTraitsWithMediaType @httpRequestTests([ { id: "RestJsonHttpPayloadTraitsWithMediaTypeWithBlob", documentation: "Serializes a blob in the HTTP payload with a content-type", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "POST", uri: "/HttpPayloadTraitsWithMediaType", body: "blobby blob blob", @@ -120,7 +121,7 @@ apply HttpPayloadTraitsWithMediaType @httpResponseTests([ { id: "RestJsonHttpPayloadTraitsWithMediaTypeWithBlob", documentation: "Serializes a blob in the HTTP payload with a content-type", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, body: "blobby blob blob", headers: { @@ -157,7 +158,7 @@ apply HttpPayloadWithStructure @httpRequestTests([ { id: "RestJsonHttpPayloadWithStructure", documentation: "Serializes a structure in the payload", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "PUT", uri: "/HttpPayloadWithStructure", body: """ @@ -182,7 +183,7 @@ apply HttpPayloadWithStructure @httpResponseTests([ { id: "RestJsonHttpPayloadWithStructure", documentation: "Serializes a structure in the payload", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, body: """ { diff --git a/smithy-aws-protocol-tests/model/rest-json/http-prefix-headers.smithy b/smithy-aws-protocol-tests/model/restJson1/http-prefix-headers.smithy similarity index 92% rename from smithy-aws-protocol-tests/model/rest-json/http-prefix-headers.smithy rename to smithy-aws-protocol-tests/model/restJson1/http-prefix-headers.smithy index fc35270c77f..b5c617b6282 100644 --- a/smithy-aws-protocol-tests/model/rest-json/http-prefix-headers.smithy +++ b/smithy-aws-protocol-tests/model/restJson1/http-prefix-headers.smithy @@ -3,8 +3,9 @@ $version: "0.5.0" -namespace aws.protocols.tests.restjson +namespace aws.protocoltests.restjson +use aws.protocols#restJson1 use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -21,7 +22,7 @@ apply HttpPrefixHeaders @httpRequestTests([ { id: "RestJsonHttpPrefixHeadersArePresent", documentation: "Adds headers by prefix", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "GET", uri: "/HttpPrefixHeaders", body: "", @@ -41,7 +42,7 @@ apply HttpPrefixHeaders @httpRequestTests([ { id: "RestJsonHttpPrefixHeadersAreNotPresent", documentation: "No prefix headers are serialized because the value is empty", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "GET", uri: "/HttpPrefixHeaders", body: "", @@ -59,7 +60,7 @@ apply HttpPrefixHeaders @httpResponseTests([ { id: "RestJsonHttpPrefixHeadersArePresent", documentation: "Adds headers by prefix", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, body: "", headers: { @@ -78,7 +79,7 @@ apply HttpPrefixHeaders @httpResponseTests([ { id: "RestJsonHttpPrefixHeadersAreNotPresent", documentation: "No prefix headers are serialized because the value is empty", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, body: "", headers: { diff --git a/smithy-aws-protocol-tests/model/rest-json/http-query.smithy b/smithy-aws-protocol-tests/model/restJson1/http-query.smithy similarity index 92% rename from smithy-aws-protocol-tests/model/rest-json/http-query.smithy rename to smithy-aws-protocol-tests/model/restJson1/http-query.smithy index 6a858852ccc..f9cedec2330 100644 --- a/smithy-aws-protocol-tests/model/rest-json/http-query.smithy +++ b/smithy-aws-protocol-tests/model/restJson1/http-query.smithy @@ -3,17 +3,18 @@ $version: "0.5.0" -namespace aws.protocols.tests.restjson - -use aws.protocols.tests.shared#BooleanList -use aws.protocols.tests.shared#DoubleList -use aws.protocols.tests.shared#FooEnum -use aws.protocols.tests.shared#FooEnumList -use aws.protocols.tests.shared#IntegerList -use aws.protocols.tests.shared#IntegerSet -use aws.protocols.tests.shared#StringList -use aws.protocols.tests.shared#StringSet -use aws.protocols.tests.shared#TimestampList +namespace aws.protocoltests.restjson + +use aws.protocols#restJson1 +use aws.protocoltests.shared#BooleanList +use aws.protocoltests.shared#DoubleList +use aws.protocoltests.shared#FooEnum +use aws.protocoltests.shared#FooEnumList +use aws.protocoltests.shared#IntegerList +use aws.protocoltests.shared#IntegerSet +use aws.protocoltests.shared#StringList +use aws.protocoltests.shared#StringSet +use aws.protocoltests.shared#TimestampList use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -28,7 +29,7 @@ apply AllQueryStringTypes @httpRequestTests([ { id: "RestJsonAllQueryStringTypes", documentation: "Serializes query string parameters with all supported types", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "GET", uri: "/AllQueryStringTypes", body: "", @@ -157,7 +158,7 @@ structure AllQueryStringTypesInput { { id: "RestJsonConstantQueryString", documentation: "Includes constant query string parameters", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "GET", uri: "/ConstantQueryString/hi", queryParams: [ @@ -193,7 +194,7 @@ apply ConstantAndVariableQueryString @httpRequestTests([ { id: "RestJsonConstantAndVariableQueryStringMissingOneValue", documentation: "Mixes constant and variable query string parameters", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "GET", uri: "/ConstantAndVariableQueryString", queryParams: [ @@ -209,7 +210,7 @@ apply ConstantAndVariableQueryString @httpRequestTests([ { id: "RestJsonConstantAndVariableQueryStringAllValues", documentation: "Mixes constant and variable query string parameters", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "GET", uri: "/ConstantAndVariableQueryString", queryParams: [ @@ -246,7 +247,7 @@ apply IgnoreQueryParamsInResponse @httpResponseTests([ { id: "RestJsonIgnoreQueryParamsInResponse", documentation: "Query parameters must be ignored when serializing the output of an operation", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, headers: { "Content-Type": "application/json" @@ -275,7 +276,7 @@ apply OmitsNullSerializesEmptyString @httpRequestTests([ { id: "RestJsonOmitsNullSerializesEmptyString", documentation: "Serializes empty query strings but omits null", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "GET", uri: "/OmitsNullSerializesEmptyString", body: "", @@ -308,7 +309,7 @@ apply QueryIdempotencyTokenAutoFill @httpRequestTests([ { id: "RestJsonQueryIdempotencyTokenAutoFill", documentation: "Automatically adds idempotency token when not set", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "POST", uri: "/QueryIdempotencyTokenAutoFill", body: "", @@ -319,7 +320,7 @@ apply QueryIdempotencyTokenAutoFill @httpRequestTests([ { id: "RestJsonQueryIdempotencyTokenAutoFillIsSet", documentation: "Uses the given idempotency token as-is", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "POST", uri: "/QueryIdempotencyTokenAutoFill", body: "", diff --git a/smithy-aws-protocol-tests/model/rest-json/json-lists.smithy b/smithy-aws-protocol-tests/model/restJson1/json-lists.smithy similarity index 92% rename from smithy-aws-protocol-tests/model/rest-json/json-lists.smithy rename to smithy-aws-protocol-tests/model/restJson1/json-lists.smithy index 67ee209055d..bed1ed49d28 100644 --- a/smithy-aws-protocol-tests/model/rest-json/json-lists.smithy +++ b/smithy-aws-protocol-tests/model/restJson1/json-lists.smithy @@ -2,17 +2,18 @@ $version: "0.5.0" -namespace aws.protocols.tests.restjson +namespace aws.protocoltests.restjson -use aws.protocols.tests.shared#BooleanList -use aws.protocols.tests.shared#EpochSeconds -use aws.protocols.tests.shared#FooEnumList -use aws.protocols.tests.shared#GreetingList -use aws.protocols.tests.shared#IntegerList -use aws.protocols.tests.shared#NestedStringList -use aws.protocols.tests.shared#StringList -use aws.protocols.tests.shared#StringSet -use aws.protocols.tests.shared#TimestampList +use aws.protocols#restJson1 +use aws.protocoltests.shared#BooleanList +use aws.protocoltests.shared#EpochSeconds +use aws.protocoltests.shared#FooEnumList +use aws.protocoltests.shared#GreetingList +use aws.protocoltests.shared#IntegerList +use aws.protocoltests.shared#NestedStringList +use aws.protocoltests.shared#StringList +use aws.protocoltests.shared#StringSet +use aws.protocoltests.shared#TimestampList use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -34,7 +35,7 @@ apply JsonLists @httpRequestTests([ { id: "RestJsonLists", documentation: "Serializes JSON lists", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "PUT", uri: "/JsonLists", body: """ @@ -136,7 +137,7 @@ apply JsonLists @httpRequestTests([ { id: "RestJsonListsEmpty", documentation: "Serializes empty JSON lists", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "PUT", uri: "/JsonLists", body: """ @@ -152,7 +153,7 @@ apply JsonLists @httpRequestTests([ { id: "RestJsonListsSerializeNull", documentation: "Serializes null values in lists", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "PUT", uri: "/JsonLists", body: """ @@ -173,7 +174,7 @@ apply JsonLists @httpResponseTests([ { id: "RestJsonLists", documentation: "Serializes JSON lists", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, body: """ { @@ -274,7 +275,7 @@ apply JsonLists @httpResponseTests([ { id: "RestJsonListsEmpty", documentation: "Serializes empty JSON lists", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, body: """ { @@ -289,7 +290,7 @@ apply JsonLists @httpResponseTests([ { id: "RestJsonListsSerializeNull", documentation: "Serializes null values in lists", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, body: """ { diff --git a/smithy-aws-protocol-tests/model/rest-json/json-maps.smithy b/smithy-aws-protocol-tests/model/restJson1/json-maps.smithy similarity index 90% rename from smithy-aws-protocol-tests/model/rest-json/json-maps.smithy rename to smithy-aws-protocol-tests/model/restJson1/json-maps.smithy index 8f21b0eff28..92be7a5e3ef 100644 --- a/smithy-aws-protocol-tests/model/rest-json/json-maps.smithy +++ b/smithy-aws-protocol-tests/model/restJson1/json-maps.smithy @@ -2,10 +2,11 @@ $version: "0.5.0" -namespace aws.protocols.tests.restjson +namespace aws.protocoltests.restjson -use aws.protocols.tests.shared#FooEnumMap -use aws.protocols.tests.shared#GreetingStruct +use aws.protocols#restJson1 +use aws.protocoltests.shared#FooEnumMap +use aws.protocoltests.shared#GreetingStruct use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -20,7 +21,7 @@ apply JsonMaps @httpRequestTests([ { id: "RestJsonJsonMaps", documentation: "Serializes JSON maps", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "POST", uri: "/JsonMaps", body: """ @@ -55,7 +56,7 @@ apply JsonMaps @httpResponseTests([ { id: "RestJsonJsonMaps", documentation: "Serializes JSON maps", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, body: """ { diff --git a/smithy-aws-protocol-tests/model/rest-json/json-structs.smithy b/smithy-aws-protocol-tests/model/restJson1/json-structs.smithy similarity index 94% rename from smithy-aws-protocol-tests/model/rest-json/json-structs.smithy rename to smithy-aws-protocol-tests/model/restJson1/json-structs.smithy index ee2c5db481b..9d900574ce3 100644 --- a/smithy-aws-protocol-tests/model/rest-json/json-structs.smithy +++ b/smithy-aws-protocol-tests/model/restJson1/json-structs.smithy @@ -3,12 +3,13 @@ $version: "0.5.0" -namespace aws.protocols.tests.restjson +namespace aws.protocoltests.restjson -use aws.protocols.tests.shared#FooEnum -use aws.protocols.tests.shared#FooEnumList -use aws.protocols.tests.shared#FooEnumSet -use aws.protocols.tests.shared#FooEnumMap +use aws.protocols#restJson1 +use aws.protocoltests.shared#FooEnum +use aws.protocoltests.shared#FooEnumList +use aws.protocoltests.shared#FooEnumSet +use aws.protocoltests.shared#FooEnumMap use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -25,7 +26,7 @@ apply SimpleScalarProperties @httpRequestTests([ { id: "RestJsonSimpleScalarProperties", documentation: "Serializes simple scalar properties", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "PUT", uri: "/SimpleScalarProperties", body: """ @@ -65,7 +66,7 @@ apply SimpleScalarProperties @httpResponseTests([ { id: "RestJsonSimpleScalarProperties", documentation: "Serializes simple scalar properties", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, body: """ { @@ -128,7 +129,7 @@ apply JsonBlobs @httpRequestTests([ { id: "RestJsonJsonBlobs", documentation: "Blobs are base64 encoded", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "POST", uri: "/JsonBlobs", body: """ @@ -149,7 +150,7 @@ apply JsonBlobs @httpResponseTests([ { id: "RestJsonJsonBlobs", documentation: "Blobs are base64 encoded", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, body: """ { @@ -182,7 +183,7 @@ apply JsonTimestamps @httpRequestTests([ { id: "RestJsonJsonTimestamps", documentation: "Tests how normal timestamps are serialized", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "POST", uri: "/JsonTimestamps", body: """ @@ -200,7 +201,7 @@ apply JsonTimestamps @httpRequestTests([ { id: "RestJsonJsonTimestampsWithDateTimeFormat", documentation: "Ensures that the timestampFormat of date-time works like normal timestamps", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "POST", uri: "/JsonTimestamps", body: """ @@ -218,7 +219,7 @@ apply JsonTimestamps @httpRequestTests([ { id: "RestJsonJsonTimestampsWithEpochSecondsFormat", documentation: "Ensures that the timestampFormat of epoch-seconds works", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "POST", uri: "/JsonTimestamps", body: """ @@ -236,7 +237,7 @@ apply JsonTimestamps @httpRequestTests([ { id: "RestJsonJsonTimestampsWithHttpDateFormat", documentation: "Ensures that the timestampFormat of http-date works", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "POST", uri: "/JsonTimestamps", body: """ @@ -257,7 +258,7 @@ apply JsonTimestamps @httpResponseTests([ { id: "RestJsonJsonTimestamps", documentation: "Tests how normal timestamps are serialized", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, body: """ { @@ -274,7 +275,7 @@ apply JsonTimestamps @httpResponseTests([ { id: "RestJsonJsonTimestampsWithDateTimeFormat", documentation: "Ensures that the timestampFormat of date-time works like normal timestamps", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, body: """ { @@ -291,7 +292,7 @@ apply JsonTimestamps @httpResponseTests([ { id: "RestJsonJsonTimestampsWithEpochSecondsFormat", documentation: "Ensures that the timestampFormat of epoch-seconds works", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, body: """ { @@ -308,7 +309,7 @@ apply JsonTimestamps @httpResponseTests([ { id: "RestJsonJsonTimestampsWithHttpDateFormat", documentation: "Ensures that the timestampFormat of http-date works", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, body: """ { @@ -349,7 +350,7 @@ apply JsonEnums @httpRequestTests([ { id: "RestJsonJsonEnums", documentation: "Serializes simple scalar properties", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "PUT", uri: "/JsonEnums", body: """ @@ -392,7 +393,7 @@ apply JsonEnums @httpResponseTests([ { id: "RestJsonJsonEnums", documentation: "Serializes simple scalar properties", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, body: """ { @@ -451,7 +452,7 @@ apply RecursiveShapes @httpRequestTests([ { id: "RestJsonRecursiveShapes", documentation: "Serializes recursive structures", - protocol: "aws.rest-json-1.1", + protocol: restJson1, method: "PUT", uri: "/JsonEnums", body: """ @@ -494,7 +495,7 @@ apply RecursiveShapes @httpResponseTests([ { id: "RestJsonRecursiveShapes", documentation: "Serializes recursive structures", - protocol: "aws.rest-json-1.1", + protocol: restJson1, code: 200, body: """ { diff --git a/smithy-aws-protocol-tests/model/rest-json/main.smithy b/smithy-aws-protocol-tests/model/restJson1/main.smithy similarity index 94% rename from smithy-aws-protocol-tests/model/rest-json/main.smithy rename to smithy-aws-protocol-tests/model/restJson1/main.smithy index 8b338ee708a..abe90a75241 100644 --- a/smithy-aws-protocol-tests/model/rest-json/main.smithy +++ b/smithy-aws-protocol-tests/model/restJson1/main.smithy @@ -1,12 +1,13 @@ $version: "0.5.0" -namespace aws.protocols.tests.restjson +namespace aws.protocoltests.restjson +use aws.protocols#restJson1 use smithy.test#httpRequestTests use smithy.test#httpResponseTests /// A REST JSON service that sends JSON requests and responses. -@protocols([{"name": "aws.rest-json-1.1"}]) +@restJson1 service RestJson { version: "2019-12-16", operations: [ diff --git a/smithy-aws-protocol-tests/model/rest-xml/document-lists.smithy b/smithy-aws-protocol-tests/model/restXml/document-lists.smithy similarity index 93% rename from smithy-aws-protocol-tests/model/rest-xml/document-lists.smithy rename to smithy-aws-protocol-tests/model/restXml/document-lists.smithy index cf649cd0d35..2f924468423 100644 --- a/smithy-aws-protocol-tests/model/rest-xml/document-lists.smithy +++ b/smithy-aws-protocol-tests/model/restXml/document-lists.smithy @@ -2,17 +2,18 @@ $version: "0.5.0" -namespace aws.protocols.tests.restxml +namespace aws.protocoltests.restxml -use aws.protocols.tests.shared#BooleanList -use aws.protocols.tests.shared#EpochSeconds -use aws.protocols.tests.shared#FooEnumList -use aws.protocols.tests.shared#GreetingList -use aws.protocols.tests.shared#IntegerList -use aws.protocols.tests.shared#NestedStringList -use aws.protocols.tests.shared#StringList -use aws.protocols.tests.shared#StringSet -use aws.protocols.tests.shared#TimestampList +use aws.protocols#restXml +use aws.protocoltests.shared#BooleanList +use aws.protocoltests.shared#EpochSeconds +use aws.protocoltests.shared#FooEnumList +use aws.protocoltests.shared#GreetingList +use aws.protocoltests.shared#IntegerList +use aws.protocoltests.shared#NestedStringList +use aws.protocoltests.shared#StringList +use aws.protocoltests.shared#StringSet +use aws.protocoltests.shared#TimestampList use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -37,7 +38,7 @@ apply XmlLists @httpRequestTests([ { id: "XmlLists", documentation: "Serializes XML lists", - protocol: "aws.rest-xml", + protocol: restXml, method: "PUT", uri: "/XmlLists", body: """ @@ -129,7 +130,7 @@ apply XmlLists @httpResponseTests([ { id: "XmlLists", documentation: "Serializes XML lists", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: """ diff --git a/smithy-aws-protocol-tests/model/rest-xml/document-maps.smithy b/smithy-aws-protocol-tests/model/restXml/document-maps.smithy similarity index 95% rename from smithy-aws-protocol-tests/model/rest-xml/document-maps.smithy rename to smithy-aws-protocol-tests/model/restXml/document-maps.smithy index b5241eb3793..704ded7a713 100644 --- a/smithy-aws-protocol-tests/model/rest-xml/document-maps.smithy +++ b/smithy-aws-protocol-tests/model/restXml/document-maps.smithy @@ -2,10 +2,11 @@ $version: "0.5.0" -namespace aws.protocols.tests.restxml +namespace aws.protocoltests.restxml -use aws.protocols.tests.shared#FooEnumMap -use aws.protocols.tests.shared#GreetingStruct +use aws.protocols#restXml +use aws.protocoltests.shared#FooEnumMap +use aws.protocoltests.shared#GreetingStruct use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -20,7 +21,7 @@ apply XmlMaps @httpRequestTests([ { id: "XmlMaps", documentation: "Serializes XML maps", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/XmlMaps", body: """ @@ -62,7 +63,7 @@ apply XmlMaps @httpResponseTests([ { id: "XmlMaps", documentation: "Serializes XML maps", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: """ @@ -119,7 +120,7 @@ apply XmlMapsXmlName @httpRequestTests([ { id: "XmlMapsXmlName", documentation: "Serializes XML maps that have xmlName on members", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/XmlMapsXmlName", body: """ @@ -161,7 +162,7 @@ apply XmlMapsXmlName @httpResponseTests([ { id: "XmlMapsXmlName", documentation: "Serializes XML lists", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: """ @@ -221,7 +222,7 @@ apply FlattenedXmlMap @httpRequestTests([ { id: "FlattenedXmlMap", documentation: "Serializes flattened XML maps in requests", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/FlattenedXmlMap", body: """ @@ -252,7 +253,7 @@ apply FlattenedXmlMap @httpResponseTests([ { id: "FlattenedXmlMap", documentation: "Serializes flattened XML maps in responses", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: """ @@ -294,7 +295,7 @@ apply FlattenedXmlMapWithXmlName @httpRequestTests([ { id: "FlattenedXmlMapWithXmlName", documentation: "Serializes flattened XML maps in requests that have xmlName on members", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/FlattenedXmlMapWithXmlName", body: """ @@ -325,7 +326,7 @@ apply FlattenedXmlMapWithXmlName @httpResponseTests([ { id: "FlattenedXmlMapWithXmlName", documentation: "Serializes flattened XML maps in responses that have xmlName on members", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: """ diff --git a/smithy-aws-protocol-tests/model/rest-xml/document-structs.smithy b/smithy-aws-protocol-tests/model/restXml/document-structs.smithy similarity index 95% rename from smithy-aws-protocol-tests/model/rest-xml/document-structs.smithy rename to smithy-aws-protocol-tests/model/restXml/document-structs.smithy index bdbc66602ab..bbc622385a6 100644 --- a/smithy-aws-protocol-tests/model/rest-xml/document-structs.smithy +++ b/smithy-aws-protocol-tests/model/restXml/document-structs.smithy @@ -3,12 +3,13 @@ $version: "0.5.0" -namespace aws.protocols.tests.restxml +namespace aws.protocoltests.restxml -use aws.protocols.tests.shared#FooEnum -use aws.protocols.tests.shared#FooEnumList -use aws.protocols.tests.shared#FooEnumSet -use aws.protocols.tests.shared#FooEnumMap +use aws.protocols#restXml +use aws.protocoltests.shared#FooEnum +use aws.protocoltests.shared#FooEnumList +use aws.protocoltests.shared#FooEnumSet +use aws.protocoltests.shared#FooEnumMap use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -25,7 +26,7 @@ apply SimpleScalarProperties @httpRequestTests([ { id: "SimpleScalarProperties", documentation: "Serializes simple scalar properties", - protocol: "aws.rest-xml", + protocol: restXml, method: "PUT", uri: "/SimpleScalarProperties", body: """ @@ -65,7 +66,7 @@ apply SimpleScalarProperties @httpResponseTests([ { id: "SimpleScalarProperties", documentation: "Serializes simple scalar properties", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: """ @@ -128,7 +129,7 @@ apply XmlBlobs @httpRequestTests([ { id: "XmlBlobs", documentation: "Blobs are base64 encoded", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/XmlBlobs", body: """ @@ -150,7 +151,7 @@ apply XmlBlobs @httpResponseTests([ { id: "XmlBlobs", documentation: "Blobs are base64 encoded", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: """ @@ -184,7 +185,7 @@ apply XmlTimestamps @httpRequestTests([ { id: "XmlTimestamps", documentation: "Tests how normal timestamps are serialized", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/XmlTimestamps", body: """ @@ -203,7 +204,7 @@ apply XmlTimestamps @httpRequestTests([ { id: "XmlTimestampsWithDateTimeFormat", documentation: "Ensures that the timestampFormat of date-time works like normal timestamps", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/XmlTimestamps", body: """ @@ -222,7 +223,7 @@ apply XmlTimestamps @httpRequestTests([ { id: "XmlTimestampsWithEpochSecondsFormat", documentation: "Ensures that the timestampFormat of epoch-seconds works", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/XmlTimestamps", body: """ @@ -241,7 +242,7 @@ apply XmlTimestamps @httpRequestTests([ { id: "XmlTimestampsWithHttpDateFormat", documentation: "Ensures that the timestampFormat of http-date works", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/XmlTimestamps", body: """ @@ -263,7 +264,7 @@ apply XmlTimestamps @httpResponseTests([ { id: "XmlTimestamps", documentation: "Tests how normal timestamps are serialized", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: """ @@ -281,7 +282,7 @@ apply XmlTimestamps @httpResponseTests([ { id: "XmlTimestampsWithDateTimeFormat", documentation: "Ensures that the timestampFormat of date-time works like normal timestamps", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: """ @@ -299,7 +300,7 @@ apply XmlTimestamps @httpResponseTests([ { id: "XmlTimestampsWithEpochSecondsFormat", documentation: "Ensures that the timestampFormat of epoch-seconds works", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: """ @@ -317,7 +318,7 @@ apply XmlTimestamps @httpResponseTests([ { id: "XmlTimestampsWithHttpDateFormat", documentation: "Ensures that the timestampFormat of http-date works", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: """ @@ -359,7 +360,7 @@ apply XmlEnums @httpRequestTests([ { id: "XmlEnums", documentation: "Serializes simple scalar properties", - protocol: "aws.rest-xml", + protocol: restXml, method: "PUT", uri: "/XmlEnums", body: """ @@ -409,7 +410,7 @@ apply XmlEnums @httpResponseTests([ { id: "XmlEnums", documentation: "Serializes simple scalar properties", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: """ @@ -475,7 +476,7 @@ apply RecursiveShapes @httpRequestTests([ { id: "RecursiveShapes", documentation: "Serializes recursive structures", - protocol: "aws.rest-xml", + protocol: restXml, method: "PUT", uri: "/XmlEnums", body: """ @@ -519,7 +520,7 @@ apply RecursiveShapes @httpResponseTests([ { id: "RecursiveShapes", documentation: "Serializes recursive structures", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: """ @@ -583,7 +584,7 @@ apply XmlNamespaces @httpRequestTests([ { id: "XmlNamespaces", documentation: "Serializes XML namespaces", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/XmlNamespaces", body: """ @@ -617,7 +618,7 @@ apply XmlNamespaces @httpResponseTests([ { id: "XmlNamespaces", documentation: "Serializes XML namespaces", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: """ diff --git a/smithy-aws-protocol-tests/model/rest-xml/document-xml-attributes.smithy b/smithy-aws-protocol-tests/model/restXml/document-xml-attributes.smithy similarity index 94% rename from smithy-aws-protocol-tests/model/rest-xml/document-xml-attributes.smithy rename to smithy-aws-protocol-tests/model/restXml/document-xml-attributes.smithy index bfa2295ffd8..cc198687ccc 100644 --- a/smithy-aws-protocol-tests/model/rest-xml/document-xml-attributes.smithy +++ b/smithy-aws-protocol-tests/model/restXml/document-xml-attributes.smithy @@ -2,8 +2,9 @@ $version: "0.5.0" -namespace aws.protocols.tests.restxml +namespace aws.protocoltests.restxml +use aws.protocols#restXml use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -19,7 +20,7 @@ apply XmlAttributes @httpRequestTests([ { id: "XmlAttributes", documentation: "Serializes XML attributes on the synthesized document", - protocol: "aws.rest-xml", + protocol: restXml, method: "PUT", uri: "/XmlAttributes", body: """ @@ -42,7 +43,7 @@ apply XmlAttributes @httpResponseTests([ { id: "XmlAttributes", documentation: "Serializes simple scalar properties", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: """ @@ -80,7 +81,7 @@ apply XmlAttributesOnPayload @httpRequestTests([ { id: "XmlAttributesOnPayload", documentation: "Serializes XML attributes on the synthesized document", - protocol: "aws.rest-xml", + protocol: restXml, method: "PUT", uri: "/XmlAttributesOnPayload", body: """ @@ -105,7 +106,7 @@ apply XmlAttributesOnPayload @httpResponseTests([ { id: "XmlAttributesOnPayload", documentation: "Serializes simple scalar properties", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: """ diff --git a/smithy-aws-protocol-tests/model/rest-xml/empty-input-output.smithy b/smithy-aws-protocol-tests/model/restXml/empty-input-output.smithy similarity index 91% rename from smithy-aws-protocol-tests/model/rest-xml/empty-input-output.smithy rename to smithy-aws-protocol-tests/model/restXml/empty-input-output.smithy index 18bd4c1fee9..ebc9cbe4a6e 100644 --- a/smithy-aws-protocol-tests/model/rest-xml/empty-input-output.smithy +++ b/smithy-aws-protocol-tests/model/restXml/empty-input-output.smithy @@ -3,8 +3,9 @@ $version: "0.5.0" -namespace aws.protocols.tests.restxml +namespace aws.protocoltests.restxml +use aws.protocols#restXml use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -18,7 +19,7 @@ apply NoInputAndNoOutput @httpRequestTests([ { id: "NoInputAndNoOutput", documentation: "No input serializes no payload", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/NoInputAndOutput", body: "" @@ -29,7 +30,7 @@ apply NoInputAndNoOutput @httpResponseTests([ { id: "NoInputAndNoOutput", documentation: "No output serializes no payload", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: "" } @@ -48,7 +49,7 @@ apply NoInputAndOutput @httpRequestTests([ { id: "NoInputAndOutput", documentation: "No input serializes no payload", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/NoInputAndOutput", body: "" @@ -59,7 +60,7 @@ apply NoInputAndOutput @httpResponseTests([ { id: "NoInputAndOutput", documentation: "Empty output serializes no payload", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: "" } @@ -81,7 +82,7 @@ apply EmptyInputAndEmptyOutput @httpRequestTests([ { id: "EmptyInputAndEmptyOutput", documentation: "Empty input serializes no payload", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/EmptyInputAndEmptyOutput", body: "" @@ -92,7 +93,7 @@ apply EmptyInputAndEmptyOutput @httpResponseTests([ { id: "EmptyInputAndEmptyOutput", documentation: "Empty output serializes no payload", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: "" }, diff --git a/smithy-aws-protocol-tests/model/rest-json/endpoint-host-trait.smithy b/smithy-aws-protocol-tests/model/restXml/endpoint-host-trait.smithy similarity index 81% rename from smithy-aws-protocol-tests/model/rest-json/endpoint-host-trait.smithy rename to smithy-aws-protocol-tests/model/restXml/endpoint-host-trait.smithy index c2302f2cd46..bfe3b8cb400 100644 --- a/smithy-aws-protocol-tests/model/rest-json/endpoint-host-trait.smithy +++ b/smithy-aws-protocol-tests/model/restXml/endpoint-host-trait.smithy @@ -3,8 +3,9 @@ $version: "0.5.0" -namespace aws.protocols.tests.restjson +namespace aws.protocoltests.restxml +use aws.protocols#restXml use smithy.test#httpRequestTests use smithy.test#httpResponseTests diff --git a/smithy-aws-protocol-tests/model/rest-xml/errors.smithy b/smithy-aws-protocol-tests/model/restXml/errors.smithy similarity index 95% rename from smithy-aws-protocol-tests/model/rest-xml/errors.smithy rename to smithy-aws-protocol-tests/model/restXml/errors.smithy index 646a35c1ece..a51427e856a 100644 --- a/smithy-aws-protocol-tests/model/rest-xml/errors.smithy +++ b/smithy-aws-protocol-tests/model/restXml/errors.smithy @@ -2,8 +2,9 @@ $version: "0.5.0" -namespace aws.protocols.tests.restxml +namespace aws.protocoltests.restxml +use aws.protocols#restXml use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -27,7 +28,7 @@ apply GreetingWithErrors @httpResponseTests([ { id: "GreetingWithErrors", documentation: "Ensures that operations with errors successfully know how to deserialize the successful response", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: "", headers: { @@ -55,7 +56,7 @@ apply InvalidGreeting @httpResponseTests([ { id: "InvalidGreetingError", documentation: "Parses simple XML errors", - protocol: "aws.rest-xml", + protocol: restXml, params: { Message: "Hi" }, @@ -94,7 +95,7 @@ structure ComplexError { apply ComplexError @httpResponseTests([ { id: "ComplexError", - protocol: "aws.rest-xml", + protocol: restXml, params: { Header: "Header", TopLevel: "Top level", diff --git a/smithy-aws-protocol-tests/model/rest-xml/http-headers.smithy b/smithy-aws-protocol-tests/model/restXml/http-headers.smithy similarity index 92% rename from smithy-aws-protocol-tests/model/rest-xml/http-headers.smithy rename to smithy-aws-protocol-tests/model/restXml/http-headers.smithy index bd4b65ff184..ff25576143d 100644 --- a/smithy-aws-protocol-tests/model/rest-xml/http-headers.smithy +++ b/smithy-aws-protocol-tests/model/restXml/http-headers.smithy @@ -3,17 +3,18 @@ $version: "0.5.0" -namespace aws.protocols.tests.restxml - -use aws.protocols.tests.shared#BooleanList -use aws.protocols.tests.shared#EpochSeconds -use aws.protocols.tests.shared#FooEnum -use aws.protocols.tests.shared#FooEnumList -use aws.protocols.tests.shared#HttpDate -use aws.protocols.tests.shared#IntegerList -use aws.protocols.tests.shared#StringList -use aws.protocols.tests.shared#StringSet -use aws.protocols.tests.shared#TimestampList +namespace aws.protocoltests.restxml + +use aws.protocols#restXml +use aws.protocoltests.shared#BooleanList +use aws.protocoltests.shared#EpochSeconds +use aws.protocoltests.shared#FooEnum +use aws.protocoltests.shared#FooEnumList +use aws.protocoltests.shared#HttpDate +use aws.protocoltests.shared#IntegerList +use aws.protocoltests.shared#StringList +use aws.protocoltests.shared#StringSet +use aws.protocoltests.shared#TimestampList use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -29,7 +30,7 @@ apply InputAndOutputWithHeaders @httpRequestTests([ { id: "InputAndOutputWithStringHeaders", documentation: "Tests requests with string header bindings", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/InputAndOutputWithHeaders", headers: { @@ -47,7 +48,7 @@ apply InputAndOutputWithHeaders @httpRequestTests([ { id: "InputAndOutputWithNumericHeaders", documentation: "Tests requests with numeric header bindings", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/InputAndOutputWithHeaders", headers: { @@ -73,7 +74,7 @@ apply InputAndOutputWithHeaders @httpRequestTests([ { id: "InputAndOutputWithBooleanHeaders", documentation: "Tests requests with boolean header bindings", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/InputAndOutputWithHeaders", headers: { @@ -91,7 +92,7 @@ apply InputAndOutputWithHeaders @httpRequestTests([ { id: "InputAndOutputWithTimestampHeaders", documentation: "Tests requests with timestamp header bindings", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/InputAndOutputWithHeaders", headers: { @@ -105,7 +106,7 @@ apply InputAndOutputWithHeaders @httpRequestTests([ { id: "InputAndOutputWithEnumHeaders", documentation: "Tests requests with enum header bindings", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/InputAndOutputWithHeaders", headers: { @@ -124,7 +125,7 @@ apply InputAndOutputWithHeaders @httpResponseTests([ { id: "InputAndOutputWithStringHeaders", documentation: "Tests responses with string header bindings", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, headers: { "X-String": "Hello", @@ -141,7 +142,7 @@ apply InputAndOutputWithHeaders @httpResponseTests([ { id: "InputAndOutputWithNumericHeaders", documentation: "Tests responses with numeric header bindings", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, headers: { "X-Byte": "1", @@ -166,7 +167,7 @@ apply InputAndOutputWithHeaders @httpResponseTests([ { id: "InputAndOutputWithBooleanHeaders", documentation: "Tests responses with boolean header bindings", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, headers: { "X-Boolean1": "true", @@ -183,7 +184,7 @@ apply InputAndOutputWithHeaders @httpResponseTests([ { id: "InputAndOutputWithTimestampHeaders", documentation: "Tests responses with timestamp header bindings", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, headers: { "X-HeaderTimestampList": "Mon, 16 Dec 2019 23:48:18 GMT, Mon, 16 Dec 2019 23:48:18 GMT" @@ -196,7 +197,7 @@ apply InputAndOutputWithHeaders @httpResponseTests([ { id: "InputAndOutputWithEnumHeaders", documentation: "Tests responses with enum header bindings", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, headers: { "X-Enum": "Foo", @@ -272,7 +273,7 @@ apply NullAndEmptyHeaders @httpRequestTests([ { id: "NullAndEmptyHeaders", documentation: "Do not send null values, empty strings, or empty lists over the wire in headers", - protocol: "aws.rest-xml", + protocol: restXml, method: "GET", uri: "/NullAndEmptyHeaders", forbidHeaders: ["X-A", "X-B", "X-C"], @@ -289,7 +290,7 @@ apply NullAndEmptyHeaders @httpResponseTests([ { id: "NullAndEmptyHeaders", documentation: "Do not send null or empty headers", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, forbidHeaders: ["X-A", "X-B", "X-C"], body: "", @@ -323,7 +324,7 @@ apply TimestampFormatHeaders @httpRequestTests([ { id: "TimestampFormatHeaders", documentation: "Tests how timestamp request headers are serialized", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/TimestampFormatHeaders", headers: { @@ -352,7 +353,7 @@ apply TimestampFormatHeaders @httpResponseTests([ { id: "TimestampFormatHeaders", documentation: "Tests how timestamp response headers are serialized", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, headers: { "X-memberEpochSeconds": "1576540098", diff --git a/smithy-aws-protocol-tests/model/rest-xml/http-labels.smithy b/smithy-aws-protocol-tests/model/restXml/http-labels.smithy similarity index 95% rename from smithy-aws-protocol-tests/model/rest-xml/http-labels.smithy rename to smithy-aws-protocol-tests/model/restXml/http-labels.smithy index 0f9d665b901..b8acedf53f5 100644 --- a/smithy-aws-protocol-tests/model/rest-xml/http-labels.smithy +++ b/smithy-aws-protocol-tests/model/restXml/http-labels.smithy @@ -3,10 +3,11 @@ $version: "0.5.0" -namespace aws.protocols.tests.restxml +namespace aws.protocoltests.restxml -use aws.protocols.tests.shared#EpochSeconds -use aws.protocols.tests.shared#HttpDate +use aws.protocols#restXml +use aws.protocoltests.shared#EpochSeconds +use aws.protocoltests.shared#HttpDate use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -22,7 +23,7 @@ apply HttpRequestWithLabels @httpRequestTests([ { id: "InputWithHeadersAndAllParams", documentation: "Sends a GET request that uses URI label bindings", - protocol: "aws.rest-xml", + protocol: restXml, method: "GET", uri: "/HttpRequestWithLabels/string/1/2/3/4.0/5.0/true/2019-12-16T23%3A48%3A18Z", body: "", @@ -87,7 +88,7 @@ apply HttpRequestWithLabelsAndTimestampFormat @httpRequestTests([ { id: "HttpRequestWithLabelsAndTimestampFormat", documentation: "Serializes different timestamp formats in URI labels", - protocol: "aws.rest-xml", + protocol: restXml, method: "GET", uri: """ /HttpRequestWithLabelsAndTimestampFormat\ @@ -155,7 +156,7 @@ apply HttpRequestWithGreedyLabelInPath @httpRequestTests([ { id: "HttpRequestWithGreedyLabelInPath", documentation: "Serializes greedy labels and normal labels", - protocol: "aws.rest-xml", + protocol: restXml, method: "GET", uri: "/HttpRequestWithGreedyLabelInPath/foo/hello/baz/there/guy", body: "", diff --git a/smithy-aws-protocol-tests/model/rest-xml/http-payload.smithy b/smithy-aws-protocol-tests/model/restXml/http-payload.smithy similarity index 94% rename from smithy-aws-protocol-tests/model/rest-xml/http-payload.smithy rename to smithy-aws-protocol-tests/model/restXml/http-payload.smithy index addc34aa7be..4d57255f187 100644 --- a/smithy-aws-protocol-tests/model/rest-xml/http-payload.smithy +++ b/smithy-aws-protocol-tests/model/restXml/http-payload.smithy @@ -3,9 +3,10 @@ $version: "0.5.0" -namespace aws.protocols.tests.restxml +namespace aws.protocoltests.restxml -use aws.protocols.tests.shared#TextPlainBlob +use aws.protocols#restXml +use aws.protocoltests.shared#TextPlainBlob use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -23,7 +24,7 @@ apply HttpPayloadTraits @httpRequestTests([ { id: "HttpPayloadTraitsWithBlob", documentation: "Serializes a blob in the HTTP payload", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/HttpPayloadTraits", body: "blobby blob blob", @@ -38,7 +39,7 @@ apply HttpPayloadTraits @httpRequestTests([ { id: "HttpPayloadTraitsWithNoBlobBody", documentation: "Serializes an empty blob in the HTTP payload", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/HttpPayloadTraits", body: "", @@ -55,7 +56,7 @@ apply HttpPayloadTraits @httpResponseTests([ { id: "HttpPayloadTraitsWithBlob", documentation: "Serializes a blob in the HTTP payload", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: "blobby blob blob", headers: { @@ -69,7 +70,7 @@ apply HttpPayloadTraits @httpResponseTests([ { id: "HttpPayloadTraitsWithNoBlobBody", documentation: "Serializes an empty blob in the HTTP payload", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: "", headers: { @@ -101,7 +102,7 @@ apply HttpPayloadTraitsWithMediaType @httpRequestTests([ { id: "HttpPayloadTraitsWithMediaTypeWithBlob", documentation: "Serializes a blob in the HTTP payload with a content-type", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/HttpPayloadTraitsWithMediaType", body: "blobby blob blob", @@ -120,7 +121,7 @@ apply HttpPayloadTraitsWithMediaType @httpResponseTests([ { id: "HttpPayloadTraitsWithMediaTypeWithBlob", documentation: "Serializes a blob in the HTTP payload with a content-type", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: "blobby blob blob", headers: { @@ -157,7 +158,7 @@ apply HttpPayloadWithStructure @httpRequestTests([ { id: "HttpPayloadWithStructure", documentation: "Serializes a structure in the payload", - protocol: "aws.rest-xml", + protocol: restXml, method: "PUT", uri: "/HttpPayloadWithStructure", body: """ @@ -183,7 +184,7 @@ apply HttpPayloadWithStructure @httpResponseTests([ { id: "HttpPayloadWithStructure", documentation: "Serializes a structure in the payload", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: """ @@ -227,7 +228,7 @@ apply HttpPayloadWithXmlName @httpRequestTests([ { id: "HttpPayloadWithXmlName", documentation: "Serializes a structure in the payload using a wrapper name based on xmlName", - protocol: "aws.rest-xml", + protocol: restXml, method: "PUT", uri: "/HttpPayloadWithStructure", body: "Phreddy", @@ -247,7 +248,7 @@ apply HttpPayloadWithXmlName @httpResponseTests([ { id: "HttpPayloadWithXmlName", documentation: "Serializes a structure in the payload using a wrapper name based on xmlName", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: "Phreddy", bodyMediaType: "application/xml", @@ -284,7 +285,7 @@ apply HttpPayloadWithXmlNamespace @httpRequestTests([ { id: "HttpPayloadWithXmlNamespace", documentation: "Serializes a structure in the payload using a wrapper with an XML namespace", - protocol: "aws.rest-xml", + protocol: restXml, method: "PUT", uri: "/HttpPayloadWithXmlNamespace", body: """ @@ -307,7 +308,7 @@ apply HttpPayloadWithXmlNamespace @httpResponseTests([ { id: "HttpPayloadWithXmlNamespace", documentation: "Serializes a structure in the payload using a wrapper with an XML namespace", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: """ @@ -347,7 +348,7 @@ apply HttpPayloadWithXmlNamespaceAndPrefix @httpRequestTests([ { id: "HttpPayloadWithXmlNamespaceAndPrefix", documentation: "Serializes a structure in the payload using a wrapper with an XML namespace", - protocol: "aws.rest-xml", + protocol: restXml, method: "PUT", uri: "/HttpPayloadWithXmlNamespaceAndPrefix", body: """ @@ -370,7 +371,7 @@ apply HttpPayloadWithXmlNamespaceAndPrefix @httpResponseTests([ { id: "HttpPayloadWithXmlNamespaceAndPrefix", documentation: "Serializes a structure in the payload using a wrapper with an XML namespace", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: """ diff --git a/smithy-aws-protocol-tests/model/rest-xml/http-prefix-headers.smithy b/smithy-aws-protocol-tests/model/restXml/http-prefix-headers.smithy similarity index 93% rename from smithy-aws-protocol-tests/model/rest-xml/http-prefix-headers.smithy rename to smithy-aws-protocol-tests/model/restXml/http-prefix-headers.smithy index 56211279c69..181cbcc11de 100644 --- a/smithy-aws-protocol-tests/model/rest-xml/http-prefix-headers.smithy +++ b/smithy-aws-protocol-tests/model/restXml/http-prefix-headers.smithy @@ -3,8 +3,9 @@ $version: "0.5.0" -namespace aws.protocols.tests.restxml +namespace aws.protocoltests.restxml +use aws.protocols#restXml use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -21,7 +22,7 @@ apply HttpPrefixHeaders @httpRequestTests([ { id: "HttpPrefixHeadersArePresent", documentation: "Adds headers by prefix", - protocol: "aws.rest-xml", + protocol: restXml, method: "GET", uri: "/HttpPrefixHeaders", body: "", @@ -41,7 +42,7 @@ apply HttpPrefixHeaders @httpRequestTests([ { id: "HttpPrefixHeadersAreNotPresent", documentation: "No prefix headers are serialized because the value is empty", - protocol: "aws.rest-xml", + protocol: restXml, method: "GET", uri: "/HttpPrefixHeaders", body: "", @@ -59,7 +60,7 @@ apply HttpPrefixHeaders @httpResponseTests([ { id: "HttpPrefixHeadersArePresent", documentation: "Adds headers by prefix", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: "", headers: { @@ -78,7 +79,7 @@ apply HttpPrefixHeaders @httpResponseTests([ { id: "HttpPrefixHeadersAreNotPresent", documentation: "No prefix headers are serialized because the value is empty", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, body: "", headers: { diff --git a/smithy-aws-protocol-tests/model/rest-xml/http-query.smithy b/smithy-aws-protocol-tests/model/restXml/http-query.smithy similarity index 92% rename from smithy-aws-protocol-tests/model/rest-xml/http-query.smithy rename to smithy-aws-protocol-tests/model/restXml/http-query.smithy index 543ec187a55..0f73a0d99e8 100644 --- a/smithy-aws-protocol-tests/model/rest-xml/http-query.smithy +++ b/smithy-aws-protocol-tests/model/restXml/http-query.smithy @@ -3,17 +3,18 @@ $version: "0.5.0" -namespace aws.protocols.tests.restxml - -use aws.protocols.tests.shared#BooleanList -use aws.protocols.tests.shared#DoubleList -use aws.protocols.tests.shared#FooEnum -use aws.protocols.tests.shared#FooEnumList -use aws.protocols.tests.shared#IntegerList -use aws.protocols.tests.shared#IntegerSet -use aws.protocols.tests.shared#StringList -use aws.protocols.tests.shared#StringSet -use aws.protocols.tests.shared#TimestampList +namespace aws.protocoltests.restxml + +use aws.protocols#restXml +use aws.protocoltests.shared#BooleanList +use aws.protocoltests.shared#DoubleList +use aws.protocoltests.shared#FooEnum +use aws.protocoltests.shared#FooEnumList +use aws.protocoltests.shared#IntegerList +use aws.protocoltests.shared#IntegerSet +use aws.protocoltests.shared#StringList +use aws.protocoltests.shared#StringSet +use aws.protocoltests.shared#TimestampList use smithy.test#httpRequestTests use smithy.test#httpResponseTests @@ -28,7 +29,7 @@ apply AllQueryStringTypes @httpRequestTests([ { id: "AllQueryStringTypes", documentation: "Serializes query string parameters with all supported types", - protocol: "aws.rest-xml", + protocol: restXml, method: "GET", uri: "/AllQueryStringTypes", body: "", @@ -157,7 +158,7 @@ structure AllQueryStringTypesInput { { id: "ConstantQueryString", documentation: "Includes constant query string parameters", - protocol: "aws.rest-xml", + protocol: restXml, method: "GET", uri: "/ConstantQueryString/hi", queryParams: [ @@ -193,7 +194,7 @@ apply ConstantAndVariableQueryString @httpRequestTests([ { id: "ConstantAndVariableQueryStringMissingOneValue", documentation: "Mixes constant and variable query string parameters", - protocol: "aws.rest-xml", + protocol: restXml, method: "GET", uri: "/ConstantAndVariableQueryString", queryParams: [ @@ -209,7 +210,7 @@ apply ConstantAndVariableQueryString @httpRequestTests([ { id: "ConstantAndVariableQueryStringAllValues", documentation: "Mixes constant and variable query string parameters", - protocol: "aws.rest-xml", + protocol: restXml, method: "GET", uri: "/ConstantAndVariableQueryString", queryParams: [ @@ -246,7 +247,7 @@ apply IgnoreQueryParamsInResponse @httpResponseTests([ { id: "IgnoreQueryParamsInResponse", documentation: "Query parameters must be ignored when serializing the output of an operation", - protocol: "aws.rest-xml", + protocol: restXml, code: 200, headers: { "Content-Type": "application/xml" @@ -275,7 +276,7 @@ apply OmitsNullSerializesEmptyString @httpRequestTests([ { id: "OmitsNullSerializesEmptyString", documentation: "Serializes empty query strings but omits null", - protocol: "aws.rest-xml", + protocol: restXml, method: "GET", uri: "/OmitsNullSerializesEmptyString", body: "", @@ -308,7 +309,7 @@ apply QueryIdempotencyTokenAutoFill @httpRequestTests([ { id: "QueryIdempotencyTokenAutoFill", documentation: "Automatically adds idempotency token when not set", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/QueryIdempotencyTokenAutoFill", body: "", @@ -319,7 +320,7 @@ apply QueryIdempotencyTokenAutoFill @httpRequestTests([ { id: "QueryIdempotencyTokenAutoFillIsSet", documentation: "Uses the given idempotency token as-is", - protocol: "aws.rest-xml", + protocol: restXml, method: "POST", uri: "/QueryIdempotencyTokenAutoFill", body: "", diff --git a/smithy-aws-protocol-tests/model/rest-xml/main.smithy b/smithy-aws-protocol-tests/model/restXml/main.smithy similarity index 95% rename from smithy-aws-protocol-tests/model/rest-xml/main.smithy rename to smithy-aws-protocol-tests/model/restXml/main.smithy index 8c32f6fa9be..3cb46b71342 100644 --- a/smithy-aws-protocol-tests/model/rest-xml/main.smithy +++ b/smithy-aws-protocol-tests/model/restXml/main.smithy @@ -1,12 +1,13 @@ $version: "0.5.0" -namespace aws.protocols.tests.restxml +namespace aws.protocoltests.restxml +use aws.protocols#restXml use smithy.test#httpRequestTests use smithy.test#httpResponseTests /// A REST XML service that sends XML requests and responses. -@protocols([{"name": "aws.rest-xml"}]) +@restXml service RestXml { version: "2019-12-16", operations: [ diff --git a/smithy-aws-protocol-tests/model/shared-types.smithy b/smithy-aws-protocol-tests/model/shared-types.smithy index 9d5d2129a01..17d9252e9e1 100644 --- a/smithy-aws-protocol-tests/model/shared-types.smithy +++ b/smithy-aws-protocol-tests/model/shared-types.smithy @@ -7,7 +7,7 @@ $version: "0.5.0" -namespace aws.protocols.tests.shared +namespace aws.protocoltests.shared list StringList { member: String, diff --git a/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/apigateway/AuthorizerDefinition.java b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/apigateway/AuthorizerDefinition.java index 3d9578b1826..65522ebb47a 100644 --- a/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/apigateway/AuthorizerDefinition.java +++ b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/apigateway/AuthorizerDefinition.java @@ -18,11 +18,13 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import software.amazon.smithy.aws.traits.auth.SigV4Trait; import software.amazon.smithy.model.node.Node; import software.amazon.smithy.model.node.NumberNode; import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.node.StringNode; import software.amazon.smithy.model.node.ToNode; +import software.amazon.smithy.model.shapes.ShapeId; import software.amazon.smithy.utils.ListUtils; import software.amazon.smithy.utils.SmithyBuilder; import software.amazon.smithy.utils.ToSmithyBuilder; @@ -47,7 +49,7 @@ public final class AuthorizerDefinition implements ToNode, ToSmithyBuilder getUri() { * *

This value is not used directly by APIGateway but will be used for * OpenAPI exports. This will default to "awsSigV4" if your scheme is - * "aws.v4", or "custom" otherwise.

+ * {@code aws.auth#sigv4}, and if not, falls back to "custom".

* * @return Returns the authType. */ public String getAuthType() { if (authType != null) { return authType; - } else if (scheme.equals("aws.v4")) { + } else if (scheme.equals(SigV4Trait.ID)) { return SIGV4_AUTH_TYPE; } else { return DEFAULT_AUTH_TYPE; @@ -190,7 +192,7 @@ public Builder toBuilder() { @Override public Node toNode() { return Node.objectNodeBuilder() - .withMember(SCHEME_KEY, Node.from(getScheme())) + .withMember(SCHEME_KEY, Node.from(getScheme().toString())) .withOptionalMember(TYPE_KEY, getType().map(Node::from)) .withOptionalMember(AUTH_TYPE_KEY, Optional.ofNullable(authType).map(Node::from)) .withOptionalMember(URI_KEY, getUri().map(Node::from)) @@ -229,7 +231,7 @@ public int hashCode() { static AuthorizerDefinition fromNode(ObjectNode node) { node.warnIfAdditionalProperties(PROPERTIES); Builder builder = builder(); - builder.scheme(node.expectStringMember(SCHEME_KEY).getValue()); + builder.scheme(node.expectStringMember(SCHEME_KEY).expectShapeId()); node.getStringMember(TYPE_KEY) .map(StringNode::getValue) .ifPresent(builder::type); @@ -259,7 +261,7 @@ static AuthorizerDefinition fromNode(ObjectNode node) { * Builder used to create an {@link AuthorizerDefinition}. */ public static final class Builder implements SmithyBuilder { - private String scheme; + private ShapeId scheme; private String type; private String authType; private String uri; @@ -276,10 +278,10 @@ public AuthorizerDefinition build() { /** * Sets the client authentication scheme name. * - * @param scheme Client authentication scheme (e.g., aws.v4). + * @param scheme Client authentication scheme. * @return Returns the builder. */ - public Builder scheme(String scheme) { + public Builder scheme(ShapeId scheme) { this.scheme = scheme; return this; } diff --git a/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/apigateway/AuthorizersTraitValidator.java b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/apigateway/AuthorizersTraitValidator.java index 98a23f4342d..49651318176 100644 --- a/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/apigateway/AuthorizersTraitValidator.java +++ b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/apigateway/AuthorizersTraitValidator.java @@ -21,13 +21,13 @@ import java.util.Set; import java.util.stream.Collectors; import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.knowledge.ServiceIndex; import software.amazon.smithy.model.shapes.ServiceShape; -import software.amazon.smithy.model.traits.ProtocolsTrait; +import software.amazon.smithy.model.shapes.ShapeId; import software.amazon.smithy.model.validation.AbstractValidator; import software.amazon.smithy.model.validation.ValidationEvent; import software.amazon.smithy.model.validation.ValidationUtils; import software.amazon.smithy.utils.OptionalUtils; -import software.amazon.smithy.utils.SetUtils; /** * Each authorizer resolved within a service must use a scheme that @@ -37,21 +37,19 @@ public class AuthorizersTraitValidator extends AbstractValidator { @Override public List validate(Model model) { return model.shapes(ServiceShape.class) - .flatMap(service -> OptionalUtils.stream(validateService(service))) + .flatMap(service -> OptionalUtils.stream(validateService(model, service))) .collect(Collectors.toList()); } - private Optional validateService(ServiceShape service) { - Set schemeNames = service.getTrait(ProtocolsTrait.class) - .map(ProtocolsTrait::getAllAuthSchemes) - .orElse(SetUtils.of()); + private Optional validateService(Model model, ServiceShape service) { + Set authSchemes = model.getKnowledge(ServiceIndex.class).getAuthSchemes(service).keySet(); // Create a comma separated string of authorizer names to schemes. String invalidMappings = service.getTrait(AuthorizersTrait.class) .map(AuthorizersTrait::getAllAuthorizers) .orElseGet(HashMap::new) .entrySet().stream() - .filter(entry -> !schemeNames.contains(entry.getValue().getScheme())) + .filter(entry -> !authSchemes.contains(entry.getValue().getScheme())) .map(entry -> entry.getKey() + " -> " + entry.getValue().getScheme()) .sorted() .collect(Collectors.joining(", ")); @@ -62,11 +60,10 @@ private Optional validateService(ServiceShape service) { AuthorizersTrait authorizersTrait = service.getTrait(AuthorizersTrait.class).get(); return Optional.of(error(service, authorizersTrait, String.format( - "Each `scheme` of the `%s` trait must target one of the auth schemes defined in the " - + "`protocols` trait of a service (i.e., [%s]). The following mappings of authorizer names to " - + "schemes are invalid: %s", + "Each `scheme` of the `%s` trait must target one of the auth schemes applied to the service " + + "(i.e., [%s]). The following mappings of authorizer names to schemes are invalid: %s", AuthorizersTrait.ID, - ValidationUtils.tickedList(schemeNames), + ValidationUtils.tickedList(authSchemes), invalidMappings))); } } diff --git a/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/CognitoUserPoolsSettingsTrait.java b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/auth/CognitoUserPoolsTrait.java similarity index 86% rename from smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/CognitoUserPoolsSettingsTrait.java rename to smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/auth/CognitoUserPoolsTrait.java index 12c197c0e23..ccdd8052541 100644 --- a/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/CognitoUserPoolsSettingsTrait.java +++ b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/auth/CognitoUserPoolsTrait.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.smithy.aws.traits; +package software.amazon.smithy.aws.traits.auth; import java.util.ArrayList; import java.util.List; @@ -32,15 +32,14 @@ /** * Configures an Amazon Cognito User Pools auth scheme. */ -public final class CognitoUserPoolsSettingsTrait - extends AbstractTrait implements ToSmithyBuilder { +public final class CognitoUserPoolsTrait extends AbstractTrait implements ToSmithyBuilder { - public static final ShapeId ID = ShapeId.from("aws.api#cognitoUserPoolsSettings"); + public static final ShapeId ID = ShapeId.from("aws.auth#cognitoUserPools"); private static final String PROVIDER_ARNS = "providerArns"; private final List providerArns; - private CognitoUserPoolsSettingsTrait(Builder builder) { + private CognitoUserPoolsTrait(Builder builder) { super(ID, builder.getSourceLocation()); this.providerArns = ListUtils.copyOf(SmithyBuilder.requiredState("providerArns", builder.providerArns)); } @@ -60,7 +59,7 @@ public Trait createTrait(ShapeId target, Node value) { } /** - * @return Creates a builder used to build a {@link CognitoUserPoolsSettingsTrait}. + * @return Creates a builder used to build a {@link CognitoUserPoolsTrait}. */ public static Builder builder() { return new Builder(); @@ -86,15 +85,15 @@ protected Node createNode() { .withMember(PROVIDER_ARNS, providerArns.stream().map(Node::from).collect(ArrayNode.collect())); } - /** Builder for {@link CognitoUserPoolsSettingsTrait}. */ - public static final class Builder extends AbstractTraitBuilder { + /** Builder for {@link CognitoUserPoolsTrait}. */ + public static final class Builder extends AbstractTraitBuilder { private final List providerArns = new ArrayList<>(); private Builder() {} @Override - public CognitoUserPoolsSettingsTrait build() { - return new CognitoUserPoolsSettingsTrait(this); + public CognitoUserPoolsTrait build() { + return new CognitoUserPoolsTrait(this); } /** diff --git a/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/auth/SigV4Trait.java b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/auth/SigV4Trait.java new file mode 100644 index 00000000000..31db562d6ae --- /dev/null +++ b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/auth/SigV4Trait.java @@ -0,0 +1,98 @@ +/* + * Copyright 2019 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.traits.auth; + +import java.util.Set; +import software.amazon.smithy.model.node.Node; +import software.amazon.smithy.model.node.ObjectNode; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.traits.AbstractTrait; +import software.amazon.smithy.model.traits.AbstractTraitBuilder; +import software.amazon.smithy.model.traits.Trait; +import software.amazon.smithy.utils.SetUtils; +import software.amazon.smithy.utils.SmithyBuilder; +import software.amazon.smithy.utils.ToSmithyBuilder; + +/** + * Adds AWS signature version 4 authentication to a service or operation. + */ +public final class SigV4Trait extends AbstractTrait implements ToSmithyBuilder { + + public static final ShapeId ID = ShapeId.from("aws.auth#sigv4"); + private static final String NAME = "name"; + private static final Set PROPERTIES = SetUtils.of(NAME); + + private final String name; + + private SigV4Trait(Builder builder) { + super(ID, builder.getSourceLocation()); + this.name = SmithyBuilder.requiredState(NAME, builder.name); + } + + /** + * @return Gets the service signing name. + */ + public String getName() { + return name; + } + + public static Builder builder() { + return new Builder(); + } + + @Override + public Builder toBuilder() { + return builder() + .name(getName()) + .sourceLocation(getSourceLocation()); + } + + @Override + protected Node createNode() { + return Node.objectNode().withMember(NAME, getName()); + } + + public static final class Builder extends AbstractTraitBuilder { + private String name; + + private Builder() {} + + public Builder name(String name) { + this.name = name; + return this; + } + + @Override + public SigV4Trait build() { + return new SigV4Trait(this); + } + } + + public static final class Provider extends AbstractTrait.Provider { + public Provider() { + super(ID); + } + + @Override + public Trait createTrait(ShapeId target, Node value) { + Builder builder = builder().sourceLocation(value); + ObjectNode objectNode = value.expectObjectNode(); + objectNode.warnIfAdditionalProperties(PROPERTIES); + builder.name(objectNode.expectStringMember(NAME).getValue()); + return builder.build(); + } + } +} diff --git a/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/AwsJson1_0Trait.java b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/AwsJson1_0Trait.java new file mode 100644 index 00000000000..92a18ebbb13 --- /dev/null +++ b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/AwsJson1_0Trait.java @@ -0,0 +1,58 @@ +/* + * Copyright 2019 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.traits.protocols; + +import software.amazon.smithy.model.node.Node; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.traits.AbstractTrait; + +/** + * An RPC-based protocol that sends JSON payloads. + * + *

Namespace names are included in shape IDs sent over the wire. + */ +public final class AwsJson1_0Trait extends AwsProtocolTrait { + + public static final ShapeId ID = ShapeId.from("aws.protocols#awsJson1_0"); + + private AwsJson1_0Trait(Builder builder) { + super(ID, builder); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends AwsProtocolTrait.Builder { + private Builder() {} + + @Override + public AwsJson1_0Trait build() { + return new AwsJson1_0Trait(this); + } + } + + public static final class Provider extends AbstractTrait.Provider { + public Provider() { + super(ID); + } + + @Override + public AwsJson1_0Trait createTrait(ShapeId target, Node value) { + return builder().sourceLocation(value).fromNode(value).build(); + } + } +} diff --git a/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/AwsJson1_1Trait.java b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/AwsJson1_1Trait.java new file mode 100644 index 00000000000..c631795dc16 --- /dev/null +++ b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/AwsJson1_1Trait.java @@ -0,0 +1,58 @@ +/* + * Copyright 2019 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.traits.protocols; + +import software.amazon.smithy.model.node.Node; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.traits.AbstractTrait; + +/** + * An RPC-based protocol that sends JSON payloads. + * + *

Namespace names are stripped from shape IDs sent over the wire. + */ +public final class AwsJson1_1Trait extends AwsProtocolTrait { + + public static final ShapeId ID = ShapeId.from("aws.protocols#awsJson1_1"); + + private AwsJson1_1Trait(Builder builder) { + super(ID, builder); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends AwsProtocolTrait.Builder { + private Builder() {} + + @Override + public AwsJson1_1Trait build() { + return new AwsJson1_1Trait(this); + } + } + + public static final class Provider extends AbstractTrait.Provider { + public Provider() { + super(ID); + } + + @Override + public AwsJson1_1Trait createTrait(ShapeId target, Node value) { + return builder().sourceLocation(value).fromNode(value).build(); + } + } +} diff --git a/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/AwsProtocolTrait.java b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/AwsProtocolTrait.java new file mode 100644 index 00000000000..19eaff922b9 --- /dev/null +++ b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/AwsProtocolTrait.java @@ -0,0 +1,192 @@ +/* + * Copyright 2019 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.traits.protocols; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import software.amazon.smithy.model.node.ArrayNode; +import software.amazon.smithy.model.node.Node; +import software.amazon.smithy.model.node.ObjectNode; +import software.amazon.smithy.model.node.StringNode; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.traits.AbstractTrait; +import software.amazon.smithy.model.traits.AbstractTraitBuilder; +import software.amazon.smithy.model.traits.Trait; +import software.amazon.smithy.utils.ListUtils; + +/** + * Represents a configurable AWS protocol trait. + * + *

Subclasses are traits that allow the supported HTTP versions and + * eventStream HTTP versions to be customized. + */ +public abstract class AwsProtocolTrait extends AbstractTrait { + + private static final String HTTP = "http"; + private static final String EVENT_STREAM_HTTP = "eventStreamHttp"; + + private final List http; + private final List eventStreamHttp; + + // package-private constructor (at least for now) + AwsProtocolTrait(ShapeId id, Builder builder) { + super(id, builder.getSourceLocation()); + http = ListUtils.copyOf(builder.http); + eventStreamHttp = ListUtils.copyOf(builder.eventStreamHttp); + } + + /** + * Gets the priority ordered list of supported HTTP protocol versions. + * + * @return Returns the supported HTTP protocol versions. + */ + public List getHttp() { + return http; + } + + /** + * Gets the priority ordered list of supported HTTP protocol versions + * that are required when using event streams. + * + * @return Returns the supported event stream HTTP protocol versions. + */ + public List getEventStreamHttp() { + return eventStreamHttp; + } + + @Override + protected Node createNode() { + ObjectNode.Builder builder = Node.objectNodeBuilder(); + + if (!getHttp().isEmpty()) { + builder.withMember(HTTP, getHttp().stream() + .map(Http::toString) + .map(Node::from) + .collect(ArrayNode.collect())); + } + + if (!getEventStreamHttp().isEmpty()) { + builder.withMember(EVENT_STREAM_HTTP, getEventStreamHttp().stream() + .map(Http::toString) + .map(Node::from) + .collect(ArrayNode.collect())); + } + + return builder.build(); + } + + /** + * HTTP protocol versions, specified based on ALPN protocol IDs. + */ + public enum Http { + HTTP_1_1("http/1.1"), + H2("h2"); + + private final String modelValue; + + Http(String modelValue) { + this.modelValue = modelValue; + } + + @Override + public String toString() { + return modelValue; + } + + private static List getAllModelValues() { + List values = new ArrayList<>(); + for (Http http : Http.values()) { + values.add(http.toString()); + } + return values; + } + + private static Http fromString(String value) { + for (Http http : Http.values()) { + if (http.toString().equals(value)) { + return http; + } + } + return null; + } + } + + /** + * Builder for creating a {@code AwsProtocolTrait}. + * + * @param The type of trait being created. + * @param The concrete builder that creates {@code T}. + */ + public abstract static class Builder extends AbstractTraitBuilder { + + private final List http = new ArrayList<>(); + private final List eventStreamHttp = new ArrayList<>(); + + /** + * Sets the list of supported HTTP protocols. + * + * @param http HTTP protocols to set and replace. + * @return Returns the builder. + */ + @SuppressWarnings("unchecked") + public B http(List http) { + this.http.clear(); + this.http.addAll(http); + return (B) this; + } + + /** + * Sets the list of supported event stream HTTP protocols. + * + * @param eventStreamHttp Event stream HTTP protocols to set and replace. + * @return Returns the builder. + */ + @SuppressWarnings("unchecked") + public B eventStreamHttp(List eventStreamHttp) { + this.eventStreamHttp.clear(); + this.eventStreamHttp.addAll(eventStreamHttp); + return (B) this; + } + + /** + * Updates the builder from a Node. + * + * @param node Node object that must be a valid {@code ObjectNode}. + * @return Returns the updated builder. + */ + @SuppressWarnings("unchecked") + public B fromNode(Node node) { + ObjectNode objectNode = node.expectObjectNode(); + http(loadHttpList(HTTP, objectNode)); + eventStreamHttp(loadHttpList(EVENT_STREAM_HTTP, objectNode)); + return (B) this; + } + + private List loadHttpList(String memberName, ObjectNode node) { + return node.getArrayMember(memberName) + .map(array -> { + List result = new ArrayList<>(array.size()); + for (StringNode value : array.getElementsAs(StringNode.class)) { + String oneOf = value.expectOneOf(Http.getAllModelValues()); + result.add(Http.fromString(oneOf)); + } + return result; + }) + .orElse(Collections.emptyList()); + } + } +} diff --git a/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/AwsQueryTrait.java b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/AwsQueryTrait.java new file mode 100644 index 00000000000..733ff7cead7 --- /dev/null +++ b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/AwsQueryTrait.java @@ -0,0 +1,45 @@ +/* + * Copyright 2019 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.traits.protocols; + +import software.amazon.smithy.model.SourceLocation; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.traits.BooleanTrait; + +/** + * An RPC-based protocol that sends query string requests and XML responses. + * + *

This protocol is deprecated. For new services, ise {@link RestJson1Trait} + * or {@link AwsJson1_1Trait} instead. + */ +public final class AwsQueryTrait extends BooleanTrait { + + public static final ShapeId ID = ShapeId.from("aws.protocols#awsQuery"); + + public AwsQueryTrait(SourceLocation sourceLocation) { + super(ID, sourceLocation); + } + + public AwsQueryTrait() { + this(SourceLocation.NONE); + } + + public static final class Provider extends BooleanTrait.Provider { + public Provider() { + super(ID, AwsQueryTrait::new); + } + } +} diff --git a/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/Ec2QueryTrait.java b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/Ec2QueryTrait.java new file mode 100644 index 00000000000..80e14960d54 --- /dev/null +++ b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/Ec2QueryTrait.java @@ -0,0 +1,46 @@ +/* + * Copyright 2019 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.traits.protocols; + +import software.amazon.smithy.model.SourceLocation; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.traits.BooleanTrait; + +/** + * An RPC-based protocol that sends query string requests and XML responses, + * customized for Amazon EC2. + * + *

This protocol is deprecated. For new services, ise {@link RestJson1Trait} + * or {@link AwsJson1_1Trait} instead. + */ +public final class Ec2QueryTrait extends BooleanTrait { + + public static final ShapeId ID = ShapeId.from("aws.protocols#ec2Query"); + + public Ec2QueryTrait(SourceLocation sourceLocation) { + super(ID, sourceLocation); + } + + public Ec2QueryTrait() { + this(SourceLocation.NONE); + } + + public static final class Provider extends BooleanTrait.Provider { + public Provider() { + super(ID, Ec2QueryTrait::new); + } + } +} diff --git a/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/RestJson1Trait.java b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/RestJson1Trait.java new file mode 100644 index 00000000000..ab31e122c87 --- /dev/null +++ b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/RestJson1Trait.java @@ -0,0 +1,56 @@ +/* + * Copyright 2019 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.traits.protocols; + +import software.amazon.smithy.model.node.Node; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.traits.AbstractTrait; + +/** + * A RESTful protocol that sends JSON in structured payloads. + */ +public final class RestJson1Trait extends AwsProtocolTrait { + + public static final ShapeId ID = ShapeId.from("aws.protocols#restJson1"); + + private RestJson1Trait(Builder builder) { + super(ID, builder); + } + + public static Builder builder() { + return new RestJson1Trait.Builder(); + } + + public static final class Builder extends AwsProtocolTrait.Builder { + private Builder() {} + + @Override + public RestJson1Trait build() { + return new RestJson1Trait(this); + } + } + + public static final class Provider extends AbstractTrait.Provider { + public Provider() { + super(ID); + } + + @Override + public RestJson1Trait createTrait(ShapeId target, Node value) { + return builder().sourceLocation(value).fromNode(value).build(); + } + } +} diff --git a/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/RestXmlTrait.java b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/RestXmlTrait.java new file mode 100644 index 00000000000..22e2ec791e1 --- /dev/null +++ b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/RestXmlTrait.java @@ -0,0 +1,56 @@ +/* + * Copyright 2019 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.traits.protocols; + +import software.amazon.smithy.model.node.Node; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.traits.AbstractTrait; + +/** + * A RESTful protocol that sends XML in structured payloads. + */ +public final class RestXmlTrait extends AwsProtocolTrait { + + public static final ShapeId ID = ShapeId.from("aws.protocols#restXml"); + + private RestXmlTrait(Builder builder) { + super(ID, builder); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends AwsProtocolTrait.Builder { + private Builder() {} + + @Override + public RestXmlTrait build() { + return new RestXmlTrait(this); + } + } + + public static final class Provider extends AbstractTrait.Provider { + public Provider() { + super(ID); + } + + @Override + public RestXmlTrait createTrait(ShapeId target, Node value) { + return builder().sourceLocation(value).fromNode(value).build(); + } + } +} diff --git a/smithy-aws-traits/src/main/resources/META-INF/services/software.amazon.smithy.model.traits.TraitService b/smithy-aws-traits/src/main/resources/META-INF/services/software.amazon.smithy.model.traits.TraitService index c1545f96b80..821f7eb2d14 100644 --- a/smithy-aws-traits/src/main/resources/META-INF/services/software.amazon.smithy.model.traits.TraitService +++ b/smithy-aws-traits/src/main/resources/META-INF/services/software.amazon.smithy.model.traits.TraitService @@ -1,6 +1,6 @@ software.amazon.smithy.aws.traits.ArnTrait$Provider software.amazon.smithy.aws.traits.ArnReferenceTrait$Provider -software.amazon.smithy.aws.traits.CognitoUserPoolsSettingsTrait$Provider +software.amazon.smithy.aws.traits.auth.CognitoUserPoolsTrait$Provider software.amazon.smithy.aws.traits.ControlPlaneTrait$Provider software.amazon.smithy.aws.traits.DataPlaneTrait$Provider software.amazon.smithy.aws.traits.DataTrait$Provider @@ -21,3 +21,10 @@ software.amazon.smithy.aws.traits.clientendpointdiscovery.ClientEndpointDiscover software.amazon.smithy.aws.traits.clientendpointdiscovery.ClientEndpointDiscoveryIdTrait$Provider software.amazon.smithy.aws.traits.clientendpointdiscovery.ClientDiscoveredEndpointTrait$Provider software.amazon.smithy.aws.traits.Ec2QueryNameTrait$Provider +software.amazon.smithy.aws.traits.protocols.AwsQueryTrait$Provider +software.amazon.smithy.aws.traits.protocols.Ec2QueryTrait$Provider +software.amazon.smithy.aws.traits.protocols.RestJson1Trait$Provider +software.amazon.smithy.aws.traits.protocols.RestXmlTrait$Provider +software.amazon.smithy.aws.traits.protocols.AwsJson1_0Trait$Provider +software.amazon.smithy.aws.traits.protocols.AwsJson1_1Trait$Provider +software.amazon.smithy.aws.traits.auth.SigV4Trait$Provider diff --git a/smithy-aws-traits/src/main/resources/META-INF/smithy/aws.api.json b/smithy-aws-traits/src/main/resources/META-INF/smithy/aws.api.json index 18a75c664e6..c49acc4707a 100644 --- a/smithy-aws-traits/src/main/resources/META-INF/smithy/aws.api.json +++ b/smithy-aws-traits/src/main/resources/META-INF/smithy/aws.api.json @@ -113,26 +113,6 @@ "smithy.api#documentation": "Designates the target as containing data of a known classification level." } }, - "aws.api#cognitoUserPoolsSettings": { - "type": "structure", - "members": { - "providerArns": { - "target": "aws.api#StringList", - "traits": { - "smithy.api#required": true - } - } - }, - "traits": { - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#documentation": "Configures an Amazon Cognito User Pools auth scheme.", - "smithy.api#tags": [ - "internal" - ] - } - }, "aws.api#controlPlane": { "type": "structure", "traits": { @@ -175,6 +155,9 @@ "type": "list", "member": { "target": "smithy.api#String" + }, + "traits": { + "smithy.api#private": true } }, "aws.api#clientDiscoveredEndpoint": { diff --git a/smithy-aws-traits/src/main/resources/META-INF/smithy/aws.apigateway.json b/smithy-aws-traits/src/main/resources/META-INF/smithy/aws.apigateway.json index aacec497997..434857b4158 100644 --- a/smithy-aws-traits/src/main/resources/META-INF/smithy/aws.apigateway.json +++ b/smithy-aws-traits/src/main/resources/META-INF/smithy/aws.apigateway.json @@ -39,7 +39,12 @@ "target": "smithy.api#String", "traits": { "smithy.api#required": true, - "smithy.api#documentation": "The Smithy authentication scheme used by the client (e.g, aws.v4)." + "smithy.api#documentation": "The Smithy authentication scheme used by the client (e.g, aws.v4).", + "smithy.api#idRef": { + "selector": "[trait|authDefinition]", + "failWhenMissing": true, + "errorMessage": "The scheme of an authorizer definition must reference an auth trait" + } } }, "type": { diff --git a/smithy-aws-traits/src/main/resources/META-INF/smithy/aws.auth.json b/smithy-aws-traits/src/main/resources/META-INF/smithy/aws.auth.json new file mode 100644 index 00000000000..84cf466da91 --- /dev/null +++ b/smithy-aws-traits/src/main/resources/META-INF/smithy/aws.auth.json @@ -0,0 +1,57 @@ +{ + "smithy": "0.5.0", + "shapes": { + "aws.auth#sigv4": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#required": true, + "smithy.api#documentation": "The signature version 4 service signing name to use in the credential scope when signing requests. This value SHOULD match the `arnNamespace` property of the `aws.api#service-trait`.", + "smithy.api#externalDocumentation": "https://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html" + } + } + }, + "traits": { + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#authDefinition": true, + "smithy.api#documentation": "Signature Version 4 is the process to add authentication information to AWS requests sent by HTTP. For security, most requests to AWS must be signed with an access key, which consists of an access key ID and secret access key. These two keys are commonly referred to as your security credentials.", + "smithy.api#externalDocumentation": "https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html" + } + }, + "aws.auth#cognitoUserPools": { + "type": "structure", + "members": { + "providerArns": { + "target": "aws.auth#StringList", + "traits": { + "smithy.api#required": true, + "smithy.api#documentation": "A list of the Amazon Cognito user pool ARNs. Each element is of this format: arn:aws:cognito-idp:{region}:{account_id}:userpool/{user_pool_id}." + } + } + }, + "traits": { + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#authDefinition": true, + "smithy.api#documentation": "Configures an Amazon Cognito User Pools auth scheme.", + "smithy.api#tags": [ + "internal" + ] + } + }, + "aws.auth#StringList": { + "type": "list", + "member": { + "target": "smithy.api#String" + }, + "traits": { + "smithy.api#private": true + } + } + } +} diff --git a/smithy-aws-traits/src/main/resources/META-INF/smithy/aws.protocols.json b/smithy-aws-traits/src/main/resources/META-INF/smithy/aws.protocols.json new file mode 100644 index 00000000000..3c324268243 --- /dev/null +++ b/smithy-aws-traits/src/main/resources/META-INF/smithy/aws.protocols.json @@ -0,0 +1,109 @@ +{ + "smithy": "0.5.0", + "shapes": { + "aws.protocols#restJson1": { + "type": "structure", + "members": { + "http": { + "target": "aws.protocols#StringList" + }, + "eventStreamHttp": { + "target": "aws.protocols#StringList" + } + }, + "traits": { + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#protocolDefinition": true, + "smithy.api#documentation": "A RESTful protocol that sends JSON in structured payloads." + } + }, + "aws.protocols#restXml": { + "type": "structure", + "members": { + "http": { + "target": "aws.protocols#StringList" + }, + "eventStreamHttp": { + "target": "aws.protocols#StringList" + } + }, + "traits": { + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#protocolDefinition": true, + "smithy.api#documentation": "A RESTful protocol that sends XML in structured payloads.", + "smithy.api#deprecated": true + } + }, + "aws.protocols#awsJson1_0": { + "type": "structure", + "members": { + "http": { + "target": "aws.protocols#StringList" + }, + "eventStreamHttp": { + "target": "aws.protocols#StringList" + } + }, + "traits": { + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#protocolDefinition": true, + "smithy.api#documentation": "An RPC-based protocol that sends JSON payloads. This protocol does not use HTTP binding traits." + } + }, + "aws.protocols#awsJson1_1": { + "type": "structure", + "members": { + "http": { + "target": "aws.protocols#StringList" + }, + "eventStreamHttp": { + "target": "aws.protocols#StringList" + } + }, + "traits": { + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#protocolDefinition": true, + "smithy.api#documentation": "An RPC-based protocol that sends JSON payloads. This protocol does not use HTTP binding traits." + } + }, + "aws.protocols#awsQuery": { + "type": "structure", + "traits": { + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#protocolDefinition": true, + "smithy.api#documentation": "An RPC-based protocol that sends query string requests and XML responses. This protocol does not use HTTP binding traits.", + "smithy.api#deprecated": true + } + }, + "aws.protocols#ec2Query": { + "type": "structure", + "traits": { + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#protocolDefinition": true, + "smithy.api#documentation": "An RPC-based protocol that sends Amazon EC2 formatted query string requests and XML responses. This protocol does not use HTTP binding traits.", + "smithy.api#deprecated": true + } + }, + "aws.protocols#StringList": { + "type": "list", + "member": { + "target": "smithy.api#String" + }, + "traits": { + "smithy.api#private": true + } + } + } +} diff --git a/smithy-aws-traits/src/main/resources/META-INF/smithy/manifest b/smithy-aws-traits/src/main/resources/META-INF/smithy/manifest index f788d831961..a16fe6388ae 100644 --- a/smithy-aws-traits/src/main/resources/META-INF/smithy/manifest +++ b/smithy-aws-traits/src/main/resources/META-INF/smithy/manifest @@ -1,3 +1,5 @@ aws.api.json aws.apigateway.json +aws.auth.json aws.iam.json +aws.protocols.json diff --git a/smithy-aws-traits/src/test/java/software/amazon/smithy/aws/traits/apigateway/AuthorizerIndexTest.java b/smithy-aws-traits/src/test/java/software/amazon/smithy/aws/traits/apigateway/AuthorizerIndexTest.java index b3b23704137..421600719b3 100644 --- a/smithy-aws-traits/src/test/java/software/amazon/smithy/aws/traits/apigateway/AuthorizerIndexTest.java +++ b/smithy-aws-traits/src/test/java/software/amazon/smithy/aws/traits/apigateway/AuthorizerIndexTest.java @@ -5,6 +5,7 @@ import java.util.Optional; import org.junit.jupiter.api.Test; +import software.amazon.smithy.aws.traits.auth.SigV4Trait; import software.amazon.smithy.model.Model; import software.amazon.smithy.model.shapes.ShapeId; @@ -31,7 +32,8 @@ public void computesAuthorizers() { // Resolves service value. assertThat(index.getAuthorizer(serviceA).get(), equalTo("foo")); - assertThat(index.getAuthorizerValue(serviceA).map(AuthorizerDefinition::getScheme), equalTo(Optional.of("aws.v4"))); + assertThat(index.getAuthorizerValue(serviceA).map(AuthorizerDefinition::getScheme), + equalTo(Optional.of(SigV4Trait.ID))); assertThat(index.getAuthorizer(serviceB), equalTo(Optional.empty())); assertThat(index.getAuthorizerValue(serviceB), equalTo(Optional.empty())); diff --git a/smithy-aws-traits/src/test/java/software/amazon/smithy/aws/traits/apigateway/AuthorizersTraitTest.java b/smithy-aws-traits/src/test/java/software/amazon/smithy/aws/traits/apigateway/AuthorizersTraitTest.java index a184697f375..aeb066a290c 100644 --- a/smithy-aws-traits/src/test/java/software/amazon/smithy/aws/traits/apigateway/AuthorizersTraitTest.java +++ b/smithy-aws-traits/src/test/java/software/amazon/smithy/aws/traits/apigateway/AuthorizersTraitTest.java @@ -18,7 +18,7 @@ public void registersTrait() { ShapeId id = ShapeId.from("smithy.example#Foo"); ObjectNode node = Node.objectNodeBuilder() .withMember("aws.v4", Node.objectNodeBuilder() - .withMember("scheme", "aws.v4") + .withMember("scheme", "aws.auth#sigv4") .withMember("type", "request") .withMember("uri", "arn:foo:baz") .withMember("credentials", "arn:foo:bar") diff --git a/smithy-aws-traits/src/test/java/software/amazon/smithy/aws/traits/apigateway/IntegrationTraitTest.java b/smithy-aws-traits/src/test/java/software/amazon/smithy/aws/traits/apigateway/IntegrationTraitTest.java index c99235aaabc..f20b1c6ef7e 100644 --- a/smithy-aws-traits/src/test/java/software/amazon/smithy/aws/traits/apigateway/IntegrationTraitTest.java +++ b/smithy-aws-traits/src/test/java/software/amazon/smithy/aws/traits/apigateway/IntegrationTraitTest.java @@ -19,6 +19,7 @@ import static org.hamcrest.Matchers.equalTo; import org.junit.jupiter.api.Test; +import software.amazon.smithy.aws.traits.TestRunnerTest; import software.amazon.smithy.model.Model; import software.amazon.smithy.model.shapes.ShapeId; @@ -46,7 +47,7 @@ public void loadsValidTrait() { public void loadsTraitFromModel() { Model model = Model.assembler() .discoverModels(getClass().getClassLoader()) - .addImport(getClass().getResource("errorfiles/valid-integration.json")) + .addImport(TestRunnerTest.class.getResource("errorfiles/apigateway/valid-integration.json")) .assemble() .unwrap(); diff --git a/smithy-aws-traits/src/test/java/software/amazon/smithy/aws/traits/apigateway/RunnerTest.java b/smithy-aws-traits/src/test/java/software/amazon/smithy/aws/traits/apigateway/RunnerTest.java deleted file mode 100644 index e1b9dc0568f..00000000000 --- a/smithy-aws-traits/src/test/java/software/amazon/smithy/aws/traits/apigateway/RunnerTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package software.amazon.smithy.aws.traits.apigateway; - -import org.junit.jupiter.api.Test; -import software.amazon.smithy.model.Model; -import software.amazon.smithy.model.loader.ModelAssembler; -import software.amazon.smithy.model.validation.testrunner.SmithyTestSuite; - -public class RunnerTest { - @Test - public void testRunner() { - ModelAssembler assembler = Model.assembler(getClass().getClassLoader()) - .discoverModels(getClass().getClassLoader()); - - System.out.println(SmithyTestSuite.runner() - .setModelAssemblerFactory(assembler::copy) - .addTestCasesFromUrl(RunnerTest.class.getResource("errorfiles")) - .run()); - } -} diff --git a/smithy-aws-traits/src/test/java/software/amazon/smithy/aws/traits/clientendpointdiscovery/RunnerTest.java b/smithy-aws-traits/src/test/java/software/amazon/smithy/aws/traits/clientendpointdiscovery/RunnerTest.java deleted file mode 100644 index f27ad1d8514..00000000000 --- a/smithy-aws-traits/src/test/java/software/amazon/smithy/aws/traits/clientendpointdiscovery/RunnerTest.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2019 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.traits.clientendpointdiscovery; - -import org.junit.jupiter.api.Test; -import software.amazon.smithy.model.Model; -import software.amazon.smithy.model.loader.ModelAssembler; -import software.amazon.smithy.model.validation.testrunner.SmithyTestSuite; - -public class RunnerTest { - @Test - public void testRunner() { - ModelAssembler assembler = Model.assembler(getClass().getClassLoader()) - .discoverModels(getClass().getClassLoader()); - - System.out.println(SmithyTestSuite.runner() - .setModelAssemblerFactory(assembler::copy) - .addTestCasesFromUrl(getClass().getResource("errorfiles")) - .run()); - } -} diff --git a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/apigateway/effective-authorizers.smithy b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/apigateway/effective-authorizers.smithy index 59f6a7c0e46..d814281e17d 100644 --- a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/apigateway/effective-authorizers.smithy +++ b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/apigateway/effective-authorizers.smithy @@ -1,10 +1,12 @@ namespace smithy.example -@protocols([{name: "aws-rest-json", auth: ["aws.v4"]}]) +use aws.auth#sigv4 + +@sigv4(name: "service") @aws.apigateway#authorizer("foo") @aws.apigateway#authorizers( - foo: {scheme: "aws.v4", type: "aws", uri: "arn:foo"}, - baz: {scheme: "aws.v4", type: "aws", uri: "arn:foo"}) + foo: {scheme: sigv4, type: "aws", uri: "arn:foo"}, + baz: {scheme: sigv4, type: "aws", uri: "arn:foo"}) service ServiceA { version: "2019-06-17", operations: [OperationA, OperationB], @@ -43,11 +45,10 @@ operation OperationE {} @aws.apigateway#authorizer("foo") operation OperationF {} - -@protocols([{name: "aws-rest-json", auth: ["aws.v4"]}]) +@sigv4(name: "service") @aws.apigateway#authorizers( - foo: {scheme: "aws.v4", type: "aws", uri: "arn:foo"}, - baz: {scheme: "aws.v4", type: "aws", uri: "arn:foo"}) + foo: {scheme: sigv4, type: "aws", uri: "arn:foo"}, + baz: {scheme: sigv4, type: "aws", uri: "arn:foo"}) service ServiceB { version: "2019-06-17", operations: [OperationA, OperationB], diff --git a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/apigateway/errorfiles/invalid-authorizers.errors b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/apigateway/errorfiles/invalid-authorizers.errors deleted file mode 100644 index 8ab3641fb7c..00000000000 --- a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/apigateway/errorfiles/invalid-authorizers.errors +++ /dev/null @@ -1 +0,0 @@ -[ERROR] ns.foo#SomeService: Each `scheme` of the `aws.apigateway#authorizers` trait must target one of the auth schemes defined in the `protocols` trait of a service (i.e., [`aws.v4`]). The following mappings of authorizer names to schemes are invalid: another -> another, invalid -> invalid | AuthorizersTrait diff --git a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/apigateway/invalid-authorizers.errors b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/apigateway/invalid-authorizers.errors new file mode 100644 index 00000000000..05579a2d570 --- /dev/null +++ b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/apigateway/invalid-authorizers.errors @@ -0,0 +1,2 @@ +[ERROR] ns.foo#SomeService: Each `scheme` of the `aws.apigateway#authorizers` trait must target one of the auth schemes applied to the service (i.e., [`aws.auth#sigv4`]). The following mappings of authorizer names to schemes are invalid: another -> smithy.api#httpBasicAuth, invalid -> ns.foo#invalid | AuthorizersTrait +[ERROR] ns.foo#SomeService: Error validating trait `aws.apigateway#authorizers`.invalid.scheme: The scheme of an authorizer definition must reference an auth trait | TraitValue diff --git a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/apigateway/errorfiles/invalid-authorizers.json b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/apigateway/invalid-authorizers.json similarity index 68% rename from smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/apigateway/errorfiles/invalid-authorizers.json rename to smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/apigateway/invalid-authorizers.json index d8873b5722a..8e8db36ed17 100644 --- a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/apigateway/errorfiles/invalid-authorizers.json +++ b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/apigateway/invalid-authorizers.json @@ -5,25 +5,20 @@ "type": "service", "version": "2018-03-17", "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json", - "auth": [ - "aws.v4" - ] - } - ], + "aws.auth#sigv4": { + "name": "someservice" + }, "aws.apigateway#authorizers": { "invalid": { - "scheme": "invalid" + "scheme": "ns.foo#invalid" }, "another": { - "scheme": "another", + "scheme": "smithy.api#httpBasicAuth", "type": "token", "uri": "arn:foo:baz" }, "aws.v4": { - "scheme": "aws.v4", + "scheme": "aws.auth#sigv4", "type": "request", "uri": "arn:foo:baz", "credentials": "arn:foo:bar", diff --git a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/apigateway/errorfiles/valid-integration.errors b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/apigateway/valid-integration.errors similarity index 100% rename from smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/apigateway/errorfiles/valid-integration.errors rename to smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/apigateway/valid-integration.errors diff --git a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/apigateway/errorfiles/valid-integration.json b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/apigateway/valid-integration.json similarity index 100% rename from smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/apigateway/errorfiles/valid-integration.json rename to smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/apigateway/valid-integration.json diff --git a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/endpoint-shape-not-structure.errors b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/endpoint-shape-not-structure.errors similarity index 100% rename from smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/endpoint-shape-not-structure.errors rename to smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/endpoint-shape-not-structure.errors diff --git a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/endpoint-shape-not-structure.json b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/endpoint-shape-not-structure.json similarity index 100% rename from smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/endpoint-shape-not-structure.json rename to smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/endpoint-shape-not-structure.json diff --git a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/endpoints-not-list.errors b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/endpoints-not-list.errors similarity index 100% rename from smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/endpoints-not-list.errors rename to smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/endpoints-not-list.errors diff --git a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/endpoints-not-list.json b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/endpoints-not-list.json similarity index 100% rename from smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/endpoints-not-list.json rename to smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/endpoints-not-list.json diff --git a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/invalid-endpoint-structure.errors b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/invalid-endpoint-structure.errors similarity index 100% rename from smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/invalid-endpoint-structure.errors rename to smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/invalid-endpoint-structure.errors diff --git a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/invalid-endpoint-structure.json b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/invalid-endpoint-structure.json similarity index 100% rename from smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/invalid-endpoint-structure.json rename to smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/invalid-endpoint-structure.json diff --git a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/invalid-input-shape.errors b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/invalid-input-shape.errors similarity index 100% rename from smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/invalid-input-shape.errors rename to smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/invalid-input-shape.errors diff --git a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/invalid-input-shape.json b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/invalid-input-shape.json similarity index 100% rename from smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/invalid-input-shape.json rename to smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/invalid-input-shape.json diff --git a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/no-endpoints-member.errors b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/no-endpoints-member.errors similarity index 100% rename from smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/no-endpoints-member.errors rename to smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/no-endpoints-member.errors diff --git a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/no-endpoints-member.json b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/no-endpoints-member.json similarity index 100% rename from smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/no-endpoints-member.json rename to smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/no-endpoints-member.json diff --git a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/no-input.errors b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/no-input.errors similarity index 100% rename from smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/no-input.errors rename to smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/no-input.errors diff --git a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/no-input.json b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/no-input.json similarity index 100% rename from smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/no-input.json rename to smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/no-input.json diff --git a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/no-output.errors b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/no-output.errors similarity index 100% rename from smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/no-output.errors rename to smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/no-output.errors diff --git a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/no-output.json b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/no-output.json similarity index 100% rename from smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/clientendpointdiscovery/errorfiles/no-output.json rename to smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/clientendpointdiscovery/no-output.json diff --git a/smithy-build/src/main/java/software/amazon/smithy/build/transforms/IncludeAuth.java b/smithy-build/src/main/java/software/amazon/smithy/build/transforms/IncludeAuth.java deleted file mode 100644 index 3f73aada159..00000000000 --- a/smithy-build/src/main/java/software/amazon/smithy/build/transforms/IncludeAuth.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2019 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.build.transforms; - -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.function.BiFunction; -import software.amazon.smithy.build.ProjectionTransformer; -import software.amazon.smithy.model.Model; -import software.amazon.smithy.model.shapes.Shape; -import software.amazon.smithy.model.traits.AuthTrait; -import software.amazon.smithy.model.traits.Protocol; -import software.amazon.smithy.model.traits.ProtocolsTrait; -import software.amazon.smithy.model.transform.ModelTransformer; -import software.amazon.smithy.utils.ListUtils; - -/** - * Removes authentication schemes from "auth" traits and from the "auth" - * property of protocols that do not match one of the given arguments - * (a list of authentication schemes). - */ -public final class IncludeAuth implements ProjectionTransformer { - @Override - public String getName() { - return "includeAuth"; - } - - @Override - public List getAliases() { - return ListUtils.of("includeAuthentication"); - } - - @Override - public BiFunction createTransformer(List arguments) { - Set includeNames = new HashSet<>(arguments); - return (transformer, model) -> transformer.mapShapes(model, shape -> { - // First update the auth trait on all shapes. - Shape result = shape.getTrait(AuthTrait.class) - .map(authTrait -> updateShapeAuth(shape, authTrait, includeNames)) - .orElse(shape); - // Next update the protocols trait on service shapes. - return result.getTrait(ProtocolsTrait.class) - .map(protocolsTrait -> updateProtocolsTrait(result, protocolsTrait, includeNames)) - .orElse(result); - }); - } - - private static Shape updateShapeAuth(Shape shape, AuthTrait authTrait, Set includeNames) { - Set names = getIntersection(authTrait.getValues(), includeNames); - - // Only modify the shape if it actually changed the listed schemes. - if (names.size() == authTrait.getValues().size()) { - return shape; - } - - AuthTrait.Builder builder = AuthTrait.builder(); - builder.clearValues(); - authTrait.getValues().stream().filter(names::contains).forEach(builder::addValue); - return Shape.shapeToBuilder(shape).addTrait(builder.build()).build(); - } - - private static Set getIntersection(Collection values, Set includeNames) { - Set names = new HashSet<>(values); - names.retainAll(includeNames); - return names; - } - - private static Shape updateProtocolsTrait(Shape shape, ProtocolsTrait trait, Set includeNames) { - Set schemes = new HashSet<>(trait.getAllAuthSchemes()); - schemes.removeAll(includeNames); - - // Return the shape as-is if it doesn't contain any additional schemes. - if (schemes.isEmpty()) { - return shape; - } - - // Clear out and then re-add each updated protocol. - ProtocolsTrait.Builder protocolTraitBuilder = trait.toBuilder().clearProtocols(); - - for (Protocol protocol : trait.getProtocols()) { - Protocol.Builder protocolBuilder = protocol.toBuilder(); - // Clear out and re-add any auth schemes that are permitted. - protocolBuilder.clearAuth(); - for (String auth : protocol.getAuth()) { - if (includeNames.contains(auth)) { - protocolBuilder.addAuth(auth); - } - } - protocolTraitBuilder.addProtocol(protocolBuilder.build()); - } - - return Shape.shapeToBuilder(shape).addTrait(protocolTraitBuilder.build()).build(); - } -} diff --git a/smithy-build/src/main/java/software/amazon/smithy/build/transforms/IncludeProtocols.java b/smithy-build/src/main/java/software/amazon/smithy/build/transforms/IncludeProtocols.java deleted file mode 100644 index f1721fbea04..00000000000 --- a/smithy-build/src/main/java/software/amazon/smithy/build/transforms/IncludeProtocols.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2019 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.build.transforms; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.function.BiFunction; -import software.amazon.smithy.build.ProjectionTransformer; -import software.amazon.smithy.model.Model; -import software.amazon.smithy.model.shapes.Shape; -import software.amazon.smithy.model.traits.ProtocolsTrait; -import software.amazon.smithy.model.transform.ModelTransformer; - -/** - * Removes protocols from service shapes that do not match one of the - * given arguments (a list of protocol names). - */ -public final class IncludeProtocols implements ProjectionTransformer { - @Override - public String getName() { - return "includeProtocols"; - } - - @Override - public BiFunction createTransformer(List arguments) { - Set includeNames = new HashSet<>(arguments); - return (transformer, model) -> transformer.mapShapes(model, shape -> shape.getTrait(ProtocolsTrait.class) - .map(protocols -> { - Set names = getSchemeNameIntersection(protocols, includeNames); - return names.size() == protocols.getProtocols().size() - ? shape - : updateTrait(shape, protocols, includeNames); - }) - .orElse(shape)); - } - - private static Set getSchemeNameIntersection(ProtocolsTrait protocols, Set includeNames) { - Set names = new HashSet<>(protocols.getProtocolNames()); - names.retainAll(includeNames); - return names; - } - - private static Shape updateTrait(Shape shape, ProtocolsTrait trait, Set names) { - ProtocolsTrait.Builder builder = ProtocolsTrait.builder(); - builder.clearProtocols(); - trait.getProtocols().stream() - .filter(protocol -> names.contains(protocol.getName())) - .forEach(builder::addProtocol); - return Shape.shapeToBuilder(shape).addTrait(builder.build()).build(); - } -} diff --git a/smithy-build/src/main/resources/META-INF/services/software.amazon.smithy.build.ProjectionTransformer b/smithy-build/src/main/resources/META-INF/services/software.amazon.smithy.build.ProjectionTransformer index f7cc20c8297..109806d0855 100644 --- a/smithy-build/src/main/resources/META-INF/services/software.amazon.smithy.build.ProjectionTransformer +++ b/smithy-build/src/main/resources/META-INF/services/software.amazon.smithy.build.ProjectionTransformer @@ -3,10 +3,8 @@ software.amazon.smithy.build.transforms.ExcludeShapesByTag software.amazon.smithy.build.transforms.ExcludeTags software.amazon.smithy.build.transforms.ExcludeTraits software.amazon.smithy.build.transforms.ExcludeTraitsByTag -software.amazon.smithy.build.transforms.IncludeAuth software.amazon.smithy.build.transforms.IncludeMetadata software.amazon.smithy.build.transforms.IncludeNamespaces -software.amazon.smithy.build.transforms.IncludeProtocols software.amazon.smithy.build.transforms.IncludeServices software.amazon.smithy.build.transforms.IncludeShapesByTag software.amazon.smithy.build.transforms.IncludeTags diff --git a/smithy-build/src/test/java/software/amazon/smithy/build/transforms/IncludeAuthTest.java b/smithy-build/src/test/java/software/amazon/smithy/build/transforms/IncludeAuthTest.java deleted file mode 100644 index ef7a6247629..00000000000 --- a/smithy-build/src/test/java/software/amazon/smithy/build/transforms/IncludeAuthTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2019 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.build.transforms; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.equalTo; - -import java.util.Collections; -import org.junit.jupiter.api.Test; -import software.amazon.smithy.model.Model; -import software.amazon.smithy.model.shapes.ServiceShape; -import software.amazon.smithy.model.shapes.Shape; -import software.amazon.smithy.model.traits.AuthTrait; -import software.amazon.smithy.model.traits.Protocol; -import software.amazon.smithy.model.traits.ProtocolsTrait; -import software.amazon.smithy.model.transform.ModelTransformer; - -public class IncludeAuthTest { - - @Test - public void filtersUnsupportedAuthSchemes() { - ServiceShape service1 = ServiceShape.builder() - .id("ns.foo#foo") - .version("1") - .addTrait(ProtocolsTrait.builder() - .addProtocol(Protocol.builder().name("foo").addAuth("foo").addAuth("baz").build()) - .build()) - .addTrait(AuthTrait.builder().addValue("foo").addValue("baz").build()) - .build(); - ServiceShape service2 = ServiceShape.builder() - .id("ns.foo#baz") - .version("1") - .build(); - ServiceShape service3 = ServiceShape.builder() - .id("ns.foo#bar") - .version("1") - .addTrait(ProtocolsTrait.builder().addProtocol(Protocol.builder().name("foo").build()).build()) - .build(); - Model model = Model.builder() - .addShapes(service1, service2, service3) - .build(); - Model result = new IncludeAuth() - .createTransformer(Collections.singletonList("foo")) - .apply(ModelTransformer.create(), model); - - Shape updateService1 = result.getShape(service1.getId()).get(); - assertThat(updateService1.getTrait(AuthTrait.class).get().getValues(), contains("foo")); - assertThat(updateService1.getTrait(ProtocolsTrait.class).get().getAllAuthSchemes(), contains("foo")); - assertThat(result.getShape(service2.getId()).get(), equalTo(service2)); - assertThat(result.getShape(service3.getId()).get(), equalTo(service3)); - } -} diff --git a/smithy-build/src/test/java/software/amazon/smithy/build/transforms/IncludeProtocolsTest.java b/smithy-build/src/test/java/software/amazon/smithy/build/transforms/IncludeProtocolsTest.java deleted file mode 100644 index f519efab9ee..00000000000 --- a/smithy-build/src/test/java/software/amazon/smithy/build/transforms/IncludeProtocolsTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2019 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.build.transforms; - -import java.util.Collections; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import software.amazon.smithy.model.Model; -import software.amazon.smithy.model.shapes.ServiceShape; -import software.amazon.smithy.model.traits.Protocol; -import software.amazon.smithy.model.traits.ProtocolsTrait; -import software.amazon.smithy.model.transform.ModelTransformer; -import software.amazon.smithy.utils.ListUtils; - -public class IncludeProtocolsTest { - - @Test - public void filtersUnsupportedProtocols() { - ServiceShape service = ServiceShape.builder() - .version("1") - .addTrait(ProtocolsTrait.builder() - .addProtocol(Protocol.builder().name("foo").build()) - .addProtocol(Protocol.builder().name("qux").build()).build()) - .id("ns.foo#baz") - .build(); - Model model = Model.builder().addShape(service).build(); - Model result = new IncludeProtocols() - .createTransformer(Collections.singletonList("qux")) - .apply(ModelTransformer.create(), model); - ServiceShape shape = result.getShape(service.getId()).get().asServiceShape().get(); - - Assertions.assertEquals(shape.getTrait(ProtocolsTrait.class).get().getProtocolNames(), ListUtils.of("qux")); - } -} diff --git a/smithy-build/src/test/resources/software/amazon/smithy/build/resource-model.json b/smithy-build/src/test/resources/software/amazon/smithy/build/resource-model.json index 783d6327a31..f103cbccfb8 100644 --- a/smithy-build/src/test/resources/software/amazon/smithy/build/resource-model.json +++ b/smithy-build/src/test/resources/software/amazon/smithy/build/resource-model.json @@ -8,17 +8,7 @@ { "target": "ns.foo#MyResource" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "foo" - }, - { - "name": "baz" - } - ] - } + ] }, "ns.foo#MyResource": { "type": "resource", diff --git a/smithy-build/src/test/resources/software/amazon/smithy/build/transforms/tree-shaker.json b/smithy-build/src/test/resources/software/amazon/smithy/build/transforms/tree-shaker.json index b8f7feedf61..c07fc17887c 100644 --- a/smithy-build/src/test/resources/software/amazon/smithy/build/transforms/tree-shaker.json +++ b/smithy-build/src/test/resources/software/amazon/smithy/build/transforms/tree-shaker.json @@ -3,14 +3,7 @@ "shapes": { "ns.foo#MyService": { "type": "service", - "version": "2017-01-19", - "traits": { - "smithy.api#protocols": [ - { - "name": "foo" - } - ] - } + "version": "2017-01-19" }, "ns.foo#Exclude1": { "type": "string" diff --git a/smithy-build/src/test/resources/software/amazon/smithy/build/transforms/tree-shaking-traits.json b/smithy-build/src/test/resources/software/amazon/smithy/build/transforms/tree-shaking-traits.json index d934d2c2df3..10476776dbf 100644 --- a/smithy-build/src/test/resources/software/amazon/smithy/build/transforms/tree-shaking-traits.json +++ b/smithy-build/src/test/resources/software/amazon/smithy/build/transforms/tree-shaking-traits.json @@ -38,14 +38,7 @@ { "target": "ns.foo#MyOperation" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "foo" - } - ] - } + ] }, "ns.foo#MyOperation": { "type": "operation", diff --git a/smithy-diff/src/main/java/software/amazon/smithy/diff/evaluators/RemovedProtocolAuthentication.java b/smithy-diff/src/main/java/software/amazon/smithy/diff/evaluators/RemovedProtocolAuthentication.java deleted file mode 100644 index 0eec997e896..00000000000 --- a/smithy-diff/src/main/java/software/amazon/smithy/diff/evaluators/RemovedProtocolAuthentication.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2019 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.diff.evaluators; - -import java.util.Collections; -import java.util.List; -import software.amazon.smithy.diff.Differences; -import software.amazon.smithy.model.validation.ValidationEvent; - -/** - * TODO: Implement evaluator to find removed authentication from protocols. - */ -public class RemovedProtocolAuthentication extends AbstractDiffEvaluator { - @Override - public List evaluate(Differences differences) { - return Collections.emptyList(); - } -} diff --git a/smithy-diff/src/main/resources/META-INF/services/software.amazon.smithy.diff.DiffEvaluator b/smithy-diff/src/main/resources/META-INF/services/software.amazon.smithy.diff.DiffEvaluator index 3faaec2fc88..9589b43ac12 100644 --- a/smithy-diff/src/main/resources/META-INF/services/software.amazon.smithy.diff.DiffEvaluator +++ b/smithy-diff/src/main/resources/META-INF/services/software.amazon.smithy.diff.DiffEvaluator @@ -20,6 +20,5 @@ software.amazon.smithy.diff.evaluators.RemovedMetadata software.amazon.smithy.diff.evaluators.RemovedOperationError software.amazon.smithy.diff.evaluators.RemovedOperationInput software.amazon.smithy.diff.evaluators.RemovedOperationOutput -software.amazon.smithy.diff.evaluators.RemovedProtocolAuthentication software.amazon.smithy.diff.evaluators.RemovedShape software.amazon.smithy.diff.evaluators.RemovedTraitDefinition diff --git a/smithy-jsonschema/src/test/resources/software/amazon/smithy/jsonschema/test-service.json b/smithy-jsonschema/src/test/resources/software/amazon/smithy/jsonschema/test-service.json index 1dd446c4f07..89c8ddd6ffa 100644 --- a/smithy-jsonschema/src/test/resources/software/amazon/smithy/jsonschema/test-service.json +++ b/smithy-jsonschema/src/test/resources/software/amazon/smithy/jsonschema/test-service.json @@ -11,14 +11,7 @@ { "target": "example.rest#PutPayload" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "smithy.example" - } - ] - } + ] }, "example.rest#PutPayload": { "type": "operation", diff --git a/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedAuthSchemesValidator.java b/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedAuthSchemesValidator.java deleted file mode 100644 index e423c1e2d19..00000000000 --- a/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedAuthSchemesValidator.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2019 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.linters; - -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import software.amazon.smithy.model.Model; -import software.amazon.smithy.model.node.Node; -import software.amazon.smithy.model.shapes.ServiceShape; -import software.amazon.smithy.model.traits.AuthTrait; -import software.amazon.smithy.model.traits.Trait; -import software.amazon.smithy.model.validation.AbstractValidator; -import software.amazon.smithy.model.validation.ValidationEvent; -import software.amazon.smithy.model.validation.ValidatorService; -import software.amazon.smithy.utils.ListUtils; - -/** - * Emits a validation event if any service auth schemes match those listed - * in the configuration as deprecated. - * - *

This validator accepts the following optional configuration options: - * - *

    - *
  • schemes: ([string]) A list of deprecated auth scheme names. - *
  • reason: (string) Provides a plain text message for a deprecated auth scheme. - *
- */ -public final class DeprecatedAuthSchemesValidator extends AbstractValidator { - private static final List ATTRIBUTES = ListUtils.of("schemes", "reason"); - - private final List schemes; - private final String reason; - - private DeprecatedAuthSchemesValidator(List schemes, String reason) { - this.schemes = schemes; - this.reason = reason; - } - - public static final class Provider extends ValidatorService.Provider { - public Provider() { - super(DeprecatedAuthSchemesValidator.class, configuration -> { - configuration.warnIfAdditionalProperties(ATTRIBUTES); - List schemes = Node.loadArrayOfString("schemes", configuration.expectMember("schemes")); - String reason = configuration.getStringMemberOrDefault("reason", ""); - return new DeprecatedAuthSchemesValidator(schemes, reason); - }); - } - } - - @Override - public List validate(Model model) { - return model.shapes(ServiceShape.class) - .flatMap(shape -> Trait.flatMapStream(shape, AuthTrait.class)) - .flatMap(pair -> validateAuthSchemes(pair.getLeft(), pair.getRight())) - .collect(Collectors.toList()); - } - - private Stream validateAuthSchemes(ServiceShape service, AuthTrait trait) { - return trait.getValues().stream() - .filter(schemes::contains) - .map(scheme -> warning(service, trait.getSourceLocation(), String.format("The %s auth scheme is " - + "deprecated. %s", scheme, reason))); - } -} diff --git a/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedProtocolsValidator.java b/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedProtocolsValidator.java deleted file mode 100644 index 27c2972fb05..00000000000 --- a/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedProtocolsValidator.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2019 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.linters; - -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import software.amazon.smithy.model.Model; -import software.amazon.smithy.model.node.Node; -import software.amazon.smithy.model.shapes.ServiceShape; -import software.amazon.smithy.model.traits.ProtocolsTrait; -import software.amazon.smithy.model.traits.Trait; -import software.amazon.smithy.model.validation.AbstractValidator; -import software.amazon.smithy.model.validation.ValidationEvent; -import software.amazon.smithy.model.validation.ValidatorService; -import software.amazon.smithy.utils.ListUtils; - -/** - * Emits a validation event if any service protocols match those listed - * in the configuration as deprecated. - * - *

This validator accepts the following optional configuration options: - * - *

    - *
  • protocols: ([string]) A list of deprecated protocol names. - *
  • reason: (string) Provides a plain text message for a deprecated protocol. - *
- */ -public final class DeprecatedProtocolsValidator extends AbstractValidator { - private static final List ATTRIBUTES = ListUtils.of("protocols", "reason"); - - private final List protocols; - private final String reason; - - private DeprecatedProtocolsValidator(List protocols, String reason) { - this.protocols = protocols; - this.reason = reason; - } - - public static final class Provider extends ValidatorService.Provider { - public Provider() { - super(DeprecatedProtocolsValidator.class, configuration -> { - configuration.warnIfAdditionalProperties(ATTRIBUTES); - List protocols = Node.loadArrayOfString("protocols", configuration.expectMember("protocols")); - String reason = configuration.getStringMemberOrDefault("reason", ""); - return new DeprecatedProtocolsValidator(protocols, reason); - }); - } - } - - @Override - public List validate(Model model) { - return model.shapes(ServiceShape.class) - .flatMap(shape -> Trait.flatMapStream(shape, ProtocolsTrait.class)) - .flatMap(pair -> validateProtocols(pair.getLeft(), pair.getRight())) - .collect(Collectors.toList()); - } - - private Stream validateProtocols(ServiceShape service, ProtocolsTrait trait) { - return trait.getProtocolNames().stream() - .filter(protocols::contains) - .map(protocol -> warning(service, trait.getSourceLocation(), String.format("The %s protocol is " - + "deprecated. %s", protocol, reason))); - } -} diff --git a/smithy-linters/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.ValidatorService b/smithy-linters/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.ValidatorService index c15ce02fde2..6d5014d1571 100644 --- a/smithy-linters/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.ValidatorService +++ b/smithy-linters/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.ValidatorService @@ -1,7 +1,5 @@ software.amazon.smithy.linters.AbbreviationNameValidator$Provider software.amazon.smithy.linters.CamelCaseValidator$Provider -software.amazon.smithy.linters.DeprecatedAuthSchemesValidator$Provider -software.amazon.smithy.linters.DeprecatedProtocolsValidator$Provider software.amazon.smithy.linters.EmitEachSelectorValidator$Provider software.amazon.smithy.linters.EmitNoneSelectorValidator$Provider software.amazon.smithy.linters.InputOutputStructureReuseValidator$Provider diff --git a/smithy-linters/src/test/java/software/amazon/smithy/linters/ErrorsFileTest.java b/smithy-linters/src/test/java/software/amazon/smithy/linters/ErrorsFileTest.java index 9ad0003eaf5..18e825dab07 100644 --- a/smithy-linters/src/test/java/software/amazon/smithy/linters/ErrorsFileTest.java +++ b/smithy-linters/src/test/java/software/amazon/smithy/linters/ErrorsFileTest.java @@ -15,7 +15,11 @@ package software.amazon.smithy.linters; -import org.junit.jupiter.api.Test; +import java.util.concurrent.Callable; +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import software.amazon.smithy.model.validation.testrunner.SmithyTestCase; import software.amazon.smithy.model.validation.testrunner.SmithyTestSuite; /** @@ -23,10 +27,13 @@ * that the corresponding .errors file errors match the validation events of loading the file. */ public class ErrorsFileTest { - @Test - public void testRunner() { - System.out.println(SmithyTestSuite.runner() - .addTestCasesFromUrl(ErrorsFileTest.class.getResource("errorfiles")) - .run()); + @ParameterizedTest(name = "{0}") + @MethodSource("source") + public void testRunner(String filename, Callable callable) throws Exception { + callable.call(); + } + + public static Stream source() { + return SmithyTestSuite.defaultParameterizedTestSource(ErrorsFileTest.class); } } diff --git a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/contains-reserved-words-validator.json b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/contains-reserved-words-validator.json index dced72469e7..dfff5f332e8 100644 --- a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/contains-reserved-words-validator.json +++ b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/contains-reserved-words-validator.json @@ -51,14 +51,7 @@ { "target": "ns.foo#OperationA" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "foo" - } - ] - } + ] }, "ns.foo#MyResource": { "type": "resource", diff --git a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-auth-schemes-validator.errors b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-auth-schemes-validator.errors deleted file mode 100644 index b7c3bd221ba..00000000000 --- a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-auth-schemes-validator.errors +++ /dev/null @@ -1,3 +0,0 @@ -[WARNING] ns.foo#MyService: The bar auth scheme is deprecated. Because it's not a good idea. | Flawed Schemes -[WARNING] ns.foo#MyService: The baz auth scheme is deprecated. Because it's not a good idea. | Flawed Schemes -[WARNING] ns.foo#MyService: The qux auth scheme is deprecated. Because we said so. | Slow Schemes diff --git a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-auth-schemes-validator.json b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-auth-schemes-validator.json deleted file mode 100644 index 0ca9bd2182a..00000000000 --- a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-auth-schemes-validator.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "smithy": "0.5.0", - "shapes": { - "ns.foo#MyService": { - "type": "service", - "version": "2017-01-17", - "traits": { - "smithy.api#protocols": [ - { - "name": "foo", - "auth": [ - "bar", - "baz", - "qux", - "cow" - ] - } - ], - "smithy.api#auth": [ - "bar", - "baz", - "qux", - "cow" - ] - } - } - }, - "metadata": { - "validators": [ - { - "name": "DeprecatedAuthSchemes", - "id": "Slow Schemes", - "configuration": { - "schemes": [ - "qux" - ], - "reason": "Because we said so." - } - }, - { - "name": "DeprecatedAuthSchemes", - "id": "Flawed Schemes", - "configuration": { - "schemes": [ - "bar", - "baz" - ], - "reason": "Because it's not a good idea." - } - } - ] - } -} diff --git a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-protocols-validator.errors b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-protocols-validator.errors deleted file mode 100644 index a38bf2f336a..00000000000 --- a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-protocols-validator.errors +++ /dev/null @@ -1,3 +0,0 @@ -[WARNING] ns.foo#MyService: The bar protocol is deprecated. Because it's not a good idea. | Flawed Protocols -[WARNING] ns.foo#MyService: The baz protocol is deprecated. Because it's not a good idea. | Flawed Protocols -[WARNING] ns.foo#MyService: The foo protocol is deprecated. Because we said so. | Old Protocols diff --git a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-protocols-validator.json b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-protocols-validator.json deleted file mode 100644 index aba9ba69032..00000000000 --- a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-protocols-validator.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "smithy": "0.5.0", - "shapes": { - "ns.foo#MyService": { - "type": "service", - "version": "2017-01-17", - "traits": { - "smithy.api#protocols": [ - { - "name": "foo" - }, - { - "name": "bar" - }, - { - "name": "baz" - }, - { - "name": "qux" - } - ] - } - } - }, - "metadata": { - "validators": [ - { - "name": "DeprecatedProtocols", - "id": "Old Protocols", - "configuration": { - "protocols": [ - "foo" - ], - "reason": "Because we said so." - } - }, - { - "name": "DeprecatedProtocols", - "id": "Flawed Protocols", - "configuration": { - "protocols": [ - "bar", - "baz" - ], - "reason": "Because it's not a good idea." - } - } - ] - } -} diff --git a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/emit-each-selector-validator.json b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/emit-each-selector-validator.json index 401df736a11..138550476b8 100644 --- a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/emit-each-selector-validator.json +++ b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/emit-each-selector-validator.json @@ -49,14 +49,7 @@ { "target": "ns.foo#OperationA" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "foo" - } - ] - } + ] }, "ns.foo#MyResource": { "type": "resource", diff --git a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/input-output-structure-reuse.json b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/input-output-structure-reuse.json index 37fad59ac37..7043302c89c 100644 --- a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/input-output-structure-reuse.json +++ b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/input-output-structure-reuse.json @@ -23,14 +23,7 @@ { "target": "ns.foo#F" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "foo" - } - ] - } + ] }, "ns.foo#A": { "type": "operation", diff --git a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/missing-documentation-selector-test.json b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/missing-documentation-selector-test.json index 48e1f04ec28..c61efed5f35 100644 --- a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/missing-documentation-selector-test.json +++ b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/missing-documentation-selector-test.json @@ -3,14 +3,7 @@ "shapes": { "ns.foo#MyService": { "type": "service", - "version": "2017-01-17", - "traits": { - "smithy.api#protocols": [ - { - "name": "foo" - } - ] - } + "version": "2017-01-17" }, "ns.foo#SomeList": { "type": "list", diff --git a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/unreferenced-shape-validator.json b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/unreferenced-shape-validator.json index 3dcd9c52e03..32a3f2330ff 100644 --- a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/unreferenced-shape-validator.json +++ b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/unreferenced-shape-validator.json @@ -8,14 +8,7 @@ { "target": "ns.foo#ReferencedOperation" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "foo" - } - ] - } + ] }, "ns.foo#ReferencedOperation": { "type": "operation", diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/knowledge/AuthIndex.java b/smithy-model/src/main/java/software/amazon/smithy/model/knowledge/AuthIndex.java deleted file mode 100644 index fed721dbf7b..00000000000 --- a/smithy-model/src/main/java/software/amazon/smithy/model/knowledge/AuthIndex.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2019 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.model.knowledge; - -import java.util.ArrayList; -import java.util.List; -import software.amazon.smithy.model.Model; -import software.amazon.smithy.model.shapes.ToShapeId; -import software.amazon.smithy.model.traits.AuthTrait; -import software.amazon.smithy.model.traits.Protocol; -import software.amazon.smithy.model.traits.ProtocolsTrait; -import software.amazon.smithy.utils.ListUtils; -import software.amazon.smithy.utils.OptionalUtils; - -/** - * Computes the effective authentication schemes of an operation - * for specific protocols. - */ -public final class AuthIndex implements KnowledgeIndex { - private final Model model; - - /** - * @param model Model to compute the index from. - */ - public AuthIndex(Model model) { - this.model = model; - } - - /** - * Gets the default authentication schemes supported by a service or - * the entire list of all auth schemes if no auth trait is set on the - * service shape in priority order. - * - * @param service Service to check. - * @return Returns the list of auth schemes or an empty list if not found. - */ - public List getDefaultServiceSchemes(ToShapeId service) { - return model.getShape(service.toShapeId()) - .flatMap(serviceShape -> OptionalUtils.or(serviceShape.getTrait(AuthTrait.class) - .map(AuthTrait::getValues), - () -> serviceShape.getTrait(ProtocolsTrait.class) - .map(ProtocolsTrait::getAllAuthSchemes) - .map(ListUtils::copyOf))) - .orElse(ListUtils.of()); - } - - /** - * Gets the effective authentication schemes of an operation bound - * to a service in priority order. - * - *

The computed result is based on either the presence of the - * {@code auth} trait applied to the operation, the {@code auth} trait - * applied to the service it's bound to, or the entire list of - * {@code auth} schemes supported by the protocols trait of the service. - * - *

This method will return an empty List in the case of invalid or - * missing shapes. - * - * @param service Service that the operation is bound to. - * @param operation Operation to check. - * @return Returns the computed authentication schemes. - */ - public List getOperationSchemes(ToShapeId service, ToShapeId operation) { - return model.getShape(operation.toShapeId()) - // Get the auth trait from the operation or the service. - .map(shape -> shape.getTrait(AuthTrait.class) - .map(AuthTrait::getValues) - .orElseGet(() -> getDefaultServiceSchemes(service))) - .orElse(ListUtils.of()); - } - - /** - * Gets the effective authentication schemes of an operation bound - * to a service that are compatible with a specific protocol of the - * service in priority order. - * - *

The result is ordered by either the effective auth trait of the - * operation or the list of protocols on the service. - * - * @param service Service that the operation is bound to. - * @param operation Operation to check. - * @param protocolName Protocol to limit the result. - * @return Returns the computed authentication schemes compatible with the protocol. - */ - public List getOperationSchemes(ToShapeId service, ToShapeId operation, String protocolName) { - // Get the authentication schemes of the protocol. - List protocolSchemes = model.getShape(service.toShapeId()) - .flatMap(serviceShape -> serviceShape.getTrait(ProtocolsTrait.class)) - .flatMap(protocolsTrait -> protocolsTrait.getProtocol(protocolName)) - .map(Protocol::getAuth) - .orElse(ListUtils.of()); - // Get the schemes of the operation or service. - List schemes = getOperationSchemes(service, operation); - return schemes.isEmpty() - // Use the protocol schemes if the operation/service define no schemes. - ? protocolSchemes - // Return the intersection, preferring the sort order of the found auth trait. - : intersection(schemes, protocolSchemes); - } - - private static List intersection(List left, List right) { - List leftCopy = new ArrayList<>(left); - - // The "none" scheme is special as it doesn't have to be explicitly - // defined in the protocols list. - if (left.contains(ProtocolsTrait.NONE_AUTH) && !right.contains(ProtocolsTrait.NONE_AUTH)) { - List copiedRight = new ArrayList<>(right); - copiedRight.add(ProtocolsTrait.NONE_AUTH); - leftCopy.retainAll(copiedRight); - } else { - leftCopy.retainAll(right); - } - - return leftCopy; - } -} diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/knowledge/ServiceIndex.java b/smithy-model/src/main/java/software/amazon/smithy/model/knowledge/ServiceIndex.java new file mode 100644 index 00000000000..f4a3ba62a2e --- /dev/null +++ b/smithy-model/src/main/java/software/amazon/smithy/model/knowledge/ServiceIndex.java @@ -0,0 +1,207 @@ +/* + * Copyright 2019 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.model.knowledge; + +import java.lang.ref.WeakReference; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.TreeMap; +import java.util.function.Function; +import java.util.stream.Collectors; +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.shapes.Shape; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.shapes.ToShapeId; +import software.amazon.smithy.model.traits.AuthDefinitionTrait; +import software.amazon.smithy.model.traits.AuthTrait; +import software.amazon.smithy.model.traits.ProtocolDefinitionTrait; +import software.amazon.smithy.model.traits.Trait; + +/** + * An index that resolves service protocols and auth schemes. + * + *

This index can be used to get all of the protocol traits applied to + * a service, to get all of the auth defining traits applied to a service, + * to get the effective authentication schemes of a service, and to get the + * effective authentication schemes of an operation bound within the + * closure of a service. + */ +public final class ServiceIndex implements KnowledgeIndex { + + private final WeakReference model; + private final Set protocolTraits; + private final Set authTraits; + + public ServiceIndex(Model model) { + this.model = new WeakReference<>(model); + + protocolTraits = model.shapes() + .filter(shape -> shape.hasTrait(ProtocolDefinitionTrait.class)) + .map(Shape::getId) + .collect(Collectors.toSet()); + + authTraits = model.shapes() + .filter(shape -> shape.hasTrait(AuthDefinitionTrait.class)) + .map(Shape::getId) + .collect(Collectors.toSet()); + } + + /** + * Get all protocol traits attached to a service. + * + *

A protocol trait is a trait that is marked with + * the {@code smithy.api#protocolDefinition} trait. + * + *

An empty map is returned if {@code service} cannot be found in the + * model or is not a service shape. + * + * @param service Service to get the protocols of. + * @return Returns a map of the protocol trait ID to the trait. + */ + public Map getProtocols(ToShapeId service) { + return getTraitMapInSet(service, protocolTraits); + } + + private Map getTraitMapInSet(ToShapeId service, Set haystack) { + return getModel() + .getShape(service.toShapeId()) + .flatMap(Shape::asServiceShape) + .>map(shape -> shape.getAllTraits().values().stream() + .filter(trait -> haystack.contains(trait.toShapeId())) + .collect(Collectors.toMap(Trait::toShapeId, Function.identity(), (a, b) -> b, TreeMap::new))) + .orElse(Collections.emptyMap()); + } + + private Model getModel() { + return Objects.requireNonNull(model.get(), "The dereferenced WeakReference is null"); + } + + /** + * Get all auth defining traits attached to a service or operation. + * + *

An auth defining trait is a trait that is marked with + * the {@code smithy.api#authDefinition} trait. + * + *

An empty map is returned if {@code id} cannot be found in the + * model or is not a service shape. + * + * @param service Service to get the auth schemes of. + * @return Returns a map of the trait shape ID to the auth trait itself. + */ + public Map getAuthSchemes(ToShapeId service) { + return getTraitMapInSet(service, authTraits); + } + + /** + * Gets a list of effective authentication schemes applied to a service. + * + *

An effective authentication scheme is derived from the + * {@code smithy.api#auth} trait and the auth defining traits applied + * to a service. If the service has the {@code smithy.api#auth} trait, + * then a map is returned that contains the traits applied to the service + * that matches the values in the auth trait. If no auth trait is applied, + * then all of the auth defining traits on the service are returned. + * + *

The returned map is provided in the same order as the values in the + * {@code auth} trait if an auth trait is present, otherwise the result + * is returned in an undefined order. + * + *

An empty map is returned if {@code service} cannot be found in the + * model or is not a service shape. + * + * @param service Service to get the effective authentication schemes of. + * @return Returns a map of the trait shape ID to the auth trait itself. + */ + public Map getEffectiveAuthSchemes(ToShapeId service) { + return getModel() + .getShape(service.toShapeId()) + .flatMap(Shape::asServiceShape) + .map(shape -> { + Map result = getAuthTraitValues(shape, shape); + if (result == null) { + result = new TreeMap<>(); + for (Map.Entry traitEntry : shape.getAllTraits().entrySet()) { + if (authTraits.contains(traitEntry.getKey())) { + result.put(traitEntry.getKey(), traitEntry.getValue()); + } + } + } + return result; + }) + .orElse(Collections.emptyMap()); + } + + /** + * Gets a list of effective authentication schemes applied to an operation + * bound within a service. + * + *

If the given operation defines that {@code smithy.api#auth} trait, + * then a map is returned that consists of the traits applied to the + * service that match the values of the {@code smithy.api#auth} trait. If + * the operation does not define an {@code smithy.api#auth} trait, then + * the effective auth schemes of the service is returned (that is, the + * return value of {@link #getEffectiveAuthSchemes(ToShapeId)}). + * + *

The returned map is provided in the same order as the values in the + * {@code auth} trait if an auth trait is present, otherwise the result + * is returned in an undefined order. + * + *

An empty map is returned if {@code service} shape cannot be found + * in the model or is not a service shape. An empty map is returned if + * {@code operation} cannot be found in the model or is not an operation + * shape. + * + * @param service Service the operation is within. + * @param operation Operation to get the effective authentication schemes of. + * @return Returns a map of the trait shape ID to the auth trait itself. + */ + public Map getEffectiveAuthSchemes(ToShapeId service, ToShapeId operation) { + Shape serviceShape = getModel() + .getShape(service.toShapeId()) + .flatMap(Shape::asServiceShape) + .orElse(null); + + if (serviceShape == null) { + return Collections.emptyMap(); + } + + return getModel() + .getShape(operation.toShapeId()) + .flatMap(Shape::asOperationShape) + .map(operationShape -> { + Map result = getAuthTraitValues(serviceShape, operationShape); + return result != null ? result : getEffectiveAuthSchemes(service); + }) + .orElse(Collections.emptyMap()); + } + + private Map getAuthTraitValues(Shape service, Shape subject) { + if (!subject.hasTrait(AuthTrait.class)) { + return null; + } + + AuthTrait authTrait = subject.expectTrait(AuthTrait.class); + Map result = new LinkedHashMap<>(); + for (ShapeId value : authTrait.getValues()) { + service.findTrait(value).ifPresent(trait -> result.put(value, trait)); + } + + return result; + } +} diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/loader/Prelude.java b/smithy-model/src/main/java/software/amazon/smithy/model/loader/Prelude.java index 96b81c4ba40..81afe18ec00 100644 --- a/smithy-model/src/main/java/software/amazon/smithy/model/loader/Prelude.java +++ b/smithy-model/src/main/java/software/amazon/smithy/model/loader/Prelude.java @@ -36,6 +36,7 @@ import software.amazon.smithy.model.shapes.StringShape; import software.amazon.smithy.model.shapes.TimestampShape; import software.amazon.smithy.model.shapes.ToShapeId; +import software.amazon.smithy.model.traits.AuthDefinitionTrait; import software.amazon.smithy.model.traits.AuthTrait; import software.amazon.smithy.model.traits.BoxTrait; import software.amazon.smithy.model.traits.CorsTrait; @@ -50,6 +51,10 @@ import software.amazon.smithy.model.traits.ExamplesTrait; import software.amazon.smithy.model.traits.ExternalDocumentationTrait; import software.amazon.smithy.model.traits.HostLabelTrait; +import software.amazon.smithy.model.traits.HttpApiKeyAuthTrait; +import software.amazon.smithy.model.traits.HttpBasicAuthTrait; +import software.amazon.smithy.model.traits.HttpBearerAuthTrait; +import software.amazon.smithy.model.traits.HttpDigestAuthTrait; import software.amazon.smithy.model.traits.HttpErrorTrait; import software.amazon.smithy.model.traits.HttpHeaderTrait; import software.amazon.smithy.model.traits.HttpLabelTrait; @@ -63,10 +68,11 @@ import software.amazon.smithy.model.traits.JsonNameTrait; import software.amazon.smithy.model.traits.LengthTrait; import software.amazon.smithy.model.traits.MediaTypeTrait; +import software.amazon.smithy.model.traits.OptionalAuthTrait; import software.amazon.smithy.model.traits.PaginatedTrait; import software.amazon.smithy.model.traits.PatternTrait; import software.amazon.smithy.model.traits.PrivateTrait; -import software.amazon.smithy.model.traits.ProtocolsTrait; +import software.amazon.smithy.model.traits.ProtocolDefinitionTrait; import software.amazon.smithy.model.traits.RangeTrait; import software.amazon.smithy.model.traits.ReadonlyTrait; import software.amazon.smithy.model.traits.ReferencesTrait; @@ -166,7 +172,13 @@ public final class Prelude { PaginatedTrait.ID, PatternTrait.ID, PrivateTrait.ID, - ProtocolsTrait.ID, + ProtocolDefinitionTrait.ID, + AuthDefinitionTrait.ID, + HttpApiKeyAuthTrait.ID, + HttpBasicAuthTrait.ID, + HttpDigestAuthTrait.ID, + HttpBearerAuthTrait.ID, + OptionalAuthTrait.ID, RangeTrait.ID, ReadonlyTrait.ID, ReferencesTrait.ID, diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/traits/AuthDefinitionTrait.java b/smithy-model/src/main/java/software/amazon/smithy/model/traits/AuthDefinitionTrait.java new file mode 100644 index 00000000000..714029a703c --- /dev/null +++ b/smithy-model/src/main/java/software/amazon/smithy/model/traits/AuthDefinitionTrait.java @@ -0,0 +1,41 @@ +/* + * Copyright 2019 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.model.traits; + +import software.amazon.smithy.model.SourceLocation; +import software.amazon.smithy.model.shapes.ShapeId; + +/** + * This trait is attached to another trait to define an auth scheme. + */ +public final class AuthDefinitionTrait extends BooleanTrait { + + public static final ShapeId ID = ShapeId.from("smithy.api#authDefinition"); + + public AuthDefinitionTrait(SourceLocation sourceLocation) { + super(ID, sourceLocation); + } + + public AuthDefinitionTrait() { + this(SourceLocation.NONE); + } + + public static final class Provider extends BooleanTrait.Provider { + public Provider() { + super(ID, AuthDefinitionTrait::new); + } + } +} diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/traits/AuthTrait.java b/smithy-model/src/main/java/software/amazon/smithy/model/traits/AuthTrait.java index eb38113806e..3e755b02f33 100644 --- a/smithy-model/src/main/java/software/amazon/smithy/model/traits/AuthTrait.java +++ b/smithy-model/src/main/java/software/amazon/smithy/model/traits/AuthTrait.java @@ -15,46 +15,61 @@ package software.amazon.smithy.model.traits; +import java.util.ArrayList; import java.util.List; import software.amazon.smithy.model.FromSourceLocation; +import software.amazon.smithy.model.SourceLocation; +import software.amazon.smithy.model.node.ArrayNode; +import software.amazon.smithy.model.node.Node; +import software.amazon.smithy.model.node.StringNode; import software.amazon.smithy.model.shapes.ShapeId; -import software.amazon.smithy.utils.ToSmithyBuilder; +import software.amazon.smithy.utils.ListUtils; /** - * Represents the Smithy {@code auth} trait, used to specify the auth - * schemes supported by default for operations bound to a service. + * Specifies the auth schemes supported by default for operations + * bound to a service. */ -public final class AuthTrait extends StringListTrait implements ToSmithyBuilder { +public final class AuthTrait extends AbstractTrait { + public static final ShapeId ID = ShapeId.from("smithy.api#auth"); - private AuthTrait(List values, FromSourceLocation sourceLocation) { - super(ID, values, sourceLocation); - } + private final List values; - public static final class Provider extends StringListTrait.Provider { - public Provider() { - super(ID, AuthTrait::new); - } - } - - @Override - public Builder toBuilder() { - return builder().values(getValues()); + public AuthTrait(List values, FromSourceLocation sourceLocation) { + super(ID, sourceLocation); + this.values = ListUtils.copyOf(values); } - public static Builder builder() { - return new Builder(); + public AuthTrait(List values) { + this(values, SourceLocation.NONE); } /** - * Builds an {@link AuthTrait}. + * Gets the auth scheme trait values. + * + * @return Returns the supported auth schemes. */ - public static final class Builder extends StringListTrait.Builder { - private Builder() {} + public List getValues() { + return values; + } + + public static final class Provider extends AbstractTrait.Provider { + public Provider() { + super(ID); + } @Override - public AuthTrait build() { - return new AuthTrait(getValues(), getSourceLocation()); + public Trait createTrait(ShapeId target, Node value) { + List values = new ArrayList<>(); + for (StringNode node : value.expectArrayNode().getElementsAs(StringNode.class)) { + values.add(node.expectShapeId()); + } + return new AuthTrait(values, value.getSourceLocation()); } } + + @Override + protected Node createNode() { + return getValues().stream().map(ShapeId::toString).map(Node::from).collect(ArrayNode.collect()); + } } diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java b/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java new file mode 100644 index 00000000000..e32e616f87b --- /dev/null +++ b/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java @@ -0,0 +1,107 @@ +/* + * Copyright 2019 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.model.traits; + +import java.util.Locale; +import software.amazon.smithy.model.node.Node; +import software.amazon.smithy.model.node.ObjectNode; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.utils.SmithyBuilder; +import software.amazon.smithy.utils.ToSmithyBuilder; + +/** + * An HTTP-specific authentication scheme that sends an arbitrary + * API key in a header or query string parameter. + */ +public final class HttpApiKeyAuthTrait extends BooleanTrait implements ToSmithyBuilder { + + public static final ShapeId ID = ShapeId.from("smithy.api#httpApiKeyAuth"); + + private final String name; + private final Location in; + + private HttpApiKeyAuthTrait(Builder builder) { + super(ID, builder.getSourceLocation()); + name = SmithyBuilder.requiredState("name", builder.name); + in = SmithyBuilder.requiredState("in", builder.in); + } + + public String getName() { + return name; + } + + public Location getIn() { + return in; + } + + @Override + public Builder toBuilder() { + return builder() + .sourceLocation(getSourceLocation()) + .name(getName()) + .in(getIn()); + } + + public static Builder builder() { + return new Builder(); + } + + public enum Location { + HEADER, QUERY; + + @Override + public String toString() { + return super.toString().toLowerCase(Locale.ENGLISH); + } + } + + public static final class Provider extends AbstractTrait.Provider { + public Provider() { + super(ID); + } + + @Override + public Trait createTrait(ShapeId target, Node value) { + ObjectNode objectNode = value.expectObjectNode(); + Builder builder = builder().sourceLocation(value.getSourceLocation()); + builder.name(objectNode.expectStringMember("name").getValue()); + builder.in(Location.valueOf(objectNode.expectStringMember("in").expectOneOf("header", "query"))); + return builder.build(); + } + } + + public static final class Builder extends AbstractTraitBuilder { + private String name; + private Location in; + + private Builder() {} + + @Override + public HttpApiKeyAuthTrait build() { + return new HttpApiKeyAuthTrait(this); + } + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder in(Location in) { + this.in = in; + return this; + } + } +} diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpBasicAuthTrait.java b/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpBasicAuthTrait.java new file mode 100644 index 00000000000..6dddef1501c --- /dev/null +++ b/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpBasicAuthTrait.java @@ -0,0 +1,41 @@ +/* + * Copyright 2019 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.model.traits; + +import software.amazon.smithy.model.SourceLocation; +import software.amazon.smithy.model.shapes.ShapeId; + +/** + * An auth scheme trait uses HTTP basic auth. + */ +public final class HttpBasicAuthTrait extends BooleanTrait { + + public static final ShapeId ID = ShapeId.from("smithy.api#httpBasicAuth"); + + public HttpBasicAuthTrait() { + this(SourceLocation.NONE); + } + + public HttpBasicAuthTrait(SourceLocation sourceLocation) { + super(ID, sourceLocation); + } + + public static final class Provider extends BooleanTrait.Provider { + public Provider() { + super(ID, HttpBasicAuthTrait::new); + } + } +} diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpBearerAuthTrait.java b/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpBearerAuthTrait.java new file mode 100644 index 00000000000..2d8c211e5e9 --- /dev/null +++ b/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpBearerAuthTrait.java @@ -0,0 +1,41 @@ +/* + * Copyright 2019 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.model.traits; + +import software.amazon.smithy.model.SourceLocation; +import software.amazon.smithy.model.shapes.ShapeId; + +/** + * An auth scheme trait uses HTTP bearer auth. + */ +public final class HttpBearerAuthTrait extends BooleanTrait { + + public static final ShapeId ID = ShapeId.from("smithy.api#httpBearerAuth"); + + public HttpBearerAuthTrait() { + this(SourceLocation.NONE); + } + + public HttpBearerAuthTrait(SourceLocation sourceLocation) { + super(ID, sourceLocation); + } + + public static final class Provider extends BooleanTrait.Provider { + public Provider() { + super(ID, HttpBearerAuthTrait::new); + } + } +} diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpDigestAuthTrait.java b/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpDigestAuthTrait.java new file mode 100644 index 00000000000..692b45e281d --- /dev/null +++ b/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpDigestAuthTrait.java @@ -0,0 +1,41 @@ +/* + * Copyright 2019 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.model.traits; + +import software.amazon.smithy.model.SourceLocation; +import software.amazon.smithy.model.shapes.ShapeId; + +/** + * An auth scheme trait uses HTTP digest auth. + */ +public final class HttpDigestAuthTrait extends BooleanTrait { + + public static final ShapeId ID = ShapeId.from("smithy.api#httpDigestAuth"); + + public HttpDigestAuthTrait() { + this(SourceLocation.NONE); + } + + public HttpDigestAuthTrait(SourceLocation sourceLocation) { + super(ID, sourceLocation); + } + + public static final class Provider extends BooleanTrait.Provider { + public Provider() { + super(ID, HttpDigestAuthTrait::new); + } + } +} diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/traits/OptionalAuthTrait.java b/smithy-model/src/main/java/software/amazon/smithy/model/traits/OptionalAuthTrait.java new file mode 100644 index 00000000000..68b88882457 --- /dev/null +++ b/smithy-model/src/main/java/software/amazon/smithy/model/traits/OptionalAuthTrait.java @@ -0,0 +1,40 @@ +/* + * Copyright 2019 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.model.traits; + +import software.amazon.smithy.model.SourceLocation; +import software.amazon.smithy.model.shapes.ShapeId; + +/** + * Indicates that an operation / service supports unauthenticated access. + */ +public final class OptionalAuthTrait extends BooleanTrait { + public static final ShapeId ID = ShapeId.from("smithy.api#optionalAuth"); + + public OptionalAuthTrait() { + this(SourceLocation.NONE); + } + + public OptionalAuthTrait(SourceLocation sourceLocation) { + super(ID, sourceLocation); + } + + public static final class Provider extends BooleanTrait.Provider { + public Provider() { + super(ID, OptionalAuthTrait::new); + } + } +} diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/traits/Protocol.java b/smithy-model/src/main/java/software/amazon/smithy/model/traits/Protocol.java deleted file mode 100644 index a08e3dcd560..00000000000 --- a/smithy-model/src/main/java/software/amazon/smithy/model/traits/Protocol.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2019 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.model.traits; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import software.amazon.smithy.model.node.ArrayNode; -import software.amazon.smithy.model.node.Node; -import software.amazon.smithy.model.node.ToNode; -import software.amazon.smithy.utils.ListUtils; -import software.amazon.smithy.utils.SmithyBuilder; -import software.amazon.smithy.utils.Tagged; -import software.amazon.smithy.utils.ToSmithyBuilder; - -/** - * Represents a Smithy protocol. - */ -public final class Protocol implements ToNode, ToSmithyBuilder, Tagged { - private final String name; - private final List auth; - private final List tags; - private Node node; - - private Protocol(Builder builder) { - name = SmithyBuilder.requiredState("name", builder.name); - auth = ListUtils.copyOf(builder.auth); - tags = ListUtils.copyOf(builder.tags); - } - - public static Builder builder() { - return new Builder(); - } - - /** - * Gets the protocol name. - * - * @return Returns the name. - */ - public String getName() { - return name; - } - - /** - * Gets the ordered list of auth schemes supported by the protocol. - * - * @return Returns the auth schemes. - */ - public List getAuth() { - return auth; - } - - @Override - public List getTags() { - return tags; - } - - @Override - public Builder toBuilder() { - Builder builder = builder().name(name); - tags.forEach(builder::addTag); - auth.forEach(builder::addAuth); - return builder; - } - - @Override - public Node toNode() { - if (node == null) { - node = Node.objectNodeBuilder() - .withMember("name", name) - .withOptionalMember("tags", !tags.isEmpty() - ? Optional.of(ArrayNode.fromStrings(tags)) - : Optional.empty()) - .withOptionalMember("auth", !auth.isEmpty() - ? Optional.of(ArrayNode.fromStrings(auth)) - : Optional.empty()) - .build(); - } - - return node; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } else if (!(o instanceof Protocol)) { - return false; - } - - Protocol protocol = (Protocol) o; - return name.equals(protocol.name) - && auth.equals(protocol.auth) - && tags.equals(protocol.tags); - } - - @Override - public int hashCode() { - return Objects.hash(name, auth, tags); - } - - /** - * Protocol builder. - */ - public static final class Builder implements SmithyBuilder { - private String name; - private final List auth = new ArrayList<>(); - private final List tags = new ArrayList<>(); - - @Override - public Protocol build() { - return new Protocol(this); - } - - /** - * Sets the protocol name. - * - * @param name Protocol name. - * @return Returns the builder. - */ - public Builder name(String name) { - this.name = name; - return this; - } - - /** - * Adds an auth scheme to the protocol. - * - * @param value Auth scheme to add. - * @return Returns the builder. - */ - public Builder addAuth(String value) { - auth.add(value); - return this; - } - - /** - * Removes an auth scheme from the protocol. - * - * @param value Auth scheme to remove. - * @return Returns the builder. - */ - public Builder removeAuth(String value) { - auth.remove(value); - return this; - } - - /** - * Removes all auth schemes from the protocol. - * - * @return Returns the builder. - */ - public Builder clearAuth() { - auth.clear(); - return this; - } - - /** - * Adds a tag to the protocol. - * - * @param tag Tag to add. - * @return Returns the builder. - */ - public Builder addTag(String tag) { - tags.add(tag); - return this; - } - - /** - * Removes a tag from the protocol. - * - * @param tag Tag to remove. - * @return Returns the builder. - */ - public Builder removeTag(String tag) { - tags.remove(tag); - return this; - } - - /** - * Removes all tags from the protocol. - * - * @return Returns the builder. - */ - public Builder clearTags() { - tags.clear(); - return this; - } - } -} diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/traits/ProtocolDefinitionTrait.java b/smithy-model/src/main/java/software/amazon/smithy/model/traits/ProtocolDefinitionTrait.java new file mode 100644 index 00000000000..69b666f5190 --- /dev/null +++ b/smithy-model/src/main/java/software/amazon/smithy/model/traits/ProtocolDefinitionTrait.java @@ -0,0 +1,41 @@ +/* + * Copyright 2019 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.model.traits; + +import software.amazon.smithy.model.SourceLocation; +import software.amazon.smithy.model.shapes.ShapeId; + +/** + * A trait that is attached to other traits to define a Smithy protocol. + */ +public final class ProtocolDefinitionTrait extends BooleanTrait { + + public static final ShapeId ID = ShapeId.from("smithy.api#protocolDefinition"); + + public ProtocolDefinitionTrait(SourceLocation sourceLocation) { + super(ID, sourceLocation); + } + + public ProtocolDefinitionTrait() { + this(SourceLocation.NONE); + } + + public static final class Provider extends BooleanTrait.Provider { + public Provider() { + super(ID, ProtocolDefinitionTrait::new); + } + } +} diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/traits/ProtocolsTrait.java b/smithy-model/src/main/java/software/amazon/smithy/model/traits/ProtocolsTrait.java deleted file mode 100644 index 37c41f2d506..00000000000 --- a/smithy-model/src/main/java/software/amazon/smithy/model/traits/ProtocolsTrait.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright 2019 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.model.traits; - -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; -import software.amazon.smithy.model.node.ArrayNode; -import software.amazon.smithy.model.node.Node; -import software.amazon.smithy.model.node.ObjectNode; -import software.amazon.smithy.model.node.StringNode; -import software.amazon.smithy.model.shapes.ShapeId; -import software.amazon.smithy.utils.ListUtils; -import software.amazon.smithy.utils.ToSmithyBuilder; - -/** - * Defines the protocols supported by a service. - */ -public final class ProtocolsTrait extends AbstractTrait implements ToSmithyBuilder { - public static final ShapeId ID = ShapeId.from("smithy.api#protocols"); - - public static final String NONE_AUTH = "none"; - private static final List PROPERTIES = ListUtils.of("name", "auth", "tags"); - - private final List protocols; - - private ProtocolsTrait(Builder builder) { - super(ID, builder.sourceLocation); - this.protocols = ListUtils.copyOf(builder.protocols); - } - - public static final class Provider extends AbstractTrait.Provider { - public Provider() { - super(ID); - } - - @Override - public Trait createTrait(ShapeId target, Node value) { - Builder builder = builder().sourceLocation(value); - - for (ObjectNode protocol : value.expectArrayNode().getElementsAs(ObjectNode.class)) { - protocol.warnIfAdditionalProperties(PROPERTIES); - Protocol.Builder protocolBuilder = Protocol.builder(); - protocolBuilder.name(protocol.expectStringMember("name").getValue()); - protocol.getMember("tags").map(Node::expectArrayNode).ifPresent(tagsNode -> { - tagsNode.getElements().stream() - .map(Node::expectStringNode) - .map(StringNode::getValue) - .forEach(protocolBuilder::addTag); - }); - protocol.getArrayMember("auth").ifPresent(auth -> { - Node.loadArrayOfString("auth", auth).forEach(protocolBuilder::addAuth); - }); - builder.addProtocol(protocolBuilder.build()); - } - - return builder.build(); - } - } - - /** - * Gets the list of protocols. - * - * @return Returns the protocols - */ - public List getProtocols() { - return protocols; - } - - /** - * Gets the list of protocol names. - * - * @return Returns the list of supported protocol names. - */ - public List getProtocolNames() { - return protocols.stream().map(Protocol::getName).collect(Collectors.toList()); - } - - /** - * Gets a protocol by name. - * - * @param name Name of the protocol to get. - * @return Returns the optionally found protocol. - */ - public Optional getProtocol(String name) { - return protocols.stream().filter(p -> p.getName().equals(name)).findFirst(); - } - - /** - * Checks if the trait contains a protocol of the given name. - * - * @param name Name of the protocol to check. - * @return Returns true if the protocol exists for this name. - */ - public boolean hasProtocol(String name) { - return getProtocol(name).isPresent(); - } - - /** - * Gets a set of all the authentication schemes listed in each protocol. - * - *

Iteration over the returned set provides priority order based on the - * order of the protocol followed by the order of the auth entry in a - * protocols list. - * - * @return Returns all supported authentication schemes. - */ - public Set getAllAuthSchemes() { - return protocols.stream() - .flatMap(protocol -> protocol.getAuth().stream()) - .collect(Collectors.toCollection(LinkedHashSet::new)); - } - - @Override - protected Node createNode() { - return protocols.stream().collect(ArrayNode.collect()); - } - - @Override - public Builder toBuilder() { - Builder builder = builder(); - protocols.forEach(builder::addProtocol); - return builder; - } - - /** - * @return Returns an protocols trait builder. - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builds the protocols trait. - */ - public static final class Builder extends AbstractTraitBuilder { - private List protocols = new ArrayList<>(); - - private Builder() {} - - @Override - public ProtocolsTrait build() { - return new ProtocolsTrait(this); - } - - /** - * Adds a protocol to the trait. - * - * @param protocol Protocol to add. - * @return Returns the builder. - */ - public Builder addProtocol(Protocol protocol) { - protocols.add(Objects.requireNonNull(protocol)); - return this; - } - - /** - * Removes a protocol by name from the builder. - * - * @param protocolName Protocol to remove. - * @return Returns the builder. - */ - public Builder removeProtocol(String protocolName) { - protocols.removeIf(p -> p.getName().equals(protocolName)); - return this; - } - - /** - * Clears all protocols from the trait. - * - * @return Returns the builder. - */ - public Builder clearProtocols() { - protocols.clear(); - return this; - } - } -} diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/AuthProtocolsValidator.java b/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/AuthProtocolsValidator.java deleted file mode 100644 index abf8c11d947..00000000000 --- a/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/AuthProtocolsValidator.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2019 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.model.validation.validators; - -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import software.amazon.smithy.model.Model; -import software.amazon.smithy.model.knowledge.TopDownIndex; -import software.amazon.smithy.model.shapes.OperationShape; -import software.amazon.smithy.model.shapes.ServiceShape; -import software.amazon.smithy.model.traits.AuthTrait; -import software.amazon.smithy.model.traits.Protocol; -import software.amazon.smithy.model.traits.ProtocolsTrait; -import software.amazon.smithy.model.validation.AbstractValidator; -import software.amazon.smithy.model.validation.ValidationEvent; -import software.amazon.smithy.utils.OptionalUtils; - -/** - * Validates that each operation in the closure of a service resolves to a - * set of authentication schemes that is compatible with at least 1 - * authentication scheme of each protocol trait protocol listed on the - * service to which it is bound (if the service defines protocols, and - * only for protocols that list explicitly supported authentication schemes). - */ -public final class AuthProtocolsValidator extends AbstractValidator { - @Override - public List validate(Model model) { - TopDownIndex topDownIndex = model.getKnowledge(TopDownIndex.class); - return model.shapes(ServiceShape.class) - .flatMap(service -> validateOperationAgainstProtocols(topDownIndex, service)) - .collect(Collectors.toList()); - } - - private Stream validateOperationAgainstProtocols(TopDownIndex index, ServiceShape service) { - ProtocolsTrait protocolsTrait = service.getTrait(ProtocolsTrait.class).orElse(null); - if (protocolsTrait == null) { - return Stream.empty(); - } - - // Ensure that every operation is valid for this protocol. - return protocolsTrait.getProtocols().stream() - .flatMap(protocol -> index.getContainedOperations(service).stream() - .flatMap(operation -> OptionalUtils.stream( - validateOperationSchemesAgainstProtocols(service, operation, protocol)))); - } - - private Optional validateOperationSchemesAgainstProtocols( - ServiceShape service, - OperationShape operation, - Protocol protocol - ) { - // Either the operation or the service has an "auth" trait. - AuthTrait authTrait = OptionalUtils.or(operation.getTrait(AuthTrait.class), - () -> service.getTrait(AuthTrait.class)).orElse(null); - - // If no auth trait was found, then assume the operation is - // compatible with all auth schemes. - if (authTrait == null) { - return Optional.empty(); - } - - // Check if any of the schemes on the operation or service are also - // supported by the protocol. - List supportedSchemes = protocol.getAuth(); - List values = authTrait.getValues(); - - // Each protocols trait is assumed to support "none". - if (values.contains(ProtocolsTrait.NONE_AUTH) || values.stream().anyMatch(supportedSchemes::contains)) { - return Optional.empty(); - } - - return Optional.of(warning(operation, String.format( - "The `auth` trait resolved for this operation, %s, is not compatible with the `%s` " - + "protocol of the `%s` service: %s", - authTrait.getValues(), protocol.getName(), service.getId(), protocol.getAuth()))); - } -} diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/AuthTraitValidator.java b/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/AuthTraitValidator.java new file mode 100644 index 00000000000..d628ddbb3e8 --- /dev/null +++ b/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/AuthTraitValidator.java @@ -0,0 +1,79 @@ +/* + * Copyright 2019 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.model.validation.validators; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.knowledge.ServiceIndex; +import software.amazon.smithy.model.knowledge.TopDownIndex; +import software.amazon.smithy.model.shapes.OperationShape; +import software.amazon.smithy.model.shapes.ServiceShape; +import software.amazon.smithy.model.shapes.Shape; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.traits.AuthTrait; +import software.amazon.smithy.model.validation.AbstractValidator; +import software.amazon.smithy.model.validation.ValidationEvent; + +/** + * All {@code @auth} trait values referenced from an operation must refer + * to authentication traits applied to service shapes that enclose the + * operation. + */ +public class AuthTraitValidator extends AbstractValidator { + @Override + public List validate(Model model) { + List events = new ArrayList<>(); + model.shapes(ServiceShape.class).forEach(service -> validateService(model, service, events)); + return events; + } + + private void validateService(Model model, ServiceShape service, List events) { + ServiceIndex serviceIndex = model.getKnowledge(ServiceIndex.class); + Set serviceAuth = serviceIndex.getAuthSchemes(service).keySet(); + TopDownIndex topDownIndex = model.getKnowledge(TopDownIndex.class); + + // Validate the service's @auth trait. + validateShape(serviceAuth, service, service, events); + + // Validate each contained operation's @auth trait. + for (OperationShape operation : topDownIndex.getContainedOperations(service)) { + validateShape(serviceAuth, service, operation, events); + } + } + + private void validateShape( + Set serviceAuth, + ServiceShape service, + Shape shape, + List events + ) { + if (shape.getTrait(AuthTrait.class).isPresent()) { + AuthTrait authTrait = shape.getTrait(AuthTrait.class).get(); + Set appliedAuthTraitValue = new TreeSet<>(authTrait.getValues()); + appliedAuthTraitValue.removeAll(serviceAuth); + + if (!appliedAuthTraitValue.isEmpty()) { + events.add(danger(shape, authTrait, String.format( + "auth trait applies authentication that is not configured on the service shape, `%s`: %s", + service.getId(), + appliedAuthTraitValue))); + } + } + } +} diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/AuthValidator.java b/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/AuthValidator.java deleted file mode 100644 index 818518721b5..00000000000 --- a/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/AuthValidator.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2019 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.model.validation.validators; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; -import software.amazon.smithy.model.Model; -import software.amazon.smithy.model.knowledge.TopDownIndex; -import software.amazon.smithy.model.shapes.ServiceShape; -import software.amazon.smithy.model.shapes.Shape; -import software.amazon.smithy.model.traits.AuthTrait; -import software.amazon.smithy.model.traits.Protocol; -import software.amazon.smithy.model.traits.ProtocolsTrait; -import software.amazon.smithy.model.validation.AbstractValidator; -import software.amazon.smithy.model.validation.ValidationEvent; -import software.amazon.smithy.model.validation.ValidationUtils; -import software.amazon.smithy.utils.ListUtils; -import software.amazon.smithy.utils.OptionalUtils; - -/** - * Validates that service shapes and every operation bound within a service - * marked with the auth trait correspond to an auth scheme defined in - * one of the protocols of the service (with the exception of "none"). - * This will also validate that every protocols trait uses a unique - * set of protocol names. - * - *

For example, if an operation is bound to a service and has an auth trait - * with a value of "http-basic", but no protocol on the service supports the - * "http-basic" auth scheme, then this validator will emit an ERROR. - */ -public final class AuthValidator extends AbstractValidator { - @Override - public List validate(Model model) { - TopDownIndex topDownIndex = model.getKnowledge(TopDownIndex.class); - return model.shapes(ServiceShape.class) - .flatMap(service -> validateService(topDownIndex, service).stream()) - .collect(Collectors.toList()); - } - - private List validateService( - TopDownIndex topDownIndex, - ServiceShape service - ) { - Optional protocols = service.getTrait(ProtocolsTrait.class); - if (!protocols.isPresent()) { - return ListUtils.of(); - } - - List result = new ArrayList<>(); - // Validate the schemes on the service itself. - OptionalUtils.stream(service.getTrait(AuthTrait.class)) - .flatMap(trait -> OptionalUtils.stream(validateSchemes(protocols.get(), service, service, trait))) - .forEach(result::add); - // Validate the schemes of each operation bound within the service. - topDownIndex.getContainedOperations(service).stream() - .flatMap(operation -> OptionalUtils.stream(operation.getTrait(AuthTrait.class)) - .flatMap(trait -> OptionalUtils.stream( - validateSchemes(protocols.get(), service, operation, trait)))) - .forEach(result::add); - // Validate for unique protocol names. - validateUniqueNames(service, protocols.get()).ifPresent(result::add); - - return result; - } - - private Optional validateSchemes( - ProtocolsTrait protocols, - ServiceShape service, - Shape shape, - AuthTrait trait - ) { - // Validates that the authentication schemes resolved for an operation or - // service are listed in the authentication schemes supported by the - // service protocols to which it is bound. - Set serviceSchemes = protocols.getAllAuthSchemes(); - Set copiedSchemes = new HashSet<>(trait.getValues()); - copiedSchemes.removeAll(serviceSchemes); - - // Remove the "none" scheme since it does not need to be explicitly - // listed in any protocol. - copiedSchemes.remove(ProtocolsTrait.NONE_AUTH); - - if (copiedSchemes.isEmpty()) { - return Optional.empty(); - } - - return Optional.of(error(shape, trait, String.format( - "The following `auth` trait values are not compatible with the `auth` schemes listed in the " - + "`protocols` trait of the service, `%s`: [%s]. This service supports the following " - + "authentication schemes: [%s]", - service.getId(), - ValidationUtils.tickedList(copiedSchemes), - ValidationUtils.tickedList(serviceSchemes)))); - } - - private Optional validateUniqueNames(ServiceShape shape, ProtocolsTrait protocols) { - // Check for protocols with conflicting names. - List result = protocols.getProtocols().stream() - .collect(Collectors.groupingBy(Protocol::getName)) - .entrySet() - .stream() - .filter(entry -> entry.getValue().size() > 1) - .map(Map.Entry::getKey) - .sorted() - .collect(Collectors.toList()); - - if (result.isEmpty()) { - return Optional.empty(); - } - - return Optional.of(error(shape, protocols, String.format( - "`protocols` trait contains conflicting protocol names: %s", result))); - } -} diff --git a/smithy-model/src/main/resources/META-INF/services/software.amazon.smithy.model.traits.TraitService b/smithy-model/src/main/resources/META-INF/services/software.amazon.smithy.model.traits.TraitService index a56a2c15b6e..667828fb915 100644 --- a/smithy-model/src/main/resources/META-INF/services/software.amazon.smithy.model.traits.TraitService +++ b/smithy-model/src/main/resources/META-INF/services/software.amazon.smithy.model.traits.TraitService @@ -28,7 +28,6 @@ software.amazon.smithy.model.traits.MediaTypeTrait$Provider software.amazon.smithy.model.traits.PaginatedTrait$Provider software.amazon.smithy.model.traits.PatternTrait$Provider software.amazon.smithy.model.traits.PrivateTrait$Provider -software.amazon.smithy.model.traits.ProtocolsTrait$Provider software.amazon.smithy.model.traits.RangeTrait$Provider software.amazon.smithy.model.traits.ReadonlyTrait$Provider software.amazon.smithy.model.traits.ReferencesTrait$Provider @@ -47,3 +46,9 @@ software.amazon.smithy.model.traits.XmlAttributeTrait$Provider software.amazon.smithy.model.traits.XmlFlattenedTrait$Provider software.amazon.smithy.model.traits.XmlNamespaceTrait$Provider software.amazon.smithy.model.traits.XmlNameTrait$Provider +software.amazon.smithy.model.traits.ProtocolDefinitionTrait$Provider +software.amazon.smithy.model.traits.AuthDefinitionTrait$Provider +software.amazon.smithy.model.traits.HttpBasicAuthTrait$Provider +software.amazon.smithy.model.traits.HttpBearerAuthTrait$Provider +software.amazon.smithy.model.traits.HttpDigestAuthTrait$Provider +software.amazon.smithy.model.traits.OptionalAuthTrait$Provider diff --git a/smithy-model/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.Validator b/smithy-model/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.Validator index 382d319ac1e..065e2bede6f 100644 --- a/smithy-model/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.Validator +++ b/smithy-model/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.Validator @@ -1,5 +1,4 @@ -software.amazon.smithy.model.validation.validators.AuthValidator -software.amazon.smithy.model.validation.validators.AuthProtocolsValidator +software.amazon.smithy.model.validation.validators.AuthTraitValidator software.amazon.smithy.model.validation.validators.EnumTraitValidator software.amazon.smithy.model.validation.validators.EventPayloadTraitValidator software.amazon.smithy.model.validation.validators.EventStreamValidator diff --git a/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude-traits.smithy b/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude-traits.smithy index c968e251177..eb0459ad37e 100644 --- a/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude-traits.smithy +++ b/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude-traits.smithy @@ -40,47 +40,82 @@ structure deprecated { @trait string documentation -/// Defines the protocols supported by a service in priority order. -@trait(selector: "service") -list protocols { - member: Protocol, +/// Provides a link to additional documentation. +@trait +string externalDocumentation + +/// Defines the list of authentication schemes supported by a service or operation. +@trait(selector: ":test(service, operation)") +@uniqueItems +list auth { + member: AuthTraitReference } +/// A string that must target an auth trait. +@idRef(selector: "[trait|authDefinition]") @private -structure Protocol { - /// The name that identifies the protocol. - /// - /// This name must be unique across the entire list. - @required - name: ProtocolOrAuthName, +string AuthTraitReference - /// Attaches a list of tags that allow protocols to be categorized and grouped. - tags: NonEmptyStringList, +/// Marks a trait as a protocol defining trait. +/// +/// The targeted trait must only be applied to service shapes, must be a +/// structure, and must have the `trait` trait. +@trait(selector: "structure[trait|trait]") +@tags(["diff.error.add", "diff.error.remove"]) +structure protocolDefinition {} - /// A priority ordered list of authentication schemes used with this protocol. - auth: AuthenticationSchemes, -} +/// Marks a trait as an auth scheme defining trait. +/// +/// The targeted trait must only be applied to service shapes or operation +/// shapes, must be a structure, and must have the `trait` trait. +@trait(selector: "structure[trait|trait]") +@tags(["diff.error.add", "diff.error.remove"]) +structure authDefinition {} -@private -@uniqueItems -list AuthenticationSchemes { - member: ProtocolOrAuthName -} +/// Enables HTTP Basic Authentication as defined in RFC 2617 +/// on a service or operation. +@trait(selector: "service") +@authDefinition +@externalDocumentation("https://tools.ietf.org/html/rfc2617.html") +structure httpBasicAuth {} -@pattern("^[a-z][a-z0-9\\-.+]*$") -@private -string ProtocolOrAuthName +/// Enables HTTP Digest Authentication as defined in RFC 2617 +/// on a service or operation. +@trait(selector: "service") +@authDefinition +@externalDocumentation("https://tools.ietf.org/html/rfc2617.html") +structure httpDigestAuth {} -/// Defines the authentication schemes supported by a service or operation. -@trait(selector: ":test(service, operation)") -@uniqueItems -list auth { - member: ProtocolOrAuthName +/// Enables HTTP Bearer Authentication as defined in RFC 6750 +/// on a service or operation. +@trait(selector: "service") +@authDefinition +@externalDocumentation("https://tools.ietf.org/html/rfc6750.html") +structure httpBearerAuth {} + +/// An HTTP-specific authentication scheme that sends an arbitrary +/// API key in a header or query string parameter. +@trait(selector: "service") +@authDefinition +structure httpApiKeyAuth { + /// Defines the name of the HTTP header or query string parameter + /// that contains the API key. + @required + name: NonEmptyString, + + /// Defines the location of where the key is serialized. This value + /// can be set to `"header"` or `"query"`. + @required + in: HttpApiKeyLocations, } -/// Provides a link to additional documentation. -@trait -string externalDocumentation +@private +@enum(header: {}, query: {}) +string HttpApiKeyLocations + +/// Indicates that an operation can be called without authentication. +@trait(selector: "operation") +structure optionalAuth {} /// Provides example inputs and outputs for operations. @trait(selector: "operation") diff --git a/smithy-model/src/test/java/software/amazon/smithy/model/knowledge/AuthIndexTest.java b/smithy-model/src/test/java/software/amazon/smithy/model/knowledge/AuthIndexTest.java deleted file mode 100644 index 6283da1a22a..00000000000 --- a/smithy-model/src/test/java/software/amazon/smithy/model/knowledge/AuthIndexTest.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2019 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.model.knowledge; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; - -import org.junit.jupiter.api.Test; -import software.amazon.smithy.model.Model; -import software.amazon.smithy.model.shapes.OperationShape; -import software.amazon.smithy.model.shapes.ServiceShape; -import software.amazon.smithy.model.traits.AuthTrait; -import software.amazon.smithy.model.traits.Protocol; -import software.amazon.smithy.model.traits.ProtocolsTrait; -import software.amazon.smithy.utils.ListUtils; - -public class AuthIndexTest { - @Test - public void supportedServiceSchemesDefaultsToAllProtocols() { - ServiceShape service = ServiceShape.builder() - .id("example.smithy#Service") - .version("XYZ") - .addTrait(ProtocolsTrait.builder() - .addProtocol(Protocol.builder().name("json").addAuth("foo").addAuth("baz").build()) - .addProtocol(Protocol.builder().name("xml").addAuth("qux").addAuth("foo").build()) - .build()) - .build(); - Model model = Model.builder().addShape(service).build(); - AuthIndex authIndex = model.getKnowledge(AuthIndex.class); - - assertThat(authIndex.getDefaultServiceSchemes(service), equalTo(ListUtils.of("foo", "baz", "qux"))); - } - - @Test - public void getSchemesOfOperationBoundToServiceAndProtocol() { - OperationShape operation1 = OperationShape.builder().id("example.smithy#O1").build(); - OperationShape operation2 = OperationShape.builder() - .id("example.smithy#O2") - .addTrait(AuthTrait.builder().addValue("foo").build()) - .build(); - OperationShape operation3 = OperationShape.builder() - .id("example.smithy#O3") - .addTrait(AuthTrait.builder().addValue("baz").addValue("foo").build()) - .build(); - ServiceShape service = ServiceShape.builder() - .id("example.smithy#Service") - .version("XYZ") - .addOperation(operation1) - .addOperation(operation2) - .addOperation(operation3) - .addTrait(AuthTrait.builder().addValue("foo").build()) - .addTrait(ProtocolsTrait.builder() - .addProtocol(Protocol.builder().name("json").addAuth("foo").addAuth("baz").build()) - .addProtocol(Protocol.builder().name("xml").addAuth("qux").build()) - .build()) - .build(); - Model model = Model.builder().addShapes(service, operation1, operation2, operation3).build(); - AuthIndex authIndex = model.getKnowledge(AuthIndex.class); - - // Use the schemes defined on the shape itself or the schemes of the service. - assertThat(authIndex.getOperationSchemes(service, operation1), equalTo(ListUtils.of("foo"))); - assertThat(authIndex.getOperationSchemes(service, operation2), equalTo(ListUtils.of("foo"))); - assertThat(authIndex.getOperationSchemes(service, operation3), equalTo(ListUtils.of("baz", "foo"))); - - // Get the intersection of the schemes of the shape and the protocol. - assertThat(authIndex.getOperationSchemes(service, operation1, "json"), equalTo(ListUtils.of("foo"))); - assertThat(authIndex.getOperationSchemes(service, operation2, "json"), equalTo(ListUtils.of("foo"))); - assertThat(authIndex.getOperationSchemes(service, operation3, "json"), equalTo(ListUtils.of("baz", "foo"))); - } - - @Test - public void includesNoneEvenIfNotListedInSchemes() { - OperationShape operation1 = OperationShape.builder() - .id("example.smithy#O1") - .addTrait(AuthTrait.builder().addValue("none").build()) - .build(); - ServiceShape service = ServiceShape.builder() - .id("example.smithy#Service") - .version("XYZ") - .addOperation(operation1) - .addTrait(ProtocolsTrait.builder() - .addProtocol(Protocol.builder().name("json").addAuth("foo").build()) - .build()) - .build(); - Model model = Model.builder().addShapes(service, operation1).build(); - AuthIndex authIndex = model.getKnowledge(AuthIndex.class); - - assertThat(authIndex.getOperationSchemes(service, operation1), equalTo(ListUtils.of("none"))); - assertThat(authIndex.getOperationSchemes(service, operation1, "json"), equalTo(ListUtils.of("none"))); - } -} diff --git a/smithy-model/src/test/java/software/amazon/smithy/model/knowledge/ServiceIndexTest.java b/smithy-model/src/test/java/software/amazon/smithy/model/knowledge/ServiceIndexTest.java new file mode 100644 index 00000000000..79782ad89e2 --- /dev/null +++ b/smithy-model/src/test/java/software/amazon/smithy/model/knowledge/ServiceIndexTest.java @@ -0,0 +1,145 @@ +/* + * Copyright 2019 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.model.knowledge; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.hasKey; +import static org.hamcrest.Matchers.hasSize; + +import java.util.Map; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.traits.HttpBasicAuthTrait; +import software.amazon.smithy.model.traits.HttpBearerAuthTrait; +import software.amazon.smithy.model.traits.HttpDigestAuthTrait; +import software.amazon.smithy.model.traits.Trait; + +public class ServiceIndexTest { + + private static Model model; + + @BeforeAll + public static void before() { + model = Model.assembler() + .addImport(ServiceIndexTest.class.getResource("service-index-finds-auth-schemes.smithy")) + .assemble() + .unwrap(); + } + + @AfterAll + public static void after() { + model = null; + } + + @Test + public void returnsProtocolsOfService() { + Model model = Model.assembler() + .addImport(getClass().getResource("service-index-loads-protocols.smithy")) + .assemble() + .unwrap(); + ServiceIndex serviceIndex = model.getKnowledge(ServiceIndex.class); + Map protocols = serviceIndex.getProtocols(ShapeId.from("smithy.example#TestService")); + + assertThat(protocols, hasKey(ShapeId.from("smithy.example#fooJson"))); + assertThat(protocols, hasKey(ShapeId.from("smithy.example#fooXml"))); + assertThat(protocols.keySet(), hasSize(2)); + } + + @Test + public void returnsAuthSchemesOfService() { + ServiceIndex serviceIndex = model.getKnowledge(ServiceIndex.class); + Map auth = serviceIndex.getAuthSchemes( + ShapeId.from("smithy.example#ServiceWithNoAuthTrait")); + + assertThat(auth.keySet(), hasSize(3)); + assertThat(auth, hasKey(HttpBasicAuthTrait.ID)); + assertThat(auth, hasKey(HttpDigestAuthTrait.ID)); + assertThat(auth, hasKey(HttpBearerAuthTrait.ID)); + } + + @Test + public void getsAuthSchemesOfServiceWithNoAuthTrait() { + ServiceIndex serviceIndex = model.getKnowledge(ServiceIndex.class); + Map auth = serviceIndex.getEffectiveAuthSchemes( + ShapeId.from("smithy.example#ServiceWithNoAuthTrait")); + + assertThat(auth.keySet(), hasSize(3)); + assertThat(auth, hasKey(HttpBasicAuthTrait.ID)); + assertThat(auth, hasKey(HttpDigestAuthTrait.ID)); + assertThat(auth, hasKey(HttpBearerAuthTrait.ID)); + } + + @Test + public void getsAuthSchemesOfServiceWithAuthTrait() { + ServiceIndex serviceIndex = model.getKnowledge(ServiceIndex.class); + Map auth = serviceIndex.getEffectiveAuthSchemes( + ShapeId.from("smithy.example#ServiceWithAuthTrait")); + + assertThat(auth.keySet(), hasSize(2)); + assertThat(auth, hasKey(HttpBasicAuthTrait.ID)); + assertThat(auth, hasKey(HttpDigestAuthTrait.ID)); + } + + @Test + public void getsAuthSchemesOfOperationWithNoAuthTraitAndServiceWithNoAuthTrait() { + ServiceIndex serviceIndex = model.getKnowledge(ServiceIndex.class); + Map auth = serviceIndex.getEffectiveAuthSchemes( + ShapeId.from("smithy.example#ServiceWithNoAuthTrait"), + ShapeId.from("smithy.example#OperationWithNoAuthTrait")); + + assertThat(auth.keySet(), hasSize(3)); + assertThat(auth, hasKey(HttpBasicAuthTrait.ID)); + assertThat(auth, hasKey(HttpDigestAuthTrait.ID)); + assertThat(auth, hasKey(HttpBearerAuthTrait.ID)); + } + + @Test + public void getsAuthSchemesOfOperationWithNoAuthTraitAndServiceWithAuthTrait() { + ServiceIndex serviceIndex = model.getKnowledge(ServiceIndex.class); + Map auth = serviceIndex.getEffectiveAuthSchemes( + ShapeId.from("smithy.example#ServiceWithAuthTrait"), + ShapeId.from("smithy.example#OperationWithNoAuthTrait")); + + assertThat(auth.keySet(), hasSize(2)); + assertThat(auth, hasKey(HttpBasicAuthTrait.ID)); + assertThat(auth, hasKey(HttpDigestAuthTrait.ID)); + } + + @Test + public void getsAuthSchemesOfOperationWithAuthTrait() { + ServiceIndex serviceIndex = model.getKnowledge(ServiceIndex.class); + Map auth = serviceIndex.getEffectiveAuthSchemes( + ShapeId.from("smithy.example#ServiceWithAuthTrait"), + ShapeId.from("smithy.example#OperationWithAuthTrait")); + + assertThat(auth.keySet(), hasSize(1)); + assertThat(auth, hasKey(HttpDigestAuthTrait.ID)); + } + + @Test + public void returnsAnEmptyCollectionWhenTheServiceDoesNotExist() { + ServiceIndex serviceIndex = model.getKnowledge(ServiceIndex.class); + Map auth = serviceIndex.getEffectiveAuthSchemes( + ShapeId.from("smithy.example#Invalid"), + ShapeId.from("smithy.example#OperationWithAuthTrait")); + + assertThat(auth.keySet(), empty()); + } +} diff --git a/smithy-model/src/test/java/software/amazon/smithy/model/traits/ProtocolsTraitTest.java b/smithy-model/src/test/java/software/amazon/smithy/model/traits/ProtocolsTraitTest.java deleted file mode 100644 index 97c3dfa6c08..00000000000 --- a/smithy-model/src/test/java/software/amazon/smithy/model/traits/ProtocolsTraitTest.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2019 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.model.traits; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.instanceOf; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.Optional; -import org.junit.jupiter.api.Test; -import software.amazon.smithy.model.node.ArrayNode; -import software.amazon.smithy.model.node.Node; -import software.amazon.smithy.model.shapes.ShapeId; -import software.amazon.smithy.utils.ListUtils; - -public class ProtocolsTraitTest { - @Test - public void loadsTraits() { - Node node = Node.arrayNode() - .withValue(Node.objectNode() - .withMember("name", Node.from("foo")) - .withMember("auth", ArrayNode.fromStrings(ListUtils.of("foo")))) - .withValue(Node.objectNode() - .withMember("name", Node.from("baz")) - .withMember("tags", ArrayNode.fromStrings(ListUtils.of("foo", "bar", "baz"))) - .withMember("auth", ArrayNode.fromStrings(ListUtils.of("abc", "def")))); - TraitFactory provider = TraitFactory.createServiceFactory(); - Optional trait = provider.createTrait( - ShapeId.from("smithy.api#protocols"), ShapeId.from("ns.qux#foo"), node); - - assertTrue(trait.isPresent()); - assertThat(trait.get(), instanceOf(ProtocolsTrait.class)); - ProtocolsTrait protocolsTrait = (ProtocolsTrait) trait.get(); - assertEquals(protocolsTrait.getProtocols().size(), 2); - - assertTrue(protocolsTrait.getProtocol("foo").isPresent()); - assertThat(protocolsTrait.getAllAuthSchemes(), containsInAnyOrder("abc", "def", "foo")); - - assertThat(protocolsTrait.toNode(), equalTo(node)); - assertThat(protocolsTrait.toBuilder().build(), equalTo(protocolsTrait)); - } -} diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/auth-trait-must-target-auth-definitions.errors b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/auth-trait-must-target-auth-definitions.errors new file mode 100644 index 00000000000..a48800aa79d --- /dev/null +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/auth-trait-must-target-auth-definitions.errors @@ -0,0 +1,2 @@ +[ERROR] ns.foo#Invalid1: Error creating trait `auth`: Invalid shape ID: not a shape ID | Model +[ERROR] ns.foo#Invalid2: Error validating trait `auth`.0: Shape ID `smithy.api#String` does not match selector `[trait|authDefinition]` | TraitValue diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/auth-trait-must-target-auth-definitions.json b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/auth-trait-must-target-auth-definitions.json new file mode 100644 index 00000000000..24836931c49 --- /dev/null +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/auth-trait-must-target-auth-definitions.json @@ -0,0 +1,29 @@ +{ + "smithy": "0.5.0", + "shapes": { + "ns.foo#Valid1": { + "type": "operation", + "traits": { + "smithy.api#auth": ["smithy.api#httpBasicAuth", "smithy.api#httpBearerAuth"] + } + }, + "ns.foo#Valid2": { + "type": "operation", + "traits": { + "smithy.api#auth": [] + } + }, + "ns.foo#Invalid1": { + "type": "operation", + "traits": { + "smithy.api#auth": ["not a shape ID"] + } + }, + "ns.foo#Invalid2": { + "type": "operation", + "traits": { + "smithy.api#auth": ["smithy.api#String"] + } + } + } +} diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/auth-trait-must-target-service-schemes.errors b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/auth-trait-must-target-service-schemes.errors new file mode 100644 index 00000000000..b0d4afa6fa6 --- /dev/null +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/auth-trait-must-target-service-schemes.errors @@ -0,0 +1 @@ +[DANGER] ns.foo#InvalidOperation: auth trait applies authentication that is not configured on the service shape, `ns.foo#Service`: [smithy.api#httpApiKeyAuth, smithy.api#httpBearerAuth] | AuthTrait diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/auth-trait-must-target-service-schemes.json b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/auth-trait-must-target-service-schemes.json new file mode 100644 index 00000000000..e8ea2fcd285 --- /dev/null +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/auth-trait-must-target-service-schemes.json @@ -0,0 +1,36 @@ +{ + "smithy": "0.5.0", + "shapes": { + "ns.foo#Service": { + "type": "service", + "version": "X", + "operations": [ + {"target": "ns.foo#ValidOperation"}, + {"target": "ns.foo#InvalidOperation"} + ], + "traits": { + "smithy.api#httpBasicAuth": true, + "smithy.api#httpDigestAuth": true + } + }, + "ns.foo#ValidOperation": { + "type": "operation", + "traits": { + "smithy.api#auth": [ + "smithy.api#httpBasicAuth", + "smithy.api#httpDigestAuth" + ] + } + }, + "ns.foo#InvalidOperation": { + "type": "operation", + "traits": { + "smithy.api#auth": [ + "smithy.api#httpBasicAuth", + "smithy.api#httpBearerAuth", + "smithy.api#httpApiKeyAuth" + ] + } + } + } +} diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/authentication-protocols-validator.errors b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/authentication-protocols-validator.errors deleted file mode 100644 index 4bf9ad9eaf5..00000000000 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/authentication-protocols-validator.errors +++ /dev/null @@ -1 +0,0 @@ -[WARNING] ns.foo#InvalidOperation1: The `auth` trait resolved for this operation, [x], is not compatible with the `baz` protocol of the `ns.foo#ValidService` service: [y] | AuthProtocols diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/authentication-protocols-validator.json b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/authentication-protocols-validator.json deleted file mode 100644 index 2d080e7f74c..00000000000 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/authentication-protocols-validator.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "smithy": "0.5.0", - "shapes": { - "ns.foo#ValidService": { - "type": "service", - "version": "2019-02-11", - "operations": [ - { - "target": "ns.foo#ValidOperation1" - }, - { - "target": "ns.foo#ValidOperation2" - }, - { - "target": "ns.foo#InvalidOperation1" - } - ], - "traits": { - "smithy.api#auth": [ - "x", - "y" - ], - "smithy.api#protocols": [ - { - "name": "foo", - "auth": [ - "x", - "y" - ] - }, - { - "name": "baz", - "auth": [ - "y" - ] - } - ] - } - }, - "ns.foo#ValidOperation1": { - "type": "operation", - "traits": { - "smithy.api#auth": [ - "y" - ] - } - }, - "ns.foo#ValidOperation2": { - "type": "operation" - }, - "ns.foo#InvalidOperation1": { - "type": "operation", - "traits": { - "smithy.api#auth": [ - "x" - ] - } - } - } -} diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/authentication-validation.errors b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/authentication-validation.errors deleted file mode 100644 index a33b6be61a9..00000000000 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/authentication-validation.errors +++ /dev/null @@ -1,3 +0,0 @@ -[ERROR] ns.foo#InvalidOperation1: The following `auth` trait values are not compatible with the `auth` schemes listed in the `protocols` trait of the service, `ns.foo#ValidService`: [`invalid`]. This service supports the following authentication schemes: [`bar`, `baz`, `foo`] | Auth -[ERROR] ns.foo#InvalidService: The following `auth` trait values are not compatible with the `auth` schemes listed in the `protocols` trait of the service, `ns.foo#InvalidService`: [`qux`]. This service supports the following authentication schemes: [`bar`, `baz`, `foo`] | Auth -[WARNING] ns.foo#InvalidOperation1: The `auth` trait resolved for this operation, [invalid], is not compatible with the `a` protocol of the `ns.foo#ValidService` service: [foo, baz, bar] | AuthProtocols diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/authentication-validation.json b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/authentication-validation.json deleted file mode 100644 index 5399ca43857..00000000000 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/authentication-validation.json +++ /dev/null @@ -1,86 +0,0 @@ -{ - "smithy": "0.5.0", - "shapes": { - "ns.foo#ValidService": { - "type": "service", - "version": "2019-02-11", - "operations": [ - { - "target": "ns.foo#ValidOperation1" - }, - { - "target": "ns.foo#ValidOperation2" - }, - { - "target": "ns.foo#ValidOperation3" - }, - { - "target": "ns.foo#InvalidOperation1" - } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "a", - "auth": [ - "foo", - "baz", - "bar" - ] - } - ], - "smithy.api#auth": [ - "foo", - "bar" - ] - } - }, - "ns.foo#ValidOperation1": { - "type": "operation", - "traits": { - "smithy.api#auth": [ - "baz" - ] - } - }, - "ns.foo#ValidOperation2": { - "type": "operation" - }, - "ns.foo#ValidOperation3": { - "type": "operation", - "traits": { - "smithy.api#auth": [ - "none" - ] - } - }, - "ns.foo#InvalidOperation1": { - "type": "operation", - "traits": { - "smithy.api#auth": [ - "invalid" - ] - } - }, - "ns.foo#InvalidService": { - "type": "service", - "version": "2019-02-11", - "traits": { - "smithy.api#protocols": [ - { - "name": "a", - "auth": [ - "foo", - "baz", - "bar" - ] - } - ], - "smithy.api#auth": [ - "foo", - "qux" - ] - } - } - } -} diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/external-documentation.json b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/external-documentation.json index e55f3d6731b..98aad66772f 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/external-documentation.json +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/external-documentation.json @@ -5,11 +5,6 @@ "type": "service", "version": "2017-01-17", "traits": { - "smithy.api#protocols": [ - { - "name": "foo" - } - ], "smithy.api#externalDocumentation": "https://www.example.com" } }, @@ -17,11 +12,6 @@ "type": "service", "version": "2017-01-17", "traits": { - "smithy.api#protocols": [ - { - "name": "foo" - } - ], "smithy.api#externalDocumentation": "invalid!" } } diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/host-request-validator.json b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/host-request-validator.json index 0fcb07629fb..04e310ef1e9 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/host-request-validator.json +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/host-request-validator.json @@ -38,14 +38,7 @@ { "target": "ns.foo#L" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "foo" - } - ] - } + ] }, "ns.foo#A": { "type": "operation", diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/http-bindings-missing-validator.json b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/http-bindings-missing-validator.json index 92304827e66..02b8805cb74 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/http-bindings-missing-validator.json +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/http-bindings-missing-validator.json @@ -14,14 +14,7 @@ { "target": "ns.foo#MissingBindings2" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "foo" - } - ] - } + ] }, "ns.foo#HasBindings": { "type": "operation", diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/http-request-response-validator.json b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/http-request-response-validator.json index 813f555a537..e2d12182eff 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/http-request-response-validator.json +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/http-request-response-validator.json @@ -53,14 +53,7 @@ { "target": "ns.foo#R" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "foo" - } - ] - } + ] }, "ns.foo#A": { "type": "operation", diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/http-uri-conflict-validator.json b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/http-uri-conflict-validator.json index bebf559afe6..852d539381b 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/http-uri-conflict-validator.json +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/http-uri-conflict-validator.json @@ -56,14 +56,7 @@ { "target": "ns.foo#ConflictsWithoutPattern2" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "example" - } - ] - } + ] }, "ns.foo#A": { "type": "operation", diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/resource-parent-validator.json b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/resource-parent-validator.json index b5e8cfc9fce..1124e696ba5 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/resource-parent-validator.json +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/resource-parent-validator.json @@ -14,14 +14,7 @@ { "target": "ns.foo#InvalidResourceBindingType" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "foo" - } - ] - } + ] }, "ns.foo#ValidResource": { "type": "resource" diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/service-validator.errors b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/service-validator.errors deleted file mode 100644 index 86e164a1307..00000000000 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/service-validator.errors +++ /dev/null @@ -1,7 +0,0 @@ -[ERROR] ns.baz#OperationB: An operation can appear only once in an entire service closure. This operation is illegally bound into the `ns.foo#InvalidServiceWithDuplicateNames` service closure from multiple shapes: (resource: `ns.baz#ResourceA`), (resource: `ns.baz#ResourceB`) | SingleOperationBinding -[ERROR] ns.foo#InvalidServiceWithDuplicateNames: All operations contained within a service hierarchy must have case-insensitively unique names regardless of their namespaces. The following operations were found in this service to have conflicting names: {operationa=[ns.baz#OperationA, ns.foo#OperationA], operationb=[ns.baz#OperationB, ns.foo#OperationB]} | Service -[ERROR] ns.foo#InvalidServiceWithDuplicateNames: All resources contained within a service hierarchy must have case-insensitively unique names regardless of their namespaces. The following resources were found in this service to have conflicting names: {resourcea=[ns.baz#ResourceA, ns.foo#ResourceA], resourceb=[ns.baz#ResourceB, ns.foo#ResourceB]} | Service -[ERROR] ns.invalid#InvalidService1: Error validating trait `protocols`.0.name: String value provided for `smithy.api#ProtocolOrAuthName` must match regular expression: ^[a-z][a-z0-9\-.+]*$ | TraitValue -[ERROR] ns.invalid#InvalidService1: Error validating trait `protocols`.1.name: String value provided for `smithy.api#ProtocolOrAuthName` must match regular expression: ^[a-z][a-z0-9\-.+]*$ | TraitValue -[ERROR] ns.invalid#InvalidService1: Error validating trait `protocols`.2.name: String value provided for `smithy.api#ProtocolOrAuthName` must match regular expression: ^[a-z][a-z0-9\-.+]*$ | TraitValue -[ERROR] ns.invalid#InvalidService1: Error validating trait `protocols`.3.name: String value provided for `smithy.api#ProtocolOrAuthName` must match regular expression: ^[a-z][a-z0-9\-.+]*$ | TraitValue diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/service-validator.json b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/service-validator.json deleted file mode 100644 index 0de707145b4..00000000000 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/service-validator.json +++ /dev/null @@ -1,217 +0,0 @@ -{ - "smithy": "0.5.0", - "shapes": { - "ns.foo#InvalidServiceWithDuplicateNames": { - "type": "service", - "version": "XYZ", - "resources": [ - { - "target": "ns.foo#ResourceA" - }, - { - "target": "ns.baz#ResourceA" - } - ], - "operations": [ - { - "target": "ns.foo#OperationA" - } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "a", - "auth": [ - "b" - ] - } - ] - } - }, - "ns.foo#OperationA": { - "type": "operation", - "traits": { - "smithy.api#readonly": true - } - }, - "ns.foo#ResourceA": { - "type": "resource", - "identifiers": { - "resourceAId": { - "target": "ns.foo#ResourceAId" - } - }, - "resources": [ - { - "target": "ns.foo#ResourceB" - } - ] - }, - "ns.foo#ResourceAId": { - "type": "string" - }, - "ns.foo#ResourceB": { - "type": "resource", - "identifiers": { - "resourceAId": { - "target": "ns.foo#ResourceAId" - } - }, - "operations": [ - { - "target": "ns.foo#OperationB" - } - ] - }, - "ns.foo#OperationB": { - "type": "operation", - "input": { - "target": "ns.foo#OperationBInput" - }, - "traits": { - "smithy.api#readonly": true - } - }, - "ns.foo#OperationBInput": { - "type": "structure", - "members": { - "resourceAId": { - "target": "ns.foo#ResourceAId", - "traits": { - "smithy.api#required": true - } - } - } - }, - "ns.baz#ResourceA": { - "type": "resource", - "identifiers": { - "resourceAId": { - "target": "ns.baz#ResourceAId" - } - }, - "operations": [ - { - "target": "ns.baz#OperationA" - }, - { - "target": "ns.baz#OperationB" - } - ], - "resources": [ - { - "target": "ns.baz#ResourceB" - } - ] - }, - "ns.baz#ResourceAId": { - "type": "string" - }, - "ns.baz#ResourceB": { - "type": "resource", - "identifiers": { - "resourceAId": { - "target": "ns.baz#ResourceAId" - } - }, - "operations": [ - { - "target": "ns.baz#OperationB" - } - ] - }, - "ns.baz#OperationA": { - "type": "operation", - "input": { - "target": "ns.baz#OperationAInput" - }, - "traits": { - "smithy.api#readonly": true - } - }, - "ns.baz#OperationAInput": { - "type": "structure", - "members": { - "resourceAId": { - "target": "ns.baz#ResourceAId", - "traits": { - "smithy.api#required": true - } - } - } - }, - "ns.baz#OperationB": { - "type": "operation", - "input": { - "target": "ns.baz#OperationBInput" - }, - "traits": { - "smithy.api#readonly": true - } - }, - "ns.baz#OperationBInput": { - "type": "structure", - "members": { - "resourceAId": { - "target": "ns.baz#ResourceAId", - "traits": { - "smithy.api#required": true - } - } - } - }, - "ns.invalid#InvalidService1": { - "type": "service", - "version": "XYZ", - "traits": { - "smithy.api#protocols": [ - { - "name": "1" - }, - { - "name": "-" - }, - { - "name": "a.$" - }, - { - "name": "a.B" - }, - { - "name": "a.-+-." - }, - { - "name": "abc" - }, - { - "name": "skip.me.too-1.1" - }, - { - "name": "skip.me.too-1.1++" - }, - { - "name": "foo", - "auth": [ - "abc", - "def" - ] - } - ] - } - }, - "ns.invalid#InvalidService2": { - "type": "service", - "version": "XYZ", - "traits": { - "smithy.api#protocols": [ - { - "name": "foo", - "auth": [ - "bar" - ] - } - ] - } - } - } -} diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/single-operation-binding.json b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/single-operation-binding.json index c750e3a0305..9c587a6530a 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/single-operation-binding.json +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/single-operation-binding.json @@ -25,14 +25,7 @@ { "target": "ns.foo#OC" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "foo" - } - ] - } + ] }, "ns.foo#RA": { "type": "resource", diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/single-resource-binding.json b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/single-resource-binding.json index 0037697c4da..1c7e3d1c4a2 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/single-resource-binding.json +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/single-resource-binding.json @@ -11,14 +11,7 @@ { "target": "ns.foo#ResourceB" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "foo" - } - ] - } + ] }, "ns.foo#ResourceA": { "type": "resource", diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/target-validator.json b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/target-validator.json index ea566fb80f7..858d42480d3 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/target-validator.json +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/target-validator.json @@ -41,14 +41,7 @@ { "target": "ns.foo#InvalidResourceLifecycle" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "foo" - } - ] - } + ] }, "ns.foo#MyResource": { "type": "resource", diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/http-index.json b/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/http-index.json index b0a68667c48..7d77eb6a86f 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/http-index.json +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/http-index.json @@ -20,14 +20,7 @@ { "target": "ns.foo#WithLabels" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "example" - } - ] - } + ] }, "ns.foo#ServiceOperationNoInputOutput": { "type": "operation", diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/operation-index-test.json b/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/operation-index-test.json index 2a3887dace3..1f78ed6ad3e 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/operation-index-test.json +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/operation-index-test.json @@ -11,14 +11,7 @@ { "target": "ns.foo#B" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "example" - } - ] - } + ] }, "ns.foo#A": { "type": "operation", diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/service-index-finds-auth-schemes.smithy b/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/service-index-finds-auth-schemes.smithy new file mode 100644 index 00000000000..e95bc72d327 --- /dev/null +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/service-index-finds-auth-schemes.smithy @@ -0,0 +1,29 @@ +namespace smithy.example + +@httpBasicAuth +@httpDigestAuth +@httpBearerAuth +service ServiceWithNoAuthTrait { + version: "2020-01-29", + operations: [ + OperationWithNoAuthTrait, + OperationWithAuthTrait + ] +} + +@httpBasicAuth +@httpDigestAuth +@httpBearerAuth +@auth([httpBasicAuth, httpDigestAuth]) +service ServiceWithAuthTrait { + version: "2020-01-29", + operations: [ + OperationWithNoAuthTrait, + OperationWithAuthTrait + ] +} + +operation OperationWithNoAuthTrait {} + +@auth([httpDigestAuth]) +operation OperationWithAuthTrait {} diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/service-index-loads-protocols.smithy b/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/service-index-loads-protocols.smithy new file mode 100644 index 00000000000..3d2c912a765 --- /dev/null +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/service-index-loads-protocols.smithy @@ -0,0 +1,15 @@ +namespace smithy.example + +@fooJson +@fooXml +service TestService { + version: "2020-01-29" +} + +@trait(selector: "service") +@protocolDefinition +structure fooJson {} + +@trait(selector: "service") +@protocolDefinition +structure fooXml {} diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/nested/other-ion-model.json b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/nested/other-ion-model.json index 11f7e1165cd..8e6a8346f8d 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/nested/other-ion-model.json +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/nested/other-ion-model.json @@ -11,14 +11,7 @@ { "target": "example.namespace#Resource" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "test-protocol" - } - ] - } + ] }, "example.namespace#Resource": { "type": "resource", diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/neighbor/unreferenced-test.json b/smithy-model/src/test/resources/software/amazon/smithy/model/neighbor/unreferenced-test.json index 29987c35b63..2b329dfb679 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/neighbor/unreferenced-test.json +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/neighbor/unreferenced-test.json @@ -30,14 +30,7 @@ { "target": "ns.foo#MyOperation" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "foo" - } - ] - } + ] }, "ns.foo#MyOperation": { "type": "operation", diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/shapes/test-model.json b/smithy-model/src/test/resources/software/amazon/smithy/model/shapes/test-model.json index 3a93ab4e110..e0dfe124f96 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/shapes/test-model.json +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/shapes/test-model.json @@ -5,14 +5,7 @@ "type": "service", "version": "2017-01-17", "traits": { - "smithy.api#protocols": [ - { - "name": "a" - }, - { - "name": "b" - } - ] + "smithy.api#documentation": "Hello" } }, "ns.foo#MyService": { @@ -25,17 +18,7 @@ { "target": "ns.foo#BasicResource" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "a" - }, - { - "name": "b" - } - ] - } + ] }, "ns.foo#MyResource": { "type": "resource", diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/transform/integration-test-model.json b/smithy-model/src/test/resources/software/amazon/smithy/model/transform/integration-test-model.json index 0a732fb0696..ea4dca05c1e 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/transform/integration-test-model.json +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/transform/integration-test-model.json @@ -13,18 +13,7 @@ { "target": "ns.foo#MyResource" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "foo", - "auth": [ - "foo.baz", - "foo.bar" - ] - } - ] - } + ] }, "ns.foo#MyOperation": { "type": "operation", diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/transform/test-model.json b/smithy-model/src/test/resources/software/amazon/smithy/model/transform/test-model.json index deb870a52ce..fbab1130208 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/transform/test-model.json +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/transform/test-model.json @@ -8,14 +8,7 @@ { "target": "ns.foo#MyOperation" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "foo" - } - ] - } + ] }, "ns.foo#MyOperation": { "type": "operation", diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/validation/node-validator.json b/smithy-model/src/test/resources/software/amazon/smithy/model/validation/node-validator.json index ea790150fb0..3067945ecde 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/validation/node-validator.json +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/validation/node-validator.json @@ -300,14 +300,7 @@ { "target": "ns.foo#Resource" } - ], - "traits": { - "smithy.api#protocols": [ - { - "name": "foo" - } - ] - } + ] }, "ns.foo#Operation": { "type": "operation", diff --git a/smithy-mqtt-traits/src/main/java/software/amazon/smithy/mqtt/traits/MqttJsonTrait.java b/smithy-mqtt-traits/src/main/java/software/amazon/smithy/mqtt/traits/MqttJsonTrait.java new file mode 100644 index 00000000000..4def2fd6e08 --- /dev/null +++ b/smithy-mqtt-traits/src/main/java/software/amazon/smithy/mqtt/traits/MqttJsonTrait.java @@ -0,0 +1,38 @@ +/* + * Copyright 2019 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.mqtt.traits; + +import software.amazon.smithy.model.SourceLocation; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.traits.BooleanTrait; + +public final class MqttJsonTrait extends BooleanTrait { + public static final ShapeId ID = ShapeId.from("smithy.mqtt#mqttJson"); + + public MqttJsonTrait(SourceLocation sourceLocation) { + super(ID, sourceLocation); + } + + public MqttJsonTrait() { + this(SourceLocation.NONE); + } + + public static final class Provider extends BooleanTrait.Provider { + public Provider() { + super(ID, MqttJsonTrait::new); + } + } +} diff --git a/smithy-mqtt-traits/src/main/resources/META-INF/services/software.amazon.smithy.model.traits.TraitService b/smithy-mqtt-traits/src/main/resources/META-INF/services/software.amazon.smithy.model.traits.TraitService index 465ad903d0c..f4fdab96ef2 100644 --- a/smithy-mqtt-traits/src/main/resources/META-INF/services/software.amazon.smithy.model.traits.TraitService +++ b/smithy-mqtt-traits/src/main/resources/META-INF/services/software.amazon.smithy.model.traits.TraitService @@ -1,3 +1,4 @@ software.amazon.smithy.mqtt.traits.PublishTrait$Provider software.amazon.smithy.mqtt.traits.SubscribeTrait$Provider software.amazon.smithy.mqtt.traits.TopicLabelTrait$Provider +software.amazon.smithy.mqtt.traits.MqttJsonTrait$Provider diff --git a/smithy-mqtt-traits/src/main/resources/META-INF/smithy/smithy.api.mqtt.smithy b/smithy-mqtt-traits/src/main/resources/META-INF/smithy/smithy.api.mqtt.smithy index 0280b5d7177..404006ac105 100644 --- a/smithy-mqtt-traits/src/main/resources/META-INF/smithy/smithy.api.mqtt.smithy +++ b/smithy-mqtt-traits/src/main/resources/META-INF/smithy/smithy.api.mqtt.smithy @@ -2,6 +2,10 @@ $version: "0.5.0" namespace smithy.mqtt +@trait(selector: "service") +@protocolDefinition +structure mqttJson {} + @trait(selector: "operation:not(-[output]->)", conflicts: ["smithy.mqtt#subscribe"]) @tags(["diff.error.const"]) diff --git a/smithy-mqtt-traits/src/test/resources/software/amazon/smithy/mqtt/traits/errorfiles/job-service.smithy b/smithy-mqtt-traits/src/test/resources/software/amazon/smithy/mqtt/traits/errorfiles/job-service.smithy index a72ab4e3b76..9e34af1090b 100644 --- a/smithy-mqtt-traits/src/test/resources/software/amazon/smithy/mqtt/traits/errorfiles/job-service.smithy +++ b/smithy-mqtt-traits/src/test/resources/software/amazon/smithy/mqtt/traits/errorfiles/job-service.smithy @@ -2,7 +2,9 @@ metadata suppressions = [{"ids": ["UnstableFeature"], "shapes": ["aws.iotjobs#Jo namespace aws.iotjobs -@protocols([{name: "aws.mqtt-json"}]) +use smithy.mqtt#mqttJson + +@mqttJson service IotJobs { version: "2018-08-14", operations: [ diff --git a/smithy-openapi/build.gradle.kts b/smithy-openapi/build.gradle.kts index df5af209772..f61739cc965 100644 --- a/smithy-openapi/build.gradle.kts +++ b/smithy-openapi/build.gradle.kts @@ -21,4 +21,5 @@ dependencies { api(project(":smithy-model")) api(project(":smithy-build")) api(project(":smithy-jsonschema")) + api(project(":smithy-aws-traits")) } diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/OpenApiConstants.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/OpenApiConstants.java index d59b0762f05..6460244b1f8 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/OpenApiConstants.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/OpenApiConstants.java @@ -27,7 +27,7 @@ public final class OpenApiConstants { /** The Smithy service Shape ID to convert. */ public static final String SERVICE = "service"; - /** The protocol name to use when converting Smithy to OpenAPI. */ + /** The protocol trait shape ID to use when converting Smithy to OpenAPI. */ public static final String PROTOCOL = "protocol"; /** Whether or not to include tags in the result. */ diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/Context.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/Context.java index b347d34fa68..b49861a0b84 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/Context.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/Context.java @@ -23,34 +23,33 @@ import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.shapes.ServiceShape; import software.amazon.smithy.model.shapes.ToShapeId; -import software.amazon.smithy.model.traits.Protocol; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.OpenApiException; /** * Smithy to OpenAPI conversion context object. */ -public final class Context { +public final class Context { private final Model model; private final ServiceShape service; private final JsonSchemaConverter jsonSchemaConverter; - private final Protocol protocol; - private final OpenApiProtocol openApiProtocol; + private final T protocolTrait; + private final OpenApiProtocol openApiProtocol; private final SchemaDocument schemas; - private final List securitySchemeConverters; + private final List> securitySchemeConverters; public Context( Model model, ServiceShape service, JsonSchemaConverter jsonSchemaConverter, - Protocol protocol, - OpenApiProtocol openApiProtocol, + OpenApiProtocol openApiProtocol, SchemaDocument schemas, - List securitySchemeConverters + List> securitySchemeConverters ) { this.model = model; this.service = service; this.jsonSchemaConverter = jsonSchemaConverter; - this.protocol = protocol; + this.protocolTrait = service.expectTrait(openApiProtocol.getProtocolType()); this.openApiProtocol = openApiProtocol; this.schemas = schemas; this.securitySchemeConverters = securitySchemeConverters; @@ -95,21 +94,12 @@ public JsonSchemaConverter getJsonSchemaConverter() { } /** - * Gets the name of the protocol that is used in the conversion. + * Gets the protocol trait that is being converted. * - * @return Returns the protocol name. + * @return Returns the protocol ID. */ - public String getProtocolName() { - return protocol.getName(); - } - - /** - * Gets the protocols trait protocol being used for the conversion. - * - * @return Returns the protocol being used. - */ - public Protocol getProtocol() { - return protocol; + public T getProtocolTrait() { + return protocolTrait; } /** @@ -117,7 +107,7 @@ public Protocol getProtocol() { * * @return Returns the OpenAPI protocol. */ - public OpenApiProtocol getOpenApiProtocol() { + public OpenApiProtocol getOpenApiProtocol() { return openApiProtocol; } @@ -160,7 +150,7 @@ public Schema createRef(ToShapeId shapeId) { * * @return Returns the security scheme converters. */ - public List getSecuritySchemeConverters() { + public List> getSecuritySchemeConverters() { return securitySchemeConverters; } diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/CoreExtension.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/CoreExtension.java index 9a683a5549e..65fc8e79210 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/CoreExtension.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/CoreExtension.java @@ -17,6 +17,7 @@ import java.util.List; import software.amazon.smithy.jsonschema.JsonSchemaMapper; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.fromsmithy.mappers.CheckForGreedyLabels; import software.amazon.smithy.openapi.fromsmithy.mappers.CheckForPrefixHeaders; import software.amazon.smithy.openapi.fromsmithy.mappers.InlineReferencesToPrimitiveTypes; @@ -37,18 +38,18 @@ */ public final class CoreExtension implements Smithy2OpenApiExtension { @Override - public List getSecuritySchemeConverters() { + public List> getSecuritySchemeConverters() { return ListUtils.of( - new AwsV4(), new HttpBasic(), new HttpBearer(), new HttpDigest(), + new AwsV4(), new XApiKey() ); } @Override - public List getProtocols() { + public List> getProtocols() { return ListUtils.of(new AwsRestJsonProtocol()); } diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/OpenApiConverter.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/OpenApiConverter.java index 9fbc923ca7a..86cb4630904 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/OpenApiConverter.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/OpenApiConverter.java @@ -18,12 +18,11 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Optional; import java.util.ServiceLoader; import java.util.Set; import java.util.logging.Logger; @@ -35,7 +34,7 @@ import software.amazon.smithy.jsonschema.Schema; import software.amazon.smithy.jsonschema.SchemaDocument; import software.amazon.smithy.model.Model; -import software.amazon.smithy.model.knowledge.AuthIndex; +import software.amazon.smithy.model.knowledge.ServiceIndex; import software.amazon.smithy.model.knowledge.TopDownIndex; import software.amazon.smithy.model.node.Node; import software.amazon.smithy.model.node.ObjectNode; @@ -47,9 +46,8 @@ import software.amazon.smithy.model.shapes.ShapeId; import software.amazon.smithy.model.traits.DocumentationTrait; import software.amazon.smithy.model.traits.ExternalDocumentationTrait; -import software.amazon.smithy.model.traits.Protocol; -import software.amazon.smithy.model.traits.ProtocolsTrait; import software.amazon.smithy.model.traits.TitleTrait; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.model.validation.ValidationUtils; import software.amazon.smithy.openapi.OpenApiConstants; import software.amazon.smithy.openapi.OpenApiException; @@ -64,11 +62,8 @@ import software.amazon.smithy.openapi.model.ResponseObject; import software.amazon.smithy.openapi.model.SecurityScheme; import software.amazon.smithy.openapi.model.TagObject; -import software.amazon.smithy.utils.ListUtils; import software.amazon.smithy.utils.MapUtils; import software.amazon.smithy.utils.OptionalUtils; -import software.amazon.smithy.utils.Pair; -import software.amazon.smithy.utils.SetUtils; import software.amazon.smithy.utils.Tagged; /** @@ -80,7 +75,6 @@ public final class OpenApiConverter { private Map settings = new HashMap<>(); private ClassLoader classLoader = OpenApiConverter.class.getClassLoader(); private JsonSchemaConverter jsonSchemaConverter; - private String protocolName; private final List mappers = new ArrayList<>(); private OpenApiConverter() {} @@ -180,14 +174,13 @@ public OpenApiConverter classLoader(ClassLoader classLoader) { } /** - * Sets the name of the protocol to use when converting the model. + * Sets the protocol trait to use when converting the model. * - * @param protocolName Name of the protocol. + * @param protocolTraitId Protocol to use when converting. * @return Returns the OpenApiConverter. */ - public OpenApiConverter protocolName(String protocolName) { - this.protocolName = protocolName; - return this; + public OpenApiConverter protocolTraitId(ShapeId protocolTraitId) { + return putSetting(OpenApiConstants.PROTOCOL, protocolTraitId.toString()); } /** @@ -220,13 +213,24 @@ public OpenApi convert(Model model, ShapeId serviceShapeId) { * @return Returns the converted model. */ public ObjectNode convertToNode(Model model, ShapeId serviceShapeId) { - ConversionEnvironment environment = createConversionEnvironment(model, serviceShapeId); + ConversionEnvironment environment = createConversionEnvironment(model, serviceShapeId); OpenApi openApi = convertWithEnvironment(environment); ObjectNode node = openApi.toNode().expectObjectNode(); return environment.mapper.updateNode(environment.context, openApi, node); } - private ConversionEnvironment createConversionEnvironment(Model model, ShapeId serviceShapeId) { + private ConversionEnvironment createConversionEnvironment(Model model, ShapeId serviceShapeId) { + // Discover OpenAPI extensions. + List extensions = new ArrayList<>(); + + for (Smithy2OpenApiExtension extension : ServiceLoader.load(Smithy2OpenApiExtension.class, classLoader)) { + extensions.add(extension); + // Add JSON schema mappers from found extensions. + for (JsonSchemaMapper mapper : extension.getJsonSchemaMappers()) { + getJsonSchemaConverter().addMapper(mapper); + } + } + // Update the JSON schema config with the settings from this class and // configure it to use OpenAPI settings. ObjectNode.Builder configBuilder = getJsonSchemaConverter() @@ -245,55 +249,68 @@ private ConversionEnvironment createConversionEnvironment(Model model, ShapeId s settings.forEach(configBuilder::withMember); ObjectNode config = configBuilder.build(); - - if (protocolName == null && config.getMember(OpenApiConstants.PROTOCOL).isPresent()) { - protocolName = config.getStringMember(OpenApiConstants.PROTOCOL).get().getValue(); - } - - // Discover OpenAPI extensions. - List extensions = new ArrayList<>(); - ServiceLoader.load(Smithy2OpenApiExtension.class, classLoader).forEach(extensions::add); - - // Add JSON schema mappers from found extensions. - extensions.forEach(extension -> extension.getJsonSchemaMappers().forEach(jsonSchemaConverter::addMapper)); - - Pair protocolPair = resolveProtocol(service, extensions); - Protocol resolvedProtocol = protocolPair.getLeft(); - OpenApiProtocol openApiProtocol = protocolPair.getRight(); - LOGGER.info(() -> "Resolved " + resolvedProtocol.getName() + " OpenAPI protocol"); + Trait protocolTrait = loadOrDeriveProtocolTrait(model, service, config); + OpenApiProtocol openApiProtocol = loadOpenApiProtocol(service, protocolTrait, extensions); // Merge in protocol default values. - for (Map.Entry entry : openApiProtocol.getDefaultSettings().getStringMap().entrySet()) { - if (!config.getMember(entry.getKey()).isPresent()) { - config = config.withMember(entry.getKey(), entry.getValue()); - } - } + config = openApiProtocol.getDefaultSettings().merge(config); getJsonSchemaConverter().config(config); - - // Set a protocol name if one wasn't set but instead derived. - protocolName = protocolName != null ? protocolName : resolvedProtocol.getName(); ComponentsObject.Builder components = ComponentsObject.builder(); SchemaDocument schemas = addSchemas(components, model, service); // Load security scheme converters. - List securitySchemeConverters = loadSecuritySchemes(service, extensions); + List> securitySchemeConverters = loadSecuritySchemes( + model, service, extensions); - Context context = new Context( + Context context = new Context<>( model, service, getJsonSchemaConverter(), - resolvedProtocol, openApiProtocol, schemas, securitySchemeConverters); + openApiProtocol, schemas, securitySchemeConverters); + + return new ConversionEnvironment<>(context, extensions, components, mappers); + } + + // Gets the protocol configured in `protocol` if set. + // + // If not set, defaults to the protocol applied to the service IFF the service + // defines a single protocol. + // + // If the derived protocol trait cannot be found on the service, an exception + // is thrown. + private Trait loadOrDeriveProtocolTrait(Model model, ServiceShape service, ObjectNode config) { + ServiceIndex serviceIndex = model.getKnowledge(ServiceIndex.class); + Set serviceProtocols = serviceIndex.getProtocols(service).keySet(); + ShapeId protocolTraitId; + + if (config.getMember(OpenApiConstants.PROTOCOL).isPresent()) { + protocolTraitId = config.expectStringMember(OpenApiConstants.PROTOCOL).expectShapeId(); + } else if (serviceProtocols.isEmpty()) { + throw new OpenApiException(String.format( + "No Smithy protocol was configured and `%s` does not define any protocols.", + service.getId())); + } else if (serviceProtocols.size() > 1) { + throw new OpenApiException(String.format( + "No Smithy protocol was configured and `%s` defines multiple protocols: %s", + service.getId(), serviceProtocols)); + } else { + protocolTraitId = serviceProtocols.iterator().next(); + } - return new ConversionEnvironment(context, extensions, components, mappers); + return service.findTrait(protocolTraitId).orElseThrow(() -> { + return new OpenApiException(String.format( + "Unable to find protocol `%s` on service `%s`. This service supports the following protocols: %s", + protocolTraitId, service.getId(), serviceProtocols)); + }); } - private static final class ConversionEnvironment { - private final Context context; + private static final class ConversionEnvironment { + private final Context context; private final List extensions; private final ComponentsObject.Builder components; private final OpenApiMapper mapper; private ConversionEnvironment( - Context context, + Context context, List extensions, ComponentsObject.Builder components, List mappers @@ -312,11 +329,11 @@ private OpenApiMapper createMapper(List mappers) { } } - private OpenApi convertWithEnvironment(ConversionEnvironment environment) { + private OpenApi convertWithEnvironment(ConversionEnvironment environment) { ServiceShape service = environment.context.getService(); - Context context = environment.context; + Context context = environment.context; OpenApiMapper mapper = environment.mapper; - OpenApiProtocol openApiProtocol = environment.context.getOpenApiProtocol(); + OpenApiProtocol openApiProtocol = environment.context.getOpenApiProtocol(); OpenApi.Builder openapi = OpenApi.builder().openapi(OpenApiConstants.VERSION).info(createInfo(service)); mapper.before(context, openapi); @@ -346,66 +363,53 @@ private JsonSchemaConverter getJsonSchemaConverter() { return jsonSchemaConverter; } - // Determine which OpenApiProtocol service provider and which service trait protocol to use. - private Pair resolveProtocol( + // Find the corresponding protocol OpenApiProtocol service provider. + @SuppressWarnings("unchecked") + private OpenApiProtocol loadOpenApiProtocol( ServiceShape service, + T protocolTrait, List extensions ) { - List protocols = extensions.stream() - .flatMap(extension -> extension.getProtocols().stream()) + // Collect into a list so that a better error message can be presented if the + // protocol converter can't be found. + List protocolProviders = extensions.stream() + .flatMap(e -> e.getProtocols().stream()) .collect(Collectors.toList()); - ProtocolsTrait protoTrait = service.getTrait(ProtocolsTrait.class) - .orElseThrow(() -> new OpenApiException("No `protocols` trait found on `" + service.getId() + "`")); - - if (protocolName == null) { - for (Protocol protocolEntry : protoTrait.getProtocols()) { - Optional maybeProtocol = findProtocol(protocolEntry.getName(), protocols); - if (maybeProtocol.isPresent()) { - return Pair.of(protocolEntry, maybeProtocol.get()); - } - } - } else if (protoTrait.getProtocol(protocolName).isPresent()) { - Optional maybeProtocol = findProtocol(protocolName, protocols); - if (maybeProtocol.isPresent()) { - return Pair.of(protoTrait.getProtocol(protocolName).get(), maybeProtocol.get()); - } - } - - throw new OpenApiException(String.format( - "Unable to resolve a supported protocol for service: `%s`. Protocol service providers were " - + "found for the following protocols: [%s]. But this service supports the following " - + "protocols: [%s]", - service.getId(), - ValidationUtils.tickedList(protocols.stream().flatMap(p -> p.getProtocolNames().stream())), - ValidationUtils.tickedList(protoTrait.getProtocolNames()))); - } - - // Finds an OpenAPI protocol matching the given protocol name. - private Optional findProtocol(String protocolName, List protocols) { - return protocols.stream() - .filter(protocol -> protocol.getProtocolNames().contains(protocolName)) - .findFirst(); + return protocolProviders.stream() + .filter(openApiProtocol -> openApiProtocol.getProtocolType().equals(protocolTrait.getClass())) + .findFirst() + .map(result -> (OpenApiProtocol) result) + .orElseThrow(() -> { + Stream supportedProtocols = protocolProviders.stream() + .map(OpenApiProtocol::getProtocolType) + .map(Class::getCanonicalName); + return new OpenApiException(String.format( + "Unable to find an OpenAPI service provider for the `%s` protocol when converting `%s`. " + + "Protocol service providers were found for the following protocol classes: [%s].", + protocolTrait.toShapeId(), + service.getId(), + ValidationUtils.tickedList(supportedProtocols))); + }); } // Loads all of the OpenAPI security scheme implementations that are referenced by a service. - private List loadSecuritySchemes( + private List> loadSecuritySchemes( + Model model, ServiceShape service, List extensions ) { - List converters = extensions.stream() + // Note: Using a LinkedHashSet here in case order is ever important. + ServiceIndex serviceIndex = model.getKnowledge(ServiceIndex.class); + Set> schemes = getTraitMapTypes(serviceIndex.getAuthSchemes(service)); + + List> converters = extensions.stream() .flatMap(extension -> extension.getSecuritySchemeConverters().stream()) .collect(Collectors.toList()); - // Get auth schemes of a specific protocol. - Set schemes = new HashSet<>(service.getTrait(ProtocolsTrait.class) - .flatMap(trait -> trait.getProtocol(protocolName)) - .map(Protocol::getAuth) - .orElse(ListUtils.of())); - List resolved = new ArrayList<>(); - - for (SecuritySchemeConverter converter: converters) { - if (schemes.remove(converter.getAuthSchemeName())) { + List> resolved = new ArrayList<>(); + for (SecuritySchemeConverter converter : converters) { + if (schemes.remove(converter.getAuthSchemeType())) { resolved.add(converter); } } @@ -454,10 +458,10 @@ private SchemaDocument addSchemas( return document; } - private void addPaths( - Context context, + private void addPaths( + Context context, OpenApi.Builder openApiBuilder, - OpenApiProtocol protocolService, + OpenApiProtocol protocolService, OpenApiMapper plugin ) { TopDownIndex topDownIndex = context.getModel().getKnowledge(TopDownIndex.class); @@ -512,7 +516,10 @@ private void addPaths( } }, () -> LOGGER.warning(String.format( "The `%s` operation is not supported by the `%s` protocol (implemented by `%s`), and " - + "was omitted", shape.getId(), protocolService.getClass().getName(), context.getProtocolName())) + + "was omitted", + shape.getId(), + protocolService.getClass().getName(), + context.getProtocolTrait().toShapeId())) ); }); @@ -524,24 +531,28 @@ private void addPaths( } } - private void addOperationSecurity( - Context context, + private void addOperationSecurity( + Context context, OperationObject.Builder builder, OperationShape shape, OpenApiMapper plugin ) { ServiceShape service = context.getService(); - AuthIndex auth = context.getModel().getKnowledge(AuthIndex.class); - List serviceSchemes = auth.getDefaultServiceSchemes(service); - // Note: the eligible schemes have already been filtered for the protocol, so no need to do that here. - List operationSchemes = auth.getOperationSchemes(service, shape, context.getProtocolName()); + ServiceIndex serviceIndex = context.getModel().getKnowledge(ServiceIndex.class); + Map serviceSchemes = serviceIndex.getEffectiveAuthSchemes(service); + Map operationSchemes = serviceIndex.getEffectiveAuthSchemes(service, shape); // Add a security requirement for the operation if it differs from the service. - if (!SetUtils.copyOf(serviceSchemes).equals(SetUtils.copyOf(operationSchemes))) { - for (SecuritySchemeConverter converter : findMatchingConverters(context, operationSchemes)) { - List result = converter.createSecurityRequirements(context, context.getService()); - Map> requirement = plugin.updateSecurity( - context, shape, converter, MapUtils.of(converter.getAuthSchemeName(), result)); + if (!operationSchemes.equals(serviceSchemes)) { + Collection> authSchemeClasses = getTraitMapTypes(operationSchemes); + // Find all the converters with matching types of auth traits on the service. + Collection> converters = findMatchingConverters( + context, authSchemeClasses); + for (SecuritySchemeConverter converter : converters) { + List result = createSecurityRequirements(context, converter, service); + String openApiAuthName = converter.getAuthSchemeId().toString(); + Map> authMap = MapUtils.of(openApiAuthName, result); + Map> requirement = plugin.updateSecurity(context, shape, converter, authMap); if (requirement != null) { builder.addSecurity(requirement); } @@ -549,6 +560,18 @@ private void addOperationSecurity( } } + // This method exists primarily to appease the type-checker. + private

List createSecurityRequirements( + Context

context, + SecuritySchemeConverter converter, + ServiceShape service + ) { + return converter.createSecurityRequirements( + context, + service.expectTrait(converter.getAuthSchemeType()), + context.getService()); + } + private OperationObject addOperationTags(Context context, Shape shape, OperationObject operation) { // Include @tags trait tags of the operation that are compatible with OpenAPI settings. if (context.getConfig().getBooleanMemberOrDefault(OpenApiConstants.OPEN_API_TAGS)) { @@ -562,8 +585,8 @@ private OperationObject addOperationTags(Context context, Shape shape, Operation } // Applies mappers to parameters and updates the operation if parameters change. - private OperationObject updateParameters( - Context context, + private OperationObject updateParameters( + Context context, OperationShape shape, OperationObject operation, OpenApiMapper plugin @@ -579,8 +602,8 @@ private OperationObject updateParameters( } // Applies mappers to each request body and update the operation if the body changes. - private OperationObject updateRequestBody( - Context context, + private OperationObject updateRequestBody( + Context context, OperationShape shape, OperationObject operation, OpenApiMapper plugin @@ -597,8 +620,8 @@ private OperationObject updateRequestBody( // Ensures that responses have at least one entry, and applies mappers to // responses and updates the operation is a response changes. - private OperationObject updateResponses( - Context context, + private OperationObject updateResponses( + Context context, OperationShape shape, OperationObject operation, OpenApiMapper plugin @@ -620,48 +643,72 @@ private OperationObject updateResponses( newResponses.put(status, responseObject); } - return !newResponses.equals(operation.getResponses()) - ? operation.toBuilder().responses(newResponses).build() - : operation; + if (newResponses.equals(operation.getResponses())) { + return operation; + } else { + return operation.toBuilder().responses(newResponses).build(); + } } - private void addSecurityComponents( - Context context, + private void addSecurityComponents( + Context context, OpenApi.Builder openApiBuilder, ComponentsObject.Builder components, OpenApiMapper plugin ) { - OptionalUtils.ifPresentOrElse( - context.getService().getTrait(ProtocolsTrait.class), - trait -> { - for (SecuritySchemeConverter converter : context.getSecuritySchemeConverters()) { - String authName = converter.getAuthSchemeName(); - SecurityScheme createdScheme = converter.createSecurityScheme(context); - SecurityScheme scheme = plugin.updateSecurityScheme(context, authName, createdScheme); - if (scheme != null) { - components.putSecurityScheme(authName, scheme); - } - } - }, - () -> LOGGER.warning("No `protocols` trait found on service while converting to OpenAPI") - ); - - // Add service-wide security requirements. - AuthIndex authIndex = context.getModel().getKnowledge(AuthIndex.class); - List schemes = authIndex.getDefaultServiceSchemes(context.getService()); - for (SecuritySchemeConverter converter : findMatchingConverters(context, schemes)) { - List result = converter.createSecurityRequirements(context, context.getService()); - Map> requirement = plugin.updateSecurity( - context, context.getService(), converter, MapUtils.of(converter.getAuthSchemeName(), result)); - if (requirement != null) { - openApiBuilder.addSecurity(requirement); + ServiceShape service = context.getService(); + ServiceIndex serviceIndex = context.getModel().getKnowledge(ServiceIndex.class); + + // Create security components for each referenced security scheme. + for (SecuritySchemeConverter converter : context.getSecuritySchemeConverters()) { + SecurityScheme createdScheme = createAndUpdateSecurityScheme(context, plugin, converter, service); + if (createdScheme != null) { + components.putSecurityScheme(converter.getAuthSchemeId().toString(), createdScheme); + } + } + + // Assign the components to the "security" of the service. This is only the + // auth schemes that apply by default across the entire service. + Map authTraitMap = serviceIndex.getEffectiveAuthSchemes(context.getService()); + Collection> defaultAuthTraits = getTraitMapTypes(authTraitMap); + + for (SecuritySchemeConverter converter : context.getSecuritySchemeConverters()) { + if (defaultAuthTraits.contains(converter.getAuthSchemeType())) { + List result = createSecurityRequirements(context, converter, context.getService()); + String authSchemeName = converter.getAuthSchemeId().toString(); + Map> requirement = plugin.updateSecurity( + context, context.getService(), converter, MapUtils.of(authSchemeName, result)); + if (requirement != null) { + openApiBuilder.addSecurity(requirement); + } } } } - private Collection findMatchingConverters(Context context, Collection schemes) { + private Set> getTraitMapTypes(Map traitMap) { + return traitMap.values().stream().map(Trait::getClass).collect(Collectors.toCollection(LinkedHashSet::new)); + } + + // This method exists primarily to appease the type-checker. + private

SecurityScheme createAndUpdateSecurityScheme( + Context

context, + OpenApiMapper plugin, + SecuritySchemeConverter converter, + ServiceShape service + ) { + A authTrait = service.expectTrait(converter.getAuthSchemeType()); + SecurityScheme createdScheme = converter.createSecurityScheme(context, authTrait); + return plugin.updateSecurityScheme(context, authTrait, createdScheme); + } + + @SuppressWarnings("unchecked") + private Collection> findMatchingConverters( + Context context, + Collection> schemes + ) { return context.getSecuritySchemeConverters().stream() - .filter(converter -> schemes.contains(converter.getAuthSchemeName())) + .filter(converter -> schemes.contains(converter.getAuthSchemeType())) + .map(converter -> (SecuritySchemeConverter) converter) .collect(Collectors.toList()); } } diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/OpenApiMapper.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/OpenApiMapper.java index 7f761d9bfbc..ff91b543a9a 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/OpenApiMapper.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/OpenApiMapper.java @@ -22,6 +22,7 @@ import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.shapes.OperationShape; import software.amazon.smithy.model.shapes.Shape; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.model.OpenApi; import software.amazon.smithy.openapi.model.OperationObject; import software.amazon.smithy.openapi.model.ParameterObject; @@ -62,7 +63,11 @@ default byte getOrder() { * @param operation OperationObject being built. * @return Returns the updated operation object. */ - default OperationObject updateOperation(Context context, OperationShape shape, OperationObject operation) { + default OperationObject updateOperation( + Context context, + OperationShape shape, + OperationObject operation + ) { return operation; } @@ -74,7 +79,7 @@ default OperationObject updateOperation(Context context, OperationShape shape, O * @param pathItem Path item being converted. * @return Returns the updated path item. */ - default PathItem updatePathItem(Context context, String path, PathItem pathItem) { + default PathItem updatePathItem(Context context, String path, PathItem pathItem) { return pathItem; } @@ -87,7 +92,7 @@ default PathItem updatePathItem(Context context, String path, PathItem pathItem) * @return Returns the updated parameter. */ default ParameterObject updateParameter( - Context context, + Context context, OperationShape operation, ParameterObject parameterObject ) { @@ -103,7 +108,7 @@ default ParameterObject updateParameter( * @return Returns the updated request body. */ default RequestBodyObject updateRequestBody( - Context context, + Context context, OperationShape shape, RequestBodyObject requestBody ) { @@ -120,7 +125,7 @@ default RequestBodyObject updateRequestBody( * @return Returns the updated response object. */ default ResponseObject updateResponse( - Context context, + Context context, String status, OperationShape shape, ResponseObject response @@ -134,17 +139,21 @@ default ResponseObject updateResponse( * @param context Conversion context. * @param builder OpenAPI builder to modify. */ - default void before(Context context, OpenApi.Builder builder) {} + default void before(Context context, OpenApi.Builder builder) {} /** * Updates a security scheme object. * * @param context Conversion context. - * @param authName Smithy authentication scheme name. + * @param authTrait Smithy authentication scheme trait. * @param securityScheme Security scheme object to update. * @return Returns the updated security scheme object. Return null to remove the scheme. */ - default SecurityScheme updateSecurityScheme(Context context, String authName, SecurityScheme securityScheme) { + default SecurityScheme updateSecurityScheme( + Context context, + Trait authTrait, + SecurityScheme securityScheme + ) { return securityScheme; } @@ -163,9 +172,9 @@ default SecurityScheme updateSecurityScheme(Context context, String authName, Se * @return Returns the updated security requirement, a mapping of scheme to requirements. */ default Map> updateSecurity( - Context context, + Context context, Shape shape, - SecuritySchemeConverter converter, + SecuritySchemeConverter converter, Map> requirement ) { return requirement; @@ -178,7 +187,7 @@ default Map> updateSecurity( * @param openapi OpenAPI object to modify. * @return Returns the updated OpenApi object. */ - default OpenApi after(Context context, OpenApi openapi) { + default OpenApi after(Context context, OpenApi openapi) { return openapi; } @@ -190,7 +199,7 @@ default OpenApi after(Context context, OpenApi openapi) { * @param node OpenAPI object node. * @return Returns the updated ObjectNode. */ - default ObjectNode updateNode(Context context, OpenApi openapi, ObjectNode node) { + default ObjectNode updateNode(Context context, OpenApi openapi, ObjectNode node) { return node; } @@ -206,7 +215,11 @@ static OpenApiMapper compose(List mappers) { return new OpenApiMapper() { @Override - public OperationObject updateOperation(Context context, OperationShape shape, OperationObject operation) { + public OperationObject updateOperation( + Context context, + OperationShape shape, + OperationObject operation + ) { for (OpenApiMapper plugin : sorted) { if (operation == null) { return null; @@ -217,7 +230,7 @@ public OperationObject updateOperation(Context context, OperationShape shape, Op } @Override - public PathItem updatePathItem(Context context, String path, PathItem pathItem) { + public PathItem updatePathItem(Context context, String path, PathItem pathItem) { for (OpenApiMapper plugin : sorted) { if (pathItem == null) { return null; @@ -229,7 +242,7 @@ public PathItem updatePathItem(Context context, String path, PathItem pathItem) @Override public ParameterObject updateParameter( - Context context, + Context context, OperationShape operation, ParameterObject parameterObject ) { @@ -244,7 +257,7 @@ public ParameterObject updateParameter( @Override public RequestBodyObject updateRequestBody( - Context context, + Context context, OperationShape shape, RequestBodyObject requestBody ) { @@ -259,7 +272,7 @@ public RequestBodyObject updateRequestBody( @Override public ResponseObject updateResponse( - Context context, + Context context, String status, OperationShape shape, ResponseObject response @@ -274,21 +287,25 @@ public ResponseObject updateResponse( } @Override - public SecurityScheme updateSecurityScheme(Context context, String name, SecurityScheme securityScheme) { + public SecurityScheme updateSecurityScheme( + Context context, + Trait authTrait, + SecurityScheme securityScheme + ) { for (OpenApiMapper plugin : sorted) { if (securityScheme == null) { return null; } - securityScheme = plugin.updateSecurityScheme(context, name, securityScheme); + securityScheme = plugin.updateSecurityScheme(context, authTrait, securityScheme); } return securityScheme; } @Override public Map> updateSecurity( - Context context, + Context context, Shape shape, - SecuritySchemeConverter converter, + SecuritySchemeConverter converter, Map> requirement ) { for (OpenApiMapper plugin : sorted) { @@ -302,14 +319,14 @@ public Map> updateSecurity( } @Override - public void before(Context context, OpenApi.Builder builder) { + public void before(Context context, OpenApi.Builder builder) { for (OpenApiMapper plugin : sorted) { plugin.before(context, builder); } } @Override - public OpenApi after(Context context, OpenApi openapi) { + public OpenApi after(Context context, OpenApi openapi) { for (OpenApiMapper plugin : sorted) { openapi = plugin.after(context, openapi); } @@ -317,7 +334,7 @@ public OpenApi after(Context context, OpenApi openapi) { } @Override - public ObjectNode updateNode(Context context, OpenApi openapi, ObjectNode node) { + public ObjectNode updateNode(Context context, OpenApi openapi, ObjectNode node) { for (OpenApiMapper plugin : sorted) { node = plugin.updateNode(context, openapi, node); } diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/OpenApiProtocol.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/OpenApiProtocol.java index ef19dd8c66d..673745cf445 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/OpenApiProtocol.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/OpenApiProtocol.java @@ -24,6 +24,7 @@ import software.amazon.smithy.model.shapes.OperationShape; import software.amazon.smithy.model.shapes.ToShapeId; import software.amazon.smithy.model.traits.HttpTrait; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.OpenApiException; import software.amazon.smithy.openapi.model.OpenApi; import software.amazon.smithy.openapi.model.OperationObject; @@ -35,15 +36,17 @@ * *

Instances of {@code OpenApiProtocol} are discovered using SPI and * matched with configuration settings based on the result of matching - * a protocol against {@link #getProtocolNames()}. + * a protocol against {@link #getProtocolType()}. + * + * @param Type of Smithy protocol to convert. */ -public interface OpenApiProtocol { +public interface OpenApiProtocol { /** - * Gets the names of the protocol that this implementation supports. + * Gets the protocol type that this converter handles. * - * @return Returns the supported protocol names. + * @return Returns the shape ID. */ - Set getProtocolNames(); + Class getProtocolType(); /** * Configures protocol-specific default values when they are not present @@ -69,7 +72,7 @@ default ObjectNode getDefaultSettings() { * @param operation The operation shape to create. * @return Returns the optionally created operation entry. */ - Optional createOperation(Context context, OperationShape operation); + Optional createOperation(Context context, OperationShape operation); /** * Gets the URI of an operation. @@ -82,7 +85,7 @@ default ObjectNode getDefaultSettings() { * @param operation The operation to get the URI of. * @return Returns the operation URI. */ - default String getOperationUri(Context context, OperationShape operation) { + default String getOperationUri(Context context, OperationShape operation) { return operation.getTrait(HttpTrait.class) .map(HttpTrait::getUri) .map(UriPattern::toString) @@ -102,7 +105,7 @@ default String getOperationUri(Context context, OperationShape operation) { * @param operation The operation to get the method of. * @return Returns the method. */ - default String getOperationMethod(Context context, OperationShape operation) { + default String getOperationMethod(Context context, OperationShape operation) { return operation.getTrait(HttpTrait.class) .map(HttpTrait::getMethod) .orElseThrow(() -> new OpenApiException( @@ -120,7 +123,7 @@ default String getOperationMethod(Context context, OperationShape operation) { * @param operationOrError Operation or error shape ID. * @return Returns the status code as a string. */ - default String getOperationResponseStatusCode(Context context, ToShapeId operationOrError) { + default String getOperationResponseStatusCode(Context context, ToShapeId operationOrError) { return String.valueOf(context.getModel() .getKnowledge(HttpBindingIndex.class) .getResponseCode(operationOrError)); @@ -137,7 +140,7 @@ default String getOperationResponseStatusCode(Context context, ToShapeId operati * @param operationShape Smithy operation * @return Returns a set of header names. */ - default Set getProtocolRequestHeaders(Context context, OperationShape operationShape) { + default Set getProtocolRequestHeaders(Context context, OperationShape operationShape) { return SetUtils.of(); } @@ -152,7 +155,7 @@ default Set getProtocolRequestHeaders(Context context, OperationShape op * @param operationShape Smithy operation * @return Returns a set of header names. */ - default Set getProtocolResponseHeaders(Context context, OperationShape operationShape) { + default Set getProtocolResponseHeaders(Context context, OperationShape operationShape) { return SetUtils.of(); } diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/SecuritySchemeConverter.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/SecuritySchemeConverter.java index 6d91fe4125b..6d33a5f5cc4 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/SecuritySchemeConverter.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/SecuritySchemeConverter.java @@ -18,6 +18,8 @@ import java.util.List; import java.util.Set; import software.amazon.smithy.model.shapes.Shape; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.model.SecurityScheme; import software.amazon.smithy.utils.ListUtils; import software.amazon.smithy.utils.SetUtils; @@ -27,24 +29,46 @@ * scheme and applies security requirements to operations. * *

Implementations of this interface are discovered using Java SPI. + * + * @param the auth scheme trait to convert. */ -public interface SecuritySchemeConverter { +public interface SecuritySchemeConverter { /** - * Get the name of the Smithy auth scheme that matches this converter. + * Get the U that matches this converter. * - * @return The Smithy security auth scheme name. + * @return The Smithy security auth scheme ID. */ - String getAuthSchemeName(); + Class getAuthSchemeType(); + + /** + * Gets the shape ID of the auth scheme type. + * + *

By default, this operation uses reflection to get the value of + * a static property of the auth scheme class named "ID". If that is + * not how a specific auth scheme class is implemented, then this + * method must be overridden. + * + * @return Returns the auth scheme's shape ID. + */ + default ShapeId getAuthSchemeId() { + try { + Class type = getAuthSchemeType(); + return (ShapeId) type.getField("ID").get(null); + } catch (ReflectiveOperationException e) { + throw new RuntimeException("Unable to find an ID property on " + getAuthSchemeType().getName()); + } + } /** * Creates an OpenAPI security scheme. * * @param context Conversion context. + * @param authTrait Authentication trait to convert. * @return The generated security scheme * * @see Security Scheme Object */ - SecurityScheme createSecurityScheme(Context context); + SecurityScheme createSecurityScheme(Context context, T authTrait); /** * Creates a "security" requirements property to apply to an operation @@ -53,10 +77,11 @@ public interface SecuritySchemeConverter { *

The default implementation will return an empty list. * * @param context OpenAPI context + * @param authTrait Authentication trait to convert. * @param shape Service or operation shape. * @return The security requirements value. */ - default List createSecurityRequirements(Context context, Shape shape) { + default List createSecurityRequirements(Context context, T authTrait, Shape shape) { return ListUtils.of(); } diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/Smithy2OpenApiExtension.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/Smithy2OpenApiExtension.java index 54e399e3c78..a56f2997ab7 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/Smithy2OpenApiExtension.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/Smithy2OpenApiExtension.java @@ -17,6 +17,7 @@ import java.util.List; import software.amazon.smithy.jsonschema.JsonSchemaMapper; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.utils.ListUtils; /** @@ -31,7 +32,7 @@ public interface Smithy2OpenApiExtension { * * @return Returns the converters to register. */ - default List getSecuritySchemeConverters() { + default List> getSecuritySchemeConverters() { return ListUtils.of(); } @@ -41,7 +42,7 @@ default List getSecuritySchemeConverters() { * * @return Returns the protocols to register. */ - default List getProtocols() { + default List> getProtocols() { return ListUtils.of(); } diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/CheckForGreedyLabels.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/CheckForGreedyLabels.java index dada4ef4606..ed3101bf2cd 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/CheckForGreedyLabels.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/CheckForGreedyLabels.java @@ -16,6 +16,7 @@ package software.amazon.smithy.openapi.fromsmithy.mappers; import java.util.logging.Logger; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.OpenApiConstants; import software.amazon.smithy.openapi.OpenApiException; import software.amazon.smithy.openapi.fromsmithy.Context; @@ -37,7 +38,7 @@ public byte getOrder() { } @Override - public OpenApi after(Context context, OpenApi openApi) { + public OpenApi after(Context context, OpenApi openApi) { boolean forbid = context.getConfig().getBooleanMemberOrDefault(OpenApiConstants.FORBID_GREEDY_LABELS); for (String path : openApi.getPaths().keySet()) { diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/CheckForPrefixHeaders.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/CheckForPrefixHeaders.java index 0957c274a41..9c526558144 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/CheckForPrefixHeaders.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/CheckForPrefixHeaders.java @@ -22,6 +22,7 @@ import software.amazon.smithy.model.shapes.MemberShape; import software.amazon.smithy.model.shapes.OperationShape; import software.amazon.smithy.model.shapes.ToShapeId; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.OpenApiConstants; import software.amazon.smithy.openapi.OpenApiException; import software.amazon.smithy.openapi.fromsmithy.Context; @@ -46,7 +47,7 @@ public byte getOrder() { } @Override - public void before(Context context, OpenApi.Builder builder) { + public void before(Context context, OpenApi.Builder builder) { HttpBindingIndex httpBindings = context.getModel().getKnowledge(HttpBindingIndex.class); context.getModel().shapes(OperationShape.class).forEach(operation -> { check(context, httpBindings.getRequestBindings(operation, HttpBinding.Location.PREFIX_HEADERS)); @@ -55,11 +56,15 @@ public void before(Context context, OpenApi.Builder builder) { }); } - private void checkForResponseHeaders(Context context, HttpBindingIndex bindingIndex, ToShapeId shapeId) { + private void checkForResponseHeaders( + Context context, + HttpBindingIndex bindingIndex, + ToShapeId shapeId + ) { check(context, bindingIndex.getResponseBindings(shapeId, HttpBinding.Location.PREFIX_HEADERS)); } - private void check(Context context, List bindings) { + private void check(Context context, List bindings) { String setting = context.getConfig().getStringMemberOrDefault( OpenApiConstants.ON_HTTP_PREFIX_HEADERS, OpenApiConstants.ON_HTTP_PREFIX_HEADERS_FAIL); diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/InlineReferencesToPrimitiveTypes.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/InlineReferencesToPrimitiveTypes.java index 5e8e9c8296f..9811e05c037 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/InlineReferencesToPrimitiveTypes.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/InlineReferencesToPrimitiveTypes.java @@ -24,6 +24,7 @@ import software.amazon.smithy.model.node.NodeVisitor; import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.node.StringNode; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.OpenApiConstants; import software.amazon.smithy.openapi.fromsmithy.Context; import software.amazon.smithy.openapi.fromsmithy.OpenApiMapper; @@ -63,7 +64,7 @@ public byte getOrder() { } @Override - public ObjectNode updateNode(Context context, OpenApi openapi, ObjectNode node) { + public ObjectNode updateNode(Context context, OpenApi openapi, ObjectNode node) { if (context.getConfig().getBooleanMemberOrDefault(OpenApiConstants.DISABLE_PRIMITIVE_INLINING)) { return node; diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/OpenApiJsonSubstitutions.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/OpenApiJsonSubstitutions.java index 6f87341909d..0c6fc5bfc4a 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/OpenApiJsonSubstitutions.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/OpenApiJsonSubstitutions.java @@ -17,6 +17,7 @@ import software.amazon.smithy.build.JsonSubstitutions; import software.amazon.smithy.model.node.ObjectNode; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.OpenApiConstants; import software.amazon.smithy.openapi.fromsmithy.Context; import software.amazon.smithy.openapi.fromsmithy.OpenApiMapper; @@ -33,7 +34,7 @@ public byte getOrder() { } @Override - public ObjectNode updateNode(Context context, OpenApi openapi, ObjectNode node) { + public ObjectNode updateNode(Context context, OpenApi openapi, ObjectNode node) { return context.getConfig().getObjectMember(OpenApiConstants.SUBSTITUTIONS) .map(substitutions -> JsonSubstitutions.create(substitutions).apply(node).expectObjectNode()) .orElse(node); diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/RemoveEmptyComponents.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/RemoveEmptyComponents.java index 0555e78e94c..94991eef60f 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/RemoveEmptyComponents.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/RemoveEmptyComponents.java @@ -18,6 +18,7 @@ import java.util.Map; import software.amazon.smithy.model.node.Node; import software.amazon.smithy.model.node.ObjectNode; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.fromsmithy.Context; import software.amazon.smithy.openapi.fromsmithy.OpenApiMapper; import software.amazon.smithy.openapi.model.OpenApi; @@ -35,7 +36,7 @@ public byte getOrder() { } @Override - public ObjectNode updateNode(Context context, OpenApi openapi, ObjectNode node) { + public ObjectNode updateNode(Context context, OpenApi openapi, ObjectNode node) { ObjectNode components = node.getObjectMember(COMPONENTS).orElse(null); if (components == null) { diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/RemoveUnusedComponents.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/RemoveUnusedComponents.java index c3703265535..f921cc05610 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/RemoveUnusedComponents.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/RemoveUnusedComponents.java @@ -28,6 +28,7 @@ import software.amazon.smithy.model.node.NodeVisitor; import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.node.StringNode; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.OpenApiConstants; import software.amazon.smithy.openapi.fromsmithy.Context; import software.amazon.smithy.openapi.fromsmithy.OpenApiMapper; @@ -55,7 +56,7 @@ public byte getOrder() { } @Override - public OpenApi after(Context context, OpenApi openapi) { + public OpenApi after(Context context, OpenApi openapi) { if (context.getConfig().getBooleanMemberOrDefault(OpenApiConstants.OPENAPI_KEEP_UNUSED_COMPONENTS)) { return openapi; } diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/UnsupportedTraits.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/UnsupportedTraits.java index e99d88a8410..051b5f0100f 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/UnsupportedTraits.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/mappers/UnsupportedTraits.java @@ -20,6 +20,7 @@ import java.util.logging.Logger; import java.util.stream.Collectors; import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.OpenApiConstants; import software.amazon.smithy.openapi.OpenApiException; import software.amazon.smithy.openapi.fromsmithy.Context; @@ -43,7 +44,7 @@ public byte getOrder() { } @Override - public void before(Context context, OpenApi.Builder builder) { + public void before(Context context, OpenApi.Builder builder) { List>> violations = context.getModel().shapes() .map(shape -> Pair.of(shape.getId(), TRAITS.stream() .filter(trait -> shape.findTrait(trait).isPresent()) diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/protocols/AbstractRestProtocol.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/protocols/AbstractRestProtocol.java index 264b5171c1c..394d08f15d9 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/protocols/AbstractRestProtocol.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/protocols/AbstractRestProtocol.java @@ -41,6 +41,7 @@ import software.amazon.smithy.model.traits.HttpTrait; import software.amazon.smithy.model.traits.MediaTypeTrait; import software.amazon.smithy.model.traits.TimestampFormatTrait; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.fromsmithy.Context; import software.amazon.smithy.openapi.fromsmithy.OpenApiProtocol; import software.amazon.smithy.openapi.model.MediaTypeObject; @@ -67,7 +68,7 @@ *

This class is currently package-private, but may be made public in the * future when we're sure about its API. */ -abstract class AbstractRestProtocol implements OpenApiProtocol { +abstract class AbstractRestProtocol implements OpenApiProtocol { /** The type of message being created. */ enum MessageType { REQUEST, RESPONSE, ERROR } @@ -84,7 +85,7 @@ enum MessageType { REQUEST, RESPONSE, ERROR } * @param messageType The type of message being created (request, response, or error). * @return Returns the media type of the document payload. */ - abstract String getDocumentMediaType(Context context, Shape operationOrError, MessageType messageType); + abstract String getDocumentMediaType(Context context, Shape operationOrError, MessageType messageType); /** * Creates a schema to send a document payload in the request, @@ -97,13 +98,14 @@ enum MessageType { REQUEST, RESPONSE, ERROR } * @return Returns the created document schema. */ abstract Schema createDocumentSchema( - Context context, + Context context, Shape operationOrError, List bindings, - MessageType messageType); + MessageType messageType + ); @Override - public Optional createOperation(Context context, OperationShape operation) { + public Optional createOperation(Context context, OperationShape operation) { return operation.getTrait(HttpTrait.class).map(httpTrait -> { String method = context.getOpenApiProtocol().getOperationMethod(context, operation); String uri = context.getOpenApiProtocol().getOperationUri(context, operation); @@ -118,7 +120,7 @@ public Optional createOperation(Context context, OperationShape opera }); } - private List createPathParameters(Context context, OperationShape operation) { + private List createPathParameters(Context context, OperationShape operation) { return context.getModel().getKnowledge(HttpBindingIndex.class) .getRequestBindings(operation, HttpBinding.Location.LABEL).stream() .map(binding -> { @@ -127,11 +129,7 @@ private List createPathParameters(Context context, OperationSha ParameterObject.Builder paramBuilder = ModelUtils.createParameterMember( context, member).in("path"); // Timestamps sent in the URI are serialized as a date-time string by default. - boolean needsInlineSchema = context.getModel().getShape(member.getTarget()) - .filter(Shape::isTimestampShape) - .isPresent() - && !ModelUtils.getMemberTrait(context, member, TimestampFormatTrait.class).isPresent(); - if (needsInlineSchema) { + if (needsInlineSchema(context, member)) { // Create a copy of the targeted schema and remove any possible numeric keywords. Schema.Builder copiedBuilder = ModelUtils.convertSchemaToStringBuilder( context.getSchema(context.getPointer(member))); @@ -142,7 +140,18 @@ private List createPathParameters(Context context, OperationSha .collect(Collectors.toList()); } - private List createQueryParameters(Context context, OperationShape operation) { + private boolean needsInlineSchema(Context context, MemberShape member) { + if (member.getMemberTrait(context.getModel(), TimestampFormatTrait.class).isPresent()) { + return false; + } + + return context.getModel() + .getShape(member.getTarget()) + .filter(Shape::isTimestampShape) + .isPresent(); + } + + private List createQueryParameters(Context context, OperationShape operation) { return context.getModel().getKnowledge(HttpBindingIndex.class) .getRequestBindings(operation, HttpBinding.Location.QUERY).stream() .map(binding -> { @@ -157,20 +166,20 @@ private List createQueryParameters(Context context, OperationSh } Schema refSchema = context.createRef(binding.getMember()); - param.schema(target.accept(new QuerySchemaVisitor(context, refSchema, binding.getMember()))); + param.schema(target.accept(new QuerySchemaVisitor<>(context, refSchema, binding.getMember()))); return param.build(); }) .collect(Collectors.toList()); } - private Collection createRequestHeaderParameters(Context context, OperationShape operation) { + private Collection createRequestHeaderParameters(Context context, OperationShape operation) { List bindings = context.getModel().getKnowledge(HttpBindingIndex.class) .getRequestBindings(operation, HttpBinding.Location.HEADER); return createHeaderParameters(context, bindings, MessageType.REQUEST).values(); } private Map createHeaderParameters( - Context context, + Context context, List bindings, MessageType messageType ) { @@ -185,14 +194,14 @@ private Map createHeaderParameters( } Shape target = context.getModel().expectShape(binding.getMember().getTarget()); Schema refSchema = context.createRef(binding.getMember()); - param.schema(target.accept(new HeaderSchemaVisitor(context, refSchema, binding.getMember()))); + param.schema(target.accept(new HeaderSchemaVisitor<>(context, refSchema, binding.getMember()))); return Pair.of(binding.getLocationName(), param.build()); }) .collect(Collectors.toMap(Pair::getLeft, Pair::getRight)); } private Optional createRequestBody( - Context context, + Context context, HttpBindingIndex bindingIndex, OperationShape operation ) { @@ -206,7 +215,10 @@ private Optional createRequestBody( } private Optional createRequestPayload( - String mediaTypeRange, Context context, HttpBinding binding) { + String mediaTypeRange, + Context context, + HttpBinding binding + ) { MediaTypeObject mediaTypeObject = MediaTypeObject.builder() .schema(context.createRef(binding.getMember())) .build(); @@ -218,7 +230,7 @@ private Optional createRequestPayload( private Optional createRequestDocument( String mediaType, - Context context, + Context context, HttpBindingIndex bindingIndex, OperationShape operation ) { @@ -235,13 +247,13 @@ private Optional createRequestDocument( } private Map createResponses( - Context context, + Context context, HttpBindingIndex bindingIndex, OperationShape operation ) { OperationIndex operationIndex = context.getModel().getKnowledge(OperationIndex.class); - // Add the successful response and errors. TODO: What about synthetic errors? + // Add the successful response and errors. return Stream.concat( OptionalUtils.stream(operationIndex.getOutput(operation)), operationIndex.getErrors(operation).stream() @@ -254,7 +266,7 @@ private Map createResponses( } private ResponseObject createResponse( - Context context, + Context context, HttpBindingIndex bindingIndex, String statusCode, OperationShape operationShape, @@ -269,7 +281,7 @@ private ResponseObject createResponse( } private Map createResponseHeaderParameters( - Context context, + Context context, OperationShape operation ) { List bindings = context.getModel().getKnowledge(HttpBindingIndex.class) @@ -278,7 +290,7 @@ private Map createResponseHeaderParameters( } private void addResponseContent( - Context context, + Context context, HttpBindingIndex bindingIndex, ResponseObject.Builder responseBuilder, Shape operationOrError @@ -296,7 +308,7 @@ private void addResponseContent( private void createResponsePayload( String mediaType, - Context context, + Context context, HttpBinding binding, ResponseObject.Builder responseBuilder ) { @@ -308,7 +320,7 @@ private void createResponsePayload( private void createResponseDocument( String mediaType, - Context context, + Context context, HttpBindingIndex bindingIndex, ResponseObject.Builder responseBuilder, Shape operationOrError @@ -324,12 +336,12 @@ private void createResponseDocument( } } - private static final class QuerySchemaVisitor extends ShapeVisitor.Default { - private Context context; + private static final class QuerySchemaVisitor extends ShapeVisitor.Default { + private Context context; private Schema schema; private MemberShape member; - private QuerySchemaVisitor(Context context, Schema schema, MemberShape member) { + private QuerySchemaVisitor(Context context, Schema schema, MemberShape member) { this.context = context; this.schema = schema; this.member = member; @@ -351,11 +363,12 @@ public Schema setShape(SetShape shape) { } private Schema collection(CollectionShape collection) { - Shape memberTarget = context.getModel().getShape(collection.getMember().getTarget()).get(); + Shape memberTarget = context.getModel().expectShape(collection.getMember().getTarget()); String memberPointer = context.getPointer(collection.getMember()); Schema currentMemberSchema = context.getSchema(memberPointer); - Schema newMemberSchema = memberTarget.accept( - new QuerySchemaVisitor(context, currentMemberSchema, collection.getMember())); + QuerySchemaVisitor visitor = new QuerySchemaVisitor<>( + context, currentMemberSchema, collection.getMember()); + Schema newMemberSchema = memberTarget.accept(visitor); return schema.toBuilder().ref(null).type("array").items(newMemberSchema).build(); } @@ -383,12 +396,12 @@ public Schema blobShape(BlobShape shape) { } } - private static final class HeaderSchemaVisitor extends ShapeVisitor.Default { - private Context context; + private static final class HeaderSchemaVisitor extends ShapeVisitor.Default { + private Context context; private Schema schema; private MemberShape member; - private HeaderSchemaVisitor(Context context, Schema schema, MemberShape member) { + private HeaderSchemaVisitor(Context context, Schema schema, MemberShape member) { this.context = context; this.schema = schema; this.member = member; @@ -413,8 +426,9 @@ private Schema collection(CollectionShape collection) { Shape memberTarget = context.getModel().expectShape(collection.getMember().getTarget()); String memberPointer = context.getPointer(collection.getMember()); Schema currentMemberSchema = context.getSchema(memberPointer); - Schema newMemberSchema = memberTarget.accept( - new HeaderSchemaVisitor(context, currentMemberSchema, collection.getMember())); + HeaderSchemaVisitor visitor = new HeaderSchemaVisitor<>( + context, currentMemberSchema, collection.getMember()); + Schema newMemberSchema = memberTarget.accept(visitor); return schema.toBuilder().ref(null).type("array").items(newMemberSchema).build(); } diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/protocols/AwsRestJsonProtocol.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/protocols/AwsRestJsonProtocol.java index a4519590635..9c2c3fd4743 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/protocols/AwsRestJsonProtocol.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/protocols/AwsRestJsonProtocol.java @@ -16,7 +16,7 @@ package software.amazon.smithy.openapi.fromsmithy.protocols; import java.util.List; -import java.util.Set; +import software.amazon.smithy.aws.traits.protocols.RestJson1Trait; import software.amazon.smithy.jsonschema.JsonSchemaConstants; import software.amazon.smithy.jsonschema.Schema; import software.amazon.smithy.model.knowledge.HttpBinding; @@ -28,16 +28,15 @@ import software.amazon.smithy.model.traits.TimestampFormatTrait; import software.amazon.smithy.openapi.OpenApiConstants; import software.amazon.smithy.openapi.fromsmithy.Context; -import software.amazon.smithy.utils.SetUtils; /** * Provides the conversion from Smithy aws.rest-json-1.0 and * aws.rest-json-1.1 to OpenAPI operations. */ -public final class AwsRestJsonProtocol extends AbstractRestProtocol { +public final class AwsRestJsonProtocol extends AbstractRestProtocol { @Override - public Set getProtocolNames() { - return SetUtils.of("aws.rest-json", "aws.rest-json-1.0", "aws.rest-json-1.1"); + public Class getProtocolType() { + return RestJson1Trait.class; } @Override @@ -55,7 +54,7 @@ String getDocumentMediaType(Context context, Shape operationOrError, MessageType @Override Schema createDocumentSchema( - Context context, + Context context, Shape operationOrError, List bindings, MessageType message diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/protocols/ModelUtils.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/protocols/ModelUtils.java index 19265b7dc0b..bf81adccf8d 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/protocols/ModelUtils.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/protocols/ModelUtils.java @@ -15,12 +15,9 @@ package software.amazon.smithy.openapi.fromsmithy.protocols; -import java.util.Optional; import software.amazon.smithy.jsonschema.Schema; import software.amazon.smithy.model.shapes.MemberShape; -import software.amazon.smithy.model.shapes.Shape; import software.amazon.smithy.model.traits.DocumentationTrait; -import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.fromsmithy.Context; import software.amazon.smithy.openapi.model.ParameterObject; @@ -34,20 +31,6 @@ final class ModelUtils { private ModelUtils() {} - /** - * Gets a trait from a shape or the shape targeted by the shape if the - * shape is a member. - * - * @param context Conversion context. - * @param shape Shape or member shape to get the trait from. - * @param trait Trait type to get. - * @param Trait type to get. - * @return Returns the optionally found trait on the shape or member. - */ - static Optional getMemberTrait(Context context, Shape shape, Class trait) { - return shape.asMemberShape().flatMap(member -> member.getMemberTrait(context.getModel(), trait)); - } - /** * Creates a request parameter from a member using some default settings. * @@ -65,7 +48,8 @@ static ParameterObject.Builder createParameterMember(Context context, MemberShap ParameterObject.Builder builder = ParameterObject.builder(); builder.required(member.isRequired()); builder.name(member.getMemberName()); - getMemberTrait(context, member, DocumentationTrait.class).map(DocumentationTrait::getValue) + member.getMemberTrait(context.getModel(), DocumentationTrait.class) + .map(DocumentationTrait::getValue) .ifPresent(builder::description); return builder; } diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/AwsV4.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/AwsV4.java index 6a1b8df7269..f2f6eb68724 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/AwsV4.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/AwsV4.java @@ -16,7 +16,9 @@ package software.amazon.smithy.openapi.fromsmithy.security; import java.util.Set; +import software.amazon.smithy.aws.traits.auth.SigV4Trait; import software.amazon.smithy.model.node.Node; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.fromsmithy.Context; import software.amazon.smithy.openapi.fromsmithy.SecuritySchemeConverter; import software.amazon.smithy.openapi.model.SecurityScheme; @@ -25,18 +27,18 @@ /** * Adds AWS signature version in a way that"s compatible with AWS API Gateway. */ -public final class AwsV4 implements SecuritySchemeConverter { +public final class AwsV4 implements SecuritySchemeConverter { private static final String AUTH_HEADER = "Authorization"; private static final Set REQUEST_HEADERS = SetUtils.of( AUTH_HEADER, "Date", "X-Amz-Date", "X-Amz-Target", "X-Amz-Security-Token"); @Override - public String getAuthSchemeName() { - return "aws.v4"; + public Class getAuthSchemeType() { + return SigV4Trait.class; } @Override - public SecurityScheme createSecurityScheme(Context context) { + public SecurityScheme createSecurityScheme(Context context, SigV4Trait trait) { return SecurityScheme.builder() .type("apiKey") .description("AWS Signature Version 4 authentication") diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/HttpBasic.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/HttpBasic.java index d2e047470ad..00a0f7ad8d7 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/HttpBasic.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/HttpBasic.java @@ -15,6 +15,8 @@ package software.amazon.smithy.openapi.fromsmithy.security; +import software.amazon.smithy.model.traits.HttpBasicAuthTrait; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.fromsmithy.Context; import software.amazon.smithy.openapi.fromsmithy.SecuritySchemeConverter; import software.amazon.smithy.openapi.model.SecurityScheme; @@ -22,14 +24,14 @@ /** * Applies Basic HTTP auth. */ -public final class HttpBasic implements SecuritySchemeConverter { +public final class HttpBasic implements SecuritySchemeConverter { @Override - public String getAuthSchemeName() { - return "http-basic"; + public Class getAuthSchemeType() { + return HttpBasicAuthTrait.class; } @Override - public SecurityScheme createSecurityScheme(Context context) { + public SecurityScheme createSecurityScheme(Context context, HttpBasicAuthTrait trait) { return SecurityScheme.builder() .type("http") .scheme("Basic") diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/HttpBearer.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/HttpBearer.java index 9f1aa812a7a..6a515416fcd 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/HttpBearer.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/HttpBearer.java @@ -15,6 +15,8 @@ package software.amazon.smithy.openapi.fromsmithy.security; +import software.amazon.smithy.model.traits.HttpBearerAuthTrait; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.fromsmithy.Context; import software.amazon.smithy.openapi.fromsmithy.SecuritySchemeConverter; import software.amazon.smithy.openapi.model.SecurityScheme; @@ -22,14 +24,14 @@ /** * Uses the Bearer scheme of the Authentication header. */ -public final class HttpBearer implements SecuritySchemeConverter { +public final class HttpBearer implements SecuritySchemeConverter { @Override - public String getAuthSchemeName() { - return "http-bearer"; + public Class getAuthSchemeType() { + return HttpBearerAuthTrait.class; } @Override - public SecurityScheme createSecurityScheme(Context context) { + public SecurityScheme createSecurityScheme(Context context, HttpBearerAuthTrait trait) { return SecurityScheme.builder() .type("http") .scheme("Bearer") diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/HttpDigest.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/HttpDigest.java index ec76d7e4ade..14af678b5ea 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/HttpDigest.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/HttpDigest.java @@ -15,6 +15,8 @@ package software.amazon.smithy.openapi.fromsmithy.security; +import software.amazon.smithy.model.traits.HttpDigestAuthTrait; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.fromsmithy.Context; import software.amazon.smithy.openapi.fromsmithy.SecuritySchemeConverter; import software.amazon.smithy.openapi.model.SecurityScheme; @@ -22,14 +24,14 @@ /** * Applies Digest HTTP auth. */ -public final class HttpDigest implements SecuritySchemeConverter { +public final class HttpDigest implements SecuritySchemeConverter { @Override - public String getAuthSchemeName() { - return "http-digest"; + public Class getAuthSchemeType() { + return HttpDigestAuthTrait.class; } @Override - public SecurityScheme createSecurityScheme(Context context) { + public SecurityScheme createSecurityScheme(Context context, HttpDigestAuthTrait trait) { return SecurityScheme.builder() .type("http") .scheme("Digest") diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/XApiKey.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/XApiKey.java index cd6ec37a5b0..d154a5d86ca 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/XApiKey.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/XApiKey.java @@ -15,6 +15,8 @@ package software.amazon.smithy.openapi.fromsmithy.security; +import software.amazon.smithy.model.traits.HttpApiKeyAuthTrait; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.fromsmithy.Context; import software.amazon.smithy.openapi.fromsmithy.SecuritySchemeConverter; import software.amazon.smithy.openapi.model.SecurityScheme; @@ -25,15 +27,16 @@ *

This is compatible with Amazon API Gateway API key authorization. * * @see API Gateway documentation + * TODO: Implement and rename */ -public final class XApiKey implements SecuritySchemeConverter { +public final class XApiKey implements SecuritySchemeConverter { @Override - public String getAuthSchemeName() { - return "http-x-api-key"; + public Class getAuthSchemeType() { + return HttpApiKeyAuthTrait.class; } @Override - public SecurityScheme createSecurityScheme(Context context) { + public SecurityScheme createSecurityScheme(Context context, HttpApiKeyAuthTrait trait) { return SecurityScheme.builder() .type("apiKey") .in("header") diff --git a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/OpenApiConverterTest.java b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/OpenApiConverterTest.java index 6dbb6a1eef1..0a136f0f203 100644 --- a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/OpenApiConverterTest.java +++ b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/OpenApiConverterTest.java @@ -31,6 +31,7 @@ import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.shapes.Shape; import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.openapi.OpenApiConstants; import software.amazon.smithy.openapi.OpenApiException; import software.amazon.smithy.openapi.model.OpenApi; @@ -44,6 +45,7 @@ public class OpenApiConverterTest { public void convertsModelsToOpenApi() { Model model = Model.assembler() .addImport(getClass().getResource("test-service.json")) + .discoverModels() .assemble() .unwrap(); ObjectNode result = OpenApiConverter.create().convertToNode(model, ShapeId.from("example.rest#RestService")); @@ -57,6 +59,7 @@ public void convertsModelsToOpenApi() { public void convertsModelsToOpenApiAndDisablesInlining() { Model model = Model.assembler() .addImport(getClass().getResource("test-service.json")) + .discoverModels() .assemble() .unwrap(); ObjectNode result = OpenApiConverter.create() @@ -72,6 +75,7 @@ public void convertsModelsToOpenApiAndDisablesInlining() { public void passesThroughTags() { Model model = Model.assembler() .addImport(getClass().getResource("tagged-service.json")) + .discoverModels() .assemble() .unwrap(); OpenApi result = OpenApiConverter.create() @@ -89,13 +93,14 @@ public void requiresProtocolsTrait() { Exception thrown = Assertions.assertThrows(OpenApiException.class, () -> { Model model = Model.assembler() .addImport(getClass().getResource("missing-protocols-trait.json")) + .discoverModels() .assemble() .unwrap(); OpenApiConverter.create() .convert(model, ShapeId.from("smithy.example#Service")); }); - assertThat(thrown.getMessage(), containsString("`protocols` trait")); + assertThat(thrown.getMessage(), containsString("does not define any protocols")); } @Test @@ -103,34 +108,21 @@ public void mustBeAbleToResolveProtocol() { Exception thrown = Assertions.assertThrows(OpenApiException.class, () -> { Model model = Model.assembler() .addImport(getClass().getResource("unable-to-resolve-protocol.json")) + .discoverModels() .assemble() .unwrap(); OpenApiConverter.create() .convert(model, ShapeId.from("smithy.example#Service")); }); - assertThat(thrown.getMessage(), containsString("Unable to resolve")); - } - - @Test - public void mustBeAbleToResolveExplicitProtocol() { - Exception thrown = Assertions.assertThrows(OpenApiException.class, () -> { - Model model = Model.assembler() - .addImport(getClass().getResource("unable-to-resolve-protocol.json")) - .assemble() - .unwrap(); - OpenApiConverter.create() - .protocolName("not-found") - .convert(model, ShapeId.from("smithy.example#Service")); - }); - - assertThat(thrown.getMessage(), containsString("Unable to resolve")); + assertThat(thrown.getMessage(), containsString("Unable to find an OpenAPI service provider")); } @Test public void omitsUnsupportedHttpMethods() { Model model = Model.assembler() .addImport(getClass().getResource("unsupported-http-method.json")) + .discoverModels() .assemble() .unwrap(); OpenApi result = OpenApiConverter.create().convert(model, ShapeId.from("smithy.example#Service")); @@ -144,6 +136,7 @@ public void omitsUnsupportedHttpMethods() { public void protocolsCanOmitOperations() { Model model = Model.assembler() .addImport(getClass().getResource("missing-http-bindings.json")) + .discoverModels() .assemble() .unwrap(); OpenApi result = OpenApiConverter.create() @@ -165,6 +158,7 @@ public void protocolsCanOmitOperations() { public void addsEmptyResponseByDefault() { Model model = Model.assembler() .addImport(getClass().getResource("adds-empty-response.json")) + .discoverModels() .assemble() .unwrap(); OpenApi result = OpenApiConverter.create().convert(model, ShapeId.from("smithy.example#Service")); @@ -176,6 +170,7 @@ public void addsEmptyResponseByDefault() { public void addsMixedSecurityService() { Model model = Model.assembler() .addImport(getClass().getResource("mixed-security-service.json")) + .discoverModels() .assemble() .unwrap(); OpenApi result = OpenApiConverter.create().convert(model, ShapeId.from("smithy.example#Service")); @@ -188,8 +183,8 @@ public void addsMixedSecurityService() { private static final class NullSecurity implements OpenApiMapper { @Override public Map> updateSecurity( - Context context, Shape shape, - SecuritySchemeConverter converter, + Context context, Shape shape, + SecuritySchemeConverter converter, Map> requirement ) { return null; @@ -200,6 +195,7 @@ public Map> updateSecurity( public void canOmitSecurityRequirements() { Model model = Model.assembler() .addImport(getClass().getResource("mixed-security-service.json")) + .discoverModels() .assemble() .unwrap(); OpenApi result = OpenApiConverter.create() @@ -213,8 +209,8 @@ public void canOmitSecurityRequirements() { private static final class ConstantSecurity implements OpenApiMapper { @Override public Map> updateSecurity( - Context context, Shape shape, - SecuritySchemeConverter converter, + Context context, Shape shape, + SecuritySchemeConverter converter, Map> requirement ) { return MapUtils.of("foo_baz", ListUtils.of()); @@ -225,6 +221,7 @@ public Map> updateSecurity( public void canChangeSecurityRequirementName() { Model model = Model.assembler() .addImport(getClass().getResource("mixed-security-service.json")) + .discoverModels() .assemble() .unwrap(); OpenApi result = OpenApiConverter.create() diff --git a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/OpenApiJsonSchemaMapperTest.java b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/OpenApiJsonSchemaMapperTest.java index b3a35d6320f..8ac6dee4d16 100644 --- a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/OpenApiJsonSchemaMapperTest.java +++ b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/OpenApiJsonSchemaMapperTest.java @@ -46,6 +46,7 @@ public class OpenApiJsonSchemaMapperTest { public void convertsModels() { Model model = Model.assembler() .addImport(getClass().getResource("test-service.json")) + .discoverModels() .assemble() .unwrap(); SchemaDocument document = JsonSchemaConverter.create() diff --git a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/mappers/CheckForGreedyLabelsTest.java b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/mappers/CheckForGreedyLabelsTest.java index 20a54d6ee37..79b69965e88 100644 --- a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/mappers/CheckForGreedyLabelsTest.java +++ b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/mappers/CheckForGreedyLabelsTest.java @@ -17,6 +17,7 @@ public class CheckForGreedyLabelsTest { public static void before() { model = Model.assembler() .addImport(RemoveUnusedComponentsTest.class.getResource("greedy-labels.smithy")) + .discoverModels() .assemble() .unwrap(); } diff --git a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/mappers/CheckForPrefixHeadersTest.java b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/mappers/CheckForPrefixHeadersTest.java index d625dc1fbe6..d3525d9a9a8 100644 --- a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/mappers/CheckForPrefixHeadersTest.java +++ b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/mappers/CheckForPrefixHeadersTest.java @@ -17,6 +17,7 @@ public class CheckForPrefixHeadersTest { public static void before() { model = Model.assembler() .addImport(RemoveUnusedComponentsTest.class.getResource("prefix-headers.smithy")) + .discoverModels() .assemble() .unwrap(); } diff --git a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/mappers/OpenApiJsonSubstitutionsPluginTest.java b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/mappers/OpenApiJsonSubstitutionsPluginTest.java index 8c213c0350c..1312fbbd876 100644 --- a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/mappers/OpenApiJsonSubstitutionsPluginTest.java +++ b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/mappers/OpenApiJsonSubstitutionsPluginTest.java @@ -29,6 +29,7 @@ public class OpenApiJsonSubstitutionsPluginTest { public void removesBySubstitution() { Model model = Model.assembler() .addImport(RemoveUnusedComponentsTest.class.getResource("substitutions.smithy")) + .discoverModels() .assemble() .unwrap(); diff --git a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/mappers/RemoveUnusedComponentsTest.java b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/mappers/RemoveUnusedComponentsTest.java index d3257affc60..01e25cc1011 100644 --- a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/mappers/RemoveUnusedComponentsTest.java +++ b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/mappers/RemoveUnusedComponentsTest.java @@ -20,6 +20,7 @@ public class RemoveUnusedComponentsTest { public static void before() { model = Model.assembler() .addImport(RemoveUnusedComponentsTest.class.getResource("small-service.smithy")) + .discoverModels() .assemble() .unwrap(); } diff --git a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/mappers/UnsupportedTraitsPluginTest.java b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/mappers/UnsupportedTraitsPluginTest.java index 2d03532e8c9..1f3822cadc0 100644 --- a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/mappers/UnsupportedTraitsPluginTest.java +++ b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/mappers/UnsupportedTraitsPluginTest.java @@ -17,6 +17,7 @@ public class UnsupportedTraitsPluginTest { public static void before() { model = Model.assembler() .addImport(UnsupportedTraitsPluginTest.class.getResource("streaming-service.smithy")) + .discoverModels() .assemble() .unwrap(); } diff --git a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/protocols/AwsRestJsonProtocolTest.java b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/protocols/AwsRestJsonProtocolTest.java index 0b9b30aecf0..8b137255e51 100644 --- a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/protocols/AwsRestJsonProtocolTest.java +++ b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/protocols/AwsRestJsonProtocolTest.java @@ -33,6 +33,7 @@ public class AwsRestJsonProtocolTest { public void testProtocolResult(String smithy) { Model model = Model.assembler() .addImport(getClass().getResource(smithy)) + .discoverModels() .assemble() .unwrap(); ObjectNode result = OpenApiConverter.create() @@ -66,6 +67,7 @@ public void testProtocolResult(String smithy) { public void canUseCustomMediaType() { Model model = Model.assembler() .addImport(getClass().getResource("adds-json-document-bodies.json")) + .discoverModels() .assemble() .unwrap(); OpenApi result = OpenApiConverter.create() diff --git a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/security/AwsV4Test.java b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/security/AwsV4Test.java index 3e9ac05652e..417a1ca8f70 100644 --- a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/security/AwsV4Test.java +++ b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/security/AwsV4Test.java @@ -13,6 +13,7 @@ public class AwsV4Test { public void addsAwsV4() { Model model = Model.assembler() .addImport(getClass().getResource("awsv4-security.json")) + .discoverModels() .assemble() .unwrap(); OpenApi result = OpenApiConverter.create().convert(model, ShapeId.from("smithy.example#Service")); diff --git a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/security/HttpBasicTest.java b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/security/HttpBasicTest.java index 09e6a37ed0f..e57cb9627dc 100644 --- a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/security/HttpBasicTest.java +++ b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/security/HttpBasicTest.java @@ -13,6 +13,7 @@ public class HttpBasicTest { public void addsHttpBasicAuth() { Model model = Model.assembler() .addImport(getClass().getResource("http-basic-security.json")) + .discoverModels() .assemble() .unwrap(); OpenApi result = OpenApiConverter.create().convert(model, ShapeId.from("smithy.example#Service")); diff --git a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/security/HttpDigestTest.java b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/security/HttpDigestTest.java index 99b8a088a58..adbe7b14ada 100644 --- a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/security/HttpDigestTest.java +++ b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/security/HttpDigestTest.java @@ -13,6 +13,7 @@ public class HttpDigestTest { public void addsHttpDigestAuth() { Model model = Model.assembler() .addImport(getClass().getResource("http-digest-security.json")) + .discoverModels() .assemble() .unwrap(); OpenApi result = OpenApiConverter.create().convert(model, ShapeId.from("smithy.example#Service")); diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/adds-empty-response.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/adds-empty-response.json index 95bf2579c93..244fc7c2036 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/adds-empty-response.json +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/adds-empty-response.json @@ -10,11 +10,7 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json" - } - ] + "aws.protocols#restJson1": true } }, "smithy.example#Operation1": { diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mappers/greedy-labels.smithy b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mappers/greedy-labels.smithy index 60e49a0e772..0c291d80536 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mappers/greedy-labels.smithy +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mappers/greedy-labels.smithy @@ -1,6 +1,6 @@ namespace smithy.example -@protocols([{"name": "aws.rest-json"}]) +@aws.protocols#restJson1 service Greedy { version: "2018-01-01", operations: [GreedyOperation] diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mappers/prefix-headers.smithy b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mappers/prefix-headers.smithy index d594c1bfc2f..46968373814 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mappers/prefix-headers.smithy +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mappers/prefix-headers.smithy @@ -1,6 +1,6 @@ namespace smithy.example -@protocols([{"name": "aws.rest-json"}]) +@aws.protocols#restJson1 service PrefixHeaders { version: "2018-01-01", operations: [PrefixHeadersOperation] diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mappers/small-service.smithy b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mappers/small-service.smithy index 74d74a84d85..be548ca08d5 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mappers/small-service.smithy +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mappers/small-service.smithy @@ -1,6 +1,7 @@ namespace smithy.example -@protocols([{"name": "aws.rest-json", auth: ["aws.v4"]}]) +@aws.auth#sigv4(name: "small") +@aws.protocols#restJson1 service Small { version: "2018-01-01", operations: [SmallOperation] diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mappers/streaming-service.smithy b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mappers/streaming-service.smithy index 700319e277f..f23eb566dd7 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mappers/streaming-service.smithy +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mappers/streaming-service.smithy @@ -1,6 +1,6 @@ namespace smithy.example -@protocols([{"name": "aws.rest-json"}]) +@aws.protocols#restJson1 service Streaming { version: "2018-01-01", operations: [StreamingOperation] diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mappers/substitutions.smithy b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mappers/substitutions.smithy index 12039a2c67e..820c0a5bd06 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mappers/substitutions.smithy +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mappers/substitutions.smithy @@ -1,6 +1,6 @@ namespace smithy.example -@protocols([{"name": "aws.rest-json"}]) +@aws.protocols#restJson1 @documentation("SUB_HELLO") service Service { version: "2018-01-01" diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/missing-http-bindings.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/missing-http-bindings.json index 1cffe9b9fc9..b49c24c3b76 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/missing-http-bindings.json +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/missing-http-bindings.json @@ -10,11 +10,7 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json" - } - ] + "aws.protocols#restJson1": true } }, "smithy.example#Operation1": { diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mixed-security-service.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mixed-security-service.json index 25dec1508a2..c0477ab1310 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mixed-security-service.json +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mixed-security-service.json @@ -16,17 +16,13 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json", - "auth": [ - "http-basic", - "aws.v4" - ] - } - ], + "aws.protocols#restJson1": true, + "aws.auth#sigv4": { + "name": "example" + }, + "smithy.api#httpBasicAuth": {}, "smithy.api#auth": [ - "aws.v4" + "aws.auth#sigv4" ] } }, @@ -47,7 +43,7 @@ "method": "GET" }, "smithy.api#auth": [ - "http-basic" + "smithy.api#httpBasicAuth" ] } }, @@ -59,8 +55,8 @@ "method": "GET" }, "smithy.api#auth": [ - "http-basic", - "aws.v4" + "smithy.api#httpBasicAuth", + "aws.auth#sigv4" ] } } diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mixed-security-service.openapi.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mixed-security-service.openapi.json index 6cb9bad7bd5..35d43d04d6b 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mixed-security-service.openapi.json +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/mixed-security-service.openapi.json @@ -25,7 +25,7 @@ }, "security": [ { - "http-basic": [ ] + "smithy.api#httpBasicAuth": [ ] } ] } @@ -40,10 +40,10 @@ }, "security": [ { - "aws.v4": [ ] + "smithy.api#httpBasicAuth": [] }, { - "http-basic": [] + "aws.auth#sigv4": [ ] } ] } @@ -51,12 +51,12 @@ }, "components": { "securitySchemes": { - "http-basic": { + "smithy.api#httpBasicAuth": { "type": "http", "description": "HTTP Basic authentication", "scheme": "Basic" }, - "aws.v4": { + "aws.auth#sigv4": { "type": "apiKey", "description": "AWS Signature Version 4 authentication", "name": "Authorization", @@ -67,7 +67,7 @@ }, "security": [ { - "aws.v4": [ ] + "aws.auth#sigv4": [ ] } ] } diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-header-mediatype-format.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-header-mediatype-format.json index abcf067a5a0..c9a2d2a13e5 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-header-mediatype-format.json +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-header-mediatype-format.json @@ -10,11 +10,7 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json-1.0" - } - ] + "aws.protocols#restJson1": true } }, "smithy.example#Operation": { diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-header-timestamp-format.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-header-timestamp-format.json index f0fc4a49104..0d1c2f8f887 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-header-timestamp-format.json +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-header-timestamp-format.json @@ -10,11 +10,7 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json-1.1" - } - ] + "aws.protocols#restJson1": true } }, "smithy.example#Operation": { diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-json-document-bodies.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-json-document-bodies.json index b839cb99eaa..8238e8aca29 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-json-document-bodies.json +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-json-document-bodies.json @@ -10,11 +10,7 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json" - } - ] + "aws.protocols#restJson1": true } }, "smithy.example#CreateDocument": { diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-path-timestamp-format.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-path-timestamp-format.json index 06a43722ffe..208af2da194 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-path-timestamp-format.json +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-path-timestamp-format.json @@ -10,11 +10,7 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json" - } - ] + "aws.protocols#restJson1": true } }, "smithy.example#Operation": { diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-query-blob-format.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-query-blob-format.json index 8bd75960bc2..5746c9ed379 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-query-blob-format.json +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-query-blob-format.json @@ -10,11 +10,7 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json" - } - ] + "aws.protocols#restJson1": true } }, "smithy.example#Operation": { diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-query-timestamp-format.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-query-timestamp-format.json index 6802ef8a157..551a3886e0e 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-query-timestamp-format.json +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/adds-query-timestamp-format.json @@ -10,11 +10,7 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json" - } - ] + "aws.protocols#restJson1": true } }, "smithy.example#Operation": { diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/aws-rest-json-uses-jsonname.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/aws-rest-json-uses-jsonname.json index 197f3b96d55..030f6d21f60 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/aws-rest-json-uses-jsonname.json +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/aws-rest-json-uses-jsonname.json @@ -10,11 +10,7 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json" - } - ] + "aws.protocols#restJson1": true } }, "smithy.example#CreateDocument": { diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/supports-payloads.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/supports-payloads.json index ea20d9cfec6..e4ed9ebd248 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/supports-payloads.json +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/protocols/supports-payloads.json @@ -10,11 +10,7 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json" - } - ] + "aws.protocols#restJson1": true } }, "smithy.example#Operation": { diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/awsv4-security.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/awsv4-security.json index 1511eef1f97..49ef4a6215a 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/awsv4-security.json +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/awsv4-security.json @@ -10,14 +10,10 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json", - "auth": [ - "aws.v4" - ] - } - ] + "aws.protocols#restJson1": true, + "aws.auth#sigv4": { + "name": "example" + } } }, "smithy.example#Operation1": { diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/awsv4-security.openapi.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/awsv4-security.openapi.json index 4218757c801..7aff7b70483 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/awsv4-security.openapi.json +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/awsv4-security.openapi.json @@ -18,7 +18,7 @@ }, "components": { "securitySchemes": { - "aws.v4": { + "aws.auth#sigv4": { "type": "apiKey", "description": "AWS Signature Version 4 authentication", "name": "Authorization", @@ -29,7 +29,7 @@ }, "security": [ { - "aws.v4": [ ] + "aws.auth#sigv4": [ ] } ] } diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-basic-security.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-basic-security.json index 215149a90b5..63c3aadb225 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-basic-security.json +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-basic-security.json @@ -10,14 +10,8 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json", - "auth": [ - "http-basic" - ] - } - ] + "aws.protocols#restJson1": true, + "smithy.api#httpBasicAuth": true } }, "smithy.example#Operation1": { diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-basic-security.openapi.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-basic-security.openapi.json index 6e64aa3e25a..5a1a1597da2 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-basic-security.openapi.json +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-basic-security.openapi.json @@ -18,7 +18,7 @@ }, "components": { "securitySchemes": { - "http-basic": { + "smithy.api#httpBasicAuth": { "type": "http", "description": "HTTP Basic authentication", "scheme": "Basic" @@ -27,7 +27,7 @@ }, "security": [ { - "http-basic": [ ] + "smithy.api#httpBasicAuth": [ ] } ] } diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-digest-security.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-digest-security.json index ffae567704c..24bea0b5664 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-digest-security.json +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-digest-security.json @@ -10,14 +10,8 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json", - "auth": [ - "http-digest" - ] - } - ] + "aws.protocols#restJson1": true, + "smithy.api#httpDigestAuth": true } }, "smithy.example#Operation1": { diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-digest-security.openapi.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-digest-security.openapi.json index b75ef0fd8ad..0a97f449b25 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-digest-security.openapi.json +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-digest-security.openapi.json @@ -18,7 +18,7 @@ }, "components": { "securitySchemes": { - "http-digest": { + "smithy.api#httpDigestAuth": { "type": "http", "scheme": "Digest", "description": "HTTP Digest authentication" @@ -27,7 +27,7 @@ }, "security": [ { - "http-digest": [ ] + "smithy.api#httpDigestAuth": [ ] } ] } diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/tagged-service.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/tagged-service.json index 496bac9ea59..c01995bd5da 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/tagged-service.json +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/tagged-service.json @@ -19,11 +19,7 @@ "smithy.api#tags": [ "foo" ], - "smithy.api#protocols": [ - { - "name": "aws.rest-json" - } - ] + "aws.protocols#restJson1": true } }, "smithy.example#Operation1": { diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/test-service.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/test-service.json index a3e9ae7bd18..5257cc8cb35 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/test-service.json +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/test-service.json @@ -13,11 +13,7 @@ } ], "traits": { - "smithy.api#protocols": [ - { - "name": "aws.rest-json" - } - ] + "aws.protocols#restJson1": true } }, "example.rest#PutPayload": { diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/unable-to-resolve-protocol.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/unable-to-resolve-protocol.json index 601f8838049..04e989a2d94 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/unable-to-resolve-protocol.json +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/unable-to-resolve-protocol.json @@ -8,11 +8,14 @@ "smithy.api#tags": [ "foo" ], - "smithy.api#protocols": [ - { - "name": "foo.baz.bar.bam.qux.lorem.ipsum" - } - ] + "smithy.example#cannotResolveMe": true + } + }, + "smithy.example#cannotResolveMe": { + "type": "structure", + "traits": { + "smithy.api#trait": {"selector": "service"}, + "smithy.api#protocolDefinition": true } } } diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/unsupported-http-method.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/unsupported-http-method.json index d0598af66ca..fc09cbc3975 100644 --- a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/unsupported-http-method.json +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/unsupported-http-method.json @@ -37,11 +37,7 @@ "smithy.api#tags": [ "foo" ], - "smithy.api#protocols": [ - { - "name": "aws.rest-json" - } - ] + "aws.protocols#restJson1": true } }, "smithy.example#Patch": { diff --git a/smithy-protocol-test-traits/src/main/java/software/amazon/smithy/protocoltests/traits/HttpMessageTestCase.java b/smithy-protocol-test-traits/src/main/java/software/amazon/smithy/protocoltests/traits/HttpMessageTestCase.java index df885e3dfc3..26c55e0ad72 100644 --- a/smithy-protocol-test-traits/src/main/java/software/amazon/smithy/protocoltests/traits/HttpMessageTestCase.java +++ b/smithy-protocol-test-traits/src/main/java/software/amazon/smithy/protocoltests/traits/HttpMessageTestCase.java @@ -26,6 +26,7 @@ import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.node.StringNode; import software.amazon.smithy.model.node.ToNode; +import software.amazon.smithy.model.shapes.ShapeId; import software.amazon.smithy.utils.ListUtils; import software.amazon.smithy.utils.SmithyBuilder; @@ -45,8 +46,8 @@ public abstract class HttpMessageTestCase implements ToNode { private final String id; private final String documentation; - private final String protocol; - private final String authScheme; + private final ShapeId protocol; + private final ShapeId authScheme; private final String body; private final String bodyMediaType; private final ObjectNode params; @@ -77,11 +78,11 @@ public Optional getDocumentation() { return Optional.ofNullable(documentation); } - public String getProtocol() { + public ShapeId getProtocol() { return protocol; } - public Optional getAuthScheme() { + public Optional getAuthScheme() { return Optional.ofNullable(authScheme); } @@ -116,9 +117,9 @@ public List getRequireHeaders() { static void updateBuilderFromNode(Builder builder, Node node) { ObjectNode o = node.expectObjectNode(); builder.id(o.expectStringMember(ID).getValue()); - builder.protocol(o.expectStringMember(PROTOCOL).getValue()); + builder.protocol(o.expectStringMember(PROTOCOL).expectShapeId()); o.getStringMember(DOCUMENTATION).map(StringNode::getValue).ifPresent(builder::documentation); - o.getStringMember(AUTH_SCHEME).map(StringNode::getValue).ifPresent(builder::authScheme); + o.getStringMember(AUTH_SCHEME).map(StringNode::expectShapeId).ifPresent(builder::authScheme); o.getStringMember(BODY).map(StringNode::getValue).ifPresent(builder::body); o.getStringMember(BODY_MEDIA_TYPE).map(StringNode::getValue).ifPresent(builder::bodyMediaType); o.getObjectMember(PARAMS).ifPresent(builder::params); @@ -143,9 +144,9 @@ static void updateBuilderFromNode(Builder builder, Node node) { public Node toNode() { ObjectNode.Builder builder = Node.objectNodeBuilder() .withMember(ID, getId()) - .withMember(PROTOCOL, getProtocol()) + .withMember(PROTOCOL, getProtocol().toString()) .withOptionalMember(DOCUMENTATION, getDocumentation().map(Node::from)) - .withOptionalMember(AUTH_SCHEME, getAuthScheme().map(Node::from)) + .withOptionalMember(AUTH_SCHEME, getAuthScheme().map(ShapeId::toString).map(Node::from)) .withOptionalMember(BODY, getBody().map(Node::from)) .withOptionalMember(BODY_MEDIA_TYPE, getBodyMediaType().map(Node::from)); @@ -207,8 +208,8 @@ abstract static class Builder private String id; private String documentation; - private String protocol; - private String authScheme; + private ShapeId protocol; + private ShapeId authScheme; private String body; private String bodyMediaType; private ObjectNode params = Node.objectNode(); @@ -230,13 +231,13 @@ public B documentation(String documentation) { } @SuppressWarnings("unchecked") - public B protocol(String protocol) { + public B protocol(ShapeId protocol) { this.protocol = protocol; return (B) this; } @SuppressWarnings("unchecked") - public B authScheme(String authScheme) { + public B authScheme(ShapeId authScheme) { this.authScheme = authScheme; return (B) this; } diff --git a/smithy-protocol-test-traits/src/main/resources/META-INF/smithy/smithy.test.smithy b/smithy-protocol-test-traits/src/main/resources/META-INF/smithy/smithy.test.smithy index 960aea51639..70ffd019bd5 100644 --- a/smithy-protocol-test-traits/src/main/resources/META-INF/smithy/smithy.test.smithy +++ b/smithy-protocol-test-traits/src/main/resources/META-INF/smithy/smithy.test.smithy @@ -23,6 +23,7 @@ structure HttpRequestTestCase { /// The name of the protocol to test. @required + @idRef(selector: "[trait|protocolDefinition]", failWhenMissing: true) protocol: String, /// The expected serialized HTTP request method. @@ -36,9 +37,10 @@ structure HttpRequestTestCase { @length(min: 1) uri: String, - /// The optional authentication scheme to assume. It's possible that - /// specific authentication schemes might influence the serialization - /// logic of an HTTP request. + /// The optional authentication scheme shape ID to assume. It's + /// possible that specific authentication schemes might influence + /// the serialization logic of an HTTP request. + @idRef(selector: "[trait|authDefinition]", failWhenMissing: true) authScheme: String, /// A list of the expected serialized query string parameters. @@ -149,8 +151,9 @@ structure HttpResponseTestCase { @pattern("[A-Za-z_][A-Za-z0-9_]+") id: String, - /// The name of the protocol to test. + /// The shape ID of the protocol to test. @required + @idRef(selector: "[trait|protocolDefinition]", failWhenMissing: true) protocol: String, /// Defines the HTTP response code. @@ -158,9 +161,10 @@ structure HttpResponseTestCase { @range(min: 100, max: 599) code: Integer, - /// The optional authentication scheme to assume. It's possible that - /// specific authentication schemes might influence the serialization + /// The optional authentication scheme shape ID to assume. It's possible + /// that specific authentication schemes might influence the serialization /// logic of an HTTP response. + @idRef(selector: "[trait|authDefinition]", failWhenMissing: true) authScheme: String, /// A map of expected HTTP headers. Each key represents a header field diff --git a/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/all-request-features.smithy b/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/all-request-features.smithy index cf63e9d2ac1..f57e678a6cf 100644 --- a/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/all-request-features.smithy +++ b/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/all-request-features.smithy @@ -2,13 +2,21 @@ namespace smithy.example use smithy.test#httpRequestTests +@trait +@protocolDefinition +structure testProtocol {} + +@trait +@authDefinition +structure testScheme {} + @http(method: "POST", uri: "/") @httpRequestTests([ { id: "foo", documentation: "Testing...", - protocol: "example", - authScheme: "test", + protocol: testProtocol, + authScheme: testScheme, method: "POST", uri: "/", queryParams: ["foo=baz"], diff --git a/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/all-response-features.smithy b/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/all-response-features.smithy index 14efd78aade..19faec86cad 100644 --- a/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/all-response-features.smithy +++ b/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/all-response-features.smithy @@ -2,13 +2,21 @@ namespace smithy.example use smithy.test#httpResponseTests +@trait +@protocolDefinition +structure testProtocol {} + +@trait +@authDefinition +structure testScheme {} + @readonly @http(method: "GET", uri: "/") @httpResponseTests([ { id: "foo2", - protocol: "example", - authScheme: "test", + protocol: testProtocol, + authScheme: testScheme, code: 200, headers: { "X-Blah": "Blarg" diff --git a/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/detects-duplicate-ids.smithy b/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/detects-duplicate-ids.smithy index e5857fd4ace..99f9facf099 100644 --- a/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/detects-duplicate-ids.smithy +++ b/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/detects-duplicate-ids.smithy @@ -3,16 +3,20 @@ namespace smithy.example use smithy.test#httpResponseTests use smithy.test#httpRequestTests +@trait +@protocolDefinition +structure testProtocol {} + @http(method: "POST", uri: "/") @httpResponseTests([ { id: "foo", // conflict with self and MyError - protocol: "example", + protocol: testProtocol, code: 200, }, { id: "foo", // conflict with self and MyError - protocol: "example", + protocol: testProtocol, code: 200, } ]) @@ -24,12 +28,12 @@ structure SayGoodbyeOutput {} @httpResponseTests([ { id: "foo", // conflict with self and SayGoodbye - protocol: "example", + protocol: testProtocol, code: 200, }, { id: "baz", // no conflict - protocol: "example", + protocol: testProtocol, code: 200, }, ]) @@ -40,13 +44,13 @@ structure MyError {} @httpRequestTests([ { id: "foo", // conflict with self and SayHello2 - protocol: "example", + protocol: testProtocol, method: "POST", uri: "/", }, { id: "foo", // conflict with self and SayHello2 - protocol: "example", + protocol: testProtocol, method: "POST", uri: "/", }, @@ -60,13 +64,13 @@ structure SayHelloInput {} @httpRequestTests([ { id: "foo", // conflict - protocol: "example", + protocol: testProtocol, method: "POST", uri: "/", }, { id: "baz", // no conflict - protocol: "example", + protocol: testProtocol, method: "POST", uri: "/", } diff --git a/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/detects-invalid-params.smithy b/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/detects-invalid-params.smithy index fb046951c30..7442a8831dd 100644 --- a/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/detects-invalid-params.smithy +++ b/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/detects-invalid-params.smithy @@ -3,11 +3,15 @@ namespace smithy.example use smithy.test#httpResponseTests use smithy.test#httpRequestTests +@trait +@protocolDefinition +structure testProtocol {} + @http(method: "POST", uri: "/") @httpResponseTests([ { id: "foo1", - protocol: "example", + protocol: testProtocol, code: 200, params: { invalid: true @@ -23,7 +27,7 @@ structure SayGoodbyeOutput {} @httpResponseTests([ { id: "foo2", - protocol: "example", + protocol: testProtocol, code: 200, params: { foo: "Hi" @@ -39,7 +43,7 @@ structure MyError { @httpRequestTests([ { id: "foo3", - protocol: "example", + protocol: testProtocol, method: "POST", uri: "/", params: { diff --git a/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/test-case-on-error.smithy b/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/test-case-on-error.smithy index a5ec06aa658..a794cb616db 100644 --- a/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/test-case-on-error.smithy +++ b/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/test-case-on-error.smithy @@ -2,12 +2,16 @@ namespace smithy.example use smithy.test#httpResponseTests +@trait +@protocolDefinition +structure testProtocol {} + @error("client") @httpError(400) @httpResponseTests([ { id: "invalid_greeting", - protocol: "example", + protocol: testProtocol, params: {foo: "baz", message: "Hi"}, code: 400, headers: {"X-Foo": "baz"}, diff --git a/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/timestamp-validation.smithy b/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/timestamp-validation.smithy index bbe832fad62..158da55b9d3 100644 --- a/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/timestamp-validation.smithy +++ b/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/timestamp-validation.smithy @@ -2,11 +2,15 @@ namespace smithy.example use smithy.test#httpRequestTests +@trait +@protocolDefinition +structure testProtocol {} + @http(method: "POST", uri: "/") @httpRequestTests([ { id: "foo3", - protocol: "example", + protocol: testProtocol, method: "POST", uri: "/", params: { diff --git a/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/say-goodbye.smithy b/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/say-goodbye.smithy index bff67448ccd..fb5d59eb521 100644 --- a/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/say-goodbye.smithy +++ b/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/say-goodbye.smithy @@ -2,11 +2,15 @@ namespace smithy.example use smithy.test#httpResponseTests +@trait +@protocolDefinition +structure exampleProtocol {} + @http(method: "POST", uri: "/") @httpResponseTests([ { id: "say_goodbye", - protocol: "example", + protocol: exampleProtocol, params: {farewell: "Bye"}, code: 200, headers: { diff --git a/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/say-hello.smithy b/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/say-hello.smithy index 6b82e3a4aff..45529c79b2f 100644 --- a/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/say-hello.smithy +++ b/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/say-hello.smithy @@ -2,11 +2,15 @@ namespace smithy.example use smithy.test#httpRequestTests +@trait +@protocolDefinition +structure exampleProtocol {} + @http(method: "POST", uri: "/") @httpRequestTests([ { id: "say_hello", - protocol: "example", + protocol: exampleProtocol, params: { "greeting": "Hi", "name": "Teddy"