mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-11-04 07:49:35 +00:00 
			
		
		
		
	This commit moves away from using a global variable for default configuration checking, and instead exposes a method on LoadingRules to determine whether a particular restclient.Config should be considered "default". This allows kubectl to provide its own defaults (the same as before, KUBERNETES_MASTER and the static localhost:8080 values) while allowing other clients to avoid defining them. In-cluster config defaulting is now easier to read.
		
			
				
	
	
		
			392 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			392 lines
		
	
	
		
			11 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 clientcmd
 | 
						|
 | 
						|
import (
 | 
						|
	"io/ioutil"
 | 
						|
	"os"
 | 
						|
	"reflect"
 | 
						|
	"strings"
 | 
						|
	"testing"
 | 
						|
 | 
						|
	"github.com/imdario/mergo"
 | 
						|
	clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
 | 
						|
)
 | 
						|
 | 
						|
func TestOldMergoLib(t *testing.T) {
 | 
						|
	type T struct {
 | 
						|
		X string
 | 
						|
	}
 | 
						|
	dst := T{X: "one"}
 | 
						|
	src := T{X: "two"}
 | 
						|
	mergo.Merge(&dst, &src)
 | 
						|
	if dst.X != "two" {
 | 
						|
		// mergo.Merge changed in an incompatible way with
 | 
						|
		//
 | 
						|
		//   https://github.com/imdario/mergo/commit/d304790b2ed594794496464fadd89d2bb266600a
 | 
						|
		//
 | 
						|
		// We have to stay with the old version which still does eager
 | 
						|
		// copying from src to dst in structs.
 | 
						|
		t.Errorf("mergo.Merge library found with incompatible, new behavior")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func createValidTestConfig() *clientcmdapi.Config {
 | 
						|
	const (
 | 
						|
		server = "https://anything.com:8080"
 | 
						|
		token  = "the-token"
 | 
						|
	)
 | 
						|
 | 
						|
	config := clientcmdapi.NewConfig()
 | 
						|
	config.Clusters["clean"] = &clientcmdapi.Cluster{
 | 
						|
		Server: server,
 | 
						|
	}
 | 
						|
	config.AuthInfos["clean"] = &clientcmdapi.AuthInfo{
 | 
						|
		Token: token,
 | 
						|
	}
 | 
						|
	config.Contexts["clean"] = &clientcmdapi.Context{
 | 
						|
		Cluster:  "clean",
 | 
						|
		AuthInfo: "clean",
 | 
						|
	}
 | 
						|
	config.CurrentContext = "clean"
 | 
						|
 | 
						|
	return config
 | 
						|
}
 | 
						|
 | 
						|
func createCAValidTestConfig() *clientcmdapi.Config {
 | 
						|
 | 
						|
	config := createValidTestConfig()
 | 
						|
	config.Clusters["clean"].CertificateAuthorityData = []byte{0, 0}
 | 
						|
	return config
 | 
						|
}
 | 
						|
 | 
						|
func TestInsecureOverridesCA(t *testing.T) {
 | 
						|
	config := createCAValidTestConfig()
 | 
						|
	clientBuilder := NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{
 | 
						|
		ClusterInfo: clientcmdapi.Cluster{
 | 
						|
			InsecureSkipTLSVerify: true,
 | 
						|
		},
 | 
						|
	}, nil)
 | 
						|
 | 
						|
	actualCfg, err := clientBuilder.ClientConfig()
 | 
						|
	if err != nil {
 | 
						|
		t.Errorf("Unexpected error: %v", err)
 | 
						|
	}
 | 
						|
 | 
						|
	matchBoolArg(true, actualCfg.Insecure, t)
 | 
						|
	matchStringArg("", actualCfg.TLSClientConfig.CAFile, t)
 | 
						|
	matchByteArg(nil, actualCfg.TLSClientConfig.CAData, t)
 | 
						|
}
 | 
						|
 | 
						|
func TestMergeContext(t *testing.T) {
 | 
						|
	const namespace = "overriden-namespace"
 | 
						|
 | 
						|
	config := createValidTestConfig()
 | 
						|
	clientBuilder := NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{}, nil)
 | 
						|
 | 
						|
	_, overridden, err := clientBuilder.Namespace()
 | 
						|
	if err != nil {
 | 
						|
		t.Errorf("Unexpected error: %v", err)
 | 
						|
	}
 | 
						|
 | 
						|
	if overridden {
 | 
						|
		t.Error("Expected namespace to not be overridden")
 | 
						|
	}
 | 
						|
 | 
						|
	clientBuilder = NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{
 | 
						|
		Context: clientcmdapi.Context{
 | 
						|
			Namespace: namespace,
 | 
						|
		},
 | 
						|
	}, nil)
 | 
						|
 | 
						|
	actual, overridden, err := clientBuilder.Namespace()
 | 
						|
	if err != nil {
 | 
						|
		t.Errorf("Unexpected error: %v", err)
 | 
						|
	}
 | 
						|
 | 
						|
	if !overridden {
 | 
						|
		t.Error("Expected namespace to be overridden")
 | 
						|
	}
 | 
						|
 | 
						|
	matchStringArg(namespace, actual, t)
 | 
						|
}
 | 
						|
 | 
						|
