mirror of
https://github.com/ahmetb/kubectx.git
synced 2025-06-23 14:08:04 +00:00
Implement facilities to parse kubeconfig file
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
This commit is contained in:
parent
7c2f8ffa75
commit
da08491f0b
@ -1,9 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func kubeconfigPath() (string, error) {
|
||||
@ -27,3 +29,15 @@ func kubeconfigPath() (string, error) {
|
||||
}
|
||||
return filepath.Join(home, ".kube", "config"), nil
|
||||
}
|
||||
|
||||
func parseKubeconfig(path string) (kubeconfig, error) {
|
||||
// TODO refactor to accept io.Reader instead of file
|
||||
var v kubeconfig
|
||||
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return v, errors.Wrap(err, "file open error")
|
||||
}
|
||||
err = yaml.NewDecoder(f).Decode(&v)
|
||||
return v, errors.Wrap(err, "yaml parse error")
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
)
|
||||
|
||||
func Test_kubeconfigPath_homePath(t *testing.T) {
|
||||
@ -72,5 +75,79 @@ func Test_kubeconfigPath_envOvverideDoesNotSupportPathSeparator(t *testing.T) {
|
||||
|
||||
_, err := kubeconfigPath()
|
||||
if err == nil { t.Fatal("expected error")}
|
||||
|
||||
}
|
||||
|
||||
|
||||
func Test_parseKubeconfig_openError(t *testing.T) {
|
||||
_, err := parseKubeconfig("/non/existing/path")
|
||||
if err == nil {
|
||||
t.Fatalf("expected error")
|
||||
}
|
||||
msg := err.Error()
|
||||
expected := `file open error`
|
||||
if !strings.Contains(msg, expected) {
|
||||
t.Fatalf("expected=%q, got=%q", expected, msg)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_parseKubeconfig_yamlFormatError(t *testing.T) {
|
||||
file, cleanup := testfile(t, `a: [1,2 `) // supposed to be invalid yaml
|
||||
defer cleanup()
|
||||
|
||||
_, err := parseKubeconfig(file)
|
||||
if err == nil {
|
||||
t.Fatal("expected error")
|
||||
}
|
||||
expected := "yaml parse error"
|
||||
if got := err.Error(); !strings.Contains(got, expected) {
|
||||
t.Fatalf("expected=%q; got=%q", expected, got)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_parseKubeconfig(t *testing.T) {
|
||||
file, cleanup := testfile(t,
|
||||
`
|
||||
apiVersion: v1
|
||||
current-context: foo
|
||||
contexts:
|
||||
- name: c3
|
||||
- name: c2
|
||||
- name: c1`)
|
||||
defer cleanup()
|
||||
|
||||
got, err := parseKubeconfig(file)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
expected := kubeconfig{
|
||||
APIVersion: "v1",
|
||||
CurrentContext: "foo",
|
||||
Contexts: []context{
|
||||
{Name:"c3"},{Name:"c2"},{Name:"c1"},
|
||||
},
|
||||
}
|
||||
|
||||
diff := cmp.Diff(expected, got)
|
||||
if diff != "" {
|
||||
t.Fatalf("got wrong object:\n%s", diff)
|
||||
}
|
||||
}
|
||||
|
||||
func testfile(t *testing.T, contents string) (path string, cleanup func()) {
|
||||
t.Helper()
|
||||
|
||||
f, err := ioutil.TempFile(os.TempDir(), "test-file")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create test file: %v", err)
|
||||
}
|
||||
path = f.Name()
|
||||
if _, err := f.Write([]byte(contents)); err != nil {
|
||||
t.Fatalf("failed to write to test file: %v", err)
|
||||
}
|
||||
|
||||
return path, func() {
|
||||
f.Close()
|
||||
os.Remove(path)
|
||||
}
|
||||
}
|
||||
|
@ -1 +1,36 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type context struct {
|
||||
Name string `yaml:"name"`
|
||||
}
|
||||
|
||||
type kubeconfig struct {
|
||||
APIVersion string `yaml:"apiVersion"`
|
||||
CurrentContext string `yaml:"current-context"`
|
||||
Contexts []context `yaml:"contexts"`
|
||||
}
|
||||
|
||||
func printListContexts(out io.Writer) error {
|
||||
cfgPath, err := kubeconfigPath()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to determine kubeconfig path")
|
||||
}
|
||||
|
||||
cfg, err := parseKubeconfig(cfgPath)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to read kubeconfig file")
|
||||
}
|
||||
_ = cfg
|
||||
|
||||
// print each context
|
||||
// - natural sort
|
||||
// - highlight current context
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -13,12 +13,12 @@ func main() {
|
||||
var op Op
|
||||
op = parseArgs(os.Args[1:])
|
||||
|
||||
// TODO consider addin Run() operation to each operation type
|
||||
switch v := op.(type) {
|
||||
case HelpOp:
|
||||
printHelp(os.Stdout)
|
||||
case ListOp:
|
||||
// TODO implement
|
||||
panic("not implemented")
|
||||
printListContexts(os.Stdout)
|
||||
case SwitchOp:
|
||||
// TODO implement
|
||||
panic("not implemented")
|
||||
|
2
go.mod
2
go.mod
@ -5,4 +5,6 @@ go 1.14
|
||||
require (
|
||||
github.com/fatih/color v1.9.0
|
||||
github.com/google/go-cmp v0.4.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
|
||||
)
|
||||
|
5
go.sum
5
go.sum
@ -7,7 +7,12 @@ github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
Loading…
Reference in New Issue
Block a user