Repository: code-ready/crc
Pull request #2407 (2021-06-08 09:26:48)

Clean kubeconfig file after crc delete
Remove contexts, auth infos and clusters related to the crc cluster from
 the kubeconfig file.

```
$ kubectx
/api-crc-testing:6443/developer
crc-admin
crc-developer
kind-reference
minishift
myproject/192-168-42-71:8443/developer
myproject/192-168-42-71:8443/system:admin
project1/api-crc-testing:6443/developer

$ crc delete
Do you want to delete the OpenShift cluster? [y/N]: y
Deleted the OpenShift cluster

$ kubectx
kind-reference
minishift
myproject/192-168-42-71:8443/developer
myproject/192-168-42-71:8443/system:admin

```

openshift-ci[bot]: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/code-ready/crc/pull/2407#" title="Author self-approved">guillaumerose</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=code-ready%2Fcrc).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/code-ready/crc/blob/master/OWNERS)~~ [guillaumerose]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
praveenkumar: /lgtm

Patch:
diff --git a/pkg/crc/machine/delete.go b/pkg/crc/machine/delete.go
index 535ea55ec..a0a73d1a6 100644
--- a/pkg/crc/machine/delete.go
+++ b/pkg/crc/machine/delete.go
@@ -1,6 +1,7 @@
 package machine
 
 import (
+	"github.com/code-ready/crc/pkg/crc/logging"
 	"github.com/pkg/errors"
 )
 
@@ -20,5 +21,9 @@ func (client *client) Delete() error {
 	if err := libMachineAPIClient.Remove(client.name); err != nil {
 		return errors.Wrap(err, "Cannot remove machine")
 	}
+
+	if err := cleanKubeconfig(getGlobalKubeConfigPath(), getGlobalKubeConfigPath()); err != nil {
+		logging.Warn(err)
+	}
 	return nil
 }
diff --git a/pkg/crc/machine/kubeconfig.go b/pkg/crc/machine/kubeconfig.go
index 20371c213..880e9442d 100644
--- a/pkg/crc/machine/kubeconfig.go
+++ b/pkg/crc/machine/kubeconfig.go
@@ -142,3 +142,55 @@ func getGlobalKubeConfigPath() string {
 	}
 	return filepath.Join(constants.GetHomeDir(), ".kube", "config")
 }
+
+func cleanKubeconfig(input, output string) error {
+	cfg, err := clientcmd.LoadFromFile(input)
+	if err != nil {
+		return err
+	}
+
+	var clusterNames []string
+	for name, cluster := range cfg.Clusters {
+		if cluster.Server == fmt.Sprintf("https://api%s:6443", constants.ClusterDomain) {
+			clusterNames = append(clusterNames, name)
+		}
+	}
+	var contextNames []string
+	authNames := make(map[string]struct{})
+	for name, context := range cfg.Contexts {
+		if contains(clusterNames, context.Cluster) {
+			contextNames = append(contextNames, name)
+			authNames[context.AuthInfo] = struct{}{}
+		}
+	}
+	// keep auth if it is shared with other contexts
+	for _, context := range cfg.Contexts {
+		if !contains(clusterNames, context.Cluster) {
+			delete(authNames, context.AuthInfo)
+		}
+	}
+
+	for _, name := range clusterNames {
+		delete(cfg.Clusters, name)
+	}
+	for _, name := range contextNames {
+		delete(cfg.Contexts, name)
+		if cfg.CurrentContext == name {
+			cfg.CurrentContext = ""
+		}
+	}
+	for name := range authNames {
+		delete(cfg.AuthInfos, name)
+	}
+
+	return clientcmd.WriteToFile(*cfg, output)
+}
+
+func contains(arr []string, str string) bool {
+	for _, a := range arr {
+		if a == str {
+			return true
+		}
+	}
+	return false
+}


