Skip to content

feat: add multi-file merge support to generate command - #36

Closed
kachawla wants to merge 1 commit into
mainfrom
pr1-generate-types
Closed

feat: add multi-file merge support to generate command#36
kachawla wants to merge 1 commit into
mainfrom
pr1-generate-types

Conversation

@kachawla

@kachawla kachawla commented May 15, 2026

Copy link
Copy Markdown
Owner

Overview

Update the existing generate subcommand of manifest-to-bicep to accept multiple manifest files. When given multiple YAML manifests with the same namespace, their Types maps are merged into a single output (types.json, index.json, index.md).

This supports per-type manifest files (e.g. containers.yaml, routes.yaml) as introduced by the automated resource type registration design, where each file defines a single resource type within a namespace.

Backward compatible: single-file usage works exactly as before.

Part of Unified Bicep extension publishing (PR 1/4). See design doc.

Changes

  • bicep-tools/cmd/manifest-to-bicep/main.go: Updated generate to accept <manifest1> [manifest2...] <output> (last arg is always output dir). Added mergeManifestFiles() that validates same namespace and rejects duplicate types.

Usage

Single file (backward compatible):

go run ./bicep-tools/cmd/manifest-to-bicep generate containers.yaml /tmp/out

Multiple files (merge into one output):

go run ./bicep-tools/cmd/manifest-to-bicep generate containers.yaml routes.yaml persistentVolumes.yaml /tmp/out

Copilot AI left a comment

Copy link
Copy Markdown

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 generate-types subcommand to manifest-to-bicep for producing only types.json, including support for merging multiple manifests that share a namespace.

Changes:

  • Registers the new generate-types Cobra subcommand.
  • Adds RunGenerateTypes, manifest merge logic, and types.json-only output handling.

Comment thread bicep-tools/cmd/manifest-to-bicep/main.go Outdated
@kachawla
kachawla force-pushed the pr1-generate-types branch from c61cf5b to 8458df0 Compare May 15, 2026 19:08
@kachawla

Copy link
Copy Markdown
Owner Author

Re: Copilot's comment on the generate-bicep-types Makefile target reference in the help text (line 145)

Good catch. Removed the forward reference to the generate-bicep-types Makefile target (which is updated in PR 2). The help text now describes the intended usage pattern generically without referencing a target that doesn't exist yet in this PR's scope.

Fixed in the latest force-push.

@kachawla
kachawla force-pushed the pr1-generate-types branch from 8458df0 to 81f917b Compare May 15, 2026 20:36
@kachawla
kachawla requested a review from Copilot May 15, 2026 20:40
@kachawla kachawla changed the title feat: add generate-types subcommand with multi-file merge support feat: add multi-file merge support to generate command May 15, 2026

Copilot AI left a comment

Copy link
Copy Markdown

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 1 comment.

Comments suppressed due to low confidence (1)

bicep-tools/cmd/manifest-to-bicep/main.go:121

  • This multi-file path still uses the full extension generator, which produces types.json, index.json, and index.md. The requested generate-types behavior needs a types-only path; otherwise callers that are aggregating namespace-specific types.json files will also overwrite or create index artifacts that should be rebuilt separately.
		result, err = generator.GenerateFromString(merged)

Comment thread bicep-tools/cmd/manifest-to-bicep/main.go

Copilot AI left a comment

Copy link
Copy Markdown

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

Comment thread bicep-tools/cmd/manifest-to-bicep/main_test.go Outdated
Comment thread bicep-tools/cmd/manifest-to-bicep/main_test.go Outdated
@kachawla
kachawla force-pushed the pr1-generate-types branch 2 times, most recently from b927fe6 to a2cddf0 Compare May 15, 2026 21:33
Update the existing 'generate' subcommand of manifest-to-bicep to accept
multiple manifest files. When given multiple YAML manifests with the same
namespace, their Types maps are merged into a single output (types.json,
index.json, index.md).

This supports per-type manifest files (e.g. containers.yaml, routes.yaml)
as introduced by the automated resource type registration design, where
each file defines a single resource type within a namespace.

Backward compatible: single-file usage works exactly as before.

Part of: unified Bicep extension publishing (PR 1/4)
@kachawla
kachawla force-pushed the pr1-generate-types branch from a2cddf0 to 6f82b5d Compare May 15, 2026 21:39
@kachawla kachawla closed this May 16, 2026
kachawla pushed a commit that referenced this pull request Jul 22, 2026
…oject#12344)

# Description

Implements secure handling of **recipe secret _outputs_** (Scenario 3 of
the recipe-secrets design). A recipe-generated secret (a connection
string, storage/access key, API key, etc.) is materialized into a
managed `Radius.Security/secrets` resource and is **never persisted as
plaintext** on the owning resource, in the application graph, or in
logs. The owner exposes only a read-only `secrets.name` reference;
consumers bind by name via a container env `valueFrom.secretKeyRef`.

