Merge pull request #1342 from mlaventure/is-serving-failfast

Disable FailFast on client.IsServing()
This commit is contained in:
Phil Estes 2017-08-11 16:47:48 -04:00 committed by GitHub
commit edc51c86f2
8 changed files with 91 additions and 67 deletions

View File

@ -104,10 +104,14 @@ type Client struct {
runtime string
}
// IsServing returns true if the client can successfully connect to the containerd daemon
// and the healthcheck service returns the SERVING response
// IsServing returns true if the client can successfully connect to the
// containerd daemon and the healthcheck service returns the SERVING
// response.
// This call will block if a transient error is encountered during
// connection. A timeout can be set in the context to ensure it returns
// early.
func (c *Client) IsServing(ctx context.Context) (bool, error) {
r, err := c.HealthService().Check(ctx, &grpc_health_v1.HealthCheckRequest{})
r, err := c.HealthService().Check(ctx, &grpc_health_v1.HealthCheckRequest{}, grpc.FailFast(false))
if err != nil {
return false, err
}

View File

@ -11,6 +11,7 @@ import (
"os/exec"
"runtime"
"testing"
"time"
"google.golang.org/grpc/grpclog"
@ -73,18 +74,20 @@ func TestMain(m *testing.M) {
}
}
client, err := ctrd.waitForStart(ctx)
waitCtx, waitCancel := context.WithTimeout(ctx, 2*time.Second)
client, err := ctrd.waitForStart(waitCtx)
waitCancel()
if err != nil {
ctrd.Kill()
ctrd.Wait()
fmt.Fprintf(os.Stderr, "%s: %s", err, buf.String())
fmt.Fprintf(os.Stderr, "%s: %s\n", err, buf.String())
os.Exit(1)
}
// print out the version in information
version, err := client.Version(ctx)
if err != nil {
fmt.Fprintf(os.Stderr, "error getting version: %s", err)
fmt.Fprintf(os.Stderr, "error getting version: %s\n", err)
os.Exit(1)
}
@ -99,7 +102,7 @@ func TestMain(m *testing.M) {
if _, err = client.Pull(ctx, testImage, WithPullUnpack); err != nil {
ctrd.Stop()
ctrd.Wait()
fmt.Fprintf(os.Stderr, "%s: %s", err, buf.String())
fmt.Fprintf(os.Stderr, "%s: %s\n", err, buf.String())
os.Exit(1)
}
}

View File

@ -1,16 +0,0 @@
package containerd
import (
"net"
"time"
winio "github.com/Microsoft/go-winio"
)
func Dialer(address string, timeout time.Duration) (net.Conn, error) {
return winio.DialPipe(address, &timeout)
}
func DialAddress(address string) string {
return address
}

View File

@ -240,14 +240,9 @@ func TestDaemonRestart(t *testing.T) {
<-statusC
serving := false
for i := 0; i < 20; i++ {
serving, err = client.IsServing(ctx)
if serving {
break
}
time.Sleep(100 * time.Millisecond)
}
waitCtx, waitCancel := context.WithTimeout(ctx, 2*time.Second)
serving, err := client.IsServing(waitCtx)
waitCancel()
if !serving {
t.Fatalf("containerd did not start within 2s: %v", err)
}

View File

@ -2,7 +2,6 @@ package containerd
import (
"context"
"fmt"
"io"
"os/exec"
"sync"
@ -44,19 +43,19 @@ func (d *daemon) waitForStart(ctx context.Context) (*Client, error) {
err error
)
for i := 0; i < 20; i++ {
if client == nil {
client, err = New(d.addr)
}
if err == nil {
serving, err = client.IsServing(ctx)
if serving {
return client, nil
}
}
time.Sleep(100 * time.Millisecond)
client, err = New(address)
if err != nil {
return nil, err
}
return nil, fmt.Errorf("containerd did not start within 2s: %v", err)
serving, err = client.IsServing(ctx)
if !serving {
client.Close()
if err == nil {
err = errors.New("connection was successful but service is not available")
}
return nil, err
}
return client, err
}
func (d *daemon) Stop() error {

View File

@ -1,31 +1,13 @@
// +build !windows
package containerd
import (
"fmt"
"net"
"os"
"strings"
"syscall"
"time"
"github.com/pkg/errors"
)
func isNoent(err error) bool {
if err != nil {
if nerr, ok := err.(*net.OpError); ok {
if serr, ok := nerr.Err.(*os.SyscallError); ok {
if serr.Err == syscall.ENOENT {
return true
}
}
}
}
return false
}
type dialResult struct {
c net.Conn
err error
@ -44,7 +26,7 @@ func Dialer(address string, timeout time.Duration) (net.Conn, error) {
case <-stopC:
return
default:
c, err := net.DialTimeout("unix", address, timeout)
c, err := dialer(address, timeout)
if isNoent(err) {
<-time.After(10 * time.Millisecond)
continue
@ -68,7 +50,3 @@ func Dialer(address string, timeout time.Duration) (net.Conn, error) {
return nil, errors.Errorf("dial %s: no such file or directory", address)
}
}
func DialAddress(address string) string {
return fmt.Sprintf("unix://%s", address)
}

32
dialer_unix.go Normal file
View File

@ -0,0 +1,32 @@
// +build !windows
package containerd
import (
"fmt"
"net"
"os"
"syscall"
"time"
)
func isNoent(err error) bool {
if err != nil {
if nerr, ok := err.(*net.OpError); ok {
if serr, ok := nerr.Err.(*os.SyscallError); ok {
if serr.Err == syscall.ENOENT {
return true
}
}
}
}
return false
}
func dialer(address string, timeout time.Duration) (net.Conn, error) {
return net.DialTimeout("unix", address, timeout)
}
func DialAddress(address string) string {
return fmt.Sprintf("unix://%s", address)
}

29
dialer_windows.go Normal file
View File

@ -0,0 +1,29 @@
package containerd
import (
"net"
"os"
"syscall"
"time"
winio "github.com/Microsoft/go-winio"
)
func isNoent(err error) bool {
if err != nil {
if oerr, ok := err.(*os.PathError); ok {
if oerr.Err == syscall.ENOENT {
return true
}
}
}
return false
}
func dialer(address string, timeout time.Duration) (net.Conn, error) {
return winio.DialPipe(address, &timeout)
}
func DialAddress(address string) string {
return address
}