github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/engine/volume/service/store_test.go (about)

     1  package service // import "github.com/docker/docker/volume/service"
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"net"
     8  	"os"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/docker/docker/volume"
    13  	volumedrivers "github.com/docker/docker/volume/drivers"
    14  	"github.com/docker/docker/volume/service/opts"
    15  	volumetestutils "github.com/docker/docker/volume/testutils"
    16  	"github.com/google/go-cmp/cmp"
    17  	"gotest.tools/v3/assert"
    18  	is "gotest.tools/v3/assert/cmp"
    19  )
    20  
    21  func TestCreate(t *testing.T) {
    22  	t.Parallel()
    23  
    24  	s, cleanup := setupTest(t)
    25  	defer cleanup()
    26  	s.drivers.Register(volumetestutils.NewFakeDriver("fake"), "fake")
    27  
    28  	ctx := context.Background()
    29  	v, err := s.Create(ctx, "fake1", "fake")
    30  	if err != nil {
    31  		t.Fatal(err)
    32  	}
    33  	if v.Name() != "fake1" {
    34  		t.Fatalf("Expected fake1 volume, got %v", v)
    35  	}
    36  	if l, _, _ := s.Find(ctx, nil); len(l) != 1 {
    37  		t.Fatalf("Expected 1 volume in the store, got %v: %v", len(l), l)
    38  	}
    39  
    40  	if _, err := s.Create(ctx, "none", "none"); err == nil {
    41  		t.Fatalf("Expected unknown driver error, got nil")
    42  	}
    43  
    44  	_, err = s.Create(ctx, "fakeerror", "fake", opts.WithCreateOptions(map[string]string{"error": "create error"}))
    45  	expected := &OpErr{Op: "create", Name: "fakeerror", Err: errors.New("create error")}
    46  	if err != nil && err.Error() != expected.Error() {
    47  		t.Fatalf("Expected create fakeError: create error, got %v", err)
    48  	}
    49  }
    50  
    51  func TestRemove(t *testing.T) {
    52  	t.Parallel()
    53  
    54  	s, cleanup := setupTest(t)
    55  	defer cleanup()
    56  
    57  	s.drivers.Register(volumetestutils.NewFakeDriver("fake"), "fake")
    58  	s.drivers.Register(volumetestutils.NewFakeDriver("noop"), "noop")
    59  
    60  	ctx := context.Background()
    61  
    62  	// doing string compare here since this error comes directly from the driver
    63  	expected := "no such volume"
    64  	var v volume.Volume = volumetestutils.NoopVolume{}
    65  	if err := s.Remove(ctx, v); err == nil || !strings.Contains(err.Error(), expected) {
    66  		t.Fatalf("Expected error %q, got %v", expected, err)
    67  	}
    68  
    69  	v, err := s.Create(ctx, "fake1", "fake", opts.WithCreateReference("fake"))
    70  	if err != nil {
    71  		t.Fatal(err)
    72  	}
    73  
    74  	if err := s.Remove(ctx, v); !IsInUse(err) {
    75  		t.Fatalf("Expected ErrVolumeInUse error, got %v", err)
    76  	}
    77  	s.Release(ctx, v.Name(), "fake")
    78  	if err := s.Remove(ctx, v); err != nil {
    79  		t.Fatal(err)
    80  	}
    81  	if l, _, _ := s.Find(ctx, nil); len(l) != 0 {
    82  		t.Fatalf("Expected 0 volumes in the store, got %v, %v", len(l), l)
    83  	}
    84  }
    85  
    86  func TestList(t *testing.T) {
    87  	t.Parallel()
    88  
    89  	dir, err := os.MkdirTemp("", "test-list")
    90  	assert.NilError(t, err)
    91  	defer os.RemoveAll(dir)
    92  
    93  	drivers := volumedrivers.NewStore(nil)
    94  	drivers.Register(volumetestutils.NewFakeDriver("fake"), "fake")
    95  	drivers.Register(volumetestutils.NewFakeDriver("fake2"), "fake2")
    96  
    97  	s, err := NewStore(dir, drivers)
    98  	assert.NilError(t, err)
    99  
   100  	ctx := context.Background()
   101  	if _, err := s.Create(ctx, "test", "fake"); err != nil {
   102  		t.Fatal(err)
   103  	}
   104  	if _, err := s.Create(ctx, "test2", "fake2"); err != nil {
   105  		t.Fatal(err)
   106  	}
   107  
   108  	ls, _, err := s.Find(ctx, nil)
   109  	if err != nil {
   110  		t.Fatal(err)
   111  	}
   112  	if len(ls) != 2 {
   113  		t.Fatalf("expected 2 volumes, got: %d", len(ls))
   114  	}
   115  	if err := s.Shutdown(); err != nil {
   116  		t.Fatal(err)
   117  	}
   118  
   119  	// and again with a new store
   120  	s, err = NewStore(dir, drivers)
   121  	if err != nil {
   122  		t.Fatal(err)
   123  	}
   124  	ls, _, err = s.Find(ctx, nil)
   125  	if err != nil {
   126  		t.Fatal(err)
   127  	}
   128  	if len(ls) != 2 {
   129  		t.Fatalf("expected 2 volumes, got: %d", len(ls))
   130  	}
   131  }
   132  
   133  func TestFindByDriver(t *testing.T) {
   134  	t.Parallel()
   135  	s, cleanup := setupTest(t)
   136  	defer cleanup()
   137  
   138  	assert.Assert(t, s.drivers.Register(volumetestutils.NewFakeDriver("fake"), "fake"))
   139  	assert.Assert(t, s.drivers.Register(volumetestutils.NewFakeDriver("noop"), "noop"))
   140  
   141  	ctx := context.Background()
   142  	_, err := s.Create(ctx, "fake1", "fake")
   143  	assert.NilError(t, err)
   144  
   145  	_, err = s.Create(ctx, "fake2", "fake")
   146  	assert.NilError(t, err)
   147  
   148  	_, err = s.Create(ctx, "fake3", "noop")
   149  	assert.NilError(t, err)
   150  
   151  	l, _, err := s.Find(ctx, ByDriver("fake"))
   152  	assert.NilError(t, err)
   153  	assert.Equal(t, len(l), 2)
   154  
   155  	l, _, err = s.Find(ctx, ByDriver("noop"))
   156  	assert.NilError(t, err)
   157  	assert.Equal(t, len(l), 1)
   158  
   159  	l, _, err = s.Find(ctx, ByDriver("nosuchdriver"))
   160  	assert.NilError(t, err)
   161  	assert.Equal(t, len(l), 0)
   162  }
   163  
   164  func TestFindByReferenced(t *testing.T) {
   165  	t.Parallel()
   166  	s, cleanup := setupTest(t)
   167  	defer cleanup()
   168  
   169  	s.drivers.Register(volumetestutils.NewFakeDriver("fake"), "fake")
   170  	s.drivers.Register(volumetestutils.NewFakeDriver("noop"), "noop")
   171  
   172  	ctx := context.Background()
   173  	if _, err := s.Create(ctx, "fake1", "fake", opts.WithCreateReference("volReference")); err != nil {
   174  		t.Fatal(err)
   175  	}
   176  	if _, err := s.Create(ctx, "fake2", "fake"); err != nil {
   177  		t.Fatal(err)
   178  	}
   179  
   180  	dangling, _, err := s.Find(ctx, ByReferenced(false))
   181  	assert.NilError(t, err)
   182  	assert.Assert(t, len(dangling) == 1)
   183  	assert.Check(t, dangling[0].Name() == "fake2")
   184  
   185  	used, _, err := s.Find(ctx, ByReferenced(true))
   186  	assert.NilError(t, err)
   187  	assert.Assert(t, len(used) == 1)
   188  	assert.Check(t, used[0].Name() == "fake1")
   189  }
   190  
   191  func TestDerefMultipleOfSameRef(t *testing.T) {
   192  	t.Parallel()
   193  	s, cleanup := setupTest(t)
   194  	defer cleanup()
   195  	s.drivers.Register(volumetestutils.NewFakeDriver("fake"), "fake")
   196  
   197  	ctx := context.Background()
   198  	v, err := s.Create(ctx, "fake1", "fake", opts.WithCreateReference("volReference"))
   199  	if err != nil {
   200  		t.Fatal(err)
   201  	}
   202  
   203  	if _, err := s.Get(ctx, "fake1", opts.WithGetDriver("fake"), opts.WithGetReference("volReference")); err != nil {
   204  		t.Fatal(err)
   205  	}
   206  
   207  	s.Release(ctx, v.Name(), "volReference")
   208  	if err := s.Remove(ctx, v); err != nil {
   209  		t.Fatal(err)
   210  	}
   211  }
   212  
   213  func TestCreateKeepOptsLabelsWhenExistsRemotely(t *testing.T) {
   214  	t.Parallel()
   215  	s, cleanup := setupTest(t)
   216  	defer cleanup()
   217  
   218  	vd := volumetestutils.NewFakeDriver("fake")
   219  	s.drivers.Register(vd, "fake")
   220  
   221  	// Create a volume in the driver directly
   222  	if _, err := vd.Create("foo", nil); err != nil {
   223  		t.Fatal(err)
   224  	}
   225  
   226  	ctx := context.Background()
   227  	v, err := s.Create(ctx, "foo", "fake", opts.WithCreateLabels(map[string]string{"hello": "world"}))
   228  	if err != nil {
   229  		t.Fatal(err)
   230  	}
   231  
   232  	switch dv := v.(type) {
   233  	case volume.DetailedVolume:
   234  		if dv.Labels()["hello"] != "world" {
   235  			t.Fatalf("labels don't match")
   236  		}
   237  	default:
   238  		t.Fatalf("got unexpected type: %T", v)
   239  	}
   240  }
   241  
   242  func TestDefererencePluginOnCreateError(t *testing.T) {
   243  	t.Parallel()
   244  
   245  	var (
   246  		l   net.Listener
   247  		err error
   248  	)
   249  
   250  	for i := 32768; l == nil && i < 40000; i++ {
   251  		l, err = net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", i))
   252  	}
   253  	if l == nil {
   254  		t.Fatalf("could not create listener: %v", err)
   255  	}
   256  	defer l.Close()
   257  
   258  	s, cleanup := setupTest(t)
   259  	defer cleanup()
   260  
   261  	d := volumetestutils.NewFakeDriver("TestDefererencePluginOnCreateError")
   262  	p, err := volumetestutils.MakeFakePlugin(d, l)
   263  	if err != nil {
   264  		t.Fatal(err)
   265  	}
   266  
   267  	pg := volumetestutils.NewFakePluginGetter(p)
   268  	s.drivers = volumedrivers.NewStore(pg)
   269  
   270  	ctx := context.Background()
   271  	// create a good volume so we have a plugin reference
   272  	_, err = s.Create(ctx, "fake1", d.Name())
   273  	if err != nil {
   274  		t.Fatal(err)
   275  	}
   276  
   277  	// Now create another one expecting an error
   278  	_, err = s.Create(ctx, "fake2", d.Name(), opts.WithCreateOptions(map[string]string{"error": "some error"}))
   279  	if err == nil || !strings.Contains(err.Error(), "some error") {
   280  		t.Fatalf("expected an error on create: %v", err)
   281  	}
   282  
   283  	// There should be only 1 plugin reference
   284  	if refs := volumetestutils.FakeRefs(p); refs != 1 {
   285  		t.Fatalf("expected 1 plugin reference, got: %d", refs)
   286  	}
   287  }
   288  
   289  func TestRefDerefRemove(t *testing.T) {
   290  	t.Parallel()
   291  
   292  	driverName := "test-ref-deref-remove"
   293  	s, cleanup := setupTest(t)
   294  	defer cleanup()
   295  	s.drivers.Register(volumetestutils.NewFakeDriver(driverName), driverName)
   296  
   297  	ctx := context.Background()
   298  	v, err := s.Create(ctx, "test", driverName, opts.WithCreateReference("test-ref"))
   299  	assert.NilError(t, err)
   300  
   301  	err = s.Remove(ctx, v)
   302  	assert.Assert(t, is.ErrorContains(err, ""))
   303  	assert.Equal(t, errVolumeInUse, err.(*OpErr).Err)
   304  
   305  	s.Release(ctx, v.Name(), "test-ref")
   306  	err = s.Remove(ctx, v)
   307  	assert.NilError(t, err)
   308  }
   309  
   310  func TestGet(t *testing.T) {
   311  	t.Parallel()
   312  
   313  	driverName := "test-get"
   314  	s, cleanup := setupTest(t)
   315  	defer cleanup()
   316  	s.drivers.Register(volumetestutils.NewFakeDriver(driverName), driverName)
   317  
   318  	ctx := context.Background()
   319  	_, err := s.Get(ctx, "not-exist")
   320  	assert.Assert(t, is.ErrorContains(err, ""))
   321  	assert.Equal(t, errNoSuchVolume, err.(*OpErr).Err)
   322  
   323  	v1, err := s.Create(ctx, "test", driverName, opts.WithCreateLabels(map[string]string{"a": "1"}))
   324  	assert.NilError(t, err)
   325  
   326  	v2, err := s.Get(ctx, "test")
   327  	assert.NilError(t, err)
   328  	assert.DeepEqual(t, v1, v2, cmpVolume)
   329  
   330  	dv := v2.(volume.DetailedVolume)
   331  	assert.Equal(t, "1", dv.Labels()["a"])
   332  
   333  	err = s.Remove(ctx, v1)
   334  	assert.NilError(t, err)
   335  }
   336  
   337  func TestGetWithReference(t *testing.T) {
   338  	t.Parallel()
   339  
   340  	driverName := "test-get-with-ref"
   341  	s, cleanup := setupTest(t)
   342  	defer cleanup()
   343  	s.drivers.Register(volumetestutils.NewFakeDriver(driverName), driverName)
   344  
   345  	ctx := context.Background()
   346  	_, err := s.Get(ctx, "not-exist", opts.WithGetDriver(driverName), opts.WithGetReference("test-ref"))
   347  	assert.Assert(t, is.ErrorContains(err, ""))
   348  
   349  	v1, err := s.Create(ctx, "test", driverName, opts.WithCreateLabels(map[string]string{"a": "1"}))
   350  	assert.NilError(t, err)
   351  
   352  	v2, err := s.Get(ctx, "test", opts.WithGetDriver(driverName), opts.WithGetReference("test-ref"))
   353  	assert.NilError(t, err)
   354  	assert.DeepEqual(t, v1, v2, cmpVolume)
   355  
   356  	err = s.Remove(ctx, v2)
   357  	assert.Assert(t, is.ErrorContains(err, ""))
   358  	assert.Equal(t, errVolumeInUse, err.(*OpErr).Err)
   359  
   360  	s.Release(ctx, v2.Name(), "test-ref")
   361  	err = s.Remove(ctx, v2)
   362  	assert.NilError(t, err)
   363  }
   364  
   365  var cmpVolume = cmp.AllowUnexported(volumetestutils.FakeVolume{}, volumeWrapper{})
   366  
   367  func setupTest(t *testing.T) (*VolumeStore, func()) {
   368  	t.Helper()
   369  
   370  	dirName := strings.Replace(t.Name(), string(os.PathSeparator), "_", -1)
   371  	dir, err := os.MkdirTemp("", dirName)
   372  	assert.NilError(t, err)
   373  
   374  	cleanup := func() {
   375  		t.Helper()
   376  		err := os.RemoveAll(dir)
   377  		assert.Check(t, err)
   378  	}
   379  
   380  	s, err := NewStore(dir, volumedrivers.NewStore(nil))
   381  	assert.Check(t, err)
   382  	return s, func() {
   383  		s.Shutdown()
   384  		cleanup()
   385  	}
   386  }
   387  
   388  func TestFilterFunc(t *testing.T) {
   389  	testDriver := volumetestutils.NewFakeDriver("test")
   390  	testVolume, err := testDriver.Create("test", nil)
   391  	assert.NilError(t, err)
   392  	testVolume2, err := testDriver.Create("test2", nil)
   393  	assert.NilError(t, err)
   394  	testVolume3, err := testDriver.Create("test3", nil)
   395  	assert.NilError(t, err)
   396  
   397  	for _, test := range []struct {
   398  		vols   []volume.Volume
   399  		fn     filterFunc
   400  		desc   string
   401  		expect []volume.Volume
   402  	}{
   403  		{desc: "test nil list", vols: nil, expect: nil, fn: func(volume.Volume) bool { return true }},
   404  		{desc: "test empty list", vols: []volume.Volume{}, expect: []volume.Volume{}, fn: func(volume.Volume) bool { return true }},
   405  		{desc: "test filter non-empty to empty", vols: []volume.Volume{testVolume}, expect: []volume.Volume{}, fn: func(volume.Volume) bool { return false }},
   406  		{desc: "test nothing to fitler non-empty list", vols: []volume.Volume{testVolume}, expect: []volume.Volume{testVolume}, fn: func(volume.Volume) bool { return true }},
   407  		{desc: "test filter some", vols: []volume.Volume{testVolume, testVolume2}, expect: []volume.Volume{testVolume}, fn: func(v volume.Volume) bool { return v.Name() == testVolume.Name() }},
   408  		{desc: "test filter middle", vols: []volume.Volume{testVolume, testVolume2, testVolume3}, expect: []volume.Volume{testVolume, testVolume3}, fn: func(v volume.Volume) bool { return v.Name() != testVolume2.Name() }},
   409  		{desc: "test filter middle and last", vols: []volume.Volume{testVolume, testVolume2, testVolume3}, expect: []volume.Volume{testVolume}, fn: func(v volume.Volume) bool { return v.Name() != testVolume2.Name() && v.Name() != testVolume3.Name() }},
   410  		{desc: "test filter first and last", vols: []volume.Volume{testVolume, testVolume2, testVolume3}, expect: []volume.Volume{testVolume2}, fn: func(v volume.Volume) bool { return v.Name() != testVolume.Name() && v.Name() != testVolume3.Name() }},
   411  	} {
   412  		t.Run(test.desc, func(t *testing.T) {
   413  			test := test
   414  			t.Parallel()
   415  
   416  			filter(&test.vols, test.fn)
   417  			assert.DeepEqual(t, test.vols, test.expect, cmpVolume)
   418  		})
   419  	}
   420  }