diff --git a/runtime/docker/docker_test.go b/runtime/docker/docker_test.go index bf48aaa5..964648e7 100644 --- a/runtime/docker/docker_test.go +++ b/runtime/docker/docker_test.go @@ -348,6 +348,31 @@ func TestRunTaskWithBind(t *testing.T) { assert.NoError(t, err) } +func TestRunTaskWithBindAndPropagation(t *testing.T) { + mm := runtime.NewMultiMounter() + vm, err := NewVolumeMounter() + assert.NoError(t, err) + mm.RegisterMounter("bind", NewBindMounter(BindConfig{Allowed: true})) + mm.RegisterMounter("volume", vm) + rt, err := NewDockerRuntime(WithMounter(mm)) + assert.NoError(t, err) + ctx := context.Background() + dir := path.Join(os.TempDir(), uuid.NewUUID()) + t1 := &tork.Task{ + ID: uuid.NewUUID(), + Image: "busybox:stable", + Run: "echo hello world > /xyz/thing", + Mounts: []*tork.Mount{{ + Type: tork.MountTypeBind, + Target: "/xyz", + Source: dir, + Opts: map[string]string{"propagation": "rslave"}, + }}, + } + err = rt.Run(ctx, t1) + assert.NoError(t, err) +} + func TestRunTaskWithTempfs(t *testing.T) { rt, err := NewDockerRuntime( WithMounter(NewTmpfsMounter()), diff --git a/runtime/docker/tcontainer.go b/runtime/docker/tcontainer.go index eb9dacf5..4b408f7f 100644 --- a/runtime/docker/tcontainer.go +++ b/runtime/docker/tcontainer.go @@ -77,13 +77,21 @@ func createTaskContainer(ctx context.Context, rt *DockerRuntime, t *tork.Task, l default: return nil, errors.Errorf("unknown mount type: %s", m.Type) } - mount := mount.Mount{ - Type: mt, - Source: m.Source, - Target: m.Target, + mn := mount.Mount{ + Type: mt, + Source: m.Source, + Target: m.Target, + ReadOnly: m.Opts["readonly"] == "true", } - log.Debug().Msgf("Mounting %s -> %s", mount.Source, mount.Target) - mounts = append(mounts, mount) + if mt == mount.TypeBind { + if prop, ok := m.Opts["propagation"]; ok { + mn.BindOptions = &mount.BindOptions{ + Propagation: mount.Propagation(prop), + } + } + } + log.Debug().Msgf("Mounting %s -> %s", mn.Source, mn.Target) + mounts = append(mounts, mn) } torkdir := &tork.Mount{ diff --git a/runtime/podman/podman.go b/runtime/podman/podman.go index c7eea32f..4715817d 100644 --- a/runtime/podman/podman.go +++ b/runtime/podman/podman.go @@ -250,7 +250,7 @@ func (d *PodmanRuntime) doRun(ctx context.Context, t *tork.Task, logger io.Write case tork.MountTypeVolume: createCmd.Args = append(createCmd.Args, "-v", fmt.Sprintf("%s:%s", mount.Source, mount.Target)) case tork.MountTypeBind: - createCmd.Args = append(createCmd.Args, "-v", fmt.Sprintf("%s:%s", mount.Source, mount.Target)) + createCmd.Args = append(createCmd.Args, "-v", formatVolumeSpec(mount)) default: return fmt.Errorf("unknown mount type: %s", mount.Type) } @@ -383,6 +383,21 @@ func (d *PodmanRuntime) stop(ctx context.Context, t *tork.Task) error { return nil } +func formatVolumeSpec(m *tork.Mount) string { + spec := fmt.Sprintf("%s:%s", m.Source, m.Target) + var opts []string + if m.Opts["readonly"] == "true" { + opts = append(opts, "ro") + } + if prop, ok := m.Opts["propagation"]; ok { + opts = append(opts, prop) + } + if len(opts) > 0 { + spec += ":" + strings.Join(opts, ",") + } + return spec +} + func (d *PodmanRuntime) HealthCheck(ctx context.Context) error { cmd := exec.CommandContext(ctx, "podman", "version") if err := cmd.Run(); err != nil { diff --git a/runtime/podman/podman_test.go b/runtime/podman/podman_test.go index 2f3c965f..171e94d9 100644 --- a/runtime/podman/podman_test.go +++ b/runtime/podman/podman_test.go @@ -407,6 +407,37 @@ func TestRunTaskWithCustomMounter(t *testing.T) { assert.NoError(t, err) } +func TestFormatVolumeSpec(t *testing.T) { + assert.Equal(t, "/src:/dst", formatVolumeSpec(&tork.Mount{Source: "/src", Target: "/dst"})) + assert.Equal(t, "/src:/dst:rslave", formatVolumeSpec(&tork.Mount{Source: "/src", Target: "/dst", Opts: map[string]string{"propagation": "rslave"}})) + assert.Equal(t, "/src:/dst:ro", formatVolumeSpec(&tork.Mount{Source: "/src", Target: "/dst", Opts: map[string]string{"readonly": "true"}})) + assert.Equal(t, "/src:/dst:ro,rslave", formatVolumeSpec(&tork.Mount{Source: "/src", Target: "/dst", Opts: map[string]string{"readonly": "true", "propagation": "rslave"}})) +} + +func TestPodmanRunTaskWithBindAndPropagation(t *testing.T) { + mm := runtime.NewMultiMounter() + vm := NewVolumeMounter() + mm.RegisterMounter("bind", docker.NewBindMounter(docker.BindConfig{Allowed: true})) + mm.RegisterMounter("volume", vm) + rt := NewPodmanRuntime(WithMounter(mm)) + ctx := context.Background() + dir := path.Join(os.TempDir(), uuid.NewUUID()) + t1 := &tork.Task{ + ID: uuid.NewUUID(), + Name: "Some task", + Image: "busybox:stable", + Run: "echo hello world > /xyz/thing", + Mounts: []*tork.Mount{{ + Type: tork.MountTypeBind, + Target: "/xyz", + Source: dir, + Opts: map[string]string{"propagation": "rslave"}, + }}, + } + err := rt.Run(ctx, t1) + assert.NoError(t, err) +} + func Test_imagePull(t *testing.T) { ctx := context.Background()