mirror of
https://github.com/moby/moby.git
synced 2026-01-11 10:41:43 +00:00
Use a more idiomatic name so that it can be used as `client.New()`. We should look if we want `New()` to have different / updated defaults i.e., enable `WithEnv` as default, and have an opt-out and have API- version negotiation enabled by default (with an opt-out option). Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
134 lines
4.3 KiB
Go
134 lines
4.3 KiB
Go
package client
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"slices"
|
|
"strings"
|
|
"testing"
|
|
|
|
"gotest.tools/v3/assert"
|
|
is "gotest.tools/v3/assert/cmp"
|
|
)
|
|
|
|
// TestPingFail tests that when a server sends a non-successful response that we
|
|
// can still grab API details, when set.
|
|
// Some of this is just exercising the code paths to make sure there are no
|
|
// panics.
|
|
func TestPingFail(t *testing.T) {
|
|
var withHeader bool
|
|
client, err := New(WithMockClient(func(req *http.Request) (*http.Response, error) {
|
|
var hdr http.Header
|
|
if withHeader {
|
|
hdr = http.Header{}
|
|
hdr.Set("Api-Version", "awesome")
|
|
hdr.Set("Docker-Experimental", "true")
|
|
hdr.Set("Swarm", "inactive")
|
|
}
|
|
return mockResponse(http.StatusInternalServerError, hdr, "some error with the server")(req)
|
|
}))
|
|
assert.NilError(t, err)
|
|
|
|
ping, err := client.Ping(t.Context(), PingOptions{})
|
|
assert.Check(t, is.ErrorContains(err, "some error with the server"))
|
|
assert.Check(t, is.Equal(false, ping.Experimental))
|
|
assert.Check(t, is.Equal("", ping.APIVersion))
|
|
var si *SwarmStatus
|
|
assert.Check(t, is.Equal(si, ping.SwarmStatus))
|
|
|
|
withHeader = true
|
|
ping2, err := client.Ping(t.Context(), PingOptions{})
|
|
assert.Check(t, is.ErrorContains(err, "some error with the server"))
|
|
assert.Check(t, is.Equal(true, ping2.Experimental))
|
|
assert.Check(t, is.Equal("awesome", ping2.APIVersion))
|
|
assert.Check(t, is.Equal(SwarmStatus{NodeState: "inactive"}, *ping2.SwarmStatus))
|
|
}
|
|
|
|
// TestPingWithError tests the case where there is a protocol error in the ping.
|
|
// This test is mostly just testing that there are no panics in this code path.
|
|
func TestPingWithError(t *testing.T) {
|
|
client, err := New(WithMockClient(func(req *http.Request) (*http.Response, error) {
|
|
return nil, errors.New("some connection error")
|
|
}))
|
|
assert.NilError(t, err)
|
|
|
|
ping, err := client.Ping(t.Context(), PingOptions{})
|
|
assert.Check(t, is.ErrorContains(err, "some connection error"))
|
|
assert.Check(t, is.Equal(false, ping.Experimental))
|
|
assert.Check(t, is.Equal("", ping.APIVersion))
|
|
var si *SwarmStatus
|
|
assert.Check(t, is.Equal(si, ping.SwarmStatus))
|
|
}
|
|
|
|
// TestPingSuccess tests that we are able to get the expected API headers/ping
|
|
// details on success.
|
|
func TestPingSuccess(t *testing.T) {
|
|
client, err := New(WithMockClient(func(req *http.Request) (*http.Response, error) {
|
|
hdr := http.Header{}
|
|
hdr.Set("Api-Version", "awesome")
|
|
hdr.Set("Docker-Experimental", "true")
|
|
hdr.Set("Swarm", "active/manager")
|
|
return mockResponse(http.StatusOK, hdr, "OK")(req)
|
|
}))
|
|
assert.NilError(t, err)
|
|
ping, err := client.Ping(t.Context(), PingOptions{})
|
|
assert.NilError(t, err)
|
|
assert.Check(t, is.Equal(true, ping.Experimental))
|
|
assert.Check(t, is.Equal("awesome", ping.APIVersion))
|
|
assert.Check(t, is.Equal(SwarmStatus{NodeState: "active", ControlAvailable: true}, *ping.SwarmStatus))
|
|
}
|
|
|
|
// TestPingHeadFallback tests that the client falls back to GET if HEAD fails.
|
|
func TestPingHeadFallback(t *testing.T) {
|
|
const expectedPath = "/_ping"
|
|
expMethods := []string{http.MethodHead, http.MethodGet}
|
|
|
|
tests := []struct {
|
|
status int
|
|
expected []string
|
|
}{
|
|
{
|
|
status: http.StatusOK,
|
|
expected: []string{http.MethodHead},
|
|
},
|
|
{
|
|
status: http.StatusInternalServerError,
|
|
expected: []string{http.MethodHead, http.MethodGet},
|
|
},
|
|
{
|
|
status: http.StatusNotFound,
|
|
expected: []string{http.MethodHead, http.MethodGet},
|
|
},
|
|
{
|
|
status: http.StatusMethodNotAllowed,
|
|
expected: []string{http.MethodHead, http.MethodGet},
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(http.StatusText(tc.status), func(t *testing.T) {
|
|
var reqs []string
|
|
client, err := New(WithMockClient(func(req *http.Request) (*http.Response, error) {
|
|
if !strings.HasPrefix(req.URL.Path, expectedPath) {
|
|
return nil, fmt.Errorf("expected URL '%s', got '%s'", expectedPath, req.URL.Path)
|
|
}
|
|
if !slices.Contains(expMethods, req.Method) {
|
|
return nil, fmt.Errorf("expected one of '%v', got '%s'", expMethods, req.Method)
|
|
}
|
|
reqs = append(reqs, req.Method)
|
|
resp := &http.Response{StatusCode: http.StatusOK, Header: http.Header{}}
|
|
if req.Method == http.MethodHead {
|
|
resp.StatusCode = tc.status
|
|
}
|
|
resp.Header.Add("Api-Version", "1.2.3")
|
|
return resp, nil
|
|
}))
|
|
assert.NilError(t, err)
|
|
ping, _ := client.Ping(t.Context(), PingOptions{})
|
|
assert.Check(t, is.Equal(ping.APIVersion, "1.2.3"))
|
|
assert.Check(t, is.DeepEqual(reqs, tc.expected))
|
|
})
|
|
}
|
|
}
|