浏览代码

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>
Yong Tang 8 年之前
父节点
当前提交
80e3975117
共有 2 个文件被更改,包括 25 次插入6 次删除
  1. 7 6
      daemon/cluster/cluster.go
  2. 18 0
      integration-cli/docker_api_swarm_test.go

+ 7 - 6
daemon/cluster/cluster.go

@@ -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,

+ 18 - 0
integration-cli/docker_api_swarm_test.go

@@ -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)
+}