Test patch:
diff --git a/pkg/crc/machine/kubeconfig_test.go b/pkg/crc/machine/kubeconfig_test.go
index 475259d60..0bbbeb555 100644
--- a/pkg/crc/machine/kubeconfig_test.go
+++ b/pkg/crc/machine/kubeconfig_test.go
@@ -2,6 +2,8 @@ package machine
 
 import (
 	"io/ioutil"
+	"os"
+	"path/filepath"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
@@ -37,3 +39,16 @@ func TestCertificateAuthority(t *testing.T) {
 	expectedString := "-----BEGIN CERTIFICATE-----\nMIIDODCCAiCgAwIBAgIIRVfCKNUa1wIwDQYJKoZIhvcNAQELBQAwJjEkMCIGA1UE\nAwwbaW5ncmVzcy1vcGVyYXRvckAxNTk5OTkxMDc4MB4XDTIwMDkxMzA5NTgwOFoX\nDTIyMDkxMzA5NTgwOVowHTEbMBkGA1UEAwwSKi5hcHBzLWNyYy50ZXN0aW5nMIIB\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtClYnM1FYiH+wcYiGIUnLvNi\nzLWWjsqJrQ/4Snnu61HDaU5w3An9yDZojyaJdCmWUg6CKXDiCoJB+lxMFdyaolXU\ndohJ9vr2wt6iuNfshmtxUwiBhI9ZBsVhztWdu3cgnUcYW8KMyUmajiEyXD8Npvba\nZ4ifUsjAYE1LByZzPIkmBmKPnv0fFZu1ejgg7HuQlYmfN/pJHudWMvwZJ8b3Zhqn\nsA0cDsaCDU1SJk6cQvNJFgF38+IWNhJpiQlGfFwKkal64/RYcR9yv8/pMV+7jj1z\nBPI9yxbFgLuxLxlyS8Kxnz9ln/4V0ZB12qU3c6aM4Ew3uhYv8ZDSOnpTUSjrRwID\nAQABo3MwcTAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYD\nVR0TAQH/BAIwADAdBgNVHQ4EFgQUTtNCBUyuPpf4M4YhlYBqJhZGQYYwHQYDVR0R\nBBYwFIISKi5hcHBzLWNyYy50ZXN0aW5nMA0GCSqGSIb3DQEBCwUAA4IBAQBkGZiv\nBqqEDKUTiifFfTxQXJzO5OBBTUDqSntrknAw0sidPgn9A8a2gGdCr7mKEH16FQ7N\n1SpkjXWZghE/1pZTaS7JVcT6+Yuplfy5Reoim/Nlu8ulDDfBSSp9S9BO+Q/lFJdM\nomwyIu0sSXI79ColhLirDinEmyQMDHdmTJ+kJfctpSH27L4j5osJxtNSAEABmUgX\n1HQ7FYzrNmys5OcK9SlDn0vCyOTHyqBbxRnF6L9Ec2bU6KD0DvEBurBpAYGMc9ss\nBD0FXdHEPg7HP0Nep79jhe10IXGrghtep3D5jUjbj1I4DGSsQ8y4df2vo6IFd96A\nf0uUS/73sncN64gl\n-----END CERTIFICATE-----\n"
 	assert.Equal(t, expectedString, string(st), "")
 }
+
+func TestCleanKubeconfig(t *testing.T) {
+	dir, err := ioutil.TempDir("", "clean")
+	assert.NoError(t, err)
+	defer os.RemoveAll(dir)
+
+	assert.NoError(t, cleanKubeconfig(filepath.Join("testdata", "kubeconfig.in"), filepath.Join(dir, "kubeconfig")))
+	actual, err := ioutil.ReadFile(filepath.Join(dir, "kubeconfig"))
+	assert.NoError(t, err)
+	expected, err := ioutil.ReadFile(filepath.Join("testdata", "kubeconfig.out"))
+	assert.NoError(t, err)
+	assert.YAMLEq(t, string(expected), string(actual))
+}
diff --git a/pkg/crc/machine/testdata/kubeconfig.in b/pkg/crc/machine/testdata/kubeconfig.in
new file mode 100644
index 000000000..bfdbc3819
--- /dev/null
+++ b/pkg/crc/machine/testdata/kubeconfig.in
@@ -0,0 +1,63 @@
+apiVersion: v1
+clusters:
+- cluster:
+    certificate-authority-data: ZW1wdHkK
+    server: https://192.168.42.71:8443
+  name: 192-168-42-71:8443
+- cluster:
+    certificate-authority-data: ZW1wdHkK
+    server: https://api.crc.testing:6443
+  name: api-crc-testing:6443
+- cluster:
+    certificate-authority-data: ZW1wdHkK
+    server: https://127.0.0.1:33407
+  name: kind-reference
+contexts:
+- context:
+    cluster: api-crc-testing:6443
+    user: developer
+  name: /api-crc-testing:6443/developer
+- context:
+    cluster: api-crc-testing:6443
+    namespace: default
+    user: kubeadmin
+  name: crc-admin
+- context:
+    cluster: api-crc-testing:6443
+    namespace: default
+    user: developer
+  name: crc-developer
+- context:
+    cluster: kind-reference
+    user: kind-reference
+  name: kind-reference
+- context:
+    cluster: 192-168-42-71:8443
+    namespace: myproject
+    user: developer/192-168-42-71:8443
+  name: minishift
+- context:
+    cluster: api-crc-testing:6443
+    namespace: project1
+    user: developer
+  name: project1/api-crc-testing:6443/developer
+current-context: project1/api-crc-testing:6443/developer
+kind: Config
+preferences: {}
+users:
+- name: developer
+  user:
+    token: token1
+- name: developer/192-168-42-71:8443
+  user:
+    token: token2
+- name: developer/api-crc-testing:6443
+  user:
+    token: token3
+- name: kind-reference
+  user:
+    client-certificate-data: ZW1wdHkK
+    client-key-data: ZW1wdHkK
+- name: kubeadmin
+  user:
+    token: token4
diff --git a/pkg/crc/machine/testdata/kubeconfig.out b/pkg/crc/machine/testdata/kubeconfig.out
new file mode 100644
index 000000000..62d93a5d9
--- /dev/null
+++ b/pkg/crc/machine/testdata/kubeconfig.out
@@ -0,0 +1,34 @@
+apiVersion: v1
+clusters:
+- cluster:
+    certificate-authority-data: ZW1wdHkK
+    server: https://192.168.42.71:8443
+  name: 192-168-42-71:8443
+- cluster:
+    certificate-authority-data: ZW1wdHkK
+    server: https://127.0.0.1:33407
+  name: kind-reference
+contexts:
+- context:
+    cluster: kind-reference
+    user: kind-reference
+  name: kind-reference
+- context:
+    cluster: 192-168-42-71:8443
+    namespace: myproject
+    user: developer/192-168-42-71:8443
+  name: minishift
+current-context: ""
+kind: Config
+preferences: {}
+users:
+- name: developer/192-168-42-71:8443
+  user:
+    token: token2
+- name: developer/api-crc-testing:6443
+  user:
+    token: token3
+- name: kind-reference
+  user:
+    client-certificate-data: ZW1wdHkK
+    client-key-data: ZW1wdHkK