diff --git a/api/csi.go b/api/csi.go index f70cefd396e4..b42202b67c18 100644 --- a/api/csi.go +++ b/api/csi.go @@ -99,16 +99,25 @@ func (v *CSIVolumes) Create(vol *CSIVolume, w *WriteOptions) ([]*CSIVolume, *Wri return resp.Volumes, meta, err } +// DEPRECATED: will be removed in Nomad 1.4.0 // Delete deletes a CSI volume from an external storage provider. The ID // passed as an argument here is for the storage provider's ID, so a volume // that's already been deregistered can be deleted. -func (v *CSIVolumes) Delete(externalVolID string, secrets string, w *WriteOptions) error { - qp := url.Values{} - if secrets != "" { - qp.Set("secrets", secrets) - } +func (v *CSIVolumes) Delete(externalVolID string, w *WriteOptions) error { + _, err := v.client.delete(fmt.Sprintf("/v1/volume/csi/%v/delete", url.PathEscape(externalVolID)), nil, w) + return err +} - _, err := v.client.delete(fmt.Sprintf("/v1/volume/csi/%v/delete?%s", url.PathEscape(externalVolID), qp.Encode()), nil, w) +// DeleteOpts deletes a CSI volume from an external storage +// provider. The ID passed in the request is for the storage +// provider's ID, so a volume that's already been deregistered can be +// deleted. +func (v *CSIVolumes) DeleteOpts(req *CSIVolumeDeleteRequest, w *WriteOptions) error { + if w == nil { + w = &WriteOptions{} + } + w.SetHeadersFromCSISecrets(req.Secrets) + _, err := v.client.delete(fmt.Sprintf("/v1/volume/csi/%v/delete", url.PathEscape(req.ExternalVolumeID)), nil, w) return err } @@ -427,6 +436,12 @@ type CSIVolumeDeregisterRequest struct { WriteRequest } +type CSIVolumeDeleteRequest struct { + ExternalVolumeID string + Secrets CSISecrets + WriteRequest +} + // CSISnapshot is the storage provider's view of a volume snapshot type CSISnapshot struct { ID string // storage provider's ID diff --git a/command/agent/csi_endpoint.go b/command/agent/csi_endpoint.go index df38fdf623b0..32d4fe194c19 100644 --- a/command/agent/csi_endpoint.go +++ b/command/agent/csi_endpoint.go @@ -223,10 +223,10 @@ func (s *HTTPServer) csiVolumeDelete(id string, resp http.ResponseWriter, req *h return nil, CodedError(405, ErrInvalidMethod) } - query := req.URL.Query() + secrets := parseCSISecrets(req) args := structs.CSIVolumeDeleteRequest{ VolumeIDs: []string{id}, - Secrets: parseSecretsParam(query["secrets"]), + Secrets: secrets, } s.parseWriteRequest(req, &args.WriteRequest) diff --git a/command/volume_delete.go b/command/volume_delete.go index b46640fd0437..6b37d419bf97 100644 --- a/command/volume_delete.go +++ b/command/volume_delete.go @@ -4,7 +4,9 @@ import ( "fmt" "strings" + "github.com/hashicorp/nomad/api" "github.com/hashicorp/nomad/api/contexts" + flaghelper "github.com/hashicorp/nomad/helper/flags" "github.com/posener/complete" ) @@ -33,7 +35,9 @@ General Options: Delete Options: - -secrets: A set of key/value secrets to be used when deleting a volume. + -secret + Secrets to pass to the plugin to delete the snapshot. Accepts multiple + flags in the form -secret key=value ` return strings.TrimSpace(helpText) } @@ -72,10 +76,10 @@ func (c *VolumeDeleteCommand) Synopsis() string { func (c *VolumeDeleteCommand) Name() string { return "volume delete" } func (c *VolumeDeleteCommand) Run(args []string) int { + var secretsArgs flaghelper.StringFlag flags := c.Meta.FlagSet(c.Name(), FlagSetClient) flags.Usage = func() { c.Ui.Output(c.Help()) } - - flags.StringVar(&c.Secrets, "secrets", "", "") + 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)) @@ -98,7 +102,21 @@ func (c *VolumeDeleteCommand) Run(args []string) int { return 1 } - err = client.CSIVolumes().Delete(volID, c.Secrets, nil) + 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 + } + } + + err = client.CSIVolumes().DeleteOpts(&api.CSIVolumeDeleteRequest{ + ExternalVolumeID: volID, + Secrets: secrets, + }, nil) if err != nil { c.Ui.Error(fmt.Sprintf("Error deleting volume: %s", err)) return 1 diff --git a/website/content/api-docs/volumes.mdx b/website/content/api-docs/volumes.mdx index fe9e2574ac90..0b5348e42e69 100644 --- a/website/content/api-docs/volumes.mdx +++ b/website/content/api-docs/volumes.mdx @@ -468,24 +468,26 @@ The table below shows this endpoint's support for | ---------------- | ---------------------------- | | `NO` | `namespace:csi-write-volume` | +This endpoint accepts a `X-Nomad-CSI-Secrets` header to set secrets +for deleting the volume as comma-separated key-value pairs (see the +example below). These secrets will be merged with any secrets already +stored when the CSI volume was created. + ### Parameters - `:volume_id` `(string: )` - Specifies the ID of the volume. This must be the full ID. This is specified as part of the path. -- `secrets` `(string: "")` - Specifies a list of key/value secrets for deleting a volume. - These key/value pairs are comma-separated and are passed directly to the CSI plugin. ### Sample Request ```shell-session $ curl \ --request DELETE \ - https://localhost:4646/v1/volume/csi/volume-id1/delete? \ - secrets=secret-key-1=secret-value-1,secret-key-2=secret-value-2 + -H "X-Nomad-CSI-Secrets: secret-key-1=value-1,secret-key-2=value-2" \ + https://localhost:4646/v1/volume/csi/volume-id1/delete ``` - ## Detach Volume This endpoint detaches an external volume from a Nomad client node. It is an @@ -678,6 +680,11 @@ The table below shows this endpoint's support for | ---------------- | ---------------------------- | | `NO` | `namespace:csi-write-volume` | +This endpoint accepts a `X-Nomad-CSI-Secrets` header to set secrets +for deleting the snapshot as comma-separated key-value pairs (see the +example below). These secrets will be merged with any secrets already +stored when the CSI snapshot was created. + ### Parameters - `plugin_id` `(string: )` - Specifies the prefix of a CSI plugin ID @@ -693,6 +700,7 @@ The table below shows this endpoint's support for ```shell-session $ curl \ --request DELETE \ + -H "X-Nomad-CSI-Secrets: secret-key-1=value-1,secret-key-2=value-2" \ https://localhost:4646/v1/volumes/snapshot ``` @@ -715,6 +723,11 @@ The table below shows this endpoint's support for | ---------------- | --------------------------- | | `YES` | `namespace:csi-list-volume` | +This endpoint accepts a `X-Nomad-CSI-Secrets` header to set secrets +for deleting the snapshot as comma-separated key-value pairs (see the +example below). These secrets will be merged with any secrets already +stored when the CSI snapshot was created. + ### Parameters - `plugin_id` `(string: )` - Specifies the prefix of a CSI plugin ID @@ -730,15 +743,12 @@ The table below shows this endpoint's support for return for this request. The response will include a `NextToken` field that can be passed to the next request to fetch additional pages. -- `secrets` `(string: "")` - Specifies a list of key/value secrets for listing snapshots. - These key/value pairs are comma-separated and are passed directly to the CSI plugin. - ### Sample Request ```shell-session $ curl \ - https://localhost:4646/v1/volumes/snapshot?plugin_id=plugin-id1&per_page=2& \ - secrets=secret-key-1=secret-value-1,secret-key-2=secret-value-2 + -H "X-Nomad-CSI-Secrets: secret-key-1=value-1,secret-key-2=value-2" \ + https://localhost:4646/v1/volumes/snapshot?plugin_id=plugin-id1&per_page=2 ``` ### Sample Response diff --git a/website/content/docs/commands/volume/delete.mdx b/website/content/docs/commands/volume/delete.mdx index 42d40b30bcc1..0d8d928c5929 100644 --- a/website/content/docs/commands/volume/delete.mdx +++ b/website/content/docs/commands/volume/delete.mdx @@ -16,7 +16,7 @@ deleted. ## Usage ```plaintext -nomad volume delete [options] [volume] [-secrets key=value,key2=value2] +nomad volume delete [options] [volume] ``` The `volume delete` command requires a single argument, specifying the ID of @@ -39,5 +39,5 @@ When ACLs are enabled, this command requires a token with the ## Delete Options -- `-secrets`: A list of comma separated secret key/value pairs to be passed - to the CSI driver. \ No newline at end of file +- `-secret`: Secrets to pass to the plugin to delete the + snapshot. Accepts multiple flags in the form `-secret key=value`