Skip to content

Direct module support for Recipes - #11876

Merged
Reshrahim merged 18 commits into
radius-project:mainfrom
Reshrahim:001-direct-module-support
Jun 15, 2026
Merged

Reshrahim merged 18 commits into
radius-project:mainfrom
Reshrahim:001-direct-module-support

Conversation

@Reshrahim

@Reshrahim Reshrahim commented May 13, 2026 •

Copy link
Copy Markdown
Contributor

This pull request adds a comprehensive design note describing the "Direct Recipe Modules" feature for Radius. The document outlines how platform engineers can use standard Bicep or Terraform modules directly as Radius Recipes, removing the need for custom wrappers and reducing maintenance overhead. It covers user personas, challenges, desired outcomes, implementation details, and usage examples.

Key documentation additions:

Feature overview and motivation

  • Introduces support for referencing standard Bicep or Terraform modules directly in the location field of a recipe, eliminating the need for Radius-specific wrappers and simplifying adoption and maintenance.
  • Details the user personas (platform engineers, application developers), their challenges with the current system, and the positive outcomes enabled by this feature.

Core features and scenarios

  • Describes three main features: direct module execution, template expression resolution for parameters, and output mapping from module outputs to resource properties.
  • Provides real-world scenarios and usage examples for Terraform registry modules, Azure Verified Modules, Git-hosted modules, and environment-level parameter overrides.

Risks, dependencies, and limitations

  • Outlines key dependencies (such as module compatibility and API stability) and explicitly lists non-goals for the initial release.

User experience and implementation details

  • Walks through the desired user experience, including how parameters and outputs are mapped
    Please explain the changes you've made.

Type of change

  • This pull request fixes a bug in Radius and has an approved issue (issue link required).
  • This pull request adds or changes features of Radius and has an approved issue (issue link required).
  • This pull request is a minor refactor, code cleanup, test improvement, or other maintenance task and doesn't change the functionality of Radius (issue link optional).
  • This pull request is a design document and only includes files in the eng/design-notes directory.

Fixes: #issue_number

Contributor checklist

Please verify that the PR meets the following requirements, where applicable:

  • An overview of proposed schema changes is included in a linked GitHub issue.
    • Yes
    • Not applicable
  • A design document is added or updated under eng/design-notes/ in this repository, if new APIs are being introduced.
    • Yes
    • Not applicable
  • The design document has been reviewed and approved by Radius maintainers/approvers.
    • Yes
    • Not applicable
  • A PR for resource-types-contrib is created, if resource types or recipes are affected by the changes in this PR.
    • Yes
    • Not applicable
  • A PR for dashboard is created, if the Radius Dashboard is affected by the changes in this PR.
    • Yes
    • Not applicable
  • A PR for the documentation repository is created, if the changes in this PR affect the documentation or any user facing updates are made.
    • Yes
    • Not applicable

@radius-functional-tests

radius-functional-tests Bot commented May 13, 2026 •

Copy link
Copy Markdown

Radius functional test overview

🔍 Go to test action run

Click here to see the test run details
Name Value
Repository Reshrahim/radius
Commit ref 534bd68
Unique ID func5e7c2189fb
Image tag pr-func5e7c2189fb
  • gotestsum 1.13.0
  • KinD: v0.29.0
  • Dapr: 1.14.4
  • Azure KeyVault CSI driver: 1.4.2
  • Azure Workload identity webhook: 1.3.0
  • Bicep recipe location ghcr.io/radius-project/dev/test/testrecipes/test-bicep-recipes/<name>:pr-func5e7c2189fb
  • Terraform recipe location http://tf-module-server.radius-test-tf-module-server.svc.cluster.local/<name>.zip (in cluster)
  • applications-rp test image location: ghcr.io/radius-project/dev/applications-rp:pr-func5e7c2189fb
  • dynamic-rp test image location: ghcr.io/radius-project/dev/dynamic-rp:pr-func5e7c2189fb
  • controller test image location: ghcr.io/radius-project/dev/controller:pr-func5e7c2189fb
  • ucp test image location: ghcr.io/radius-project/dev/ucpd:pr-func5e7c2189fb
  • deployment-engine test image location: ghcr.io/radius-project/deployment-engine:latest

