Merge pull request #1160 from r2d4/kubeconfig-tests

Add test coverage for SetupKubeConfig
pull/1169/head
Matt Rickard 2017-02-22 13:25:54 -08:00 committed by GitHub
commit b78fb926bc
3 changed files with 190 additions and 62 deletions

View File

@ -29,7 +29,7 @@ import (
"github.com/golang/glog"
"github.com/spf13/cobra"
"github.com/spf13/viper"
cfg "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
cmdUtil "k8s.io/minikube/cmd/util"
"k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/constants"
@ -161,18 +161,31 @@ func runStart(cmd *cobra.Command, args []string) {
fmt.Println("Setting up kubeconfig...")
// setup kubeconfig
keepContext := viper.GetBool(keepContext)
name := constants.MinikubeContext
certAuth := constants.MakeMiniPath("ca.crt")
clientCert := constants.MakeMiniPath("apiserver.crt")
clientKey := constants.MakeMiniPath("apiserver.key")
if err := setupKubeconfig(name, kubeHost, certAuth, clientCert, clientKey, keepContext); err != nil {
kubeConfigEnv := os.Getenv(constants.KubeconfigEnvVar)
var kubeConfigFile string
if kubeConfigEnv == "" {
kubeConfigFile = constants.KubeconfigPath
} else {
kubeConfigFile = filepath.SplitList(kubeConfigEnv)[0]
}
kubeCfgSetup := &kubeconfig.KubeConfigSetup{
ClusterName: constants.MinikubeContext,
ClusterServerAddress: kubeHost,
ClientCertificate: constants.MakeMiniPath("apiserver.crt"),
ClientKey: constants.MakeMiniPath("apiserver.key"),
CertificateAuthority: constants.MakeMiniPath("ca.crt"),
KeepContext: viper.GetBool(keepContext),
KubeConfigFile: kubeConfigFile,
}
if err := kubeconfig.SetupKubeConfig(kubeCfgSetup); err != nil {
glog.Errorln("Error setting up kubeconfig: ", err)
cmdUtil.MaybeReportErrorAndExit(err)
}
if keepContext {
fmt.Printf("The local Kubernetes cluster has started. The kubectl context has not been altered, kubectl will require \"--context=%s\" to use the local Kubernetes cluster.\n", name)
if kubeCfgSetup.KeepContext {
fmt.Printf("The local Kubernetes cluster has started. The kubectl context has not been altered, kubectl will require \"--context=%s\" to use the local Kubernetes cluster.\n", kubeCfgSetup.ClusterName)
} else {
fmt.Println("Kubectl is now configured to use the cluster.")
}
@ -186,59 +199,6 @@ func calculateDiskSizeInMB(humanReadableDiskSize string) int {
return int(diskSize / units.MB)
}
// setupKubeconfig reads config from disk, adds the minikube settings, and writes it back.
// activeContext is true when minikube is the CurrentContext
// If no CurrentContext is set, the given name will be used.
func setupKubeconfig(name, server, certAuth, cliCert, cliKey string, keepContext bool) error {
configEnv := os.Getenv(constants.KubeconfigEnvVar)
var configFile string
if configEnv == "" {
configFile = constants.KubeconfigPath
} else {
configFile = filepath.SplitList(configEnv)[0]
}
glog.Infoln("Using kubeconfig: ", configFile)
// read existing config or create new if does not exist
config, err := kubeconfig.ReadConfigOrNew(configFile)
if err != nil {
return err
}
clusterName := name
cluster := cfg.NewCluster()
cluster.Server = server
cluster.CertificateAuthority = certAuth
config.Clusters[clusterName] = cluster
// user
userName := name
user := cfg.NewAuthInfo()
user.ClientCertificate = cliCert
user.ClientKey = cliKey
config.AuthInfos[userName] = user
// context
contextName := name
context := cfg.NewContext()
context.Cluster = clusterName
context.AuthInfo = userName
config.Contexts[contextName] = context
// Only set current context to minikube if the user has not used the keepContext flag
if !keepContext {
config.CurrentContext = contextName
}
// write back to disk
if err := kubeconfig.WriteConfig(config, configFile); err != nil {
return err
}
return nil
}
func init() {
startCmd.Flags().Bool(keepContext, constants.DefaultKeepContext, "This will keep the existing kubectl context and will create a minikube context.")
startCmd.Flags().String(isoURL, constants.DefaultIsoUrl, "Location of the minikube iso")

View File

@ -28,6 +28,73 @@ import (
"k8s.io/kubernetes/pkg/runtime"
)
type KubeConfigSetup struct {
// The name of the cluster for this context
ClusterName string
// ClusterServerAddress is the address of of the kubernetes cluster
ClusterServerAddress string
// ClientCertificate is the path to a client cert file for TLS.
ClientCertificate string
// CertificateAuthority is the path to a cert file for the certificate authority.
CertificateAuthority string
// ClientKey is the path to a client key file for TLS.
ClientKey string
// Should the current context be kept when setting up this one
KeepContext bool
// KubeConfigFile is the path where the kube config is stored
KubeConfigFile string
}
// SetupKubeconfig reads config from disk, adds the minikube settings, and writes it back.
// activeContext is true when minikube is the CurrentContext
// If no CurrentContext is set, the given name will be used.
func SetupKubeConfig(cfg *KubeConfigSetup) error {
glog.Infoln("Using kubeconfig: ", cfg.KubeConfigFile)
// read existing config or create new if does not exist
config, err := ReadConfigOrNew(cfg.KubeConfigFile)
if err != nil {
return err
}
clusterName := cfg.ClusterName
cluster := api.NewCluster()
cluster.Server = cfg.ClusterServerAddress
cluster.CertificateAuthority = cfg.CertificateAuthority
config.Clusters[clusterName] = cluster
// user
userName := cfg.ClusterName
user := api.NewAuthInfo()
user.ClientCertificate = cfg.ClientCertificate
user.ClientKey = cfg.ClientKey
config.AuthInfos[userName] = user
// context
contextName := cfg.ClusterName
context := api.NewContext()
context.Cluster = cfg.ClusterName
context.AuthInfo = userName
config.Contexts[contextName] = context
// Only set current context to minikube if the user has not used the keepContext flag
if !cfg.KeepContext {
config.CurrentContext = contextName
}
// write back to disk
if err := WriteConfig(config, cfg.KubeConfigFile); err != nil {
return err
}
return nil
}
// ReadConfigOrNew retrieves Kubernetes client configuration from a file.
// If no files exists, an empty configuration is returned.
func ReadConfigOrNew(filename string) (*api.Config, error) {

View File

@ -27,6 +27,107 @@ import (
"k8s.io/minikube/pkg/minikube/constants"
)
var fakeKubeCfg = []byte(`
apiVersion: v1
clusters:
- cluster:
certificate-authority: /home/la-croix/apiserver.crt
server: 192.168.1.1:8080
name: la-croix
contexts:
- context:
cluster: la-croix
user: la-croix
name: la-croix
current-context: la-croix
kind: Config
preferences: {}
users:
- name: la-croix
user:
client-certificate: /home/la-croix/apiserver.crt
client-key: /home/la-croix/apiserver.key
`)
func TestSetupKubeConfig(t *testing.T) {
setupCfg := &KubeConfigSetup{
ClusterName: "test",
ClusterServerAddress: "192.168.1.1:8080",
ClientCertificate: "/home/apiserver.crt",
ClientKey: "/home/apiserver.key",
CertificateAuthority: "/home/apiserver.crt",
KeepContext: false,
}
var tests = []struct {
description string
cfg *KubeConfigSetup
existingCfg []byte
expected api.Config
err bool
}{
{
description: "new kube config",
cfg: setupCfg,
},
{
description: "add to kube config",
cfg: setupCfg,
existingCfg: fakeKubeCfg,
},
{
description: "use config env var",
cfg: setupCfg,
},
{
description: "keep context",
cfg: &KubeConfigSetup{
ClusterName: "test",
ClusterServerAddress: "192.168.1.1:8080",
ClientCertificate: "/home/apiserver.crt",
ClientKey: "/home/apiserver.key",
CertificateAuthority: "/home/apiserver.crt",
KeepContext: true,
},
existingCfg: fakeKubeCfg,
},
}
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
t.Parallel()
tmpDir, err := ioutil.TempDir("", "")
if err != nil {
t.Fatalf("Error making temp directory %s", err)
}
test.cfg.KubeConfigFile = filepath.Join(tmpDir, "kubeconfig")
if len(test.existingCfg) != 0 {
ioutil.WriteFile(test.cfg.KubeConfigFile, test.existingCfg, 0600)
}
err = SetupKubeConfig(test.cfg)
if err != nil && !test.err {
t.Errorf("Got unexpected error: %s", err)
}
if err == nil && test.err {
t.Errorf("Expected error but got none")
}
config, err := ReadConfigOrNew(test.cfg.KubeConfigFile)
if err != nil {
t.Errorf("Error reading kubeconfig file: %s", err)
}
if test.cfg.KeepContext && config.CurrentContext == test.cfg.ClusterName {
t.Errorf("Context was changed even though KeepContext was true")
}
if !test.cfg.KeepContext && config.CurrentContext != test.cfg.ClusterName {
t.Errorf("Context was not switched")
}
os.RemoveAll(tmpDir)
})
}
}
func TestEmptyConfig(t *testing.T) {
tmp := tempFile(t, []byte{})
defer os.Remove(tmp)