Skip to content

Commit

Permalink
Add delete command.
Browse files Browse the repository at this point in the history
  • Loading branch information
gjbae1212 committed Feb 4, 2021
1 parent 8186e4a commit 052be17
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 2 deletions.
59 changes: 59 additions & 0 deletions cmd/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package cmd

import (
"fmt"

"github.com/fatih/color"
"github.com/gjbae1212/kubectl-cred/internal"
"github.com/spf13/cobra"
)

var (
deleteCmd = &cobra.Command{
Use: "delete",
Short: "Delete context in k8s config, using an interactive CLI.",
Long: "Delete context in k8s config, using an interactive CLI.",
PreRun: deletePreRun(),
Run: deleteRun(),
}
)

func deletePreRun() commandRun {
return func(cmd *cobra.Command, args []string) {}
}

func deleteRun() commandRun {
return func(cmd *cobra.Command, args []string) {
contexts, err := kubeConfig.GetContexts()
if err != nil {
internal.PanicWithRed(fmt.Errorf("[err] failed getting current kubernetes context. %w", err))
}

deleteContextName, err := askContext(contexts)
if err != nil {
internal.PanicWithRed(fmt.Errorf("[err] failed context selecting"))
}

if ok := askConfirmDeletingContextName(deleteContextName); !ok {
return
}

if err := kubeConfig.DeleteContext(deleteContextName); err != nil {
internal.PanicWithRed(fmt.Errorf("[err] failed delete context"))
}

if err := kubeConfig.Sync(); err != nil {
internal.PanicWithRed(fmt.Errorf("[err] config sync error"))
}

fmt.Printf("%s %s %s\n",
color.GreenString("[success]"),
color.YellowString("delete context:"),
color.CyanString(deleteContextName),
)
}
}

func init() {
rootCmd.AddCommand(deleteCmd)
}
1 change: 1 addition & 0 deletions cmd/delete_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package cmd
1 change: 0 additions & 1 deletion cmd/rename.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"

"github.com/fatih/color"

"github.com/gjbae1212/kubectl-cred/internal"
"github.com/spf13/cobra"
)
Expand Down
11 changes: 10 additions & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,16 @@ func askWantedContextName() string {
func askConfirmChangingContextName(currentContextName, changeContextName string) bool {
ok := false
prompt := &survey.Confirm{
Message: fmt.Sprintf("Do you really want to change %s to %s", currentContextName, changeContextName),
Message: fmt.Sprintf("Do you really want to change %s to %s?", currentContextName, changeContextName),
}
survey.AskOne(prompt, &ok)
return ok
}

func askConfirmDeletingContextName(contextName string) bool {
ok := false
prompt := &survey.Confirm{
Message: fmt.Sprintf("Do you really want to delete %s?", contextName),
}
survey.AskOne(prompt, &ok)
return ok
Expand Down
84 changes: 84 additions & 0 deletions internal/kubeconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"reflect"

"github.com/mitchellh/go-homedir"
"github.com/tomwright/dasel"
Expand Down Expand Up @@ -185,6 +186,62 @@ func (k *KubeConfig) GetContexts() ([]*KubeContext, error) {
return kubectxs, nil
}

// DeleteContext deletes context.
func (k *KubeConfig) DeleteContext(ctxName string) error {
contexts, err := k.GetContexts()
if err != nil {
return err
}

var deleteContext *KubeContext
for _, c := range contexts {
if c.Name == ctxName {
deleteContext = c
break
}
}
if deleteContext == nil {
return nil
}

unmarshalYaml := k.rootNode.OriginalValue
if yamlMap, ok := unmarshalYaml.(map[interface{}]interface{}); ok {
for name, value := range yamlMap {
switch name.(string) {
case "clusters":
changed, err := k.deleteByName(value.([]interface{}), deleteContext.Cluster)
if err != nil {
return err
}
yamlMap[name] = changed
case "contexts":
changed, err := k.deleteByName(value.([]interface{}), deleteContext.Name)
if err != nil {
return err
}
yamlMap[name] = changed
case "current-context":
valueString, err := InterfaceToString(value)
if err != nil {
return err
}
if valueString == deleteContext.Name {
yamlMap[name] = ""
}
case "users":
changed, err := k.deleteByName(value.([]interface{}), deleteContext.User)
if err != nil {
return err
}
yamlMap[name] = changed
}
}
k.rootNode.Value = reflect.ValueOf(yamlMap)
k.rootNode.OriginalValue = yamlMap
}
return nil
}

// Sync syncs rootNode to file.
func (k *KubeConfig) Sync() error {
// copy origin file to prev file.
Expand Down Expand Up @@ -225,6 +282,33 @@ func (k *KubeConfig) RawBytes() ([]byte, error) {
return bys, err
}

func (k *KubeConfig) deleteByName(arr []interface{}, name string) ([]interface{}, error) {
deleteIndex := -1
Loop:
for index, data := range arr {
if m, ok := data.(map[interface{}]interface{}); ok {
for k, v := range m {
if k.(string) == "name" {
vStr, err := InterfaceToString(v)
if err != nil {
return nil, err
}
if vStr == name {
deleteIndex = index
break Loop
}
}
}
}
}

if deleteIndex != -1 {
arr = append(arr[:deleteIndex], arr[deleteIndex+1:]...)
}

return arr, nil
}

// NewKubeConfig returns struct for kubernetes config file.
func NewKubeConfig(path string) (*KubeConfig, error) {
if path == "" {
Expand Down
43 changes: 43 additions & 0 deletions internal/kubeconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,50 @@ func TestKubeConfig_GetContexts(t *testing.T) {
assert.NotEmpty(ctx.Server)
}
}
}
}

func TestKubeConfig_DeleteContext(t *testing.T) {
assert := assert.New(t)

cfgPath, err := KubeConfigPath()
if err != nil {
return
}

kubeConfig, err := NewKubeConfig(cfgPath)
assert.NoError(err)

tests := map[string]struct {
input string
isErr bool
}{
"success": {input: "minikube"},
}

for _, t := range tests {
ctxs, err := kubeConfig.GetContexts()
assert.NoError(err)
var deleteContxt *KubeContext
for _, ctx := range ctxs {
if ctx.Name == t.input {
deleteContxt = ctx
break
}
}
if deleteContxt != nil {
err := kubeConfig.DeleteContext(t.input)
assert.Equal(t.isErr, err != nil)
if err == nil {
ctxs, err := kubeConfig.GetContexts()
assert.NoError(err)
for _, ctx := range ctxs {
assert.NotEqual(deleteContxt.Name, ctx.Name)
assert.NotEmpty(deleteContxt.Cluster, ctx.Cluster)
assert.NotEmpty(deleteContxt.User, ctx.User)
}
}
}
}
}

Expand Down

0 comments on commit 052be17

Please sign in to comment.