2020-02-13 12:57:41 +00:00
|
|
|
package taskrunner
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/hashicorp/nomad/client/allocrunner/interfaces"
|
|
|
|
"github.com/hashicorp/nomad/client/pluginmanager/csimanager"
|
|
|
|
cstructs "github.com/hashicorp/nomad/client/structs"
|
2020-03-17 14:25:03 +00:00
|
|
|
"github.com/hashicorp/nomad/client/taskenv"
|
2020-02-13 12:57:41 +00:00
|
|
|
"github.com/hashicorp/nomad/helper/testlog"
|
2020-03-17 14:25:03 +00:00
|
|
|
"github.com/hashicorp/nomad/nomad/mock"
|
2020-02-13 12:57:41 +00:00
|
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
|
|
|
"github.com/hashicorp/nomad/plugins/drivers"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestVolumeHook_PartitionMountsByVolume_Works(t *testing.T) {
|
|
|
|
mounts := []*structs.VolumeMount{
|
|
|
|
{
|
|
|
|
Volume: "foo",
|
|
|
|
Destination: "/tmp",
|
|
|
|
ReadOnly: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Volume: "foo",
|
|
|
|
Destination: "/bar",
|
|
|
|
ReadOnly: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Volume: "baz",
|
|
|
|
Destination: "/baz",
|
|
|
|
ReadOnly: false,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
expected := map[string][]*structs.VolumeMount{
|
|
|
|
"foo": {
|
|
|
|
{
|
|
|
|
Volume: "foo",
|
|
|
|
Destination: "/tmp",
|
|
|
|
ReadOnly: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Volume: "foo",
|
|
|
|
Destination: "/bar",
|
|
|
|
ReadOnly: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"baz": {
|
|
|
|
{
|
|
|
|
Volume: "baz",
|
|
|
|
Destination: "/baz",
|
|
|
|
ReadOnly: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test with a real collection
|
|
|
|
|
|
|
|
partitioned := partitionMountsByVolume(mounts)
|
|
|
|
require.Equal(t, expected, partitioned)
|
|
|
|
|
|
|
|
// Test with nil/emptylist
|
|
|
|
|
|
|
|
partitioned = partitionMountsByVolume(nil)
|
|
|
|
require.Equal(t, map[string][]*structs.VolumeMount{}, partitioned)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestVolumeHook_prepareCSIVolumes(t *testing.T) {
|
|
|
|
req := &interfaces.TaskPrestartRequest{
|
|
|
|
Task: &structs.Task{
|
|
|
|
VolumeMounts: []*structs.VolumeMount{
|
|
|
|
{
|
|
|
|
Volume: "foo",
|
|
|
|
Destination: "/bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
volumes := map[string]*structs.VolumeRequest{
|
|
|
|
"foo": {
|
|
|
|
Type: "csi",
|
|
|
|
Source: "my-test-volume",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
tr := &TaskRunner{
|
|
|
|
allocHookResources: &cstructs.AllocHookResources{
|
|
|
|
CSIMounts: map[string]*csimanager.MountInfo{
|
2020-03-17 14:25:03 +00:00
|
|
|
"foo": {
|
2020-02-13 12:57:41 +00:00
|
|
|
Source: "/mnt/my-test-volume",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
expected := []*drivers.MountConfig{
|
|
|
|
{
|
|
|
|
HostPath: "/mnt/my-test-volume",
|
|
|
|
TaskPath: "/bar",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
hook := &volumeHook{
|
|
|
|
logger: testlog.HCLogger(t),
|
|
|
|
alloc: structs.MockAlloc(),
|
|
|
|
runner: tr,
|
|
|
|
}
|
|
|
|
mounts, err := hook.prepareCSIVolumes(req, volumes)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, expected, mounts)
|
|
|
|
}
|
2020-03-17 14:25:03 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
}
|