Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: remove invalid defaults for some services #1116

Merged
merged 1 commit into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/190be92b-a106-476b-99b3-224a80f81d7d.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"id": "190be92b-a106-476b-99b3-224a80f81d7d",
"type": "bugfix",
"description": "**Breaking**: Make some types for various services optional by removing default values",
"requiresMinorVersionBump": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package aws.sdk.kotlin.codegen.customization

import software.amazon.smithy.codegen.core.CodegenException
import software.amazon.smithy.kotlin.codegen.KotlinSettings
import software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration
import software.amazon.smithy.kotlin.codegen.model.hasTrait
import software.amazon.smithy.model.Model
import software.amazon.smithy.model.shapes.AbstractShapeBuilder
import software.amazon.smithy.model.shapes.MemberShape
import software.amazon.smithy.model.shapes.Shape
import software.amazon.smithy.model.shapes.ShapeId
import software.amazon.smithy.model.traits.DefaultTrait
import software.amazon.smithy.model.transform.ModelTransformer
import software.amazon.smithy.utils.ToSmithyBuilder

/**
* Removes the default value of certain shapes, and any member that target
* those shapes,for certain services. These default values may cause
* serialization, validation, or other unexpected issues.
*/
class RemoveDefaults : KotlinIntegration {
// Service shape id -> Shape id of each root shape to remove default values from.
private val removeDefaultsFrom = mapOf(
ShapeId.from("com.amazonaws.amplifyuibuilder#AmplifyUIBuilder") to setOf(
ShapeId.from("com.amazonaws.amplifyuibuilder#ListComponentsLimit"),
ShapeId.from("com.amazonaws.amplifyuibuilder#ListFormsLimit"),
ShapeId.from("com.amazonaws.amplifyuibuilder#ListThemesLimit"),
),
ShapeId.from("com.amazonaws.drs#ElasticDisasterRecoveryService") to setOf(
ShapeId.from("com.amazonaws.drs#Validity"),
ShapeId.from("com.amazonaws.drs#CostOptimizationConfiguration\$burstBalanceThreshold"),
ShapeId.from("com.amazonaws.drs#CostOptimizationConfiguration\$burstBalanceDeltaThreshold"),
ShapeId.from("com.amazonaws.drs#ListStagingAccountsRequest\$maxResults"),
ShapeId.from("com.amazonaws.drs#StrictlyPositiveInteger"),
ShapeId.from("com.amazonaws.drs#MaxResultsType"),
ShapeId.from("com.amazonaws.drs#MaxResultsReplicatingSourceServers"),
ShapeId.from("com.amazonaws.drs#LaunchActionOrder"),
),
ShapeId.from("com.amazonaws.evidently#Evidently") to setOf(
ShapeId.from("com.amazonaws.evidently#ResultsPeriod"),
),
ShapeId.from("com.amazonaws.location#LocationService") to setOf(
ShapeId.from("com.amazonaws.location#ListPlaceIndexesRequest\$MaxResults"),
ShapeId.from("com.amazonaws.location#SearchPlaceIndexForSuggestionsRequest\$MaxResults"),
ShapeId.from("com.amazonaws.location#PlaceIndexSearchResultLimit"),
),
ShapeId.from("com.amazonaws.paymentcryptographydata#PaymentCryptographyDataPlane") to setOf(
ShapeId.from("com.amazonaws.paymentcryptographydata#IntegerRangeBetween4And12"),
),
ShapeId.from("com.amazonaws.emrserverless#AwsToledoWebService") to setOf(
ShapeId.from("com.amazonaws.emrserverless#WorkerCounts"),
),
)

override val order: Byte = 0

override fun enabledForService(model: Model, settings: KotlinSettings): Boolean =
settings.service in removeDefaultsFrom

override fun preprocessModel(model: Model, settings: KotlinSettings): Model {
val serviceId = settings.service
val removeDefaultsFromShapes = removeDefaultsFrom[serviceId]
?: throw CodegenException("expected $serviceId in removed defaults map")
return removeDefaults(model, removeDefaultsFromShapes)
}

fun removeDefaults(model: Model, fromShapes: Set<ShapeId>): Model {
val removedRootDefaults: MutableSet<ShapeId> = HashSet()
val removedRootDefaultsModel = ModelTransformer.create().mapShapes(model) {
if (shouldRemoveRootDefault(it, fromShapes)) {
removedRootDefaults.add(it.id)
removeDefault(it)
} else {
it
}
}

return ModelTransformer.create().mapShapes(removedRootDefaultsModel) {
if (shouldRemoveMemberDefault(it, removedRootDefaults, fromShapes)) {
removeDefault(it)
} else {
it
}
}
}

private fun shouldRemoveRootDefault(shape: Shape, removeDefaultsFrom: Set<ShapeId>): Boolean =
shape !is MemberShape && shape.id in removeDefaultsFrom && shape.hasTrait<DefaultTrait>()

private fun shouldRemoveMemberDefault(
shape: Shape,
removedRootDefaults: Set<ShapeId>,
removeDefaultsFrom: Set<ShapeId>,
): Boolean = shape is MemberShape &&
// Check the original set of shapes to remove for this shape id, to remove members that were in that set.
(shape.target in removedRootDefaults || shape.id in removeDefaultsFrom) &&
shape.hasTrait<DefaultTrait>()

private fun removeDefault(shape: Shape): Shape =
((shape as ToSmithyBuilder<*>).toBuilder() as AbstractShapeBuilder<*, *>)
.removeTrait(DefaultTrait.ID)
.build()
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ aws.sdk.kotlin.codegen.customization.machinelearning.MachineLearningEndpointCust
aws.sdk.kotlin.codegen.customization.route53.TrimResourcePrefix
aws.sdk.kotlin.codegen.customization.route53.ChangeResourceRecordSetsUnmarshallingIntegration
aws.sdk.kotlin.codegen.customization.ec2.EC2MakePrimitivesOptional
aws.sdk.kotlin.codegen.customization.RemoveDefaults
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package aws.sdk.kotlin.codegen.customization

import org.junit.jupiter.api.Test
import software.amazon.smithy.kotlin.codegen.model.hasTrait
import software.amazon.smithy.kotlin.codegen.test.toSmithyModel
import software.amazon.smithy.model.shapes.ShapeId
import software.amazon.smithy.model.traits.DefaultTrait
import kotlin.test.assertFalse

class RemoveDefaultsTest {
@Test
fun removesDefaults() {
val model = """
${"$"}version: "2.0"

namespace test

structure Foo {
bar: Bar = 0
baz: Integer = 0
}

@default(0)
integer Bar

""".toSmithyModel()

val removeDefaultsFrom = setOf(ShapeId.from("test#Bar"), ShapeId.from("test#Foo\$baz"))
val transformed = RemoveDefaults().removeDefaults(model, removeDefaultsFrom)
val barMember = transformed.expectShape(ShapeId.from("test#Foo\$bar"))
assertFalse(barMember.hasTrait<DefaultTrait>())
val bazMember = transformed.expectShape(ShapeId.from("test#Foo\$baz"))
assertFalse(bazMember.hasTrait<DefaultTrait>())
val root = transformed.expectShape(ShapeId.from("test#Bar"))
assertFalse(root.hasTrait<DefaultTrait>())
}
}
Loading