2
0
Эх сурвалжийг харах

[mirror config] job fails on pattern match in log

z4yx 5 жил өмнө
parent
commit
908f098c72

+ 30 - 2
worker/cmd_provider.go

@@ -2,6 +2,9 @@ package worker
 
 
 import (
 import (
 	"errors"
 	"errors"
+	"fmt"
+	"io/ioutil"
+	"regexp"
 	"time"
 	"time"
 
 
 	"github.com/anmitsu/go-shlex"
 	"github.com/anmitsu/go-shlex"
@@ -14,12 +17,14 @@ type cmdConfig struct {
 	interval                    time.Duration
 	interval                    time.Duration
 	retry                       int
 	retry                       int
 	env                         map[string]string
 	env                         map[string]string
+	failOnMatch                 string
 }
 }
 
 
 type cmdProvider struct {
 type cmdProvider struct {
 	baseProvider
 	baseProvider
 	cmdConfig
 	cmdConfig
-	command []string
+	command     []string
+	failOnMatch *regexp.Regexp
 }
 }
 
 
 func newCmdProvider(c cmdConfig) (*cmdProvider, error) {
 func newCmdProvider(c cmdConfig) (*cmdProvider, error) {
@@ -46,6 +51,14 @@ func newCmdProvider(c cmdConfig) (*cmdProvider, error) {
 		return nil, err
 		return nil, err
 	}
 	}
 	provider.command = cmd
 	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
 	return provider, nil
 }
 }
@@ -62,7 +75,22 @@ func (p *cmdProvider) Run() error {
 	if err := p.Start(); err != nil {
 	if err := p.Start(); err != nil {
 		return err
 		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 {
 func (p *cmdProvider) Start() error {

+ 1 - 0
worker/config.go

@@ -130,6 +130,7 @@ type mirrorConfig struct {
 	ExecOnFailureExtra []string `toml:"exec_on_failure_extra"`
 	ExecOnFailureExtra []string `toml:"exec_on_failure_extra"`
 
 
 	Command       string   `toml:"command"`
 	Command       string   `toml:"command"`
+	FailOnMatch   string   `toml:"fail_on_match"`
 	UseIPv6       bool     `toml:"use_ipv6"`
 	UseIPv6       bool     `toml:"use_ipv6"`
 	UseIPv4       bool     `toml:"use_ipv4"`
 	UseIPv4       bool     `toml:"use_ipv4"`
 	ExcludeFile   string   `toml:"exclude_file"`
 	ExcludeFile   string   `toml:"exclude_file"`

+ 1 - 0
worker/provider.go

@@ -112,6 +112,7 @@ func newMirrorProvider(mirror mirrorConfig, cfg *Config) mirrorProvider {
 			upstreamURL: mirror.Upstream,
 			upstreamURL: mirror.Upstream,
 			command:     mirror.Command,
 			command:     mirror.Command,
 			workingDir:  mirrorDir,
 			workingDir:  mirrorDir,
+			failOnMatch: mirror.FailOnMatch,
 			logDir:      logDir,
 			logDir:      logDir,
 			logFile:     filepath.Join(logDir, "latest.log"),
 			logFile:     filepath.Join(logDir, "latest.log"),
 			interval:    time.Duration(mirror.Interval) * time.Minute,
 			interval:    time.Duration(mirror.Interval) * time.Minute,

+ 35 - 0
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) {
 func TestTwoStageRsyncProvider(t *testing.T) {