|
@@ -81,6 +81,15 @@ type Client struct {
|
|
|
customHTTPHeaders map[string]string
|
|
|
// manualOverride is set to true when the version was set by users.
|
|
|
manualOverride bool
|
|
|
+
|
|
|
+ // negotiateVersion indicates if the client should automatically negotiate
|
|
|
+ // the API version to use when making requests. API version negotiation is
|
|
|
+ // performed on the first request, after which negotiated is set to "true"
|
|
|
+ // so that subsequent requests do not re-negotiate.
|
|
|
+ negotiateVersion bool
|
|
|
+
|
|
|
+ // negotiated indicates that API version negotiation took place
|
|
|
+ negotiated bool
|
|
|
}
|
|
|
|
|
|
// CheckRedirect specifies the policy for dealing with redirect responses:
|
|
@@ -169,8 +178,11 @@ func (cli *Client) Close() error {
|
|
|
|
|
|
// getAPIPath returns the versioned request path to call the api.
|
|
|
// It appends the query parameters to the path if they are not empty.
|
|
|
-func (cli *Client) getAPIPath(p string, query url.Values) string {
|
|
|
+func (cli *Client) getAPIPath(ctx context.Context, p string, query url.Values) string {
|
|
|
var apiPath string
|
|
|
+ if cli.negotiateVersion && !cli.negotiated {
|
|
|
+ cli.NegotiateAPIVersion(ctx)
|
|
|
+ }
|
|
|
if cli.version != "" {
|
|
|
v := strings.TrimPrefix(cli.version, "v")
|
|
|
apiPath = path.Join(cli.basePath, "/v"+v, p)
|
|
@@ -186,19 +198,31 @@ func (cli *Client) ClientVersion() string {
|
|
|
}
|
|
|
|
|
|
// NegotiateAPIVersion queries the API and updates the version to match the
|
|
|
-// API version. Any errors are silently ignored.
|
|
|
+// API version. Any errors are silently ignored. If a manual override is in place,
|
|
|
+// either through the `DOCKER_API_VERSION` environment variable, or if the client
|
|
|
+// was initialized with a fixed version (`opts.WithVersion(xx)`), no negotiation
|
|
|
+// will be performed.
|
|
|
func (cli *Client) NegotiateAPIVersion(ctx context.Context) {
|
|
|
- ping, _ := cli.Ping(ctx)
|
|
|
- cli.NegotiateAPIVersionPing(ping)
|
|
|
+ if !cli.manualOverride {
|
|
|
+ ping, _ := cli.Ping(ctx)
|
|
|
+ cli.negotiateAPIVersionPing(ping)
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// NegotiateAPIVersionPing updates the client version to match the Ping.APIVersion
|
|
|
-// if the ping version is less than the default version.
|
|
|
+// if the ping version is less than the default version. If a manual override is
|
|
|
+// in place, either through the `DOCKER_API_VERSION` environment variable, or if
|
|
|
+// the client was initialized with a fixed version (`opts.WithVersion(xx)`), no
|
|
|
+// negotiation is performed.
|
|
|
func (cli *Client) NegotiateAPIVersionPing(p types.Ping) {
|
|
|
- if cli.manualOverride {
|
|
|
- return
|
|
|
+ if !cli.manualOverride {
|
|
|
+ cli.negotiateAPIVersionPing(p)
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
+// negotiateAPIVersionPing queries the API and updates the version to match the
|
|
|
+// API version. Any errors are silently ignored.
|
|
|
+func (cli *Client) negotiateAPIVersionPing(p types.Ping) {
|
|
|
// try the latest version before versioning headers existed
|
|
|
if p.APIVersion == "" {
|
|
|
p.APIVersion = "1.24"
|
|
@@ -213,6 +237,12 @@ func (cli *Client) NegotiateAPIVersionPing(p types.Ping) {
|
|
|
if versions.LessThan(p.APIVersion, cli.version) {
|
|
|
cli.version = p.APIVersion
|
|
|
}
|
|
|
+
|
|
|
+ // Store the results, so that automatic API version negotiation (if enabled)
|
|
|
+ // won't be performed on the next request.
|
|
|
+ if cli.negotiateVersion {
|
|
|
+ cli.negotiated = true
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// DaemonHost returns the host address used by the client
|