feat: CommunityToolkit.Aspire.Hosting.Floci — Floci cloud emulator hosing integration - #1479
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/CommunityToolkit/Aspire/main/eng/scripts/dogfood-pr.sh | bash -s -- 1479Or
iex "& { $(irm https://raw.githubusercontent.com/CommunityToolkit/Aspire/main/eng/scripts/dogfood-pr.ps1) } 1479" |
|
@aaronpowell in addition to this feature I had to fix the restore issue for the security vulnerabilities caused by The PR is ready for your review, so please take a look and let me know if you have any concern. |
5ea6d20 to
04cebcd
Compare
|
@aaronpowell can you take a look please? |
There was a problem hiding this comment.
Pull request overview
This PR introduces a new Aspire Community Toolkit hosting integration (CommunityToolkit.Aspire.Hosting.Floci) for running Floci local cloud emulator containers (AWS/Azure/GCP) in an AppHost, including an optional companion Floci UI container and polyglot (TypeScript) AppHost support.
Integration classification (per hosting-integration-authoring):
- Resource shape: container-backed service resources (AWS/Azure/GCP emulators) + companion/admin tool container (Floci UI)
- Lifecycle mode: run-mode oriented (container resources + health checks + runtime env-var injection via events)
- Integration role: local emulator + reference/env-var plumbing for dependent workloads
- Structure: hosting extension methods + resource types + examples + tests + TypeScript AppHost assets
Changes:
- Adds Floci container resources (AWS/Azure/GCP) with shared connection/endpoint plumbing and health checks.
- Adds Floci UI companion resource with “plugged cloud” support to attach multiple emulators to one UI.
- Adds examples (C# + TypeScript) and a new test project covering resource creation and Docker-gated integration scenarios.
Show a summary per file
| File | Description |
|---|---|
| tests/CommunityToolkit.Aspire.Hosting.Floci.Tests/TypeScriptAppHostTests.cs | TypeScript AppHost compile/start coverage |
| tests/CommunityToolkit.Aspire.Hosting.Floci.Tests/MultiCloudUITests.cs | Validates single shared UI + env wiring |
| tests/CommunityToolkit.Aspire.Hosting.Floci.Tests/GcpContainerResourceCreationTests.cs | GCP resource creation/env tests |
| tests/CommunityToolkit.Aspire.Hosting.Floci.Tests/CommunityToolkit.Aspire.Hosting.Floci.Tests.csproj | New Floci test project |
| tests/CommunityToolkit.Aspire.Hosting.Floci.Tests/AzureContainerResourceCreationTests.cs | Azure resource creation/env tests |
| tests/CommunityToolkit.Aspire.Hosting.Floci.Tests/AwsContainerResourceCreationTests.cs | AWS resource creation/env tests |
| tests/CommunityToolkit.Aspire.Hosting.Floci.Tests/AppHostTests.cs | Docker-gated health checks for example AppHost resources |
| src/CommunityToolkit.Aspire.Hosting.Floci/README.md | Integration documentation (C#/TS examples) |
| src/CommunityToolkit.Aspire.Hosting.Floci/FlociUIContainerResource.cs | UI companion resource model |
| src/CommunityToolkit.Aspire.Hosting.Floci/FlociHostingExtension.Gcp.cs | AddFlociGcp + GCP-specific builder APIs |
| src/CommunityToolkit.Aspire.Hosting.Floci/FlociHostingExtension.FlociUI.cs | WithFlociUI + WithPluggedCloud + UI configuration APIs |
| src/CommunityToolkit.Aspire.Hosting.Floci/FlociHostingExtension.Common.cs | Shared WithDockerSocket/WithData* implementations |
| src/CommunityToolkit.Aspire.Hosting.Floci/FlociHostingExtension.Azure.cs | AddFlociAzure + Azure-specific reference/env wiring |
| src/CommunityToolkit.Aspire.Hosting.Floci/FlociHostingExtension.Aws.cs | AddFlociAws + AWS-specific reference/env wiring |
| src/CommunityToolkit.Aspire.Hosting.Floci/FlociGcpContainerResource.cs | GCP resource model + UI env wiring |
| src/CommunityToolkit.Aspire.Hosting.Floci/FlociContainerResource.cs | Shared base resource + connection properties |
| src/CommunityToolkit.Aspire.Hosting.Floci/FlociContainerImageTags.cs | Centralized container image/tag constants |
| src/CommunityToolkit.Aspire.Hosting.Floci/FlociAzureContainerResource.cs | Azure resource model + UI env wiring |
| src/CommunityToolkit.Aspire.Hosting.Floci/FlociAwsContainerResource.cs | AWS resource model + UI env wiring |
| src/CommunityToolkit.Aspire.Hosting.Floci/CommunityToolkit.Aspire.Hosting.Floci.csproj | New integration package project |
| README.md | Adds Floci to the integrations table |
| examples/floci/CommunityToolkit.Aspire.Hosting.Floci.AppHost/Program.cs | C# AppHost example wiring AWS/Azure/GCP + shared UI |
| examples/floci/CommunityToolkit.Aspire.Hosting.Floci.AppHost/CommunityToolkit.Aspire.Hosting.Floci.AppHost.csproj | Example AppHost project |
| examples/floci/CommunityToolkit.Aspire.Hosting.Floci.AppHost.TypeScript/tsconfig.json | TypeScript AppHost TS config |
| examples/floci/CommunityToolkit.Aspire.Hosting.Floci.AppHost.TypeScript/package.json | TypeScript AppHost npm metadata |
| examples/floci/CommunityToolkit.Aspire.Hosting.Floci.AppHost.TypeScript/package-lock.json | TypeScript AppHost lockfile |
| examples/floci/CommunityToolkit.Aspire.Hosting.Floci.AppHost.TypeScript/eslint.config.mjs | TypeScript AppHost lint config |
| examples/floci/CommunityToolkit.Aspire.Hosting.Floci.AppHost.TypeScript/aspire.config.json | TypeScript AppHost Aspire config |
| examples/floci/CommunityToolkit.Aspire.Hosting.Floci.AppHost.TypeScript/apphost.mts | TypeScript AppHost example wiring + compile-only API coverage |
| examples/floci/CommunityToolkit.Aspire.Hosting.Floci.ApiService/Properties/launchSettings.json | Example ApiService launch profile |
| examples/floci/CommunityToolkit.Aspire.Hosting.Floci.ApiService/Program.cs | Example API exercising AWS/Azure/GCP SDKs |
| examples/floci/CommunityToolkit.Aspire.Hosting.Floci.ApiService/CommunityToolkit.Aspire.Hosting.Floci.ApiService.csproj | Example API project references |
| Directory.Packages.props | Adds Azure.Storage.Blobs + Google.Cloud.Storage.V1 versions |
| CommunityToolkit.Aspire.slnx | Wires new projects into the solution |
Review details
Files not reviewed (1)
- examples/floci/CommunityToolkit.Aspire.Hosting.Floci.AppHost.TypeScript/package-lock.json: Generated file
Suppressed comments (1)
src/CommunityToolkit.Aspire.Hosting.Floci/FlociHostingExtension.Azure.cs:70
- Same as above for host-process dependents: the connection string currently only sets BlobEndpoint. Adding QueueEndpoint/TableEndpoint makes AZURE_STORAGE_CONNECTION_STRING usable by Queue/Table clients as well.
var blobEndpoint = ReferenceExpression.Create($"{resource.ConnectionStringExpression}/{FlociAzureContainerResource.DefaultAccountName}");
ctx.EnvironmentVariables["AZURE_STORAGE_CONNECTION_STRING"] = ReferenceExpression.Create(
$"DefaultEndpointsProtocol=http;AccountName={FlociAzureContainerResource.DefaultAccountName};AccountKey={FlociAzureContainerResource.DefaultAccountKey};BlobEndpoint={blobEndpoint};");
}));
- Files reviewed: 33/34 changed files
- Comments generated: 5
- Review effort level: Lite
|
@aaronpowell can you take a look again please? |
Closes floci-io/floci#1242
Adds
CommunityToolkit.Aspire.Hosting.Floci— a hosting integration for Floci, a family of high-performance local cloud emulators (floci/flocifor AWS,floci/floci-azfor Azure,floci/floci-gcpfor GCP) that run as containers inside the Aspire AppHost.What's included
Core integration (
src/CommunityToolkit.Aspire.Hosting.Floci/)AddFlociAws(name, port?, defaultRegion?, defaultAccountId?)— adds the Floci AWS container with an HTTP health check at/_floci/infoAddFlociAzure(name, port?)— adds the Floci Azure container (floci/floci-az), health check at/_floci/healthAddFlociGcp(name, port?, defaultProjectId?)— adds the Floci GCP container (floci/floci-gcp), health check at/_floci-gcp/healthFlociContainerResource) that holds endpoint/connection-string plumbing, soHost,Port,PrimaryEndpoint, andConnectionStringExpressionare implemented once and inherited — not duplicated per cloudWithReferenceautomatically injects the standardConnectionStrings__<name>plus provider-specific env vars via aBeforeStartEventsubscriber; host processes receivelocalhost:{port}, containers receivehost.docker.internal:{port}:AWS_ENDPOINT_URL,AWS_DEFAULT_REGION,AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEYAZURE_STORAGE_CONNECTION_STRING(well-knowndevstoreaccount1dev credentials)PUBSUB_EMULATOR_HOST,FIRESTORE_EMULATOR_HOST,DATASTORE_EMULATOR_HOST,STORAGE_EMULATOR_HOST,SECRET_MANAGER_EMULATOR_HOST,GOOGLE_CLOUD_PROJECT,CLOUDSDK_CORE_PROJECTWithDataVolume/WithDataBindMount— switches Floci from in-memory to persistent storage mode; implemented once and shared across all three cloudsWithDockerSocket— mounts the Docker socket so Lambda / Azure Functions / Cloud Run and other container-backed services can launch sibling containers; adds--add-host=host.docker.internal:host-gatewayto container dependents; shared across all three cloudsWithConfigFile(hostPath)— bind-mounts a Quarkusapplication.ymloverride at/deployments/config/application.ymlfor advanced configuration (AWS only — Azure/GCP images don't expose this)Floci UI web console (
WithFlociUI/WithPluggedCloud)WithFlociUI(configureContainer?, containerName?)— available on all three cloud resource types, adds a single sharedFlociUIContainerResourcerunningdocker.io/floci/floci-ui:0.2.0:FLOCI_ENDPOINTfor AWS,FLOCI_AZURE_ENDPOINTfor Azure,FLOCI_GCP_ENDPOINTfor GCP)/; excluded from manifest (ExcludeFromManifest())WithFlociUItwice re-configures the existing UI container instead of adding a duplicateWithReference(cloud)— attaches an additional cloud resource to an already-created UI console, so one console can browse AWS + Azure + GCP at once instead of spinning up three separate UI containers. In C# this is a single overloaded method name; the generated TypeScript bindings expose it aswithAwsReference/withAzureReference/withGcpReferencesince the polyglot export generator needs distinct names when all three overloads share the same target typeWithHostPort(int?)on the UI resource builder to pin the host portExamples and tests
aws.WithFlociUI(configureContainer: ui => { ui.WithPluggedCloud(azure); ui.WithPluggedCloud(gcp); }))ApiServiceexercises all three clouds end-to-end: S3 (AWS SDK), Blob Storage (Azure SDK), and Cloud Storage (GCP SDK), each with its own health check (floci-s3,floci-azure-blob,floci-gcp-storage) and a hosted service that creates a demo bucket/container on startupWithPluggedCloudattaches correctly, single UI container, correct env vars per attached cloud), the TypeScript AppHost, and Docker-gated AppHost integration tests asserting all three cloud resources and the UI resource become healthyConnectionStrings__<name>behavior alongside each cloud's provider-specific env varsPR Checklist
Other information
floci/floci,floci/floci-az,floci/floci-gcp) expose certificate-based configuration the way the earlier AWS-only prototype assumed, so that support was removed rather than shipped half-workingAWS_ENDPOINT_URLis the standard SDK v4 env var; noAmazonS3Config.RegionEndpointshould be set alongsideServiceURL(triggers aNullReferenceExceptionin the v4 endpoint rule engine — documented in the example)StorageClientis built withEmulatorDetection.EmulatorOnlyso it readsSTORAGE_EMULATOR_HOSTand skips real GCP credential resolution entirelyASPIREATS001experimental diagnostic (polyglot export attributes) is suppressed at file level in the hosting extension files