Skip to content

Commit

Permalink
client: NegotiateAPIVersion: do not ignore (connection) errors from Ping
Browse files Browse the repository at this point in the history
NegotiateAPIVersion was ignoring errors returned by Ping. The intent here
was to handle API responses from a daemon that may be in an unhealthy state,
however this case is already handled by Ping itself.

Ping only returns an error when either failing to connect to the API (daemon
not running or permissions errors), or when failing to parse the API response.

Neither of those should be ignored in this code, or considered a successful
"ping", so update the code to return

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
  • Loading branch information
thaJeztah committed Feb 23, 2024
1 parent 349abc6 commit 901b905
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 2 deletions.
6 changes: 5 additions & 1 deletion client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,11 @@ func (cli *Client) ClientVersion() string {
// added (1.24).
func (cli *Client) NegotiateAPIVersion(ctx context.Context) {
if !cli.manualOverride {
ping, _ := cli.Ping(ctx)
ping, err := cli.Ping(ctx)
if err != nil {
// FIXME(thaJeztah): Ping returns an error when failing to connect to the API; we should not swallow the error here, and instead returning it.
return
}
cli.negotiateAPIVersionPing(ping)
}
}
Expand Down
13 changes: 13 additions & 0 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,19 @@ func TestNegotiateAPVersionOverride(t *testing.T) {
assert.Equal(t, client.ClientVersion(), expected)
}

// TestNegotiateAPVersionConnectionFailure asserts that we do not modify the
// API version when failing to connect.
func TestNegotiateAPVersionConnectionFailure(t *testing.T) {
const expected = "9.99"

client, err := NewClientWithOpts(WithHost("unix:///no-such-socket"))
assert.NilError(t, err)

client.version = expected
client.NegotiateAPIVersion(context.Background())
assert.Equal(t, client.ClientVersion(), expected)
}

func TestNegotiateAPIVersionAutomatic(t *testing.T) {
var pingVersion string
httpClient := newMockClient(func(req *http.Request) (*http.Response, error) {
Expand Down
5 changes: 4 additions & 1 deletion client/ping.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ import (
// Ping pings the server and returns the value of the "Docker-Experimental",
// "Builder-Version", "OS-Type" & "API-Version" headers. It attempts to use
// a HEAD request on the endpoint, but falls back to GET if HEAD is not supported
// by the daemon.
// by the daemon. It ignores internal server errors returned by the API, which
// may be returned if the daemon is in an unhealthy state, but returns errors
// for other non-success status codes, failing to connect to the API, or failing
// to parse the API response.
func (cli *Client) Ping(ctx context.Context) (types.Ping, error) {
var ping types.Ping

Expand Down

0 comments on commit 901b905

Please sign in to comment.