forked from osuthailand/api
/
meta_linux.go
108 lines (97 loc) · 2.38 KB
/
meta_linux.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// +build !windows
// TODO: Make all these methods POST
package v1
import (
"io"
"io/ioutil"
"log"
"os"
"os/exec"
"syscall"
"time"
"github.com/RealistikOsu/RealistikAPI/common"
)
// MetaRestartGET restarts the API with Zero Downtime™.
func MetaRestartGET(md common.MethodData) common.CodeMessager {
proc, err := os.FindProcess(syscall.Getpid())
if err != nil {
return common.SimpleResponse(500, "couldn't find process. what the fuck?")
}
go func() {
time.Sleep(time.Second)
proc.Signal(syscall.SIGUSR2)
}()
return common.SimpleResponse(200, "brb")
}
var upSince = time.Now()
type metaUpSinceResponse struct {
common.ResponseBase
Code int `json:"code"`
Since int64 `json:"since"`
}
// MetaUpSinceGET retrieves the moment the API application was started.
// Mainly used to get if the API was restarted.
func MetaUpSinceGET(md common.MethodData) common.CodeMessager {
return metaUpSinceResponse{
Code: 200,
Since: int64(upSince.UnixNano()),
}
}
// MetaUpdateGET updates the API to the latest version, and restarts it.
func MetaUpdateGET(md common.MethodData) common.CodeMessager {
if f, err := os.Stat(".git"); err == os.ErrNotExist || !f.IsDir() {
return common.SimpleResponse(500, "instance is not using git")
}
go func() {
if !execCommand("git", "pull", "origin", "master") {
return
}
// go get
// -u: update all dependencies
// -d: stop after downloading deps
if !execCommand("go", "get", "-v", "-u", "-d") {
return
}
if !execCommand("bash", "-c", "go build -v -ldflags \"-X main.Version=`git rev-parse HEAD`\"") {
return
}
proc, err := os.FindProcess(syscall.Getpid())
if err != nil {
log.Println(err)
return
}
proc.Signal(syscall.SIGUSR2)
}()
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
}