2021-03-01 17:08:40 +01:00
|
|
|
// The structure of how to add new method types to the system.
|
|
|
|
// -----------------------------------------------------------
|
|
|
|
// All methods need 3 things:
|
|
|
|
// - A type definition
|
|
|
|
// - The type needs a getKind method
|
|
|
|
// - The type needs a handler method
|
|
|
|
// Overall structure example shown below.
|
|
|
|
//
|
|
|
|
// ---
|
|
|
|
// type methodCommandCLICommand struct {
|
|
|
|
// commandOrEvent CommandOrEvent
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// func (m methodCommandCLICommand) getKind() CommandOrEvent {
|
|
|
|
// return m.commandOrEvent
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// func (m methodCommandCLICommand) handler(s *server, message Message, node string) ([]byte, error) {
|
|
|
|
// ...
|
|
|
|
// ...
|
|
|
|
// outMsg := []byte(fmt.Sprintf("confirmed from node: %v: messageID: %v\n---\n%s---", node, message.ID, out))
|
|
|
|
// return outMsg, nil
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// ---
|
|
|
|
// You also need to make a constant for the Method, and add
|
|
|
|
// that constant as the key in the map, where the value is
|
|
|
|
// the actual type you want to map it to with a handler method.
|
|
|
|
// You also specify if it is a Command or Event, and if it is
|
|
|
|
// ACK or NACK.
|
|
|
|
// Check out the existing code below for more examples.
|
2021-02-11 15:39:19 +01:00
|
|
|
|
|
|
|
package steward
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"os/exec"
|
2021-02-19 16:58:16 +01:00
|
|
|
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
2021-02-11 15:39:19 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
// ------------------------------------------------------------
|
2021-03-01 17:08:40 +01:00
|
|
|
// The constants that will be used throughout the system for
|
|
|
|
// when specifying what kind of Method to send or work with.
|
|
|
|
const (
|
|
|
|
// Shell command to be executed via f.ex. bash
|
|
|
|
CLICommand Method = "CLICommand"
|
|
|
|
// Send text logging to some host
|
|
|
|
TextLogging Method = "TextLogging"
|
|
|
|
// Send Hello I'm here message
|
|
|
|
SayHello Method = "SayHello"
|
|
|
|
// Error log methods to centralError
|
|
|
|
ErrorLog Method = "ErrorLog"
|
|
|
|
)
|
2021-02-11 15:39:19 +01:00
|
|
|
|
|
|
|
// Method is used to specify the actual function/method that
|
|
|
|
// is represented in a typed manner.
|
|
|
|
type Method string
|
|
|
|
|
2021-03-01 17:08:40 +01:00
|
|
|
// The mapping of all the method constants specified, what type
|
|
|
|
// it references, and the kind if it is an Event or Command, and
|
|
|
|
// if it is ACK or NACK.
|
|
|
|
// Allowed values for the commandOrEvent field are:
|
|
|
|
// - CommandACK
|
|
|
|
// - CommandNACK
|
|
|
|
// - EventACK
|
|
|
|
// - EventNack
|
2021-02-11 15:39:19 +01:00
|
|
|
func (m Method) GetMethodsAvailable() MethodsAvailable {
|
|
|
|
ma := MethodsAvailable{
|
|
|
|
topics: map[Method]methodHandler{
|
2021-03-01 17:08:40 +01:00
|
|
|
CLICommand: methodCommandCLICommand{
|
|
|
|
commandOrEvent: CommandACK,
|
|
|
|
},
|
|
|
|
TextLogging: methodEventTextLogging{
|
|
|
|
commandOrEvent: EventACK,
|
|
|
|
},
|
|
|
|
SayHello: methodEventSayHello{
|
|
|
|
commandOrEvent: EventNACK,
|
|
|
|
},
|
|
|
|
ErrorLog: methodEventErrorLog{
|
|
|
|
commandOrEvent: EventACK,
|
|
|
|
},
|
2021-02-11 15:39:19 +01:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
return ma
|
|
|
|
}
|
|
|
|
|
2021-03-01 17:08:40 +01:00
|
|
|
// getHandler will check the methodsAvailable map, and return the
|
|
|
|
// method handler for the method given
|
|
|
|
// as input argument.
|
|
|
|
func (m Method) getHandler(method Method) methodHandler {
|
|
|
|
ma := m.GetMethodsAvailable()
|
|
|
|
mh := ma.topics[method]
|
|
|
|
|
|
|
|
return mh
|
|
|
|
}
|
2021-02-11 15:39:19 +01:00
|
|
|
|
|
|
|
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 {
|
2021-02-16 04:57:54 +01:00
|
|
|
// fmt.Printf("******THE TOPIC EXISTS: %v******\n", m)
|
2021-02-11 15:39:19 +01:00
|
|
|
return mFunc, true
|
|
|
|
} else {
|
2021-02-16 04:57:54 +01:00
|
|
|
// fmt.Printf("******THE TOPIC DO NOT EXIST: %v******\n", m)
|
2021-02-11 15:39:19 +01:00
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-18 14:27:53 +01:00
|
|
|
// ------------------------------------------------------------
|
|
|
|
// Subscriber method handlers
|
2021-02-11 15:39:19 +01:00
|
|
|
// ------------------------------------------------------------
|
|
|
|
|
|
|
|
type methodHandler interface {
|
2021-02-11 15:51:07 +01:00
|
|
|
handler(server *server, message Message, node string) ([]byte, error)
|
2021-03-01 17:08:40 +01:00
|
|
|
getKind() CommandOrEvent
|
2021-02-11 15:39:19 +01:00
|
|
|
}
|
|
|
|
|
2021-03-01 17:08:40 +01:00
|
|
|
// -----
|
|
|
|
|
|
|
|
type methodCommandCLICommand struct {
|
|
|
|
commandOrEvent CommandOrEvent
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m methodCommandCLICommand) getKind() CommandOrEvent {
|
|
|
|
return m.commandOrEvent
|
|
|
|
}
|
2021-02-11 15:39:19 +01:00
|
|
|
|
2021-03-01 12:16:36 +01:00
|
|
|
func (m methodCommandCLICommand) handler(s *server, message Message, node string) ([]byte, error) {
|
2021-02-11 15:39:19 +01:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2021-02-18 14:27:53 +01:00
|
|
|
// -----
|
|
|
|
|
2021-03-01 17:08:40 +01:00
|
|
|
type methodEventTextLogging struct {
|
|
|
|
commandOrEvent CommandOrEvent
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m methodEventTextLogging) getKind() CommandOrEvent {
|
|
|
|
return m.commandOrEvent
|
|
|
|
}
|
2021-02-11 15:39:19 +01:00
|
|
|
|
|
|
|
func (m methodEventTextLogging) handler(s *server, message Message, node string) ([]byte, error) {
|
|
|
|
for _, d := range message.Data {
|
2021-02-24 10:58:02 +01:00
|
|
|
s.subscriberServices.logCh <- []byte(d)
|
2021-02-11 15:39:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
outMsg := []byte("confirmed from: " + node + ": " + fmt.Sprint(message.ID))
|
|
|
|
return outMsg, nil
|
|
|
|
}
|
2021-02-18 14:27:53 +01:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2021-03-01 17:08:40 +01:00
|
|
|
type methodEventSayHello struct {
|
|
|
|
commandOrEvent CommandOrEvent
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m methodEventSayHello) getKind() CommandOrEvent {
|
|
|
|
return m.commandOrEvent
|
|
|
|
}
|
2021-02-18 14:27:53 +01:00
|
|
|
|
|
|
|
func (m methodEventSayHello) handler(s *server, message Message, node string) ([]byte, error) {
|
2021-02-26 07:55:28 +01:00
|
|
|
log.Printf("<--- Received hello from %v \n", message.FromNode)
|
2021-02-19 16:58:16 +01:00
|
|
|
// Since the handler is only called to handle a specific type of message we need
|
|
|
|
// to store it elsewhere, and choice for now is under s.metrics.sayHelloNodes
|
2021-02-24 10:58:02 +01:00
|
|
|
s.subscriberServices.sayHelloNodes[message.FromNode] = struct{}{}
|
2021-02-19 16:58:16 +01:00
|
|
|
|
|
|
|
// update the prometheus metrics
|
|
|
|
s.metrics.metricsCh <- metricType{
|
|
|
|
metric: prometheus.NewGauge(prometheus.GaugeOpts{
|
|
|
|
Name: "hello_nodes",
|
|
|
|
Help: "The current number of total nodes who have said hello",
|
|
|
|
}),
|
2021-02-24 10:58:02 +01:00
|
|
|
value: float64(len(s.subscriberServices.sayHelloNodes)),
|
2021-02-19 16:58:16 +01:00
|
|
|
}
|
2021-02-18 14:27:53 +01:00
|
|
|
outMsg := []byte("confirmed from: " + node + ": " + fmt.Sprint(message.ID))
|
|
|
|
return outMsg, nil
|
|
|
|
}
|
2021-02-24 15:43:31 +01:00
|
|
|
|
|
|
|
// ---
|
|
|
|
|
2021-03-01 17:08:40 +01:00
|
|
|
type methodEventErrorLog struct {
|
|
|
|
commandOrEvent CommandOrEvent
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m methodEventErrorLog) getKind() CommandOrEvent {
|
|
|
|
return m.commandOrEvent
|
|
|
|
}
|
2021-02-24 15:43:31 +01:00
|
|
|
|
|
|
|
func (m methodEventErrorLog) handler(s *server, message Message, node string) ([]byte, error) {
|
|
|
|
log.Printf("----------------------------------------------------------------------------..\n")
|
|
|
|
log.Printf("Received error from: %v, containing: %v", message.FromNode, message.Data)
|
|
|
|
log.Printf("----------------------------------------------------------------------------..\n")
|
|
|
|
return nil, nil
|
|
|
|
}
|