From c8f74a3d9c98ae67367af1fdebed8ea414134f3e Mon Sep 17 00:00:00 2001 From: Diptanu Choudhury Date: Mon, 28 Mar 2016 11:06:22 -0700 Subject: [PATCH] Added the /fs/cat/ api --- api/fs.go | 31 +++++++++++++++++++++++++++++++ command/agent/fs_endpoint.go | 32 ++++++++++++++++++++++++++++++++ command/fs_cat.go | 14 +------------- 3 files changed, 64 insertions(+), 13 deletions(-) diff --git a/api/fs.go b/api/fs.go index e1331368a..87ac986d2 100644 --- a/api/fs.go +++ b/api/fs.go @@ -139,6 +139,37 @@ func (a *AllocFS) ReadAt(alloc *Allocation, path string, offset int64, limit int return resp.Body, nil, nil } +// Cat is used to read contents of a file at the given path in an allocation +// directory +func (a *AllocFS) Cat(alloc *Allocation, path string, q *QueryOptions) (io.Reader, *QueryMeta, error) { + node, _, err := a.client.Nodes().Info(alloc.NodeID, &QueryOptions{}) + if err != nil { + return nil, nil, err + } + + if node.HTTPAddr == "" { + return nil, nil, fmt.Errorf("http addr of the node where alloc %q is running is not advertised", alloc.ID) + } + u := &url.URL{ + Scheme: "http", + Host: node.HTTPAddr, + Path: fmt.Sprintf("/v1/client/fs/cat/%s", alloc.ID), + } + v := url.Values{} + v.Set("path", path) + u.RawQuery = v.Encode() + req := &http.Request{ + Method: "GET", + URL: u, + } + c := http.Client{} + resp, err := c.Do(req) + if err != nil { + return nil, nil, err + } + return resp.Body, nil, nil +} + func (a *AllocFS) getErrorMsg(resp *http.Response) error { if errMsg, err := ioutil.ReadAll(resp.Body); err == nil { return fmt.Errorf(string(errMsg)) diff --git a/command/agent/fs_endpoint.go b/command/agent/fs_endpoint.go index 584bf6cc6..052d80574 100644 --- a/command/agent/fs_endpoint.go +++ b/command/agent/fs_endpoint.go @@ -27,6 +27,8 @@ func (s *HTTPServer) FsRequest(resp http.ResponseWriter, req *http.Request) (int return s.FileStatRequest(resp, req) case strings.HasPrefix(path, "readat/"): return s.FileReadAtRequest(resp, req) + case strings.HasPrefix(path, "cat/"): + return s.FileCatRequest(resp, req) default: return nil, CodedError(404, ErrInvalidMethod) } @@ -94,3 +96,33 @@ func (s *HTTPServer) FileReadAtRequest(resp http.ResponseWriter, req *http.Reque io.Copy(resp, r) return nil, nil } + +func (s *HTTPServer) FileCatRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) { + var allocID, path string + var err error + + q := req.URL.Query() + + if allocID = strings.TrimPrefix(req.URL.Path, "/v1/client/fs/cat/"); allocID == "" { + return nil, allocIDNotPresentErr + } + if path = q.Get("path"); path == "" { + return nil, fileNameNotPresentErr + } + fs, err := s.agent.client.GetAllocFS(allocID) + if err != nil { + return nil, err + } + + fileInfo, err := fs.Stat(path) + if err != nil { + return nil, err + } + if fileInfo.IsDir { + return nil, fmt.Errorf("file %q is a directory") + } + + r, err := fs.ReadAt(path, int64(0), fileInfo.Size) + io.Copy(resp, r) + return nil, nil +} diff --git a/command/fs_cat.go b/command/fs_cat.go index 83d080b94..1a374bc7e 100644 --- a/command/fs_cat.go +++ b/command/fs_cat.go @@ -130,21 +130,9 @@ nomad alloc-status %s`, allocID, allocID) f.Ui.Error(msg) return 0 } - // Stat the file to find it's size - file, _, err := client.AllocFS().Stat(alloc, path, nil) - if err != nil { - f.Ui.Error(err.Error()) - return 1 - } - if file.IsDir { - f.Ui.Error(fmt.Sprintf("The file %q is a directory", file.Name)) - return 1 - } // Get the contents of the file - offset := 0 - limit := file.Size - r, _, err := client.AllocFS().ReadAt(alloc, path, int64(offset), limit, nil) + r, _, err := client.AllocFS().Cat(alloc, path, nil) if err != nil { f.Ui.Error(fmt.Sprintf("Error reading file: %v", err)) return 1