Skip to content

Adding design for automatically registering core RRTs#11610

Open
kachawla wants to merge 7 commits into
radius-project:mainfrom
kachawla:rrt-auto-registration
Open

Adding design for automatically registering core RRTs#11610
kachawla wants to merge 7 commits into
radius-project:mainfrom
kachawla:rrt-auto-registration

Conversation

@kachawla
Copy link
Copy Markdown
Member

@kachawla kachawla commented Apr 8, 2026

Description

Certain resource types defined in the resource-types-contrib repo are expected to be registered with Radius by default for every installation. The way we enable it today is by manually copying over the manifests into Radius repo and maintaining duplicate files. This design automates propagating the changes to the Radius repo.

Type of change

Fixes: #11108

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 PR is created in the design-notes 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 the samples repository is created, if existing samples are 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
  • A PR for the recipes repository is created, if existing recipes are affected by the changes in this PR.
    • Yes
    • Not applicable

Copilot AI review requested due to automatic review settings April 8, 2026 18:33
@kachawla kachawla requested review from a team as code owners April 8, 2026 18:33
@kachawla kachawla force-pushed the rrt-auto-registration branch from f165ae2 to 4177f2d Compare April 8, 2026 18:34
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a design note proposing automated default registration of Radius resource types by embedding selected manifests from resource-types-contrib into the Radius binary and registering them during UCP initialization.

Changes:

  • Introduces a design for using resource-types-contrib as a Go module dependency and embedding default manifests via go:embed.
  • Proposes a centralized defaults.yaml + go generate workflow to control which manifests ship as defaults.
  • Describes initializer/runtime behavior, error handling, and a test/CI validation plan for generated embed lists.

@kachawla kachawla marked this pull request as draft April 8, 2026 18:42
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 8, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 51.38%. Comparing base (9b812b3) to head (4177f2d).

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #11610   +/-   ##
=======================================
  Coverage   51.38%   51.38%           
=======================================
  Files         699      699           
  Lines       44114    44114           
=======================================
  Hits        22666    22666           
  Misses      19279    19279           
  Partials     2169     2169           

☔ 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.

@kachawla kachawla force-pushed the rrt-auto-registration branch 2 times, most recently from 06da8d4 to 369e713 Compare April 30, 2026 18:02
@kachawla kachawla requested a review from Copilot April 30, 2026 18:04
@kachawla kachawla force-pushed the rrt-auto-registration branch from 369e713 to 9262bfb Compare April 30, 2026 18:07
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 1 out of 1 changed files in this pull request and generated 2 comments.

@kachawla kachawla marked this pull request as ready for review April 30, 2026 18:08

### High Level Design

The design introduces `resource-types-contrib` as a Go module dependency of `radius`. Resource type manifests are embedded into the Radius binary using Go's `embed.FS` mechanism. A central `defaults.yaml` file in `resource-types-contrib` lists which manifests should be embedded and registered by default.
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.

Naming nit: default-types.yaml might be more appropriate if the design is to only store default type definitions in the file.

However, if additional default items (e.g. default recipe packs @nithyatsu 👀) may be stored in the same config file, then defaults.yaml makes sense.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think we would include recipes corresponding to each type in this file as well. What do you think @nithyatsu?

Copy link
Copy Markdown
Contributor

@nithyatsu nithyatsu May 13, 2026

Choose a reason for hiding this comment

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

yes, it makes sense to store bicep recipe corresponding to each type as well to help with creation of correct default recipe pack. Would the memory increase that comes along be ok?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Would the memory increase that comes along be ok?

I wasn't thinking of changing how recipes stored, but mainly when they are published. Since we want to make sure any time a default type is added, corresponding recipe is published and default recipe pack is updated to include it, we should point the workflow that does this today to look at defaults.yaml.

Copy link
Copy Markdown
Member

@brooke-hamilton brooke-hamilton left a comment

Choose a reason for hiding this comment

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

🚀 I really like how this proposal sets up resource-types-contrib as a clear dependency of Radius via a Golang module dependecy.


### 3. Tagged releases and automated dependency updates for `resource-types-contrib`

`resource-types-contrib` does not have a formal release or tagging process today. Without tagged releases, Radius depends on Go pseudo-versions (e.g., `v0.0.0-20260408153021-abc123def456`), and dependency updates require a maintainer to manually run `go get -u`. This limits automation and makes it harder to track what changed between versions.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

+1 on creating GitHub releases for the generated go code. Having releases would allow for idiomatic consumption of the releases in the Radius repo, and trigger dependabot updates when a new version is available.

