From 8ce35777ef8bb11cf32d2f06baa39bb577ef187b Mon Sep 17 00:00:00 2001 From: liyao Date: Thu, 23 Nov 2023 11:39:53 +0800 Subject: [PATCH] refactor: adjust agent server to raw error and cli error display (#472) * feat: introduce RawError and middleware Signed-off-by: mlycore * feat: introduce new errors Signed-off-by: mlycore * refactor: using raw error and new error code Signed-off-by: mlycore * refactor: using InvalidHttpRequestBody Signed-off-by: mlycore * refactor: using raw error as cmd error Signed-off-by: mlycore * fix: fix MvTempToPgData error handle Signed-off-by: mlycore * feat: introduce http request raw error Signed-off-by: mlycore * refactor: using unwrapped error Signed-off-by: mlycore * chore: adjust style Signed-off-by: mlycore * chore: adjust style Signed-off-by: mlycore * chore: adjust style Signed-off-by: mlycore * chore: adjust style Signed-off-by: mlycore * chore: adjust style Signed-off-by: mlycore * chore: adjust style Signed-off-by: mlycore --------- Signed-off-by: mlycore --- pitr/agent/internal/cons/error.go | 76 +++++---- .../handler/middleware/uniform_err_resp.go | 17 +- pitr/agent/internal/handler/restore.go | 9 +- pitr/agent/internal/handler/view/restore.go | 2 +- pitr/agent/internal/pkg/opengauss.go | 151 +++++++++++------- pitr/agent/main.go | 3 +- pitr/agent/pkg/cmds/cmd.go | 17 +- pitr/agent/pkg/responder/resp.go | 13 +- pitr/cli/internal/cmd/backup.go | 6 +- pitr/cli/internal/cmd/restore.go | 2 +- pitr/cli/internal/pkg/agent-server.go | 15 +- pitr/cli/internal/pkg/xerr/err.go | 15 +- 12 files changed, 208 insertions(+), 118 deletions(-) diff --git a/pitr/agent/internal/cons/error.go b/pitr/agent/internal/cons/error.go index ff747ca1..66a968ea 100644 --- a/pitr/agent/internal/cons/error.go +++ b/pitr/agent/internal/cons/error.go @@ -22,35 +22,49 @@ import ( ) var ( - Internal = xerror.New(10000, "Internal error.") - InvalidHTTPHeader = xerror.New(10001, "Invalid http header.") - DataNotFound = xerror.New(10002, "Data not found.") - CmdOperateFailed = xerror.New(10003, "Command operate failed.") - BackupPathAlreadyExist = xerror.New(10004, "The backup path already exists.") - NoPermission = xerror.New(10005, "No permission to operate.") - InstanceAlreadyExist = xerror.New(10006, "The instance already exist.") - InstanceNotExist = xerror.New(10007, "The instance not exist.") - StartOpenGaussFailed = xerror.New(10008, "Failed to start opengauss.") - StopOpenGaussFailed = xerror.New(10009, "Failed to stop opengauss.") - RestoreFailed = xerror.New(10010, "Failed to restore opengauss.") - InvalidDBPort = xerror.New(10011, "Invalid db port or missing db port.") - MissingUsername = xerror.New(10012, "Missing username") - MissingPassword = xerror.New(10013, "Missing password.") - MissingDnBackupPath = xerror.New(10014, "Missing dn backup path.") - InvalidDnThreadsNum = xerror.New(10015, "Invalid dn threads num.") - MissingDnBackupMode = xerror.New(10016, "Missing dn backup mode.") - InvalidDnBackupMode = xerror.New(10017, "Invalid dn backup mode.") - MissingInstance = xerror.New(10018, "Missing instance.") - MissingDnBackupID = xerror.New(10019, "Missing dn backup id.") - BodyParseFailed = xerror.New(10020, "Invalid http request body.") - MissingDBName = xerror.New(10021, "Missing db name.") - DBConnectionFailed = xerror.New(10022, "Database connection failed.") - UnmatchBackupID = xerror.New(10023, "Unmatch any backup id.") - InvalidPgDataDir = xerror.New(10024, "Invalid PGDATA dir.") - UnknownOgStatus = xerror.New(10025, "Unknown openGauss status.") - MvPgDataToTempFailed = xerror.New(10026, "Move pgdata dir to temp failed.") - MvTempToPgDataFailed = xerror.New(10027, "Move temp dir to pgdata failed.") - CleanPgDataTempFailed = xerror.New(10028, "Clean pgdata temp dir failed.") - MissingDiskPath = xerror.New(10029, "Missing disk path.") - MissingBackupID = xerror.New(10030, "Missing backup id.") + Internal = xerror.New(10000, "Agent server internal error.") + InvalidHTTPHeader = xerror.New(10001, "Invalid http header.") + DataNotFound = xerror.New(10002, "Data not found.") + CmdOperateFailed = xerror.New(10003, "Command operate failed.") + BackupPathAlreadyExist = xerror.New(10004, "The backup path already exists.") + NoPermission = xerror.New(10005, "No permission to operate.") + InstanceAlreadyExist = xerror.New(10006, "The instance already exist.") + InstanceNotExist = xerror.New(10007, "The instance not exist.") + StartOpenGaussFailed = xerror.New(10008, "Failed to start opengauss.") + StopOpenGaussFailed = xerror.New(10009, "Failed to stop opengauss.") + RestoreFailed = xerror.New(10010, "Failed to restore opengauss.") + InvalidDBPort = xerror.New(10011, "Invalid db port or missing db port.") + MissingUsername = xerror.New(10012, "Missing username") + MissingPassword = xerror.New(10013, "Missing password.") + MissingDnBackupPath = xerror.New(10014, "Missing dn backup path.") + InvalidDnThreadsNum = xerror.New(10015, "Invalid dn threads num.") + MissingDnBackupMode = xerror.New(10016, "Missing dn backup mode.") + InvalidDnBackupMode = xerror.New(10017, "Invalid dn backup mode.") + MissingInstance = xerror.New(10018, "Missing instance.") + MissingDnBackupID = xerror.New(10019, "Missing dn backup id.") + BodyParseFailed = xerror.New(10020, "Invalid http request body.") + MissingDBName = xerror.New(10021, "Missing db name.") + DBConnectionFailed = xerror.New(10022, "Database connection failed.") + UnmatchBackupID = xerror.New(10023, "Unmatch any backup id.") + InvalidPgDataDir = xerror.New(10024, "Invalid PGDATA dir.") + UnknownOgStatus = xerror.New(10025, "Unknown openGauss status.") + MvPgDataToTempFailed = xerror.New(10026, "Move pgdata dir to temp failed.") + MvTempToPgDataFailed = xerror.New(10027, "Move temp dir to pgdata failed.") + CleanPgDataTempFailed = xerror.New(10028, "Clean pgdata temp dir failed.") + MissingDiskPath = xerror.New(10029, "Missing disk path.") + MissingBackupID = xerror.New(10030, "Missing backup id.") + MissingDBInformation = xerror.New(10031, "Missing db information.") + GetBackupIDFailed = xerror.New(10032, "Get backup id failed.") + InvalidHTTPRequestBody = xerror.New(10033, "Invalid http request body") + JSONUnmarshalFailed = xerror.New(10034, "Json unmarshal failed.") + CmdAsyncBackupFailed = xerror.New(10035, "Command `gs_probackup backup` failed.") + CmdShowBackupFailed = xerror.New(10036, "Command `gs_probackup show` failed.") + CmdDeleteBackupFailed = xerror.New(10037, "Command `gs_probackup delete` failed.") + CmdInitBackupFailed = xerror.New(10038, "Command `gs_probackup init` failed.") + CmdAddInstanceFailed = xerror.New(10039, "Command `gs_probackup add-instance` failed.") + CmdDelInstanceFailed = xerror.New(10040, "Command `gs_probackup del-instance` failed.") + CmdStartOpenGaussFailed = xerror.New(10041, "Command `gs_ctl start` failed.") + CmdStopOpenGaussFailed = xerror.New(10042, "Command `gs_ctl stop` failed.") + CmdStatusOpenGaussFailed = xerror.New(10043, "Command `gs_ctl status` failed.") + CmdAsyncRestoreFailed = xerror.New(10044, "Command `gs_ctl restore` failed.") ) diff --git a/pitr/agent/internal/handler/middleware/uniform_err_resp.go b/pitr/agent/internal/handler/middleware/uniform_err_resp.go index 8bc064e1..867ec507 100644 --- a/pitr/agent/internal/handler/middleware/uniform_err_resp.go +++ b/pitr/agent/internal/handler/middleware/uniform_err_resp.go @@ -36,10 +36,25 @@ func UniformErrResp(log logging.ILog) fiber.Handler { log.Fields(map[logging.FieldKey]string{ logging.ErrorKey: err.Error(), logging.RequestID: ctx.Get(cons.RequestID), - }).Error("UniformErrResp:an error occurred") + }).Error("UniformErrResp: an error occurred") if e, b := xerror.FromError(err); b { return responder.Error(ctx, e) } return responder.Error(ctx, cons.Internal) } } + +func UniformRawErrResp(log logging.ILog) fiber.Handler { + return func(ctx *fiber.Ctx) error { + err := ctx.Next() + if err == nil { + return nil + } + //nolint:exhaustive + log.Fields(map[logging.FieldKey]string{ + logging.ErrorKey: err.Error(), + logging.RequestID: ctx.Get(cons.RequestID), + }).Error("UniformErrResp: an error occurred") + return responder.RawError(ctx, err) + } +} diff --git a/pitr/agent/internal/handler/restore.go b/pitr/agent/internal/handler/restore.go index 722d9851..08d4fad4 100644 --- a/pitr/agent/internal/handler/restore.go +++ b/pitr/agent/internal/handler/restore.go @@ -73,14 +73,17 @@ func Restore(ctx *fiber.Ctx) (err error) { defer func() { if status != "restore success" { mvErr := pkg.OG.MvTempToPgData() - err = fmt.Errorf("resotre failre[err=%s], pkg.OG.MvTempToPgData return err wrap: %w", err, mvErr) + if mvErr != nil { + err = fmt.Errorf("restore failure[err=%s], pkg.OG.MvTempToPgData return err: %s", err, mvErr) + return + } + err = fmt.Errorf("restore failure[err=%s]", err) + return } }() // restore data from backup if err = pkg.OG.Restore(in.DnBackupPath, in.Instance, in.DnBackupID, in.DnThreadsNum); err != nil { - efmt := "pkg.OG.Restore failure[path=%s,instance=%s,backupID=%s], err wrap: %w" - err = fmt.Errorf(efmt, in.DnBackupPath, in.Instance, in.DnBackupID, err) status = "restore failure" return } diff --git a/pitr/agent/internal/handler/view/restore.go b/pitr/agent/internal/handler/view/restore.go index 15f5f07b..bbfc35c9 100644 --- a/pitr/agent/internal/handler/view/restore.go +++ b/pitr/agent/internal/handler/view/restore.go @@ -33,7 +33,7 @@ type RestoreIn struct { //nolint:dupl func (in *RestoreIn) Validate() error { if in == nil { - return cons.Internal + return cons.InvalidHTTPRequestBody } if in.DBPort == 0 { diff --git a/pitr/agent/internal/pkg/opengauss.go b/pitr/agent/internal/pkg/opengauss.go index b1b8b13d..21872c69 100644 --- a/pitr/agent/internal/pkg/opengauss.go +++ b/pitr/agent/internal/pkg/opengauss.go @@ -93,13 +93,15 @@ const ( _showListFmt = "gs_probackup show --instance=%s --backup-path=%s --format=json 2>&1" _mvFmt = "mv %s %s" + + _CmdErrorFmt = "cmds.Exec[shell=%s,cmd=%s] return err wrap: %s" ) func (og *openGauss) AsyncBackup(backupPath, instanceName, backupMode string, threadsNum uint8, dbPort uint16) (string, error) { cmd := fmt.Sprintf(_backupFmt, backupPath, instanceName, backupMode, og.pgData, threadsNum, dbPort) outputs, err := cmds.AsyncExec(og.shell, cmd) if err != nil { - return "", fmt.Errorf("cmds.AsyncExec[shell=%s,cmd=%s] return err wrap: %w", og.shell, cmd, err) + return "", fmt.Errorf("cmds.AsyncExec[shell=%s,cmd=%s] return err wrap: %w", og.shell, cmd, cons.CmdAsyncBackupFailed) } for output := range outputs { @@ -111,13 +113,15 @@ func (og *openGauss) AsyncBackup(backupPath, instanceName, backupMode string, th Debug(fmt.Sprintf("AsyncBackup output[lineNo=%d,msg=%s,err=%v]", output.LineNo, output.Message, output.Error)) if output.Error != nil { - return "", fmt.Errorf("output.Error[%w] is not nil", output.Error) + og.log.Error(fmt.Sprintf("output.Error[%s] is not nil", output.Error)) + return "", output.Error } // get the backup id from the first line bid, err := og.getBackupID(output.Message) if err != nil { - return "", fmt.Errorf("og.getBackupID[source=%s] return err wrap: %w", output.Message, err) + og.log.Error(fmt.Sprintf("og.getBackupID[source=%s] return err wrap: %s", output.Message, err)) + return "", err } // ignore other output go og.ignore(outputs) @@ -126,36 +130,25 @@ func (og *openGauss) AsyncBackup(backupPath, instanceName, backupMode string, th return "", fmt.Errorf("unknow err") } +//nolint:dupl func (og *openGauss) ShowBackup(backupPath, instanceName, backupID string) (*model.Backup, error) { cmd := fmt.Sprintf(_showFmt, instanceName, backupPath, backupID) - output, err := cmds.Exec(og.shell, cmd) + list, err := og.showbackup(cmd, instanceName) if err != nil { - return nil, fmt.Errorf("cmds.Exec[shell=%s,cmd=%s] return err wrap: %w", og.shell, cmd, err) + return nil, err } - - var list []*model.BackupList - if err = json.Unmarshal([]byte(output), &list); err != nil { - return nil, fmt.Errorf("json.Unmarshal[output=%s] return err: %s, wrap: %w", output, err, cons.Internal) - } - - for _, ins := range list { - if ins.Instance == instanceName { - if len(ins.List) == 0 { - return nil, fmt.Errorf("instance[name=%s], backupList[v=%+v], err wrap: %w", ins.Instance, list, cons.DataNotFound) - } - - return ins.List[0], nil - } + if len(list) > 0 { + return list[0], nil } - - return nil, fmt.Errorf("backupList[v=%+v], err wrap: %w", list, cons.DataNotFound) + return nil, err } func (og *openGauss) DelBackup(backupPath, instanceName, backupID string) error { cmd := fmt.Sprintf(_delBackupFmt, backupPath, instanceName, backupID) _, err := cmds.Exec(og.shell, cmd) if err != nil { - return fmt.Errorf("cmds.Exec[shell=%s,cmd=%s] return err wrap: %w", og.shell, cmd, err) + og.log.Error(fmt.Sprintf(_CmdErrorFmt, og.shell, cmd, err)) + return err } return nil } @@ -167,11 +160,14 @@ func (og *openGauss) Init(backupPath string) error { og.log.Debug(fmt.Sprintf("Init output[msg=%s,err=%v]", output, err)) if errors.Is(err, cons.CmdOperateFailed) { - return fmt.Errorf("init backup path failure,err: %s, wrap: %w", err, cons.BackupPathAlreadyExist) + og.log.Error(fmt.Sprintf("init backup path failure,err: %s, wrap: %s", err, cons.BackupPathAlreadyExist)) + return err } if err != nil { - return fmt.Errorf("cmds.Exec[shell=%s,cmd=%s] return err wrap: %w", og.shell, cmd, err) + og.log.Error(fmt.Sprintf(_CmdErrorFmt, og.shell, cmd, err)) + return err } + return nil } @@ -182,7 +178,8 @@ func (og *openGauss) deinit(backupPath string) error { cmd := fmt.Sprintf(_rmDirFmt, backupPath) if _, err := cmds.Exec(og.shell, cmd); err != nil { - return fmt.Errorf("cmds.Exec[shell=%s,cmd=%s] return err wrap: %w", og.shell, cmd, err) + og.log.Error(fmt.Sprintf(_CmdErrorFmt, og.shell, cmd, err)) + return err } return nil } @@ -194,11 +191,14 @@ func (og *openGauss) AddInstance(backupPath, instance string) error { og.log.Debug(fmt.Sprintf("AddInstance[output=%s,err=%v]", output, err)) if errors.Is(err, cons.CmdOperateFailed) { - return fmt.Errorf("add instance failure[output=%s], err: %s, wrap: %w", output, err, cons.InstanceAlreadyExist) + og.log.Error(fmt.Sprintf("add instance failure[output=%s], err: %s, wrap: %s", output, err, cons.InstanceAlreadyExist)) + return err } if err != nil { - return fmt.Errorf("cmds.Exec[shell=%s,cmd=%s] return err wrap: %w", og.shell, cmd, err) + og.log.Error(fmt.Sprintf(_CmdErrorFmt, og.shell, cmd, cons.CmdAddInstanceFailed)) + return err } + return nil } @@ -208,39 +208,47 @@ func (og *openGauss) DelInstance(backupPath, instance string) error { og.log.Debug(fmt.Sprintf("DelInstance[output=%s,err=%v]", output, err)) if errors.Is(err, cons.CmdOperateFailed) { - return fmt.Errorf("delete instance failure[output=%s], err: %s, wrap: %w", output, err, cons.InstanceNotExist) + og.log.Error(fmt.Sprintf("delete instance failure[output=%s], err: %s, wrap: %s", output, err, cons.InstanceNotExist)) + return err } if err != nil { - return fmt.Errorf("cmds.Exec[shell=%s,cmd=%s] return err wrap: %w", og.shell, cmd, err) + og.log.Error(fmt.Sprintf(_CmdErrorFmt, og.shell, cmd, cons.CmdDelInstanceFailed)) + return err } return nil } +//nolint:dupl func (og *openGauss) Start() error { cmd := fmt.Sprintf(_startOpenGaussFmt, og.pgData) output, err := cmds.Exec(og.shell, cmd) og.log.Debug(fmt.Sprintf("Start openGauss[output=%s]", output)) if errors.Is(err, cons.CmdOperateFailed) { - return fmt.Errorf("start openGauss failure[output=%s], err: %s, wrap: %w", output, err, cons.StartOpenGaussFailed) + og.log.Error(fmt.Sprintf("start openGauss failure[output=%s], err: %s, wrap: %s", output, err, cons.StartOpenGaussFailed)) + return err } if err != nil { - return fmt.Errorf("cmds.Exec[shell=%s,cmd=%s,output=%s] return err wrap: %w", og.shell, cmd, output, err) + og.log.Error(fmt.Sprintf("cmds.Exec[shell=%s,cmd=%s] output=%s return err wrap: %s", og.shell, cmd, output, cons.CmdStartOpenGaussFailed)) + return err } return nil } +//nolint:dupl func (og *openGauss) Stop() error { cmd := fmt.Sprintf(_stopOpenGaussFmt, og.pgData) output, err := cmds.Exec(og.shell, cmd) og.log.Debug(fmt.Sprintf("Stop openGauss[output=%s]", output)) if errors.Is(err, cons.CmdOperateFailed) { - return fmt.Errorf("stop openGauss failure[output=%s], err: %s, wrap: %w", output, err, cons.StopOpenGaussFailed) + og.log.Error(fmt.Sprintf("stop openGauss failure[output=%s], err: %s, wrap: %s", output, err, cons.StopOpenGaussFailed)) + return err } if err != nil { - return fmt.Errorf("cmds.Exec[shell=%s,cmd=%s,output=%s] return err wrap: %w", og.shell, cmd, output, err) + og.log.Error(fmt.Sprintf("cmds.Exec[shell=%s,cmd=%s] output=%s return err wrap: %s", og.shell, cmd, output, cons.CmdStopOpenGaussFailed)) + return err } return nil @@ -263,10 +271,12 @@ func (og *openGauss) Status() (string, error) { if strings.Contains(err.Error(), "no server running") { return "Stopped", nil } - return "", fmt.Errorf("get openGauss status failure[output=%s], err: %s, wrap: %w", output, err, cons.StopOpenGaussFailed) + og.log.Error(fmt.Sprintf("get openGauss status failure[output=%s], err: %s, wrap: %s", output, err, cons.StopOpenGaussFailed)) + return "", err } if err != nil { - return "", fmt.Errorf("cmds.Exec[shell=%s,cmd=%s,output=%s] return err wrap: %w", og.shell, cmd, output, err) + og.log.Error(fmt.Sprintf("cmds.Exec[shell=%s,cmd=%s] output=%s return err wrap: %s", og.shell, cmd, output, cons.CmdStatusOpenGaussFailed)) + return "", err } if strings.Contains(output, "server is running") { @@ -290,39 +300,51 @@ func (og *openGauss) Restore(backupPath, instance, backupID string, threadsNum u }). Debug(fmt.Sprintf("Restore openGauss[lineNo=%d,msg=%s]", output.LineNo, output.Message)) - if errors.Is(err, cons.CmdOperateFailed) { - return fmt.Errorf("cmds.AsyncExec[output=%s] return err: %s, wrap: %w", output.Message, output.Error, cons.RestoreFailed) + if err != nil { + og.log.Error(fmt.Sprintf("cmds.AsyncExec[output=%s] return err: %s, wrap: %s", output.Message, output.Error, cons.RestoreFailed)) + return err } + if output.Error != nil { - return fmt.Errorf("cmds.AsyncExec outputs: Error[%s] is not nil, wrap: %w", output.Error, cons.RestoreFailed) + og.log.Error(fmt.Sprintf("cmds.AsyncExec outputs: Error[%s] is not nil, wrap: %s", output.Error, cons.RestoreFailed)) + return output.Error } } return nil } -func (og *openGauss) ShowBackupList(backupPath, instanceName string) ([]*model.Backup, error) { - cmd := fmt.Sprintf(_showListFmt, instanceName, backupPath) +//nolint:dupl +func (og *openGauss) showbackup(cmd, instanceName string) ([]*model.Backup, error) { output, err := cmds.Exec(og.shell, cmd) if err != nil { - return nil, fmt.Errorf("cmds.Exec[shell=%s,cmd=%s] return err wrap: %w", og.shell, cmd, err) + og.log.Error(fmt.Sprintf(_CmdErrorFmt, og.shell, cmd, cons.CmdShowBackupFailed)) + return nil, err } var list []*model.BackupList if err = json.Unmarshal([]byte(output), &list); err != nil { - return nil, fmt.Errorf("json.Unmarshal[output=%s] return err: %s, wrap: %w", output, err, cons.Internal) + og.log.Error(fmt.Sprintf("json.Unmarshal[output=%s] return err: %s, wrap: %s", output, err, cons.JSONUnmarshalFailed)) + return nil, err } for _, ins := range list { if ins.Instance == instanceName { if len(ins.List) == 0 { - return nil, fmt.Errorf("instance[name=%s], backupList[v=%+v], err wrap: %w", ins.Instance, list, cons.DataNotFound) + og.log.Error(fmt.Sprintf("instance[name=%s], backupList[v=%+v], err wrap: %s", ins.Instance, list, cons.DataNotFound)) + return nil, err } return ins.List, nil } } - return nil, fmt.Errorf("backupList[v=%+v], err wrap: %w", list, cons.DataNotFound) + og.log.Error(fmt.Sprintf("backupList[v=%+v], err wrap: %s", list, cons.DataNotFound)) + return nil, err +} + +func (og *openGauss) ShowBackupList(backupPath, instanceName string) ([]*model.Backup, error) { + cmd := fmt.Sprintf(_showListFmt, instanceName, backupPath) + return og.showbackup(cmd, instanceName) } func (og *openGauss) ignore(outputs chan *cmds.Output) { @@ -340,11 +362,14 @@ func (og *openGauss) getBackupID(msg string) (string, error) { re := regexp2.MustCompile("(?<=backup ID:\\s+)\\w+(?=,)", 0) match, err := re.FindStringMatch(msg) if err != nil { - return "", fmt.Errorf("unmatch any backup id[msg=%s], err: %s", msg, err) + og.log.Error(fmt.Sprintf("unmatch any backup id[msg=%s], err: %s", msg, err)) + return "", err } - if match.Length == 0 { - return "", fmt.Errorf("unmatch any backup id,match.lenght is 0, err wrap: %w", cons.UnmatchBackupID) + if match == nil || match.Length == 0 { + og.log.Error(fmt.Sprintf("unmatch any backup id,match.lenght is 0, err wrap: %s", cons.UnmatchBackupID)) + return "", err } + return match.String(), err } @@ -353,16 +378,18 @@ func (og *openGauss) Auth(user, password, dbName string, dbPort uint16) error { strings.Trim(password, " ") == "" || strings.Trim(dbName, " ") == "" || dbPort == 0 { - return fmt.Errorf("invalid inputs[user=%s,password=%s,dbName=%s,dbPort=%d]", user, password, dbName, dbPort) + return fmt.Errorf("invalid inputs[user=%s,password=%s,dbName=%s,dbPort=%d], err wrap: %w", user, password, dbName, dbPort, cons.MissingDBInformation) } _og, err := gsutil.Open(user, password, dbName, dbPort) if err != nil { - return fmt.Errorf("gsutil.Open failure,err=%w", err) + og.log.Error(fmt.Sprintf("gsutil.Open failure,err=%s", err)) + return err } if err := _og.Ping(); err != nil { - return fmt.Errorf("ping openGauss fail[user=%s,pw length=%d,dbName=%s], err wrap: %w", user, len(password), dbName, err) + og.log.Error(fmt.Sprintf("ping openGauss fail[user=%s,pw length=%d,dbName=%s], err wrap: %s", user, len(password), dbName, err)) + return err } return nil @@ -372,10 +399,12 @@ func (og *openGauss) MvPgDataToTemp() error { cmd := fmt.Sprintf(_mvFmt, og.pgData, og.pgDataTemp) _, err := cmds.Exec(og.shell, cmd) if errors.Is(err, cons.CmdOperateFailed) { - return fmt.Errorf("mv pgdata to temp dir failure, err: %s, wrap: %w", err, cons.MvPgDataToTempFailed) + og.log.Error(fmt.Sprintf("mv pgdata to temp dir failure, err: %s, wrap: %s", err, cons.MvPgDataToTempFailed)) + return err } if err != nil { - return fmt.Errorf("cmds.Exec[shell=%s,cmd=%s] return err wrap: %w", og.shell, cmd, err) + og.log.Error(fmt.Sprintf(_CmdErrorFmt, og.shell, cmd, err)) + return err } return nil @@ -385,10 +414,12 @@ func (og *openGauss) MvTempToPgData() error { cmd := fmt.Sprintf(_mvFmt, og.pgDataTemp, og.pgData) _, err := cmds.Exec(og.shell, cmd) if errors.Is(err, cons.CmdOperateFailed) { - return fmt.Errorf("mv temp to pgdata dir failure, err: %s, wrap: %w", err, cons.MvTempToPgDataFailed) + og.log.Error(fmt.Sprintf("mv temp to pgdata dir failure, err: %s, wrap: %s", err, cons.MvTempToPgDataFailed)) + return err } if err != nil { - return fmt.Errorf("cmds.Exec[shell=%s,cmd=%s] return err wrap: %w", og.shell, cmd, err) + og.log.Error(fmt.Sprintf(_CmdErrorFmt, og.shell, cmd, err)) + return err } return nil } @@ -397,10 +428,12 @@ func (og *openGauss) CleanPgDataTemp() error { cmd := fmt.Sprintf(_rmDirFmt, og.pgDataTemp) _, err := cmds.Exec(og.shell, cmd) if errors.Is(err, cons.CmdOperateFailed) { - return fmt.Errorf("clean pgdata temp dir failure, err: %s, wrap: %w", err, cons.CleanPgDataTempFailed) + og.log.Error(fmt.Sprintf("clean pgdata temp dir failure, err: %s, wrap: %s", err, cons.CleanPgDataTempFailed)) + return err } if err != nil { - return fmt.Errorf("cmds.Exec[shell=%s,cmd=%s] return err wrap: %w", og.shell, cmd, err) + og.log.Error(fmt.Sprintf(_CmdErrorFmt, og.shell, cmd, err)) + return err } return nil } @@ -408,11 +441,13 @@ func (og *openGauss) CleanPgDataTemp() error { func (og *openGauss) CheckSchema(user, password, dbName string, dbPort uint16, schema string) error { _og, err := gsutil.Open(user, password, dbName, dbPort) if err != nil { - return fmt.Errorf("gsutil.Open failure, err wrap: %w", err) + og.log.Error(fmt.Sprintf("gsutil.Open failure, err wrap: %s", err)) + return err } if err := _og.CheckSchema(schema); err != nil { - return fmt.Errorf("check openGauss schema fail[user=%s,dbName=%s, schema=%s], err wrap: %w", user, dbName, schema, err) + og.log.Error(fmt.Sprintf("check openGauss schema fail[user=%s,dbName=%s, schema=%s], err wrap: %s", user, dbName, schema, err)) + return err } return nil } diff --git a/pitr/agent/main.go b/pitr/agent/main.go index 2147259c..32eaf866 100644 --- a/pitr/agent/main.go +++ b/pitr/agent/main.go @@ -146,7 +146,8 @@ func SetupApp() { app.Use( middleware.Recover(logging.Log()), - middleware.UniformErrResp(logging.Log()), + // middleware.UniformErrResp(logging.Log()), + middleware.UniformRawErrResp(logging.Log()), ) app.Get("/ping", func(ctx *fiber.Ctx) error { diff --git a/pitr/agent/pkg/cmds/cmd.go b/pitr/agent/pkg/cmds/cmd.go index c7d72b08..486148b1 100644 --- a/pitr/agent/pkg/cmds/cmd.go +++ b/pitr/agent/pkg/cmds/cmd.go @@ -78,14 +78,13 @@ func AsyncExec(name string, args ...string) (chan *Output, error) { if err = cmd.Wait(); err != nil { if ee, ok := err.(*exec.ExitError); ok { - output <- &Output{ - Error: fmt.Errorf("exec failure[ee=%s],wrap=%w", ee, cons.CmdOperateFailed), - } - } else { - output <- &Output{ - Error: fmt.Errorf("cmd.Wait return err=%s,wrap=%w", err, cons.Internal), - } + logging.Error(fmt.Sprintf("exec failure[ee=%s], wrap=%s", ee, cons.CmdOperateFailed)) } + + output <- &Output{ + Error: fmt.Errorf("%s err: %s", cmd.String(), err), + } + } return nil })(); err != nil { @@ -125,9 +124,9 @@ func Exec(name string, args ...string) (string, error) { if err = cmd.Wait(); err != nil { if ee, ok := err.(*exec.ExitError); ok { - return "", fmt.Errorf("exec failure[ee=%s,stdout=%s],wrap=%w", ee, string(reader), cons.CmdOperateFailed) + logging.Error(fmt.Sprintf("exec failure[ee=%s,stdout=%s]", ee, string(reader))) } - return "", cons.Internal + return "", fmt.Errorf("%s err: %s", cmd.String(), err) } return string(reader), nil } diff --git a/pitr/agent/pkg/responder/resp.go b/pitr/agent/pkg/responder/resp.go index 7a635244..8fcbeba6 100644 --- a/pitr/agent/pkg/responder/resp.go +++ b/pitr/agent/pkg/responder/resp.go @@ -66,7 +66,18 @@ func Error(ctx *fiber.Ctx, e error) error { }) } -func ErrorWitData(ctx *fiber.Ctx, e error, data any) error { +func RawError(ctx *fiber.Ctx, e error) error { + if e == nil { + return xerror.New(unknownErrCode, unknownErrMsg) + } + ctx.Status(http.StatusOK) + return ctx.JSON(&resp{ + Code: unknownErrCode, + Msg: e.Error(), + }) +} + +func ErrorWithData(ctx *fiber.Ctx, e error, data any) error { if e == nil { return xerror.New(unknownErrCode, unknownErrMsg) } diff --git a/pitr/cli/internal/cmd/backup.go b/pitr/cli/internal/cmd/backup.go index 96bc2ca1..1b59e3c6 100644 --- a/pitr/cli/internal/cmd/backup.go +++ b/pitr/cli/internal/cmd/backup.go @@ -174,7 +174,7 @@ func backup() error { return xerr.NewCliErr(fmt.Sprintf("check disk space failed. err: %s", err)) } - prompt := fmt.Sprintln(backupPromptFmt) + prompt := backupPromptFmt err = promptutil.GetUserApproveInTerminal(prompt) if err != nil { cancel = true @@ -286,7 +286,7 @@ func execBackup(lsBackup *model.LsBackup) error { // if backup failed, return error if err != nil { lsBackup.SsBackup.Status = model.SsBackupStatusFailed - return xerr.NewCliErr(fmt.Sprintf("node backup failed. err: %s", err)) + return xerr.NewCliErr(err.Error()) } // save data node list to lsBackup @@ -311,7 +311,7 @@ func _execBackup(as pkg.IAgentServer, node *model.StorageNode, dnCh chan *model. } backupID, err := as.Backup(in) if err != nil { - return xerr.NewCliErr(fmt.Sprintf("backup failed, err: %s", err)) + return xerr.NewCliErr(err.Error()) } // update DnList of lsBackup diff --git a/pitr/cli/internal/cmd/restore.go b/pitr/cli/internal/cmd/restore.go index 9a08f28f..ad684b7b 100644 --- a/pitr/cli/internal/cmd/restore.go +++ b/pitr/cli/internal/cmd/restore.go @@ -285,7 +285,7 @@ func (t *restoretask) checkProgress() (bool, error) { } if err = t.As.Restore(in); err != nil { - r.Status = "Failed" + r.Status = fmt.Sprintf("Failed: %s", err) t.ResultCh <- r return false, err } diff --git a/pitr/cli/internal/pkg/agent-server.go b/pitr/cli/internal/pkg/agent-server.go index 9e61aac3..261c68ec 100644 --- a/pitr/cli/internal/pkg/agent-server.go +++ b/pitr/cli/internal/pkg/agent-server.go @@ -19,6 +19,7 @@ package pkg import ( "context" + "errors" "fmt" "net/http" @@ -78,7 +79,7 @@ func (as *agentServer) CheckStatus(in *model.HealthCheckIn) error { r.Body(in) if err := r.Send(out); err != nil { - return xerr.NewUnknownErr(url, in, nil, err) + return xerr.NewHTTPRawRequestErr(errors.Unwrap(err)) } if out.Code != 0 { @@ -96,7 +97,7 @@ func (as *agentServer) Backup(in *model.BackupIn) (string, error) { r.Body(in) if err := r.Send(out); err != nil { - return "", xerr.NewUnknownErr(url, in, out, err) + return "", xerr.NewHTTPRawRequestErr(errors.Unwrap(err)) } if out.Code != 0 { @@ -115,7 +116,7 @@ func (as *agentServer) Restore(in *model.RestoreIn) error { r.Body(in) if err := r.Send(out); err != nil { - return xerr.NewUnknownErr(url, in, out, err) + return xerr.NewHTTPRawRequestErr(errors.Unwrap(err)) } if out.Code != 0 { @@ -133,7 +134,7 @@ func (as *agentServer) ShowDetail(in *model.ShowDetailIn) (*model.BackupInfo, er r.Body(in) if err := r.Send(out); err != nil { - return nil, xerr.NewUnknownErr(url, in, out, err) + return nil, xerr.NewHTTPRawRequestErr(errors.Unwrap(err)) } if out.Code != 0 { @@ -151,7 +152,7 @@ func (as *agentServer) ShowList(in *model.ShowListIn) ([]model.BackupInfo, error r.Body(in) if err := r.Send(out); err != nil { - return nil, xerr.NewUnknownErr(url, in, out, err) + return nil, xerr.NewHTTPRawRequestErr(errors.Unwrap(err)) } if out.Code != 0 { @@ -169,7 +170,7 @@ func (as *agentServer) ShowDiskSpace(in *model.DiskSpaceIn) (*model.DiskSpaceInf r.Body(in) if err := r.Send(out); err != nil { - return nil, xerr.NewUnknownErr(url, in, out, err) + return nil, xerr.NewHTTPRawRequestErr(errors.Unwrap(err)) } if out.Code != 0 { @@ -188,7 +189,7 @@ func (as *agentServer) DeleteBackup(in *model.DeleteBackupIn) error { r.Body(in) if err := r.Send(out); err != nil { - return xerr.NewUnknownErr(url, in, out, err) + return xerr.NewHTTPRawRequestErr(errors.Unwrap(err)) } if out.Code != 0 { diff --git a/pitr/cli/internal/pkg/xerr/err.go b/pitr/cli/internal/pkg/xerr/err.go index edca9f83..32969da2 100644 --- a/pitr/cli/internal/pkg/xerr/err.go +++ b/pitr/cli/internal/pkg/xerr/err.go @@ -24,11 +24,14 @@ type err struct { } const ( - postErrFmt = "httputils.NewRequest[url=%s,body=%v,out=%v] return err=%s,wrap=%w" + postErrFmt = "httputils.NewRequest[url=%s, body=%v, out=%v] return err=%s, wrap=%w" + httpErrFmt = "httputils.NewRequest[method=%s, url=%s, body=%v, out=%v] return err=%s, wrap=%w" + httpRawErrFmt = "err=%s" Unknown = "Unknown error" InvalidHTTPStatus = "Invalid http status" NotFound = "Not found" + HTTPRequest = "Http request error" ) func (e *err) Error() string { @@ -45,8 +48,16 @@ func NewUnknownErr(url string, in, out interface{}, err error) error { return fmt.Errorf(postErrFmt, url, in, out, err, NewCliErr(Unknown)) } +func NewHTTPRequestErr(method, url string, in, out interface{}, err error) error { + return fmt.Errorf(httpErrFmt, method, url, in, out, err, NewCliErr(HTTPRequest)) +} + +func NewHTTPRawRequestErr(err error) error { + return fmt.Errorf(httpRawErrFmt, err) +} + func NewAgentServerErr(code int, msg string) error { return &err{ - msg: fmt.Sprintf("agent server err[code=%d,msg=%s]", code, msg), + msg: fmt.Sprintf("agent server err[code=%d, msg=%s]", code, msg), } }