Skip to content

Commit 133e092

Browse files
committed
Address feedback
Signed-off-by: Karishma Chawla <kachawla@microsoft.com>
1 parent 0d9d0aa commit 133e092

1 file changed

Lines changed: 28 additions & 21 deletions

File tree

eng/design-notes/extensibility/2026-04-automated-default-resource-type-registration.md

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@ This eliminates the need to copy files between repositories, ensures schemas sta
4747
A platform engineer creates a new resource type `Radius.Networking/loadBalancers` in `resource-types-contrib`. To make it a default in Radius:
4848

4949
1. They add the YAML manifest at `Networking/loadBalancers/loadBalancers.yaml`.
50-
2. They add the file path to `defaults.yaml`:
50+
2. They add the resource type to `defaults.yaml`:
5151
```yaml
5252
defaultRegistration:
53-
- Networking/loadBalancers/loadBalancers.yaml
53+
- Radius.Networking/loadBalancers
5454
```
55-
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).
55+
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). `gen_embed.go` resolves each resource type name to its corresponding file path by scanning the directory tree.
5656
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`).
5757

5858
#### Platform engineer updates a resource type schema
@@ -72,7 +72,7 @@ The design introduces `resource-types-contrib` as a Go module dependency of `rad
7272
At startup, the UCP initializer service:
7373
1. Reads `defaults.yaml` from the embedded filesystem to discover which manifests to load.
7474
2. Parses each listed manifest, validates its schema, and merges manifests sharing a namespace into a single resource provider.
75-
3. Registers the merged resource providers with UCP.
75+
3. Registers the merged resource providers directly to the database, consistent with the existing startup registration path.
7676
4. Proceeds to register any additional directory-based manifests as before.
7777

7878
The `location` field is intentionally omitted from `resource-types-contrib` manifests. When a manifest has no `location`, UCP's existing fallback mechanism routes requests to `DefaultDownstreamEndpoint` (dynamic-rp), which is the correct handler for all UDT-based resource types.
@@ -83,7 +83,7 @@ The `location` field is intentionally omitted from `resource-types-contrib` mani
8383
┌─────────────────────────────────────────────────────────────┐
8484
│ resource-types-contrib (Go module) │
8585
│ │
86-
│ defaults.yaml ─── lists paths ──► go generate
86+
│ defaults.yaml ─── lists types ──► go generate │
8787
│ │ │
8888
│ Compute/containers/containers.yaml ▼ │
8989
│ Compute/routes/routes.yaml manifests_gen.go │
@@ -142,7 +142,7 @@ Add a `defaultRegistration` boolean field to each manifest YAML and to the `Reso
142142
143143
#### Option 2: Central `defaults.yaml` + `go generate` (Proposed)
144144
145-
A `defaults.yaml` file at the repo root lists which manifest paths should be default-registered. A `go generate` script reads this file and produces `manifests_gen.go` with `//go:embed` directives for exactly those files (plus `defaults.yaml` itself). At runtime, `RegisterFS` reads `defaults.yaml` from the embedded FS to know which paths to load.
145+
A `defaults.yaml` file at the repo root lists which resource types should be default-registered using canonical `<namespace>/<typeName>` names. Running `go generate` invokes `gen_embed.go`, which reads this file, resolves each name to its corresponding manifest file path, and produces `manifests_gen.go` with `//go:embed` directives for exactly those files (plus `defaults.yaml` itself). At runtime, `RegisterFS` reads `defaults.yaml` from the embedded FS to know which paths to load.
146146
147147
##### Advantages
148148
@@ -170,37 +170,40 @@ A `defaults.yaml` file at the repo root lists which manifest paths should be def
170170
| File | Purpose |
171171
|---|---|
172172
| `go.mod` | Makes the repository a Go module (`github.com/radius-project/resource-types-contrib`). |
173-
| `defaults.yaml` | Central list of manifest paths for default registration. |
174-
| `gen_embed.go` | `go generate` script that reads `defaults.yaml` and produces `manifests_gen.go`. Build-tagged `//go:build ignore`. |
173+
| `defaults.yaml` | Central list of resource types for default registration, using canonical `<namespace>/<typeName>` names. |
174+
| `gen_embed.go` | Invoked by `go generate`. Reads `defaults.yaml`, resolves each resource type name to its file path, and produces `manifests_gen.go`. Build-tagged `//go:build ignore`. |
175175
| `manifests.go` | Contains `//go:generate go run gen_embed.go` directive and package documentation. |
176176
| `manifests_gen.go` | **Generated**. Contains `//go:embed` directives for `defaults.yaml` and each listed manifest. Exports `DefaultManifests embed.FS`. |
177177
178178
**`defaults.yaml` format:**
179179
```yaml
180180
defaultRegistration:
181-
- Compute/containers/containers.yaml
182-
- Compute/persistentVolumes/persistentVolumes.yaml
183-
- Compute/routes/routes.yaml
184-
- Data/mySqlDatabases/mySqlDatabases.yaml
185-
- Data/postgreSqlDatabases/postgreSqlDatabases.yaml
186-
- Security/secrets/secrets.yaml
181+
- Radius.Compute/containers
182+
- Radius.Compute/persistentVolumes
183+
- Radius.Compute/routes
184+
- Radius.Data/mySqlDatabases
185+
- Radius.Data/postgreSqlDatabases
186+
- Radius.Security/secrets
187187
```
188188