If there is a need for more granular releases for specific resource types, then each resource type could be separated into its own go module and released separately. I don't think this would be required, but it's an option if we find ourselves updating the individual types in different cycles.

Copy link
Copy Markdown
Contributor

@nellshamrell nellshamrell left a comment

Choose a reason for hiding this comment

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

Excellent work, @kachawla!


Today, resource type manifests for default registration in Radius are manually duplicated from the `resource-types-contrib` repository into the `radius` repository under `deploy/manifest/built-in-providers/`. This creates a maintenance burden - when a resource type schema is updated in `resource-types-contrib`, the corresponding file in `radius` must be manually updated, leading to schema drift, stale definitions, and duplicated effort.

This design introduces a mechanism to automatically embed resource type manifests from `resource-types-contrib` as a Go module dependency of `radius`. A central configuration file (`defaults.yaml`) in `resource-types-contrib` declares which resource types should be default-registered. At build time, only those manifests are embedded into the Radius binary via `go:embed`. At startup, the UCP initializer reads the embedded manifests and registers them alongside any existing directory-based manifests.
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.

I like this - it lets us define recipes that require extra scrutiny when reviewing (we can also use CI to flag when recipes on the defaults.yml are changed and require additional review). This makes the threat of malicious contributions easier to manage (malicious contributions are a risk in any OSS project).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

that's a good point to use CI for flagging changes. I'll add that. Thanks for reviewing

- **Runtime fetching of manifests**: Manifests are embedded at build time, not downloaded at runtime. This avoids network dependencies during startup.
- **Migrating non-dynamic-rp providers**: Resource types served by `applications-rp` or the deployment engine (e.g., `Applications.Core`, `Microsoft.Resources`) require explicit `location` addresses and remain as directory-based manifests in `radius`. Migrating them is out of scope.
- **Recipe registration**: This design covers resource type schema registration only, not recipe registration or recipe pack management.
- **Release process for `resource-types-contrib`**: This design assumes a Radius maintainer manually bumps the `resource-types-contrib` dependency in `go.mod` to pick up changes. Establishing a formal release/tagging process for `resource-types-contrib` is out of scope.
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.

This was going to be my next question - whether there is a release/tagging process which would prevent a bug that was accidentally merged into a default resource type from manifesting in Radius. I agree it is out of scope for this proposal, but would be good to consider in the future.

- Networking/loadBalancers/loadBalancers.yaml
```
3. They run `go generate` and commit `defaults.yaml` along with the auto-generated `manifests_gen.go` (which contains the `//go:embed` directives that tell the Go compiler which files to embed in the binary).
4. A Radius maintainer manually bumps the dependency by running `go get -u github.com/radius-project/resource-types-contrib` in the `radius` repository and merging the resulting `go.mod` change. Since `resource-types-contrib` does not have tagged releases today, Go resolves a pseudo-version based on the latest commit (e.g., `v0.0.0-20260408153021-abc123def456`).
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.

ah - excellent use of the commit hash! This should not be used as a long-term solution as I believe git by default uses SHA-1 for its hashes, which is not very strong and can be broken. More to consider when we think about tagged releases in the future, but not a blocker to this proposal.

- **Discoverability**: A single file shows all defaults at a glance.
- **Reviewability**: PR diffs for `defaults.yaml` clearly show what's being added or removed.
- **No parser coupling**: `resource-types-contrib` metadata stays out of the Radius manifest parser.
- **Extensible**: Works for any directory structure; new top-level directories (e.g., `Networking/`) work without changing Go code.
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.

Good consideration!


## Security

No changes to the security model. The embedded manifests are static YAML files compiled into the binary at build time, so there is no new attack surface for injection or tampering beyond what exists for any compiled-in resource. The `defaults.yaml` file is validated at startup, and invalid entries cause a clear startup failure.
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.

Agreed - to me this adds no more significant risks than manually copying and pasting resource types does. Like all OSS projects, we need to consider ways to do more extensive security filtering/testing of pull requests, but this design does not add additional risk.


1. **`go generate` enforcement**: Should `resource-types-contrib` CI block merges if `manifests_gen.go` is out of date, or should CI auto-regenerate and commit?

- **Option A: CI blocks merges (proposed).** CI runs `go generate` and `git diff --exit-code manifests_gen.go`. If the file is stale, the PR fails. Contributors must run `go generate` locally before pushing. This keeps generated files explicitly reviewed in PRs and avoids hidden auto-commits.
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.

