github.com/hernad/nomad@v1.6.112/command/volume_register_test.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package command 5 6 import ( 7 "testing" 8 9 "github.com/hashicorp/hcl" 10 "github.com/hernad/nomad/api" 11 "github.com/hernad/nomad/ci" 12 "github.com/stretchr/testify/require" 13 ) 14 15 func TestVolumeDispatchParse(t *testing.T) { 16 ci.Parallel(t) 17 18 cases := []struct { 19 hcl string 20 t string 21 err string 22 }{{ 23 hcl: ` 24 type = "foo" 25 rando = "bar" 26 `, 27 t: "foo", 28 err: "", 29 }, { 30 hcl: `{"id": "foo", "type": "foo", "other": "bar"}`, 31 t: "foo", 32 err: "", 33 }} 34 35 for _, c := range cases { 36 t.Run(c.hcl, func(t *testing.T) { 37 _, s, err := parseVolumeType(c.hcl) 38 require.Equal(t, c.t, s) 39 if c.err == "" { 40 require.NoError(t, err) 41 } else { 42 require.Contains(t, err.Error(), c.err) 43 } 44 45 }) 46 } 47 } 48 49 func TestCSIVolumeDecode(t *testing.T) { 50 ci.Parallel(t) 51 52 cases := []struct { 53 name string 54 hcl string 55 expected *api.CSIVolume 56 err string 57 }{{ 58 name: "volume creation", 59 hcl: ` 60 id = "testvolume" 61 namespace = "prod" 62 name = "test" 63 type = "csi" 64 plugin_id = "myplugin" 65 66 capacity_min = "10 MiB" 67 capacity_max = "1G" 68 snapshot_id = "snap-12345" 69 70 mount_options { 71 fs_type = "ext4" 72 mount_flags = ["ro"] 73 } 74 75 secrets { 76 password = "xyzzy" 77 } 78 79 parameters { 80 skuname = "Premium_LRS" 81 } 82 83 capability { 84 access_mode = "single-node-writer" 85 attachment_mode = "file-system" 86 } 87 88 capability { 89 access_mode = "single-node-reader-only" 90 attachment_mode = "block-device" 91 } 92 93 topology_request { 94 preferred { 95 topology { segments {rack = "R1"} } 96 } 97 98 required { 99 topology { segments {rack = "R1"} } 100 topology { segments {rack = "R2", zone = "us-east-1a"} } 101 } 102 } 103 `, 104 expected: &api.CSIVolume{ 105 ID: "testvolume", 106 Namespace: "prod", 107 Name: "test", 108 PluginID: "myplugin", 109 SnapshotID: "snap-12345", 110 RequestedCapacityMin: 10485760, 111 RequestedCapacityMax: 1000000000, 112 RequestedCapabilities: []*api.CSIVolumeCapability{ 113 { 114 AccessMode: api.CSIVolumeAccessModeSingleNodeWriter, 115 AttachmentMode: api.CSIVolumeAttachmentModeFilesystem, 116 }, 117 { 118 AccessMode: api.CSIVolumeAccessModeSingleNodeReader, 119 AttachmentMode: api.CSIVolumeAttachmentModeBlockDevice, 120 }, 121 }, 122 MountOptions: &api.CSIMountOptions{ 123 FSType: "ext4", 124 MountFlags: []string{"ro"}, 125 }, 126 Parameters: map[string]string{"skuname": "Premium_LRS"}, 127 Secrets: map[string]string{"password": "xyzzy"}, 128 RequestedTopologies: &api.CSITopologyRequest{ 129 Required: []*api.CSITopology{ 130 {Segments: map[string]string{"rack": "R1"}}, 131 {Segments: map[string]string{"rack": "R2", "zone": "us-east-1a"}}, 132 }, 133 Preferred: []*api.CSITopology{ 134 {Segments: map[string]string{"rack": "R1"}}, 135 }, 136 }, 137 Topologies: nil, // this is left empty 138 }, 139 err: "", 140 }, { 141 name: "volume registration", 142 hcl: ` 143 id = "testvolume" 144 namespace = "prod" 145 external_id = "vol-12345" 146 name = "test" 147 type = "csi" 148 plugin_id = "myplugin" 149 capacity_min = "" # meaningless for registration 150 151 capability { 152 access_mode = "single-node-writer" 153 attachment_mode = "file-system" 154 } 155 156 topology_request { 157 # make sure we safely handle empty blocks even 158 # if they're invalid 159 preferred { 160 topology {} 161 topology { segments {} } 162 } 163 164 required { 165 topology { segments { rack = "R2", zone = "us-east-1a"} } 166 } 167 } 168 `, 169 expected: &api.CSIVolume{ 170 ID: "testvolume", 171 Namespace: "prod", 172 ExternalID: "vol-12345", 173 Name: "test", 174 PluginID: "myplugin", 175 RequestedCapabilities: []*api.CSIVolumeCapability{ 176 { 177 AccessMode: api.CSIVolumeAccessModeSingleNodeWriter, 178 AttachmentMode: api.CSIVolumeAttachmentModeFilesystem, 179 }, 180 }, 181 RequestedTopologies: &api.CSITopologyRequest{ 182 Required: []*api.CSITopology{ 183 {Segments: map[string]string{"rack": "R2", "zone": "us-east-1a"}}, 184 }, 185 Preferred: nil, 186 }, 187 Topologies: nil, 188 }, 189 err: "", 190 }, 191 } 192 193 for _, c := range cases { 194 t.Run(c.name, func(t *testing.T) { 195 ast, err := hcl.ParseString(c.hcl) 196 require.NoError(t, err) 197 vol, err := csiDecodeVolume(ast) 198 if c.err == "" { 199 require.NoError(t, err) 200 } else { 201 require.Contains(t, err.Error(), c.err) 202 } 203 require.Equal(t, c.expected, vol) 204 205 }) 206 207 } 208 }