feat(s3): add Amazon S3 Files control-plane support (#707)#709
feat(s3): add Amazon S3 Files control-plane support (#707)#709nancysangani wants to merge 2 commits intokestra-io:mainfrom
Conversation
There was a problem hiding this comment.
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
AbstractS3Fileswith 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.
| .putHeader("Content-Type", "application/json") | ||
| .putHeader("Host", serviceHost); |
There was a problem hiding this comment.
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.
| .putHeader("Content-Type", "application/json") | |
| .putHeader("Host", serviceHost); | |
| .putHeader("Content-Type", "application/json"); |
| private AwsCredentialsProvider stsCredentialsProvider(AbstractConnection.AwsClientConfig cfg) { | ||
| StsClientBuilder stsBuilder = StsClient.builder() | ||
| .region(Region.of(cfg.region())); | ||
|
|
There was a problem hiding this comment.
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.
| stsBuilder.credentialsProvider( | ||
| StaticCredentialsProvider.create( | ||
| AwsBasicCredentials.create(cfg.accessKeyId(), cfg.secretKeyId()) | ||
| ) | ||
| ); |
There was a problem hiding this comment.
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).
| 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()) | |
| ) | |
| ); | |
| } |
| try (ApacheHttpClient httpClient = (ApacheHttpClient) ApacheHttpClient.create()) { | ||
| ExecutableHttpRequest executableRequest = httpClient.prepareRequest( | ||
| HttpExecuteRequest.builder() | ||
| .request(signedRequest) |
There was a problem hiding this comment.
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.
| @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> { |
There was a problem hiding this comment.
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.
Summary
Implements Amazon S3 Files control-plane REST API support with 8 new tasks:
Implementation
Technical Details
Aws4Signerfromsoftware.amazon.awssdk:authendpointOverridefor LocalStack testingTesting
Fixes issue #707. No breaking changes. All tests pass.