[Feature] Options for formatted output of `cluster list` (#416, @inercia))

This adds a `--ouput` flag to `cluster list` for dumping the
list of clusters as a JSON or YAML document.

Signed-off-by: Alvaro Saurin <alvaro.saurin@gmail.com>
pull/419/head
Alvaro 4 years ago committed by GitHub
parent db0b929e83
commit a93932e5b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 78
      cmd/cluster/clusterList.go
  2. 1
      go.mod
  3. 6
      pkg/types/types.go
  4. 1
      vendor/modules.txt

@ -23,6 +23,7 @@ package cluster
import (
"context"
"encoding/json"
"fmt"
"os"
"strings"
@ -32,6 +33,7 @@ import (
"github.com/rancher/k3d/v3/pkg/runtimes"
k3d "github.com/rancher/k3d/v3/pkg/types"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"
log "github.com/sirupsen/logrus"
@ -42,11 +44,11 @@ import (
type clusterFlags struct {
noHeader bool
token bool
output string
}
// NewCmdClusterList returns a new cobra command
func NewCmdClusterList() *cobra.Command {
clusterFlags := clusterFlags{}
// create new command
@ -65,6 +67,7 @@ func NewCmdClusterList() *cobra.Command {
// add flags
cmd.Flags().BoolVar(&clusterFlags.noHeader, "no-headers", false, "Disable headers")
cmd.Flags().BoolVar(&clusterFlags.token, "token", false, "Print k3s cluster token")
cmd.Flags().StringVarP(&clusterFlags.output, "output", "o", "", "Output format. One of: json|yaml")
// add subcommands
@ -98,18 +101,33 @@ func buildClusterList(ctx context.Context, args []string) []*k3d.Cluster {
// PrintPrintClusters : display list of cluster
func PrintClusters(clusters []*k3d.Cluster, flags clusterFlags) {
// the output details printed when we dump JSON/YAML
type jsonOutput struct {
k3d.Cluster
ServersRunning int `yaml:"servers_running" json:"serversRunning"`
ServersCount int `yaml:"servers_count" json:"serversCount"`
AgentsRunning int `yaml:"agents_running" json:"agentsRunning"`
AgentsCount int `yaml:"agents_count" json:"agentsCount"`
LoadBalancer bool `yaml:"has_lb,omitempty" json:"hasLoadbalancer,omitempty"`
}
jsonOutputEntries := []jsonOutput{}
outputFormat := strings.ToLower(flags.output)
tabwriter := tabwriter.NewWriter(os.Stdout, 6, 4, 3, ' ', tabwriter.RememberWidths)
defer tabwriter.Flush()
if !flags.noHeader {
headers := []string{"NAME", "SERVERS", "AGENTS", "LOADBALANCER"} // TODO: getCluster: add status column
if flags.token {
headers = append(headers, "TOKEN")
}
_, err := fmt.Fprintf(tabwriter, "%s\n", strings.Join(headers, "\t"))
if err != nil {
log.Fatalln("Failed to print headers")
if outputFormat != "json" && outputFormat != "yaml" {
if !flags.noHeader {
headers := []string{"NAME", "SERVERS", "AGENTS", "LOADBALANCER"} // TODO: getCluster: add status column
if flags.token {
headers = append(headers, "TOKEN")
}
_, err := fmt.Fprintf(tabwriter, "%s\n", strings.Join(headers, "\t"))
if err != nil {
log.Fatalln("Failed to print headers")
}
}
}
@ -120,10 +138,46 @@ func PrintClusters(clusters []*k3d.Cluster, flags clusterFlags) {
agentCount, agentsRunning := cluster.AgentCountRunning()
hasLB := cluster.HasLoadBalancer()
if flags.token {
fmt.Fprintf(tabwriter, "%s\t%d/%d\t%d/%d\t%t\t%s\n", cluster.Name, serversRunning, serverCount, agentsRunning, agentCount, hasLB, cluster.Token)
if outputFormat == "json" || outputFormat == "yaml" {
entry := jsonOutput{
Cluster: *cluster,
ServersRunning: serversRunning,
ServersCount: serverCount,
AgentsRunning: agentsRunning,
AgentsCount: agentCount,
LoadBalancer: hasLB,
}
if !flags.token {
entry.Token = ""
}
// clear some things
entry.ExternalDatastore = nil
jsonOutputEntries = append(jsonOutputEntries, entry)
} else {
fmt.Fprintf(tabwriter, "%s\t%d/%d\t%d/%d\t%t\n", cluster.Name, serversRunning, serverCount, agentsRunning, agentCount, hasLB)
if flags.token {
fmt.Fprintf(tabwriter, "%s\t%d/%d\t%d/%d\t%t\t%s\n", cluster.Name, serversRunning, serverCount, agentsRunning, agentCount, hasLB, cluster.Token)
} else {
fmt.Fprintf(tabwriter, "%s\t%d/%d\t%d/%d\t%t\n", cluster.Name, serversRunning, serverCount, agentsRunning, agentCount, hasLB)
}
}
}
if outputFormat == "json" {
b, err := json.Marshal(jsonOutputEntries)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(b))
} else if outputFormat == "yaml" {
b, err := yaml.Marshal(jsonOutputEntries)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(b))
}
}

@ -39,6 +39,7 @@ require (
google.golang.org/grpc v1.33.1 // indirect
google.golang.org/protobuf v1.25.0 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/yaml.v2 v2.3.0
gotest.tools/v3 v3.0.2 // indirect
k8s.io/client-go v0.17.0
k8s.io/utils v0.0.0-20200109141947-94aeca20bf09 // indirect

@ -182,10 +182,10 @@ type Cluster struct {
Token string `yaml:"cluster_token" json:"clusterToken,omitempty"`
Nodes []*Node `yaml:"nodes" json:"nodes,omitempty"`
InitNode *Node // init server node
ExternalDatastore ExternalDatastore `yaml:"external_datastore" json:"externalDatastore,omitempty"`
CreateClusterOpts *ClusterCreateOpts `yaml:"options" json:"options,omitempty"`
ExternalDatastore *ExternalDatastore `yaml:"external_datastore,omitempty" json:"externalDatastore,omitempty"`
CreateClusterOpts *ClusterCreateOpts `yaml:"options,omitempty" json:"options,omitempty"`
ExposeAPI ExposeAPI `yaml:"expose_api" json:"exposeAPI,omitempty"`
ServerLoadBalancer *Node `yaml:"server_loadbalancer" json:"serverLoadBalancer,omitempty"`
ServerLoadBalancer *Node `yaml:"server_loadbalancer,omitempty" json:"serverLoadBalancer,omitempty"`
ImageVolume string `yaml:"image_volume" json:"imageVolume,omitempty"`
}

@ -366,6 +366,7 @@ google.golang.org/protobuf/types/known/timestamppb
# gopkg.in/inf.v0 v0.9.1
gopkg.in/inf.v0
# gopkg.in/yaml.v2 v2.3.0
## explicit
gopkg.in/yaml.v2
# gotest.tools/v3 v3.0.2
## explicit

Loading…
Cancel
Save