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

Adds list of string to endpoint/auth scheme parameters and support for JmesPath-defined operation context parameters #5168

Merged
merged 16 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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/next-release/feature-AWSSDKforJavav2-e2f515d.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"type": "feature",
"category": "AWS SDK for Java v2",
"contributor": "",
"description": "Adds capability to resolve endpoint and auth scheme parameters of type list of string as well as new functions to JmesPath runtime (keys and wildcard)"
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ private static void configurePackageName(Metadata metadata,
.withPaginatorsPackageName(namingStrategy.getPaginatorsPackageName(service))
.withWaitersPackageName(namingStrategy.getWaitersPackageName(service))
.withEndpointRulesPackageName(namingStrategy.getEndpointRulesPackageName(service))
.withAuthSchemePackageName(namingStrategy.getAuthSchemePackageName(service));
.withAuthSchemePackageName(namingStrategy.getAuthSchemePackageName(service))
.withJmesPathPackageName(namingStrategy.getJmesPathPackageName(service));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ public Map<String, OperationModel> constructOperations() {
operationModel.setHttpChecksum(op.getHttpChecksum());
operationModel.setRequestcompression(op.getRequestcompression());
operationModel.setStaticContextParams(op.getStaticContextParams());
operationModel.setOperationContextParams(op.getOperationContextParams());
operationModel.setAuth(getAuthFromOperation(op));

Input input = op.getInput();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import software.amazon.awssdk.codegen.model.intermediate.ShapeModel;
import software.amazon.awssdk.codegen.model.rules.endpoints.EndpointTestSuiteModel;
import software.amazon.awssdk.codegen.model.service.AuthType;
import software.amazon.awssdk.codegen.model.service.CustomOperationContextParam;
import software.amazon.awssdk.codegen.model.service.EndpointRuleSetModel;
import software.amazon.awssdk.codegen.model.service.Operation;
import software.amazon.awssdk.codegen.model.service.Paginators;
Expand Down Expand Up @@ -167,10 +168,43 @@ public IntermediateModel build() {
setSimpleMethods(trimmedModel);

namingStrategy.validateCustomerVisibleNaming(trimmedModel);

customizeEndpointParameters(fullModel, endpointRuleSet);
customizeOperationContextParams(trimmedModel, fullModel.getCustomizationConfig().getCustomOperationContextParams());
return trimmedModel;
}

private static void customizeOperationContextParams(IntermediateModel trimmedModel,
List<CustomOperationContextParam> customOperationContextParams) {

if (CollectionUtils.isNullOrEmpty(customOperationContextParams)) {
return;
}
customOperationContextParams.forEach(customOperationContextParam -> {
String operationName = customOperationContextParam.getOperationName();
OperationModel operation = trimmedModel.getOperation(operationName);
if (operation == null) {
throw new IllegalStateException(
"Could not find operation " + operationName + " to customize Operation Context Params.");
}
if (operation.getOperationContextParams() != null) {
throw new IllegalStateException(
"Cannot customize operation " + operationName + " which already has OperationContextParams.");
}
operation.setOperationContextParams(customOperationContextParam.getOperationContextParamsMap());
});
}

private void customizeEndpointParameters(IntermediateModel fullModel, EndpointRuleSetModel endpointRuleSet) {
if (fullModel.getCustomizationConfig().getEndpointParameters() != null) {
fullModel.getCustomizationConfig().getEndpointParameters().keySet().forEach(key -> {
if (endpointRuleSet.getParameters().containsKey(key)) {
throw new IllegalStateException("Duplicate parameters found in customizationConfig");
}
});
fullModel.getCustomizationConfig().getEndpointParameters().forEach(endpointRuleSet.getParameters()::put);
}
}

/**
* Link the member to it's corresponding shape (if it exists).
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,7 @@ public String getAuthSchemeInternalDirectory() {
return sourceDirectory + "/" + Utils.packageToDirectory(model.getMetadata().getFullInternalAuthSchemePackageName());
}

public String getJmesPathInternalDirectory() {
return sourceDirectory + "/" + Utils.packageToDirectory(model.getMetadata().getFullInternalJmesPathPackageName());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import software.amazon.awssdk.codegen.emitters.GeneratorTask;
import software.amazon.awssdk.codegen.emitters.GeneratorTaskParams;
import software.amazon.awssdk.codegen.emitters.PoetGeneratorTask;
import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig;
import software.amazon.awssdk.codegen.model.rules.endpoints.ParameterModel;
import software.amazon.awssdk.codegen.model.service.ClientContextParam;
import software.amazon.awssdk.codegen.poet.rules.ClientContextParamsClassSpec;
import software.amazon.awssdk.codegen.poet.rules.DefaultPartitionDataProviderSpec;
Expand Down Expand Up @@ -57,6 +59,9 @@ protected List<GeneratorTask> createTasks() throws Exception {
tasks.add(generateDefaultProvider());
tasks.add(new RulesEngineRuntimeGeneratorTask(generatorTaskParams));
}
if (shouldGenerateJmesPathRuntime()) {
tasks.add(new JmesPathRuntimeGeneratorTask(generatorTaskParams));
}
tasks.addAll(generateInterceptors());
if (shouldGenerateEndpointTests()) {
tasks.add(generateProviderTests());
Expand Down Expand Up @@ -149,4 +154,27 @@ private boolean hasClientContextParams() {
(customClientContextParams != null && !customClientContextParams.isEmpty());
}

private boolean shouldGenerateJmesPathRuntime() {
boolean isAlreadyGenerated = model.hasWaiters();
if (isAlreadyGenerated) {
return true;
}

Map<String, ParameterModel> endpointParameters = model.getCustomizationConfig().getEndpointParameters();
if (endpointParameters == null) {
return false;
}

return endpointParameters.values().stream().anyMatch(this::paramRequiresPathParserRuntime);
}

private boolean paramRequiresPathParserRuntime(ParameterModel parameterModel) {
return paramIsOperationalContextParam(parameterModel) &&
"stringarray".equals(parameterModel.getType().toLowerCase(Locale.US));
}

//TODO (string-array-params): resolve this logical test before finalizing coding
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Adding handling this TODO to the fast-follow cleanup task.

private boolean paramIsOperationalContextParam(ParameterModel parameterModel) {
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* 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.emitters.tasks;

import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.util.Collections;
import java.util.List;
import software.amazon.awssdk.codegen.emitters.GeneratorTask;
import software.amazon.awssdk.codegen.emitters.GeneratorTaskParams;
import software.amazon.awssdk.codegen.emitters.SimpleGeneratorTask;
import software.amazon.awssdk.utils.IoUtils;

public final class JmesPathRuntimeGeneratorTask extends BaseGeneratorTasks {
public static final String RUNTIME_CLASS_NAME = "JmesPathRuntime";

private final String runtimeClassDir;
private final String runtimePackageName;
private final String fileHeader;
private final String runtimeClassCode;

public JmesPathRuntimeGeneratorTask(GeneratorTaskParams generatorTaskParams) {
super(generatorTaskParams);
this.runtimeClassDir = generatorTaskParams.getPathProvider().getJmesPathInternalDirectory();
this.runtimePackageName = generatorTaskParams.getModel().getMetadata().getFullInternalJmesPathPackageName();
this.fileHeader = generatorTaskParams.getModel().getFileHeader();
this.runtimeClassCode = loadRuntimeCode();
}

@Override
protected List<GeneratorTask> createTasks() throws Exception {
String codeContents =
"package " + runtimePackageName + ";\n" +
"\n"
+ runtimeClassCode;

String fileName = RUNTIME_CLASS_NAME + ".java";
return Collections.singletonList(new SimpleGeneratorTask(runtimeClassDir, fileName, fileHeader,
() -> codeContents));
}

private static String loadRuntimeCode() {
try {
InputStream is = JmesPathRuntimeGeneratorTask.class.getResourceAsStream(
String.format("/software/amazon/awssdk/codegen/jmespath/%s.java.resource", RUNTIME_CLASS_NAME));
return IoUtils.toUtf8String(is);
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ protected List<GeneratorTask> createTasks() {
generatorTasks.addAll(createSyncTasks());
generatorTasks.addAll(createAsyncTasks());
generatorTasks.add(new WaitersRuntimeGeneratorTask(generatorTaskParams));
generatorTasks.add(new JmesPathRuntimeGeneratorTask(generatorTaskParams));
return generatorTasks;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ protected List<GeneratorTask> createTasks() throws Exception {
private static String loadWaitersRuntimeCode() {
try {
InputStream is = WaitersRuntimeGeneratorTask.class.getResourceAsStream(
"/software/amazon/awssdk/codegen/waiters/WaitersRuntime.java.resource");
"/software/amazon/awssdk/codegen/waiters/WaitersRuntime.java.resource");
return IoUtils.toUtf8String(is);
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ public final class Constant {

public static final String PACKAGE_NAME_AUTH_SCHEME_PATTERN = "%s.auth.scheme";

public static final String PACKAGE_NAME_JMESPATH_PATTERN = "%s.jmespath";

public static final String PACKAGE_NAME_SMOKE_TEST_PATTERN = "%s.smoketests";

public static final String PACKAGE_NAME_CUSTOM_AUTH_PATTERN = "%s.auth";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import software.amazon.awssdk.codegen.model.rules.endpoints.ParameterModel;
import software.amazon.awssdk.codegen.model.service.ClientContextParam;
import software.amazon.awssdk.codegen.model.service.CustomOperationContextParam;
import software.amazon.awssdk.core.retry.RetryMode;
import software.amazon.awssdk.core.traits.PayloadTrait;
import software.amazon.awssdk.utils.AttributeMap;
Expand Down Expand Up @@ -318,6 +320,14 @@ public class CustomizationConfig {
*/
private boolean useMultiAuth;

/**
* Special case for a service where model changes for endpoint params were not updated .
* This should be removed once the service updates its models
*/
private Map<String, ParameterModel> endpointParameters;

private List<CustomOperationContextParam> customOperationContextParams;

private CustomizationConfig() {
}

Expand Down Expand Up @@ -843,4 +853,20 @@ public void setUseMultiAuth(boolean useMultiAuth) {
public boolean useMultiAuth() {
return useMultiAuth;
}

public Map<String, ParameterModel> getEndpointParameters() {
return endpointParameters;
}

public void setEndpointParameters(Map<String, ParameterModel> endpointParameters) {
this.endpointParameters = endpointParameters;
}

public List<CustomOperationContextParam> getCustomOperationContextParams() {
return customOperationContextParams;
}

public void setCustomOperationContextParams(List<CustomOperationContextParam> customOperationContextParams) {
this.customOperationContextParams = customOperationContextParams;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ public class Metadata {

private String authSchemePackageName;

private String jmesPathPackageName;

private String serviceAbbreviation;

private String serviceFullName;
Expand Down Expand Up @@ -764,4 +766,27 @@ public String getFullInternalAuthSchemePackageName() {
public String getFullInternalPackageName() {
return joinPackageNames(getFullClientPackageName(), "internal");
}

public Metadata setJmesPathPackageName(String jmesPathPackageName) {
this.jmesPathPackageName = jmesPathPackageName;
return this;
}

public Metadata withJmesPathPackageName(String jmesPathPackageName) {
setJmesPathPackageName(jmesPathPackageName);
return this;
}

public String getJmesPathPackageName() {
return jmesPathPackageName;
}

public String getFullJmesPathPackageName() {
return joinPackageNames(rootPackageName, getJmesPathPackageName());
}

public String getFullInternalJmesPathPackageName() {
return joinPackageNames(getFullJmesPathPackageName(), "internal");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import software.amazon.awssdk.codegen.internal.Utils;
import software.amazon.awssdk.codegen.model.service.AuthType;
import software.amazon.awssdk.codegen.model.service.EndpointTrait;
import software.amazon.awssdk.codegen.model.service.OperationContextParam;
import software.amazon.awssdk.codegen.model.service.StaticContextParam;

public class OperationModel extends DocumentationModel {
Expand Down Expand Up @@ -83,6 +84,9 @@ public class OperationModel extends DocumentationModel {
@JsonIgnore
private Map<String, StaticContextParam> staticContextParams;

@JsonIgnore
private Map<String, OperationContextParam> operationContextParams;

public String getOperationName() {
return operationName;
}
Expand Down Expand Up @@ -357,4 +361,12 @@ public Map<String, StaticContextParam> getStaticContextParams() {
public void setStaticContextParams(Map<String, StaticContextParam> staticContextParams) {
this.staticContextParams = staticContextParams;
}

public Map<String, OperationContextParam> getOperationContextParams() {
return operationContextParams;
}

public void setOperationContextParams(Map<String, OperationContextParam> operationContextParams) {
this.operationContextParams = operationContextParams;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* 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.model.service;


import java.util.Map;
import software.amazon.awssdk.annotations.SdkInternalApi;

@SdkInternalApi
public class CustomOperationContextParam {
Map<String, OperationContextParam> operationContextParamsMap;

String operationName;

public Map<String, OperationContextParam> getOperationContextParamsMap() {
return operationContextParamsMap;
}

public void setOperationContextParamsMap(Map<String, OperationContextParam> operationContextParamsMap) {
this.operationContextParamsMap = operationContextParamsMap;
}

public String getOperationName() {
return operationName;
}

public void setOperationName(String operationName) {
this.operationName = operationName;
}
}
Loading
Loading