Skip to content

Resolve recipe pack references by name in Radius.Core/environments#12134

Open
willdavsmith wants to merge 1 commit into
mainfrom
willdavsmith/recipe-pack-by-name-design
Open

Resolve recipe pack references by name in Radius.Core/environments#12134
willdavsmith wants to merge 1 commit into
mainfrom
willdavsmith/recipe-pack-by-name-design

Conversation

@willdavsmith

@willdavsmith willdavsmith commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Description

Today an environment's recipePacks array only accepts fully-qualified resource IDs, so a simple recipePacks: ['postgresPack'] in Bicep fails. This implements issue #12117 by letting each entry be either a bare pack name or a full resource ID.

Resolution and validation happen server-side in the Radius.Core/environments CreateOrUpdate controller, which is the single write choke point for Bicep deploy, direct API, and CLI create/update. Canonical full resource IDs are persisted, so every downstream reader (backend config loader, app graph, rad env show, referencedBy maintenance) is unchanged. No API schema change is required since recipePacks is already string[].

Resolution flow

Every entry in recipePacks[] is processed in Run() via resolveAndValidateRecipePacks -> resolveRecipePackRef, one entry at a time. Each entry is classified by whether it parses as a full resource ID:

  1. Full resource ID (resources.ParseResource(ref) succeeds) - treated as explicit. Its type must be Radius.Core/recipePacks; the canonical id.String() is returned as-is.
  2. Bare name (parse fails, e.g. postgresPack) - resolved against the environment's own scope:
    • scopeID = ParseScope(envID.RootScope())
    • packID = scopeID.Append(TypeSegment{Type: "Radius.Core/recipePacks", Name: ref})
    • re-parsed to reject structurally invalid names.

The normalized canonical IDs are written back to newResource.Properties.RecipePacks before save, so downstream readers only ever see full IDs.

Which environment / resource group

envID is the environment being created or updated, taken from the request URL. envID.RootScope() is its plane + resource group, so a bare name resolves into the same plane and resource group as the environment itself. Cross-scope packs require a full ID.

Example: env /planes/radius/local/resourceGroups/myGroup/providers/Radius.Core/environments/myEnv + postgresPack resolves to /planes/radius/local/resourceGroups/myGroup/providers/Radius.Core/recipePacks/postgresPack.

Error cases

Checked per-entry, in order; the first failure short-circuits the whole request. Empty or nil recipePacks is a no-op.

Case Status Message (abridged)
Full ID, wrong type 400 ...has type %q; expected "Radius.Core/recipePacks".
Bare name, structurally invalid (empty, contains /) 400 Invalid recipe pack reference %q: provide a recipe pack name or a ... resource ID.
Resolved pack does not exist (DatabaseClient().Get fails) 400 Referenced recipe pack %q could not be found (resolved to %q): %v
Stored object will not parse as a RecipePack 400 Failed to parse recipe pack %q: %v
Same resource type defined by two packs 409 Resource type '%s' is defined in multiple recipe packs: %s and %s
Scope parse failure (defensive) 400 Could not resolve recipe pack %q within scope %q.

