From bad563dce7ad7e80caeca3b390ec6cb9f50b18d1 Mon Sep 17 00:00:00 2001 From: mountain Date: Wed, 5 Jun 2024 13:40:10 +0900 Subject: [PATCH] =?UTF-8?q?autorun=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/client.go | 49 ++++++++++++++++++++++++++++++++++++----- client/deploy.go | 14 ++++++++++-- client/operation.go | 53 +++++++++++++++++++++++++++++++++++++-------- 3 files changed, 99 insertions(+), 17 deletions(-) diff --git a/client/client.go b/client/client.go index 4073c86..276f9d1 100644 --- a/client/client.go +++ b/client/client.go @@ -23,6 +23,7 @@ import ( "unsafe" "repositories.action2quare.com/ayo/gocommon" + "repositories.action2quare.com/ayo/gocommon/flagx" "repositories.action2quare.com/ayo/gocommon/logger" "repositories.action2quare.com/ayo/houston/shared" "repositories.action2quare.com/ayo/houston/shared/protos" @@ -31,14 +32,23 @@ import ( "google.golang.org/grpc/credentials/insecure" ) -type clientConfig struct { - GrpcAddress string `json:"grpc_server_address"` - HttpAddress string `json:"http_server_address"` - StorageRoot string `json:"storage_path"` - MetricNamespace string `json:"metric_namespace"` - ConstLabels map[string]string `json:"metric_const_labels"` +type runcommand struct { + Exec string `json:"exec"` + Args []string `json:"args"` + Version string `json:"version"` } +type clientConfig struct { + GrpcAddress string `json:"grpc_server_address"` + HttpAddress string `json:"http_server_address"` + StorageRoot string `json:"storage_path"` + MetricNamespace string `json:"metric_namespace"` + ConstLabels map[string]string `json:"metric_const_labels"` + Autorun map[string]runcommand `json:"autorun"` +} + +var autorun = flagx.String("autorun", "", "") + func loadClientConfig() (clientConfig, error) { configFile, err := os.Open("config.json") if err != nil { @@ -295,6 +305,7 @@ func NewClient(standalone bool) (HoustonClient, error) { operationChan := make(chan *protos.OperationQueryResponse, 10) hc.wg.Add(1) + // autorun 처리 go func() { defer hc.wg.Done() @@ -316,6 +327,32 @@ func NewClient(standalone bool) (HoustonClient, error) { case newClient := <-hc.clientChan: op = protos.NewOperationClient(newClient) + if autorun != nil && len(*autorun) > 0 { + hascount := strings.Split(*autorun, "/") + var service string + count := 1 + if len(hascount) > 1 { + service = hascount[0] + count, _ = strconv.Atoi(hascount[1]) + } else { + service = *autorun + } + + if cmd, ok := hc.config.Autorun[service]; ok { + // service 서비스 + for i := 0; i < count; i++ { + sr := shared.StartProcessRequest{ + Name: service, + Version: cmd.Version, + Args: append([]string{cmd.Exec}, cmd.Args...), + } + + if err := hc.startChildProcess(&sr, op); err != nil { + logger.Println("startChildProcess failed by autorun :", err) + } + } + } + } case exited := <-exitChan: var newprocs []*procmeta diff --git a/client/deploy.go b/client/deploy.go index 770cf74..94820f4 100644 --- a/client/deploy.go +++ b/client/deploy.go @@ -3,6 +3,8 @@ package client import ( "archive/tar" "archive/zip" + "crypto/md5" + "encoding/hex" "errors" "fmt" "io" @@ -58,6 +60,7 @@ func download(dir string, urlpath string, accessToken string, cb func(int64, int req, _ := http.NewRequest("GET", urlpath, nil) req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.51") + req.Header.Add("As-X-UrlHash", accessToken) resp, err := http.DefaultClient.Do(req) if err != nil { return "", err @@ -328,7 +331,10 @@ func (hc *houstonClient) deploy(req *shared.DeployRequest, cb func(*protos.Deplo } // verpath에 배포 시작 - fname, err := download(root, hc.makeDownloadUrl(req.Url), req.AccessToken, func(written int64, total int64) { + h := md5.New() + h.Write([]byte(strings.Trim(req.Url, "/"))) + at := hex.EncodeToString(h.Sum(nil)) + fname, err := download(root, hc.makeDownloadUrl(req.Url), at, func(written int64, total int64) { prog := protos.DeployingProgress{ State: "download", Progress: written, @@ -356,7 +362,11 @@ func (hc *houstonClient) deploy(req *shared.DeployRequest, cb func(*protos.Deplo if err == nil && len(req.Config) > 0 { // config.json도 다운로드 - _, err = download(root, hc.makeDownloadUrl(req.Config), req.AccessToken, nil) + h := md5.New() + h.Write([]byte(strings.Trim(req.Config, "/"))) + at = hex.EncodeToString(h.Sum(nil)) + + _, err = download(root, hc.makeDownloadUrl(req.Config), at, nil) } return err diff --git a/client/operation.go b/client/operation.go index b69076d..93839a4 100644 --- a/client/operation.go +++ b/client/operation.go @@ -142,14 +142,47 @@ func zipLogFiles(storageRoot string, req *shared.UploadRequest) (string, []strin return f.Name(), matches, nil } -func prepareProcessLaunch(storageRoot string, req *shared.StartProcessRequest) *procmeta { +func prepareProcessLaunch(storageRoot string, req *shared.StartProcessRequest) (*procmeta, error) { if len(req.Args) == 0 { - return nil + return nil, errors.New("args is empty") } + + if req.Version == "latest" { + entries, err := os.ReadDir(path.Join(storageRoot, req.Name)) + if err != nil { + return nil, err + } + + var latestTimestamp time.Time + var latestVersion string + for _, entry := range entries { + if !entry.IsDir() { + continue + } + + fi, err := entry.Info() + if err != nil { + return nil, err + } + createTime := fi.ModTime() + if latestTimestamp.Before(createTime) { + latestTimestamp = fi.ModTime() + latestVersion = fi.Name() + } + } + + if len(latestVersion) > 0 { + req.Version = latestVersion + } + } + verpath := path.Join(storageRoot, req.Name, req.Version) fi, err := os.Stat(verpath) + if err != nil { + return nil, err + } - if err == nil && fi.IsDir() { + if fi.IsDir() { exefile := "./" + path.Clean(strings.TrimPrefix(req.Args[0], "/")) os.Chmod(path.Join(verpath, exefile), 0777) @@ -158,7 +191,8 @@ func prepareProcessLaunch(storageRoot string, req *shared.StartProcessRequest) * for i, arg := range req.Args { expanded[i] = os.ExpandEnv(arg) } - exename := path.Join(path.Dir(exef), verpath, exefile) + + exename := path.Join(path.Dir(strings.ReplaceAll(exef, "\\", "/")), verpath, exefile) logger.Println("exefile :", exefile) logger.Println("verpath :", verpath) @@ -181,9 +215,9 @@ func prepareProcessLaunch(storageRoot string, req *shared.StartProcessRequest) * verpath: verpath, state: int32(protos.ProcessState_Stopped), stdin: stdin, - } + }, nil } - return nil + return nil, errors.New("not found") } func makeLogFilePrefix(meta *procmeta, index int) string { @@ -392,10 +426,11 @@ func (hc *houstonClient) launch(meta *procmeta) error { var errPrepareprocessLaunchFailed = errors.New("prepareProcessLaunch failed") func (hc *houstonClient) startChildProcess(req *shared.StartProcessRequest, op protos.OperationClient) error { - meta := prepareProcessLaunch(hc.config.StorageRoot, req) - if meta == nil { - return errPrepareprocessLaunchFailed + meta, err := prepareProcessLaunch(hc.config.StorageRoot, req) + if err != nil { + return err } + if err := hc.launch(meta); err != nil { return err }