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

AWS S3 SDK Migration from V1 to V2 #118

Merged
merged 10 commits into from
Jan 27, 2025
2 changes: 1 addition & 1 deletion .github/workflows/source.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
uses: actions/checkout@v4

- name: Cache Maven packages
uses: actions/cache@v2
uses: actions/cache@v4
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('pom.xml') }}
Expand Down
44 changes: 33 additions & 11 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,13 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/software.amazon.awssdk/aws-sdk-java -->
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>1.12.100</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-core</artifactId>
<version>1.12.100</version>
<groupId>software.amazon.awssdk</groupId>
<artifactId>aws-sdk-java</artifactId>
<version>2.29.29</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
Expand Down Expand Up @@ -92,6 +89,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
Expand All @@ -110,6 +112,11 @@
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
Expand All @@ -120,11 +127,14 @@
<artifactId>sqlite-jdbc</artifactId>
<version>3.41.2.2</version>
</dependency>

<!-- swagger docs -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.5.10</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
Expand All @@ -133,13 +143,13 @@
<dependency>
<groupId>com.adobe.testing</groupId>
<artifactId>s3mock</artifactId>
<version>3.4.0</version>
<version>3.12.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.adobe.testing</groupId>
<artifactId>s3mock-junit5</artifactId>
<version>3.4.0</version>
<version>3.12.0</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down Expand Up @@ -263,6 +273,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>

<configuration>
<argLine>${surefireArgLine}</argLine>
<argLine>-Djava.io.tmpdir=${basedir}/target/tmp</argLine>
Expand Down Expand Up @@ -319,6 +330,17 @@
</execution>
</executions>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>

<configuration>
<show>protected</show>
<stylesheetfile>${basedir}/src/main/etc/stylesheet.css</stylesheetfile>
</configuration>
</plugin>
</plugins>
</build>
</project>

</project>
752 changes: 456 additions & 296 deletions src/main/java/gov/nist/oar/distrib/cachemgr/storage/AWSS3CacheVolume.java

Large diffs are not rendered by default.

130 changes: 64 additions & 66 deletions src/main/java/gov/nist/oar/distrib/storage/AWSS3ClientProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@
*/
package gov.nist.oar.distrib.storage;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.client.builder.AwsClientBuilder.EndpointConfiguration;
import java.net.URI;

import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.S3ClientBuilder;
import software.amazon.awssdk.services.s3.S3Configuration;

/**
* A wrapper for an AmazonS3Client that regulates is resource usage.
Expand All @@ -33,104 +35,100 @@
*/
public class AWSS3ClientProvider implements Cloneable {

protected AmazonS3 s3 = null;
protected String reg = null;
protected AWSCredentialsProvider credpro = null;
protected int acclim = 25;
protected S3Client s3 = null;
protected String region = null;
protected AwsCredentialsProvider credProvider = null;
protected int accessLimit = 25;
protected int accesses = 0;
private String ep = null;
private String endpoint = null;

static Logger log = LoggerFactory.getLogger(AWSS3ClientProvider.class);

/**
* create the provider
* @param creds the credentials to use when recreating the client
* @param region the AWS region to connect to
* @param accessLimit the maximum number of accesses allowed before the client is recreated;
* a non-positive number will result in a new client with every access.
* Create the provider.
* @param creds The credentials to use for S3.
* @param region The AWS region to connect to.
* @param accessLimit Maximum number of accesses before recreating the client.
*/
public AWSS3ClientProvider(AWSCredentialsProvider creds, String region, int accessLimit) {
public AWSS3ClientProvider(AwsCredentialsProvider creds, String region, int accessLimit) {
this(creds, region, accessLimit, null);
}

/**
* create the provider. This constructor is intended for use with an mock S3 service for
* testing purposes.
* @param creds the credentials to use when recreating the client
* @param region the AWS region to connect to
* @param accessLimit the maximum number of accesses allowed before the client is recreated;
* a non-positive number will result in a new client with every access.
* @param endpoint the endpoint to use for the AWS s3 service
* Create the provider with a custom endpoint (e.g., for testing with a mock S3 service).
* @param creds The credentials to use for S3.
* @param region The AWS region to connect to.
* @param accessLimit Maximum number of accesses before recreating the client.
* @param endpoint The custom endpoint URL.
*/
public AWSS3ClientProvider(AWSCredentialsProvider creds, String region,
int accessLimit, String endpoint)
{
credpro = creds;
reg = region;
acclim = accessLimit;
ep = endpoint;
public AWSS3ClientProvider(AwsCredentialsProvider creds, String region, int accessLimit, String endpoint) {
this.credProvider = creds;
this.region = region;
this.accessLimit = accessLimit;
this.endpoint = endpoint;
refresh();
}

/**
* return the maximum number of accesses allowed before the client is recreated
*/
public int getAccessLimit() { return acclim; }

/**
* return the S3 client
* Return the S3 client.
*/
public synchronized AmazonS3 client() {
if (accesses >= acclim || s3 == null)
public synchronized S3Client client() {
if (accesses >= accessLimit || s3 == null) {
refresh();
}
accesses++;
return s3;
}

/**
* free up the client resources and recreate the client
* Refresh the S3 client (recreate it).
*/
public synchronized void refresh() {
/*
if (s3 != null)
s3.shutdown();
*/
log.info("FYI: Refreshing the S3 client");
AmazonS3ClientBuilder bldr = AmazonS3Client.builder().standard()
.withCredentials(credpro);
if (ep == null)
bldr.withRegion(reg);
else
bldr.withEndpointConfiguration(new EndpointConfiguration(ep, reg))
.enablePathStyleAccess();
s3 = bldr.build();
log.info("Refreshing the S3 client");
S3ClientBuilder builder = S3Client.builder()
.credentialsProvider(credProvider)
.region(Region.of(region));

accesses = 0;
}
if (endpoint != null) {
builder.endpointOverride(URI.create(endpoint))
.serviceConfiguration(S3Configuration.builder()
.pathStyleAccessEnabled(true)
.build());
}

/**
* return the number of accesses are left before the client is refreshed
*/
public int accessesLeft() {
if (s3 == null)
return 0;
return acclim - accesses;
if (s3 != null) {
s3.close();
}

s3 = builder.build();
accesses = 0;
}

/**
* free up resources by shutting down the client
* Shut down the S3 client and free resources.
*/
public synchronized void shutdown() {
if (s3 != null) {
s3.shutdown();
s3.close();
s3 = null;
}
accesses = 0;
}

/**
* Return the number of accesses left before a refresh is triggered.
*/
public int accessesLeft() {
if (s3 == null) return 0;
return accessLimit - accesses;
}

@Override
public Object clone() {
return new AWSS3ClientProvider(credpro, reg, acclim, ep);
return new AWSS3ClientProvider(credProvider, region, accessLimit, endpoint);
}

public AWSS3ClientProvider cloneMe() {
return (AWSS3ClientProvider) clone();
}
}
}
Loading
Loading