Skip to content

Commit

Permalink
Refactoring with client-go
Browse files Browse the repository at this point in the history
  • Loading branch information
sunny0826 committed Nov 18, 2019
1 parent 0f05045 commit 13a41d8
Show file tree
Hide file tree
Showing 8 changed files with 259 additions and 221 deletions.
192 changes: 104 additions & 88 deletions cmd/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,54 +18,20 @@ package cmd
import (
"fmt"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"
"io/ioutil"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/tools/clientcmd"
"log"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
clientcmdlatest "k8s.io/client-go/tools/clientcmd/api/latest"
"os"
syaml "sigs.k8s.io/yaml"
"strings"
)

var file string
var name string
var cover bool

type (
Config struct {
ApiVersion string `yaml:"apiVersion"`
Kind string `yaml:"kind"`
Clusters []Clusters `yaml:"clusters"`
Contexts []Contexts `yaml:"contexts"`
CurrentContext string `yaml:"current-context"`
Users []Users `yaml:"users"`
}
Clusters struct {
Cluster Cluster `yaml:"cluster"`
Name string `yaml:"name"`
}
Cluster struct {
Server string `yaml:"server"`
CertificateAuthorityData string `yaml:"certificate-authority-data"`
}
Contexts struct {
Context Context `yaml:"context"`
Name string `yaml:"name"`
}
Context struct {
Cluster string `yaml:"cluster"`
User string `yaml:"user"`
NameSpace string `yaml:"namespace,omitempty"`
}
Users struct {
Name string `yaml:"name"`
User User `yaml:"user"`
}
User struct {
ClientCertificateData string `yaml:"client-certificate-data"`
ClientKeyData string `yaml:"client-key-data"`
}
)

