github.com/ali-iotechsys/cli@v20.10.0+incompatible/cli/compose/convert/volume_test.go (about)

     1  package convert
     2  
     3  import (
     4  	"testing"
     5  
     6  	composetypes "github.com/docker/cli/cli/compose/types"
     7  	"github.com/docker/docker/api/types/mount"
     8  	"gotest.tools/v3/assert"
     9  	is "gotest.tools/v3/assert/cmp"
    10  )
    11  
    12  func TestConvertVolumeToMountAnonymousVolume(t *testing.T) {
    13  	config := composetypes.ServiceVolumeConfig{
    14  		Type:   "volume",
    15  		Target: "/foo/bar",
    16  	}
    17  	expected := mount.Mount{
    18  		Type:   mount.TypeVolume,
    19  		Target: "/foo/bar",
    20  	}
    21  	mount, err := convertVolumeToMount(config, volumes{}, NewNamespace("foo"))
    22  	assert.NilError(t, err)
    23  	assert.Check(t, is.DeepEqual(expected, mount))
    24  }
    25  
    26  func TestConvertVolumeToMountAnonymousBind(t *testing.T) {
    27  	config := composetypes.ServiceVolumeConfig{
    28  		Type:   "bind",
    29  		Target: "/foo/bar",
    30  		Bind: &composetypes.ServiceVolumeBind{
    31  			Propagation: "slave",
    32  		},
    33  	}
    34  	_, err := convertVolumeToMount(config, volumes{}, NewNamespace("foo"))
    35  	assert.Error(t, err, "invalid bind source, source cannot be empty")
    36  }
    37  
    38  func TestConvertVolumeToMountUnapprovedType(t *testing.T) {
    39  	config := composetypes.ServiceVolumeConfig{
    40  		Type:   "foo",
    41  		Target: "/foo/bar",
    42  	}
    43  	_, err := convertVolumeToMount(config, volumes{}, NewNamespace("foo"))
    44  	assert.Error(t, err, "volume type must be volume, bind, tmpfs or npipe")
    45  }
    46  
    47  func TestConvertVolumeToMountConflictingOptionsBindInVolume(t *testing.T) {
    48  	namespace := NewNamespace("foo")
    49  
    50  	config := composetypes.ServiceVolumeConfig{
    51  		Type:   "volume",
    52  		Source: "foo",
    53  		Target: "/target",
    54  		Bind: &composetypes.ServiceVolumeBind{
    55  			Propagation: "slave",
    56  		},
    57  	}
    58  	_, err := convertVolumeToMount(config, volumes{}, namespace)
    59  	assert.Error(t, err, "bind options are incompatible with type volume")
    60  }
    61  
    62  func TestConvertVolumeToMountConflictingOptionsTmpfsInVolume(t *testing.T) {
    63  	namespace := NewNamespace("foo")
    64  
    65  	config := composetypes.ServiceVolumeConfig{
    66  		Type:   "volume",
    67  		Source: "foo",
    68  		Target: "/target",
    69  		Tmpfs: &composetypes.ServiceVolumeTmpfs{
    70  			Size: 1000,
    71  		},
    72  	}
    73  	_, err := convertVolumeToMount(config, volumes{}, namespace)
    74  	assert.Error(t, err, "tmpfs options are incompatible with type volume")
    75  }
    76  
    77  func TestConvertVolumeToMountConflictingOptionsVolumeInBind(t *testing.T) {
    78  	namespace := NewNamespace("foo")
    79  
    80  	config := composetypes.ServiceVolumeConfig{
    81  		Type:   "bind",
    82  		Source: "/foo",
    83  		Target: "/target",
    84  		Volume: &composetypes.ServiceVolumeVolume{
    85  			NoCopy: true,
    86  		},
    87  	}
    88  	_, err := convertVolumeToMount(config, volumes{}, namespace)
    89  	assert.Error(t, err, "volume options are incompatible with type bind")
    90  }
    91  
    92  func TestConvertVolumeToMountConflictingOptionsTmpfsInBind(t *testing.T) {
    93  	namespace := NewNamespace("foo")
    94  
    95  	config := composetypes.ServiceVolumeConfig{
    96  		Type:   "bind",
    97  		Source: "/foo",
    98  		Target: "/target",
    99  		Tmpfs: &composetypes.ServiceVolumeTmpfs{
   100  			Size: 1000,
   101  		},
   102  	}
   103  	_, err := convertVolumeToMount(config, volumes{}, namespace)
   104  	assert.Error(t, err, "tmpfs options are incompatible with type bind")
   105  }
   106  
   107  func TestConvertVolumeToMountConflictingOptionsBindInTmpfs(t *testing.T) {
   108  	namespace := NewNamespace("foo")
   109  
   110  	config := composetypes.ServiceVolumeConfig{
   111  		Type:   "tmpfs",
   112  		Target: "/target",
   113  		Bind: &composetypes.ServiceVolumeBind{
   114  			Propagation: "slave",
   115  		},
   116  	}
   117  	_, err := convertVolumeToMount(config, volumes{}, namespace)
   118  	assert.Error(t, err, "bind options are incompatible with type tmpfs")
   119  }
   120  
   121  func TestConvertVolumeToMountConflictingOptionsVolumeInTmpfs(t *testing.T) {
   122  	namespace := NewNamespace("foo")
   123  
   124  	config := composetypes.ServiceVolumeConfig{
   125  		Type:   "tmpfs",
   126  		Target: "/target",
   127  		Volume: &composetypes.ServiceVolumeVolume{
   128  			NoCopy: true,
   129  		},
   130  	}
   131  	_, err := convertVolumeToMount(config, volumes{}, namespace)
   132  	assert.Error(t, err, "volume options are incompatible with type tmpfs")
   133  }
   134  
   135  func TestConvertVolumeToMountNamedVolume(t *testing.T) {
   136  	stackVolumes := volumes{
   137  		"normal": composetypes.VolumeConfig{
   138  			Driver: "glusterfs",
   139  			DriverOpts: map[string]string{
   140  				"opt": "value",
   141  			},
   142  			Labels: map[string]string{
   143  				"something": "labeled",
   144  			},
   145  		},
   146  	}
   147  	namespace := NewNamespace("foo")
   148  	expected := mount.Mount{
   149  		Type:     mount.TypeVolume,
   150  		Source:   "foo_normal",
   151  		Target:   "/foo",
   152  		ReadOnly: true,
   153  		VolumeOptions: &mount.VolumeOptions{
   154  			Labels: map[string]string{
   155  				LabelNamespace: "foo",
   156  				"something":    "labeled",
   157  			},
   158  			DriverConfig: &mount.Driver{
   159  				Name: "glusterfs",
   160  				Options: map[string]string{
   161  					"opt": "value",
   162  				},
   163  			},
   164  			NoCopy: true,
   165  		},
   166  	}
   167  	config := composetypes.ServiceVolumeConfig{
   168  		Type:     "volume",
   169  		Source:   "normal",
   170  		Target:   "/foo",
   171  		ReadOnly: true,
   172  		Volume: &composetypes.ServiceVolumeVolume{
   173  			NoCopy: true,
   174  		},
   175  	}
   176  	mount, err := convertVolumeToMount(config, stackVolumes, namespace)
   177  	assert.NilError(t, err)
   178  	assert.Check(t, is.DeepEqual(expected, mount))
   179  }
   180  
   181  func TestConvertVolumeToMountNamedVolumeWithNameCustomizd(t *testing.T) {
   182  	stackVolumes := volumes{
   183  		"normal": composetypes.VolumeConfig{
   184  			Name:   "user_specified_name",
   185  			Driver: "vsphere",
   186  			DriverOpts: map[string]string{
   187  				"opt": "value",
   188  			},
   189  			Labels: map[string]string{
   190  				"something": "labeled",
   191  			},
   192  		},
   193  	}
   194  	namespace := NewNamespace("foo")
   195  	expected := mount.Mount{
   196  		Type:     mount.TypeVolume,
   197  		Source:   "user_specified_name",
   198  		Target:   "/foo",
   199  		ReadOnly: true,
   200  		VolumeOptions: &mount.VolumeOptions{
   201  			Labels: map[string]string{
   202  				LabelNamespace: "foo",
   203  				"something":    "labeled",
   204  			},
   205  			DriverConfig: &mount.Driver{
   206  				Name: "vsphere",
   207  				Options: map[string]string{
   208  					"opt": "value",
   209  				},
   210  			},
   211  			NoCopy: true,
   212  		},
   213  	}
   214  	config := composetypes.ServiceVolumeConfig{
   215  		Type:     "volume",
   216  		Source:   "normal",
   217  		Target:   "/foo",
   218  		ReadOnly: true,
   219  		Volume: &composetypes.ServiceVolumeVolume{
   220  			NoCopy: true,
   221  		},
   222  	}
   223  	mount, err := convertVolumeToMount(config, stackVolumes, namespace)
   224  	assert.NilError(t, err)
   225  	assert.Check(t, is.DeepEqual(expected, mount))
   226  }
   227  
   228  func TestConvertVolumeToMountNamedVolumeExternal(t *testing.T) {
   229  	stackVolumes := volumes{
   230  		"outside": composetypes.VolumeConfig{
   231  			Name:     "special",
   232  			External: composetypes.External{External: true},
   233  		},
   234  	}
   235  	namespace := NewNamespace("foo")
   236  	expected := mount.Mount{
   237  		Type:          mount.TypeVolume,
   238  		Source:        "special",
   239  		Target:        "/foo",
   240  		VolumeOptions: &mount.VolumeOptions{NoCopy: false},
   241  	}
   242  	config := composetypes.ServiceVolumeConfig{
   243  		Type:   "volume",
   244  		Source: "outside",
   245  		Target: "/foo",
   246  	}
   247  	mount, err := convertVolumeToMount(config, stackVolumes, namespace)
   248  	assert.NilError(t, err)
   249  	assert.Check(t, is.DeepEqual(expected, mount))
   250  }
   251  
   252  func TestConvertVolumeToMountNamedVolumeExternalNoCopy(t *testing.T) {
   253  	stackVolumes := volumes{
   254  		"outside": composetypes.VolumeConfig{
   255  			Name:     "special",
   256  			External: composetypes.External{External: true},
   257  		},
   258  	}
   259  	namespace := NewNamespace("foo")
   260  	expected := mount.Mount{
   261  		Type:   mount.TypeVolume,
   262  		Source: "special",
   263  		Target: "/foo",
   264  		VolumeOptions: &mount.VolumeOptions{
   265  			NoCopy: true,
   266  		},
   267  	}
   268  	config := composetypes.ServiceVolumeConfig{
   269  		Type:   "volume",
   270  		Source: "outside",
   271  		Target: "/foo",
   272  		Volume: &composetypes.ServiceVolumeVolume{
   273  			NoCopy: true,
   274  		},
   275  	}
   276  	mount, err := convertVolumeToMount(config, stackVolumes, namespace)
   277  	assert.NilError(t, err)
   278  	assert.Check(t, is.DeepEqual(expected, mount))
   279  }
   280  
   281  func TestConvertVolumeToMountBind(t *testing.T) {
   282  	stackVolumes := volumes{}
   283  	namespace := NewNamespace("foo")
   284  	expected := mount.Mount{
   285  		Type:        mount.TypeBind,
   286  		Source:      "/bar",
   287  		Target:      "/foo",
   288  		ReadOnly:    true,
   289  		BindOptions: &mount.BindOptions{Propagation: mount.PropagationShared},
   290  	}
   291  	config := composetypes.ServiceVolumeConfig{
   292  		Type:     "bind",
   293  		Source:   "/bar",
   294  		Target:   "/foo",
   295  		ReadOnly: true,
   296  		Bind:     &composetypes.ServiceVolumeBind{Propagation: "shared"},
   297  	}
   298  	mount, err := convertVolumeToMount(config, stackVolumes, namespace)
   299  	assert.NilError(t, err)
   300  	assert.Check(t, is.DeepEqual(expected, mount))
   301  }
   302  
   303  func TestConvertVolumeToMountVolumeDoesNotExist(t *testing.T) {
   304  	namespace := NewNamespace("foo")
   305  	config := composetypes.ServiceVolumeConfig{
   306  		Type:     "volume",
   307  		Source:   "unknown",
   308  		Target:   "/foo",
   309  		ReadOnly: true,
   310  	}
   311  	_, err := convertVolumeToMount(config, volumes{}, namespace)
   312  	assert.Error(t, err, "undefined volume \"unknown\"")
   313  }
   314  
   315  func TestConvertTmpfsToMountVolume(t *testing.T) {
   316  	config := composetypes.ServiceVolumeConfig{
   317  		Type:   "tmpfs",
   318  		Target: "/foo/bar",
   319  		Tmpfs: &composetypes.ServiceVolumeTmpfs{
   320  			Size: 1000,
   321  		},
   322  	}
   323  	expected := mount.Mount{
   324  		Type:         mount.TypeTmpfs,
   325  		Target:       "/foo/bar",
   326  		TmpfsOptions: &mount.TmpfsOptions{SizeBytes: 1000},
   327  	}
   328  	mount, err := convertVolumeToMount(config, volumes{}, NewNamespace("foo"))
   329  	assert.NilError(t, err)
   330  	assert.Check(t, is.DeepEqual(expected, mount))
   331  }
   332  
   333  func TestConvertTmpfsToMountVolumeWithSource(t *testing.T) {
   334  	config := composetypes.ServiceVolumeConfig{
   335  		Type:   "tmpfs",
   336  		Source: "/bar",
   337  		Target: "/foo/bar",
   338  		Tmpfs: &composetypes.ServiceVolumeTmpfs{
   339  			Size: 1000,
   340  		},
   341  	}
   342  
   343  	_, err := convertVolumeToMount(config, volumes{}, NewNamespace("foo"))
   344  	assert.Error(t, err, "invalid tmpfs source, source must be empty")
   345  }
   346  
   347  func TestConvertVolumeToMountAnonymousNpipe(t *testing.T) {
   348  	config := composetypes.ServiceVolumeConfig{
   349  		Type:   "npipe",
   350  		Source: `\\.\pipe\foo`,
   351  		Target: `\\.\pipe\foo`,
   352  	}
   353  	expected := mount.Mount{
   354  		Type:   mount.TypeNamedPipe,
   355  		Source: `\\.\pipe\foo`,
   356  		Target: `\\.\pipe\foo`,
   357  	}
   358  	mount, err := convertVolumeToMount(config, volumes{}, NewNamespace("foo"))
   359  	assert.NilError(t, err)
   360  	assert.Check(t, is.DeepEqual(expected, mount))
   361  }