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

Localstack Support: add way to change an AWS endpoint to custom #17

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,4 +156,12 @@ When you installed `awsmeter` using **jmeter-plugins** and executed JMeter with

![Screenshot](https://raw.githubusercontent.com/JoseLuisSR/awsmeter/main/doc/img/awsmeter-compiled-issue.png)

To fix it, please install Java 11 and execute JMeter with this version or install `awsmeter` following the steps described in the [Install](https://github.com/JoseLuisSR/awsmeter#install) section and execute JMeter with th version of Java you have (minimum 8).
To fix it, please install Java 11 and execute JMeter with this version or install `awsmeter` following the steps described in the [Install](https://github.com/JoseLuisSR/awsmeter#install) section and execute JMeter with th version of Java you have (minimum 8).

# Localstack Support
If you need to use the Localstack instead of real AWS - you should change **aws_endpoint_custom** parameter in plugin GUI from empty stirng to some URL of your Localstack instance (with Localstack Edge port)

To avoid a problem with SSL validation - please add SSL certificate of your Localstack to JVM cacerts:
```
keytool -alias ANY_NAME -import -keystore "%JAVA_HOME%\lib\security\cacerts" -file some_localstack_selfsigned_certificate.crt
```
12 changes: 12 additions & 0 deletions src/main/java/org/apache/jmeter/protocol/aws/AWSClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,18 @@ default String getAWSSessionToken(Map<String, String> credentials){
});
}

/**
* Get custom AWS endpoint from input of JMeter Java Request parameter.
* @param credentials
* Represents the input of JMeter Java Request parameters.
* @return AWS endpoint String.
*/
default String getAWSEndpoint(Map<String, String> credentials){
return Optional.ofNullable(credentials.get(AWSSampler.AWS_ENDPOINT_CUSTOM))
.filter(Predicate.not(String::isEmpty))
.orElse("");
}

/**
* Function to get DefaultAwsRegionProviderChain from profile file.
*/
Expand Down
38 changes: 38 additions & 0 deletions src/main/java/org/apache/jmeter/protocol/aws/AWSSampler.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package org.apache.jmeter.protocol.aws;

import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.client.builder.AwsSyncClientBuilder;
import com.amazonaws.regions.Regions;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.jmeter.config.Argument;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerClient;
import org.apache.jmeter.samplers.SampleResult;
import software.amazon.awssdk.core.client.builder.SdkClientBuilder;

import java.net.URI;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
Expand Down Expand Up @@ -52,6 +57,11 @@ public abstract class AWSSampler implements JavaSamplerClient{
*/
protected static final String AWS_DEFAULT_PROFILE = "default";

/**
* Custom AWS endpoint.
*/
protected static final String AWS_ENDPOINT_CUSTOM = "aws_endpoint_custom";

/**
* Fail code.
*/
Expand Down Expand Up @@ -105,6 +115,7 @@ public abstract class AWSSampler implements JavaSamplerClient{
new Argument(AWS_SECRET_ACCESS_KEY, EMPTY),
new Argument(AWS_SESSION_TOKEN, EMPTY),
new Argument(AWS_REGION, EMPTY),
new Argument(AWS_ENDPOINT_CUSTOM, EMPTY),
new Argument(AWS_CONFIG_PROFILE, AWS_DEFAULT_PROFILE))
.collect(Collectors.toList());

Expand Down Expand Up @@ -188,4 +199,31 @@ protected List<MessageAttribute> readMsgAttributes(final String msgAttributes) t
.collect(Collectors.toList());
}

protected <T extends AwsSyncClientBuilder> T wrapClientForLocalstack(
T sdkClientBuilder,
String customEndpoint,
String region
) {
if (customEndpoint.isBlank()) {
return (T) sdkClientBuilder.withRegion(Regions.fromName(region));
} else {
return (T) sdkClientBuilder.withEndpointConfiguration(
new AwsClientBuilder.EndpointConfiguration(customEndpoint, region)
);
}
}

protected <T extends SdkClientBuilder> T wrapClientForLocalstack(
T sdkClientBuilder,
String customEndpoint
) {
if (customEndpoint.isBlank()) {
return sdkClientBuilder;
} else {
return (T) sdkClientBuilder.endpointOverride(
URI.create(customEndpoint)
);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public abstract class CognitoProducerSampler extends AWSSampler implements AWSCl
*/
@Override
public SdkClient createSdkClient(Map<String, String> credentials) {
return CognitoIdentityProviderClient.builder()
return wrapClientForLocalstack(CognitoIdentityProviderClient.builder(), getAWSEndpoint(credentials))
.region(Region.of(getAWSRegion(credentials)))
.credentialsProvider(getAwsCredentialsProvider(credentials))
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public class KinesisProducerSampler extends AWSSampler implements AWSClientSDK2
*/
@Override
public SdkClient createSdkClient(Map<String, String> credentials) {
return KinesisClient.builder()
return wrapClientForLocalstack(KinesisClient.builder(), getAWSEndpoint(credentials))
.region(Region.of(getAWSRegion(credentials)))
.credentialsProvider(getAwsCredentialsProvider(credentials))
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ public abstract class SNSProducerSampler extends AWSSampler implements AWSClient
*/
@Override
public AwsSyncClientBuilder createAWSClient(Map<String, String> credentials) {
return AmazonSNSClient.builder()
.withCredentials(getAWSCredentialsProvider(credentials))
.withRegion(Regions.fromName(getAWSRegion(credentials)));
String awsRegion = getAWSRegion(credentials);
return wrapClientForLocalstack(AmazonSNSClient.builder(), getAWSEndpoint(credentials), awsRegion)
.withCredentials(getAWSCredentialsProvider(credentials));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public abstract class SQSProducerSampler extends AWSSampler implements AWSClient
*/
@Override
public SdkClient createSdkClient(Map<String, String> credentials) {
return SqsClient.builder()
return wrapClientForLocalstack(SqsClient.builder(), getAWSEndpoint(credentials))
.region(Region.of(getAWSRegion(credentials)))
.credentialsProvider(getAwsCredentialsProvider(credentials))
.build();
Expand Down