**What's included**

- **Schema `secrets:` block** (`pkg/schema/secrets.go`): resource types
declare a top-level read-only `secrets` object with a reserved `name`
reference; `GetSecretsBlock` / `ValidateSecretsBlock` helpers. `secrets`
is treated as a framework-owned basic property.
- **Managed-secret materializer** (`pkg/dynamicrp/backend/secret`):
creates / updates / deletes a `Radius.Security/secrets` per owner via
the generic resources client. The managed secret name is derived
deterministically as `<owner-name>-<short-hash>-secrets`, where a short
hash of the owner's fully-qualified resource ID disambiguates owners
that share a name but differ in resource type or scope.
- **Processor leak-fix**
(`pkg/dynamicrp/backend/processor/dynamicresource.go`): once a type
declares a `secrets` block, materializes **all** of the recipe's secret
outputs into the managed secret (the declared keys are advisory and do
not filter), sets the read-only `properties.secrets.name` reference, and
**stops writing secret plaintext** into resource properties/status;
cascade-deletes the managed secret on delete.
- **Nested `outputs.secrets` recipe-pack mapping** for direct (AVM)
modules — an entry under the reserved `secrets` key inside a recipe's
`outputs` (e.g. `outputs: { host: 'name', secrets: { connectionString:
'primaryConnectionString' } }`) forces the named module output into the
secret set regardless of how the module classified it. The API models
`outputs` as an untyped map; the versioned↔datamodel converter splits
the nested `secrets` object back out (typespec + swagger + generated
models + datamodel + converter + `recipes` configloader).
- **No-leak verification**: integration test asserts a recipe secret
output never appears in the `rad resource show` GET/LIST body;
functional test (`sensitive_fields_test.go`) asserts secret values never
appear in the `rad resource show` response.
- **Docs**: secret-output section in
`docs/architecture/extensibility.md`.

Secret _inputs_ (Scenario 1) are unchanged — already handled by
`x-radius-sensitive`.

## End-to-end validation

Proven end-to-end against **real Azure** across 7 resource types in
`resource-types-verification`. Each run confirms the recipe secret
output is materialized into a managed `Radius.Security/secrets`
(`state=Succeeded`), the owner exposes only the read-only
`properties.secrets.name` reference, **no plaintext appears on the
owner**, and a container consumes the secret via `secretKeyRef`:

| Type | PR | Base provisioning | Consumer round-trip |
|---|---|---|---|
| kafka | #32 | ✅ | kcat whole-value + quarkus `$(VAR)` JAAS (explicit
in-pod substitution assert) → Event Hubs |
| redis | #37 | ✅ | live POST/GET → Azure Managed Redis |
| mongodb | #36 | ✅ | mongo-express → Cosmos DB |
| rabbitmq | #38 | ✅ | bento AMQP send/receive → Service Bus |
| storage | #35 | ✅ | sftpgo → Blob (multi-key secret; selects
`accountKey`) |
| search | #34 | ✅ | hurl → Azure AI Search |
| llm/models | #33 | ✅ | LiteLLM → Azure OpenAI chat |

## Type of change

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

Fixes: radius-project#12347

## Related PRs

- `radius-project/resource-types-contrib` radius-project#224 (merged) — container
recipe env ordering fix (emit secret/`valueFrom` env vars before `value`
vars), which enables the developer-side `$(VAR)` secret-composition
pattern this feature relies on.
- `radius-project/resource-types-verification` #32 (kafka reference) and
#33#38 (llm, search, storage, mongodb, redis, rabbitmq) — the 7-type
end-to-end validation above; each pins the `radius` submodule to this
branch.

## Not yet included (follow-ups)

- Registration-time `secrets`-block schema validation and `readOnly`
input enforcement.
- Durable managed-secret provisioning status (requeue/verify the managed
secret exists before marking the owner Succeeded) — see review
discussion.
- Scenario 2 (re-fetchable secret output: store an identifier and
re-resolve the live value from the cloud provider at bind time).
- Converting the shipped built-in types in `resource-types-contrib` to
declare `secrets:` blocks (the verification repo converted its test
manifests to prove the flow).

## Contributor checklist

- An overview of proposed schema changes is included in a linked GitHub
issue.
    - [x] 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](https://github.com/radius-project/resource-types-contrib/)
is created, if resource types or recipes are affected by the changes in
this PR.
    - [x] Yes <!-- resource-types-contrib#224 -->
    - [ ] Not applicable
- A PR for [dashboard](https://github.com/radius-project/dashboard/) is
created, if the Radius Dashboard is affected by the changes in this PR.
    - [ ] Yes
    - [x] Not applicable
- A PR for the [documentation
repository](https://github.com/radius-project/docs) is created, if the
changes in this PR affect the documentation or any user facing updates
are made.
    - [ ] Yes
- [x] Not applicable <!-- architecture doc updated in-repo; user docs to
follow with the tracking issue -->

---------

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants