mirror of https://github.com/k3s-io/k3s
950 lines
28 KiB
Go
950 lines
28 KiB
Go
/*
|
|
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())
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|