2018-05-09 04:04:36 +02:00
|
|
|
/*
|
2019-08-13 06:25:34 +02:00
|
|
|
* MinIO Cloud Storage, (C) 2018-2019 MinIO, Inc.
|
2018-05-09 04:04:36 +02:00
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package cmd
|
|
|
|
|
|
|
|
import (
|
2019-09-11 19:21:43 +02:00
|
|
|
"errors"
|
2018-05-09 04:04:36 +02:00
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"os"
|
2019-08-13 06:25:34 +02:00
|
|
|
"syscall"
|
2018-05-09 04:04:36 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
// uiErr is a structure which contains all information
|
|
|
|
// to print a fatal error message in json or pretty mode
|
|
|
|
// uiErr implements error so we can use it anywhere
|
|
|
|
type uiErr struct {
|
|
|
|
msg string
|
|
|
|
detail string
|
|
|
|
action string
|
2019-08-13 06:25:34 +02:00
|
|
|
hint string
|
2018-05-09 04:04:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Return the error message
|
|
|
|
func (u uiErr) Error() string {
|
|
|
|
if u.detail == "" {
|
|
|
|
return u.msg
|
|
|
|
}
|
|
|
|
return u.detail
|
|
|
|
}
|
|
|
|
|
|
|
|
// Replace the current error's message
|
|
|
|
func (u uiErr) Msg(m string, args ...interface{}) uiErr {
|
|
|
|
return uiErr{
|
|
|
|
msg: fmt.Sprintf(m, args...),
|
|
|
|
detail: u.detail,
|
|
|
|
action: u.action,
|
2019-08-13 06:25:34 +02:00
|
|
|
hint: u.hint,
|
2018-05-09 04:04:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type uiErrFn func(err error) uiErr
|
|
|
|
|
|
|
|
// Create a UI error generator, this is needed to simplify
|
|
|
|
// the update of the detailed error message in several places
|
2019-04-09 20:39:42 +02:00
|
|
|
// in MinIO code
|
2019-08-13 06:25:34 +02:00
|
|
|
func newUIErrFn(msg, action, hint string) uiErrFn {
|
2018-05-09 04:04:36 +02:00
|
|
|
return func(err error) uiErr {
|
|
|
|
u := uiErr{
|
|
|
|
msg: msg,
|
|
|
|
action: action,
|
2019-08-13 06:25:34 +02:00
|
|
|
hint: hint,
|
2018-05-09 04:04:36 +02:00
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
u.detail = err.Error()
|
|
|
|
}
|
|
|
|
return u
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// errorToUIError inspects the passed error and transforms it
|
|
|
|
// to the appropriate UI error.
|
|
|
|
func errorToUIErr(err error) uiErr {
|
|
|
|
// If this is already a uiErr, do nothing
|
|
|
|
if e, ok := err.(uiErr); ok {
|
|
|
|
return e
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show a generic message for known golang errors
|
2019-09-11 19:21:43 +02:00
|
|
|
if errors.Is(err, syscall.EADDRINUSE) {
|
|
|
|
return uiErrPortAlreadyInUse(err).Msg("Specified port is already in use")
|
|
|
|
} else if errors.Is(err, syscall.EACCES) {
|
|
|
|
return uiErrPortAccess(err).Msg("Insufficient permissions to use specified port")
|
|
|
|
} else if os.IsPermission(err) {
|
|
|
|
return uiErrNoPermissionsToAccessDirFiles(err).Msg("Insufficient permissions to access path")
|
|
|
|
} else if errors.Is(err, io.ErrUnexpectedEOF) {
|
2018-05-09 04:04:36 +02:00
|
|
|
return uiErrUnexpectedDataContent(err)
|
2019-09-11 19:21:43 +02:00
|
|
|
} else {
|
2018-05-09 04:04:36 +02:00
|
|
|
// Failed to identify what type of error this, return a simple UI error
|
|
|
|
return uiErr{msg: err.Error()}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-05-09 22:29:37 +02:00
|
|
|
// fmtError() converts a fatal error message to a more clear error
|
2018-05-09 04:04:36 +02:00
|
|
|
// using some colors
|
|
|
|
func fmtError(introMsg string, err error, jsonFlag bool) string {
|
|
|
|
renderedTxt := ""
|
|
|
|
uiErr := errorToUIErr(err)
|
|
|
|
// JSON print
|
|
|
|
if jsonFlag {
|
|
|
|
// Message text in json should be simple
|
|
|
|
if uiErr.detail != "" {
|
|
|
|
return uiErr.msg + ": " + uiErr.detail
|
|
|
|
}
|
|
|
|
return uiErr.msg
|
|
|
|
}
|
|
|
|
// Pretty print error message
|
|
|
|
introMsg += ": "
|
|
|
|
if uiErr.msg != "" {
|
2019-08-13 06:25:34 +02:00
|
|
|
introMsg += colorBold(uiErr.msg)
|
2018-05-09 04:04:36 +02:00
|
|
|
} else {
|
2019-08-13 06:25:34 +02:00
|
|
|
introMsg += colorBold(err.Error())
|
2018-05-09 04:04:36 +02:00
|
|
|
}
|
|
|
|
renderedTxt += colorRed(introMsg) + "\n"
|
|
|
|
// Add action message
|
|
|
|
if uiErr.action != "" {
|
2019-08-13 06:25:34 +02:00
|
|
|
renderedTxt += "> " + colorBgYellow(colorBlack(uiErr.action)) + "\n"
|
2018-05-09 04:04:36 +02:00
|
|
|
}
|
2019-08-13 06:25:34 +02:00
|
|
|
// Add hint
|
|
|
|
if uiErr.hint != "" {
|
|
|
|
renderedTxt += colorBold("HINT:") + "\n"
|
|
|
|
renderedTxt += " " + uiErr.hint
|
2018-05-09 04:04:36 +02:00
|
|
|
}
|
|
|
|
return renderedTxt
|
|
|
|
}
|