func TestCertificateData(t *testing.T) {
 | 
						|
	caData := []byte("ca-data")
 | 
						|
	certData := []byte("cert-data")
 | 
						|
	keyData := []byte("key-data")
 | 
						|
 | 
						|
	config := clientcmdapi.NewConfig()
 | 
						|
	config.Clusters["clean"] = &clientcmdapi.Cluster{
 | 
						|
		Server: "https://localhost:8443",
 | 
						|
		CertificateAuthorityData: caData,
 | 
						|
	}
 | 
						|
	config.AuthInfos["clean"] = &clientcmdapi.AuthInfo{
 | 
						|
		ClientCertificateData: certData,
 | 
						|
		ClientKeyData:         keyData,
 | 
						|
	}
 | 
						|
	config.Contexts["clean"] = &clientcmdapi.Context{
 | 
						|
		Cluster:  "clean",
 | 
						|
		AuthInfo: "clean",
 | 
						|
	}
 | 
						|
	config.CurrentContext = "clean"
 | 
						|
 | 
						|
	clientBuilder := NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{}, nil)
 | 
						|
 | 
						|
	clientConfig, err := clientBuilder.ClientConfig()
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("Unexpected error: %v", err)
 | 
						|
	}
 | 
						|
 | 
						|
	// Make sure cert data gets into config (will override file paths)
 | 
						|
	matchByteArg(caData, clientConfig.TLSClientConfig.CAData, t)
 | 
						|
	matchByteArg(certData, clientConfig.TLSClientConfig.CertData, t)
 | 
						|
	matchByteArg(keyData, clientConfig.TLSClientConfig.KeyData, t)
 | 
						|
}
 | 
						|
 | 
						|
func TestBasicAuthData(t *testing.T) {
 | 
						|
	username := "myuser"
 | 
						|
	password := "mypass"
 | 
						|
 | 
						|
	config := clientcmdapi.NewConfig()
 | 
						|
	config.Clusters["clean"] = &clientcmdapi.Cluster{
 | 
						|
		Server: "https://localhost:8443",
 | 
						|
	}
 | 
						|
	config.AuthInfos["clean"] = &clientcmdapi.AuthInfo{
 | 
						|
		Username: username,
 | 
						|
		Password: password,
 | 
						|
	}
 | 
						|
	config.Contexts["clean"] = &clientcmdapi.Context{
 | 
						|
		Cluster:  "clean",
 | 
						|
		AuthInfo: "clean",
 | 
						|
	}
 | 
						|
	config.CurrentContext = "clean"
 | 
						|
 | 
						|
	clientBuilder := NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{}, nil)
 | 
						|
 | 
						|
	clientConfig, err := clientBuilder.ClientConfig()
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("Unexpected error: %v", err)
 | 
						|
	}
 | 
						|
 | 
						|
	// Make sure basic auth data gets into config
 | 
						|
	matchStringArg(username, clientConfig.Username, t)
 | 
						|
	matchStringArg(password, clientConfig.Password, t)
 | 
						|
}
 | 
						|
 | 
						|