Agreed

@kachawla kachawla force-pushed the rrt-auto-registration branch 2 times, most recently from ce6d3d4 to 133e092 Compare May 12, 2026 07:54
@radius-functional-tests
Copy link
Copy Markdown

radius-functional-tests Bot commented May 12, 2026

Radius functional test overview

🔍 Go to test action run

Click here to see the test run details
Name Value
Repository kachawla/radius
Commit ref 133e092
Unique ID func46f0aa2a96
Image tag pr-func46f0aa2a96
  • 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-func46f0aa2a96
  • 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-func46f0aa2a96
  • dynamic-rp test image location: ghcr.io/radius-project/dev/dynamic-rp:pr-func46f0aa2a96
  • controller test image location: ghcr.io/radius-project/dev/controller:pr-func46f0aa2a96
  • ucp test image location: ghcr.io/radius-project/dev/ucpd:pr-func46f0aa2a96
  • 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 test failed. Please check the logs for more details
❌ corerp-cloud functional test failed. Please check the logs for more details

@kachawla kachawla force-pushed the rrt-auto-registration branch 2 times, most recently from 8044493 to c834f40 Compare May 12, 2026 22:55
2. **`go.mod` bump requires PR review in `radius`.** Changes in `resource-types-contrib` only reach Radius when a maintainer runs `go get -u` and merges the resulting `go.mod`/`go.sum` change. This is a second review gate.

3. **Manifest parsing and schema validation.** Manifests are parsed using a strict YAML decoder that rejects unknown top-level fields, duplicate keys, and any data that does not conform to the expected `ResourceProvider` structure. Schemas within each manifest are further validated against OpenAPI format; malformed or structurally invalid schemas are rejected at startup. There is no risk of code execution through YAML parsing, as Go YAML parsers do not support executable YAML tags.

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.

It would be to describe what happens when ,say, schema validation flags issues for one resource-type and how we can proceed with a release when that happens.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

3. **Manifest parsing and schema validation.** Manifests are parsed using a strict YAML decoder that rejects unknown top-level fields, duplicate keys, and any data that does not conform to the expected `ResourceProvider` structure. Schemas within each manifest are further validated against OpenAPI format; malformed or structurally invalid schemas are rejected at startup. There is no risk of code execution through YAML parsing, as Go YAML parsers do not support executable YAML tags.

4. **Schema runtime behavior.** The `schema` field within each API version accepts arbitrary JSON Schema content (including `additionalProperties: true`), so its contents are not structurally restricted beyond OpenAPI validity. After registration, dynamic-rp reads stored schemas at runtime for request validation and sensitive field identification (encryption). The schema is never passed to Terraform or Bicep recipes, and users always provide resource property values explicitly, so a crafted schema cannot inject values into recipe execution. The residual risks are limited to weakened request validation (overly permissive properties), unnecessary encryption overhead (incorrectly marking fields as sensitive), or performance degradation (very large or deeply nested schemas). These risks are mitigated by the requirement for manifest changes to go through code review, where reviewers can inspect the schema content.

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.

I agree reviews are essential to mitigate risk. We had initially disallowed additionalProperties: true for security reasons, but ACI had a use case which required us to support it.

kachawla added 3 commits May 13, 2026 18:15
Signed-off-by: Karishma Chawla <kachawla@microsoft.com>
Signed-off-by: Karishma Chawla <kachawla@microsoft.com>
Signed-off-by: Karishma Chawla <kachawla@microsoft.com>
@kachawla kachawla force-pushed the rrt-auto-registration branch from c834f40 to 735706a Compare May 14, 2026 01:16
Signed-off-by: Karishma Chawla <kachawla@microsoft.com>
kachawla added 3 commits May 14, 2026 23:28
Signed-off-by: Karishma Chawla <kachawla@microsoft.com>
- Add doc.go and pkg/resourcetypescontrib/import.go to implementation details
- Remove postgreSqlDatabases from defaults.yaml examples
- Add radius_data.yaml to removed files list
- Update file paths to show {dev,self-hosted}/ subdirectories
- Replace go get -u with go get MODULE@latest
- Fix Security section to describe copy-based approach (not embedded/compiled)
- Update sync-resource-types example to show stale file cleanup
- Update Test plan with actual test name and mark upgrade test as follow-up
- Update Development plan with all implementation details

Signed-off-by: Karishma Chawla <kachawla@microsoft.com>
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.

[Design] Automatically sync default resource manifests from resoure-type-contrib repo