From f9aa451d02b35b12256ccbc1599d81bfeb754a0c Mon Sep 17 00:00:00 2001 From: Tim Gross Date: Wed, 23 Mar 2022 11:10:36 -0400 Subject: [PATCH] csi: add `-secret` and `-parameter` flag to `volume snapshot create` 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. --- .changelog/12360.txt | 3 ++ api/csi.go | 4 +++ command/volume_snapshot_create.go | 34 +++++++++++++++++++ command/volume_snapshot_delete.go | 2 +- nomad/csi_endpoint.go | 8 ++++- .../docs/commands/volume/snapshot-create.mdx | 8 +++++ 6 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 .changelog/12360.txt diff --git a/.changelog/12360.txt b/.changelog/12360.txt new file mode 100644 index 00000000000..8422c38cd60 --- /dev/null +++ b/.changelog/12360.txt @@ -0,0 +1,3 @@ +```release-note:improvement +csi: Added `-secret` and `-parameter` flags to `volume snapshot create` command +``` diff --git a/api/csi.go b/api/csi.go index 25cddc50ba8..829e3a2517b 100644 --- a/api/csi.go +++ b/api/csi.go @@ -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 diff --git a/command/volume_snapshot_create.go b/command/volume_snapshot_create.go index 4fcfdcd7345..a72d2f1336c 100644 --- a/command/volume_snapshot_create.go +++ b/command/volume_snapshot_create.go @@ -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" ) @@ -30,6 +31,17 @@ Usage: nomad volume snapshot create [snapshot_name] When ACLs are enabled, this command requires a token with the 'csi-write-volume' capability for the volume's namespace. + +Snapshot Create Options: + + -secret + Secrets to pass to the plugin to create snapshot. Accepts multiple + flags in the form -secret key=value + + -parameter + Parameters to pass to the plugin to create a snapshot. Accepts multiple + flags in the form -parameter key=value + General Options: ` + generalOptionsUsage(usageOptsDefault) + ` @@ -70,7 +82,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(¶metersArgs, "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 +113,27 @@ 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] + } + } + + 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)) diff --git a/command/volume_snapshot_delete.go b/command/volume_snapshot_delete.go index a2ac23c7b3c..ffe7286132c 100644 --- a/command/volume_snapshot_delete.go +++ b/command/volume_snapshot_delete.go @@ -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: ") c.Ui.Error(commandErrorText(c)) return 1 diff --git a/nomad/csi_endpoint.go b/nomad/csi_endpoint.go index add9c3cd8b8..4043955cc2d 100644 --- a/nomad/csi_endpoint.go +++ b/nomad/csi_endpoint.go @@ -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 diff --git a/website/content/docs/commands/volume/snapshot-create.mdx b/website/content/docs/commands/volume/snapshot-create.mdx index 241e18e0ee7..0d862b35951 100644 --- a/website/content/docs/commands/volume/snapshot-create.mdx +++ b/website/content/docs/commands/volume/snapshot-create.mdx @@ -35,6 +35,14 @@ 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` + ## Examples Snapshot a volume: