client도 storageroot지원

This commit is contained in:
2023-06-14 14:16:47 +09:00
parent 46aedbe767
commit 279c9f47f0
7 changed files with 60 additions and 36 deletions

View File

@ -6,6 +6,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"io/fs"
"os" "os"
"os/exec" "os/exec"
"os/signal" "os/signal"
@ -31,6 +32,7 @@ import (
type clientConfig struct { type clientConfig struct {
GrpcAddress string `json:"grpc_server_address"` GrpcAddress string `json:"grpc_server_address"`
HttpAddress string `json:"http_server_address"` HttpAddress string `json:"http_server_address"`
StorageRoot string `json:"storage_path"`
} }
func loadClientConfig() (clientConfig, error) { func loadClientConfig() (clientConfig, error) {
@ -132,12 +134,13 @@ func unmarshal[T any](val *T, src map[string]string) {
} }
} }
func gatherDeployedPrograms(name string) []*protos.VersionAndArgs { func gatherDeployedPrograms(storageRoot, name string) []*protos.VersionAndArgs {
var rawvers []*protos.VersionAndArgs var rawvers []*protos.VersionAndArgs
if vers, err := os.ReadDir(name); err == nil { targetPath := path.Join(storageRoot, name)
if vers, err := os.ReadDir(targetPath); err == nil {
for _, ver := range vers { for _, ver := range vers {
if ver.IsDir() { if ver.IsDir() {
args := lastExecutionArgs(path.Join(name, ver.Name())) args := lastExecutionArgs(path.Join(targetPath, ver.Name()))
rawvers = append(rawvers, &protos.VersionAndArgs{ rawvers = append(rawvers, &protos.VersionAndArgs{
Version: ver.Name(), Version: ver.Name(),
Args: args, Args: args,
@ -205,13 +208,26 @@ func NewClient() (HoustonClient, error) {
return nil, err return nil, err
} }
sp, err := os.Stat(clientConfig.StorageRoot)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
err = os.MkdirAll(clientConfig.StorageRoot, 0775)
}
} else if !sp.IsDir() {
err = errors.New(clientConfig.StorageRoot + " is not directory")
}
if err != nil {
return nil, err
}
deploys := make(map[string][]*protos.VersionAndArgs) deploys := make(map[string][]*protos.VersionAndArgs)
if dirs, err := os.ReadDir("./"); err == nil { if dirs, err := os.ReadDir(clientConfig.StorageRoot); err == nil {
for _, dir := range dirs { for _, dir := range dirs {
if dir.IsDir() { if dir.IsDir() {
flagf := path.Join(dir.Name(), "@houston") flagf := path.Join(clientConfig.StorageRoot, dir.Name(), "@houston")
if _, err := os.Stat(flagf); !os.IsNotExist(err) { if _, err := os.Stat(flagf); !os.IsNotExist(err) {
deploys[dir.Name()] = gatherDeployedPrograms(dir.Name()) deploys[dir.Name()] = gatherDeployedPrograms(clientConfig.StorageRoot, dir.Name())
} }
} }
} }
@ -289,7 +305,7 @@ func NewClient() (HoustonClient, error) {
} }
} else { } else {
if err := hc.deploy(&dr); err == nil { if err := hc.deploy(&dr); err == nil {
prog := gatherDeployedPrograms(dr.Name) prog := gatherDeployedPrograms(hc.config.StorageRoot, dr.Name)
hc.deploys[dr.Name] = prog hc.deploys[dr.Name] = prog
op.Refresh(ctx, hc.makeOperationQueryRequest()) op.Refresh(ctx, hc.makeOperationQueryRequest())
} else { } else {
@ -302,7 +318,7 @@ func NewClient() (HoustonClient, error) {
unmarshal(&wr, resp.Args) unmarshal(&wr, resp.Args)
err := hc.withdraw(&wr) err := hc.withdraw(&wr)
if err == nil { if err == nil {
prog := gatherDeployedPrograms(wr.Name) prog := gatherDeployedPrograms(hc.config.StorageRoot, wr.Name)
if len(prog) == 0 { if len(prog) == 0 {
delete(hc.deploys, wr.Name) delete(hc.deploys, wr.Name)
} else { } else {

View File

@ -56,9 +56,6 @@ func download(dir string, urlpath string, accessToken string) (string, error) {
return filepath.ToSlash(out.Name()), nil return filepath.ToSlash(out.Name()), nil
} }
func UnzipTest(fname string) error {
return unzip(fname)
}
func unzip(fname string) error { func unzip(fname string) error {
archive, err := zip.OpenReader(fname) archive, err := zip.OpenReader(fname)
if err != nil { if err != nil {
@ -161,8 +158,9 @@ func (hc *houstonClient) prepareDeploy(name string, version string) (destPath st
// houston관리용임을 표시하기 위해 더미파일 생성 // houston관리용임을 표시하기 위해 더미파일 생성
defer func() { defer func() {
var flagf *os.File var flagf *os.File
if _, err := os.Stat(path.Join(name, "@houston")); os.IsNotExist(err) { markerPath := path.Join(hc.config.StorageRoot, name, "@houston")
flagf, err = os.Create(path.Join(name, "@houston")) if _, err := os.Stat(markerPath); os.IsNotExist(err) {
flagf, err = os.Create(markerPath)
if err != nil { if err != nil {
return return
} }
@ -171,7 +169,7 @@ func (hc *houstonClient) prepareDeploy(name string, version string) (destPath st
} }
}() }()
verpath := path.Join(name, version) verpath := path.Join(hc.config.StorageRoot, name, version)
if _, err := os.Stat(verpath); os.IsNotExist(err) { if _, err := os.Stat(verpath); os.IsNotExist(err) {
// 없네? 만들면 된다. // 없네? 만들면 된다.
err = os.MkdirAll(verpath, 0775) err = os.MkdirAll(verpath, 0775)
@ -293,7 +291,7 @@ func (hc *houstonClient) deploy(req *shared.DeployRequest) error {
err = untar(fname) err = untar(fname)
} }
if err == nil { if err == nil && len(req.Config) > 0 {
// config.json도 다운로드 // config.json도 다운로드
_, err = download(root, hc.makeDownloadUrl(req.Config), req.AccessToken) _, err = download(root, hc.makeDownloadUrl(req.Config), req.AccessToken)
} }
@ -302,7 +300,8 @@ func (hc *houstonClient) deploy(req *shared.DeployRequest) error {
} }
func (hc *houstonClient) withdraw(req *shared.WithdrawRequest) error { func (hc *houstonClient) withdraw(req *shared.WithdrawRequest) error {
fd, _ := os.Stat(path.Join(req.Name, req.Version)) targetPath := path.Join(hc.config.StorageRoot, req.Name, req.Version)
fd, _ := os.Stat(targetPath)
if fd != nil { if fd != nil {
if fd.IsDir() { if fd.IsDir() {
for _, running := range hc.childProcs { for _, running := range hc.childProcs {
@ -312,7 +311,7 @@ func (hc *houstonClient) withdraw(req *shared.WithdrawRequest) error {
} }
} }
return os.RemoveAll(path.Join(req.Name, req.Version)) return os.RemoveAll(targetPath)
} }
} }

View File

@ -74,8 +74,8 @@ func (hc *houstonClient) uploadZipLogFile(zipFile string, name string, version s
return nil return nil
} }
func zipLogFiles(req *shared.UploadRequest, start, except string) (string, []string, error) { func zipLogFiles(storageRoot string, req *shared.UploadRequest, start, except string) (string, []string, error) {
root := path.Join(req.Name, req.Version) root := path.Join(storageRoot, req.Name, req.Version)
matches, err := filepath.Glob(path.Join(root, req.Filter)) matches, err := filepath.Glob(path.Join(root, req.Filter))
if err != nil { if err != nil {
return "", nil, err return "", nil, err
@ -164,14 +164,14 @@ func zipLogFiles(req *shared.UploadRequest, start, except string) (string, []str
//return nil //return nil
} }
func prepareProcessLaunch(req *shared.StartProcessRequest) *procmeta { func prepareProcessLaunch(storageRoot string, req *shared.StartProcessRequest) *procmeta {
re := regexp.MustCompile(`[^\s"']+|"([^"]*)"|'([^']*)`) re := regexp.MustCompile(`[^\s"']+|"([^"]*)"|'([^']*)`)
args := re.FindAllString(req.Args, -1) args := re.FindAllString(req.Args, -1)
if len(args) == 0 { if len(args) == 0 {
return nil return nil
} }
verpath := path.Join(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 && fi.IsDir() { if err == nil && fi.IsDir() {
@ -258,7 +258,7 @@ func (hc *houstonClient) launch(meta *procmeta) error {
startFile := uploadStartFile startFile := uploadStartFile
uploadStartFile = nextFile uploadStartFile = nextFile
go func(startFile, nextFile string) { go func(startFile, nextFile string) {
zipFile, srcFiles, err := zipLogFiles(req, startFile, nextFile) zipFile, srcFiles, err := zipLogFiles(hc.config.StorageRoot, req, startFile, nextFile)
if err == nil && len(zipFile) > 0 && len(srcFiles) > 0 { if err == nil && len(zipFile) > 0 && len(srcFiles) > 0 {
if err = hc.uploadZipLogFile(zipFile, meta.name, meta.version); err == nil { if err = hc.uploadZipLogFile(zipFile, meta.name, meta.version); err == nil {
for _, oldf := range srcFiles { for _, oldf := range srcFiles {
@ -327,7 +327,7 @@ func (hc *houstonClient) startChildProcess(req *shared.StartProcessRequest, op p
logger.Println("startChildProcess :", *req) logger.Println("startChildProcess :", *req)
if req.Version == "latest" { if req.Version == "latest" {
// 최신 버전을 찾음 // 최신 버전을 찾음
latest, err := shared.FindLastestVersion(req.Name) latest, err := shared.FindLastestVersion(hc.config.StorageRoot, req.Name)
if err != nil { if err != nil {
return err return err
} }
@ -335,7 +335,7 @@ func (hc *houstonClient) startChildProcess(req *shared.StartProcessRequest, op p
req.Version = latest req.Version = latest
} }
meta := prepareProcessLaunch(req) meta := prepareProcessLaunch(hc.config.StorageRoot, req)
if meta == nil { if meta == nil {
return errPrepareprocessLaunchFailed return errPrepareprocessLaunchFailed
} }
@ -351,12 +351,12 @@ func (hc *houstonClient) startChildProcess(req *shared.StartProcessRequest, op p
} }
} }
if argfile, err := os.Create(path.Join(req.Name, "@args")); err == nil { if argfile, err := os.Create(path.Join(hc.config.StorageRoot, req.Name, "@args")); err == nil {
enc := json.NewEncoder(argfile) enc := json.NewEncoder(argfile)
enc.Encode(meta.cmd.Args) enc.Encode(meta.cmd.Args)
argfile.Close() argfile.Close()
} }
if argfile, err := os.Create(path.Join(req.Name, req.Version, "@args")); err == nil { if argfile, err := os.Create(path.Join(hc.config.StorageRoot, req.Name, req.Version, "@args")); err == nil {
enc := json.NewEncoder(argfile) enc := json.NewEncoder(argfile)
enc.Encode(meta.cmd.Args) enc.Encode(meta.cmd.Args)
argfile.Close() argfile.Close()
@ -373,7 +373,7 @@ var errNoRunningProcess = errors.New("no running processed")
func (hc *houstonClient) stopChildProcess(req *shared.StopProcessRequest, op protos.OperationClient) error { func (hc *houstonClient) stopChildProcess(req *shared.StopProcessRequest, op protos.OperationClient) error {
if req.Version == "latest" { if req.Version == "latest" {
// 최신 버전을 찾음 // 최신 버전을 찾음
latest, err := shared.FindLastestVersion(req.Name) latest, err := shared.FindLastestVersion(hc.config.StorageRoot, req.Name)
if err != nil { if err != nil {
return err return err
} }
@ -439,7 +439,7 @@ func (hc *houstonClient) stopChildProcess(req *shared.StopProcessRequest, op pro
func (hc *houstonClient) restartChildProcess(req *shared.RestartProcessRequest, op protos.OperationClient) error { func (hc *houstonClient) restartChildProcess(req *shared.RestartProcessRequest, op protos.OperationClient) error {
if req.Version == "latest" { if req.Version == "latest" {
// 최신 버전을 찾음 // 최신 버전을 찾음
latest, err := shared.FindLastestVersion(req.Name) latest, err := shared.FindLastestVersion(hc.config.StorageRoot, req.Name)
if err != nil { if err != nil {
return err return err
} }
@ -490,7 +490,7 @@ func (hc *houstonClient) restartChildProcess(req *shared.RestartProcessRequest,
func (hc *houstonClient) uploadFiles(req *shared.UploadRequest) error { func (hc *houstonClient) uploadFiles(req *shared.UploadRequest) error {
if req.Version == "latest" { if req.Version == "latest" {
// 최신 버전을 찾음 // 최신 버전을 찾음
latest, err := shared.FindLastestVersion(req.Name) latest, err := shared.FindLastestVersion(hc.config.StorageRoot, req.Name)
if err != nil { if err != nil {
return err return err
} }
@ -509,7 +509,7 @@ func (hc *houstonClient) uploadFiles(req *shared.UploadRequest) error {
// 실행 중이 아닌 폴더에서도 대상을 찾는다 // 실행 중이 아닌 폴더에서도 대상을 찾는다
// 전체 파일을 대상으로 // 전체 파일을 대상으로
zipFile, srcFiles, err := zipLogFiles(req, "", "") zipFile, srcFiles, err := zipLogFiles(hc.config.StorageRoot, req, "", "")
if err == nil && len(zipFile) > 0 && len(srcFiles) > 0 { if err == nil && len(zipFile) > 0 && len(srcFiles) > 0 {
if err = hc.uploadZipLogFile(zipFile, req.Name, req.Version); err == nil { if err = hc.uploadZipLogFile(zipFile, req.Name, req.Version); err == nil {
for _, oldf := range srcFiles { for _, oldf := range srcFiles {

View File

@ -2,7 +2,9 @@ package server
import ( import (
"encoding/json" "encoding/json"
"errors"
"io" "io"
"io/fs"
"net/http" "net/http"
"os" "os"
"path" "path"
@ -176,12 +178,17 @@ func (h *houstonHandler) Deploy(w http.ResponseWriter, r *http.Request) {
return return
} }
configPath := ""
if _, err := os.Stat(path.Join(h.deployPath, name, "config", "config.json")); err == nil || errors.Is(err, fs.ErrExist) {
configPath = path.Join("deploys", name, "config", "config.json")
}
h.Operation().Deploy(MakeDeployRequest( h.Operation().Deploy(MakeDeployRequest(
shared.DeployRequest{ shared.DeployRequest{
Name: name, Name: name,
Version: version, Version: version,
Url: path.Join("deploys", name, version, latestFilename), Url: path.Join("deploys", name, version, latestFilename),
Config: path.Join("deploys", name, "config", "config.json"), Config: configPath,
}, },
targets, targets,
)) ))
@ -338,7 +345,7 @@ func (h *houstonHandler) GetLogFileLinks(w http.ResponseWriter, r *http.Request)
} }
if version == "latest" { if version == "latest" {
version, _ = shared.FindLastestVersion(path.Join(h.downloadPath, name)) version, _ = shared.FindLastestVersion(h.downloadPath, name)
} }
root := path.Join(h.downloadPath, name, version) root := path.Join(h.downloadPath, name, version)

View File

@ -45,7 +45,7 @@ func NewHoustonHandler() HoustonServerWithHandler {
} }
func (h *houstonHandler) RegisterHandlers(serveMux *http.ServeMux, prefix string) error { func (h *houstonHandler) RegisterHandlers(serveMux *http.ServeMux, prefix string) error {
storagePath := loadServerConfig().StoragePath storagePath := loadServerConfig().StorageRoot
h.deployPath = path.Join(storagePath, "deploys") h.deployPath = path.Join(storagePath, "deploys")
h.downloadPath = path.Join(storagePath, "downloads") h.downloadPath = path.Join(storagePath, "downloads")

View File

@ -22,7 +22,7 @@ type HoustonServer interface {
type serverConfig struct { type serverConfig struct {
GrpcPort int `json:"grpc_port"` GrpcPort int `json:"grpc_port"`
StoragePath string `json:"storage_path"` StorageRoot string `json:"storage_path"`
} }
type DeployRequest struct { type DeployRequest struct {

View File

@ -3,6 +3,7 @@ package shared
import ( import (
"io/fs" "io/fs"
"os" "os"
"path"
"strings" "strings"
) )
@ -89,9 +90,10 @@ func CompareVersionString(lhs, rhs ParsedVersionString) int {
return len(lhs) - len(rhs) return len(lhs) - len(rhs)
} }
func FindLastestVersion(root string) (string, error) { func FindLastestVersion(storageRoot, name string) (string, error) {
// 최신 버전을 찾음 // 최신 버전을 찾음
entries, err := os.ReadDir(root) targetPath := path.Join(storageRoot, name)
entries, err := os.ReadDir(targetPath)
if err != nil { if err != nil {
return "", err return "", err
} }