From a0ce71ec1363c210f12b92926ba911896bd32134 Mon Sep 17 00:00:00 2001
From: haozi007 <liuhao27@huawei.com>
Date: Thu, 9 Sep 2021 03:28:17 +0100
Subject: [PATCH 3/4] add list command for eggo

Signed-off-by: haozi007 <liuhao27@huawei.com>
---
 cmd/configs.go   |   6 +--
 cmd/eggo.go      |   1 +
 cmd/list.go      | 122 +++++++++++++++++++++++++++++++++++++++++++++++
 pkg/api/tools.go |   4 ++
 4 files changed, 130 insertions(+), 3 deletions(-)
 create mode 100644 cmd/list.go

diff --git a/cmd/configs.go b/cmd/configs.go
index dfc4c45..04e1ec8 100644
--- a/cmd/configs.go
+++ b/cmd/configs.go
@@ -90,11 +90,11 @@ func defaultDeployConfigPath() string {
 }
 
 func eggoPlaceHolderPath(ClusterID string) string {
-	return filepath.Join(api.EggoHomePath, ClusterID, ".eggo.pid")
+	return filepath.Join(api.GetEggoClusterPath(), ClusterID, ".eggo.pid")
 }
 
 func savedDeployConfigPath(ClusterID string) string {
-	return filepath.Join(api.EggoHomePath, ClusterID, "deploy.yaml")
+	return filepath.Join(api.GetEggoClusterPath(), ClusterID, "deploy.yaml")
 }
 
 func saveDeployConfig(cc *DeployConfig, filePath string) error {
@@ -104,7 +104,7 @@ func saveDeployConfig(cc *DeployConfig, filePath string) error {
 	}
 
 	cleanPath := filepath.Clean(filePath)
-	if !strings.HasPrefix(cleanPath, api.EggoHomePath) {
+	if !strings.HasPrefix(cleanPath, api.GetEggoClusterPath()) {
 		return fmt.Errorf("invalid config file path %v", filePath)
 	}
 
diff --git a/cmd/eggo.go b/cmd/eggo.go
index 7e42833..272fb17 100644
--- a/cmd/eggo.go
+++ b/cmd/eggo.go
@@ -99,6 +99,7 @@ func NewEggoCmd() *cobra.Command {
 	eggoCmd.AddCommand(NewTemplateCmd())
 	eggoCmd.AddCommand(NewJoinCmd())
 	eggoCmd.AddCommand(NewDeleteCmd())
+	eggoCmd.AddCommand(NewListCmd())
 
 	return eggoCmd
 }
diff --git a/cmd/list.go b/cmd/list.go
new file mode 100644
index 0000000..27729ba
--- /dev/null
+++ b/cmd/list.go
@@ -0,0 +1,122 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
+ * eggo licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ *     http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: haozi007
+ * Create: 2021-09-09
+ * Description: eggo list command implement
+ ******************************************************************************/
+
+package cmd
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+
+	"github.com/sirupsen/logrus"
+	"github.com/spf13/cobra"
+	"isula.org/eggo/pkg/api"
+)
+
+type clusterInfo struct {
+	name      string
+	masterCnt int
+	workerCnt int
+	status    string
+}
+
+var (
+	infos []clusterInfo
+)
+
+func addClusterInfo(name string, conf *DeployConfig, err error) {
+	info := clusterInfo{
+		name: name,
+	}
+	if err != nil {
+		info.status = "unknow"
+		logrus.Debugf("%s: %s", info.name, err.Error())
+		infos = append(infos, info)
+		return
+	}
+	if conf.Masters != nil {
+		info.masterCnt = len(conf.Masters)
+	}
+	if conf.Workers != nil {
+		info.workerCnt = len(conf.Workers)
+	}
+
+	if terr := RunChecker(conf); terr != nil {
+		info.status = "broken"
+		logrus.Debugf("%s: %s", info.name, terr.Error())
+	} else {
+		info.status = "success"
+	}
+
+	infos = append(infos, info)
+}
+
+func checkFile(path string, info os.FileInfo, err error) error {
+	if err != nil {
+		return err
+	}
+	if !info.IsDir() {
+		logrus.Debugf("ingore non-dir: %q", path)
+		return nil
+	}
+
+	if path == api.GetEggoClusterPath() {
+		return nil
+	}
+
+	conf, err := loadDeployConfig(savedDeployConfigPath(info.Name()))
+	addClusterInfo(info.Name(), conf, err)
+	return filepath.SkipDir
+}
+
+func showClustersInfo() {
+	maxLen := 8
+	for _, info := range infos {
+		if len(info.name) > maxLen {
+			maxLen = len(info.name)
+		}
+	}
+	fmt.Printf("Name%*s\tMasters\tWorkers\tStatus\n", maxLen, "")
+	for _, info := range infos {
+		fmt.Printf("%s%*s\t%d\t%d\t%s\n", info.name, len(info.name)-maxLen, "", info.masterCnt, info.workerCnt, info.status)
+	}
+}
+
+func listClusters(cmd *cobra.Command, args []string) error {
+	infos = nil
+	if opts.debug {
+		initLog()
+	}
+
+	eggoDir := api.GetEggoClusterPath()
+
+	if err := filepath.Walk(eggoDir, checkFile); err != nil {
+		logrus.Debugf("walk eggo cluster dir: %s, err: %v\n", eggoDir, err)
+	}
+
+	showClustersInfo()
+
+	return nil
+}
+
+func NewListCmd() *cobra.Command {
+	listCmd := &cobra.Command{
+		Use:   "list",
+		Short: "list clusters which manager by eggo",
+		RunE:  listClusters,
+	}
+
+	return listCmd
+}
diff --git a/pkg/api/tools.go b/pkg/api/tools.go
index 89a82d5..c9aaf93 100644
--- a/pkg/api/tools.go
+++ b/pkg/api/tools.go
@@ -63,6 +63,10 @@ func GetCertificateStorePath(cluster string) string {
 	return filepath.Join(EggoHomePath, cluster, "pki")
 }
 
+func GetEggoClusterPath() string {
+	return EggoHomePath
+}
+
 func GetEtcdServers(ecc *EtcdClusterConfig) string {
 	//etcd_servers="https://${MASTER_IPS[$i]}:2379"
 	//etcd_servers="$etcd_servers,https://${MASTER_IPS[$i]}:2379"
-- 
2.25.1

