isle/go/cmd/entrypoint/main.go

111 lines
2.4 KiB
Go

package main
import (
"context"
"fmt"
"os"
"os/signal"
"path/filepath"
"syscall"
"github.com/adrg/xdg"
"dev.mediocregopher.com/mediocre-go-lib.git/mctx"
"dev.mediocregopher.com/mediocre-go-lib.git/mlog"
)
// The purpose of this binary is to act as the entrypoint of the isle
// process. It processes the command-line arguments which are passed in, and
// then passes execution along to an appropriate binary housed in AppDir/bin
// (usually a bash script, which is more versatile than a go program).
func getAppDirPath() string {
appDirPath := os.Getenv("APPDIR")
if appDirPath == "" {
appDirPath = "."
}
return appDirPath
}
func getRPCSocketDirPath() string {
path, err := firstExistingDir(
"/run",
"/var/run",
"/tmp",
"/dev/shm",
)
if err != nil {
panic(fmt.Sprintf("Failed to find directory for RPC socket: %v", err))
}
return path
}
// RUNTIME_DIRECTORY/STATE_DIRECTORY are used by the systemd service in
// conjunction with the RuntimeDirectory/StateDirectory directives.
var (
envAppDirPath = getAppDirPath()
envRuntimeDirPath = envOr(
"RUNTIME_DIRECTORY",
func() string { return filepath.Join(xdg.RuntimeDir, "isle") },
)
envStateDirPath = envOr(
"STATE_DIRECTORY",
func() string { return filepath.Join(xdg.StateHome, "isle") },
)
envBinDirPath = filepath.Join(envAppDirPath, "bin")
envSocketPath = envOr(
"ISLE_SOCKET_PATH",
func() string {
return filepath.Join(getRPCSocketDirPath(), "isle-daemon.sock")
},
)
)
func binPath(name string) string {
return filepath.Join(envBinDirPath, name)
}
func main() {
logger := mlog.NewLogger(&mlog.LoggerOpts{
MessageHandler: newLogMsgHandler(),
MaxLevel: mlog.LevelInfo.Int(),
})
defer logger.Close()
ctx, cancel := context.WithCancel(context.Background())
signalCh := make(chan os.Signal, 2)
signal.Notify(signalCh, syscall.SIGINT, syscall.SIGTERM)
go func() {
sig := <-signalCh
cancel()
ctx := mctx.Annotate(ctx, "signal", sig.String())
logger.Info(ctx, "got signal, exiting gracefully")
sig = <-signalCh
ctx = mctx.Annotate(ctx, "signal", sig.String())
logger.FatalString(ctx, "second signal received, force quitting, there may be zombie children left behind, good luck!")
}()
err := subCmdCtx{
args: os.Args[1:],
ctx: ctx,
logger: logger,
}.doSubCmd(
subCmdAdmin,
subCmdDaemon,
subCmdGarage,
subCmdHosts,
subCmdNebula,
subCmdVersion,
)
if err != nil {
logger.Fatal(ctx, "error running command", err)
}
}