ripple-api/app/v1/meta.go

126 lines
2.9 KiB
Go
Raw Permalink Normal View History

2016-04-07 17:32:48 +00:00
package v1
import (
2016-04-09 16:14:38 +00:00
"fmt"
"io"
"io/ioutil"
"log"
2016-04-07 17:32:48 +00:00
"os"
"os/exec"
2016-04-07 17:32:48 +00:00
"syscall"
2016-04-09 16:14:38 +00:00
"time"
2016-04-07 17:32:48 +00:00
2016-04-19 14:07:27 +00:00
"git.zxq.co/ripple/rippleapi/common"
2016-04-07 17:32:48 +00:00
)
// MetaRestartGET restarts the API with Zero Downtime™.
2016-04-16 16:05:24 +00:00
func MetaRestartGET(md common.MethodData) common.CodeMessager {
2016-04-07 17:32:48 +00:00
proc, err := os.FindProcess(syscall.Getpid())
if err != nil {
2016-04-16 16:05:24 +00:00
return common.SimpleResponse(500, "couldn't find process. what the fuck?")
2016-04-07 17:32:48 +00:00
}
2016-04-09 16:14:38 +00:00
go func() {
time.Sleep(time.Second)
proc.Signal(syscall.SIGUSR2)
}()
2016-04-16 16:05:24 +00:00
return common.SimpleResponse(200, "brb")
2016-04-07 17:32:48 +00:00
}
2016-04-09 16:14:38 +00:00
// MetaKillGET kills the API process. NOTE TO EVERYONE: NEVER. EVER. USE IN PROD.
// Mainly created because I couldn't bother to fire up a terminal, do htop and kill the API each time.
2016-04-16 16:05:24 +00:00
func MetaKillGET(md common.MethodData) common.CodeMessager {
2016-04-09 16:14:38 +00:00
proc, err := os.FindProcess(syscall.Getpid())
if err != nil {
2016-04-16 16:05:24 +00:00
return common.SimpleResponse(500, "couldn't find process. what the fuck?")
2016-04-09 16:14:38 +00:00
}
const form = "02/01/2006"
2016-04-16 16:05:24 +00:00
r := common.ResponseBase{
Code: 200,
Message: fmt.Sprintf("RIP ripple API %s - %s", upSince.Format(form), time.Now().Format(form)),
}
2016-04-09 16:14:38 +00:00
// yes
go func() {
time.Sleep(time.Second)
proc.Kill()
}()
2016-04-16 16:05:24 +00:00
return r
2016-04-09 16:14:38 +00:00
}
2016-04-10 09:51:34 +00:00
var upSince = time.Now()
2016-04-09 16:14:38 +00:00
2016-04-16 16:05:24 +00:00
type metaUpSinceResponse struct {
common.ResponseBase
Code int `json:"code"`
Since int64 `json:"since"`
}
2016-04-09 16:14:38 +00:00
// MetaUpSinceGET retrieves the moment the API application was started.
// Mainly used to get if the API was restarted.
2016-04-16 16:05:24 +00:00
func MetaUpSinceGET(md common.MethodData) common.CodeMessager {
return metaUpSinceResponse{
Code: 200,
Since: int64(upSince.UnixNano()),
2016-04-09 16:14:38 +00:00
}
}
// MetaUpdateGET updates the API to the latest version, and restarts it.
2016-04-16 16:05:24 +00:00
func MetaUpdateGET(md common.MethodData) common.CodeMessager {
if f, err := os.Stat(".git"); err == os.ErrNotExist || !f.IsDir() {
2016-04-16 16:05:24 +00:00
return common.SimpleResponse(500, "instance is not using git")
}
go func() {
2016-04-19 14:07:27 +00:00
if !execCommand("git", "pull", "origin", "master") {
return
}
// go get
2016-04-19 14:07:27 +00:00
// -u: update all dependencies
// -d: stop after downloading deps
2016-05-14 18:31:28 +00:00
if !execCommand("go", "get", "-v", "-u", "-d") {
return
}
2016-04-27 18:18:55 +00:00
if !execCommand("go", "build", "-v", "-o", "api") {
return
}
proc, err := os.FindProcess(syscall.Getpid())
if err != nil {
log.Println(err)
return
}
proc.Signal(syscall.SIGUSR2)
}()
2016-04-16 16:05:24 +00:00
return common.SimpleResponse(200, "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))
}
io.Copy(os.Stdout, stdout)
cmd.Wait()
stdout.Close()
return true
}