You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by or...@apache.org on 2020/10/09 14:04:15 UTC

[camel] branch master updated: Migrated the AWS SDK v2 Test infra from Camel Kafka Connector (#4408)

This is an automated email from the ASF dual-hosted git repository.

orpiske pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/master by this push:
     new bb473a6  Migrated the AWS SDK v2 Test infra from Camel Kafka Connector (#4408)
bb473a6 is described below

commit bb473a6a7fd935ea311e675ef5d9ef6ce884ddff
Author: Otavio Rodolfo Piske <or...@users.noreply.github.com>
AuthorDate: Fri Oct 9 16:02:56 2020 +0200

    Migrated the AWS SDK v2 Test infra from Camel Kafka Connector (#4408)
    
    This simplifies using localstack containers as well as the actual AWS
    service as part of the tests
---
 test-infra/camel-test-infra-aws-v2/pom.xml         |  90 ++++++++++++++
 .../src/main/resources/META-INF/MANIFEST.MF        |   0
 .../test/infra/aws2/clients/AWSSDKClientUtils.java | 133 +++++++++++++++++++++
 .../aws2/common/TestAWSCredentialsProvider.java    |  68 +++++++++++
 .../test/infra/aws2/services/AWSContainer.java     |  79 ++++++++++++
 .../services/AWSKinesisLocalContainerService.java  |  47 ++++++++
 .../aws2/services/AWSLocalContainerService.java    |  93 ++++++++++++++
 .../test/infra/aws2/services/AWSRemoteService.java |  65 ++++++++++
 .../aws2/services/AWSS3LocalContainerService.java  |  46 +++++++
 .../aws2/services/AWSSQSLocalContainerService.java |  48 ++++++++
 .../infra/aws2/services/AWSServiceFactory.java     |  93 ++++++++++++++
 .../camel/test/infra/aws2/services/Service.java    |  38 ++++++
 test-infra/pom.xml                                 |   3 +-
 13 files changed, 802 insertions(+), 1 deletion(-)

diff --git a/test-infra/camel-test-infra-aws-v2/pom.xml b/test-infra/camel-test-infra-aws-v2/pom.xml
new file mode 100644
index 0000000..889da71
--- /dev/null
+++ b/test-infra/camel-test-infra-aws-v2/pom.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>camel-test-infra-parent</artifactId>
+        <groupId>org.apache.camel</groupId>
+        <relativePath>../camel-test-infra-parent/pom.xml</relativePath>
+        <version>3.6.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>camel-test-infra-aws-v2</artifactId>
+    <name>Camel :: Test Infra :: AWS SDK v2</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-infra-common</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-infra-aws-common</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.testcontainers</groupId>
+            <artifactId>testcontainers</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>software.amazon.awssdk</groupId>
+            <artifactId>sqs</artifactId>
+            <version>${aws-java-sdk2-version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>software.amazon.awssdk</groupId>
+            <artifactId>kinesis</artifactId>
+            <version>${aws-java-sdk2-version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>software.amazon.awssdk</groupId>
+            <artifactId>s3</artifactId>
+            <version>${aws-java-sdk2-version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>software.amazon.awssdk</groupId>
+            <artifactId>apache-client</artifactId>
+            <version>${aws-java-sdk2-version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+
+</project>
\ No newline at end of file
diff --git a/test-infra/camel-test-infra-aws-v2/src/main/resources/META-INF/MANIFEST.MF b/test-infra/camel-test-infra-aws-v2/src/main/resources/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..e69de29
diff --git a/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/clients/AWSSDKClientUtils.java b/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/clients/AWSSDKClientUtils.java
new file mode 100644
index 0000000..a6961bb
--- /dev/null
+++ b/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/clients/AWSSDKClientUtils.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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 org.apache.camel.test.infra.aws2.clients;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.apache.camel.test.infra.aws.common.AWSConfigs;
+import org.apache.camel.test.infra.aws2.common.TestAWSCredentialsProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.kinesis.KinesisClient;
+import software.amazon.awssdk.services.kinesis.KinesisClientBuilder;
+import software.amazon.awssdk.services.s3.S3Client;
+import software.amazon.awssdk.services.s3.S3ClientBuilder;
+import software.amazon.awssdk.services.sqs.SqsClient;
+import software.amazon.awssdk.services.sqs.SqsClientBuilder;
+
+public final class AWSSDKClientUtils {
+    private static final Logger LOG = LoggerFactory.getLogger(AWSSDKClientUtils.class);
+
+    private AWSSDKClientUtils() {
+
+    }
+
+    private static URI getEndpoint() {
+        String amazonHost = System.getProperty(AWSConfigs.AMAZON_AWS_HOST);
+
+        if (amazonHost == null || amazonHost.isEmpty()) {
+            return null;
+        }
+
+        try {
+            return new URI(String.format("http://%s", amazonHost));
+        } catch (URISyntaxException e) {
+            throw new RuntimeException("Invalid endpoint");
+        }
+    }
+
+    private static boolean isLocalContainer(String awsInstanceType) {
+        return awsInstanceType == null || awsInstanceType.equals("local-aws-container");
+    }
+
+    public static KinesisClient newKinesisClient() {
+        LOG.debug("Creating a new AWS v2 Kinesis client");
+
+        String awsInstanceType = System.getProperty("aws-service.kinesis.instance.type");
+
+        KinesisClientBuilder clientBuilder = KinesisClient.builder();
+
+        clientBuilder.region(Region.US_EAST_1);
+
+        URI endpoint = getEndpoint();
+
+        if (isLocalContainer(awsInstanceType) || endpoint != null) {
+            clientBuilder.endpointOverride(endpoint);
+        }
+
+        if (isLocalContainer(awsInstanceType)) {
+            clientBuilder.credentialsProvider(TestAWSCredentialsProvider.CONTAINER_LOCAL_DEFAULT_PROVIDER);
+
+        } else {
+            clientBuilder.credentialsProvider(TestAWSCredentialsProvider.SYSTEM_PROPERTY_PROVIDER);
+        }
+
+        return clientBuilder.build();
+    }
+
+    public static SqsClient newSQSClient() {
+        LOG.debug("Creating a new AWS v2 SQS client");
+
+        String awsInstanceType = System.getProperty("aws-service.instance.type");
+
+        SqsClientBuilder clientBuilder = SqsClient.builder();
+
+        clientBuilder.region(Region.US_EAST_1);
+
+        URI endpoint = getEndpoint();
+
+        if (isLocalContainer(awsInstanceType) || endpoint != null) {
+            clientBuilder.endpointOverride(endpoint);
+        }
+
+        if (isLocalContainer(awsInstanceType)) {
+            clientBuilder.credentialsProvider(TestAWSCredentialsProvider.CONTAINER_LOCAL_DEFAULT_PROVIDER);
+
+        } else {
+            clientBuilder.credentialsProvider(TestAWSCredentialsProvider.SYSTEM_PROPERTY_PROVIDER);
+        }
+
+        return clientBuilder.build();
+    }
+
+    public static S3Client newS3Client() {
+        LOG.debug("Creating a new S3 client");
+        S3ClientBuilder clientBuilder = S3Client.builder();
+
+        String awsInstanceType = System.getProperty("aws-service.instance.type");
+
+        clientBuilder.region(Region.US_EAST_1);
+
+        URI endpoint = getEndpoint();
+
+        if (isLocalContainer(awsInstanceType) || endpoint != null) {
+            clientBuilder.endpointOverride(endpoint);
+        }
+
+        if (isLocalContainer(awsInstanceType)) {
+            clientBuilder.credentialsProvider(TestAWSCredentialsProvider.CONTAINER_LOCAL_DEFAULT_PROVIDER);
+
+        } else {
+            clientBuilder.credentialsProvider(TestAWSCredentialsProvider.SYSTEM_PROPERTY_PROVIDER);
+        }
+
+        return clientBuilder.build();
+    }
+}
diff --git a/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/common/TestAWSCredentialsProvider.java b/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/common/TestAWSCredentialsProvider.java
new file mode 100644
index 0000000..6ecbca4
--- /dev/null
+++ b/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/common/TestAWSCredentialsProvider.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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 org.apache.camel.test.infra.aws2.common;
+
+import org.apache.camel.test.infra.aws.common.AWSConfigs;
+import software.amazon.awssdk.auth.credentials.AwsCredentials;
+import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
+
+public class TestAWSCredentialsProvider implements AwsCredentialsProvider {
+    public static final TestAWSCredentialsProvider CONTAINER_LOCAL_DEFAULT_PROVIDER
+            = new TestAWSCredentialsProvider("accesskey", "secretkey");
+
+    public static final TestAWSCredentialsProvider SYSTEM_PROPERTY_PROVIDER = new TestAWSCredentialsProvider();
+
+    private static class TestAWSCredentials implements AwsCredentials {
+        private final String accessKey;
+        private final String secretKey;
+
+        public TestAWSCredentials() {
+            this(System.getProperty(AWSConfigs.ACCESS_KEY), System.getProperty(AWSConfigs.SECRET_KEY));
+        }
+
+        public TestAWSCredentials(String accessKey, String secretKey) {
+            this.accessKey = accessKey;
+            this.secretKey = secretKey;
+        }
+
+        @Override
+        public String accessKeyId() {
+            return accessKey;
+        }
+
+        @Override
+        public String secretAccessKey() {
+            return secretKey;
+        }
+
+    };
+
+    private AwsCredentials credentials;
+
+    public TestAWSCredentialsProvider() {
+        credentials = new TestAWSCredentials();
+    }
+
+    public TestAWSCredentialsProvider(String accessKey, String secretKey) {
+        credentials = new TestAWSCredentials(accessKey, secretKey);
+    }
+
+    @Override
+    public AwsCredentials resolveCredentials() {
+        return credentials;
+    }
+}
diff --git a/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/AWSContainer.java b/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/AWSContainer.java
new file mode 100644
index 0000000..45988b3
--- /dev/null
+++ b/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/AWSContainer.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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 org.apache.camel.test.infra.aws2.services;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+import org.apache.camel.test.infra.aws2.common.TestAWSCredentialsProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.containers.wait.strategy.Wait;
+import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
+
+/*
+ The reason we are not using LocalStack containers here is because they bundle AWS SDK v1. They would
+ be added to the classpath during the test and, potentially, cause errors or cause the code to not
+ behave as in runtime.
+ */
+public class AWSContainer extends GenericContainer<AWSContainer> {
+    private static final String LOCALSTACK_CONTAINER = "localstack/localstack:0.11.3";
+
+    private static final Logger LOG = LoggerFactory.getLogger(AWSLocalContainerService.class);
+    private static final int SERVICE_PORT = 4566;
+
+    public AWSContainer(Service... services) {
+        this(LOCALSTACK_CONTAINER, services);
+    }
+
+    public AWSContainer(String container, Service... services) {
+        super(container);
+
+        String serviceList = Arrays.stream(services)
+                .map(Service::serviceName)
+                .collect(Collectors.joining(","));
+
+        LOG.debug("Creating services {}", serviceList);
+        withEnv("SERVICE", serviceList);
+        withExposedPorts(SERVICE_PORT);
+        waitingFor(Wait.forLogMessage(".*Ready\\.\n", 1));
+    }
+
+    public AwsCredentialsProvider getCredentialsProvider() {
+        return TestAWSCredentialsProvider.CONTAINER_LOCAL_DEFAULT_PROVIDER;
+    }
+
+    protected String getAmazonHost() {
+        return getContainerIpAddress() + ":" + getMappedPort(SERVICE_PORT);
+    }
+
+    public URI getServiceEndpoint() {
+        try {
+            String address = String.format("http://%s:%d", getContainerIpAddress(), getMappedPort(SERVICE_PORT));
+            LOG.debug("Running on service endpoint: {}", address);
+
+            return new URI(address);
+        } catch (URISyntaxException e) {
+            throw new RuntimeException(String.format("Unable to determine the service endpoint: %s", e.getMessage()), e);
+        }
+
+    }
+}
diff --git a/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/AWSKinesisLocalContainerService.java b/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/AWSKinesisLocalContainerService.java
new file mode 100644
index 0000000..58b5290
--- /dev/null
+++ b/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/AWSKinesisLocalContainerService.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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 org.apache.camel.test.infra.aws2.services;
+
+import org.apache.camel.test.infra.aws2.common.TestAWSCredentialsProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.kinesis.KinesisClient;
+
+public class AWSKinesisLocalContainerService extends AWSLocalContainerService<KinesisClient> {
+    private static final Logger LOG = LoggerFactory.getLogger(AWSKinesisLocalContainerService.class);
+
+    public AWSKinesisLocalContainerService() {
+        super(Service.KINESIS);
+
+        LOG.info("Initializing the local AWS services");
+        getContainer().start();
+    }
+
+    @Override
+    public KinesisClient getClient() {
+        Region region = Region.US_EAST_1;
+        KinesisClient client = KinesisClient.builder()
+                .region(region)
+                .credentialsProvider(TestAWSCredentialsProvider.CONTAINER_LOCAL_DEFAULT_PROVIDER)
+                .endpointOverride(getServiceEndpoint())
+                .build();
+
+        return client;
+    }
+}
diff --git a/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/AWSLocalContainerService.java b/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/AWSLocalContainerService.java
new file mode 100644
index 0000000..f48c9bf
--- /dev/null
+++ b/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/AWSLocalContainerService.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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 org.apache.camel.test.infra.aws2.services;
+
+import java.net.URI;
+import java.util.Properties;
+
+import org.apache.camel.test.infra.aws.common.AWSConfigs;
+import org.apache.camel.test.infra.aws.common.services.AWSService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import software.amazon.awssdk.auth.credentials.AwsCredentials;
+import software.amazon.awssdk.regions.Region;
+
+abstract class AWSLocalContainerService<T> implements AWSService<T> {
+    private static final Logger LOG = LoggerFactory.getLogger(AWSLocalContainerService.class);
+    private AWSContainer container;
+
+    public AWSLocalContainerService(Service... services) {
+        container = new AWSContainer(services);
+    }
+
+    public AWSLocalContainerService(String containerName, Service... services) {
+        container = new AWSContainer(containerName, services);
+    }
+
+    private String getAmazonHost() {
+        return container.getAmazonHost();
+    }
+
+    protected AWSContainer getContainer() {
+        return container;
+    }
+
+    @Override
+    public Properties getConnectionProperties() {
+        Properties properties = new Properties();
+
+        AwsCredentials credentials = container.getCredentialsProvider().resolveCredentials();
+
+        properties.put(AWSConfigs.ACCESS_KEY, credentials.accessKeyId());
+
+        properties.put(AWSConfigs.SECRET_KEY, credentials.secretAccessKey());
+
+        properties.put(AWSConfigs.REGION, Region.US_EAST_1.toString());
+
+        properties.put(AWSConfigs.AMAZON_AWS_HOST, container.getAmazonHost());
+
+        /**
+         * We need to set this one. For some sets, when they instantiate the clients within Camel, they need to know
+         * what is the Amazon host being used (ie.: when creating them using the withEndpointConfiguration()). Because
+         * this happens within Camel, there's no way to pass that information easily. Therefore, the host is set as a
+         * property and read by whatever class/method creates the clients to pass to Camel.
+         *
+         * Do not unset.
+         */
+        System.setProperty(AWSConfigs.AMAZON_AWS_HOST, getAmazonHost());
+
+        properties.put(AWSConfigs.PROTOCOL, "http");
+
+        return properties;
+    }
+
+    public URI getServiceEndpoint() {
+        return container.getServiceEndpoint();
+    }
+
+    @Override
+    public void initialize() {
+        LOG.info("AWS service running at address {}", getServiceEndpoint());
+    }
+
+    @Override
+    public void shutdown() {
+        LOG.info("Stopping the local AWS services");
+        container.stop();
+    }
+}
diff --git a/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/AWSRemoteService.java b/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/AWSRemoteService.java
new file mode 100644
index 0000000..c45c0ea
--- /dev/null
+++ b/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/AWSRemoteService.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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 org.apache.camel.test.infra.aws2.services;
+
+import java.util.Properties;
+import java.util.function.Supplier;
+
+import org.apache.camel.test.infra.aws.common.AWSConfigs;
+import org.apache.camel.test.infra.aws.common.services.AWSService;
+import org.apache.camel.test.infra.aws2.common.TestAWSCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.AwsCredentials;
+import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
+import software.amazon.awssdk.regions.Region;
+
+public class AWSRemoteService<T> implements AWSService<T> {
+    private static final AwsCredentialsProvider CREDENTIALS_PROVIDER = new TestAWSCredentialsProvider();
+    private Supplier<T> remoteClientSupplier;
+
+    public AWSRemoteService(Supplier<T> remoteClientSupplier) {
+        this.remoteClientSupplier = remoteClientSupplier;
+    }
+
+    @Override
+    public T getClient() {
+        return remoteClientSupplier.get();
+    }
+
+    @Override
+    public Properties getConnectionProperties() {
+        Properties properties = new Properties();
+
+        AwsCredentials credentials = CREDENTIALS_PROVIDER.resolveCredentials();
+
+        properties.put(AWSConfigs.ACCESS_KEY, credentials.accessKeyId());
+        properties.put(AWSConfigs.SECRET_KEY, credentials.secretAccessKey());
+        properties.put(AWSConfigs.REGION, Region.US_EAST_1.toString());
+
+        return properties;
+    }
+
+    @Override
+    public void initialize() {
+
+    }
+
+    @Override
+    public void shutdown() {
+
+    }
+}
diff --git a/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/AWSS3LocalContainerService.java b/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/AWSS3LocalContainerService.java
new file mode 100644
index 0000000..873ad15
--- /dev/null
+++ b/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/AWSS3LocalContainerService.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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 org.apache.camel.test.infra.aws2.services;
+
+import org.apache.camel.test.infra.aws2.common.TestAWSCredentialsProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.s3.S3Client;
+
+public class AWSS3LocalContainerService extends AWSLocalContainerService<S3Client> {
+    private static final Logger LOG = LoggerFactory.getLogger(AWSS3LocalContainerService.class);
+
+    public AWSS3LocalContainerService() {
+        super(Service.S3);
+
+        LOG.info("Initializing the local AWS services");
+        getContainer().start();
+    }
+
+    @Override
+    public S3Client getClient() {
+        Region region = Region.US_EAST_1;
+
+        return S3Client.builder()
+                .region(region)
+                .credentialsProvider(TestAWSCredentialsProvider.CONTAINER_LOCAL_DEFAULT_PROVIDER)
+                .endpointOverride(getServiceEndpoint())
+                .build();
+    }
+}
diff --git a/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/AWSSQSLocalContainerService.java b/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/AWSSQSLocalContainerService.java
new file mode 100644
index 0000000..c6e59ab
--- /dev/null
+++ b/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/AWSSQSLocalContainerService.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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 org.apache.camel.test.infra.aws2.services;
+
+import org.apache.camel.test.infra.aws2.common.TestAWSCredentialsProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.sqs.SqsClient;
+
+public class AWSSQSLocalContainerService extends AWSLocalContainerService<SqsClient> {
+    private static final Logger LOG = LoggerFactory.getLogger(AWSSQSLocalContainerService.class);
+
+    public AWSSQSLocalContainerService() {
+        // Current latest container - localstack/localstack:0.11.3 - is broken for SQS
+        // therefore uses an older version
+        super("localstack/localstack:0.11.2", Service.SQS);
+
+        LOG.info("Initializing the local AWS services");
+        getContainer().start();
+    }
+
+    @Override
+    public SqsClient getClient() {
+        Region region = Region.US_EAST_1;
+
+        return SqsClient.builder()
+                .region(region)
+                .credentialsProvider(TestAWSCredentialsProvider.CONTAINER_LOCAL_DEFAULT_PROVIDER)
+                .endpointOverride(getServiceEndpoint())
+                .build();
+    }
+}
diff --git a/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/AWSServiceFactory.java b/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/AWSServiceFactory.java
new file mode 100644
index 0000000..02b3242
--- /dev/null
+++ b/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/AWSServiceFactory.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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 org.apache.camel.test.infra.aws2.services;
+
+import org.apache.camel.test.infra.aws.common.services.AWSService;
+import org.apache.camel.test.infra.aws2.clients.AWSSDKClientUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import software.amazon.awssdk.core.SdkSystemSetting;
+import software.amazon.awssdk.services.kinesis.KinesisClient;
+import software.amazon.awssdk.services.s3.S3Client;
+import software.amazon.awssdk.services.sqs.SqsClient;
+
+public final class AWSServiceFactory {
+    private static final Logger LOG = LoggerFactory.getLogger(AWSServiceFactory.class);
+
+    private AWSServiceFactory() {
+
+    }
+
+    private static String getInstanceTypeName(String awsInstanceType) {
+        return awsInstanceType == null ? "default" : awsInstanceType;
+    }
+
+    public static AWSService<KinesisClient> createKinesisService() {
+        String awsInstanceType = System.getProperty("aws-service.kinesis.instance.type");
+        LOG.info("Creating a {} AWS kinesis instance", getInstanceTypeName(awsInstanceType));
+
+        if (awsInstanceType == null || awsInstanceType.equals("local-aws-container")) {
+
+            System.setProperty(SdkSystemSetting.CBOR_ENABLED.property(), "false");
+
+            return new AWSKinesisLocalContainerService();
+        }
+
+        if (awsInstanceType.equals("remote")) {
+            return new AWSRemoteService<>(AWSSDKClientUtils::newKinesisClient);
+        }
+
+        LOG.error("Invalid AWS instance type: {}. Must be either 'remote' or 'local-aws-container'",
+                awsInstanceType);
+        throw new UnsupportedOperationException("Invalid AWS instance type");
+    }
+
+    public static AWSService<SqsClient> createSQSService() {
+        String awsInstanceType = System.getProperty("aws-service.instance.type");
+        LOG.info("Creating a {} AWS SQS instance", getInstanceTypeName(awsInstanceType));
+
+        if (awsInstanceType == null || awsInstanceType.equals("local-aws-container")) {
+            return new AWSSQSLocalContainerService();
+        }
+
+        if (awsInstanceType.equals("remote")) {
+            return new AWSRemoteService<>(AWSSDKClientUtils::newSQSClient);
+        }
+
+        LOG.error("Invalid AWS instance type: {}. Must be either 'remote' or 'local-aws-container'",
+                awsInstanceType);
+        throw new UnsupportedOperationException("Invalid AWS instance type");
+    }
+
+    public static AWSService<S3Client> createS3Service() {
+        String awsInstanceType = System.getProperty("aws-service.instance.type");
+        LOG.info("Creating a {} AWS S3 instance", awsInstanceType);
+
+        if (awsInstanceType == null || awsInstanceType.equals("local-aws-container")) {
+            return new AWSS3LocalContainerService();
+        }
+
+        if (awsInstanceType.equals("remote")) {
+            return new AWSRemoteService<>(AWSSDKClientUtils::newS3Client);
+        }
+
+        LOG.error("Invalid AWS instance type: {}. Must be either 'remote' or 'local-aws-container'",
+                awsInstanceType);
+        throw new UnsupportedOperationException("Invalid AWS instance type");
+    }
+}
diff --git a/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/Service.java b/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/Service.java
new file mode 100644
index 0000000..099500b
--- /dev/null
+++ b/test-infra/camel-test-infra-aws-v2/src/test/java/org/apache/camel/test/infra/aws2/services/Service.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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 org.apache.camel.test.infra.aws2.services;
+
+public enum Service {
+    KINESIS("kinesis"),
+    SQS("sqs"),
+    S3("s3");
+
+    private final String serviceName;
+
+    Service(String serviceName) {
+        this.serviceName = serviceName;
+    }
+
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    public static String serviceName(Service service) {
+        return service.serviceName;
+    }
+}
diff --git a/test-infra/pom.xml b/test-infra/pom.xml
index f4c8034..a859524 100644
--- a/test-infra/pom.xml
+++ b/test-infra/pom.xml
@@ -37,7 +37,8 @@
         <module>camel-test-infra-common</module>
         <module>camel-test-infra-kafka</module>
         <module>camel-test-infra-parent</module>
-        <module>camel-test-infra-aws-v1</module>
         <module>camel-test-infra-aws-common</module>
+        <module>camel-test-infra-aws-v1</module>
+        <module>camel-test-infra-aws-v2</module>
     </modules>
 </project>
\ No newline at end of file