diff --git a/src/frontend/src/content/docs/app-host/go-apphost.mdx b/src/frontend/src/content/docs/app-host/go-apphost.mdx index 392c6b22c..6aadb0851 100644 --- a/src/frontend/src/content/docs/app-host/go-apphost.mdx +++ b/src/frontend/src/content/docs/app-host/go-apphost.mdx @@ -136,6 +136,6 @@ Add `.aspire/` to `.gitignore`. The generated Go module can be recreated from `a ## See also -- [Build your first Aspire app](/get-started/first-app/?lang=go) +- [Build your first Aspire app](/get-started/first-app/?aspire-lang=go) - [Multi-language architecture](/architecture/multi-language-architecture/) - [Author multi-language integrations](/extensibility/multi-language-integration-authoring/) diff --git a/src/frontend/src/content/docs/app-host/java-apphost.mdx b/src/frontend/src/content/docs/app-host/java-apphost.mdx index e29cf10c1..34f200e69 100644 --- a/src/frontend/src/content/docs/app-host/java-apphost.mdx +++ b/src/frontend/src/content/docs/app-host/java-apphost.mdx @@ -122,6 +122,6 @@ Keep the scaffolded `.gitignore`. Generated `.aspire` content and compiled AppHo ## See also -- [Build your first Aspire app](/get-started/first-app/?lang=java) +- [Build your first Aspire app](/get-started/first-app/?aspire-lang=java) - [Multi-language architecture](/architecture/multi-language-architecture/) - [Author multi-language integrations](/extensibility/multi-language-integration-authoring/) diff --git a/src/frontend/src/content/docs/app-host/python-apphost.mdx b/src/frontend/src/content/docs/app-host/python-apphost.mdx index aad13bb76..7eff6a920 100644 --- a/src/frontend/src/content/docs/app-host/python-apphost.mdx +++ b/src/frontend/src/content/docs/app-host/python-apphost.mdx @@ -118,6 +118,6 @@ Add `.aspire/` and the AppHost virtual environment to `.gitignore`. Both can be ## See also -- [Build your first Aspire app](/get-started/first-app/?lang=python) +- [Build your first Aspire app](/get-started/first-app/?aspire-lang=python) - [Multi-language architecture](/architecture/multi-language-architecture/) - [Author multi-language integrations](/extensibility/multi-language-integration-authoring/) diff --git a/src/frontend/src/content/docs/app-host/rust-apphost.mdx b/src/frontend/src/content/docs/app-host/rust-apphost.mdx index 80c3fe5f5..89a922f84 100644 --- a/src/frontend/src/content/docs/app-host/rust-apphost.mdx +++ b/src/frontend/src/content/docs/app-host/rust-apphost.mdx @@ -128,6 +128,6 @@ Add `.aspire/` and Cargo build output to `.gitignore`. The generated module can ## See also -- [Build your first Aspire app](/get-started/first-app/?lang=rust) +- [Build your first Aspire app](/get-started/first-app/?aspire-lang=rust) - [Multi-language architecture](/architecture/multi-language-architecture/) - [Author multi-language integrations](/extensibility/multi-language-integration-authoring/) diff --git a/src/frontend/src/content/docs/integrations/ai/github-models/github-models-get-started.mdx b/src/frontend/src/content/docs/integrations/ai/github-models/github-models-get-started.mdx index e78f6db59..d77aceba0 100644 --- a/src/frontend/src/content/docs/integrations/ai/github-models/github-models-get-started.mdx +++ b/src/frontend/src/content/docs/integrations/ai/github-models/github-models-get-started.mdx @@ -64,27 +64,29 @@ Getting there is a two-step process: model the GitHub Model resource in your App 1. ### Model GitHub Models in your AppHost - Add the GitHub Models hosting integration to your AppHost, then declare a model resource and reference it from the apps that need to call the API. The [GitHub Models hosting integration](/integrations/ai/github-models/github-models-host/) article walks through every capability — adding model resources, API key parameters, organization configuration, and health checks — with side-by-side C# and TypeScript examples. + Add the GitHub Models hosting integration to your AppHost, then declare a model resource and reference it from the apps that need to call the API. The [GitHub Models hosting integration](/integrations/ai/github-models/github-models-host/) article walks through every capability — adding model resources, API key parameters, organization configuration, and health checks — with examples for C#, TypeScript, Python, Go, Java, and Rust. - - Set up GitHub Models in the AppHost - + + Set up GitHub Models in the AppHost + 2. ### Connect from your consuming app - When you reference a GitHub Model resource from a consuming app, Aspire injects its connection information as environment variables. See [Connect to GitHub Models](/integrations/ai/github-models/github-models-connect/) for the connection properties reference and per-language examples for C#, Go, Python, and TypeScript — including the full C# client integration. + When you reference a GitHub Model resource from a consuming app, Aspire injects its connection information as environment variables. See [Connect to GitHub Models](/integrations/ai/github-models/github-models-connect/) for the connection properties reference and per-language examples for C#, Go, Python, and TypeScript — including the full C# client integration. - - Connect to GitHub Models - + + Connect to GitHub Models + diff --git a/src/frontend/src/content/docs/integrations/ai/github-models/github-models-host.mdx b/src/frontend/src/content/docs/integrations/ai/github-models/github-models-host.mdx index 26b8f05e9..d0fbe5d0a 100644 --- a/src/frontend/src/content/docs/integrations/ai/github-models/github-models-host.mdx +++ b/src/frontend/src/content/docs/integrations/ai/github-models/github-models-host.mdx @@ -23,7 +23,7 @@ import githubIcon from '@assets/icons/github-icon.png'; The GitHub Models service is **no longer available to new customers**. The `Aspire.Hosting.GitHub.Models` integration is sunset as of Aspire 13.5. All public APIs are marked `[Obsolete]` and the package no longer appears in `aspire add` output. The package will ship one final obsolete release on NuGet and will be removed entirely in a future version. For new and existing apps, use the [Azure AI Foundry integration](/integrations/cloud/azure/azure-ai-foundry/azure-ai-foundry-get-started/) instead, which provides access to a broad catalog of models — including OpenAI's GPT models — and supports local development with `RunAsFoundryLocal()`. See [microsoft/aspire#18402](https://github.com/microsoft/aspire/issues/18402) for details. ::: -This article is the reference for the Aspire GitHub Models hosting integration. It enumerates the AppHost APIs — with examples for both `AppHost.cs` and `apphost.mts` — that you use to model GitHub Model resources in your [`AppHost`](/get-started/app-host/) project. +This article is the reference for the Aspire GitHub Models hosting integration. It shows the generated AppHost APIs for C#, TypeScript, Python, Go, Java, and Rust that model GitHub Model resources. If you're new to the GitHub Models integration, start with the [Get started with GitHub Models integrations](/integrations/ai/github-models/github-models-get-started/) guide. For how consuming apps read the connection information this page exposes, see [Connect to GitHub Models](../github-models-connect/). @@ -39,7 +39,8 @@ aspire add github-models ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. Or, choose a manual installation approach: @@ -60,7 +61,8 @@ aspire add github-models ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. This updates your `aspire.config.json` with the GitHub Models hosting integration package: @@ -73,6 +75,58 @@ This updates your `aspire.config.json` with the GitHub Models hosting integratio } ``` + + + +The package is obsolete and no longer appears in `aspire add` results. Add it directly to `aspire.config.json`: + +```json title="aspire.config.json" ins={3} +{ + "packages": { + "Aspire.Hosting.GitHub.Models": "%ASPIRE_VERSION%" + } +} +``` + + + + +The package is obsolete and no longer appears in `aspire add` results. Add it directly to `aspire.config.json`: + +```json title="aspire.config.json" ins={3} +{ + "packages": { + "Aspire.Hosting.GitHub.Models": "%ASPIRE_VERSION%" + } +} +``` + + + + +The package is obsolete and no longer appears in `aspire add` results. Add it directly to `aspire.config.json`: + +```json title="aspire.config.json" ins={3} +{ + "packages": { + "Aspire.Hosting.GitHub.Models": "%ASPIRE_VERSION%" + } +} +``` + + + + +The package is obsolete and no longer appears in `aspire add` results. Add it directly to `aspire.config.json`: + +```json title="aspire.config.json" ins={3} +{ + "packages": { + "Aspire.Hosting.GitHub.Models": "%ASPIRE_VERSION%" + } +} +``` + @@ -88,10 +142,11 @@ var builder = DistributedApplication.CreateBuilder(args); var chat = builder.AddGitHubModel("chat", GitHubModel.OpenAI.OpenAIGpt4oMini); var exampleProject = builder.AddProject("apiservice") - .WithReference(chat); +.WithReference(chat); // After adding all resources, run the app... -``` + +```` ```typescript title="apphost.mts" twoslash @@ -105,22 +160,112 @@ await builder.addNodeApp("api", "./api", "index.js") .withReference(chat); // After adding all resources, run the app... -``` +```` + + + +```python title="apphost.py" +from aspire_app import create_builder + +with create_builder() as builder: +chat = builder.add_git_hub_model("chat", "OpenAIGpt4oMini") +builder.run() + +```` + + +```go title="apphost.go" +package main + +import ( + "log" + + "apphost/modules/aspire" +) + +func main() { + builder, err := aspire.CreateBuilder() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + + chat := builder.AddGitHubModel( + "chat", + aspire.GitHubModelNameOpenAIGpt4oMini, + ) + if err := chat.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + app, err := builder.Build() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + if err := app.Run(); err != nil { + log.Fatal(aspire.FormatError(err)) + } +} +```` + + + +```java title="AppHost.java" +import aspire.*; + +void main() throws Exception { +var builder = DistributedApplication.CreateBuilder(); + + var chat = builder.addGitHubModel( + "chat", + GitHubModelName.OPEN_AIGPT4O_MINI); + + builder.build().run(); + +} + +```` + + +```rust title="apphost.rs" +#[path = ".aspire/modules/mod.rs"] +mod aspire; + +use aspire::*; + +fn main() -> Result<(), Box> { + let builder = create_builder(None)?; + + let chat = builder.add_git_hub_model( + "chat", + GitHubModelName::OpenAIGpt4oMini, + None, + )?; + + let app = builder.build()?; + app.run(None)?; + Ok(()) +} +```` + -1. Calling `AddGitHubModel` (or `addGitHubModel`) creates a `GitHubModelResource`. It registers a secret parameter for the API key that defaults to the `GITHUB_TOKEN` environment variable. +1. Adding a GitHub Model creates a `GitHubModelResource`. It registers a secret parameter for the API key that defaults to the `GITHUB_TOKEN` environment variable. -1. The model identifier selects which GitHub-hosted model to target. In C#, use the strongly-typed `GitHubModel` constants grouped by publisher; in TypeScript, use the `GitHubModelName` enum. +1. The model identifier selects which GitHub-hosted model to target. C# uses publisher-grouped `GitHubModel` constants. TypeScript, Python, Go, Java, and Rust use generated `GitHubModelName` values in each language's naming convention. -1. The AppHost reference call configures a connection in the consuming project named after the resource (for example, `chat` in the preceding example). +1. When a consuming resource references the model, Aspire configures a connection named after that resource, such as `chat`. ## Use a model identifier string @@ -135,10 +280,11 @@ var builder = DistributedApplication.CreateBuilder(args); var chat = builder.AddGitHubModel("chat", "openai/gpt-4o-mini"); var exampleProject = builder.AddProject("apiservice") - .WithReference(chat); +.WithReference(chat); // After adding all resources, run the app... -``` + +```` ```typescript title="apphost.mts" twoslash @@ -152,21 +298,105 @@ await builder.addNodeApp("api", "./api", "index.js") .withReference(chat); // After adding all resources, run the app... -``` +```` + + + +```python title="apphost.py" +from aspire_app import create_builder + +with create_builder() as builder: +chat = builder.add_git_hub_model_by_id("chat", "openai/gpt-4o-mini") +builder.run() + +```` + + +```go title="apphost.go" +package main + +import ( + "log" + + "apphost/modules/aspire" +) + +func main() { + builder, err := aspire.CreateBuilder() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + + chat := builder.AddGitHubModelById("chat", "openai/gpt-4o-mini") + if err := chat.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + app, err := builder.Build() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + if err := app.Run(); err != nil { + log.Fatal(aspire.FormatError(err)) + } +} +```` + + + +```java title="AppHost.java" +import aspire.*; + +void main() throws Exception { +var builder = DistributedApplication.CreateBuilder(); + + var chat = builder.addGitHubModelById( + "chat", + "openai/gpt-4o-mini"); + + builder.build().run(); + +} + +```` + + +```rust title="apphost.rs" +#[path = ".aspire/modules/mod.rs"] +mod aspire; + +use aspire::*; + +fn main() -> Result<(), Box> { + let builder = create_builder(None)?; + + let chat = builder.add_git_hub_model_by_id( + "chat", + "openai/gpt-4o-mini", + None, + )?; + + let app = builder.build()?; + app.run(None)?; + Ok(()) +} +```` + ## Use default API key parameter -Calling `AddGitHubModel("chat", ...)` (or `addGitHubModel("chat", ...)`) automatically creates a secret parameter named `chat-gh-apikey`. Aspire resolves its value in this order: +Adding a GitHub Model named `chat` automatically creates a secret parameter named `chat-gh-apikey`. Aspire resolves its value in this order: 1. The `Parameters:chat-gh-apikey` configuration key (user secrets, `appsettings.*`, or environment variables). 2. The `GITHUB_TOKEN` environment variable. @@ -179,7 +409,7 @@ aspire secret set Parameters:chat-gh-apikey github_pat_YOUR_TOKEN_HERE ## Use a custom API key parameter -Replace the default parameter by creating your own secret parameter and passing it to `WithApiKey` (or `withApiKey`): +Replace the default parameter by creating your own secret parameter and passing it to the generated API-key method: @@ -189,13 +419,14 @@ var builder = DistributedApplication.CreateBuilder(args); var apiKey = builder.AddParameter("my-gh-token", secret: true); var chat = builder.AddGitHubModel("chat", GitHubModel.OpenAI.OpenAIGpt4oMini) - .WithApiKey(apiKey); +.WithApiKey(apiKey); var exampleProject = builder.AddProject("apiservice") - .WithReference(chat); +.WithReference(chat); // After adding all resources, run the app... -``` + +```` ```typescript title="apphost.mts" twoslash @@ -212,11 +443,119 @@ await builder.addNodeApp("api", "./api", "index.js") .withReference(chat); // After adding all resources, run the app... -``` +```` + + + +```python title="apphost.py" +from aspire_app import create_builder + +with create_builder() as builder: +api_key = builder.add_parameter("my-gh-token", secret=True) +chat = builder.add_git_hub_model( +"chat", +"OpenAIGpt4oMini", +).with_api_key(api_key) +builder.run() + +```` + + +```go title="apphost.go" +package main + +import ( + "log" + + "apphost/modules/aspire" +) + +func main() { + builder, err := aspire.CreateBuilder() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + + secret := true + apiKey := builder.AddParameter( + "my-gh-token", + &aspire.AddParameterOptions{Secret: &secret}, + ) + if err := apiKey.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + chat := builder.AddGitHubModel( + "chat", + aspire.GitHubModelNameOpenAIGpt4oMini, + ).WithApiKey(apiKey) + if err := chat.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + app, err := builder.Build() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + if err := app.Run(); err != nil { + log.Fatal(aspire.FormatError(err)) + } +} +```` + + + +```java title="AppHost.java" +import aspire.*; + +void main() throws Exception { +var builder = DistributedApplication.CreateBuilder(); + + var apiKey = builder.addParameter( + "my-gh-token", + new AddParameterOptions().secret(true)); + var chat = builder.addGitHubModel( + "chat", + GitHubModelName.OPEN_AIGPT4O_MINI).withApiKey(apiKey); + + builder.build().run(); + +} + +```` + + +```rust title="apphost.rs" +#[path = ".aspire/modules/mod.rs"] +mod aspire; + +use aspire::*; + +fn main() -> Result<(), Box> { + let builder = create_builder(None)?; + + let api_key = builder.add_parameter("my-gh-token", None, None, Some(true))?; + let chat = builder + .add_git_hub_model( + "chat", + GitHubModelName::OpenAIGpt4oMini, + None, + )? + .with_api_key(&api_key)?; + + let app = builder.build()?; + app.run(None)?; + Ok(()) +} +```` + - + ## Specify an organization @@ -232,10 +571,11 @@ var organization = builder.AddParameter("github-org"); var chat = builder.AddGitHubModel("chat", GitHubModel.OpenAI.OpenAIGpt4oMini, organization); var exampleProject = builder.AddProject("apiservice") - .WithReference(chat); +.WithReference(chat); // After adding all resources, run the app... -``` + +```` ```typescript title="apphost.mts" twoslash @@ -253,7 +593,107 @@ await builder.addNodeApp("api", "./api", "index.js") .withReference(chat); // After adding all resources, run the app... -``` +```` + + + +```python title="apphost.py" +from aspire_app import create_builder + +with create_builder() as builder: +organization = builder.add_parameter("github-org") +chat = builder.add_git_hub_model( +"chat", +"OpenAIGpt4oMini", +organization=organization, +) +builder.run() + +```` + + +```go title="apphost.go" +package main + +import ( + "log" + + "apphost/modules/aspire" +) + +func main() { + builder, err := aspire.CreateBuilder() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + + organization := builder.AddParameter("github-org") + if err := organization.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + chat := builder.AddGitHubModel( + "chat", + aspire.GitHubModelNameOpenAIGpt4oMini, + &aspire.AddGitHubModelOptions{Organization: &organization}, + ) + if err := chat.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + app, err := builder.Build() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + if err := app.Run(); err != nil { + log.Fatal(aspire.FormatError(err)) + } +} +```` + + + +```java title="AppHost.java" +import aspire.*; + +void main() throws Exception { +var builder = DistributedApplication.CreateBuilder(); + + var organization = builder.addParameter("github-org"); + var chat = builder.addGitHubModel( + "chat", + GitHubModelName.OPEN_AIGPT4O_MINI, + organization); + + builder.build().run(); + +} + +```` + + +```rust title="apphost.rs" +#[path = ".aspire/modules/mod.rs"] +mod aspire; + +use aspire::*; + +fn main() -> Result<(), Box> { + let builder = create_builder(None)?; + + let organization = builder.add_parameter("github-org", None, None, None)?; + let chat = builder.add_git_hub_model( + "chat", + GitHubModelName::OpenAIGpt4oMini, + Some(&organization), + )?; + + let app = builder.build()?; + app.run(None)?; + Ok(()) +} +```` + @@ -269,13 +709,14 @@ Add an optional health check to verify endpoint reachability and API key validit var builder = DistributedApplication.CreateBuilder(args); var chat = builder.AddGitHubModel("chat", GitHubModel.OpenAI.OpenAIGpt4oMini) - .WithHealthCheck(); +.WithHealthCheck(); var exampleProject = builder.AddProject("apiservice") - .WithReference(chat); +.WithReference(chat); // After adding all resources, run the app... -``` + +```` ```typescript title="apphost.mts" twoslash @@ -290,7 +731,98 @@ await builder.addNodeApp("api", "./api", "index.js") .withReference(chat); // After adding all resources, run the app... -``` +```` + + + +```python title="apphost.py" +from aspire_app import create_builder + +with create_builder() as builder: +chat = builder.add_git_hub_model( +"chat", +"OpenAIGpt4oMini", +).enable_health_check() +builder.run() + +```` + + +```go title="apphost.go" +package main + +import ( + "log" + + "apphost/modules/aspire" +) + +func main() { + builder, err := aspire.CreateBuilder() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + + chat := builder.AddGitHubModel( + "chat", + aspire.GitHubModelNameOpenAIGpt4oMini, + ).EnableHealthCheck() + if err := chat.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + app, err := builder.Build() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + if err := app.Run(); err != nil { + log.Fatal(aspire.FormatError(err)) + } +} +```` + + + +```java title="AppHost.java" +import aspire.*; + +void main() throws Exception { +var builder = DistributedApplication.CreateBuilder(); + + var chat = builder.addGitHubModel( + "chat", + GitHubModelName.OPEN_AIGPT4O_MINI).enableHealthCheck(); + + builder.build().run(); + +} + +```` + + +```rust title="apphost.rs" +#[path = ".aspire/modules/mod.rs"] +mod aspire; + +use aspire::*; + +fn main() -> Result<(), Box> { + let builder = create_builder(None)?; + + let chat = builder + .add_git_hub_model( + "chat", + GitHubModelName::OpenAIGpt4oMini, + None, + )? + .enable_health_check()?; + + let app = builder.build()?; + app.run(None)?; + Ok(()) +} +```` + @@ -302,21 +834,22 @@ await builder.addNodeApp("api", "./api", "index.js") ## Available models -GitHub Models supports a broad and growing catalog of models. Use the strongly-typed constants for the most accurate list: +GitHub Models supports a broad and growing catalog of models. Use the strongly typed constants for the most accurate list. The table shows the C# and TypeScript spellings; Python, Go, Java, and Rust generate the same `GitHubModelName` values using each language's enum or literal conventions. -| Publisher | C# constant (examples) | TypeScript enum (examples) | -| ---------- | --------------------------------------------------- | --------------------------------------------------- | -| OpenAI | `GitHubModel.OpenAI.OpenAIGpt4oMini` | `GitHubModelName.OpenAIGpt4oMini` | -| OpenAI | `GitHubModel.OpenAI.OpenAIGpt41Mini` | `GitHubModelName.OpenAIGpt41Mini` | -| DeepSeek | `GitHubModel.DeepSeek.DeepSeekV30324` | `GitHubModelName.DeepSeekV30324` | -| DeepSeek | `GitHubModel.DeepSeek.DeepSeekR1` | `GitHubModelName.DeepSeekR1` | -| Microsoft | `GitHubModel.Microsoft.Phi4MiniInstruct` | `GitHubModelName.Phi4MiniInstruct` *(see note)* | -| Meta | `GitHubModel.Meta.MetaLlama318BInstruct` | `GitHubModelName.MetaLlama318BInstruct` | +| Publisher | C# constant (examples) | TypeScript enum (examples) | +| --------- | ---------------------------------------- | ----------------------------------------------- | +| OpenAI | `GitHubModel.OpenAI.OpenAIGpt4oMini` | `GitHubModelName.OpenAIGpt4oMini` | +| OpenAI | `GitHubModel.OpenAI.OpenAIGpt41Mini` | `GitHubModelName.OpenAIGpt41Mini` | +| DeepSeek | `GitHubModel.DeepSeek.DeepSeekV30324` | `GitHubModelName.DeepSeekV30324` | +| DeepSeek | `GitHubModel.DeepSeek.DeepSeekR1` | `GitHubModelName.DeepSeekR1` | +| Microsoft | `GitHubModel.Microsoft.Phi4MiniInstruct` | `GitHubModelName.Phi4MiniInstruct` _(see note)_ | +| Meta | `GitHubModel.Meta.MetaLlama318BInstruct` | `GitHubModelName.MetaLlama318BInstruct` | For the full catalogue, visit the [GitHub Models Marketplace](https://github.com/marketplace/models). diff --git a/src/frontend/src/content/docs/integrations/ai/ollama/ollama-host.mdx b/src/frontend/src/content/docs/integrations/ai/ollama/ollama-host.mdx index 105d381b8..ee03c9088 100644 --- a/src/frontend/src/content/docs/integrations/ai/ollama/ollama-host.mdx +++ b/src/frontend/src/content/docs/integrations/ai/ollama/ollama-host.mdx @@ -1,6 +1,6 @@ --- title: Set up Ollama in the AppHost -seoTitle: "Set up Ollama in the Aspire AppHost: hosting integration" +seoTitle: 'Set up Ollama in the Aspire AppHost: hosting integration' description: Learn how to use the Aspire Ollama hosting integration to orchestrate and configure Ollama models in an Aspire solution. --- @@ -23,7 +23,7 @@ import ollamaIcon from '@assets/icons/ollama-icon.png'; data-zoom-off /> -This article is the reference for the Aspire Ollama hosting integration from the [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire). It enumerates the AppHost APIs — with examples for both `AppHost.cs` and `apphost.mts` — that you use to model an Ollama server and its model resources in your [`AppHost`](/get-started/app-host/) project. +This article is the reference for the Aspire Ollama hosting integration from the [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire). It shows the generated AppHost APIs for C#, TypeScript, Python, and Go that model an Ollama server and its model resources. The daily Java and Rust generators currently have package-level output conflicts, documented with each example. If you're new to the Ollama integration, start with the [Get started with Ollama integrations](/integrations/ai/ollama/ollama-get-started/) guide. For how consuming apps read the connection information this page exposes, see [Connect to Ollama](../ollama-connect/). @@ -31,7 +31,10 @@ If you're new to the Ollama integration, start with the [Get started with Ollama To start building an Aspire app that uses Ollama, install the [📦 CommunityToolkit.Aspire.Hosting.Ollama](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.Ollama) NuGet package: - + ```bash title="Terminal" @@ -39,7 +42,8 @@ aspire add ollama --source CommunityToolkit ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. Or, choose a manual installation approach: @@ -60,7 +64,8 @@ aspire add ollama --source CommunityToolkit ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. This updates your `aspire.config.json` with the Ollama hosting integration package: @@ -74,9 +79,30 @@ This updates your `aspire.config.json` with the Ollama hosting integration packa ``` + + + +```bash title="Terminal" +aspire add ollama --source CommunityToolkit +``` + +This updates `aspire.config.json` with the Ollama hosting integration package. + + + + +```bash title="Terminal" +aspire add ollama --source CommunityToolkit +``` + +This updates `aspire.config.json` with the Ollama hosting integration package. + @@ -84,7 +110,10 @@ This updates your `aspire.config.json` with the Ollama hosting integration packa Once you've installed the hosting integration in your AppHost project, you can add an Ollama server resource and then add model resources as shown in the following examples: - + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -93,10 +122,11 @@ var ollama = builder.AddOllama("ollama"); var llama3 = ollama.AddModel("llama3"); var exampleProject = builder.AddProject("apiservice") - .WithReference(llama3); +.WithReference(llama3); // After adding all resources, run the app... -``` + +```` ```typescript title="apphost.mts" twoslash @@ -111,7 +141,56 @@ await builder.addNodeApp("api", "./api", "index.js") .withReference(llama3); // After adding all resources, run the app... -``` +```` + + + +```python title="apphost.py" +from aspire_app import create_builder + +with create_builder() as builder: +ollama = builder.add_ollama("ollama") +llama3 = ollama.add_model("llama3") +builder.run() + +```` + + +```go title="apphost.go" +package main + +import ( + "log" + + "apphost/modules/aspire" +) + +func main() { + builder, err := aspire.CreateBuilder() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + + ollama := builder.AddOllama("ollama") + if err := ollama.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + llama3 := ollama.AddModel("llama3") + if err := llama3.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + app, err := builder.Build() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + if err := app.Run(); err != nil { + log.Fatal(aspire.FormatError(err)) + } +} +```` + @@ -121,19 +200,25 @@ await builder.addNodeApp("api", "./api", "index.js") 1. The resource name passed to `AddOllama` is used as the connection string name when referenced in a dependency. Model sub-resources are named by sanitizing the model name (for example, `"llama3"` produces the resource name `"ollama-llama3"`). -1. The AppHost reference call configures a connection in the consuming project named after the referenced model resource. +1. When a consuming resource references the model, Aspire configures a connection named after that model resource. ## Add Ollama model resource -Models are sub-resources of an Ollama server resource. You add them with the `AddModel` (or `addModel`) method. Each model is downloaded when the Ollama container first starts. +Models are sub-resources of an Ollama server resource. Add them with the generated model methods. Each model is downloaded when the Ollama container first starts. - + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -147,11 +232,12 @@ var phi35 = ollama.AddModel("phi3.5"); var llama3 = ollama.AddModel("ollama-llama3", "llama3"); var exampleProject = builder.AddProject("apiservice") - .WithReference(phi35) - .WithReference(llama3); +.WithReference(phi35) +.WithReference(llama3); // After adding all resources, run the app... -``` + +```` ```typescript title="apphost.mts" twoslash @@ -172,7 +258,70 @@ await builder.addNodeApp("api", "./api", "index.js") .withReference(llama3); // After adding all resources, run the app... -``` +```` + + + +```python title="apphost.py" +from aspire_app import create_builder + +with create_builder() as builder: +ollama = builder.add_ollama("ollama") + + # Add by model name - resource name is generated automatically + phi35 = ollama.add_model("phi3.5") + + # Add with an explicit resource name + llama3 = ollama.add_model("llama3", name="ollama-llama3") + + builder.run() + +```` + + +```go title="apphost.go" +package main + +import ( + "log" + + "apphost/modules/aspire" +) + +func main() { + builder, err := aspire.CreateBuilder() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + + ollama := builder.AddOllama("ollama") + if err := ollama.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + // Add by model name - resource name is generated automatically + phi35 := ollama.AddModel("phi3.5") + + // Add with an explicit resource name + llama3 := ollama.AddNamedModel("ollama-llama3", "llama3") + + if err := phi35.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + if err := llama3.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + app, err := builder.Build() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + if err := app.Run(); err != nil { + log.Fatal(aspire.FormatError(err)) + } +} +```` + @@ -189,21 +338,25 @@ When the Ollama container for this integration first spins up, it downloads the Add a data volume to the Ollama resource to persist downloaded models across container restarts: - + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var ollama = builder.AddOllama("ollama") - .WithDataVolume(); +.WithDataVolume(); var llama3 = ollama.AddModel("llama3"); var exampleProject = builder.AddProject() - .WithReference(llama3); +.WithReference(llama3); // After adding all resources, run the app... -``` + +```` ```typescript title="apphost.mts" twoslash @@ -220,7 +373,56 @@ await builder.addNodeApp("api", "./api", "index.js") .withReference(llama3); // After adding all resources, run the app... -``` +```` + + + +```python title="apphost.py" +from aspire_app import create_builder + +with create_builder() as builder: +ollama = builder.add_ollama("ollama").with_data_volume() +llama3 = ollama.add_model("llama3") +builder.run() + +```` + + +```go title="apphost.go" +package main + +import ( + "log" + + "apphost/modules/aspire" +) + +func main() { + builder, err := aspire.CreateBuilder() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + + ollama := builder.AddOllama("ollama").WithDataVolume() + if err := ollama.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + llama3 := ollama.AddModel("llama3") + if err := llama3.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + app, err := builder.Build() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + if err := app.Run(); err != nil { + log.Fatal(aspire.FormatError(err)) + } +} +```` + @@ -228,9 +430,12 @@ The data volume is mounted at `/root/.ollama` in the Ollama container. When a `n ## Use GPUs when available -By default, the Ollama container runs on CPU. To enable GPU acceleration, use the `WithGPUSupport` (or `withGPUSupport`) extension method: +By default, the Ollama container runs on CPU. To enable GPU acceleration, use the generated GPU-support method: - + **Nvidia:** @@ -269,10 +474,10 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const ollama = await builder.addOllama("ollama"); +const ollama = await builder.addOllama('ollama'); await ollama.withGPUSupport(); -await ollama.addModel("llama3"); +await ollama.addModel('llama3'); // After adding all resources, run the app... ``` @@ -284,18 +489,125 @@ import { createBuilder, OllamaGpuVendor } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const ollama = await builder.addOllama("ollama"); +const ollama = await builder.addOllama('ollama'); await ollama.withGPUSupport({ vendor: OllamaGpuVendor.AMD }); -await ollama.addModel("llama3"); +await ollama.addModel('llama3'); // After adding all resources, run the app... ``` + + + +**Nvidia:** + +```python title="apphost.py" +from aspire_app import create_builder + +with create_builder() as builder: + ollama = builder.add_ollama("ollama").with_gpu_support() + ollama.add_model("llama3") + builder.run() +``` + +**AMD:** + +```python title="apphost.py" +from aspire_app import create_builder + +with create_builder() as builder: + ollama = builder.add_ollama("ollama").with_gpu_support(vendor="AMD") + ollama.add_model("llama3") + builder.run() +``` + + + + +**Nvidia:** + +```go title="apphost.go" +package main + +import ( + "log" + + "apphost/modules/aspire" +) + +func main() { + builder, err := aspire.CreateBuilder() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + + ollama := builder.AddOllama("ollama").WithGPUSupport() + if err := ollama.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + model := ollama.AddModel("llama3") + if err := model.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + app, err := builder.Build() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + if err := app.Run(); err != nil { + log.Fatal(aspire.FormatError(err)) + } +} +``` + +**AMD:** + +```go title="apphost.go" +package main + +import ( + "log" + + "apphost/modules/aspire" +) + +func main() { + builder, err := aspire.CreateBuilder() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + + vendor := aspire.OllamaGpuVendorAMD + ollama := builder.AddOllama("ollama").WithGPUSupport( + &aspire.WithGPUSupportOptions{Vendor: &vendor}, + ) + if err := ollama.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + model := ollama.AddModel("llama3") + if err := model.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + app, err := builder.Build() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + if err := app.Run(); err != nil { + log.Fatal(aspire.FormatError(err)) + } +} +``` + @@ -303,9 +615,12 @@ For more information, see [GPU support in Docker Desktop](https://docs.docker.co ## Add a model from Hugging Face -To use a model in GGUF format from [Hugging Face](https://huggingface.co/), use the `AddHuggingFaceModel` (or `addHuggingFaceModel`) extension method: +To use a model in GGUF format from [Hugging Face](https://huggingface.co/), use the generated Hugging Face model method: - + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -313,14 +628,15 @@ var builder = DistributedApplication.CreateBuilder(args); var ollama = builder.AddOllama("ollama"); var llama = ollama.AddHuggingFaceModel( - "llama", - "bartowski/Llama-3.2-1B-Instruct-GGUF:IQ4_XS"); +"llama", +"bartowski/Llama-3.2-1B-Instruct-GGUF:IQ4_XS"); var exampleProject = builder.AddProject() - .WithReference(llama); +.WithReference(llama); // After adding all resources, run the app... -``` + +```` ```typescript title="apphost.mts" twoslash @@ -338,7 +654,62 @@ await builder.addNodeApp("api", "./api", "index.js") .withReference(llama); // After adding all resources, run the app... -``` +```` + + + +```python title="apphost.py" +from aspire_app import create_builder + +with create_builder() as builder: +ollama = builder.add_ollama("ollama") +llama = ollama.add_hugging_face_model( +"llama", +"bartowski/Llama-3.2-1B-Instruct-GGUF:IQ4_XS", +) +builder.run() + +```` + + +```go title="apphost.go" +package main + +import ( + "log" + + "apphost/modules/aspire" +) + +func main() { + builder, err := aspire.CreateBuilder() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + + ollama := builder.AddOllama("ollama") + if err := ollama.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + llama := ollama.AddHuggingFaceModel( + "llama", + "bartowski/Llama-3.2-1B-Instruct-GGUF:IQ4_XS", + ) + if err := llama.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + app, err := builder.Build() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + if err := app.Run(); err != nil { + log.Fatal(aspire.FormatError(err)) + } +} +```` + @@ -348,7 +719,10 @@ Only models in GGUF format are supported. The integration automatically prefixes To use a fixed port for the Ollama container, pass it as a parameter: - + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -358,7 +732,8 @@ var ollama = builder.AddOllama("ollama", port: 11434); ollama.AddModel("llama3"); // After adding all resources, run the app... -``` + +```` ```typescript title="apphost.mts" twoslash @@ -371,7 +746,60 @@ const ollama = await builder.addOllama("ollama", { port: 11434 }); await ollama.addModel("llama3"); // After adding all resources, run the app... -``` +```` + + + +```python title="apphost.py" +from aspire_app import create_builder + +with create_builder() as builder: +ollama = builder.add_ollama("ollama", port=11434) +ollama.add_model("llama3") +builder.run() + +```` + + +```go title="apphost.go" +package main + +import ( + "log" + + "apphost/modules/aspire" +) + +func main() { + builder, err := aspire.CreateBuilder() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + + port := float64(11434) + ollama := builder.AddOllama( + "ollama", + &aspire.AddOllamaOptions{Port: &port}, + ) + if err := ollama.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + model := ollama.AddModel("llama3") + if err := model.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + app, err := builder.Build() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + if err := app.Run(); err != nil { + log.Fatal(aspire.FormatError(err)) + } +} +```` + @@ -379,18 +807,22 @@ await ollama.addModel("llama3"); The Ollama integration also provides support for running [Open WebUI](https://openwebui.com/) alongside the Ollama container: - + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var ollama = builder.AddOllama("ollama") - .WithOpenWebUI(); +.WithOpenWebUI(); ollama.AddModel("llama3"); // After adding all resources, run the app... -``` + +```` ```typescript title="apphost.mts" twoslash @@ -404,7 +836,55 @@ await ollama.withOpenWebUI(); await ollama.addModel("llama3"); // After adding all resources, run the app... -``` +```` + + + +```python title="apphost.py" +from aspire_app import create_builder + +with create_builder() as builder: +ollama = builder.add_ollama("ollama").with_open_web_ui() +ollama.add_model("llama3") +builder.run() + +```` + + +```go title="apphost.go" +package main + +import ( + "log" + + "apphost/modules/aspire" +) + +func main() { + builder, err := aspire.CreateBuilder() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + + ollama := builder.AddOllama("ollama").WithOpenWebUI() + if err := ollama.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + model := ollama.AddModel("llama3") + if err := model.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + app, err := builder.Build() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + if err := app.Run(); err != nil { + log.Fatal(aspire.FormatError(err)) + } +} +```` diff --git a/src/frontend/src/content/docs/integrations/ai/openai/openai-get-started.mdx b/src/frontend/src/content/docs/integrations/ai/openai/openai-get-started.mdx index 9bb176901..c2c62bab3 100644 --- a/src/frontend/src/content/docs/integrations/ai/openai/openai-get-started.mdx +++ b/src/frontend/src/content/docs/integrations/ai/openai/openai-get-started.mdx @@ -61,27 +61,29 @@ Getting there is a two-step process: model the OpenAI resources in your AppHost, 1. ### Model OpenAI in your AppHost - Add the OpenAI hosting integration to your AppHost, then declare an OpenAI parent resource and one or more model resources, and reference them from the apps that need to call the API. The [OpenAI hosting integration](/integrations/ai/openai/openai-host/) article walks through every capability — adding models, API key parameters, endpoint overrides, and health checks — with side-by-side C# and TypeScript examples. + Add the OpenAI hosting integration to your AppHost, then declare an OpenAI parent resource and one or more model resources, and reference them from the apps that need to call the API. The [OpenAI hosting integration](/integrations/ai/openai/openai-host/) article walks through every capability — adding models, API key parameters, endpoint overrides, and health checks — with examples for C#, TypeScript, Python, Go, Java, and Rust. - - Set up OpenAI in the AppHost - + + Set up OpenAI in the AppHost + 2. ### Connect from your consuming app - When you reference an OpenAI model resource from a consuming app, Aspire injects its connection information as environment variables. See [Connect to OpenAI](/integrations/ai/openai/openai-connect/) for the connection properties reference and per-language examples for C#, Go, Python, and TypeScript — including the full C# client integration. + When you reference an OpenAI model resource from a consuming app, Aspire injects its connection information as environment variables. See [Connect to OpenAI](/integrations/ai/openai/openai-connect/) for the connection properties reference and per-language examples for C#, Go, Python, and TypeScript — including the full C# client integration. - - Connect to OpenAI - + + Connect to OpenAI + diff --git a/src/frontend/src/content/docs/integrations/ai/openai/openai-host.mdx b/src/frontend/src/content/docs/integrations/ai/openai/openai-host.mdx index b1ce6f685..2925a5609 100644 --- a/src/frontend/src/content/docs/integrations/ai/openai/openai-host.mdx +++ b/src/frontend/src/content/docs/integrations/ai/openai/openai-host.mdx @@ -1,6 +1,6 @@ --- title: Set up OpenAI in the AppHost -seoTitle: "Set up OpenAI in the Aspire AppHost: hosting integration" +seoTitle: 'Set up OpenAI in the Aspire AppHost: hosting integration' description: Learn how to use the Aspire OpenAI hosting integration to orchestrate and configure OpenAI resources in an Aspire solution. --- @@ -20,7 +20,7 @@ import openaiIcon from '@assets/icons/openai-icon.png'; data-zoom-off /> -This article is the reference for the Aspire OpenAI hosting integration. It enumerates the AppHost APIs — with examples for both `AppHost.cs` and `apphost.mts` — that you use to model an OpenAI parent resource and model resources in your [`AppHost`](/get-started/app-host/) project. +This article is the reference for the Aspire OpenAI hosting integration. It shows the generated AppHost APIs for C#, TypeScript, Python, Go, Java, and Rust that model an OpenAI parent resource and its model resources. If you're new to the OpenAI integration, start with the [Get started with OpenAI integrations](/integrations/ai/openai/openai-get-started/) guide. For how consuming apps read the connection information this page exposes, see [Connect to OpenAI](../openai-connect/). @@ -36,7 +36,8 @@ aspire add openai ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. Or, choose a manual installation approach: @@ -57,7 +58,8 @@ aspire add openai ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. This updates your `aspire.config.json` with the OpenAI hosting integration package: @@ -70,6 +72,42 @@ This updates your `aspire.config.json` with the OpenAI hosting integration packa } ``` + + + +```bash title="Terminal" +aspire add openai +``` + +This updates `aspire.config.json` with the OpenAI hosting integration package. + + + + +```bash title="Terminal" +aspire add openai +``` + +This updates `aspire.config.json` with the OpenAI hosting integration package. + + + + +```bash title="Terminal" +aspire add openai +``` + +This updates `aspire.config.json` with the OpenAI hosting integration package. + + + + +```bash title="Terminal" +aspire add openai +``` + +This updates `aspire.config.json` with the OpenAI hosting integration package. + @@ -87,10 +125,11 @@ var openai = builder.AddOpenAI("openai"); var chat = openai.AddModel("chat", "gpt-4o-mini"); var exampleProject = builder.AddProject("apiservice") - .WithReference(chat); +.WithReference(chat); // After adding all resources, run the app... -``` + +```` ```typescript title="apphost.mts" twoslash @@ -106,22 +145,110 @@ await builder.addNodeApp("api", "./api", "index.js") .withReference(chat); // After adding all resources, run the app... -``` +```` + + + +```python title="apphost.py" +from aspire_app import create_builder + +with create_builder() as builder: +openai = builder.add_open_ai("openai") +chat = openai.add_model("chat", "gpt-4o-mini") +builder.run() + +```` + + +```go title="apphost.go" +package main + +import ( + "log" + + "apphost/modules/aspire" +) + +func main() { + builder, err := aspire.CreateBuilder() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + + openai := builder.AddOpenAI("openai") + if err := openai.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + chat := openai.AddModel("chat", "gpt-4o-mini") + if err := chat.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + app, err := builder.Build() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + if err := app.Run(); err != nil { + log.Fatal(aspire.FormatError(err)) + } +} +```` + + + +```java title="AppHost.java" +import aspire.*; + +void main() throws Exception { +var builder = DistributedApplication.CreateBuilder(); + + var openai = builder.addOpenAI("openai"); + var chat = openai.addModel("chat", "gpt-4o-mini"); + + builder.build().run(); + +} + +```` + + +```rust title="apphost.rs" +#[path = ".aspire/modules/mod.rs"] +mod aspire; + +use aspire::*; + +fn main() -> Result<(), Box> { + let builder = create_builder(None)?; + + let openai = builder.add_open_ai("openai")?; + let chat = openai.add_model("chat", "gpt-4o-mini")?; + + let app = builder.build()?; + app.run(None)?; + Ok(()) +} +```` + -1. Calling `AddOpenAI` (or `addOpenAI`) creates an `OpenAIResource` that models the OpenAI account. It registers a secret parameter for the API key that defaults to the `OPENAI_API_KEY` environment variable. +1. Adding the OpenAI parent creates an `OpenAIResource` that models the OpenAI account. It registers a secret parameter for the API key that defaults to the `OPENAI_API_KEY` environment variable. -1. Calling `AddModel` (or `addModel`) creates an `OpenAIModelResource` child whose connection string is composed from the parent endpoint, API key, and the model name you supply. +1. Adding a model creates an `OpenAIModelResource` child whose connection string is composed from the parent endpoint, API key, and the model name you supply. -1. The AppHost reference call configures a connection in the consuming project named after the referenced model resource, such as `chat` in the preceding example. Multiple models can share the single API key and endpoint from the parent resource. +1. When a consuming resource references a model, Aspire configures a connection named after that model resource, such as `chat`. Multiple models can share the single API key and endpoint from the parent resource. ## Add multiple OpenAI model resources @@ -139,11 +266,12 @@ var chat = openai.AddModel("chat", "gpt-4o-mini"); var embeddings = openai.AddModel("embeddings", "text-embedding-3-small"); var exampleProject = builder.AddProject("apiservice") - .WithReference(chat) - .WithReference(embeddings); +.WithReference(chat) +.WithReference(embeddings); // After adding all resources, run the app... -``` + +```` ```typescript title="apphost.mts" twoslash @@ -161,7 +289,99 @@ await builder.addNodeApp("api", "./api", "index.js") .withReference(embeddings); // After adding all resources, run the app... -``` +```` + + + +```python title="apphost.py" +from aspire_app import create_builder + +with create_builder() as builder: +openai = builder.add_open_ai("openai") +chat = openai.add_model("chat", "gpt-4o-mini") +embeddings = openai.add_model("embeddings", "text-embedding-3-small") +builder.run() + +```` + + +```go title="apphost.go" +package main + +import ( + "log" + + "apphost/modules/aspire" +) + +func main() { + builder, err := aspire.CreateBuilder() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + + openai := builder.AddOpenAI("openai") + if err := openai.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + chat := openai.AddModel("chat", "gpt-4o-mini") + embeddings := openai.AddModel("embeddings", "text-embedding-3-small") + if err := chat.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + if err := embeddings.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + app, err := builder.Build() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + if err := app.Run(); err != nil { + log.Fatal(aspire.FormatError(err)) + } +} +```` + + + +```java title="AppHost.java" +import aspire.*; + +void main() throws Exception { +var builder = DistributedApplication.CreateBuilder(); + + var openai = builder.addOpenAI("openai"); + var chat = openai.addModel("chat", "gpt-4o-mini"); + var embeddings = openai.addModel("embeddings", "text-embedding-3-small"); + + builder.build().run(); + +} + +```` + + +```rust title="apphost.rs" +#[path = ".aspire/modules/mod.rs"] +mod aspire; + +use aspire::*; + +fn main() -> Result<(), Box> { + let builder = create_builder(None)?; + + let openai = builder.add_open_ai("openai")?; + let chat = openai.add_model("chat", "gpt-4o-mini")?; + let embeddings = openai.add_model("embeddings", "text-embedding-3-small")?; + + let app = builder.build()?; + app.run(None)?; + Ok(()) +} +```` + @@ -169,7 +389,7 @@ Referencing `chat` passes a connection string named `chat` to the project, and r ## Use default API key parameter -Calling `AddOpenAI("openai")` (or `addOpenAI("openai")`) automatically creates a secret parameter named `openai-openai-apikey`. Aspire resolves its value in this order: +Adding an OpenAI parent named `openai` automatically creates a secret parameter named `openai-openai-apikey`. Aspire resolves its value in this order: 1. The `Parameters:openai-openai-apikey` configuration key (user secrets, `appsettings.*`, or environment variables). 2. The `OPENAI_API_KEY` environment variable. @@ -182,7 +402,7 @@ aspire secret set Parameters:openai-openai-apikey sk-your-api-key ## Use custom API key parameter -Replace the default parameter by creating your own secret parameter and passing it to `WithApiKey` (or `withApiKey`) on the parent: +Replace the default parameter by creating your own secret parameter and passing it to the generated API-key method on the parent: @@ -192,15 +412,16 @@ var builder = DistributedApplication.CreateBuilder(args); var apiKey = builder.AddParameter("my-api-key", secret: true); var openai = builder.AddOpenAI("openai") - .WithApiKey(apiKey); +.WithApiKey(apiKey); var chat = openai.AddModel("chat", "gpt-4o-mini"); var exampleProject = builder.AddProject("apiservice") - .WithReference(chat); +.WithReference(chat); // After adding all resources, run the app... -``` + +```` ```typescript title="apphost.mts" twoslash @@ -219,15 +440,117 @@ await builder.addNodeApp("api", "./api", "index.js") .withReference(chat); // After adding all resources, run the app... -``` +```` + + + +```python title="apphost.py" +from aspire_app import create_builder + +with create_builder() as builder: +api_key = builder.add_parameter("my-api-key", secret=True) +openai = builder.add_open_ai("openai").with_api_key(api_key) +chat = openai.add_model("chat", "gpt-4o-mini") +builder.run() + +```` + + +```go title="apphost.go" +package main + +import ( + "log" + + "apphost/modules/aspire" +) + +func main() { + builder, err := aspire.CreateBuilder() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + + secret := true + apiKey := builder.AddParameter( + "my-api-key", + &aspire.AddParameterOptions{Secret: &secret}, + ) + if err := apiKey.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + openai := builder.AddOpenAI("openai").WithApiKey(apiKey) + if err := openai.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + chat := openai.AddModel("chat", "gpt-4o-mini") + if err := chat.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + app, err := builder.Build() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + if err := app.Run(); err != nil { + log.Fatal(aspire.FormatError(err)) + } +} +```` + + + +```java title="AppHost.java" +import aspire.*; + +void main() throws Exception { +var builder = DistributedApplication.CreateBuilder(); + + var apiKey = builder.addParameter( + "my-api-key", + new AddParameterOptions().secret(true)); + var openai = builder.addOpenAI("openai").withApiKey(apiKey); + var chat = openai.addModel("chat", "gpt-4o-mini"); + + builder.build().run(); + +} + +```` + + +```rust title="apphost.rs" +#[path = ".aspire/modules/mod.rs"] +mod aspire; + +use aspire::*; + +fn main() -> Result<(), Box> { + let builder = create_builder(None)?; + + let api_key = builder.add_parameter("my-api-key", None, None, Some(true))?; + let openai = builder.add_open_ai("openai")?.with_api_key(&api_key)?; + let chat = openai.add_model("chat", "gpt-4o-mini")?; + + let app = builder.build()?; + app.run(None)?; + Ok(()) +} +```` + - + ## Add a custom endpoint -Override the default `https://api.openai.com/v1` endpoint to use a proxy, an Azure OpenAI endpoint, or any OpenAI-compatible gateway. Call `WithEndpoint` (or `withEndpoint`) on the parent resource: +Override the default `https://api.openai.com/v1` endpoint to use a proxy, an Azure OpenAI endpoint, or any OpenAI-compatible gateway. Use the generated endpoint method on the parent resource: @@ -235,15 +558,16 @@ Override the default `https://api.openai.com/v1` endpoint to use a proxy, an Azu var builder = DistributedApplication.CreateBuilder(args); var openai = builder.AddOpenAI("openai") - .WithEndpoint("https://my-gateway.example.com/v1"); +.WithEndpoint("https://my-gateway.example.com/v1"); var chat = openai.AddModel("chat", "gpt-4o-mini"); var exampleProject = builder.AddProject("apiservice") - .WithReference(chat); +.WithReference(chat); // After adding all resources, run the app... -``` + +```` ```typescript title="apphost.mts" twoslash @@ -260,7 +584,97 @@ await builder.addNodeApp("api", "./api", "index.js") .withReference(chat); // After adding all resources, run the app... -``` +```` + + + +```python title="apphost.py" +from aspire_app import create_builder + +with create_builder() as builder: +openai = builder.add_open_ai("openai") +openai.with_endpoint("https://my-gateway.example.com/v1") +chat = openai.add_model("chat", "gpt-4o-mini") +builder.run() + +```` + + +```go title="apphost.go" +package main + +import ( + "log" + + "apphost/modules/aspire" +) + +func main() { + builder, err := aspire.CreateBuilder() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + + openai := builder.AddOpenAI("openai"). + WithEndpoint("https://my-gateway.example.com/v1") + if err := openai.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + chat := openai.AddModel("chat", "gpt-4o-mini") + if err := chat.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + app, err := builder.Build() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + if err := app.Run(); err != nil { + log.Fatal(aspire.FormatError(err)) + } +} +```` + + + +```java title="AppHost.java" +import aspire.*; + +void main() throws Exception { +var builder = DistributedApplication.CreateBuilder(); + + var openai = builder.addOpenAI("openai") + .withEndpoint("https://my-gateway.example.com/v1"); + var chat = openai.addModel("chat", "gpt-4o-mini"); + + builder.build().run(); + +} + +```` + + +```rust title="apphost.rs" +#[path = ".aspire/modules/mod.rs"] +mod aspire; + +use aspire::*; + +fn main() -> Result<(), Box> { + let builder = create_builder(None)?; + + let openai = builder + .add_open_ai("openai")? + .with_endpoint("https://my-gateway.example.com/v1")?; + let chat = openai.add_model("chat", "gpt-4o-mini")?; + + let app = builder.build()?; + app.run(None)?; + Ok(()) +} +```` + @@ -278,13 +692,14 @@ var builder = DistributedApplication.CreateBuilder(args); var openai = builder.AddOpenAI("openai"); var chat = openai.AddModel("chat", "gpt-4o-mini") - .WithHealthCheck(); +.WithHealthCheck(); var exampleProject = builder.AddProject("apiservice") - .WithReference(chat); +.WithReference(chat); // After adding all resources, run the app... -``` + +```` ```typescript title="apphost.mts" twoslash @@ -301,28 +716,119 @@ await builder.addNodeApp("api", "./api", "index.js") .withReference(chat); // After adding all resources, run the app... -``` +```` + + + +```python title="apphost.py" +from aspire_app import create_builder + +with create_builder() as builder: +openai = builder.add_open_ai("openai") +chat = openai.add_model("chat", "gpt-4o-mini").with_health_check() +builder.run() + +```` + + +```go title="apphost.go" +package main + +import ( + "log" + + "apphost/modules/aspire" +) + +func main() { + builder, err := aspire.CreateBuilder() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + + openai := builder.AddOpenAI("openai") + if err := openai.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + chat := openai.AddModel("chat", "gpt-4o-mini").WithHealthCheck() + if err := chat.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + app, err := builder.Build() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + if err := app.Run(); err != nil { + log.Fatal(aspire.FormatError(err)) + } +} +```` + + + +```java title="AppHost.java" +import aspire.*; + +void main() throws Exception { +var builder = DistributedApplication.CreateBuilder(); + + var openai = builder.addOpenAI("openai"); + var chat = openai.addModel("chat", "gpt-4o-mini") + .withHealthCheck(); + + builder.build().run(); + +} + +```` + + +```rust title="apphost.rs" +#[path = ".aspire/modules/mod.rs"] +mod aspire; + +use aspire::*; + +fn main() -> Result<(), Box> { + let builder = create_builder(None)?; + + let openai = builder.add_open_ai("openai")?; + let chat = openai + .add_model("chat", "gpt-4o-mini")? + .with_health_check()?; + + let app = builder.build()?; + app.run(None)?; + Ok(()) +} +```` + The model health check validates endpoint reachability, API key validity (401), and model existence (404). It executes only once per application instance to limit rate-limit implications. ## Available models Common model identifiers for the OpenAI API: -| Category | Model identifiers | -| ---------- | ----------------- | -| Chat | `gpt-5`, `gpt-4o`, `gpt-4o-mini`, `gpt-4-turbo` | -| Reasoning | `o3`, `o3-mini`, `o4-mini` | -| Realtime | `gpt-realtime` | +| Category | Model identifiers | +| ---------- | -------------------------------------------------- | +| Chat | `gpt-5`, `gpt-4o`, `gpt-4o-mini`, `gpt-4-turbo` | +| Reasoning | `o3`, `o3-mini`, `o4-mini` | +| Realtime | `gpt-realtime` | | Embeddings | `text-embedding-3-small`, `text-embedding-3-large` | -| Images | `dall-e-3` | -| Audio | `whisper-1` | +| Images | `dall-e-3` | +| Audio | `whisper-1` | For the full and up-to-date list, see the [OpenAI models documentation](https://platform.openai.com/docs/models). diff --git a/src/frontend/src/content/docs/integrations/caching/garnet/garnet-host.mdx b/src/frontend/src/content/docs/integrations/caching/garnet/garnet-host.mdx index 0ab7c87e3..c0a2b6d03 100644 --- a/src/frontend/src/content/docs/integrations/caching/garnet/garnet-host.mdx +++ b/src/frontend/src/content/docs/integrations/caching/garnet/garnet-host.mdx @@ -1,6 +1,6 @@ --- title: Set up Garnet in the AppHost -seoTitle: "Set up Garnet in the Aspire AppHost: hosting integration" +seoTitle: 'Set up Garnet in the Aspire AppHost: hosting integration' description: Learn how to use the Aspire Garnet Hosting integration to orchestrate and configure a Garnet resource in an Aspire solution. --- @@ -21,7 +21,7 @@ import garnetIcon from '@assets/icons/garnet-icon.png'; data-zoom-off /> -This article is the reference for the Aspire Garnet Hosting integration. It enumerates the AppHost APIs — with examples for both `AppHost.cs` and `apphost.mts` — that you use to model a Garnet resource in your [`AppHost`](/get-started/app-host/) project. +This article is the reference for the Aspire Garnet Hosting integration. It enumerates the AppHost APIs — with examples across all six supported AppHost languages (C#, TypeScript, Python, Go, Java, and Rust) — that you use to model a Garnet resource in your [`AppHost`](/get-started/app-host/) project. If you're new to the Garnet integration, start with the [Get started with Garnet integrations](/integrations/caching/garnet/garnet-get-started/) guide. For how consuming apps read the connection information this page exposes, see [Connect to Garnet](../garnet-connect/). @@ -29,7 +29,12 @@ If you're new to the Garnet integration, start with the [Get started with Garnet To start building an Aspire app that uses Garnet, install the [📦 Aspire.Hosting.Garnet](https://www.nuget.org/packages/Aspire.Hosting.Garnet) NuGet package: - + ```bash title="Terminal" @@ -37,7 +42,8 @@ aspire add garnet ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. Or, choose a manual installation approach: @@ -58,7 +64,8 @@ aspire add garnet ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. This updates your `aspire.config.json` with the Garnet hosting integration package: @@ -78,20 +85,29 @@ This updates your `aspire.config.json` with the Garnet hosting integration packa Once you've installed the hosting integration in your AppHost project, you can add a Garnet resource as shown in the following examples: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var cache = builder.AddGarnet("cache"); var exampleProject = builder.AddProject("apiservice") - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` + + ```typescript title="apphost.mts" import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -104,6 +120,7 @@ await builder.addNodeApp("api", "./api", "index.js") // After adding all resources, run the app... ``` + @@ -118,7 +135,11 @@ await builder.addNodeApp("api", "./api", "index.js") @@ -127,21 +148,30 @@ await builder.addNodeApp("api", "./api", "index.js") Add a data volume to the Garnet resource as shown in the following examples: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var cache = builder.AddGarnet("cache") - .WithDataVolume(isReadOnly: false); +.WithDataVolume(isReadOnly: false); var exampleProject = builder.AddProject() - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` + + ```typescript title="apphost.mts" twoslash import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -155,6 +185,7 @@ await builder.addNodeApp("api", "./api", "index.js") // After adding all resources, run the app... ``` + @@ -164,23 +195,32 @@ The data volume is used to persist Garnet data outside the lifecycle of its cont Add a data bind mount to the Garnet resource as shown in the following examples: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var cache = builder.AddGarnet("cache") - .WithDataBindMount( - source: "/Garnet/Data", - isReadOnly: false); +.WithDataBindMount( +source: "/Garnet/Data", +isReadOnly: false); var exampleProject = builder.AddProject() - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` + + ```typescript title="apphost.mts" twoslash import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -194,11 +234,18 @@ await builder.addNodeApp("api", "./api", "index.js") // After adding all resources, run the app... ``` + Data bind mounts rely on the host machine's filesystem to persist Garnet data across container restarts. The data bind mount is mounted at the `C:\Garnet\Data` on Windows (or `/Garnet/Data` on Unix) path on the host machine in the Garnet container. As with `WithDataVolume`, this call also enables persistence. For more information on data bind mounts, see [Docker docs: Bind mounts](https://docs.docker.com/engine/storage/bind-mounts). @@ -207,24 +254,33 @@ Data bind mounts rely on the host machine's filesystem to persist Garnet data ac To configure Garnet snapshot persistence explicitly, call `WithPersistence` (or `withPersistence`) alongside a data volume or bind mount: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var cache = builder.AddGarnet("cache") - .WithDataVolume() - .WithPersistence( - interval: TimeSpan.FromMinutes(5), - keysChangedThreshold: 100); +.WithDataVolume() +.WithPersistence( +interval: TimeSpan.FromMinutes(5), +keysChangedThreshold: 100); var exampleProject = builder.AddProject() - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` + + ```typescript title="apphost.mts" twoslash import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -241,21 +297,28 @@ await builder.addNodeApp("api", "./api", "index.js") // After adding all resources, run the app... ``` + -The preceding code adds explicit persistence to the Garnet resource by snapshotting data at the configured interval. The C# AppHost accepts a `TimeSpan` for `interval` and a `keysChangedThreshold` to also trigger snapshots when a minimum number of keys change; the TypeScript AppHost accepts the interval as milliseconds. +The preceding code adds explicit persistence to the Garnet resource by snapshotting data at the configured interval. The C# AppHost accepts a `TimeSpan` for `interval` and a `keysChangedThreshold` to also trigger snapshots when a minimum number of keys change; every other AppHost language accepts the interval as milliseconds and doesn't expose `keysChangedThreshold`. :::note -The TypeScript `WithPersistenceOptions` does not currently expose `keysChangedThreshold`. If you need threshold-based snapshotting, use the C# AppHost. +`keysChangedThreshold`-based snapshotting for Garnet is only available from the C# AppHost. TypeScript, Python, Go, Java, and Rust all generate a `WithPersistence` overload that accepts only `interval`. ::: ## Add Garnet resource with parameters When you want to explicitly provide the port and password used by the Garnet container, you can pass them as parameters: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -264,12 +327,15 @@ var password = builder.AddParameter("password", secret: true); var cache = builder.AddGarnet("cache", port: 6379, password: password); var exampleProject = builder.AddProject() - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` + + ```typescript title="apphost.mts" twoslash import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -284,6 +350,7 @@ await builder.addNodeApp("api", "./api", "index.js") // After adding all resources, run the app... ``` + @@ -293,26 +360,35 @@ When no `password` parameter is provided, Aspire generates a strong password aut By default, Aspire injects the Garnet connection information using variable names derived from the resource name (for example, `CACHE_URI`, `CACHE_HOST`, `CACHE_PORT`, `CACHE_PASSWORD`). If your consuming app expects a different set of environment variable names, pass individual connection properties from the AppHost: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var cache = builder.AddGarnet("cache"); var app = builder.AddExecutable("my-app", "node", "app.js", ".") - .WithReference(cache) - .WithEnvironment(context => - { - context.EnvironmentVariables["GARNET_HOST"] = cache.Resource.PrimaryEndpoint.Property(EndpointProperty.Host); - context.EnvironmentVariables["GARNET_PORT"] = cache.Resource.PrimaryEndpoint.Property(EndpointProperty.Port); - context.EnvironmentVariables["GARNET_PASSWORD"] = cache.Resource.PasswordParameter; - }); +.WithReference(cache) +.WithEnvironment(context => +{ +context.EnvironmentVariables["GARNET_HOST"] = cache.Resource.PrimaryEndpoint.Property(EndpointProperty.Host); +context.EnvironmentVariables["GARNET_PORT"] = cache.Resource.PrimaryEndpoint.Property(EndpointProperty.Port); +context.EnvironmentVariables["GARNET_PASSWORD"] = cache.Resource.PasswordParameter; +}); builder.Build().Run(); + ``` + + ```typescript title="apphost.mts" twoslash import { createBuilder, EndpointProperty } from './.aspire/modules/aspire.mjs'; @@ -331,6 +407,7 @@ await builder.addNodeApp("my-app", "./app", "index.js") await builder.build().run(); ``` + @@ -338,20 +415,29 @@ await builder.build().run(); To reference an externally managed Garnet instance instead of running one as a container, use `AddConnectionString`: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var cache = builder.AddConnectionString("cache"); var exampleProject = builder.AddProject() - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` + + ```typescript title="apphost.mts" import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -365,6 +451,7 @@ await builder.addNodeApp("my-app", "./app", "index.js") // After adding all resources, run the app... await builder.build().run(); ``` + @@ -372,7 +459,7 @@ With `AddConnectionString` and `addConnectionString`, Aspire resolves `cache` fr ## Connection properties -For the full reference of Garnet resource connection properties — and how consuming apps in C#, TypeScript, Python, and Go read them — see [Connect to Garnet](../garnet-connect/). +For the full reference of Garnet resource connection properties — and how consuming apps in C#, TypeScript, Python, Go, Java, and Rust read them — see [Connect to Garnet](../garnet-connect/). ## Hosting integration health checks diff --git a/src/frontend/src/content/docs/integrations/caching/redis-distributed/redis-distributed-host.mdx b/src/frontend/src/content/docs/integrations/caching/redis-distributed/redis-distributed-host.mdx index d2d966210..a77477977 100644 --- a/src/frontend/src/content/docs/integrations/caching/redis-distributed/redis-distributed-host.mdx +++ b/src/frontend/src/content/docs/integrations/caching/redis-distributed/redis-distributed-host.mdx @@ -35,7 +35,8 @@ aspire add redis ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. Or, choose a manual installation approach: @@ -56,7 +57,8 @@ aspire add redis ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. This updates your `aspire.config.json` with the Redis hosting integration package: @@ -69,6 +71,34 @@ This updates your `aspire.config.json` with the Redis hosting integration packag } ``` + + + +```bash title="Terminal" +aspire add redis +``` + + + + +```bash title="Terminal" +aspire add redis +``` + + + + +```bash title="Terminal" +aspire add redis +``` + + + + +```bash title="Terminal" +aspire add redis +``` + @@ -78,30 +108,129 @@ Once the hosting integration is installed, add a Redis resource in your AppHost + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var cache = builder.AddRedis("cache"); var exampleProject = builder.AddProject("apiservice") - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` + + ```typescript title="apphost.mts" import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const cache = await builder.addRedis("cache"); +const cache = await builder.addRedis('cache'); -await builder.addNodeApp("api", "./api", "index.js") - .withReference(cache); +await builder.addNodeApp('api', './api', 'index.js').withReference(cache); // After adding all resources, run the app... ``` + + + + +```python title="apphost.py" +from aspire_app import create_builder + +with create_builder() as builder: + cache = builder.add_redis("cache") + + builder.add_project( + "apiservice", + "../ExampleProject/ExampleProject.csproj", + ).with_reference(cache) + + builder.run() + +``` + + + + +```go title="apphost.go" +package main + +import ( + "log" + + "apphost/modules/aspire" +) + +func main() { + builder, err := aspire.CreateBuilder() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + + cache := builder.AddRedis("cache") + if err := cache.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + api := builder.AddProject( + "apiservice", + "../ExampleProject/ExampleProject.csproj", + ).WithReference(cache) + if err := api.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } +} +``` + + + + +```java title="AppHost.java" +import aspire.*; + +void main() throws Exception { +var builder = DistributedApplication.CreateBuilder(); + + var cache = builder.addRedis("cache"); + builder.addProject( + "apiservice", + "../ExampleProject/ExampleProject.csproj") + .withReference(cache); + +} + +``` + + + + +```rust title="apphost.rs" +#[path = ".aspire/modules/mod.rs"] +mod aspire; + +use aspire::*; + +fn main() -> Result<(), Box> { + let builder = create_builder(None)?; + + let cache = builder.add_redis("cache", None, None)?; + builder + .add_project( + "apiservice", + "../ExampleProject/ExampleProject.csproj", + None, + )? + .with_reference(cache.handle().to_json(), None, None, None)?; + + Ok(()) +} +``` + @@ -116,7 +245,11 @@ await builder.addNodeApp("api", "./api", "index.js") ## Full AppHost API reference diff --git a/src/frontend/src/content/docs/integrations/caching/redis-extensions.mdx b/src/frontend/src/content/docs/integrations/caching/redis-extensions.mdx index ec0e4e2fd..5943ea9fc 100644 --- a/src/frontend/src/content/docs/integrations/caching/redis-extensions.mdx +++ b/src/frontend/src/content/docs/integrations/caching/redis-extensions.mdx @@ -56,6 +56,34 @@ This updates your `aspire.config.json` with the Redis extensions package: } ``` + + + +```bash title="Terminal" +aspire add CommunityToolkit.Aspire.Hosting.Redis.Extensions +``` + + + + +```bash title="Terminal" +aspire add CommunityToolkit.Aspire.Hosting.Redis.Extensions +``` + + + + +```bash title="Terminal" +aspire add CommunityToolkit.Aspire.Hosting.Redis.Extensions +``` + + + + +```bash title="Terminal" +aspire add CommunityToolkit.Aspire.Hosting.Redis.Extensions +``` + @@ -100,6 +128,112 @@ await exampleProject.withReference(redis); await builder.build().run(); ``` + + + +```python title="apphost.py" +from aspire_app import create_builder + +with create_builder() as builder: + redis = builder.add_redis("redis").with_db_gate() + + builder.add_project( + "example-project", + "../ExampleProject/ExampleProject.csproj", + ).with_reference(redis) + + builder.run() +``` + + + + +```go title="apphost.go" +package main + +import ( + "log" + + "apphost/modules/aspire" +) + +func main() { + builder, err := aspire.CreateBuilder() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + + redis := builder.AddRedis("redis").WithDbGate() + if err := redis.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + project := builder. + AddProject("example-project", "../ExampleProject/ExampleProject.csproj"). + WithReference(redis) + if err := project.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + app, err := builder.Build() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + if err := app.Run(); err != nil { + log.Fatal(aspire.FormatError(err)) + } +} +``` + + + + +```java title="AppHost.java" +import aspire.*; + +void main() throws Exception { + var builder = DistributedApplication.CreateBuilder(); + + var redis = builder.addRedis("redis").withDbGate(); + builder.addProject( + "example-project", + "../ExampleProject/ExampleProject.csproj") + .withReference(redis); + + builder.build().run(); +} +``` + + + + +```rust title="apphost.rs" +#[path = ".aspire/modules/mod.rs"] +mod aspire; + +use aspire::*; +use serde_json::Value; + +fn main() -> Result<(), Box> { + let builder = create_builder(None)?; + + let redis = builder + .add_redis("redis", None, None)? + .with_db_gate(|_| Value::Null, None)?; + builder + .add_project( + "example-project", + "../ExampleProject/ExampleProject.csproj", + None, + )? + .with_reference(redis.handle().to_json(), None, None, None)?; + + let app = builder.build()?; + app.run(None)?; + Ok(()) +} +``` + @@ -138,10 +272,91 @@ await redis.withDbx({ await builder.build().run(); ``` + + + +```python title="apphost.py" +from aspire_app import create_builder + +with create_builder() as builder: + builder.add_redis("redis").with_dbx() + builder.run() +``` + + + + +```go title="apphost.go" +package main + +import ( + "log" + + "apphost/modules/aspire" +) + +func main() { + builder, err := aspire.CreateBuilder() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + + redis := builder.AddRedis("redis").WithDbx() + if err := redis.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + app, err := builder.Build() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + if err := app.Run(); err != nil { + log.Fatal(aspire.FormatError(err)) + } +} +``` + + + + +```java title="AppHost.java" +import aspire.*; + +void main() throws Exception { + var builder = DistributedApplication.CreateBuilder(); + + builder.addRedis("redis").withDbx(); + + builder.build().run(); +} +``` + + + + +```rust title="apphost.rs" +#[path = ".aspire/modules/mod.rs"] +mod aspire; + +use aspire::*; + +fn main() -> Result<(), Box> { + let builder = create_builder(None)?; + + builder + .add_redis("redis", None, None)? + .with_dbx(None, None)?; + + let app = builder.build()?; + app.run(None)?; + Ok(()) +} +``` + -The C# overload accepts an optional container configuration callback and `containerName`. The TypeScript binding accepts optional `containerName` and `imageTag` values. +The C# overload accepts an optional container configuration callback and `containerName`. The generated AppHost bindings accept optional container-name and image-tag values using each language's options shape. ## See also diff --git a/src/frontend/src/content/docs/integrations/caching/redis-output/redis-output-host.mdx b/src/frontend/src/content/docs/integrations/caching/redis-output/redis-output-host.mdx index 0439357f0..8761a9a86 100644 --- a/src/frontend/src/content/docs/integrations/caching/redis-output/redis-output-host.mdx +++ b/src/frontend/src/content/docs/integrations/caching/redis-output/redis-output-host.mdx @@ -35,7 +35,8 @@ aspire add redis ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. Or, choose a manual installation approach: @@ -56,7 +57,8 @@ aspire add redis ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. This updates your `aspire.config.json` with the Redis hosting integration package: @@ -69,6 +71,34 @@ This updates your `aspire.config.json` with the Redis hosting integration packag } ``` + + + +```bash title="Terminal" +aspire add redis +``` + + + + +```bash title="Terminal" +aspire add redis +``` + + + + +```bash title="Terminal" +aspire add redis +``` + + + + +```bash title="Terminal" +aspire add redis +``` + @@ -98,19 +128,110 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const cache = await builder.addRedis("cache"); +const cache = await builder.addRedis('cache'); -await builder.addProject("apiservice", "../ApiService/ApiService.csproj") - .withReference(cache); +await builder + .addProject('apiservice', '../ApiService/ApiService.csproj') + .withReference(cache); // After adding all resources, run the app... ``` + + + +```python title="apphost.py" +from aspire_app import create_builder + +with create_builder() as builder: + cache = builder.add_redis("cache") + + builder.add_project( + "apiservice", + "../ApiService/ApiService.csproj", + ).with_reference(cache) +``` + + + + +```go title="apphost.go" +package main + +import ( + "log" + + "apphost/modules/aspire" +) + +func main() { + builder, err := aspire.CreateBuilder() + if err != nil { + log.Fatal(aspire.FormatError(err)) + } + + cache := builder.AddRedis("cache") + if err := cache.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } + + api := builder.AddProject( + "apiservice", + "../ApiService/ApiService.csproj", + ).WithReference(cache) + if err := api.Err(); err != nil { + log.Fatal(aspire.FormatError(err)) + } +} +``` + + + + +```java title="AppHost.java" +import aspire.*; + +void main() throws Exception { + var builder = DistributedApplication.CreateBuilder(); + + var cache = builder.addRedis("cache"); + builder.addProject( + "apiservice", + "../ApiService/ApiService.csproj") + .withReference(cache); +} +``` + + + + +```rust title="apphost.rs" +#[path = ".aspire/modules/mod.rs"] +mod aspire; + +use aspire::*; + +fn main() -> Result<(), Box> { + let builder = create_builder(None)?; + + let cache = builder.add_redis("cache", None, None)?; + builder + .add_project("apiservice", "../ApiService/ApiService.csproj", None)? + .with_reference(cache.handle().to_json(), None, None, None)?; + + Ok(()) +} +``` + ## More AppHost options diff --git a/src/frontend/src/content/docs/integrations/caching/redis/redis-host.mdx b/src/frontend/src/content/docs/integrations/caching/redis/redis-host.mdx index f6b511a0f..2cc3890cb 100644 --- a/src/frontend/src/content/docs/integrations/caching/redis/redis-host.mdx +++ b/src/frontend/src/content/docs/integrations/caching/redis/redis-host.mdx @@ -1,6 +1,6 @@ --- title: Set up Redis in the AppHost -seoTitle: "Set up Redis in the Aspire AppHost: hosting integration" +seoTitle: 'Set up Redis in the Aspire AppHost: hosting integration' description: Learn how to use the Aspire Redis Hosting integration to orchestrate and configure a Redis resource in an Aspire solution. --- @@ -37,7 +37,8 @@ aspire add redis ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. Or, choose a manual installation approach: @@ -58,7 +59,8 @@ aspire add redis ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. This updates your `aspire.config.json` with the Redis hosting integration package: @@ -71,6 +73,34 @@ This updates your `aspire.config.json` with the Redis hosting integration packag } ``` + + + +```bash title="Terminal" +aspire add redis +``` + + + + +```bash title="Terminal" +aspire add redis +``` + + + + +```bash title="Terminal" +aspire add redis +``` + + + + +```bash title="Terminal" +aspire add redis +``` + @@ -78,20 +108,29 @@ This updates your `aspire.config.json` with the Redis hosting integration packag Once you've installed the hosting integration in your AppHost project, you can add a Redis resource as shown in the following examples: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var cache = builder.AddRedis("cache"); var exampleProject = builder.AddProject("apiservice") - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` + + ```typescript title="apphost.mts" import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -104,6 +143,7 @@ await builder.addNodeApp("api", "./api", "index.js") // After adding all resources, run the app... ``` + @@ -118,7 +158,11 @@ await builder.addNodeApp("api", "./api", "index.js") @@ -127,21 +171,30 @@ await builder.addNodeApp("api", "./api", "index.js") Add a data volume to the Redis resource as shown in the following examples: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var cache = builder.AddRedis("cache") - .WithDataVolume(isReadOnly: false); +.WithDataVolume(isReadOnly: false); var exampleProject = builder.AddProject() - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` + + ```typescript title="apphost.mts" twoslash import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -155,6 +208,7 @@ await builder.addNodeApp("api", "./api", "index.js") // After adding all resources, run the app... ``` + @@ -164,23 +218,32 @@ The data volume is used to persist Redis data outside the lifecycle of its conta Add a data bind mount to the Redis resource as shown in the following examples: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var cache = builder.AddRedis("cache") - .WithDataBindMount( - source: @"C:\Redis\Data", - isReadOnly: false); +.WithDataBindMount( +source: @"C:\Redis\Data", +isReadOnly: false); var exampleProject = builder.AddProject() - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` + + ```typescript title="apphost.mts" twoslash import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -194,11 +257,18 @@ await builder.addNodeApp("api", "./api", "index.js") // After adding all resources, run the app... ``` + Data bind mounts rely on the host machine's filesystem to persist Redis data across container restarts. The data bind mount is mounted at the `C:\Redis\Data` on Windows (or `/Redis/Data` on Unix) path on the host machine in the Redis container. As with `WithDataVolume`, this call also enables persistence. For more information on data bind mounts, see [Docker docs: Bind mounts](https://docs.docker.com/engine/storage/bind-mounts). @@ -207,24 +277,33 @@ Data bind mounts rely on the host machine's filesystem to persist Redis data acr To configure Redis snapshot persistence explicitly, call `WithPersistence` (or `withPersistence`) alongside a data volume or bind mount: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var cache = builder.AddRedis("cache") - .WithDataVolume() - .WithPersistence( - interval: TimeSpan.FromMinutes(5), - keysChangedThreshold: 100); +.WithDataVolume() +.WithPersistence( +interval: TimeSpan.FromMinutes(5), +keysChangedThreshold: 100); var exampleProject = builder.AddProject() - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` + + ```typescript title="apphost.mts" twoslash import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -242,6 +321,7 @@ await builder.addNodeApp("api", "./api", "index.js") // After adding all resources, run the app... ``` + @@ -251,8 +331,14 @@ The preceding code adds explicit persistence to the Redis resource by snapshotti When you want to explicitly provide the port and password used by the Redis container, you can pass them as parameters: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -261,12 +347,15 @@ var password = builder.AddParameter("password", secret: true); var cache = builder.AddRedis("cache", port: 6379, password: password); var exampleProject = builder.AddProject() - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` + + ```typescript title="apphost.mts" twoslash import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -281,6 +370,7 @@ await builder.addNodeApp("api", "./api", "index.js") // After adding all resources, run the app... ``` + @@ -290,21 +380,30 @@ When no `password` parameter is provided, Aspire generates a strong password aut [Redis Insight](https://redis.io/insight/) is a free graphical interface for analyzing Redis data. Add it to the Redis resource as shown in the following examples: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var cache = builder.AddRedis("cache") - .WithRedisInsight(); +.WithRedisInsight(); var exampleProject = builder.AddProject() - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` + + ```typescript title="apphost.mts" twoslash import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -318,6 +417,7 @@ await builder.addNodeApp("api", "./api", "index.js") // After adding all resources, run the app... ``` + @@ -329,21 +429,30 @@ The preceding code adds a container based on the `docker.io/redis/redisinsight` To configure the host port for the Redis Insight container, use the `configureContainer` callback as shown in the following examples: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var cache = builder.AddRedis("cache") - .WithRedisInsight(redisInsight => redisInsight.WithHostPort(8001)); +.WithRedisInsight(redisInsight => redisInsight.WithHostPort(8001)); var exampleProject = builder.AddProject() - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` + + ```typescript title="apphost.mts" twoslash import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -361,6 +470,7 @@ await builder.addNodeApp("api", "./api", "index.js") // After adding all resources, run the app... ``` + @@ -370,21 +480,30 @@ The preceding code adds and configures the host port for the Redis Insight conta [Redis Commander](https://joeferner.github.io/redis-commander/) is a Node.js web application for viewing, editing, and managing a Redis database. Add it to the Redis resource as shown in the following examples: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var cache = builder.AddRedis("cache") - .WithRedisCommander(); +.WithRedisCommander(); var exampleProject = builder.AddProject() - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` + + ```typescript title="apphost.mts" twoslash import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -398,6 +517,7 @@ await builder.addNodeApp("api", "./api", "index.js") // After adding all resources, run the app... ``` + @@ -409,21 +529,30 @@ The preceding code adds a container based on the `ghcr.io/joeferner/redis-comman To configure the host port for the Redis Commander container, use the `configureContainer` callback as shown in the following examples: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var cache = builder.AddRedis("cache") - .WithRedisCommander(redisCommander => redisCommander.WithHostPort(8081)); +.WithRedisCommander(redisCommander => redisCommander.WithHostPort(8081)); var exampleProject = builder.AddProject() - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` + + ```typescript title="apphost.mts" twoslash import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -441,6 +570,7 @@ await builder.addNodeApp("api", "./api", "index.js") // After adding all resources, run the app... ``` + @@ -450,28 +580,43 @@ The preceding code adds and configures the host port for the Redis Commander con The `WithClearCommand` method adds a **CLEAR** command button to the Aspire dashboard for the Redis resource. When clicked, it flushes all keys from the Redis database, which is useful during development to reset cache state without restarting the container. + + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var cache = builder.AddRedis("cache") - .WithClearCommand(); +.WithClearCommand(); var exampleProject = builder.AddProject() - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` - + + ## Pass custom environment variables By default, Aspire injects the Redis connection information using variable names derived from the resource name (for example, `CACHE_URI`, `CACHE_HOST`, `CACHE_PORT`, `CACHE_PASSWORD`). If your consuming app expects a different set of environment variable names, pass individual connection properties from the AppHost: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -488,8 +633,10 @@ var app = builder.AddExecutable("my-app", "node", "app.js", ".") builder.Build().Run(); ``` + + ```typescript title="apphost.mts" twoslash import { createBuilder, EndpointProperty } from './.aspire/modules/aspire.mjs'; @@ -501,13 +648,15 @@ const cacheHost = await cacheEndpoint.property(EndpointProperty.Host); const cachePort = await cacheEndpoint.property(EndpointProperty.Port); await builder.addNodeApp("my-app", "./app", "index.js") - .withReference(cache) - .withEnvironment("REDIS_HOST", cacheHost) - .withEnvironment("REDIS_PORT", cachePort) - .withEnvironment("REDIS_PASSWORD", await cache.passwordParameter()); +.withReference(cache) +.withEnvironment("REDIS_HOST", cacheHost) +.withEnvironment("REDIS_PORT", cachePort) +.withEnvironment("REDIS_PASSWORD", await cache.passwordParameter()); await builder.build().run(); + ``` + @@ -515,8 +664,14 @@ await builder.build().run(); To reference an externally managed Redis instance instead of running one as a container, use `AddConnectionString`: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -527,8 +682,10 @@ var exampleProject = builder.AddProject() // After adding all resources, run the app... ``` + + ```typescript title="apphost.mts" import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -537,11 +694,13 @@ const builder = await createBuilder(); const cache = await builder.addConnectionString("cache"); await builder.addNodeApp("my-app", "./app", "index.js") - .withReference(cache); +.withReference(cache); // After adding all resources, run the app... await builder.build().run(); + ``` + @@ -556,3 +715,4 @@ For the full reference of Redis resource connection properties — and how consu The Redis hosting integration automatically adds a health check for the Redis resource. The health check verifies that the Redis instance is running and that a connection can be established to it. The hosting integration relies on the [📦 AspNetCore.HealthChecks.Redis](https://www.nuget.org/packages/AspNetCore.HealthChecks.Redis) NuGet package. +``` diff --git a/src/frontend/src/content/docs/integrations/caching/valkey/valkey-host.mdx b/src/frontend/src/content/docs/integrations/caching/valkey/valkey-host.mdx index 522787954..97386ac90 100644 --- a/src/frontend/src/content/docs/integrations/caching/valkey/valkey-host.mdx +++ b/src/frontend/src/content/docs/integrations/caching/valkey/valkey-host.mdx @@ -1,6 +1,6 @@ --- title: Set up Valkey in the AppHost -seoTitle: "Set up Valkey in the Aspire AppHost: hosting integration" +seoTitle: 'Set up Valkey in the Aspire AppHost: hosting integration' description: Learn how to use the Aspire Valkey Hosting integration to orchestrate and configure a Valkey resource in an Aspire solution. --- @@ -29,7 +29,12 @@ If you're new to the Valkey integration, start with the [Get started with Valkey To start building an Aspire app that uses Valkey, install the [📦 Aspire.Hosting.Valkey](https://www.nuget.org/packages/Aspire.Hosting.Valkey) NuGet package: - + ```bash title="Terminal" @@ -37,7 +42,8 @@ aspire add valkey ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. Or, choose a manual installation approach: @@ -58,7 +64,8 @@ aspire add valkey ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. This updates your `aspire.config.json` with the Valkey hosting integration package: @@ -78,20 +85,29 @@ This updates your `aspire.config.json` with the Valkey hosting integration packa Once you've installed the hosting integration in your AppHost project, you can add a Valkey resource as shown in the following examples: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var cache = builder.AddValkey("cache"); var exampleProject = builder.AddProject("apiservice") - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` + + ```typescript title="apphost.mts" import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -104,6 +120,7 @@ await builder.addNodeApp("api", "./api", "index.js") // After adding all resources, run the app... ``` + @@ -118,7 +135,11 @@ await builder.addNodeApp("api", "./api", "index.js") @@ -127,21 +148,30 @@ await builder.addNodeApp("api", "./api", "index.js") Add a data volume to the Valkey resource as shown in the following examples: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var cache = builder.AddValkey("cache") - .WithDataVolume(isReadOnly: false); +.WithDataVolume(isReadOnly: false); var exampleProject = builder.AddProject() - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` + + ```typescript title="apphost.mts" twoslash import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -155,6 +185,7 @@ await builder.addNodeApp("api", "./api", "index.js") // After adding all resources, run the app... ``` + @@ -164,23 +195,32 @@ The data volume is used to persist Valkey data outside the lifecycle of its cont Add a data bind mount to the Valkey resource as shown in the following examples: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var cache = builder.AddValkey("cache") - .WithDataBindMount( - source: "/Valkey/Data", - isReadOnly: false); +.WithDataBindMount( +source: "/Valkey/Data", +isReadOnly: false); var exampleProject = builder.AddProject() - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` + + ```typescript title="apphost.mts" twoslash import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -194,11 +234,18 @@ await builder.addNodeApp("api", "./api", "index.js") // After adding all resources, run the app... ``` + Data bind mounts rely on the host machine's filesystem to persist Valkey data across container restarts. The data bind mount is mounted at the `C:\Valkey\Data` on Windows (or `/Valkey/Data` on Unix) path on the host machine in the Valkey container. As with `WithDataVolume`, this call also enables persistence. For more information on data bind mounts, see [Docker docs: Bind mounts](https://docs.docker.com/engine/storage/bind-mounts). @@ -207,24 +254,33 @@ Data bind mounts rely on the host machine's filesystem to persist Valkey data ac To configure Valkey snapshot persistence explicitly, call `WithPersistence` (or `withPersistence`) alongside a data volume or bind mount: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var cache = builder.AddValkey("cache") - .WithDataVolume() - .WithPersistence( - interval: TimeSpan.FromMinutes(5), - keysChangedThreshold: 100); +.WithDataVolume() +.WithPersistence( +interval: TimeSpan.FromMinutes(5), +keysChangedThreshold: 100); var exampleProject = builder.AddProject() - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` + + ```typescript title="apphost.mts" twoslash import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -242,6 +298,7 @@ await builder.addNodeApp("api", "./api", "index.js") // After adding all resources, run the app... ``` + @@ -251,8 +308,14 @@ The preceding code adds explicit persistence to the Valkey resource by snapshott When you want to explicitly provide the port and password used by the Valkey container, you can pass them as parameters: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -261,12 +324,15 @@ var password = builder.AddParameter("password", secret: true); var cache = builder.AddValkey("cache", port: 6379, password: password); var exampleProject = builder.AddProject() - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` + + ```typescript title="apphost.mts" twoslash import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -281,6 +347,7 @@ await builder.addNodeApp("api", "./api", "index.js") // After adding all resources, run the app... ``` + @@ -290,26 +357,35 @@ When no `password` parameter is provided, Aspire generates a strong password aut By default, Aspire injects the Valkey connection information using variable names derived from the resource name (for example, `CACHE_URI`, `CACHE_HOST`, `CACHE_PORT`, `CACHE_PASSWORD`). If your consuming app expects a different set of environment variable names, pass individual connection properties from the AppHost: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var cache = builder.AddValkey("cache"); var app = builder.AddExecutable("my-app", "node", "app.js", ".") - .WithReference(cache) - .WithEnvironment(context => - { - context.EnvironmentVariables["VALKEY_HOST"] = cache.Resource.PrimaryEndpoint.Property(EndpointProperty.Host); - context.EnvironmentVariables["VALKEY_PORT"] = cache.Resource.PrimaryEndpoint.Property(EndpointProperty.Port); - context.EnvironmentVariables["VALKEY_PASSWORD"] = cache.Resource.PasswordParameter; - }); +.WithReference(cache) +.WithEnvironment(context => +{ +context.EnvironmentVariables["VALKEY_HOST"] = cache.Resource.PrimaryEndpoint.Property(EndpointProperty.Host); +context.EnvironmentVariables["VALKEY_PORT"] = cache.Resource.PrimaryEndpoint.Property(EndpointProperty.Port); +context.EnvironmentVariables["VALKEY_PASSWORD"] = cache.Resource.PasswordParameter; +}); builder.Build().Run(); + ``` + + ```typescript title="apphost.mts" twoslash import { createBuilder, EndpointProperty } from './.aspire/modules/aspire.mjs'; @@ -328,6 +404,7 @@ await builder.addNodeApp("my-app", "./app", "index.js") await builder.build().run(); ``` + @@ -335,20 +412,29 @@ await builder.build().run(); To reference an externally managed Valkey instance instead of running one as a container, use `AddConnectionString`: - + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); var cache = builder.AddConnectionString("cache"); var exampleProject = builder.AddProject() - .WithReference(cache); +.WithReference(cache); // After adding all resources, run the app... + ``` + + ```typescript title="apphost.mts" import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -362,6 +448,7 @@ await builder.addNodeApp("my-app", "./app", "index.js") // After adding all resources, run the app... await builder.build().run(); ``` + diff --git a/src/frontend/src/content/docs/integrations/cloud/azure/ai-compatibility-matrix.mdx b/src/frontend/src/content/docs/integrations/cloud/azure/ai-compatibility-matrix.mdx index a127d40aa..132864fc9 100644 --- a/src/frontend/src/content/docs/integrations/cloud/azure/ai-compatibility-matrix.mdx +++ b/src/frontend/src/content/docs/integrations/cloud/azure/ai-compatibility-matrix.mdx @@ -24,12 +24,12 @@ Aspire provides several AI hosting and client integrations that enable you to wo The following table shows the compatibility between Aspire AI hosting and client integrations: -| **Hosting Integration** | **Aspire.OpenAI** | **Aspire.Azure.AI.OpenAI** | **Aspire.Azure.AI.Inference** | -|--|--|--|--| -| `Aspire.Hosting.Foundry` | ❌ No | ⚠️ Partial | ✅ Yes (preferred) | -| `Aspire.Hosting.Azure.CognitiveServices` | ❌ No | ✅ Yes (preferred) | ❌ No | -| `Aspire.Hosting.OpenAI` | ✅ Yes (preferred) | ✅ Yes | ❌ No | -| `Aspire.Hosting.GitHub.Models` | ⚠️ Partial | ❌ No | ✅ Yes (preferred) | +| **Hosting Integration** | **Aspire.OpenAI** | **Aspire.Azure.AI.OpenAI** | **Aspire.Azure.AI.Inference** | +| ---------------------------------------- | ------------------ | -------------------------- | ----------------------------- | +| `Aspire.Hosting.Foundry` | ❌ No | ⚠️ Partial | ✅ Yes (preferred) | +| `Aspire.Hosting.Azure.CognitiveServices` | ❌ No | ✅ Yes (preferred) | ❌ No | +| `Aspire.Hosting.OpenAI` | ✅ Yes (preferred) | ✅ Yes | ❌ No | +| `Aspire.Hosting.GitHub.Models` | ⚠️ Partial | ❌ No | ✅ Yes (preferred) | ## Role-based access @@ -463,7 +541,12 @@ Azure Event Hubs uses role-based access control (RBAC). The hosting integration To customise role assignments, call `withRoleAssignments`: - + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -471,11 +554,12 @@ var builder = DistributedApplication.CreateBuilder(args); var eventHubs = builder.AddAzureEventHubs("event-hubs"); builder.AddProject() - .WithReference(eventHubs) - .WithRoleAssignments(eventHubs, AzureEventHubsRole.AzureEventHubsDataSender); +.WithReference(eventHubs) +.WithRoleAssignments(eventHubs, AzureEventHubsRole.AzureEventHubsDataSender); // After adding all resources, run the app... -``` + +```` ```typescript title="apphost.mts" @@ -492,17 +576,18 @@ const api = await builder.addNodeApp("api", "./api", "index.js") await eventHubs.withRoleAssignments(api, [AzureEventHubsRole.AzureEventHubsDataSender]); // After adding all resources, run the app... -``` +```` + The available roles are: -| Role | Description | -| ----------------------------- | ----------- | -| `AzureEventHubsDataOwner` | Full access to Azure Event Hubs resources | -| `AzureEventHubsDataReceiver` | Receive access to Azure Event Hubs resources | -| `AzureEventHubsDataSender` | Send access to Azure Event Hubs resources | +| Role | Description | +| ---------------------------- | -------------------------------------------- | +| `AzureEventHubsDataOwner` | Full access to Azure Event Hubs resources | +| `AzureEventHubsDataReceiver` | Receive access to Azure Event Hubs resources | +| `AzureEventHubsDataSender` | Send access to Azure Event Hubs resources | ## Provisioning-generated Bicep @@ -571,17 +656,22 @@ The generated Bicep is a starting point — customise it through the C# provisio All Aspire Azure resources subclass `AzureProvisioningResource`. The `ConfigureInfrastructure` (or `configureInfrastructure`) API lets you customise the generated Bicep with a fluent callback: - + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); builder.AddAzureEventHubs("event-hubs") - .ConfigureInfrastructure(infra => - { - var eventHubs = infra.GetProvisionableResources() - .OfType() - .Single(); +.ConfigureInfrastructure(infra => +{ +var eventHubs = infra.GetProvisionableResources() +.OfType() +.Single(); eventHubs.Sku = new EventHubsSku() { @@ -592,7 +682,8 @@ builder.AddAzureEventHubs("event-hubs") eventHubs.PublicNetworkAccess = EventHubsPublicNetworkAccess.SecuredByPerimeter; eventHubs.Tags.Add("ExampleKey", "Example value"); }); -``` + +```` ```typescript title="apphost.mts" @@ -606,7 +697,8 @@ await eventHubs.configureInfrastructure(async (infra) => { }); // After adding all resources, run the app... -``` +```` + @@ -628,4 +720,3 @@ For the full reference of Azure Event Hubs connection properties — and how con The Azure Event Hubs hosting integration automatically adds a health check for the Event Hubs resource. The health check verifies that the Event Hubs namespace is running and that a connection can be established to it. The hosting integration relies on the [📦 AspNetCore.HealthChecks.Azure.Messaging.EventHubs](https://www.nuget.org/packages/AspNetCore.HealthChecks.Azure.Messaging.EventHubs) NuGet package. - diff --git a/src/frontend/src/content/docs/integrations/cloud/azure/azure-front-door.mdx b/src/frontend/src/content/docs/integrations/cloud/azure/azure-front-door.mdx index 6ec942548..841427b43 100644 --- a/src/frontend/src/content/docs/integrations/cloud/azure/azure-front-door.mdx +++ b/src/frontend/src/content/docs/integrations/cloud/azure/azure-front-door.mdx @@ -36,7 +36,12 @@ To access this type and APIs, add the [📦 Aspire.Hosting.Azure.FrontDoor](http In your AppHost, call `addAzureFrontDoor` to add a Front Door profile, then call `withOrigin` to attach a backend resource as an origin: - + ```csharp title="AppHost.cs" @@ -62,12 +67,12 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -await builder.addAzureAppServiceEnvironment("production"); +await builder.addAzureAppServiceEnvironment('production'); -const api = await builder.addProject("api", "../Api/Api.csproj"); +const api = await builder.addProject('api', '../Api/Api.csproj'); await api.withExternalHttpEndpoints(); -const frontdoor = await builder.addAzureFrontDoor("frontdoor"); +const frontdoor = await builder.addAzureFrontDoor('frontdoor'); await frontdoor.withOrigin(api); // After adding all resources, run the app... @@ -97,7 +102,12 @@ Each call to `withOrigin` creates a separate Front Door endpoint, origin group, You can add multiple backends to the same Front Door profile. Each origin gets its own Front Door endpoint and route: - + ```csharp title="AppHost.cs" @@ -126,15 +136,15 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -await builder.addAzureAppServiceEnvironment("production"); +await builder.addAzureAppServiceEnvironment('production'); -const api = await builder.addProject("api", "../Api/Api.csproj"); +const api = await builder.addProject('api', '../Api/Api.csproj'); await api.withExternalHttpEndpoints(); -const web = await builder.addProject("web", "../Web/Web.csproj"); +const web = await builder.addProject('web', '../Web/Web.csproj'); await web.withExternalHttpEndpoints(); -const frontdoor = await builder.addAzureFrontDoor("frontdoor"); +const frontdoor = await builder.addAzureFrontDoor('frontdoor'); await frontdoor.withOrigin(api); await frontdoor.withOrigin(web); @@ -155,7 +165,12 @@ Front Door uses health probes to determine which origins are healthy. By default When you publish your app, Aspire generates Bicep alongside the manifest. A Front Door resource with a single origin generates Bicep similar to the following: ```bicep title="Generated Bicep — frontdoor.bicep" @@ -236,7 +251,12 @@ The generated Bicep is a starting point and is influenced by changes to the prov For advanced scenarios such as upgrading to the Premium SKU, attaching a Web Application Firewall (WAF) policy, configuring caching, or tuning routes, use `ConfigureInfrastructure` (`configureInfrastructure` in TypeScript) to modify the generated Bicep model directly: - + ```csharp title="AppHost.cs" @@ -269,17 +289,17 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -await builder.addAzureAppServiceEnvironment("production"); +await builder.addAzureAppServiceEnvironment('production'); -const api = await builder.addProject("api", "../Api/Api.csproj"); +const api = await builder.addProject('api', '../Api/Api.csproj'); await api.withExternalHttpEndpoints(); -const frontdoor = await builder.addAzureFrontDoor("frontdoor"); +const frontdoor = await builder.addAzureFrontDoor('frontdoor'); await frontdoor.withOrigin(api); await frontdoor.configureInfrastructure(async (infra) => { - // Use the AzureResourceInfrastructure API to customize Bicep - // parameters or resources directly. - await infra.addParameter("skuName", "Premium_AzureFrontDoor"); + // Use the AzureResourceInfrastructure API to customize Bicep + // parameters or resources directly. + await infra.addParameter('skuName', 'Premium_AzureFrontDoor'); }); await builder.build().run(); diff --git a/src/frontend/src/content/docs/integrations/cloud/azure/azure-functions/azure-functions-host.mdx b/src/frontend/src/content/docs/integrations/cloud/azure/azure-functions/azure-functions-host.mdx index 5d0217411..2ec683df6 100644 --- a/src/frontend/src/content/docs/integrations/cloud/azure/azure-functions/azure-functions-host.mdx +++ b/src/frontend/src/content/docs/integrations/cloud/azure/azure-functions/azure-functions-host.mdx @@ -42,14 +42,20 @@ If you encounter the error **"There is no Functions runtime available that match Visual Studio: Options / Projects and Solutions / Azure Functions. + alt="Visual Studio: Options / Projects and Solutions / Azure Functions." +/> ::: ## Installation To start building an Aspire app that uses Azure Functions, install the [📦 Aspire.Hosting.Azure.Functions](https://www.nuget.org/packages/Aspire.Hosting.Azure.Functions) NuGet package: - + ```bash title="Terminal" @@ -57,7 +63,8 @@ aspire add azure-functions ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. Or, choose a manual installation approach: @@ -78,7 +85,8 @@ aspire add azure-functions ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. This updates your `aspire.config.json` with the Azure Functions hosting integration package: @@ -104,6 +112,15 @@ There are two ways to add an Azure Functions project in C#, depending on whether If the Azure Functions project is referenced in your C# AppHost project, use the generic overload of `AddAzureFunctionsProject`: + + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -118,11 +135,19 @@ builder.AddProject() builder.Build().Run(); ``` + + + ### Add a Functions project by file path If the Azure Functions project is not referenced in your AppHost project (or you are using a TypeScript AppHost), specify the path to the project file: - + ```csharp title="AppHost.cs" @@ -148,14 +173,15 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); const functions = await builder.addAzureFunctionsProject( - "functions", - "../MyFunctions/MyFunctions.csproj" + 'functions', + '../MyFunctions/MyFunctions.csproj' ); await functions.withExternalHttpEndpoints(); -await builder.addNodeApp("api", "./api", "index.js") - .withReference(functions) - .waitFor(functions); +await builder + .addNodeApp('api', './api', 'index.js') + .withReference(functions) + .waitFor(functions); // After adding all resources, run the app... ``` @@ -174,14 +200,23 @@ await builder.addNodeApp("api", "./api", "index.js") ## Add Azure Functions resource with host storage Azure Functions requires an Azure Storage account as host storage for checkpoints, leases, and other internal state. By default, Aspire creates an implicit host storage resource automatically. To use a specific storage account, call `WithHostStorage` (or `withHostStorage`) on the Azure Functions resource: - + ```csharp title="AppHost.cs" @@ -209,12 +244,12 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const storage = await builder.addAzureStorage("storage"); +const storage = await builder.addAzureStorage('storage'); await storage.runAsEmulator(); const functions = await builder.addAzureFunctionsProject( - "functions", - "../MyFunctions/MyFunctions.csproj" + 'functions', + '../MyFunctions/MyFunctions.csproj' ); await functions.withHostStorage(storage); @@ -236,6 +271,15 @@ If you are not using implicit host storage, you must manually assign the `Storag For production, register the storage account explicitly and assign a minimal set of roles: + + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -247,16 +291,25 @@ builder.AddAzureFunctionsProject("functions") StorageBuiltInRole.StorageQueueDataReader); ``` + + + :::caution[TypeScript gap] `WithRoleAssignments` is available in the C# AppHost only. The TypeScript AppHost does not currently expose an equivalent API for scoped role assignments on Azure Functions resources. ::: + ## Reference resources in Azure Functions To connect Azure Functions triggers and bindings to other Azure resources, chain `WithReference` (or `withReference`) on the Azure Functions project resource: - + ```csharp title="AppHost.cs" @@ -280,13 +333,13 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const storage = await builder.addAzureStorage("storage"); +const storage = await builder.addAzureStorage('storage'); await storage.runAsEmulator(); -const blobs = await storage.addBlobs("blobs"); +const blobs = await storage.addBlobs('blobs'); const functions = await builder.addAzureFunctionsProject( - "functions", - "../MyFunctions/MyFunctions.csproj" + 'functions', + '../MyFunctions/MyFunctions.csproj' ); await functions.withHostStorage(storage); await functions.withReference(blobs); @@ -303,7 +356,12 @@ The connection information required to connect to the `blobs` resource is automa To make HTTP triggers publicly accessible when deployed, call `WithExternalHttpEndpoints` (or `withExternalHttpEndpoints`) on the Azure Functions resource: - + ```csharp title="AppHost.cs" @@ -324,8 +382,8 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); const functions = await builder.addAzureFunctionsProject( - "functions", - "../MyFunctions/MyFunctions.csproj" + 'functions', + '../MyFunctions/MyFunctions.csproj' ); await functions.withExternalHttpEndpoints(); @@ -349,7 +407,12 @@ The `Aspire.Hosting.Azure.Functions` package includes support for [Azure Durable Call `AddDurableTaskScheduler` on the `builder` instance to add a scheduler resource, then call `AddTaskHub` to create a task hub and pass its reference to the Azure Functions project: - + ```csharp title="AppHost.cs" @@ -382,17 +445,17 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const storage = await builder.addAzureStorage("storage"); +const storage = await builder.addAzureStorage('storage'); await storage.runAsEmulator(); -const scheduler = await builder.addDurableTaskScheduler("scheduler"); +const scheduler = await builder.addDurableTaskScheduler('scheduler'); await scheduler.runAsEmulator(); -const taskHub = await scheduler.addTaskHub("taskhub"); +const taskHub = await scheduler.addTaskHub('taskhub'); const functions = await builder.addAzureFunctionsProject( - "functions", - "../MyFunctions/MyFunctions.csproj" + 'functions', + '../MyFunctions/MyFunctions.csproj' ); await functions.withHostStorage(storage); await functions.withReference(taskHub); @@ -416,12 +479,24 @@ When using `RunAsEmulator()`, Aspire starts a local container running the DTS em - A **Task Hub Dashboard** URL on each task hub resource. - A `DTS_TASK_HUB_NAMES` environment variable on the emulator container listing the associated task hub names. - + ### Use an existing scheduler To connect to an already-deployed Durable Task Scheduler instance instead of provisioning a new one, use `RunAsExisting`. The overload accepts either a plain `string` connection string or an `IResourceBuilder` for securely supplying the value at runtime: + + + ```csharp title="AppHost.cs" #pragma warning disable ASPIREDURABLETASK001 @@ -443,8 +518,13 @@ builder.Build().Run(); #pragma warning restore ASPIREDURABLETASK001 ``` + + + ## Deployment diff --git a/src/frontend/src/content/docs/integrations/cloud/azure/azure-key-vault/azure-key-vault-host.mdx b/src/frontend/src/content/docs/integrations/cloud/azure/azure-key-vault/azure-key-vault-host.mdx index 3c28f0d2c..0cc227019 100644 --- a/src/frontend/src/content/docs/integrations/cloud/azure/azure-key-vault/azure-key-vault-host.mdx +++ b/src/frontend/src/content/docs/integrations/cloud/azure/azure-key-vault/azure-key-vault-host.mdx @@ -27,7 +27,12 @@ If you're new to the Azure Key Vault integration, start with the [Get started wi To start building an Aspire app that uses Azure Key Vault, install the [📦 Aspire.Hosting.Azure.KeyVault](https://www.nuget.org/packages/Aspire.Hosting.Azure.KeyVault) NuGet package: - + ```bash title="Terminal" @@ -35,7 +40,8 @@ aspire add azure-key-vault ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. Or, choose a manual installation approach: @@ -56,7 +62,8 @@ aspire add azure-key-vault ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. This updates your `aspire.config.json` with the Azure Key Vault hosting integration package: @@ -76,7 +83,12 @@ This updates your `aspire.config.json` with the Azure Key Vault hosting integrat Once you've installed the hosting integration in your AppHost project, you can add an Azure Key Vault resource as shown in the following examples: - + ```csharp title="AppHost.cs" @@ -99,10 +111,11 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const keyVault = await builder.addAzureKeyVault("key-vault"); +const keyVault = await builder.addAzureKeyVault('key-vault'); -await builder.addProject("apiservice", "../ExampleProject/ExampleProject.csproj") - .withReference(keyVault); +await builder + .addProject('apiservice', '../ExampleProject/ExampleProject.csproj') + .withReference(keyVault); await builder.build().run(); ``` @@ -131,7 +144,12 @@ The `WithReference` (or `withReference`) method configures a connection in the c You might have an existing Azure Key Vault instance that you want to connect to. Chain a call to `AsExisting` (or `asExisting`) to annotate that your resource already exists in Azure: - + ```csharp title="AppHost.cs" @@ -158,19 +176,22 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const existingKeyVaultName = await builder.addParameter("existingKeyVaultName"); +const existingKeyVaultName = await builder.addParameter('existingKeyVaultName'); -const keyVault = await builder.addAzureKeyVault("key-vault"); +const keyVault = await builder.addAzureKeyVault('key-vault'); await keyVault.asExisting(existingKeyVaultName); -await builder.addProject("apiservice", "../ExampleProject/ExampleProject.csproj") - .withReference(keyVault); +await builder + .addProject('apiservice', '../ExampleProject/ExampleProject.csproj') + .withReference(keyVault); await builder.build().run(); ``` @@ -187,7 +208,12 @@ await builder.build().run(); By default, `AddAzureKeyVault` configures a [Key Vault Administrator built-in role](https://learn.microsoft.com/azure/role-based-access-control/built-in-roles/security#key-vault-administrator) for the consuming project. To assign a more restrictive role — such as `KeyVaultSecretsUser` — use `WithRoleAssignments` (or `withRoleAssignments`) on the consuming resource: - + ```csharp title="AppHost.cs" @@ -209,10 +235,15 @@ import { createBuilder, AzureKeyVaultRole } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const keyVault = await builder.addAzureKeyVault("key-vault"); +const keyVault = await builder.addAzureKeyVault('key-vault'); -const api = await builder.addProject("apiservice", "../ExampleProject/ExampleProject.csproj"); -await api.withRoleAssignments(keyVault, [AzureKeyVaultRole.KeyVaultSecretsUser]); +const api = await builder.addProject( + 'apiservice', + '../ExampleProject/ExampleProject.csproj' +); +await api.withRoleAssignments(keyVault, [ + AzureKeyVaultRole.KeyVaultSecretsUser, +]); await builder.build().run(); ``` @@ -230,7 +261,12 @@ You can reference secrets stored in an Azure Key Vault directly from your AppHos To add a secret to the Key Vault resource from the AppHost, call `AddSecret` (or `addSecret`) providing a name and a parameter: - + ```csharp title="AppHost.cs" @@ -253,10 +289,10 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const keyVault = await builder.addAzureKeyVault("key-vault"); +const keyVault = await builder.addAzureKeyVault('key-vault'); -const apiKey = await builder.addParameter("api-key", { secret: true }); -await keyVault.addSecret("my-api-key", apiKey); +const apiKey = await builder.addParameter('api-key', { secret: true }); +await keyVault.addSecret('my-api-key', apiKey); await builder.build().run(); ``` @@ -268,7 +304,12 @@ await builder.build().run(); To reference an existing secret in the vault and pass it to a consuming resource, use `GetSecret` (or `getSecret`): - + ```csharp title="AppHost.cs" @@ -296,16 +337,17 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const existingKeyVaultName = await builder.addParameter("existingKeyVaultName"); +const existingKeyVaultName = await builder.addParameter('existingKeyVaultName'); -const keyVault = await builder.addAzureKeyVault("key-vault"); +const keyVault = await builder.addAzureKeyVault('key-vault'); await keyVault.asExisting(existingKeyVaultName); -const secretRef = await keyVault.getSecret("my-api-key"); +const secretRef = await keyVault.getSecret('my-api-key'); -await builder.addProject("apiservice", "../ExampleProject/ExampleProject.csproj") - .withReference(keyVault) - .withEnvironment("API_KEY", secretRef); +await builder + .addProject('apiservice', '../ExampleProject/ExampleProject.csproj') + .withReference(keyVault) + .withEnvironment('API_KEY', secretRef); await builder.build().run(); ``` @@ -375,7 +417,12 @@ The generated Bicep is a starting point and is influenced by changes to the prov All Aspire Azure resources are subclasses of the `AzureProvisioningResource` type. This type enables the customization of the generated Bicep by providing a fluent API to configure the Azure resources using the `ConfigureInfrastructure` (or `configureInfrastructure`) API: - + ```csharp title="AppHost.cs" @@ -409,15 +456,16 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const keyVault = await builder.addAzureKeyVault("key-vault"); +const keyVault = await builder.addAzureKeyVault('key-vault'); await keyVault.configureInfrastructure(async (infra) => { - const kv = (await infra.getProvisionableResources()) - .filter(r => r.resourceType === 'Microsoft.KeyVault/vaults')[0]; + const kv = (await infra.getProvisionableResources()).filter( + (r) => r.resourceType === 'Microsoft.KeyVault/vaults' + )[0]; - if (kv) { - kv.properties.sku = { family: 'A', name: 'premium' }; - kv.tags['ExampleKey'] = 'Example value'; - } + if (kv) { + kv.properties.sku = { family: 'A', name: 'premium' }; + kv.tags['ExampleKey'] = 'Example value'; + } }); await builder.build().run(); diff --git a/src/frontend/src/content/docs/integrations/cloud/azure/azure-log-analytics.mdx b/src/frontend/src/content/docs/integrations/cloud/azure/azure-log-analytics.mdx index 2c293afb6..b67880e35 100644 --- a/src/frontend/src/content/docs/integrations/cloud/azure/azure-log-analytics.mdx +++ b/src/frontend/src/content/docs/integrations/cloud/azure/azure-log-analytics.mdx @@ -28,7 +28,12 @@ This article is the reference for the Aspire Azure Log Analytics Hosting integra To start building an Aspire app that uses Azure Log Analytics, install the [📦 Aspire.Hosting.Azure.OperationalInsights](https://www.nuget.org/packages/Aspire.Hosting.Azure.OperationalInsights) NuGet package: - + ```bash title="Terminal" @@ -79,7 +84,12 @@ This updates your `aspire.config.json` with the Azure Log Analytics hosting inte The Aspire Azure Log Analytics hosting integration models the Log Analytics workspace as the `AzureLogAnalyticsWorkspaceResource` type. To add a Log Analytics workspace resource to your app host, call `AddAzureLogAnalyticsWorkspace` (or `addAzureLogAnalyticsWorkspace`): - + ```csharp title="AppHost.cs" @@ -124,7 +134,12 @@ The preceding code adds an Azure Log Analytics workspace resource named `log-ana A common pattern is to use a Log Analytics workspace with Application Insights for centralized telemetry collection. You can link an Application Insights resource to a Log Analytics workspace: - + ```csharp title="AppHost.cs" @@ -211,6 +226,15 @@ The generated Bicep is a starting point and is influenced by changes to the prov All Aspire Azure resources are subclasses of the `AzureProvisioningResource` type. This type enables the customization of the generated Bicep by providing a fluent API to configure the Azure resources using the `ConfigureInfrastructure` API. For example, you can configure the SKU, retention period, and more. The following example demonstrates how to customize the Azure Log Analytics workspace: + + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -230,11 +254,15 @@ var logAnalytics = builder.AddAzureLogAnalyticsWorkspace("log-analytics") var appInsights = builder.AddAzureApplicationInsights("app-insights", logAnalytics); ``` + + + The preceding code: diff --git a/src/frontend/src/content/docs/integrations/cloud/azure/azure-openai/azure-openai-host.mdx b/src/frontend/src/content/docs/integrations/cloud/azure/azure-openai/azure-openai-host.mdx index 57525012f..120e92780 100644 --- a/src/frontend/src/content/docs/integrations/cloud/azure/azure-openai/azure-openai-host.mdx +++ b/src/frontend/src/content/docs/integrations/cloud/azure/azure-openai/azure-openai-host.mdx @@ -27,7 +27,12 @@ If you're new to the Azure OpenAI integration, start with the [Get started with To start building an Aspire app that uses Azure OpenAI, install the [📦 Aspire.Hosting.Azure.CognitiveServices](https://www.nuget.org/packages/Aspire.Hosting.Azure.CognitiveServices) NuGet package: - + ```bash title="Terminal" @@ -35,7 +40,8 @@ aspire add azure-cognitive-services ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. Or, choose a manual installation approach: @@ -56,7 +62,8 @@ aspire add azure-cognitive-services ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. This updates your `aspire.config.json` with the Azure OpenAI hosting integration package: @@ -76,7 +83,12 @@ This updates your `aspire.config.json` with the Azure OpenAI hosting integration Once you've installed the hosting integration in your AppHost project, you can add an Azure OpenAI account resource and then add one or more deployment resources beneath it: - + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -84,16 +96,17 @@ var builder = DistributedApplication.CreateBuilder(args); var openai = builder.AddAzureOpenAI("openai"); var chat = openai.AddDeployment( - name: "chat", - modelName: "gpt-4o", - modelVersion: "2024-08-06"); +name: "chat", +modelName: "gpt-4o", +modelVersion: "2024-08-06"); builder.AddProject("apiservice") - .WithReference(chat) - .WaitFor(chat); +.WithReference(chat) +.WaitFor(chat); // After adding all resources, run the app... -``` + +```` ```typescript title="apphost.mts" twoslash @@ -110,7 +123,8 @@ await builder.addNodeApp("api", "./api", "index.js") .waitFor(chat); // After adding all resources, run the app... -``` +```` + @@ -133,14 +147,23 @@ await builder.addNodeApp("api", "./api", "index.js") ## Add multiple Azure OpenAI deployments Add multiple deployment children beneath the same account to share a single Azure OpenAI resource: - + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -151,13 +174,14 @@ var chat = openai.AddDeployment("chat", "gpt-4o", "2024-08-06"); var embeddings = openai.AddDeployment("embeddings", "text-embedding-3-small", "1"); builder.AddProject("apiservice") - .WithReference(chat) - .WithReference(embeddings) - .WaitFor(chat) - .WaitFor(embeddings); +.WithReference(chat) +.WithReference(embeddings) +.WaitFor(chat) +.WaitFor(embeddings); // After adding all resources, run the app... -``` + +```` ```typescript title="apphost.mts" twoslash @@ -177,7 +201,8 @@ await builder.addNodeApp("api", "./api", "index.js") .waitFor(embeddings); // After adding all resources, run the app... -``` +```` + @@ -189,7 +214,12 @@ By default, Aspire provisions Azure OpenAI with `disableLocalAuth: true` and aut To explicitly assign roles to a consuming app (for example, to grant contributor access for fine-tuning scenarios), call `WithRoleAssignments` in C# or `withCognitiveServicesRoleAssignments` in TypeScript on the consuming resource: - + ```csharp title="AppHost.cs" using Aspire.Hosting.Azure; @@ -201,12 +231,13 @@ var openai = builder.AddAzureOpenAI("openai"); var chat = openai.AddDeployment("chat", "gpt-4o", "2024-08-06"); builder.AddProject("apiservice") - .WithReference(chat) - .WaitFor(chat) - .WithRoleAssignments(openai, AzureOpenAIRole.CognitiveServicesOpenAIContributor); +.WithReference(chat) +.WaitFor(chat) +.WithRoleAssignments(openai, AzureOpenAIRole.CognitiveServicesOpenAIContributor); // After adding all resources, run the app... -``` + +```` ```typescript title="apphost.mts" twoslash @@ -224,21 +255,27 @@ await builder.addNodeApp("api", "./api", "index.js") .withCognitiveServicesRoleAssignments(openai, [AzureOpenAIRole.CognitiveServicesOpenAIContributor]); // After adding all resources, run the app... -``` +```` + The available `AzureOpenAIRole` values are: -| Role | Description | -| ---- | ----------- | -| `CognitiveServicesOpenAIUser` | Read access to models, deployments, and completions. Default when using `WithReference`. | -| `CognitiveServicesOpenAIContributor` | Create and delete deployments in addition to user permissions. | -| `CognitiveServicesUser` | Broader Cognitive Services access. | +| Role | Description | +| ------------------------------------ | ---------------------------------------------------------------------------------------- | +| `CognitiveServicesOpenAIUser` | Read access to models, deployments, and completions. Default when using `WithReference`. | +| `CognitiveServicesOpenAIContributor` | Create and delete deployments in addition to user permissions. | +| `CognitiveServicesUser` | Broader Cognitive Services access. | To remove the default automatic role assignments and manage them entirely yourself, call `ClearDefaultRoleAssignments` (or `clearDefaultRoleAssignments`) on the Azure OpenAI resource: - + ```csharp title="AppHost.cs" var openai = builder.AddAzureOpenAI("openai") @@ -253,7 +290,8 @@ const builder = await createBuilder(); const openai = await builder.addAzureOpenAI("openai"); await openai.clearDefaultRoleAssignments(); -``` + +```` @@ -261,7 +299,12 @@ await openai.clearDefaultRoleAssignments(); You might have an already-deployed Azure OpenAI account in your Azure subscription that you want to connect to. Use `AsExisting` (or `asExisting`) to point the resource at an existing account instead of provisioning a new one: - + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -279,7 +322,8 @@ builder.AddProject("apiservice") .WaitFor(chat); // After adding all resources, run the app... -``` +```` + ```typescript title="apphost.mts" twoslash @@ -296,11 +340,12 @@ await openai.asExisting(existingOpenAIName, existingOpenAIResourceGroup); const chat = await openai.addDeployment("chat", "gpt-4o", "2024-08-06"); await builder.addNodeApp("api", "./api", "index.js") - .withReference(chat) - .waitFor(chat); +.withReference(chat) +.waitFor(chat); // After adding all resources, run the app... -``` + +```` @@ -354,7 +399,7 @@ resource chat 'Microsoft.CognitiveServices/accounts/deployments@2024-10-01' = { output connectionString string = 'Endpoint=${openai.properties.endpoint}' output name string = openai.name -``` +```` Role assignments are created in a companion module: @@ -389,7 +434,12 @@ The generated Bicep is a starting point and is influenced by changes to the prov All Aspire Azure resources are subclasses of `AzureProvisioningResource`. This enables customization of the generated Bicep by providing a fluent API to configure Azure resources using the `ConfigureInfrastructure` API: - + ```csharp title="AppHost.cs" using Azure.Provisioning.CognitiveServices; @@ -397,10 +447,10 @@ using Azure.Provisioning.CognitiveServices; var builder = DistributedApplication.CreateBuilder(args); builder.AddAzureOpenAI("openai") - .ConfigureInfrastructure(infra => - { - var resources = infra.GetProvisionableResources(); - var account = resources.OfType().Single(); +.ConfigureInfrastructure(infra => +{ +var resources = infra.GetProvisionableResources(); +var account = resources.OfType().Single(); account.Sku = new CognitiveServicesSku { @@ -411,7 +461,8 @@ builder.AddAzureOpenAI("openai") }); // After adding all resources, run the app... -``` + +```` ```typescript title="apphost.mts" twoslash @@ -427,7 +478,8 @@ await openai.configureInfrastructure(async infra => { }); // After adding all resources, run the app... -``` +```` + @@ -443,13 +495,13 @@ The preceding C# code: Common model identifiers for Azure OpenAI: -| Category | Model identifiers | -| ---------- | ----------------- | -| Chat | `gpt-4o`, `gpt-4o-mini`, `gpt-4-turbo` | -| Reasoning | `o3`, `o3-mini`, `o4-mini` | +| Category | Model identifiers | +| ---------- | -------------------------------------------------- | +| Chat | `gpt-4o`, `gpt-4o-mini`, `gpt-4-turbo` | +| Reasoning | `o3`, `o3-mini`, `o4-mini` | | Embeddings | `text-embedding-3-small`, `text-embedding-3-large` | -| Images | `dall-e-3` | -| Audio | `whisper` | +| Images | `dall-e-3` | +| Audio | `whisper` | For the full list and current model versions, see the [Azure OpenAI models documentation](https://learn.microsoft.com/azure/ai-services/openai/concepts/models). @@ -462,4 +514,4 @@ For the full reference of Azure OpenAI connection properties — and how consumi - [Get started with the Azure OpenAI integrations](/integrations/cloud/azure/azure-openai/azure-openai-get-started/) - [Connect to Azure OpenAI](/integrations/cloud/azure/azure-openai/azure-openai-connect/) - [Azure OpenAI Service documentation](https://learn.microsoft.com/azure/ai-services/openai/) -- [Local provisioning: Configuration](/integrations/cloud/azure/local-provisioning/#configuration) \ No newline at end of file +- [Local provisioning: Configuration](/integrations/cloud/azure/local-provisioning/#configuration) diff --git a/src/frontend/src/content/docs/integrations/cloud/azure/azure-postgresql/azure-postgresql-host.mdx b/src/frontend/src/content/docs/integrations/cloud/azure/azure-postgresql/azure-postgresql-host.mdx index fbe48ffe9..422ef5f73 100644 --- a/src/frontend/src/content/docs/integrations/cloud/azure/azure-postgresql/azure-postgresql-host.mdx +++ b/src/frontend/src/content/docs/integrations/cloud/azure/azure-postgresql/azure-postgresql-host.mdx @@ -27,7 +27,12 @@ If you're new to the Azure PostgreSQL integration, start with the [Get started w To start building an Aspire app that uses Azure Database for PostgreSQL, install the [📦 Aspire.Hosting.Azure.PostgreSQL](https://www.nuget.org/packages/Aspire.Hosting.Azure.PostgreSQL) NuGet package: - + ```bash title="Terminal" @@ -78,7 +83,12 @@ This updates your `aspire.config.json` with the Azure PostgreSQL hosting integra Once you've installed the hosting integration in your AppHost project, you can add a PostgreSQL flexible server resource and then add a database resource: - + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -138,7 +148,12 @@ The preceding code adds an Azure PostgreSQL flexible server resource named `post You can add multiple named databases to the same flexible server resource: - + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -185,7 +200,12 @@ await builder.addNodeApp("orders", "./orders", "index.js") You can also customize the underlying database name (as distinct from the Aspire resource name) by passing `databaseName` in the options: - + ```csharp title="AppHost.cs" var postgresdb = postgres.AddDatabase("postgresdb", databaseName: "app_catalog"); @@ -202,7 +222,12 @@ const postgresdb = await postgres.addDatabase("postgresdb", { databaseName: "app The Azure PostgreSQL hosting integration supports running the PostgreSQL server as a local Docker container. This is beneficial for local development and testing — you get a real PostgreSQL server without needing an Azure subscription or connection to an existing Azure PostgreSQL instance. - + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -264,7 +289,12 @@ For a comparison of the two hosting integrations, see [PostgreSQL Hosting integr If you have an existing Azure Database for PostgreSQL Flexible Server that you want to connect to rather than provisioning a new one, use `AsExisting` / `asExisting`: - + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -311,7 +341,12 @@ For more information on treating Azure resources as existing, see [Use existing By default, the Azure PostgreSQL flexible server is configured to use [Microsoft Entra ID](https://learn.microsoft.com/azure/postgresql/flexible-server/concepts-azure-ad-authentication) authentication — no username or password is stored in your app configuration. If you need password authentication (for example, to connect with a legacy client that doesn't support Entra tokens), call `WithPasswordAuthentication` / `withPasswordAuthentication`: - + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -454,6 +489,15 @@ The generated Bicep is a starting point and is influenced by changes to the prov All Aspire Azure resources are subclasses of the `AzureProvisioningResource` type. This type enables the customization of the generated Bicep by providing a fluent API to configure the Azure resources using the `ConfigureInfrastructure` API: + + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -481,11 +525,15 @@ builder.AddAzurePostgresFlexibleServer("postgres") builder.Build().Run(); ``` + + + The preceding code: diff --git a/src/frontend/src/content/docs/integrations/cloud/azure/azure-service-bus/azure-service-bus-host.mdx b/src/frontend/src/content/docs/integrations/cloud/azure/azure-service-bus/azure-service-bus-host.mdx index 97513cf12..7357b9c01 100644 --- a/src/frontend/src/content/docs/integrations/cloud/azure/azure-service-bus/azure-service-bus-host.mdx +++ b/src/frontend/src/content/docs/integrations/cloud/azure/azure-service-bus/azure-service-bus-host.mdx @@ -36,7 +36,12 @@ The following resource types are available in the hosting integration: To start building an Aspire app that uses Azure Service Bus, install the [📦 Aspire.Hosting.Azure.ServiceBus](https://www.nuget.org/packages/Aspire.Hosting.Azure.ServiceBus) NuGet package: - + ```bash title="Terminal" @@ -44,7 +49,8 @@ aspire add azure-service-bus ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. Or, choose a manual installation approach: @@ -65,7 +71,8 @@ aspire add azure-service-bus ``` - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. This updates your `aspire.config.json` with the Azure Service Bus hosting integration package: @@ -85,7 +92,12 @@ This updates your `aspire.config.json` with the Azure Service Bus hosting integr Once you've installed the hosting integration in your AppHost project, add an Azure Service Bus namespace resource: - + ```csharp title="AppHost.cs" @@ -105,7 +117,7 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const serviceBus = await builder.addAzureServiceBus("messaging"); +const serviceBus = await builder.addAzureServiceBus('messaging'); await builder.build().run(); ``` @@ -118,14 +130,15 @@ await builder.build().run(); it implicitly calls `AddAzureProvisioning`—which adds support for generating Azure resources dynamically during app startup. The app must configure the appropriate subscription and location. For more information, see [Local - provisioning: Configuration](/integrations/cloud/azure/local-provisioning/#configuration). + provisioning: + Configuration](/integrations/cloud/azure/local-provisioning/#configuration). @@ -133,7 +146,12 @@ await builder.build().run(); If you have an existing Azure Service Bus namespace, chain a call to `AsExisting` (C#) or `asExisting` (TypeScript) to connect to it instead of provisioning a new one: - + ```csharp title="AppHost.cs" @@ -160,14 +178,20 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const existingServiceBusName = await builder.addParameter("existingServiceBusName"); -const existingServiceBusResourceGroup = await builder.addParameter("existingServiceBusResourceGroup"); +const existingServiceBusName = await builder.addParameter( + 'existingServiceBusName' +); +const existingServiceBusResourceGroup = await builder.addParameter( + 'existingServiceBusResourceGroup' +); -const serviceBus = await builder.addAzureServiceBus("messaging") - .asExisting(existingServiceBusName, { resourceGroup: existingServiceBusResourceGroup }); +const serviceBus = await builder + .addAzureServiceBus('messaging') + .asExisting(existingServiceBusName, { + resourceGroup: existingServiceBusResourceGroup, + }); -await builder.addNodeApp("web", "./web", "index.js") - .withReference(serviceBus); +await builder.addNodeApp('web', './web', 'index.js').withReference(serviceBus); await builder.build().run(); ``` @@ -182,14 +206,20 @@ For more information on treating Azure resources as existing resources, see [Use you can add a connection string directly to the AppHost. This approach is weakly-typed and doesn't work with role assignments or infrastructure customizations. For more information, see [Add existing Azure resources with - connection strings](/integrations/cloud/azure/overview/#add-existing-azure-resources-with-connection-strings). + connection + strings](/integrations/cloud/azure/overview/#add-existing-azure-resources-with-connection-strings). ## Add Azure Service Bus queue To add a queue to an Azure Service Bus namespace, call `AddServiceBusQueue` (C#) or `addServiceBusQueue` (TypeScript) on the Service Bus resource builder: - + ```csharp title="AppHost.cs" @@ -213,11 +243,10 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const serviceBus = await builder.addAzureServiceBus("messaging"); -const queue = await serviceBus.addServiceBusQueue("queue"); +const serviceBus = await builder.addAzureServiceBus('messaging'); +const queue = await serviceBus.addServiceBusQueue('queue'); -await builder.addNodeApp("api", "./api", "index.js") - .withReference(queue); +await builder.addNodeApp('api', './api', 'index.js').withReference(queue); await builder.build().run(); ``` @@ -231,7 +260,12 @@ This expresses an explicit parent-child relationship between the `messaging` Ser To add a topic, call `AddServiceBusTopic` (C#) or `addServiceBusTopic` (TypeScript) on the Service Bus resource builder: - + ```csharp title="AppHost.cs" @@ -252,8 +286,8 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const serviceBus = await builder.addAzureServiceBus("messaging"); -const topic = await serviceBus.addServiceBusTopic("topic"); +const serviceBus = await builder.addAzureServiceBus('messaging'); +const topic = await serviceBus.addServiceBusTopic('topic'); await builder.build().run(); ``` @@ -267,7 +301,12 @@ The topic is created in the namespace that the `AzureServiceBusResource` represe To add a subscription for a topic, call `AddServiceBusSubscription` (C#) or `addServiceBusSubscription` (TypeScript) on the topic resource builder: - + ```csharp title="AppHost.cs" @@ -289,9 +328,9 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const serviceBus = await builder.addAzureServiceBus("messaging"); -const topic = await serviceBus.addServiceBusTopic("topic"); -await topic.addServiceBusSubscription("sub1"); +const serviceBus = await builder.addAzureServiceBus('messaging'); +const topic = await serviceBus.addServiceBusTopic('topic'); +await topic.addServiceBusSubscription('sub1'); await builder.build().run(); ``` @@ -305,6 +344,15 @@ For more information, see [Queues, topics, and subscriptions in Azure Service Bu In C# AppHosts, you can configure advanced subscription properties — such as maximum delivery count and correlation filter rules — using the `WithProperties` method: + + + ```csharp title="AppHost.cs" using Aspire.Hosting.Azure; @@ -337,6 +385,9 @@ topic.AddServiceBusSubscription("sub1") builder.Build().Run(); ``` + + +