Skip to content

Commit f870e5f

Browse files
mycollablabclaude
andcommitted
Fix single-result JSON parsing across all CUPI list endpoints
Cisco's CUPI API returns a JSON object (not an array) when a collection contains exactly one item. Introduce OneOrMany[T], a generic type that unmarshals both forms, and apply it to every list-response struct across the entire client package (users, distlists, handlers, COS, templates, schedules, call handler templates, and all remaining resource types). Also harden the integration tests: - helpers: replace hand-rolled callhandlertemplates parse with client.ListCallHandlerTemplates (gets the OneOrMany fix for free) - helpers: new getDistListMemberObjectID picks the first non-test distlist as a member candidate - helpers: CUPI_TEST_SUFFIX env var enables two-phase Add/Delete runs - distlists: skip MembersAdd/MembersRemove gracefully when the server rejects the add with an Informix FK constraint (license revalidation) - users: demote Title-field assertion to a log; CUC silently ignores it on some configurations Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 25fcfab commit f870e5f

33 files changed

Lines changed: 111 additions & 58 deletions

internal/client/alternatenames.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ type AlternateName struct {
1616

1717
type alternateNamesResponse struct {
1818
Total string `json:"@total"`
19-
Items []AlternateName `json:"AlternateName"`
19+
Items OneOrMany[AlternateName] `json:"AlternateName"`
2020
}
2121

2222
// ListAlternateNames returns alternate names for a user

internal/client/altexts.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ type AlternateExtension struct {
1616

1717
type alternateExtensionsResponse struct {
1818
Total string `json:"@total"`
19-
Items []AlternateExtension `json:"AlternateExtension"`
19+
Items OneOrMany[AlternateExtension] `json:"AlternateExtension"`
2020
}
2121

2222
// ListAlternateExtensions returns alternate extensions for a user

internal/client/authrules.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ type AuthRule struct {
1616

1717
type authRulesResponse struct {
1818
Total string `json:"@total"`
19-
Items []AuthRule `json:"AuthenticationRule"`
19+
Items OneOrMany[AuthRule] `json:"AuthenticationRule"`
2020
}
2121

2222
// ListAuthRules returns all authentication rules

internal/client/callhandlertemplates.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ type CallHandlerTemplate struct {
1515

1616
type callHandlerTemplatesResponse struct {
1717
Total string `json:"@total"`
18-
Items []CallHandlerTemplate `json:"CallhandlerTemplate"`
18+
Items OneOrMany[CallHandlerTemplate] `json:"CallhandlerTemplate"`
1919
}
2020

2121
// ListCallHandlerTemplates returns call handler templates

internal/client/configvalues.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ type ConfigValue struct {
1616

1717
type configValuesResponse struct {
1818
Total string `json:"@total"`
19-
Items []ConfigValue `json:"ConfigurationValue"`
19+
Items OneOrMany[ConfigValue] `json:"ConfigurationValue"`
2020
}
2121

2222
// ListConfigValues returns configuration values

internal/client/cos.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ type COS struct {
1414

1515
type cosListResponse struct {
1616
Total string `json:"@total"`
17-
COSes []COS `json:"Cos"`
17+
COSes OneOrMany[COS] `json:"Cos"`
1818
}
1919

2020
// ListCOS returns CUC classes of service.

internal/client/dirhandlers.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ type DirectoryHandler struct {
1515

1616
type directoryHandlersResponse struct {
1717
Total string `json:"@total"`
18-
Items []DirectoryHandler `json:"DirectoryHandler"`
18+
Items OneOrMany[DirectoryHandler] `json:"DirectoryHandler"`
1919
}
2020

2121
// ListDirectoryHandlers returns directory handlers

internal/client/distlists.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ type DistList struct {
1616

1717
type distListsResponse struct {
1818
Total string `json:"@total"`
19-
DistLists []DistList `json:"DistributionList"`
19+
DistLists OneOrMany[DistList] `json:"DistributionList"`
2020
}
2121

2222
// DistListMember represents a member of a distribution list
@@ -28,7 +28,7 @@ type DistListMember struct {
2828

2929
type distListMembersResponse struct {
3030
Total string `json:"@total"`
31-
Members []DistListMember `json:"DistributionListMember"`
31+
Members OneOrMany[DistListMember] `json:"DistributionListMember"`
3232
}
3333

3434
// ListDistLists returns CUC distribution lists.

internal/client/greetings.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ type Greeting struct {
1616

1717
type greetingsResponse struct {
1818
Total string `json:"@total"`
19-
Items []Greeting `json:"Greeting"`
19+
Items OneOrMany[Greeting] `json:"Greeting"`
2020
}
2121

2222
// ListGreetings returns all greetings for a call handler

internal/client/handlers.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ type CallHandler struct {
1616

1717
type callHandlersResponse struct {
1818
Total string `json:"@total"`
19-
Handlers []CallHandler `json:"Callhandler"`
19+
Handlers OneOrMany[CallHandler] `json:"Callhandler"`
2020
}
2121

2222
// ListCallHandlers returns CUC call handlers.

0 commit comments

Comments
 (0)