Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 66 additions & 1 deletion runtime/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"time"

"github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/mount"
"github.com/docker/go-units"
"golang.org/x/sys/unix"

Expand Down Expand Up @@ -503,8 +504,17 @@ func (d *DockerRuntime) CreateContainer(ctx context.Context, node *types.NodeCon
Soft: int64(rlimit.Max),
}
resources.Ulimits = []*units.Ulimit{&ulimit}

bindMounts, volumeMounts, err := d.convertMounts(node.Binds)
if err != nil {
log.Errorf("Cannot convert mounts %v: %v", node.Binds, err)
bindMounts = nil
volumeMounts = nil
}

containerHostConfig := &container.HostConfig{
Binds: node.Binds,
Binds: bindMounts,
Mounts: volumeMounts,
PortBindings: node.PortBindings,
Sysctls: node.Sysctls,
Privileged: true,
Expand Down Expand Up @@ -1150,3 +1160,58 @@ func (*DockerRuntime) GetCooCBindMounts() types.Binds {
types.NewBind("/run/netns", "/run/netns", ""),
}
}

// convertMounts takes a list of filesystem bind mounts from the node "binds"
// field in docker/clab format (src:dest:options) and separates them into bind
// mounts (for HostConfig.Binds) and volumes (for HostConfig.Mounts) This
// maintains backards compatibility with the existing containerlab topology
// schema where anonymous volumes are sort of supported via the "binds" field.
// While this does work, it is not technically correct as volumes (anonymous or
// named) should be specified in the "volumes" field.
func (*DockerRuntime) convertMounts(binds []string) ([]string, []mount.Mount, error) {
if len(binds) == 0 {
return nil, nil, nil
}
log.Debugf("convertMounts function received binds %v", binds)

var bindMounts []string
var volumes []mount.Mount

// Note: we don't do any input validation here
for _, bind := range binds {
b, err := types.NewBindFromString(bind)
if err != nil {
return nil, nil, err
}

if b.Src() == "" {
// This is an anonymous volume - use Mount API
volMount := mount.Mount{
Target: b.Dst(),
Type: mount.TypeVolume,
}

// Handle volume-specific options (https://docs.docker.com/engine/storage/volumes/#options-for---volume).
if b.Mode() != "" {
options := strings.Split(b.Mode(), ",")
for _, option := range options {
if option == "ro" {
volMount.ReadOnly = true
} else if option == "volume-nocopy" {
volMount.VolumeOptions = &mount.VolumeOptions{
NoCopy: true,
}
}
}
}
volumes = append(volumes, volMount)
log.Debugf("parsed bind %q as a volume mount %+v", bind, volMount)
} else {
// This is a bind mount - use legacy Binds format
bindMounts = append(bindMounts, bind)
log.Debugf("parsed bind %q as a bind mount", bind)
}
}

return bindMounts, volumes, nil
}
15 changes: 7 additions & 8 deletions runtime/podman/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,21 +285,20 @@
mntSpec := make([]specs.Mount, len(mounts))
// Note: we don't do any input validation here
for i, mnt := range mounts {
mntSplit := strings.SplitN(mnt, ":", 3)

if len(mntSplit) == 1 {
return nil, fmt.Errorf("%w: %s", errInvalidBind, mnt)
bind, err := types.NewBind(mnt)

Check failure on line 288 in runtime/podman/util.go

View workflow job for this annotation

GitHub Actions / build-containerlab / build-clab

not enough arguments in call to types.NewBind

Check failure on line 288 in runtime/podman/util.go

View workflow job for this annotation

GitHub Actions / build-containerlab / build-clab

assignment mismatch: 2 variables but types.NewBind returns 1 value
if err != nil {
return nil, err
}

mntSpec[i] = specs.Mount{
Destination: mntSplit[1],
Destination: bind.Dst(),
Type: "bind",
Source: mntSplit[0],
Source: bind.Src(),
}

// when options are provided in the bind mount spec
if len(mntSplit) == 3 {
mntSpec[i].Options = strings.Split(mntSplit[2], ",")
if bind.Mode() != "" {
mntSpec[i].Options = strings.Split(bind.Mode(), ",")
}
}
log.Debugf("convertMounts method received mounts %v and produced %+v as a result", mounts, mntSpec)
Expand Down
Loading