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 }