csi: allow `namespace` field to be passed in volume spec (#12400)

Use the volume spec's `namespace` field to override the value of the
`-namespace` and `NOMAD_NAMESPACE` field, just as we do with job spec.
This commit is contained in:
Tim Gross 2022-03-29 14:46:39 -04:00 committed by GitHub
parent 19703e3316
commit 03c1904112
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 33 additions and 11 deletions

3
.changelog/12400.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
csi: allow namespace field to be passed in volume spec
```

View File

@ -110,6 +110,7 @@ func (c *VolumeInitCommand) Run(args []string) int {
var defaultHclVolumeSpec = strings.TrimSpace(`
id = "ebs_prod_db1"
namespace = "default"
name = "database"
type = "csi"
plugin_id = "plugin_id"
@ -183,6 +184,7 @@ context {
var defaultJsonVolumeSpec = strings.TrimSpace(`
{
"id": "ebs_prod_db1",
"namespace": "default",
"name": "database",
"type": "csi",
"plugin_id": "plugin_id",

View File

@ -55,6 +55,7 @@ func TestCSIVolumeDecode(t *testing.T) {
name: "volume creation",
hcl: `
id = "testvolume"
namespace = "prod"
name = "test"
type = "csi"
plugin_id = "myplugin"
@ -99,6 +100,7 @@ topology_request {
`,
expected: &api.CSIVolume{
ID: "testvolume",
Namespace: "prod",
Name: "test",
PluginID: "myplugin",
SnapshotID: "snap-12345",
@ -136,6 +138,7 @@ topology_request {
name: "volume registration",
hcl: `
id = "testvolume"
namespace = "prod"
external_id = "vol-12345"
name = "test"
type = "csi"
@ -162,6 +165,7 @@ topology_request {
`,
expected: &api.CSIVolume{
ID: "testvolume",
Namespace: "prod",
ExternalID: "vol-12345",
Name: "test",
PluginID: "myplugin",

View File

@ -332,8 +332,6 @@ func (v *CSIVolume) Register(args *structs.CSIVolumeRegisterRequest, reply *stru
if err != nil {
return err
}
// TODO: allow volume spec file to set namespace
// https://github.com/hashicorp/nomad/issues/11196
if vol.Namespace == "" {
vol.Namespace = args.RequestNamespace()
}
@ -921,7 +919,9 @@ func (v *CSIVolume) Create(args *structs.CSIVolumeCreateRequest, reply *structs.
// We also validate that the plugin exists for each plugin, and validate the
// capabilities when the plugin has a controller.
for _, vol := range args.Volumes {
if vol.Namespace == "" {
vol.Namespace = args.RequestNamespace()
}
if err = vol.Validate(); err != nil {
return err
}

View File

@ -125,13 +125,15 @@ func TestCSIVolumeEndpoint_Register(t *testing.T) {
defer shutdown()
testutil.WaitForLeader(t, srv.RPC)
ns := structs.DefaultNamespace
state := srv.fsm.State()
store := srv.fsm.State()
codec := rpcClient(t, srv)
id0 := uuid.Generate()
// Create the register request
ns := mock.Namespace()
store.UpsertNamespaces(900, []*structs.Namespace{ns})
// Create the node and plugin
node := mock.Node()
node.CSINodePlugins = map[string]*structs.CSIInfo{
@ -142,11 +144,12 @@ func TestCSIVolumeEndpoint_Register(t *testing.T) {
NodeInfo: &structs.CSINodeInfo{},
},
}
require.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 1000, node))
require.NoError(t, store.UpsertNode(structs.MsgTypeTestSetup, 1000, node))
// Create the volume
vols := []*structs.CSIVolume{{
ID: id0,
Namespace: ns.Name,
PluginID: "minnie",
AccessMode: structs.CSIVolumeAccessModeSingleNodeReader, // legacy field ignored
AttachmentMode: structs.CSIVolumeAttachmentModeBlockDevice, // legacy field ignored
@ -166,7 +169,7 @@ func TestCSIVolumeEndpoint_Register(t *testing.T) {
Volumes: vols,
WriteRequest: structs.WriteRequest{
Region: "global",
Namespace: ns,
Namespace: "",
},
}
resp1 := &structs.CSIVolumeRegisterResponse{}
@ -179,6 +182,7 @@ func TestCSIVolumeEndpoint_Register(t *testing.T) {
ID: id0,
QueryOptions: structs.QueryOptions{
Region: "global",
Namespace: ns.Name,
},
}
resp2 := &structs.CSIVolumeGetResponse{}
@ -201,7 +205,7 @@ func TestCSIVolumeEndpoint_Register(t *testing.T) {
VolumeIDs: []string{id0},
WriteRequest: structs.WriteRequest{
Region: "global",
Namespace: ns,
Namespace: ns.Name,
},
}
resp3 := &structs.CSIVolumeDeregisterResponse{}
@ -1029,7 +1033,7 @@ func TestCSIVolumeEndpoint_Create(t *testing.T) {
vols := []*structs.CSIVolume{{
ID: volID,
Name: "vol",
Namespace: "notTheNamespace", // overriden by WriteRequest
Namespace: "", // overriden by WriteRequest
PluginID: "minnie",
AccessMode: structs.CSIVolumeAccessModeSingleNodeReader, // legacy field ignored
AttachmentMode: structs.CSIVolumeAttachmentModeBlockDevice, // legacy field ignored

View File

@ -37,6 +37,7 @@ The file may be provided as either HCL or JSON. An example HCL configuration:
```hcl
id = "ebs_prod_db1"
namespace = "default"
name = "database"
type = "csi"
plugin_id = "ebs-prod"
@ -84,6 +85,10 @@ parameters {
[`volume.source`][csi_volume_source] field in a job specification will refer
to the volume.
- `namespace` `(string: <optional>)` - The namespace of the volume. This field
overrides the namespace provided by the `-namespace` flag or `NOMAD_NAMESPACE`
environment variable. Defaults to `"default"` if unset.
- `name` `(string: <required>)` - The display name of the volume. This field
may be used by the external storage provider to tag the volume.

View File

@ -87,6 +87,10 @@ context {
[`volume.source`][csi_volume_source] field in a job specification will refer
to the volume.
- `namespace` `(string: <optional>)` - The namespace of the volume. This field
overrides the namespace provided by the `-namespace` flag or `NOMAD_NAMESPACE`
environment variable. Defaults to `"default"` if unset.
- `name` `(string: <required>)` - The display name of the volume.
- `type` `(string: <required>)` - The type of volume. Currently only `"csi"`