client도 storageroot지원
This commit is contained in:
@ -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 {
|
||||||
|
|||||||
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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")
|
||||||
|
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user