internal/genapi: correct list response body and map
When using the new auto-pagination logic, we would previously return the Body and Map of the last response, instead of one corresponding to the returned result. Correct this by overwriting the Body and Map after pagination has finished.
This commit is contained in:
1 parent
af61b688c6
commit
acc048a1d1
21 files changed
+687
-81
No files matched your search
@@ -6,6 +6,7 @@ package accounts
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@@ -352,6 +353,9 @@ func (c *Client) List(ctx context.Context, authMethodId string, opt ...Option) (
|
||||
for i, item := range target.Items {
|
||||
idToIndex[item.Id] = i
|
||||
}
|
||||
// Removed IDs in the response may contain duplicates,
|
||||
// maintain a set to avoid returning duplicates to the user.
|
||||
removedIds := map[string]struct{}{}
|
||||
for {
|
||||
req, err := c.client.NewRequest(ctx, "GET", "accounts", nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -389,7 +393,9 @@ func (c *Client) List(ctx context.Context, authMethodId string, opt ...Option) (
|
||||
idToIndex[item.Id] = len(target.Items) - 1
|
||||
}
|
||||
}
|
||||
target.RemovedIds = append(target.RemovedIds, page.RemovedIds...)
|
||||
for _, removedId := range page.RemovedIds {
|
||||
removedIds[removedId] = struct{}{}
|
||||
}
|
||||
target.EstItemCount = page.EstItemCount
|
||||
target.ListToken = page.ListToken
|
||||
target.ResponseType = page.ResponseType
|
||||
@@ -408,10 +414,34 @@ func (c *Client) List(ctx context.Context, authMethodId string, opt ...Option) (
|
||||
idToIndex[target.Items[i].Id] = i
|
||||
}
|
||||
}
|
||||
// Finally, sort the results again since in-place updates and deletes
|
||||
// may have shuffled items.
|
||||
for deletedId := range removedIds {
|
||||
target.RemovedIds = append(target.RemovedIds, deletedId)
|
||||
}
|
||||
// Sort to make response deterministic
|
||||
slices.Sort(target.RemovedIds)
|
||||
// Since we paginated to the end, we can avoid confusion
|
||||
// for the user by setting the estimated item count to the
|
||||
// length of the items slice. If we don't set this here, it
|
||||
// will equal the value returned in the last response, which is
|
||||
// often much smaller than the total number returned.
|
||||
target.EstItemCount = uint(len(target.Items))
|
||||
// Sort the results again since in-place updates and deletes
|
||||
// may have shuffled items. We sort by created time descending
|
||||
// (most recently created first), same as the API.
|
||||
slices.SortFunc(target.Items, func(i, j *Account) int {
|
||||
return i.UpdatedTime.Compare(j.UpdatedTime)
|
||||
return j.CreatedTime.Compare(i.CreatedTime)
|
||||
})
|
||||
// Finally, since we made at least 2 requests to the server to fulfill this
|
||||
// function call, resp.Body and resp.Map will only contain the most recent response.
|
||||
// Overwrite them with the true response.
|
||||
target.response.Body.Reset()
|
||||
if err := json.NewEncoder(target.response.Body).Encode(target); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final JSON list response: %w", err)
|
||||
}
|
||||
if err := json.Unmarshal(target.response.Body.Bytes(), &target.response.Map); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final map list response: %w", err)
|
||||
}
|
||||
// Note: the HTTP response body is consumed by resp.Decode in the loop,
|
||||
// so it doesn't need to be updated (it will always be, and has always been, empty).
|
||||
return target, nil
|
||||
}
|
||||
@@ -6,6 +6,7 @@ package authmethods
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@@ -358,6 +359,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Auth
|
||||
for i, item := range target.Items {
|
||||
idToIndex[item.Id] = i
|
||||
}
|
||||
// Removed IDs in the response may contain duplicates,
|
||||
// maintain a set to avoid returning duplicates to the user.
|
||||
removedIds := map[string]struct{}{}
|
||||
for {
|
||||
req, err := c.client.NewRequest(ctx, "GET", "auth-methods", nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -395,7 +399,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Auth
|
||||
idToIndex[item.Id] = len(target.Items) - 1
|
||||
}
|
||||
}
|
||||
target.RemovedIds = append(target.RemovedIds, page.RemovedIds...)
|
||||
for _, removedId := range page.RemovedIds {
|
||||
removedIds[removedId] = struct{}{}
|
||||
}
|
||||
target.EstItemCount = page.EstItemCount
|
||||
target.ListToken = page.ListToken
|
||||
target.ResponseType = page.ResponseType
|
||||
@@ -414,10 +420,34 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Auth
|
||||
idToIndex[target.Items[i].Id] = i
|
||||
}
|
||||
}
|
||||
// Finally, sort the results again since in-place updates and deletes
|
||||
// may have shuffled items.
|
||||
for deletedId := range removedIds {
|
||||
target.RemovedIds = append(target.RemovedIds, deletedId)
|
||||
}
|
||||
// Sort to make response deterministic
|
||||
slices.Sort(target.RemovedIds)
|
||||
// Since we paginated to the end, we can avoid confusion
|
||||
// for the user by setting the estimated item count to the
|
||||
// length of the items slice. If we don't set this here, it
|
||||
// will equal the value returned in the last response, which is
|
||||
// often much smaller than the total number returned.
|
||||
target.EstItemCount = uint(len(target.Items))
|
||||
// Sort the results again since in-place updates and deletes
|
||||
// may have shuffled items. We sort by created time descending
|
||||
// (most recently created first), same as the API.
|
||||
slices.SortFunc(target.Items, func(i, j *AuthMethod) int {
|
||||
return i.UpdatedTime.Compare(j.UpdatedTime)
|
||||
return j.CreatedTime.Compare(i.CreatedTime)
|
||||
})
|
||||
// Finally, since we made at least 2 requests to the server to fulfill this
|
||||
// function call, resp.Body and resp.Map will only contain the most recent response.
|
||||
// Overwrite them with the true response.
|
||||
target.response.Body.Reset()
|
||||
if err := json.NewEncoder(target.response.Body).Encode(target); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final JSON list response: %w", err)
|
||||
}
|
||||
if err := json.Unmarshal(target.response.Body.Bytes(), &target.response.Map); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final map list response: %w", err)
|
||||
}
|
||||
// Note: the HTTP response body is consumed by resp.Decode in the loop,
|
||||
// so it doesn't need to be updated (it will always be, and has always been, empty).
|
||||
return target, nil
|
||||
}
|
||||
@@ -6,6 +6,7 @@ package authtokens
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"slices"
|
||||
@@ -243,6 +244,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Auth
|
||||
for i, item := range target.Items {
|
||||
idToIndex[item.Id] = i
|
||||
}
|
||||
// Removed IDs in the response may contain duplicates,
|
||||
// maintain a set to avoid returning duplicates to the user.
|
||||
removedIds := map[string]struct{}{}
|
||||
for {
|
||||
req, err := c.client.NewRequest(ctx, "GET", "auth-tokens", nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -280,7 +284,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Auth
|
||||
idToIndex[item.Id] = len(target.Items) - 1
|
||||
}
|
||||
}
|
||||
target.RemovedIds = append(target.RemovedIds, page.RemovedIds...)
|
||||
for _, removedId := range page.RemovedIds {
|
||||
removedIds[removedId] = struct{}{}
|
||||
}
|
||||
target.EstItemCount = page.EstItemCount
|
||||
target.ListToken = page.ListToken
|
||||
target.ResponseType = page.ResponseType
|
||||
@@ -299,10 +305,34 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Auth
|
||||
idToIndex[target.Items[i].Id] = i
|
||||
}
|
||||
}
|
||||
// Finally, sort the results again since in-place updates and deletes
|
||||
// may have shuffled items.
|
||||
for deletedId := range removedIds {
|
||||
target.RemovedIds = append(target.RemovedIds, deletedId)
|
||||
}
|
||||
// Sort to make response deterministic
|
||||
slices.Sort(target.RemovedIds)
|
||||
// Since we paginated to the end, we can avoid confusion
|
||||
// for the user by setting the estimated item count to the
|
||||
// length of the items slice. If we don't set this here, it
|
||||
// will equal the value returned in the last response, which is
|
||||
// often much smaller than the total number returned.
|
||||
target.EstItemCount = uint(len(target.Items))
|
||||
// Sort the results again since in-place updates and deletes
|
||||
// may have shuffled items. We sort by created time descending
|
||||
// (most recently created first), same as the API.
|
||||
slices.SortFunc(target.Items, func(i, j *AuthToken) int {
|
||||
return i.UpdatedTime.Compare(j.UpdatedTime)
|
||||
return j.CreatedTime.Compare(i.CreatedTime)
|
||||
})
|
||||
// Finally, since we made at least 2 requests to the server to fulfill this
|
||||
// function call, resp.Body and resp.Map will only contain the most recent response.
|
||||
// Overwrite them with the true response.
|
||||
target.response.Body.Reset()
|
||||
if err := json.NewEncoder(target.response.Body).Encode(target); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final JSON list response: %w", err)
|
||||
}
|
||||
if err := json.Unmarshal(target.response.Body.Bytes(), &target.response.Map); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final map list response: %w", err)
|
||||
}
|
||||
// Note: the HTTP response body is consumed by resp.Decode in the loop,
|
||||
// so it doesn't need to be updated (it will always be, and has always been, empty).
|
||||
return target, nil
|
||||
}
|
||||
@@ -6,6 +6,7 @@ package credentiallibraries
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@@ -358,6 +359,9 @@ func (c *Client) List(ctx context.Context, credentialStoreId string, opt ...Opti
|
||||
for i, item := range target.Items {
|
||||
idToIndex[item.Id] = i
|
||||
}
|
||||
// Removed IDs in the response may contain duplicates,
|
||||
// maintain a set to avoid returning duplicates to the user.
|
||||
removedIds := map[string]struct{}{}
|
||||
for {
|
||||
req, err := c.client.NewRequest(ctx, "GET", "credential-libraries", nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -395,7 +399,9 @@ func (c *Client) List(ctx context.Context, credentialStoreId string, opt ...Opti
|
||||
idToIndex[item.Id] = len(target.Items) - 1
|
||||
}
|
||||
}
|
||||
target.RemovedIds = append(target.RemovedIds, page.RemovedIds...)
|
||||
for _, removedId := range page.RemovedIds {
|
||||
removedIds[removedId] = struct{}{}
|
||||
}
|
||||
target.EstItemCount = page.EstItemCount
|
||||
target.ListToken = page.ListToken
|
||||
target.ResponseType = page.ResponseType
|
||||
@@ -414,10 +420,34 @@ func (c *Client) List(ctx context.Context, credentialStoreId string, opt ...Opti
|
||||
idToIndex[target.Items[i].Id] = i
|
||||
}
|
||||
}
|
||||
// Finally, sort the results again since in-place updates and deletes
|
||||
// may have shuffled items.
|
||||
for deletedId := range removedIds {
|
||||
target.RemovedIds = append(target.RemovedIds, deletedId)
|
||||
}
|
||||
// Sort to make response deterministic
|
||||
slices.Sort(target.RemovedIds)
|
||||
// Since we paginated to the end, we can avoid confusion
|
||||
// for the user by setting the estimated item count to the
|
||||
// length of the items slice. If we don't set this here, it
|
||||
// will equal the value returned in the last response, which is
|
||||
// often much smaller than the total number returned.
|
||||
target.EstItemCount = uint(len(target.Items))
|
||||
// Sort the results again since in-place updates and deletes
|
||||
// may have shuffled items. We sort by created time descending
|
||||
// (most recently created first), same as the API.
|
||||
slices.SortFunc(target.Items, func(i, j *CredentialLibrary) int {
|
||||
return i.UpdatedTime.Compare(j.UpdatedTime)
|
||||
return j.CreatedTime.Compare(i.CreatedTime)
|
||||
})
|
||||
// Finally, since we made at least 2 requests to the server to fulfill this
|
||||
// function call, resp.Body and resp.Map will only contain the most recent response.
|
||||
// Overwrite them with the true response.
|
||||
target.response.Body.Reset()
|
||||
if err := json.NewEncoder(target.response.Body).Encode(target); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final JSON list response: %w", err)
|
||||
}
|
||||
if err := json.Unmarshal(target.response.Body.Bytes(), &target.response.Map); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final map list response: %w", err)
|
||||
}
|
||||
// Note: the HTTP response body is consumed by resp.Decode in the loop,
|
||||
// so it doesn't need to be updated (it will always be, and has always been, empty).
|
||||
return target, nil
|
||||
}
|
||||
@@ -6,6 +6,7 @@ package credentials
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@@ -356,6 +357,9 @@ func (c *Client) List(ctx context.Context, credentialStoreId string, opt ...Opti
|
||||
for i, item := range target.Items {
|
||||
idToIndex[item.Id] = i
|
||||
}
|
||||
// Removed IDs in the response may contain duplicates,
|
||||
// maintain a set to avoid returning duplicates to the user.
|
||||
removedIds := map[string]struct{}{}
|
||||
for {
|
||||
req, err := c.client.NewRequest(ctx, "GET", "credentials", nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -393,7 +397,9 @@ func (c *Client) List(ctx context.Context, credentialStoreId string, opt ...Opti
|
||||
idToIndex[item.Id] = len(target.Items) - 1
|
||||
}
|
||||
}
|
||||
target.RemovedIds = append(target.RemovedIds, page.RemovedIds...)
|
||||
for _, removedId := range page.RemovedIds {
|
||||
removedIds[removedId] = struct{}{}
|
||||
}
|
||||
target.EstItemCount = page.EstItemCount
|
||||
target.ListToken = page.ListToken
|
||||
target.ResponseType = page.ResponseType
|
||||
@@ -412,10 +418,34 @@ func (c *Client) List(ctx context.Context, credentialStoreId string, opt ...Opti
|
||||
idToIndex[target.Items[i].Id] = i
|
||||
}
|
||||
}
|
||||
// Finally, sort the results again since in-place updates and deletes
|
||||
// may have shuffled items.
|
||||
for deletedId := range removedIds {
|
||||
target.RemovedIds = append(target.RemovedIds, deletedId)
|
||||
}
|
||||
// Sort to make response deterministic
|
||||
slices.Sort(target.RemovedIds)
|
||||
// Since we paginated to the end, we can avoid confusion
|
||||
// for the user by setting the estimated item count to the
|
||||
// length of the items slice. If we don't set this here, it
|
||||
// will equal the value returned in the last response, which is
|
||||
// often much smaller than the total number returned.
|
||||
target.EstItemCount = uint(len(target.Items))
|
||||
// Sort the results again since in-place updates and deletes
|
||||
// may have shuffled items. We sort by created time descending
|
||||
// (most recently created first), same as the API.
|
||||
slices.SortFunc(target.Items, func(i, j *Credential) int {
|
||||
return i.UpdatedTime.Compare(j.UpdatedTime)
|
||||
return j.CreatedTime.Compare(i.CreatedTime)
|
||||
})
|
||||
// Finally, since we made at least 2 requests to the server to fulfill this
|
||||
// function call, resp.Body and resp.Map will only contain the most recent response.
|
||||
// Overwrite them with the true response.
|
||||
target.response.Body.Reset()
|
||||
if err := json.NewEncoder(target.response.Body).Encode(target); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final JSON list response: %w", err)
|
||||
}
|
||||
if err := json.Unmarshal(target.response.Body.Bytes(), &target.response.Map); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final map list response: %w", err)
|
||||
}
|
||||
// Note: the HTTP response body is consumed by resp.Decode in the loop,
|
||||
// so it doesn't need to be updated (it will always be, and has always been, empty).
|
||||
return target, nil
|
||||
}
|
||||
@@ -6,6 +6,7 @@ package credentialstores
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@@ -357,6 +358,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Cred
|
||||
for i, item := range target.Items {
|
||||
idToIndex[item.Id] = i
|
||||
}
|
||||
// Removed IDs in the response may contain duplicates,
|
||||
// maintain a set to avoid returning duplicates to the user.
|
||||
removedIds := map[string]struct{}{}
|
||||
for {
|
||||
req, err := c.client.NewRequest(ctx, "GET", "credential-stores", nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -394,7 +398,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Cred
|
||||
idToIndex[item.Id] = len(target.Items) - 1
|
||||
}
|
||||
}
|
||||
target.RemovedIds = append(target.RemovedIds, page.RemovedIds...)
|
||||
for _, removedId := range page.RemovedIds {
|
||||
removedIds[removedId] = struct{}{}
|
||||
}
|
||||
target.EstItemCount = page.EstItemCount
|
||||
target.ListToken = page.ListToken
|
||||
target.ResponseType = page.ResponseType
|
||||
@@ -413,10 +419,34 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Cred
|
||||
idToIndex[target.Items[i].Id] = i
|
||||
}
|
||||
}
|
||||
// Finally, sort the results again since in-place updates and deletes
|
||||
// may have shuffled items.
|
||||
for deletedId := range removedIds {
|
||||
target.RemovedIds = append(target.RemovedIds, deletedId)
|
||||
}
|
||||
// Sort to make response deterministic
|
||||
slices.Sort(target.RemovedIds)
|
||||
// Since we paginated to the end, we can avoid confusion
|
||||
// for the user by setting the estimated item count to the
|
||||
// length of the items slice. If we don't set this here, it
|
||||
// will equal the value returned in the last response, which is
|
||||
// often much smaller than the total number returned.
|
||||
target.EstItemCount = uint(len(target.Items))
|
||||
// Sort the results again since in-place updates and deletes
|
||||
// may have shuffled items. We sort by created time descending
|
||||
// (most recently created first), same as the API.
|
||||
slices.SortFunc(target.Items, func(i, j *CredentialStore) int {
|
||||
return i.UpdatedTime.Compare(j.UpdatedTime)
|
||||
return j.CreatedTime.Compare(i.CreatedTime)
|
||||
})
|
||||
// Finally, since we made at least 2 requests to the server to fulfill this
|
||||
// function call, resp.Body and resp.Map will only contain the most recent response.
|
||||
// Overwrite them with the true response.
|
||||
target.response.Body.Reset()
|
||||
if err := json.NewEncoder(target.response.Body).Encode(target); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final JSON list response: %w", err)
|
||||
}
|
||||
if err := json.Unmarshal(target.response.Body.Bytes(), &target.response.Map); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final map list response: %w", err)
|
||||
}
|
||||
// Note: the HTTP response body is consumed by resp.Decode in the loop,
|
||||
// so it doesn't need to be updated (it will always be, and has always been, empty).
|
||||
return target, nil
|
||||
}
|
||||
+34
-4
@@ -6,6 +6,7 @@ package groups
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@@ -351,6 +352,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Grou
|
||||
for i, item := range target.Items {
|
||||
idToIndex[item.Id] = i
|
||||
}
|
||||
// Removed IDs in the response may contain duplicates,
|
||||
// maintain a set to avoid returning duplicates to the user.
|
||||
removedIds := map[string]struct{}{}
|
||||
for {
|
||||
req, err := c.client.NewRequest(ctx, "GET", "groups", nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -388,7 +392,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Grou
|
||||
idToIndex[item.Id] = len(target.Items) - 1
|
||||
}
|
||||
}
|
||||
target.RemovedIds = append(target.RemovedIds, page.RemovedIds...)
|
||||
for _, removedId := range page.RemovedIds {
|
||||
removedIds[removedId] = struct{}{}
|
||||
}
|
||||
target.EstItemCount = page.EstItemCount
|
||||
target.ListToken = page.ListToken
|
||||
target.ResponseType = page.ResponseType
|
||||
@@ -407,11 +413,35 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Grou
|
||||
idToIndex[target.Items[i].Id] = i
|
||||
}
|
||||
}
|
||||
// Finally, sort the results again since in-place updates and deletes
|
||||
// may have shuffled items.
|
||||
for deletedId := range removedIds {
|
||||
target.RemovedIds = append(target.RemovedIds, deletedId)
|
||||
}
|
||||
// Sort to make response deterministic
|
||||
slices.Sort(target.RemovedIds)
|
||||
// Since we paginated to the end, we can avoid confusion
|
||||
// for the user by setting the estimated item count to the
|
||||
// length of the items slice. If we don't set this here, it
|
||||
// will equal the value returned in the last response, which is
|
||||
// often much smaller than the total number returned.
|
||||
target.EstItemCount = uint(len(target.Items))
|
||||
// Sort the results again since in-place updates and deletes
|
||||
// may have shuffled items. We sort by created time descending
|
||||
// (most recently created first), same as the API.
|
||||
slices.SortFunc(target.Items, func(i, j *Group) int {
|
||||
return i.UpdatedTime.Compare(j.UpdatedTime)
|
||||
return j.CreatedTime.Compare(i.CreatedTime)
|
||||
})
|
||||
// Finally, since we made at least 2 requests to the server to fulfill this
|
||||
// function call, resp.Body and resp.Map will only contain the most recent response.
|
||||
// Overwrite them with the true response.
|
||||
target.response.Body.Reset()
|
||||
if err := json.NewEncoder(target.response.Body).Encode(target); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final JSON list response: %w", err)
|
||||
}
|
||||
if err := json.Unmarshal(target.response.Body.Bytes(), &target.response.Map); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final map list response: %w", err)
|
||||
}
|
||||
// Note: the HTTP response body is consumed by resp.Decode in the loop,
|
||||
// so it doesn't need to be updated (it will always be, and has always been, empty).
|
||||
return target, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ package hostcatalogs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@@ -362,6 +363,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Host
|
||||
for i, item := range target.Items {
|
||||
idToIndex[item.Id] = i
|
||||
}
|
||||
// Removed IDs in the response may contain duplicates,
|
||||
// maintain a set to avoid returning duplicates to the user.
|
||||
removedIds := map[string]struct{}{}
|
||||
for {
|
||||
req, err := c.client.NewRequest(ctx, "GET", "host-catalogs", nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -399,7 +403,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Host
|
||||
idToIndex[item.Id] = len(target.Items) - 1
|
||||
}
|
||||
}
|
||||
target.RemovedIds = append(target.RemovedIds, page.RemovedIds...)
|
||||
for _, removedId := range page.RemovedIds {
|
||||
removedIds[removedId] = struct{}{}
|
||||
}
|
||||
target.EstItemCount = page.EstItemCount
|
||||
target.ListToken = page.ListToken
|
||||
target.ResponseType = page.ResponseType
|
||||
@@ -418,10 +424,34 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Host
|
||||
idToIndex[target.Items[i].Id] = i
|
||||
}
|
||||
}
|
||||
// Finally, sort the results again since in-place updates and deletes
|
||||
// may have shuffled items.
|
||||
for deletedId := range removedIds {
|
||||
target.RemovedIds = append(target.RemovedIds, deletedId)
|
||||
}
|
||||
// Sort to make response deterministic
|
||||
slices.Sort(target.RemovedIds)
|
||||
// Since we paginated to the end, we can avoid confusion
|
||||
// for the user by setting the estimated item count to the
|
||||
// length of the items slice. If we don't set this here, it
|
||||
// will equal the value returned in the last response, which is
|
||||
// often much smaller than the total number returned.
|
||||
target.EstItemCount = uint(len(target.Items))
|
||||
// Sort the results again since in-place updates and deletes
|
||||
// may have shuffled items. We sort by created time descending
|
||||
// (most recently created first), same as the API.
|
||||
slices.SortFunc(target.Items, func(i, j *HostCatalog) int {
|
||||
return i.UpdatedTime.Compare(j.UpdatedTime)
|
||||
return j.CreatedTime.Compare(i.CreatedTime)
|
||||
})
|
||||
// Finally, since we made at least 2 requests to the server to fulfill this
|
||||
// function call, resp.Body and resp.Map will only contain the most recent response.
|
||||
// Overwrite them with the true response.
|
||||
target.response.Body.Reset()
|
||||
if err := json.NewEncoder(target.response.Body).Encode(target); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final JSON list response: %w", err)
|
||||
}
|
||||
if err := json.Unmarshal(target.response.Body.Bytes(), &target.response.Map); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final map list response: %w", err)
|
||||
}
|
||||
// Note: the HTTP response body is consumed by resp.Decode in the loop,
|
||||
// so it doesn't need to be updated (it will always be, and has always been, empty).
|
||||
return target, nil
|
||||
}
|
||||
+34
-4
@@ -6,6 +6,7 @@ package hosts
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@@ -358,6 +359,9 @@ func (c *Client) List(ctx context.Context, hostCatalogId string, opt ...Option)
|
||||
for i, item := range target.Items {
|
||||
idToIndex[item.Id] = i
|
||||
}
|
||||
// Removed IDs in the response may contain duplicates,
|
||||
// maintain a set to avoid returning duplicates to the user.
|
||||
removedIds := map[string]struct{}{}
|
||||
for {
|
||||
req, err := c.client.NewRequest(ctx, "GET", "hosts", nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -395,7 +399,9 @@ func (c *Client) List(ctx context.Context, hostCatalogId string, opt ...Option)
|
||||
idToIndex[item.Id] = len(target.Items) - 1
|
||||
}
|
||||
}
|
||||
target.RemovedIds = append(target.RemovedIds, page.RemovedIds...)
|
||||
for _, removedId := range page.RemovedIds {
|
||||
removedIds[removedId] = struct{}{}
|
||||
}
|
||||
target.EstItemCount = page.EstItemCount
|
||||
target.ListToken = page.ListToken
|
||||
target.ResponseType = page.ResponseType
|
||||
@@ -414,10 +420,34 @@ func (c *Client) List(ctx context.Context, hostCatalogId string, opt ...Option)
|
||||
idToIndex[target.Items[i].Id] = i
|
||||
}
|
||||
}
|
||||
// Finally, sort the results again since in-place updates and deletes
|
||||
// may have shuffled items.
|
||||
for deletedId := range removedIds {
|
||||
target.RemovedIds = append(target.RemovedIds, deletedId)
|
||||
}
|
||||
// Sort to make response deterministic
|
||||
slices.Sort(target.RemovedIds)
|
||||
// Since we paginated to the end, we can avoid confusion
|
||||
// for the user by setting the estimated item count to the
|
||||
// length of the items slice. If we don't set this here, it
|
||||
// will equal the value returned in the last response, which is
|
||||
// often much smaller than the total number returned.
|
||||
target.EstItemCount = uint(len(target.Items))
|
||||
// Sort the results again since in-place updates and deletes
|
||||
// may have shuffled items. We sort by created time descending
|
||||
// (most recently created first), same as the API.
|
||||
slices.SortFunc(target.Items, func(i, j *Host) int {
|
||||
return i.UpdatedTime.Compare(j.UpdatedTime)
|
||||
return j.CreatedTime.Compare(i.CreatedTime)
|
||||
})
|
||||
// Finally, since we made at least 2 requests to the server to fulfill this
|
||||
// function call, resp.Body and resp.Map will only contain the most recent response.
|
||||
// Overwrite them with the true response.
|
||||
target.response.Body.Reset()
|
||||
if err := json.NewEncoder(target.response.Body).Encode(target); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final JSON list response: %w", err)
|
||||
}
|
||||
if err := json.Unmarshal(target.response.Body.Bytes(), &target.response.Map); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final map list response: %w", err)
|
||||
}
|
||||
// Note: the HTTP response body is consumed by resp.Decode in the loop,
|
||||
// so it doesn't need to be updated (it will always be, and has always been, empty).
|
||||
return target, nil
|
||||
}
|
||||
@@ -6,6 +6,7 @@ package hostsets
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@@ -356,6 +357,9 @@ func (c *Client) List(ctx context.Context, hostCatalogId string, opt ...Option)
|
||||
for i, item := range target.Items {
|
||||
idToIndex[item.Id] = i
|
||||
}
|
||||
// Removed IDs in the response may contain duplicates,
|
||||
// maintain a set to avoid returning duplicates to the user.
|
||||
removedIds := map[string]struct{}{}
|
||||
for {
|
||||
req, err := c.client.NewRequest(ctx, "GET", "host-sets", nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -393,7 +397,9 @@ func (c *Client) List(ctx context.Context, hostCatalogId string, opt ...Option)
|
||||
idToIndex[item.Id] = len(target.Items) - 1
|
||||
}
|
||||
}
|
||||
target.RemovedIds = append(target.RemovedIds, page.RemovedIds...)
|
||||
for _, removedId := range page.RemovedIds {
|
||||
removedIds[removedId] = struct{}{}
|
||||
}
|
||||
target.EstItemCount = page.EstItemCount
|
||||
target.ListToken = page.ListToken
|
||||
target.ResponseType = page.ResponseType
|
||||
@@ -412,11 +418,35 @@ func (c *Client) List(ctx context.Context, hostCatalogId string, opt ...Option)
|
||||
idToIndex[target.Items[i].Id] = i
|
||||
}
|
||||
}
|
||||
// Finally, sort the results again since in-place updates and deletes
|
||||
// may have shuffled items.
|
||||
for deletedId := range removedIds {
|
||||
target.RemovedIds = append(target.RemovedIds, deletedId)
|
||||
}
|
||||
// Sort to make response deterministic
|
||||
slices.Sort(target.RemovedIds)
|
||||
// Since we paginated to the end, we can avoid confusion
|
||||
// for the user by setting the estimated item count to the
|
||||
// length of the items slice. If we don't set this here, it
|
||||
// will equal the value returned in the last response, which is
|
||||
// often much smaller than the total number returned.
|
||||
target.EstItemCount = uint(len(target.Items))
|
||||
// Sort the results again since in-place updates and deletes
|
||||
// may have shuffled items. We sort by created time descending
|
||||
// (most recently created first), same as the API.
|
||||
slices.SortFunc(target.Items, func(i, j *HostSet) int {
|
||||
return i.UpdatedTime.Compare(j.UpdatedTime)
|
||||
return j.CreatedTime.Compare(i.CreatedTime)
|
||||
})
|
||||
// Finally, since we made at least 2 requests to the server to fulfill this
|
||||
// function call, resp.Body and resp.Map will only contain the most recent response.
|
||||
// Overwrite them with the true response.
|
||||
target.response.Body.Reset()
|
||||
if err := json.NewEncoder(target.response.Body).Encode(target); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final JSON list response: %w", err)
|
||||
}
|
||||
if err := json.Unmarshal(target.response.Body.Bytes(), &target.response.Map); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final map list response: %w", err)
|
||||
}
|
||||
// Note: the HTTP response body is consumed by resp.Decode in the loop,
|
||||
// so it doesn't need to be updated (it will always be, and has always been, empty).
|
||||
return target, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ package managedgroups
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@@ -352,6 +353,9 @@ func (c *Client) List(ctx context.Context, authMethodId string, opt ...Option) (
|
||||
for i, item := range target.Items {
|
||||
idToIndex[item.Id] = i
|
||||
}
|
||||
// Removed IDs in the response may contain duplicates,
|
||||
// maintain a set to avoid returning duplicates to the user.
|
||||
removedIds := map[string]struct{}{}
|
||||
for {
|
||||
req, err := c.client.NewRequest(ctx, "GET", "managed-groups", nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -389,7 +393,9 @@ func (c *Client) List(ctx context.Context, authMethodId string, opt ...Option) (
|
||||
idToIndex[item.Id] = len(target.Items) - 1
|
||||
}
|
||||
}
|
||||
target.RemovedIds = append(target.RemovedIds, page.RemovedIds...)
|
||||
for _, removedId := range page.RemovedIds {
|
||||
removedIds[removedId] = struct{}{}
|
||||
}
|
||||
target.EstItemCount = page.EstItemCount
|
||||
target.ListToken = page.ListToken
|
||||
target.ResponseType = page.ResponseType
|
||||
@@ -408,10 +414,34 @@ func (c *Client) List(ctx context.Context, authMethodId string, opt ...Option) (
|
||||
idToIndex[target.Items[i].Id] = i
|
||||
}
|
||||
}
|
||||
// Finally, sort the results again since in-place updates and deletes
|
||||
// may have shuffled items.
|
||||
for deletedId := range removedIds {
|
||||
target.RemovedIds = append(target.RemovedIds, deletedId)
|
||||
}
|
||||
// Sort to make response deterministic
|
||||
slices.Sort(target.RemovedIds)
|
||||
// Since we paginated to the end, we can avoid confusion
|
||||
// for the user by setting the estimated item count to the
|
||||
// length of the items slice. If we don't set this here, it
|
||||
// will equal the value returned in the last response, which is
|
||||
// often much smaller than the total number returned.
|
||||
target.EstItemCount = uint(len(target.Items))
|
||||
// Sort the results again since in-place updates and deletes
|
||||
// may have shuffled items. We sort by created time descending
|
||||
// (most recently created first), same as the API.
|
||||
slices.SortFunc(target.Items, func(i, j *ManagedGroup) int {
|
||||
return i.UpdatedTime.Compare(j.UpdatedTime)
|
||||
return j.CreatedTime.Compare(i.CreatedTime)
|
||||
})
|
||||
// Finally, since we made at least 2 requests to the server to fulfill this
|
||||
// function call, resp.Body and resp.Map will only contain the most recent response.
|
||||
// Overwrite them with the true response.
|
||||
target.response.Body.Reset()
|
||||
if err := json.NewEncoder(target.response.Body).Encode(target); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final JSON list response: %w", err)
|
||||
}
|
||||
if err := json.Unmarshal(target.response.Body.Bytes(), &target.response.Map); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final map list response: %w", err)
|
||||
}
|
||||
// Note: the HTTP response body is consumed by resp.Decode in the loop,
|
||||
// so it doesn't need to be updated (it will always be, and has always been, empty).
|
||||
return target, nil
|
||||
}
|
||||
+34
-4
@@ -6,6 +6,7 @@ package roles
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@@ -354,6 +355,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Role
|
||||
for i, item := range target.Items {
|
||||
idToIndex[item.Id] = i
|
||||
}
|
||||
// Removed IDs in the response may contain duplicates,
|
||||
// maintain a set to avoid returning duplicates to the user.
|
||||
removedIds := map[string]struct{}{}
|
||||
for {
|
||||
req, err := c.client.NewRequest(ctx, "GET", "roles", nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -391,7 +395,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Role
|
||||
idToIndex[item.Id] = len(target.Items) - 1
|
||||
}
|
||||
}
|
||||
target.RemovedIds = append(target.RemovedIds, page.RemovedIds...)
|
||||
for _, removedId := range page.RemovedIds {
|
||||
removedIds[removedId] = struct{}{}
|
||||
}
|
||||
target.EstItemCount = page.EstItemCount
|
||||
target.ListToken = page.ListToken
|
||||
target.ResponseType = page.ResponseType
|
||||
@@ -410,11 +416,35 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Role
|
||||
idToIndex[target.Items[i].Id] = i
|
||||
}
|
||||
}
|
||||
// Finally, sort the results again since in-place updates and deletes
|
||||
// may have shuffled items.
|
||||
for deletedId := range removedIds {
|
||||
target.RemovedIds = append(target.RemovedIds, deletedId)
|
||||
}
|
||||
// Sort to make response deterministic
|
||||
slices.Sort(target.RemovedIds)
|
||||
// Since we paginated to the end, we can avoid confusion
|
||||
// for the user by setting the estimated item count to the
|
||||
// length of the items slice. If we don't set this here, it
|
||||
// will equal the value returned in the last response, which is
|
||||
// often much smaller than the total number returned.
|
||||
target.EstItemCount = uint(len(target.Items))
|
||||
// Sort the results again since in-place updates and deletes
|
||||
// may have shuffled items. We sort by created time descending
|
||||
// (most recently created first), same as the API.
|
||||
slices.SortFunc(target.Items, func(i, j *Role) int {
|
||||
return i.UpdatedTime.Compare(j.UpdatedTime)
|
||||
return j.CreatedTime.Compare(i.CreatedTime)
|
||||
})
|
||||
// Finally, since we made at least 2 requests to the server to fulfill this
|
||||
// function call, resp.Body and resp.Map will only contain the most recent response.
|
||||
// Overwrite them with the true response.
|
||||
target.response.Body.Reset()
|
||||
if err := json.NewEncoder(target.response.Body).Encode(target); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final JSON list response: %w", err)
|
||||
}
|
||||
if err := json.Unmarshal(target.response.Body.Bytes(), &target.response.Map); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final map list response: %w", err)
|
||||
}
|
||||
// Note: the HTTP response body is consumed by resp.Decode in the loop,
|
||||
// so it doesn't need to be updated (it will always be, and has always been, empty).
|
||||
return target, nil
|
||||
}
|
||||
|
||||
|
||||
+34
-4
@@ -6,6 +6,7 @@ package scopes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@@ -351,6 +352,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Scop
|
||||
for i, item := range target.Items {
|
||||
idToIndex[item.Id] = i
|
||||
}
|
||||
// Removed IDs in the response may contain duplicates,
|
||||
// maintain a set to avoid returning duplicates to the user.
|
||||
removedIds := map[string]struct{}{}
|
||||
for {
|
||||
req, err := c.client.NewRequest(ctx, "GET", "scopes", nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -388,7 +392,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Scop
|
||||
idToIndex[item.Id] = len(target.Items) - 1
|
||||
}
|
||||
}
|
||||
target.RemovedIds = append(target.RemovedIds, page.RemovedIds...)
|
||||
for _, removedId := range page.RemovedIds {
|
||||
removedIds[removedId] = struct{}{}
|
||||
}
|
||||
target.EstItemCount = page.EstItemCount
|
||||
target.ListToken = page.ListToken
|
||||
target.ResponseType = page.ResponseType
|
||||
@@ -407,10 +413,34 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Scop
|
||||
idToIndex[target.Items[i].Id] = i
|
||||
}
|
||||
}
|
||||
// Finally, sort the results again since in-place updates and deletes
|
||||
// may have shuffled items.
|
||||
for deletedId := range removedIds {
|
||||
target.RemovedIds = append(target.RemovedIds, deletedId)
|
||||
}
|
||||
// Sort to make response deterministic
|
||||
slices.Sort(target.RemovedIds)
|
||||
// Since we paginated to the end, we can avoid confusion
|
||||
// for the user by setting the estimated item count to the
|
||||
// length of the items slice. If we don't set this here, it
|
||||
// will equal the value returned in the last response, which is
|
||||
// often much smaller than the total number returned.
|
||||
target.EstItemCount = uint(len(target.Items))
|
||||
// Sort the results again since in-place updates and deletes
|
||||
// may have shuffled items. We sort by created time descending
|
||||
// (most recently created first), same as the API.
|
||||
slices.SortFunc(target.Items, func(i, j *Scope) int {
|
||||
return i.UpdatedTime.Compare(j.UpdatedTime)
|
||||
return j.CreatedTime.Compare(i.CreatedTime)
|
||||
})
|
||||
// Finally, since we made at least 2 requests to the server to fulfill this
|
||||
// function call, resp.Body and resp.Map will only contain the most recent response.
|
||||
// Overwrite them with the true response.
|
||||
target.response.Body.Reset()
|
||||
if err := json.NewEncoder(target.response.Body).Encode(target); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final JSON list response: %w", err)
|
||||
}
|
||||
if err := json.Unmarshal(target.response.Body.Bytes(), &target.response.Map); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final map list response: %w", err)
|
||||
}
|
||||
// Note: the HTTP response body is consumed by resp.Decode in the loop,
|
||||
// so it doesn't need to be updated (it will always be, and has always been, empty).
|
||||
return target, nil
|
||||
}
|
||||
@@ -6,6 +6,7 @@ package sessionrecordings
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"slices"
|
||||
@@ -193,6 +194,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Sess
|
||||
for i, item := range target.Items {
|
||||
idToIndex[item.Id] = i
|
||||
}
|
||||
// Removed IDs in the response may contain duplicates,
|
||||
// maintain a set to avoid returning duplicates to the user.
|
||||
removedIds := map[string]struct{}{}
|
||||
for {
|
||||
req, err := c.client.NewRequest(ctx, "GET", "session-recordings", nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -230,7 +234,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Sess
|
||||
idToIndex[item.Id] = len(target.Items) - 1
|
||||
}
|
||||
}
|
||||
target.RemovedIds = append(target.RemovedIds, page.RemovedIds...)
|
||||
for _, removedId := range page.RemovedIds {
|
||||
removedIds[removedId] = struct{}{}
|
||||
}
|
||||
target.EstItemCount = page.EstItemCount
|
||||
target.ListToken = page.ListToken
|
||||
target.ResponseType = page.ResponseType
|
||||
@@ -249,10 +255,34 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Sess
|
||||
idToIndex[target.Items[i].Id] = i
|
||||
}
|
||||
}
|
||||
// Finally, sort the results again since in-place updates and deletes
|
||||
// may have shuffled items.
|
||||
for deletedId := range removedIds {
|
||||
target.RemovedIds = append(target.RemovedIds, deletedId)
|
||||
}
|
||||
// Sort to make response deterministic
|
||||
slices.Sort(target.RemovedIds)
|
||||
// Since we paginated to the end, we can avoid confusion
|
||||
// for the user by setting the estimated item count to the
|
||||
// length of the items slice. If we don't set this here, it
|
||||
// will equal the value returned in the last response, which is
|
||||
// often much smaller than the total number returned.
|
||||
target.EstItemCount = uint(len(target.Items))
|
||||
// Sort the results again since in-place updates and deletes
|
||||
// may have shuffled items. We sort by created time descending
|
||||
// (most recently created first), same as the API.
|
||||
slices.SortFunc(target.Items, func(i, j *SessionRecording) int {
|
||||
return i.UpdatedTime.Compare(j.UpdatedTime)
|
||||
return j.CreatedTime.Compare(i.CreatedTime)
|
||||
})
|
||||
// Finally, since we made at least 2 requests to the server to fulfill this
|
||||
// function call, resp.Body and resp.Map will only contain the most recent response.
|
||||
// Overwrite them with the true response.
|
||||
target.response.Body.Reset()
|
||||
if err := json.NewEncoder(target.response.Body).Encode(target); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final JSON list response: %w", err)
|
||||
}
|
||||
if err := json.Unmarshal(target.response.Body.Bytes(), &target.response.Map); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final map list response: %w", err)
|
||||
}
|
||||
// Note: the HTTP response body is consumed by resp.Decode in the loop,
|
||||
// so it doesn't need to be updated (it will always be, and has always been, empty).
|
||||
return target, nil
|
||||
}
|
||||
@@ -6,6 +6,7 @@ package sessions
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"slices"
|
||||
@@ -210,6 +211,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Sess
|
||||
for i, item := range target.Items {
|
||||
idToIndex[item.Id] = i
|
||||
}
|
||||
// Removed IDs in the response may contain duplicates,
|
||||
// maintain a set to avoid returning duplicates to the user.
|
||||
removedIds := map[string]struct{}{}
|
||||
for {
|
||||
req, err := c.client.NewRequest(ctx, "GET", "sessions", nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -247,7 +251,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Sess
|
||||
idToIndex[item.Id] = len(target.Items) - 1
|
||||
}
|
||||
}
|
||||
target.RemovedIds = append(target.RemovedIds, page.RemovedIds...)
|
||||
for _, removedId := range page.RemovedIds {
|
||||
removedIds[removedId] = struct{}{}
|
||||
}
|
||||
target.EstItemCount = page.EstItemCount
|
||||
target.ListToken = page.ListToken
|
||||
target.ResponseType = page.ResponseType
|
||||
@@ -266,10 +272,34 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Sess
|
||||
idToIndex[target.Items[i].Id] = i
|
||||
}
|
||||
}
|
||||
// Finally, sort the results again since in-place updates and deletes
|
||||
// may have shuffled items.
|
||||
for deletedId := range removedIds {
|
||||
target.RemovedIds = append(target.RemovedIds, deletedId)
|
||||
}
|
||||
// Sort to make response deterministic
|
||||
slices.Sort(target.RemovedIds)
|
||||
// Since we paginated to the end, we can avoid confusion
|
||||
// for the user by setting the estimated item count to the
|
||||
// length of the items slice. If we don't set this here, it
|
||||
// will equal the value returned in the last response, which is
|
||||
// often much smaller than the total number returned.
|
||||
target.EstItemCount = uint(len(target.Items))
|
||||
// Sort the results again since in-place updates and deletes
|
||||
// may have shuffled items. We sort by created time descending
|
||||
// (most recently created first), same as the API.
|
||||
slices.SortFunc(target.Items, func(i, j *Session) int {
|
||||
return i.UpdatedTime.Compare(j.UpdatedTime)
|
||||
return j.CreatedTime.Compare(i.CreatedTime)
|
||||
})
|
||||
// Finally, since we made at least 2 requests to the server to fulfill this
|
||||
// function call, resp.Body and resp.Map will only contain the most recent response.
|
||||
// Overwrite them with the true response.
|
||||
target.response.Body.Reset()
|
||||
if err := json.NewEncoder(target.response.Body).Encode(target); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final JSON list response: %w", err)
|
||||
}
|
||||
if err := json.Unmarshal(target.response.Body.Bytes(), &target.response.Map); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final map list response: %w", err)
|
||||
}
|
||||
// Note: the HTTP response body is consumed by resp.Decode in the loop,
|
||||
// so it doesn't need to be updated (it will always be, and has always been, empty).
|
||||
return target, nil
|
||||
}
|
||||
@@ -6,6 +6,7 @@ package storagebuckets
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@@ -359,6 +360,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Stor
|
||||
for i, item := range target.Items {
|
||||
idToIndex[item.Id] = i
|
||||
}
|
||||
// Removed IDs in the response may contain duplicates,
|
||||
// maintain a set to avoid returning duplicates to the user.
|
||||
removedIds := map[string]struct{}{}
|
||||
for {
|
||||
req, err := c.client.NewRequest(ctx, "GET", "storage-buckets", nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -396,7 +400,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Stor
|
||||
idToIndex[item.Id] = len(target.Items) - 1
|
||||
}
|
||||
}
|
||||
target.RemovedIds = append(target.RemovedIds, page.RemovedIds...)
|
||||
for _, removedId := range page.RemovedIds {
|
||||
removedIds[removedId] = struct{}{}
|
||||
}
|
||||
target.EstItemCount = page.EstItemCount
|
||||
target.ListToken = page.ListToken
|
||||
target.ResponseType = page.ResponseType
|
||||
@@ -415,10 +421,34 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Stor
|
||||
idToIndex[target.Items[i].Id] = i
|
||||
}
|
||||
}
|
||||
// Finally, sort the results again since in-place updates and deletes
|
||||
// may have shuffled items.
|
||||
for deletedId := range removedIds {
|
||||
target.RemovedIds = append(target.RemovedIds, deletedId)
|
||||
}
|
||||
// Sort to make response deterministic
|
||||
slices.Sort(target.RemovedIds)
|
||||
// Since we paginated to the end, we can avoid confusion
|
||||
// for the user by setting the estimated item count to the
|
||||
// length of the items slice. If we don't set this here, it
|
||||
// will equal the value returned in the last response, which is
|
||||
// often much smaller than the total number returned.
|
||||
target.EstItemCount = uint(len(target.Items))
|
||||
// Sort the results again since in-place updates and deletes
|
||||
// may have shuffled items. We sort by created time descending
|
||||
// (most recently created first), same as the API.
|
||||
slices.SortFunc(target.Items, func(i, j *StorageBucket) int {
|
||||
return i.UpdatedTime.Compare(j.UpdatedTime)
|
||||
return j.CreatedTime.Compare(i.CreatedTime)
|
||||
})
|
||||
// Finally, since we made at least 2 requests to the server to fulfill this
|
||||
// function call, resp.Body and resp.Map will only contain the most recent response.
|
||||
// Overwrite them with the true response.
|
||||
target.response.Body.Reset()
|
||||
if err := json.NewEncoder(target.response.Body).Encode(target); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final JSON list response: %w", err)
|
||||
}
|
||||
if err := json.Unmarshal(target.response.Body.Bytes(), &target.response.Map); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final map list response: %w", err)
|
||||
}
|
||||
// Note: the HTTP response body is consumed by resp.Decode in the loop,
|
||||
// so it doesn't need to be updated (it will always be, and has always been, empty).
|
||||
return target, nil
|
||||
}
|
||||
@@ -4,7 +4,9 @@
|
||||
|
||||
package targets
|
||||
|
||||
import "encoding/json"
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
type SessionSecret struct {
|
||||
Raw json.RawMessage `json:"raw,omitempty"`
|
||||
|
||||
@@ -6,6 +6,7 @@ package targets
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@@ -368,6 +369,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Targ
|
||||
for i, item := range target.Items {
|
||||
idToIndex[item.Id] = i
|
||||
}
|
||||
// Removed IDs in the response may contain duplicates,
|
||||
// maintain a set to avoid returning duplicates to the user.
|
||||
removedIds := map[string]struct{}{}
|
||||
for {
|
||||
req, err := c.client.NewRequest(ctx, "GET", "targets", nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -405,7 +409,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Targ
|
||||
idToIndex[item.Id] = len(target.Items) - 1
|
||||
}
|
||||
}
|
||||
target.RemovedIds = append(target.RemovedIds, page.RemovedIds...)
|
||||
for _, removedId := range page.RemovedIds {
|
||||
removedIds[removedId] = struct{}{}
|
||||
}
|
||||
target.EstItemCount = page.EstItemCount
|
||||
target.ListToken = page.ListToken
|
||||
target.ResponseType = page.ResponseType
|
||||
@@ -424,11 +430,35 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Targ
|
||||
idToIndex[target.Items[i].Id] = i
|
||||
}
|
||||
}
|
||||
// Finally, sort the results again since in-place updates and deletes
|
||||
// may have shuffled items.
|
||||
for deletedId := range removedIds {
|
||||
target.RemovedIds = append(target.RemovedIds, deletedId)
|
||||
}
|
||||
// Sort to make response deterministic
|
||||
slices.Sort(target.RemovedIds)
|
||||
// Since we paginated to the end, we can avoid confusion
|
||||
// for the user by setting the estimated item count to the
|
||||
// length of the items slice. If we don't set this here, it
|
||||
// will equal the value returned in the last response, which is
|
||||
// often much smaller than the total number returned.
|
||||
target.EstItemCount = uint(len(target.Items))
|
||||
// Sort the results again since in-place updates and deletes
|
||||
// may have shuffled items. We sort by created time descending
|
||||
// (most recently created first), same as the API.
|
||||
slices.SortFunc(target.Items, func(i, j *Target) int {
|
||||
return i.UpdatedTime.Compare(j.UpdatedTime)
|
||||
return j.CreatedTime.Compare(i.CreatedTime)
|
||||
})
|
||||
// Finally, since we made at least 2 requests to the server to fulfill this
|
||||
// function call, resp.Body and resp.Map will only contain the most recent response.
|
||||
// Overwrite them with the true response.
|
||||
target.response.Body.Reset()
|
||||
if err := json.NewEncoder(target.response.Body).Encode(target); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final JSON list response: %w", err)
|
||||
}
|
||||
if err := json.Unmarshal(target.response.Body.Bytes(), &target.response.Map); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final map list response: %w", err)
|
||||
}
|
||||
// Note: the HTTP response body is consumed by resp.Decode in the loop,
|
||||
// so it doesn't need to be updated (it will always be, and has always been, empty).
|
||||
return target, nil
|
||||
}
|
||||
|
||||
|
||||
+34
-4
@@ -6,6 +6,7 @@ package users
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@@ -355,6 +356,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*User
|
||||
for i, item := range target.Items {
|
||||
idToIndex[item.Id] = i
|
||||
}
|
||||
// Removed IDs in the response may contain duplicates,
|
||||
// maintain a set to avoid returning duplicates to the user.
|
||||
removedIds := map[string]struct{}{}
|
||||
for {
|
||||
req, err := c.client.NewRequest(ctx, "GET", "users", nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -392,7 +396,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*User
|
||||
idToIndex[item.Id] = len(target.Items) - 1
|
||||
}
|
||||
}
|
||||
target.RemovedIds = append(target.RemovedIds, page.RemovedIds...)
|
||||
for _, removedId := range page.RemovedIds {
|
||||
removedIds[removedId] = struct{}{}
|
||||
}
|
||||
target.EstItemCount = page.EstItemCount
|
||||
target.ListToken = page.ListToken
|
||||
target.ResponseType = page.ResponseType
|
||||
@@ -411,11 +417,35 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*User
|
||||
idToIndex[target.Items[i].Id] = i
|
||||
}
|
||||
}
|
||||
// Finally, sort the results again since in-place updates and deletes
|
||||
// may have shuffled items.
|
||||
for deletedId := range removedIds {
|
||||
target.RemovedIds = append(target.RemovedIds, deletedId)
|
||||
}
|
||||
// Sort to make response deterministic
|
||||
slices.Sort(target.RemovedIds)
|
||||
// Since we paginated to the end, we can avoid confusion
|
||||
// for the user by setting the estimated item count to the
|
||||
// length of the items slice. If we don't set this here, it
|
||||
// will equal the value returned in the last response, which is
|
||||
// often much smaller than the total number returned.
|
||||
target.EstItemCount = uint(len(target.Items))
|
||||
// Sort the results again since in-place updates and deletes
|
||||
// may have shuffled items. We sort by created time descending
|
||||
// (most recently created first), same as the API.
|
||||
slices.SortFunc(target.Items, func(i, j *User) int {
|
||||
return i.UpdatedTime.Compare(j.UpdatedTime)
|
||||
return j.CreatedTime.Compare(i.CreatedTime)
|
||||
})
|
||||
// Finally, since we made at least 2 requests to the server to fulfill this
|
||||
// function call, resp.Body and resp.Map will only contain the most recent response.
|
||||
// Overwrite them with the true response.
|
||||
target.response.Body.Reset()
|
||||
if err := json.NewEncoder(target.response.Body).Encode(target); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final JSON list response: %w", err)
|
||||
}
|
||||
if err := json.Unmarshal(target.response.Body.Bytes(), &target.response.Map); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final map list response: %w", err)
|
||||
}
|
||||
// Note: the HTTP response body is consumed by resp.Decode in the loop,
|
||||
// so it doesn't need to be updated (it will always be, and has always been, empty).
|
||||
return target, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ package workers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@@ -409,6 +410,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Work
|
||||
for i, item := range target.Items {
|
||||
idToIndex[item.Id] = i
|
||||
}
|
||||
// Removed IDs in the response may contain duplicates,
|
||||
// maintain a set to avoid returning duplicates to the user.
|
||||
removedIds := map[string]struct{}{}
|
||||
for {
|
||||
req, err := c.client.NewRequest(ctx, "GET", "workers", nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -446,7 +450,9 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Work
|
||||
idToIndex[item.Id] = len(target.Items) - 1
|
||||
}
|
||||
}
|
||||
target.RemovedIds = append(target.RemovedIds, page.RemovedIds...)
|
||||
for _, removedId := range page.RemovedIds {
|
||||
removedIds[removedId] = struct{}{}
|
||||
}
|
||||
target.EstItemCount = page.EstItemCount
|
||||
target.ListToken = page.ListToken
|
||||
target.ResponseType = page.ResponseType
|
||||
@@ -465,11 +471,35 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Work
|
||||
idToIndex[target.Items[i].Id] = i
|
||||
}
|
||||
}
|
||||
// Finally, sort the results again since in-place updates and deletes
|
||||
// may have shuffled items.
|
||||
for deletedId := range removedIds {
|
||||
target.RemovedIds = append(target.RemovedIds, deletedId)
|
||||
}
|
||||
// Sort to make response deterministic
|
||||
slices.Sort(target.RemovedIds)
|
||||
// Since we paginated to the end, we can avoid confusion
|
||||
// for the user by setting the estimated item count to the
|
||||
// length of the items slice. If we don't set this here, it
|
||||
// will equal the value returned in the last response, which is
|
||||
// often much smaller than the total number returned.
|
||||
target.EstItemCount = uint(len(target.Items))
|
||||
// Sort the results again since in-place updates and deletes
|
||||
// may have shuffled items. We sort by created time descending
|
||||
// (most recently created first), same as the API.
|
||||
slices.SortFunc(target.Items, func(i, j *Worker) int {
|
||||
return i.UpdatedTime.Compare(j.UpdatedTime)
|
||||
return j.CreatedTime.Compare(i.CreatedTime)
|
||||
})
|
||||
// Finally, since we made at least 2 requests to the server to fulfill this
|
||||
// function call, resp.Body and resp.Map will only contain the most recent response.
|
||||
// Overwrite them with the true response.
|
||||
target.response.Body.Reset()
|
||||
if err := json.NewEncoder(target.response.Body).Encode(target); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final JSON list response: %w", err)
|
||||
}
|
||||
if err := json.Unmarshal(target.response.Body.Bytes(), &target.response.Map); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final map list response: %w", err)
|
||||
}
|
||||
// Note: the HTTP response body is consumed by resp.Decode in the loop,
|
||||
// so it doesn't need to be updated (it will always be, and has always been, empty).
|
||||
return target, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -276,6 +276,9 @@ func (c *Client) List(ctx context.Context, {{ .CollectionFunctionArg }} string,
|
||||
for i, item := range target.Items {
|
||||
idToIndex[item.Id] = i
|
||||
}
|
||||
// Removed IDs in the response may contain duplicates,
|
||||
// maintain a set to avoid returning duplicates to the user.
|
||||
removedIds := map[string]struct{}{}
|
||||
for {
|
||||
req, err := c.client.NewRequest(ctx, "GET", "{{ .CollectionPath }}", nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -313,7 +316,9 @@ func (c *Client) List(ctx context.Context, {{ .CollectionFunctionArg }} string,
|
||||
idToIndex[item.Id] = len(target.Items)-1
|
||||
}
|
||||
}
|
||||
target.RemovedIds = append(target.RemovedIds, page.RemovedIds...)
|
||||
for _, removedId := range page.RemovedIds {
|
||||
removedIds[removedId] = struct{}{}
|
||||
}
|
||||
target.EstItemCount = page.EstItemCount
|
||||
target.ListToken = page.ListToken
|
||||
target.ResponseType = page.ResponseType
|
||||
@@ -332,11 +337,35 @@ func (c *Client) List(ctx context.Context, {{ .CollectionFunctionArg }} string,
|
||||
idToIndex[target.Items[i].Id] = i
|
||||
}
|
||||
}
|
||||
// Finally, sort the results again since in-place updates and deletes
|
||||
// may have shuffled items.
|
||||
for deletedId := range removedIds {
|
||||
target.RemovedIds = append(target.RemovedIds, deletedId)
|
||||
}
|
||||
// Sort to make response deterministic
|
||||
slices.Sort(target.RemovedIds)
|
||||
// Since we paginated to the end, we can avoid confusion
|
||||
// for the user by setting the estimated item count to the
|
||||
// length of the items slice. If we don't set this here, it
|
||||
// will equal the value returned in the last response, which is
|
||||
// often much smaller than the total number returned.
|
||||
target.EstItemCount = uint(len(target.Items))
|
||||
// Sort the results again since in-place updates and deletes
|
||||
// may have shuffled items. We sort by created time descending
|
||||
// (most recently created first), same as the API.
|
||||
slices.SortFunc(target.Items, func(i, j *{{ .Name }}) int {
|
||||
return i.UpdatedTime.Compare(j.UpdatedTime)
|
||||
return j.CreatedTime.Compare(i.CreatedTime)
|
||||
})
|
||||
// Finally, since we made at least 2 requests to the server to fulfill this
|
||||
// function call, resp.Body and resp.Map will only contain the most recent response.
|
||||
// Overwrite them with the true response.
|
||||
target.response.Body.Reset()
|
||||
if err := json.NewEncoder(target.response.Body).Encode(target); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final JSON list response: %w", err)
|
||||
}
|
||||
if err := json.Unmarshal(target.response.Body.Bytes(), &target.response.Map); err != nil {
|
||||
return nil, fmt.Errorf("error encoding final map list response: %w", err)
|
||||
}
|
||||
// Note: the HTTP response body is consumed by resp.Decode in the loop,
|
||||
// so it doesn't need to be updated (it will always be, and has always been, empty).
|
||||
return target, nil
|
||||
}
|
||||
`))
|
||||
@@ -671,8 +700,13 @@ var structTemplate = template.Must(template.New("").Funcs(
|
||||
package {{ .Package }}
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
|
||||
Reference in new issue
Block a user