...
1 package main
2
3 import (
4 "context"
5 "flag"
6 "fmt"
7 "os"
8 "strings"
9 "time"
10
11 healthpb "google.golang.org/grpc/health/grpc_health_v1"
12
13 "github.com/letsencrypt/boulder/cmd"
14 bgrpc "github.com/letsencrypt/boulder/grpc"
15 "github.com/letsencrypt/boulder/metrics"
16 )
17
18 type config struct {
19 GRPC *cmd.GRPCClientConfig
20 TLS *cmd.TLSConfig
21 }
22
23 func main() {
24 defer cmd.AuditPanic()
25
26
27 configFile := flag.String("config", "", "Path to the TLS configuration file")
28 serverAddr := flag.String("addr", "", "Address of the gRPC server to check")
29 flag.Parse()
30 if *configFile == "" {
31 flag.Usage()
32 os.Exit(1)
33 }
34
35 var c config
36 err := cmd.ReadConfigFile(*configFile, &c)
37 cmd.FailOnError(err, "failed to read json config")
38
39 if c.GRPC.ServerAddress == "" && *serverAddr == "" {
40 cmd.Fail("must specify either -addr flag or client.ServerAddress config")
41 } else if c.GRPC.ServerAddress != "" && *serverAddr != "" {
42 cmd.Fail("cannot specify both -addr flag and client.ServerAddress config")
43 } else if c.GRPC.ServerAddress == "" {
44 c.GRPC.ServerAddress = *serverAddr
45 }
46
47 tlsConfig, err := c.TLS.Load(metrics.NoopRegisterer)
48 cmd.FailOnError(err, "failed to load TLS credentials")
49
50
51 clk := cmd.Clock()
52
53
54 ticker := time.NewTicker(100 * time.Millisecond)
55 ctx, cancel := context.WithTimeout(context.Background(), 10*c.GRPC.Timeout.Duration)
56 defer cancel()
57
58 for {
59 select {
60 case <-ticker.C:
61 fmt.Fprintf(os.Stderr, "Connecting to %s health service\n", *serverAddr)
62 _, hostOverride, err := c.GRPC.MakeTargetAndHostOverride()
63 cmd.FailOnError(err, "")
64
65
66 c.GRPC.HostOverride = strings.Replace(hostOverride, ".service.consul", ".boulder", 1)
67
68
69 conn, err := bgrpc.ClientSetup(c.GRPC, tlsConfig, metrics.NoopRegisterer, clk)
70 cmd.FailOnError(err, "failed to connect to service")
71 client := healthpb.NewHealthClient(conn)
72 ctx2, cancel2 := context.WithTimeout(ctx, c.GRPC.Timeout.Duration)
73 defer cancel2()
74
75
76 req := &healthpb.HealthCheckRequest{
77 Service: "",
78 }
79 resp, err := client.Check(ctx2, req)
80 if err != nil {
81 fmt.Fprintf(os.Stderr, "got error connecting to health service %s: %s\n", *serverAddr, err)
82 } else if resp.Status == healthpb.HealthCheckResponse_SERVING {
83 return
84 } else {
85 cmd.Fail(fmt.Sprintf("service %s failed health check with status %s", *serverAddr, resp.Status))
86 }
87
88 case <-ctx.Done():
89 cmd.Fail(fmt.Sprintf("timed out waiting for %s health check", *serverAddr))
90 }
91 }
92 }
93
View as plain text