abh1sar opened a new pull request, #162:
URL: https://github.com/apache/cloudstack-go/pull/162
### Description
CloudStack keys a list response's item array by the **response object** name
(`UserVmResponse` serialises as `virtualmachine`, `TemplateResponse` as
`template`). The generator derived that key from the **API name** instead, and
carried the exceptions in a switch of hand-written arms.
Where an API's response object does not share its name and no arm existed,
the generated tag never matched the key on the wire. The failure is silent and
therefore expensive: `count` parses from the same body, so a caller sees a
correct count beside an empty slice and **no error**.
Sweeping all 210 list APIs against three servers found **16** such APIs:
| API | Struct tag | Server sends |
| --- | --- | --- |
| `listASNRanges` | `asnrange` | `asnumberrange` |
| `listBackupProviders` | `backupprovider` | `providers` |
| `listCaCertificate` | `cacertificate` | `cacertificates` |
| `listClustersMetrics` | `clustersmetric` | `cluster` |
| `listCustomActions` | `customaction` | `extensioncustomaction` |
| `listHostsMetrics` | `hostsmetric` | `host` |
| `listIpv4SubnetsForZone` | `ipv4subnetsforzone` | `zoneipv4subnet` |
| `listNetworkIsolationMethods` | `networkisolationmethod` |
`isolationmethod` |
| `listRoutingFirewallRules` | `routingfirewallrule` | `firewallrule` |
| `listSupportedNetworkServices` | `supportednetworkservice` |
`networkservice` |
| `listSystemVmsUsageHistory` | `systemvmsusagehistory` | `virtualmachine` |
| `listTrafficTypeImplementors` | `traffictypeimplementor` |
`traffictypeimplementorresponse` |
| `listUsageServerMetrics` | `usageservermetric` | `usageMetrics` |
| `listUserTwoFactorAuthenticatorProviders` |
`usertwofactorauthenticatorprovider` | `providers` |
| `listVolumesMetrics` | `volumesmetric` | `volume` |
| `listZonesMetrics` | `zonesmetric` | `zone` |
The gaps fall into families, which is the clearest sign the exception list
was maintained reactively:
| Family | Already had an arm | Was still broken |
| --- | --- | --- |
| `list*Metrics` | VirtualMachines, StoragePools, ManagementServers, Db |
Clusters, Hosts, Volumes, Zones, UsageServer |
| `list*UsageHistory` | Volumes, VirtualMachines | SystemVms |
`#154` and `#161` each fixed instances of this same class, so this would
have been the third and fourth time it was patched case by case.
### Why the key is not derived
Deriving it was the obvious fix and it is not possible. `listApis` reports
each response object's *fields* but never its *name*, and `related` is empty
for exactly the affected APIs, so the generator's only input cannot reconcile
the two names:
```
--- listZonesMetrics ---
top-level fields: ['description', 'isasync', 'name', 'params', 'related',
'response', 'since']
related:
```
So the exceptions stay data, but become *good* data: a single documented
`listResponseKeys` map replaces 24 switch arms, leaving only genuine **shape**
differences (single object, no count, multiple collections, hand-written field
lists) in the switch. Every entry was observed on a real server and is pinned
by a test, because a guessed entry looks deliberate and fails just as silently
as a missing one.
A `list*Metrics` derivation rule was considered and **rejected**: it would
produce `usageserver` for `listUsageServerMetrics`, whose real key is
`usageMetrics`. It would have looked like a principled generalisation while
being wrong.
### Breaking change
`listCaCertificate` and `listUsageServerMetrics` return a **single object
with no `count`**, so those two fields change from `[]*T` to `*T`. This is
source-breaking for anyone compiling against them. As with `vnfnics` in #161,
neither field could ever decode anything, so no working code can depend on it.
Worth a release note.
### Also fixed
`#154` added an empty-array guard to `getRawValue` but edited it into the
**generated** `cloudstack/cloudstack.go` without adding it to the generator, so
`make code` silently reverted it. Confirmed on a pristine `main` worktree. The
guard now lives in the generator and survives regeneration.
### Types of changes
- [x] Bug fix (non-breaking change which fixes an issue)
- [x] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Enhancement (improves an existing feature and functionality)
### How Has This Been Tested?
Against three management servers: two on **4.22.1.0** and the QA simulator
on **4.21.0.0**.
The keys were found by extracting the expected key from every generated
`List*Response`, then observing the key the server actually sends by issuing
raw requests and reading the top-level JSON keys **without decoding**, so the
observation does not depend on the code under test.
```
list APIs in the client: 210
response key observed at least once: 131
exact match: 126
case-only difference (works): 5
still broken: 0
never observable: 79
observed on both 4.21 and 4.22.1: 83 disagreements: 0
```
- **Zero remaining mismatches** among the 131 APIs whose key can be observed.
- **Zero disagreements** between 4.21 and 4.22.1 across the 83 APIs observed
on both lines, which is what makes simulator evidence usable here. The two APIs
found only on 4.21 were additionally corroborated by `setObjectName` in the
CloudStack source (`ApiResponseHelper.java`, `RoutedIpv4ManagerImpl.java`) and
by the keys the CloudStack UI itself reads.
- Five APIs differ only in letter case (`listAffinityGroupTypes`,
`listDeploymentPlanners`, `listLdapConfigurations`, `listLdapUsers`,
`listVMSnapshot`) and need no change, since `encoding/json` falls back to
case-insensitive matching. Every candidate was executed rather than judged from
the sweep, which is what separated these from real bugs.
- All 16 assertions **fail** on pristine `main` and pass here, so they are
not vacuous.
- `make code` reproduces the committed tree byte for byte; `go build`, `go
vet` and the existing suite are clean.
79 list APIs still have no observable key on any of the three environments,
mostly needing external systems (Netscaler, Swift, UCS, OpenDaylight,
baremetal), so this is the known set rather than a proof of completeness.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]