Merge pull request #1160 from r2d4/kubeconfig-tests
Add test coverage for SetupKubeConfigpull/1169/head
commit
b78fb926bc
|
@ -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")
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue