From 7092265d8c6e6f122ac5d7739ae3039578642852 Mon Sep 17 00:00:00 2001 From: postmannen Date: Wed, 12 Jan 2022 07:42:41 +0100 Subject: [PATCH] added tui req handler --- processes.go | 5 ++++- requests.go | 32 ++++++++++++++++++++++++++++++-- server.go | 4 ++-- tui.go | 40 ++++++++++++++++++++++++++++++++-------- 4 files changed, 68 insertions(+), 13 deletions(-) diff --git a/processes.go b/processes.go index 42565c7..db4ccae 100644 --- a/processes.go +++ b/processes.go @@ -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. diff --git a/requests.go b/requests.go index 0b4c3fd..233395e 100644 --- a/requests.go +++ b/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 } diff --git a/server.go b/server.go index 0e40762..668d484 100644 --- a/server.go +++ b/server.go @@ -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) diff --git a/tui.go b/tui.go index 54a4f10..1f57b4a 100644 --- a/tui.go +++ b/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 }