mirror of
https://github.com/moby/moby.git
synced 2026-01-11 18:51:37 +00:00
commit [moby@5d6b566] migrated this validation from the CLI to the client,
but for some reason picked the wrong API version inside ServiceCreate.
The CLI code was added to an existing validation, which only handled
validation when creating a service, but not when updating, which meant
that adding this option to an existing service would not invalidate it.
This patch:
- moves the version-gate to the validation code
- merges validateServiceSpecForAPIVersion into validateServiceSpec, to
keep the validation combined, and to make sure validation happens both
on create and update.
[moby@5d6b566]: 5d6b56699d
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
83 lines
2.7 KiB
Go
83 lines
2.7 KiB
Go
package client
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/url"
|
|
|
|
"github.com/moby/moby/api/types/registry"
|
|
"github.com/moby/moby/api/types/swarm"
|
|
)
|
|
|
|
// ServiceUpdate updates a Service. The version number is required to avoid
|
|
// conflicting writes. It must be the value as set *before* the update.
|
|
// You can find this value in the [swarm.Service.Meta] field, which can
|
|
// be found using [Client.ServiceInspectWithRaw].
|
|
func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options ServiceUpdateOptions) (swarm.ServiceUpdateResponse, error) {
|
|
serviceID, err := trimID("service", serviceID)
|
|
if err != nil {
|
|
return swarm.ServiceUpdateResponse{}, err
|
|
}
|
|
|
|
// 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.
|
|
if err := cli.checkVersion(ctx); err != nil {
|
|
return swarm.ServiceUpdateResponse{}, err
|
|
}
|
|
if err := validateServiceSpec(service, cli.version); err != nil {
|
|
return swarm.ServiceUpdateResponse{}, err
|
|
}
|
|
|
|
query := url.Values{}
|
|
if options.RegistryAuthFrom != "" {
|
|
query.Set("registryAuthFrom", options.RegistryAuthFrom)
|
|
}
|
|
|
|
if options.Rollback != "" {
|
|
query.Set("rollback", options.Rollback)
|
|
}
|
|
|
|
query.Set("version", version.String())
|
|
|
|
// ensure that the image is tagged
|
|
var resolveWarning string
|
|
switch {
|
|
case service.TaskTemplate.ContainerSpec != nil:
|
|
if taggedImg := imageWithTagString(service.TaskTemplate.ContainerSpec.Image); taggedImg != "" {
|
|
service.TaskTemplate.ContainerSpec.Image = taggedImg
|
|
}
|
|
if options.QueryRegistry {
|
|
resolveWarning = resolveContainerSpecImage(ctx, cli, &service.TaskTemplate, options.EncodedRegistryAuth)
|
|
}
|
|
case service.TaskTemplate.PluginSpec != nil:
|
|
if taggedImg := imageWithTagString(service.TaskTemplate.PluginSpec.Remote); taggedImg != "" {
|
|
service.TaskTemplate.PluginSpec.Remote = taggedImg
|
|
}
|
|
if options.QueryRegistry {
|
|
resolveWarning = resolvePluginSpecRemote(ctx, cli, &service.TaskTemplate, options.EncodedRegistryAuth)
|
|
}
|
|
}
|
|
|
|
headers := http.Header{}
|
|
if options.EncodedRegistryAuth != "" {
|
|
headers.Set(registry.AuthHeader, options.EncodedRegistryAuth)
|
|
}
|
|
resp, err := cli.post(ctx, "/services/"+serviceID+"/update", query, service, headers)
|
|
defer ensureReaderClosed(resp)
|
|
if err != nil {
|
|
return swarm.ServiceUpdateResponse{}, err
|
|
}
|
|
|
|
var response swarm.ServiceUpdateResponse
|
|
err = json.NewDecoder(resp.Body).Decode(&response)
|
|
if resolveWarning != "" {
|
|
response.Warnings = append(response.Warnings, resolveWarning)
|
|
}
|
|
|
|
return response, err
|
|
}
|