From d0c352c5bf7387d11d51aadad45318c081b39a11 Mon Sep 17 00:00:00 2001 From: Ahmet Alp Balkan Date: Sat, 18 Apr 2020 14:05:32 -0700 Subject: [PATCH] Implement list (via exec kubectl), clearer color settings Signed-off-by: Ahmet Alp Balkan --- cmd/kubectx/list.go | 6 +-- cmd/kubens/list.go | 71 +++++++++++++++++++++++++++++++++- internal/printer/color.go | 16 +++++++- internal/printer/color_test.go | 12 +++--- internal/printer/printer.go | 2 +- 5 files changed, 92 insertions(+), 15 deletions(-) diff --git a/cmd/kubectx/list.go b/cmd/kubectx/list.go index 9df0534..361efcd 100644 --- a/cmd/kubectx/list.go +++ b/cmd/kubectx/list.go @@ -34,11 +34,7 @@ func (_ ListOp) Run(stdout, stderr io.Writer) error { // TODO support KUBECTX_CURRENT_BGCOLOR currentColor := color.New(color.FgGreen, color.Bold) - if v := printer.UseColors(); v != nil && *v { - currentColor.EnableColor() - } else if v != nil && !*v { - currentColor.DisableColor() - } + printer.EnableOrDisableColor(currentColor) cur := kc.GetCurrentContext() for _, c := range ctxs { diff --git a/cmd/kubens/list.go b/cmd/kubens/list.go index 51ccba9..2a3e01f 100644 --- a/cmd/kubens/list.go +++ b/cmd/kubens/list.go @@ -1,11 +1,80 @@ package main import ( + "bytes" + "fmt" "io" + "os" + "os/exec" + "strings" + + "github.com/fatih/color" + "github.com/pkg/errors" + + "github.com/ahmetb/kubectx/internal/cmdutil" + "github.com/ahmetb/kubectx/internal/kubeconfig" + "github.com/ahmetb/kubectx/internal/printer" ) type ListOp struct{} func (op ListOp) Run(stdout, stderr io.Writer) error { - panic("implement me") + kc := new(kubeconfig.Kubeconfig).WithLoader(cmdutil.DefaultLoader) + defer kc.Close() + if err := kc.Parse(); err != nil { + if cmdutil.IsNotFoundErr(err) { + printer.Warning(stderr, "kubeconfig file not found") + return nil + } + return errors.Wrap(err, "kubeconfig error") + } + + ctx := kc.GetCurrentContext() + if ctx == "" { + return errors.New("current-context is not set") + } + curNs, err := kc.NamespaceOfContext(ctx) + if err != nil { + return errors.Wrap(err, "cannot read current namespace") + } + + kubectl, err := findKubectl() + if err != nil { + return err + } + ns, err := queryNamespaces(kubectl) + if err != nil { + return err + } + + currentColor := color.New(color.FgGreen, color.Bold) + printer.EnableOrDisableColor(currentColor) + + for _, c := range ns { + s := c + if c == curNs { + s = currentColor.Sprint(c) + } + fmt.Fprintf(stdout, "%s\n", s) + } + return nil +} + +func findKubectl() (string, error) { + if v := os.Getenv("KUBECTL"); v != "" { + return v, nil + } + v, err := exec.LookPath("kubectl") + return v, errors.Wrap(err, "kubectl not found, needed for kubens") +} + +func queryNamespaces(kubectl string) ([]string, error) { + var b bytes.Buffer + cmd := exec.Command(kubectl, "get", "namespaces", `-o=jsonpath={range .items[*].metadata.name}{@}{"\n"}{end}`) + cmd.Env = os.Environ() + cmd.Stdout, cmd.Stderr = &b, &b + if err := cmd.Run(); err != nil { + return nil, errors.Wrapf(err, "failed to query namespaces: %v", b.String()) + } + return strings.Split(strings.TrimSpace(b.String()), "\n"), nil } diff --git a/internal/printer/color.go b/internal/printer/color.go index 42a957b..8f87f5b 100644 --- a/internal/printer/color.go +++ b/internal/printer/color.go @@ -3,13 +3,15 @@ package printer import ( "os" + "github.com/fatih/color" + "github.com/ahmetb/kubectx/internal/env" ) -// UseColors returns true if colors are force-enabled, +// useColors returns true if colors are force-enabled, // false if colors are disabled, or nil for default behavior // which is determined based on factors like if stdout is tty. -func UseColors() *bool { +func useColors() *bool { tr, fa := true, false if os.Getenv(env.EnvForceColor) != "" { return &tr @@ -18,3 +20,13 @@ func UseColors() *bool { } return nil } + +// EnableOrDisableColor determines if color should be force-enabled or force-disabled +// or left untouched based on environment configuration. +func EnableOrDisableColor(c *color.Color) { + if v := useColors(); v != nil && *v { + c.EnableColor() + } else if v != nil && !*v { + c.DisableColor() + } +} diff --git a/internal/printer/color_test.go b/internal/printer/color_test.go index fd6e1f7..3efe8f6 100644 --- a/internal/printer/color_test.go +++ b/internal/printer/color_test.go @@ -16,16 +16,16 @@ func Test_useColors_forceColors(t *testing.T) { defer testutil.WithEnvVar("_KUBECTX_FORCE_COLOR", "1")() defer testutil.WithEnvVar("NO_COLOR", "1")() - if v := UseColors(); !cmp.Equal(v, &tr) { - t.Fatalf("expected UseColors() = true; got = %v", v) + if v := useColors(); !cmp.Equal(v, &tr) { + t.Fatalf("expected useColors() = true; got = %v", v) } } func Test_useColors_disableColors(t *testing.T) { defer testutil.WithEnvVar("NO_COLOR", "1")() - if v := UseColors(); !cmp.Equal(v, &fa) { - t.Fatalf("expected UseColors() = false; got = %v", v) + if v := useColors(); !cmp.Equal(v, &fa) { + t.Fatalf("expected useColors() = false; got = %v", v) } } @@ -33,7 +33,7 @@ func Test_useColors_default(t *testing.T) { defer testutil.WithEnvVar("NO_COLOR", "")() defer testutil.WithEnvVar("_KUBECTX_FORCE_COLOR", "")() - if v := UseColors(); v != nil { - t.Fatalf("expected UseColors() = nil; got=%v", *v) + if v := useColors(); v != nil { + t.Fatalf("expected useColors() = nil; got=%v", *v) } } diff --git a/internal/printer/printer.go b/internal/printer/printer.go index 54452dc..1cef44f 100644 --- a/internal/printer/printer.go +++ b/internal/printer/printer.go @@ -14,7 +14,7 @@ var ( ) func init() { - colors := UseColors() + colors := useColors() if colors == nil { return }