commit 4ad61b6640f7e8df08e445ff7f13c89da744746e Author: Joakim Olsson Date: Wed Feb 27 16:05:41 2019 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bdc2045 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +release +.idea diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..b513e19 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,50 @@ +variables: + GOCACHE: "${CI_PROJECT_DIR}/_go/cache" + +# A hack to make Golang-in-Gitlab happy +before_script: + - rm -rf /go/pkg + - ln -s ${CI_PROJECT_DIR}/_go/pkg /go/pkg + - ln -s ${CI_PROJECT_DIR}/_go/bin /go/bin + - cd ${PACKAGE_PATH} + +cache: + key: "$CI_COMMIT_REF_NAME" + paths: + - _go + untracked: true + +stages: + - deps + - test + - build + +deps: + stage: deps + image: golang:1.12 + script: + - go get + +test: + stage: test + dependencies: + - deps + image: golang:1.12 + script: + - go fmt $(go list ./...) + - go vet $(go list ./...) + - CGO_ENABLED=1 go test -race $(go list ./...) -coverprofile .testCoverage.txt + +build: + stage: build + dependencies: + - deps + image: golang:1.12 + script: + - go get github.com/ahmetb/govvv + - GOOS=linux GOARCH=amd64 CGO_ENABLED=0 govvv build -o release/linux/kubesplit -ldflags '-w -s' + - GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 govvv build -o release/darwin/kubesplit -ldflags '-w -s' + - GOOS=windows GOARCH=amd64 CGO_ENABLED=0 govvv build -o release/windows/kubesplit -ldflags '-w -s' + artifacts: + paths: + - release/ diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..4cf9b1b --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module gitlab.com/unboundsoftware/kubesplit + +go 1.12 + +require gopkg.in/yaml.v2 v2.2.2 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..bd555a3 --- /dev/null +++ b/go.sum @@ -0,0 +1,3 @@ +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/kubesplit.go b/kubesplit.go new file mode 100644 index 0000000..77e38f2 --- /dev/null +++ b/kubesplit.go @@ -0,0 +1,148 @@ +package main + +import ( + "fmt" + "log" + "os" + "runtime" + "strings" + + "io/ioutil" + + "gopkg.in/yaml.v2" +) + +type Clusters struct { + Cluster struct { + InsecureSkipTLSVerify bool `yaml:"insecure-skip-tls-verify"` + CertificateAuthorityData string `yaml:"certificate-authority-data"` + Server string `yaml:"server"` + } `yaml:"cluster"` + Name string `yaml:"name"` +} + +type Users struct { + Name string `yaml:"name"` + User struct { + ClientCertificateData string `yaml:"client-certificate-data"` + ClientKeyData string `yaml:"client-key-data"` + Username string `yaml:"username"` + Password string `yaml:"password"` + } `yaml:"user"` +} + +type Kubecfg struct { + APIVersion string `yaml:"apiVersion"` + Clusters []Clusters `yaml:"clusters"` + Contexts []struct { + Context struct { + Cluster string `yaml:"cluster"` + User string `yaml:"user"` + } `yaml:"context"` + Name string `yaml:"name"` + } `yaml:"contexts"` + CurrentContext string `yaml:"current-context"` + Kind string `yaml:"kind"` + Preferences struct { + } `yaml:"preferences"` + Users []Users `yaml:"users"` +} + +func main() { + cfg := Kubecfg{} + + home := userHomeDir() + data, err := ioutil.ReadFile(strings.Join([]string{home, ".kube", "config"}, "/")) + + if err != nil { + log.Fatalf("error: %v", err) + } + + err2 := yaml.Unmarshal(data, &cfg) + if err2 != nil { + log.Fatalf("error: %v", err2) + } + + if len(os.Args) == 1 { + fmt.Println("Contexts:") + for i := 0; i < len(cfg.Contexts); i++ { + name := cfg.Contexts[i].Name + fmt.Printf("%v\n", name) + } + } else { + var ix = -1 + for i, n := range cfg.Contexts { + if n.Name == os.Args[1] { + ix = i + break + } + } + + if ix == -1 { + fmt.Printf("Context named '%v' not found in kube-config\n\n", os.Args[1]) + } else { + cluster := cfg.Contexts[ix].Context.Cluster + user := cfg.Contexts[ix].Context.User + + x := Kubecfg{} + x.APIVersion = "v1" + x.Kind = "Config" + x.Contexts = append(x.Contexts, cfg.Contexts[ix]) + if c, ok := findCluster(cluster, cfg); ok { + x.Clusters = append(x.Clusters, c) + } + if u, ok := findUsers(user, cfg); ok { + x.Users = u + } + + d, err := yaml.Marshal(&x) + if err != nil { + log.Fatalf("error: %v", err) + } + fmt.Printf("%s\n", string(d)) + } + } +} + +func findCluster(cluster string, cfg Kubecfg) (Clusters, bool) { + var ix = -1 + for i, n := range cfg.Clusters { + if n.Name == cluster { + ix = i + break + } + } + if ix != -1 { + return cfg.Clusters[ix], true + } + return Clusters{}, false +} + +func findUsers(user string, cfg Kubecfg) ([]Users, bool) { + var users []Users + for i, n := range cfg.Users { + if strings.HasPrefix(n.Name, user) { + users = append(users, cfg.Users[i]) + } + } + if len(users) != 0 { + return users, true + } + return users, false +} + +func userHomeDir() string { + if runtime.GOOS == "windows" { + home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") + if home == "" { + home = os.Getenv("USERPROFILE") + } + return home + } else if runtime.GOOS == "linux" { + home := os.Getenv("XDG_CONFIG_HOME") + if home != "" { + return home + } + } + return os.Getenv("HOME") +} \ No newline at end of file