// addCmd represents the add command
var addCmd = &cobra.Command{
Use: "add",
Expand All @@ -88,14 +54,15 @@ kubecm add -f example.yaml -c
os.Exit(1)
}
cover, _ = cmd.Flags().GetBool("cover")
oldYaml := Config{}
oldYaml.ReadYaml(cfgFile)
addYaml := Config{}
addYaml.ReadYaml(file)
err = oldYaml.MergeConfig(addYaml)
config, err := GetAddConfig(file)
if err != nil {
fmt.Println(err)
}
output := Merge2Master(config)
err = WriteConfig(output)
if err != nil {
fmt.Println(err.Error())
}
} else {
fmt.Printf("%s file does not exist", file)
os.Exit(1)
Expand All @@ -111,41 +78,112 @@ func init() {
addCmd.MarkFlagRequired("file")
}

func FileExists(path string) bool {
_, err := os.Stat(path) //os.Stat获取文件信息
func LoadClientConfig(kubeconfig string) (*clientcmdapi.Config, error) {
b, err := ioutil.ReadFile(kubeconfig)
if err != nil {
if os.IsExist(err) {
return true
}
return false
return nil, err
}
return true
config, err := clientcmd.Load(b)
if err != nil {
return nil, err
}
return config, nil
}

func (c *Config) ReadYaml(f string) {
buffer, err := ioutil.ReadFile(f)
func GetAddConfig(kubeconfig string) (*clientcmdapi.Config, error) {

config, err := LoadClientConfig(kubeconfig)
if err != nil {
log.Fatalf(err.Error())
return nil, err
}

if len(config.AuthInfos) != 1 {
fmt.Println("Only support add 1 context.")
os.Exit(-1)
}
err = yaml.Unmarshal(buffer, &c)

name := GetName()
err = NameCheck(name)
if err != nil {
log.Fatalf(err.Error())
fmt.Println(err)
os.Exit(-1)
}
suffix := HashSuf(config)
username := fmt.Sprintf("user-%v", suffix)
clustername := fmt.Sprintf("cluster-%v", suffix)

for key, obj := range config.AuthInfos {
config.AuthInfos[username] = obj
delete(config.AuthInfos, key)
break
}
for key, obj := range config.Clusters {
config.Clusters[clustername] = obj
delete(config.Clusters, key)
break
}
for key, obj := range config.Contexts {
obj.AuthInfo = username
obj.Cluster = clustername
config.Contexts[name] = obj
delete(config.Contexts, key)
break
}

return config, nil
}

func (c *Config) WriteYaml() {
buffer, err := yaml.Marshal(&c)
func Merge2Master(config *clientcmdapi.Config) []byte {
commandLineFile, _ := ioutil.TempFile("", "")
defer os.Remove(commandLineFile.Name())
configType := clientcmdapi.Config{
AuthInfos: config.AuthInfos,
Clusters: config.Clusters,
Contexts: config.Contexts,
}
_ = clientcmd.WriteToFile(configType, commandLineFile.Name())
loadingRules := &clientcmd.ClientConfigLoadingRules{
Precedence: []string{cfgFile, commandLineFile.Name()},
}

mergedConfig, err := loadingRules.Load()

json, err := runtime.Encode(clientcmdlatest.Codec, mergedConfig)
if err != nil {
fmt.Printf("Unexpected error: %v", err)
}
output, err := syaml.JSONToYAML(json)
if err != nil {
log.Fatalf(err.Error())
fmt.Printf("Unexpected error: %v", err)
}

return output
}

func WriteConfig(config []byte) error {
if cover {
err = ioutil.WriteFile(cfgFile, buffer, 0777)
err := ioutil.WriteFile(cfgFile, config, 0777)
if err != nil {
return err
}
} else {
err = ioutil.WriteFile("./config.yaml", buffer, 0777)
err := ioutil.WriteFile("./config.yaml", config, 0777)
if err != nil {
return err
}
}
return nil
}

func FileExists(path string) bool {
_, err := os.Stat(path) //os.Stat获取文件信息
if err != nil {
fmt.Println(err.Error())
if os.IsExist(err) {
return true
}
return false
}
return true
}

func GetName() string {
Expand All @@ -158,35 +196,13 @@ func GetName() string {
}
}

func (c *Config) MergeConfig(a Config) error {
name := GetName()
err := c.Check(name)
func NameCheck(name string) error {
c, err := LoadClientConfig(cfgFile)
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
suffix := HashSuffix(a)
for _, obj := range a.Clusters {
obj.Name = fmt.Sprintf("cluster-%v", suffix)
c.Clusters = append(c.Clusters, obj)
}
for _, obj := range a.Contexts {
obj.Name = fmt.Sprintf("%s", name)
obj.Context.Cluster = fmt.Sprintf("cluster-%v", suffix)
obj.Context.User = fmt.Sprintf("user-%v", suffix)
c.Contexts = append(c.Contexts, obj)
}
for _, obj := range a.Users {
obj.Name = fmt.Sprintf("user-%v", suffix)
c.Users = append(c.Users, obj)
return err
}
c.WriteYaml()
return nil
}

func (c *Config) Check(name string) error {
for _, old := range c.Contexts {
if old.Name == name {
for key, _ := range c.Contexts {
if key == name {
return fmt.Errorf("The name: %s already exists, please replace it.", name)
}
}
Expand Down
42 changes: 19 additions & 23 deletions cmd/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package cmd
import (
"fmt"
"github.com/spf13/cobra"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"os"
)

Expand All @@ -32,12 +33,15 @@ var deleteCmd = &cobra.Command{
`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 0 {
kubeYaml := Config{}
kubeYaml.ReadYaml(cfgFile)
err := kubeYaml.DeleteContext(args)
config, err := LoadClientConfig(cfgFile)
if err != nil {
fmt.Println(err)
os.Exit(1)
os.Exit(-1)
}
err = deleteContext(args, config)
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
} else {
fmt.Println("Please enter the context you want to delete.")
Expand All @@ -50,28 +54,20 @@ func init() {
deleteCmd.SetArgs([]string{""})
}

func (c *Config) DeleteContext(ctxs []string) error {
for i, ct := range c.Contexts {
func deleteContext(ctxs []string, config *clientcmdapi.Config) error {
for key, _ := range config.Contexts {
for _, ctx := range ctxs {
if ct.Name == ctx {
fmt.Println(fmt.Sprintf("delete: %s", ctx))
c.Contexts = append(c.Contexts[:i], c.Contexts[i+1:]...)
user := ct.Context.User
cluster := ct.Context.Cluster
for j, us := range c.Users {
if us.Name == user {
c.Users = append(c.Users[:j], c.Users[j+1:]...)
}
}
for k, clu := range c.Clusters {
if clu.Name == cluster {
c.Clusters = append(c.Clusters[:k], c.Clusters[k+1:]...)
}
}
if ctx == key {
delete(config.Contexts, key)
break
}
}
}
cover = true
c.WriteYaml()
err := ModifyKubeConfig(config)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Printf("Context delete succeeded!\nDelete: %v \n", ctxs)
return nil
}
48 changes: 20 additions & 28 deletions cmd/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ var getCmd = &cobra.Command{
}
}
err := ClusterStatus()
if err!=nil {
if err != nil {
fmt.Printf("Cluster check failure!\n%v", err)
}
},
Expand All @@ -60,51 +60,43 @@ func init() {
getCmd.SetArgs([]string{""})
}

func GetContexts() ([]Contexts, string) {
c := Config{}
c.ReadYaml(cfgFile)
return c.Contexts, c.CurrentContext
}

func Formatable(args []string) error {
contexts, curr := GetContexts()
config, err := LoadClientConfig(cfgFile)
if err != nil {
return err
}
var table [][]string
var i int
if args == nil {
for i = 0; i < len(contexts); i++ {
for key, obj := range config.Contexts {
var tmp []string
if curr == contexts[i].Name {
if config.CurrentContext == key {
tmp = append(tmp, "*")
} else {
tmp = append(tmp, "")
}
tmp = append(tmp, contexts[i].Name)
tmp = append(tmp, contexts[i].Context.Cluster)
tmp = append(tmp, contexts[i].Context.User)
tmp = append(tmp, key)
tmp = append(tmp, obj.Cluster)
tmp = append(tmp, obj.AuthInfo)
tmp = append(tmp, obj.Namespace)
table = append(table, tmp)
}
} else {
for i = 0; i < len(contexts); i++ {
for key, obj := range config.Contexts {
var tmp []string
for _, name := range args {
if name == contexts[i].Name {
if curr == contexts[i].Name {
tmp = append(tmp, "*")
} else {
tmp = append(tmp, "")
}
tmp = append(tmp, contexts[i].Name)
tmp = append(tmp, contexts[i].Context.Cluster)
tmp = append(tmp, contexts[i].Context.User)
table = append(table, tmp)
}
if config.CurrentContext == key {
tmp = append(tmp, "*")
tmp = append(tmp, key)
tmp = append(tmp, obj.Cluster)
tmp = append(tmp, obj.AuthInfo)
tmp = append(tmp, obj.Namespace)
table = append(table, tmp)
}
}
}

if table != nil {
tabulate := gotabulate.Create(table)
tabulate.SetHeaders([]string{"CURRENT", "NAME", "CLUSTER", "USER"})
tabulate.SetHeaders([]string{"CURRENT", "NAME", "CLUSTER", "USER", "Namespace"})
// Turn On String Wrapping
tabulate.SetWrapStrings(true)
// Render the table
Expand Down
Loading

0 comments on commit 13a41d8

Please sign in to comment.