Skip to content

Make Name field match what service returns#44118

Open
matthchr wants to merge 1 commit into
mainfrom
matthchr/fix-resource-sku-zone-details
Open

Make Name field match what service returns#44118
matthchr wants to merge 1 commit into
mainfrom
matthchr/fix-resource-sku-zone-details

Conversation

@matthchr

Copy link
Copy Markdown
Member

ARM (Control Plane) API Specification Update Pull Request

Tip

Overwhelmed by all this guidance? See the Getting help section at the bottom of this PR description.

PR review workflow diagram

Please understand this diagram before proceeding. It explains how to get your PR approved & merged.

spec_pr_review_workflow_diagram

Purpose of this PR

What's the purpose of this PR? Check the specific option that applies. This is mandatory!

Due diligence checklist

To merge this PR, you must go through the following checklist and confirm you understood
and followed the instructions by checking all the boxes:

  • I confirm this PR is modifying Azure Resource Manager (ARM) related specifications, and not data plane related specifications.
  • I have reviewed following Resource Provider guidelines, including
    ARM resource provider contract and
    REST guidelines (estimated time: 4 hours).
    I understand this is required before I can proceed to the diagram Step 2, "ARM API changes review", for this PR.
  • A release plan has been created. If not, please create one as it will help guide you through the REST API and SDK creation process.

Additional information

Viewing API changes

For convenient view of the API changes made by this PR, refer to the URLs provided in the table
in the Generated ApiView comment added to this PR. You can use ApiView to show API versions diff.

Suppressing failures

If one or multiple validation error/warning suppression(s) is detected in your PR, please follow the
suppressions guide to get approval.

Getting help

  • First, please carefully read through this PR description, from top to bottom. Please fill out the Purpose of this PR and Due diligence checklist.
  • If you don't have permissions to remove or add labels to the PR, request write access per aka.ms/azsdk/access#request-access-to-rest-api-or-sdk-repositories
  • To understand what you must do next to merge this PR, see the Next Steps to Merge comment. It will appear within few minutes of submitting this PR and will continue to be up-to-date with current PR state.
  • For guidance on fixing this PR CI check failures, see the hyperlinks provided in given failure
    and https://aka.ms/ci-fix.
  • For help with ARM review (PR workflow diagram Step 2), see https://aka.ms/azsdk/pr-arm-review.
  • If the PR CI checks appear to be stuck in queued state, please add a comment with contents /azp run.
    This should result in a new comment denoting a PR validation pipeline has started and the checks should be updated after few minutes.
  • If the help provided by the previous points is not enough, post to https://aka.ms/azsdk/support/specreview-channel and link to this PR.
  • For guidance on SDK breaking change review, refer to https://aka.ms/ci-fix.

@github-actions

github-actions Bot commented Jun 20, 2026

Copy link
Copy Markdown

Next Steps to Merge

Next steps that must be taken to merge this PR:
  • ❌ This PR targets either the main branch of the public specs repo or the RPSaaSMaster branch of the private specs repo. These branches are not intended for iterative development. Therefore, you must acknowledge you understand that after this PR is merged, the APIs are considered shipped to Azure customers. Any further attempts at in-place modifications to the APIs will be subject to Azure's versioning and breaking change policies. Additionally, for control plane APIs, you must acknowledge that you are following all the best practices documented by ARM at aka.ms/armapibestpractices. If you do intend to release the APIs to your customers by merging this PR, add the PublishToCustomers label to your PR in acknowledgement of the above. Otherwise, retarget this PR onto a feature branch, i.e. with prefix release- (see aka.ms/azsdk/api-versions#release--branches).
  • ❌ This PR is in purview of the ARM review (label: ARMReview). This PR must get ARMSignedOff label from an ARM reviewer.
    This PR is not ready for ARM review (label: NotReadyForARMReview). This PR will not be reviewed by ARM until relevant problems are fixed. Consult the rest of this Next Steps to Merge comment for details.
    Once the blocking problems are addressed, add to the PR a comment with contents /azp run. Automation will re-evaluate this PR and if everything looks good, it will add WaitForARMFeedback label which will put this PR on the ARM review queue.
    For details of the ARM review, see aka.ms/azsdk/pr-arm-review
  • ❌ This PR is NotReadyForARMReview because it has the BreakingChangeReviewRequired label.
  • ❌ This PR has at least one breaking change (label: BreakingChangeReviewRequired).
    To unblock this PR, follow the process at aka.ms/brch.
  • ❌ The required check named TypeSpec Validation has failed. Refer to the check in the PR's 'Checks' tab for details on how to fix it and consult the aka.ms/ci-fix guide


