From ed3ae1dbc37c911564bed38de39a3dd57e2d9a4e Mon Sep 17 00:00:00 2001 From: postmannen Date: Thu, 11 Feb 2021 15:39:19 +0100 Subject: [PATCH] implemented map for method handler types --- message.go => commandOrEventType.go | 66 +-------------------- methodType.go | 91 +++++++++++++++++++++++++++++ publisher.go | 17 +++++- textlogging.log | 2 + 4 files changed, 112 insertions(+), 64 deletions(-) rename message.go => commandOrEventType.go (53%) create mode 100644 methodType.go diff --git a/message.go b/commandOrEventType.go similarity index 53% rename from message.go rename to commandOrEventType.go index 3a44326..f77f832 100644 --- a/message.go +++ b/commandOrEventType.go @@ -3,6 +3,7 @@ // types, make sure to also add them to the map // Available since the this will be used // to check if the message values are valid later on. + package steward import "fmt" @@ -21,8 +22,8 @@ type CommandOrEvent string func (c CommandOrEvent) GetCommandOrEventAvailable() CommandOrEventAvailable { ma := CommandOrEventAvailable{ topics: map[CommandOrEvent]struct{}{ - Command: struct{}{}, - Event: struct{}{}, + Command: {}, + Event: {}, }, } @@ -60,64 +61,3 @@ func (co CommandOrEventAvailable) CheckIfExists(c CommandOrEvent) bool { return false } } - -// ------------------------------------------------------------ - -// Method is used to specify the actual function/method that -// is represented in a typed manner. -type Method string - -func (m Method) GetMethodsAvailable() MethodsAvailable { - // var ma MethodsAvailable - // ma.topics = make(map[Method]struct{}) - // - // ma.topics[ShellCommand] = struct{}{} - // ma.topics[TextLogging] = struct{}{} - ma := MethodsAvailable{ - topics: map[Method]struct{}{ - ShellCommand: struct{}{}, - TextLogging: struct{}{}, - }, - } - - return ma -} - -const ( - // Shell command to be executed via f.ex. bash - ShellCommand Method = "shellCommand" - // Send text logging to some host - TextLogging Method = "textLogging" -) - -type MethodsAvailable struct { - topics map[Method]struct{} -} - -func (ma MethodsAvailable) CheckIfExists(m Method) bool { - _, ok := ma.topics[m] - if ok { - fmt.Printf("******THE TOPIC EXISTS: %v******\n", m) - return true - } else { - fmt.Printf("******THE TOPIC DO NOT EXIST: %v******\n", m) - return false - } -} - -// ------------------------------------------------------------ - -type Message struct { - ToNode node `json:"toNode" yaml:"toNode"` - // The Unique ID of the message - ID int `json:"id" yaml:"id"` - // The actual data in the message - // TODO: Change this to a slice instead...or maybe use an - // interface type here to handle several data types ? - Data []string `json:"data" yaml:"data"` - // The type of the message being sent - CommandOrEvent CommandOrEvent `json:"commandOrEvent" yaml:"commandOrEvent"` - // method, what is this message doing, etc. shellCommand, syslog, etc. - Method Method `json:"method" yaml:"method"` - FromNode node -} diff --git a/methodType.go b/methodType.go new file mode 100644 index 0000000..eabb948 --- /dev/null +++ b/methodType.go @@ -0,0 +1,91 @@ +// NB: +// When adding new constants for the Method or CommandOrEvent +// types, make sure to also add them to the map +// Available since the this will be used +// to check if the message values are valid later on. + +package steward + +import ( + "fmt" + "log" + "os/exec" +) + +// ------------------------------------------------------------ + +// Method is used to specify the actual function/method that +// is represented in a typed manner. +type Method string + +func (m Method) GetMethodsAvailable() MethodsAvailable { + ma := MethodsAvailable{ + topics: map[Method]methodHandler{ + ShellCommand: methodCommandShellCommand{}, + TextLogging: methodEventTextLogging{}, + }, + } + + return ma +} + +const ( + // Shell command to be executed via f.ex. bash + ShellCommand Method = "shellCommand" + // Send text logging to some host + TextLogging Method = "textLogging" +) + +type MethodsAvailable struct { + topics map[Method]methodHandler +} + +// Check if exists will check if the Method is defined. If true the bool +// value will be set to true, and the methodHandler function for that type +// will be returned. +func (ma MethodsAvailable) CheckIfExists(m Method) (methodHandler, bool) { + mFunc, ok := ma.topics[m] + if ok { + fmt.Printf("******THE TOPIC EXISTS: %v******\n", m) + return mFunc, true + } else { + fmt.Printf("******THE TOPIC DO NOT EXIST: %v******\n", m) + return nil, false + } +} + +// ------------------------------------------------------------ + +type methodHandler interface { + handler(*server, Message, string) ([]byte, error) +} + +type methodCommandShellCommand struct{} + +func (m methodCommandShellCommand) handler(s *server, message Message, node string) ([]byte, error) { + // Since the command to execute is at the first position in the + // slice we need to slice it out. The arguments are at the + // remaining positions. + c := message.Data[0] + a := message.Data[1:] + cmd := exec.Command(c, a...) + //cmd.Stdout = os.Stdout + out, err := cmd.CombinedOutput() + if err != nil { + log.Printf("error: execution of command failed: %v\n", err) + } + + outMsg := []byte(fmt.Sprintf("confirmed from node: %v: messageID: %v\n---\n%s---", node, message.ID, out)) + return outMsg, nil +} + +type methodEventTextLogging struct{} + +func (m methodEventTextLogging) handler(s *server, message Message, node string) ([]byte, error) { + for _, d := range message.Data { + s.logCh <- []byte(d) + } + + outMsg := []byte("confirmed from: " + node + ": " + fmt.Sprint(message.ID)) + return outMsg, nil +} diff --git a/publisher.go b/publisher.go index dfdb91b..1680ae2 100644 --- a/publisher.go +++ b/publisher.go @@ -14,6 +14,21 @@ import ( "github.com/nats-io/nats.go" ) +type Message struct { + ToNode node `json:"toNode" yaml:"toNode"` + // The Unique ID of the message + ID int `json:"id" yaml:"id"` + // The actual data in the message + // TODO: Change this to a slice instead...or maybe use an + // interface type here to handle several data types ? + Data []string `json:"data" yaml:"data"` + // The type of the message being sent + CommandOrEvent CommandOrEvent `json:"commandOrEvent" yaml:"commandOrEvent"` + // method, what is this message doing, etc. shellCommand, syslog, etc. + Method Method `json:"method" yaml:"method"` + FromNode node +} + // server is the structure that will hold the state about spawned // processes on a local instance. type server struct { @@ -132,7 +147,7 @@ func (s *server) handleMessagesToPublish() { // TODO: Send a message to the error kernel here that // it was unable to process the message with the reason // why ? - if !s.methodsAvailable.CheckIfExists(sam.Message.Method) { + if _, ok := s.methodsAvailable.CheckIfExists(sam.Message.Method); !ok { continue } if !s.commandOrEventAvailable.CheckIfExists(sam.Message.CommandOrEvent) { diff --git a/textlogging.log b/textlogging.log index 6692757..c8c87a4 100644 --- a/textlogging.log +++ b/textlogging.log @@ -14,3 +14,5 @@ some message sent from a ship for testing some message sent from a ship for testing some message sent from a ship for testing some message sent from a ship for testing +some message sent from a ship for testing +some message sent from a ship for testing