diff --git a/docs/content/concepts/compute-extensibility/index.md b/docs/content/concepts/compute-extensibility/index.md new file mode 100644 index 000000000..4dc11d986 --- /dev/null +++ b/docs/content/concepts/compute-extensibility/index.md @@ -0,0 +1,121 @@ +--- +type: docs +title: "Compute extensibility concepts" +linkTitle: "Compute extensibility" +description: "Understand the compute extensibility model in Radius and how it changes the way platforms, environments, recipes, and applications are composed" +weight: 25 +--- + +Compute extensibility is the evolution of the Radius architecture that removes the previous hard-coded coupling between Radius and a specific compute platform (Kubernetes). With compute extensibility, the compute platform itself — Kubernetes today, but other platforms in the future — is modeled as a Radius Resource Type that platform engineers select, configure, and back with Recipes, exactly like every other resource in Radius. + +This page describes the new model conceptually. For step-by-step migration from the legacy architecture, see the [migration guide]({{< ref "guides/operations/migration" >}}). + +## What changed and why + +Before compute extensibility, the *compute* in `Environment.properties.compute` was a special, built-in field with hard-coded support for `kubernetes`. Containers were modeled by the built-in `Applications.Core/containers` Resource Type and were always rendered into Kubernetes objects by the Application RP. Adding a new compute platform required changes to Radius itself. + +With compute extensibility: + +- **Compute platforms are Resource Types.** Compute resources (for example, `Radius.Compute/containers`, `Radius.Compute/gateways`, `Radius.Compute/secretStores`) are user-resolvable Resource Types with Recipes — they are not hard-coded into Radius. A platform engineer can swap or extend the compute implementation by registering a different Recipe. +- **The Environment is decomposed.** Configuration that previously lived inside a single, monolithic `Environment.properties.recipes` and `Environment.properties.recipeConfig` is now factored into dedicated, independently-managed resources: **Recipe Packs**, **BicepSettings**, and **TerraformSettings**. Environments reference these resources by ID. +- **A new resource namespace.** New, extensible resource types live under the `Radius.*` namespace (for example `Radius.Core/environments`, `Radius.Core/recipePacks`, `Radius.Compute/containers`). The legacy `Applications.*` namespace remains while users migrate. + +The result is a smaller, more pluggable core and a much cleaner separation between *what* a Resource Type is and *how* it is implemented. + +## The new building blocks + +### Resource Types in `Radius.Compute` + +Compute resources used by application developers — containers, gateways, secret stores, volumes — now live under `Radius.Compute/*`. Each of them is a Resource Type with the same authoring model as any other Recipe-backed Resource Type. See the [Resource Types concept page]({{< ref "concepts/resource-types" >}}) for the general model and the [resource-types-contrib](https://github.com/radius-project/resource-types-contrib) repository for reference implementations. + +### Recipe Packs + +A **Recipe Pack** is a reusable, named collection of Recipe assignments that can be referenced by one or more Environments. Recipe Packs let platform engineers manage the mapping of *Resource Type → Recipe* in a single place and reuse it across many Environments instead of repeating the entire `recipes` map per Environment. + +```bicep +resource computeRecipePack 'Radius.Core/recipePacks@2025-08-01-preview' = { + name: 'kubernetes-compute' + properties: { + recipes: { + 'Radius.Compute/containers': { + default: { + recipeKind: 'bicep' + recipeLocation: 'ghcr.io/myorg/recipes/container:1.0.0' + } + } + 'Radius.Compute/gateways': { + default: { + recipeKind: 'terraform' + recipeLocation: 'git::https://github.com/myorg/recipes//gateway?ref=v1.0.0' + } + } + } + } +} +``` + +See the [Recipe Packs concept page]({{< ref "concepts/recipe-packs" >}}) and the [Recipe Packs how-to guide]({{< ref "guides/recipes/recipe-packs" >}}) for details. + +### BicepSettings and TerraformSettings + +Settings that previously lived inside `Environment.properties.recipeConfig` are now first-class resources: + +- **`Radius.Core/bicepSettings`** holds OCI registry authentication for private Bicep registries. It replaces `Environment.properties.recipeConfig.bicep.authentication`. See the [BicepSettings how-to guide]({{< ref "guides/recipes/howto-bicep-settings" >}}). +- **`Radius.Core/terraformSettings`** holds the Terraform CLI configuration (`terraformrc`), backend configuration, and process environment variables. It replaces `Environment.properties.recipeConfig.terraform.*`. See the [TerraformSettings how-to guide]({{< ref "guides/recipes/howto-terraform-settings" >}}). + +Environments reference these resources by ID: + +```bicep +resource myEnvironment 'Radius.Core/environments@2025-08-01-preview' = { + name: 'myEnvironment' + properties: { + recipePacks: [computeRecipePack.id] + bicepSettings: myBicepSettings.id + terraformSettings: myTerraformSettings.id + } +} +``` + +### Terraform is platform-engineer-managed + +Radius no longer downloads the Terraform binary on demand. Platform engineers explicitly install Terraform into the Radius control plane with `rad terraform install` and upgrade or remove it with the same command family. This puts Terraform versioning, mirror selection, and lifecycle in the platform engineer's control. See the [TerraformSettings how-to guide]({{< ref "guides/recipes/howto-terraform-settings" >}}). + +## How the pieces fit together + +```text + ┌──────────────────────┐ + │ Radius.Core/ │ + │ environments │ + └──────────┬───────────┘ + │ references + ┌──────────────────────┼──────────────────────┐ + │ │ │ + ▼ ▼ ▼ +┌───────────────┐ ┌────────────────────┐ ┌─────────────────────┐ +│ recipePacks[] │ │ bicepSettings │ │ terraformSettings │ +│ (one or many) │ │ (private OCI auth)│ │ (CLI / backend / │ +└──────┬────────┘ └────────────────────┘ │ provider creds) │ + │ recipes for └─────────────────────┘ + ▼ Resource Types +┌─────────────────────────────────────────────────────────────────┐ +│ Radius.Compute/containers, gateways, secretStores, volumes … │ +│ (and any other Resource Types defined by platform engineers) │ +└─────────────────────────────────────────────────────────────────┘ +``` + +When a developer deploys an Application, Radius: + +1. Looks up the Resource Type referenced by each resource in the Application. +2. Finds the matching Recipe by walking the Environment's referenced Recipe Packs. +3. Applies any BicepSettings / TerraformSettings the Environment references when invoking the Bicep or Terraform CLI. +4. Returns the Recipe `result` outputs to Radius, which populates the resource's read-only properties. + +## Status and stability + +The compute extensibility resources use the `2025-08-01-preview` API version. Schemas and behavior may continue to evolve until the APIs are promoted to stable. Track the in-flight design notes under [`radius/eng/design-notes/extensibility`](https://github.com/radius-project/radius/tree/main/eng/design-notes/extensibility) and the related [Terraform and Bicep settings feature spec](https://github.com/radius-project/design-notes/blob/main/features/2025-08-14-terraform-bicep-settings.md). + +## Next steps + +- Read the [Recipe Packs concept page]({{< ref "concepts/recipe-packs" >}}) +- Follow the [migration guide]({{< ref "guides/operations/migration" >}}) to move an existing solution to the new model +- Review [breaking changes]({{< ref "guides/operations/migration/breaking-changes" >}}) diff --git a/docs/content/concepts/recipe-packs/index.md b/docs/content/concepts/recipe-packs/index.md new file mode 100644 index 000000000..af724bcc1 --- /dev/null +++ b/docs/content/concepts/recipe-packs/index.md @@ -0,0 +1,82 @@ +--- +type: docs +title: "Recipe Packs concepts" +linkTitle: "Recipe Packs" +description: "Group, share, and version sets of Recipe assignments using Recipe Packs" +weight: 30 +--- + +A **Recipe Pack** is a named, reusable bundle of Recipe assignments (Resource Type → Recipe). Recipe Packs are part of the [compute extensibility]({{< ref "concepts/compute-extensibility" >}}) model and are the recommended way to manage Recipes at scale. + +## Why Recipe Packs + +Before Recipe Packs, every Environment carried its own complete `recipes` map. Two Environments that should expose the same set of databases, queues, and containers had to duplicate the entire map, and a change to a single Recipe location required updating every Environment that used it. + +Recipe Packs solve this by: + +- **Decoupling Recipe selection from Environments.** A Recipe Pack is an independently-deployed resource that can be referenced by many Environments. +- **Letting platforms be composed.** An Environment can reference multiple Recipe Packs — for example, a `kubernetes-compute` pack plus an `aws-data-services` pack — instead of redefining everything in one place. +- **Making upgrades atomic.** Updating the Recipe for a Resource Type in one Recipe Pack flows to every Environment that references that pack on its next deployment. + +## Anatomy of a Recipe Pack + +```bicep +resource awsDataServices 'Radius.Core/recipePacks@2025-08-01-preview' = { + name: 'aws-data-services' + properties: { + recipes: { + 'Radius.Data/postgreSql': { + default: { + recipeKind: 'terraform' + recipeLocation: 'git::https://github.com/myorg/recipes//aws-postgres?ref=v1.2.0' + parameters: { + instanceClass: 'db.t3.medium' + } + } + } + 'Radius.Messaging/rabbitMQ': { + default: { + recipeKind: 'bicep' + recipeLocation: 'ghcr.io/myorg/recipes/rabbitmq:1.0.0' + } + } + } + } +} +``` + +A Recipe Pack contains, per Resource Type, one or more **named** Recipe entries (`default` is conventional). Each entry specifies: + +| Field | Description | +|------------------|-----------------------------------------------------------------------------| +| `recipeKind` | `bicep` or `terraform`. | +| `recipeLocation` | The OCI image reference (Bicep) or Git/module source (Terraform). | +| `parameters` | Optional Recipe parameters that should be passed when this Recipe is run. | + +## Referencing Recipe Packs from Environments + +```bicep +resource myEnvironment 'Radius.Core/environments@2025-08-01-preview' = { + name: 'production-east' + properties: { + recipePacks: [ + kubernetesCompute.id + awsDataServices.id + ] + } +} +``` + +If two Recipe Packs both define a Recipe for the same Resource Type and name, the **later entry in the `recipePacks` array wins**. Order packs with the most-specific overrides last. + +## How Recipe Packs interact with BicepSettings and TerraformSettings + +Recipe Packs only describe *which* Recipe to run for a Resource Type. *How* the Recipe is fetched and executed — private registry credentials, Terraform provider mirrors, backend state — is described by the [BicepSettings]({{< ref "guides/recipes/howto-bicep-settings" >}}) and [TerraformSettings]({{< ref "guides/recipes/howto-terraform-settings" >}}) resources that the Environment references. + +This separation lets the same Recipe Pack be reused across Environments that pull from different registries or use different Terraform backends. + +## Next steps + +- Author a Recipe Pack with the [Recipe Packs how-to guide]({{< ref "guides/recipes/recipe-packs" >}}) +- Configure private Bicep registries with [BicepSettings]({{< ref "guides/recipes/howto-bicep-settings" >}}) +- Configure Terraform with [TerraformSettings]({{< ref "guides/recipes/howto-terraform-settings" >}}) diff --git a/docs/content/guides/operations/migration/_index.md b/docs/content/guides/operations/migration/_index.md new file mode 100644 index 000000000..4c70a778c --- /dev/null +++ b/docs/content/guides/operations/migration/_index.md @@ -0,0 +1,264 @@ +--- +type: docs +title: "Migrating to compute extensibility" +linkTitle: "Migration guide" +description: "Step-by-step guide for migrating an existing Radius solution from the legacy architecture to the compute extensibility model" +weight: 700 +--- + +This guide walks platform engineers and application authors through migrating an existing Radius solution from the legacy architecture (where compute was hard-coded to Kubernetes and Recipes/registry settings were embedded inside `Environment.properties.recipeConfig`) to the new [compute extensibility]({{< ref "concepts/compute-extensibility" >}}) model. + +> Read [Compute extensibility concepts]({{< ref "concepts/compute-extensibility" >}}) and [Recipe Packs concepts]({{< ref "concepts/recipe-packs" >}}) before working through the migration. + +## What is changing + +| Concern | Legacy | New (compute extensibility) | +|-----------------------------------------------|------------------------------------------------------------|------------------------------------------------------------------------| +| Container, gateway, secret store Resource Types | Built into Radius (`Applications.Core/containers`, etc.) | Recipe-backed Resource Types (`Radius.Compute/containers`, etc.) | +| Mapping Resource Type → Recipe | `Environment.properties.recipes` | `Radius.Core/recipePacks` referenced by the Environment | +| Private Bicep registry authentication | `Environment.properties.recipeConfig.bicep.authentication` | `Radius.Core/bicepSettings` | +| Terraform CLI / backend / credentials | `Environment.properties.recipeConfig.terraform.*` | `Radius.Core/terraformSettings` | +| Terraform binary lifecycle | Auto-downloaded by Application RP | `rad terraform install` / `rad terraform uninstall` | +| Custom Terraform provider credentials | `recipeConfig.terraform.providers` map | Recipe parameters that reference `Radius.Security/secrets` values | +| API namespace | `Applications.*` | `Radius.*` (Core, Compute, Data, Messaging, Security, …) | +| API version | `2023-10-01-preview` | `2025-08-01-preview` | + +For the complete list, see [Breaking changes]({{< ref "breaking-changes" >}}). + +## Recommended migration order + +1. **Inventory.** List the Environments, Applications, Recipes, and Secrets currently in use. Note any private registries, custom Terraform providers, and non-default Terraform configuration (mirrors, backends, env vars). +2. **Install Terraform** into the Radius control plane with `rad terraform install` so Terraform Recipes continue to execute after the auto-download is removed. +3. **Author Recipe Packs** that mirror the `recipes` block of each existing Environment. +4. **Author BicepSettings / TerraformSettings** that mirror each existing Environment's `recipeConfig`. +5. **Re-author each Environment** to reference the new Recipe Packs and Settings resources, using the `Radius.Core/environments@2025-08-01-preview` API. +6. **Update Applications** to use the new `Radius.Compute/*` (and other `Radius.*`) Resource Types. +7. **Validate** by deploying to a non-production Environment first, then rolling forward. + +## Before / after: a Bicep Environment with private registry and Terraform settings + +### Before (legacy) + +```bicep +resource registrySecrets 'Applications.Core/secretStores@2023-10-01-preview' = { + name: 'registry-secrets' + properties: { + resource: 'registry-secrets/ecr' + type: 'awsIRSA' + data: { + roleARN: { value: 'arn:aws:iam::123456789012:role/radius-ecr-pull' } + } + } +} + +resource env 'Applications.Core/environments@2023-10-01-preview' = { + name: 'my-env' + properties: { + compute: { + kind: 'kubernetes' + namespace: 'my-namespace' + } + recipeConfig: { + bicep: { + authentication: { + '123456789012.dkr.ecr.us-east-1.amazonaws.com': { + secret: registrySecrets.id + } + } + } + terraform: { + authentication: { + git: { + pat: { + 'github.com': { secret: gitSecret.id } + } + } + } + } + env: { + TF_LOG: 'INFO' + } + } + recipes: { + 'Applications.Datastores/redisCaches': { + default: { + templateKind: 'terraform' + templatePath: 'git::https://github.com/myorg/recipes//redis?ref=v1.0.0' + } + } + 'Applications.Messaging/rabbitMQQueues': { + default: { + templateKind: 'bicep' + templatePath: '123456789012.dkr.ecr.us-east-1.amazonaws.com/recipes/rabbitmq:1.0.0' + } + } + } + } +} +``` + +### After (compute extensibility) + +```bicep +// 1. Secrets — same idea, new namespace and API version. +resource gitSecret 'Radius.Security/secrets@2025-08-01-preview' = { + name: 'git-pat' + properties: { + data: { + token: { value: '' } + } + } +} + +// 2. BicepSettings replaces recipeConfig.bicep.authentication. +resource myBicepSettings 'Radius.Core/bicepSettings@2025-08-01-preview' = { + name: 'my-bicep-settings' + properties: { + registryAuthentication: { + authenticationMethod: 'AwsIrsa' + awsIamRoleArn: 'arn:aws:iam::123456789012:role/radius-ecr-pull' + } + } +} + +// 3. TerraformSettings replaces recipeConfig.terraform.* and recipeConfig.env. +resource myTerraformSettings 'Radius.Core/terraformSettings@2025-08-01-preview' = { + name: 'my-terraform-settings' + properties: { + terraformrc: { + credentials: [ + { + host: 'github.com' + secret: gitSecret.id + } + ] + } + env: { + TF_LOG: 'INFO' + } + } +} + +// 4. Recipe Pack replaces the inline `recipes` map and uses the Radius.* types. +resource myRecipePack 'Radius.Core/recipePacks@2025-08-01-preview' = { + name: 'my-recipes' + properties: { + recipes: { + 'Radius.Data/redis': { + default: { + recipeKind: 'terraform' + recipeLocation: 'git::https://github.com/myorg/recipes//redis?ref=v1.0.0' + } + } + 'Radius.Messaging/rabbitMQ': { + default: { + recipeKind: 'bicep' + recipeLocation: '123456789012.dkr.ecr.us-east-1.amazonaws.com/recipes/rabbitmq:1.0.0' + } + } + } + } +} + +// 5. Environment becomes a thin reference to the resources above. +resource env 'Radius.Core/environments@2025-08-01-preview' = { + name: 'my-env' + properties: { + recipePacks: [myRecipePack.id] + bicepSettings: myBicepSettings.id + terraformSettings: myTerraformSettings.id + } +} +``` + +## Before / after: an Application + +### Before (legacy) + +```bicep +resource app 'Applications.Core/applications@2023-10-01-preview' = { + name: 'my-app' + properties: { environment: env.id } +} + +resource frontend 'Applications.Core/containers@2023-10-01-preview' = { + name: 'frontend' + properties: { + application: app.id + container: { image: 'ghcr.io/myorg/frontend:1.0.0' } + connections: { + cache: { source: cache.id } + } + } +} + +resource cache 'Applications.Datastores/redisCaches@2023-10-01-preview' = { + name: 'cache' + properties: { + application: app.id + environment: env.id + } +} +``` + +### After (compute extensibility) + +```bicep +resource app 'Radius.Core/applications@2025-08-01-preview' = { + name: 'my-app' + properties: { environment: env.id } +} + +resource frontend 'Radius.Compute/containers@2025-08-01-preview' = { + name: 'frontend' + properties: { + application: app.id + container: { image: 'ghcr.io/myorg/frontend:1.0.0' } + connections: { + cache: { source: cache.id } + } + } +} + +resource cache 'Radius.Data/redis@2025-08-01-preview' = { + name: 'cache' + properties: { + application: app.id + environment: env.id + } +} +``` + +The application graph and developer mental model are unchanged. What changed is that `Radius.Compute/containers` and `Radius.Data/redis` are now Recipe-backed Resource Types resolved via the Environment's Recipe Packs, instead of being built into Radius. + +## Migrating custom Terraform providers + +Replace `recipeConfig.terraform.providers` maps with **Recipe parameters** that reference `Radius.Security/secrets`. See the [TerraformSettings how-to]({{< ref "guides/recipes/howto-terraform-settings" >}}#step-4-inject-secrets-into-custom-terraform-providers) for a worked Datadog example. + +## Validating the migration + +After re-deploying the Environment and Application: + +```bash +rad app list --environment my-env +rad resource list Radius.Compute/containers --environment my-env +rad recipe list --environment my-env +``` + +If a deployment fails, the Application RP logs include the Recipe lookup decisions and the resolved BicepSettings / TerraformSettings — these are usually the fastest way to see whether the new Environment is wired up correctly. + +## What to do with the legacy resources + +While the new `Radius.*` resources are stabilizing, the legacy `Applications.*` resources remain available so you can migrate incrementally. Once every Application in an Environment has been re-authored against `Radius.*` types and the Environment references its new Recipe Packs / Settings resources, the legacy `Applications.Core/environments` resource and any associated `recipeConfig` can be deleted. + +For the full enumeration of breaking behaviour, see [Breaking changes]({{< ref "breaking-changes" >}}). + +## Further reading + +- [Compute extensibility concepts]({{< ref "concepts/compute-extensibility" >}}) +- [Recipe Packs concepts]({{< ref "concepts/recipe-packs" >}}) +- [Recipe Packs how-to]({{< ref "guides/recipes/recipe-packs" >}}) +- [BicepSettings how-to]({{< ref "guides/recipes/howto-bicep-settings" >}}) +- [TerraformSettings how-to]({{< ref "guides/recipes/howto-terraform-settings" >}}) +- [Extensibility design notes](https://github.com/radius-project/radius/tree/main/eng/design-notes/extensibility) +- [`resource-types-contrib`](https://github.com/radius-project/resource-types-contrib) diff --git a/docs/content/guides/operations/migration/breaking-changes.md b/docs/content/guides/operations/migration/breaking-changes.md new file mode 100644 index 000000000..c43dca925 --- /dev/null +++ b/docs/content/guides/operations/migration/breaking-changes.md @@ -0,0 +1,101 @@ +--- +type: docs +title: "Breaking changes: compute extensibility" +linkTitle: "Breaking changes" +description: "Enumerated breaking changes between the legacy Radius architecture and the compute extensibility model" +weight: 100 +categories: "Reference" +tags: ["extensibility", "migration"] +--- + +This page enumerates the breaking changes introduced by the [compute extensibility]({{< ref "concepts/compute-extensibility" >}}) work. It is the companion reference to the [migration guide]({{< ref "guides/operations/migration" >}}). + +> Compute extensibility resources use the `2025-08-01-preview` API version. Behaviour and schemas may continue to evolve until the APIs are promoted to stable. + +## API namespace and versions + +- New resources live under `Radius.*` (e.g. `Radius.Core/environments`, `Radius.Core/recipePacks`, `Radius.Compute/containers`, `Radius.Security/secrets`). +- The legacy `Applications.*` namespace (`Applications.Core/*`, `Applications.Datastores/*`, `Applications.Messaging/*`) remains available during migration but should be considered deprecated. +- The new preview API version is `2025-08-01-preview`. The legacy `2023-10-01-preview` API version is unchanged. + +**Mitigation:** Re-author Bicep files against the new types/API version. The migration guide includes side-by-side examples. + +## Environments are decomposed + +The following properties of `Applications.Core/environments@2023-10-01-preview` are no longer present on `Radius.Core/environments@2025-08-01-preview`: + +| Removed property | Replacement | +|-----------------------------------------------------------|--------------------------------------------------------------------| +| `properties.recipes` | One or more `Radius.Core/recipePacks` referenced via `properties.recipePacks` | +| `properties.recipeConfig.bicep.authentication` | `Radius.Core/bicepSettings` referenced via `properties.bicepSettings` | +| `properties.recipeConfig.terraform.authentication` | `Radius.Core/terraformSettings` `terraformrc.credentials` | +| `properties.recipeConfig.terraform.providers` | Recipe parameters that reference `Radius.Security/secrets` values | +| `properties.recipeConfig.env` | `Radius.Core/terraformSettings` `properties.env` | +| `properties.compute.kind` (hard-coded `kubernetes`) | Compute Resource Types from the Environment's Recipe Packs | + +**Mitigation:** Author Recipe Packs, BicepSettings, and TerraformSettings resources first, then re-create the Environment as a thin reference to them. See the migration guide. + +## Compute is no longer hard-coded + +`Applications.Core/containers`, `Applications.Core/gateways`, `Applications.Core/secretStores`, and similar built-ins are replaced by Recipe-backed Resource Types under `Radius.Compute/*`. The semantics are similar but the Recipe behind the type is now selected by the platform engineer rather than hard-coded into the Application RP. + +**Mitigation:** Use Recipe Packs to publish a `Radius.Compute/containers` (etc.) Recipe. Reference implementations live in [`resource-types-contrib`](https://github.com/radius-project/resource-types-contrib). + +## Terraform binary lifecycle + +The Application RP no longer downloads Terraform on demand from `releases.hashicorp.com`. Terraform must be installed explicitly into the Radius control plane. + +**Mitigation:** + +```bash +rad terraform install # latest from hashicorp.com +rad terraform install --url \ + --checksum # pinned version from a mirror +``` + +Existing automation that assumed Terraform was always present without operator action must add a `rad terraform install` step. + +## Custom Terraform providers + +`recipeConfig.terraform.providers` (an arbitrary map injected into named providers) is removed. Provider credentials are now passed as **Recipe parameters** that reference `Radius.Security/secrets` values, and the Recipe declares the corresponding `var`s. + +**Mitigation:** Update Recipes to declare `var datadog_api_key` (and similar) and update Recipe Pack entries to pass `parameters: { apiKey: secret.properties.data.apiKey.value }`. See the [TerraformSettings how-to]({{< ref "guides/recipes/howto-terraform-settings" >}}#step-4-inject-secrets-into-custom-terraform-providers). + +## Terraform backends + +The default Terraform backend is still `kubernetes`. Other backends are now configured via `Radius.Core/terraformSettings.properties.backend`: + +- **Tier 1** (integrated authentication, tested): `kubernetes`, `s3`, `azurerm`. +- **Tier 2** (schema available, BYO authentication): `oss`, `consul`, `gcs`, `http`, `oci`, `pg`, `cos`. +- The Terraform `local` and `remote` backend types are not supported. + +**Mitigation:** If you previously relied on the Kubernetes backend implicitly, no change is required. To use a different backend, declare it in TerraformSettings. + +## Bicep registry authentication property names + +The legacy schema used a registry-host → secret map. The new schema uses an `authenticationMethod` discriminator with named fields: + +| `authenticationMethod` | Required field | +|------------------------|-----------------------| +| `BasicAuth` | `basicAuthSecretId` | +| `AzureWI` | `azureWiClientId`, `azureWiTenantId` | +| `AwsIrsa` | `awsIamRoleArn` | + +**Mitigation:** Replace the registry-host → secret map with a single BicepSettings resource per Environment. The Azure WI client/tenant IDs and the AWS IAM role ARN are not stored as secret values. + +## Secret resource changes + +`Radius.Security/secrets` replaces `Applications.Core/secretStores`. The legacy `kind`/`type` discriminator (`basicAuthentication`, `azureWorkloadIdentity`, `awsIRSA`) is removed because the discriminator now lives on the BicepSettings resource. Secrets simply hold key/value data. + +**Mitigation:** Re-create secrets without the `type` discriminator. For workload-identity and IRSA flows, supply the client/tenant/role identifiers directly to BicepSettings — they are not secrets. + +## Deprecation timeline + +The legacy `Applications.*` resource types and the `2023-10-01-preview` API version remain available so existing solutions are not broken at the moment compute extensibility lands. A formal deprecation timeline will be published once the `Radius.*` API version is promoted from preview to stable. Until then, plan to migrate but do not assume the legacy types will disappear in a specific release. + +## Further reading + +- [Compute extensibility concepts]({{< ref "concepts/compute-extensibility" >}}) +- [Migration guide]({{< ref "guides/operations/migration" >}}) +- [Extensibility design notes](https://github.com/radius-project/radius/tree/main/eng/design-notes/extensibility) +- [Terraform and Bicep settings feature spec](https://github.com/radius-project/design-notes/blob/main/features/2025-08-14-terraform-bicep-settings.md) diff --git a/docs/content/guides/recipes/howto-bicep-settings/index.md b/docs/content/guides/recipes/howto-bicep-settings/index.md new file mode 100644 index 000000000..fbcd23387 --- /dev/null +++ b/docs/content/guides/recipes/howto-bicep-settings/index.md @@ -0,0 +1,152 @@ +--- +type: docs +title: "How-To: Configure Bicep with BicepSettings" +linkTitle: "BicepSettings (private Bicep registries)" +description: "Use the BicepSettings resource to authenticate Radius to a private OCI registry hosting Bicep Recipes" +weight: 510 +categories: "How-To" +tags: ["recipes", "bicep", "extensibility"] +--- + +`Radius.Core/bicepSettings` is the resource that holds Bicep-related configuration for Radius — most importantly, authentication for private OCI registries that host your Bicep Recipes. It is the [compute extensibility]({{< ref "concepts/compute-extensibility" >}}) replacement for the legacy `Environment.properties.recipeConfig.bicep.authentication` property. + +> **Preview API:** BicepSettings uses the `2025-08-01-preview` API version. The schema may change as the feature is finalized. The legacy [`recipeConfig` private Bicep registry guide]({{< ref "howto-private-bicep-registry" >}}) still applies for environments that have not yet migrated. + +## When to use this guide + +Use BicepSettings when you store your Bicep Recipe templates in a private registry such as: + +- Azure Container Registry (ACR) +- Amazon Elastic Container Registry (ECR) +- GitHub Container Registry (GHCR) +- Any OCI-compliant registry that requires authentication + +If your Recipes live in an anonymous public registry, no BicepSettings resource is required. + +## Prerequisites + +- [rad CLI]({{< ref "installation#step-1-install-the-rad-cli" >}}) +- [Radius initialized with `rad init`]({{< ref howto-environment >}}) +- A private OCI registry with at least one Bicep Recipe published to it +- Credentials for that registry + +## Supported authentication methods + +| Method | Property | Use for | +|------------|-------------------------|--------------------------------------------------------| +| `BasicAuth`| `basicAuthSecretId` | Any OCI-compliant registry (Docker Hub, GHCR, etc.) | +| `AzureWI` | `azureWiClientId`, `azureWiTenantId` | Azure Container Registry via workload identity | +| `AwsIrsa` | `awsIamRoleArn` | Amazon ECR via IRSA | + +## Step 1: Create a Secret with the registry credentials + +For `BasicAuth`, the Secret must have `username` and `password` keys: + +```bicep +resource bicepRegistrySecret 'Radius.Security/secrets@2025-08-01-preview' = { + name: 'bicepRegistrySecret' + properties: { + data: { + username: { + value: '' + } + password: { + value: '' + } + } + } +} +``` + +For `AzureWI` and `AwsIrsa` no Secret is required — the workload-identity client/tenant IDs and the IAM role ARN are not secrets. + +## Step 2: Create the BicepSettings resource + +```bicep +resource myBicepSettings 'Radius.Core/bicepSettings@2025-08-01-preview' = { + name: 'myBicepSettings' + properties: { + registryAuthentication: { + authenticationMethod: 'BasicAuth' + basicAuthSecretId: bicepRegistrySecret.id + } + } +} +``` + +ACR with workload identity: + +```bicep +resource myBicepSettings 'Radius.Core/bicepSettings@2025-08-01-preview' = { + name: 'myBicepSettings' + properties: { + registryAuthentication: { + authenticationMethod: 'AzureWI' + azureWiClientId: '12345678-abcd-efgh-ijkl-9876543210ab' + azureWiTenantId: '12345678-abcd-efgh-ijkl-9876543210ab' + } + } +} +``` + +ECR with IRSA: + +```bicep +resource myBicepSettings 'Radius.Core/bicepSettings@2025-08-01-preview' = { + name: 'myBicepSettings' + properties: { + registryAuthentication: { + authenticationMethod: 'AwsIrsa' + awsIamRoleArn: 'arn:aws:iam::012345678901:role/radius-ecr-pull' + } + } +} +``` + +## Step 3: Reference BicepSettings from your Environment + +```bicep +resource myEnvironment 'Radius.Core/environments@2025-08-01-preview' = { + name: 'myEnvironment' + properties: { + recipePacks: [myRecipePack.id] + bicepSettings: myBicepSettings.id + } +} +``` + +## Step 4: Deploy + +```bash +rad deploy ./environment.bicep --group myGroup +``` + +When Radius next executes a Bicep Recipe whose `recipeLocation` resolves to your private registry, the Application RP authenticates using the credentials referenced by the BicepSettings resource. + +## Migrating from `recipeConfig.bicep.authentication` + +The legacy form embedded the registry-to-secret mapping inside the Environment: + +```bicep +// Legacy +properties: { + recipeConfig: { + bicep: { + authentication: { + '': { + secret: registrySecrets.id + } + } + } + } +} +``` + +In the new model, the same information lives in a standalone BicepSettings resource and the Environment simply references it. See the [migration guide]({{< ref "guides/operations/migration" >}}) for full before/after examples. + +## Further reading + +- [Compute extensibility concepts]({{< ref "concepts/compute-extensibility" >}}) +- [Recipe Packs how-to]({{< ref "guides/recipes/recipe-packs" >}}) +- [TerraformSettings how-to]({{< ref "guides/recipes/howto-terraform-settings" >}}) +- [Migration guide]({{< ref "guides/operations/migration" >}}) diff --git a/docs/content/guides/recipes/howto-private-bicep-registry/index.md b/docs/content/guides/recipes/howto-private-bicep-registry/index.md index c8474921f..6a95dec26 100644 --- a/docs/content/guides/recipes/howto-private-bicep-registry/index.md +++ b/docs/content/guides/recipes/howto-private-bicep-registry/index.md @@ -8,6 +8,10 @@ categories: "How-To" tags: ["recipes", "bicep"] --- +{{% alert title="Legacy guide" color="warning" %}} +This guide describes the **legacy** `Environment.properties.recipeConfig.bicep.authentication` model. With the new [compute extensibility]({{< ref "concepts/compute-extensibility" >}}) architecture, private Bicep registries are configured through a dedicated `Radius.Core/bicepSettings` resource. New users should follow the [BicepSettings how-to guide]({{< ref "howto-bicep-settings" >}}) instead, and existing users should consult the [migration guide]({{< ref "guides/operations/migration" >}}). +{{% /alert %}} + This guide will describe how to: - Configure a Radius environment to utilize Bicep Recipe templates that are stored in a private OCI (Open Container Initiative) complaint container registry. This setup will ensure the templates are securely stored within a private OCI registry and accessed by Radius using required credentials. diff --git a/docs/content/guides/recipes/howto-terraform-settings/index.md b/docs/content/guides/recipes/howto-terraform-settings/index.md new file mode 100644 index 000000000..36fb9cc9e --- /dev/null +++ b/docs/content/guides/recipes/howto-terraform-settings/index.md @@ -0,0 +1,216 @@ +--- +type: docs +title: "How-To: Configure Terraform with TerraformSettings" +linkTitle: "TerraformSettings (Terraform CLI, backend, and credentials)" +description: "Install, configure, and authenticate Terraform inside the Radius control plane using the TerraformSettings resource" +weight: 520 +categories: "How-To" +tags: ["recipes", "terraform", "extensibility"] +--- + +`Radius.Core/terraformSettings` is the resource that holds the Terraform configuration used by Radius when it executes Terraform Recipes. It supersedes the various `Environment.properties.recipeConfig.terraform.*` properties from the legacy model. Together with the new `rad terraform install` command, it gives platform engineers full control over the Terraform binary, its CLI configuration (`terraformrc`), the Terraform backend, and provider authentication. + +> **Preview API:** TerraformSettings uses the `2025-08-01-preview` API version. The schema and behaviour may evolve as the feature is finalized. The full feature spec is in [Terraform and Bicep Settings](https://github.com/radius-project/design-notes/blob/main/features/2025-08-14-terraform-bicep-settings.md). + +## What changed + +- Radius **no longer downloads Terraform on demand.** The platform engineer installs (and upgrades) Terraform explicitly with `rad terraform install`. +- Terraform CLI configuration, backend, environment variables, and provider mirrors are configured through a **TerraformSettings resource** that the Environment references — not through fields embedded in the Environment. +- Provider credentials that aren't AWS/Azure (for example Datadog, GitHub, Cloudflare) are injected by passing **Recipe parameters** that reference Radius `Secret` values instead of using the legacy `recipeConfig.terraform.providers` map. + +## Prerequisites + +- [rad CLI]({{< ref "installation#step-1-install-the-rad-cli" >}}) +- [Radius initialized with `rad init`]({{< ref howto-environment >}}) + +## Step 1: Install Terraform into the Radius control plane + +Quick install (latest from `releases.hashicorp.com`): + +```bash +rad terraform install +``` + +Pinned install from a mirror with checksum validation: + +```bash +rad terraform install \ + --url "https:///terraform_1.5.7_linux_amd64.zip" \ + --checksum "sha256:37f2d497ea512324d59b50ebf1b58a6fcc2a2828d638a4f6fdb1f41af00140f3" +``` + +Re-running `rad terraform install` upgrades or replaces the existing installation. Use `rad terraform uninstall` to remove it. + +## Step 2: Author a TerraformSettings resource + +A minimal TerraformSettings resource — useful when you only need to set environment variables or change the log level: + +```bicep +resource myTerraformSettings 'Radius.Core/terraformSettings@2025-08-01-preview' = { + name: 'myTerraformSettings' + properties: { + env: { + TF_LOG: 'INFO' + TF_REGISTRY_CLIENT_TIMEOUT: '15' + } + } +} +``` + +A richer example using a private provider mirror, registry credentials stored in a Secret, and an S3 backend: + +```bicep +param mirrorToken string + +resource providerSecret 'Radius.Security/secrets@2025-08-01-preview' = { + name: 'tfProviderSecret' + properties: { + data: { + token: { + value: mirrorToken + } + } + } +} + +resource myTerraformSettings 'Radius.Core/terraformSettings@2025-08-01-preview' = { + name: 'myTerraformSettings' + properties: { + terraformrc: { + provider_installation: { + network_mirror: { + path: 'https:///' + include: ['*'] + } + direct: { + exclude: ['azurerm'] + } + } + credentials: [ + { + host: '' + secret: providerSecret.id + } + ] + } + backend: { + type: 's3' + bucket: 'my-company-dev-tfstate-bucket' + key: 'radius/terraform.tfstate' + region: 'us-east-1' + encrypt: 'true' + dynamodb_table: 'terraform-global-locks' + } + env: { + TF_LOG: 'TRACE' + } + } +} +``` + +### `terraformrc` properties supported by Radius + +| Setting | Supported | +|-----------------------------------------------------|-----------| +| `credentials` | ✅ | +| `provider_installation` | ✅ | +| `credential_helper` | ❌ | +| `disable_checkpoint` / `disable_checkpoint_signature` | ❌ | +| `plugin_cache_dir` | ❌ | + +Unsupported settings are not part of the resource schema; deployment will fail if they are specified. + +### Backend types + +Tier 1 backends (integrated authentication, tested by the Radius project): `kubernetes` (default), `s3`, `azurerm`. + +Tier 2 backends (schema available, authentication BYO): `oss`, `consul`, `gcs`, `http`, `oci`, `pg`, `cos`. + +The Terraform `local` and `remote` backends are not supported. + +## Step 3: Reference TerraformSettings from your Environment + +```bicep +resource myEnvironment 'Radius.Core/environments@2025-08-01-preview' = { + name: 'myEnvironment' + properties: { + recipePacks: [myRecipePack.id] + terraformSettings: myTerraformSettings.id + } +} +``` + +Deploy: + +```bash +rad deploy ./environment.bicep --group myGroup +``` + +## Step 4: Inject Secrets into custom Terraform providers + +For providers other than AWS / Azure / Kubernetes, pass Recipe parameters that read from a Radius Secret: + +```bicep +resource datadogCredentials 'Radius.Security/secrets@2025-08-01-preview' = { + name: 'datadogCredentials' + properties: { + data: { + apiKey: { value: '' } + appKey: { value: '' } + } + } +} + +resource observabilityRecipePack 'Radius.Core/recipePacks@2025-08-01-preview' = { + name: 'observability' + properties: { + recipes: { + 'Radius.Observability/dashboard': { + default: { + recipeKind: 'terraform' + recipeLocation: 'git::https://github.com/myorg/recipes//datadog?ref=v1.0.0' + parameters: { + apiKey: datadogCredentials.properties.data.apiKey.value + appKey: datadogCredentials.properties.data.appKey.value + } + } + } + } + } +} +``` + +Inside the Recipe itself, declare the corresponding `var`s and use them in the `provider` block. + +## Migrating from `recipeConfig.terraform.*` + +The legacy model stored authentication, environment variables, and custom provider configuration directly on the Environment: + +```bicep +// Legacy +properties: { + recipeConfig: { + terraform: { + authentication: { ... } + providers: { ... } + } + env: { ... } + } +} +``` + +In the new model: + +- `recipeConfig.terraform.authentication` → `terraformSettings.properties.terraformrc.credentials` +- `recipeConfig.terraform.providers` → Recipe `parameters` referencing `Radius.Security/secrets` +- `recipeConfig.env` → `terraformSettings.properties.env` + +See the [migration guide]({{< ref "guides/operations/migration" >}}) for end-to-end before/after examples. + +## Further reading + +- [Compute extensibility concepts]({{< ref "concepts/compute-extensibility" >}}) +- [Recipe Packs how-to]({{< ref "guides/recipes/recipe-packs" >}}) +- [BicepSettings how-to]({{< ref "guides/recipes/howto-bicep-settings" >}}) +- [Migration guide]({{< ref "guides/operations/migration" >}}) +- [Terraform and Bicep Settings feature spec](https://github.com/radius-project/design-notes/blob/main/features/2025-08-14-terraform-bicep-settings.md) diff --git a/docs/content/guides/recipes/recipe-packs/index.md b/docs/content/guides/recipes/recipe-packs/index.md new file mode 100644 index 000000000..4e7087d47 --- /dev/null +++ b/docs/content/guides/recipes/recipe-packs/index.md @@ -0,0 +1,122 @@ +--- +type: docs +title: "How-To: Author and consume Recipe Packs" +linkTitle: "Recipe Packs" +description: "Create a Recipe Pack and reference it from one or more Radius Environments" +weight: 200 +categories: "How-To" +tags: ["recipes", "recipe packs", "extensibility"] +--- + +This guide walks through creating a Radius **Recipe Pack** and using it from an Environment. Recipe Packs are part of the [compute extensibility]({{< ref "concepts/compute-extensibility" >}}) model. They let platform engineers manage `Resource Type → Recipe` assignments as a reusable resource shared across Environments. See the [Recipe Packs concept page]({{< ref "concepts/recipe-packs" >}}) for the conceptual overview. + +> **Preview API:** Recipe Packs use the `2025-08-01-preview` API version. The schema may change as the feature is finalized. + +## Prerequisites + +- [rad CLI]({{< ref "installation#step-1-install-the-rad-cli" >}}) +- [Bicep VSCode extension]({{< ref "installation#step-2-install-the-vs-code-extension" >}}) +- [Radius initialized with `rad init`]({{< ref howto-environment >}}) +- One or more published Recipe templates (Bicep in an OCI registry, Terraform in a Git repository) + +## Step 1: Author the Recipe Pack + +Create `recipePack.bicep`: + +```bicep +resource computeRecipePack 'Radius.Core/recipePacks@2025-08-01-preview' = { + name: 'kubernetes-compute' + properties: { + recipes: { + 'Radius.Compute/containers': { + default: { + recipeKind: 'bicep' + recipeLocation: 'ghcr.io/myorg/recipes/container:1.0.0' + } + } + 'Radius.Compute/gateways': { + default: { + recipeKind: 'terraform' + recipeLocation: 'git::https://github.com/myorg/recipes//gateway?ref=v1.0.0' + } + } + 'Radius.Compute/secretStores': { + default: { + recipeKind: 'bicep' + recipeLocation: 'ghcr.io/myorg/recipes/secretstore:1.0.0' + } + } + } + } +} + +output recipePackId string = computeRecipePack.id +``` + +Each entry under `recipes` is keyed by the fully-qualified Resource Type name and contains one or more **named** Recipe entries. `default` is the conventional name for the Recipe selected when the developer does not request a specific Recipe. + +## Step 2: Deploy the Recipe Pack + +Recipe Packs are deployed like any other Radius resource: + +```bash +rad deploy ./recipePack.bicep --group platform +``` + +You can list deployed Recipe Packs with: + +```bash +rad resource list Radius.Core/recipePacks --group platform +``` + +## Step 3: Reference the Recipe Pack from an Environment + +Create or update your Environment to point at the Recipe Pack: + +```bicep +resource computeRecipePack 'Radius.Core/recipePacks@2025-08-01-preview' existing = { + name: 'kubernetes-compute' + scope: resourceGroup('platform') +} + +resource myEnvironment 'Radius.Core/environments@2025-08-01-preview' = { + name: 'production-east' + properties: { + recipePacks: [computeRecipePack.id] + } +} +``` + +Deploy: + +```bash +rad deploy ./environment.bicep --group production +``` + +Any Application deployed to `production-east` will now resolve `Radius.Compute/containers`, `Radius.Compute/gateways`, and `Radius.Compute/secretStores` against the Recipe Pack you just registered. + +## Step 4 (optional): Compose multiple Recipe Packs + +An Environment can reference more than one Recipe Pack. The packs are evaluated in array order, and **later entries override earlier ones** when two packs define a Recipe for the same Resource Type and name: + +```bicep +properties: { + recipePacks: [ + baseCompute.id // generic defaults + awsDataServices.id // adds Radius.Data/* recipes + productionOverrides.id // overrides the container recipe with a hardened variant + ] +} +``` + +## Updating a Recipe Pack + +Updating the Recipe Pack resource (for example, bumping `recipeLocation` to a new tag) and redeploying it is enough — every Environment that references the pack will use the new Recipes on the next deployment. There is no need to redeploy the Environment. + +## Further reading + +- [Recipe Packs concepts]({{< ref "concepts/recipe-packs" >}}) +- [Compute extensibility concepts]({{< ref "concepts/compute-extensibility" >}}) +- [BicepSettings how-to]({{< ref "guides/recipes/howto-bicep-settings" >}}) +- [TerraformSettings how-to]({{< ref "guides/recipes/howto-terraform-settings" >}}) +- [Migration guide]({{< ref "guides/operations/migration" >}})