Two design points: the not-found error is fail-fast (matching the issue's "previously deployed pack" model - the pack must already exist), and it echoes both the original reference and the resolved ID, so a mistyped name or wrong-resource-group mistake is obvious.

Type of change

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

Fixes: #12117

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

    This is a user-facing change; a follow-up docs PR is needed before this leaves draft.

@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@willdavsmith willdavsmith marked this pull request as ready for review June 17, 2026 17:41
@willdavsmith willdavsmith requested a review from a team as a code owner June 17, 2026 17:41
Copilot AI review requested due to automatic review settings June 17, 2026 17:41
@willdavsmith willdavsmith requested a review from a team as a code owner June 17, 2026 17:41
@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown

Unit Tests

    2 files  ± 0    439 suites  ±0   7m 38s ⏱️ -1s
5 385 tests +10  5 383 ✅ +10  2 💤 ±0  0 ❌ ±0 
6 565 runs  +10  6 563 ✅ +10  2 💤 ±0  0 ❌ ±0 

Results for commit f2e847c. ± Comparison against base commit 76fd2e4.

This pull request removes 2 and adds 12 tests. Note that renamed tests count towards both.
github.com/radius-project/radius/pkg/corerp/frontend/controller/environments/v20250801preview ‑ TestCreateOrUpdateEnvironment_RecipePackValidation/invalid-recipe-pack-id
github.com/radius-project/radius/pkg/corerp/frontend/controller/environments/v20250801preview ‑ TestCreateOrUpdateEnvironment_RecipePackValidation/single-recipe-pack-no-validation
github.com/radius-project/radius/pkg/corerp/frontend/controller/environments/v20250801preview ‑ TestCreateOrUpdateEnvironment_RecipePackNormalization
github.com/radius-project/radius/pkg/corerp/frontend/controller/environments/v20250801preview ‑ TestCreateOrUpdateEnvironment_RecipePackValidation/conflicting-recipe-packs-same-resource-type-different-case
github.com/radius-project/radius/pkg/corerp/frontend/controller/environments/v20250801preview ‑ TestCreateOrUpdateEnvironment_RecipePackValidation/duplicate-same-recipe-pack-by-name-and-id-no-conflict
github.com/radius-project/radius/pkg/corerp/frontend/controller/environments/v20250801preview ‑ TestCreateOrUpdateEnvironment_RecipePackValidation/invalid-empty-recipe-pack-name
github.com/radius-project/radius/pkg/corerp/frontend/controller/environments/v20250801preview ‑ TestCreateOrUpdateEnvironment_RecipePackValidation/invalid-recipe-pack-name
github.com/radius-project/radius/pkg/corerp/frontend/controller/environments/v20250801preview ‑ TestCreateOrUpdateEnvironment_RecipePackValidation/invalid-recipe-pack-name-leading-slash
github.com/radius-project/radius/pkg/corerp/frontend/controller/environments/v20250801preview ‑ TestCreateOrUpdateEnvironment_RecipePackValidation/mixed-name-and-full-id
github.com/radius-project/radius/pkg/corerp/frontend/controller/environments/v20250801preview ‑ TestCreateOrUpdateEnvironment_RecipePackValidation/recipe-pack-by-name-not-found
github.com/radius-project/radius/pkg/corerp/frontend/controller/environments/v20250801preview ‑ TestCreateOrUpdateEnvironment_RecipePackValidation/recipe-pack-by-name-resolved
github.com/radius-project/radius/pkg/corerp/frontend/controller/environments/v20250801preview ‑ TestCreateOrUpdateEnvironment_RecipePackValidation/recipe-pack-lookup-error
…

♻️ This comment has been updated with latest results.

@codecov

codecov Bot commented Jun 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 81.57895% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 52.36%. Comparing base (76fd2e4) to head (f2e847c).

Files with missing lines Patch % Lines
...ents/v20250801preview/createorupdateenvironment.go 81.57% 4 Missing and 3 partials ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main   #12134   +/-   ##
=======================================
  Coverage   52.35%   52.36%           
=======================================
  Files         737      737           
  Lines       47240    47263   +23     
=======================================
+ Hits        24733    24747   +14     
- Misses      20141    20146    +5     
- Partials     2366     2370    +4     

☔ View full report in Codecov by Harness.
📢 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.

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.

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

@willdavsmith willdavsmith force-pushed the willdavsmith/recipe-pack-by-name-design branch 3 times, most recently from 3d1d996 to 8d0dfff Compare June 17, 2026 19:23
@willdavsmith willdavsmith requested a review from Copilot June 17, 2026 19:30

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

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment on lines +215 to 218
// Re-parse to reject structurally invalid names (e.g. empty or containing '/').
if parsed, err := resources.ParseResource(packID.String()); err != nil || !parsed.IsResource() {
return "", rest.NewBadRequestResponse(fmt.Sprintf("Invalid recipe pack reference %q: provide a recipe pack name or a %s resource ID.", ref, datamodel.RecipePackResourceType))
}
Comment on lines +173 to +183
func Test_RecipePacks_ByName_Deployment(t *testing.T) {
template := "testdata/recipepacks-test-by-name.bicep"
appName := "recipepacks-byname-app"
appNamespace := "recipepacks-byname-ns"
parentResourceTypeName := "Test.Resources/userTypeAlpha"
parentResourceTypeParam := strings.Split(parentResourceTypeName, "/")[1]
filepath := "testdata/testresourcetypes.yaml"
options := rp.NewRPTestOptions(t)
cli := radcli.NewCLI(t, options.ConfigFilePath)

test := rp.NewRPTest(t, appName, []rp.TestStep{
@willdavsmith willdavsmith requested a review from nithyatsu June 17, 2026 19:47
Allow the recipePacks array on Radius.Core/environments to contain bare
names (e.g. 'postgresPack') in addition to full resource IDs. The
CreateOrUpdate controller resolves each name against the environment's own
plane and resource group, fail-fast validates the pack exists (HTTP 400 if
not), and persists canonical full resource IDs so every downstream reader
(config loader, app graph, rad env show, referencedBy maintenance) is
unchanged.

- Add resolveAndValidateRecipePacks / resolveRecipePackRef and normalize
  stored references in the controller
- Unit tests for name resolution, mixed name/ID, not-found, wrong-type,
  invalid name, and stored-ID normalization
- Functional test variant that references a pack by name (explicit dependsOn
  for deterministic ordering)

Signed-off-by: willdavsmith <willdavsmith@gmail.com>
@willdavsmith willdavsmith force-pushed the willdavsmith/recipe-pack-by-name-design branch from 8d0dfff to f2e847c Compare June 17, 2026 19:48
@radius-functional-tests

radius-functional-tests Bot commented Jun 17, 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 radius-project/radius
Commit ref f2e847c
Unique ID funcfd75d51ec4
Image tag pr-funcfd75d51ec4
  • 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-funcfd75d51ec4
  • 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-funcfd75d51ec4
  • dynamic-rp test image location: ghcr.io/radius-project/dev/dynamic-rp:pr-funcfd75d51ec4
  • controller test image location: ghcr.io/radius-project/dev/controller:pr-funcfd75d51ec4
  • ucp test image location: ghcr.io/radius-project/dev/ucpd:pr-funcfd75d51ec4
  • 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 corerp-cloud functional tests...
⌛ Starting ucp-cloud functional tests...
✅ ucp-cloud functional tests succeeded
✅ corerp-cloud functional tests succeeded

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reference recipe packs by name

2 participants