master
go 118 lines 2.61 KB
Raw
1 // pollEndpoint is a helper utility that waits for a http endpoint to be reachable and return with http.StatusOK
2 package main
3
4 import (
5 "context"
6 "flag"
7 "io"
8 "net"
9 "net/http"
10 "os"
11 "time"
12
13 logging "github.com/ipfs/go-log/v2"
14 ma "github.com/multiformats/go-multiaddr"
15 manet "github.com/multiformats/go-multiaddr/net"
16 )
17
18 var (
19 host = flag.String("host", "/ip4/127.0.0.1/tcp/5001", "the multiaddr host to dial on")
20 tries = flag.Int("tries", 10, "how many tries to make before failing")
21 timeout = flag.Duration("tout", time.Second, "how long to wait between attempts")
22 httpURL = flag.String("http-url", "", "HTTP URL to fetch")
23 httpOut = flag.Bool("http-out", false, "Print the HTTP response body to stdout")
24 verbose = flag.Bool("v", false, "verbose logging")
25 )
26
27 var log = logging.Logger("pollEndpoint")
28
29 func main() {
30 flag.Parse()
31
32 // extract address from host flag
33 addr, err := ma.NewMultiaddr(*host)
34 if err != nil {
35 log.Fatal("NewMultiaddr() failed: ", err)
36 }
37
38 if *verbose { // lower log level
39 logging.SetDebugLogging()
40 }
41
42 // show what we got
43 start := time.Now()
44 log.Debugf("starting at %s, tries: %d, timeout: %s, addr: %s", start, *tries, *timeout, addr)
45
46 connTries := *tries
47 for connTries > 0 {
48 c, err := manet.Dial(addr)
49 if err == nil {
50 log.Debugf("ok - endpoint reachable with %d tries remaining, took %s", *tries, time.Since(start))
51 c.Close()
52 break
53 }
54 log.Debug("connect failed: ", err)
55 time.Sleep(*timeout)
56 connTries--
57 }
58
59 if err != nil {
60 goto Fail
61 }
62
63 if *httpURL != "" {
64 dialer := &connDialer{addr: addr}
65 httpClient := http.Client{Transport: &http.Transport{
66 DialContext: dialer.DialContext,
67 }}
68 reqTries := *tries
69 for reqTries > 0 {
70 try := (*tries - reqTries) + 1
71 log.Debugf("trying HTTP req %d: '%s'", try, *httpURL)
72 if tryHTTPGet(&httpClient, *httpURL) {
73 log.Debugf("HTTP req %d to '%s' succeeded", try, *httpURL)
74 goto Success
75 }
76 log.Debugf("HTTP req %d to '%s' failed", try, *httpURL)
77 time.Sleep(*timeout)
78 reqTries--
79 }
80 goto Fail
81 }
82
83 Success:
84 os.Exit(0)
85
86 Fail:
87 log.Error("failed")
88 os.Exit(1)
89 }
90
91 func tryHTTPGet(client *http.Client, url string) bool {
92 resp, err := client.Get(*httpURL)
93 if resp != nil && resp.Body != nil {
94 defer resp.Body.Close()
95 }
96 if err != nil {
97 return false
98 }
99 if resp.StatusCode != http.StatusOK {
100 return false
101 }
102 if *httpOut {
103 _, err := io.Copy(os.Stdout, resp.Body)
104 if err != nil {
105 panic(err)
106 }
107 }
108
109 return true
110 }
111
112 type connDialer struct {
113 addr ma.Multiaddr
114 }
115
116 func (d connDialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
117 return (&manet.Dialer{}).DialContext(ctx, d.addr)
118 }