From 908f098c72541b5b9b73d9be425904f33393b1a7 Mon Sep 17 00:00:00 2001 From: z4yx Date: Mon, 9 Mar 2020 21:48:06 +0800 Subject: [PATCH] [mirror config] job fails on pattern match in log --- worker/cmd_provider.go | 32 ++++++++++++++++++++++++++++++-- worker/config.go | 1 + worker/provider.go | 1 + worker/provider_test.go | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 2 deletions(-) diff --git a/worker/cmd_provider.go b/worker/cmd_provider.go index 6b05681..447b8ab 100644 --- a/worker/cmd_provider.go +++ b/worker/cmd_provider.go @@ -2,6 +2,9 @@ package worker import ( "errors" + "fmt" + "io/ioutil" + "regexp" "time" "github.com/anmitsu/go-shlex" @@ -14,12 +17,14 @@ type cmdConfig struct { interval time.Duration retry int env map[string]string + failOnMatch string } type cmdProvider struct { baseProvider cmdConfig - command []string + command []string + failOnMatch *regexp.Regexp } func newCmdProvider(c cmdConfig) (*cmdProvider, error) { @@ -46,6 +51,14 @@ func newCmdProvider(c cmdConfig) (*cmdProvider, error) { return nil, err } provider.command = cmd + if len(c.failOnMatch) > 0 { + var err error + failOnMatch, err := regexp.Compile(c.failOnMatch) + if err != nil { + return nil, errors.New("fail-on-match regexp error: " + err.Error()) + } + provider.failOnMatch = failOnMatch + } return provider, nil } @@ -62,7 +75,22 @@ func (p *cmdProvider) Run() error { if err := p.Start(); err != nil { return err } - return p.Wait() + if err := p.Wait(); err != nil { + return err + } + if p.failOnMatch != nil { + if logContent, err := ioutil.ReadFile(p.LogFile()); err == nil { + matches := p.failOnMatch.FindAllSubmatch(logContent, -1) + if len(matches) != 0 { + logger.Debug("Fail-on-match: %r", matches) + return errors.New( + fmt.Sprintf("Fail-on-match regexp found %d matches", len(matches))) + } + } else { + return err + } + } + return nil } func (p *cmdProvider) Start() error { diff --git a/worker/config.go b/worker/config.go index 565a11b..bd65d21 100644 --- a/worker/config.go +++ b/worker/config.go @@ -130,6 +130,7 @@ type mirrorConfig struct { ExecOnFailureExtra []string `toml:"exec_on_failure_extra"` Command string `toml:"command"` + FailOnMatch string `toml:"fail_on_match"` UseIPv6 bool `toml:"use_ipv6"` UseIPv4 bool `toml:"use_ipv4"` ExcludeFile string `toml:"exclude_file"` diff --git a/worker/provider.go b/worker/provider.go index 4e3e199..ccda722 100644 --- a/worker/provider.go +++ b/worker/provider.go @@ -112,6 +112,7 @@ func newMirrorProvider(mirror mirrorConfig, cfg *Config) mirrorProvider { upstreamURL: mirror.Upstream, command: mirror.Command, workingDir: mirrorDir, + failOnMatch: mirror.FailOnMatch, logDir: logDir, logFile: filepath.Join(logDir, "latest.log"), interval: time.Duration(mirror.Interval) * time.Minute, diff --git a/worker/provider_test.go b/worker/provider_test.go index 91b221d..bb72d7e 100644 --- a/worker/provider_test.go +++ b/worker/provider_test.go @@ -300,6 +300,41 @@ sleep 5 }) }) + Convey("Command Provider with fail-on-match regexp should work", t, func(ctx C) { + tmpDir, err := ioutil.TempDir("", "tunasync") + defer os.RemoveAll(tmpDir) + So(err, ShouldBeNil) + tmpFile := filepath.Join(tmpDir, "log_file") + + c := cmdConfig{ + name: "run-uptime", + upstreamURL: "http://mirrors.tuna.moe/", + command: "uptime", + failOnMatch: "", + workingDir: tmpDir, + logDir: tmpDir, + logFile: tmpFile, + interval: 600 * time.Second, + } + + Convey("when regexp matches", func() { + c.failOnMatch = `[a-z]+` + provider, err := newCmdProvider(c) + So(err, ShouldBeNil) + + err = provider.Run() + So(err, ShouldNotBeNil) + }) + + Convey("when regexp does not match", func() { + c.failOnMatch = `load average_` + provider, err := newCmdProvider(c) + So(err, ShouldBeNil) + + err = provider.Run() + So(err, ShouldBeNil) + }) + }) } func TestTwoStageRsyncProvider(t *testing.T) {