提交 57781631 编写于 作者: A Abby Tisdale 提交者: Abby Tisdale

Added update-context and kubeconfig to status.

上级 baa724d7
......@@ -27,14 +27,16 @@ import (
cmdUtil "k8s.io/minikube/cmd/util"
"k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/constants"
kcfg "k8s.io/minikube/pkg/minikube/kubeconfig"
"k8s.io/minikube/pkg/minikube/machine"
)
var statusFormat string
type Status struct {
MinikubeStatus string
LocalkubeStatus string
MinikubeStatus string
LocalkubeStatus string
KubeconfigStatus string
}
// statusCmd represents the status command
......@@ -57,14 +59,32 @@ var statusCmd = &cobra.Command{
}
ls := state.None.String()
ks := state.None.String()
if ms == state.Running.String() {
ls, err = cluster.GetLocalkubeStatus(api)
if err != nil {
glog.Errorln("Error localkube status:", err)
cmdUtil.MaybeReportErrorAndExit(err)
}
ip, err := cluster.GetHostDriverIP(api)
if err != nil {
glog.Errorln("Error host driver ip status:", err)
cmdUtil.MaybeReportErrorAndExit(err)
}
kstatus, err := kcfg.GetKubeConfigStatus(ip, constants.KubeconfigPath)
if err != nil {
glog.Errorln("Error kubeconfig status:", err)
cmdUtil.MaybeReportErrorAndExit(err)
}
if kstatus {
ks = "Correctly Configured: pointing to minikube-vm at " + ip.String()
} else {
ks = "Misconfigured: pointing to stale minikube-vm." +
"\nTo fix the kubectl context, run minikube update-context"
}
}
status := Status{ms, ls}
status := Status{ms, ls, ks}
tmpl, err := template.New("status").Parse(statusFormat)
if err != nil {
......
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
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 cmd
import (
"fmt"
"os"
"github.com/golang/glog"
"github.com/spf13/cobra"
cmdUtil "k8s.io/minikube/cmd/util"
"k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/constants"
kcfg "k8s.io/minikube/pkg/minikube/kubeconfig"
"k8s.io/minikube/pkg/minikube/machine"
)
// updateContextCmd represents the update-context command
var updateContextCmd = &cobra.Command{
Use: "update-context",
Short: "Verify the IP address of the running cluster in kubeconfig.",
Long: `Retrieves the IP address of the running cluster, checks it
with IP in kubeconfig, and corrects kubeconfig if incorrect.`,
Run: func(cmd *cobra.Command, args []string) {
api, err := machine.NewAPIClient(clientType)
if err != nil {
fmt.Fprintf(os.Stderr, "Error getting client: %s\n", err)
os.Exit(1)
}
defer api.Close()
ip, err := cluster.GetHostDriverIP(api)
if err != nil {
glog.Errorln("Error host driver ip status:", err)
cmdUtil.MaybeReportErrorAndExit(err)
}
kstatus, err := kcfg.UpdateKubeconfigIP(ip, constants.KubeconfigPath)
if err != nil {
glog.Errorln("Error kubeconfig status:", err)
cmdUtil.MaybeReportErrorAndExit(err)
}
if kstatus {
fmt.Println("Reconfigured kubeconfig IP, now pointing at " + ip.String())
} else {
fmt.Println("Kubeconfig IP correctly configured, pointing at " + ip.String())
}
},
}
func init() {
RootCmd.AddCommand(updateContextCmd)
}
......@@ -165,6 +165,24 @@ func GetLocalkubeStatus(api libmachine.API) (string, error) {
}
}
// GetHostDriverIP gets the ip address of the current minikube cluster
func GetHostDriverIP(api libmachine.API) (net.IP, error) {
host, err := CheckIfApiExistsAndLoad(api)
if err != nil {
return nil, err
}
ipStr, err := host.Driver.GetIP()
if err != nil {
return nil, errors.Wrap(err, "Error getting IP")
}
ip := net.ParseIP(ipStr)
if ip == nil {
return nil, errors.Wrap(err, "Error parsing IP")
}
return ip, nil
}
// StartCluster starts a k8s cluster on the specified Host.
func StartCluster(api libmachine.API, kubernetesConfig KubernetesConfig) error {
h, err := CheckIfApiExistsAndLoad(api)
......
......@@ -90,7 +90,7 @@ const (
MinimumDiskSizeMB = 2000
DefaultVMDriver = "virtualbox"
DefaultStatusFormat = "minikube: {{.MinikubeStatus}}\n" +
"localkube: {{.LocalkubeStatus}}\n"
"localkube: {{.LocalkubeStatus}}\n" + "kubectl: {{.KubeconfigStatus}}\n"
DefaultAddonListFormat = "- {{.AddonName}}: {{.AddonStatus}}\n"
DefaultConfigViewFormat = "- {{.ConfigKey}}: {{.ConfigValue}}\n"
GithubMinikubeReleasesURL = "https://storage.googleapis.com/minikube/releases.json"
......
......@@ -17,9 +17,13 @@ limitations under the License.
package kubeconfig
import (
"fmt"
"io/ioutil"
"net"
"net/url"
"os"
"path/filepath"
"strconv"
"sync/atomic"
"github.com/golang/glog"
......@@ -27,6 +31,8 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/tools/clientcmd/api"
"k8s.io/client-go/tools/clientcmd/api/latest"
cfg "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/constants"
)
type KubeConfigSetup struct {
......@@ -178,3 +184,68 @@ func decode(data []byte) (*api.Config, error) {
return config.(*api.Config), nil
}
// GetKubeConfigStatus verifys the ip stored in kubeconfig.
func GetKubeConfigStatus(ip net.IP, filename string) (bool, error) {
if ip == nil {
return false, fmt.Errorf("Error, empty ip passed")
}
kip, err := getIPFromKubeConfig(filename)
if err != nil {
return false, err
}
if kip.Equal(ip) {
return true, nil
}
// Kubeconfig IP misconfigured
return false, nil
}
// UpdateKubeconfigIP overwrites the IP stored in kubeconfig with the provided IP.
func UpdateKubeconfigIP(ip net.IP, filename string) (bool, error) {
if ip == nil {
return false, fmt.Errorf("Error, empty ip passed")
}
kip, err := getIPFromKubeConfig(filename)
if err != nil {
return false, err
}
if kip.Equal(ip) {
return false, nil
}
con, err := ReadConfigOrNew(filename)
if err != nil {
return false, errors.Wrap(err, "Error getting kubeconfig status")
}
// Safe to lookup server because if field non-existent getIPFromKubeconfig would have given an error
con.Clusters[cfg.GetMachineName()].Server = "https://" + ip.String() + ":" + strconv.Itoa(constants.APIServerPort)
err = WriteConfig(con, filename)
if err != nil {
return false, err
}
// Kubeconfig IP reconfigured
return true, nil
}
// getIPFromKubeConfig returns the IP address stored for minikube in the kubeconfig specified
func getIPFromKubeConfig(filename string) (net.IP, error) {
con, err := ReadConfigOrNew(filename)
if err != nil {
return nil, errors.Wrap(err, "Error getting kubeconfig status")
}
cluster, ok := con.Clusters[cfg.GetMachineName()]
if !ok {
return nil, errors.Errorf("Kubeconfig does not have a record of the machine cluster")
}
kurl, err := url.Parse(cluster.Server)
if err != nil {
return net.ParseIP(cluster.Server), nil
}
kip, _, err := net.SplitHostPort(kurl.Host)
if err != nil {
return net.ParseIP(kurl.Host), nil
}
ip := net.ParseIP(kip)
return ip, nil
}
......@@ -18,6 +18,7 @@ package kubeconfig
import (
"io/ioutil"
"net"
"os"
"path/filepath"
"strconv"
......@@ -49,6 +50,50 @@ users:
client-key: /home/la-croix/apiserver.key
`)
var fakeKubeCfg2 = []byte(`
apiVersion: v1
clusters:
- cluster:
certificate-authority: /home/la-croix/apiserver.crt
server: https://192.168.10.100:8443
name: minikube
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
`)
var fakeKubeCfg3 = []byte(`
apiVersion: v1
clusters:
- cluster:
certificate-authority: /home/la-croix/apiserver.crt
server: https://192.168.1.1:8443
name: minikube
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",
......@@ -128,6 +173,116 @@ func TestSetupKubeConfig(t *testing.T) {
}
}
func TestGetKubeConfigStatus(t *testing.T) {
var tests = []struct {
description string
ip net.IP
existing []byte
err bool
status bool
}{
{
description: "empty ip",
ip: nil,
existing: fakeKubeCfg,
err: true,
},
{
description: "no minikube cluster",
ip: net.ParseIP("192.168.10.100"),
existing: fakeKubeCfg,
err: true,
},
{
description: "exactly matching ip",
ip: net.ParseIP("192.168.10.100"),
existing: fakeKubeCfg2,
status: true,
},
{
description: "different ips",
ip: net.ParseIP("192.168.10.100"),
existing: fakeKubeCfg3,
},
}
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
t.Parallel()
configFilename := tempFile(t, test.existing)
statusActual, err := GetKubeConfigStatus(test.ip, configFilename)
if err != nil && !test.err {
t.Errorf("Got unexpected error: %s", err)
}
if err == nil && test.err {
t.Errorf("Expected error but got none: %s", err)
}
if test.status != statusActual {
t.Errorf("Expected status %t, but got %t", test.status, statusActual)
}
})
}
}
func TestUpdateKubeconfigIP(t *testing.T) {
var tests = []struct {
description string
ip net.IP
existing []byte
err bool
status bool
expCfg []byte
}{
{
description: "empty ip",
ip: nil,
existing: fakeKubeCfg2,
err: true,
expCfg: fakeKubeCfg2,
},
{
description: "no minikube cluster",
ip: net.ParseIP("192.168.10.100"),
existing: fakeKubeCfg,
err: true,
expCfg: fakeKubeCfg,
},
{
description: "same IP",
ip: net.ParseIP("192.168.10.100"),
existing: fakeKubeCfg2,
expCfg: fakeKubeCfg2,
},
{
description: "different IP",
ip: net.ParseIP("192.168.10.100"),
existing: fakeKubeCfg3,
status: true,
expCfg: fakeKubeCfg2,
},
}
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
t.Parallel()
configFilename := tempFile(t, test.existing)
statusActual, err := UpdateKubeconfigIP(test.ip, configFilename)
if err != nil && !test.err {
t.Errorf("Got unexpected error: %s", err)
}
if err == nil && test.err {
t.Errorf("Expected error but got none: %s", err)
}
if test.status != statusActual {
t.Errorf("Expected status %t, but got %t", test.status, statusActual)
}
})
}
}
func TestEmptyConfig(t *testing.T) {
tmp := tempFile(t, []byte{})
defer os.Remove(tmp)
......@@ -178,6 +333,42 @@ func TestNewConfig(t *testing.T) {
}
}
func TestGetIPFromKubeConfig(t *testing.T) {
var tests = []struct {
description string
cfg []byte
ip net.IP
err bool
}{
{
description: "normal IP",
cfg: fakeKubeCfg2,
ip: net.ParseIP("192.168.10.100"),
},
{
description: "no minikube cluster",
cfg: fakeKubeCfg,
err: true,
},
}
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
configFilename := tempFile(t, test.cfg)
ip, err := getIPFromKubeConfig(configFilename)
if err != nil && !test.err {
t.Errorf("Got unexpected error: %s", err)
}
if err == nil && test.err {
t.Errorf("Expected error but got none: %s", err)
}
if !ip.Equal(test.ip) {
t.Errorf("IP returned: %s does not match ip given: %s", ip, test.ip)
}
})
}
}
// tempFile creates a temporary with the provided bytes as its contents.
// The caller is responsible for deleting file after use.
func tempFile(t *testing.T, data []byte) string {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册