csi: add pagination args to `volume snapshot list` (#12193)
The snapshot list API supports pagination as part of the CSI specification, but we didn't have it plumbed through to the command line.
This commit is contained in:
parent
2dafe46fe3
commit
b94837a2b8
|
@ -0,0 +1,3 @@
|
|||
```release-note:improvement
|
||||
csi: Add pagination parameters to `volume snapshot list` command
|
||||
```
|
|
@ -3,6 +3,7 @@ package command
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
|
@ -41,6 +42,12 @@ List Options:
|
|||
-secret
|
||||
Secrets to pass to the plugin to list snapshots. Accepts multiple
|
||||
flags in the form -secret key=value
|
||||
|
||||
-per-page
|
||||
How many results to show per page. Defaults to 30.
|
||||
|
||||
-page-token
|
||||
Where to start pagination.
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
@ -75,12 +82,16 @@ func (c *VolumeSnapshotListCommand) Run(args []string) int {
|
|||
var pluginID string
|
||||
var verbose bool
|
||||
var secretsArgs flaghelper.StringFlag
|
||||
var perPage int
|
||||
var pageToken string
|
||||
|
||||
flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
|
||||
flags.Usage = func() { c.Ui.Output(c.Help()) }
|
||||
flags.StringVar(&pluginID, "plugin", "", "")
|
||||
flags.BoolVar(&verbose, "verbose", false, "")
|
||||
flags.Var(&secretsArgs, "secret", "secrets for snapshot, ex. -secret key=value")
|
||||
flags.IntVar(&perPage, "per-page", 30, "")
|
||||
flags.StringVar(&pageToken, "page-token", "", "")
|
||||
|
||||
if err := flags.Parse(args); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing arguments %s", err))
|
||||
|
@ -132,32 +143,33 @@ func (c *VolumeSnapshotListCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
req := &api.CSISnapshotListRequest{
|
||||
PluginID: pluginID,
|
||||
Secrets: secrets,
|
||||
QueryOptions: api.QueryOptions{PerPage: 30},
|
||||
PluginID: pluginID,
|
||||
Secrets: secrets,
|
||||
QueryOptions: api.QueryOptions{
|
||||
PerPage: int32(perPage),
|
||||
NextToken: pageToken,
|
||||
Params: map[string]string{},
|
||||
},
|
||||
}
|
||||
|
||||
for {
|
||||
resp, _, err := client.CSIVolumes().ListSnapshotsOpts(req)
|
||||
if err != nil && !errors.Is(err, io.EOF) {
|
||||
c.Ui.Error(fmt.Sprintf(
|
||||
"Error querying CSI external snapshots for plugin %q: %s", pluginID, err))
|
||||
return 1
|
||||
}
|
||||
if resp == nil || len(resp.Snapshots) == 0 {
|
||||
// several plugins return EOF once you hit the end of the page,
|
||||
// rather than an empty list
|
||||
break
|
||||
}
|
||||
resp, _, err := client.CSIVolumes().ListSnapshotsOpts(req)
|
||||
if err != nil && !errors.Is(err, io.EOF) {
|
||||
c.Ui.Error(fmt.Sprintf(
|
||||
"Error querying CSI external snapshots for plugin %q: %s", pluginID, err))
|
||||
return 1
|
||||
}
|
||||
if resp == nil || len(resp.Snapshots) == 0 {
|
||||
// several plugins return EOF once you hit the end of the page,
|
||||
// rather than an empty list
|
||||
return 0
|
||||
}
|
||||
|
||||
c.Ui.Output(csiFormatSnapshots(resp.Snapshots, verbose))
|
||||
req.NextToken = resp.NextToken
|
||||
if req.NextToken == "" {
|
||||
break
|
||||
}
|
||||
// we can't know the shape of arbitrarily-sized lists of snapshots,
|
||||
// so break after each page
|
||||
c.Ui.Output("...")
|
||||
c.Ui.Output(csiFormatSnapshots(resp.Snapshots, verbose))
|
||||
|
||||
if resp.NextToken != "" {
|
||||
c.Ui.Output(fmt.Sprintf(`
|
||||
Results have been paginated. To get the next page run:
|
||||
%s -page-token %s`, argsWithoutPageToken(os.Args), resp.NextToken))
|
||||
}
|
||||
|
||||
return 0
|
||||
|
|
|
@ -176,7 +176,11 @@ func (tc *CSIControllerPluginEBSTest) TestSnapshot(f *framework.F) {
|
|||
f.NoError(err, fmt.Sprintf("could not parse output:\n%v", out))
|
||||
f.Len(snaps, 1, fmt.Sprintf("could not parse output:\n%v", out))
|
||||
|
||||
out, err = e2e.Command("nomad", "volume", "snapshot", "list", "-plugin", ebsPluginID)
|
||||
// the snapshot we're looking for should be the first one because
|
||||
// we just created it, but give us some breathing room to allow
|
||||
// for concurrent test runs
|
||||
out, err = e2e.Command("nomad", "volume", "snapshot", "list",
|
||||
"-plugin", ebsPluginID, "-per-page", "10")
|
||||
requireNoErrorElseDump(f, err, "could not list volume snapshots", tc.pluginJobIDs)
|
||||
f.Contains(out, snaps[0]["ID"],
|
||||
fmt.Sprintf("volume snapshot list did not include expected snapshot:\n%v", out))
|
||||
|
|
|
@ -36,6 +36,8 @@ Nomad.
|
|||
matching plugins will be displayed.
|
||||
- `-secret`: Secrets to pass to the plugin to list snapshots. Accepts
|
||||
multiple flags in the form `-secret key=value`
|
||||
- `-per-page`: How many results to show per page.
|
||||
- `-page-token`: Where to start pagination.
|
||||
|
||||
When ACLs are enabled, this command requires a token with the
|
||||
`csi-list-volumes` capability for the plugin's namespace.
|
||||
|
|
Loading…
Reference in New Issue