csi: add `-secret` and `-parameter` flag to `volume snapshot create` (#12360)

Pass-through the `-secret` and `-parameter` flags to allow setting
parameters for the snapshot and overriding the secrets we've stored on
the CSI volume in the state store.
This commit is contained in:
Tim Gross 2022-03-24 10:29:50 -04:00 committed by GitHub
parent 65c950baf4
commit ff1bed38cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 83 additions and 9 deletions

3
.changelog/12360.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
csi: Added `-secret` and `-parameter` flags to `volume snapshot create` command
```

View File

@ -120,6 +120,10 @@ func (v *CSIVolumes) CreateSnapshot(snap *CSISnapshot, w *WriteOptions) (*CSISna
req := &CSISnapshotCreateRequest{
Snapshots: []*CSISnapshot{snap},
}
if w == nil {
w = &WriteOptions{}
}
w.SetHeadersFromCSISecrets(snap.Secrets)
resp := &CSISnapshotCreateResponse{}
meta, err := v.client.write("/v1/volumes/snapshot", req, resp, w)
return resp, meta, err

View File

@ -6,6 +6,7 @@ import (
"github.com/hashicorp/nomad/api"
"github.com/hashicorp/nomad/api/contexts"
flaghelper "github.com/hashicorp/nomad/helper/flags"
"github.com/posener/complete"
)
@ -34,7 +35,20 @@ General Options:
` + generalOptionsUsage(usageOptsDefault) + `
Snapshot Create Options:
-parameter
Parameters to pass to the plugin to create a snapshot. Accepts multiple
flags in the form -parameter key=value
-secret
Secrets to pass to the plugin to create snapshot. Accepts multiple
flags in the form -secret key=value
-verbose
Display full information for the resulting snapshot.
`
return strings.TrimSpace(helpText)
}
@ -70,7 +84,11 @@ func (c *VolumeSnapshotCreateCommand) Run(args []string) int {
flags.Usage = func() { c.Ui.Output(c.Help()) }
var verbose bool
var parametersArgs flaghelper.StringFlag
var secretsArgs flaghelper.StringFlag
flags.BoolVar(&verbose, "verbose", false, "")
flags.Var(&parametersArgs, "parameter", "parameters for snapshot, ex. -parameter key=value")
flags.Var(&secretsArgs, "secret", "secrets for snapshot, ex. -secret key=value")
if err := flags.Parse(args); err != nil {
c.Ui.Error(fmt.Sprintf("Error parsing arguments %s", err))
@ -97,9 +115,30 @@ func (c *VolumeSnapshotCreateCommand) Run(args []string) int {
return 1
}
secrets := api.CSISecrets{}
for _, kv := range secretsArgs {
s := strings.Split(kv, "=")
if len(s) == 2 {
secrets[s[0]] = s[1]
} else {
c.Ui.Error("Secret must be in the format: -secret key=value")
return 1
}
}
params := map[string]string{}
for _, kv := range parametersArgs {
p := strings.Split(kv, "=")
if len(p) == 2 {
params[p[0]] = p[1]
}
}
snaps, _, err := client.CSIVolumes().CreateSnapshot(&api.CSISnapshot{
SourceVolumeID: volID,
Name: snapshotName,
Secrets: secrets,
Parameters: params,
}, nil)
if err != nil {
c.Ui.Error(fmt.Sprintf("Error snapshotting volume: %s", err))

View File

@ -77,7 +77,7 @@ func (c *VolumeSnapshotDeleteCommand) Run(args []string) int {
}
// Check that we get exactly two arguments
args = flags.Args()
if l := len(args); l != 2 {
if l := len(args); l < 2 {
c.Ui.Error("This command takes two arguments: <plugin id> <snapshot id>")
c.Ui.Error(commandErrorText(c))
return 1
@ -97,6 +97,9 @@ func (c *VolumeSnapshotDeleteCommand) Run(args []string) int {
s := strings.Split(kv, "=")
if len(s) == 2 {
secrets[s[0]] = s[1]
} else {
c.Ui.Error("Secret must be in the format: -secret key=value")
return 1
}
}

View File

@ -36,6 +36,12 @@ General Options:
List Options:
-page-token
Where to start pagination.
-per-page
How many results to show per page. Defaults to 30.
-plugin: Display only snapshots managed by a particular plugin. This
parameter is required.
@ -43,12 +49,10 @@ List Options:
Secrets to pass to the plugin to list snapshots. Accepts multiple
flags in the form -secret key=value
-per-page
How many results to show per page. Defaults to 30.
-page-token
Where to start pagination.
-verbose
Display full information for snapshots.
`
return strings.TrimSpace(helpText)
}
@ -139,6 +143,9 @@ func (c *VolumeSnapshotListCommand) Run(args []string) int {
s := strings.Split(kv, "=")
if len(s) == 2 {
secrets[s[0]] = s[1]
} else {
c.Ui.Error("Secret must be in the format: -secret key=value")
return 1
}
}

View File

@ -1195,10 +1195,16 @@ func (v *CSIVolume) CreateSnapshot(args *structs.CSISnapshotCreateRequest, reply
continue
}
secrets := vol.Secrets
for k, v := range snap.Secrets {
// merge request secrets onto volume secrets
secrets[k] = v
}
cReq := &cstructs.ClientCSIControllerCreateSnapshotRequest{
ExternalSourceVolumeID: vol.ExternalID,
Name: snap.Name,
Secrets: vol.Secrets,
Secrets: secrets,
Parameters: snap.Parameters,
}
cReq.PluginID = pluginID

View File

@ -1,5 +1,6 @@
---
layout: docs
page_title: 'Commands: volume snapshot create'
description: |
Create external volume snapshots.
@ -35,6 +36,16 @@ When ACLs are enabled, this command requires a token with the
@include 'general_options.mdx'
## Snapshot Create Options
- `-parameter`: Parameters to pass to the plugin to create a
snapshot. Accepts multiple flags in the form `-parameter key=value`
- `-secret`: Secrets to pass to the plugin to create a snapshot. Accepts
multiple flags in the form `-secret key=value`
- `-verbose`: Display full information for the resulting snapshot.
## Examples
Snapshot a volume:

View File

@ -29,6 +29,8 @@ Nomad.
## Snapshot List Options
- `-page-token`: Where to start pagination.
- `-per-page`: How many results to show per page.
- `-plugin`: Display only snapshots managed by a particular [CSI
plugin][csi_plugin]. This flag is required and accepts a plugin ID
or prefix. If there is an exact match based on the provided plugin,
@ -36,8 +38,7 @@ Nomad.
matching plugins will be displayed.
- `-secret`: Secrets to pass to the plugin to list snapshots. Accepts
multiple flags in the form `-secret key=value`
- `-per-page`: How many results to show per page.
- `-page-token`: Where to start pagination.
- `-verbose`: Display full information for the resulting snapshot.
When ACLs are enabled, this command requires a token with the
`csi-list-volumes` capability for the plugin's namespace.