From a141ddfcb36eb07c6399d288f3bb9c8efa9d51a3 Mon Sep 17 00:00:00 2001 From: Denis Zheleztsov Date: Wed, 15 Feb 2017 17:09:28 +0300 Subject: [PATCH] Initial with working ls and get --- main.go | 40 +++++++++++++++++++++++ rest/api.go | 83 ++++++++++++++++++++++++++++++++++++++++++++++ rest/zoo.go | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 217 insertions(+) create mode 100644 main.go create mode 100644 rest/api.go create mode 100644 rest/zoo.go diff --git a/main.go b/main.go new file mode 100644 index 0000000..e07c85b --- /dev/null +++ b/main.go @@ -0,0 +1,40 @@ +package main + +import ( + "flag" + "github.com/Difrex/zoorest/rest" + "strings" +) + +var ( + zk string + listen string + path string +) + +// init ... +func init() { + flag.StringVar(&zk, "zk", "127.0.0.1:2181", "Zk servers. Comma separated") + flag.StringVar(&listen, "listen", "127.0.0.1:8889", "Address to listen") + flag.StringVar(&path, "path", "/", "Zk root path") + flag.Parse() +} + +// main ... +func main() { + var z rest.Zk + hosts := strings.Split(zk, ",") + z.Hosts = hosts + conn, err := z.InitConnection() + if err != nil { + panic(err) + } + + zoo := rest.ZooNode{ + path, + conn, + z, + } + + rest.Serve(listen, zoo) +} diff --git a/rest/api.go b/rest/api.go new file mode 100644 index 0000000..6400093 --- /dev/null +++ b/rest/api.go @@ -0,0 +1,83 @@ +package rest + +import ( + "encoding/json" + "github.com/gorilla/mux" + "log" + "net/http" + "time" +) + +// Ls ... +type Ls struct { + Childrens []string `json:"childrens"` + Path string `json:"path"` + State string `json:"state"` + Error error `json:"error"` +} + +// Get ... +type Get struct { + Path string `json:"path"` + State string `json:"state"` + Error error `json:"error"` + Data []byte `json:"data"` +} + +// LS ... +func (zk ZooNode) LS(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + path := vars["path"] + + ch := make(chan Ls) + + go func() { ch <- zk.GetChildrens(path) }() + + childrens := <-ch + + data, err := json.Marshal(childrens) + if err != nil { + w.WriteHeader(500) + } + w.WriteHeader(200) + w.Write(data) +} + +// GET ... +func (zk ZooNode) GET(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + path := vars["path"] + + ch := make(chan Get) + + go func() { ch <- zk.GetNode(path) }() + + childrens := <-ch + + data, err := json.Marshal(childrens) + if err != nil { + w.WriteHeader(500) + } + w.WriteHeader(200) + w.Write(data) +} + +// Serve ... +func Serve(listen string, zk ZooNode) { + r := mux.NewRouter() + + r.HandleFunc("/v1/ls{path:[a-z0-9-_/.:]+}", zk.LS) + r.HandleFunc("/v1/get{path:[a-z0-9-_/.:]+}", zk.GET) + + http.Handle("/", r) + + srv := http.Server{ + Handler: r, + Addr: listen, + WriteTimeout: 15 * time.Second, + ReadTimeout: 15 * time.Second, + } + + log.Print("Listening API on ", listen) + log.Fatal(srv.ListenAndServe()) +} diff --git a/rest/zoo.go b/rest/zoo.go new file mode 100644 index 0000000..0e68d2e --- /dev/null +++ b/rest/zoo.go @@ -0,0 +1,94 @@ +package rest + +import ( + "github.com/samuel/go-zookeeper/zk" + "log" + "strings" + "time" +) + +//ZooNode zookeeper node +type ZooNode struct { + Path string + Conn *zk.Conn + Zoo Zk +} + +//Zk Zookeeper connection settings +type Zk struct { + Hosts []string + Path string + Tick int +} + +//InitConnection Initialize Zookeeper connection +func (conf Zk) InitConnection() (*zk.Conn, error) { + conn, _, err := zk.Connect(conf.Hosts, time.Second) + if err != nil { + log.Panic("[ERROR] ", err) + } + + return conn, err +} + +// GetChildrens ... +func (z ZooNode) GetChildrens(path string) Ls { + var lsPath string + lsPath = strings.Join([]string{z.Path, path}, "") + if path == "/" { + lsPath = z.Path + } + + if strings.Contains(lsPath, "//") { + lsPath = strings.Replace(lsPath, "//", "/", 1) + } + + log.Print("ls: ", lsPath) + + var l Ls + l.State = "OK" + + childrens, _, err := z.Conn.Children(lsPath) + if err != nil { + l.State = "ERROR" + l.Error = err + return l + } + + l.Error = nil + l.Childrens = childrens + l.Path = lsPath + + return l +} + +// GetNode ... +func (z ZooNode) GetNode(path string) Get { + var getPath string + getPath = strings.Join([]string{z.Path, path}, "") + if path == "/" { + getPath = z.Path + } + + if strings.Contains(getPath, "//") { + getPath = strings.Replace(getPath, "//", "/", 1) + } + + log.Print("ls: ", getPath) + + var g Get + g.State = "OK" + + data, _, err := z.Conn.Get(getPath) + if err != nil { + g.State = "ERROR" + g.Error = err + return g + } + + g.Error = nil + g.Data = data + g.Path = getPath + + return g +}