Skip to content

Commit f2531c9

Browse files
committed
feat: add volume-nocopy
Signed-off-by: Jiwoo Ahn <ikwydls1314@gmail.com>
1 parent fcaa66c commit f2531c9

6 files changed

Lines changed: 40 additions & 2 deletions

File tree

cmd/nerdctl/container/container_run_mount_linux_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,12 @@ CMD ["cat", "/mnt/initial_file"]
234234
volName := data.Identifier("vol")
235235
helpers.Ensure("volume", "create", volName)
236236

237+
noCopyVolName := data.Identifier("nocopy-vol")
238+
helpers.Ensure("volume", "create", noCopyVolName)
239+
237240
data.Labels().Set("img", imgName)
238241
data.Labels().Set("vol", volName)
242+
data.Labels().Set("nocopy-vol", noCopyVolName)
239243
}
240244

241245
testCase.SubTests = []*test.Case{
@@ -263,12 +267,22 @@ CMD ["cat", "/mnt/initial_file"]
263267
},
264268
Expected: test.Expects(expect.ExitCodeSuccess, nil, expect.Equals("hi\n")),
265269
},
270+
{
271+
Description: "with volume-nocopy",
272+
NoParallel: true,
273+
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
274+
mount := fmt.Sprintf("type=volume,source=%s,target=/mnt,volume-nocopy", data.Labels().Get("nocopy-vol"))
275+
return helpers.Command("run", "--rm", "--mount", mount, data.Labels().Get("img"), "sh", "-c", "test ! -e /mnt/initial_file")
276+
},
277+
Expected: test.Expects(expect.ExitCodeSuccess, nil, nil),
278+
},
266279
}
267280

268281
testCase.Cleanup = func(data test.Data, helpers test.Helpers) {
269282
helpers.Anyhow("volume", "rm", data.Labels().Get("vol"))
270283
helpers.Anyhow("rmi", data.Labels().Get("img"))
271284
helpers.Anyhow("builder", "prune", "--all", "--force")
285+
helpers.Anyhow("volume", "rm", data.Labels().Get("nocopy-vol"))
272286
}
273287

274288
testCase.Run(t)

docs/command-reference.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,8 @@ Volume flags:
324324
- :whale: `tmpfs-mode`: File mode of the tmpfs in **octal**.
325325
Defaults to `1777` or world-writable.
326326
- Options specific to `volume`:
327-
- unimplemented options: `volume-nocopy`, `volume-label`, `volume-driver`, `volume-opt`
327+
- :whale: `volume-nocopy`: Do not copy existing data from the container into the volume.
328+
- unimplemented options: `volume-label`, `volume-driver`, `volume-opt`
328329
- Options specific to `image`:
329330
- :whale: `src`, `source`: image reference (mandatory).
330331
- :whale: Currently, the image filesystem is mounted read-only.

pkg/cmd/container/run_mount.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ func generateMountOpts(ctx context.Context, client *containerd.Client, ensuredIm
319319
}
320320

321321
// Copying content in AnonymousVolume and namedVolume
322-
if x.Type == "volume" {
322+
if x.Type == mountutil.Volume && !x.VolumeNoCopy {
323323
if err := copyExistingContents(target, x.Mount.Source); err != nil {
324324
return nil, nil, nil, err
325325
}

pkg/mountutil/mountutil.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ type Processed struct {
5151
AnonymousVolume string // anonymous volume name
5252
Mode string
5353
Opts []oci.SpecOpts
54+
VolumeNoCopy bool
5455
// ImageMountSnapshot is the snapshotter key of the read-only view for a
5556
// type=image mount; empty for other mount types.
5657
ImageMountSnapshot string

pkg/mountutil/mountutil_linux.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,7 @@ func ProcessFlagMount(s string, volStore volumestore.VolumeStore, ociRuntime str
369369
bindPropagation string
370370
bindNonRecursive bool
371371
bindRecursive string // "enabled", "disabled", "writable", or "readonly"
372+
volumeNoCopy bool
372373
rwOption string
373374
tmpfsSize int64
374375
tmpfsMode os.FileMode
@@ -404,6 +405,9 @@ func ProcessFlagMount(s string, volStore volumestore.VolumeStore, ociRuntime str
404405
log.L.Warn("The mount option \"bind-nonrecursive\" is deprecated; use \"bind-recursive=disabled\" instead")
405406
bindNonRecursive = true
406407
continue
408+
case "volume-nocopy":
409+
volumeNoCopy = true
410+
continue
407411
}
408412
}
409413

@@ -480,6 +484,10 @@ func ProcessFlagMount(s string, volStore volumestore.VolumeStore, ociRuntime str
480484
}
481485
}
482486

487+
if volumeNoCopy && mountType != Volume {
488+
return nil, fmt.Errorf("the option 'volume-nocopy' is only supported for volume mounts")
489+
}
490+
483491
// type=image's source is an image reference resolved later with a containerd
484492
// client; validate the intent here. Like Docker, an image mount is always
485493
// read-only: a readonly/ro option is accepted for compatibility but the
@@ -593,6 +601,7 @@ func ProcessFlagMount(s string, volStore volumestore.VolumeStore, ociRuntime str
593601
if err != nil {
594602
return nil, err
595603
}
604+
res.VolumeNoCopy = volumeNoCopy
596605
if rwOption != "" {
597606
roOpts, err := readOnlyMountOptions(roMode, ociRuntime)
598607
if err != nil {

pkg/mountutil/mountutil_linux_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,3 +665,16 @@ func TestProcessFlagMountImage(t *testing.T) {
665665
})
666666
}
667667
}
668+
669+
func TestProcessFlagMountVolumeNoCopy(t *testing.T) {
670+
got, err := ProcessFlagMount(
671+
"type=volume,source=TestVolume,target=/mnt,volume-nocopy",
672+
mockVolumeStore,
673+
"",
674+
)
675+
assert.NilError(t, err)
676+
677+
assert.Equal(t, got.Type, Volume)
678+
assert.Equal(t, got.Name, "TestVolume")
679+
assert.Assert(t, got.VolumeNoCopy)
680+
}

0 commit comments

Comments
 (0)