Description
resolveArmResources can promote HDInsight action/status/sub-operation endpoints into false ARM resources. These paths are not valid Bicep resources, and the HDInsight spec explicitly scopes several of them out for C# generation.
Real case: HDInsight
Spec location used by .NET SDK generation:
# azure-sdk-for-net/sdk/hdinsight/Azure.ResourceManager.HDInsight/tsp-location.yaml
directory: specification/hdinsight/resource-manager/Microsoft.HDInsight/HDInsight
commit: dc596edd6c19f889bd5f9089734dbabfae7bca77
repo: Azure/azure-rest-api-specs
Generated schema comparison:
legacy resource detection: 4 resources
resolveArmResources detection: 10 resources
The 6 extra resolveArmResources resources are:
Microsoft.HDInsight/clusters/applications/azureasyncoperations
Microsoft.HDInsight/clusters/azureasyncoperations
Microsoft.HDInsight/clusters/configurations
Microsoft.HDInsight/clusters/extensions
Microsoft.HDInsight/clusters/extensions/azureAsyncOperations
Microsoft.HDInsight/clusters/scriptExecutionHistory
The Bicep reference includes the package API version (2025-01-15-preview) for the real HDInsight resources, for example:
https://learn.microsoft.com/en-us/azure/templates/microsoft.hdinsight/2025-01-15-preview/clusters?pivots=deployment-language-bicep
But all 6 extra resolveArmResources resource types return 404 in the Bicep reference.
Spec evidence
client.tsp explicitly says these are not standalone ARM resources and scopes them out for C#:
/*
* @@scope suppressions for C# SDK generation.
*
* The HDInsight ARM resource hierarchy has exactly 4 resource types
* (see https://learn.microsoft.com/en-us/azure/templates/microsoft.hdinsight):
* - Microsoft.HDInsight/clusters
* - Microsoft.HDInsight/clusters/applications
* Operations below are NOT standalone ARM resources — they are action endpoints
* or sub-operations on the Cluster resource. Without suppression, the MPG generator
* would create phantom resource types (e.g., clusters/azureasyncoperations,
* clusters/extensions) due to extra path segments being interpreted as child resources.
*/
@@scope(Configurations.update, "!csharp");
@@scope(Configurations.get, "!csharp");
@@scope(VirtualMachines.restartHosts, "!csharp");
@@scope(VirtualMachines.getAsyncOperationStatus, "!csharp");
@@scope(Applications.getAzureAsyncOperationStatus, "!csharp");
@@scope(Clusters.getAzureAsyncOperationStatus, "!csharp");
@@scope(Extensions.getAzureAsyncOperationStatus, "!csharp");
@@scope(Extensions.get, "!csharp");
@@scope(Extensions.delete, "!csharp");
@@scope(ScriptActions.getExecutionAsyncOperationStatus, "!csharp");
@@scope(ScriptActions.getExecutionDetail, "!csharp");
@@scope(LocationsOperationGroup.getAzureAsyncOperationStatus, "!csharp");
Experiment
I temporarily removed @@scope(Configurations.get, "!csharp") and regenerated the .NET SDK with saved inputs.
Result:
- The legacy detector still reported only the 4 real HDInsight resources.
Microsoft.HDInsight.Configurations.get became visible to the legacy detector, but legacy classified it as an Action on Microsoft.HDInsight/clusters, not as a Microsoft.HDInsight/clusters/configurations resource.
resource: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.HDInsight/clusters/{clusterName}
kind: Action
operationPath: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.HDInsight/clusters/{clusterName}/configurations/{configurationName}
So the issue is not that C# scope is hiding a real resource from legacy detection. The issue is that resolveArmResources promotes the path into a false child resource.
Expected behavior
resolveArmResources should not create concrete resources for action/status/sub-operation endpoints that are not valid ARM resource types.
At minimum, the resolver should align with the proposed design/linter direction in the doc PR: resource detection should come from valid Read/Create resource instance paths whose response shape matches the resource, and resolver output should honor language scope/projection when used for SDK generation.
Related context
Description
resolveArmResourcescan promote HDInsight action/status/sub-operation endpoints into false ARM resources. These paths are not valid Bicep resources, and the HDInsight spec explicitly scopes several of them out for C# generation.Real case: HDInsight
Spec location used by .NET SDK generation:
Generated schema comparison:
The 6 extra
resolveArmResourcesresources are:The Bicep reference includes the package API version (
2025-01-15-preview) for the real HDInsight resources, for example:https://learn.microsoft.com/en-us/azure/templates/microsoft.hdinsight/2025-01-15-preview/clusters?pivots=deployment-language-bicep
But all 6 extra
resolveArmResourcesresource types return 404 in the Bicep reference.Spec evidence
client.tspexplicitly says these are not standalone ARM resources and scopes them out for C#:Experiment
I temporarily removed
@@scope(Configurations.get, "!csharp")and regenerated the .NET SDK with saved inputs.Result:
Microsoft.HDInsight.Configurations.getbecame visible to the legacy detector, but legacy classified it as anActiononMicrosoft.HDInsight/clusters, not as aMicrosoft.HDInsight/clusters/configurationsresource.So the issue is not that C# scope is hiding a real resource from legacy detection. The issue is that
resolveArmResourcespromotes the path into a false child resource.Expected behavior
resolveArmResourcesshould not create concrete resources for action/status/sub-operation endpoints that are not valid ARM resource types.At minimum, the resolver should align with the proposed design/linter direction in the doc PR: resource detection should come from valid Read/Create resource instance paths whose response shape matches the resource, and resolver output should honor language scope/projection when used for SDK generation.
Related context
ArmResourceRead<ParentResource>returning non-resource DTOs