storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/config/errors-utils.go (about) 1 /* 2 * MinIO Cloud Storage, (C) 2018-2019 MinIO, Inc. 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 config 18 19 import ( 20 "errors" 21 "fmt" 22 "net" 23 "syscall" 24 25 "storj.io/minio/pkg/color" 26 ) 27 28 // Err is a structure which contains all information 29 // to print a fatal error message in json or pretty mode 30 // Err implements error so we can use it anywhere 31 type Err struct { 32 msg string 33 detail string 34 action string 35 hint string 36 } 37 38 // Clone returns a new Err struct with the same information 39 func (u Err) Clone() Err { 40 return Err{ 41 msg: u.msg, 42 detail: u.detail, 43 action: u.action, 44 hint: u.hint, 45 } 46 } 47 48 // Error returns the error message 49 func (u Err) Error() string { 50 if u.detail == "" { 51 if u.msg != "" { 52 return u.msg 53 } 54 return "<nil>" 55 } 56 return u.detail 57 } 58 59 // Msg - Replace the current error's message 60 func (u Err) Msg(m string, args ...interface{}) Err { 61 e := u.Clone() 62 e.msg = fmt.Sprintf(m, args...) 63 return e 64 } 65 66 // Hint - Replace the current error's message 67 func (u Err) Hint(m string, args ...interface{}) Err { 68 e := u.Clone() 69 e.hint = fmt.Sprintf(m, args...) 70 return e 71 } 72 73 // ErrFn function wrapper 74 type ErrFn func(err error) Err 75 76 // Create a UI error generator, this is needed to simplify 77 // the update of the detailed error message in several places 78 // in MinIO code 79 func newErrFn(msg, action, hint string) ErrFn { 80 return func(err error) Err { 81 u := Err{ 82 msg: msg, 83 action: action, 84 hint: hint, 85 } 86 if err != nil { 87 u.detail = err.Error() 88 } 89 return u 90 } 91 } 92 93 // ErrorToErr inspects the passed error and transforms it 94 // to the appropriate UI error. 95 func ErrorToErr(err error) Err { 96 if err == nil { 97 return Err{} 98 } 99 100 // If this is already a Err, do nothing 101 if e, ok := err.(Err); ok { 102 return e 103 } 104 105 // Show a generic message for known golang errors 106 if errors.Is(err, syscall.EADDRINUSE) { 107 return ErrPortAlreadyInUse(err).Msg("Specified port is already in use") 108 } else if errors.Is(err, syscall.EACCES) || errors.Is(err, syscall.EPERM) { 109 switch err.(type) { 110 case *net.OpError: 111 return ErrPortAccess(err).Msg("Insufficient permissions to use specified port") 112 } 113 } 114 115 // Failed to identify what type of error this, return a simple UI error 116 return Err{msg: err.Error()} 117 } 118 119 // FmtError converts a fatal error message to a more clear error 120 // using some colors 121 func FmtError(introMsg string, err error, jsonFlag bool) string { 122 123 renderedTxt := "" 124 uiErr := ErrorToErr(err) 125 // JSON print 126 if jsonFlag { 127 // Message text in json should be simple 128 if uiErr.detail != "" { 129 return uiErr.msg + ": " + uiErr.detail 130 } 131 return uiErr.msg 132 } 133 // Pretty print error message 134 introMsg += ": " 135 if uiErr.msg != "" { 136 introMsg += color.Bold(uiErr.msg) 137 } else { 138 introMsg += color.Bold(err.Error()) 139 } 140 renderedTxt += color.Red(introMsg) + "\n" 141 // Add action message 142 if uiErr.action != "" { 143 renderedTxt += "> " + color.BgYellow(color.Black(uiErr.action)) + "\n" 144 } 145 // Add hint 146 if uiErr.hint != "" { 147 renderedTxt += color.Bold("HINT:") + "\n" 148 renderedTxt += " " + uiErr.hint 149 } 150 return renderedTxt 151 }