فهرست منبع

Fix panic when plugin responds with null volume

In cases where the a plugin responds with both a null or empty volume
and a null or empty Err, the daemon would panic.
This is because we assumed the idiom if `err` is nil, then `v` must not
be but in reality the plugin may return whatever it wants and we want to
make sure it doesn't harm the daemon.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
Brian Goff 9 سال پیش
والد
کامیت
96c79a1934
2فایلهای تغییر یافته به همراه27 افزوده شده و 2 حذف شده
  1. 17 1
      integration-cli/docker_cli_start_volume_driver_unix_test.go
  2. 10 1
      volume/drivers/adapter.go

+ 17 - 1
integration-cli/docker_cli_start_volume_driver_unix_test.go

@@ -60,6 +60,7 @@ func (s *DockerExternalVolumeSuite) SetUpSuite(c *check.C) {
 
 	type pluginRequest struct {
 		Name string
+		Opts map[string]string
 	}
 
 	type pluginResp struct {
@@ -70,6 +71,7 @@ func (s *DockerExternalVolumeSuite) SetUpSuite(c *check.C) {
 	type vol struct {
 		Name       string
 		Mountpoint string
+		Ninja      bool // hack used to trigger an null volume return on `Get`
 	}
 	var volList []vol
 
@@ -107,7 +109,8 @@ func (s *DockerExternalVolumeSuite) SetUpSuite(c *check.C) {
 			send(w, err)
 			return
 		}
-		volList = append(volList, vol{Name: pr.Name})
+		_, isNinja := pr.Opts["ninja"]
+		volList = append(volList, vol{Name: pr.Name, Ninja: isNinja})
 		send(w, nil)
 	})
 
@@ -126,6 +129,10 @@ func (s *DockerExternalVolumeSuite) SetUpSuite(c *check.C) {
 
 		for _, v := range volList {
 			if v.Name == pr.Name {
+				if v.Ninja {
+					send(w, map[string]vol{})
+					return
+				}
 				v.Mountpoint = hostVolumePath(pr.Name)
 				send(w, map[string]vol{"Volume": v})
 				return
@@ -423,3 +430,12 @@ func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverWithDaemnRestart(c *
 	c.Assert(mounts, checker.HasLen, 1)
 	c.Assert(mounts[0].Driver, checker.Equals, "test-external-volume-driver")
 }
+
+// Ensures that the daemon handles when the plugin responds to a `Get` request with a null volume and a null error.
+// Prior the daemon would panic in this scenario.
+func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverGetEmptyResponse(c *check.C) {
+	dockerCmd(c, "volume", "create", "-d", "test-external-volume-driver", "--name", "abc", "--opt", "ninja=1")
+	out, _, err := dockerCmdWithError("volume", "inspect", "abc")
+	c.Assert(err, checker.NotNil, check.Commentf(out))
+	c.Assert(out, checker.Contains, "No such volume")
+}

+ 10 - 1
volume/drivers/adapter.go

@@ -1,6 +1,10 @@
 package volumedrivers
 
-import "github.com/docker/docker/volume"
+import (
+	"fmt"
+
+	"github.com/docker/docker/volume"
+)
 
 type volumeDriverAdapter struct {
 	name  string
@@ -49,6 +53,11 @@ func (a *volumeDriverAdapter) Get(name string) (volume.Volume, error) {
 		return nil, err
 	}
 
+	// plugin may have returned no volume and no error
+	if v == nil {
+		return nil, fmt.Errorf("no such volume")
+	}
+
 	return &volumeAdapter{
 		proxy:      a.proxy,
 		name:       v.Name,