func TestBasicTokenFile(t *testing.T) {
 | 
						|
	token := "exampletoken"
 | 
						|
	f, err := ioutil.TempFile("", "tokenfile")
 | 
						|
	if err != nil {
 | 
						|
		t.Errorf("Unexpected error: %v", err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	defer os.Remove(f.Name())
 | 
						|
	if err := ioutil.WriteFile(f.Name(), []byte(token), 0644); err != nil {
 | 
						|
		t.Errorf("Unexpected error: %v", err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	config := clientcmdapi.NewConfig()
 | 
						|
	config.Clusters["clean"] = &clientcmdapi.Cluster{
 | 
						|
		Server: "https://localhost:8443",
 | 
						|
	}
 | 
						|
	config.AuthInfos["clean"] = &clientcmdapi.AuthInfo{
 | 
						|
		TokenFile: f.Name(),
 | 
						|
	}
 | 
						|
	config.Contexts["clean"] = &clientcmdapi.Context{
 | 
						|
		Cluster:  "clean",
 | 
						|
		AuthInfo: "clean",
 | 
						|
	}
 | 
						|
	config.CurrentContext = "clean"
 | 
						|
 | 
						|
	clientBuilder := NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{}, nil)
 | 
						|
 | 
						|
	clientConfig, err := clientBuilder.ClientConfig()
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("Unexpected error: %v", err)
 | 
						|
	}
 | 
						|
 | 
						|
	matchStringArg(token, clientConfig.BearerToken, t)
 | 
						|
}
 | 
						|
 | 
						|
func TestPrecedenceTokenFile(t *testing.T) {
 | 
						|
	token := "exampletoken"
 | 
						|
	f, err := ioutil.TempFile("", "tokenfile")
 | 
						|
	if err != nil {
 | 
						|
		t.Errorf("Unexpected error: %v", err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	defer os.Remove(f.Name())
 | 
						|
	if err := ioutil.WriteFile(f.Name(), []byte(token), 0644); err != nil {
 | 
						|
		t.Errorf("Unexpected error: %v", err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	config := clientcmdapi.NewConfig()
 | 
						|
	config.Clusters["clean"] = &clientcmdapi.Cluster{
 | 
						|
		Server: "https://localhost:8443",
 | 
						|
	}
 | 
						|
	expectedToken := "expected"
 | 
						|
	config.AuthInfos["clean"] = &clientcmdapi.AuthInfo{
 | 
						|
		Token:     expectedToken,
 | 
						|
		TokenFile: f.Name(),
 | 
						|
	}
 | 
						|
	config.Contexts["clean"] = &clientcmdapi.Context{
 | 
						|
		Cluster:  "clean",
 | 
						|
		AuthInfo: "clean",
 | 
						|
	}
 | 
						|
	config.CurrentContext = "clean"
 | 
						|
 | 
						|
	clientBuilder := NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{}, nil)
 | 
						|
 | 
						|
	clientConfig, err := clientBuilder.ClientConfig()
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("Unexpected error: %v", err)
 | 
						|
	}
 | 
						|
 | 
						|
	matchStringArg(expectedToken, clientConfig.BearerToken, t)
 | 
						|
}
 | 
						|
 | 
						|
func TestCreateClean(t *testing.T) {
 | 
						|
	config := createValidTestConfig()
 | 
						|
	clientBuilder := NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{}, nil)
 | 
						|
 | 
						|
	clientConfig, err := clientBuilder.ClientConfig()
 | 
						|
	if err != nil {
 | 
						|
		t.Errorf("Unexpected error: %v", err)
 | 
						|
	}
 | 
						|
 | 
						|
	matchStringArg(config.Clusters["clean"].Server, clientConfig.Host, t)
 | 
						|
	matchStringArg("", clientConfig.APIPath, t)
 | 
						|
	matchBoolArg(config.Clusters["clean"].InsecureSkipTLSVerify, clientConfig.Insecure, t)
 | 
						|
	matchStringArg(config.AuthInfos["clean"].Token, clientConfig.BearerToken, t)
 | 
						|
}
 | 
						|
 | 
						|
func TestCreateCleanWithPrefix(t *testing.T) {
 | 
						|
	tt := []struct {
 | 
						|
		server string
 | 
						|
		host   string
 | 
						|
	}{
 | 
						|
		{"https://anything.com:8080/foo/bar", "https://anything.com:8080/foo/bar"},
 | 
						|
		{"http://anything.com:8080/foo/bar", "http://anything.com:8080/foo/bar"},
 | 
						|
		{"http://anything.com:8080/foo/bar/", "http://anything.com:8080/foo/bar/"},
 | 
						|
		{"http://anything.com:8080/", "http://anything.com:8080/"},
 | 
						|
		{"http://anything.com:8080//", "http://anything.com:8080//"},
 | 
						|
		{"anything.com:8080/foo/bar", "anything.com:8080/foo/bar"},
 | 
						|
		{"anything.com:8080", "anything.com:8080"},
 | 
						|
		{"anything.com", "anything.com"},
 | 
						|
		{"anything", "anything"},
 | 
						|
	}
 | 
						|
 | 
						|
	tt = append(tt, struct{ server, host string }{"", "http://localhost:8080"})
 | 
						|
 | 
						|
	for _, tc := range tt {
 | 
						|
		config := createValidTestConfig()
 | 
						|
 | 
						|
		cleanConfig := config.Clusters["clean"]
 | 
						|
		cleanConfig.Server = tc.server
 | 
						|
		config.Clusters["clean"] = cleanConfig
 | 
						|
 | 
						|
		clientBuilder := NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{
 | 
						|
			ClusterDefaults: clientcmdapi.Cluster{Server: "http://localhost:8080"},
 | 
						|
		}, nil)
 | 
						|
 | 
						|
		clientConfig, err := clientBuilder.ClientConfig()
 | 
						|
		if err != nil {
 | 
						|
			t.Fatalf("Unexpected error: %v", err)
 | 
						|
		}
 | 
						|
 | 
						|
		matchStringArg(tc.host, clientConfig.Host, t)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestCreateCleanDefault(t *testing.T) {
 | 
						|
	config := createValidTestConfig()
 | 
						|
	clientBuilder := NewDefaultClientConfig(*config, &ConfigOverrides{})
 | 
						|
 | 
						|
	clientConfig, err := clientBuilder.ClientConfig()
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("Unexpected error: %v", err)
 | 
						|
	}
 | 
						|
 | 
						|
	matchStringArg(config.Clusters["clean"].Server, clientConfig.Host, t)
 | 
						|
	matchBoolArg(config.Clusters["clean"].InsecureSkipTLSVerify, clientConfig.Insecure, t)
 | 
						|
	matchStringArg(config.AuthInfos["clean"].Token, clientConfig.BearerToken, t)
 | 
						|
}
 | 
						|
 | 
						|
func TestCreateCleanDefaultCluster(t *testing.T) {
 | 
						|
	config := createValidTestConfig()
 | 
						|
	clientBuilder := NewDefaultClientConfig(*config, &ConfigOverrides{
 | 
						|
		ClusterDefaults: clientcmdapi.Cluster{Server: "http://localhost:8080"},
 | 
						|
	})
 | 
						|
 | 
						|
	clientConfig, err := clientBuilder.ClientConfig()
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("Unexpected error: %v", err)
 | 
						|
	}
 | 
						|
 | 
						|
	matchStringArg(config.Clusters["clean"].Server, clientConfig.Host, t)
 | 
						|
	matchBoolArg(config.Clusters["clean"].InsecureSkipTLSVerify, clientConfig.Insecure, t)
 | 
						|
	matchStringArg(config.AuthInfos["clean"].Token, clientConfig.BearerToken, t)
 | 
						|
}
 | 
						|
 | 
						|
func TestCreateMissingContextNoDefault(t *testing.T) {
 | 
						|
	const expectedErrorContains = "Context was not found for specified context"
 | 
						|
	config := createValidTestConfig()
 | 
						|
	clientBuilder := NewNonInteractiveClientConfig(*config, "not-present", &ConfigOverrides{}, nil)
 | 
						|
 | 
						|
	_, err := clientBuilder.ClientConfig()
 | 
						|
	if err == nil {
 | 
						|
		t.Fatalf("Unexpected error: %v", err)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestCreateMissingContext(t *testing.T) {
 | 
						|
	const expectedErrorContains = "context was not found for specified context: not-present"
 | 
						|
	config := createValidTestConfig()
 | 
						|
	clientBuilder := NewNonInteractiveClientConfig(*config, "not-present", &ConfigOverrides{
 | 
						|
		ClusterDefaults: clientcmdapi.Cluster{Server: "http://localhost:8080"},
 | 
						|
	}, nil)
 | 
						|
 | 
						|
	_, err := clientBuilder.ClientConfig()
 | 
						|
	if err == nil {
 | 
						|
		t.Fatalf("Expected error: %v", expectedErrorContains)
 | 
						|
	}
 | 
						|
	if !strings.Contains(err.Error(), expectedErrorContains) {
 | 
						|
		t.Fatalf("Expected error: %v, but got %v", expectedErrorContains, err)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func matchBoolArg(expected, got bool, t *testing.T) {
 | 
						|
	if expected != got {
 | 
						|
		t.Errorf("Expected %v, got %v", expected, got)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func matchStringArg(expected, got string, t *testing.T) {
 | 
						|
	if expected != got {
 | 
						|
		t.Errorf("Expected %q, got %q", expected, got)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func matchByteArg(expected, got []byte, t *testing.T) {
 | 
						|
	if !reflect.DeepEqual(expected, got) {
 | 
						|
		t.Errorf("Expected %v, got %v", expected, got)
 | 
						|
	}
 | 
						|
}
 |