Compare commits

...

3 Commits

7 changed files with 86 additions and 82 deletions

View File

@@ -10,6 +10,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"slices" "slices"
"strings"
"syscall" "syscall"
"time" "time"
@@ -49,12 +50,12 @@ func Init2Hook(cs *corestate.CoreState, x *app.AppX) {
if err := x.Config.LoadEnv(); err != nil { if err := x.Config.LoadEnv(); err != nil {
x.Log.Fatalf("env load error: %s", err) x.Log.Fatalf("env load error: %s", err)
} }
cs.NodePath = x.Config.Env.NodePath cs.NodePath = *x.Config.Env.NodePath
if cfgPath := x.Config.CMDLine.Run.ConfigPath; cfgPath != "" { if cfgPath := x.Config.CMDLine.Run.ConfigPath; cfgPath != "" {
x.Config.Env.ConfigPath = cfgPath x.Config.Env.ConfigPath = &cfgPath
} }
if err := x.Config.LoadConf(x.Config.Env.ConfigPath); err != nil { if err := x.Config.LoadConf(*x.Config.Env.ConfigPath); err != nil {
x.Log.Fatalf("conf load error: %s", err) x.Log.Fatalf("conf load error: %s", err)
} }
} }
@@ -77,10 +78,7 @@ func Init3Hook(cs *corestate.CoreState, x *app.AppX) {
} }
func Init4Hook(cs *corestate.CoreState, x *app.AppX) { func Init4Hook(cs *corestate.CoreState, x *app.AppX) {
if x.Config.Env.ParentStagePID != os.Getpid() { if *x.Config.Env.ParentStagePID != os.Getpid() {
if !slices.Contains(x.Config.Conf.DisableWarnings, "--WNonStdTmpDir") && os.TempDir() != "/tmp" {
x.Log.Printf("%s: %s", logs.PrintWarn(), "Non-standard value specified for temporary directory")
}
// still pre-init stage // still pre-init stage
runDir, err := run_manager.Create(cs.UUID32) runDir, err := run_manager.Create(cs.UUID32)
if err != nil { if err != nil {
@@ -174,6 +172,16 @@ func Init5Hook(cs *corestate.CoreState, x *app.AppX) {
} }
func Init6Hook(cs *corestate.CoreState, x *app.AppX) { func Init6Hook(cs *corestate.CoreState, x *app.AppX) {
if !slices.Contains(*x.Config.Conf.DisableWarnings, "--WNonStdTmpDir") && os.TempDir() != "/tmp" {
x.Log.Printf("%s: %s", logs.PrintWarn(), "Non-standard value specified for temporary directory")
}
if strings.Contains(*x.Config.Conf.Log.OutPath, `%tmp%`) {
replaced := strings.ReplaceAll(*x.Config.Conf.Log.OutPath, "%tmp%", filepath.Clean(run_manager.RuntimeDir()))
x.Config.Conf.Log.OutPath = &replaced
}
}
func Init7Hook(cs *corestate.CoreState, x *app.AppX) {
cs.Stage = corestate.StageReady cs.Stage = corestate.StageReady
x.Log.SetPrefix(logs.SetGreen(fmt.Sprintf("(%s) ", cs.Stage))) x.Log.SetPrefix(logs.SetGreen(fmt.Sprintf("(%s) ", cs.Stage)))
@@ -185,3 +193,27 @@ func Init6Hook(cs *corestate.CoreState, x *app.AppX) {
} }
*x.SLog = *newSlog *x.SLog = *newSlog
} }
// repl := map[string]string{
// "tmp": filepath.Clean(run_manager.RuntimeDir()),
// }
// re := regexp.MustCompile(`%(\w+)%`)
// result := re.ReplaceAllStringFunc(x.Config.Conf.Log.OutPath, func(match string) string {
// sub := re.FindStringSubmatch(match)
// if len(sub) < 2 {
// return match
// }
// key := sub[1]
// if val, ok := repl[key]; ok {
// return val
// }
// return match
// })
// if strings.Contains(x.Config.Conf.Log.OutPath, "%tmp%") {
// relPath := strings.TrimPrefix(result, filepath.Clean(run_manager.RuntimeDir()))
// if err := run_manager.SetDir(relPath); err != nil {
// _ = run_manager.Clean()
// x.Log.Fatalf("Unexpected failure: %s", err.Error())
// }
// }

View File

@@ -31,7 +31,7 @@ func Run(cmd *cobra.Command, args []string) {
nodeApp.InitialHooks( nodeApp.InitialHooks(
Init0Hook, Init1Hook, Init2Hook, Init0Hook, Init1Hook, Init2Hook,
Init3Hook, Init4Hook, Init5Hook, Init3Hook, Init4Hook, Init5Hook,
Init6Hook, Init6Hook, Init7Hook,
) )
nodeApp.Run(RunHook) nodeApp.Run(RunHook)
@@ -82,7 +82,7 @@ func RunHook(ctx context.Context, cs *corestate.CoreState, x *app.AppX) error {
}) })
srv := &http.Server{ srv := &http.Server{
Addr: x.Config.Conf.HTTPServer.Address, Addr: *x.Config.Conf.HTTPServer.Address,
Handler: r, Handler: r,
ErrorLog: log.New(&logs.SlogWriter{ ErrorLog: log.New(&logs.SlogWriter{
Logger: x.SLog, Logger: x.SLog,
@@ -107,22 +107,22 @@ func RunHook(ctx context.Context, cs *corestate.CoreState, x *app.AppX) error {
go func() { go func() {
defer utils.CatchPanicWithCancel(cancelMain) defer utils.CatchPanicWithCancel(cancelMain)
if x.Config.Conf.TLS.TlsEnabled { if *x.Config.Conf.TLS.TlsEnabled {
listener, err := net.Listen("tcp", fmt.Sprintf("%s:%s", x.Config.Conf.HTTPServer.Address, x.Config.Conf.HTTPServer.Port)) listener, err := net.Listen("tcp", fmt.Sprintf("%s:%s", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port))
if err != nil { if err != nil {
x.Log.Printf("%s: Failed to start TLS listener: %s", logs.PrintError(), err.Error()) x.Log.Printf("%s: Failed to start TLS listener: %s", logs.PrintError(), err.Error())
cancelMain() cancelMain()
return return
} }
x.Log.Printf("Serving on %s port %s with TLS... (https://%s%s)", x.Config.Conf.HTTPServer.Address, x.Config.Conf.HTTPServer.Port, fmt.Sprintf("%s:%s", x.Config.Conf.HTTPServer.Address, x.Config.Conf.HTTPServer.Port), config.ComDirRoute) x.Log.Printf("Serving on %s port %s with TLS... (https://%s%s)", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port, fmt.Sprintf("%s:%s", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port), config.ComDirRoute)
limitedListener := netutil.LimitListener(listener, 100) limitedListener := netutil.LimitListener(listener, 100)
if err := srv.ServeTLS(limitedListener, x.Config.Conf.TLS.CertFile, x.Config.Conf.TLS.KeyFile); err != nil && !errors.Is(err, http.ErrServerClosed) { if err := srv.ServeTLS(limitedListener, *x.Config.Conf.TLS.CertFile, *x.Config.Conf.TLS.KeyFile); err != nil && !errors.Is(err, http.ErrServerClosed) {
x.Log.Printf("%s: Failed to start HTTPS server: %s", logs.PrintError(), err.Error()) x.Log.Printf("%s: Failed to start HTTPS server: %s", logs.PrintError(), err.Error())
cancelMain() cancelMain()
} }
} else { } else {
x.Log.Printf("Serving on %s port %s... (http://%s%s)", x.Config.Conf.HTTPServer.Address, x.Config.Conf.HTTPServer.Port, fmt.Sprintf("%s:%s", x.Config.Conf.HTTPServer.Address, x.Config.Conf.HTTPServer.Port), config.ComDirRoute) x.Log.Printf("Serving on %s port %s... (http://%s%s)", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port, fmt.Sprintf("%s:%s", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port), config.ComDirRoute)
listener, err := net.Listen("tcp", fmt.Sprintf("%s:%s", x.Config.Conf.HTTPServer.Address, x.Config.Conf.HTTPServer.Port)) listener, err := net.Listen("tcp", fmt.Sprintf("%s:%s", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port))
if err != nil { if err != nil {
x.Log.Printf("%s: Failed to start listener: %s", logs.PrintError(), err.Error()) x.Log.Printf("%s: Failed to start listener: %s", logs.PrintError(), err.Error())
cancelMain() cancelMain()
@@ -136,7 +136,7 @@ func RunHook(ctx context.Context, cs *corestate.CoreState, x *app.AppX) error {
} }
}() }()
if x.Config.Conf.Updates.UpdatesEnabled { if *x.Config.Conf.Updates.UpdatesEnabled {
go func() { go func() {
defer utils.CatchPanicWithCancel(cancelMain) defer utils.CatchPanicWithCancel(cancelMain)
updated := update.NewUpdater(&update.UpdaterInit{ updated := update.NewUpdater(&update.UpdaterInit{
@@ -157,7 +157,7 @@ func RunHook(ctx context.Context, cs *corestate.CoreState, x *app.AppX) error {
x.Log.Printf("Update completed successfully") x.Log.Printf("Update completed successfully")
} }
} }
time.Sleep(x.Config.Conf.Updates.CheckInterval) time.Sleep(*x.Config.Conf.Updates.CheckInterval)
} }
}() }()
} }

View File

@@ -134,7 +134,7 @@ func (u *Updater) GetCurrentVersion() (Version, Branch, error) {
} }
func (u *Updater) GetLatestVersion(updateBranch Branch) (Version, Branch, error) { func (u *Updater) GetLatestVersion(updateBranch Branch) (Version, Branch, error) {
repoURL := u.x.Config.Conf.Updates.RepositoryURL repoURL := *u.x.Config.Conf.Updates.RepositoryURL
if repoURL == "" { if repoURL == "" {
u.x.Log.Printf("Failed to get latest version: %s", "RepositoryURL is empty in config") u.x.Log.Printf("Failed to get latest version: %s", "RepositoryURL is empty in config")
return "", "", errors.New("repository URL is empty") return "", "", errors.New("repository URL is empty")
@@ -192,7 +192,7 @@ func (u *Updater) CkeckUpdates() (IsNewUpdate, error) {
} }
func (u *Updater) Update() error { func (u *Updater) Update() error {
if !u.x.Config.Conf.Updates.UpdatesEnabled { if !*u.x.Config.Conf.Updates.UpdatesEnabled {
return errors.New("updates are disabled in config, skipping update") return errors.New("updates are disabled in config, skipping update")
} }
@@ -212,7 +212,7 @@ func (u *Updater) Update() error {
} }
updateArchiveName := fmt.Sprintf("%s.v%s-%s", config.UpdateArchiveName, latestVersion, latestBranch) updateArchiveName := fmt.Sprintf("%s.v%s-%s", config.UpdateArchiveName, latestVersion, latestBranch)
updateDest := fmt.Sprintf("%s/%s.%s", u.x.Config.Conf.Updates.RepositoryURL, updateArchiveName, "tar.gz") updateDest := fmt.Sprintf("%s/%s.%s", *u.x.Config.Conf.Updates.RepositoryURL, updateArchiveName, "tar.gz")
resp, err := http.Get(updateDest) resp, err := http.Get(updateDest)
if err != nil { if err != nil {
@@ -278,7 +278,7 @@ func (u *Updater) Update() error {
func (u *Updater) InstallAndRestart() error { func (u *Updater) InstallAndRestart() error {
nodePath := u.x.Config.Env.NodePath nodePath := *u.x.Config.Env.NodePath
if nodePath == "" { if nodePath == "" {
return errors.New("GS_NODE_PATH environment variable is not set") return errors.New("GS_NODE_PATH environment variable is not set")
} }

View File

@@ -18,45 +18,45 @@ type Compositor struct {
} }
type Conf struct { type Conf struct {
Mode string `mapstructure:"mode"` Mode *string `mapstructure:"mode"`
ComDir string `mapstructure:"com_dir"` ComDir *string `mapstructure:"com_dir"`
HTTPServer HTTPServer `mapstructure:"http_server"` HTTPServer *HTTPServer `mapstructure:"http_server"`
TLS TLS `mapstructure:"tls"` TLS *TLS `mapstructure:"tls"`
Updates Updates `mapstructure:"updates"` Updates *Updates `mapstructure:"updates"`
Log Log `mapstructure:"log"` Log *Log `mapstructure:"log"`
DisableWarnings []string `mapstructure:"disable_warnings"` DisableWarnings *[]string `mapstructure:"disable_warnings"`
} }
type HTTPServer struct { type HTTPServer struct {
Address string `mapstructure:"address"` Address *string `mapstructure:"address"`
Port string `mapstructure:"port"` Port *string `mapstructure:"port"`
Timeout time.Duration `mapstructure:"timeout"` Timeout *time.Duration `mapstructure:"timeout"`
IdleTimeout time.Duration `mapstructure:"idle_timeout"` IdleTimeout *time.Duration `mapstructure:"idle_timeout"`
} }
type TLS struct { type TLS struct {
TlsEnabled bool `mapstructure:"enabled"` TlsEnabled *bool `mapstructure:"enabled"`
CertFile string `mapstructure:"cert_file"` CertFile *string `mapstructure:"cert_file"`
KeyFile string `mapstructure:"key_file"` KeyFile *string `mapstructure:"key_file"`
} }
type Updates struct { type Updates struct {
UpdatesEnabled bool `mapstructure:"enabled"` UpdatesEnabled *bool `mapstructure:"enabled"`
CheckInterval time.Duration `mapstructure:"check_interval"` CheckInterval *time.Duration `mapstructure:"check_interval"`
RepositoryURL string `mapstructure:"repository_url"` RepositoryURL *string `mapstructure:"repository_url"`
WantedVersion string `mapstructure:"wanted_version"` WantedVersion *string `mapstructure:"wanted_version"`
} }
type Log struct { type Log struct {
Level string `mapstructure:"level"` Level *string `mapstructure:"level"`
OutPath string `mapstructure:"out_path"` OutPath *string `mapstructure:"out_path"`
} }
// ConfigEnv structure for environment variables // ConfigEnv structure for environment variables
type Env struct { type Env struct {
ConfigPath string `mapstructure:"config_path"` ConfigPath *string `mapstructure:"config_path"`
NodePath string `mapstructure:"node_path"` NodePath *string `mapstructure:"node_path"`
ParentStagePID int `mapstructure:"parent_pid"` ParentStagePID *int `mapstructure:"parent_pid"`
} }
type CMDLine struct { type CMDLine struct {

View File

@@ -10,10 +10,7 @@ import (
"log/slog" "log/slog"
"os" "os"
"path/filepath" "path/filepath"
"regexp"
"strings"
"github.com/akyaiy/GoSally-mvp/internal/core/run_manager"
"github.com/akyaiy/GoSally-mvp/internal/engine/config" "github.com/akyaiy/GoSally-mvp/internal/engine/config"
"gopkg.in/natefinch/lumberjack.v2" "gopkg.in/natefinch/lumberjack.v2"
) )
@@ -32,11 +29,11 @@ func (w *SlogWriter) Write(p []byte) (n int, err error) {
} }
// SetupLogger initializes and returns a logger based on the provided environment. // SetupLogger initializes and returns a logger based on the provided environment.
func SetupLogger(o config.Log) (*slog.Logger, error) { func SetupLogger(o *config.Log) (*slog.Logger, error) {
var handlerOpts = slog.HandlerOptions{} var handlerOpts = slog.HandlerOptions{}
var writer io.Writer = os.Stdout var writer io.Writer = os.Stdout
switch o.Level { switch *o.Level {
case "debug": case "debug":
GlobalLevel = slog.LevelDebug GlobalLevel = slog.LevelDebug
handlerOpts.Level = slog.LevelDebug handlerOpts.Level = slog.LevelDebug
@@ -48,32 +45,9 @@ func SetupLogger(o config.Log) (*slog.Logger, error) {
handlerOpts.Level = slog.LevelInfo handlerOpts.Level = slog.LevelInfo
} }
if o.OutPath != "" { if *o.OutPath != "" {
repl := map[string]string{
"tmp": filepath.Clean(run_manager.RuntimeDir()),
}
re := regexp.MustCompile(`%(\w+)%`)
result := re.ReplaceAllStringFunc(o.OutPath, func(match string) string {
sub := re.FindStringSubmatch(match)
if len(sub) < 2 {
return match
}
key := sub[1]
if val, ok := repl[key]; ok {
return val
}
return match
})
if strings.Contains(o.OutPath, "%tmp%") {
relPath := strings.TrimPrefix(result, filepath.Clean(run_manager.RuntimeDir()))
if err := run_manager.SetDir(relPath); err != nil {
return nil, err
}
}
logFile := &lumberjack.Logger{ logFile := &lumberjack.Logger{
Filename: filepath.Join(result, "event.log"), Filename: filepath.Join(*o.OutPath, "event.log"),
MaxSize: 10, MaxSize: 10,
MaxBackups: 5, MaxBackups: 5,
MaxAge: 28, MaxAge: 28,

View File

@@ -12,8 +12,6 @@ import (
lua "github.com/yuin/gopher-lua" lua "github.com/yuin/gopher-lua"
) )
func (h *HandlerV1) handleLUA(path string, req *rpc.RPCRequest) *rpc.RPCResponse { func (h *HandlerV1) handleLUA(path string, req *rpc.RPCRequest) *rpc.RPCResponse {
L := lua.NewState() L := lua.NewState()
defer L.Close() defer L.Close()
@@ -70,7 +68,7 @@ func (h *HandlerV1) handleLUA(path string, req *rpc.RPCRequest) *rpc.RPCResponse
L.SetGlobal("Log", logTable) L.SetGlobal("Log", logTable)
prep := filepath.Join(h.x.Config.Conf.ComDir, "_prepare.lua") prep := filepath.Join(*h.x.Config.Conf.ComDir, "_prepare.lua")
if _, err := os.Stat(prep); err == nil { if _, err := os.Stat(prep); err == nil {
if err := L.DoFile(prep); err != nil { if err := L.DoFile(prep); err != nil {
return rpc.NewError(rpc.ErrInternalError, err.Error(), req.ID) return rpc.NewError(rpc.ErrInternalError, err.Error(), req.ID)

View File

@@ -16,7 +16,7 @@ func (h *HandlerV1) resolveMethodPath(method string) (string, error) {
parts := strings.Split(method, ">") parts := strings.Split(method, ">")
relPath := filepath.Join(parts...) + ".lua" relPath := filepath.Join(parts...) + ".lua"
fullPath := filepath.Join(h.x.Config.Conf.ComDir, relPath) fullPath := filepath.Join(*h.x.Config.Conf.ComDir, relPath)
if _, err := os.Stat(fullPath); os.IsNotExist(err) { if _, err := os.Stat(fullPath); os.IsNotExist(err) {
return "", errors.New(rpc.ErrMethodNotFoundS) return "", errors.New(rpc.ErrMethodNotFoundS)