|
@@ -2,20 +2,16 @@ package main
|
|
|
|
|
|
import (
|
|
import (
|
|
"encoding/json"
|
|
"encoding/json"
|
|
- "errors"
|
|
|
|
"fmt"
|
|
"fmt"
|
|
"github.com/flashmob/go-guerrilla"
|
|
"github.com/flashmob/go-guerrilla"
|
|
- "github.com/flashmob/go-guerrilla/backends"
|
|
|
|
"github.com/flashmob/go-guerrilla/log"
|
|
"github.com/flashmob/go-guerrilla/log"
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/cobra"
|
|
- "io/ioutil"
|
|
|
|
"os"
|
|
"os"
|
|
"os/exec"
|
|
"os/exec"
|
|
"os/signal"
|
|
"os/signal"
|
|
"strconv"
|
|
"strconv"
|
|
"strings"
|
|
"strings"
|
|
"syscall"
|
|
"syscall"
|
|
- "time"
|
|
|
|
)
|
|
)
|
|
|
|
|
|
const (
|
|
const (
|
|
@@ -33,29 +29,29 @@ var (
|
|
}
|
|
}
|
|
|
|
|
|
cmdConfig = CmdConfig{}
|
|
cmdConfig = CmdConfig{}
|
|
- signalChannel = make(chan os.Signal, 1) // for trapping SIG_HUP
|
|
|
|
|
|
+ signalChannel = make(chan os.Signal, 1) // for trapping SIGHUP and friends
|
|
mainlog log.Logger
|
|
mainlog log.Logger
|
|
|
|
+
|
|
|
|
+ d guerrilla.Daemon
|
|
)
|
|
)
|
|
|
|
|
|
func init() {
|
|
func init() {
|
|
// log to stderr on startup
|
|
// log to stderr on startup
|
|
- var logOpenError error
|
|
|
|
- if mainlog, logOpenError = log.GetLogger(log.OutputStderr.String()); logOpenError != nil {
|
|
|
|
- mainlog.WithError(logOpenError).Errorf("Failed creating a logger to %s", log.OutputStderr)
|
|
|
|
|
|
+ var err error
|
|
|
|
+ mainlog, err = log.GetLogger(log.OutputStderr.String())
|
|
|
|
+ if err != nil {
|
|
|
|
+ mainlog.WithError(err).Errorf("Failed creating a logger to %s", log.OutputStderr)
|
|
}
|
|
}
|
|
serveCmd.PersistentFlags().StringVarP(&configPath, "config", "c",
|
|
serveCmd.PersistentFlags().StringVarP(&configPath, "config", "c",
|
|
"goguerrilla.conf", "Path to the configuration file")
|
|
"goguerrilla.conf", "Path to the configuration file")
|
|
// intentionally didn't specify default pidFile; value from config is used if flag is empty
|
|
// intentionally didn't specify default pidFile; value from config is used if flag is empty
|
|
serveCmd.PersistentFlags().StringVarP(&pidFile, "pidFile", "p",
|
|
serveCmd.PersistentFlags().StringVarP(&pidFile, "pidFile", "p",
|
|
"", "Path to the pid file")
|
|
"", "Path to the pid file")
|
|
-
|
|
|
|
rootCmd.AddCommand(serveCmd)
|
|
rootCmd.AddCommand(serveCmd)
|
|
}
|
|
}
|
|
|
|
|
|
-func sigHandler(app guerrilla.Guerrilla) {
|
|
|
|
-
|
|
|
|
- signal.Notify(
|
|
|
|
- signalChannel,
|
|
|
|
|
|
+func sigHandler() {
|
|
|
|
+ signal.Notify(signalChannel,
|
|
syscall.SIGHUP,
|
|
syscall.SIGHUP,
|
|
syscall.SIGTERM,
|
|
syscall.SIGTERM,
|
|
syscall.SIGQUIT,
|
|
syscall.SIGQUIT,
|
|
@@ -63,27 +59,14 @@ func sigHandler(app guerrilla.Guerrilla) {
|
|
syscall.SIGKILL,
|
|
syscall.SIGKILL,
|
|
syscall.SIGUSR1,
|
|
syscall.SIGUSR1,
|
|
)
|
|
)
|
|
-
|
|
|
|
for sig := range signalChannel {
|
|
for sig := range signalChannel {
|
|
if sig == syscall.SIGHUP {
|
|
if sig == syscall.SIGHUP {
|
|
- // save old config & load in new one
|
|
|
|
- oldConfig := cmdConfig
|
|
|
|
- newConfig := CmdConfig{}
|
|
|
|
- err := readConfig(configPath, pidFile, &newConfig)
|
|
|
|
- if err != nil {
|
|
|
|
- // new config will not be applied
|
|
|
|
- mainlog.WithError(err).Error("Error while ReadConfig (reload)")
|
|
|
|
- } else {
|
|
|
|
- cmdConfig = newConfig
|
|
|
|
- mainlog.Infof("Configuration was reloaded at %s", guerrilla.ConfigLoadTime)
|
|
|
|
- cmdConfig.emitChangeEvents(&oldConfig, app)
|
|
|
|
- }
|
|
|
|
|
|
+ d.ReloadConfigFile(configPath)
|
|
} else if sig == syscall.SIGUSR1 {
|
|
} else if sig == syscall.SIGUSR1 {
|
|
- // re-open logs
|
|
|
|
- cmdConfig.EmitLogReopenEvents(app)
|
|
|
|
|
|
+ d.ReopenLogs()
|
|
} else if sig == syscall.SIGTERM || sig == syscall.SIGQUIT || sig == syscall.SIGINT {
|
|
} else if sig == syscall.SIGTERM || sig == syscall.SIGQUIT || sig == syscall.SIGINT {
|
|
mainlog.Infof("Shutdown signal caught")
|
|
mainlog.Infof("Shutdown signal caught")
|
|
- app.Shutdown()
|
|
|
|
|
|
+ d.Shutdown()
|
|
mainlog.Infof("Shutdown completed, exiting.")
|
|
mainlog.Infof("Shutdown completed, exiting.")
|
|
return
|
|
return
|
|
} else {
|
|
} else {
|
|
@@ -95,8 +78,8 @@ func sigHandler(app guerrilla.Guerrilla) {
|
|
|
|
|
|
func serve(cmd *cobra.Command, args []string) {
|
|
func serve(cmd *cobra.Command, args []string) {
|
|
logVersion()
|
|
logVersion()
|
|
-
|
|
|
|
- err := readConfig(configPath, pidFile, &cmdConfig)
|
|
|
|
|
|
+ d = guerrilla.Daemon{Logger: mainlog}
|
|
|
|
+ err := readConfig(configPath, pidFile)
|
|
if err != nil {
|
|
if err != nil {
|
|
mainlog.WithError(err).Fatal("Error while reading config")
|
|
mainlog.WithError(err).Fatal("Error while reading config")
|
|
}
|
|
}
|
|
@@ -116,53 +99,12 @@ func serve(cmd *cobra.Command, args []string) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- // Backend setup
|
|
|
|
- var backend backends.Backend
|
|
|
|
- backend, err = backends.New(cmdConfig.BackendConfig, mainlog)
|
|
|
|
- if err != nil {
|
|
|
|
- mainlog.WithError(err).Fatalf("Error while loading the backend")
|
|
|
|
- }
|
|
|
|
- /*
|
|
|
|
- // add our custom processor to the backend
|
|
|
|
- backends.Service.AddProcessor("MailDir", maildiranasaurus.MaildirProcessor)
|
|
|
|
- config := guerrilla.AppConfig {
|
|
|
|
- LogFile: log.OutputStderr,
|
|
|
|
- LogLevel: "info",
|
|
|
|
- AllowedHosts: []string{"example.com"},
|
|
|
|
- PidFile: "./pidfile.pid",
|
|
|
|
- Servers: []guerrilla.ServerConfig{
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- */
|
|
|
|
-
|
|
|
|
- // g := guerrilla.NewSMTPD{config: cmdConfig}
|
|
|
|
-
|
|
|
|
- app, err := guerrilla.New(&cmdConfig.AppConfig, backend, mainlog)
|
|
|
|
|
|
+ err = d.Start()
|
|
if err != nil {
|
|
if err != nil {
|
|
mainlog.WithError(err).Error("Error(s) when creating new server(s)")
|
|
mainlog.WithError(err).Error("Error(s) when creating new server(s)")
|
|
|
|
+ os.Exit(1)
|
|
}
|
|
}
|
|
-
|
|
|
|
- // start the app
|
|
|
|
- err = app.Start()
|
|
|
|
- if err != nil {
|
|
|
|
- mainlog.WithError(err).Error("Error(s) when starting server(s)")
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Write out our PID
|
|
|
|
- writePid(cmdConfig.PidFile)
|
|
|
|
- // ...and write out our pid whenever the file name changes in the config
|
|
|
|
- app.Subscribe(guerrilla.EventConfigPidFile, func(ac *guerrilla.AppConfig) {
|
|
|
|
- writePid(ac.PidFile)
|
|
|
|
- })
|
|
|
|
- // change the logger from stdrerr to one from config
|
|
|
|
- mainlog.Infof("main log configured to %s", cmdConfig.LogFile)
|
|
|
|
- var logOpenError error
|
|
|
|
- if mainlog, logOpenError = log.GetLogger(cmdConfig.LogFile); logOpenError != nil {
|
|
|
|
- mainlog.WithError(logOpenError).Errorf("Failed changing to a custom logger [%s]", cmdConfig.LogFile)
|
|
|
|
- }
|
|
|
|
- app.SetLogger(mainlog)
|
|
|
|
- sigHandler(app)
|
|
|
|
|
|
+ sigHandler()
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
@@ -190,29 +132,22 @@ func (c *CmdConfig) emitChangeEvents(oldConfig *CmdConfig, app guerrilla.Guerril
|
|
}
|
|
}
|
|
|
|
|
|
// ReadConfig which should be called at startup, or when a SIG_HUP is caught
|
|
// ReadConfig which should be called at startup, or when a SIG_HUP is caught
|
|
-func readConfig(path string, pidFile string, config *CmdConfig) error {
|
|
|
|
|
|
+func readConfig(path string, pidFile string) error {
|
|
// Load in the config.
|
|
// Load in the config.
|
|
// Note here is the only place we can make an exception to the
|
|
// Note here is the only place we can make an exception to the
|
|
// "treat config values as immutable". For example, here the
|
|
// "treat config values as immutable". For example, here the
|
|
// command line flags can override config values
|
|
// command line flags can override config values
|
|
- data, err := ioutil.ReadFile(path)
|
|
|
|
|
|
+ appConfig, err := d.LoadConfig(path)
|
|
if err != nil {
|
|
if err != nil {
|
|
return fmt.Errorf("Could not read config file: %s", err.Error())
|
|
return fmt.Errorf("Could not read config file: %s", err.Error())
|
|
}
|
|
}
|
|
- if err := config.load(data); err != nil {
|
|
|
|
- return err
|
|
|
|
- }
|
|
|
|
// override config pidFile with with flag from the command line
|
|
// override config pidFile with with flag from the command line
|
|
if len(pidFile) > 0 {
|
|
if len(pidFile) > 0 {
|
|
- config.AppConfig.PidFile = pidFile
|
|
|
|
- } else if len(config.AppConfig.PidFile) == 0 {
|
|
|
|
- config.AppConfig.PidFile = defaultPidFile
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if len(config.AllowedHosts) == 0 {
|
|
|
|
- return errors.New("Empty `allowed_hosts` is not allowed")
|
|
|
|
|
|
+ appConfig.PidFile = pidFile
|
|
|
|
+ } else if len(appConfig.PidFile) == 0 {
|
|
|
|
+ appConfig.PidFile = defaultPidFile
|
|
}
|
|
}
|
|
- guerrilla.ConfigLoadTime = time.Now()
|
|
|
|
|
|
+ d.SetConfig(appConfig)
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|
|
@@ -228,20 +163,3 @@ func getFileLimit() int {
|
|
}
|
|
}
|
|
return limit
|
|
return limit
|
|
}
|
|
}
|
|
-
|
|
|
|
-func writePid(pidFile string) {
|
|
|
|
- if len(pidFile) > 0 {
|
|
|
|
- if f, err := os.Create(pidFile); err == nil {
|
|
|
|
- defer f.Close()
|
|
|
|
- pid := os.Getpid()
|
|
|
|
- if _, err := f.WriteString(fmt.Sprintf("%d", pid)); err == nil {
|
|
|
|
- f.Sync()
|
|
|
|
- mainlog.Infof("(serve.go) pid_file (%s) written with pid:%v", pidFile, pid)
|
|
|
|
- } else {
|
|
|
|
- mainlog.WithError(err).Fatalf("Error while writing pidFile (%s)", pidFile)
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- mainlog.WithError(err).Fatalf("Error while creating pidFile (%s)", pidFile)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-}
|
|
|