Comment generated by summarize-checks workflow run.

@github-actions github-actions Bot added ARMReview resource-manager TypeSpec Authored with TypeSpec WaitForARMFeedback <valid label in PR review process> add this label when ARM review is required labels Jun 20, 2026
@github-actions

github-actions Bot commented Jun 20, 2026

Copy link
Copy Markdown

API Change Check

APIView identified API level changes in this PR and created the following API reviews

Language API Review for Package
TypeSpec ComputeSku
Java com.azure.resourcemanager:azure-resourcemanager-compute
Python azure-mgmt-compute
Swagger Microsoft.Compute-Compute
Go sdk/resourcemanager/compute/armcompute
JavaScript @azure/arm-compute
C# Azure.ResourceManager.Compute

Comment generated by After APIView workflow run.

@ravimeda ravimeda left a comment

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.

ARM API Review

Posting findings from the ARM API Reviewer agent (critic-verified, 1 iteration, converged) against commit 8412021. See the inline comment for finding 1. Findings 2–4 below concern a line and a file outside this PR's diff (models.tsp line 192 and the generated skus.json), so they are posted here as a top-level comment.


2. [NEW] 🔴 Blocking [XmsIdentifierValidation (R4041)] specification/compute/resource-manager/Microsoft.Compute/Compute/ComputeSku/models.tsp — line 192 — @identifiers(#["name"]) references a renamed property.

The zoneDetails?: ResourceSkuZoneDetails[] array (line 193, model ResourceSkuLocationInfo) declares @identifiers(#["name"]), pointing at ResourceSkuZoneDetails.name. This PR renamed that property to Name, so after the swagger regenerates, the emitted x-ms-identifiers: ["name"] on zoneDetails will reference a non-existent property → XmsIdentifierValidation failure. If the rename is kept, update to @identifiers(#["Name"]). If the @encodedName fix in finding 1 is adopted, the property stays name so this decorator is valid — verify the emitted x-ms-identifiers resolves to the wire name. (The second @identifiers(#["name"]) at line 222 targets ResourceSkuCapabilities.name, unchanged — not affected.)

3. [NEW] 🔴 Blocking [TypeSpec generated output must match source] specification/compute/resource-manager/Microsoft.Compute/Compute/stable/2021-07-01/skus.jsonResourceSkuZoneDetails, line 413 — Generated swagger not regenerated.

The PR changes only models.tsp; the committed skus.json still declares name. TypeSpec source and generated OpenAPI are out of sync, so the TypeSpec Validation CI check (which regenerates and diffs) will fail. Regenerate the ComputeSku project and commit the updated skus.json.

4. [NEW] 🟠 Warning [Breaking changes guidelines] specification/compute/resource-manager/Microsoft.Compute/Compute/stable/2021-07-01/skus.jsonResourceSkuZoneDetails.name, line 413 — In-place breaking change to a released stable version.

Renaming a property in the already-shipped stable 2021-07-01 is a wire-contract breaking change that OAD will flag once the swagger regenerates, and released versions are normally immutable. The service-correctness rationale supports an in-place fix, but the breaking-change review/suppression flow must be followed and ARM should confirm an in-place edit (vs. a new version) is acceptable.


Worth surfacing — the underlying tension: The service returns PascalCase Name, so any faithful spec carries a PascalCase wire name. @encodedName keeps the TypeSpec/SDK property camelCase, but the emitted swagger property is still Name, which may itself need a swagger-level naming suppression in LintDiff. This tension can only be managed (encodedName + breaking-change approval + possibly a suppression), not eliminated in the spec — the truly correct long-term fix is service-side (return name).

@ravimeda ravimeda added ARMChangesRequested and removed WaitForARMFeedback <valid label in PR review process> add this label when ARM review is required labels Jun 22, 2026
@matthchr matthchr force-pushed the matthchr/fix-resource-sku-zone-details branch from 8412021 to 6b09604 Compare June 22, 2026 21:01
@matthchr

Copy link
Copy Markdown
Member Author

Good comments @ravimeda, I've fixed them and pushed. Also rebased so this is based on latest main to get rid of the "out of date branch" comment

@github-actions github-actions Bot added BreakingChangeReviewRequired <valid label in PR review process>add this label when breaking change review is required NotReadyForARMReview and removed ARMChangesRequested labels Jun 22, 2026
@matthchr

Copy link
Copy Markdown
Member Author

Here's an example raw REST response that shows the current response mismatches with the documented API shape:

    {
      "capabilities": [
        {
          "name": "MaxSizeGiB",
          "value": "65536"
        },
        {
          "name": "MinSizeGiB",
          "value": "1"
        },
        {
          "name": "MaxIOpsReadWrite",
          "value": "80000"
        },
        {
          "name": "MinIOpsReadWrite",
          "value": "3000"
        },
        {
          "name": "MaxBandwidthMBpsReadWrite",
          "value": "2000"
        },
        {
          "name": "MinBandwidthMBpsReadWrite",
          "value": "125"
        },
        {
          "name": "MaxValueOfMaxShares",
          "value": "15"
        },
        {
          "name": "MinIOSizeKiBps",
          "value": "4"
        },
        {
          "name": "MaxIOSizeKiBps",
          "value": "256"
        },
        {
          "name": "MinIopsReadOnly",
          "value": "3000"
        },
        {
          "name": "MaxIopsReadOnly",
          "value": "80000"
        },
        {
          "name": "MinBandwidthMBpsReadOnly",
          "value": "125"
        },
        {
          "name": "MaxBandwidthMBpsReadOnly",
          "value": "2000"
        },
        {
          "name": "MaxIopsPerGiBReadWrite",
          "value": "500"
        },
        {
          "name": "MaxIopsPerGiBReadOnly",
          "value": "500"
        },
        {
          "name": "MinIopsPerGiBReadWrite",
          "value": "1"
        },
        {
          "name": "MinIopsPerGiBReadOnly",
          "value": "1"
        },
        {
          "name": "BillingPartitionSizes",
          "value": "1, 2, 3, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192, 9216, 10240, 11264, 12288, 13312, 14336, 15360, 16384, 17408, 18432, 19456, 20480, 21504, 22528, 23552,24576,25600,26624,27648,28672,29696,30720,31744,32768,33792,34816,35840,36864,37888,38912,39936,40960,41984,43008,44032,45056,46080,47104,48128,49152,50176,51200,52224,53248,54272,55296,56320,57344,58368,59392,60416,61440,62464,63488,64512,65536"
        },
        {
          "name": "MaxZonalFaultDomainCount",
          "value": "2"
        },
        {
          "name": "PlatformFaultDomainCount",
          "value": "2"
        }
      ],
      "locationInfo": [
        {
          "location": "eastus2euap",
          "zoneDetails": [
            {
              "Name": [
                "3"
              ],
              "capabilities": [
                {
                  "name": "MaxFaultDomainCountInZone",
                  "value": "2"
                }
              ]
            },
            {
              "Name": [
                "2"
              ],
              "capabilities": [
                {
                  "name": "MaxFaultDomainCountInZone",
                  "value": "2"
                }
              ]
            }
          ],
          "zones": [
            "3",
            "2"
          ]
        }
      ],
      "locations": [
        "eastus2euap"
      ],
      "name": "PremiumV2_LRS",
      "resourceType": "disks",
      "restrictions": [],
      "size": "P",
      "tier": "Premium"
    },

@matthchr matthchr force-pushed the matthchr/fix-resource-sku-zone-details branch from 6b09604 to 8d33b47 Compare June 22, 2026 21:44
@matthchr

matthchr commented Jul 1, 2026

Copy link
Copy Markdown
Member Author

Here's an AI report of this issue's impact in the various SDKs:

Azure SDK Case-Sensitivity Report: ResourceSkuZoneDetails.name

Background

  • Issue (Azure/azure-sdk-for-go#23342): The Compute Resource Skus - List API returns the zone-details field as Name (capital N), but the OpenAPI/TypeSpec spec declared it as name (lowercase). The Go SDK deserializes only name, so ZoneDetails[].Name always came back empty.
  • Fix (Azure/azure-rest-api-specs#44118): Change the wire name to Name (via @encodedName("application/json", "Name") in TypeSpec / "Name" + "x-ms-client-name": "name" in the swagger) so the generated code reads the key the service actually sends, while still exposing the property to users as name.

Conclusion (headline)

All three SDKs — Go, C#, and Python — are case-sensitive on this field. Go is the one that got reported, but C# and Python were equally broken. None of them would populate the field when the service returns Name. This is why the fix had to be made in the spec (change the wire name) rather than per-language — a case-insensitive language would not have needed the fix.


1. Go — case-sensitive ❌ (confirmed broken)

Generated UnmarshalJSON uses a switch over the raw JSON key with a literal "name" case:

sdk/resourcemanager/compute/armcompute/models_serde.go L11106–11117

func (r *ResourceSKUZoneDetails) UnmarshalJSON(data []byte) error {
        ...
        for key, val := range rawMsg {
                switch key {
                case "capabilities":
                        err = unpopulate(val, "Capabilities", &r.Capabilities)
                case "name":                          // <-- exact, lowercase match only
                        err = unpopulate(val, "Name", &r.Name)
                }
        }
}

A Go switch on a string does an exact comparison, so "Name" never matches case "name". The issue author proved this — his repro prints 0 for len(d.Name).

2. C# — case-sensitive ❌ (broken)

The System.Text.Json–based generated deserializer matches with JsonProperty.NameEquals("name"u8):

sdk/compute/Azure.ResourceManager.Compute/src/Generated/Models/ComputeResourceSkuZoneDetails.Serialization.cs L147–189

foreach (var prop in element.EnumerateObject())
{
    if (prop.NameEquals("name"u8))   // ordinal, case-sensitive UTF-8 byte compare
    {
        ...
        name = array;
        continue;
    }
    if (prop.NameEquals("capabilities"u8)) { ... }

    if (options.Format != "W")
    {
        // unmatched keys ("Name") fall through to here and are discarded into raw data
        additionalBinaryDataProperties.Add(prop.Name, BinaryData.FromString(prop.Value.GetRawText()));
    }
}

JsonProperty.NameEquals(ReadOnlySpan<byte>) performs an ordinal (case-sensitive) byte comparison — it is not affected by any PropertyNameCaseInsensitive option because the matching is hand-written, not reflection-based. So a wire key of Name fails all NameEquals checks, name stays default (null → empty ChangeTrackingList), and the Name value is silently swept into additionalBinaryDataProperties. Broken, same as Go.

3. Python — case-sensitive ❌ (broken)

The current Compute SDK uses the new TypeSpec _Model base (not legacy msrest). The field is a plain rest_field() with no explicit wire name:

sdk/compute/azure-mgmt-compute/azure/mgmt/compute/models/_models.py L14783

class ResourceSkuZoneDetails(_Model):
    name: Optional[list[str]] = rest_field(visibility=["read"])   # wire name defaults to "name"

_Model stores the raw JSON dict verbatim and resolves attributes lazily through the descriptor, using a plain dict lookup on the wire name:

azure/mgmt/compute/_utils/model_base.py_RestField.__get__ L1413–1417 and _rest_name L1406–1410:

@property
def _rest_name(self) -> str:
    if self._rest_name_input is None:
        raise ValueError(...)
    return self._rest_name_input          # == "name" (defaults to the attribute name)

def __get__(self, obj, type=None):
    item = obj._data.get(self._rest_name, _UNSET)   # obj._data is the raw JSON dict
    if item is _UNSET:
        return self._default if ... else None       # -> None when key is "Name"

obj._data.get("name") is an ordinary, case-sensitive dict lookup against the raw payload. When the service sends Name, _data has key "Name", so .get("name") misses and .name returns None. Broken, same as Go and C#. (Note: the older msrest-based Python generation was likewise case-sensitive via exact attribute-map keys, so this is not a regression.)


Summary table

SDK Read mechanism Match Result when service returns Name
Go switch key { case "name": } exact string ❌ empty (len==0)
C# JsonProperty.NameEquals("name"u8) ordinal / case-sensitive bytes ❌ null; value dumped into raw additionalBinaryDataProperties
Python _data.get("name") dict lookup case-sensitive key None

Bottom line: none of Go, C#, or Python are case-insensitive here. The correct fix is exactly what PR #44118 does — align the spec wire name to Name (keeping the client-facing name name), which regenerates all three SDKs to read the key the service actually returns.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ARMReview BreakingChangeReviewRequired <valid label in PR review process>add this label when breaking change review is required Compute NotReadyForARMReview resource-manager TypeSpec Authored with TypeSpec

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants