Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

some new future #16

Merged
merged 5 commits into from
Dec 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ func formatNewConfig(file string) (*clientcmdapi.Config, string, error) {
return nil, "", errors.New("Only support add 1 context. You can use `merge` cmd")
}
name, err := formatAndCheckName(file)
config = CheckValidContext(config)
if err != nil {
return nil, "", err
}
Expand Down
75 changes: 75 additions & 0 deletions cmd/clear.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package cmd

import (
"fmt"
"os"
"reflect"

"github.com/spf13/cobra"
"k8s.io/client-go/tools/clientcmd"
)

// ClearCommand clean command struct
type ClearCommand struct {
BaseCommand
}

// Init AliasCommand
func (cl *ClearCommand) Init() {
cl.command = &cobra.Command{
Use: "clear",
Short: "Clear lapsed context, cluster and user",
Long: "Clear lapsed context, cluster and user",
RunE: func(cmd *cobra.Command, args []string) error {
return cl.runClear(cmd, args)
},
Example: clearExample(),
}
cl.command.DisableFlagsInUseLine = true
}

func (cl *ClearCommand) runClear(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
if ok, err := clearContext(cfgFile); ok {
printString(os.Stdout, fmt.Sprintf("There is nothing to clean in 「%s」\n", cfgFile))
return nil
} else if err != nil {
return err
}
} else {
for _, file := range args {
if ok, err := clearContext(file); ok {
printString(os.Stdout, fmt.Sprintf("There is nothing to clean in 「%s」\n", file))
} else if err != nil {
return err
}
}
}
return nil
}

func clearContext(file string) (bool, error) {
config, err := clientcmd.LoadFromFile(file)
if err != nil {
return false, err
}
outConfig := config.DeepCopy()
outConfig = CheckValidContext(outConfig)
if reflect.DeepEqual(config, outConfig) {
return true, nil
}
err = UpdateConfigFile(file, outConfig)
if err != nil {
return false, err
}
return false, nil
}

func clearExample() string {
return fmt.Sprintf(`
# Clear lapsed context, cluster and user (default is %s)
kubecm clear
# Customised clear lapsed files
kubecm clear config.yaml test.yaml
`, cfgFile)
}
44 changes: 44 additions & 0 deletions cmd/clear_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package cmd

import (
"io/ioutil"
"os"
"testing"

"k8s.io/client-go/tools/clientcmd"
)

func Test_clearContext(t *testing.T) {
trueFile, _ := ioutil.TempFile("", "")
falseFile, _ := ioutil.TempFile("", "")
defer os.Remove(trueFile.Name())
defer os.Remove(falseFile.Name())
_ = clientcmd.WriteToFile(appendMergeConfig, trueFile.Name())
_ = clientcmd.WriteToFile(wrongRootConfig, falseFile.Name())

type args struct {
file string
}
tests := []struct {
name string
args args
want bool
wantErr bool
}{
// TODO: Add test cases.
{"true", args{file: trueFile.Name()}, true, false},
{"false", args{file: falseFile.Name()}, false, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := clearContext(tt.args.file)
if (err != nil) != tt.wantErr {
t.Errorf("clearContext() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("clearContext() got = %v, want %v", got, tt.want)
}
})
}
}
1 change: 1 addition & 0 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func NewBaseCommand() *BaseCommand {
&NamespaceCommand{}, // namespace command
&ListCommand{}, // list command
&AliasCommand{}, // alias command
&ClearCommand{}, // clear command
)

return baseCmd
Expand Down
45 changes: 41 additions & 4 deletions cmd/list.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package cmd

import (
"log"
"fmt"
"strings"

clientcmdapi "k8s.io/client-go/tools/clientcmd/api"

"github.com/spf13/cobra"
"k8s.io/client-go/tools/clientcmd"
)

// ListCommand list cmd struct
Expand All @@ -27,23 +31,56 @@ func (lc *ListCommand) Init() {
}

func (lc *ListCommand) runList(command *cobra.Command, args []string) error {
err := Formatable()
config, err := clientcmd.LoadFromFile(cfgFile)
if err != nil {
return err
}
err = ClusterStatus()
config = CheckValidContext(config)
outConfig, err := filterArgs(args, config)
if err != nil {
log.Fatalf("Cluster check failure!\n%v", err)
return err
}
err = PrintTable(outConfig)
if err != nil {
return err
}
err = ClusterStatus()
if err != nil {
return fmt.Errorf("Cluster check failure!\n%v", err)
}
return nil
}

