From 7a40a5ed07c740dbdf56d1f6f8d0997f8599d131 Mon Sep 17 00:00:00 2001 From: Ahmet Alp Balkan Date: Fri, 10 Apr 2020 14:25:00 -0700 Subject: [PATCH] Add utils for r/w ~/.kube/kubectx file Signed-off-by: Ahmet Alp Balkan --- cmd/kubectx/state.go | 37 ++++++++++++++++ cmd/kubectx/state_test.go | 88 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 cmd/kubectx/state.go create mode 100644 cmd/kubectx/state_test.go diff --git a/cmd/kubectx/state.go b/cmd/kubectx/state.go new file mode 100644 index 0000000..1d0f334 --- /dev/null +++ b/cmd/kubectx/state.go @@ -0,0 +1,37 @@ +package main + +import ( + "io/ioutil" + "os" + "path/filepath" + + "github.com/pkg/errors" +) + +func kubectxFilePath() (string, error) { + home := homeDir() + if home == "" { + return "", errors.New("HOME or USERPROFILE environment variable not set") + } + return filepath.Join(home, ".kube", "kubectx"), nil +} + +// readLastContext returns the saved previous context +// if the state file exists, otherwise returns "". +func readLastContext(path string) (string, error) { + b, err := ioutil.ReadFile(path) + if os.IsNotExist(err) { + return "", nil + } + return string(b), err +} + +// writeLastContext saves the specified value to the state file. +// It creates missing parent directories. +func writeLastContext(path, value string) error { + dir := filepath.Dir(path) + if err := os.MkdirAll(dir, 0755); err != nil { + return errors.Wrap(err, "failed to create parent directories") + } + return ioutil.WriteFile(path, []byte(value), 0644) +} diff --git a/cmd/kubectx/state_test.go b/cmd/kubectx/state_test.go new file mode 100644 index 0000000..b67fd3e --- /dev/null +++ b/cmd/kubectx/state_test.go @@ -0,0 +1,88 @@ +package main + +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" +) + +func Test_readLastContext_nonExistingFile(t *testing.T) { + s, err := readLastContext(filepath.FromSlash("/non/existing/file")) + if err != nil { + t.Fatal(err) + } + if s != "" { + t.Fatalf("expected empty string; got=%q", s) + } +} + +func Test_readLastContext(t *testing.T) { + path, cleanup := testfile(t, "foo") + defer cleanup() + + s, err := readLastContext(path) + if err != nil { + t.Fatal(err) + } + if expected := "foo"; s != expected { + t.Fatalf("expected=%q; got=%q", expected, s) + } +} + +func Test_writeLastContext_err(t *testing.T) { + path := filepath.Join(os.DevNull, "foo", "bar") + err := writeLastContext(path, "foo") + if err == nil { + t.Fatal("got empty error") + } +} + +func Test_writeLastContext(t *testing.T) { + dir, err := ioutil.TempDir(os.TempDir(), "state-file-test") + if err != nil { + t.Fatal(err) + } + path := filepath.Join(dir, "foo", "bar") + + if err := writeLastContext(path, "ctx1"); err != nil { + t.Fatal(err) + } + + v, err := readLastContext(path) + if err != nil { + t.Fatal(err) + } + if expected := "ctx1"; v != expected { + t.Fatalf("read wrong value=%q; expected=%q", v, expected) + } +} + +func Test_kubectxFilePath(t *testing.T) { + origHome := os.Getenv("HOME") + os.Setenv("HOME", filepath.FromSlash("/foo/bar")) + defer os.Setenv("HOME", origHome) + + expected := filepath.Join(filepath.FromSlash("/foo/bar"), ".kube", "kubectx") + v, err := kubectxFilePath() + if err != nil { + t.Fatal(err) + } + if v != expected { + t.Fatalf("expected=%q got=%q", expected, v) + } +} + +func Test_kubectxFilePath_error(t *testing.T) { + origHome := os.Getenv("HOME") + origUserprofile := os.Getenv("USERPROFILE") + os.Unsetenv("HOME") + os.Unsetenv("USERPROFILE") + defer os.Setenv("HOME", origHome) + defer os.Setenv("USERPROFILE", origUserprofile) + + _, err := kubectxFilePath() + if err == nil { + t.Fatal(err) + } +}