Skip to content

feat: add RustFs#1295

Open
konnta0 wants to merge 14 commits into
CommunityToolkit:mainfrom
konnta0:feature/rustfs
Open

feat: add RustFs#1295
konnta0 wants to merge 14 commits into
CommunityToolkit:mainfrom
konnta0:feature/rustfs

Conversation

@konnta0
Copy link
Copy Markdown

@konnta0 konnta0 commented Apr 29, 2026

Closes #1271

Adds a new hosting integration for RustFs, a high-performance, MinIO-compatible S3-compatible object storage server.

What's included

  • CommunityToolkit.Aspire.Hosting.RustFs — new hosting integration package
  • AddRustFs() — adds a RustFs container with configurable access/secret keys and ports
  • WithDataVolume() / WithDataBindMount() — persistent storage support
  • AddBucket() / AddBucket(IReadOnlyList<string>) — creates S3 buckets via minio/mc on startup
  • Separate console endpoint (port 9001) for the admin UI

Notes

  • RustFs implements the MinIO S3 protocol, so minio/mc is reused for bucket creation — consistent with the existing MinIO integration pattern.

PR Checklist

  • Created a feature/dev branch in your fork (vs. submitting directly from a commit on main)
  • Based off latest main branch of toolkit
  • PR doesn't include merge commits (always rebase on top of our main, if needed)
  • New integration
    • Docs are written
    • Added description of major feature to project description for NuGet package (4000 total character limit, so don't push entire description over that)
  • Tests for the changes have been added (for bug fixes / features) (if applicable)
  • Contains NO breaking changes
  • Every new API (including internal ones) has full XML docs
  • Code follows all style conventions

Other information

RustFs implements the MinIO-compatible S3 API (rustfs/rustfs#2212), which allows reuse of minio/mc for bucket
management without adding a new dependency. The connection string format is intentionally kept identical to the MinIO integration to ease migration.

Copilot AI review requested due to automatic review settings April 29, 2026 03:58
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 29, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/CommunityToolkit/Aspire/main/eng/scripts/dogfood-pr.sh | bash -s -- 1295

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/CommunityToolkit/Aspire/main/eng/scripts/dogfood-pr.ps1) } 1295"

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 Aspire hosting integration (CommunityToolkit.Aspire.Hosting.RustFs) to run RustFs (MinIO/S3-compatible object storage) as a container resource, along with an example AppHost and CI-enabled test coverage.

Changes:

  • Introduces AddRustFs() plus persistence helpers (WithDataVolume/WithDataBindMount) and connection-string support via RustFsResource.
  • Adds bucket-creation helpers (AddBucket) implemented via a companion minio/mc container.
  • Adds a new example AppHost, a new test project (unit + docker functional), and wires tests into the solution + CI workflow.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
tests/CommunityToolkit.Aspire.Hosting.RustFs.Tests/RustFsPublicApiTests.cs Public API guard/contract tests (null/empty checks, connection string).
tests/CommunityToolkit.Aspire.Hosting.RustFs.Tests/RustFsFunctionalTests.cs Docker functional tests for health + persisted storage behavior.
tests/CommunityToolkit.Aspire.Hosting.RustFs.Tests/CommunityToolkit.Aspire.Hosting.RustFs.Tests.csproj New test project setup and references for RustFs integration.
tests/CommunityToolkit.Aspire.Hosting.RustFs.Tests/AppHostTests.cs End-to-end example AppHost smoke tests (health + console endpoint).
tests/CommunityToolkit.Aspire.Hosting.RustFs.Tests/AddRustFsTests.cs Model-level tests for resource registration, endpoints, health checks, and connection string.
src/CommunityToolkit.Aspire.Hosting.RustFs/RustFsResource.cs New container resource type implementing connection-string support.
src/CommunityToolkit.Aspire.Hosting.RustFs/RustFsContainerImageTags.cs Centralizes RustFs and minio/mc image/tag constants.
src/CommunityToolkit.Aspire.Hosting.RustFs/RustFsBuilderExtensions.cs Core AddRustFs + persistence + bucket-creation extension methods.
src/CommunityToolkit.Aspire.Hosting.RustFs/README.md Package-level usage documentation.
src/CommunityToolkit.Aspire.Hosting.RustFs/CommunityToolkit.Aspire.Hosting.RustFs.csproj New hosting integration project definition and NuGet metadata.
examples/rustfs/CommunityToolkit.Aspire.Hosting.RustFs.AppHost/appsettings.json Example AppHost logging configuration.
examples/rustfs/CommunityToolkit.Aspire.Hosting.RustFs.AppHost/Properties/launchSettings.json Example AppHost launch profiles.
examples/rustfs/CommunityToolkit.Aspire.Hosting.RustFs.AppHost/Program.cs Example showing AddRustFs().WithDataVolume().AddBucket(...).
examples/rustfs/CommunityToolkit.Aspire.Hosting.RustFs.AppHost/CommunityToolkit.Aspire.Hosting.RustFs.AppHost.csproj Example AppHost project wiring to the new integration project.
README.md Adds RustFs to the integrations list + NuGet/doc links.
CommunityToolkit.Aspire.slnx Adds the new RustFs projects (src/tests/example) into the solution.
.github/workflows/tests.yaml Adds Hosting.RustFs.Tests to CI test matrix.

