diff --git a/cmd/get/get.go b/cmd/get/get.go index 0ab7bd5d..e46f14f5 100644 --- a/cmd/get/get.go +++ b/cmd/get/get.go @@ -47,7 +47,6 @@ func NewCmdGet() *cobra.Command { cmd.AddCommand(NewCmdGetCluster()) cmd.AddCommand(NewCmdGetNode()) cmd.AddCommand(NewCmdGetKubeconfig()) - cmd.AddCommand(NewCmdGetClusterToken()) // done return cmd diff --git a/cmd/get/getCluster.go b/cmd/get/getCluster.go index 1063001c..e2708fc5 100644 --- a/cmd/get/getCluster.go +++ b/cmd/get/getCluster.go @@ -22,9 +22,9 @@ THE SOFTWARE. package get import ( + "context" "fmt" "os" - "sort" "strings" k3cluster "github.com/rancher/k3d/pkg/cluster" @@ -37,41 +37,32 @@ import ( "github.com/liggitt/tabwriter" ) +// TODO : deal with --all flag to manage differentiate started cluster and stopped cluster like `docker ps` and `docker ps -a` +type clusterFlags struct { + noHeader bool + token bool +} + // NewCmdGetCluster returns a new cobra command func NewCmdGetCluster() *cobra.Command { + clusterFlags := clusterFlags{} + // create new command cmd := &cobra.Command{ Use: "cluster [NAME [NAME...]]", Aliases: []string{"clusters"}, Short: "Get cluster(s)", Long: `Get cluster(s).`, - Args: cobra.MinimumNArgs(0), // 0 or more; 0 = all Run: func(cmd *cobra.Command, args []string) { - clusters, headersOff := parseGetClusterCmd(cmd, args) - var existingClusters []*k3d.Cluster - if len(clusters) == 0 { // Option a) no cluster name specified -> get all clusters - found, err := k3cluster.GetClusters(cmd.Context(), runtimes.SelectedRuntime) - if err != nil { - log.Fatalln(err) - } - existingClusters = append(existingClusters, found...) - } else { // Option b) cluster name specified -> get specific cluster - for _, cluster := range clusters { - found, err := k3cluster.GetCluster(cmd.Context(), runtimes.SelectedRuntime, cluster) - if err != nil { - log.Fatalln(err) - } - existingClusters = append(existingClusters, found) - } - } - // print existing clusters - printClusters(existingClusters, headersOff) + clusters := buildClusterList(cmd.Context(), args) + PrintClusters(clusters, clusterFlags) }, } // add flags - cmd.Flags().Bool("no-headers", false, "Disable headers") + cmd.Flags().BoolVar(&clusterFlags.noHeader, "no-headers", false, "Disable headers") + cmd.Flags().BoolVar(&clusterFlags.token, "token", false, "Print k3s cluster token") // add subcommands @@ -79,54 +70,57 @@ func NewCmdGetCluster() *cobra.Command { return cmd } -func parseGetClusterCmd(cmd *cobra.Command, args []string) ([]*k3d.Cluster, bool) { +func buildClusterList(ctx context.Context, args []string) []*k3d.Cluster { + var clusters []*k3d.Cluster + var err error - // --no-headers - headersOff, err := cmd.Flags().GetBool("no-headers") - if err != nil { - log.Fatalln(err) - } - - // Args = cluster name if len(args) == 0 { - return nil, headersOff - } - - clusters := []*k3d.Cluster{} - for _, name := range args { - clusters = append(clusters, &k3d.Cluster{Name: name}) + // cluster name not specified : get all clusters + clusters, err = k3cluster.GetClusters(ctx, runtimes.SelectedRuntime) + if err != nil { + log.Fatalln(err) + } + } else { + for _, clusterName := range args { + // cluster name specified : get specific cluster + retrievedCluster, err := k3cluster.GetCluster(ctx, runtimes.SelectedRuntime, &k3d.Cluster{Name: clusterName}) + if err != nil { + log.Fatalln(err) + } + clusters = append(clusters, retrievedCluster) + } } - return clusters, headersOff + return clusters } -func printClusters(clusters []*k3d.Cluster, headersOff bool) { +// PrintPrintClusters : display list of cluster +func PrintClusters(clusters []*k3d.Cluster, flags clusterFlags) { tabwriter := tabwriter.NewWriter(os.Stdout, 6, 4, 3, ' ', tabwriter.RememberWidths) defer tabwriter.Flush() - if !headersOff { + if !flags.noHeader { headers := []string{"NAME", "MASTERS", "WORKERS"} // 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") } } - sort.Slice(clusters, func(i, j int) bool { - return clusters[i].Name < clusters[j].Name - }) + k3cluster.SortClusters(clusters) for _, cluster := range clusters { - masterCount := 0 - workerCount := 0 - for _, node := range cluster.Nodes { - if node.Role == k3d.MasterRole { - masterCount++ - } else if node.Role == k3d.WorkerRole { - workerCount++ - } + masterCount := cluster.MasterCount() + workerCount := cluster.WorkerCount() + + if flags.token { + fmt.Fprintf(tabwriter, "%s\t%d\t%d\t%s\n", cluster.Name, masterCount, workerCount, cluster.Token) + } else { + fmt.Fprintf(tabwriter, "%s\t%d\t%d\n", cluster.Name, masterCount, workerCount) } - fmt.Fprintf(tabwriter, "%s\t%d\t%d\n", cluster.Name, masterCount, workerCount) } } diff --git a/cmd/get/getClusterToken.go b/cmd/get/getClusterToken.go deleted file mode 100644 index 199b19ee..00000000 --- a/cmd/get/getClusterToken.go +++ /dev/null @@ -1,111 +0,0 @@ -/* -Copyright © 2020 The k3d Author(s) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -package get - -import ( - "fmt" - "os" - "sort" - "strings" - - "github.com/liggitt/tabwriter" - cliutil "github.com/rancher/k3d/cmd/util" - "github.com/rancher/k3d/pkg/cluster" - "github.com/rancher/k3d/pkg/runtimes" - k3d "github.com/rancher/k3d/pkg/types" - log "github.com/sirupsen/logrus" - "github.com/spf13/cobra" -) - -type clusterTokenFlags struct { - validableFlags cliutil.ValidableFlags - noHeader bool -} - -// NewCmdGetClusterToken returns a new cobra command -func NewCmdGetClusterToken() *cobra.Command { - - getClusterTokenFlags := clusterTokenFlags{} - - // create new command - cmd := &cobra.Command{ - Use: "k3stoken [CLUSTER [CLUSTER [...]] | --all]", - Short: "Get cluster token", - Long: `Get k3s cluster token.`, - Args: func(cmd *cobra.Command, args []string) error { - return cliutil.ValidateClusterNameOrAllFlag(args, getClusterTokenFlags.validableFlags) - }, - Run: func(cmd *cobra.Command, args []string) { - var clusters []*k3d.Cluster - var err error - - // generate list of clusters - if getClusterTokenFlags.validableFlags.All { - clusters, err = cluster.GetClusters(cmd.Context(), runtimes.SelectedRuntime) - if err != nil { - log.Fatalln(err) - } - } else { - for _, clusterName := range args { - retrievedCluster, err := cluster.GetCluster(cmd.Context(), runtimes.SelectedRuntime, &k3d.Cluster{Name: clusterName}) - if err != nil { - log.Fatalln(err) - } - clusters = append(clusters, retrievedCluster) - } - } - - // pretty print token - printToken(clusters, getClusterTokenFlags.noHeader) - }, - } - - // add flags - cmd.Flags().BoolVarP(&getClusterTokenFlags.validableFlags.All, "all", "a", false, "Get k3s token from all existing clusters") - cmd.Flags().BoolVar(&getClusterTokenFlags.noHeader, "no-headers", false, "Disable headers") - - // done - return cmd -} - -func printToken(clusters []*k3d.Cluster, headersOff bool) { - - tabwriter := tabwriter.NewWriter(os.Stdout, 6, 4, 3, ' ', tabwriter.RememberWidths) - defer tabwriter.Flush() - - if !headersOff { - headers := []string{"CLUSTER", "TOKEN"} - _, err := fmt.Fprintf(tabwriter, "%s\n", strings.Join(headers, "\t")) - if err != nil { - log.Fatalln("Failed to print headers") - } - } - - // alphabetical sort by cluster name - sort.Slice(clusters, func(i, j int) bool { - return clusters[i].Name < clusters[j].Name - }) - - for _, cluster := range clusters { - fmt.Fprintf(tabwriter, "%s\t%s\n", cluster.Name, string(cluster.Token)) - } -} diff --git a/cmd/util/args.go b/cmd/util/args.go deleted file mode 100644 index e2a7fa79..00000000 --- a/cmd/util/args.go +++ /dev/null @@ -1,44 +0,0 @@ -/* -Copyright © 2020 The k3d Author(s) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -package util - -import ( - "fmt" -) - -// struct describe flags which could be validate thanks to this file's functions -type ValidableFlags struct { - All bool -} - -// ValidateClusterNameOrAllFlag checks, if cluster name or --all arg is set -func ValidateClusterNameOrAllFlag(args []string, flagStruct ValidableFlags) error { - - clusterNamePresent := len(args) > 0 - getAllFlagPresent := flagStruct.All - - // xor : provide cluster name or all flags - if clusterNamePresent != getAllFlagPresent { - return nil - } - return fmt.Errorf("Need to specify one or more cluster names *or* set `--all` flag") -} diff --git a/pkg/cluster/cluster.go b/pkg/cluster/cluster.go index ea0b6c96..3b6634c7 100644 --- a/pkg/cluster/cluster.go +++ b/pkg/cluster/cluster.go @@ -25,6 +25,7 @@ import ( "bytes" "context" "fmt" + "sort" "strconv" "strings" "time" @@ -591,3 +592,11 @@ func StopCluster(ctx context.Context, runtime k3drt.Runtime, cluster *k3d.Cluste } return nil } + +// SortClusters : in place sort cluster list by cluster name alphabetical order +func SortClusters(clusters []*k3d.Cluster) []*k3d.Cluster { + sort.Slice(clusters, func(i, j int) bool { + return clusters[i].Name < clusters[j].Name + }) + return clusters +} \ No newline at end of file diff --git a/pkg/types/types.go b/pkg/types/types.go index cb06a182..b1950259 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -170,6 +170,27 @@ type Cluster struct { ImageVolume string `yaml:"image_volume" json:"imageVolume,omitempty"` } +// MasterCount return number of master node into cluster +func (c *Cluster) MasterCount() int { + masterCount := 0 + for _, node := range c.Nodes { + if node.Role == MasterRole { + masterCount++ + } + } + return masterCount +} +// WorkerCount return number of worker node into cluster +func (c *Cluster) WorkerCount() int { + workerCount := 0 + for _, node := range c.Nodes { + if node.Role == WorkerRole { + workerCount++ + } + } + return workerCount +} + // Node describes a k3d node type Node struct { Name string `yaml:"name" json:"name,omitempty"` diff --git a/tests/common.sh b/tests/common.sh index 7b9eb5ca..42b180f4 100755 --- a/tests/common.sh +++ b/tests/common.sh @@ -110,5 +110,5 @@ check_volume_exists() { check_cluster_token_exist() { [ -n "$EXE" ] || abort "EXE is not defined" - $EXE get k3stoken "$1" >/dev/null 2>&1 + $EXE get cluster "$1" --token | grep "TOKEN" >/dev/null 2>&1 }