Add paused state to apiserver status
parent
09b2780fb2
commit
e6999caea3
|
@ -23,8 +23,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/docker/machine/libmachine"
|
||||||
"github.com/docker/machine/libmachine/state"
|
"github.com/docker/machine/libmachine/state"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config"
|
cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config"
|
||||||
|
@ -40,16 +42,13 @@ import (
|
||||||
var statusFormat string
|
var statusFormat string
|
||||||
var output string
|
var output string
|
||||||
|
|
||||||
// KubeconfigStatus represents the kubeconfig status
|
const (
|
||||||
var KubeconfigStatus = struct {
|
// Additional states used by kubeconfig
|
||||||
Configured string
|
Configured = "Configured" // analagous to state.Saved
|
||||||
Misconfigured string
|
Misconfigured = "Misconfigured" // analagous to state.Error
|
||||||
}{
|
)
|
||||||
Configured: `Configured`,
|
|
||||||
Misconfigured: `Misconfigured`,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Status represents the status
|
// Status holds string representations of libmachine.state.State
|
||||||
type Status struct {
|
type Status struct {
|
||||||
Host string
|
Host string
|
||||||
Kubelet string
|
Kubelet string
|
||||||
|
@ -81,7 +80,6 @@ var statusCmd = &cobra.Command{
|
||||||
exit.UsageT("Cannot use both --output and --format options")
|
exit.UsageT("Cannot use both --output and --format options")
|
||||||
}
|
}
|
||||||
|
|
||||||
var returnCode = 0
|
|
||||||
api, err := machine.NewAPIClient()
|
api, err := machine.NewAPIClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exit.WithCodeT(exit.Unavailable, "Error getting client: {{.error}}", out.V{"error": err})
|
exit.WithCodeT(exit.Unavailable, "Error getting client: {{.error}}", out.V{"error": err})
|
||||||
|
@ -89,81 +87,91 @@ var statusCmd = &cobra.Command{
|
||||||
defer api.Close()
|
defer api.Close()
|
||||||
|
|
||||||
machineName := viper.GetString(config.MachineProfile)
|
machineName := viper.GetString(config.MachineProfile)
|
||||||
|
st, err := status(api, machineName)
|
||||||
hostSt, err := cluster.GetHostStatus(api, machineName)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exit.WithError("Error getting host status", err)
|
glog.Errorf("status error: %v", err)
|
||||||
}
|
|
||||||
|
|
||||||
kubeletSt := state.None.String()
|
|
||||||
kubeconfigSt := state.None.String()
|
|
||||||
apiserverSt := state.None.String()
|
|
||||||
|
|
||||||
if hostSt == state.Running.String() {
|
|
||||||
clusterBootstrapper, err := getClusterBootstrapper(api, viper.GetString(cmdcfg.Bootstrapper))
|
|
||||||
if err != nil {
|
|
||||||
exit.WithError("Error getting bootstrapper", err)
|
|
||||||
}
|
|
||||||
kubeletSt, err = clusterBootstrapper.GetKubeletStatus()
|
|
||||||
if err != nil {
|
|
||||||
glog.Warningf("kubelet err: %v", err)
|
|
||||||
returnCode |= clusterNotRunningStatusFlag
|
|
||||||
} else if kubeletSt != state.Running.String() {
|
|
||||||
returnCode |= clusterNotRunningStatusFlag
|
|
||||||
}
|
|
||||||
|
|
||||||
ip, err := cluster.GetHostDriverIP(api, machineName)
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorln("Error host driver ip status:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
apiserverPort, err := kubeconfig.Port(machineName)
|
|
||||||
if err != nil {
|
|
||||||
// Fallback to presuming default apiserver port
|
|
||||||
apiserverPort = constants.APIServerPort
|
|
||||||
}
|
|
||||||
|
|
||||||
apiserverSt, err = clusterBootstrapper.GetAPIServerStatus(ip, apiserverPort)
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorln("Error apiserver status:", err)
|
|
||||||
} else if apiserverSt != state.Running.String() {
|
|
||||||
returnCode |= clusterNotRunningStatusFlag
|
|
||||||
}
|
|
||||||
|
|
||||||
ks, err := kubeconfig.IsClusterInConfig(ip, machineName)
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorln("Error kubeconfig status:", err)
|
|
||||||
}
|
|
||||||
if ks {
|
|
||||||
kubeconfigSt = KubeconfigStatus.Configured
|
|
||||||
} else {
|
|
||||||
kubeconfigSt = KubeconfigStatus.Misconfigured
|
|
||||||
returnCode |= k8sNotRunningStatusFlag
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
returnCode |= minikubeNotRunningStatusFlag
|
|
||||||
}
|
|
||||||
|
|
||||||
status := Status{
|
|
||||||
Host: hostSt,
|
|
||||||
Kubelet: kubeletSt,
|
|
||||||
APIServer: apiserverSt,
|
|
||||||
Kubeconfig: kubeconfigSt,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch strings.ToLower(output) {
|
switch strings.ToLower(output) {
|
||||||
case "text":
|
case "text":
|
||||||
printStatusText(status)
|
printStatusText(st)
|
||||||
case "json":
|
case "json":
|
||||||
printStatusJSON(status)
|
printStatusJSON(st)
|
||||||
default:
|
default:
|
||||||
exit.WithCodeT(exit.BadUsage, fmt.Sprintf("invalid output format: %s. Valid values: 'text', 'json'", output))
|
exit.WithCodeT(exit.BadUsage, fmt.Sprintf("invalid output format: %s. Valid values: 'text', 'json'", output))
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Exit(returnCode)
|
os.Exit(exitCode(st))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func exitCode(st *Status) int {
|
||||||
|
c := 0
|
||||||
|
if st.Host != state.Running.String() {
|
||||||
|
c |= minikubeNotRunningStatusFlag
|
||||||
|
}
|
||||||
|
if st.APIServer != state.Running.String() || st.Kubelet != state.Running.String() {
|
||||||
|
c |= clusterNotRunningStatusFlag
|
||||||
|
}
|
||||||
|
if st.Kubeconfig != Configured {
|
||||||
|
c |= k8sNotRunningStatusFlag
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func status(api libmachine.API, name string) (*Status, error) {
|
||||||
|
st := &Status{}
|
||||||
|
hs, err := cluster.GetHostStatus(api, name)
|
||||||
|
if err != nil {
|
||||||
|
return st, errors.Wrap(err, "host")
|
||||||
|
}
|
||||||
|
st.Host = hs
|
||||||
|
if st.Host != state.Running.String() {
|
||||||
|
return st, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
bs, err := getClusterBootstrapper(api, viper.GetString(cmdcfg.Bootstrapper))
|
||||||
|
if err != nil {
|
||||||
|
return st, errors.Wrap(err, "bootstrapper")
|
||||||
|
}
|
||||||
|
|
||||||
|
st.Kubelet, err = bs.GetKubeletStatus()
|
||||||
|
if err != nil {
|
||||||
|
glog.Warningf("kubelet err: %v", err)
|
||||||
|
st.Kubelet = state.Error.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
ip, err := cluster.GetHostDriverIP(api, name)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorln("Error host driver ip status:", err)
|
||||||
|
st.APIServer = state.Error.String()
|
||||||
|
return st, err
|
||||||
|
}
|
||||||
|
|
||||||
|
port, err := kubeconfig.Port(name)
|
||||||
|
if err != nil {
|
||||||
|
glog.Warningf("unable to get port: %v", err)
|
||||||
|
port = constants.APIServerPort
|
||||||
|
}
|
||||||
|
|
||||||
|
st.APIServer, err = bs.GetAPIServerStatus(ip, port)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorln("Error apiserver status:", err)
|
||||||
|
st.APIServer = state.Error.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
ks, err := kubeconfig.IsClusterInConfig(ip, name)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorln("Error kubeconfig status:", err)
|
||||||
|
}
|
||||||
|
if ks {
|
||||||
|
st.Kubeconfig = Configured
|
||||||
|
} else {
|
||||||
|
st.Kubeconfig = Misconfigured
|
||||||
|
}
|
||||||
|
return st, nil
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
statusCmd.Flags().StringVarP(&statusFormat, "format", "f", defaultStatusFormat,
|
statusCmd.Flags().StringVarP(&statusFormat, "format", "f", defaultStatusFormat,
|
||||||
`Go template format string for the status output. The format for Go templates can be found here: https://golang.org/pkg/text/template/
|
`Go template format string for the status output. The format for Go templates can be found here: https://golang.org/pkg/text/template/
|
||||||
|
@ -172,25 +180,24 @@ For the list accessible variables for the template, see the struct values here:
|
||||||
`minikube status --output OUTPUT. json, text`)
|
`minikube status --output OUTPUT. json, text`)
|
||||||
}
|
}
|
||||||
|
|
||||||
var printStatusText = func(status Status) {
|
var printStatusText = func(st *Status) {
|
||||||
tmpl, err := template.New("status").Parse(statusFormat)
|
tmpl, err := template.New("status").Parse(statusFormat)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exit.WithError("Error creating status template", err)
|
exit.WithError("Error creating status template", err)
|
||||||
}
|
}
|
||||||
err = tmpl.Execute(os.Stdout, status)
|
err = tmpl.Execute(os.Stdout, st)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exit.WithError("Error executing status template", err)
|
exit.WithError("Error executing status template", err)
|
||||||
}
|
}
|
||||||
if status.Kubeconfig == KubeconfigStatus.Misconfigured {
|
if st.Kubeconfig == Misconfigured {
|
||||||
out.WarningT("Warning: Your kubectl is pointing to stale minikube-vm.\nTo fix the kubectl context, run `minikube update-context`")
|
out.WarningT("Warning: Your kubectl is pointing to stale minikube-vm.\nTo fix the kubectl context, run `minikube update-context`")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var printStatusJSON = func(status Status) {
|
var printStatusJSON = func(st *Status) {
|
||||||
|
js, err := json.Marshal(st)
|
||||||
jsonString, err := json.Marshal(status)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exit.WithError("Error converting status to json", err)
|
exit.WithError("Error converting status to json", err)
|
||||||
}
|
}
|
||||||
out.String(string(jsonString))
|
out.String(string(js))
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ package kubeadm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path"
|
||||||
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
@ -77,9 +78,11 @@ func NewBootstrapper(api libmachine.API) (*Bootstrapper, error) {
|
||||||
func (k *Bootstrapper) GetKubeletStatus() (string, error) {
|
func (k *Bootstrapper) GetKubeletStatus() (string, error) {
|
||||||
rr, err := k.c.RunCmd(exec.Command("sudo", "systemctl", "is-active", "kubelet"))
|
rr, err := k.c.RunCmd(exec.Command("sudo", "systemctl", "is-active", "kubelet"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrapf(err, "getting kublet status. command: %q", rr.Command())
|
// Do not return now, as we still have parsing to do!
|
||||||
|
glog.Warningf("%s returned error: %v", rr.Command(), err)
|
||||||
}
|
}
|
||||||
s := strings.TrimSpace(rr.Stdout.String())
|
s := strings.TrimSpace(rr.Stdout.String())
|
||||||
|
glog.Infof("kubelet is-active: %s", s)
|
||||||
switch s {
|
switch s {
|
||||||
case "active":
|
case "active":
|
||||||
return state.Running.String(), nil
|
return state.Running.String(), nil
|
||||||
|
@ -93,6 +96,24 @@ func (k *Bootstrapper) GetKubeletStatus() (string, error) {
|
||||||
|
|
||||||
// GetAPIServerStatus returns the api-server status
|
// GetAPIServerStatus returns the api-server status
|
||||||
func (k *Bootstrapper) GetAPIServerStatus(ip net.IP, apiserverPort int) (string, error) {
|
func (k *Bootstrapper) GetAPIServerStatus(ip net.IP, apiserverPort int) (string, error) {
|
||||||
|
// sudo, in case hidepid is set
|
||||||
|
rr, err := k.c.RunCmd(exec.Command("sudo", "pgrep", "kube-apiserver"))
|
||||||
|
if err != nil {
|
||||||
|
return state.Stopped.String(), nil
|
||||||
|
}
|
||||||
|
pid := strings.TrimSpace(rr.Stdout.String())
|
||||||
|
|
||||||
|
// Check if apiserver is in an uninteruptible sleep
|
||||||
|
rr, err = k.c.RunCmd(exec.Command("sudo", "cut", "-d", " ", "-f3", path.Join("/proc", pid, "stat")))
|
||||||
|
if err != nil {
|
||||||
|
return state.Error.String(), err
|
||||||
|
}
|
||||||
|
st := strings.TrimSpace(rr.Stdout.String())
|
||||||
|
glog.Infof("apiserver process state: %s", st)
|
||||||
|
if st == "S" {
|
||||||
|
return state.Paused.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
return kverify.APIServerStatus(ip, apiserverPort)
|
return kverify.APIServerStatus(ip, apiserverPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue