Implement /fromcurto/ to make use of kept state

This commit is contained in:
Joel Elkins 2022-11-06 01:32:49 -06:00
parent 3d77d98d50
commit 47c3077524
Signed by: joel
GPG Key ID: 133589DC38921AE2
2 changed files with 68 additions and 42 deletions

View File

@ -1,20 +1,24 @@
package config
import (
"os/exec"
"github.com/BurntSushi/toml"
)
type TargetId string
type Command string
func (c *Command) Exec() ([]byte, error) {
return exec.Command("/bin/sh", "-c", string(*c)).Output()
}
type Target struct {
Id TargetId `toml:"id"`
Id string `toml:"id"`
CommandsTo []Command `toml:"commands_to"`
CommandsFrom []Command `toml:"commands_from"`
}
type Targets []Target
const HostTarget TargetId = "host"
type T struct {
Globals struct {
Listen *string

View File

@ -6,25 +6,26 @@ import (
"log"
"net/http"
"os"
"os/exec"
"path"
"regexp"
"gitea.elkins.co/Networking/kvmswitcher/internal/config"
)
var (
confFile = flag.String("config",
path.Join(os.Getenv("HOME"), ".config", "kvmswitcher", "config.toml"),
"Path to the configuration file",
)
listen = flag.String("listen", ":5001", "Address and port to listen on")
targets config.Targets
curTargetId config.TargetId // currently unused, but keeps track of what is activated
const (
hostTgt = "host"
dirTo = true
dirFrom = false
)
func targetIds(t config.Targets) []config.TargetId {
x := make([]config.TargetId, len(t))
var (
confFile = flag.String("config", "/etc/kvmswitcher/config.toml", "Path to the configuration file")
listen = flag.String("listen", ":5001", "Address and port to listen on")
curTargetId = flag.String("initial", "host", "Intitially active target")
targets config.Targets
)
func targetIds(t config.Targets) []string {
x := make([]string, len(t))
for i := range t {
x[i] = t[i].Id
}
@ -45,8 +46,6 @@ func main() {
log.Fatal("No targets configured")
}
curTargetId = config.HostTarget
if c.Globals.Listen != nil {
listen = c.Globals.Listen
}
@ -55,60 +54,83 @@ func main() {
log.Printf("listening on %s\n", *listen)
http.HandleFunc("/to/", doSwitchTo)
http.HandleFunc("/from/", doSwitchFrom)
http.HandleFunc("/fromcurto/", doSwitchFromCurTo)
http.ListenAndServe(*listen, nil)
}
func getTarget(r *http.Request) (string, error) {
ct, _ := regexp.Compile("^/(from|to|fromcurto)/")
u := ct.ReplaceAllString(r.URL.String(), "")
if u == r.URL.String() {
log.Printf("Malformed request: %s\n", u)
return "", fmt.Errorf("Malformed request: %s", u)
}
return u, nil
}
func doSwitchFrom(w http.ResponseWriter, r *http.Request) {
doSwitch(false, w, r)
t, err := getTarget(r)
if err != nil {
fmt.Fprintf(w, "%s", err)
}
doSwitch(dirFrom, t, w)
}
func doSwitchTo(w http.ResponseWriter, r *http.Request) {
doSwitch(true, w, r)
t, err := getTarget(r)
if err != nil {
fmt.Fprintf(w, "%s", err)
}
doSwitch(dirTo, t, w)
}
func doSwitch(to bool, w http.ResponseWriter, r *http.Request) {
ct, _ := regexp.Compile("^/(from|to)/")
u := config.TargetId(ct.ReplaceAllString(r.URL.String(), ""))
if u == config.TargetId(r.URL.String()) {
fmt.Fprintf(w, "Malformed request: %s\n", u)
return
func doSwitchFromCurTo(w http.ResponseWriter, r *http.Request) {
t, err := getTarget(r)
if err != nil {
fmt.Fprintf(w, "%s", err)
}
doSwitch(dirFrom, *curTargetId, w)
doSwitch(dirTo, t, w)
}
func doSwitch(dir bool, tgt string, w http.ResponseWriter) {
var t *config.Target
for i := range targets {
if targets[i].Id == config.TargetId(u) {
if targets[i].Id == tgt {
t = &targets[i]
}
}
if t == nil {
fmt.Fprintf(w, "Invalid Target: %s\n", u)
fmt.Fprintf(w, "Invalid Target: %s\n", tgt)
return
}
cmds := t.CommandsFrom
toFrom := "from"
curTargetId = config.HostTarget
if to {
h := hostTgt
curTargetId = &h
if dir == dirTo {
cmds = t.CommandsTo
toFrom = "to"
curTargetId = t.Id
curTargetId = &t.Id
}
log.Printf("Switching %s %s\n", toFrom, u)
out, err := runCommands(cmds)
if err != nil {
fmt.Fprintf(w, "ERROR:\n%s", err)
log.Printf("Error on command execution (switching %s %s): %s\n", toFrom, u, err)
log.Printf("Switching %s %s\n", toFrom, tgt)
out := make(chan string)
go runCommands(cmds, out)
for o := range out {
fmt.Fprint(w, o)
}
fmt.Fprintf(w, "OUTPUT:\n%s", out)
}
func runCommands(cmds []config.Command) (out string, err error) {
func runCommands(cmds []config.Command, out chan string) {
for _, c := range cmds {
o, err := exec.Command("/bin/sh", "-c", string(c)).Output()
o, err := c.Exec()
if err != nil {
return out, fmt.Errorf("Error executing %s: %s\n", c, err)
log.Printf("Error on command execution (cmd = %s): %s\n", c, err)
}
out = out + string(o)
out <- string(o)
}
return
close(out)
}