mirror of
https://github.com/ahmetb/kubectx.git
synced 2025-07-29 14:08:26 +00:00
Move kubeconfig loader utils to cmdutil pkg
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
This commit is contained in:
parent
1982becb15
commit
c4252b5795
@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/ahmetb/kubectx/internal/cmdutil"
|
||||||
"github.com/ahmetb/kubectx/internal/kubeconfig"
|
"github.com/ahmetb/kubectx/internal/kubeconfig"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -13,7 +14,7 @@ import (
|
|||||||
type CurrentOp struct{}
|
type CurrentOp struct{}
|
||||||
|
|
||||||
func (_op CurrentOp) Run(stdout, _ io.Writer) error {
|
func (_op CurrentOp) Run(stdout, _ io.Writer) error {
|
||||||
kc := new(kubeconfig.Kubeconfig).WithLoader(defaultLoader)
|
kc := new(kubeconfig.Kubeconfig).WithLoader(cmdutil.DefaultLoader)
|
||||||
defer kc.Close()
|
defer kc.Close()
|
||||||
if err := kc.Parse(); err != nil {
|
if err := kc.Parse(); err != nil {
|
||||||
return errors.Wrap(err, "kubeconfig error")
|
return errors.Wrap(err, "kubeconfig error")
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/ahmetb/kubectx/internal/cmdutil"
|
||||||
"github.com/ahmetb/kubectx/internal/kubeconfig"
|
"github.com/ahmetb/kubectx/internal/kubeconfig"
|
||||||
"github.com/ahmetb/kubectx/internal/printer"
|
"github.com/ahmetb/kubectx/internal/printer"
|
||||||
)
|
)
|
||||||
@ -35,7 +36,7 @@ func (op DeleteOp) Run(_, stderr io.Writer) error {
|
|||||||
// deleteContext deletes a context entry by NAME or current-context
|
// deleteContext deletes a context entry by NAME or current-context
|
||||||
// indicated by ".".
|
// indicated by ".".
|
||||||
func deleteContext(name string) (deleteName string, wasActiveContext bool, err error) {
|
func deleteContext(name string) (deleteName string, wasActiveContext bool, err error) {
|
||||||
kc := new(kubeconfig.Kubeconfig).WithLoader(defaultLoader)
|
kc := new(kubeconfig.Kubeconfig).WithLoader(cmdutil.DefaultLoader)
|
||||||
defer kc.Close()
|
defer kc.Close()
|
||||||
if err := kc.Parse(); err != nil {
|
if err := kc.Parse(); err != nil {
|
||||||
return deleteName, false, errors.Wrap(err, "kubeconfig error")
|
return deleteName, false, errors.Wrap(err, "kubeconfig error")
|
||||||
|
@ -20,7 +20,7 @@ func (op UnsupportedOp) Run(_, _ io.Writer) error {
|
|||||||
// and decides which operation should be taken.
|
// and decides which operation should be taken.
|
||||||
func parseArgs(argv []string) Op {
|
func parseArgs(argv []string) Op {
|
||||||
if len(argv) == 0 {
|
if len(argv) == 0 {
|
||||||
if env.IsInteractiveMode(os.Stdout) {
|
if cmdutil.IsInteractiveMode(os.Stdout) {
|
||||||
return InteractiveSwitchOp{SelfCmd: os.Args[0]}
|
return InteractiveSwitchOp{SelfCmd: os.Args[0]}
|
||||||
}
|
}
|
||||||
return ListOp{}
|
return ListOp{}
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/ahmetb/kubectx/internal/cmdutil"
|
||||||
"github.com/ahmetb/kubectx/internal/env"
|
"github.com/ahmetb/kubectx/internal/env"
|
||||||
"github.com/ahmetb/kubectx/internal/kubeconfig"
|
"github.com/ahmetb/kubectx/internal/kubeconfig"
|
||||||
"github.com/ahmetb/kubectx/internal/printer"
|
"github.com/ahmetb/kubectx/internal/printer"
|
||||||
@ -21,9 +22,9 @@ type InteractiveSwitchOp struct {
|
|||||||
|
|
||||||
func (op InteractiveSwitchOp) Run(_, stderr io.Writer) error {
|
func (op InteractiveSwitchOp) Run(_, stderr io.Writer) error {
|
||||||
// parse kubeconfig just to see if it can be loaded
|
// parse kubeconfig just to see if it can be loaded
|
||||||
kc := new(kubeconfig.Kubeconfig).WithLoader(defaultLoader)
|
kc := new(kubeconfig.Kubeconfig).WithLoader(cmdutil.DefaultLoader)
|
||||||
if err := kc.Parse(); err != nil {
|
if err := kc.Parse(); err != nil {
|
||||||
if isENOENT(err) {
|
if cmdutil.IsNotFoundErr(err) {
|
||||||
printer.Warning(stderr, "kubeconfig file not found")
|
printer.Warning(stderr, "kubeconfig file not found")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,12 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
|
||||||
|
|
||||||
"facette.io/natsort"
|
"facette.io/natsort"
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/ahmetb/kubectx/internal/cmdutil"
|
||||||
"github.com/ahmetb/kubectx/internal/kubeconfig"
|
"github.com/ahmetb/kubectx/internal/kubeconfig"
|
||||||
"github.com/ahmetb/kubectx/internal/printer"
|
"github.com/ahmetb/kubectx/internal/printer"
|
||||||
)
|
)
|
||||||
@ -17,10 +17,10 @@ import (
|
|||||||
type ListOp struct{}
|
type ListOp struct{}
|
||||||
|
|
||||||
func (_ ListOp) Run(stdout, stderr io.Writer) error {
|
func (_ ListOp) Run(stdout, stderr io.Writer) error {
|
||||||
kc := new(kubeconfig.Kubeconfig).WithLoader(defaultLoader)
|
kc := new(kubeconfig.Kubeconfig).WithLoader(cmdutil.DefaultLoader)
|
||||||
defer kc.Close()
|
defer kc.Close()
|
||||||
if err := kc.Parse(); err != nil {
|
if err := kc.Parse(); err != nil {
|
||||||
if isENOENT(err) {
|
if cmdutil.IsNotFoundErr(err) {
|
||||||
printer.Warning(stderr, "kubeconfig file not found")
|
printer.Warning(stderr, "kubeconfig file not found")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -50,14 +50,3 @@ func (_ ListOp) Run(stdout, stderr io.Writer) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// isENOENT determines if the underlying error is os.IsNotExist. Right now
|
|
||||||
// errors from github.com/pkg/errors doesn't work with os.IsNotExist.
|
|
||||||
func isENOENT(err error) bool {
|
|
||||||
for e := err; e != nil; e = errors.Unwrap(e) {
|
|
||||||
if os.IsNotExist(e) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/ahmetb/kubectx/internal/cmdutil"
|
||||||
"github.com/ahmetb/kubectx/internal/kubeconfig"
|
"github.com/ahmetb/kubectx/internal/kubeconfig"
|
||||||
"github.com/ahmetb/kubectx/internal/printer"
|
"github.com/ahmetb/kubectx/internal/printer"
|
||||||
)
|
)
|
||||||
@ -34,7 +35,7 @@ func parseRenameSyntax(v string) (string, string, bool) {
|
|||||||
// to the "new" value. If the old refers to the current-context,
|
// to the "new" value. If the old refers to the current-context,
|
||||||
// current-context preference is also updated.
|
// current-context preference is also updated.
|
||||||
func (op RenameOp) Run(_, stderr io.Writer) error {
|
func (op RenameOp) Run(_, stderr io.Writer) error {
|
||||||
kc := new(kubeconfig.Kubeconfig).WithLoader(defaultLoader)
|
kc := new(kubeconfig.Kubeconfig).WithLoader(cmdutil.DefaultLoader)
|
||||||
defer kc.Close()
|
defer kc.Close()
|
||||||
if err := kc.Parse(); err != nil {
|
if err := kc.Parse(); err != nil {
|
||||||
return errors.Wrap(err, "kubeconfig error")
|
return errors.Wrap(err, "kubeconfig error")
|
||||||
|
@ -6,10 +6,12 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/ahmetb/kubectx/internal/cmdutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
func kubectxPrevCtxFile() (string, error) {
|
func kubectxPrevCtxFile() (string, error) {
|
||||||
home := homeDir()
|
home := cmdutil.HomeDir()
|
||||||
if home == "" {
|
if home == "" {
|
||||||
return "", errors.New("HOME or USERPROFILE environment variable not set")
|
return "", errors.New("HOME or USERPROFILE environment variable not set")
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ahmetb/kubectx/internal/testutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_readLastContext_nonExistingFile(t *testing.T) {
|
func Test_readLastContext_nonExistingFile(t *testing.T) {
|
||||||
@ -18,7 +20,7 @@ func Test_readLastContext_nonExistingFile(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_readLastContext(t *testing.T) {
|
func Test_readLastContext(t *testing.T) {
|
||||||
path, cleanup := testfile(t, "foo")
|
path, cleanup := testutil.TempFile(t, "foo")
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
s, err := readLastContext(path)
|
s, err := readLastContext(path)
|
||||||
@ -86,3 +88,4 @@ func Test_kubectxFilePath_error(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/ahmetb/kubectx/internal/cmdutil"
|
||||||
"github.com/ahmetb/kubectx/internal/kubeconfig"
|
"github.com/ahmetb/kubectx/internal/kubeconfig"
|
||||||
"github.com/ahmetb/kubectx/internal/printer"
|
"github.com/ahmetb/kubectx/internal/printer"
|
||||||
)
|
)
|
||||||
@ -36,7 +37,7 @@ func switchContext(name string) (string, error) {
|
|||||||
return "", errors.Wrap(err, "failed to determine state file")
|
return "", errors.Wrap(err, "failed to determine state file")
|
||||||
}
|
}
|
||||||
|
|
||||||
kc := new(kubeconfig.Kubeconfig).WithLoader(defaultLoader)
|
kc := new(kubeconfig.Kubeconfig).WithLoader(cmdutil.DefaultLoader)
|
||||||
defer kc.Close()
|
defer kc.Close()
|
||||||
if err := kc.Parse(); err != nil {
|
if err := kc.Parse(); err != nil {
|
||||||
return "", errors.Wrap(err, "kubeconfig error")
|
return "", errors.Wrap(err, "kubeconfig error")
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/ahmetb/kubectx/internal/cmdutil"
|
||||||
"github.com/ahmetb/kubectx/internal/kubeconfig"
|
"github.com/ahmetb/kubectx/internal/kubeconfig"
|
||||||
"github.com/ahmetb/kubectx/internal/printer"
|
"github.com/ahmetb/kubectx/internal/printer"
|
||||||
)
|
)
|
||||||
@ -13,7 +14,7 @@ import (
|
|||||||
type UnsetOp struct{}
|
type UnsetOp struct{}
|
||||||
|
|
||||||
func (_ UnsetOp) Run(_, stderr io.Writer) error {
|
func (_ UnsetOp) Run(_, stderr io.Writer) error {
|
||||||
kc := new(kubeconfig.Kubeconfig).WithLoader(defaultLoader)
|
kc := new(kubeconfig.Kubeconfig).WithLoader(cmdutil.DefaultLoader)
|
||||||
defer kc.Close()
|
defer kc.Close()
|
||||||
if err := kc.Parse(); err != nil {
|
if err := kc.Parse(); err != nil {
|
||||||
return errors.Wrap(err, "kubeconfig error")
|
return errors.Wrap(err, "kubeconfig error")
|
||||||
|
@ -1,9 +1,32 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "io"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/ahmetb/kubectx/internal/cmdutil"
|
||||||
|
"github.com/ahmetb/kubectx/internal/kubeconfig"
|
||||||
|
)
|
||||||
|
|
||||||
type CurrentOp struct{}
|
type CurrentOp struct{}
|
||||||
|
|
||||||
func (c CurrentOp) Run(stdout, stderr io.Writer) error {
|
func (c CurrentOp) Run(stdout, _ io.Writer) error {
|
||||||
panic("implement me")
|
kc := new(kubeconfig.Kubeconfig).WithLoader(cmdutil.DefaultLoader)
|
||||||
|
defer kc.Close()
|
||||||
|
if err := kc.Parse(); err != nil {
|
||||||
|
return errors.Wrap(err, "kubeconfig error")
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := kc.GetCurrentContext()
|
||||||
|
if ctx == "" {
|
||||||
|
return errors.New("current-context is not set")
|
||||||
|
}
|
||||||
|
ns, err := kc.NamespaceOfContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to read namespace of %q", ctx)
|
||||||
|
}
|
||||||
|
_, err = fmt.Fprintln(stdout, ns)
|
||||||
|
return errors.Wrap(err, "write error")
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package env
|
package cmdutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package main
|
package cmdutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
@ -10,21 +10,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
defaultLoader kubeconfig.Loader = new(StandardKubeconfigLoader)
|
DefaultLoader kubeconfig.Loader = new(StandardKubeconfigLoader)
|
||||||
)
|
)
|
||||||
|
|
||||||
type StandardKubeconfigLoader struct{}
|
type StandardKubeconfigLoader struct{}
|
||||||
|
|
||||||
type kubeconfigFile struct{ *os.File }
|
type kubeconfigFile struct{ *os.File }
|
||||||
|
|
||||||
func (kf *kubeconfigFile) Reset() error {
|
|
||||||
if err := kf.Truncate(0); err != nil {
|
|
||||||
return errors.Wrap(err, "failed to truncate file")
|
|
||||||
}
|
|
||||||
_, err := kf.Seek(0, 0)
|
|
||||||
return errors.Wrap(err, "failed to seek in file")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*StandardKubeconfigLoader) Load() (kubeconfig.ReadWriteResetCloser, error) {
|
func (*StandardKubeconfigLoader) Load() (kubeconfig.ReadWriteResetCloser, error) {
|
||||||
cfgPath, err := kubeconfigPath()
|
cfgPath, err := kubeconfigPath()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -40,6 +32,14 @@ func (*StandardKubeconfigLoader) Load() (kubeconfig.ReadWriteResetCloser, error)
|
|||||||
return &kubeconfigFile{f}, nil
|
return &kubeconfigFile{f}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (kf *kubeconfigFile) Reset() error {
|
||||||
|
if err := kf.Truncate(0); err != nil {
|
||||||
|
return errors.Wrap(err, "failed to truncate file")
|
||||||
|
}
|
||||||
|
_, err := kf.Seek(0, 0)
|
||||||
|
return errors.Wrap(err, "failed to seek in file")
|
||||||
|
}
|
||||||
|
|
||||||
func kubeconfigPath() (string, error) {
|
func kubeconfigPath() (string, error) {
|
||||||
// KUBECONFIG env var
|
// KUBECONFIG env var
|
||||||
if v := os.Getenv("KUBECONFIG"); v != "" {
|
if v := os.Getenv("KUBECONFIG"); v != "" {
|
||||||
@ -52,14 +52,14 @@ func kubeconfigPath() (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// default path
|
// default path
|
||||||
home := homeDir()
|
home := HomeDir()
|
||||||
if home == "" {
|
if home == "" {
|
||||||
return "", errors.New("HOME or USERPROFILE environment variable not set")
|
return "", errors.New("HOME or USERPROFILE environment variable not set")
|
||||||
}
|
}
|
||||||
return filepath.Join(home, ".kube", "config"), nil
|
return filepath.Join(home, ".kube", "config"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func homeDir() string {
|
func HomeDir() string {
|
||||||
if v := os.Getenv("XDG_CACHE_HOME"); v != "" {
|
if v := os.Getenv("XDG_CACHE_HOME"); v != "" {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
@ -69,3 +69,14 @@ func homeDir() string {
|
|||||||
}
|
}
|
||||||
return home
|
return home
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsNotFoundErr determines if the underlying error is os.IsNotExist. Right now
|
||||||
|
// errors from github.com/pkg/errors doesn't work with os.IsNotExist.
|
||||||
|
func IsNotFoundErr(err error) bool {
|
||||||
|
for e := err; e != nil; e = errors.Unwrap(e) {
|
||||||
|
if os.IsNotExist(e) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
package main
|
package cmdutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
@ -61,7 +60,7 @@ func Test_homeDir(t *testing.T) {
|
|||||||
unsets = append(unsets, testutil.WithEnvVar(e.k, e.v))
|
unsets = append(unsets, testutil.WithEnvVar(e.k, e.v))
|
||||||
}
|
}
|
||||||
|
|
||||||
got := homeDir()
|
got := HomeDir()
|
||||||
if got != c.want {
|
if got != c.want {
|
||||||
t.Errorf("expected:%q got:%q", c.want, got)
|
t.Errorf("expected:%q got:%q", c.want, got)
|
||||||
}
|
}
|
||||||
@ -120,30 +119,12 @@ func Test_kubeconfigPath_envOvverideDoesNotSupportPathSeparator(t *testing.T) {
|
|||||||
|
|
||||||
func TestStandardKubeconfigLoader_returnsNotFoundErr(t *testing.T) {
|
func TestStandardKubeconfigLoader_returnsNotFoundErr(t *testing.T) {
|
||||||
defer testutil.WithEnvVar("KUBECONFIG", "foo")()
|
defer testutil.WithEnvVar("KUBECONFIG", "foo")()
|
||||||
kc := new(kubeconfig.Kubeconfig).WithLoader(defaultLoader)
|
kc := new(kubeconfig.Kubeconfig).WithLoader(DefaultLoader)
|
||||||
err := kc.Parse()
|
err := kc.Parse()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("expected err")
|
t.Fatal("expected err")
|
||||||
}
|
}
|
||||||
if !isENOENT(err) {
|
if !IsNotFoundErr(err) {
|
||||||
t.Fatalf("expected ENOENT error; got=%v", err)
|
t.Fatalf("expected ENOENT error; got=%v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 +0,0 @@
|
|||||||
package kubeconfig
|
|
39
internal/kubeconfig/namespace.go
Normal file
39
internal/kubeconfig/namespace.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package kubeconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultNamespace = "default"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (k *Kubeconfig) contextNode(name string) (*yaml.Node, error) {
|
||||||
|
contexts := valueOf(k.rootNode, "contexts")
|
||||||
|
if contexts == nil {
|
||||||
|
return nil, errors.New("\"contexts\" entry is nil")
|
||||||
|
} else if contexts.Kind != yaml.SequenceNode {
|
||||||
|
return nil, errors.New("\"contexts\" is not a sequence node")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, contextNode := range contexts.Content {
|
||||||
|
nameNode := valueOf(contextNode, "name")
|
||||||
|
if nameNode.Kind == yaml.ScalarNode && nameNode.Value == name {
|
||||||
|
return contextNode, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, errors.Errorf("context with name %q not found", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *Kubeconfig) NamespaceOfContext(contextName string) (string, error) {
|
||||||
|
ctx, err := k.contextNode(contextName)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
ns := valueOf(ctx, "namespace")
|
||||||
|
if ns == nil || ns.Value == "" {
|
||||||
|
return defaultNamespace, nil
|
||||||
|
}
|
||||||
|
return ns.Value, nil
|
||||||
|
}
|
46
internal/kubeconfig/namespace_test.go
Normal file
46
internal/kubeconfig/namespace_test.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package kubeconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ahmetb/kubectx/internal/testutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestKubeconfig_NamespaceOfContext_ctxNotFound(t *testing.T) {
|
||||||
|
kc := new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(testutil.KC().
|
||||||
|
WithCtxs(testutil.Ctx("c1")).ToYAML(t)))
|
||||||
|
if err := kc.Parse(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := kc.NamespaceOfContext("c2")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected err")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKubeconfig_NamespaceOfContext(t *testing.T) {
|
||||||
|
kc := new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(testutil.KC().
|
||||||
|
WithCtxs(
|
||||||
|
testutil.Ctx("c1"),
|
||||||
|
testutil.Ctx("c2").Ns("c2n1")).ToYAML(t)))
|
||||||
|
if err := kc.Parse(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
v1, err := kc.NamespaceOfContext("c1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected err")
|
||||||
|
}
|
||||||
|
if expected := `default`; v1 != expected {
|
||||||
|
t.Fatalf("c1: expected=%q got=%q", expected, v1)
|
||||||
|
}
|
||||||
|
|
||||||
|
v2, err := kc.NamespaceOfContext("c2")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected err")
|
||||||
|
}
|
||||||
|
if expected := `c2n1`; v2 != expected {
|
||||||
|
t.Fatalf("c2: expected=%q got=%q", expected, v2)
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,8 @@ type Context struct {
|
|||||||
Namespace string `yaml:"namespace,omitempty"`
|
Namespace string `yaml:"namespace,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func Ctx(name string) *Context { return &Context{Name: name} }
|
func Ctx(name string) *Context { return &Context{Name: name} }
|
||||||
|
func (c *Context) Ns(ns string) *Context { c.Namespace = ns; return c }
|
||||||
|
|
||||||
type Kubeconfig map[string]interface{}
|
type Kubeconfig map[string]interface{}
|
||||||
|
|
||||||
|
26
internal/testutil/tempfile.go
Normal file
26
internal/testutil/tempfile.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package testutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TempFile(t *testing.T, contents string) (path string, cleanup func()) {
|
||||||
|
// TODO consider removing, used only in one place.
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user