cli: add pagination flags to service info command. (#12730)
This commit is contained in:
parent
d200a66509
commit
046831466c
|
@ -99,7 +99,7 @@ func (s *HTTPServer) serviceGetRequest(
|
|||
if err := s.agent.RPC(structs.ServiceRegistrationGetServiceRPCMethod, &args, &reply); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
setIndex(resp, reply.Index)
|
||||
setMeta(resp, &reply.QueryMeta)
|
||||
|
||||
if reply.Services == nil {
|
||||
reply.Services = make([]*structs.ServiceRegistration, 0)
|
||||
|
|
|
@ -2,6 +2,7 @@ package command
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
|
@ -37,6 +38,12 @@ Service Info Options:
|
|||
-verbose
|
||||
Display full information.
|
||||
|
||||
-per-page
|
||||
How many results to show per page.
|
||||
|
||||
-page-token
|
||||
Where to start pagination.
|
||||
|
||||
-filter
|
||||
Specifies an expression used to filter query results.
|
||||
|
||||
|
@ -57,10 +64,12 @@ func (s *ServiceInfoCommand) Synopsis() string {
|
|||
func (s *ServiceInfoCommand) AutocompleteFlags() complete.Flags {
|
||||
return mergeAutocompleteFlags(s.Meta.AutocompleteFlags(FlagSetClient),
|
||||
complete.Flags{
|
||||
"-json": complete.PredictNothing,
|
||||
"-filter": complete.PredictAnything,
|
||||
"-t": complete.PredictAnything,
|
||||
"-verbose": complete.PredictNothing,
|
||||
"-json": complete.PredictNothing,
|
||||
"-filter": complete.PredictAnything,
|
||||
"-per-page": complete.PredictAnything,
|
||||
"-page-token": complete.PredictAnything,
|
||||
"-t": complete.PredictAnything,
|
||||
"-verbose": complete.PredictNothing,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -70,8 +79,9 @@ func (s *ServiceInfoCommand) Name() string { return "service info" }
|
|||
// Run satisfies the cli.Command Run function.
|
||||
func (s *ServiceInfoCommand) Run(args []string) int {
|
||||
var (
|
||||
json, verbose bool
|
||||
tmpl, filter string
|
||||
json, verbose bool
|
||||
perPage int
|
||||
tmpl, filter, pageToken string
|
||||
)
|
||||
|
||||
flags := s.Meta.FlagSet(s.Name(), FlagSetClient)
|
||||
|
@ -80,6 +90,8 @@ func (s *ServiceInfoCommand) Run(args []string) int {
|
|||
flags.BoolVar(&verbose, "verbose", false, "")
|
||||
flags.StringVar(&tmpl, "t", "", "")
|
||||
flags.StringVar(&filter, "filter", "", "")
|
||||
flags.IntVar(&perPage, "per-page", 0, "")
|
||||
flags.StringVar(&pageToken, "page-token", "", "")
|
||||
if err := flags.Parse(args); err != nil {
|
||||
return 1
|
||||
}
|
||||
|
@ -99,10 +111,12 @@ func (s *ServiceInfoCommand) Run(args []string) int {
|
|||
|
||||
// Set up the options to capture any filter passed.
|
||||
opts := api.QueryOptions{
|
||||
Filter: filter,
|
||||
Filter: filter,
|
||||
PerPage: int32(perPage),
|
||||
NextToken: pageToken,
|
||||
}
|
||||
|
||||
serviceInfo, _, err := client.Services().Get(args[0], &opts)
|
||||
serviceInfo, qm, err := client.Services().Get(args[0], &opts)
|
||||
if err != nil {
|
||||
s.Ui.Error(fmt.Sprintf("Error listing service registrations: %s", err))
|
||||
return 1
|
||||
|
@ -147,6 +161,12 @@ func (s *ServiceInfoCommand) Run(args []string) int {
|
|||
} else {
|
||||
s.formatOutput(sortedJobID, jobIDServices)
|
||||
}
|
||||
|
||||
if qm.NextToken != "" {
|
||||
s.Ui.Output(fmt.Sprintf("\nResults have been paginated. To get the next page run: \n\n%s ",
|
||||
argsWithNewPageToken(os.Args, qm.NextToken)))
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
@ -194,3 +214,41 @@ func (s *ServiceInfoCommand) formatVerboseOutput(jobIDs []string, jobServices ma
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// argsWithNewPageToken takes the arguments which called the CLI and modifies
|
||||
// them to include the correct next token. The function ensures the argument
|
||||
// ordering is maintained which is vital when using pagination on info related
|
||||
// calls which have an identifier as their final argument.
|
||||
func argsWithNewPageToken(osArgs []string, nextToken string) string {
|
||||
|
||||
// Copy the arguments into a new array which will be modified and make a
|
||||
// note of the original length as we may need to modify the length if this
|
||||
// is the first pagination call without a next token.
|
||||
newArgs := osArgs
|
||||
numArgs := len(newArgs)
|
||||
|
||||
for i := 0; i < numArgs; i++ {
|
||||
|
||||
// If the caller already included a pagination token, replace this
|
||||
// occurrence with the new next token and exit as we don't need to
|
||||
// modify any other arguments.
|
||||
if strings.HasPrefix(newArgs[i], "-page-token") {
|
||||
if strings.Contains(newArgs[i], "=") {
|
||||
newArgs[i] = "-page-token=" + nextToken
|
||||
} else {
|
||||
newArgs[i+1] = nextToken
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
// If we have reached the final argument (service name) and are still
|
||||
// looping we have not added the next token argument. Add this while
|
||||
// ensuring the service name if the final argument on the command.
|
||||
if i == numArgs-1 {
|
||||
serviceName := newArgs[i]
|
||||
newArgs[i] = "-page-token=" + nextToken
|
||||
newArgs = append(newArgs, serviceName)
|
||||
}
|
||||
}
|
||||
return strings.Join(newArgs, " ")
|
||||
}
|
||||
|
|
|
@ -120,3 +120,58 @@ func TestServiceInfoCommand_Run(t *testing.T) {
|
|||
ui.OutputWriter.Reset()
|
||||
ui.ErrorWriter.Reset()
|
||||
}
|
||||
|
||||
func Test_argsWithNewPageToken(t *testing.T) {
|
||||
ci.Parallel(t)
|
||||
|
||||
testCases := []struct {
|
||||
inputOsArgs []string
|
||||
inputNextToken string
|
||||
expectedOutput string
|
||||
name string
|
||||
}{
|
||||
{
|
||||
inputOsArgs: []string{"nomad", "service", "info", "-page-token=abcdef", "example-cache"},
|
||||
inputNextToken: "ghijkl",
|
||||
expectedOutput: "nomad service info -page-token=ghijkl example-cache",
|
||||
name: "page token with equals sign",
|
||||
},
|
||||
{
|
||||
inputOsArgs: []string{"nomad", "service", "info", "-page-token", "abcdef", "example-cache"},
|
||||
inputNextToken: "ghijkl",
|
||||
expectedOutput: "nomad service info -page-token ghijkl example-cache",
|
||||
name: "page token with whitespace gap",
|
||||
},
|
||||
{
|
||||
inputOsArgs: []string{"nomad", "service", "info", "-per-page", "3", "-page-token", "abcdef", "example-cache"},
|
||||
inputNextToken: "ghijkl",
|
||||
expectedOutput: "nomad service info -per-page 3 -page-token ghijkl example-cache",
|
||||
name: "per page and page token",
|
||||
},
|
||||
{
|
||||
inputOsArgs: []string{"nomad", "service", "info", "-page-token", "abcdef", "-per-page", "3", "example-cache"},
|
||||
inputNextToken: "ghijkl",
|
||||
expectedOutput: "nomad service info -page-token ghijkl -per-page 3 example-cache",
|
||||
name: "page token and per page",
|
||||
},
|
||||
{
|
||||
inputOsArgs: []string{"nomad", "service", "info", "-page-token", "abcdef", "-per-page=3", "example-cache"},
|
||||
inputNextToken: "ghijkl",
|
||||
expectedOutput: "nomad service info -page-token ghijkl -per-page=3 example-cache",
|
||||
name: "page token and per page with equal",
|
||||
},
|
||||
{
|
||||
inputOsArgs: []string{"nomad", "service", "info", "-verbose", "-page-token", "abcdef", "-per-page=3", "example-cache"},
|
||||
inputNextToken: "ghijkl",
|
||||
expectedOutput: "nomad service info -verbose -page-token ghijkl -per-page=3 example-cache",
|
||||
name: "page token per page with verbose",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
actualOutput := argsWithNewPageToken(tc.inputOsArgs, tc.inputNextToken)
|
||||
require.Equal(t, tc.expectedOutput, actualOutput)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,12 @@ capability for the service's namespace.
|
|||
|
||||
## Info Options
|
||||
|
||||
- `-per-page`: How many results to show per page.
|
||||
|
||||
- `-page-token`: Where to start pagination.
|
||||
|
||||
- `-filter`: Specifies an expression used to filter query results.
|
||||
|
||||
- `-json` : Output the service registrations in JSON format.
|
||||
|
||||
- `-t` : Format and display the service registrations using a Go template.
|
||||
|
|
Loading…
Reference in New Issue