func main() { cli_app := cli.NewApp() cli_app.Name = AppName cli_app.Version = AppVersion app := &Application{ App: cli_app, } cfg := config.GetDefaultConfig() app.Flags = []cli.Flag{ cli.StringFlag{ Name: "level, l", Value: "WARN", Usage: "change log level", }, } app.Before = func(c *cli.Context) error { var err error cfgfile := filepath.Join(os.Getenv("HOME"), ".voyager") if util.FileExists(cfgfile) { err = cfg.LoadYaml(cfgfile) if err != nil { log.Errorf("load config %s: %s", cfgfile, err) return err } } app.Cfg = cfg gologging.SetLogLevel(c.String("level")) app.Ctx = context.Background() return nil } ping := cli.Command{ Name: "ping", Usage: "ping rpc", Description: PingDescription, Flags: PingFlags, Action: app.Ping, } app.Commands = []cli.Command{ ping, } app.Run(os.Args) }
func (app *Application) Setup(c *cli.Context) { log_level := c.String("log-level") verbose := c.Bool("verbose") service_dir := c.String("service-dir") active_dir := c.String("active-service-dir") log_dir := c.String("log-dir") enable := c.Bool("enable") disable := c.Bool("disable") run := c.String("run") log_run := c.String("log-run") script := c.StringSlice("script") restart := c.Bool("restart") uid := c.Int("uid") gid := c.Int("gid") args := c.Args() name := args.First() if verbose { gologging.SetLogLevel("trace") } if log_level != "" { gologging.SetLogLevel(log_level) } // template does nothing // make the runit api locally for these flags to function rcfg := runit.DefaultRunitConfig() if service_dir != "" { rcfg.ServiceDir = service_dir } if active_dir != "" { rcfg.ActiveDir = active_dir } rapi := runit.NewRunit(rcfg) if name == "" { log.Errorf("service name is required") return } if run == "" { log.Errorf("run command is required") return } if log_run != "" { log.Warnf("specifying log-run is not supported, argument is ignored") } log.Tracef("setup %s", name) lcfg := runit.DefaultLoggingConfig() if log_dir == "" { lcfg.Directory = filepath.Join(runit.DefaultLogDir, name) } else { lcfg.Directory = log_dir } var exec string if uid != 0 || gid != 0 { exec = fmt.Sprintf("chpst -u %d:%d %s", uid, gid, run) } else { exec = run } if enable { disable = false } // log_run is not supported cfg := &runit.ServiceConfig{ Name: name, Exec: exec, Logging: lcfg, Disabled: disable, Activated: true, RedirectStderr: true, } copts := &runit.CreateOptions{ Force: true, Restart: restart, Script: script, } err := rapi.Create2(cfg, copts) if err != nil { log.Warnf("Create2 %s: %s", name, err) } }
func main() { c := cli.NewApp() c.Name = "runitcmd" c.Version = "0.0.1" c.Usage = "manage runit services" app := &Application{ App: c, } app.Flags = []cli.Flag{ cli.StringFlag{ Name: "config, c", Usage: "override configuration file", }, cli.StringFlag{ Name: "level, l", Value: "WARN", Usage: "change log level", }, cli.StringFlag{ Name: "service-dir", Usage: "change service dir", }, cli.StringFlag{ Name: "active-dir", Usage: "change active service dir", }, } app.Before = func(c *cli.Context) error { gologging.SetLogLevel(c.String("level")) config_file := c.String("config") config_files := []string{ "/etc/runitcmd.yaml", } user_config := filepath.Join(os.Getenv("HOME"), ".runitcmd.yaml") if config_file == "" { config_files = append(config_files, user_config) } else { config_files = []string{config_file} } app.Conf = GetDefaultConfig() for _, config_file := range config_files { _, err := os.Stat(config_file) if err != nil && os.IsNotExist(err) { continue } log.Tracef("Loading %s", config_file) err = app.Conf.LoadYaml(config_file) if err != nil { log.Warnf("load %s: %s", config_file, err) } } if app.Conf.Sudo { current_user, err := user.Current() if err == nil && current_user.Uid != "0" { log.Tracef("sudo uid:%s", current_user.Uid) argv0, err := exec.LookPath(os.Args[0]) if err != nil { return err } sudo, err := exec.LookPath("sudo") if err != nil { log.Errorf("no sudo: %s", err) os.Exit(1) } args := []string{} args = append(args, sudo) args = append(args, "--") args = append(args, os.Args...) args[2] = argv0 log.Tracef("sudo:%s args:%s", sudo, args) if err := syscall.Exec(args[0], args, os.Environ()); err != nil { log.Errorf("exec: %s", err) os.Exit(1) } // never reached panic("what") os.Exit(0) } } rcfg := runit.DefaultRunitConfig() service_dir := c.String("service-dir") active_dir := c.String("active-dir") if service_dir == "" { rcfg.ServiceDir = app.Conf.ServiceDir } else { rcfg.ServiceDir = service_dir } if active_dir == "" { rcfg.ActiveDir = app.Conf.ActiveDir } else { rcfg.ActiveDir = active_dir } app.Runit = runit.NewRunit(rcfg) return nil } app.Commands = []cli.Command{ initList(app), initCreate(app), initSetup(app), initApply(app), initStatus(app), initImport(app), initExport(app), // more commands makeCommand("delete", app.Delete), makeCommand("activate", app.Activate), makeCommand("deactivate", app.Deactivate), makeCommand("enable", app.Enable), makeCommand("disable", app.Disable), makeCommand("reset", app.Reset), // commands makeCommand("up", app.Up), makeCommand("down", app.Down), makeCommand("pause", app.Pause), makeCommand("cont", app.Cont), makeCommand("hup", app.Cont), makeCommand("alarm", app.Cont), makeCommand("interrupt", app.Cont), makeCommand("quit", app.Quit), makeCommand("usr1", app.Usr1), makeCommand("usr2", app.Usr2), makeCommand("term", app.Term), makeCommand("kill", app.Kill), // lsb makeCommand("start", app.Start), makeCommand("stop", app.Stop), makeCommand("reload", app.Reload), makeCommand("restart", app.Restart), makeCommand("shutdown", app.Shutdown), } app.Run(os.Args) }
func main() { cfg := config.GetDefaultConfig() flag.StringVar(&cfg.Http.BindAddr, "bind", cfg.Http.BindAddr, "bind address") flag.StringVar(&cfg.LogLevel, "log", cfg.LogLevel, "log level") flag.Parse() var err error cfgfile := filepath.Join(os.Getenv("HOME"), ".voyager") if util.FileExists(cfgfile) { err = cfg.LoadYaml(cfgfile) if err != nil { log.Errorf("load config %s: %s", cfgfile, err) return } } if cfg.LogLevel != "" { gologging.SetLogLevel(cfg.LogLevel) } gologging.SetLogLevels(cfg.LogLevels) if log.IsTrace() { cfg.PrintYaml() } if cfg.AutoRestart { devrestarter.Init() } if util.FileExists(cfg.CacheDir) == false { err = os.MkdirAll(cfg.CacheDir, 0755) if err != nil { log.Errorf("cache dir error %s: %s", cfg.CacheDir, err) return } } if cfg.AutoUpgrade { gw := reload_git.NewGitWatch(".", "master") gw.Interval = 30 gw.OnChange = func(dir, branch, lhash, rhash string) error { err = Shell("git", "pull") if err != nil { log.Warnf("git pull error: %s", err) } err = Shell("go", "install", "-v", "./...") if err != nil { log.Warnf("go install error: %s", err) } return err } err := gw.Start() if err != nil { log.Errorf("starting git watch %s", err) return } } cache := cache.NewFileCache(cfg.CacheDir) if err != nil { log.Errorf("cache error: %s %s", cfg.CacheDir, err) return } // core components handlerFactory := handler.NewHandlerFactory() pathLoader := handler.NewFilesystemPathLoader() layoutResolver := layout.NewLayoutResolver() voyLoader := voy.NewVoyLoader() root_template := template.New("root") template.Must(root_template.New("footer").Parse(footerTemplate)) md := metadata.Pairs("request-secret", cfg.Rpc.Secret) ctx := context.Background() ctx = metadata.NewContext(ctx, md) // the HTTP server log.Infof("starting HTTP server at %s", cfg.Http.BindAddr) opts := &http_api.Options{ Networks: cfg.ACL, } srv := http_api.NewServer(cfg.Http.BindAddr, opts) srv.Conf = cfg srv.Cache = cache srv.Factory = handlerFactory srv.PathLoader = pathLoader srv.Layout = layoutResolver srv.VoyFile = voyLoader srv.Ctx = ctx srv.Template = root_template srv.Dashboard = handler.NewDashboardHandler() srv.Dashboard.Ctx = ctx srv.Dashboard.VoyFile = voyLoader srv.Dashboard.Username = cfg.Username go func() { err = srv.Start() if err != nil { log.Errorf("starting server %s", err) return } }() // the RPC server log.Infof("starting RPC server at %s", cfg.Rpc.BindAddr) lis, err := net.Listen("tcp", cfg.Rpc.BindAddr) if err != nil { util.ExitIfError(err, "grpc listen %s: %s", cfg.Rpc.BindAddr, err) } http2_serv := grpc.NewServer() http2_api := api.MakeApi(cfg) http2_api.WithHandlerFactory(handlerFactory) http2_api.PathLoader = pathLoader http2_api.Layout = layoutResolver http2_api.VoyFile = voyLoader http2_api.ServerName = cfg.ServerName vapi.RegisterVApiServer(http2_serv, http2_api) log.Infof("finished initializing") log.Infof("%s", cfg.StartupBanner) err = http2_serv.Serve(lis) if err != nil { util.ExitIfError(err, "grpc serve %s: %s", cfg.Rpc.BindAddr, err) } }