func showStatus(s *rest.ServiceInfo) { d := time.Since(s.TimeStamp) // for printing second resolution is sufficient d -= d % time.Second fmt.Printf("%-20s %-10s %10s %s\n", s.Name, util.Status(s), util.FormatDuration(d), s.Status) }
// update must be called with AppLock held. func (i *InfoPanel) update() { s, e := i.app.GetItem(i.name) if i.info == s && i.err == e { return } i.info = s i.err = e words := []string{"[ESC] Main", "[H] Help"} i.titlebar.SetCenter("Details for " + i.name) if s == nil { if i.err != nil { i.statusbar.SetStatus(fmt.Sprintf( "No data: %v", i.err)) i.statusbar.SetFail() } else { i.statusbar.SetStatus("Loading...") i.statusbar.SetNormal() } i.text.SetLines(nil) i.keybar.SetKeys(words) return } i.statusbar.SetStatus("") if !s.Enabled { i.statusbar.SetNormal() } else if s.Failed { i.statusbar.SetFail() } else if s.Running { i.statusbar.SetGood() } else { i.statusbar.SetWarn() } lines := make([]string, 0, 8) lines = append(lines, fmt.Sprintf("%13s %s", "Name:", s.Name)) lines = append(lines, fmt.Sprintf("%13s %s", "Description:", s.Description)) lines = append(lines, fmt.Sprintf("%13s %s", "Status:", util.Status(s))) lines = append(lines, fmt.Sprintf("%13s %v", "Since:", s.TimeStamp)) lines = append(lines, fmt.Sprintf("%13s %s", "Detail:", s.Status)) l := fmt.Sprintf("%13s", "Provides:") for _, p := range s.Provides { l = l + fmt.Sprintf(" %s", p) } lines = append(lines, l) l = fmt.Sprintf("%13s", "Depends:") for _, p := range s.Depends { l = l + fmt.Sprintf(" %s", p) } lines = append(lines, l) l = fmt.Sprintf("%13s", "Conflicts:") for _, p := range s.Conflicts { l = l + fmt.Sprintf(" %s", p) } lines = append(lines, l) i.text.SetLines(lines) words = append(words, "[L] Log") if !s.Enabled { words = append(words, "[E] Enable") } else { words = append(words, "[D] Disable") if s.Failed { words = append(words, "[C] Clear") } words = append(words, "[R] Restart") } i.keybar.SetKeys(words) }
// update is called to update content, e.g. in response to Draw() or // as part of another update. It is called with the AppLock held. func (m *MainPanel) update() { items, err := m.app.GetItems() m.items = items // preserve selected item if sel := m.selected; sel != nil { m.selected = nil cury := 0 for _, item := range m.items { if item.Name == sel.Name { m.selected = item m.cury = cury } cury++ } } if err != nil { m.statusbar.SetFail() m.statusbar.SetStatus(fmt.Sprintf("Cannot load items: %v", err)) m.lines = []string{} m.styles = []topsl.Style{} return } lines := make([]string, 0, len(m.items)) styles := make([]topsl.Style, 0, len(m.items)) m.ndisabled = 0 m.nfailed = 0 m.nstopped = 0 m.nrunning = 0 m.height = 0 m.width = 0 for _, info := range items { d := time.Since(info.TimeStamp) d -= d % time.Second line := fmt.Sprintf("%-20s %-10s %10s %-10s", info.Name, util.Status(info), util.FormatDuration(d), info.Status) if len(line) > m.width { m.width = len(line) } m.height++ lines = append(lines, line) var style topsl.Style if !info.Enabled { style = topsl.StyleText m.ndisabled++ } else if info.Failed { style = topsl.StyleError m.nfailed++ } else if !info.Running { style = topsl.StyleWarn m.nstopped++ } else { style = topsl.StyleGood m.nrunning++ } styles = append(styles, style) } m.lines = lines m.styles = styles m.statusbar.SetStatus(fmt.Sprintf( "%6d Services %6d Faulted %6d Running %6d Standby %6d Disabled", len(m.items), m.nfailed, m.nrunning, m.nstopped, m.ndisabled)) if m.nfailed > 0 { m.statusbar.SetFail() } else if m.nstopped > 0 { m.statusbar.SetWarn() } else if m.nrunning > 0 { m.statusbar.SetGood() } else { m.statusbar.SetNormal() } words := []string{"[Q] Quit", "[H] Help"} if item := m.selected; item != nil { words = append(words, "[I] Info") words = append(words, "[L] Log") if !item.Enabled { words = append(words, "[E] Enable") } else { words = append(words, "[D] Disable") if item.Failed { words = append(words, "[C] Clear") } words = append(words, "[R] Restart") } } else { words = append(words, "[L] Log") } m.keybar.SetKeys(words) }
func main() { user := "" pass := "" logfile := "" cafile := "" capath := "" insecure := false flag.StringVar(&addr, "addr", addr, "govisor address") flag.StringVar(&user, "user", user, "user name for authentication") flag.StringVar(&pass, "pass", pass, "password for authentication") flag.StringVar(&cafile, "cacert", cafile, "CA certificate file") flag.StringVar(&capath, "capath", capath, "CA certificates directory") flag.StringVar(&logfile, "debuglog", logfile, "debug log file") flag.BoolVar(&insecure, "insecure", insecure, "allow insecure TLS connections") flag.Parse() var dlog *log.Logger if logfile != "" { f, e := os.Create(logfile) if e == nil { dlog = log.New(f, "DEBUG:", log.LstdFlags) log.SetOutput(f) } } roots := x509.NewCertPool() if cafile == "" && capath == "" { roots = nil } else { if cafile != "" { if e := loadCertFile(roots, cafile); e != nil { fatal("Unable to load cert file", e) } } if capath != "" { if e := loadCertPath(roots, capath); e != nil { fatal("Unable to load cert path", e) } } } u, e := url.Parse(addr) if e != nil { fatal("Bad address", e) } tcfg := &tls.Config{ RootCAs: roots, ServerName: u.Host, InsecureSkipVerify: insecure, } tran := &http.Transport{ TLSClientConfig: tcfg, } client := rest.NewClient(tran, addr) if user != "" || pass != "" { client.SetAuth(user, pass) } args := flag.Args() if len(args) == 0 { if e := doUI(client, addr, dlog); e != nil { // status by default args = []string{"status"} } else { return } } switch args[0] { case "services": if len(args) != 1 { usage() } s, e := client.Services() if e != nil { fatal("Error", e) } sort.Strings(s) for _, name := range s { fmt.Println(name) } case "enable": if len(args) != 2 { usage() } e := client.EnableService(args[1]) if e != nil { fatal("Error", e) } case "disable": if len(args) != 2 { usage() } e := client.DisableService(args[1]) if e != nil { fatal("Error", e) } case "restart": if len(args) != 2 { usage() } e := client.RestartService(args[1]) if e != nil { fatal("Error", e) } case "clear": if len(args) != 2 { usage() } e := client.ClearService(args[1]) if e != nil { fatal("Error", e) } case "log": loginfo := &rest.LogInfo{} switch len(args) { case 0: usage() case 1: loginfo, e = client.GetLog("") case 2: loginfo, e = client.GetLog(args[1]) } if e != nil { fatal("Error", e) } for _, line := range loginfo.Records { fmt.Printf("%s %s\n", line.Time.Format(time.StampMilli), line.Text) } case "info": if len(args) != 2 { usage() } s, e := client.GetService(args[1]) if e != nil { fatal("Failed", e) } fmt.Printf("Name: %s\n", s.Name) fmt.Printf("Desc: %s\n", s.Description) fmt.Printf("Status: %s\n", util.Status(s)) fmt.Printf("Since: %v\n", time.Now().Sub(s.TimeStamp)) fmt.Printf("Detail: %s\n", s.Status) fmt.Printf("Provides: ") for _, p := range s.Provides { fmt.Printf(" %s", p) } fmt.Printf("\n") fmt.Printf("Depends: ") for _, p := range s.Depends { fmt.Printf(" %s", p) } fmt.Printf("\n") fmt.Printf("Conflicts: ") for _, p := range s.Conflicts { fmt.Printf(" %s", p) } fmt.Printf("\n") case "status": names := args[1:] var e error if len(names) == 0 { names, e = client.Services() if e != nil { fatal("Error", e) } } if len(names) == 0 { // No services? return } infos := []*rest.ServiceInfo{} for _, n := range names { info, e := client.GetService(n) if e == nil { infos = append(infos, info) } else { fatal("Error", e) } } util.SortServices(infos) for _, info := range infos { showStatus(info) } case "ui": if e := doUI(client, addr, dlog); e != nil { fatal("Error", e) } } }