client: negotiate api version before handling version-specific code
We try to perform API-version negotiation as lazy as possible (and only execute when we are about to make an API request). However, some code requires API-version dependent handling (to set options, or remove options based on the version of the API we're using). Currently this code depended on the caller code to perform API negotiation (or to configure the API version) first, which may not happen, and because of that we may be missing options (or set options that are not supported on older API versions). This patch: - splits the code that triggered API-version negotiation to a separate Client.checkVersion() function. - updates NewVersionError to accept a context - updates NewVersionError to perform API-version negotiation (if enabled) - updates various Client functions to manually trigger API-version negotiation Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
7cfb81ba04
commit
e6907243af
31 changed files with 126 additions and 38 deletions
|
@ -13,7 +13,7 @@ import (
|
||||||
|
|
||||||
// BuildCachePrune requests the daemon to delete unused cache data
|
// BuildCachePrune requests the daemon to delete unused cache data
|
||||||
func (cli *Client) BuildCachePrune(ctx context.Context, opts types.BuildCachePruneOptions) (*types.BuildCachePruneReport, error) {
|
func (cli *Client) BuildCachePrune(ctx context.Context, opts types.BuildCachePruneOptions) (*types.BuildCachePruneReport, error) {
|
||||||
if err := cli.NewVersionError("1.31", "build prune"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.31", "build prune"); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -254,13 +254,21 @@ func (cli *Client) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkVersion manually triggers API version negotiation (if configured).
|
||||||
|
// This allows for version-dependent code to use the same version as will
|
||||||
|
// be negotiated when making the actual requests, and for which cases
|
||||||
|
// we cannot do the negotiation lazily.
|
||||||
|
func (cli *Client) checkVersion(ctx context.Context) {
|
||||||
|
if cli.negotiateVersion && !cli.negotiated {
|
||||||
|
cli.NegotiateAPIVersion(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// getAPIPath returns the versioned request path to call the API.
|
// getAPIPath returns the versioned request path to call the API.
|
||||||
// It appends the query parameters to the path if they are not empty.
|
// It appends the query parameters to the path if they are not empty.
|
||||||
func (cli *Client) getAPIPath(ctx context.Context, p string, query url.Values) string {
|
func (cli *Client) getAPIPath(ctx context.Context, p string, query url.Values) string {
|
||||||
var apiPath string
|
var apiPath string
|
||||||
if cli.negotiateVersion && !cli.negotiated {
|
cli.checkVersion(ctx)
|
||||||
cli.NegotiateAPIVersion(ctx)
|
|
||||||
}
|
|
||||||
if cli.version != "" {
|
if cli.version != "" {
|
||||||
v := strings.TrimPrefix(cli.version, "v")
|
v := strings.TrimPrefix(cli.version, "v")
|
||||||
apiPath = path.Join(cli.basePath, "/v"+v, p)
|
apiPath = path.Join(cli.basePath, "/v"+v, p)
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
// ConfigCreate creates a new config.
|
// ConfigCreate creates a new config.
|
||||||
func (cli *Client) ConfigCreate(ctx context.Context, config swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
|
func (cli *Client) ConfigCreate(ctx context.Context, config swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
|
||||||
var response types.ConfigCreateResponse
|
var response types.ConfigCreateResponse
|
||||||
if err := cli.NewVersionError("1.30", "config create"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.30", "config create"); err != nil {
|
||||||
return response, err
|
return response, err
|
||||||
}
|
}
|
||||||
resp, err := cli.post(ctx, "/configs/create", nil, config, nil)
|
resp, err := cli.post(ctx, "/configs/create", nil, config, nil)
|
||||||
|
|
|
@ -14,7 +14,7 @@ func (cli *Client) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.C
|
||||||
if id == "" {
|
if id == "" {
|
||||||
return swarm.Config{}, nil, objectNotFoundError{object: "config", id: id}
|
return swarm.Config{}, nil, objectNotFoundError{object: "config", id: id}
|
||||||
}
|
}
|
||||||
if err := cli.NewVersionError("1.30", "config inspect"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.30", "config inspect"); err != nil {
|
||||||
return swarm.Config{}, nil, err
|
return swarm.Config{}, nil, err
|
||||||
}
|
}
|
||||||
resp, err := cli.get(ctx, "/configs/"+id, nil, nil)
|
resp, err := cli.get(ctx, "/configs/"+id, nil, nil)
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
|
|
||||||
// ConfigList returns the list of configs.
|
// ConfigList returns the list of configs.
|
||||||
func (cli *Client) ConfigList(ctx context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
|
func (cli *Client) ConfigList(ctx context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||||
if err := cli.NewVersionError("1.30", "config list"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.30", "config list"); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
query := url.Values{}
|
query := url.Values{}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import "context"
|
||||||
|
|
||||||
// ConfigRemove removes a config.
|
// ConfigRemove removes a config.
|
||||||
func (cli *Client) ConfigRemove(ctx context.Context, id string) error {
|
func (cli *Client) ConfigRemove(ctx context.Context, id string) error {
|
||||||
if err := cli.NewVersionError("1.30", "config remove"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.30", "config remove"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
resp, err := cli.delete(ctx, "/configs/"+id, nil, nil)
|
resp, err := cli.delete(ctx, "/configs/"+id, nil, nil)
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
|
|
||||||
// ConfigUpdate attempts to update a config
|
// ConfigUpdate attempts to update a config
|
||||||
func (cli *Client) ConfigUpdate(ctx context.Context, id string, version swarm.Version, config swarm.ConfigSpec) error {
|
func (cli *Client) ConfigUpdate(ctx context.Context, id string, version swarm.Version, config swarm.ConfigSpec) error {
|
||||||
if err := cli.NewVersionError("1.30", "config update"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.30", "config update"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
query := url.Values{}
|
query := url.Values{}
|
||||||
|
|
|
@ -23,13 +23,20 @@ type configWrapper struct {
|
||||||
func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error) {
|
func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error) {
|
||||||
var response container.CreateResponse
|
var response container.CreateResponse
|
||||||
|
|
||||||
if err := cli.NewVersionError("1.25", "stop timeout"); config != nil && config.StopTimeout != nil && err != nil {
|
// Make sure we negotiated (if the client is configured to do so),
|
||||||
|
// as code below contains API-version specific handling of options.
|
||||||
|
//
|
||||||
|
// Normally, version-negotiation (if enabled) would not happen until
|
||||||
|
// the API request is made.
|
||||||
|
cli.checkVersion(ctx)
|
||||||
|
|
||||||
|
if err := cli.NewVersionError(ctx, "1.25", "stop timeout"); config != nil && config.StopTimeout != nil && err != nil {
|
||||||
return response, err
|
return response, err
|
||||||
}
|
}
|
||||||
if err := cli.NewVersionError("1.41", "specify container image platform"); platform != nil && err != nil {
|
if err := cli.NewVersionError(ctx, "1.41", "specify container image platform"); platform != nil && err != nil {
|
||||||
return response, err
|
return response, err
|
||||||
}
|
}
|
||||||
if err := cli.NewVersionError("1.44", "specify health-check start interval"); config != nil && config.Healthcheck != nil && config.Healthcheck.StartInterval != 0 && err != nil {
|
if err := cli.NewVersionError(ctx, "1.44", "specify health-check start interval"); config != nil && config.Healthcheck != nil && config.Healthcheck.StartInterval != 0 && err != nil {
|
||||||
return response, err
|
return response, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,14 @@ import (
|
||||||
func (cli *Client) ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.IDResponse, error) {
|
func (cli *Client) ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.IDResponse, error) {
|
||||||
var response types.IDResponse
|
var response types.IDResponse
|
||||||
|
|
||||||
if err := cli.NewVersionError("1.25", "env"); len(config.Env) != 0 && err != nil {
|
// Make sure we negotiated (if the client is configured to do so),
|
||||||
|
// as code below contains API-version specific handling of options.
|
||||||
|
//
|
||||||
|
// Normally, version-negotiation (if enabled) would not happen until
|
||||||
|
// the API request is made.
|
||||||
|
cli.checkVersion(ctx)
|
||||||
|
|
||||||
|
if err := cli.NewVersionError(ctx, "1.25", "env"); len(config.Env) != 0 && err != nil {
|
||||||
return response, err
|
return response, err
|
||||||
}
|
}
|
||||||
if versions.LessThan(cli.ClientVersion(), "1.42") {
|
if versions.LessThan(cli.ClientVersion(), "1.42") {
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
func (cli *Client) ContainersPrune(ctx context.Context, pruneFilters filters.Args) (types.ContainersPruneReport, error) {
|
func (cli *Client) ContainersPrune(ctx context.Context, pruneFilters filters.Args) (types.ContainersPruneReport, error) {
|
||||||
var report types.ContainersPruneReport
|
var report types.ContainersPruneReport
|
||||||
|
|
||||||
if err := cli.NewVersionError("1.25", "container prune"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.25", "container prune"); err != nil {
|
||||||
return report, err
|
return report, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,16 @@ func (cli *Client) ContainerRestart(ctx context.Context, containerID string, opt
|
||||||
if options.Timeout != nil {
|
if options.Timeout != nil {
|
||||||
query.Set("t", strconv.Itoa(*options.Timeout))
|
query.Set("t", strconv.Itoa(*options.Timeout))
|
||||||
}
|
}
|
||||||
if options.Signal != "" && versions.GreaterThanOrEqualTo(cli.version, "1.42") {
|
if options.Signal != "" {
|
||||||
query.Set("signal", options.Signal)
|
// Make sure we negotiated (if the client is configured to do so),
|
||||||
|
// as code below contains API-version specific handling of options.
|
||||||
|
//
|
||||||
|
// Normally, version-negotiation (if enabled) would not happen until
|
||||||
|
// the API request is made.
|
||||||
|
cli.checkVersion(ctx)
|
||||||
|
if versions.GreaterThanOrEqualTo(cli.version, "1.42") {
|
||||||
|
query.Set("signal", options.Signal)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
resp, err := cli.post(ctx, "/containers/"+containerID+"/restart", query, nil, nil)
|
resp, err := cli.post(ctx, "/containers/"+containerID+"/restart", query, nil, nil)
|
||||||
ensureReaderClosed(resp)
|
ensureReaderClosed(resp)
|
||||||
|
|
|
@ -21,8 +21,16 @@ func (cli *Client) ContainerStop(ctx context.Context, containerID string, option
|
||||||
if options.Timeout != nil {
|
if options.Timeout != nil {
|
||||||
query.Set("t", strconv.Itoa(*options.Timeout))
|
query.Set("t", strconv.Itoa(*options.Timeout))
|
||||||
}
|
}
|
||||||
if options.Signal != "" && versions.GreaterThanOrEqualTo(cli.version, "1.42") {
|
if options.Signal != "" {
|
||||||
query.Set("signal", options.Signal)
|
// Make sure we negotiated (if the client is configured to do so),
|
||||||
|
// as code below contains API-version specific handling of options.
|
||||||
|
//
|
||||||
|
// Normally, version-negotiation (if enabled) would not happen until
|
||||||
|
// the API request is made.
|
||||||
|
cli.checkVersion(ctx)
|
||||||
|
if versions.GreaterThanOrEqualTo(cli.version, "1.42") {
|
||||||
|
query.Set("signal", options.Signal)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
resp, err := cli.post(ctx, "/containers/"+containerID+"/stop", query, nil, nil)
|
resp, err := cli.post(ctx, "/containers/"+containerID+"/stop", query, nil, nil)
|
||||||
ensureReaderClosed(resp)
|
ensureReaderClosed(resp)
|
||||||
|
|
|
@ -30,6 +30,12 @@ const containerWaitErrorMsgLimit = 2 * 1024 /* Max: 2KiB */
|
||||||
// synchronize ContainerWait with other calls, such as specifying a
|
// synchronize ContainerWait with other calls, such as specifying a
|
||||||
// "next-exit" condition before issuing a ContainerStart request.
|
// "next-exit" condition before issuing a ContainerStart request.
|
||||||
func (cli *Client) ContainerWait(ctx context.Context, containerID string, condition container.WaitCondition) (<-chan container.WaitResponse, <-chan error) {
|
func (cli *Client) ContainerWait(ctx context.Context, containerID string, condition container.WaitCondition) (<-chan container.WaitResponse, <-chan error) {
|
||||||
|
// Make sure we negotiated (if the client is configured to do so),
|
||||||
|
// as code below contains API-version specific handling of options.
|
||||||
|
//
|
||||||
|
// Normally, version-negotiation (if enabled) would not happen until
|
||||||
|
// the API request is made.
|
||||||
|
cli.checkVersion(ctx)
|
||||||
if versions.LessThan(cli.ClientVersion(), "1.30") {
|
if versions.LessThan(cli.ClientVersion(), "1.30") {
|
||||||
return cli.legacyContainerWait(ctx, containerID)
|
return cli.legacyContainerWait(ctx, containerID)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegist
|
||||||
return distributionInspect, objectNotFoundError{object: "distribution", id: image}
|
return distributionInspect, objectNotFoundError{object: "distribution", id: image}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cli.NewVersionError("1.30", "distribution inspect"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.30", "distribution inspect"); err != nil {
|
||||||
return distributionInspect, err
|
return distributionInspect, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package client // import "github.com/docker/docker/client"
|
package client // import "github.com/docker/docker/client"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types/versions"
|
"github.com/docker/docker/api/types/versions"
|
||||||
|
@ -48,9 +49,18 @@ func (e objectNotFoundError) Error() string {
|
||||||
return fmt.Sprintf("Error: No such %s: %s", e.object, e.id)
|
return fmt.Sprintf("Error: No such %s: %s", e.object, e.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewVersionError returns an error if the APIVersion required
|
// NewVersionError returns an error if the APIVersion required is less than the
|
||||||
// if less than the current supported version
|
// current supported version.
|
||||||
func (cli *Client) NewVersionError(APIrequired, feature string) error {
|
//
|
||||||
|
// It performs API-version negotiation if the Client is configured with this
|
||||||
|
// option, otherwise it assumes the latest API version is used.
|
||||||
|
func (cli *Client) NewVersionError(ctx context.Context, APIrequired, feature string) error {
|
||||||
|
// Make sure we negotiated (if the client is configured to do so),
|
||||||
|
// as code below contains API-version specific handling of options.
|
||||||
|
//
|
||||||
|
// Normally, version-negotiation (if enabled) would not happen until
|
||||||
|
// the API request is made.
|
||||||
|
cli.checkVersion(ctx)
|
||||||
if cli.version != "" && versions.LessThan(cli.version, APIrequired) {
|
if cli.version != "" && versions.LessThan(cli.version, APIrequired) {
|
||||||
return fmt.Errorf("%q requires API version %s, but the Docker daemon API version is %s", feature, APIrequired, cli.version)
|
return fmt.Errorf("%q requires API version %s, but the Docker daemon API version is %s", feature, APIrequired, cli.version)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ import (
|
||||||
// The Body in the response implements an io.ReadCloser and it's up to the caller to
|
// The Body in the response implements an io.ReadCloser and it's up to the caller to
|
||||||
// close it.
|
// close it.
|
||||||
func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
|
func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
|
||||||
query, err := cli.imageBuildOptionsToQuery(options)
|
query, err := cli.imageBuildOptionsToQuery(ctx, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.ImageBuildResponse{}, err
|
return types.ImageBuildResponse{}, err
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, optio
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli *Client) imageBuildOptionsToQuery(options types.ImageBuildOptions) (url.Values, error) {
|
func (cli *Client) imageBuildOptionsToQuery(ctx context.Context, options types.ImageBuildOptions) (url.Values, error) {
|
||||||
query := url.Values{
|
query := url.Values{
|
||||||
"t": options.Tags,
|
"t": options.Tags,
|
||||||
"securityopt": options.SecurityOpt,
|
"securityopt": options.SecurityOpt,
|
||||||
|
@ -73,7 +73,7 @@ func (cli *Client) imageBuildOptionsToQuery(options types.ImageBuildOptions) (ur
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.Squash {
|
if options.Squash {
|
||||||
if err := cli.NewVersionError("1.25", "squash"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.25", "squash"); err != nil {
|
||||||
return query, err
|
return query, err
|
||||||
}
|
}
|
||||||
query.Set("squash", "1")
|
query.Set("squash", "1")
|
||||||
|
@ -123,7 +123,7 @@ func (cli *Client) imageBuildOptionsToQuery(options types.ImageBuildOptions) (ur
|
||||||
query.Set("session", options.SessionID)
|
query.Set("session", options.SessionID)
|
||||||
}
|
}
|
||||||
if options.Platform != "" {
|
if options.Platform != "" {
|
||||||
if err := cli.NewVersionError("1.32", "platform"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.32", "platform"); err != nil {
|
||||||
return query, err
|
return query, err
|
||||||
}
|
}
|
||||||
query.Set("platform", strings.ToLower(options.Platform))
|
query.Set("platform", strings.ToLower(options.Platform))
|
||||||
|
|
|
@ -12,6 +12,13 @@ import (
|
||||||
|
|
||||||
// ImageList returns a list of images in the docker host.
|
// ImageList returns a list of images in the docker host.
|
||||||
func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions) ([]types.ImageSummary, error) {
|
func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions) ([]types.ImageSummary, error) {
|
||||||
|
// Make sure we negotiated (if the client is configured to do so),
|
||||||
|
// as code below contains API-version specific handling of options.
|
||||||
|
//
|
||||||
|
// Normally, version-negotiation (if enabled) would not happen until
|
||||||
|
// the API request is made.
|
||||||
|
cli.checkVersion(ctx)
|
||||||
|
|
||||||
var images []types.ImageSummary
|
var images []types.ImageSummary
|
||||||
query := url.Values{}
|
query := url.Values{}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
func (cli *Client) ImagesPrune(ctx context.Context, pruneFilters filters.Args) (types.ImagesPruneReport, error) {
|
func (cli *Client) ImagesPrune(ctx context.Context, pruneFilters filters.Args) (types.ImagesPruneReport, error) {
|
||||||
var report types.ImagesPruneReport
|
var report types.ImagesPruneReport
|
||||||
|
|
||||||
if err := cli.NewVersionError("1.25", "image prune"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.25", "image prune"); err != nil {
|
||||||
return report, err
|
return report, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,13 @@ import (
|
||||||
|
|
||||||
// NetworkCreate creates a new network in the docker host.
|
// NetworkCreate creates a new network in the docker host.
|
||||||
func (cli *Client) NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) {
|
func (cli *Client) NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) {
|
||||||
|
// Make sure we negotiated (if the client is configured to do so),
|
||||||
|
// as code below contains API-version specific handling of options.
|
||||||
|
//
|
||||||
|
// Normally, version-negotiation (if enabled) would not happen until
|
||||||
|
// the API request is made.
|
||||||
|
cli.checkVersion(ctx)
|
||||||
|
|
||||||
networkCreateRequest := types.NetworkCreateRequest{
|
networkCreateRequest := types.NetworkCreateRequest{
|
||||||
NetworkCreate: options,
|
NetworkCreate: options,
|
||||||
Name: name,
|
Name: name,
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
func (cli *Client) NetworksPrune(ctx context.Context, pruneFilters filters.Args) (types.NetworksPruneReport, error) {
|
func (cli *Client) NetworksPrune(ctx context.Context, pruneFilters filters.Args) (types.NetworksPruneReport, error) {
|
||||||
var report types.NetworksPruneReport
|
var report types.NetworksPruneReport
|
||||||
|
|
||||||
if err := cli.NewVersionError("1.25", "network prune"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.25", "network prune"); err != nil {
|
||||||
return report, err
|
return report, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
|
|
||||||
// PluginUpgrade upgrades a plugin
|
// PluginUpgrade upgrades a plugin
|
||||||
func (cli *Client) PluginUpgrade(ctx context.Context, name string, options types.PluginInstallOptions) (rc io.ReadCloser, err error) {
|
func (cli *Client) PluginUpgrade(ctx context.Context, name string, options types.PluginInstallOptions) (rc io.ReadCloser, err error) {
|
||||||
if err := cli.NewVersionError("1.26", "plugin upgrade"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.26", "plugin upgrade"); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
query := url.Values{}
|
query := url.Values{}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
// SecretCreate creates a new secret.
|
// SecretCreate creates a new secret.
|
||||||
func (cli *Client) SecretCreate(ctx context.Context, secret swarm.SecretSpec) (types.SecretCreateResponse, error) {
|
func (cli *Client) SecretCreate(ctx context.Context, secret swarm.SecretSpec) (types.SecretCreateResponse, error) {
|
||||||
var response types.SecretCreateResponse
|
var response types.SecretCreateResponse
|
||||||
if err := cli.NewVersionError("1.25", "secret create"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.25", "secret create"); err != nil {
|
||||||
return response, err
|
return response, err
|
||||||
}
|
}
|
||||||
resp, err := cli.post(ctx, "/secrets/create", nil, secret, nil)
|
resp, err := cli.post(ctx, "/secrets/create", nil, secret, nil)
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
|
|
||||||
// SecretInspectWithRaw returns the secret information with raw data
|
// SecretInspectWithRaw returns the secret information with raw data
|
||||||
func (cli *Client) SecretInspectWithRaw(ctx context.Context, id string) (swarm.Secret, []byte, error) {
|
func (cli *Client) SecretInspectWithRaw(ctx context.Context, id string) (swarm.Secret, []byte, error) {
|
||||||
if err := cli.NewVersionError("1.25", "secret inspect"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.25", "secret inspect"); err != nil {
|
||||||
return swarm.Secret{}, nil, err
|
return swarm.Secret{}, nil, err
|
||||||
}
|
}
|
||||||
if id == "" {
|
if id == "" {
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
|
|
||||||
// SecretList returns the list of secrets.
|
// SecretList returns the list of secrets.
|
||||||
func (cli *Client) SecretList(ctx context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
|
func (cli *Client) SecretList(ctx context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||||
if err := cli.NewVersionError("1.25", "secret list"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.25", "secret list"); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
query := url.Values{}
|
query := url.Values{}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import "context"
|
||||||
|
|
||||||
// SecretRemove removes a secret.
|
// SecretRemove removes a secret.
|
||||||
func (cli *Client) SecretRemove(ctx context.Context, id string) error {
|
func (cli *Client) SecretRemove(ctx context.Context, id string) error {
|
||||||
if err := cli.NewVersionError("1.25", "secret remove"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.25", "secret remove"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
resp, err := cli.delete(ctx, "/secrets/"+id, nil, nil)
|
resp, err := cli.delete(ctx, "/secrets/"+id, nil, nil)
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
|
|
||||||
// SecretUpdate attempts to update a secret.
|
// SecretUpdate attempts to update a secret.
|
||||||
func (cli *Client) SecretUpdate(ctx context.Context, id string, version swarm.Version, secret swarm.SecretSpec) error {
|
func (cli *Client) SecretUpdate(ctx context.Context, id string, version swarm.Version, secret swarm.SecretSpec) error {
|
||||||
if err := cli.NewVersionError("1.25", "secret update"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.25", "secret update"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
query := url.Values{}
|
query := url.Values{}
|
||||||
|
|
|
@ -20,6 +20,13 @@ import (
|
||||||
func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec, options types.ServiceCreateOptions) (types.ServiceCreateResponse, error) {
|
func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec, options types.ServiceCreateOptions) (types.ServiceCreateResponse, error) {
|
||||||
var response types.ServiceCreateResponse
|
var response types.ServiceCreateResponse
|
||||||
|
|
||||||
|
// Make sure we negotiated (if the client is configured to do so),
|
||||||
|
// as code below contains API-version specific handling of options.
|
||||||
|
//
|
||||||
|
// Normally, version-negotiation (if enabled) would not happen until
|
||||||
|
// the API request is made.
|
||||||
|
cli.checkVersion(ctx)
|
||||||
|
|
||||||
// Make sure containerSpec is not nil when no runtime is set or the runtime is set to container
|
// Make sure containerSpec is not nil when no runtime is set or the runtime is set to container
|
||||||
if service.TaskTemplate.ContainerSpec == nil && (service.TaskTemplate.Runtime == "" || service.TaskTemplate.Runtime == swarm.RuntimeContainer) {
|
if service.TaskTemplate.ContainerSpec == nil && (service.TaskTemplate.Runtime == "" || service.TaskTemplate.Runtime == swarm.RuntimeContainer) {
|
||||||
service.TaskTemplate.ContainerSpec = &swarm.ContainerSpec{}
|
service.TaskTemplate.ContainerSpec = &swarm.ContainerSpec{}
|
||||||
|
|
|
@ -16,6 +16,13 @@ import (
|
||||||
// It should be the value as set *before* the update. You can find this value in the Meta field
|
// It should be the value as set *before* the update. You can find this value in the Meta field
|
||||||
// of swarm.Service, which can be found using ServiceInspectWithRaw.
|
// of swarm.Service, which can be found using ServiceInspectWithRaw.
|
||||||
func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) {
|
func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) {
|
||||||
|
// Make sure we negotiated (if the client is configured to do so),
|
||||||
|
// as code below contains API-version specific handling of options.
|
||||||
|
//
|
||||||
|
// Normally, version-negotiation (if enabled) would not happen until
|
||||||
|
// the API request is made.
|
||||||
|
cli.checkVersion(ctx)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
query = url.Values{}
|
query = url.Values{}
|
||||||
response = types.ServiceUpdateResponse{}
|
response = types.ServiceUpdateResponse{}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
func (cli *Client) VolumesPrune(ctx context.Context, pruneFilters filters.Args) (types.VolumesPruneReport, error) {
|
func (cli *Client) VolumesPrune(ctx context.Context, pruneFilters filters.Args) (types.VolumesPruneReport, error) {
|
||||||
var report types.VolumesPruneReport
|
var report types.VolumesPruneReport
|
||||||
|
|
||||||
if err := cli.NewVersionError("1.25", "volume prune"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.25", "volume prune"); err != nil {
|
||||||
return report, err
|
return report, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,14 @@ import (
|
||||||
// VolumeRemove removes a volume from the docker host.
|
// VolumeRemove removes a volume from the docker host.
|
||||||
func (cli *Client) VolumeRemove(ctx context.Context, volumeID string, force bool) error {
|
func (cli *Client) VolumeRemove(ctx context.Context, volumeID string, force bool) error {
|
||||||
query := url.Values{}
|
query := url.Values{}
|
||||||
if versions.GreaterThanOrEqualTo(cli.version, "1.25") {
|
if force {
|
||||||
if force {
|
// Make sure we negotiated (if the client is configured to do so),
|
||||||
|
// as code below contains API-version specific handling of options.
|
||||||
|
//
|
||||||
|
// Normally, version-negotiation (if enabled) would not happen until
|
||||||
|
// the API request is made.
|
||||||
|
cli.checkVersion(ctx)
|
||||||
|
if versions.GreaterThanOrEqualTo(cli.version, "1.25") {
|
||||||
query.Set("force", "1")
|
query.Set("force", "1")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
// VolumeUpdate updates a volume. This only works for Cluster Volumes, and
|
// VolumeUpdate updates a volume. This only works for Cluster Volumes, and
|
||||||
// only some fields can be updated.
|
// only some fields can be updated.
|
||||||
func (cli *Client) VolumeUpdate(ctx context.Context, volumeID string, version swarm.Version, options volume.UpdateOptions) error {
|
func (cli *Client) VolumeUpdate(ctx context.Context, volumeID string, version swarm.Version, options volume.UpdateOptions) error {
|
||||||
if err := cli.NewVersionError("1.42", "volume update"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.42", "volume update"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue