github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/build/docker/errors.go (about)

     1  /*
     2  Copyright 2020 The Skaffold Authors
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package docker
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"regexp"
    23  
    24  	"github.com/docker/docker/errdefs"
    25  	"github.com/docker/docker/pkg/jsonmessage"
    26  
    27  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/config"
    28  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker"
    29  	sErrors "github.com/GoogleContainerTools/skaffold/pkg/skaffold/errors"
    30  	"github.com/GoogleContainerTools/skaffold/proto/v1"
    31  )
    32  
    33  var (
    34  	noSpaceLeft = regexp.MustCompile(".*no space left.*")
    35  )
    36  
    37  // newBuildError turns Docker-specific errors into actionable errors.
    38  // The input errors are assumed to be from the Skaffold docker invocation.
    39  func newBuildError(err error, cfg docker.Config) error {
    40  	errU := errors.Unwrap(err)
    41  	if errU == nil {
    42  		return err
    43  	}
    44  
    45  	switch errU.(type) {
    46  	case *jsonmessage.JSONError:
    47  		return sErrors.NewError(err,
    48  			&proto.ActionableErr{
    49  				Message: err.Error(),
    50  				ErrCode: proto.StatusCode_BUILD_USER_ERROR,
    51  				Suggestions: []*proto.Suggestion{
    52  					{
    53  						SuggestionCode: proto.SuggestionCode_FIX_USER_BUILD_ERR,
    54  						Action:         "Please fix the Dockerfile and try again.",
    55  					},
    56  				},
    57  			})
    58  	default:
    59  		return sErrors.NewError(err, getActionableErr(errU, cfg))
    60  	}
    61  }
    62  
    63  func getActionableErr(err error, cfg docker.Config) *proto.ActionableErr {
    64  	var errCode proto.StatusCode
    65  	suggestions := []*proto.Suggestion{
    66  		{
    67  			SuggestionCode: proto.SuggestionCode_DOCKER_BUILD_RETRY,
    68  			Action:         "Docker build ran into internal error. Please retry.\nIf this keeps happening, please open an issue.",
    69  		},
    70  	}
    71  	switch err.(type) {
    72  	case errdefs.ErrNotFound:
    73  		errCode = proto.StatusCode_BUILD_DOCKER_ERROR_NOT_FOUND
    74  	case errdefs.ErrInvalidParameter:
    75  		errCode = proto.StatusCode_BUILD_DOCKER_INVALID_PARAM_ERR
    76  	case errdefs.ErrConflict:
    77  		errCode = proto.StatusCode_BUILD_DOCKER_CONFLICT_ERR
    78  	case errdefs.ErrCancelled:
    79  		errCode = proto.StatusCode_BUILD_DOCKER_CANCELLED
    80  	case errdefs.ErrForbidden:
    81  		errCode = proto.StatusCode_BUILD_DOCKER_FORBIDDEN_ERR
    82  	case errdefs.ErrDataLoss:
    83  		errCode = proto.StatusCode_BUILD_DOCKER_DATA_LOSS_ERR
    84  	case errdefs.ErrDeadline:
    85  		errCode = proto.StatusCode_BUILD_DOCKER_DEADLINE
    86  	case errdefs.ErrNotImplemented:
    87  		errCode = proto.StatusCode_BUILD_DOCKER_NOT_IMPLEMENTED_ERR
    88  	case errdefs.ErrNotModified:
    89  		errCode = proto.StatusCode_BUILD_DOCKER_NOT_MODIFIED_ERR
    90  	case errdefs.ErrSystem:
    91  		errCode = proto.StatusCode_BUILD_DOCKER_SYSTEM_ERR
    92  		if noSpaceLeft.MatchString(err.Error()) {
    93  			errCode = proto.StatusCode_BUILD_DOCKER_NO_SPACE_ERR
    94  			suggestions = []*proto.Suggestion{
    95  				{
    96  					SuggestionCode: proto.SuggestionCode_RUN_DOCKER_PRUNE,
    97  					Action:         "Docker ran out of memory. Please run 'docker system prune' to removed unused docker data",
    98  				},
    99  			}
   100  			if !cfg.Prune() && (cfg.Mode() == config.RunModes.Dev || cfg.Mode() == config.RunModes.Debug) {
   101  				suggestions = append(suggestions, &proto.Suggestion{
   102  					SuggestionCode: proto.SuggestionCode_SET_CLEANUP_FLAG,
   103  					Action:         fmt.Sprintf("Run skaffold %s with --cleanup=true to clean up images built by skaffold", cfg.Mode()),
   104  				})
   105  			}
   106  		}
   107  	case errdefs.ErrUnauthorized:
   108  		errCode = proto.StatusCode_BUILD_DOCKER_UNAUTHORIZED
   109  	case errdefs.ErrUnavailable:
   110  		errCode = proto.StatusCode_BUILD_DOCKER_UNAVAILABLE
   111  	default:
   112  		errCode = proto.StatusCode_BUILD_DOCKER_UNKNOWN
   113  	}
   114  
   115  	return &proto.ActionableErr{
   116  		Message:     err.Error(),
   117  		ErrCode:     errCode,
   118  		Suggestions: suggestions,
   119  	}
   120  }
   121  
   122  func dockerfileNotFound(err error, artifact string) error {
   123  	return sErrors.NewError(err,
   124  		&proto.ActionableErr{
   125  			Message: err.Error(),
   126  			ErrCode: proto.StatusCode_BUILD_DOCKERFILE_NOT_FOUND,
   127  			Suggestions: []*proto.Suggestion{
   128  				{
   129  					SuggestionCode: proto.SuggestionCode_FIX_SKAFFOLD_CONFIG_DOCKERFILE,
   130  					Action: fmt.Sprintf("Dockerfile not found. Please check config `dockerfile` for artifact %s."+
   131  						"\nRefer https://skaffold.dev/docs/references/yaml/#build-artifacts-docker for details.", artifact),
   132  				},
   133  			},
   134  		})
   135  }
   136  
   137  func cacheFromPullErr(err error, artifact string) error {
   138  	return sErrors.NewError(err,
   139  		&proto.ActionableErr{
   140  			Message: err.Error(),
   141  			ErrCode: proto.StatusCode_BUILD_DOCKER_CACHE_FROM_PULL_ERR,
   142  			Suggestions: []*proto.Suggestion{
   143  				{
   144  					SuggestionCode: proto.SuggestionCode_FIX_CACHE_FROM_ARTIFACT_CONFIG,
   145  					Action: fmt.Sprintf("Fix `cacheFrom` config for artifact %s."+
   146  						"\nRefer https://skaffold.dev/docs/references/yaml/#build-artifacts-docker for details.", artifact),
   147  				},
   148  			},
   149  		})
   150  }