Unverified Commit ff587f4c authored by Matteo Bigoi's avatar Matteo Bigoi Committed by GitHub
Browse files

Add decorator to allow to make all operations fallible (#1190)



Force all operations in the model to be fallible.

When this decorator is applied, operations that do not have a Smithy error attatched, will return Result<OperationOutput, InternalServerError>.

To enable this decorator, create a file called META-INF/service/software.amazon.smithy.rust.codegen.smithy.customize.RustCodegenDecorator containing codegen-server/src/main/resources/META-INF/services/software.amazon.smithy.rust.codegen.smithy.customize.RustCodegenDecorator.

Closes: #1150
Signed-off-by: default avatarBigo <1781140+crisidev@users.noreply.github.com>
parent 116f81bf
Loading
Loading
Loading
Loading
+54 −0
Original line number Diff line number Diff line
/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

package software.amazon.smithy.rust.codegen.server.smithy.customizations

import software.amazon.smithy.model.Model
import software.amazon.smithy.model.shapes.MemberShape
import software.amazon.smithy.model.shapes.OperationShape
import software.amazon.smithy.model.shapes.ServiceShape
import software.amazon.smithy.model.shapes.StructureShape
import software.amazon.smithy.model.traits.ErrorTrait
import software.amazon.smithy.model.traits.RequiredTrait
import software.amazon.smithy.model.transform.ModelTransformer
import software.amazon.smithy.rust.codegen.smithy.customize.RustCodegenDecorator

/**
 * Add at least one error to all operations in the model.
 *
 * When this decorator is applied, operations that do not have a Smithy error attatched,
 * will return `Result<OperationOutput, InternalServerError>`.
 *
 * To enable this decorator, create a file called `META-INF/services/software.amazon.smithy.rust.codegen.smithy.customize.RustCodegenDecorator`
 * containing `codegen-server/src/main/resources/META-INF/services/software.amazon.smithy.rust.codegen.smithy.customize.RustCodegenDecorator`.
 */
class FallibleOperationsDecorator : RustCodegenDecorator {
    override val name: String = "FallibleOperations"
    override val order: Byte = 0

    private fun internalServerError(namespace: String): StructureShape {
        return StructureShape.builder().id("$namespace#InternalServerError")
            .addTrait(ErrorTrait("server"))
            .addMember(
                MemberShape.builder()
                    .id("$namespace#InternalServerError\$message")
                    .target("smithy.api#String")
                    .addTrait(RequiredTrait())
                    .build()
            ).build()
    }

    override fun transformModel(service: ServiceShape, model: Model): Model {
        val errorShape = internalServerError(service.id.getNamespace())
        val modelShapes = model.toBuilder().addShapes(listOf(errorShape)).build()
        return ModelTransformer.create().mapShapes(modelShapes) { shape ->
            if (shape is OperationShape && shape.errors.isEmpty()) {
                shape.toBuilder().addError(errorShape).build()
            } else {
                shape
            }
        }
    }
}
+64 −0
Original line number Diff line number Diff line
/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

package software.amazon.smithy.rust.codegen.server.smithy.customizations

import io.kotest.matchers.shouldBe
import org.junit.jupiter.api.Test
import software.amazon.smithy.model.shapes.OperationShape
import software.amazon.smithy.model.shapes.ServiceShape
import software.amazon.smithy.model.shapes.ShapeId
import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestSymbolProvider
import software.amazon.smithy.rust.codegen.smithy.transformers.OperationNormalizer
import software.amazon.smithy.rust.codegen.testutil.asSmithyModel

class FallibleOperationsDecoratorTest {
    private val baseModel = """
        namespace smithy.test
        use aws.protocols#restJson1

        @restJson1
        @title("Test")
        service Test {
            version: "2022-01-01",
            operations: [
                Infallible,
                Fallible
            ]
        }

        operation Infallible {
            input: InfallibleInput,
            output: InfallibleOutput
        }
        structure InfallibleInput {}
        structure InfallibleOutput {}

        operation Fallible {
            input: FallibleInput,
            output: FallibleOutput,
            errors: [FallibleError]
        }
        structure FallibleInput {}
        structure FallibleOutput {}
        @error("client")
        structure FallibleError {}
    """.asSmithyModel()
    private val model = OperationNormalizer.transform(baseModel)
    private val symbolProvider = serverTestSymbolProvider(model)

    @Test
    fun `add InternalServerError to infallible operations only`() {
        val service = ServiceShape.builder().id("smithy.test#Test").build()
        val infallibleId = ShapeId.from("smithy.test#Infallible")
        val fallibleId = ShapeId.from("smithy.test#Fallible")
        model.expectShape(infallibleId, OperationShape::class.java).errors.isEmpty() shouldBe true
        model.expectShape(fallibleId, OperationShape::class.java).errors.size shouldBe 1
        val model = FallibleOperationsDecorator().transformModel(service, model)
        model.expectShape(infallibleId, OperationShape::class.java).errors.isEmpty() shouldBe false
        model.expectShape(infallibleId, OperationShape::class.java).errors.size shouldBe 1
        model.expectShape(fallibleId, OperationShape::class.java).errors.size shouldBe 1
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -3,13 +3,13 @@
 * SPDX-License-Identifier: Apache-2.0.
 */

package software.amazon.smithy.rust.codegen.smithy.generators
package software.amazon.smithy.rust.codegen.server.smithy.generators

import org.junit.jupiter.api.Test
import software.amazon.smithy.model.shapes.StructureShape
import software.amazon.smithy.rust.codegen.rustlang.RustModule
import software.amazon.smithy.rust.codegen.server.smithy.generators.ServerCombinedErrorGenerator
import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestSymbolProvider
import software.amazon.smithy.rust.codegen.smithy.generators.CodegenTarget
import software.amazon.smithy.rust.codegen.smithy.transformers.OperationNormalizer
import software.amazon.smithy.rust.codegen.testutil.TestWorkspace
import software.amazon.smithy.rust.codegen.testutil.asSmithyModel