mirror of
https://github.com/postmannen/ctrl.git
synced 2025-03-05 14:56:49 +00:00
added tui req handler
This commit is contained in:
parent
28cb3a6509
commit
7092265d8c
4 changed files with 68 additions and 13 deletions
|
@ -26,13 +26,16 @@ type processes struct {
|
|||
metrics *metrics
|
||||
// Waitgroup to keep track of all the processes started
|
||||
wg sync.WaitGroup
|
||||
// tui
|
||||
tui *tui
|
||||
}
|
||||
|
||||
// newProcesses will prepare and return a *processes which
|
||||
// is map containing all the currently running processes.
|
||||
func newProcesses(ctx context.Context, metrics *metrics) *processes {
|
||||
func newProcesses(ctx context.Context, metrics *metrics, tui *tui) *processes {
|
||||
p := processes{
|
||||
active: *newProcsMap(),
|
||||
tui: tui,
|
||||
}
|
||||
|
||||
// Prepare the parent context for the subscribers.
|
||||
|
|
32
requests.go
32
requests.go
|
@ -86,6 +86,8 @@ const (
|
|||
// The data field is a slice of strings where the first string
|
||||
// value should be the command, and the following the arguments.
|
||||
REQToConsole Method = "REQToConsole"
|
||||
// REQTuiToConsole
|
||||
REQTuiToConsole Method = "REQTuiToConsole"
|
||||
// Send text logging to some host by appending the output to a
|
||||
// file, if the file do not exist we create it.
|
||||
// A file with the full subject+hostName will be created on
|
||||
|
@ -163,6 +165,9 @@ func (m Method) GetMethodsAvailable() MethodsAvailable {
|
|||
REQToConsole: methodREQToConsole{
|
||||
commandOrEvent: EventACK,
|
||||
},
|
||||
REQTuiToConsole: methodREQTuiToConsole{
|
||||
commandOrEvent: EventACK,
|
||||
},
|
||||
REQToFileAppend: methodREQToFileAppend{
|
||||
commandOrEvent: EventACK,
|
||||
},
|
||||
|
@ -212,7 +217,7 @@ func (m Method) GetMethodsAvailable() MethodsAvailable {
|
|||
// the Stew client for knowing what of the req types are generally
|
||||
// used as reply methods.
|
||||
func (m Method) GetReplyMethods() []Method {
|
||||
rm := []Method{REQToConsole, REQToFile, REQToFileAppend, REQToSocket}
|
||||
rm := []Method{REQToConsole, REQTuiToConsole, REQCliCommand, REQCliCommandCont, REQToFile, REQToFileAppend, REQToSocket}
|
||||
return rm
|
||||
}
|
||||
|
||||
|
@ -1285,7 +1290,7 @@ func (m methodREQToConsole) getKind() CommandOrEvent {
|
|||
func (m methodREQToConsole) handler(proc process, message Message, node string) ([]byte, error) {
|
||||
|
||||
for _, v := range message.Data {
|
||||
fmt.Fprintf(os.Stdout, "%v", string(v))
|
||||
fmt.Fprintf(os.Stdout, "%v", v)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
|
@ -1296,6 +1301,29 @@ func (m methodREQToConsole) handler(proc process, message Message, node string)
|
|||
|
||||
// ---
|
||||
|
||||
type methodREQTuiToConsole struct {
|
||||
commandOrEvent CommandOrEvent
|
||||
}
|
||||
|
||||
func (m methodREQTuiToConsole) getKind() CommandOrEvent {
|
||||
return m.commandOrEvent
|
||||
}
|
||||
|
||||
// Handler to write directly to console.
|
||||
func (m methodREQTuiToConsole) handler(proc process, message Message, node string) ([]byte, error) {
|
||||
|
||||
if proc.processes.tui.toConsoleCh != nil {
|
||||
proc.processes.tui.toConsoleCh <- message.Data
|
||||
} else {
|
||||
log.Printf("error: no tui client started\n")
|
||||
}
|
||||
|
||||
ackMsg := []byte("confirmed from: " + node + ": " + fmt.Sprint(message.ID))
|
||||
return ackMsg, nil
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
type methodREQHttpGet struct {
|
||||
commandOrEvent CommandOrEvent
|
||||
}
|
||||
|
|
|
@ -142,7 +142,7 @@ func NewServer(c *Configuration, version string) (*server, error) {
|
|||
nodeName: c.NodeName,
|
||||
natsConn: conn,
|
||||
StewardSocket: stewardSocket,
|
||||
processes: newProcesses(ctx, metrics),
|
||||
processes: newProcesses(ctx, metrics, tuiClient),
|
||||
newMessagesCh: make(chan []subjectAndMessage),
|
||||
metrics: metrics,
|
||||
version: version,
|
||||
|
@ -263,7 +263,7 @@ func (s *server) Start() {
|
|||
|
||||
if s.configuration.EnableTUI {
|
||||
go func() {
|
||||
err := s.tui.Start()
|
||||
err := s.tui.Start(s.ctx, s.newMessagesCh)
|
||||
if err != nil {
|
||||
log.Printf("%v\n", err)
|
||||
os.Exit(1)
|
||||
|
|
40
tui.go
40
tui.go
|
@ -2,6 +2,7 @@ package steward
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
@ -21,10 +22,16 @@ import (
|
|||
// Main structure
|
||||
// ---------------------------------------------------------------------
|
||||
type tui struct {
|
||||
toConsoleCh chan []string
|
||||
toRingbufferCh chan []subjectAndMessage
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func newTui() (*tui, error) {
|
||||
s := tui{}
|
||||
ch := make(chan []string)
|
||||
s := tui{
|
||||
toConsoleCh: ch,
|
||||
}
|
||||
return &s, nil
|
||||
}
|
||||
|
||||
|
@ -34,7 +41,10 @@ type slide struct {
|
|||
primitive tview.Primitive
|
||||
}
|
||||
|
||||
func (s *tui) Start() error {
|
||||
func (t *tui) Start(ctx context.Context, toRingBufferCh chan []subjectAndMessage) error {
|
||||
t.ctx = ctx
|
||||
t.toRingbufferCh = toRingBufferCh
|
||||
|
||||
pages := tview.NewPages()
|
||||
|
||||
app := tview.NewApplication()
|
||||
|
@ -66,9 +76,9 @@ func (s *tui) Start() error {
|
|||
// chronological order, so we can auto generate the info menu with it's
|
||||
// corresponding F key based on the slice index+1.
|
||||
slides := []slide{
|
||||
{name: "console", key: tcell.KeyF1, primitive: console(app)},
|
||||
{name: "message", key: tcell.KeyF2, primitive: messageSlide(app)},
|
||||
{name: "info", key: tcell.KeyF3, primitive: infoSlide(app)},
|
||||
{name: "console", key: tcell.KeyF1, primitive: t.console(app)},
|
||||
{name: "message", key: tcell.KeyF2, primitive: t.messageSlide(app)},
|
||||
{name: "info", key: tcell.KeyF3, primitive: t.infoSlide(app)},
|
||||
}
|
||||
|
||||
// Add a page for each slide.
|
||||
|
@ -105,7 +115,7 @@ func (s *tui) Start() error {
|
|||
// Slides
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
func infoSlide(app *tview.Application) tview.Primitive {
|
||||
func (t *tui) infoSlide(app *tview.Application) tview.Primitive {
|
||||
flex := tview.NewFlex()
|
||||
flex.SetTitle("info")
|
||||
flex.SetBorder(true)
|
||||
|
@ -118,7 +128,7 @@ func infoSlide(app *tview.Application) tview.Primitive {
|
|||
return flex
|
||||
}
|
||||
|
||||
func messageSlide(app *tview.Application) tview.Primitive {
|
||||
func (t *tui) messageSlide(app *tview.Application) tview.Primitive {
|
||||
|
||||
// pageMessage is a struct for holding all the main forms and
|
||||
// views used in the message slide, so we can easily reference
|
||||
|
@ -446,7 +456,7 @@ func messageSlide(app *tview.Application) tview.Primitive {
|
|||
return p.flex
|
||||
}
|
||||
|
||||
func console(app *tview.Application) tview.Primitive {
|
||||
func (t *tui) console(app *tview.Application) tview.Primitive {
|
||||
|
||||
// pageMessage is a struct for holding all the main forms and
|
||||
// views used in the message slide, so we can easily reference
|
||||
|
@ -532,6 +542,20 @@ func console(app *tview.Application) tview.Primitive {
|
|||
// here ........
|
||||
})
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case messageData := <-t.toConsoleCh:
|
||||
for _, v := range messageData {
|
||||
fmt.Fprintf(p.outputForm, "%v", v)
|
||||
}
|
||||
case <-t.ctx.Done():
|
||||
log.Printf("info: stopped tui toConsole worker\n")
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return p.flex
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue