未验证 提交 2759b20b 编写于 作者: R runzexia

docker api version negotiation

Signed-off-by: Nrunzexia <runzexia@yunify.com>
上级 7c049a24
......@@ -27,7 +27,7 @@ require (
github.com/deckarep/golang-set v1.7.1 // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/docker/distribution v2.7.1+incompatible
github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0
github.com/docker/docker v1.4.2-0.20190822205725-ed20165a37b4
github.com/docker/go-connections v0.3.0 // indirect
github.com/docker/go-units v0.3.3 // indirect
github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c // indirect
......@@ -195,7 +195,7 @@ replace (
github.com/deckarep/golang-set => github.com/deckarep/golang-set v1.7.1
github.com/dgrijalva/jwt-go => github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/docker/distribution => github.com/docker/distribution v2.7.1+incompatible
github.com/docker/docker => github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0
github.com/docker/docker => github.com/docker/engine v1.4.2-0.20190822205725-ed20165a37b4
github.com/docker/go-connections => github.com/docker/go-connections v0.3.0
github.com/docker/go-units => github.com/docker/go-units v0.3.3
github.com/docker/spdystream => github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c
......
......@@ -55,7 +55,7 @@ type DockerConfigEntry struct {
func RegistryVerify(authInfo AuthInfo) error {
auth := base64.StdEncoding.EncodeToString([]byte(authInfo.Username + ":" + authInfo.Password))
ctx := context.Background()
cli, err := client.NewEnvClient()
cli, err := client.NewClientWithOpts(client.WithAPIVersionNegotiation())
if err != nil {
glog.Error(err)
......
......@@ -44,7 +44,7 @@ Ajey Charantimath <ajey.charantimath@gmail.com>
ajneu <ajneu@users.noreply.github.com>
Akash Gupta <akagup@microsoft.com>
Akihiro Matsushima <amatsusbit@gmail.com>
Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
Akim Demaille <akim.demaille@docker.com>
Akira Koyasu <mail@akirakoyasu.net>
Akshay Karle <akshay.a.karle@gmail.com>
......@@ -81,6 +81,7 @@ Alexandre Garnier <zigarn@gmail.com>
Alexandre González <agonzalezro@gmail.com>
Alexandre Jomin <alexandrejomin@gmail.com>
Alexandru Sfirlogea <alexandru.sfirlogea@gmail.com>
Alexei Margasov <alexei38@yandex.ru>
Alexey Guskov <lexag@mail.ru>
Alexey Kotlyarov <alexey@infoxchange.net.au>
Alexey Shamrin <shamrin@gmail.com>
......@@ -153,6 +154,7 @@ Andy Wilson <wilson.andrew.j+github@gmail.com>
Anes Hasicic <anes.hasicic@gmail.com>
Anil Belur <askb23@gmail.com>
Anil Madhavapeddy <anil@recoil.org>
Ankit Jain <ajatkj@yahoo.co.in>
Ankush Agarwal <ankushagarwal11@gmail.com>
Anonmily <michelle@michelleliu.io>
Anran Qiao <anran.qiao@daocloud.io>
......@@ -184,6 +186,7 @@ Asad Saeeduddin <masaeedu@gmail.com>
Asbjørn Enge <asbjorn@hanafjedle.net>
averagehuman <averagehuman@users.noreply.github.com>
Avi Das <andas222@gmail.com>
Avi Kivity <avi@scylladb.com>
Avi Miller <avi.miller@oracle.com>
Avi Vaid <avaid1996@gmail.com>
ayoshitake <airandfingers@gmail.com>
......@@ -507,6 +510,7 @@ Dmitri Shuralyov <shurcooL@gmail.com>
Dmitry Demeshchuk <demeshchuk@gmail.com>
Dmitry Gusev <dmitry.gusev@gmail.com>
Dmitry Kononenko <d@dm42.ru>
Dmitry Sharshakov <d3dx12.xx@gmail.com>
Dmitry Shyshkin <dmitry@shyshkin.org.ua>
Dmitry Smirnov <onlyjob@member.fsf.org>
Dmitry V. Krivenok <krivenok.dmitry@gmail.com>
......@@ -656,6 +660,7 @@ Frederik Loeffert <frederik@zitrusmedia.de>
Frederik Nordahl Jul Sabroe <frederikns@gmail.com>
Freek Kalter <freek@kalteronline.org>
Frieder Bluemle <frieder.bluemle@gmail.com>
Fu JinLin <withlin@yeah.net>
Félix Baylac-Jacqué <baylac.felix@gmail.com>
Félix Cantournet <felix.cantournet@cloudwatt.com>
Gabe Rosenhouse <gabe@missionst.com>
......@@ -688,6 +693,7 @@ Ghislain Bourgeois <ghislain.bourgeois@gmail.com>
Giampaolo Mancini <giampaolo@trampolineup.com>
Gianluca Borello <g.borello@gmail.com>
Gildas Cuisinier <gildas.cuisinier@gcuisinier.net>
Giovan Isa Musthofa <giovanism@outlook.co.id>
gissehel <public-devgit-dantus@gissehel.org>
Giuseppe Mazzotta <gdm85@users.noreply.github.com>
Gleb Fotengauer-Malinovskiy <glebfm@altlinux.org>
......@@ -898,6 +904,7 @@ Jimmy Cuadra <jimmy@jimmycuadra.com>
Jimmy Puckett <jimmy.puckett@spinen.com>
Jimmy Song <rootsongjc@gmail.com>
Jinsoo Park <cellpjs@gmail.com>
Jintao Zhang <zhangjintao9020@gmail.com>
Jiri Appl <jiria@microsoft.com>
Jiri Popelka <jpopelka@redhat.com>
Jiuyue Ma <majiuyue@huawei.com>
......@@ -1079,6 +1086,7 @@ Kunal Kushwaha <kushwaha_kunal_v7@lab.ntt.co.jp>
Kunal Tyagi <tyagi.kunal@live.com>
Kyle Conroy <kyle.j.conroy@gmail.com>
Kyle Linden <linden.kyle@gmail.com>
Kyle Wuolle <kyle.wuolle@gmail.com>
kyu <leehk1227@gmail.com>
Lachlan Coote <lcoote@vmware.com>
Lai Jiangshan <jiangshanlai@gmail.com>
......@@ -1255,6 +1263,7 @@ Maxim Kulkin <mkulkin@mirantis.com>
Maxim Treskin <zerthurd@gmail.com>
Maxime Petazzoni <max@signalfuse.com>
Maximiliano Maccanti <maccanti@amazon.com>
Maxwell <csuhp007@gmail.com>
Meaglith Ma <genedna@gmail.com>
meejah <meejah@meejah.ca>
Megan Kostick <mkostick@us.ibm.com>
......@@ -1519,6 +1528,7 @@ Quentin Brossard <qbrossard@gmail.com>
Quentin Perez <qperez@ocs.online.net>
Quentin Tayssier <qtayssier@gmail.com>
r0n22 <cameron.regan@gmail.com>
Radostin Stoyanov <rstoyanov1@gmail.com>
Rafal Jeczalik <rjeczalik@gmail.com>
Rafe Colton <rafael.colton@gmail.com>
Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
......@@ -1976,6 +1986,7 @@ xamyzhao <x.amy.zhao@gmail.com>
Xian Chaobo <xianchaobo@huawei.com>
Xianglin Gao <xlgao@zju.edu.cn>
Xianlu Bird <xianlubird@gmail.com>
Xiao YongBiao <xyb4638@gmail.com>
XiaoBing Jiang <s7v7nislands@gmail.com>
Xiaodong Zhang <a4012017@sina.com>
Xiaoxi He <xxhe@alauda.io>
......
......@@ -463,10 +463,6 @@ definitions:
type: "array"
items:
$ref: "#/definitions/DeviceRequest"
DiskQuota:
description: "Disk limit (in bytes)."
type: "integer"
format: "int64"
KernelMemory:
description: "Kernel memory limit in bytes."
type: "integer"
......@@ -1145,6 +1141,7 @@ definitions:
type: "object"
additionalProperties:
type: "array"
x-nullable: true
items:
$ref: "#/definitions/PortBinding"
example:
......@@ -1169,7 +1166,6 @@ definitions:
PortBinding represents a binding between a host IP address and a host
port.
type: "object"
x-nullable: true
properties:
HostIp:
description: "Host IP address that the container's port is mapped to."
......@@ -3809,7 +3805,7 @@ definitions:
description: |
The driver to use for managing cgroups.
type: "string"
enum: ["cgroupfs", "systemd"]
enum: ["cgroupfs", "systemd", "none"]
default: "cgroupfs"
example: "cgroupfs"
NEventsListener:
......@@ -4044,7 +4040,7 @@ definitions:
SecurityOptions:
description: |
List of security features that are enabled on the daemon, such as
apparmor, seccomp, SELinux, and user-namespaces (userns).
apparmor, seccomp, SELinux, user-namespaces (userns), and rootless.
Additional configuration options for each security feature may
be present, and are included as a comma-separated list of key/value
......@@ -4057,6 +4053,7 @@ definitions:
- "name=seccomp,profile=default"
- "name=selinux"
- "name=userns"
- "name=rootless"
ProductLicense:
description: |
Reports a summary of the product license on the daemon.
......@@ -4611,9 +4608,9 @@ paths:
parameters:
- name: "name"
in: "query"
description: "Assign the specified name to the container. Must match `/?[a-zA-Z0-9_-]+`."
description: "Assign the specified name to the container. Must match `/?[a-zA-Z0-9][a-zA-Z0-9_.-]+`."
type: "string"
pattern: "/?[a-zA-Z0-9_-]+"
pattern: "^/?[a-zA-Z0-9][a-zA-Z0-9_.-]+$"
- name: "body"
in: "body"
description: "Container to create"
......@@ -5177,15 +5174,15 @@ paths:
Note: This endpoint works only for containers with the `json-file` or `journald` logging driver.
operationId: "ContainerLogs"
responses:
101:
description: "logs returned as a stream"
schema:
type: "string"
format: "binary"
200:
description: "logs returned as a string in response body"
description: |
logs returned as a stream in response body.
For the stream format, [see the documentation for the attach endpoint](#operation/ContainerAttach).
Note that unlike the attach endpoint, the logs endpoint does not upgrade the connection and does not
set Content-Type.
schema:
type: "string"
format: "binary"
404:
description: "no such container"
schema:
......@@ -5205,10 +5202,7 @@ paths:
type: "string"
- name: "follow"
in: "query"
description: |
Return the logs as a stream.
This will return a `101` HTTP response with a `Connection: upgrade` header, then hijack the HTTP connection to send raw output. For more information about hijacking and the stream format, [see the documentation for the attach endpoint](#operation/ContainerAttach).
description: "Keep connection after returning logs."
type: "boolean"
default: false
- name: "stdout"
......@@ -5469,7 +5463,7 @@ paths:
/containers/{id}/resize:
post:
summary: "Resize a container TTY"
description: "Resize the TTY for a container. You must restart the container for the resize to take effect."
description: "Resize the TTY for a container."
operationId: "ContainerResize"
consumes:
- "application/octet-stream"
......@@ -6223,12 +6217,17 @@ paths:
in: "query"
description: "If “1”, “true”, or “True” then it will be an error if unpacking the given content would cause an existing directory to be replaced with a non-directory and vice versa."
type: "string"
- name: "copyUIDGID"
in: "query"
description: "If “1”, “true”, then it will copy UID/GID maps to the dest file or dir"
type: "string"
- name: "inputStream"
in: "body"
required: true
description: "The input stream must be a tar archive compressed with one of the following algorithms: identity (no compression), gzip, bzip2, xz."
schema:
type: "string"
format: "binary"
tags: ["Container"]
/containers/prune:
post:
......@@ -9113,6 +9112,8 @@ paths:
type: "string"
RemoteAddrs:
description: "Addresses of manager nodes already participating in the swarm."
type: "array"
items:
type: "string"
JoinToken:
description: "Secret token for joining this swarm."
......@@ -9569,23 +9570,16 @@ paths:
get:
summary: "Get service logs"
description: |
Get `stdout` and `stderr` logs from a service.
Get `stdout` and `stderr` logs from a service. See also [`/containers/{id}/logs`](#operation/ContainerLogs).
**Note**: This endpoint works only for services with the `json-file` or `journald` logging drivers.
**Note**: This endpoint works only for services with the `local`, `json-file` or `journald` logging drivers.
operationId: "ServiceLogs"
produces:
- "application/vnd.docker.raw-stream"
- "application/json"
responses:
101:
description: "logs returned as a stream"
schema:
type: "string"
format: "binary"
200:
description: "logs returned as a string in response body"
description: "logs returned as a stream in response body"
schema:
type: "string"
format: "binary"
404:
description: "no such service"
schema:
......@@ -9614,10 +9608,7 @@ paths:
default: false
- name: "follow"
in: "query"
description: |
Return the logs as a stream.
This will return a `101` HTTP response with a `Connection: upgrade` header, then hijack the HTTP connection to send raw output. For more information about hijacking and the stream format, [see the documentation for the attach endpoint](#operation/ContainerAttach).
description: "Keep connection after returning logs."
type: "boolean"
default: false
- name: "stdout"
......@@ -9826,23 +9817,16 @@ paths:
get:
summary: "Get task logs"
description: |
Get `stdout` and `stderr` logs from a task.
Get `stdout` and `stderr` logs from a task. See also [`/containers/{id}/logs`](#operation/ContainerLogs).
**Note**: This endpoint works only for services with the `json-file` or `journald` logging drivers.
**Note**: This endpoint works only for services with the `local`, `json-file` or `journald` logging drivers.
operationId: "TaskLogs"
produces:
- "application/vnd.docker.raw-stream"
- "application/json"
responses:
101:
description: "logs returned as a stream"
schema:
type: "string"
format: "binary"
200:
description: "logs returned as a string in response body"
description: "logs returned as a stream in response body"
schema:
type: "string"
format: "binary"
404:
description: "no such task"
schema:
......@@ -9871,10 +9855,7 @@ paths:
default: false
- name: "follow"
in: "query"
description: |
Return the logs as a stream.
This will return a `101` HTTP response with a `Connection: upgrade` header, then hijack the HTTP connection to send raw output. For more information about hijacking and the stream format, [see the documentation for the attach endpoint](#operation/ContainerAttach).
description: "Keep connection after returning logs."
type: "boolean"
default: false
- name: "stdout"
......
package container
package container // import "github.com/docker/docker/api/types/container"
// ----------------------------------------------------------------------------
// DO NOT EDIT THIS FILE
......
package container
package container // import "github.com/docker/docker/api/types/container"
// ----------------------------------------------------------------------------
// DO NOT EDIT THIS FILE
......
package container
package container // import "github.com/docker/docker/api/types/container"
// ----------------------------------------------------------------------------
// DO NOT EDIT THIS FILE
......
package container
package container // import "github.com/docker/docker/api/types/container"
// ----------------------------------------------------------------------------
// DO NOT EDIT THIS FILE
......
package container
package container // import "github.com/docker/docker/api/types/container"
// ----------------------------------------------------------------------------
// DO NOT EDIT THIS FILE
......
......@@ -338,7 +338,6 @@ type Resources struct {
Devices []DeviceMapping // List of devices to map inside the container
DeviceCgroupRules []string // List of rule to be added to the device cgroup
DeviceRequests []DeviceRequest // List of device requests for device drivers
DiskQuota int64 // Disk limit (in bytes)
KernelMemory int64 // Kernel memory limit (in bytes)
KernelMemoryTCP int64 // Hard limit for kernel TCP buffer memory (in bytes)
MemoryReservation int64 // Memory soft limit (in bytes)
......
......@@ -5,7 +5,6 @@ package filters // import "github.com/docker/docker/api/types/filters"
import (
"encoding/json"
"errors"
"regexp"
"strings"
......@@ -37,41 +36,6 @@ func NewArgs(initialArgs ...KeyValuePair) Args {
return args
}
// ParseFlag parses a key=value string and adds it to an Args.
//
// Deprecated: Use Args.Add()
func ParseFlag(arg string, prev Args) (Args, error) {
filters := prev
if len(arg) == 0 {
return filters, nil
}
if !strings.Contains(arg, "=") {
return filters, ErrBadFormat
}
f := strings.SplitN(arg, "=", 2)
name := strings.ToLower(strings.TrimSpace(f[0]))
value := strings.TrimSpace(f[1])
filters.Add(name, value)
return filters, nil
}
// ErrBadFormat is an error returned when a filter is not in the form key=value
//
// Deprecated: this error will be removed in a future version
var ErrBadFormat = errors.New("bad format of filter (expected name=value)")
// ToParam encodes the Args as args JSON encoded string
//
// Deprecated: use ToJSON
func ToParam(a Args) (string, error) {
return ToJSON(a)
}
// MarshalJSON returns a JSON byte representation of the Args
func (args Args) MarshalJSON() ([]byte, error) {
if len(args.fields) == 0 {
......@@ -107,13 +71,6 @@ func ToParamWithVersion(version string, a Args) (string, error) {
return ToJSON(a)
}
// FromParam decodes a JSON encoded string into Args
//
// Deprecated: use FromJSON
func FromParam(p string) (Args, error) {
return FromJSON(p)
}
// FromJSON decodes a JSON encoded string into Args
func FromJSON(p string) (Args, error) {
args := NewArgs()
......@@ -275,14 +232,6 @@ func (args Args) FuzzyMatch(key, source string) bool {
return false
}
// Include returns true if the key exists in the mapping
//
// Deprecated: use Contains
func (args Args) Include(field string) bool {
_, ok := args.fields[field]
return ok
}
// Contains returns true if the key exists in the mapping
func (args Args) Contains(field string) bool {
_, ok := args.fields[field]
......
package image
package image // import "github.com/docker/docker/api/types/image"
// ----------------------------------------------------------------------------
// DO NOT EDIT THIS FILE
......
package volume
package volume // import "github.com/docker/docker/api/types/volume"
// ----------------------------------------------------------------------------
// DO NOT EDIT THIS FILE
......
package volume
package volume // import "github.com/docker/docker/api/types/volume"
// ----------------------------------------------------------------------------
// DO NOT EDIT THIS FILE
......
......@@ -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:
......@@ -107,7 +116,7 @@ func CheckRedirect(req *http.Request, via []*http.Request) error {
// It won't send any version information if the version number is empty. It is
// highly recommended that you set a version or your client may break if the
// server is upgraded.
func NewClientWithOpts(ops ...func(*Client) error) (*Client, error) {
func NewClientWithOpts(ops ...Opt) (*Client, error) {
client, err := defaultHTTPClient(DefaultDockerHost)
if err != nil {
return nil, err
......@@ -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) {
if !cli.manualOverride {
ping, _ := cli.Ping(ctx)
cli.NegotiateAPIVersionPing(ping)
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
......
......@@ -23,7 +23,7 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu
return types.HijackedResponse{}, err
}
apiPath := cli.getAPIPath(path, query)
apiPath := cli.getAPIPath(ctx, path, query)
req, err := http.NewRequest("POST", apiPath, bodyEncoded)
if err != nil {
return types.HijackedResponse{}, err
......@@ -38,6 +38,17 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu
return types.HijackedResponse{Conn: conn, Reader: bufio.NewReader(conn)}, err
}
// DialHijack returns a hijacked connection with negotiated protocol proto.
func (cli *Client) DialHijack(ctx context.Context, url, proto string, meta map[string][]string) (net.Conn, error) {
req, err := http.NewRequest("POST", url, nil)
if err != nil {
return nil, err
}
req = cli.addHeaders(req, meta)
return cli.setupHijackConn(ctx, req, proto)
}
// fallbackDial is used when WithDialer() was not called.
// See cli.Dialer().
func fallbackDial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) {
......
......@@ -38,7 +38,7 @@ type CommonAPIClient interface {
ServerVersion(ctx context.Context) (types.Version, error)
NegotiateAPIVersion(ctx context.Context)
NegotiateAPIVersionPing(types.Ping)
DialSession(ctx context.Context, proto string, meta map[string][]string) (net.Conn, error)
DialHijack(ctx context.Context, url, proto string, meta map[string][]string) (net.Conn, error)
Dialer() func(context.Context) (net.Conn, error)
Close() error
}
......
......@@ -6,12 +6,16 @@ import (
"net/http"
"os"
"path/filepath"
"time"
"github.com/docker/go-connections/sockets"
"github.com/docker/go-connections/tlsconfig"
"github.com/pkg/errors"
)
// Opt is a configuration option to initialize a client
type Opt func(*Client) error
// FromEnv configures the client with values from environment variables.
//
// Supported environment variables:
......@@ -55,13 +59,13 @@ func FromEnv(c *Client) error {
// WithDialer applies the dialer.DialContext to the client transport. This can be
// used to set the Timeout and KeepAlive settings of the client.
// Deprecated: use WithDialContext
func WithDialer(dialer *net.Dialer) func(*Client) error {
func WithDialer(dialer *net.Dialer) Opt {
return WithDialContext(dialer.DialContext)
}
// WithDialContext applies the dialer to the client transport. This can be
// used to set the Timeout and KeepAlive settings of the client.
func WithDialContext(dialContext func(ctx context.Context, network, addr string) (net.Conn, error)) func(*Client) error {
func WithDialContext(dialContext func(ctx context.Context, network, addr string) (net.Conn, error)) Opt {
return func(c *Client) error {
if transport, ok := c.client.Transport.(*http.Transport); ok {
transport.DialContext = dialContext
......@@ -72,7 +76,7 @@ func WithDialContext(dialContext func(ctx context.Context, network, addr string)
}
// WithHost overrides the client host with the specified one.
func WithHost(host string) func(*Client) error {
func WithHost(host string) Opt {
return func(c *Client) error {
hostURL, err := ParseHostURL(host)
if err != nil {
......@@ -90,7 +94,7 @@ func WithHost(host string) func(*Client) error {
}
// WithHTTPClient overrides the client http client with the specified one
func WithHTTPClient(client *http.Client) func(*Client) error {
func WithHTTPClient(client *http.Client) Opt {
return func(c *Client) error {
if client != nil {
c.client = client
......@@ -99,8 +103,16 @@ func WithHTTPClient(client *http.Client) func(*Client) error {
}
}
// WithTimeout configures the time limit for requests made by the HTTP client
func WithTimeout(timeout time.Duration) Opt {
return func(c *Client) error {
c.client.Timeout = timeout
return nil
}
}
// WithHTTPHeaders overrides the client default http headers
func WithHTTPHeaders(headers map[string]string) func(*Client) error {
func WithHTTPHeaders(headers map[string]string) Opt {
return func(c *Client) error {
c.customHTTPHeaders = headers
return nil
......@@ -108,7 +120,7 @@ func WithHTTPHeaders(headers map[string]string) func(*Client) error {
}
// WithScheme overrides the client scheme with the specified one
func WithScheme(scheme string) func(*Client) error {
func WithScheme(scheme string) Opt {
return func(c *Client) error {
c.scheme = scheme
return nil
......@@ -116,7 +128,7 @@ func WithScheme(scheme string) func(*Client) error {
}
// WithTLSClientConfig applies a tls config to the client transport.
func WithTLSClientConfig(cacertPath, certPath, keyPath string) func(*Client) error {
func WithTLSClientConfig(cacertPath, certPath, keyPath string) Opt {
return func(c *Client) error {
opts := tlsconfig.Options{
CAFile: cacertPath,
......@@ -136,11 +148,25 @@ func WithTLSClientConfig(cacertPath, certPath, keyPath string) func(*Client) err
}
}
// WithVersion overrides the client version with the specified one
func WithVersion(version string) func(*Client) error {
// WithVersion overrides the client version with the specified one. If an empty
// version is specified, the value will be ignored to allow version negotiation.
func WithVersion(version string) Opt {
return func(c *Client) error {
if version != "" {
c.version = version
c.manualOverride = true
}
return nil
}
}
// WithAPIVersionNegotiation enables automatic API version negotiation for the client.
// With this option enabled, the client automatically negotiates the API version
// to use when making requests. API version negotiation is performed on the first
// request; subsequent requests will not re-negotiate.
func WithAPIVersionNegotiation() Opt {
return func(c *Client) error {
c.negotiateVersion = true
return nil
}
}
......@@ -31,6 +31,8 @@ func (cli *Client) Ping(ctx context.Context) (types.Ping, error) {
// Server handled the request, so parse the response
return parsePingResponse(cli, serverResp)
}
} else if IsErrConnectionFailed(err) {
return ping, err
}
req, err = cli.buildRequest("GET", path.Join(cli.basePath, "/_ping"), nil, nil)
......
......@@ -115,7 +115,7 @@ func (cli *Client) buildRequest(method, path string, body io.Reader, headers hea
}
func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, body io.Reader, headers headers) (serverResponse, error) {
req, err := cli.buildRequest(method, cli.getAPIPath(path, query), body, headers)
req, err := cli.buildRequest(method, cli.getAPIPath(ctx, path, query), body, headers)
if err != nil {
return serverResponse{}, err
}
......
package client // import "github.com/docker/docker/client"
import (
"context"
"net"
"net/http"
)
// DialSession returns a connection that can be used communication with daemon
func (cli *Client) DialSession(ctx context.Context, proto string, meta map[string][]string) (net.Conn, error) {
req, err := http.NewRequest("POST", "/session", nil)
if err != nil {
return nil, err
}
req = cli.addHeaders(req, meta)
return cli.setupHijackConn(ctx, req, proto)
}
......@@ -118,7 +118,7 @@ github.com/docker/distribution/manifest
github.com/docker/distribution/manifest/schema2
github.com/docker/distribution/reference
github.com/docker/distribution/registry/api/errcode
# github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0 => github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0
# github.com/docker/docker v1.4.2-0.20190822205725-ed20165a37b4 => github.com/docker/engine v1.4.2-0.20190822205725-ed20165a37b4
github.com/docker/docker/api
github.com/docker/docker/api/types
github.com/docker/docker/api/types/blkiodev
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册