Merge pull request #9343 from tstromberg/docker-detect
Add 'docker status' check, improve deadline-exceeded error messagepull/9356/head
commit
0d6b6fcce7
|
@ -144,9 +144,11 @@ func runCmd(cmd *exec.Cmd, warnSlow ...bool) (*RunResult, error) {
|
|||
}
|
||||
}
|
||||
|
||||
if exitError, ok := err.(*exec.ExitError); ok {
|
||||
rr.ExitCode = exitError.ExitCode()
|
||||
if ex, ok := err.(*exec.ExitError); ok {
|
||||
glog.Warningf("%s returned with exit code %d", rr.Command(), ex.ExitCode())
|
||||
rr.ExitCode = ex.ExitCode()
|
||||
}
|
||||
|
||||
// Decrease log spam
|
||||
if elapsed > (1 * time.Second) {
|
||||
glog.Infof("Completed: %s: (%s)", rr.Command(), elapsed)
|
||||
|
|
|
@ -22,20 +22,24 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// SysInfo Info represents common system Information between docker and podman that minikube cares
|
||||
type SysInfo struct {
|
||||
CPUs int // CPUs is Number of CPUs
|
||||
TotalMemory int64 // TotalMemory Total available ram
|
||||
OSType string // container's OsType (windows or linux)
|
||||
Swarm bool // Weather or not the docker swarm is active
|
||||
StorageDriver string // the storage driver for the daemon (for example overlay2)
|
||||
CPUs int // CPUs is Number of CPUs
|
||||
TotalMemory int64 // TotalMemory Total available ram
|
||||
OSType string // container's OsType (windows or linux)
|
||||
Swarm bool // Weather or not the docker swarm is active
|
||||
StorageDriver string // the storage driver for the daemon (for example overlay2)
|
||||
Errors []string // any server issues
|
||||
}
|
||||
|
||||
var cachedSysInfo *SysInfo
|
||||
var cachedSysInfoErr *error
|
||||
var (
|
||||
cachedSysInfo *SysInfo
|
||||
cachedSysInfoErr *error
|
||||
)
|
||||
|
||||
// CachedDaemonInfo will run and return a docker/podman info only once per minikube run time. to avoid performance
|
||||
func CachedDaemonInfo(ociBin string) (SysInfo, error) {
|
||||
|
@ -58,7 +62,7 @@ func DaemonInfo(ociBin string) (SysInfo, error) {
|
|||
return *cachedSysInfo, err
|
||||
}
|
||||
d, err := dockerSystemInfo()
|
||||
cachedSysInfo = &SysInfo{CPUs: d.NCPU, TotalMemory: d.MemTotal, OSType: d.OSType, Swarm: d.Swarm.LocalNodeState == "active", StorageDriver: d.Driver}
|
||||
cachedSysInfo = &SysInfo{CPUs: d.NCPU, TotalMemory: d.MemTotal, OSType: d.OSType, Swarm: d.Swarm.LocalNodeState == "active", StorageDriver: d.Driver, Errors: d.ServerErrors}
|
||||
return *cachedSysInfo, err
|
||||
}
|
||||
|
||||
|
@ -163,6 +167,7 @@ type dockerSysInfo struct {
|
|||
SecurityOptions []string `json:"SecurityOptions"`
|
||||
ProductLicense string `json:"ProductLicense"`
|
||||
Warnings interface{} `json:"Warnings"`
|
||||
ServerErrors []string
|
||||
ClientInfo struct {
|
||||
Debug bool `json:"Debug"`
|
||||
Plugins []interface{} `json:"Plugins"`
|
||||
|
@ -245,6 +250,7 @@ func dockerSystemInfo() (dockerSysInfo, error) {
|
|||
return ds, errors.Wrapf(err, "unmarshal docker system info")
|
||||
}
|
||||
|
||||
glog.Infof("docker info: %+v", ds)
|
||||
return ds, nil
|
||||
}
|
||||
|
||||
|
@ -264,5 +270,6 @@ func podmanSystemInfo() (podmanSysInfo, error) {
|
|||
if err := json.Unmarshal([]byte(strings.TrimSpace(rawJSON)), &ps); err != nil {
|
||||
return ps, errors.Wrapf(err, "unmarshal podman system info")
|
||||
}
|
||||
glog.Infof("podman info: %+v", ps)
|
||||
return ps, nil
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import (
|
|||
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/minikube/pkg/drivers/kic"
|
||||
"k8s.io/minikube/pkg/drivers/kic/oci"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
|
@ -86,34 +87,41 @@ func status() registry.State {
|
|||
ctx, cancel := context.WithTimeout(context.Background(), 6*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// Quickly returns an error code if server is not running
|
||||
cmd := exec.CommandContext(ctx, oci.Docker, "version", "--format", "{{.Server.Os}}-{{.Server.Version}}")
|
||||
o, err := cmd.Output()
|
||||
output := string(o)
|
||||
if strings.Contains(output, "windows-") {
|
||||
return registry.State{Error: oci.ErrWindowsContainers, Installed: true, Healthy: false, Fix: "Change container type to \"linux\" in Docker Desktop settings", Doc: docURL + "#verify-docker-container-type-is-linux"}
|
||||
if err != nil {
|
||||
if ctx.Err() == context.DeadlineExceeded {
|
||||
err = errors.Wrapf(err, "deadline exceeded running %q", strings.Join(cmd.Args, " "))
|
||||
}
|
||||
|
||||
}
|
||||
if err == nil {
|
||||
glog.Infof("docker version: %s", output)
|
||||
return checkNeedsImprovement()
|
||||
}
|
||||
glog.Warningf("docker version returned error: %v", err)
|
||||
|
||||
glog.Warningf("docker returned error: %v", err)
|
||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||
stderr := strings.TrimSpace(string(exitErr.Stderr))
|
||||
newErr := fmt.Errorf(`%q %v: %s`, strings.Join(cmd.Args, " "), exitErr, stderr)
|
||||
|
||||
return suggestFix(stderr, newErr)
|
||||
}
|
||||
|
||||
// Basic timeout
|
||||
if ctx.Err() == context.DeadlineExceeded {
|
||||
glog.Warningf("%q timed out. ", strings.Join(cmd.Args, " "))
|
||||
return registry.State{Error: err, Installed: true, Healthy: false, Fix: "Restart the Docker service", Doc: docURL}
|
||||
}
|
||||
|
||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||
stderr := strings.TrimSpace(string(exitErr.Stderr))
|
||||
newErr := fmt.Errorf(`%q %v: %s`, strings.Join(cmd.Args, " "), exitErr, stderr)
|
||||
return suggestFix(stderr, newErr)
|
||||
glog.Infof("docker version: %s", o)
|
||||
if strings.Contains(string(o), "windows-") {
|
||||
return registry.State{Error: oci.ErrWindowsContainers, Installed: true, Healthy: false, Fix: "Change container type to \"linux\" in Docker Desktop settings", Doc: docURL + "#verify-docker-container-type-is-linux"}
|
||||
}
|
||||
|
||||
return registry.State{Error: err, Installed: true, Healthy: false, Doc: docURL}
|
||||
si, err := oci.CachedDaemonInfo("docker")
|
||||
if err != nil {
|
||||
// No known fix because we haven't yet seen a failure here
|
||||
return registry.State{Error: errors.Wrap(err, "docker info"), Installed: true, Healthy: false, Doc: docURL}
|
||||
}
|
||||
|
||||
for _, serr := range si.Errors {
|
||||
return suggestFix(serr, fmt.Errorf("docker info error: %s", serr))
|
||||
}
|
||||
|
||||
return checkNeedsImprovement()
|
||||
}
|
||||
|
||||
// checkNeedsImprovement if overlay mod is installed on a system
|
||||
|
@ -121,6 +129,7 @@ func checkNeedsImprovement() registry.State {
|
|||
if runtime.GOOS == "linux" {
|
||||
return checkOverlayMod()
|
||||
}
|
||||
|
||||
return registry.State{Installed: true, Healthy: true}
|
||||
}
|
||||
|
||||
|
@ -128,15 +137,18 @@ func checkNeedsImprovement() registry.State {
|
|||
func checkOverlayMod() registry.State {
|
||||
if _, err := os.Stat("/sys/module/overlay"); err == nil {
|
||||
glog.Info("overlay module found")
|
||||
|
||||
return registry.State{Installed: true, Healthy: true}
|
||||
}
|
||||
|
||||
if _, err := os.Stat("/sys/module/overlay2"); err == nil {
|
||||
glog.Info("overlay2 module found")
|
||||
|
||||
return registry.State{Installed: true, Healthy: true}
|
||||
}
|
||||
|
||||
glog.Warningf("overlay modules were not found")
|
||||
|
||||
return registry.State{NeedsImprovement: true, Installed: true, Healthy: true, Fix: "enable the overlay Linux kernel module using 'modprobe overlay'"}
|
||||
}
|
||||
|
||||
|
@ -150,10 +162,14 @@ func suggestFix(stderr string, err error) registry.State {
|
|||
return registry.State{Error: err, Installed: true, Running: false, Healthy: false, Fix: "Start the Docker service. If Docker is already running, you may need to reset Docker to factory settings with: Settings > Reset.", Doc: "https://github.com/docker/for-win/issues/1825#issuecomment-450501157"}
|
||||
}
|
||||
|
||||
if strings.Contains(stderr, "Cannot connect") || strings.Contains(stderr, "refused") || strings.Contains(stderr, "Is the docker daemon running") || strings.Contains(stderr, "docker daemon is not running") {
|
||||
if dockerNotRunning(stderr) {
|
||||
return registry.State{Error: err, Installed: true, Running: false, Healthy: false, Fix: "Start the Docker service", Doc: docURL}
|
||||
}
|
||||
|
||||
// We don't have good advice, but at least we can provide a good error message
|
||||
return registry.State{Error: err, Installed: true, Running: true, Healthy: false, Doc: docURL}
|
||||
}
|
||||
|
||||
func dockerNotRunning(s string) bool {
|
||||
return strings.Contains(s, "Cannot connect") || strings.Contains(s, "refused") || strings.Contains(s, "Is the docker daemon running") || strings.Contains(s, "docker daemon is not running")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue