From ce8625cf9c46e0aee29b0df238a9d8d8536166ce Mon Sep 17 00:00:00 2001 From: Lang Martin Date: Thu, 12 Mar 2020 14:20:40 -0400 Subject: [PATCH] csi: change the API paths to match CLI command layout (#7325) * command/agent/csi_endpoint: support type filter in volumes & plugins * command/agent/http: use /v1/volume/csi & /v1/plugin/csi * api/csi: use /v1/volume/csi & /v1/plugin/csi * api/nodes: use /v1/volume/csi & /v1/plugin/csi * api/nodes: not /volumes/csi, just /volumes * command/agent/csi_endpoint: fix ot parameter parsing --- api/csi.go | 12 ++++++------ api/nodes.go | 2 +- command/agent/csi_endpoint.go | 29 ++++++++++++++++++++++++++--- command/agent/http.go | 8 ++++---- 4 files changed, 37 insertions(+), 14 deletions(-) diff --git a/api/csi.go b/api/csi.go index a97b797e1..df1c372d3 100644 --- a/api/csi.go +++ b/api/csi.go @@ -18,7 +18,7 @@ func (c *Client) CSIVolumes() *CSIVolumes { // List returns all CSI volumes func (v *CSIVolumes) List(q *QueryOptions) ([]*CSIVolumeListStub, *QueryMeta, error) { var resp []*CSIVolumeListStub - qm, err := v.client.query("/v1/csi/volumes", &resp, q) + qm, err := v.client.query("/v1/volumes?type=csi", &resp, q) if err != nil { return nil, nil, err } @@ -34,7 +34,7 @@ func (v *CSIVolumes) PluginList(pluginID string) ([]*CSIVolumeListStub, *QueryMe // Info is used to retrieve a single CSIVolume func (v *CSIVolumes) Info(id string, q *QueryOptions) (*CSIVolume, *QueryMeta, error) { var resp CSIVolume - qm, err := v.client.query("/v1/csi/volume/"+id, &resp, q) + qm, err := v.client.query("/v1/volume/csi/"+id, &resp, q) if err != nil { return nil, nil, err } @@ -49,12 +49,12 @@ func (v *CSIVolumes) Register(vol *CSIVolume, w *WriteOptions) (*WriteMeta, erro req := CSIVolumeRegisterRequest{ Volumes: []*CSIVolume{vol}, } - meta, err := v.client.write("/v1/csi/volume/"+vol.ID, req, nil, w) + meta, err := v.client.write("/v1/volume/csi/"+vol.ID, req, nil, w) return meta, err } func (v *CSIVolumes) Deregister(id string, w *WriteOptions) error { - _, err := v.client.delete("/v1/csi/volume/"+id, nil, w) + _, err := v.client.delete("/v1/volume/csi/"+id, nil, w) return err } @@ -229,7 +229,7 @@ func (c *Client) CSIPlugins() *CSIPlugins { // List returns all CSI plugins func (v *CSIPlugins) List(q *QueryOptions) ([]*CSIPluginListStub, *QueryMeta, error) { var resp []*CSIPluginListStub - qm, err := v.client.query("/v1/csi/plugins", &resp, q) + qm, err := v.client.query("/v1/plugins?type=csi", &resp, q) if err != nil { return nil, nil, err } @@ -240,7 +240,7 @@ func (v *CSIPlugins) List(q *QueryOptions) ([]*CSIPluginListStub, *QueryMeta, er // Info is used to retrieve a single CSI Plugin Job func (v *CSIPlugins) Info(id string, q *QueryOptions) (*CSIPlugin, *QueryMeta, error) { var resp *CSIPlugin - qm, err := v.client.query("/v1/csi/plugin/"+id, &resp, q) + qm, err := v.client.query("/v1/plugin/csi/"+id, &resp, q) if err != nil { return nil, nil, err } diff --git a/api/nodes.go b/api/nodes.go index f567a9b51..8ec6f8d0a 100644 --- a/api/nodes.go +++ b/api/nodes.go @@ -394,7 +394,7 @@ func (n *Nodes) Allocations(nodeID string, q *QueryOptions) ([]*Allocation, *Que func (n *Nodes) CSIVolumes(nodeID string, q *QueryOptions) ([]*CSIVolumeListStub, error) { var resp []*CSIVolumeListStub - path := fmt.Sprintf("/v1/csi/volumes?node_id=%s", nodeID) + path := fmt.Sprintf("/v1/volumes?type=csi&node_id=%s", nodeID) if _, err := n.client.query(path, &resp, q); err != nil { return nil, err } diff --git a/command/agent/csi_endpoint.go b/command/agent/csi_endpoint.go index 6f8d6e240..28db3cc8b 100644 --- a/command/agent/csi_endpoint.go +++ b/command/agent/csi_endpoint.go @@ -7,18 +7,30 @@ import ( "github.com/hashicorp/nomad/nomad/structs" ) +const errRequiresType = "Missing required parameter type" + func (s *HTTPServer) CSIVolumesRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) { if req.Method != "GET" { return nil, CodedError(405, ErrInvalidMethod) } + // Type filters volume lists to a specific type. When support for non-CSI volumes is + // introduced, we'll need to dispatch here + query := req.URL.Query() + qtype, ok := query["type"] + if !ok { + return nil, CodedError(400, errRequiresType) + } + if qtype[0] != "csi" { + return nil, nil + } + args := structs.CSIVolumeListRequest{} if s.parse(resp, req, &args.Region, &args.QueryOptions) { return nil, nil } - query := req.URL.Query() if plugin, ok := query["plugin_id"]; ok { args.PluginID = plugin[0] } @@ -38,7 +50,7 @@ func (s *HTTPServer) CSIVolumesRequest(resp http.ResponseWriter, req *http.Reque // CSIVolumeSpecificRequest dispatches GET and PUT func (s *HTTPServer) CSIVolumeSpecificRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) { // Tokenize the suffix of the path to get the volume id - reqSuffix := strings.TrimPrefix(req.URL.Path, "/v1/csi/volume/") + reqSuffix := strings.TrimPrefix(req.URL.Path, "/v1/volume/csi/") tokens := strings.Split(reqSuffix, "/") if len(tokens) > 2 || len(tokens) < 1 { return nil, CodedError(404, resourceNotFoundErr) @@ -129,6 +141,17 @@ func (s *HTTPServer) CSIPluginsRequest(resp http.ResponseWriter, req *http.Reque return nil, CodedError(405, ErrInvalidMethod) } + // Type filters plugin lists to a specific type. When support for non-CSI plugins is + // introduced, we'll need to dispatch here + query := req.URL.Query() + qtype, ok := query["type"] + if !ok { + return nil, CodedError(400, errRequiresType) + } + if qtype[0] != "csi" { + return nil, nil + } + args := structs.CSIPluginListRequest{} if s.parse(resp, req, &args.Region, &args.QueryOptions) { @@ -151,7 +174,7 @@ func (s *HTTPServer) CSIPluginSpecificRequest(resp http.ResponseWriter, req *htt } // Tokenize the suffix of the path to get the plugin id - reqSuffix := strings.TrimPrefix(req.URL.Path, "/v1/csi/plugin/") + reqSuffix := strings.TrimPrefix(req.URL.Path, "/v1/plugin/csi/") tokens := strings.Split(reqSuffix, "/") if len(tokens) > 2 || len(tokens) < 1 { return nil, CodedError(404, resourceNotFoundErr) diff --git a/command/agent/http.go b/command/agent/http.go index dcd270213..ca4f3d137 100644 --- a/command/agent/http.go +++ b/command/agent/http.go @@ -253,10 +253,10 @@ func (s *HTTPServer) registerHandlers(enableDebug bool) { s.mux.HandleFunc("/v1/deployments", s.wrap(s.DeploymentsRequest)) s.mux.HandleFunc("/v1/deployment/", s.wrap(s.DeploymentSpecificRequest)) - s.mux.HandleFunc("/v1/csi/volumes", s.wrap(s.CSIVolumesRequest)) - s.mux.HandleFunc("/v1/csi/volume/", s.wrap(s.CSIVolumeSpecificRequest)) - s.mux.HandleFunc("/v1/csi/plugins", s.wrap(s.CSIPluginsRequest)) - s.mux.HandleFunc("/v1/csi/plugin/", s.wrap(s.CSIPluginSpecificRequest)) + s.mux.HandleFunc("/v1/volumes", s.wrap(s.CSIVolumesRequest)) + s.mux.HandleFunc("/v1/volume/csi/", s.wrap(s.CSIVolumeSpecificRequest)) + s.mux.HandleFunc("/v1/plugins", s.wrap(s.CSIPluginsRequest)) + s.mux.HandleFunc("/v1/plugin/csi/", s.wrap(s.CSIPluginSpecificRequest)) s.mux.HandleFunc("/v1/acl/policies", s.wrap(s.ACLPoliciesRequest)) s.mux.HandleFunc("/v1/acl/policy/", s.wrap(s.ACLPolicySpecificRequest))