Add targetOS to WithVolumes()

Windows systems are capable of running both Windows Containers and Linux
containers. For windows containers we need to sanitize the volume path
and skip non-C volumes from the copy existing contents code path. Linux
containers running on Windows and Linux must not have the path sanitized
in any way.

Supplying the targetOS of the container allows us to proprely decide
when to activate that code path.

Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This commit is contained in:
Gabriel Adrian Samfira 2023-05-16 10:55:10 +03:00
parent c7ec95caf4
commit 88a3e25b3d
3 changed files with 19 additions and 17 deletions

View File

@ -55,7 +55,7 @@ func WithNewSnapshot(id string, i containerd.Image, opts ...snapshots.Opt) conta
// WithVolumes copies ownership of volume in rootfs to its corresponding host path. // WithVolumes copies ownership of volume in rootfs to its corresponding host path.
// It doesn't update runtime spec. // It doesn't update runtime spec.
// The passed in map is a host path to container path map for all volumes. // The passed in map is a host path to container path map for all volumes.
func WithVolumes(volumeMounts map[string]string) containerd.NewContainerOpts { func WithVolumes(volumeMounts map[string]string, targetOS string) containerd.NewContainerOpts {
return func(ctx context.Context, client *containerd.Client, c *containers.Container) (err error) { return func(ctx context.Context, client *containerd.Client, c *containers.Container) (err error) {
if c.Snapshotter == "" { if c.Snapshotter == "" {
return errors.New("no snapshotter set for container") return errors.New("no snapshotter set for container")
@ -97,21 +97,23 @@ func WithVolumes(volumeMounts map[string]string) containerd.NewContainerOpts {
}() }()
for host, volume := range volumeMounts { for host, volume := range volumeMounts {
// Windows allows volume mounts in subfolders under C: and as any other drive letter like D:, E:, etc. if targetOS == "windows" {
// An image may contain files inside a folder defined as a VOLUME in a Dockerfile. On Windows, images // Windows allows volume mounts in subfolders under C: and as any other drive letter like D:, E:, etc.
// can only contain pre-existing files for volumes situated on the root filesystem, which is C:. // An image may contain files inside a folder defined as a VOLUME in a Dockerfile. On Windows, images
// For any other volumes, we need to skip attempting to copy existing contents. // can only contain pre-existing files for volumes situated on the root filesystem, which is C:.
// // For any other volumes, we need to skip attempting to copy existing contents.
// C:\some\volume --> \some\volume //
// D:\some\volume --> skip // C:\some\volume --> \some\volume
if len(volume) >= 2 && string(volume[1]) == ":" { // D:\some\volume --> skip
// Perform a case insensitive comparison to "C", and skip non-C mounted volumes. if len(volume) >= 2 && string(volume[1]) == ":" {
if !strings.EqualFold(string(volume[0]), "c") { // Perform a case insensitive comparison to "C", and skip non-C mounted volumes.
continue if !strings.EqualFold(string(volume[0]), "c") {
continue
}
// This is a volume mounted somewhere under C:\. We strip the drive letter and allow fs.RootPath()
// to append the remaining path to the rootfs path as seen by the host OS.
volume = volume[2:]
} }
// This is a volume mounted somewhere under C:\. We strip the drive letter and allow fs.RootPath()
// to append the remaining path to the rootfs path as seen by the host OS.
volume = volume[2:]
} }
src, err := fs.RootPath(root, volume) src, err := fs.RootPath(root, volume)
if err != nil { if err != nil {

View File

@ -223,7 +223,7 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta
for _, v := range volumeMounts { for _, v := range volumeMounts {
mountMap[filepath.Clean(v.HostPath)] = v.ContainerPath mountMap[filepath.Clean(v.HostPath)] = v.ContainerPath
} }
opts = append(opts, customopts.WithVolumes(mountMap)) opts = append(opts, customopts.WithVolumes(mountMap, image.ImageSpec.OS))
} }
meta.ImageRef = image.ID meta.ImageRef = image.ID
meta.StopSignal = image.ImageSpec.Config.StopSignal meta.StopSignal = image.ImageSpec.Config.StopSignal

View File

@ -203,7 +203,7 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta
for _, v := range volumeMounts { for _, v := range volumeMounts {
mountMap[filepath.Clean(v.HostPath)] = v.ContainerPath mountMap[filepath.Clean(v.HostPath)] = v.ContainerPath
} }
opts = append(opts, customopts.WithVolumes(mountMap)) opts = append(opts, customopts.WithVolumes(mountMap, image.ImageSpec.OS))
} }
meta.ImageRef = image.ID meta.ImageRef = image.ID
meta.StopSignal = image.ImageSpec.Config.StopSignal meta.StopSignal = image.ImageSpec.Config.StopSignal