130 lines
4.3 KiB
Go
130 lines
4.3 KiB
Go
package bucket
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/influxdata/influx-cli/v2/api"
|
|
"github.com/influxdata/influx-cli/v2/clients"
|
|
)
|
|
|
|
type BucketsListParams struct {
|
|
clients.OrgBucketParams
|
|
Limit int
|
|
Offset int
|
|
PageSize int
|
|
}
|
|
|
|
func (c Client) List(ctx context.Context, params *BucketsListParams) error {
|
|
if params.OrgID == "" && params.OrgName == "" && c.ActiveConfig.Org == "" {
|
|
return clients.ErrMustSpecifyOrg
|
|
}
|
|
|
|
req := c.GetBuckets(ctx)
|
|
if params.OrgID != "" {
|
|
req = req.OrgID(params.OrgID)
|
|
}
|
|
if params.OrgName != "" {
|
|
req = req.Org(params.OrgName)
|
|
}
|
|
if params.OrgID == "" && params.OrgName == "" {
|
|
req = req.Org(c.ActiveConfig.Org)
|
|
}
|
|
if params.BucketName != "" || params.BucketID != "" {
|
|
return c.findOneBucket(params, req)
|
|
}
|
|
|
|
// Set the limit for the number of items to return per HTTP request.
|
|
// NOTE this is not the same as the `--limit` option to the CLI, which sets
|
|
// the max number of rows to pull across _all_ HTTP requests in total.
|
|
limit := params.PageSize
|
|
// Adjust if the total limit < the per-request limit.
|
|
// This is convenient for users, since the per-request limit has a default
|
|
// value that people might not want to override on every CLI call.
|
|
if params.Limit != 0 && params.Limit < limit {
|
|
limit = params.Limit
|
|
}
|
|
offset := params.Offset
|
|
|
|
printOpts := bucketPrintOptions{}
|
|
|
|
// Iteratively fetch pages of bucket metadata.
|
|
//
|
|
// NOTE: This algorithm used an `offset`-based pagination. The API also documents that an `after`-based
|
|
// approach would work. Pagination via `after` would typically be much more efficient than the `offset`-
|
|
// based approach used here, but we still use `offset` because:
|
|
// 1. As of this writing (10/15/2021) Cloud doesn't support pagination via `after` when filtering by org.
|
|
// Versions of OSS prior to v2.1 had the same restriction. Both Cloud and OSS have supported `offset`-
|
|
// based pagination since before the OSS/Cloud split.
|
|
// 2. Listing buckets-by-org uses a secondary index on orgID+bucketName in both OSS and Cloud. Since bucket
|
|
// ID isn't part of the index, implementing pagination via `after` requires scanning the subset of the
|
|
// index for the target org until the given ID is found. This is just as (in)efficient as the implementation
|
|
// of `offset`-based filtering.
|
|
//
|
|
// If you are thinking of copy-paste-adjusting this code for another command, CONSIDER USING `after` INSTEAD OF
|
|
// `offset`! The conditions that make `offset` OK for buckets probably aren't present for other resource types.
|
|
//
|
|
// We should eventually convert this to use `after` for consistency across the CLI.
|
|
for {
|
|
req := req
|
|
if limit != 0 {
|
|
req = req.Limit(int32(limit))
|
|
}
|
|
if offset != 0 {
|
|
req = req.Offset(int32(offset))
|
|
}
|
|
|
|
res, err := req.Execute()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to list buckets: %w", err)
|
|
}
|
|
var buckets []api.Bucket
|
|
if res.Buckets != nil {
|
|
buckets = *res.Buckets
|
|
}
|
|
printOpts.buckets = append(printOpts.buckets, buckets...)
|
|
|
|
// Break out of the loop if:
|
|
// * The server returned less than a full page of results
|
|
// * We've collected as many results as the user asked for
|
|
if len(buckets) == 0 || len(buckets) < params.PageSize ||
|
|
(params.Limit != 0 && len(printOpts.buckets) == params.Limit) {
|
|
break
|
|
}
|
|
|
|
// Adjust the page-size for the next request (if needed) so we don't pull down more information
|
|
// than the user requested.
|
|
if params.Limit != 0 && len(printOpts.buckets)+limit > params.Limit {
|
|
limit = params.Limit - len(printOpts.buckets)
|
|
}
|
|
// Bump the offset for the next request to pull the next page.
|
|
offset = offset + len(buckets)
|
|
}
|
|
|
|
return c.printBuckets(printOpts)
|
|
}
|
|
|
|
// findOneBucket queries for a single bucket resoruce using the list API.
|
|
// Used to look up buckets by ID or name.
|
|
func (c Client) findOneBucket(params *BucketsListParams, req api.ApiGetBucketsRequest) error {
|
|
var description string
|
|
if params.BucketID != "" {
|
|
req = req.Id(params.BucketID)
|
|
description = " by ID"
|
|
} else if params.BucketName != "" {
|
|
req = req.Name(params.BucketName)
|
|
description = " by name"
|
|
}
|
|
|
|
buckets, err := req.Execute()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to find bucket%s: %w", description, err)
|
|
}
|
|
|
|
printOpts := bucketPrintOptions{}
|
|
if buckets.Buckets != nil {
|
|
printOpts.buckets = *buckets.Buckets
|
|
}
|
|
return c.printBuckets(printOpts)
|
|
}
|