Test Status

⌛ Building Radius and pushing container images for functional tests...
✅ Container images build succeeded
⌛ Publishing Bicep Recipes for functional tests...
✅ Recipe publishing succeeded
⌛ Starting ucp-cloud functional tests...
⌛ Starting corerp-cloud functional tests...
✅ ucp-cloud functional tests succeeded
✅ corerp-cloud functional tests succeeded

@codecov

codecov Bot commented May 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 51.69%. Comparing base (251d7f3) to head (534bd68).
⚠️ Report is 27 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #11876      +/-   ##
==========================================
+ Coverage   51.47%   51.69%   +0.21%     
==========================================
  Files         699      725      +26     
  Lines       44130    45595    +1465     
==========================================
+ Hits        22718    23572     +854     
- Misses      19251    19798     +547     
- Partials     2161     2225      +64     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread specs/001-direct-module-support/spec.md Resolved
Comment thread specs/001-direct-module-support/spec.md Resolved
Comment thread specs/001-direct-module-support/spec.md Resolved
Comment thread specs/001-direct-module-support/spec.md Resolved
Comment thread specs/001-direct-module-support/spec.md Resolved
Comment thread specs/001-direct-module-support/spec.md Resolved
@Reshrahim Reshrahim added the pr:standard Ongoing maintenance, minor improvements, documentation updates, and routine development work label May 19, 2026
@Reshrahim Reshrahim linked an issue Jun 1, 2026 that may be closed by this pull request
6 tasks
@Reshrahim
Reshrahim marked this pull request as ready for review June 9, 2026 23:58
Copilot AI review requested due to automatic review settings June 9, 2026 23:58
@Reshrahim
Reshrahim requested review from a team as code owners June 9, 2026 23:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This pull request adds a new design note under eng/design-notes/recipes/ describing the proposed “Direct Recipe Modules” feature, which would allow Radius recipe packs to reference standard Terraform/Bicep modules directly (without Radius-specific wrapper modules), including proposed parameter expression resolution and output mapping behavior.

Changes:

  • Adds a comprehensive design note for “Direct Recipe Modules” (motivation, scenarios, risks, UX, and examples).
  • Introduces proposed concepts for parameter expression resolution ({{context.*}}) and module output-to-resource-property mapping (outputs).
  • Includes multiple end-to-end Bicep examples for recipe packs, environments, and output/secrets handling.

@willdavsmith willdavsmith left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚀

Reshrahim and others added 12 commits June 15, 2026 11:45
Signed-off-by: Reshma Abdul Rahim <reshmarahim.abdul@microsoft.com>
Signed-off-by: Reshma Abdul Rahim <reshmarahim.abdul@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Reshma Abdul Rahim <61033581+Reshrahim@users.noreply.github.com>
Signed-off-by: Reshma Abdul Rahim <reshmarahim.abdul@microsoft.com>
Signed-off-by: Reshma Abdul Rahim <reshmarahim.abdul@microsoft.com>
Signed-off-by: Reshma Abdul Rahim <reshmarahim.abdul@microsoft.com>
Signed-off-by: Reshma Abdul Rahim <reshmarahim.abdul@microsoft.com>
Signed-off-by: Reshma Abdul Rahim <reshmarahim.abdul@microsoft.com>
Signed-off-by: Reshma Abdul Rahim <reshmarahim.abdul@microsoft.com>
Signed-off-by: Reshma Abdul Rahim <reshmarahim.abdul@microsoft.com>
Signed-off-by: Reshma Abdul Rahim <61033581+Reshrahim@users.noreply.github.com>
Signed-off-by: Reshma Abdul Rahim <reshmarahim.abdul@microsoft.com>
Signed-off-by: Reshma Abdul Rahim <reshmarahim.abdul@microsoft.com>
Signed-off-by: Reshma Abdul Rahim <reshmarahim.abdul@microsoft.com>
@Reshrahim
Reshrahim force-pushed the 001-direct-module-support branch from 88e80e2 to 71bc0d3 Compare June 15, 2026 18:46
@willdavsmith
willdavsmith self-requested a review June 15, 2026 19:39
@Reshrahim
Reshrahim merged commit ed47232 into radius-project:main Jun 15, 2026
43 checks passed
@Reshrahim Reshrahim removed a link to an issue Jun 16, 2026
6 tasks
pull Bot pushed a commit to TheTechOddBug/radius that referenced this pull request Jun 24, 2026
# Description

