diff --git a/.gitignore b/.gitignore index b9d99d8..a0ba309 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,5 @@ _testmain.go *.test *.prof -gosuv \ No newline at end of file +gosuv +bindata_assetfs.go diff --git a/README.md b/README.md index 09d9f70..18ad10a 100644 --- a/README.md +++ b/README.md @@ -2,18 +2,17 @@ [![Build Status](https://travis-ci.org/codeskyblue/gosuv.svg)](https://travis-ci.org/codeskyblue/gosuv) ## Program not implement -**Not done yet.** - -golang port of python-supervisor +Process managerment writtern by golang, inspired by python-supervisor Features -* [ ] Realtime log view +* [x] Realtime log view +* [x] Web control page * [ ] Github webhook -* [ ] Web control page +* [ ] 中文文档 ## Requirements -Go version at least `1.5+` +Go version at least `1.6+` ## Installation Binary can be download from @@ -23,29 +22,47 @@ Or if you have go enviroment, you can also build from source. ```sh go get -d github.com/codeskyblue/gosuv cd $GOPATH/src/github.com/codeskyblue/gosuv +go build +``` + +If you want to build a standalone binary, run the following command. + +```sh +go get github.com/elazarl/go-bindata-assetfs/... +go-bindata-assetfs -tags bindata res/... go build -tags bindata ``` ## Usage +Start server in the background + +```sh +gosuv start-server +``` + +Show server status + ```sh $ gosuv status -NAME STATUS -timetest running -$ gosuv help -... +Server is running ``` ## Configuration Default config file stored in directory `$HOME/.gosuv/` ## Design -### Get or Update program +HTTP is follow the RESTFul guide. + +Get or Update program + ` /api/programs/:name` -### Add new program +Add new program + `POST /api/programs` -### Del program +Del program + `DELETE /api/programs/:name` ## State diff --git a/docs/states.png b/docs/states.png new file mode 100644 index 0000000..9a96e2d Binary files /dev/null and b/docs/states.png differ diff --git a/gosuv.go b/gosuv.go index 43c81f0..e64a324 100644 --- a/gosuv.go +++ b/gosuv.go @@ -67,7 +67,7 @@ func actionStartServer(c *cli.Context) error { if err != nil { log.Fatal(err) } else { - log.Println("Server started") + log.Printf("Server started, address %s", addr) } } return nil diff --git a/res.go b/res.go index dd23fbe..914da02 100644 --- a/res.go +++ b/res.go @@ -1,24 +1,3 @@ package main -import "html/template" - -var ( - tmpl *template.Template - templates = map[string]string{ - "index": "res/index.html", - "setting": "res/setting.html", - } -) - -func ParseTemplate(name string, content string) { - if tmpl == nil { - tmpl = template.New(name) - } - var t *template.Template - if tmpl.Name() == name { - t = tmpl - } else { - t = tmpl.New(name) - } - template.Must(t.New(name).Delims("[[", "]]").Parse(content)) -} +var templateDir = "res" diff --git a/res/index.html b/res/index.html index fd0107c..42fe0da 100644 --- a/res/index.html +++ b/res/index.html @@ -83,7 +83,7 @@ - + diff --git a/res_bindata.go b/res_bindata.go new file mode 100644 index 0000000..269a7c4 --- /dev/null +++ b/res_bindata.go @@ -0,0 +1,42 @@ +// +build bindata + +package main + +import ( + "html/template" + "io" + "log" + "net/http" + "path/filepath" +) + +var tmpl *template.Template + +func parseTemplate(name string, content string) { + if tmpl == nil { + tmpl = template.New(name) + } + var t *template.Template + if tmpl.Name() == name { + t = tmpl + } else { + t = tmpl.New(name) + } + template.Must(t.New(name).Delims("[[", "]]").Parse(content)) +} + +func init() { + http.Handle("/res/", http.StripPrefix("/res/", http.FileServer(assetFS()))) +} + +func executeTemplate(wr io.Writer, name string, data interface{}) { + if tmpl == nil || tmpl.Lookup(name) == nil { + path := filepath.Join(templateDir, name+".html") + data, err := Asset(path) + if err != nil { + log.Fatal(err) + } + parseTemplate(name, string(data)) + } + tmpl.ExecuteTemplate(wr, name, data) +} diff --git a/res_nobindata.go b/res_nobindata.go new file mode 100644 index 0000000..5df50d5 --- /dev/null +++ b/res_nobindata.go @@ -0,0 +1,25 @@ +// +build !bindata + +package main + +import ( + "html/template" + "io" + "io/ioutil" + "net/http" + "path/filepath" +) + +func init() { + fs := http.FileServer(http.Dir(templateDir)) + http.Handle("/res/", http.StripPrefix("/res/", fs)) +} + +func executeTemplate(wr io.Writer, name string, data interface{}) { + path := filepath.Join(templateDir, name+".html") + body, err := ioutil.ReadFile(path) + if err != nil { + panic(err) + } + template.Must(template.New("t").Delims("[[", "]]").Parse(string(body))).Execute(wr, data) +} diff --git a/web.go b/web.go index 244c54e..6ad40ab 100644 --- a/web.go +++ b/web.go @@ -4,7 +4,6 @@ import ( "encoding/json" "errors" "fmt" - "html/template" "io/ioutil" "net/http" "os" @@ -175,9 +174,11 @@ func (s *Supervisor) saveDB() error { } func (s *Supervisor) renderHTML(w http.ResponseWriter, name string, data interface{}) { - baseName := filepath.Base(name) - t := template.Must(template.New("t").Delims("[[", "]]").ParseFiles(name)) - t.ExecuteTemplate(w, baseName, data) + executeTemplate(w, name, data) + // baseName := filepath.Base(name) + + // t := template.Must(template.New("t").Delims("[[", "]]").ParseFiles(name)) + // t.ExecuteTemplate(w, baseName, data) } type JSONResponse struct { @@ -192,11 +193,11 @@ func (s *Supervisor) renderJSON(w http.ResponseWriter, data JSONResponse) { } func (s *Supervisor) hIndex(w http.ResponseWriter, r *http.Request) { - s.renderHTML(w, "./res/index.html", nil) + s.renderHTML(w, "index", nil) } func (s *Supervisor) hSetting(w http.ResponseWriter, r *http.Request) { - s.renderHTML(w, "./res/setting.html", nil) + s.renderHTML(w, "setting", nil) } func (s *Supervisor) hStatus(w http.ResponseWriter, r *http.Request) { @@ -424,8 +425,8 @@ func registerHTTPHandlers() error { r.HandleFunc("/ws/events", suv.wsEvents) r.HandleFunc("/ws/logs/{name}", suv.wsLog) - fs := http.FileServer(http.Dir("res")) + // fs := http.FileServer(http.Dir("res")) http.Handle("/", r) - http.Handle("/res/", http.StripPrefix("/res/", fs)) + // http.Handle("/res/", http.StripPrefix("/res/", fs)) return nil }