autorun 추가
This commit is contained in:
@ -23,6 +23,7 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"repositories.action2quare.com/ayo/gocommon"
|
"repositories.action2quare.com/ayo/gocommon"
|
||||||
|
"repositories.action2quare.com/ayo/gocommon/flagx"
|
||||||
"repositories.action2quare.com/ayo/gocommon/logger"
|
"repositories.action2quare.com/ayo/gocommon/logger"
|
||||||
"repositories.action2quare.com/ayo/houston/shared"
|
"repositories.action2quare.com/ayo/houston/shared"
|
||||||
"repositories.action2quare.com/ayo/houston/shared/protos"
|
"repositories.action2quare.com/ayo/houston/shared/protos"
|
||||||
@ -31,14 +32,23 @@ import (
|
|||||||
"google.golang.org/grpc/credentials/insecure"
|
"google.golang.org/grpc/credentials/insecure"
|
||||||
)
|
)
|
||||||
|
|
||||||
type clientConfig struct {
|
type runcommand struct {
|
||||||
GrpcAddress string `json:"grpc_server_address"`
|
Exec string `json:"exec"`
|
||||||
HttpAddress string `json:"http_server_address"`
|
Args []string `json:"args"`
|
||||||
StorageRoot string `json:"storage_path"`
|
Version string `json:"version"`
|
||||||
MetricNamespace string `json:"metric_namespace"`
|
|
||||||
ConstLabels map[string]string `json:"metric_const_labels"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
func loadClientConfig() (clientConfig, error) {
|
||||||
configFile, err := os.Open("config.json")
|
configFile, err := os.Open("config.json")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -295,6 +305,7 @@ func NewClient(standalone bool) (HoustonClient, error) {
|
|||||||
operationChan := make(chan *protos.OperationQueryResponse, 10)
|
operationChan := make(chan *protos.OperationQueryResponse, 10)
|
||||||
hc.wg.Add(1)
|
hc.wg.Add(1)
|
||||||
|
|
||||||
|
// autorun 처리
|
||||||
go func() {
|
go func() {
|
||||||
defer hc.wg.Done()
|
defer hc.wg.Done()
|
||||||
|
|
||||||
@ -316,6 +327,32 @@ func NewClient(standalone bool) (HoustonClient, error) {
|
|||||||
|
|
||||||
case newClient := <-hc.clientChan:
|
case newClient := <-hc.clientChan:
|
||||||
op = protos.NewOperationClient(newClient)
|
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:
|
case exited := <-exitChan:
|
||||||
var newprocs []*procmeta
|
var newprocs []*procmeta
|
||||||
|
|||||||
@ -3,6 +3,8 @@ package client
|
|||||||
import (
|
import (
|
||||||
"archive/tar"
|
"archive/tar"
|
||||||
"archive/zip"
|
"archive/zip"
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -58,6 +60,7 @@ func download(dir string, urlpath string, accessToken string, cb func(int64, int
|
|||||||
|
|
||||||
req, _ := http.NewRequest("GET", urlpath, nil)
|
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("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)
|
resp, err := http.DefaultClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@ -328,7 +331,10 @@ func (hc *houstonClient) deploy(req *shared.DeployRequest, cb func(*protos.Deplo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// verpath에 배포 시작
|
// 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{
|
prog := protos.DeployingProgress{
|
||||||
State: "download",
|
State: "download",
|
||||||
Progress: written,
|
Progress: written,
|
||||||
@ -356,7 +362,11 @@ func (hc *houstonClient) deploy(req *shared.DeployRequest, cb func(*protos.Deplo
|
|||||||
|
|
||||||
if err == nil && len(req.Config) > 0 {
|
if err == nil && len(req.Config) > 0 {
|
||||||
// config.json도 다운로드
|
// 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
|
return err
|
||||||
|
|||||||
@ -142,14 +142,47 @@ func zipLogFiles(storageRoot string, req *shared.UploadRequest) (string, []strin
|
|||||||
return f.Name(), matches, nil
|
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 {
|
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)
|
verpath := path.Join(storageRoot, req.Name, req.Version)
|
||||||
fi, err := os.Stat(verpath)
|
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], "/"))
|
exefile := "./" + path.Clean(strings.TrimPrefix(req.Args[0], "/"))
|
||||||
os.Chmod(path.Join(verpath, exefile), 0777)
|
os.Chmod(path.Join(verpath, exefile), 0777)
|
||||||
|
|
||||||
@ -158,7 +191,8 @@ func prepareProcessLaunch(storageRoot string, req *shared.StartProcessRequest) *
|
|||||||
for i, arg := range req.Args {
|
for i, arg := range req.Args {
|
||||||
expanded[i] = os.ExpandEnv(arg)
|
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("exefile :", exefile)
|
||||||
logger.Println("verpath :", verpath)
|
logger.Println("verpath :", verpath)
|
||||||
@ -181,9 +215,9 @@ func prepareProcessLaunch(storageRoot string, req *shared.StartProcessRequest) *
|
|||||||
verpath: verpath,
|
verpath: verpath,
|
||||||
state: int32(protos.ProcessState_Stopped),
|
state: int32(protos.ProcessState_Stopped),
|
||||||
stdin: stdin,
|
stdin: stdin,
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
return nil
|
return nil, errors.New("not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeLogFilePrefix(meta *procmeta, index int) string {
|
func makeLogFilePrefix(meta *procmeta, index int) string {
|
||||||
@ -392,10 +426,11 @@ func (hc *houstonClient) launch(meta *procmeta) error {
|
|||||||
var errPrepareprocessLaunchFailed = errors.New("prepareProcessLaunch failed")
|
var errPrepareprocessLaunchFailed = errors.New("prepareProcessLaunch failed")
|
||||||
|
|
||||||
func (hc *houstonClient) startChildProcess(req *shared.StartProcessRequest, op protos.OperationClient) error {
|
func (hc *houstonClient) startChildProcess(req *shared.StartProcessRequest, op protos.OperationClient) error {
|
||||||
meta := prepareProcessLaunch(hc.config.StorageRoot, req)
|
meta, err := prepareProcessLaunch(hc.config.StorageRoot, req)
|
||||||
if meta == nil {
|
if err != nil {
|
||||||
return errPrepareprocessLaunchFailed
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := hc.launch(meta); err != nil {
|
if err := hc.launch(meta); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user