Skip to main content

shiny-aspire-orleans

Generate code using Shiny Aspire integrations — Orleans ADO.NET hosting and Gluetun VPN container routing

설치로 이동

소스 정보

저장소
shinyorg/templates
최근 소스 활동
2026년 4월 2일 01:50
감지된 SKILL.md 언어
영어
스타
155
포크
15

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
shiny-aspire-orleans
description
Generate code using Shiny Aspire integrations — Orleans ADO.NET hosting and Gluetun VPN container routing
auto_invoke
true
triggers
["aspire orleans","orleans aspire","WithDatabaseSetup","UseAdoNet","UseAdoNetClient","orleans database setup","orleans schema","orleans clustering","orleans grain storage","orleans reminders","OrleansFeature","Shiny.Aspire.Orleans","aspire orleans hosting","aspire orleans server","aspire orleans client","orleans adonet","orleans ado.net","gluetun","gluetun vpn","AddGluetun","WithRoutedContainer","WithVpnProvider","WithWireGuard","WithOpenVpn","vpn container","aspire vpn","Shiny.Aspire.Hosting.Gluetun","GluetunResource","network_mode","vpn routing"]
# Shiny Aspire Skill You are an expert in Shiny's .NET Aspire integrations: 1. **Shiny.Aspire.Orleans** — Zero-friction integration between .NET Aspire and Microsoft Orleans for ADO.NET storage backends. Automatically provisions Orleans database schemas and wires up clustering, grain persistence, and reminders from Aspire configuration. 2. **Shiny.Aspire.Hosting.Gluetun** — Aspire hosting integration for Gluetun VPN containers. Models Gluetun as a first-class Aspire resource and lets other containers route their traffic through the VPN tunnel. ## When to Use This Skill Invoke this skill when the user wants to: - Set up Orleans with .NET Aspire using ADO.NET storage (PostgreSQL, SQL Server, or MySQL) - Automatically create Orleans database schemas from Aspire - Configure an Orleans silo with ADO.NET providers from Aspire-injected config - Configure an Orleans client with ADO.NET clustering from Aspire-injected config - Use `WithDatabaseSetup` to auto-provision Orleans tables - Use `silo.UseAdoNet()` to configure a silo inside `UseOrleans` - Use `client.UseAdoNetClient()` to configure a client inside `UseOrleansClient` - Select which Orleans features to provision (clustering, persistence, reminders) - Set up multiple named grain storage providers - Add a Gluetun VPN container to an Aspire app - Route container traffic through a VPN tunnel - Configure VPN providers, WireGuard, or OpenVPN in Aspire - Use `AddGluetun`, `WithRoutedContainer`, `WithVpnProvider`, `WithWireGuard`, or `WithOpenVpn` - Set up Docker Compose publishing with VPN network mode and port transfer ## Library Overview - **Repository**: https://github.com/shinyorg/aspire - **Target**: `net10.0` - **Aspire**: 13.1+ - **Orleans**: 10.0+ (Orleans packages only) ### Packages | Package | NuGet | Usage | |---|---|---| | `Shiny.Aspire.Orleans.Hosting` | Install in Aspire AppHost | Auto-runs Orleans schema scripts when the database becomes ready | | `Shiny.Aspire.Orleans.Server` | Install in Orleans silo | Registers ADO.NET provider builders for clustering, grain storage, and reminders | | `Shiny.Aspire.Orleans.Client` | Install in Orleans client | Registers ADO.NET provider builder for clustering | | `Shiny.Aspire.Hosting.Gluetun` | Install in Aspire AppHost | Adds a Gluetun VPN container and routes other containers through it | ### Supported Databases | Database | ADO.NET Invariant | ProviderType Value | |---|---|---| | PostgreSQL | `Npgsql` | `PostgresDatabase` | | SQL Server | `Microsoft.Data.SqlClient` | `SqlServerDatabase` | | MySQL | `MySql.Data.MySqlClient` | `MySqlDatabase` | ## Architecture: Provider Registration The Server and Client packages register Orleans provider builders via `[assembly: RegisterProvider]` attributes. When Orleans calls `ApplyConfiguration` during `UseOrleans()`, it reads the Aspire-injected configuration (e.g. `Orleans:Clustering:ProviderType = "PostgresDatabase"`) and resolves the matching provider builder automatically. The provider builder maps the database type to the correct ADO.NET invariant and resolves the connection string from the `ServiceKey`. This means: - **No manual configuration** — providers are resolved automatically from Aspire config. - **Extension methods** — `UseAdoNet()` on `ISiloBuilder` and `UseAdoNetClient()` on `IClientBuilder` are identity methods for discoverability. The actual wiring happens through the registered provider builders. - **Composable** — because configuration happens inside `UseOrleans(silo => { ... })` or `UseOrleansClient(client => { ... })`, users can add other features alongside. ## Setup ### 1. Aspire AppHost Install `Shiny.Aspire.Orleans.Hosting` in the AppHost project. ```csharp using Shiny.Aspire.Orleans.Hosting; var builder = DistributedApplication.CreateBuilder(args); var db = builder.AddPostgres("pg") .WithPgAdmin() .AddDatabase("orleans-db"); var orleans = builder.AddOrleans("cluster") .WithClustering(db) .WithGrainStorage("Default", db) .WithReminders(db) .WithDatabaseSetup(db); // creates all Orleans tables automatically builder.AddProject<Projects.MySilo>("silo") .WithReference(orleans) .WaitFor(db); builder.AddProject<Projects.MyApi>("api") .WithReference(orleans.AsClient()) .WaitFor(db); builder.Build().Run(); ``` ### 2. Orleans Silo Install `Shiny.Aspire.Orleans.Server` in the silo project. Call `silo.UseAdoNet()` inside `UseOrleans`. ```csharp using Shiny.Aspire.Orleans.Server; var builder = WebApplication.CreateBuilder(args); builder.UseOrleans(silo => { silo.UseAdoNet(); }); var app = builder.Build(); app.Run(); ``` ### 3. Orleans Client Install `Shiny.Aspire.Orleans.Client` in the client project (e.g. an API gateway). Call `client.UseAdoNetClient()` inside `UseOrleansClient`. ```csharp using Shiny.Aspire.Orleans.Client; var builder = WebApplication.CreateBuilder(args); builder.UseOrleansClient(client => { client.UseAdoNetClient(); }); var app = builder.Build(); app.MapGet("/counter/{name}", async (string name, IClusterClient client) => { var grain = client.GetGrain<ICounterGrain>(name); var count = await grain.GetCount(); return Results.Ok(new { name, count }); }); app.Run(); ``` ## API Reference ### Hosting Package — `Shiny.Aspire.Orleans.Hosting` #### WithDatabaseSetup ```csharp public static OrleansService WithDatabaseSetup( this OrleansService orleans, IResourceBuilder<IResourceWithConnectionString> database, OrleansFeature features = OrleansFeature.All ) ``` Subscribes to Aspire's `ResourceReadyEvent` for the database resource. When the database is up and accepting connections, it executes embedded Orleans SQL schema scripts. The database type (PostgreSQL, SQL Server, MySQL) is auto-detected from the Aspire resource. **Parameters:** - `orleans` — The Orleans service from `builder.AddOrleans()` - `database` — An Aspire database resource (e.g. from `AddPostgres`, `AddSqlServer`, `AddMySql`) - `features` — Which Orleans features to provision (default: `OrleansFeature.All`) #### OrleansFeature (Flags Enum) ```csharp [Flags] public enum OrleansFeature { Clustering = 1, // Membership tables for silo discovery Persistence = 2, // Grain storage tables Reminders = 4, // Reminder tables All = Clustering | Persistence | Reminders } ``` Use to limit which schemas are provisioned: ```csharp // Only clustering and persistence (no reminders) orleans.WithDatabaseSetup(db, OrleansFeature.Clustering | OrleansFeature.Persistence); // Only clustering orleans.WithDatabaseSetup(db, OrleansFeature.Clustering); ``` #### DatabaseType (Enum) ```csharp public enum DatabaseType { SqlServer, PostgreSQL, MySql } ``` Auto-detected from the Aspire resource — you do not need to specify this directly. ### Server Package — `Shiny.Aspire.Orleans.Server` #### UseAdoNet (ISiloBuilder extension) ```csharp public static ISiloBuilder UseAdoNet(this ISiloBuilder siloBuilder) ``` Marker extension for discoverability. The actual provider registration happens automatically via `[assembly: RegisterProvider]` attributes when the package is referenced. Providers are registered for all three database types across Clustering, GrainStorage, and Reminders. Call inside `UseOrleans`: ```csharp builder.UseOrleans(silo => { silo.UseAdoNet(); // compose with other silo features here }); ``` ### Client Package — `Shiny.Aspire.Orleans.Client` #### UseAdoNetClient (IClientBuilder extension) ```csharp public static IClientBuilder UseAdoNetClient(this IClientBuilder clientBuilder) ``` Marker extension for discoverability. Registers ADO.NET clustering provider builders for both Silo and Client targets. Clients do not need grain storage or reminders. Call inside `UseOrleansClient`: ```csharp builder.UseOrleansClient(client => { client.UseAdoNetClient(); }); ``` ## Configuration Flow Aspire injects the following configuration when you use `.WithReference(orleans)`: ``` Orleans:Clustering:ProviderType = "PostgresDatabase" Orleans:Clustering:ServiceKey = "orleans-db" Orleans:GrainStorage:Default:ProviderType = "PostgresDatabase" Orleans:GrainStorage:Default:ServiceKey = "orleans-db" Orleans:Reminders:ProviderType = "PostgresDatabase" Orleans:Reminders:ServiceKey = "orleans-db" ConnectionStrings:orleans-db = "Host=...;Database=..." ``` Orleans' `ApplyConfiguration` reads these sections and delegates to the registered provider builders, which configure the ADO.NET providers with the correct connection strings and invariants. ## Schema Provisioning Order `WithDatabaseSetup` runs embedded SQL scripts in order: 1. **Main** — creates the `OrleansQuery` table (query registry) 2. **Clustering** — creates `OrleansMembershipVersionTable`, `OrleansMembershipTable`, and stored procedures 3. **Persistence** — creates `OrleansStorage` table and stored procedures 4. **Reminders** — creates `OrleansRemindersTable` and stored procedures ## Switching Databases Swap the Aspire resource builder — everything else stays the same: ```csharp // PostgreSQL var db = builder.AddPostgres("pg").AddDatabase("orleans-db"); // SQL Server var db = builder.AddSqlServer("sql").AddDatabase("orleans-db"); // MySQL var db = builder.AddMySql("mysql").AddDatabase("orleans-db"); ``` ## Multiple Grain Storage Providers ```csharp // AppHost var orleans = builder.AddOrleans("cluster") .WithClustering(db) .WithGrainStorage("Default", db) .WithGrainStorage("Archive", archiveDb) .WithDatabaseSetup(db); // Grain public class MyGrain( [PersistentState("state", "Default")] IPersistentState<MyState> state, [PersistentState("archive", "Archive")] IPersistentState<ArchiveState> archive ) : Grain, IMyGrain { } ``` Each named provider reads from `Orleans:GrainStorage:{Name}:ProviderType` and `Orleans:GrainStorage:{Name}:ServiceKey`. ## Code Generation Best Practices 1. **Always use `WithDatabaseSetup`** in the AppHost to auto-provision schemas — never require manual SQL scripts. 2. **Always call `WaitFor(db)`** on projects that reference Orleans, so the database is ready before the silo starts. 3. **Use `.AsClient()`** when wiring a client project — this provides only clustering config, not full silo config. 4. **Use `UseOrleans` and `UseOrleansClient`** — call `silo.UseAdoNet()` in silo projects inside `UseOrleans` and `client.UseAdoNetClient()` in client projects inside `UseOrleansClient`. 5. **Feature flags are optional** — only use `OrleansFeature` flags if the user explicitly wants to skip certain schemas. 6. **Don't hardcode connection strings** — Aspire injects them automatically via configuration. 7. **Don't manually configure ADO.NET invariants** — the packages auto-detect the correct invariant from the provider type. 8. **Use named grain storage** for multiple persistence stores — each name maps to a separate configuration section. --- # Gluetun VPN — `Shiny.Aspire.Hosting.Gluetun` ## Setup Install `Shiny.Aspire.Hosting.Gluetun` in the Aspire AppHost project. ```csharp var builder = DistributedApplication.CreateBuilder(args); var vpn = builder.AddGluetun("vpn") .WithVpnProvider("mullvad") .WithWireGuard(builder.AddParameter("wireguard-key", secret: true)) .WithServerCountries("US", "Canada"); var scraper = builder.AddContainer("scraper", "my-scraper") .WithHttpEndpoint(targetPort: 8080); vpn.WithRoutedContainer(scraper); builder.Build().Run(); ``` ## API Reference ### AddGluetun ```csharp public static IResourceBuilder<GluetunResource> AddGluetun( this IDistributedApplicationBuilder builder, string name, int? httpProxyPort = null, int? shadowsocksPort = null) ``` Creates a Gluetun container resource with: - Image: `qmcgaw/gluetun:latest` from `docker.io` - `--cap-add NET_ADMIN` runtime arg - `--device /dev/net/tun` runtime arg - Docker Compose publish callback that sets `cap_add`, `devices`, and transfers ports from routed containers Optional port parameters expose Gluetun's built-in HTTP proxy (target port 8888) and Shadowsocks proxy (target port 8388). ### WithVpnProvider ```csharp vpn.WithVpnProvider("mullvad"); ``` Sets the `VPN_SERVICE_PROVIDER` environment variable. Required for all Gluetun setups. ### WithOpenVpn ```csharp // String credentials vpn.WithOpenVpn("username", "password"); // Aspire parameter resources (recommended for secrets) vpn.WithOpenVpn( builder.AddParameter("openvpn-user"), builder.AddParameter("openvpn-pass", secret: true)); ``` Sets `VPN_TYPE=openvpn`, `OPENVPN_USER`, and `OPENVPN_PASSWORD`. ### WithWireGuard ```csharp // String key vpn.WithWireGuard("my-private-key"); // Aspire parameter resource (recommended for secrets) vpn.WithWireGuard(builder.AddParameter("wireguard-key", secret: true)); ``` Sets `VPN_TYPE=wireguard` and `WIREGUARD_PRIVATE_KEY`. ### WithServerCountries / WithServerCities ```csharp vpn.WithServerCountries("US", "Canada", "Germany"); vpn.WithServerCities("New York", "Toronto"); ``` Values are comma-joined and set as `SERVER_COUNTRIES` / `SERVER_CITIES` environment variables. ### WithHttpProxy / WithShadowsocks ```csharp vpn.WithHttpProxy(); // HTTPPROXY=on vpn.WithHttpProxy(false); // HTTPPROXY=off vpn.WithShadowsocks(); // SHADOWSOCKS=on vpn.WithShadowsocks(false); // SHADOWSOCKS=off ``` ### WithFirewallOutboundSubnets ```csharp vpn.WithFirewallOutboundSubnets("10.0.0.0/8", "192.168.0.0/16"); ``` Sets `FIREWALL_OUTBOUND_SUBNETS` (comma-joined). Useful for allowing traffic to local network resources outside the VPN tunnel. ### WithTimezone ```csharp vpn.WithTimezone("America/New_York"); ``` Sets the `TZ` environment variable. ### WithGluetunEnvironment ```csharp // String value
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기