gowiki/pkg/cmd/cmd.go
2018-09-14 00:14:49 +02:00

203 lines
4.3 KiB
Go

// Copyright (C) 2017 Marius Schellenberger
package cmd
import (
"errors"
"git.giftfish.de/ston1th/godrop"
"github.com/urfave/cli"
stdlog "log"
"net"
"os"
"os/signal"
"syscall"
"time"
"git.giftfish.de/ston1th/gowiki/pkg/log"
"git.giftfish.de/ston1th/gowiki/pkg/server"
)
const (
blevePath = "bleve"
defDataDir = "/var/lib/gowiki"
defListen = "127.0.0.1:8090"
defLogFile = "gowiki.log"
defRunUser = "wiki"
defRunGroup = "wiki"
)
func initServer(conf serverConfig) (err error) {
dropCfg := godrop.Config{
User: conf.User,
Group: conf.Group,
Foreground: conf.Foreground,
}
err = godrop.Drop(dropCfg, func() (net.Listener, error) {
return net.Listen("tcp", conf.ListenAddr)
})
if err != nil {
return
}
if err = os.Chdir(conf.DataDir); err != nil {
return
}
log.NewLogger(conf.LogFile)
l, err := godrop.GetListener()
if err != nil {
return
}
srv := server.NewHTTPServer(l, conf.Version, conf.DataDir+"/"+blevePath, conf.SecureCookie)
err = srv.Start()
if err != nil {
return
}
log.Println("gowiki started")
sigs := make(chan os.Signal)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
sig := <-sigs
log.Println("caught " + sig.String())
go func() {
time.Sleep(time.Second * 20)
//TODO error needed?
log.Fatal(errors.New("stop timed out: killing"))
}()
err = srv.Stop()
if err != nil {
log.Println(err)
}
log.Println("gowiki stopped")
return
}
var (
verbose bool
conf serverConfig
)
func Run(version string) {
app := cli.NewApp()
app.Name = "gowiki"
app.Usage = "a simple wiki engine"
app.Version = version
app.Commands = []cli.Command{
{
Name: "server",
Usage: "start gowiki server",
Flags: defaultFlags(serverFlags()),
Action: func(c *cli.Context) error {
conf.Version = app.Version
if err := initServer(conf); err != nil {
stdlog.Fatal("server: ", err)
}
return nil
},
},
{
Name: "dump",
Usage: "create a json dump of all articles in the data directory (dump is written to stdout) gowiki needs to be stopped",
Flags: defaultFlags(dumpRestoreFlags()),
Action: func(c *cli.Context) error {
if err := os.Chdir(conf.DataDir); err != nil {
stdlog.Fatal("dump: ", err)
}
//TODO
//if err := db.Dump(blevePath, verbose); err != nil {
// stdlog.Fatal("dump: ", err)
//}
return nil
},
},
{
Name: "restore",
Usage: "restore a json dump to the data directory (dump is read from stdin) gowiki needs to be stopped",
Flags: defaultFlags(dumpRestoreFlags()),
Action: func(c *cli.Context) error {
if err := os.Chdir(conf.DataDir); err != nil {
stdlog.Fatal("restore: ", err)
}
//TODO
//if err := db.Restore(blevePath, verbose); err != nil {
// stdlog.Fatal("restore: ", err)
//}
return nil
},
},
}
app.Run(os.Args)
}
type serverConfig struct {
DataDir string
User string
Group string
ListenAddr string
LogFile string
Version string
Foreground bool
SecureCookie bool
}
func serverFlags() []cli.Flag {
return []cli.Flag{
cli.StringFlag{
Name: "user, u",
Value: defRunUser,
Usage: "drop privileges to user",
Destination: &conf.User,
},
cli.StringFlag{
Name: "group, g",
Value: defRunGroup,
Usage: "drop privileges to group",
Destination: &conf.Group,
},
cli.StringFlag{
Name: "listen, l",
Value: defListen,
Usage: "listening <address>:<port>",
Destination: &conf.ListenAddr,
},
cli.StringFlag{
Name: "log",
Value: defLogFile,
Usage: "log file (leave empty for stdout, this only works in combination with -f)",
Destination: &conf.LogFile,
},
cli.BoolFlag{
Name: "foreground, f",
Usage: "do not fork into the background",
Destination: &conf.Foreground,
},
cli.BoolFlag{
Name: "secure, s",
Usage: "enable secure cookie",
Destination: &conf.SecureCookie,
},
}
}
func dumpRestoreFlags() []cli.Flag {
return []cli.Flag{
cli.BoolFlag{
Name: "verbose, v",
Usage: "enable verbose mode",
Destination: &verbose,
},
}
}
func defaultFlags(f []cli.Flag) []cli.Flag {
return append([]cli.Flag{
cli.StringFlag{
Name: "data, d",
Value: defDataDir,
Usage: "data directory",
Destination: &conf.DataDir,
},
}, f...)
}