Implements **Direct Module Support for Recipes** (design: radius-project#11876).

Today every Bicep/Terraform module used as a Radius Recipe must be
wrapped to add a `context` input variable and a structured `result`
output. This blocks direct use of community modules (Terraform Registry,
Azure Verified Modules) and adds maintenance overhead. This PR lets a
platform engineer point a recipe's `source` directly at a standard
module — Radius resolves parameters (including `{{context.*}}`
expressions), executes the module via the existing driver, and maps the
module's outputs back to resource-type properties via a new `outputs`
field.

Existing wrapped recipes are unchanged.

## What's included

- **Parameter expression resolution** — new `pkg/recipes/paramresolver`
resolves `{{context.*}}` expressions (and single-level ternaries) in
recipe parameters.
- **`outputs` mapping** — new `outputs` field on
`Radius.Core/recipePacks` recipe definitions maps module output names
onto resource property names (TypeSpec → swagger → generated models →
datamodel → conversion → bicep types). Precedence: `outputs` mapping >
`result` output > flat passthrough.
- **Bicep + Terraform drivers** — direct-module detection and execution.
Terraform mapped outputs preserve per-output `sensitive` so secret
outputs still route to Secrets rather than Values.
- **Parameter merge** — `ShallowMergeParameters` (environment-wins) in
`pkg/recipes/util`.
- **Terraform registry versioning** — registry modules aren't URLs and
need a separate `version` argument, so RecipePacks use a
`<source>:<version>` convention in the recipe's `source` field (e.g.
`terraform-aws-modules/rds/aws:6.1.0`), mirroring how Bicep/OCI recipes
embed the version in the image tag (per
[radius-project#12086](radius-project#12086)), parsed
into the module source + version. The split is collision-safe: only a
colon in the final path segment is a version, so a registry `host:port`
(e.g. `my.registry.com:8443/ns/name/aws`) and `://` URL sources are left
untouched. Verified end-to-end: a Radius-shaped `main.tf.json` with
split `source` + `version` resolves the module from
`registry.terraform.io`, whereas an un-split `source:version` is
rejected by Terraform.
- **dynamic-rp hardening** — non-string secret values are stringified
instead of panicking.

## Testing

- Unit tests across all touched packages (paramresolver, util,
bicep/terraform drivers, terraform config/execute/module, configloader,
conversion, dynamic-rp processor).
- Noncloud functional test `Test_DirectModule_Terraform` deploying a
non-wrapped Terraform module fixture
(`test/testrecipes/test-terraform-recipes/direct-kubernetes`),
validating `{{context.*}}` resolution, module execution, and outputs
mapping end-to-end.

## Known limitations / hard to test in CI

- Terraform **registry** module download + version resolution can't run
in noncloud CI (needs a live registry). The `<source>:<version>` parsing
is unit-tested, but end-to-end registry resolution is manual/cloud-only.
- Private registry / Git / OCI auth, cloud-backed modules (AVM Bicep,
AWS RDS Terraform), and `x-radius-sensitive` encryption-at-rest are
validated at unit boundaries only.
- Link-time source-reachability validation is out of scope (proposed as
follow-up).

## Type of change

- This pull request adds or changes features of Radius and has an
approved issue (issue link required).

Design: radius-project#11876

Closes radius-project#12086

## Contributor checklist

- A PR for
[resource-types-contrib](https://github.com/radius-project/resource-types-contrib/)
— _follow-up if recipes/types are affected._
- A PR for the [documentation
repository](https://github.com/radius-project/docs) — _follow-up: the
new `outputs` field and the `<source>:<version>` Terraform registry
convention are user-facing._

> Synced with `main`: this branch now builds on the recipe-pack
`kind`/`source` field naming (radius-project#11879). The `outputs` field and
direct-module logic sit alongside it. Issue link and
docs/resource-types-contrib follow-ups to be finalized.

---------

Signed-off-by: willdavsmith <willdavsmith@gmail.com>
sk593 pushed a commit that referenced this pull request Jul 6, 2026
# Description

Implements **Direct Module Support for Recipes** (design: #11876).

Today every Bicep/Terraform module used as a Radius Recipe must be
wrapped to add a `context` input variable and a structured `result`
output. This blocks direct use of community modules (Terraform Registry,
Azure Verified Modules) and adds maintenance overhead. This PR lets a
platform engineer point a recipe's `source` directly at a standard
module — Radius resolves parameters (including `{{context.*}}`
expressions), executes the module via the existing driver, and maps the
module's outputs back to resource-type properties via a new `outputs`
field.

Existing wrapped recipes are unchanged.

## What's included

- **Parameter expression resolution** — new `pkg/recipes/paramresolver`
resolves `{{context.*}}` expressions (and single-level ternaries) in
recipe parameters.
- **`outputs` mapping** — new `outputs` field on
`Radius.Core/recipePacks` recipe definitions maps module output names
onto resource property names (TypeSpec → swagger → generated models →
datamodel → conversion → bicep types). Precedence: `outputs` mapping >
`result` output > flat passthrough.
- **Bicep + Terraform drivers** — direct-module detection and execution.
Terraform mapped outputs preserve per-output `sensitive` so secret
outputs still route to Secrets rather than Values.
- **Parameter merge** — `ShallowMergeParameters` (environment-wins) in
`pkg/recipes/util`.
- **Terraform registry versioning** — registry modules aren't URLs and
need a separate `version` argument, so RecipePacks use a
`<source>:<version>` convention in the recipe's `source` field (e.g.
`terraform-aws-modules/rds/aws:6.1.0`), mirroring how Bicep/OCI recipes
embed the version in the image tag (per
[#12086](#12086)), parsed
into the module source + version. The split is collision-safe: only a
colon in the final path segment is a version, so a registry `host:port`
(e.g. `my.registry.com:8443/ns/name/aws`) and `://` URL sources are left
untouched. Verified end-to-end: a Radius-shaped `main.tf.json` with
split `source` + `version` resolves the module from
`registry.terraform.io`, whereas an un-split `source:version` is
rejected by Terraform.
- **dynamic-rp hardening** — non-string secret values are stringified
instead of panicking.

## Testing

- Unit tests across all touched packages (paramresolver, util,
bicep/terraform drivers, terraform config/execute/module, configloader,
conversion, dynamic-rp processor).
- Noncloud functional test `Test_DirectModule_Terraform` deploying a
non-wrapped Terraform module fixture
(`test/testrecipes/test-terraform-recipes/direct-kubernetes`),
validating `{{context.*}}` resolution, module execution, and outputs
mapping end-to-end.

## Known limitations / hard to test in CI

- Terraform **registry** module download + version resolution can't run
in noncloud CI (needs a live registry). The `<source>:<version>` parsing
is unit-tested, but end-to-end registry resolution is manual/cloud-only.
- Private registry / Git / OCI auth, cloud-backed modules (AVM Bicep,
AWS RDS Terraform), and `x-radius-sensitive` encryption-at-rest are
validated at unit boundaries only.
- Link-time source-reachability validation is out of scope (proposed as
follow-up).

## Type of change

- This pull request adds or changes features of Radius and has an
approved issue (issue link required).

Design: #11876

Closes #12086

## Contributor checklist

- A PR for
[resource-types-contrib](https://github.com/radius-project/resource-types-contrib/)
— _follow-up if recipes/types are affected._
- A PR for the [documentation
repository](https://github.com/radius-project/docs) — _follow-up: the
new `outputs` field and the `<source>:<version>` Terraform registry
convention are user-facing._

> Synced with `main`: this branch now builds on the recipe-pack
`kind`/`source` field naming (#11879). The `outputs` field and
direct-module logic sit alongside it. Issue link and
docs/resource-types-contrib follow-ups to be finalized.

---------

Signed-off-by: willdavsmith <willdavsmith@gmail.com>
Signed-off-by: sk593 <shruthikumar@microsoft.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:standard Ongoing maintenance, minor improvements, documentation updates, and routine development work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants