| /* |
| Copyright 2014 The Kubernetes Authors. |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| package config |
| |
| import ( |
| "fmt" |
| "io/ioutil" |
| "os" |
| "path" |
| "reflect" |
| "strings" |
| "testing" |
| |
| apiequality "k8s.io/apimachinery/pkg/api/equality" |
| "k8s.io/apimachinery/pkg/util/diff" |
| "k8s.io/cli-runtime/pkg/genericclioptions" |
| "k8s.io/client-go/tools/clientcmd" |
| clientcmdapi "k8s.io/client-go/tools/clientcmd/api" |
| cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" |
| ) |
| |
| func newRedFederalCowHammerConfig() clientcmdapi.Config { |
| return clientcmdapi.Config{ |
| AuthInfos: map[string]*clientcmdapi.AuthInfo{ |
| "red-user": {Token: "red-token"}}, |
| Clusters: map[string]*clientcmdapi.Cluster{ |
| "cow-cluster": {Server: "http://cow.org:8080"}}, |
| Contexts: map[string]*clientcmdapi.Context{ |
| "federal-context": {AuthInfo: "red-user", Cluster: "cow-cluster"}}, |
| CurrentContext: "federal-context", |
| } |
| } |
| |
| func Example_view() { |
| expectedConfig := newRedFederalCowHammerConfig() |
| test := configCommandTest{ |
| args: []string{"view"}, |
| startingConfig: newRedFederalCowHammerConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| output := test.run(nil) |
| fmt.Printf("%v", output) |
| // Output: |
| // apiVersion: v1 |
| // clusters: |
| // - cluster: |
| // server: http://cow.org:8080 |
| // name: cow-cluster |
| // contexts: |
| // - context: |
| // cluster: cow-cluster |
| // user: red-user |
| // name: federal-context |
| // current-context: federal-context |
| // kind: Config |
| // preferences: {} |
| // users: |
| // - name: red-user |
| // user: |
| // token: red-token |
| } |
| |
| func TestCurrentContext(t *testing.T) { |
| startingConfig := newRedFederalCowHammerConfig() |
| test := configCommandTest{ |
| args: []string{"current-context"}, |
| startingConfig: startingConfig, |
| expectedConfig: startingConfig, |
| expectedOutputs: []string{startingConfig.CurrentContext}, |
| } |
| test.run(t) |
| } |
| |
| func TestSetCurrentContext(t *testing.T) { |
| expectedConfig := newRedFederalCowHammerConfig() |
| startingConfig := newRedFederalCowHammerConfig() |
| |
| newContextName := "the-new-context" |
| |
| startingConfig.Contexts[newContextName] = clientcmdapi.NewContext() |
| expectedConfig.Contexts[newContextName] = clientcmdapi.NewContext() |
| |
| expectedConfig.CurrentContext = newContextName |
| |
| test := configCommandTest{ |
| args: []string{"use-context", "the-new-context"}, |
| startingConfig: startingConfig, |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestSetNonExistentContext(t *testing.T) { |
| expectedConfig := newRedFederalCowHammerConfig() |
| |
| test := configCommandTest{ |
| args: []string{"use-context", "non-existent-config"}, |
| startingConfig: expectedConfig, |
| expectedConfig: expectedConfig, |
| } |
| |
| func() { |
| defer func() { |
| // Restore cmdutil behavior. |
| cmdutil.DefaultBehaviorOnFatal() |
| }() |
| |
| // Check exit code. |
| cmdutil.BehaviorOnFatal(func(e string, code int) { |
| if code != 1 { |
| t.Errorf("The exit code is %d, expected 1", code) |
| } |
| expectedOutputs := []string{`no context exists with the name: "non-existent-config"`} |
| test.checkOutput(e, expectedOutputs, t) |
| }) |
| |
| test.run(t) |
| }() |
| } |
| |
| func TestSetIntoExistingStruct(t *testing.T) { |
| expectedConfig := newRedFederalCowHammerConfig() |
| expectedConfig.AuthInfos["red-user"].Password = "new-path-value" |
| test := configCommandTest{ |
| args: []string{"set", "users.red-user.password", "new-path-value"}, |
| startingConfig: newRedFederalCowHammerConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestSetWithPathPrefixIntoExistingStruct(t *testing.T) { |
| expectedConfig := newRedFederalCowHammerConfig() |
| expectedConfig.Clusters["cow-cluster"].Server = "http://cow.org:8080/foo/baz" |
| test := configCommandTest{ |
| args: []string{"set", "clusters.cow-cluster.server", "http://cow.org:8080/foo/baz"}, |
| startingConfig: newRedFederalCowHammerConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| |
| dc := clientcmd.NewDefaultClientConfig(expectedConfig, &clientcmd.ConfigOverrides{}) |
| dcc, err := dc.ClientConfig() |
| if err != nil { |
| t.Fatalf("unexpected error: %v", err) |
| } |
| expectedHost := "http://cow.org:8080/foo/baz" |
| if expectedHost != dcc.Host { |
| t.Fatalf("expected client.Config.Host = %q instead of %q", expectedHost, dcc.Host) |
| } |
| } |
| |
| func TestUnsetStruct(t *testing.T) { |
| expectedConfig := newRedFederalCowHammerConfig() |
| delete(expectedConfig.AuthInfos, "red-user") |
| test := configCommandTest{ |
| args: []string{"unset", "users.red-user"}, |
| startingConfig: newRedFederalCowHammerConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestUnsetField(t *testing.T) { |
| expectedConfig := newRedFederalCowHammerConfig() |
| expectedConfig.AuthInfos["red-user"] = clientcmdapi.NewAuthInfo() |
| test := configCommandTest{ |
| args: []string{"unset", "users.red-user.token"}, |
| startingConfig: newRedFederalCowHammerConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestSetIntoNewStruct(t *testing.T) { |
| expectedConfig := newRedFederalCowHammerConfig() |
| cluster := clientcmdapi.NewCluster() |
| cluster.Server = "new-server-value" |
| expectedConfig.Clusters["big-cluster"] = cluster |
| test := configCommandTest{ |
| args: []string{"set", "clusters.big-cluster.server", "new-server-value"}, |
| startingConfig: newRedFederalCowHammerConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestSetBoolean(t *testing.T) { |
| expectedConfig := newRedFederalCowHammerConfig() |
| cluster := clientcmdapi.NewCluster() |
| cluster.InsecureSkipTLSVerify = true |
| expectedConfig.Clusters["big-cluster"] = cluster |
| test := configCommandTest{ |
| args: []string{"set", "clusters.big-cluster.insecure-skip-tls-verify", "true"}, |
| startingConfig: newRedFederalCowHammerConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestSetIntoNewConfig(t *testing.T) { |
| expectedConfig := *clientcmdapi.NewConfig() |
| context := clientcmdapi.NewContext() |
| context.AuthInfo = "fake-user" |
| expectedConfig.Contexts["new-context"] = context |
| test := configCommandTest{ |
| args: []string{"set", "contexts.new-context.user", "fake-user"}, |
| startingConfig: *clientcmdapi.NewConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestNewEmptyAuth(t *testing.T) { |
| expectedConfig := *clientcmdapi.NewConfig() |
| expectedConfig.AuthInfos["the-user-name"] = clientcmdapi.NewAuthInfo() |
| test := configCommandTest{ |
| args: []string{"set-credentials", "the-user-name"}, |
| startingConfig: *clientcmdapi.NewConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestAdditionalAuth(t *testing.T) { |
| expectedConfig := newRedFederalCowHammerConfig() |
| authInfo := clientcmdapi.NewAuthInfo() |
| authInfo.Token = "token" |
| expectedConfig.AuthInfos["another-user"] = authInfo |
| test := configCommandTest{ |
| args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagBearerToken + "=token"}, |
| startingConfig: newRedFederalCowHammerConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestEmbedClientCert(t *testing.T) { |
| fakeCertFile, _ := ioutil.TempFile("", "") |
| defer os.Remove(fakeCertFile.Name()) |
| fakeData := []byte("fake-data") |
| ioutil.WriteFile(fakeCertFile.Name(), fakeData, 0600) |
| expectedConfig := newRedFederalCowHammerConfig() |
| authInfo := clientcmdapi.NewAuthInfo() |
| authInfo.ClientCertificateData = fakeData |
| expectedConfig.AuthInfos["another-user"] = authInfo |
| |
| test := configCommandTest{ |
| args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagCertFile + "=" + fakeCertFile.Name(), "--" + clientcmd.FlagEmbedCerts + "=true"}, |
| startingConfig: newRedFederalCowHammerConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestEmbedClientKey(t *testing.T) { |
| fakeKeyFile, _ := ioutil.TempFile("", "") |
| defer os.Remove(fakeKeyFile.Name()) |
| fakeData := []byte("fake-data") |
| ioutil.WriteFile(fakeKeyFile.Name(), fakeData, 0600) |
| expectedConfig := newRedFederalCowHammerConfig() |
| authInfo := clientcmdapi.NewAuthInfo() |
| authInfo.ClientKeyData = fakeData |
| expectedConfig.AuthInfos["another-user"] = authInfo |
| |
| test := configCommandTest{ |
| args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagKeyFile + "=" + fakeKeyFile.Name(), "--" + clientcmd.FlagEmbedCerts + "=true"}, |
| startingConfig: newRedFederalCowHammerConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestEmbedNoKeyOrCertDisallowed(t *testing.T) { |
| expectedConfig := newRedFederalCowHammerConfig() |
| test := configCommandTest{ |
| args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagEmbedCerts + "=true"}, |
| startingConfig: newRedFederalCowHammerConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| func() { |
| defer func() { |
| // Restore cmdutil behavior. |
| cmdutil.DefaultBehaviorOnFatal() |
| }() |
| |
| // Check exit code. |
| cmdutil.BehaviorOnFatal(func(e string, code int) { |
| if code != 1 { |
| t.Errorf("The exit code is %d, expected 1", code) |
| } |
| expectedOutputs := []string{"--client-certificate", "--client-key", "embed"} |
| test.checkOutput(e, expectedOutputs, t) |
| }) |
| |
| test.run(t) |
| }() |
| } |
| |
| func TestEmptyTokenAndCertAllowed(t *testing.T) { |
| fakeCertFile, _ := ioutil.TempFile("", "cert-file") |
| defer os.Remove(fakeCertFile.Name()) |
| expectedConfig := newRedFederalCowHammerConfig() |
| authInfo := clientcmdapi.NewAuthInfo() |
| authInfo.ClientCertificate = path.Base(fakeCertFile.Name()) |
| expectedConfig.AuthInfos["another-user"] = authInfo |
| |
| test := configCommandTest{ |
| args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagCertFile + "=" + fakeCertFile.Name(), "--" + clientcmd.FlagBearerToken + "="}, |
| startingConfig: newRedFederalCowHammerConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestTokenAndCertAllowed(t *testing.T) { |
| expectedConfig := newRedFederalCowHammerConfig() |
| authInfo := clientcmdapi.NewAuthInfo() |
| authInfo.Token = "token" |
| authInfo.ClientCertificate = "/cert-file" |
| expectedConfig.AuthInfos["another-user"] = authInfo |
| test := configCommandTest{ |
| args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagCertFile + "=/cert-file", "--" + clientcmd.FlagBearerToken + "=token"}, |
| startingConfig: newRedFederalCowHammerConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestTokenAndBasicDisallowed(t *testing.T) { |
| expectedConfig := newRedFederalCowHammerConfig() |
| test := configCommandTest{ |
| args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagUsername + "=myuser", "--" + clientcmd.FlagBearerToken + "=token"}, |
| startingConfig: newRedFederalCowHammerConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| func() { |
| defer func() { |
| // Restore cmdutil behavior. |
| cmdutil.DefaultBehaviorOnFatal() |
| }() |
| |
| // Check exit code. |
| cmdutil.BehaviorOnFatal(func(e string, code int) { |
| if code != 1 { |
| t.Errorf("The exit code is %d, expected 1", code) |
| } |
| |
| expectedOutputs := []string{"--token", "--username"} |
| test.checkOutput(e, expectedOutputs, t) |
| }) |
| |
| test.run(t) |
| }() |
| } |
| |
| func TestBasicClearsToken(t *testing.T) { |
| authInfoWithToken := clientcmdapi.NewAuthInfo() |
| authInfoWithToken.Token = "token" |
| |
| authInfoWithBasic := clientcmdapi.NewAuthInfo() |
| authInfoWithBasic.Username = "myuser" |
| authInfoWithBasic.Password = "mypass" |
| |
| startingConfig := newRedFederalCowHammerConfig() |
| startingConfig.AuthInfos["another-user"] = authInfoWithToken |
| |
| expectedConfig := newRedFederalCowHammerConfig() |
| expectedConfig.AuthInfos["another-user"] = authInfoWithBasic |
| |
| test := configCommandTest{ |
| args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagUsername + "=myuser", "--" + clientcmd.FlagPassword + "=mypass"}, |
| startingConfig: startingConfig, |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestTokenClearsBasic(t *testing.T) { |
| authInfoWithBasic := clientcmdapi.NewAuthInfo() |
| authInfoWithBasic.Username = "myuser" |
| authInfoWithBasic.Password = "mypass" |
| |
| authInfoWithToken := clientcmdapi.NewAuthInfo() |
| authInfoWithToken.Token = "token" |
| |
| startingConfig := newRedFederalCowHammerConfig() |
| startingConfig.AuthInfos["another-user"] = authInfoWithBasic |
| |
| expectedConfig := newRedFederalCowHammerConfig() |
| expectedConfig.AuthInfos["another-user"] = authInfoWithToken |
| |
| test := configCommandTest{ |
| args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagBearerToken + "=token"}, |
| startingConfig: startingConfig, |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestTokenLeavesCert(t *testing.T) { |
| authInfoWithCerts := clientcmdapi.NewAuthInfo() |
| authInfoWithCerts.ClientCertificate = "cert" |
| authInfoWithCerts.ClientCertificateData = []byte("certdata") |
| authInfoWithCerts.ClientKey = "key" |
| authInfoWithCerts.ClientKeyData = []byte("keydata") |
| |
| authInfoWithTokenAndCerts := clientcmdapi.NewAuthInfo() |
| authInfoWithTokenAndCerts.Token = "token" |
| authInfoWithTokenAndCerts.ClientCertificate = "cert" |
| authInfoWithTokenAndCerts.ClientCertificateData = []byte("certdata") |
| authInfoWithTokenAndCerts.ClientKey = "key" |
| authInfoWithTokenAndCerts.ClientKeyData = []byte("keydata") |
| |
| startingConfig := newRedFederalCowHammerConfig() |
| startingConfig.AuthInfos["another-user"] = authInfoWithCerts |
| |
| expectedConfig := newRedFederalCowHammerConfig() |
| expectedConfig.AuthInfos["another-user"] = authInfoWithTokenAndCerts |
| |
| test := configCommandTest{ |
| args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagBearerToken + "=token"}, |
| startingConfig: startingConfig, |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestCertLeavesToken(t *testing.T) { |
| authInfoWithToken := clientcmdapi.NewAuthInfo() |
| authInfoWithToken.Token = "token" |
| |
| authInfoWithTokenAndCerts := clientcmdapi.NewAuthInfo() |
| authInfoWithTokenAndCerts.Token = "token" |
| authInfoWithTokenAndCerts.ClientCertificate = "/cert" |
| authInfoWithTokenAndCerts.ClientKey = "/key" |
| |
| startingConfig := newRedFederalCowHammerConfig() |
| startingConfig.AuthInfos["another-user"] = authInfoWithToken |
| |
| expectedConfig := newRedFederalCowHammerConfig() |
| expectedConfig.AuthInfos["another-user"] = authInfoWithTokenAndCerts |
| |
| test := configCommandTest{ |
| args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagCertFile + "=/cert", "--" + clientcmd.FlagKeyFile + "=/key"}, |
| startingConfig: startingConfig, |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestSetBytesBad(t *testing.T) { |
| startingConfig := newRedFederalCowHammerConfig() |
| startingConfig.Clusters["another-cluster"] = clientcmdapi.NewCluster() |
| |
| test := configCommandTest{ |
| args: []string{"set", "clusters.another-cluster.certificate-authority-data", "cadata"}, |
| startingConfig: startingConfig, |
| expectedConfig: startingConfig, |
| } |
| |
| func() { |
| defer func() { |
| // Restore cmdutil behavior. |
| cmdutil.DefaultBehaviorOnFatal() |
| }() |
| |
| // Check exit code. |
| cmdutil.BehaviorOnFatal(func(e string, code int) { |
| if code != 1 { |
| t.Errorf("The exit code is %d, expected 1", code) |
| } |
| }) |
| |
| test.run(t) |
| }() |
| } |
| |
| func TestSetBytes(t *testing.T) { |
| clusterInfoWithCAData := clientcmdapi.NewCluster() |
| clusterInfoWithCAData.CertificateAuthorityData = []byte("cadata") |
| |
| startingConfig := newRedFederalCowHammerConfig() |
| startingConfig.Clusters["another-cluster"] = clientcmdapi.NewCluster() |
| |
| expectedConfig := newRedFederalCowHammerConfig() |
| expectedConfig.Clusters["another-cluster"] = clusterInfoWithCAData |
| |
| test := configCommandTest{ |
| args: []string{"set", "clusters.another-cluster.certificate-authority-data", "cadata", "--set-raw-bytes"}, |
| startingConfig: startingConfig, |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestSetBase64Bytes(t *testing.T) { |
| clusterInfoWithCAData := clientcmdapi.NewCluster() |
| clusterInfoWithCAData.CertificateAuthorityData = []byte("cadata") |
| |
| startingConfig := newRedFederalCowHammerConfig() |
| startingConfig.Clusters["another-cluster"] = clientcmdapi.NewCluster() |
| |
| expectedConfig := newRedFederalCowHammerConfig() |
| expectedConfig.Clusters["another-cluster"] = clusterInfoWithCAData |
| |
| test := configCommandTest{ |
| args: []string{"set", "clusters.another-cluster.certificate-authority-data", "Y2FkYXRh"}, |
| startingConfig: startingConfig, |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestUnsetBytes(t *testing.T) { |
| clusterInfoWithCAData := clientcmdapi.NewCluster() |
| clusterInfoWithCAData.CertificateAuthorityData = []byte("cadata") |
| |
| startingConfig := newRedFederalCowHammerConfig() |
| startingConfig.Clusters["another-cluster"] = clusterInfoWithCAData |
| |
| expectedConfig := newRedFederalCowHammerConfig() |
| expectedConfig.Clusters["another-cluster"] = clientcmdapi.NewCluster() |
| |
| test := configCommandTest{ |
| args: []string{"unset", "clusters.another-cluster.certificate-authority-data"}, |
| startingConfig: startingConfig, |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestCAClearsInsecure(t *testing.T) { |
| fakeCAFile, _ := ioutil.TempFile("", "ca-file") |
| defer os.Remove(fakeCAFile.Name()) |
| clusterInfoWithInsecure := clientcmdapi.NewCluster() |
| clusterInfoWithInsecure.InsecureSkipTLSVerify = true |
| |
| clusterInfoWithCA := clientcmdapi.NewCluster() |
| clusterInfoWithCA.CertificateAuthority = path.Base(fakeCAFile.Name()) |
| |
| startingConfig := newRedFederalCowHammerConfig() |
| startingConfig.Clusters["another-cluster"] = clusterInfoWithInsecure |
| |
| expectedConfig := newRedFederalCowHammerConfig() |
| expectedConfig.Clusters["another-cluster"] = clusterInfoWithCA |
| |
| test := configCommandTest{ |
| args: []string{"set-cluster", "another-cluster", "--" + clientcmd.FlagCAFile + "=" + fakeCAFile.Name()}, |
| startingConfig: startingConfig, |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestCAClearsCAData(t *testing.T) { |
| clusterInfoWithCAData := clientcmdapi.NewCluster() |
| clusterInfoWithCAData.CertificateAuthorityData = []byte("cadata") |
| |
| clusterInfoWithCA := clientcmdapi.NewCluster() |
| clusterInfoWithCA.CertificateAuthority = "/cafile" |
| |
| startingConfig := newRedFederalCowHammerConfig() |
| startingConfig.Clusters["another-cluster"] = clusterInfoWithCAData |
| |
| expectedConfig := newRedFederalCowHammerConfig() |
| expectedConfig.Clusters["another-cluster"] = clusterInfoWithCA |
| |
| test := configCommandTest{ |
| args: []string{"set-cluster", "another-cluster", "--" + clientcmd.FlagCAFile + "=/cafile", "--" + clientcmd.FlagInsecure + "=false"}, |
| startingConfig: startingConfig, |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestInsecureClearsCA(t *testing.T) { |
| clusterInfoWithInsecure := clientcmdapi.NewCluster() |
| clusterInfoWithInsecure.InsecureSkipTLSVerify = true |
| |
| clusterInfoWithCA := clientcmdapi.NewCluster() |
| clusterInfoWithCA.CertificateAuthority = "cafile" |
| clusterInfoWithCA.CertificateAuthorityData = []byte("cadata") |
| |
| startingConfig := newRedFederalCowHammerConfig() |
| startingConfig.Clusters["another-cluster"] = clusterInfoWithCA |
| |
| expectedConfig := newRedFederalCowHammerConfig() |
| expectedConfig.Clusters["another-cluster"] = clusterInfoWithInsecure |
| |
| test := configCommandTest{ |
| args: []string{"set-cluster", "another-cluster", "--" + clientcmd.FlagInsecure + "=true"}, |
| startingConfig: startingConfig, |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestCADataClearsCA(t *testing.T) { |
| fakeCAFile, _ := ioutil.TempFile("", "") |
| defer os.Remove(fakeCAFile.Name()) |
| fakeData := []byte("cadata") |
| ioutil.WriteFile(fakeCAFile.Name(), fakeData, 0600) |
| |
| clusterInfoWithCAData := clientcmdapi.NewCluster() |
| clusterInfoWithCAData.CertificateAuthorityData = fakeData |
| |
| clusterInfoWithCA := clientcmdapi.NewCluster() |
| clusterInfoWithCA.CertificateAuthority = "cafile" |
| |
| startingConfig := newRedFederalCowHammerConfig() |
| startingConfig.Clusters["another-cluster"] = clusterInfoWithCA |
| |
| expectedConfig := newRedFederalCowHammerConfig() |
| expectedConfig.Clusters["another-cluster"] = clusterInfoWithCAData |
| |
| test := configCommandTest{ |
| args: []string{"set-cluster", "another-cluster", "--" + clientcmd.FlagCAFile + "=" + fakeCAFile.Name(), "--" + clientcmd.FlagEmbedCerts + "=true"}, |
| startingConfig: startingConfig, |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestEmbedNoCADisallowed(t *testing.T) { |
| expectedConfig := newRedFederalCowHammerConfig() |
| test := configCommandTest{ |
| args: []string{"set-cluster", "another-cluster", "--" + clientcmd.FlagEmbedCerts + "=true"}, |
| startingConfig: newRedFederalCowHammerConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| func() { |
| defer func() { |
| // Restore cmdutil behavior. |
| cmdutil.DefaultBehaviorOnFatal() |
| }() |
| |
| // Check exit code. |
| cmdutil.BehaviorOnFatal(func(e string, code int) { |
| if code != 1 { |
| t.Errorf("The exit code is %d, expected 1", code) |
| } |
| |
| expectedOutputs := []string{"--certificate-authority", "embed"} |
| test.checkOutput(e, expectedOutputs, t) |
| }) |
| |
| test.run(t) |
| }() |
| } |
| |
| func TestCAAndInsecureDisallowed(t *testing.T) { |
| test := configCommandTest{ |
| args: []string{"set-cluster", "another-cluster", "--" + clientcmd.FlagCAFile + "=cafile", "--" + clientcmd.FlagInsecure + "=true"}, |
| startingConfig: newRedFederalCowHammerConfig(), |
| expectedConfig: newRedFederalCowHammerConfig(), |
| } |
| |
| func() { |
| defer func() { |
| // Restore cmdutil behavior. |
| cmdutil.DefaultBehaviorOnFatal() |
| }() |
| |
| // Check exit code. |
| cmdutil.BehaviorOnFatal(func(e string, code int) { |
| if code != 1 { |
| t.Errorf("The exit code is %d, expected 1", code) |
| } |
| |
| expectedOutputs := []string{"certificate", "insecure"} |
| test.checkOutput(e, expectedOutputs, t) |
| }) |
| |
| test.run(t) |
| }() |
| } |
| |
| func TestMergeExistingAuth(t *testing.T) { |
| expectedConfig := newRedFederalCowHammerConfig() |
| authInfo := expectedConfig.AuthInfos["red-user"] |
| authInfo.ClientKey = "/key" |
| expectedConfig.AuthInfos["red-user"] = authInfo |
| test := configCommandTest{ |
| args: []string{"set-credentials", "red-user", "--" + clientcmd.FlagKeyFile + "=/key"}, |
| startingConfig: newRedFederalCowHammerConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestNewEmptyCluster(t *testing.T) { |
| expectedConfig := *clientcmdapi.NewConfig() |
| expectedConfig.Clusters["new-cluster"] = clientcmdapi.NewCluster() |
| test := configCommandTest{ |
| args: []string{"set-cluster", "new-cluster"}, |
| startingConfig: *clientcmdapi.NewConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestAdditionalCluster(t *testing.T) { |
| expectedConfig := newRedFederalCowHammerConfig() |
| cluster := clientcmdapi.NewCluster() |
| cluster.CertificateAuthority = "/ca-location" |
| cluster.InsecureSkipTLSVerify = false |
| cluster.Server = "serverlocation" |
| expectedConfig.Clusters["different-cluster"] = cluster |
| test := configCommandTest{ |
| args: []string{"set-cluster", "different-cluster", "--" + clientcmd.FlagAPIServer + "=serverlocation", "--" + clientcmd.FlagInsecure + "=false", "--" + clientcmd.FlagCAFile + "=/ca-location"}, |
| startingConfig: newRedFederalCowHammerConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestOverwriteExistingCluster(t *testing.T) { |
| expectedConfig := newRedFederalCowHammerConfig() |
| cluster := clientcmdapi.NewCluster() |
| cluster.Server = "serverlocation" |
| expectedConfig.Clusters["cow-cluster"] = cluster |
| |
| test := configCommandTest{ |
| args: []string{"set-cluster", "cow-cluster", "--" + clientcmd.FlagAPIServer + "=serverlocation"}, |
| startingConfig: newRedFederalCowHammerConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestNewEmptyContext(t *testing.T) { |
| expectedConfig := *clientcmdapi.NewConfig() |
| expectedConfig.Contexts["new-context"] = clientcmdapi.NewContext() |
| test := configCommandTest{ |
| args: []string{"set-context", "new-context"}, |
| startingConfig: *clientcmdapi.NewConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestAdditionalContext(t *testing.T) { |
| expectedConfig := newRedFederalCowHammerConfig() |
| context := clientcmdapi.NewContext() |
| context.Cluster = "some-cluster" |
| context.AuthInfo = "some-user" |
| context.Namespace = "different-namespace" |
| expectedConfig.Contexts["different-context"] = context |
| test := configCommandTest{ |
| args: []string{"set-context", "different-context", "--" + clientcmd.FlagClusterName + "=some-cluster", "--" + clientcmd.FlagAuthInfoName + "=some-user", "--" + clientcmd.FlagNamespace + "=different-namespace"}, |
| startingConfig: newRedFederalCowHammerConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestMergeExistingContext(t *testing.T) { |
| expectedConfig := newRedFederalCowHammerConfig() |
| context := expectedConfig.Contexts["federal-context"] |
| context.Namespace = "hammer" |
| expectedConfig.Contexts["federal-context"] = context |
| |
| test := configCommandTest{ |
| args: []string{"set-context", "federal-context", "--" + clientcmd.FlagNamespace + "=hammer"}, |
| startingConfig: newRedFederalCowHammerConfig(), |
| expectedConfig: expectedConfig, |
| } |
| |
| test.run(t) |
| } |
| |
| func TestToBool(t *testing.T) { |
| type test struct { |
| in string |
| out bool |
| err string |
| } |
| |
| tests := []test{ |
| {"", false, ""}, |
| {"true", true, ""}, |
| {"on", false, `strconv.ParseBool: parsing "on": invalid syntax`}, |
| } |
| |
| for _, curr := range tests { |
| b, err := toBool(curr.in) |
| if (len(curr.err) != 0) && err == nil { |
| t.Errorf("Expected error: %v, but got nil", curr.err) |
| } |
| if (len(curr.err) == 0) && err != nil { |
| t.Errorf("Unexpected error: %v", err) |
| } |
| if (err != nil) && (err.Error() != curr.err) { |
| t.Errorf("Expected %v, got %v", curr.err, err) |
| |
| } |
| if b != curr.out { |
| t.Errorf("Expected %v, got %v", curr.out, b) |
| } |
| } |
| |
| } |
| |
| func testConfigCommand(args []string, startingConfig clientcmdapi.Config, t *testing.T) (string, clientcmdapi.Config) { |
| fakeKubeFile, _ := ioutil.TempFile("", "") |
| defer os.Remove(fakeKubeFile.Name()) |
| err := clientcmd.WriteToFile(startingConfig, fakeKubeFile.Name()) |
| if err != nil { |
| t.Fatalf("unexpected error: %v", err) |
| } |
| |
| argsToUse := make([]string, 0, 2+len(args)) |
| argsToUse = append(argsToUse, "--kubeconfig="+fakeKubeFile.Name()) |
| argsToUse = append(argsToUse, args...) |
| |
| streams, _, buf, _ := genericclioptions.NewTestIOStreams() |
| cmd := NewCmdConfig(cmdutil.NewFactory(genericclioptions.NewTestConfigFlags()), clientcmd.NewDefaultPathOptions(), streams) |
| // "context" is a global flag, inherited from base kubectl command in the real world |
| cmd.PersistentFlags().String("context", "", "The name of the kubeconfig context to use") |
| cmd.SetArgs(argsToUse) |
| cmd.Execute() |
| |
| config := clientcmd.GetConfigFromFileOrDie(fakeKubeFile.Name()) |
| return buf.String(), *config |
| } |
| |
| type configCommandTest struct { |
| args []string |
| startingConfig clientcmdapi.Config |
| expectedConfig clientcmdapi.Config |
| expectedOutputs []string |
| } |
| |
| func (test configCommandTest) checkOutput(out string, expectedOutputs []string, t *testing.T) { |
| for _, expectedOutput := range expectedOutputs { |
| if !strings.Contains(out, expectedOutput) { |
| t.Errorf("expected '%s' in output, got '%s'", expectedOutput, out) |
| } |
| } |
| } |
| |
| func (test configCommandTest) run(t *testing.T) string { |
| out, actualConfig := testConfigCommand(test.args, test.startingConfig, t) |
| |
| testSetNilMapsToEmpties(reflect.ValueOf(&test.expectedConfig)) |
| testSetNilMapsToEmpties(reflect.ValueOf(&actualConfig)) |
| testClearLocationOfOrigin(&actualConfig) |
| |
| if !apiequality.Semantic.DeepEqual(test.expectedConfig, actualConfig) { |
| t.Errorf("diff: %v", diff.ObjectDiff(test.expectedConfig, actualConfig)) |
| t.Errorf("expected: %#v\n actual: %#v", test.expectedConfig, actualConfig) |
| } |
| |
| test.checkOutput(out, test.expectedOutputs, t) |
| |
| return out |
| } |
| func testClearLocationOfOrigin(config *clientcmdapi.Config) { |
| for key, obj := range config.AuthInfos { |
| obj.LocationOfOrigin = "" |
| config.AuthInfos[key] = obj |
| } |
| for key, obj := range config.Clusters { |
| obj.LocationOfOrigin = "" |
| config.Clusters[key] = obj |
| } |
| for key, obj := range config.Contexts { |
| obj.LocationOfOrigin = "" |
| config.Contexts[key] = obj |
| } |
| } |
| func testSetNilMapsToEmpties(curr reflect.Value) { |
| actualCurrValue := curr |
| if curr.Kind() == reflect.Ptr { |
| actualCurrValue = curr.Elem() |
| } |
| |
| switch actualCurrValue.Kind() { |
| case reflect.Map: |
| for _, mapKey := range actualCurrValue.MapKeys() { |
| currMapValue := actualCurrValue.MapIndex(mapKey) |
| testSetNilMapsToEmpties(currMapValue) |
| } |
| |
| case reflect.Struct: |
| for fieldIndex := 0; fieldIndex < actualCurrValue.NumField(); fieldIndex++ { |
| currFieldValue := actualCurrValue.Field(fieldIndex) |
| |
| if currFieldValue.Kind() == reflect.Map && currFieldValue.IsNil() { |
| newValue := reflect.MakeMap(currFieldValue.Type()) |
| currFieldValue.Set(newValue) |
| } else { |
| testSetNilMapsToEmpties(currFieldValue.Addr()) |
| } |
| } |
| |
| } |
| |
| } |