Comment on lines +129 to +137
/// <summary>
/// Adds a bucket to the RustFs resource using the MinIO CLI (<c>minio/mc</c>).
/// </summary>
/// <param name="builder">The resource builder.</param>
/// <param name="bucketName">The name of the bucket to create.</param>
/// <returns>A reference to the <see cref="IResourceBuilder{ContainerResource}"/> for the bucket creation container.</returns>
public static IResourceBuilder<ContainerResource> AddBucket(this IResourceBuilder<RustFsResource> builder, string bucketName)
{
ArgumentNullException.ThrowIfNull(builder);
Comment on lines +7 to +11
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Aspire.Hosting" />
Comment on lines +164 to +166
return builder.AddBucket(
name: $"{builder.Resource.Name}-create-buckets-{bucketNames[0]}",
bucketNames: bucketNames);
Comment on lines +63 to +64
.WithEnvironment(AccessKeyEnvVarName, resource.AccessKey)
.WithEnvironment(SecretKeyEnvVarName, resource.SecretKey)
Comment on lines +144 to +146
return builder.AddBucket(
name: $"{builder.Resource.Name}-create-bucket-{bucketName}",
bucketNames: [bucketName]);
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup>
<Compile Include="..\..\src\CommunityToolkit.Aspire.Hosting.RustFs\RustFsContainerImageTags.cs" Link="RustFsContainerImageTags.cs" />
using Aspire.Components.Common.Tests;
using Aspire.Hosting;
using Aspire.Hosting.Utils;
using Microsoft.Extensions.Hosting;
Comment thread README.md
| - **Learn More**: [`Hosting.MySql.Extensions`][mysql-ext-integration-docs] <br /> - Stable 📦: [![CommunityToolkit.Aspire.MySql.Extensions][mysql-ext-shields]][mysql-ext-nuget] <br /> - Preview 📦: [![CommunityToolkit.Aspire.Hosting.MySql.Extensions][mysql-ext-shields-preview]][mysql-ext-nuget-preview] | An integration that contains some additional extensions for hosting MySql container. |
| - **Learn More**: [`Hosting.MinIO`][minio-integration-docs] <br /> - Stable 📦: [![CommunityToolkit.Aspire.Hosting.Minio][minio-hosting-shields]][minio-hosting-nuget] <br /> - Preview 📦: [![CommunityToolkit.Aspire.Hosting.Minio][minio-hosting-shields-preview]][minio-hosting-nuget-preview] | An Aspire hosting integration to setup a [MinIO S3](https://min.io/) storage. |
| - **Learn More**: [`MinIO.Client`][minio-integration-docs] <br /> - Stable 📦: [![CommunityToolkit.Aspire.Minio.Client][minio-client-shields]][minio-client-nuget] <br /> - Preview 📦: [![CommunityToolkit.Aspire.Client.Minio][minio-client-shields-preview]][minio-client-nuget-preview] | An Aspire client integration for the [MinIO](https://github.com/minio/minio-dotnet) package. |
| - **Learn More**: [`Hosting.RustFs`][rustfs-integration-docs] <br /> - Stable 📦: [![CommunityToolkit.Aspire.Hosting.RustFs][rustfs-hosting-shields]][rustfs-hosting-nuget] <br /> - Preview 📦: [![CommunityToolkit.Aspire.Hosting.RustFs][rustfs-hosting-shields-preview]][rustfs-hosting-nuget-preview] | An Aspire hosting integration to setup a [RustFs](https://github.com/rustfs/rustfs) S3-compatible storage. |
IReadOnlyList<string> bucketNames)
{
return builder.ApplicationBuilder
.AddContainer(name, RustFsContainerImageTags.McImage, RustFsContainerImageTags.McTag)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

todo: I can see there is an HTTP endpoint to create a bucket. Wouldn't it be simpler/faster to execute a HTTP query over running a container? https://docs.rustfs.com/management/bucket/creation.html

Comment thread src/CommunityToolkit.Aspire.Hosting.RustFs/RustFsBuilderExtensions.cs Outdated
@konnta0
Copy link
Copy Markdown
Author

konnta0 commented Apr 29, 2026

@konnta0 please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.

@dotnet-policy-service agree [company="{your company}"]

Options:

  • (default - no company specified) I have sole ownership of intellectual property rights to my Submissions and I am not making Submissions in the course of work for my employer.
@dotnet-policy-service agree
  • (when company given) I am making Submissions in the course of work for my employer (or my employer has intellectual property rights in my Submissions by contract or applicable law). I have permission from my employer to make Submissions and enter into this Agreement on behalf of my employer. By signing below, the defined term “You” includes me and my employer.
@dotnet-policy-service agree company="Microsoft"

Contributor License Agreement

@dotnet-policy-service agree

@konnta0
Copy link
Copy Markdown
Author

konnta0 commented May 12, 2026

Please let me know if there’s anything I need to do.

@Odonno
Copy link
Copy Markdown
Contributor

Odonno commented May 12, 2026

Have you checked my comments?

@github-actions github-actions Bot added the Stale label May 24, 2026
Copy link
Copy Markdown
Member

@aaronpowell aaronpowell left a comment

Choose a reason for hiding this comment

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

I have concerns on the usage of mc since it's archived and we've previously removed our support for MinIO (see #1171).

Comment thread src/CommunityToolkit.Aspire.Hosting.RustFs/RustFsBuilderExtensions.cs Outdated
Comment thread src/CommunityToolkit.Aspire.Hosting.RustFs/RustFsBuilderExtensions.cs Outdated
aaronpowell and others added 4 commits May 25, 2026 16:07
…/CommunityToolkit.Aspire.Hosting.RustFs.AppHost.csproj
…S3 API

  - Add RustFsBucketResource as a child resource visible in the Aspire Dashboard
  - Remove minio/mc container dependency; create buckets via signed PUT requests
  - Implement minimal SigV4 signer (no external deps) in RustFsS3Signer
  - Use ArgumentException.ThrowIfNullOrWhiteSpace for bucket name validation
  - Add WithSigningRegion
@konnta0 konnta0 requested review from Odonno and aaronpowell May 26, 2026 15:42
Copy link
Copy Markdown
Contributor

@Odonno Odonno left a comment

Choose a reason for hiding this comment

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

Amazing!

@github-actions github-actions Bot removed the Stale label May 27, 2026
@aaronpowell
Copy link
Copy Markdown
Member

LGTM but there's a failing test:

konnta0 and others added 2 commits May 29, 2026 01:06
On Linux, Directory.CreateTempSubdirectory() creates a directory with restrictive permissions (700). The RustFs container runs as a non-root user and cannot write to the mounted path, causing an immediate exit.
 Apply File.SetUnixFileMode with 0777 on non-Windows platforms before mounting, matching the pattern used in KurrentDB and SurrealDb tests.
@konnta0
Copy link
Copy Markdown
Author

konnta0 commented May 28, 2026

Fixed the Ubuntu CI failure in WithDataShouldPersistStateBetweenUsages(useVolume: False).
Root cause: On Linux, Directory.CreateTempSubdirectory() creates the
directory with mode 700 (owner-only). The RustFs container runs as a non-root user, so it cannot write to the bind-mounted /data path and exits immediately — causing the health check to time out.

Fix: Call File.SetUnixFileMode(bindMountPath, 0777) on non-Windows platforms before passing the path to WithDataBindMount, following the same pattern used in:

@konnta0
Copy link
Copy Markdown
Author

konnta0 commented May 29, 2026

@aaronpowell Thank you for the review! I've fixed the tests. Could you approve the workflows to run CI?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Garage S3-compatible hosting and client integration

4 participants