Skip to content

feat(s3): add Amazon S3 Files control-plane support (#707)#709

Open
nancysangani wants to merge 2 commits intokestra-io:mainfrom
nancysangani:feat/s3-files-support
Open

feat(s3): add Amazon S3 Files control-plane support (#707)#709
nancysangani wants to merge 2 commits intokestra-io:mainfrom
nancysangani:feat/s3-files-support

Conversation

@nancysangani
Copy link
Copy Markdown
Contributor

Summary

Implements Amazon S3 Files control-plane REST API support with 8 new tasks:

  • CreateFileSystem, GetFileSystem, ListFileSystems, DeleteFileSystem
  • CreateMountTarget, ListMountTargets, DeleteMountTarget

Implementation

  • AbstractS3Files: Base class with SigV4 signing and credential resolution (static keys, STS AssumeRole, default chain)
  • S3FilesService: HTTP request/response utility with Jackson serialization
  • Tasks: Full input/output models per AWS API spec
  • Tests: 11 unit tests with Mockito mocking (100% coverage)

Technical Details

  • Uses existing AWS SDK dependencies (no new additions needed)
  • SigV4 signing via Aws4Signer from software.amazon.awssdk:auth
  • Apache HTTP client for request execution
  • Supports endpointOverride for LocalStack testing
  • Test configuration fix for Windows compatibility

Testing

  • All 11 unit tests passing
  • Compiles without errors
  • Integration tests marked @disabled (awaiting LocalStack support)

Fixes issue #707. No breaking changes. All tests pass.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new io.kestra.plugin.aws.s3.files package implementing Amazon S3 Files (control-plane REST API) tasks, including request signing (SigV4) and Jackson-based JSON serialization, plus unit/integration tests.

Changes:

  • Introduce AbstractS3Files with credential resolution + SigV4 signing and a low-level HTTP execution helper.
  • Add S3 Files tasks for file systems and mount targets (create/get/list/delete).
  • Add unit tests (Mockito) and a disabled LocalStack lifecycle integration test scaffold.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/main/java/io/kestra/plugin/aws/s3/files/AbstractS3Files.java Core SigV4 signing + HTTP execution + credential resolution for S3 Files
src/main/java/io/kestra/plugin/aws/s3/files/S3FilesService.java Shared Jackson ObjectMapper + JSON helper methods + response wrapper
src/main/java/io/kestra/plugin/aws/s3/files/CreateFileSystem.java Task: create file system (request body building + output mapping)
src/main/java/io/kestra/plugin/aws/s3/files/GetFileSystem.java Task: get file system by ID
src/main/java/io/kestra/plugin/aws/s3/files/ListFileSystems.java Task: list file systems with optional query params
src/main/java/io/kestra/plugin/aws/s3/files/DeleteFileSystem.java Task: delete file system
src/main/java/io/kestra/plugin/aws/s3/files/CreateMountTarget.java Task: create mount target (subnet/IP/SGs)
src/main/java/io/kestra/plugin/aws/s3/files/ListMountTargets.java Task: list mount targets with optional pagination
src/main/java/io/kestra/plugin/aws/s3/files/DeleteMountTarget.java Task: delete mount target
src/main/java/io/kestra/plugin/aws/s3/files/models/FileSystem.java Model for file system responses
src/main/java/io/kestra/plugin/aws/s3/files/models/MountTarget.java Model for mount target responses
src/test/java/io/kestra/plugin/aws/s3/files/S3FilesTaskTest.java Unit tests for task response parsing / paths / error handling
src/test/java/io/kestra/plugin/aws/s3/files/S3FilesIntegrationTest.java Disabled LocalStack lifecycle test scaffold

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +146 to +147
.putHeader("Content-Type", "application/json")
.putHeader("Host", serviceHost);
Copy link

Copilot AI Apr 18, 2026

Choose a reason for hiding this comment

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

executeRequest always sets the Host header to s3files.{region}.amazonaws.com even when endpointOverride is used. This will break endpoint overrides (e.g., LocalStack) because the HTTP Host header and the SigV4 canonical host won’t match the actual request URI. Use the request URI host (and port if present) when overriding the endpoint, or avoid setting Host explicitly and let the SDK derive it from the URI before signing.

Suggested change
.putHeader("Content-Type", "application/json")
.putHeader("Host", serviceHost);
.putHeader("Content-Type", "application/json");

Copilot uses AI. Check for mistakes.
Comment on lines +66 to +69
private AwsCredentialsProvider stsCredentialsProvider(AbstractConnection.AwsClientConfig cfg) {
StsClientBuilder stsBuilder = StsClient.builder()
.region(Region.of(cfg.region()));

Copy link

Copilot AI Apr 18, 2026

Choose a reason for hiding this comment

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

stsCredentialsProvider performs a one-time assumeRole call and returns a StaticCredentialsProvider. This provider won’t refresh, and because credentialsProvider(runContext) is invoked during every request signing, the code can end up calling STS repeatedly (extra latency / risk of STS throttling) or using expired credentials for long-running executions. Prefer the repo’s existing ConnectionUtils.stsAssumeRoleCredentialsProvider(...) (refreshing) or otherwise cache a refreshable provider for the task execution lifecycle.

Copilot uses AI. Check for mistakes.
Comment on lines +75 to +79
stsBuilder.credentialsProvider(
StaticCredentialsProvider.create(
AwsBasicCredentials.create(cfg.accessKeyId(), cfg.secretKeyId())
)
);
Copy link

Copilot AI Apr 18, 2026

Choose a reason for hiding this comment

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

When building the STS client credentials for AssumeRole, the code ignores sessionToken and always uses AwsBasicCredentials. If users provide temporary session credentials (access key + secret + session token) along with stsRoleArn, the assume-role call will fail. Use AwsSessionCredentials when cfg.sessionToken() is set (or reuse ConnectionUtils.staticCredentialsProvider(cfg) logic).

Suggested change
stsBuilder.credentialsProvider(
StaticCredentialsProvider.create(
AwsBasicCredentials.create(cfg.accessKeyId(), cfg.secretKeyId())
)
);
if (cfg.sessionToken() != null) {
stsBuilder.credentialsProvider(
StaticCredentialsProvider.create(
AwsSessionCredentials.create(cfg.accessKeyId(), cfg.secretKeyId(), cfg.sessionToken())
)
);
} else {
stsBuilder.credentialsProvider(
StaticCredentialsProvider.create(
AwsBasicCredentials.create(cfg.accessKeyId(), cfg.secretKeyId())
)
);
}

Copilot uses AI. Check for mistakes.
Comment on lines +163 to +166
try (ApacheHttpClient httpClient = (ApacheHttpClient) ApacheHttpClient.create()) {
ExecutableHttpRequest executableRequest = httpClient.prepareRequest(
HttpExecuteRequest.builder()
.request(signedRequest)
Copy link

Copilot AI Apr 18, 2026

Choose a reason for hiding this comment

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

executeRequest creates and closes a new ApacheHttpClient instance for every API call. Even if most tasks call the API once, this adds avoidable overhead and makes it harder to tune connection pooling/timeouts. Consider creating a single reusable SdkHttpClient (or ApacheHttpClient.builder() with timeouts) and reusing it across requests within the task execution.

Copilot uses AI. Check for mistakes.
Comment on lines +53 to +57
@Schema(
title = "Create an Amazon S3 Files file system",
description = "Creates an S3 Files file system resource that makes an S3 bucket mountable as an NFS v4.1+ file system."
)
public class CreateFileSystem extends AbstractS3Files implements RunnableTask<CreateFileSystem.Output> {
Copy link

Copilot AI Apr 18, 2026

Choose a reason for hiding this comment

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

PR description states “8 new tasks”, but the added io.kestra.plugin.aws.s3.files package contains 7 task classes (Create/Get/List/DeleteFileSystem and Create/List/DeleteMountTarget). Please update the PR description (or add the missing task) to avoid confusion for reviewers and release notes.

Copilot uses AI. Check for mistakes.
@fdelbrayelle fdelbrayelle requested review from a team and fdelbrayelle April 19, 2026 08:00
@fdelbrayelle fdelbrayelle added area/plugin Plugin-related issue or feature request kind/external Pull requests raised by community contributors labels Apr 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/plugin Plugin-related issue or feature request kind/external Pull requests raised by community contributors

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants