Splitting this out as the systemic root cause behind a recurring class of bugs (#135, #136 / #137, and the four just fixed in #154).
Problem
For List<X>Response structs, generate.go derives the JSON wrapper tag from strings.ToLower(parseSingular(listName)). But the key CloudStack actually returns is set server-side via setObjectName(...), and it is frequently not what parseSingular produces:
- camelCase:
listHypervisorCapabilities → server hypervisorCapabilities, generator hypervisorcapability
-xes plural: …Ipv6Prefixes → Prefixe (also corrupts the element type name), server guestnetworkipv6prefix
- hand-chosen keys:
listLBHealthCheckPolicies → server healthcheckpolicies (drops the lb, stays plural), generator lbhealthcheckpolicy
When the tag is wrong, json.Unmarshal populates Count but leaves the slice nil — silent data loss — and the generated Get<X>ByID helper then panics on slice[0].
Current mitigation doesn’t scale
generateResponseType already carries a hand-maintained override switch (~30 cases, incl. the metrics ones) that exists precisely to patch this. Each new case is added reactively, only after a user hits a nil slice. #154 adds four more; there are almost certainly others not yet reported.
Note: listApis.json (the generator input) does not expose the list wrapper object name — it carries each item’s response fields and related, but not the setObjectName value — so the correct key can’t simply be read from there.
Proposed directions
- Harden
parseSingular for the regular English plurals it currently mishandles — -xes/-ses/-ches/-shes → drop es (it already does -ies/-sses). This fixes the Prefixe type-name corruption and several tags for free, shrinking the override set.
- Make the override set verifiable instead of reactive: add a CI/test check that asserts each
List<X>Response tag against the keys in the test/testdata/*.json fixtures (and/or a captured real response), so drift is caught at build time rather than by users in production.
- Optionally, a curated
command → objectName override map (cleaner than inline switch cases) seeded from the verified keys.
I verified the #154 keys against the CloudStack server source (setObjectName) and have a 4.22 environment; happy to take on (1) and/or (2) if a maintainer signals a preferred direction.
Splitting this out as the systemic root cause behind a recurring class of bugs (#135, #136 / #137, and the four just fixed in #154).
Problem
For
List<X>Responsestructs,generate.goderives the JSON wrapper tag fromstrings.ToLower(parseSingular(listName)). But the key CloudStack actually returns is set server-side viasetObjectName(...), and it is frequently not whatparseSingularproduces:listHypervisorCapabilities→ serverhypervisorCapabilities, generatorhypervisorcapability-xesplural:…Ipv6Prefixes→Prefixe(also corrupts the element type name), serverguestnetworkipv6prefixlistLBHealthCheckPolicies→ serverhealthcheckpolicies(drops thelb, stays plural), generatorlbhealthcheckpolicyWhen the tag is wrong,
json.UnmarshalpopulatesCountbut leaves the slice nil — silent data loss — and the generatedGet<X>ByIDhelper then panics onslice[0].Current mitigation doesn’t scale
generateResponseTypealready carries a hand-maintained overrideswitch(~30 cases, incl. the metrics ones) that exists precisely to patch this. Each new case is added reactively, only after a user hits a nil slice. #154 adds four more; there are almost certainly others not yet reported.Note:
listApis.json(the generator input) does not expose the list wrapper object name — it carries each item’sresponsefields andrelated, but not thesetObjectNamevalue — so the correct key can’t simply be read from there.Proposed directions
parseSingularfor the regular English plurals it currently mishandles —-xes/-ses/-ches/-shes→ dropes(it already does-ies/-sses). This fixes thePrefixetype-name corruption and several tags for free, shrinking the override set.List<X>Responsetag against the keys in thetest/testdata/*.jsonfixtures (and/or a captured real response), so drift is caught at build time rather than by users in production.command → objectNameoverride map (cleaner than inlineswitchcases) seeded from the verified keys.I verified the #154 keys against the CloudStack server source (
setObjectName) and have a 4.22 environment; happy to take on (1) and/or (2) if a maintainer signals a preferred direction.