[resource-manager] resolveArmResources returns zero resources for customAzureResource-based converted specs
- Dominant language
- TypeScript
- Stars
- 27
- Forks
- 90
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 156
Description
## Description
`resolveArmResources` currently returns no resources for converted/legacy TypeSpec specs that model ARM resources through `Azure.ResourceManager.Legacy.customAzureResource(#{ isAzureResource: true })` or equivalent custom resource bases, instead of the standard `TrackedResource` / `ProxyResource` templates.
This creates an intentional mismatch between:
- resource detection based on the Swagger-shaped/legacy path, which can still identify these resources from paths and legacy/custom resource metadata; and
- resource detection based on TypeSpec `resolveArmResources`, which only sees resources registered into the ARM library resource registry.
If the intended design is that only `Azure.ResourceManager.Legacy.CustomAzureResource` (or another specific library-supported pattern) should be used, then existing converted specs need to be fixed and we need a way to guarantee future converted specs will not use the older/incorrect custom-resource shape. Otherwise, `resolveArmResources` likely needs to support this custom-resource pattern from the library side so the two detection paths do not diverge.
## Real case: Network
The Network management TypeSpec spec is a concrete example.
Spec location used by the .NET SDK generation:
```yaml
# azure-sdk-for-net/sdk/network/Azure.ResourceManager.Network/tsp-location.yaml
directory: specification/network/resource-manager/Microsoft.Network/Network
commit: 280622e57e9bd85a10d355dd5295144dd25af1d9
repo: Azure/azure-rest-api-specs
```
In the generated schema comparison from the .NET management emitter:
```text
legacy resource detection: 140 resources, 35 non-resource methods
resolveArmResources detection: 0 resources, 776 non-resource methods
```
So `resolveArmResources` does not retain even one Network ARM resource; all resource operations fall through as non-resource methods.
Representative Network TypeSpec patterns:
```typespec
@Http.Private.includeInapplicableMetadataInPayload(false)
model ApplicationGateway extends Common.Resource {
@visibility(Lifecycle.Read)
@path
@key("applicationGatewayName")
@segment("applicationGateways")
name: string;
}
@Azure.ResourceManager.Legacy.feature(Features.applicationGateway)
@armResourceOperations(#{ omitTags: true })
interface ApplicationGateways { ... }
```
The shared/custom resource bases in `Network/models.tsp` use the legacy custom resource decorator, for example:
```typespec
@Azure.ResourceManager.Legacy.customAzureResource(#{ isAzureResource: true })
model ProxyResource { ... }
@Azure.ResourceManager.Legacy.customAzureResource(#{ isAzureResource: true })
model CommonTrackedResource extends CommonResource { ... }
@Azure.ResourceManager.Legacy.customAzureResource(#{ isAzureResource: true })
model WritableResource { ... }
```
This is exactly the kind of spec shape converted from Swagger where the old detection logic can still infer ARM resources, but `resolveArmResources` returns none.
## Relationship to #3430 / #3748
#3430 was closed by #3748, which introduced:
```typespec
@Http.Private.includeInapplicableMetadataInPayload(false)
@customAzureResource(#{ isAzureResource: isResource })
model CustomAzureResource {}
```
That appears to mean the preferred/validated solution is to use `Azure.ResourceManager.Legacy.CustomAzureResource` rather than hand-applying `@customAzureResource(#{ isAzureResource: true })` on arbitrary custom base models.
However, Network is a large real converted spec that already uses custom-resource-marked bases and now demonstrates that `resolveArmResources` can produce zero resources for this pattern.
## Expected behavior
We need one of these outcomes:
1. **Spec-side fix path:** If the old Network pattern is considered incorrect, document and enforce the correct pattern. For example, migrate Network to `Azure.ResourceManager.Legacy.CustomAzureResource` or another supported template, and add diagnostics/linter rules/tests to guarantee future converted specs do not use the unsupported pattern.
2. **Library-side fix path:** If converted specs using `@customAzureResource(#{ isAzureResource: true })` should continue to work, then `resolveArmResources` should register/resolve these custom Azure resources so it does not return zero resources for specs like Network.
## Actual behavior
For Network, `resolveArmResources` returns:
```text
resources.length = 0
nonResourceMethods.length = 776
```
This makes the new API unusable as a replacement for legacy resource detection for this spec, and causes a large mismatch against Swagger/legacy resource detection results.
## Why this matters
The .NET management emitter is comparing its legacy detector with `resolveArmResources` as part of migration. Network is the largest mismatch found so far: 140 legacy-only resource ID patterns.
Without a spec-side migration + enforcement plan or a library-side fix, adopting `resolveArmResources` would drop all Network resources.
Contributor guide
Assessment
This issue has not been assessed yet.