189+
`gen_embed.go` resolves each entry to a file path using the convention: strip the `Radius.` prefix from the namespace, then `<namespace>/<typeName>/<typeName>.yaml` (e.g., `Radius.Compute/containers` resolves to `Compute/containers/containers.yaml`). If a file does not exist at the resolved path, `go generate` fails immediately.
190+
189191
**Manifest YAML files** remain unchanged: no `location` field, no `defaultRegistration` field. They contain only `namespace` and `types`.
190192

191193
#### UCP
192194

193195
**`pkg/cli/manifest/registermanifest.go`**: New `RegisterFS` function:
194-
- Reads `defaults.yaml` from the provided `fs.FS` to get the list of manifest file paths.
195-
- For each path, reads and parses the manifest using the existing `ReadBytes` function.
196+
- Reads `defaults.yaml` from the provided `fs.FS` to get the list of resource type names.
197+
- For each entry, resolves the resource type name to the corresponding embedded manifest file path.
198+
- Reads and parses the manifest using the existing `ReadBytes` function.
196199
- Validates schemas using the existing `validateManifestSchemas` function.
197200
- Merges manifests sharing a namespace (e.g., three `Radius.Compute` files) into a single `ResourceProvider` with all types under one `Types` map.
198-
- Registers each merged provider using the existing `RegisterResourceProvider` function.
201+
- Returns the merged providers to the initializer for direct database registration.
199202

200203
**`pkg/ucp/initializer/service.go`** (updated):
201204
- `NewService` accepts an additional `fs.FS` parameter for embedded manifests.
202-
- `Run` calls `manifest.RegisterFS` for embedded manifests **before** `manifest.RegisterDirectory` for directory-based manifests.
203-
- If both embedded and directory manifests exist, both are registered. Directory-based manifests can override embedded ones (last-write-wins via UCP's `CreateOrUpdate`).
205+
- `Run` processes embedded manifests by calling `RegisterFS` to parse and merge them, then registers each merged provider using `registerResourceProviderDirect` (direct database writes), consistent with how directory-based manifests are already registered at startup. This avoids HTTP round-trips, async operation queues, and polling.
206+
- If both embedded and directory manifests exist, both are registered. Directory-based manifests can override embedded ones (last-write-wins via direct database save).
204207

205208
**`pkg/ucp/server/server.go`** (updated):
206209
- Imports `resource-types-contrib` and passes `resourcetypes.DefaultManifests` to `initializer.NewService`.
@@ -220,8 +223,7 @@ Remaining files ( `radius_core.yaml`, `microsoft_resources.yaml`) stay because t
220223
| Manifest YAML has invalid syntax | `ReadBytes` returns parse error. Startup fails with the specific file identified. |
221224
| Manifest schema validation fails | `validateManifestSchemas` returns error. Startup fails with the specific file identified. |
222225
| `defaults.yaml` is empty (no entries) | `RegisterFS` logs a message and returns nil. Startup continues with directory-based manifests only. |
223-
| UCP not reachable at startup | Existing `waitForServer` timeout behavior. No change from current behavior. |
224-
| 409 conflict during registration | Existing retry logic with exponential backoff. No change from current behavior. |
226+
| `rad upgrade` introduces new default resource types | New types are registered via direct database save on startup. Existing types are updated. No error expected. |
225227

226228
## Test plan
227229

@@ -236,6 +238,7 @@ Remaining files ( `radius_core.yaml`, `microsoft_resources.yaml`) stay because t
236238
2. **Integration tests**:
237239
- Existing `Test_ResourceProvider_RegisterManifests` continues to work (tests directory-based registration).
238240
- New test that passes an `embed.FS` to `NewService` and verifies the resource provider is registered correctly.
241+
- Test `rad upgrade` scenario: register an initial set of embedded types, then simulate an upgrade with an updated `embed.FS` containing an additional default type. Verify the new type is registered and existing types are updated without errors.
239242

240243
3. **CI validation for `manifests_gen.go`**:
241244
- In `resource-types-contrib` CI: run `go generate` and verify no diff to ensure the generated file is up to date.
@@ -394,6 +397,10 @@ update-resource-types:
394397
go mod tidy
395398
```
396399

400+
### Ensuring the dependency is kept up to date
401+
402+
Until tagged releases and Dependabot automation are in place (see Follow-up Item #3), bumping the `resource-types-contrib` dependency in `radius` is a manual step. To ensure this is not forgotten, include a step in the Radius release checklist to run `make update-resource-types` and verify the latest resource type schemas are included before each release.
403+
397404
## Open Questions
398405

399406
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?

0 commit comments

Comments
 (0)