add plugin hosts to seperate plugins from gloomi
This adds a plugin host that seperates plugins from the gloomi process, allowing for plugins to be unloaded and loaded. This commit also has a fair amount of other changes, nice to haves and bug fixes, some notable changes are: - Highly available reverse proxy from my Flux project - Improved gloomi functionality
This commit is contained in:
145
pluginHost/main.go
Normal file
145
pluginHost/main.go
Normal file
@@ -0,0 +1,145 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"plugin"
|
||||
|
||||
"github.com/gofiber/fiber/v3"
|
||||
)
|
||||
|
||||
var pluginPath string
|
||||
var socketPath string
|
||||
var controlPath string
|
||||
|
||||
func init() {
|
||||
if len(os.Args) < 3 {
|
||||
fmt.Fprintf(os.Stderr, "Usage: pluginHost <pluginPath> <socketPath>")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
pluginPath = os.Args[1]
|
||||
socketPath = os.Args[2]
|
||||
if len(os.Args) > 3 {
|
||||
controlPath = os.Args[3]
|
||||
}
|
||||
}
|
||||
|
||||
type Plugin interface {
|
||||
Init() (*fiber.Config, error)
|
||||
RegisterRoutes(app fiber.Router)
|
||||
// Name() string
|
||||
}
|
||||
|
||||
type PluginInstance struct {
|
||||
Plugin Plugin
|
||||
Name string
|
||||
Path string
|
||||
Router *fiber.App
|
||||
}
|
||||
|
||||
// Init is the entry point for a container process
|
||||
func (p *PluginInstance) Run(pluginName string) {
|
||||
log.Printf("Starting container with plugin %s", pluginName)
|
||||
// Load and initialize the plugin here
|
||||
}
|
||||
|
||||
func main() {
|
||||
signalChan := make(chan os.Signal, 1)
|
||||
signal.Notify(signalChan, os.Interrupt)
|
||||
|
||||
go func() {
|
||||
<-signalChan
|
||||
// TODO: maybe do something graceful here
|
||||
fmt.Println("Received SIGINT, shutting down...")
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
var writer io.Writer
|
||||
writer = os.Stderr
|
||||
if controlPath != "" {
|
||||
fmt.Printf("Waiting for control connection on %s\n", controlPath)
|
||||
|
||||
controlListener, err := net.Listen("unix", controlPath)
|
||||
if err != nil {
|
||||
log.Fatalf("Error listening on control socket: %v", err)
|
||||
}
|
||||
defer controlListener.Close()
|
||||
|
||||
conn, err := controlListener.Accept()
|
||||
if err != nil {
|
||||
log.Printf("Error accepting control connection: %v", err)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
var ok bool
|
||||
writer, ok = conn.(io.Writer)
|
||||
if !ok {
|
||||
log.Printf("Control connection is not a writer")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := os.Stat(socketPath); err == nil {
|
||||
fmt.Fprintf(writer, "Error: Socket %s already exists\n", socketPath)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
realPluginPath, err := filepath.Abs(pluginPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(writer, "Error: could not get absolute plugin path: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
p, err := plugin.Open(realPluginPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(writer, "Error: could not open plugin %s: %v\n", realPluginPath, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
symbol, err := p.Lookup("Plugin")
|
||||
if err != nil {
|
||||
fmt.Fprintf(writer, "Error: could not find 'Plugin' symbol in %s: %v\n", realPluginPath, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
pluginLib, ok := symbol.(Plugin)
|
||||
if !ok {
|
||||
fmt.Fprintf(writer, "Error: symbol 'Plugin' in %s is not a Plugin interface\n", realPluginPath)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
pluginConfig, err := pluginLib.Init()
|
||||
if err != nil {
|
||||
fmt.Fprintf(writer, "Error: error initializing plugin %s: %v\n", realPluginPath, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
config := fiber.Config{}
|
||||
if pluginConfig != nil {
|
||||
config = *pluginConfig
|
||||
}
|
||||
router := fiber.New(config)
|
||||
|
||||
pluginLib.RegisterRoutes(router)
|
||||
|
||||
// listen for connections on the socket
|
||||
listener, err := net.Listen("unix", socketPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(writer, "Error: error listening on socket %s: %v\n", socketPath, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Fprintf(writer, "ready\n")
|
||||
|
||||
// technically this can still error
|
||||
router.Listener(listener, fiber.ListenConfig{
|
||||
DisableStartupMessage: true,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user