Compare commits
12 Commits
ds-live
...
7fe5090efa
| Author | SHA1 | Date | |
|---|---|---|---|
| 7fe5090efa | |||
| e9370513c2 | |||
| 387d4f3ea8 | |||
| e5984b3342 | |||
| f174a165fe | |||
| a112f20cb8 | |||
| 97fc64be81 | |||
| 7ae391b599 | |||
| f5e491325f | |||
| 2fa02374fd | |||
| 380586fb73 | |||
| da37ed11cd |
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,3 +4,4 @@ houston
|
|||||||
houston.zip
|
houston.zip
|
||||||
config.json
|
config.json
|
||||||
.vscode/
|
.vscode/
|
||||||
|
/data
|
||||||
|
|||||||
110
client/client.go
110
client/client.go
@ -2,6 +2,7 @@ package client
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -32,9 +33,26 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type runcommand struct {
|
type runcommand struct {
|
||||||
Exec string `json:"exec"`
|
Exec string `json:"exec"`
|
||||||
Args []string `json:"args"`
|
Args []string `json:"args"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
|
AutoRestart bool `json:"auto_restart"`
|
||||||
|
OutputLogFile string `json:"logfile"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type easyruncommand runcommand
|
||||||
|
|
||||||
|
func (t *runcommand) UnmarshalJSON(b []byte) error {
|
||||||
|
easy := easyruncommand{
|
||||||
|
Version: "latest",
|
||||||
|
AutoRestart: true,
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(b, &easy); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*t = runcommand(easy)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type clientConfig struct {
|
type clientConfig struct {
|
||||||
@ -73,14 +91,17 @@ type HoustonClient interface {
|
|||||||
var seq = int32(1)
|
var seq = int32(1)
|
||||||
|
|
||||||
type procmeta struct {
|
type procmeta struct {
|
||||||
id int32
|
id int32
|
||||||
cmd *exec.Cmd
|
cmd *exec.Cmd
|
||||||
name string
|
name string
|
||||||
args []string
|
args []string
|
||||||
version string
|
version string
|
||||||
verpath string
|
verpath string
|
||||||
state int32
|
recover bool
|
||||||
stdin io.WriteCloser
|
state int32
|
||||||
|
stdin io.WriteCloser
|
||||||
|
logfile string
|
||||||
|
keepLatest bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pm *procmeta) isState(s protos.ProcessState) bool {
|
func (pm *procmeta) isState(s protos.ProcessState) bool {
|
||||||
@ -113,6 +134,13 @@ type houstonClient struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func unmarshal[T any](val *T, src map[string]string) {
|
func unmarshal[T any](val *T, src map[string]string) {
|
||||||
|
defer func() {
|
||||||
|
r := recover()
|
||||||
|
if r != nil {
|
||||||
|
logger.Error(r)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
argval := reflect.ValueOf(val)
|
argval := reflect.ValueOf(val)
|
||||||
for i := 0; i < argval.Elem().Type().NumField(); i++ {
|
for i := 0; i < argval.Elem().Type().NumField(); i++ {
|
||||||
if !argval.Elem().Type().Field(i).IsExported() {
|
if !argval.Elem().Type().Field(i).IsExported() {
|
||||||
@ -125,6 +153,9 @@ func unmarshal[T any](val *T, src map[string]string) {
|
|||||||
} else if argval.Elem().Field(i).Kind() == reflect.Array || argval.Elem().Field(i).Kind() == reflect.Slice {
|
} else if argval.Elem().Field(i).Kind() == reflect.Array || argval.Elem().Field(i).Kind() == reflect.Slice {
|
||||||
conv := strings.Split(arg, "\n")
|
conv := strings.Split(arg, "\n")
|
||||||
argval.Elem().Field(i).Set(reflect.ValueOf(conv))
|
argval.Elem().Field(i).Set(reflect.ValueOf(conv))
|
||||||
|
} else if argval.Elem().Field(i).Kind() == reflect.Bool {
|
||||||
|
bv, _ := strconv.ParseBool(arg)
|
||||||
|
argval.Elem().Field(i).SetBool(bv)
|
||||||
} else {
|
} else {
|
||||||
argval.Elem().Field(i).SetString(arg)
|
argval.Elem().Field(i).SetString(arg)
|
||||||
}
|
}
|
||||||
@ -332,6 +363,10 @@ func NewClient(standalone bool) (HoustonClient, error) {
|
|||||||
proc.cmd.Process.Release()
|
proc.cmd.Process.Release()
|
||||||
|
|
||||||
if proc.isState(protos.ProcessState_Restart) {
|
if proc.isState(protos.ProcessState_Restart) {
|
||||||
|
if proc.keepLatest {
|
||||||
|
proc.version = "latest"
|
||||||
|
}
|
||||||
|
|
||||||
if err := hc.startChildProcess(&shared.StartProcessRequest{
|
if err := hc.startChildProcess(&shared.StartProcessRequest{
|
||||||
Version: proc.version,
|
Version: proc.version,
|
||||||
Name: proc.name,
|
Name: proc.name,
|
||||||
@ -352,10 +387,14 @@ func NewClient(standalone bool) (HoustonClient, error) {
|
|||||||
op.Refresh(ctx, hc.makeOperationQueryRequest())
|
op.Refresh(ctx, hc.makeOperationQueryRequest())
|
||||||
|
|
||||||
case resp := <-operationChan:
|
case resp := <-operationChan:
|
||||||
|
logger.Println("houton query operation :", resp.Operation)
|
||||||
|
|
||||||
switch shared.Operation(resp.Operation) {
|
switch shared.Operation(resp.Operation) {
|
||||||
case shared.Deploy:
|
case shared.Deploy:
|
||||||
var dr shared.DeployRequest
|
var dr shared.DeployRequest
|
||||||
unmarshal(&dr, resp.Args)
|
unmarshal(&dr, resp.Args)
|
||||||
|
logger.Println("args :", dr)
|
||||||
|
|
||||||
if dr.Name == myname {
|
if dr.Name == myname {
|
||||||
if srcdir, replacer, err := hc.prepareUpdateSelf(&dr); err == nil {
|
if srcdir, replacer, err := hc.prepareUpdateSelf(&dr); err == nil {
|
||||||
args := []string{
|
args := []string{
|
||||||
@ -411,6 +450,8 @@ func NewClient(standalone bool) (HoustonClient, error) {
|
|||||||
case shared.Withdraw:
|
case shared.Withdraw:
|
||||||
var wr shared.WithdrawRequest
|
var wr shared.WithdrawRequest
|
||||||
unmarshal(&wr, resp.Args)
|
unmarshal(&wr, resp.Args)
|
||||||
|
logger.Println("args :", wr)
|
||||||
|
|
||||||
err := hc.withdraw(&wr)
|
err := hc.withdraw(&wr)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
prog := gatherDeployedPrograms(hc.config.StorageRoot, wr.Name)
|
prog := gatherDeployedPrograms(hc.config.StorageRoot, wr.Name)
|
||||||
@ -427,6 +468,8 @@ func NewClient(standalone bool) (HoustonClient, error) {
|
|||||||
case shared.Start:
|
case shared.Start:
|
||||||
var sr shared.StartProcessRequest
|
var sr shared.StartProcessRequest
|
||||||
unmarshal(&sr, resp.Args)
|
unmarshal(&sr, resp.Args)
|
||||||
|
logger.Println("args :", sr)
|
||||||
|
|
||||||
if err := hc.startChildProcess(&sr); err != nil {
|
if err := hc.startChildProcess(&sr); err != nil {
|
||||||
logger.ErrorWithCallStack(err)
|
logger.ErrorWithCallStack(err)
|
||||||
} else {
|
} else {
|
||||||
@ -436,6 +479,8 @@ func NewClient(standalone bool) (HoustonClient, error) {
|
|||||||
case shared.Stop:
|
case shared.Stop:
|
||||||
var sr shared.StopProcessRequest
|
var sr shared.StopProcessRequest
|
||||||
unmarshal(&sr, resp.Args)
|
unmarshal(&sr, resp.Args)
|
||||||
|
logger.Println("args :", sr)
|
||||||
|
|
||||||
if err := hc.stopChildProcess(&sr, op); err != nil {
|
if err := hc.stopChildProcess(&sr, op); err != nil {
|
||||||
logger.Println(err)
|
logger.Println(err)
|
||||||
}
|
}
|
||||||
@ -443,6 +488,8 @@ func NewClient(standalone bool) (HoustonClient, error) {
|
|||||||
case shared.Restart:
|
case shared.Restart:
|
||||||
var rr shared.RestartProcessRequest
|
var rr shared.RestartProcessRequest
|
||||||
unmarshal(&rr, resp.Args)
|
unmarshal(&rr, resp.Args)
|
||||||
|
logger.Println("args :", rr)
|
||||||
|
|
||||||
if err := hc.restartChildProcess(&rr, op); err != nil {
|
if err := hc.restartChildProcess(&rr, op); err != nil {
|
||||||
logger.Println(err)
|
logger.Println(err)
|
||||||
}
|
}
|
||||||
@ -450,6 +497,8 @@ func NewClient(standalone bool) (HoustonClient, error) {
|
|||||||
case shared.Upload:
|
case shared.Upload:
|
||||||
var ur shared.UploadRequest
|
var ur shared.UploadRequest
|
||||||
unmarshal(&ur, resp.Args)
|
unmarshal(&ur, resp.Args)
|
||||||
|
logger.Println("args :", ur)
|
||||||
|
|
||||||
if err := hc.uploadFiles(&ur); err != nil {
|
if err := hc.uploadFiles(&ur); err != nil {
|
||||||
logger.Println(err)
|
logger.Println(err)
|
||||||
}
|
}
|
||||||
@ -459,16 +508,41 @@ func NewClient(standalone bool) (HoustonClient, error) {
|
|||||||
id64, _ := strconv.ParseInt(idstr, 10, 0)
|
id64, _ := strconv.ParseInt(idstr, 10, 0)
|
||||||
id := int32(id64)
|
id := int32(id64)
|
||||||
|
|
||||||
|
var found *procmeta
|
||||||
hc.childProcs = gocommon.ShrinkSlice(hc.childProcs, func(e *procmeta) bool {
|
hc.childProcs = gocommon.ShrinkSlice(hc.childProcs, func(e *procmeta) bool {
|
||||||
if e.id == id {
|
if e.id == id {
|
||||||
e.cmd.Wait()
|
found = e
|
||||||
e.cmd.Process.Release()
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
op.Refresh(context.Background(), hc.makeOperationQueryRequest())
|
if found != nil {
|
||||||
|
found.cmd.Wait()
|
||||||
|
found.cmd.Process.Release()
|
||||||
|
|
||||||
|
if found.recover {
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
sr := shared.StartProcessRequest{
|
||||||
|
Name: found.name,
|
||||||
|
Version: found.version,
|
||||||
|
Args: found.args,
|
||||||
|
AutoRestart: found.recover,
|
||||||
|
OutputLogFile: found.logfile,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := hc.startChildProcess(&sr); err != nil {
|
||||||
|
logger.Println("startChildProcess failed by autorun :", err)
|
||||||
|
logger.ErrorWithCallStack(err)
|
||||||
|
} else {
|
||||||
|
logger.Println("recover success :", sr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if op != nil {
|
||||||
|
op.Refresh(context.Background(), hc.makeOperationQueryRequest())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -541,9 +615,11 @@ func (hc *houstonClient) Start() {
|
|||||||
// service 서비스
|
// service 서비스
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
sr := shared.StartProcessRequest{
|
sr := shared.StartProcessRequest{
|
||||||
Name: service,
|
Name: service,
|
||||||
Version: cmd.Version,
|
Version: cmd.Version,
|
||||||
Args: append([]string{cmd.Exec}, cmd.Args...),
|
Args: append([]string{cmd.Exec}, cmd.Args...),
|
||||||
|
AutoRestart: cmd.AutoRestart,
|
||||||
|
OutputLogFile: cmd.OutputLogFile,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := hc.startChildProcess(&sr); err != nil {
|
if err := hc.startChildProcess(&sr); err != nil {
|
||||||
|
|||||||
@ -15,7 +15,6 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
@ -79,30 +78,34 @@ func (hc *houstonClient) uploadZipLogFile(zipFile string, name string, version s
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func zipLogFiles(storageRoot string, req *shared.UploadRequest) (string, []string, error) {
|
func findMatchFiles(storageRoot, name, version, filter string) (string, []string) {
|
||||||
root := path.Join(storageRoot, req.Name, req.Version)
|
root := path.Join(storageRoot, name, version)
|
||||||
matches, err := filepath.Glob(path.Join(root, req.Filter))
|
matches, err := filepath.Glob(path.Join(root, filter))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(matches) == 0 {
|
if len(matches) == 0 {
|
||||||
return "", nil, nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, file := range matches {
|
root = path.Join(root, path.Dir(filter))
|
||||||
|
out := make([]string, 0, len(matches))
|
||||||
|
for _, file := range matches {
|
||||||
file = filepath.ToSlash(file)
|
file = filepath.ToSlash(file)
|
||||||
matches[i] = file
|
if file == root {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
out = append(out, file)
|
||||||
}
|
}
|
||||||
|
return root, out
|
||||||
|
}
|
||||||
|
|
||||||
root = path.Join(root, path.Dir(req.Filter))
|
func zipCompressFiles(root string, matches []string) (string, error) {
|
||||||
hostname, _ := os.Hostname()
|
f, err := os.CreateTemp(os.TempDir(), "*.zip")
|
||||||
zipFileName := path.Join(os.TempDir(), hostname+"_"+path.Base(filepath.ToSlash(matches[0]))) + ".zip"
|
|
||||||
os.Remove(zipFileName)
|
|
||||||
f, err := os.OpenFile(zipFileName, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
@ -111,10 +114,6 @@ func zipLogFiles(storageRoot string, req *shared.UploadRequest) (string, []strin
|
|||||||
|
|
||||||
oldestFile := ""
|
oldestFile := ""
|
||||||
for i, file := range matches {
|
for i, file := range matches {
|
||||||
if file == root {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if fi, err := os.Lstat(file); err == nil {
|
if fi, err := os.Lstat(file); err == nil {
|
||||||
if (fi.Mode() & os.ModeSymlink) == os.ModeSymlink {
|
if (fi.Mode() & os.ModeSymlink) == os.ModeSymlink {
|
||||||
matches[i] = ""
|
matches[i] = ""
|
||||||
@ -129,21 +128,21 @@ func zipLogFiles(storageRoot string, req *shared.UploadRequest) (string, []strin
|
|||||||
relative := file[len(root)+1:]
|
relative := file[len(root)+1:]
|
||||||
fw, err := w.Create(relative)
|
fw, err := w.Create(relative)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
src, err := os.Open(file)
|
src, err := os.Open(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", err
|
||||||
}
|
}
|
||||||
defer src.Close()
|
defer src.Close()
|
||||||
|
|
||||||
if _, err = io.Copy(fw, src); err != nil {
|
if _, err = io.Copy(fw, src); err != nil {
|
||||||
return "", nil, err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return f.Name(), matches, nil
|
return f.Name(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareProcessLaunch(storageRoot string, req *shared.StartProcessRequest) (*procmeta, error) {
|
func prepareProcessLaunch(storageRoot string, req *shared.StartProcessRequest) (*procmeta, error) {
|
||||||
@ -151,6 +150,7 @@ func prepareProcessLaunch(storageRoot string, req *shared.StartProcessRequest) (
|
|||||||
return nil, errors.New("args is empty")
|
return nil, errors.New("args is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foundVersion := req.Version
|
||||||
if req.Version == "latest" {
|
if req.Version == "latest" {
|
||||||
entries, err := os.ReadDir(path.Join(storageRoot, req.Name))
|
entries, err := os.ReadDir(path.Join(storageRoot, req.Name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -176,11 +176,11 @@ func prepareProcessLaunch(storageRoot string, req *shared.StartProcessRequest) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(latestVersion) > 0 {
|
if len(latestVersion) > 0 {
|
||||||
req.Version = latestVersion
|
foundVersion = latestVersion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
verpath := path.Join(storageRoot, req.Name, req.Version)
|
verpath := path.Join(storageRoot, req.Name, foundVersion)
|
||||||
fi, err := os.Stat(verpath)
|
fi, err := os.Stat(verpath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -211,45 +211,22 @@ func prepareProcessLaunch(storageRoot string, req *shared.StartProcessRequest) (
|
|||||||
|
|
||||||
seq++
|
seq++
|
||||||
return &procmeta{
|
return &procmeta{
|
||||||
id: seq,
|
id: seq,
|
||||||
cmd: cmd,
|
cmd: cmd,
|
||||||
name: req.Name,
|
name: req.Name,
|
||||||
args: req.Args,
|
args: req.Args,
|
||||||
version: req.Version,
|
version: foundVersion,
|
||||||
verpath: verpath,
|
recover: req.AutoRestart,
|
||||||
state: int32(protos.ProcessState_Stopped),
|
verpath: verpath,
|
||||||
stdin: stdin,
|
state: int32(protos.ProcessState_Stopped),
|
||||||
|
stdin: stdin,
|
||||||
|
logfile: req.OutputLogFile,
|
||||||
|
keepLatest: req.Version == "latest",
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
return nil, errors.New("not found")
|
return nil, errors.New("not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeLogFilePrefix(meta *procmeta, index int) string {
|
|
||||||
now := time.Now().UTC()
|
|
||||||
ext := path.Ext(meta.args[0])
|
|
||||||
nameonly := path.Base(filepath.ToSlash(meta.args[0]))
|
|
||||||
if len(ext) > 0 {
|
|
||||||
nameonly = nameonly[:len(nameonly)-len(ext)]
|
|
||||||
}
|
|
||||||
ts := now.Format("2006-01-02T15-04-05")
|
|
||||||
if index == 0 {
|
|
||||||
|
|
||||||
return path.Join(meta.verpath, "logs", fmt.Sprintf("%s_%s", nameonly, ts))
|
|
||||||
}
|
|
||||||
|
|
||||||
return path.Join(meta.verpath, "logs", fmt.Sprintf("%s_%d_%s", nameonly, index, ts))
|
|
||||||
}
|
|
||||||
|
|
||||||
func evaluateExpression(expression string, params map[string]any) (any, error) {
|
|
||||||
expression = strings.TrimSpace(expression)
|
|
||||||
expr, err := govaluate.NewEvaluableExpression(expression)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return expr.Evaluate(params)
|
|
||||||
}
|
|
||||||
|
|
||||||
func evaluateArgs(args []string, params map[string]any) ([]string, error) {
|
func evaluateArgs(args []string, params map[string]any) ([]string, error) {
|
||||||
re := regexp.MustCompile(`\$\(\((.*?)\)\)`)
|
re := regexp.MustCompile(`\$\(\((.*?)\)\)`)
|
||||||
|
|
||||||
@ -307,17 +284,27 @@ func (hc *houstonClient) launch(meta *procmeta) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
stderr, err := meta.cmd.StderrPipe()
|
||||||
err = os.MkdirAll(path.Join(meta.verpath, "logs"), 0775)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
stdReader := func(jobName string, r io.ReadCloser, index int) {
|
logfolder := path.Join(meta.verpath, "logs")
|
||||||
|
err = os.MkdirAll(logfolder, 0775)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
stdReader := func(jobName string, r io.ReadCloser, index int, logfilePath string) {
|
||||||
defer func() {
|
defer func() {
|
||||||
reco := recover()
|
logger.Println("stdReader is terminated :", meta.name)
|
||||||
if reco != nil {
|
if meta.isState(protos.ProcessState_Running) {
|
||||||
logger.Println(reco)
|
hc.operationChan <- &protos.OperationQueryResponse{
|
||||||
|
Operation: string(shared.Exception),
|
||||||
|
Args: map[string]string{
|
||||||
|
"id": fmt.Sprintf("%d", meta.id),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -331,90 +318,35 @@ func (hc *houstonClient) launch(meta *procmeta) error {
|
|||||||
hc.siblingProcIndex[key] = runningFlags
|
hc.siblingProcIndex[key] = runningFlags
|
||||||
}()
|
}()
|
||||||
|
|
||||||
defer r.Close()
|
|
||||||
|
|
||||||
reader := bufio.NewReader(r)
|
|
||||||
thisFileSize := 0
|
|
||||||
logFileIndex := 0
|
|
||||||
|
|
||||||
var logWriter func([]byte)
|
|
||||||
if *logger.UseLogFile {
|
|
||||||
logFileNamePrefix := makeLogFilePrefix(meta, index)
|
|
||||||
logFileName := fmt.Sprintf("%s_%d.log", logFileNamePrefix, logFileIndex)
|
|
||||||
targetFile, err := os.Create(logFileName)
|
|
||||||
if err != nil {
|
|
||||||
logger.Println("failed to create log file :", logFileName)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
exef, _ := os.Executable()
|
|
||||||
var linkPath string
|
|
||||||
if index == 0 {
|
|
||||||
linkPath = path.Join(path.Dir(exef), path.Dir(logFileName), meta.name+".log")
|
|
||||||
} else {
|
|
||||||
linkPath = path.Join(path.Dir(exef), path.Dir(logFileName), fmt.Sprintf("%s_%d.log", meta.name, index))
|
|
||||||
}
|
|
||||||
|
|
||||||
os.Remove(linkPath)
|
|
||||||
os.Symlink(path.Base(filepath.ToSlash(targetFile.Name())), linkPath)
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if targetFile != nil {
|
|
||||||
targetFile.Close()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
logWriter = func(buff []byte) {
|
|
||||||
for written := 0; written < len(buff); {
|
|
||||||
n, err := targetFile.Write(buff)
|
|
||||||
if err != nil {
|
|
||||||
logger.Println("write log file failed :", logFileName, err)
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
written += n
|
|
||||||
thisFileSize += n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if thisFileSize > 5*1024*1024 {
|
|
||||||
logFileIndex++
|
|
||||||
logFileName = fmt.Sprintf("%s_%d.log", logFileNamePrefix, logFileIndex)
|
|
||||||
nextTargetFile, err := os.Create(logFileName)
|
|
||||||
if err != nil {
|
|
||||||
logger.Println("failed to create log file :", logFileName)
|
|
||||||
} else {
|
|
||||||
targetFile.Close()
|
|
||||||
targetFile = nextTargetFile
|
|
||||||
os.Remove(linkPath)
|
|
||||||
os.Symlink(path.Base(filepath.ToSlash(targetFile.Name())), linkPath)
|
|
||||||
thisFileSize = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logWriter = func(buff []byte) {
|
|
||||||
os.Stdout.Write(buff)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
readingMetric := false
|
|
||||||
var metricBuffer []byte
|
|
||||||
defer func() {
|
defer func() {
|
||||||
logger.Println("stdReader is terminated :", meta.name)
|
reco := recover()
|
||||||
if meta.isState(protos.ProcessState_Running) {
|
if reco != nil {
|
||||||
hc.operationChan <- &protos.OperationQueryResponse{
|
logger.Println(reco)
|
||||||
Operation: string(shared.Exception),
|
|
||||||
Args: map[string]string{
|
|
||||||
"id": fmt.Sprintf("%d", meta.id),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
metricExporter := metric.NewPrometheusExport(hc.config.MetricNamespace)
|
metricExporter := metric.NewPrometheusExport(hc.config.MetricNamespace)
|
||||||
defer metricExporter.Shutdown()
|
defer metricExporter.Shutdown()
|
||||||
|
|
||||||
|
total := 0
|
||||||
|
hn, _ := os.Hostname()
|
||||||
|
var targetFile *os.File
|
||||||
|
ext := path.Ext(logfilePath)
|
||||||
|
head := logfilePath[:len(logfilePath)-len(ext)]
|
||||||
|
reader := bufio.NewReader(r)
|
||||||
|
readingMetric := false
|
||||||
|
ext = "." + hn + ext
|
||||||
|
|
||||||
|
var metricBuffer []byte
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
if targetFile == nil {
|
||||||
|
currentFile := head + time.Now().UTC().Format(".2006-01-02.150405") + ext
|
||||||
|
targetFile, _ = os.OpenFile(currentFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666)
|
||||||
|
}
|
||||||
|
|
||||||
buff, err := reader.ReadBytes('\n')
|
buff, err := reader.ReadBytes('\n')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Println("ReadBytes at stdReader return err :", err, meta.name)
|
logger.Println("ReadBytes at stdReader return err :", err, meta.name)
|
||||||
@ -458,11 +390,79 @@ func (hc *houstonClient) launch(meta *procmeta) error {
|
|||||||
|
|
||||||
metricBuffer = metricBuffer[:0]
|
metricBuffer = metricBuffer[:0]
|
||||||
}
|
}
|
||||||
|
} else if targetFile != nil && len(buff) > 0 {
|
||||||
|
for written := 0; written < len(buff); {
|
||||||
|
n, err := targetFile.Write(buff[written:])
|
||||||
|
if err != nil {
|
||||||
|
logger.Println("write log file failed :", logfilePath, err)
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
written += n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
total += len(buff)
|
||||||
|
|
||||||
continue
|
if total > 1024*1024 {
|
||||||
|
total = 0
|
||||||
|
targetFile.Close()
|
||||||
|
targetFile = nil
|
||||||
|
|
||||||
|
hc.uploadProcFiles(meta, "logs/*"+ext, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errReader := func(r io.ReadCloser, logfilePath string) {
|
||||||
|
defer func() {
|
||||||
|
reco := recover()
|
||||||
|
if reco != nil {
|
||||||
|
logger.Println(reco)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
defer r.Close()
|
||||||
|
|
||||||
|
total := 0
|
||||||
|
hn, _ := os.Hostname()
|
||||||
|
|
||||||
|
var targetFile *os.File
|
||||||
|
ext := path.Ext(logfilePath)
|
||||||
|
head := logfilePath[:len(logfilePath)-len(ext)]
|
||||||
|
reader := bufio.NewReader(r)
|
||||||
|
ext = "." + hn + ext
|
||||||
|
|
||||||
|
for {
|
||||||
|
if targetFile == nil {
|
||||||
|
currentFile := head + time.Now().UTC().Format(".2006-01-02.150405") + ext
|
||||||
|
targetFile, _ = os.OpenFile(currentFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666)
|
||||||
}
|
}
|
||||||
|
|
||||||
logWriter(buff)
|
buff, errRead := reader.ReadBytes('\n')
|
||||||
|
if errRead != nil {
|
||||||
|
logger.Println("ReadBytes at stdReader return err :", err, meta.name)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if targetFile != nil && len(buff) > 0 {
|
||||||
|
for written := 0; written < len(buff); {
|
||||||
|
n, err := targetFile.Write(buff[written:])
|
||||||
|
if err != nil {
|
||||||
|
logger.Println("write log file failed :", logfilePath, err)
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
written += n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
total += len(buff)
|
||||||
|
|
||||||
|
if total > 1024*1024 {
|
||||||
|
total = 0
|
||||||
|
targetFile.Close()
|
||||||
|
targetFile = nil
|
||||||
|
|
||||||
|
hc.uploadProcFiles(meta, "logs/*"+ext, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,14 +486,43 @@ func (hc *houstonClient) launch(meta *procmeta) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
go stdReader(meta.name, stdout, index)
|
// 자체 환경 변수
|
||||||
|
customEnv := map[string]string{
|
||||||
|
"HOUSTON_SIBLIING_INDEX": fmt.Sprintf("%d", index),
|
||||||
|
"HOUSTON_PROC_TIMESTAMP": time.Now().UTC().Format("2006-01-02T15-04-05"),
|
||||||
|
}
|
||||||
|
|
||||||
meta.cmd.Env = append(os.Environ(), fmt.Sprintf("HOUSTON_SIBLIING_INDEX=%d", index))
|
// 프로세스 환경 변수에 반영
|
||||||
|
meta.cmd.Env = os.Environ()
|
||||||
|
for k, v := range customEnv {
|
||||||
|
meta.cmd.Env = append(meta.cmd.Env, fmt.Sprintf("%s=%s", k, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// argument 표현식 계산
|
||||||
meta.cmd.Args, err = evaluateArgs(meta.cmd.Args, parseEnv(meta.cmd.Env))
|
meta.cmd.Args, err = evaluateArgs(meta.cmd.Args, parseEnv(meta.cmd.Env))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Println("evaluateArgs failed :", err)
|
logger.Println("evaluateArgs failed :", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 로그파일에 환경변수 적용
|
||||||
|
evalfile := os.Expand(meta.logfile, func(n string) string {
|
||||||
|
v := os.Getenv(n)
|
||||||
|
if len(v) == 0 {
|
||||||
|
return customEnv[n]
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(evalfile) > 0 {
|
||||||
|
evalfile = path.Join(logfolder, evalfile)
|
||||||
|
} else {
|
||||||
|
evalfile = path.Join(logfolder, path.Base(meta.cmd.Args[0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
go stdReader(meta.name, stdout, index, evalfile+".log")
|
||||||
|
go errReader(stderr, evalfile+".err")
|
||||||
|
|
||||||
logger.Println("startChildProcess :", meta.cmd.Args)
|
logger.Println("startChildProcess :", meta.cmd.Args)
|
||||||
|
|
||||||
err = meta.cmd.Start()
|
err = meta.cmd.Start()
|
||||||
@ -605,54 +634,52 @@ func (hc *houstonClient) restartChildProcess(req *shared.RestartProcessRequest,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (hc *houstonClient) uploadProcFiles(child *procmeta, filter string, deleteAfterUpload bool) {
|
||||||
|
logger.Println("uploadFiles found :", child.version, child.name)
|
||||||
|
root, matches := findMatchFiles(hc.config.StorageRoot, child.name, child.version, filter)
|
||||||
|
|
||||||
|
go func(deleteAfterUpload bool, root string, matches []string) {
|
||||||
|
zipFile, err := zipCompressFiles(root, matches)
|
||||||
|
if err == nil && len(zipFile) > 0 {
|
||||||
|
if err = hc.uploadZipLogFile(zipFile, child.name, child.version); err == nil {
|
||||||
|
if deleteAfterUpload {
|
||||||
|
for _, fn := range matches {
|
||||||
|
if len(fn) > 0 {
|
||||||
|
os.Remove(fn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.Println("uploadZipLogFile failed :", err)
|
||||||
|
}
|
||||||
|
os.Remove(zipFile)
|
||||||
|
} else if err != nil {
|
||||||
|
logger.Println("zipLogFiles failed :", err)
|
||||||
|
}
|
||||||
|
}(deleteAfterUpload, root, matches)
|
||||||
|
}
|
||||||
|
|
||||||
func (hc *houstonClient) uploadFiles(req *shared.UploadRequest) error {
|
func (hc *houstonClient) uploadFiles(req *shared.UploadRequest) error {
|
||||||
logger.Println("uploadFiles req :", *req)
|
logger.Println("uploadFiles req :", *req)
|
||||||
for _, child := range hc.childProcs {
|
for _, child := range hc.childProcs {
|
||||||
if child.version == req.Version && child.name == req.Name {
|
if child.version == req.Version && child.name == req.Name {
|
||||||
logger.Println("uploadFiles found :", child.version, child.name)
|
hc.uploadProcFiles(child, req.Filter, false)
|
||||||
|
|
||||||
go func() {
|
|
||||||
zipFile, srcFiles, err := zipLogFiles(hc.config.StorageRoot, req)
|
|
||||||
if err == nil && len(zipFile) > 0 && len(srcFiles) > 0 {
|
|
||||||
if err = hc.uploadZipLogFile(zipFile, child.name, child.version); err == nil {
|
|
||||||
// 마지막거 빼고 삭제
|
|
||||||
if req.DeleteAfterUploaded == "true" {
|
|
||||||
for i := 0; i < len(srcFiles)-1; i++ {
|
|
||||||
os.Remove(srcFiles[i])
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sort.StringSlice(srcFiles).Sort()
|
|
||||||
|
|
||||||
for i := 0; i < len(srcFiles)-1; i++ {
|
|
||||||
if len(srcFiles[i]) > 0 {
|
|
||||||
os.Remove(srcFiles[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logger.Println("uploadZipLogFile failed :", err)
|
|
||||||
}
|
|
||||||
} else if err != nil {
|
|
||||||
logger.Println("zipLogFiles failed :", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 실행 중이 아닌 폴더에서도 대상을 찾는다
|
// 실행 중이 아닌 폴더에서도 대상을 찾는다
|
||||||
// 전체 파일을 대상으로
|
// 전체 파일을 대상으로
|
||||||
zipFile, srcFiles, err := zipLogFiles(hc.config.StorageRoot, req)
|
root, matches := findMatchFiles(hc.config.StorageRoot, req.Name, req.Version, req.Filter)
|
||||||
if err == nil && len(zipFile) > 0 && len(srcFiles) > 0 {
|
zipFile, err := zipCompressFiles(root, matches)
|
||||||
|
if err == nil && len(zipFile) > 0 && len(zipFile) > 0 {
|
||||||
if err = hc.uploadZipLogFile(zipFile, req.Name, req.Version); err == nil {
|
if err = hc.uploadZipLogFile(zipFile, req.Name, req.Version); err == nil {
|
||||||
// 마지막거 빼고 삭제
|
for _, fn := range matches {
|
||||||
sort.StringSlice(srcFiles).Sort()
|
if len(fn) > 0 {
|
||||||
for i := 0; i < len(srcFiles)-1; i++ {
|
os.Remove(fn)
|
||||||
if len(srcFiles[i]) > 0 {
|
|
||||||
os.Remove(srcFiles[i])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
os.Remove(zipFile)
|
||||||
} else {
|
} else {
|
||||||
logger.Println("uploadZipLogFile failed :", err)
|
logger.Println("uploadZipLogFile failed :", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
"repositories.action2quare.com/ayo/gocommon/flagx"
|
"repositories.action2quare.com/ayo/gocommon/flagx"
|
||||||
|
"repositories.action2quare.com/ayo/gocommon/logger"
|
||||||
"repositories.action2quare.com/ayo/houston/client"
|
"repositories.action2quare.com/ayo/houston/client"
|
||||||
|
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -23,7 +24,14 @@ func main() {
|
|||||||
|
|
||||||
http.Handle("/metrics", promhttp.Handler())
|
http.Handle("/metrics", promhttp.Handler())
|
||||||
server := &http.Server{Addr: ":9100", Handler: nil}
|
server := &http.Server{Addr: ":9100", Handler: nil}
|
||||||
go server.ListenAndServe()
|
|
||||||
|
go func() {
|
||||||
|
logger.Println("listen /metrics")
|
||||||
|
err := server.ListenAndServe()
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
hc.Start()
|
hc.Start()
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
|||||||
@ -29,6 +29,8 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (h *houstonHandler) GetAgents(w http.ResponseWriter, r *http.Request) {
|
func (h *houstonHandler) GetAgents(w http.ResponseWriter, r *http.Request) {
|
||||||
|
logger.Println("GetAgents")
|
||||||
|
|
||||||
enc := json.NewEncoder(w)
|
enc := json.NewEncoder(w)
|
||||||
allHosts := h.Operation().Hosts()
|
allHosts := h.Operation().Hosts()
|
||||||
enc.Encode(allHosts)
|
enc.Encode(allHosts)
|
||||||
@ -45,6 +47,8 @@ func readTagsFromFile(paths ...string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *houstonHandler) GetDeploySources(w http.ResponseWriter, r *http.Request) {
|
func (h *houstonHandler) GetDeploySources(w http.ResponseWriter, r *http.Request) {
|
||||||
|
logger.Println("GetDeploySources")
|
||||||
|
|
||||||
files, err := os.ReadDir(h.deployPath)
|
files, err := os.ReadDir(h.deployPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Println(err)
|
logger.Println(err)
|
||||||
@ -100,6 +104,7 @@ func (h *houstonHandler) UploadDeploySource(w http.ResponseWriter, r *http.Reque
|
|||||||
// <input type="submit" value="업로드">
|
// <input type="submit" value="업로드">
|
||||||
// </form>
|
// </form>
|
||||||
file, header, err := r.FormFile("file")
|
file, header, err := r.FormFile("file")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Println(err)
|
logger.Println(err)
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
@ -118,6 +123,8 @@ func (h *houstonHandler) UploadDeploySource(w http.ResponseWriter, r *http.Reque
|
|||||||
name := r.FormValue("name")
|
name := r.FormValue("name")
|
||||||
ext := path.Ext(header.Filename)
|
ext := path.Ext(header.Filename)
|
||||||
|
|
||||||
|
logger.Println("UploadDeploySource :", name, version)
|
||||||
|
|
||||||
var filename string
|
var filename string
|
||||||
|
|
||||||
if version == "config" {
|
if version == "config" {
|
||||||
@ -154,6 +161,7 @@ func (h *houstonHandler) DeleteDeploySource(w http.ResponseWriter, r *http.Reque
|
|||||||
version := r.FormValue("version")
|
version := r.FormValue("version")
|
||||||
name := r.FormValue("name")
|
name := r.FormValue("name")
|
||||||
|
|
||||||
|
logger.Println("DeleteDeploySource :", name, version)
|
||||||
if len(version) == 0 || len(name) == 0 {
|
if len(version) == 0 || len(name) == 0 {
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
@ -161,6 +169,8 @@ func (h *houstonHandler) DeleteDeploySource(w http.ResponseWriter, r *http.Reque
|
|||||||
|
|
||||||
// deploys 폴더는 파일시스템 서비스이므로 다운로드 가능
|
// deploys 폴더는 파일시스템 서비스이므로 다운로드 가능
|
||||||
targetpath := path.Join(h.deployPath, name, version)
|
targetpath := path.Join(h.deployPath, name, version)
|
||||||
|
logger.Println("DeleteDeploySource :", name, version, targetpath)
|
||||||
|
|
||||||
if err := os.RemoveAll(targetpath); err != nil {
|
if err := os.RemoveAll(targetpath); err != nil {
|
||||||
logger.Println("deleteDeploySource failed :", err)
|
logger.Println("deleteDeploySource failed :", err)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
@ -220,6 +230,8 @@ func (h *houstonHandler) Deploy(w http.ResponseWriter, r *http.Request) {
|
|||||||
version := r.FormValue("version")
|
version := r.FormValue("version")
|
||||||
traws := r.FormValue("targets")
|
traws := r.FormValue("targets")
|
||||||
|
|
||||||
|
logger.Println("Deploy :", name, version, traws)
|
||||||
|
|
||||||
var targets []string
|
var targets []string
|
||||||
if len(traws) > 0 {
|
if len(traws) > 0 {
|
||||||
if err := json.Unmarshal([]byte(traws), &targets); err != nil {
|
if err := json.Unmarshal([]byte(traws), &targets); err != nil {
|
||||||
@ -292,6 +304,8 @@ func (h *houstonHandler) Undeploy(w http.ResponseWriter, r *http.Request) {
|
|||||||
version := r.FormValue("version")
|
version := r.FormValue("version")
|
||||||
traws := r.FormValue("targets")
|
traws := r.FormValue("targets")
|
||||||
|
|
||||||
|
logger.Println("Undeploy :", name, version, traws)
|
||||||
|
|
||||||
var targets []string
|
var targets []string
|
||||||
if len(traws) > 0 {
|
if len(traws) > 0 {
|
||||||
if err := json.Unmarshal([]byte(traws), &targets); err != nil {
|
if err := json.Unmarshal([]byte(traws), &targets); err != nil {
|
||||||
@ -328,6 +342,8 @@ func (h *houstonHandler) StartProcess(w http.ResponseWriter, r *http.Request) {
|
|||||||
argsline := r.FormValue("args")
|
argsline := r.FormValue("args")
|
||||||
traws := r.FormValue("targets")
|
traws := r.FormValue("targets")
|
||||||
|
|
||||||
|
logger.Println("StartProcess :", name, version, argsline, traws)
|
||||||
|
|
||||||
var targets []string
|
var targets []string
|
||||||
if len(traws) > 0 {
|
if len(traws) > 0 {
|
||||||
if err := json.Unmarshal([]byte(traws), &targets); err != nil {
|
if err := json.Unmarshal([]byte(traws), &targets); err != nil {
|
||||||
@ -380,6 +396,8 @@ func (h *houstonHandler) StopProcess(w http.ResponseWriter, r *http.Request) {
|
|||||||
// <input type="submit" value="업로드">
|
// <input type="submit" value="업로드">
|
||||||
// </form>
|
// </form>
|
||||||
name := r.FormValue("name")
|
name := r.FormValue("name")
|
||||||
|
logger.Println("StopProcess :", name)
|
||||||
|
|
||||||
if len(name) == 0 {
|
if len(name) == 0 {
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
@ -424,6 +442,8 @@ func (h *houstonHandler) RestartProcess(w http.ResponseWriter, r *http.Request)
|
|||||||
pidstr := r.FormValue("pid")
|
pidstr := r.FormValue("pid")
|
||||||
target := r.FormValue("target")
|
target := r.FormValue("target")
|
||||||
name := r.FormValue("name")
|
name := r.FormValue("name")
|
||||||
|
logger.Println("RestartProcess :", name, pidstr, target)
|
||||||
|
|
||||||
if len(target) == 0 || len(pidstr) == 0 || len(name) == 0 {
|
if len(target) == 0 || len(pidstr) == 0 || len(name) == 0 {
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
@ -468,6 +488,8 @@ func (h *houstonHandler) UploadLogs(w http.ResponseWriter, r *http.Request) {
|
|||||||
// <input type="submit" value="업로드">
|
// <input type="submit" value="업로드">
|
||||||
// </form>
|
// </form>
|
||||||
name := r.FormValue("name")
|
name := r.FormValue("name")
|
||||||
|
logger.Println("UploadLogs :", name)
|
||||||
|
|
||||||
if len(name) == 0 {
|
if len(name) == 0 {
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
@ -501,6 +523,8 @@ func (h *houstonHandler) GetLogFileLinks(w http.ResponseWriter, r *http.Request)
|
|||||||
// </form>
|
// </form>
|
||||||
name := r.FormValue("name")
|
name := r.FormValue("name")
|
||||||
version := r.FormValue("version")
|
version := r.FormValue("version")
|
||||||
|
logger.Println("GetLogFileLinks :", name, version)
|
||||||
|
|
||||||
if len(name) == 0 || len(version) == 0 {
|
if len(name) == 0 || len(version) == 0 {
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"archive/zip"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -25,9 +26,10 @@ type HoustonServerWithHandler interface {
|
|||||||
|
|
||||||
type houstonHandler struct {
|
type houstonHandler struct {
|
||||||
HoustonServer
|
HoustonServer
|
||||||
methods map[string]reflect.Method
|
methods map[string]reflect.Method
|
||||||
deployPath string
|
deployPath string
|
||||||
downloadPath string
|
downloadPath string
|
||||||
|
maingateApiToken string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHoustonHandler() HoustonServerWithHandler {
|
func NewHoustonHandler() HoustonServerWithHandler {
|
||||||
@ -40,8 +42,9 @@ func NewHoustonHandler() HoustonServerWithHandler {
|
|||||||
methods[strings.ToLower(method.Name)] = method
|
methods[strings.ToLower(method.Name)] = method
|
||||||
}
|
}
|
||||||
return &houstonHandler{
|
return &houstonHandler{
|
||||||
HoustonServer: NewServer(),
|
HoustonServer: NewServer(),
|
||||||
methods: methods,
|
methods: methods,
|
||||||
|
maingateApiToken: loadServerConfig().MaingateApiToken,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,8 +129,7 @@ func (h *houstonHandler) RegisterHandlers(serveMux gocommon.ServerMuxInterface,
|
|||||||
defer func() {
|
defer func() {
|
||||||
s := recover()
|
s := recover()
|
||||||
if s != nil {
|
if s != nil {
|
||||||
logger.Println(s)
|
logger.Error(s)
|
||||||
debug.PrintStack()
|
|
||||||
}
|
}
|
||||||
io.Copy(io.Discard, r.Body)
|
io.Copy(io.Discard, r.Body)
|
||||||
r.Body.Close()
|
r.Body.Close()
|
||||||
@ -138,11 +140,26 @@ func (h *houstonHandler) RegisterHandlers(serveMux gocommon.ServerMuxInterface,
|
|||||||
filename := r.Header.Get("Houston-Service-Filename")
|
filename := r.Header.Get("Houston-Service-Filename")
|
||||||
dir := path.Join(h.downloadPath, name, version)
|
dir := path.Join(h.downloadPath, name, version)
|
||||||
if err := os.MkdirAll(dir, 0775); err == nil {
|
if err := os.MkdirAll(dir, 0775); err == nil {
|
||||||
file, _ := os.Create(path.Join(dir, filename))
|
filepath := path.Join(dir, filename)
|
||||||
if file != nil {
|
localfile, _ := os.Create(filepath)
|
||||||
defer file.Close()
|
logger.Println("file uploaded :", localfile)
|
||||||
if _, err = io.Copy(file, r.Body); err != nil {
|
if localfile != nil {
|
||||||
|
if _, err = io.Copy(localfile, r.Body); err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
} else {
|
||||||
|
localfile.Close()
|
||||||
|
localfile, _ = os.Open(filepath)
|
||||||
|
if strings.HasSuffix(filename, ".zip") {
|
||||||
|
stat, _ := localfile.Stat()
|
||||||
|
zipreader, _ := zip.NewReader(localfile, stat.Size())
|
||||||
|
for _, f := range zipreader.File {
|
||||||
|
file, _ := os.Create(path.Join(dir, f.Name))
|
||||||
|
comp, _ := f.Open()
|
||||||
|
io.Copy(file, comp)
|
||||||
|
file.Close()
|
||||||
|
}
|
||||||
|
os.Remove(filepath)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
@ -172,6 +189,7 @@ func (h *houstonHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
r.Body.Close()
|
r.Body.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// TODO : 구글 인증까지 붙인 후에 주석 제거
|
||||||
// var userinfo map[string]any
|
// var userinfo map[string]any
|
||||||
// if !*noauth && (*authtype == "on" || *authtype == "both") {
|
// if !*noauth && (*authtype == "on" || *authtype == "both") {
|
||||||
// authheader := r.Header.Get("Authorization")
|
// authheader := r.Header.Get("Authorization")
|
||||||
|
|||||||
@ -20,8 +20,9 @@ type HoustonServer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type serverConfig struct {
|
type serverConfig struct {
|
||||||
GrpcPort int `json:"grpc_port"`
|
GrpcPort int `json:"grpc_port"`
|
||||||
StorageRoot string `json:"storage_path"`
|
StorageRoot string `json:"storage_path"`
|
||||||
|
MaingateApiToken string `json:"maingate_api_token"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeployRequest struct {
|
type DeployRequest struct {
|
||||||
|
|||||||
@ -27,9 +27,11 @@ type WithdrawRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type StartProcessRequest struct {
|
type StartProcessRequest struct {
|
||||||
Name string
|
Name string
|
||||||
Version string
|
Version string
|
||||||
Args []string
|
Args []string
|
||||||
|
AutoRestart bool
|
||||||
|
OutputLogFile string
|
||||||
}
|
}
|
||||||
|
|
||||||
type StopProcessRequest struct {
|
type StopProcessRequest struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user