mirror of https://github.com/docker/cli.git
always add but hide experimental cmds and flags
Signed-off-by: Victor Vieux <vieux@docker.com> update cobra and use Tags Signed-off-by: Victor Vieux <vieux@docker.com> allow client to talk to an older server Signed-off-by: Victor Vieux <vieux@docker.com>
This commit is contained in:
parent
3f7264473d
commit
4f63bfb619
15
client.go
15
client.go
|
@ -79,6 +79,8 @@ type Client struct {
|
|||
version string
|
||||
// custom http headers configured by users.
|
||||
customHTTPHeaders map[string]string
|
||||
// manualOverride is set to true when the version was set by users.
|
||||
manualOverride bool
|
||||
}
|
||||
|
||||
// NewEnvClient initializes a new API client based on environment variables.
|
||||
|
@ -111,13 +113,19 @@ func NewEnvClient() (*Client, error) {
|
|||
if host == "" {
|
||||
host = DefaultDockerHost
|
||||
}
|
||||
|
||||
version := os.Getenv("DOCKER_API_VERSION")
|
||||
if version == "" {
|
||||
version = DefaultVersion
|
||||
}
|
||||
|
||||
return NewClient(host, version, client, nil)
|
||||
cli, err := NewClient(host, version, client, nil)
|
||||
if err != nil {
|
||||
return cli, err
|
||||
}
|
||||
if version != "" {
|
||||
cli.manualOverride = true
|
||||
}
|
||||
return cli, nil
|
||||
}
|
||||
|
||||
// NewClient initializes a new API client for the given host and API version.
|
||||
|
@ -211,7 +219,10 @@ func (cli *Client) ClientVersion() string {
|
|||
// UpdateClientVersion updates the version string associated with this
|
||||
// instance of the Client.
|
||||
func (cli *Client) UpdateClientVersion(v string) {
|
||||
if !cli.manualOverride {
|
||||
cli.version = v
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ParseHost verifies that the given host strings is valid.
|
||||
|
|
|
@ -20,6 +20,11 @@ type configWrapper struct {
|
|||
// It can be associated with a name, but it's not mandatory.
|
||||
func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (container.ContainerCreateCreatedBody, error) {
|
||||
var response container.ContainerCreateCreatedBody
|
||||
|
||||
if err := cli.NewVersionError("1.25", "stop timeout"); config != nil && config.StopTimeout != nil && err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
query := url.Values{}
|
||||
if containerName != "" {
|
||||
query.Set("name", containerName)
|
||||
|
|
|
@ -10,6 +10,11 @@ import (
|
|||
// ContainerExecCreate creates a new exec configuration to run an exec process.
|
||||
func (cli *Client) ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.IDResponse, error) {
|
||||
var response types.IDResponse
|
||||
|
||||
if err := cli.NewVersionError("1.25", "env"); len(config.Env) != 0 && err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
resp, err := cli.post(ctx, "/containers/"+container+"/exec", nil, config, nil)
|
||||
if err != nil {
|
||||
return response, err
|
||||
|
|
|
@ -12,6 +12,10 @@ import (
|
|||
func (cli *Client) ContainersPrune(ctx context.Context, cfg types.ContainersPruneConfig) (types.ContainersPruneReport, error) {
|
||||
var report types.ContainersPruneReport
|
||||
|
||||
if err := cli.NewVersionError("1.25", "container prune"); err != nil {
|
||||
return report, err
|
||||
}
|
||||
|
||||
serverResp, err := cli.post(ctx, "/containers/prune", nil, cfg, nil)
|
||||
if err != nil {
|
||||
return report, err
|
||||
|
|
11
errors.go
11
errors.go
|
@ -3,6 +3,8 @@ package client
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
)
|
||||
|
||||
// ErrConnectionFailed is an error raised when the connection between the client and the server failed.
|
||||
|
@ -206,3 +208,12 @@ func IsErrPluginPermissionDenied(err error) bool {
|
|||
_, ok := err.(pluginPermissionDenied)
|
||||
return ok
|
||||
}
|
||||
|
||||
// NewVersionError returns an error if the APIVersion required
|
||||
// if less than the current supported version
|
||||
func (cli *Client) NewVersionError(APIrequired, feature string) error {
|
||||
if versions.LessThan(cli.version, APIrequired) {
|
||||
return fmt.Errorf("%q requires API version %s, but the Docker server is version %s", feature, APIrequired, cli.version)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ var headerRegexp = regexp.MustCompile(`\ADocker/.+\s\((.+)\)\z`)
|
|||
// The Body in the response implement an io.ReadCloser and it's up to the caller to
|
||||
// close it.
|
||||
func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
|
||||
query, err := imageBuildOptionsToQuery(options)
|
||||
query, err := cli.imageBuildOptionsToQuery(options)
|
||||
if err != nil {
|
||||
return types.ImageBuildResponse{}, err
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, optio
|
|||
}, nil
|
||||
}
|
||||
|
||||
func imageBuildOptionsToQuery(options types.ImageBuildOptions) (url.Values, error) {
|
||||
func (cli *Client) imageBuildOptionsToQuery(options types.ImageBuildOptions) (url.Values, error) {
|
||||
query := url.Values{
|
||||
"t": options.Tags,
|
||||
"securityopt": options.SecurityOpt,
|
||||
|
@ -76,6 +76,9 @@ func imageBuildOptionsToQuery(options types.ImageBuildOptions) (url.Values, erro
|
|||
}
|
||||
|
||||
if options.Squash {
|
||||
if err := cli.NewVersionError("1.25", "squash"); err != nil {
|
||||
return query, err
|
||||
}
|
||||
query.Set("squash", "1")
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,10 @@ import (
|
|||
func (cli *Client) ImagesPrune(ctx context.Context, cfg types.ImagesPruneConfig) (types.ImagesPruneReport, error) {
|
||||
var report types.ImagesPruneReport
|
||||
|
||||
if err := cli.NewVersionError("1.25", "image prune"); err != nil {
|
||||
return report, err
|
||||
}
|
||||
|
||||
serverResp, err := cli.post(ctx, "/images/prune", nil, cfg, nil)
|
||||
if err != nil {
|
||||
return report, err
|
||||
|
|
|
@ -129,7 +129,7 @@ type SystemAPIClient interface {
|
|||
Info(ctx context.Context) (types.Info, error)
|
||||
RegistryLogin(ctx context.Context, auth types.AuthConfig) (registry.AuthenticateOKBody, error)
|
||||
DiskUsage(ctx context.Context) (types.DiskUsage, error)
|
||||
Ping(ctx context.Context) (bool, error)
|
||||
Ping(ctx context.Context) (types.Ping, error)
|
||||
}
|
||||
|
||||
// VolumeAPIClient defines API client methods for the volumes
|
||||
|
|
29
ping.go
29
ping.go
|
@ -1,19 +1,30 @@
|
|||
package client
|
||||
|
||||
import "golang.org/x/net/context"
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
// Ping pings the server and return the value of the "Docker-Experimental" header
|
||||
func (cli *Client) Ping(ctx context.Context) (bool, error) {
|
||||
serverResp, err := cli.get(ctx, "/_ping", nil, nil)
|
||||
"github.com/docker/docker/api/types"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// Ping pings the server and return the value of the "Docker-Experimental" & "API-Version" headers
|
||||
func (cli *Client) Ping(ctx context.Context) (types.Ping, error) {
|
||||
var ping types.Ping
|
||||
req, err := cli.buildRequest("GET", fmt.Sprintf("%s/_ping", cli.basePath), nil, nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return ping, err
|
||||
}
|
||||
serverResp, err := cli.doRequest(ctx, req)
|
||||
if err != nil {
|
||||
return ping, err
|
||||
}
|
||||
defer ensureReaderClosed(serverResp)
|
||||
|
||||
exp := serverResp.header.Get("Docker-Experimental")
|
||||
if exp != "true" {
|
||||
return false, nil
|
||||
ping.APIVersion = serverResp.header.Get("API-Version")
|
||||
|
||||
if serverResp.header.Get("Docker-Experimental") == "true" {
|
||||
ping.Experimental = true
|
||||
}
|
||||
|
||||
return true, nil
|
||||
return ping, nil
|
||||
}
|
||||
|
|
|
@ -214,6 +214,9 @@ func (cli *Client) addHeaders(req *http.Request, headers headers) *http.Request
|
|||
// Add CLI Config's HTTP Headers BEFORE we set the Docker headers
|
||||
// then the user can't change OUR headers
|
||||
for k, v := range cli.customHTTPHeaders {
|
||||
if versions.LessThan(cli.version, "1.25") && k == "User-Agent" {
|
||||
continue
|
||||
}
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,10 @@ import (
|
|||
func (cli *Client) VolumesPrune(ctx context.Context, cfg types.VolumesPruneConfig) (types.VolumesPruneReport, error) {
|
||||
var report types.VolumesPruneReport
|
||||
|
||||
if err := cli.NewVersionError("1.25", "volume prune"); err != nil {
|
||||
return report, err
|
||||
}
|
||||
|
||||
serverResp, err := cli.post(ctx, "/volumes/prune", nil, cfg, nil)
|
||||
if err != nil {
|
||||
return report, err
|
||||
|
|
|
@ -3,15 +3,18 @@ package client
|
|||
import (
|
||||
"net/url"
|
||||
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// VolumeRemove removes a volume from the docker host.
|
||||
func (cli *Client) VolumeRemove(ctx context.Context, volumeID string, force bool) error {
|
||||
query := url.Values{}
|
||||
if versions.GreaterThanOrEqualTo(cli.version, "1.25") {
|
||||
if force {
|
||||
query.Set("force", "1")
|
||||
}
|
||||
}
|
||||
resp, err := cli.delete(ctx, "/volumes/"+volumeID, query, nil)
|
||||
ensureReaderClosed(resp)
|
||||
return err
|
||||
|
|
Loading…
Reference in New Issue