diff --git a/README.md b/README.md index 6bef52dbcb..c8bd7535f4 100644 --- a/README.md +++ b/README.md @@ -170,6 +170,8 @@ To delete a cluster, run: ``` eksctl delete cluster --name= [--region=] ``` +> NOTE: Cluster info will be cleaned up in kubernetes config file. Please run `kubectl config get-contexts` to select right context. + ### Managing nodegroups diff --git a/humans.txt b/humans.txt index 22f4dbc828..678ea08c59 100644 --- a/humans.txt +++ b/humans.txt @@ -29,6 +29,7 @@ Yusuke Kuoka @mumoshu Daniel Herman @dcherman Takuma Hashimoto @af12066 Yasuhiro Hara @toricls +Jiaxin Shan @Jeffwan /* Thanks */ diff --git a/pkg/utils/kubeconfig/kubeconfig.go b/pkg/utils/kubeconfig/kubeconfig.go index dae7aa7830..d7e872e760 100644 --- a/pkg/utils/kubeconfig/kubeconfig.go +++ b/pkg/utils/kubeconfig/kubeconfig.go @@ -201,18 +201,26 @@ func deleteClusterInfo(existing *clientcmdapi.Config, cl *api.ClusterMeta) bool isChanged = true } - for username, context := range existing.Contexts { + var currentContextName string + for name, context := range existing.Contexts { if context.Cluster == clusterName { - delete(existing.Contexts, username) - logger.Debug("removed context for %q from kubeconfig", username) + delete(existing.Contexts, name) + logger.Debug("removed context for %q from kubeconfig", name) isChanged = true - if existing.AuthInfos[username] != nil { - delete(existing.AuthInfos, username) - logger.Debug("removed auth info for %q from kubeconfig", username) + if existing.AuthInfos[name] != nil { + delete(existing.AuthInfos, name) + logger.Debug("removed auth info for %q from kubeconfig", name) } + currentContextName = name break } } + if existing.CurrentContext == currentContextName { + existing.CurrentContext = "" + logger.Debug("removed current-context %q from kubeconfig", currentContextName) + isChanged = true + } + return isChanged } diff --git a/pkg/utils/kubeconfig/kubeconfig_test.go b/pkg/utils/kubeconfig/kubeconfig_test.go index fd10ffbc09..8563331d49 100644 --- a/pkg/utils/kubeconfig/kubeconfig_test.go +++ b/pkg/utils/kubeconfig/kubeconfig_test.go @@ -17,13 +17,16 @@ import ( var _ = Describe("Kubeconfig", func() { var configFile *os.File + var contextName = "test-context" + var testConfig = api.Config{ AuthInfos: map[string]*api.AuthInfo{ "test-user": {Token: "test-token"}}, Clusters: map[string]*api.Cluster{ "test-cluster": {Server: "https://127.0.0.1:8443"}}, Contexts: map[string]*api.Context{ - "test-context": {AuthInfo: "test-user", Cluster: "test-cluster", Namespace: "test-ns"}}, + contextName: {AuthInfo: "test-user", Cluster: "test-cluster", Namespace: "test-ns"}}, + CurrentContext: contextName, } BeforeEach(func() { @@ -168,10 +171,12 @@ var _ = Describe("Kubeconfig", func() { } var ( - oneClusterAsBytes []byte - twoClustersAsBytes []byte - kubeconfigPathToRestore string - hasKubeconfigPath bool + emptyClusterAsBytes []byte + oneClusterAsBytes []byte + twoClustersAsBytes []byte + oneClusterWithoutContextAsBytes []byte + kubeconfigPathToRestore string + hasKubeconfigPath bool ) // Returns an ClusterConfig with a cluster name equal to the provided clusterName. @@ -203,6 +208,10 @@ var _ = Describe("Kubeconfig", func() { var err error + if emptyClusterAsBytes, err = ioutil.ReadFile("testdata/empty_cluster.golden"); err != nil { + GinkgoT().Fatalf("failed reading .golden: %v", err) + } + if oneClusterAsBytes, err = ioutil.ReadFile("testdata/one_cluster.golden"); err != nil { GinkgoT().Fatalf("failed reading .golden: %v", err) } @@ -211,6 +220,10 @@ var _ = Describe("Kubeconfig", func() { GinkgoT().Fatalf("failed reading .golden: %v", err) } + if oneClusterWithoutContextAsBytes, err = ioutil.ReadFile("testdata/one_cluster_without_context.golden"); err != nil { + GinkgoT().Fatalf("failed reading .golden: %v", err) + } + _, err = configFile.Write(twoClustersAsBytes) Expect(err).To(BeNil()) }) @@ -219,7 +232,28 @@ var _ = Describe("Kubeconfig", func() { RestoreKubeconfig() }) - It("removes a cluster from the kubeconfig if the kubeconfig file includes the cluster", func() { + It("removes the only current cluster from the kubeconfig if the kubeconfig file includes the cluster", func() { + _, err := configFile.Write(oneClusterAsBytes) + Expect(err).To(BeNil()) + + existingClusterConfig := GetClusterConfig("cluster-one") + kubeconfig.MaybeDeleteConfig(existingClusterConfig.Metadata) + + configFileAsBytes, err := ioutil.ReadFile(configFile.Name()) + Expect(err).To(BeNil()) + Expect(bytes.Equal(configFileAsBytes, emptyClusterAsBytes)).To(BeTrue(), "Failed to delete cluster from config") + }) + + It("removes current cluster from the kubeconfig if the kubeconfig file includes the cluster", func() { + existingClusterConfig := GetClusterConfig("cluster-one") + kubeconfig.MaybeDeleteConfig(existingClusterConfig.Metadata) + + configFileAsBytes, err := ioutil.ReadFile(configFile.Name()) + Expect(err).To(BeNil()) + Expect(bytes.Equal(configFileAsBytes, oneClusterWithoutContextAsBytes)).To(BeTrue(), "Failed to delete cluster from config") + }) + + It("removes a secondary cluster from the kubeconfig if the kubeconfig file includes the cluster", func() { existingClusterConfig := GetClusterConfig("cluster-two") kubeconfig.MaybeDeleteConfig(existingClusterConfig.Metadata) diff --git a/pkg/utils/kubeconfig/testdata/empty_cluster.golden b/pkg/utils/kubeconfig/testdata/empty_cluster.golden new file mode 100644 index 0000000000..e3045f58d4 --- /dev/null +++ b/pkg/utils/kubeconfig/testdata/empty_cluster.golden @@ -0,0 +1,7 @@ +apiVersion: v1 +clusters: [] +contexts: [] +current-context: "" +kind: Config +preferences: {} +users: [] diff --git a/pkg/utils/kubeconfig/testdata/one_cluster_without_context.golden b/pkg/utils/kubeconfig/testdata/one_cluster_without_context.golden new file mode 100644 index 0000000000..2b72c1a69a --- /dev/null +++ b/pkg/utils/kubeconfig/testdata/one_cluster_without_context.golden @@ -0,0 +1,25 @@ +apiVersion: v1 +clusters: +- cluster: + certificate-authority-data: LS0tLS9CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5PENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTLS0tLS9CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5PENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTLS0tLS9CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5PENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTLS0tLS9CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5PENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTLS0tLS9CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5PENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTLS0tLS9CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5PENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTLS0tLS9CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5PENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTLS0tLS9CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5PENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTLS0tLS9CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5PENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTLS0tLS9CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5PENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTLS0tLS9CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5PENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTLS0tLS9CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5PENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTLS0tLS9CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5PENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTLS0tLS9CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5PENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREUBFWTLS0tLQo= + server: https://21.sk1.us-west-2.eks.amazonaws.com + name: cluster-two.us-west-2.eksctl.io +contexts: +- context: + cluster: cluster-two.us-west-2.eksctl.io + user: admin@cluster-two.us-west-2.eksctl.io + name: admin@cluster-two.us-west-2.eksctl.io +current-context: "" +kind: Config +preferences: {} +users: +- name: admin@cluster-two.us-west-2.eksctl.io + user: + exec: + apiVersion: client.authentication.k8s.io/v1alpha1 + args: + - token + - -i + - cluster-two + command: aws-iam-authenticator + env: null