mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2026-06-11 09:00:29 +00:00
80 lines
1.7 KiB
Go
80 lines
1.7 KiB
Go
package services
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/mailcow/mailcow-dockerized/agent/internal/commands"
|
|
)
|
|
|
|
// runError is what we return when a shell command exited non-zero but the
|
|
// failure is not a "target not found" case. The bus maps it to
|
|
// ErrCodeInternal.
|
|
type runError struct{ msg string }
|
|
|
|
func (e *runError) Error() string { return e.msg }
|
|
|
|
// asError converts a (RunResult, err) pair from commands.Run into a single
|
|
// error: pre-exec error → return as-is; non-zero exit → wrap stderr.
|
|
func asError(r *commands.RunResult, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if r.ExitCode != 0 {
|
|
msg := strings.TrimSpace(r.Stderr)
|
|
if msg == "" {
|
|
msg = "command exited " + itoa(r.ExitCode)
|
|
}
|
|
return &runError{msg: msg}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// asNotFoundOrError is the variant for queue/mailbox operations that may fail
|
|
// because the target doesn't live on this node. Maps known stderr fragments
|
|
// to commands.ErrNotFound so broadcast aggregation works.
|
|
func asNotFoundOrError(r *commands.RunResult, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if r.ExitCode == 0 {
|
|
return nil
|
|
}
|
|
if matchesAny(r.Stderr, notFoundFragments) {
|
|
return commands.ErrNotFound
|
|
}
|
|
return &runError{msg: strings.TrimSpace(r.Stderr)}
|
|
}
|
|
|
|
func matchesAny(haystack string, fragments []string) bool {
|
|
for _, f := range fragments {
|
|
if strings.Contains(haystack, f) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func itoa(i int) string {
|
|
// avoid strconv import for a one-shot; small ints only
|
|
if i == 0 {
|
|
return "0"
|
|
}
|
|
neg := false
|
|
if i < 0 {
|
|
neg = true
|
|
i = -i
|
|
}
|
|
var b [20]byte
|
|
n := len(b)
|
|
for i > 0 {
|
|
n--
|
|
b[n] = byte('0' + i%10)
|
|
i /= 10
|
|
}
|
|
if neg {
|
|
n--
|
|
b[n] = '-'
|
|
}
|
|
return string(b[n:])
|
|
}
|