From 68571329114f739cdfa3715670b3656f8a54f247 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Fri, 14 Nov 2025 14:52:14 +0100 Subject: [PATCH] client: client.Ping: allow ForceNegotiate with manual override While a manual overridden version shouldn't perform automatic version negotiation, the "ForceNegotiate" option could still be used to (re) negotiate a version. This allows a client to be configured with an initial API version, then triggered to perform API-version negotiation. Signed-off-by: Sebastiaan van Stijn --- client/client_test.go | 15 ++++++++++++--- client/ping.go | 8 ++++---- vendor/github.com/moby/moby/client/ping.go | 8 ++++---- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/client/client_test.go b/client/client_test.go index b8133b5c27..2e9937c62a 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -437,19 +437,28 @@ func TestNegotiateAPIVersionWithEmptyVersion(t *testing.T) { // TestNegotiateAPIVersionWithFixedVersion asserts that initializing a client // with a fixed version disables API-version negotiation func TestNegotiateAPIVersionWithFixedVersion(t *testing.T) { - const customVersion = "1.50" + const ( + customVersion = "1.50" + pingVersion = "1.49" + ) client, err := New( WithAPIVersion(customVersion), - WithMockClient(mockResponse(http.StatusOK, http.Header{"Api-Version": []string{"1.49"}}, "OK")), + WithMockClient(mockResponse(http.StatusOK, http.Header{"Api-Version": []string{pingVersion}}, "OK")), ) assert.NilError(t, err) + _, err = client.Ping(t.Context(), PingOptions{ + NegotiateAPIVersion: true, + }) + assert.NilError(t, err) + assert.Check(t, is.Equal(client.ClientVersion(), customVersion)) + _, err = client.Ping(t.Context(), PingOptions{ NegotiateAPIVersion: true, ForceNegotiate: true, }) assert.NilError(t, err) - assert.Check(t, is.Equal(client.ClientVersion(), customVersion)) + assert.Check(t, is.Equal(client.ClientVersion(), pingVersion)) } // TestCustomAPIVersion tests initializing the client with a custom diff --git a/client/ping.go b/client/ping.go index 0fe9523766..8233c33e56 100644 --- a/client/ping.go +++ b/client/ping.go @@ -29,9 +29,8 @@ type PingOptions struct { NegotiateAPIVersion bool // ForceNegotiate forces the client to re-negotiate the API version, even if - // API-version negotiation already happened. This option cannot be - // used if the client is configured with a fixed version using (using - // [WithAPIVersion] or [WithAPIVersionFromEnv]). + // API-version negotiation already happened or it the client is configured + // with a fixed version (using [WithAPIVersion] or [WithAPIVersionFromEnv]). // // This option has no effect if NegotiateAPIVersion is not set. ForceNegotiate bool @@ -72,7 +71,8 @@ type SwarmStatus struct { // 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, options PingOptions) (PingResult, error) { - if cli.manualOverride { + if (cli.manualOverride || cli.negotiated.Load()) && !options.ForceNegotiate { + // API version was already negotiated or manually set. return cli.ping(ctx) } if !options.NegotiateAPIVersion && !cli.negotiateVersion { diff --git a/vendor/github.com/moby/moby/client/ping.go b/vendor/github.com/moby/moby/client/ping.go index 0fe9523766..8233c33e56 100644 --- a/vendor/github.com/moby/moby/client/ping.go +++ b/vendor/github.com/moby/moby/client/ping.go @@ -29,9 +29,8 @@ type PingOptions struct { NegotiateAPIVersion bool // ForceNegotiate forces the client to re-negotiate the API version, even if - // API-version negotiation already happened. This option cannot be - // used if the client is configured with a fixed version using (using - // [WithAPIVersion] or [WithAPIVersionFromEnv]). + // API-version negotiation already happened or it the client is configured + // with a fixed version (using [WithAPIVersion] or [WithAPIVersionFromEnv]). // // This option has no effect if NegotiateAPIVersion is not set. ForceNegotiate bool @@ -72,7 +71,8 @@ type SwarmStatus struct { // 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, options PingOptions) (PingResult, error) { - if cli.manualOverride { + if (cli.manualOverride || cli.negotiated.Load()) && !options.ForceNegotiate { + // API version was already negotiated or manually set. return cli.ping(ctx) } if !options.NegotiateAPIVersion && !cli.negotiateVersion {