Skip to content

Commit

Permalink
Merge pull request #10212 from tstromberg/docker-info-err
Browse files Browse the repository at this point in the history
Split PROVIDER_DOCKER_ERROR into more specific reason codes
  • Loading branch information
medyagh authored Jan 22, 2021
2 parents 3668e15 + 545c1c1 commit bc27322
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 17 deletions.
6 changes: 5 additions & 1 deletion cmd/minikube/cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,11 @@ func validateDriver(ds registry.DriverState, existing *config.ClusterConfig) {
}, `The '{{.driver}}' provider was not found: {{.error}}`, out.V{"driver": name, "error": st.Error})
}

id := fmt.Sprintf("PROVIDER_%s_ERROR", strings.ToUpper(name))
id := st.Reason
if id == "" {
id = fmt.Sprintf("PROVIDER_%s_ERROR", strings.ToUpper(name))
}

code := reason.ExProviderUnavailable

if !st.Running {
Expand Down
49 changes: 35 additions & 14 deletions pkg/minikube/registry/drvs/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,35 +95,36 @@ func status() registry.State {
cmd := exec.CommandContext(ctx, oci.Docker, "version", "--format", "{{.Server.Os}}-{{.Server.Version}}")
o, err := cmd.Output()
if err != nil {
reason := ""
if ctx.Err() == context.DeadlineExceeded {
err = errors.Wrapf(err, "deadline exceeded running %q", strings.Join(cmd.Args, " "))
reason = "PROVIDER_DOCKER_DEADLINE_EXCEEDED"
}

klog.Warningf("docker version 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)
return suggestFix("version", exitErr.ExitCode(), stderr, newErr)
}

return registry.State{Error: err, Installed: true, Healthy: false, Fix: "Restart the Docker service", Doc: docURL}
return registry.State{Reason: reason, Error: err, Installed: true, Healthy: false, Fix: "Restart the Docker service", Doc: docURL}
}

klog.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{Reason: "PROVIDER_DOCKER_WINDOWS_CONTAINERS", 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"}
}

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}
return registry.State{Reason: "PROVIDER_DOCKER_INFO_FAILED", 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 suggestFix("info", -1, serr, fmt.Errorf("docker info error: %s", serr))
}

return checkNeedsImprovement()
Expand Down Expand Up @@ -157,23 +158,43 @@ func checkOverlayMod() registry.State {
}

// suggestFix matches a stderr with possible fix for the docker driver
func suggestFix(stderr string, err error) registry.State {
func suggestFix(src string, exitcode int, stderr string, err error) registry.State {
if strings.Contains(stderr, "permission denied") && runtime.GOOS == "linux" {
return registry.State{Error: err, Installed: true, Running: true, Healthy: false, Fix: "Add your user to the 'docker' group: 'sudo usermod -aG docker $USER && newgrp docker'", Doc: "https://docs.docker.com/engine/install/linux-postinstall/"}
return registry.State{Reason: "PROVIDER_DOCKER_NEWGRP", Error: err, Installed: true, Running: true, Healthy: false, Fix: "Add your user to the 'docker' group: 'sudo usermod -aG docker $USER && newgrp docker'", Doc: "https://docs.docker.com/engine/install/linux-postinstall/"}
}

if strings.Contains(stderr, "/pipe/docker_engine: The system cannot find the file specified.") && runtime.GOOS == "windows" {
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"}
return registry.State{Reason: "PROVIDER_DOCKER_PIPE_NOT_FOUND", 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 dockerNotRunning(stderr) {
return registry.State{Error: err, Installed: true, Running: false, Healthy: false, Fix: "Start the Docker service", Doc: docURL}
reason := dockerNotRunning(stderr)
if reason != "" {
return registry.State{Reason: reason, 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}
reason = strings.ToUpper(fmt.Sprintf("PROVIDER_DOCKER_%s_ERROR", src))
if exitcode > 0 {
reason = strings.ToUpper(fmt.Sprintf("PROVIDER_DOCKER_%s_EXIT_%d", src, exitcode))
}
return registry.State{Reason: reason, 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")
// Return a reason code for Docker not running
func dockerNotRunning(s string) string {
// These codes are explicitly in order of the most likely to be helpful to a user

if strings.Contains(s, "Is the docker daemon running") || strings.Contains(s, "docker daemon is not running") {
return "PROVIDER_DOCKER_NOT_RUNNING"
}

if strings.Contains(s, "Cannot connect") {
return "PROVIDER_DOCKER_CANNOT_CONNECT"
}

if strings.Contains(s, "refused") {
return "PROVIDER_DOCKER_REFUSED"
}

return ""
}
6 changes: 4 additions & 2 deletions pkg/minikube/registry/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,10 @@ type State struct {
Running bool // it at least appears to be running
NeedsImprovement bool // healthy but could be improved
Error error
Fix string
Doc string

Reason string // A reason ID, propagated to reason.Kind.ID
Fix string
Doc string
}

// DriverDef defines how to initialize and load a machine driver
Expand Down

0 comments on commit bc27322

Please sign in to comment.