Skip to content

Commit

Permalink
feat(autok3s): add support for describe cluster command
Browse files Browse the repository at this point in the history
Signed-off-by: JacieChao <kathyyy@163.com>
  • Loading branch information
JacieChao authored and rancher-sy-bot committed Dec 24, 2020
1 parent 183cee5 commit a1b7c82
Show file tree
Hide file tree
Showing 12 changed files with 547 additions and 121 deletions.
5 changes: 5 additions & 0 deletions cmd/cmd.go
Expand Up @@ -7,6 +7,11 @@ import (
"github.com/cnrancher/autok3s/pkg/common"
"github.com/cnrancher/autok3s/pkg/utils"

// import custom provider
_ "github.com/cnrancher/autok3s/pkg/providers/alibaba"
_ "github.com/cnrancher/autok3s/pkg/providers/native"
_ "github.com/cnrancher/autok3s/pkg/providers/tencent"

"github.com/morikuni/aec"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
Expand Down
49 changes: 49 additions & 0 deletions cmd/common/common.go
Expand Up @@ -7,8 +7,16 @@ import (

"github.com/cnrancher/autok3s/pkg/common"
"github.com/cnrancher/autok3s/pkg/providers"
"github.com/cnrancher/autok3s/pkg/providers/alibaba"
"github.com/cnrancher/autok3s/pkg/providers/native"
"github.com/cnrancher/autok3s/pkg/providers/tencent"
"github.com/cnrancher/autok3s/pkg/types"
typesAli "github.com/cnrancher/autok3s/pkg/types/alibaba"
typesNative "github.com/cnrancher/autok3s/pkg/types/native"
typesTencent "github.com/cnrancher/autok3s/pkg/types/tencent"
"github.com/cnrancher/autok3s/pkg/utils"

"github.com/ghodss/yaml"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
Expand Down Expand Up @@ -104,3 +112,44 @@ func MakeSureCredentialFlag(flags *pflag.FlagSet, p providers.Provider) error {

return nil
}

func GetProviderByState(c types.Cluster) (providers.Provider, error) {
b, err := yaml.Marshal(c.Options)
if err != nil {
return nil, err
}
switch c.Provider {
case "alibaba":
option := &typesAli.Options{}
if err := yaml.Unmarshal(b, option); err != nil {
return nil, err
}
return &alibaba.Alibaba{
Metadata: c.Metadata,
Options: *option,
Status: c.Status,
}, nil
case "tencent":
option := &typesTencent.Options{}
if err := yaml.Unmarshal(b, option); err != nil {
return nil, err
}
return &tencent.Tencent{
Metadata: c.Metadata,
Options: *option,
Status: c.Status,
}, nil
case "native":
option := &typesNative.Options{}
if err := yaml.Unmarshal(b, option); err != nil {
return nil, err
}
return &native.Native{
Metadata: c.Metadata,
Options: *option,
Status: c.Status,
}, nil
default:
return nil, fmt.Errorf("invalid provider name %s", c.Provider)
}
}
117 changes: 117 additions & 0 deletions cmd/describe.go
@@ -0,0 +1,117 @@
package cmd

import (
"fmt"
"os"
"text/tabwriter"

c "github.com/cnrancher/autok3s/cmd/common"
"github.com/cnrancher/autok3s/pkg/cluster"
"github.com/cnrancher/autok3s/pkg/common"
"github.com/cnrancher/autok3s/pkg/utils"

"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

var (
describeCmd = &cobra.Command{
Use: "describe",
Short: "Show details of a specific resource",
Example: ` autok3s describe cluster <cluster name>`,
}
)

func DescribeCommand() *cobra.Command {
describeCmd.PreRunE = func(cmd *cobra.Command, args []string) error {
if len(args) == 0 || len(args) < 2 {
logrus.Fatalln("you must specify the type of resource to describe, e.g. autok3s describe cluster <cluster name>")
}
return nil
}
describeCmd.Run = func(cmd *cobra.Command, args []string) {
describeCluster(args)
}
return describeCmd
}

func describeCluster(args []string) {
if len(args) < 2 {
logrus.Fatalln("you must specify the type of resource to describe, e.g. autok3s describe cluster <cluster name>")
}
resource := args[0]
if resource != "cluster" {
logrus.Fatalf("autok3s doesn't support resource type %s", resource)
}
v := common.CfgPath
if v == "" {
logrus.Fatalln("state path is empty")
}
// get all clusters from state
clusters, err := utils.ReadYaml(v, common.StateFile)
if err != nil {
logrus.Fatalf("read state file error, msg: %v\n", err)
}

result, err := cluster.ConvertToClusters(clusters)
if err != nil {
logrus.Fatalf("failed to unmarshal state file, msg: %v\n", err)
}

resourceNames := args[1:]
allErr := []string{}
kubeCfg := fmt.Sprintf("%s/%s", common.CfgPath, common.KubeCfgFile)
out := new(tabwriter.Writer)
out.Init(os.Stdout, 0, 8, 0, '\t', 0)

for _, name := range resourceNames {
notExist := true
for _, r := range result {
if r.Name == name {
notExist = false
p, err := c.GetProviderByState(r)
if err != nil {
logrus.Errorf("failed to convert cluster options for cluster %s", r.Name)
continue
}
isExist, _, err := p.IsClusterExist()
if err != nil {
logrus.Errorf("failed to check cluster %s exist, got error: %v ", r.Name, err)
continue
}
if !isExist {
allErr = append(allErr, fmt.Sprintf("cluster %s is not exist", name))
continue
}
info := p.GetCluster(kubeCfg)
fmt.Fprintf(out, "Name: %s\n", info.Name)
fmt.Fprintf(out, "Provider: %s\n", info.Provider)
fmt.Fprintf(out, "Region: %s\n", info.Region)
fmt.Fprintf(out, "Zone: %s\n", info.Zone)
fmt.Fprintf(out, "Master: %s\n", info.Master)
fmt.Fprintf(out, "Worker: %s\n", info.Worker)
fmt.Fprintf(out, "Status: %s\n", info.Status)
fmt.Fprintf(out, "Version: %s\n", info.Version)
fmt.Fprintf(out, "Nodes:%s\n", "")
for _, node := range info.Nodes {
fmt.Fprintf(out, " - internal-ip: %s\n", node.InternalIP)
fmt.Fprintf(out, " external-ip: %s\n", node.ExternalIP)
fmt.Fprintf(out, " instance-status: %s\n", node.InstanceStatus)
fmt.Fprintf(out, " instance-id: %s\n", node.InstanceID)
fmt.Fprintf(out, " roles: %s\n", node.Roles)
fmt.Fprintf(out, " status: %s\n", node.Status)
fmt.Fprintf(out, " hostname: %s\n", node.HostName)
fmt.Fprintf(out, " container-runtime: %s\n", node.ContainerRuntimeVersion)
fmt.Fprintf(out, " version: %s\n", node.Version)
}
}
}
if notExist {
allErr = append(allErr, fmt.Sprintf("cluster %s is not exist", name))
}
}
for _, e := range allErr {
fmt.Fprintf(out, "%s\n", e)
}
out.Flush()
}
147 changes: 34 additions & 113 deletions cmd/list.go
@@ -1,22 +1,16 @@
package cmd

import (
"fmt"
"os"
"strings"

c "github.com/cnrancher/autok3s/cmd/common"
"github.com/cnrancher/autok3s/pkg/cluster"
"github.com/cnrancher/autok3s/pkg/common"
"github.com/cnrancher/autok3s/pkg/providers"
"github.com/cnrancher/autok3s/pkg/providers/alibaba"
"github.com/cnrancher/autok3s/pkg/providers/native"
"github.com/cnrancher/autok3s/pkg/providers/tencent"
"github.com/cnrancher/autok3s/pkg/types"
typesAli "github.com/cnrancher/autok3s/pkg/types/alibaba"
typesNative "github.com/cnrancher/autok3s/pkg/types/native"
typesTencent "github.com/cnrancher/autok3s/pkg/types/tencent"
"github.com/cnrancher/autok3s/pkg/utils"

"github.com/ghodss/yaml"
"github.com/olekukonko/tablewriter"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
Expand All @@ -43,13 +37,13 @@ func listCluster() {
table.SetHeaderLine(false)
table.SetColumnSeparator("")
table.SetAlignment(tablewriter.ALIGN_LEFT)
table.SetHeader([]string{"Name", "Region", "Provider", "Status", "Masters", "Workers"})
table.SetHeader([]string{"Name", "Region", "Provider", "Status", "Masters", "Workers", "Version"})

v := common.CfgPath
if v == "" {
logrus.Fatalln("state path is empty")
}

// get all clusters from state
clusters, err := utils.ReadYaml(v, common.StateFile)
if err != nil {
logrus.Fatalf("read state file error, msg: %v\n", err)
Expand All @@ -61,127 +55,54 @@ func listCluster() {
}

var (
p providers.Provider
filters []*types.Cluster
removeCtx []string
p providers.Provider
filters []*types.ClusterInfo
clusterList []*types.Cluster
)

// filter useless clusters & contexts.
kubeCfg := fmt.Sprintf("%s/%s", common.CfgPath, common.KubeCfgFile)
for _, r := range result {
switch r.Provider {
case "alibaba":
region := r.Name[strings.LastIndex(r.Name, ".")+1:]

b, err := yaml.Marshal(r.Options)
if err != nil {
logrus.Debugf("failed to convert cluster %s options\n", r.Name)
removeCtx = append(removeCtx, r.Name)
continue
}

option := &typesAli.Options{}
if err := yaml.Unmarshal(b, option); err != nil {
removeCtx = append(removeCtx, r.Name)
logrus.Debugf("failed to convert cluster %s options\n", r.Name)
continue
}
option.Region = region

p = &alibaba.Alibaba{
Metadata: r.Metadata,
Options: *option,
}
case "tencent":
region := r.Name[strings.LastIndex(r.Name, ".")+1:]

b, err := yaml.Marshal(r.Options)
if err != nil {
logrus.Debugf("failed to convert cluster %s options\n", r.Name)
removeCtx = append(removeCtx, r.Name)
continue
}

option := &typesTencent.Options{}
if err := yaml.Unmarshal(b, option); err != nil {
removeCtx = append(removeCtx, r.Name)
logrus.Debugf("failed to convert cluster %s options\n", r.Name)
continue
}
option.Region = region

p = &tencent.Tencent{
Metadata: r.Metadata,
Options: *option,
}
case "native":
b, err := yaml.Marshal(r.Options)
if err != nil {
logrus.Debugf("failed to convert cluster %s options\n", r.Name)
removeCtx = append(removeCtx, r.Name)
continue
}
option := &typesNative.Options{}
if err := yaml.Unmarshal(b, option); err != nil {
removeCtx = append(removeCtx, r.Name)
logrus.Debugf("failed to convert cluster %s options\n", r.Name)
continue
}
p = &native.Native{
Metadata: r.Metadata,
Options: *option,
Status: r.Status,
}
}
if p == nil {
p, err = c.GetProviderByState(r)
if err != nil {
logrus.Errorf("failed to convert cluster options for cluster %s", r.Name)
continue
}
isExist, ids, err := p.IsClusterExist()
isExist, _, err := p.IsClusterExist()
if err != nil {
logrus.Fatalln(err)
logrus.Errorf("failed to check cluster %s exist, got error: %v ", r.Name, err)
continue
}

if isExist && len(ids) > 0 {
filters = append(filters, &types.Cluster{
Metadata: r.Metadata,
Options: r.Options,
Status: r.Status,
})
} else {
removeCtx = append(removeCtx, r.Name)
if !isExist {
logrus.Warnf("cluster %s is not exist, will remove from config", r.Name)
// remove kube config if cluster not exist
if err := cluster.OverwriteCfg(r.Name); err != nil {
logrus.Errorf("failed to remove unexist cluster %s from kube config", r.Name)
}
continue
}
}

// remove useless clusters from .state.
if err := cluster.FilterState(filters); err != nil {
logrus.Fatalf("failed to remove useless clusters\n")
filters = append(filters, p.GetCluster(kubeCfg))
clusterList = append(clusterList, &types.Cluster{
Metadata: r.Metadata,
Options: r.Options,
Status: r.Status,
})
}

// remove useless contexts from kubeCfg.
for _, r := range removeCtx {
if err := cluster.OverwriteCfg(r); err != nil {
logrus.Fatalf("failed to remove useless contexts\n")
}
// remove useless clusters from .state.
if err := cluster.FilterState(clusterList); err != nil {
logrus.Errorf("failed to remove useless clusters\n")
}

var (
name string
region string
)
for _, f := range filters {
if f.Provider != "native" && strings.Contains(f.Name, ".") {
name = f.Name[:strings.LastIndex(f.Name, ".")]
region = f.Name[strings.LastIndex(f.Name, ".")+1:]
} else {
name = f.Name
region = "-"
}
table.Append([]string{
name,
region,
f.Name,
f.Region,
f.Provider,
strings.ToLower(f.Status.Status),
f.Status,
f.Master,
f.Worker,
f.Version,
})
}

Expand Down
1 change: 1 addition & 0 deletions go.mod
Expand Up @@ -56,6 +56,7 @@ require (
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
k8s.io/api v0.19.0
k8s.io/apimachinery v0.19.0
k8s.io/cli-runtime v0.0.0
k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible
Expand Down

0 comments on commit a1b7c82

Please sign in to comment.