Add paused state to apiserver status
parent
09b2780fb2
commit
e6999caea3
|
@ -23,8 +23,10 @@ import (
|
|||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config"
|
||||
|
@ -40,16 +42,13 @@ import (
|
|||
var statusFormat string
|
||||
var output string
|
||||
|
||||
// KubeconfigStatus represents the kubeconfig status
|
||||
var KubeconfigStatus = struct {
|
||||
Configured string
|
||||
Misconfigured string
|
||||
}{
|
||||
Configured: `Configured`,
|
||||
Misconfigured: `Misconfigured`,
|
||||
}
|
||||
const (
|
||||
// Additional states used by kubeconfig
|
||||
Configured = "Configured" // analagous to state.Saved
|
||||
Misconfigured = "Misconfigured" // analagous to state.Error
|
||||
)
|
||||
|
||||
// Status represents the status
|
||||
// Status holds string representations of libmachine.state.State
|
||||
type Status struct {
|
||||
Host string
|
||||
Kubelet string
|
||||
|
@ -81,7 +80,6 @@ var statusCmd = &cobra.Command{
|
|||
exit.UsageT("Cannot use both --output and --format options")
|
||||
}
|
||||
|
||||
var returnCode = 0
|
||||
api, err := machine.NewAPIClient()
|
||||
if err != nil {
|
||||
exit.WithCodeT(exit.Unavailable, "Error getting client: {{.error}}", out.V{"error": err})
|
||||
|
@ -89,81 +87,91 @@ var statusCmd = &cobra.Command{
|
|||
defer api.Close()
|
||||
|
||||
machineName := viper.GetString(config.MachineProfile)
|
||||
|
||||
hostSt, err := cluster.GetHostStatus(api, machineName)
|
||||
st, err := status(api, machineName)
|
||||
if err != nil {
|
||||
exit.WithError("Error getting host status", 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,
|
||||
glog.Errorf("status error: %v", err)
|
||||
}
|
||||
|
||||
switch strings.ToLower(output) {
|
||||
case "text":
|
||||
printStatusText(status)
|
||||
printStatusText(st)
|
||||
case "json":
|
||||
printStatusJSON(status)
|
||||
printStatusJSON(st)
|
||||
default:
|
||||
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() {
|
||||
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/
|
||||
|
@ -172,25 +180,24 @@ For the list accessible variables for the template, see the struct values here:
|
|||
`minikube status --output OUTPUT. json, text`)
|
||||
}
|
||||
|
||||
var printStatusText = func(status Status) {
|
||||
var printStatusText = func(st *Status) {
|
||||
tmpl, err := template.New("status").Parse(statusFormat)
|
||||
if err != nil {
|
||||
exit.WithError("Error creating status template", err)
|
||||
}
|
||||
err = tmpl.Execute(os.Stdout, status)
|
||||
err = tmpl.Execute(os.Stdout, st)
|
||||
if err != nil {
|
||||
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`")
|
||||
}
|
||||
}
|
||||
|
||||
var printStatusJSON = func(status Status) {
|
||||
|
||||
jsonString, err := json.Marshal(status)
|
||||
var printStatusJSON = func(st *Status) {
|
||||
js, err := json.Marshal(st)
|
||||
if err != nil {
|
||||
exit.WithError("Error converting status to json", err)
|
||||
}
|
||||
out.String(string(jsonString))
|
||||
out.String(string(js))
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package kubeadm
|
|||
|
||||
import (
|
||||
"os/exec"
|
||||
"path"
|
||||
|
||||
"fmt"
|
||||
"net"
|
||||
|
@ -77,9 +78,11 @@ func NewBootstrapper(api libmachine.API) (*Bootstrapper, error) {
|
|||
func (k *Bootstrapper) GetKubeletStatus() (string, error) {
|
||||
rr, err := k.c.RunCmd(exec.Command("sudo", "systemctl", "is-active", "kubelet"))
|
||||
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())
|
||||
glog.Infof("kubelet is-active: %s", s)
|
||||
switch s {
|
||||
case "active":
|
||||
return state.Running.String(), nil
|
||||
|
@ -93,6 +96,24 @@ func (k *Bootstrapper) GetKubeletStatus() (string, error) {
|
|||
|
||||
// GetAPIServerStatus returns the api-server status
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue