1package checks 2 3import ( 4 "errors" 5 "fmt" 6 "net" 7 "net/http" 8 "os" 9 "path/filepath" 10 "strconv" 11 "time" 12 13 "github.com/docker/distribution/health" 14) 15 16// FileChecker checks the existence of a file and returns an error 17// if the file exists. 18func FileChecker(f string) health.Checker { 19 return health.CheckFunc(func() error { 20 absoluteFilePath, err := filepath.Abs(f) 21 if err != nil { 22 return fmt.Errorf("failed to get absolute path for %q: %v", f, err) 23 } 24 25 _, err = os.Stat(absoluteFilePath) 26 if err == nil { 27 return errors.New("file exists") 28 } else if os.IsNotExist(err) { 29 return nil 30 } 31 32 return err 33 }) 34} 35 36// HTTPChecker does a HEAD request and verifies that the HTTP status code 37// returned matches statusCode. 38func HTTPChecker(r string, statusCode int, timeout time.Duration, headers http.Header) health.Checker { 39 return health.CheckFunc(func() error { 40 client := http.Client{ 41 Timeout: timeout, 42 } 43 req, err := http.NewRequest("HEAD", r, nil) 44 if err != nil { 45 return errors.New("error creating request: " + r) 46 } 47 for headerName, headerValues := range headers { 48 for _, headerValue := range headerValues { 49 req.Header.Add(headerName, headerValue) 50 } 51 } 52 response, err := client.Do(req) 53 if err != nil { 54 return errors.New("error while checking: " + r) 55 } 56 if response.StatusCode != statusCode { 57 return errors.New("downstream service returned unexpected status: " + strconv.Itoa(response.StatusCode)) 58 } 59 return nil 60 }) 61} 62 63// TCPChecker attempts to open a TCP connection. 64func TCPChecker(addr string, timeout time.Duration) health.Checker { 65 return health.CheckFunc(func() error { 66 conn, err := net.DialTimeout("tcp", addr, timeout) 67 if err != nil { 68 return errors.New("connection to " + addr + " failed") 69 } 70 conn.Close() 71 return nil 72 }) 73} 74