From 5fbdc822cfc7ce0cde701b1e1b3cccad444c4a40 Mon Sep 17 00:00:00 2001 From: Tim Gross Date: Tue, 17 Mar 2020 09:36:11 -0400 Subject: [PATCH] volumes: add task environment interpolation to volume_mount --- client/allocrunner/taskrunner/volume_hook.go | 19 ++++- .../taskrunner/volume_hook_test.go | 71 +++++++++++++++++++ 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/client/allocrunner/taskrunner/volume_hook.go b/client/allocrunner/taskrunner/volume_hook.go index 5e35f99d3543..5447c50290f3 100644 --- a/client/allocrunner/taskrunner/volume_hook.go +++ b/client/allocrunner/taskrunner/volume_hook.go @@ -7,14 +7,16 @@ import ( log "github.com/hashicorp/go-hclog" multierror "github.com/hashicorp/go-multierror" "github.com/hashicorp/nomad/client/allocrunner/interfaces" + "github.com/hashicorp/nomad/client/taskenv" "github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/plugins/drivers" ) type volumeHook struct { - alloc *structs.Allocation - runner *TaskRunner - logger log.Logger + alloc *structs.Allocation + runner *TaskRunner + logger log.Logger + taskEnv *taskenv.TaskEnv } func newVolumeHook(runner *TaskRunner, logger log.Logger) *volumeHook { @@ -169,6 +171,9 @@ func (h *volumeHook) prepareCSIVolumes(req *interfaces.TaskPrestartRequest, volu } func (h *volumeHook) Prestart(ctx context.Context, req *interfaces.TaskPrestartRequest, resp *interfaces.TaskPrestartResponse) error { + h.taskEnv = req.TaskEnv + interpolateVolumeMounts(req.Task.VolumeMounts, h.taskEnv) + volumes := partitionVolumesByType(h.alloc.Job.LookupTaskGroup(h.alloc.TaskGroup).Volumes) hostVolumeMounts, err := h.prepareHostVolumes(req, volumes[structs.VolumeTypeHost]) @@ -196,3 +201,11 @@ func (h *volumeHook) Prestart(ctx context.Context, req *interfaces.TaskPrestartR return nil } + +func interpolateVolumeMounts(mounts []*structs.VolumeMount, taskEnv *taskenv.TaskEnv) { + for _, mount := range mounts { + mount.Volume = taskEnv.ReplaceEnv(mount.Volume) + mount.Destination = taskEnv.ReplaceEnv(mount.Destination) + mount.PropagationMode = taskEnv.ReplaceEnv(mount.PropagationMode) + } +} diff --git a/client/allocrunner/taskrunner/volume_hook_test.go b/client/allocrunner/taskrunner/volume_hook_test.go index 8c0e924fb042..f06896d5ddbb 100644 --- a/client/allocrunner/taskrunner/volume_hook_test.go +++ b/client/allocrunner/taskrunner/volume_hook_test.go @@ -6,7 +6,9 @@ import ( "github.com/hashicorp/nomad/client/allocrunner/interfaces" "github.com/hashicorp/nomad/client/pluginmanager/csimanager" cstructs "github.com/hashicorp/nomad/client/structs" + "github.com/hashicorp/nomad/client/taskenv" "github.com/hashicorp/nomad/helper/testlog" + "github.com/hashicorp/nomad/nomad/mock" "github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/plugins/drivers" "github.com/stretchr/testify/require" @@ -109,3 +111,72 @@ func TestVolumeHook_prepareCSIVolumes(t *testing.T) { require.NoError(t, err) require.Equal(t, expected, mounts) } + +func TestVolumeHook_Interpolation(t *testing.T) { + + alloc := mock.Alloc() + task := alloc.Job.TaskGroups[0].Tasks[0] + taskEnv := taskenv.NewBuilder(mock.Node(), alloc, task, "global").SetHookEnv("volume", + map[string]string{ + "PROPAGATION_MODE": "private", + "VOLUME_ID": "my-other-volume", + }, + ).Build() + + mounts := []*structs.VolumeMount{ + { + Volume: "foo", + Destination: "/tmp", + ReadOnly: false, + PropagationMode: "bidirectional", + }, + { + Volume: "foo", + Destination: "/bar-${NOMAD_JOB_NAME}", + ReadOnly: false, + PropagationMode: "bidirectional", + }, + { + Volume: "${VOLUME_ID}", + Destination: "/baz", + ReadOnly: false, + PropagationMode: "bidirectional", + }, + { + Volume: "foo", + Destination: "/quux", + ReadOnly: false, + PropagationMode: "${PROPAGATION_MODE}", + }, + } + + expected := []*structs.VolumeMount{ + { + Volume: "foo", + Destination: "/tmp", + ReadOnly: false, + PropagationMode: "bidirectional", + }, + { + Volume: "foo", + Destination: "/bar-my-job", + ReadOnly: false, + PropagationMode: "bidirectional", + }, + { + Volume: "my-other-volume", + Destination: "/baz", + ReadOnly: false, + PropagationMode: "bidirectional", + }, + { + Volume: "foo", + Destination: "/quux", + ReadOnly: false, + PropagationMode: "private", + }, + } + + interpolateVolumeMounts(mounts, taskEnv) + require.Equal(t, expected, mounts) +}