try to do add handler

master
shengxiang 9 years ago
parent 43894f70eb
commit 98dcff54bb

@ -10,6 +10,8 @@ import (
"time"
"github.com/codegangsta/cli"
"github.com/franela/goreq"
"github.com/qiniu/log"
)
func MkdirIfNoExists(dir string) error {
@ -43,8 +45,14 @@ func wrapAction(f func(*cli.Context)) func(*cli.Context) {
//host := c.GlobalString("host")
//port := c.GlobalInt("port")
//ServeAddr(host, port)
go exec.Command(os.Args[0], "serv").Run()
time.Sleep(time.Millisecond * 500)
_, err := goreq.Request{
Method: "GET",
Uri: buildURI(c, "/api/version"),
}.Do()
if err != nil {
go exec.Command(os.Args[0], "serv").Run()
time.Sleep(time.Millisecond * 500)
}
f(c)
}
}
@ -61,7 +69,52 @@ func StatusAction(ctx *cli.Context) {
func AddAction(ctx *cli.Context) {
name := ctx.String("name")
dir, _ := os.Getwd()
if len(ctx.Args()) < 1 {
log.Fatal("need at least one args")
}
if name == "" {
name = ctx.Args()[0]
}
log.Println(ctx.Args().Tail())
log.Println([]string(ctx.Args()))
log.Println(ctx.Args().Tail())
log.Println(ctx.StringSlice("env"))
log.Println("Dir:", dir)
cmdName := ctx.Args().First()
log.Println("cmd name:", cmdName)
cmdPath, err := exec.LookPath(cmdName)
if err != nil {
log.Fatal(err)
}
fmt.Printf("program: %s has been added\n", strconv.Quote(name))
p := &ProgramInfo{
Name: name,
Dir: dir,
Command: append([]string{cmdPath}, ctx.Args().Tail()...),
Environ: ctx.StringSlice("env"),
}
res, err := goreq.Request{
Method: "POST",
Uri: buildURI(ctx, "/api/programs"),
Body: p,
}.Do()
if err != nil {
log.Fatal(err)
}
var jres JSONResponse
if res.StatusCode != http.StatusOK {
log.Fatal(res.Body.ToString())
}
if err = res.Body.FromJsonTo(&jres); err != nil {
log.Fatal(err)
}
fmt.Println(jres.Message)
}
func buildURI(ctx *cli.Context, uri string) string {
return fmt.Sprintf("http://%s:%d%s",
ctx.GlobalString("host"), ctx.GlobalInt("port"), uri)
}
func StopAction(ctx *cli.Context) {
@ -71,7 +124,8 @@ func ShutdownAction(ctx *cli.Context) {
res, err := chttp("POST", fmt.Sprintf("http://%s:%d/api/shutdown",
ctx.GlobalString("host"), ctx.GlobalInt("port")))
if err != nil {
panic(err)
log.Println("Already shutdown")
return
}
fmt.Println(res.Message)
}
@ -128,8 +182,12 @@ func init() {
Name: "name, n",
Usage: "program name",
},
cli.StringSliceFlag{
Name: "env, e",
Usage: "Specify environ",
},
},
Action: AddAction,
Action: wrapAction(AddAction),
},
{
Name: "stop",

@ -5,9 +5,13 @@ import (
"fmt"
"net/http"
"os"
"os/exec"
"path/filepath"
"time"
"github.com/codeskyblue/kproc"
"github.com/gorilla/mux"
"github.com/qiniu/log"
)
type JSONResponse struct {
@ -15,6 +19,17 @@ type JSONResponse struct {
Message string `json:"message"`
}
type ProgramInfo struct {
Name string `json:"name"`
Command []string `json:"command"`
Dir string `json:"dir"`
Environ []string `json:"environ"`
}
var programTable struct {
table map[string]*Program
}
func renderJSON(w http.ResponseWriter, v interface{}) {
w.Header().Add("Content-Type", "json")
json.NewEncoder(w).Encode(v)
@ -27,6 +42,95 @@ func versionHandler(w http.ResponseWriter, r *http.Request) {
})
}
func addHandler(w http.ResponseWriter, r *http.Request) {
pinfo := new(ProgramInfo)
err := json.NewDecoder(r.Body).Decode(pinfo)
if err != nil {
http.Error(w, err.Error(), 502)
return
}
log.Printf("add: %#v", pinfo)
// init cmd
cmd := exec.Command(pinfo.Command[0], pinfo.Command[1:]...)
cmd.Dir = pinfo.Dir
cmd.Env = append(os.Environ(), pinfo.Environ...)
program := NewProgram(cmd, pinfo)
// set output
logFd, err := program.createLog()
if err != nil {
http.Error(w, err.Error(), 503)
return
}
cmd.Stdout = logFd
cmd.Stderr = logFd
if err = program.Start(); err != nil {
http.Error(w, err.Error(), 503)
return
}
program.Status = ST_RUNNING
// wait func finish
go func() {
finish := false
ch := GoFunc(program.Wait)
for !finish {
select {
case err := <-ch:
if err != nil {
log.Warnf("program finish: %v", err)
}
finish = true
case sig := <-program.Sig:
program.Terminate(sig)
}
}
}()
renderJSON(w, &JSONResponse{
Code: 200,
Message: "program add success",
})
}
func GoFunc(f func() error) chan error {
ch := make(chan error)
go func() {
ch <- f()
}()
return ch
}
const (
ST_PENDING = "pending"
ST_RUNNING = "running"
ST_STOPPED = "stopped"
)
type Program struct {
*kproc.Process
Status string `json:"state"`
Sig chan os.Signal
info *ProgramInfo
}
func NewProgram(cmd *exec.Cmd, info *ProgramInfo) *Program {
return &Program{
Process: kproc.ProcCommand(cmd),
Status: ST_PENDING,
Sig: make(chan os.Signal),
info: info,
}
}
func (p *Program) createLog() (*os.File, error) {
logDir := os.ExpandEnv("$HOME/.gosuv/logs")
os.MkdirAll(logDir, 0755) // just do it, err ignore it
logFile := filepath.Join(logDir, p.info.Name+".output.log")
return os.Create(logFile)
}
func shutdownHandler(w http.ResponseWriter, r *http.Request) {
go func() {
time.Sleep(50 * time.Millisecond)
@ -42,5 +146,6 @@ func ServeAddr(host string, port int) error {
r := mux.NewRouter()
r.HandleFunc("/api/version", versionHandler)
r.Methods("POST").Path("/api/shutdown").HandlerFunc(shutdownHandler)
r.Methods("POST").Path("/api/programs").HandlerFunc(addHandler)
return http.ListenAndServe(fmt.Sprintf("%s:%d", host, port), r)
}

Loading…
Cancel
Save