Fix issue in API `POST /services/(id or name)/update`

This fix tries to address the issue raised in 26090 where
remote API `POST /services/(id or name)/update` cannot
use `name` to update. This is not consistent with the
documentation of the remote API.

This fix fixes this issue by performing a lookup with `getService`
in case `name` instead of `id` is used in API.

This fix adds an integration test to cover the changes.

This fix fixes 26090.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
This commit is contained in:
Yong Tang 2016-08-28 21:15:03 -07:00
parent 13094ffef9
commit 80e3975117
2 changed files with 25 additions and 6 deletions

View File

@ -892,7 +892,7 @@ func (c *Cluster) GetService(input string) (types.Service, error) {
}
// UpdateService updates existing service to match new properties.
func (c *Cluster) UpdateService(serviceID string, version uint64, spec types.ServiceSpec, encodedAuth string) error {
func (c *Cluster) UpdateService(serviceIDOrName string, version uint64, spec types.ServiceSpec, encodedAuth string) error {
c.RLock()
defer c.RUnlock()
@ -913,6 +913,11 @@ func (c *Cluster) UpdateService(serviceID string, version uint64, spec types.Ser
return err
}
currentService, err := getService(ctx, c.client, serviceIDOrName)
if err != nil {
return err
}
if encodedAuth != "" {
ctnr := serviceSpec.Task.GetContainer()
if ctnr == nil {
@ -922,10 +927,6 @@ func (c *Cluster) UpdateService(serviceID string, version uint64, spec types.Ser
} else {
// this is needed because if the encodedAuth isn't being updated then we
// shouldn't lose it, and continue to use the one that was already present
currentService, err := getService(ctx, c.client, serviceID)
if err != nil {
return err
}
ctnr := currentService.Spec.Task.GetContainer()
if ctnr == nil {
return fmt.Errorf("service does not use container tasks")
@ -936,7 +937,7 @@ func (c *Cluster) UpdateService(serviceID string, version uint64, spec types.Ser
_, err = c.client.UpdateService(
ctx,
&swarmapi.UpdateServiceRequest{
ServiceID: serviceID,
ServiceID: currentService.ID,
Spec: &serviceSpec,
ServiceVersion: &swarmapi.Version{
Index: version,

View File

@ -1168,3 +1168,21 @@ func (s *DockerSwarmSuite) TestApiSwarmRestartCluster(c *check.C) {
checkClusterHealth(c, nodes, mCount, wCount)
}
func (s *DockerSwarmSuite) TestApiSwarmServicesUpdateWithName(c *check.C) {
d := s.AddDaemon(c, true, true)
instances := 2
id := d.createService(c, simpleTestService, setInstances(instances))
waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, instances)
service := d.getService(c, id)
instances = 5
setInstances(instances)(service)
url := fmt.Sprintf("/services/%s/update?version=%d", service.Spec.Name, service.Version.Index)
status, out, err := d.SockRequest("POST", url, service.Spec)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out)))
waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, instances)
}