Skip to content

Add customization in S3 to keep expires as timestamp type #5610

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

Merged
merged 1 commit into from
Sep 20, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import software.amazon.awssdk.codegen.model.service.Operation;
import software.amazon.awssdk.codegen.model.service.ServiceModel;
import software.amazon.awssdk.codegen.model.service.Shape;
import software.amazon.awssdk.utils.CollectionUtils;
import software.amazon.awssdk.utils.Validate;

/**
* This processor internally keeps track of all the structure members whose
Expand All @@ -53,6 +55,8 @@ final class ShapeSubstitutionsProcessor implements CodegenCustomizationProcessor
*/
private final Map<String, Map<String, String>> substitutedListMemberReferences = new HashMap<>();

private final Map<String, Shape> newShapesToAdd = new HashMap<>();

ShapeSubstitutionsProcessor(
Map<String, ShapeSubstitution> shapeSubstitutions) {
this.shapeSubstitutions = shapeSubstitutions;
Expand All @@ -66,12 +70,15 @@ public void preprocess(ServiceModel serviceModel) {
}

// Make sure the substituted shapes exist in the service model
for (String substitutedShape : shapeSubstitutions.keySet()) {
if (!serviceModel.getShapes().containsKey(substitutedShape)) {
for (Entry<String, ShapeSubstitution> substitutedShapeEntry : shapeSubstitutions.entrySet()) {
if (!serviceModel.getShapes().containsKey(substitutedShapeEntry.getKey())) {
throw new IllegalStateException(
"shapeSubstitution customization found for shape "
+ substitutedShape + ", which does not exist in the service model.");
"shapeSubstitution customization found for shape "
+ substitutedShapeEntry + ", which does not exist in the service model.");
}
ShapeSubstitution shapeSubstitution = substitutedShapeEntry.getValue();
Validate.mutuallyExclusive("emitAsShape and emitAsType are mutually exclusive",
shapeSubstitution.getEmitAsShape(), shapeSubstitution.getEmitAsType());
}

// Make sure the substituted shapes are not referenced by any operation
Expand All @@ -84,9 +91,12 @@ public void preprocess(ServiceModel serviceModel) {
for (Entry<String, Shape> entry : serviceModel.getShapes().entrySet()) {
String shapeName = entry.getKey();
Shape shape = entry.getValue();

preprocessSubstituteShapeReferencesInShape(shapeName, shape, serviceModel);
}

if (!CollectionUtils.isNullOrEmpty(newShapesToAdd)) {
serviceModel.getShapes().putAll(newShapesToAdd);
}
}

@Override
Expand Down Expand Up @@ -209,8 +219,24 @@ private void preprocessSubstituteShapeReferencesInShape(
private ShapeSubstitution substituteMemberShape(Member member) {
ShapeSubstitution substitute = shapeSubstitutions.get(member.getShape());

if (substitute != null) {
member.setShape(substitute.getEmitAsShape());
if (substitute == null) {
return null;
}

String emitAsShape = substitute.getEmitAsShape();
if (emitAsShape != null) {
member.setShape(emitAsShape);
return substitute;
}

String emitAsType = substitute.getEmitAsType();

if (emitAsType != null) {
Shape newShapeForType = new Shape();
newShapeForType.setType(emitAsType);
String shapeName = "SdkCustomization_" + emitAsType;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for my understanding, what is this SdkCustomization_ name prefix for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for the case where we need to add a new type to the service model. In this case, we are adding "SdkCustomization_ expires": {"type": "timestamp"} to S3 since it doesn't have a generic timestamp type.

member.setShape(shapeName);
newShapesToAdd.put(shapeName, newShapeForType);
return substitute;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ public static boolean isStructure(Shape shape) {
}

public static boolean isListShape(Shape shape) {
return shape.getType().equals("list");
return shape != null && shape.getType() != null && shape.getType().equals("list");
}

public static boolean isMapShape(Shape shape) {
return shape.getType().equals("map");
return shape.getType() != null && shape.getType().equals("map");
}

public static boolean isEnumShape(Shape shape) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
public class ShapeSubstitution {

private String emitAsShape;
private String emitAsType;
private String emitFromMember;

/**
Expand All @@ -54,6 +55,14 @@ public String getEmitFromMember() {
return emitFromMember;
}

public String getEmitAsType() {
return emitAsType;
}

public void setEmitAsType(String emitAsType) {
this.emitAsType = emitAsType;
}

public void setEmitFromMember(String emitFromMember) {
this.emitFromMember = emitFromMember;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

package software.amazon.awssdk.codegen.customization.processors;

import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;

import java.io.File;
import java.io.IOException;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import software.amazon.awssdk.codegen.C2jModels;
import software.amazon.awssdk.codegen.IntermediateModelBuilder;
import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig;
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
import software.amazon.awssdk.codegen.model.service.ServiceModel;
import software.amazon.awssdk.codegen.model.service.Shape;
import software.amazon.awssdk.codegen.utils.ModelLoaderUtils;

public class ShapeSubstitutionsProcessorTest {

private static CustomizationConfig config;
private static ServiceModel serviceModel;

@BeforeAll
public static void setUp() throws IOException {
File serviceModelFile = new File(ShapeSubstitutionsProcessorTest.class.getResource("service-2.json").getFile());
serviceModel = ModelLoaderUtils.loadModel(ServiceModel.class, serviceModelFile);
File customizationConfigFile = new File(ShapeSubstitutionsProcessorTest.class.getResource("customization.config").getFile());
serviceModel = ModelLoaderUtils.loadModel(ServiceModel.class, serviceModelFile);
config = ModelLoaderUtils.loadModel(CustomizationConfig.class, customizationConfigFile);
}

@Test
public void setCustomStringShape_isAddedToModel() {
assertThat(serviceModel.getShapes().get("Timestamp").getType()).isEqualTo("string");
IntermediateModel intermediateModel = new IntermediateModelBuilder(C2jModels.builder()
.serviceModel(serviceModel)
.customizationConfig(config)
.build())
.build();

assertThat(serviceModel.getShapes().get("AllTypesStructure").getMembers().get("Timestamp").getShape()).isEqualTo(
"SdkCustomization_timestamp");
Shape listShape = serviceModel.getShapes().get("ListOfTimestamps");
assertThat(listShape.getListMember().getShape()).isEqualTo("SdkCustomization_timestamp");

Shape structShape = serviceModel.getShapes().get("StructWithTimestamp");
assertThat(structShape.getMembers().get("Timestamp").getShape()).isEqualTo("SdkCustomization_timestamp");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"shapeSubstitutions": {
"Timestamp": {
"emitAsType": "timestamp"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"version":"2.0",
"metadata":{
"apiVersion":"2016-03-11",
"endpointPrefix":"restjson",
"jsonVersion":"1.1",
"protocol":"rest-json",
"serviceAbbreviation":"JsonProtocolTests",
"serviceFullName":"AWS DR Tools JSON Protocol Tests",
"serviceId":"Json Protocol Tests",
"signatureVersion":"v4",
"targetPrefix":"ProtocolTestsJsonRpcService",
"timestampFormat":"unixTimestamp",
"uid":"restjson-2016-03-11"
},
"operations":{
"AllTypes":{
"name":"AllTypes",
"http":{
"method":"POST",
"requestUri":"/"
},
"input":{"shape":"AllTypesStructure"}
}
},
"shapes": {
"AllTypesStructure": {
"type": "structure",
"members": {
"TimeStampMember": {
"shape": "Timestamp"
},
"ListOfTimestamps": {
"shape": "ListOfTimestamps"
},
"Timestamp": {
"shape": "Timestamp"
},
"StructWithTimestamp": {
"shape": "StructWithTimestamp"
}
}
},
"ListOfTimestamps": {
"type": "list",
"member": {
"shape": "Timestamp"
}
},
"StructWithTimestamp": {
"type": "structure",
"members": {
"Timestamp": {
"shape": "Timestamp"
}
}
},
"Timestamp": {
"type": "string"
},
"String" : {
"type" : "string"
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
{
"shapeSubstitutions": {
"Expires": {
"emitAsType": "timestamp"
}
},
"verifiedSimpleMethods": [
"listBuckets"
],
Expand Down Expand Up @@ -27,24 +32,6 @@
}
]
},
"PutObjectRequest": {
"modify": [
{
"Expires": {
"emitAsType": "timestamp"
}
}
]
},
"WriteGetObjectResponseRequest": {
"modify": [
{
"Expires": {
"emitAsType": "timestamp"
}
}
]
},
"GetObjectOutput": {
"modify": [
{
Expand Down Expand Up @@ -89,15 +76,6 @@
}
]
},
"CreateMultipartUploadRequest": {
"modify": [
{
"Expires": {
"emitAsType": "timestamp"
}
}
]
},
"UploadPartRequest": {
"inject": [
{
Expand Down Expand Up @@ -138,11 +116,7 @@
"Key": {
"emitPropertyName": "DestinationKey",
"existingNameDeprecated": true
},
"Expires": {
"emitAsType": "timestamp"
}

}
]
},
Expand Down
Loading