Implement mirror.success_exit_codes and global.dangerous_global_success_exit_codes

Signed-off-by: Harry Chen <i@harrychen.xyz>
This commit is contained in:
Shengqi Chen 2025-02-28 14:43:51 +08:00
parent d2b3e731bf
commit 033aa60540
No known key found for this signature in database
4 changed files with 53 additions and 5 deletions

View File

@ -22,6 +22,7 @@ type baseProvider struct {
cmd *cmdJob cmd *cmdJob
logFileFd *os.File logFileFd *os.File
isRunning atomic.Value isRunning atomic.Value
successExitCodes []int
cgroup *cgroupHook cgroup *cgroupHook
zfs *zfsHook zfs *zfsHook
@ -186,3 +187,18 @@ func (p *baseProvider) Terminate() error {
func (p *baseProvider) DataSize() string { func (p *baseProvider) DataSize() string {
return "" return ""
} }
func (p *baseProvider) SetSuccessExitCodes(codes []int) {
if codes == nil {
p.successExitCodes = []int{}
} else {
p.successExitCodes = codes
}
}
func (p *baseProvider) GetSuccessExitCodes() []int {
if p.successExitCodes == nil {
return []int{}
}
return p.successExitCodes
}

View File

@ -63,6 +63,9 @@ type globalConfig struct {
ExecOnSuccess []string `toml:"exec_on_success"` ExecOnSuccess []string `toml:"exec_on_success"`
ExecOnFailure []string `toml:"exec_on_failure"` ExecOnFailure []string `toml:"exec_on_failure"`
// merged with mirror-specific options. make sure you know what you are doing!
SuccessExitCodes []int `toml:"dangerous_global_success_exit_codes"`
} }
type managerConfig struct { type managerConfig struct {
@ -169,6 +172,9 @@ type mirrorConfig struct {
ExecOnSuccessExtra []string `toml:"exec_on_success_extra"` ExecOnSuccessExtra []string `toml:"exec_on_success_extra"`
ExecOnFailureExtra []string `toml:"exec_on_failure_extra"` ExecOnFailureExtra []string `toml:"exec_on_failure_extra"`
// will be merged with global option
SuccessExitCodes []int `toml:"success_exit_codes"`
Command string `toml:"command"` Command string `toml:"command"`
FailOnMatch string `toml:"fail_on_match"` FailOnMatch string `toml:"fail_on_match"`
SizePattern string `toml:"size_pattern"` SizePattern string `toml:"size_pattern"`

View File

@ -60,6 +60,10 @@ type mirrorProvider interface {
ExitContext() *Context ExitContext() *Context
// return context // return context
Context() *Context Context() *Context
// set in newMirrorProvider, used by cmdJob.Wait
SetSuccessExitCodes(codes []int)
GetSuccessExitCodes() []int
} }
// newProvider creates a mirrorProvider instance // newProvider creates a mirrorProvider instance
@ -249,5 +253,17 @@ func newMirrorProvider(mirror mirrorConfig, cfg *Config) mirrorProvider {
} }
addHookFromCmdList(mirror.ExecOnFailureExtra, execOnFailure) addHookFromCmdList(mirror.ExecOnFailureExtra, execOnFailure)
successExitCodes := []int{}
if cfg.Global.SuccessExitCodes != nil {
successExitCodes = append(successExitCodes, cfg.Global.SuccessExitCodes...)
}
if mirror.SuccessExitCodes != nil {
successExitCodes = append(successExitCodes, mirror.SuccessExitCodes...)
}
if len(successExitCodes) > 0 {
logger.Infof("Non-zero success exit codes set for mirror %s: %v", mirror.Name, successExitCodes)
provider.SetSuccessExitCodes(successExitCodes)
}
return provider return provider
} }

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"os" "os"
"os/exec" "os/exec"
"slices"
"strings" "strings"
"sync" "sync"
"syscall" "syscall"
@ -171,9 +172,18 @@ func (c *cmdJob) Wait() error {
return c.retErr return c.retErr
default: default:
err := c.cmd.Wait() err := c.cmd.Wait()
c.retErr = err
close(c.finished) close(c.finished)
return err if err != nil {
code := err.(*exec.ExitError).ExitCode()
allowedCodes := c.provider.GetSuccessExitCodes()
if slices.Contains(allowedCodes, code) {
// process exited with non-success status
logger.Infof("Command %s exited with code %d: treated as success (allowed: %v)", c.cmd.Args, code, allowedCodes)
} else {
c.retErr = err
}
}
return c.retErr
} }
} }