github.com/uriddle/docker@v0.0.0-20210926094723-4072e6aeb013/integration-cli/docker_cli_volume_driver_compat_unix_test.go (about)

     1  // +build !windows
     2  
     3  package main
     4  
     5  import (
     6  	"encoding/json"
     7  	"fmt"
     8  	"io"
     9  	"io/ioutil"
    10  	"net/http"
    11  	"net/http/httptest"
    12  	"os"
    13  	"path/filepath"
    14  	"strings"
    15  
    16  	"github.com/docker/docker/pkg/integration/checker"
    17  
    18  	"github.com/go-check/check"
    19  )
    20  
    21  func init() {
    22  	check.Suite(&DockerExternalVolumeSuiteCompatV1_1{
    23  		ds: &DockerSuite{},
    24  	})
    25  }
    26  
    27  type vol struct {
    28  	Name       string
    29  	Mountpoint string
    30  	Opts       map[string]string
    31  }
    32  
    33  type DockerExternalVolumeSuiteCompatV1_1 struct {
    34  	server  *httptest.Server
    35  	ds      *DockerSuite
    36  	d       *Daemon
    37  	ec      *eventCounter
    38  	volList []vol
    39  }
    40  
    41  func (s *DockerExternalVolumeSuiteCompatV1_1) SetUpTest(c *check.C) {
    42  	s.d = NewDaemon(c)
    43  	s.ec = &eventCounter{}
    44  }
    45  
    46  func (s *DockerExternalVolumeSuiteCompatV1_1) TearDownTest(c *check.C) {
    47  	s.d.Stop()
    48  	s.ds.TearDownTest(c)
    49  }
    50  
    51  func (s *DockerExternalVolumeSuiteCompatV1_1) SetUpSuite(c *check.C) {
    52  	mux := http.NewServeMux()
    53  	s.server = httptest.NewServer(mux)
    54  
    55  	type pluginRequest struct {
    56  		Name string
    57  		Opts map[string]string
    58  	}
    59  
    60  	type pluginResp struct {
    61  		Mountpoint string `json:",omitempty"`
    62  		Err        string `json:",omitempty"`
    63  	}
    64  
    65  	read := func(b io.ReadCloser) (pluginRequest, error) {
    66  		defer b.Close()
    67  		var pr pluginRequest
    68  		if err := json.NewDecoder(b).Decode(&pr); err != nil {
    69  			return pr, err
    70  		}
    71  		return pr, nil
    72  	}
    73  
    74  	send := func(w http.ResponseWriter, data interface{}) {
    75  		switch t := data.(type) {
    76  		case error:
    77  			http.Error(w, t.Error(), 500)
    78  		case string:
    79  			w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
    80  			fmt.Fprintln(w, t)
    81  		default:
    82  			w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
    83  			json.NewEncoder(w).Encode(&data)
    84  		}
    85  	}
    86  
    87  	mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) {
    88  		s.ec.activations++
    89  		send(w, `{"Implements": ["VolumeDriver"]}`)
    90  	})
    91  
    92  	mux.HandleFunc("/VolumeDriver.Create", func(w http.ResponseWriter, r *http.Request) {
    93  		s.ec.creations++
    94  		pr, err := read(r.Body)
    95  		if err != nil {
    96  			send(w, err)
    97  			return
    98  		}
    99  		s.volList = append(s.volList, vol{Name: pr.Name, Opts: pr.Opts})
   100  		send(w, nil)
   101  	})
   102  
   103  	mux.HandleFunc("/VolumeDriver.Remove", func(w http.ResponseWriter, r *http.Request) {
   104  		s.ec.removals++
   105  		pr, err := read(r.Body)
   106  		if err != nil {
   107  			send(w, err)
   108  			return
   109  		}
   110  
   111  		if err := os.RemoveAll(hostVolumePath(pr.Name)); err != nil {
   112  			send(w, &pluginResp{Err: err.Error()})
   113  			return
   114  		}
   115  
   116  		for i, v := range s.volList {
   117  			if v.Name == pr.Name {
   118  				if err := os.RemoveAll(hostVolumePath(v.Name)); err != nil {
   119  					send(w, fmt.Sprintf(`{"Err": "%v"}`, err))
   120  					return
   121  				}
   122  				s.volList = append(s.volList[:i], s.volList[i+1:]...)
   123  				break
   124  			}
   125  		}
   126  		send(w, nil)
   127  	})
   128  
   129  	mux.HandleFunc("/VolumeDriver.Path", func(w http.ResponseWriter, r *http.Request) {
   130  		s.ec.paths++
   131  
   132  		pr, err := read(r.Body)
   133  		if err != nil {
   134  			send(w, err)
   135  			return
   136  		}
   137  		p := hostVolumePath(pr.Name)
   138  		send(w, &pluginResp{Mountpoint: p})
   139  	})
   140  
   141  	mux.HandleFunc("/VolumeDriver.Mount", func(w http.ResponseWriter, r *http.Request) {
   142  		s.ec.mounts++
   143  
   144  		pr, err := read(r.Body)
   145  		if err != nil {
   146  			send(w, err)
   147  			return
   148  		}
   149  
   150  		p := hostVolumePath(pr.Name)
   151  		if err := os.MkdirAll(p, 0755); err != nil {
   152  			send(w, &pluginResp{Err: err.Error()})
   153  			return
   154  		}
   155  
   156  		if err := ioutil.WriteFile(filepath.Join(p, "test"), []byte(s.server.URL), 0644); err != nil {
   157  			send(w, err)
   158  			return
   159  		}
   160  
   161  		send(w, &pluginResp{Mountpoint: p})
   162  	})
   163  
   164  	mux.HandleFunc("/VolumeDriver.Unmount", func(w http.ResponseWriter, r *http.Request) {
   165  		s.ec.unmounts++
   166  
   167  		_, err := read(r.Body)
   168  		if err != nil {
   169  			send(w, err)
   170  			return
   171  		}
   172  
   173  		send(w, nil)
   174  	})
   175  
   176  	err := os.MkdirAll("/etc/docker/plugins", 0755)
   177  	c.Assert(err, checker.IsNil)
   178  
   179  	err = ioutil.WriteFile("/etc/docker/plugins/test-external-volume-driver.spec", []byte(s.server.URL), 0644)
   180  	c.Assert(err, checker.IsNil)
   181  }
   182  
   183  func (s *DockerExternalVolumeSuiteCompatV1_1) TearDownSuite(c *check.C) {
   184  	s.server.Close()
   185  
   186  	err := os.RemoveAll("/etc/docker/plugins")
   187  	c.Assert(err, checker.IsNil)
   188  }
   189  
   190  func (s *DockerExternalVolumeSuiteCompatV1_1) TestExternalVolumeDriverCompatV1_1(c *check.C) {
   191  	err := s.d.StartWithBusybox()
   192  	c.Assert(err, checker.IsNil)
   193  
   194  	out, err := s.d.Cmd("run", "--name=test", "-v", "foo:/bar", "--volume-driver", "test-external-volume-driver", "busybox", "sh", "-c", "echo hello > /bar/hello")
   195  	c.Assert(err, checker.IsNil, check.Commentf(out))
   196  	out, err = s.d.Cmd("rm", "test")
   197  	c.Assert(err, checker.IsNil, check.Commentf(out))
   198  
   199  	out, err = s.d.Cmd("run", "--name=test2", "-v", "foo:/bar", "busybox", "cat", "/bar/hello")
   200  	c.Assert(err, checker.IsNil, check.Commentf(out))
   201  	c.Assert(strings.TrimSpace(out), checker.Equals, "hello")
   202  
   203  	err = s.d.Restart()
   204  	c.Assert(err, checker.IsNil)
   205  
   206  	out, err = s.d.Cmd("start", "-a", "test2")
   207  	c.Assert(strings.TrimSpace(out), checker.Equals, "hello")
   208  
   209  	out, err = s.d.Cmd("rm", "test2")
   210  	c.Assert(err, checker.IsNil, check.Commentf(out))
   211  
   212  	out, err = s.d.Cmd("volume", "inspect", "foo")
   213  	c.Assert(err, checker.IsNil, check.Commentf(out))
   214  
   215  	out, err = s.d.Cmd("volume", "rm", "foo")
   216  	c.Assert(err, checker.IsNil, check.Commentf(out))
   217  }
   218  
   219  func (s *DockerExternalVolumeSuiteCompatV1_1) TestExternalVolumeDriverCompatOptionsV1_1(c *check.C) {
   220  	err := s.d.StartWithBusybox()
   221  	c.Assert(err, checker.IsNil)
   222  
   223  	out, err := s.d.Cmd("volume", "create", "--name", "optvol", "--driver", "test-external-volume-driver", "--opt", "opt1=opt1val", "--opt", "opt2=opt2val")
   224  	c.Assert(err, checker.IsNil, check.Commentf(out))
   225  
   226  	out, err = s.d.Cmd("volume", "inspect", "optvol")
   227  	c.Assert(err, checker.IsNil, check.Commentf(out))
   228  
   229  	c.Assert(s.volList[0].Opts["opt1"], checker.Equals, "opt1val")
   230  	c.Assert(s.volList[0].Opts["opt2"], checker.Equals, "opt2val")
   231  
   232  	out, err = s.d.Cmd("volume", "rm", "optvol")
   233  	c.Assert(err, checker.IsNil, check.Commentf(out))
   234  }