github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/internal/config/errors-utils.go (about) 1 // Copyright (c) 2015-2021 MinIO, Inc. 2 // 3 // This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package config 19 20 import ( 21 "errors" 22 "fmt" 23 "net" 24 "syscall" 25 26 "github.com/minio/minio/internal/color" 27 ) 28 29 // Err is a structure which contains all information 30 // to print a fatal error message in json or pretty mode 31 // Err implements error so we can use it anywhere 32 type Err struct { 33 msg string 34 detail string 35 action string 36 hint string 37 } 38 39 // Clone returns a new Err struct with the same information 40 func (u Err) Clone() Err { 41 return Err{ 42 msg: u.msg, 43 detail: u.detail, 44 action: u.action, 45 hint: u.hint, 46 } 47 } 48 49 // Error returns the error message 50 func (u Err) Error() string { 51 if u.detail == "" { 52 if u.msg != "" { 53 return u.msg 54 } 55 return "<nil>" 56 } 57 return u.detail 58 } 59 60 // Msg - Replace the current error's message 61 func (u Err) Msg(m string, args ...interface{}) Err { 62 e := u.Clone() 63 e.msg = fmt.Sprintf(m, args...) 64 return e 65 } 66 67 // Hint - Replace the current error's message 68 func (u Err) Hint(m string, args ...interface{}) Err { 69 e := u.Clone() 70 e.hint = fmt.Sprintf(m, args...) 71 return e 72 } 73 74 // ErrFn function wrapper 75 type ErrFn func(err error) Err 76 77 // Create a UI error generator, this is needed to simplify 78 // the update of the detailed error message in several places 79 // in MinIO code 80 func newErrFn(msg, action, hint string) ErrFn { 81 return func(err error) Err { 82 u := Err{ 83 msg: msg, 84 action: action, 85 hint: hint, 86 } 87 if err != nil { 88 u.detail = err.Error() 89 } 90 return u 91 } 92 } 93 94 // ErrorToErr inspects the passed error and transforms it 95 // to the appropriate UI error. 96 func ErrorToErr(err error) Err { 97 if err == nil { 98 return Err{} 99 } 100 101 // If this is already a Err, do nothing 102 if e, ok := err.(Err); ok { 103 return e 104 } 105 106 // Show a generic message for known golang errors 107 if errors.Is(err, syscall.EADDRINUSE) { 108 return ErrPortAlreadyInUse(err).Msg("Specified port is already in use") 109 } else if errors.Is(err, syscall.EACCES) || errors.Is(err, syscall.EPERM) { 110 if netErr, ok := err.(*net.OpError); ok { 111 return ErrPortAccess(netErr).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 renderedTxt := "" 123 uiErr := ErrorToErr(err) 124 // JSON print 125 if jsonFlag { 126 // Message text in json should be simple 127 if uiErr.detail != "" { 128 return uiErr.msg + ": " + uiErr.detail 129 } 130 return uiErr.msg 131 } 132 // Pretty print error message 133 introMsg += ": " 134 if uiErr.msg != "" { 135 introMsg += color.Bold(uiErr.msg) 136 } else { 137 introMsg += color.Bold(err.Error()) 138 } 139 renderedTxt += color.Red(introMsg) + "\n" 140 // Add action message 141 if uiErr.action != "" { 142 renderedTxt += "> " + color.BgYellow(color.Black(uiErr.action)) + "\n" 143 } 144 // Add hint 145 if uiErr.hint != "" { 146 renderedTxt += color.Bold("HINT:") + "\n" 147 renderedTxt += " " + uiErr.hint 148 } 149 return renderedTxt 150 }