func filterArgs(args []string, config *clientcmdapi.Config) (*clientcmdapi.Config, error) {
if len(args) == 0 {
return config, nil
}
contextList := make(map[string]string)
for key := range config.Contexts {
for _, search := range args {
if strings.Contains(key, search) {
contextList[key] = search
}
}
}
for key := range config.Contexts {
if _, ok := contextList[key]; !ok {
delete(config.Contexts, key)
}
}
if len(config.Contexts) == 0 {
return nil, fmt.Errorf("there is no matching context for %v", args)
}
return config, nil
}

func listExample() string {
return `
# List all the contexts in your kubeconfig file
kubecm ls
# Aliases
kubecm l
# Filter out keywords(Multi-keyword support)
kubecm ls kind k3s
`
}
72 changes: 72 additions & 0 deletions cmd/list_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package cmd

import (
"reflect"
"testing"

clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
)

var (
noRootMergeConfig = clientcmdapi.Config{
AuthInfos: map[string]*clientcmdapi.AuthInfo{
"black-user": {Token: "black-token"},
"red-user": {Token: "red-token"},
},
Clusters: map[string]*clientcmdapi.Cluster{
"pig-cluster": {Server: "http://pig.org:8080"},
"cow-cluster": {Server: "http://cow.org:8080"},
},
Contexts: map[string]*clientcmdapi.Context{
"federal-context": {AuthInfo: "red-user", Cluster: "cow-cluster", Namespace: "hammer-ns"},
},
}
noFederalMergeConfig = clientcmdapi.Config{
AuthInfos: map[string]*clientcmdapi.AuthInfo{
"black-user": {Token: "black-token"},
"red-user": {Token: "red-token"},
},
Clusters: map[string]*clientcmdapi.Cluster{
"pig-cluster": {Server: "http://pig.org:8080"},
"cow-cluster": {Server: "http://cow.org:8080"},
},
Contexts: map[string]*clientcmdapi.Context{
"root-context": {AuthInfo: "black-user", Cluster: "pig-cluster", Namespace: "saw-ns"},
},
}
)

func NewAllConfig() *clientcmdapi.Config {
return appendMergeConfig.DeepCopy()
}

func Test_filterArgs(t *testing.T) {

type args struct {
args []string
config *clientcmdapi.Config
}
tests := []struct {
name string
args args
want *clientcmdapi.Config
wantErr bool
}{
// TODO: Add test cases.
{"noFederal", args{[]string{"root"}, NewAllConfig()}, &noFederalMergeConfig, false},
{"noRoot", args{[]string{"federal"}, NewAllConfig()}, &noRootMergeConfig, false},
{"all-context", args{[]string{"root", "federal"}, NewAllConfig()}, &appendMergeConfig, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := filterArgs(tt.args.args, tt.args.config)
if (err != nil) != tt.wantErr {
t.Errorf("filterArgs() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("filterArgs() got = %v, want %v", got, tt.want)
}
})
}
}
53 changes: 49 additions & 4 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@ limitations under the License.
*/

import (
"bytes"
"flag"
"fmt"
"os"
"os/exec"
"os/user"
"path/filepath"
"runtime"
"strings"

"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -73,10 +79,49 @@ func (cli *Cli) Run() error {
}
return cli.rootCmd.Execute()
}

func homeDir() string {
if h := os.Getenv("HOME"); h != "" {
return h
u, err := user.Current()
if nil == err {
return u.HomeDir
}
// cross compile support
if "windows" == runtime.GOOS {
return homeWindows()
}
// Unix-like system, so just assume Unix
return homeUnix()
}

func homeUnix() string {
if home := os.Getenv("HOME"); home != "" {
return home
}
var stdout bytes.Buffer
cmd := exec.Command("sh", "-c", "eval echo ~$USER")
cmd.Stdout = &stdout
if err := cmd.Run(); err != nil {
return ""
}
result := strings.TrimSpace(stdout.String())
if result == "" {
fmt.Println("blank output when reading home directory")
os.Exit(0)
}
return os.Getenv("USERPROFILE") // windows

return result
}

func homeWindows() string {
drive := os.Getenv("HOMEDRIVE")
path := os.Getenv("HOMEPATH")
home := drive + path
if drive == "" || path == "" {
home = os.Getenv("USERPROFILE")
}
if home == "" {
fmt.Println("HOMEDRIVE, HOMEPATH, and USERPROFILE are blank")
os.Exit(0)
}

return home
}
4 changes: 0 additions & 4 deletions cmd/switch.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,6 @@ func (sc *SwitchCommand) runSwitch(command *cobra.Command, args []string) error
return err
}
sc.command.Printf("Switched to context 「%s」\n", config.CurrentContext)
//err = Formatable()
//if err != nil {
// return err
//}
return nil
}

Expand Down
Loading