func main() { conf, err := config.LoadFromEnvironment() fatalize(err) sshConf, err := conf.ReadMap("ssh_monitor") fatalize(err) sshKeyPath, err := sshConf.ReadString("ssh_key") fatalize(err) sshUser, err := sshConf.ReadString("ssh_user") fatalize(err) sshAddr, err := sshConf.ReadString("ssh_address") fatalize(err) monitorPortStr, err := sshConf.ReadString("port") fatalize(err) if sshKeyPath == "" || sshUser == "" || sshAddr == "" || monitorPortStr == "" { logging.DefaultLogger.NoFields().Fatalln("Must set all of ssh_key, ssh_user, ssh_address and port") } monitorPort, err := strconv.Atoi(monitorPortStr) fatalize(err) privateKey, err := ioutil.ReadFile(sshKeyPath) if err != nil { logging.DefaultLogger.WithErrorAndFields(err, logrus.Fields{ "key": sshKeyPath, }).Fatalln("Could not read SSH private key") } authSigner, err := ssh.ParsePrivateKey(privateKey) if err != nil { logging.DefaultLogger.WithErrorAndFields(err, logrus.Fields{ "key": sshKeyPath, }).Fatalln("Could not parse SSH private key") } clientConf := &ssh.ClientConfig{ User: sshUser, Auth: []ssh.AuthMethod{ ssh.PublicKeys(authSigner), }, } http.HandleFunc("/_status", func(w http.ResponseWriter, r *http.Request) { c, err := ssh.Dial("tcp", sshAddr, clientConf) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) logging.DefaultLogger.WithErrorAndFields(err, logrus.Fields{ "user": sshUser, "key": sshKeyPath, "address": sshAddr, }).Errorln("Could not connect to SSHd") return } defer c.Close() logging.DefaultLogger.NoFields().Debugln("Connected to SSHd successfully") _, _ = w.Write([]byte("ok")) }) if err := http.ListenAndServe(fmt.Sprintf(":%d", monitorPort), nil); err != nil { logging.DefaultLogger.WithError(err).Fatalln("Monitor HTTP server crashed") } }
func main() { config, err := config.LoadFromEnvironment() fatalize(err) runitMonCfg, err := config.ReadMap("runit_monitor") fatalize(err) childDurationStr, err := config.ReadString("child_duration") fatalize(err) if childDurationStr == "" { childDurationStr = "10s" } childDuration, err := time.ParseDuration(childDurationStr) fatalize(err) toMonitor, err := runitMonCfg.ReadString("to_monitor") fatalize(err) runitDir, err := runitMonCfg.ReadString("runit_root") fatalize(err) if runitDir == "" { runitDir = runit.DefaultBuilder.RunitRoot } statusPortStr, err := runitMonCfg.ReadString("port") fatalize(err) if statusPortStr == "" { logging.DefaultLogger.NoFields().Fatalln("Should have assigned a port under the runit_monitor config") } statusPort, err := strconv.Atoi(statusPortStr) fatalize(err) service := &runit.Service{Name: toMonitor, Path: filepath.Join(runitDir, toMonitor)} http.HandleFunc("/_status", func(w http.ResponseWriter, r *http.Request) { statResult, err := runit.DefaultSV.Stat(service) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) } else { statusString := fmt.Sprintf(`{"status": "%s", "time": "%s"}`, statResult.ChildStatus, statResult.ChildTime) if statResult.ChildTime > childDuration && statResult.ChildStatus == runit.STATUS_RUN { w.Header().Set("Content-Type", "application/json") fmt.Fprintf(w, statusString) } else { http.Error(w, statusString, http.StatusServiceUnavailable) } } }) if err = http.ListenAndServe(fmt.Sprintf(":%d", statusPort), nil); err != nil { logging.DefaultLogger.WithError(err).Fatalln("Service crashed") } }