From 537adf313b9cd4eff4e19f79859e17bab1967052 Mon Sep 17 00:00:00 2001 From: baurine <2008.hbl@gmail.com> Date: Thu, 18 Feb 2021 16:22:35 +0800 Subject: [PATCH 1/3] refine ListCluster method, extract GetClusterList --- pkg/cluster/manager/list.go | 50 +++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/pkg/cluster/manager/list.go b/pkg/cluster/manager/list.go index b103721bf1..74f25a9d25 100644 --- a/pkg/cluster/manager/list.go +++ b/pkg/cluster/manager/list.go @@ -22,9 +22,18 @@ import ( "github.com/pingcap/tiup/pkg/meta" ) +// Cluster represents a clsuter +type Cluster struct { + Name string `json:"name"` + User string `json:"user"` + Version string `json:"version"` + Path string `json:"path"` + PrivateKey string `json:"private_key"` +} + // ListCluster list the clusters. func (m *Manager) ListCluster() error { - names, err := m.specManager.List() + clusters, err := m.GetClusterList() if err != nil { return err } @@ -33,25 +42,46 @@ func (m *Manager) ListCluster() error { // Header {"Name", "User", "Version", "Path", "PrivateKey"}, } + for _, v := range clusters { + clusterTable = append(clusterTable, []string{ + v.Name, + v.User, + v.Version, + v.Path, + v.PrivateKey, + }) + } + + cliutil.PrintTable(clusterTable, true) + return nil +} + +// GetClusterList get the clusters list. +func (m *Manager) GetClusterList() ([]Cluster, error) { + names, err := m.specManager.List() + if err != nil { + return nil, err + } + + var clusters = []Cluster{} for _, name := range names { metadata, err := m.meta(name) if err != nil && !errors.Is(perrs.Cause(err), meta.ErrValidate) && !errors.Is(perrs.Cause(err), spec.ErrNoTiSparkMaster) { - return perrs.Trace(err) + return nil, perrs.Trace(err) } base := metadata.GetBaseMeta() - clusterTable = append(clusterTable, []string{ - name, - base.User, - base.Version, - m.specManager.Path(name), - m.specManager.Path(name, "ssh", "id_rsa"), + clusters = append(clusters, Cluster{ + Name: name, + User: base.User, + Version: base.Version, + Path: m.specManager.Path(name), + PrivateKey: m.specManager.Path(name, "ssh", "id_rsa"), }) } - cliutil.PrintTable(clusterTable, true) - return nil + return clusters, nil } From a3eecc29f40e6d496a54c07dae36c6d1f968c5cf Mon Sep 17 00:00:00 2001 From: baurine <2008.hbl@gmail.com> Date: Thu, 18 Feb 2021 21:42:53 +0800 Subject: [PATCH 2/3] refine Display method, extract GetClusterTopology --- pkg/cluster/manager/display.go | 170 +++++++++++++++++++++++---------- 1 file changed, 117 insertions(+), 53 deletions(-) diff --git a/pkg/cluster/manager/display.go b/pkg/cluster/manager/display.go index 8948e9cce4..b6249a9b5e 100644 --- a/pkg/cluster/manager/display.go +++ b/pkg/cluster/manager/display.go @@ -35,14 +35,30 @@ import ( "github.com/pingcap/tiup/pkg/utils" ) +// InstInfo represents an instance info +type InstInfo struct { + ID string `json:"id"` + Role string `json:"role"` + Host string `json:"host"` + Ports string `json:"ports"` + OsArch string `json:"os_arch"` + Status string `json:"status"` + DataDir string `json:"data_dir"` + DeployDir string `json:"deploy_dir"` + + ComponentName string + Port int +} + // Display cluster meta and topology. func (m *Manager) Display(name string, opt operator.Options) error { - metadata, err := m.meta(name) - if err != nil && !errors.Is(perrs.Cause(err), meta.ErrValidate) && - !errors.Is(perrs.Cause(err), spec.ErrNoTiSparkMaster) { + ctx := ctxt.New(context.Background()) + clusterInstInfos, err := m.GetClusterTopology(ctx, name, opt) + if err != nil { return err } + metadata, _ := m.meta(name) topo := metadata.GetTopology() base := metadata.GetBaseMeta() // display cluster meta @@ -71,16 +87,87 @@ func (m *Manager) Display(name string, opt operator.Options) error { // Header {"ID", "Role", "Host", "Ports", "OS/Arch", "Status", "Data Dir", "Deploy Dir"}, } + masterActive := make([]string, 0) + for _, v := range clusterInstInfos { + clusterTable = append(clusterTable, []string{ + color.CyanString(v.ID), + v.Role, + v.Host, + v.Ports, + v.OsArch, + formatInstanceStatus(v.Status), + v.DataDir, + v.DeployDir, + }) - ctx := ctxt.New(context.Background()) - err = SetSSHKeySet(ctx, m.specManager.Path(name, "ssh", "id_rsa"), m.specManager.Path(name, "ssh", "id_rsa.pub")) + if v.ComponentName != spec.ComponentPD && v.ComponentName != spec.ComponentDMMaster { + continue + } + if strings.HasPrefix(v.Status, "Up") || strings.HasPrefix(v.Status, "Healthy") { + instAddr := fmt.Sprintf("%s:%d", v.Host, v.Port) + masterActive = append(masterActive, instAddr) + } + } + + tlsCfg, err := topo.TLSConfig(m.specManager.Path(name, spec.TLSCertKeyDir)) if err != nil { return err } + var dashboardAddr string + if t, ok := topo.(*spec.Specification); ok { + var err error + dashboardAddr, err = t.GetDashboardAddress(tlsCfg, masterActive...) + if err == nil && !set.NewStringSet("", "auto", "none").Exist(dashboardAddr) { + schema := "http" + if tlsCfg != nil { + schema = "https" + } + fmt.Printf("Dashboard URL: %s\n", cyan.Sprintf("%s://%s/dashboard", schema, dashboardAddr)) + } + } + + cliutil.PrintTable(clusterTable, true) + fmt.Printf("Total nodes: %d\n", len(clusterTable)-1) + + if t, ok := topo.(*spec.Specification); ok { + // Check if TiKV's label set correctly + pdClient := api.NewPDClient(masterActive, 10*time.Second, tlsCfg) + if lbs, err := pdClient.GetLocationLabels(); err != nil { + log.Debugf("get location labels from pd failed: %v", err) + } else if err := spec.CheckTiKVLabels(lbs, pdClient); err != nil { + color.Yellow("\nWARN: there is something wrong with TiKV labels, which may cause data losing:\n%v", err) + } + + // Check if there is some instance in tombstone state + nodes, _ := operator.DestroyTombstone(ctx, t, true /* returnNodesOnly */, opt, tlsCfg) + if len(nodes) != 0 { + color.Green("There are some nodes can be pruned: \n\tNodes: %+v\n\tYou can destroy them with the command: `tiup cluster prune %s`", nodes, name) + } + } + + return nil +} + +// GetClusterTopology get the topology of the cluster. +func (m *Manager) GetClusterTopology(ctx context.Context, name string, opt operator.Options) ([]InstInfo, error) { + metadata, err := m.meta(name) + if err != nil && !errors.Is(perrs.Cause(err), meta.ErrValidate) && + !errors.Is(perrs.Cause(err), spec.ErrNoTiSparkMaster) { + return nil, err + } + + topo := metadata.GetTopology() + base := metadata.GetBaseMeta() + + err = SetSSHKeySet(ctx, m.specManager.Path(name, "ssh", "id_rsa"), m.specManager.Path(name, "ssh", "id_rsa.pub")) + if err != nil { + return nil, err + } + err = SetClusterSSH(ctx, topo, base.User, opt.SSHTimeout, opt.SSHType, topo.BaseTopo().GlobalOptions.SSHType) if err != nil { - return err + return nil, err } filterRoles := set.NewStringSet(opt.Roles...) @@ -88,7 +175,7 @@ func (m *Manager) Display(name string, opt operator.Options) error { masterList := topo.BaseTopo().MasterList tlsCfg, err := topo.TLSConfig(m.specManager.Path(name, spec.TLSCertKeyDir)) if err != nil { - return err + return nil, err } masterActive := make([]string, 0) @@ -108,17 +195,11 @@ func (m *Manager) Display(name string, opt operator.Options) error { var dashboardAddr string if t, ok := topo.(*spec.Specification); ok { - var err error - dashboardAddr, err = t.GetDashboardAddress(tlsCfg, masterActive...) - if err == nil && !set.NewStringSet("", "auto", "none").Exist(dashboardAddr) { - schema := "http" - if tlsCfg != nil { - schema = "https" - } - fmt.Printf("Dashboard URL: %s\n", cyan.Sprintf("%s://%s/dashboard", schema, dashboardAddr)) - } + dashboardAddr, _ = t.GetDashboardAddress(tlsCfg, masterActive...) } + clusterInstInfos := []InstInfo{} + topo.IterInstance(func(ins spec.Instance) { // apply role filter if len(filterRoles) > 0 && !filterRoles.Exist(ins.Role()) { @@ -164,50 +245,33 @@ func (m *Manager) Display(name string, opt operator.Options) error { } } } - clusterTable = append(clusterTable, []string{ - color.CyanString(ins.ID()), - ins.Role(), - ins.GetHost(), - utils.JoinInt(ins.UsedPorts(), "/"), - cliutil.OsArch(ins.OS(), ins.Arch()), - formatInstanceStatus(status), - dataDir, - deployDir, + clusterInstInfos = append(clusterInstInfos, InstInfo{ + ID: ins.ID(), + Role: ins.Role(), + Host: ins.GetHost(), + Ports: utils.JoinInt(ins.UsedPorts(), "/"), + OsArch: cliutil.OsArch(ins.OS(), ins.Arch()), + Status: status, + DataDir: dataDir, + DeployDir: deployDir, + ComponentName: ins.ComponentName(), + Port: ins.GetPort(), }) }) // Sort by role,host,ports - sort.Slice(clusterTable[1:], func(i, j int) bool { - lhs, rhs := clusterTable[i+1], clusterTable[j+1] - // column: 1 => role, 2 => host, 3 => ports - for _, col := range []int{1, 2} { - if lhs[col] != rhs[col] { - return lhs[col] < rhs[col] - } + sort.Slice(clusterInstInfos, func(i, j int) bool { + lhs, rhs := clusterInstInfos[i], clusterInstInfos[j] + if lhs.Role != rhs.Role { + return lhs.Role < rhs.Role } - return lhs[3] < rhs[3] - }) - - cliutil.PrintTable(clusterTable, true) - fmt.Printf("Total nodes: %d\n", len(clusterTable)-1) - - if t, ok := topo.(*spec.Specification); ok { - // Check if TiKV's label set correctly - pdClient := api.NewPDClient(masterActive, 10*time.Second, tlsCfg) - if lbs, err := pdClient.GetLocationLabels(); err != nil { - log.Debugf("get location labels from pd failed: %v", err) - } else if err := spec.CheckTiKVLabels(lbs, pdClient); err != nil { - color.Yellow("\nWARN: there is something wrong with TiKV labels, which may cause data losing:\n%v", err) - } - - // Check if there is some instance in tombstone state - nodes, _ := operator.DestroyTombstone(ctx, t, true /* returnNodesOnly */, opt, tlsCfg) - if len(nodes) != 0 { - color.Green("There are some nodes can be pruned: \n\tNodes: %+v\n\tYou can destroy them with the command: `tiup cluster prune %s`", nodes, name) + if lhs.Host != rhs.Host { + return lhs.Host < rhs.Host } - } + return lhs.Ports < rhs.Ports + }) - return nil + return clusterInstInfos, nil } func formatInstanceStatus(status string) string { From f89aeaa827e49dff58bb98dc07a00722f5812fe3 Mon Sep 17 00:00:00 2001 From: baurine <2008.hbl@gmail.com> Date: Thu, 18 Feb 2021 22:54:30 +0800 Subject: [PATCH 3/3] refine --- pkg/cluster/manager/display.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkg/cluster/manager/display.go b/pkg/cluster/manager/display.go index b6249a9b5e..27840fd576 100644 --- a/pkg/cluster/manager/display.go +++ b/pkg/cluster/manager/display.go @@ -52,8 +52,7 @@ type InstInfo struct { // Display cluster meta and topology. func (m *Manager) Display(name string, opt operator.Options) error { - ctx := ctxt.New(context.Background()) - clusterInstInfos, err := m.GetClusterTopology(ctx, name, opt) + clusterInstInfos, err := m.GetClusterTopology(name, opt) if err != nil { return err } @@ -130,6 +129,7 @@ func (m *Manager) Display(name string, opt operator.Options) error { cliutil.PrintTable(clusterTable, true) fmt.Printf("Total nodes: %d\n", len(clusterTable)-1) + ctx := ctxt.New(context.Background()) if t, ok := topo.(*spec.Specification); ok { // Check if TiKV's label set correctly pdClient := api.NewPDClient(masterActive, 10*time.Second, tlsCfg) @@ -150,7 +150,8 @@ func (m *Manager) Display(name string, opt operator.Options) error { } // GetClusterTopology get the topology of the cluster. -func (m *Manager) GetClusterTopology(ctx context.Context, name string, opt operator.Options) ([]InstInfo, error) { +func (m *Manager) GetClusterTopology(name string, opt operator.Options) ([]InstInfo, error) { + ctx := ctxt.New(context.Background()) metadata, err := m.meta(name) if err != nil && !errors.Is(perrs.Cause(err), meta.ErrValidate) && !errors.Is(perrs.Cause(err), spec.ErrNoTiSparkMaster) { @@ -245,6 +246,7 @@ func (m *Manager) GetClusterTopology(ctx context.Context, name string, opt opera } } } + clusterInstInfos = append(clusterInstInfos, InstInfo{ ID: ins.ID(), Role: ins.Role(),