Merge branch '21894-diagnostics-dev-version-mismatch'
[arvados.git] / sdk / go / health / aggregator.go
index b5301dffe006ec280f379d56ca9330818eb029b6..19bafb54c56e41c6f8729749cec68f0e0bd15621 100644 (file)
@@ -135,6 +135,7 @@ type CheckResult struct {
        Response       map[string]interface{} `json:",omitempty"`
        ResponseTime   json.Number
        ClockTime      time.Time
        Response       map[string]interface{} `json:",omitempty"`
        ResponseTime   json.Number
        ClockTime      time.Time
+       Server         string // "Server" header in http response
        Metrics
        respTime time.Duration
 }
        Metrics
        respTime time.Duration
 }
@@ -223,7 +224,8 @@ func (agg *Aggregator) ClusterHealth() ClusterHealthResponse {
        for svcName, sh := range resp.Services {
                switch svcName {
                case arvados.ServiceNameDispatchCloud,
        for svcName, sh := range resp.Services {
                switch svcName {
                case arvados.ServiceNameDispatchCloud,
-                       arvados.ServiceNameDispatchLSF:
+                       arvados.ServiceNameDispatchLSF,
+                       arvados.ServiceNameDispatchSLURM:
                        // ok to not run any given dispatcher
                case arvados.ServiceNameHealth,
                        arvados.ServiceNameWorkbench1,
                        // ok to not run any given dispatcher
                case arvados.ServiceNameHealth,
                        arvados.ServiceNameWorkbench1,
@@ -359,6 +361,7 @@ func (agg *Aggregator) ping(target *url.URL) (result CheckResult) {
        }
        result.Health = "OK"
        result.ClockTime, _ = time.Parse(time.RFC1123, resp.Header.Get("Date"))
        }
        result.Health = "OK"
        result.ClockTime, _ = time.Parse(time.RFC1123, resp.Header.Get("Date"))
+       result.Server = resp.Header.Get("Server")
        return
 }
 
        return
 }
 
@@ -437,7 +440,7 @@ func (ccmd checkCommand) RunCommand(prog string, args []string, stdin io.Reader,
        err := ccmd.run(ctx, prog, args, stdin, stdout, stderr)
        if err != nil {
                if err != errSilent {
        err := ccmd.run(ctx, prog, args, stdin, stdout, stderr)
        if err != nil {
                if err != errSilent {
-                       fmt.Fprintln(stdout, err.Error())
+                       fmt.Fprintln(stderr, err.Error())
                }
                return 1
        }
                }
                return 1
        }
@@ -451,7 +454,8 @@ func (ccmd checkCommand) run(ctx context.Context, prog string, args []string, st
        loader.SetupFlags(flags)
        versionFlag := flags.Bool("version", false, "Write version information to stdout and exit 0")
        timeout := flags.Duration("timeout", defaultTimeout.Duration(), "Maximum time to wait for health responses")
        loader.SetupFlags(flags)
        versionFlag := flags.Bool("version", false, "Write version information to stdout and exit 0")
        timeout := flags.Duration("timeout", defaultTimeout.Duration(), "Maximum time to wait for health responses")
-       outputYAML := flags.Bool("yaml", false, "Output full health report in YAML format (default mode shows errors as plain text, is silent on success)")
+       quiet := flags.Bool("quiet", false, "Silent on success (suppress 'health check OK' message on stderr)")
+       outputYAML := flags.Bool("yaml", false, "Output full health report in YAML format (default mode prints 'health check OK' or plain text errors)")
        if ok, _ := cmd.ParseFlags(flags, prog, args, "", stderr); !ok {
                // cmd.ParseFlags already reported the error
                return errSilent
        if ok, _ := cmd.ParseFlags(flags, prog, args, "", stderr); !ok {
                // cmd.ParseFlags already reported the error
                return errSilent
@@ -486,15 +490,21 @@ func (ccmd checkCommand) run(ctx context.Context, prog string, args []string, st
        }
        if resp.Health != "OK" {
                for _, msg := range resp.Errors {
        }
        if resp.Health != "OK" {
                for _, msg := range resp.Errors {
-                       fmt.Fprintln(stdout, msg)
+                       fmt.Fprintln(stderr, msg)
                }
                fmt.Fprintln(stderr, "health check failed")
                return errSilent
        }
                }
                fmt.Fprintln(stderr, "health check failed")
                return errSilent
        }
+       if !*quiet {
+               fmt.Fprintln(stderr, "health check OK")
+       }
        return nil
 }
 
        return nil
 }
 
-var reGoVersion = regexp.MustCompile(` \(go\d+([\d.])*\)$`)
+var (
+       reGoVersion  = regexp.MustCompile(` \(go\d+([\d.])*\)$`)
+       reDevVersion = regexp.MustCompile(`~dev\d+$`)
+)
 
 // Return true if either a==b or the only difference is that one has a
 // " (go1.2.3)" suffix and the other does not.
 
 // Return true if either a==b or the only difference is that one has a
 // " (go1.2.3)" suffix and the other does not.
@@ -502,17 +512,10 @@ var reGoVersion = regexp.MustCompile(` \(go\d+([\d.])*\)$`)
 // This allows us to recognize a non-Go (rails) service as the same
 // version as a Go service.
 func sameVersion(a, b string) bool {
 // This allows us to recognize a non-Go (rails) service as the same
 // version as a Go service.
 func sameVersion(a, b string) bool {
-       if a == b {
-               return true
-       }
-       anogo := reGoVersion.ReplaceAllLiteralString(a, "")
-       bnogo := reGoVersion.ReplaceAllLiteralString(b, "")
-       if (anogo == a) != (bnogo == b) {
-               // only one of a/b has a (go1.2.3) suffix, so compare
-               // without that part
-               return anogo == bnogo
-       }
-       // both or neither has a (go1.2.3) suffix, and we already know
-       // a!=b
-       return false
+       // Strip " (go1.2.3)" suffix
+       a = reGoVersion.ReplaceAllLiteralString(a, "")
+       b = reGoVersion.ReplaceAllLiteralString(b, "")
+       anodev := reDevVersion.ReplaceAllLiteralString(a, "")
+       bnodev := reDevVersion.ReplaceAllLiteralString(b, "")
+       return anodev == bnodev && (a == anodev) == (b == bnodev)
 }
 }