1package client // import "github.com/docker/docker/client" 2 3import ( 4 "context" 5 "encoding/json" 6 "net/url" 7 "strconv" 8 9 "github.com/docker/docker/api/types" 10 "github.com/docker/docker/api/types/swarm" 11) 12 13// ServiceUpdate updates a Service. The version number is required to avoid conflicting writes. 14// It should be the value as set *before* the update. You can find this value in the Meta field 15// of swarm.Service, which can be found using ServiceInspectWithRaw. 16func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) { 17 var ( 18 query = url.Values{} 19 response = types.ServiceUpdateResponse{} 20 ) 21 22 headers := map[string][]string{ 23 "version": {cli.version}, 24 } 25 26 if options.EncodedRegistryAuth != "" { 27 headers["X-Registry-Auth"] = []string{options.EncodedRegistryAuth} 28 } 29 30 if options.RegistryAuthFrom != "" { 31 query.Set("registryAuthFrom", options.RegistryAuthFrom) 32 } 33 34 if options.Rollback != "" { 35 query.Set("rollback", options.Rollback) 36 } 37 38 query.Set("version", strconv.FormatUint(version.Index, 10)) 39 40 if err := validateServiceSpec(service); err != nil { 41 return response, err 42 } 43 44 // ensure that the image is tagged 45 var resolveWarning string 46 switch { 47 case service.TaskTemplate.ContainerSpec != nil: 48 if taggedImg := imageWithTagString(service.TaskTemplate.ContainerSpec.Image); taggedImg != "" { 49 service.TaskTemplate.ContainerSpec.Image = taggedImg 50 } 51 if options.QueryRegistry { 52 resolveWarning = resolveContainerSpecImage(ctx, cli, &service.TaskTemplate, options.EncodedRegistryAuth) 53 } 54 case service.TaskTemplate.PluginSpec != nil: 55 if taggedImg := imageWithTagString(service.TaskTemplate.PluginSpec.Remote); taggedImg != "" { 56 service.TaskTemplate.PluginSpec.Remote = taggedImg 57 } 58 if options.QueryRegistry { 59 resolveWarning = resolvePluginSpecRemote(ctx, cli, &service.TaskTemplate, options.EncodedRegistryAuth) 60 } 61 } 62 63 resp, err := cli.post(ctx, "/services/"+serviceID+"/update", query, service, headers) 64 defer ensureReaderClosed(resp) 65 if err != nil { 66 return response, err 67 } 68 69 err = json.NewDecoder(resp.body).Decode(&response) 70 if resolveWarning != "" { 71 response.Warnings = append(response.Warnings, resolveWarning) 72 } 73 74 return response, err 75} 76