From 63e57a391f26ac7dae042382f0da18e455429433 Mon Sep 17 00:00:00 2001 From: b5 Date: Fri, 12 Jul 2019 11:39:21 -0400 Subject: [PATCH] feat(api.FSI): initial FSI api methods --- api/api.go | 3 +++ api/fsi.go | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++ fsi/fsi.go | 3 +++ fsi/status.go | 16 ++++++++++++++ go.sum | 2 ++ lib/fsi.go | 13 ++++++++++++ 6 files changed, 96 insertions(+) create mode 100644 api/fsi.go diff --git a/api/api.go b/api/api.go index 8c331bc63..2fdfd7a91 100644 --- a/api/api.go +++ b/api/api.go @@ -289,6 +289,9 @@ func NewServerRoutes(s Server) *http.ServeMux { m.Handle("/update/logs/file", s.middleware(uh.LogFileHandler)) m.Handle("/update/service", s.middleware(uh.ServiceHandler)) + fsih := NewFSIHandlers(s.Instance, cfg.API.ReadOnly) + m.Handle("/dsstatus", s.middleware(fsih.StatusHandler)) + renderh := NewRenderHandlers(node.Repo) m.Handle("/render/", s.middleware(renderh.RenderHandler)) diff --git a/api/fsi.go b/api/fsi.go new file mode 100644 index 000000000..4be121bac --- /dev/null +++ b/api/fsi.go @@ -0,0 +1,59 @@ +package api + +import ( + "fmt" + "net/http" + + util "github.com/qri-io/apiutil" + "github.com/qri-io/qri/lib" +) + + +// FSIHandlers connects HTTP requests to the FSI subsystem +type FSIHandlers struct { + lib.FSIMethods + ReadOnly bool +} + +// NewFSIHandlers creates handlers that talk to qri's filesystem integration +func NewFSIHandlers(inst *lib.Instance, readOnly bool) FSIHandlers { + return FSIHandlers{ + FSIMethods: *lib.NewFSIMethods(inst), + ReadOnly: readOnly, + } +} + + +// StatusHandler is the endpoint for getting the status of a linked dataset +func (h *FSIHandlers) StatusHandler(w http.ResponseWriter, r *http.Request) { + switch r.Method { + case "OPTIONS": + util.EmptyOkHandler(w, r) + case "GET": + if h.ReadOnly { + readOnlyResponse(w, "/status") + return + } + h.statusHandler(w, r) + case "POST": + h.statusHandler(w, r) + default: + util.NotFoundHandler(w, r) + } +} + +func (h *FSIHandlers) statusHandler(w http.ResponseWriter, r *http.Request) { + ref, err := DatasetRefFromPath(r.URL.Path[len("/dsstatus"):]) + if err != nil { + util.WriteErrResponse(w, http.StatusBadRequest, fmt.Errorf("bad reference: %s", err.Error())) + return + } + + alias := ref.AliasString() + res := []lib.StatusItem{} + if err = h.AliasStatus(&alias, &res); err != nil { + util.WriteErrResponse(w, http.StatusInternalServerError, fmt.Errorf("error getting status: %s", err.Error())) + return + } + util.WriteResponse(w, res) +} \ No newline at end of file diff --git a/fsi/fsi.go b/fsi/fsi.go index 6036cf82a..dfed12767 100644 --- a/fsi/fsi.go +++ b/fsi/fsi.go @@ -169,6 +169,9 @@ func (fsi *FSI) load() (links, error) { data, err := ioutil.ReadFile(fsi.linksPath) if err != nil { + if os.IsNotExist(err) { + return links{}, nil + } return nil, err } diff --git a/fsi/status.go b/fsi/status.go index 19f8fbcba..f9392e0ac 100644 --- a/fsi/status.go +++ b/fsi/status.go @@ -30,6 +30,22 @@ type StatusItem struct { Message string } +// AliasStatus returns the status for a given dataset alias +func (fsi *FSI) AliasStatus(alias string) (changes []StatusItem, err error) { + links, err := fsi.load() + if err != nil { + return nil, err + } + + for _, l := range links { + if l.Alias == alias { + return fsi.Status(l.Path) + } + } + + return nil, fmt.Errorf("alias not found: %s", alias) +} + // Status reads the diff status from the current working directory func (fsi *FSI) Status(dir string) (changes []StatusItem, err error) { refStr, ok := GetLinkedFilesysRef(dir) diff --git a/go.sum b/go.sum index a1fc43131..5d6014e83 100644 --- a/go.sum +++ b/go.sum @@ -394,6 +394,7 @@ github.com/libp2p/go-libp2p-net v0.0.0-20190226201932-e71fff5ba6e9/go.mod h1:8W6 github.com/libp2p/go-libp2p-net v0.0.1/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8EgNU9DrCcR8c= github.com/libp2p/go-libp2p-net v0.0.2 h1:qP06u4TYXfl7uW/hzqPhlVVTSA2nw1B/bHBJaUnbh6M= github.com/libp2p/go-libp2p-net v0.0.2/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8EgNU9DrCcR8c= +github.com/libp2p/go-libp2p-netutil v0.0.1 h1:LgD6+skofkOx8z6odD9+MZHKjupv3ng1u6KRhaADTnA= github.com/libp2p/go-libp2p-netutil v0.0.1/go.mod h1:GdusFvujWZI9Vt0X5BKqwWWmZFxecf9Gt03cKxm2f/Q= github.com/libp2p/go-libp2p-peer v0.0.1/go.mod h1:nXQvOBbwVqoP+T5Y5nCjeH4sP9IX/J0AMzcDUVruVoo= github.com/libp2p/go-libp2p-peer v0.1.1 h1:qGCWD1a+PyZcna6htMPo26jAtqirVnJ5NvBQIKV7rRY= @@ -468,6 +469,7 @@ github.com/libp2p/go-tcp-transport v0.0.1/go.mod h1:mnjg0o0O5TmXUaUIanYPUqkW4+u6 github.com/libp2p/go-tcp-transport v0.0.3/go.mod h1:f11C2zvCaGDkE8aFPUKmuYZwd3pP6HI24LeLMWhJnkQ= github.com/libp2p/go-tcp-transport v0.0.4 h1:2iRu994wCT/iEz62F+c60FUoSkijNEQ0q2Itc+79XlQ= github.com/libp2p/go-tcp-transport v0.0.4/go.mod h1:+E8HvC8ezEVOxIo3V5vCK9l1y/19K427vCzQ+xHKH/o= +github.com/libp2p/go-testutil v0.0.1 h1:Xg+O0G2HIMfHqBOBDcMS1iSZJ3GEcId4qOxCQvsGZHk= github.com/libp2p/go-testutil v0.0.1/go.mod h1:iAcJc/DKJQanJ5ws2V+u5ywdL2n12X1WbbEG+Jjy69I= github.com/libp2p/go-ws-transport v0.0.1/go.mod h1:p3bKjDWHEgtuKKj+2OdPYs5dAPIjtpQGHF2tJfGz7Ww= github.com/libp2p/go-ws-transport v0.0.3/go.mod h1:iU0kzfMcO4tBVIk3z+7srp1YG/RFLWTSuO4enpivw8g= diff --git a/lib/fsi.go b/lib/fsi.go index b485e24d5..a23c48997 100644 --- a/lib/fsi.go +++ b/lib/fsi.go @@ -72,3 +72,16 @@ func (m *FSIMethods) Status(dir *string, res *[]StatusItem) (err error) { *res, err = fsint.Status(*dir) return err } + + +// AlisStatus checks for any modifications or errors in a dataset alias +func (m *FSIMethods) AliasStatus(alias *string, res *[]StatusItem) (err error) { + if m.inst.rpc != nil { + return m.inst.rpc.Call("FSIMethods.AliasStatus", alias, res) + } + + // TODO (b5) - inst should have an fsi instance + fsint := fsi.NewFSI(m.inst.repo, fsi.RepoPath(m.inst.repoPath)) + *res, err = fsint.AliasStatus(*alias) + return err +}