Integrate ctx swap, check for wrong ctx names

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
This commit is contained in:
Ahmet Alp Balkan 2020-04-10 14:41:57 -07:00
parent 8aaefb8a94
commit ff6326c122
No known key found for this signature in database
GPG Key ID: 441833503E604E2C
2 changed files with 70 additions and 12 deletions

View File

@ -20,13 +20,15 @@ func main() {
case ListOp: case ListOp:
printListContexts(os.Stdout) printListContexts(os.Stdout)
case SwitchOp: case SwitchOp:
var newCtx string
var err error
if v.Target == "-" { if v.Target == "-" {
// TODO implement swap newCtx, err = swapContext()
panic("not implemented") } else {
} newCtx, err = switchContext(v.Target)
newCtx, err := switchContext(v.Target) }
if err != nil { if err != nil {
printError("faield to switch context: %v", err) printError("failed to switch context: %v", err)
os.Exit(1) os.Exit(1)
} }
fmt.Fprintf(os.Stderr, "Switched to context %q.\n", newCtx) fmt.Fprintf(os.Stderr, "Switched to context %q.\n", newCtx)
@ -40,5 +42,5 @@ func main() {
} }
func printError(format string, args ...interface{}) { func printError(format string, args ...interface{}) {
fmt.Fprintf(os.Stderr, color.RedString("error: "+format+"\n"), args...) fmt.Fprintf(os.Stderr, color.RedString("error: ")+format+"\n", args...)
} }

View File

@ -32,11 +32,16 @@ func switchContext(name string) (string, error) {
prev := getCurrentContext(kc) prev := getCurrentContext(kc)
// TODO: add a check to ensure user can't switch to non-existing context.
if !checkContextExists(kc, name) {
return "", errors.Errorf("no context exists with the name: %q", name)
}
if err := modifyCurrentContext(kc, name); err != nil { if err := modifyCurrentContext(kc, name); err != nil {
return "", err return "", err
} }
if err := f.Truncate(0); err != nil { if err := f.Truncate(0); err != nil {
return "", errors.Wrap(err, "failed to truncate") return "", errors.Wrap(err, "failed to truncate")
} }
@ -57,6 +62,58 @@ func switchContext(name string) (string, error) {
return name, nil return name, nil
} }
func checkContextExists(rootNode *yaml.Node, name string) bool {
contexts := valueOf(rootNode, "contexts")
if contexts == nil {
return false
}
if contexts.Kind != yaml.SequenceNode {
return false
}
var ctxNames []string
for _, ctx := range contexts.Content {
nameVal := valueOf(ctx, "name")
if nameVal != nil {
ctxNames = append(ctxNames, nameVal.Value)
}
}
for _, v := range ctxNames {
if v == name {
return true
}
}
return false
}
func valueOf(mapNode *yaml.Node, key string) *yaml.Node {
if mapNode.Kind != yaml.MappingNode {
return nil
}
for i, ch := range mapNode.Content {
if i%2 == 0 && ch.Kind == yaml.ScalarNode && ch.Value == key {
return mapNode.Content[i+1]
}
}
return nil
}
// swapContext switches to previously switch context.
func swapContext() (string, error) {
stateFile, err := kubectxFilePath()
if err != nil {
return "", errors.Wrap(err, "failed to determine state file")
}
prev, err := readLastContext(stateFile)
if err != nil {
return "", errors.Wrap(err, "failed to read previous context file")
}
if prev == "" {
return "", errors.New("no previous context found")
}
return switchContext(prev)
}
// getCurrentContext returns "current-context" value in given // getCurrentContext returns "current-context" value in given
// kubeconfig object Node, or returns "" if not found. // kubeconfig object Node, or returns "" if not found.
@ -64,12 +121,11 @@ func getCurrentContext(rootNode *yaml.Node) string {
if rootNode.Kind != yaml.MappingNode { if rootNode.Kind != yaml.MappingNode {
return "" return ""
} }
for i, ch := range rootNode.Content { v := valueOf(rootNode, "current-context")
if i%2 == 0 && ch.Value == "current-context" { if v == nil {
return rootNode.Content[i+1].Value return ""
}
} }
return "" return v.Value
} }
func modifyCurrentContext(rootNode *yaml.Node, name string) error { func modifyCurrentContext(rootNode *yaml.Node, name string) error {