diff --git a/app/start.go b/app/start.go index 37ce668..b0d67aa 100644 --- a/app/start.go +++ b/app/start.go @@ -47,11 +47,12 @@ func Start(conf common.Conf, db *sql.DB) *gin.Engine { // M E T A // E T "wow thats so meta" - // T E -- the one who said "wow that's so meta" + // T E -- the one who said "wow thats so meta" // A T E M gv1.GET("/meta/restart", Method(v1.MetaRestartGET, db, common.PrivilegeAPIMeta)) gv1.GET("/meta/kill", Method(v1.MetaKillGET, db, common.PrivilegeAPIMeta)) gv1.GET("/meta/up_since", Method(v1.MetaUpSinceGET, db, common.PrivilegeAPIMeta)) + gv1.GET("/meta/update", Method(v1.MetaUpdateGET, db, common.PrivilegeAPIMeta)) } } diff --git a/app/v1/meta.go b/app/v1/meta.go index 42d9260..5a3c86a 100644 --- a/app/v1/meta.go +++ b/app/v1/meta.go @@ -2,7 +2,11 @@ package v1 import ( "fmt" + "io" + "io/ioutil" + "log" "os" + "os/exec" "syscall" "time" @@ -56,3 +60,68 @@ func MetaUpSinceGET(md common.MethodData) common.Response { Data: upSince.UnixNano(), } } + +// MetaUpdateGET updates the API to the latest version, and restarts it. +func MetaUpdateGET(md common.MethodData) common.Response { + if f, err := os.Stat(".git"); err == os.ErrNotExist || !f.IsDir() { + return common.Response{ + Code: 500, + Message: "repo is not using git", + } + } + go func() { + // go get + // -u: update all dependencies (including API source) + // -d: stop after downloading deps + if !execCommand("go", "get", "-u", "-d") { + return + } + if !execCommand("go", "build") { + return + } + + proc, err := os.FindProcess(syscall.Getpid()) + if err != nil { + log.Println(err) + return + } + proc.Signal(syscall.SIGUSR2) + }() + return common.Response{ + Code: 200, + Message: "Started updating! " + surpriseMe(), + } +} + +func execCommand(command string, args ...string) bool { + cmd := exec.Command(command, args...) + cmd.Env = os.Environ() + stdout, err := cmd.StdoutPipe() + if err != nil { + log.Println(err) + return false + } + stderr, err := cmd.StderrPipe() + if err != nil { + log.Println(err) + return false + } + if err := cmd.Start(); err != nil { + log.Println(err) + return false + } + data, err := ioutil.ReadAll(stderr) + if err != nil { + log.Println(err) + return false + } + // Bob. We got a problem. + if len(data) != 0 { + log.Println(string(data)) + return false + } + io.Copy(os.Stdout, stdout) + cmd.Wait() + stdout.Close() + return true +}