Skip to content

Fix list-response JSON tags + guard getRawValue against empty arrays#154

Open
jmsperu wants to merge 1 commit into
apache:mainfrom
jmsperu:fix/list-response-json-tags
Open

Fix list-response JSON tags + guard getRawValue against empty arrays#154
jmsperu wants to merge 1 commit into
apache:mainfrom
jmsperu:fix/list-response-json-tags

Conversation

@jmsperu

@jmsperu jmsperu commented Jun 20, 2026

Copy link
Copy Markdown

Fixes several list-response robustness bugs in the same family as #135/#136 (PR #137).

1. List wrapper JSON-tag mismatches (silent data loss)

The generator derives the list wrapper tag from parseSingular(), which does not always match the key CloudStack returns. When it does not, Count unmarshals but the slice stays nil — the caller silently gets an empty list, and the Get<X>ByID helper then panics on slice[0]. I verified each against the CloudStack source object names (setObjectName(...)):

API current tag correct key (source)
listHypervisorCapabilities hypervisorcapability hypervisorCapabilities
listGuestNetworkIpv6Prefixes guestnetworkipv6prefixe guestnetworkipv6prefix
listLBHealthCheckPolicies lbhealthcheckpolicy healthcheckpolicies
listLBStickinessPolicies lbstickinesspolicy stickinesspolicies

Fixed via explicit cases in the generator override switch (right where the metrics cases from #135/#136 already live) plus the regenerated tags. The inner healthcheckpolicy / stickinesspolicy tags are correct and left untouched.

(I also checked the other -ies/-es siblings — autoscalepolicy, backuprepository, oscategory, snapshotpolicy, webhookdelivery — and they match the source, so they are not touched here.)

2. getRawValue() panic on empty count-wrapped array

In the count-wrapped branch, getRawValue did return resp[0], nil with no length check, so a {"count":0,"<entity>":[]} body panics with index-out-of-range. Now returns a descriptive error. Latent/defensive (only a malformed/edge-case body reaches it), not a live crash.

Tests

  • test/ListResponseJSONTagsRegression_test.go — unmarshals each of the 4 responses under the correct key; fails on the old tags (nil slice), passes with the fix.
  • cloudstack/GetRawValueGuard_test.gopanics without the guard (reproduces the index-out-of-range), passes with it.

Verification

  • go build ./... clean; both regression tests pass with the fix and fail/panic when reverted.

Note (follow-up, not in this PR)

The root cause is that wrapper keys are fabricated from parseSingular() rather than sourced from the API’s declared object name. A systemic fix would source the key from listApis.json / a curated override map. Happy to open a separate issue for that.

Several List<X>Response structs use a json tag that does not match the key
CloudStack actually returns (the generator derives it from parseSingular()),
so Count parses but the slice stays nil — silent data loss. Verified against
the CloudStack source object names (setObjectName):

- listHypervisorCapabilities: hypervisorcapability -> hypervisorCapabilities
- listGuestNetworkIpv6Prefixes: guestnetworkipv6prefixe -> guestnetworkipv6prefix
- listLBHealthCheckPolicies: lbhealthcheckpolicy -> healthcheckpolicies
- listLBStickinessPolicies: lbstickinesspolicy -> stickinesspolicies

Fixed via explicit cases in the generator's override switch (alongside the
existing metrics cases) and the regenerated tags.

Also guards getRawValue() against a count-wrapped response carrying an empty
data array, which previously panicked on resp[0] (index out of range); it now
returns a descriptive error.

Adds regression tests for both.

Signed-off-by: James Peru <james@xcobean.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant