TUN-3854: cloudflared tunnel list flags to sort output

This commit is contained in:
Adam Chalmers 2021-02-03 12:22:57 -06:00
parent 0d22106416
commit dca77ee13e
1 changed files with 57 additions and 6 deletions

View File

@ -28,6 +28,7 @@ import (
) )
const ( const (
allSortByOptions = "name, id, createdAt, deletedAt, numConnections"
CredFileFlagAlias = "cred-file" CredFileFlagAlias = "cred-file"
CredFileFlag = "credentials-file" CredFileFlag = "credentials-file"
@ -67,6 +68,17 @@ var (
Aliases: []string{"o"}, Aliases: []string{"o"},
Usage: "Render output using given `FORMAT`. Valid options are 'json' or 'yaml'", Usage: "Render output using given `FORMAT`. Valid options are 'json' or 'yaml'",
}) })
sortByFlag = &cli.StringFlag{
Name: "sort-by",
Value: "name",
Usage: fmt.Sprintf("Sorts the list of tunnels by the given field. Valid options are {%s}", allSortByOptions),
EnvVars: []string{"TUNNEL_LIST_SORT_BY"},
}
invertSortFlag = &cli.BoolFlag{
Name: "invert-sort",
Usage: "Inverts the sort order of the tunnel list.",
EnvVars: []string{"TUNNEL_LIST_INVERT_SORT"},
}
forceFlag = altsrc.NewBoolFlag(&cli.BoolFlag{ forceFlag = altsrc.NewBoolFlag(&cli.BoolFlag{
Name: "force", Name: "force",
Aliases: []string{"f"}, Aliases: []string{"f"},
@ -166,7 +178,16 @@ func buildListCommand() *cli.Command {
Usage: "List existing tunnels", Usage: "List existing tunnels",
UsageText: "cloudflared tunnel [tunnel command options] list [subcommand options]", UsageText: "cloudflared tunnel [tunnel command options] list [subcommand options]",
Description: "cloudflared tunnel list will display all active tunnels, their created time and associated connections. Use -d flag to include deleted tunnels. See the list of options to filter the list", Description: "cloudflared tunnel list will display all active tunnels, their created time and associated connections. Use -d flag to include deleted tunnels. See the list of options to filter the list",
Flags: []cli.Flag{outputFormatFlag, showDeletedFlag, listNameFlag, listExistedAtFlag, listIDFlag, showRecentlyDisconnected}, Flags: []cli.Flag{
outputFormatFlag,
showDeletedFlag,
listNameFlag,
listExistedAtFlag,
listIDFlag,
showRecentlyDisconnected,
sortByFlag,
invertSortFlag,
},
CustomHelpTemplate: commandHelpTemplate(), CustomHelpTemplate: commandHelpTemplate(),
} }
} }
@ -200,6 +221,36 @@ func listCommand(c *cli.Context) error {
return err return err
} }
// Sort the tunnels
sortBy := c.String("sort-by")
invalidSortField := false
sort.Slice(tunnels, func(i, j int) bool {
cmp := func() bool {
switch sortBy {
case "name":
return tunnels[i].Name < tunnels[j].Name
case "id":
return tunnels[i].ID.String() < tunnels[j].ID.String()
case "createdAt":
return tunnels[i].CreatedAt.Unix() < tunnels[j].CreatedAt.Unix()
case "deletedAt":
return tunnels[i].DeletedAt.Unix() < tunnels[j].DeletedAt.Unix()
case "numConnections":
return len(tunnels[i].Connections) < len(tunnels[j].Connections)
default:
invalidSortField = true
return tunnels[i].Name < tunnels[j].Name
}
}()
if c.Bool("invert-sort") {
return !cmp
}
return cmp
})
if invalidSortField {
sc.log.Error().Msgf("%s is not a valid sort field. Valid sort fields are %s. Defaulting to 'name'.", sortBy, allSortByOptions)
}
if outputFormat := c.String(outputFormatFlag.Name); outputFormat != "" { if outputFormat := c.String(outputFormatFlag.Name); outputFormat != "" {
return renderOutput(outputFormat, tunnels) return renderOutput(outputFormat, tunnels)
} }