Switch service start, stop and restart commands to JSON

This commit is contained in:
2025-08-27 12:51:55 +03:00
parent 1d4a51abe0
commit d344347782
2 changed files with 176 additions and 109 deletions
+39 -48
View File
@@ -1,9 +1,10 @@
package main package main
import ( import (
"encoding/json"
"flag" "flag"
"fmt" "fmt"
"gopkg.in/yaml.v3" "io"
"log" "log"
"net" "net"
"os" "os"
@@ -12,6 +13,8 @@ import (
"strings" "strings"
"syscall" "syscall"
"time" "time"
"gopkg.in/yaml.v3"
) )
// Build-time variables // Build-time variables
@@ -19,7 +22,7 @@ var version = "dev"
var sysconfdir = "/etc/" var sysconfdir = "/etc/"
var runstatedir = "/var/run/" var runstatedir = "/var/run/"
var socket net.Conn var conn net.Conn
func main() { func main() {
@@ -29,7 +32,7 @@ func main() {
// Dial esvm socket // Dial esvm socket
dialSocket() dialSocket()
defer socket.Close() defer conn.Close()
if flag.NArg() < 1 { if flag.NArg() < 1 {
printUsage() printUsage()
@@ -85,66 +88,54 @@ func main() {
} else if len(flag.Args()) <= 2 { } else if len(flag.Args()) <= 2 {
fmt.Printf("Usage: ectl service %s <service>\n", flag.Args()[1]) fmt.Printf("Usage: ectl service %s <service>\n", flag.Args()[1])
return return
} else if flag.Args()[1] == "start" { } else if flag.Arg(1) == "start" || flag.Arg(1) == "stop" || flag.Arg(1) == "restart" {
if _, err := os.Stat(path.Join(runstatedir, "esvm", flag.Args()[2])); err != nil { type ServiceCommandJsonStruct struct {
log.Fatalf("Could not start service! Error: %s\n", err) Command string `json:"command"`
Service string `json:"service"`
}
serviceCommandJson := ServiceCommandJsonStruct{
Command: flag.Arg(1),
Service: flag.Arg(2),
} }
_, err := socket.Write([]byte("start " + flag.Args()[2])) // Encode struct to json string
jsonData, err := json.Marshal(serviceCommandJson)
if err != nil { if err != nil {
log.Fatalf("Could not start service! Error: %s\n", err) log.Fatalf("Could not encode JSON data! Error: %s\n", err)
} }
buf := make([]byte, 1024) _, err = conn.Write(jsonData)
n, err := socket.Read(buf)
if err != nil { if err != nil {
log.Fatalf("Could not start service! Error: %s\n", err) log.Fatalf("Could not write JSON data to socket! Error: %s\n", err)
}
if string(buf[:n]) != "ok" {
log.Fatalf("Could not start service! Error: expcted 'ok' got '%s'\n", string(buf))
} }
fmt.Println("Service started successfully!") // Create a buffer for incoming data.
return buf := make([]byte, 4096)
} else if flag.Args()[1] == "stop" {
if _, err := os.Stat(path.Join(runstatedir, "esvm", flag.Args()[2])); err != nil {
log.Fatalf("Could not stop service! Error: %s\n", err)
}
_, err := socket.Write([]byte("stop " + flag.Args()[2])) // Read data from the connection.
n, err := conn.Read(buf)
if err == io.EOF {
return
}
if err != nil { if err != nil {
log.Fatalf("Could not stop service! Error: %s\n", err) return
} }
buf := make([]byte, 1024) // Decoode JSON data
n, err := socket.Read(buf) var returnedJsonData map[string]any
err = json.Unmarshal(buf[:n], &returnedJsonData)
if err != nil { if err != nil {
log.Fatalf("Could not stop service! Error: %s\n", err) log.Fatalf("Could not decode JSON data from connection!")
}
if string(buf[:n]) != "ok" {
log.Fatalf("Could not stop service! Error: expcted 'ok' got '%s'\n", string(buf))
}
fmt.Println("Service stopped successfully!")
return
} else if flag.Args()[1] == "restart" || flag.Args()[1] == "reload" {
if _, err := os.Stat(path.Join(runstatedir, "esvm", flag.Args()[2])); err != nil {
log.Fatalf("Could not restart service! Error: %s\n", err)
} }
_, err := socket.Write([]byte("restart " + flag.Args()[2])) if err, ok := returnedJsonData["error"]; ok {
if err != nil { log.Fatal(err)
log.Fatalf("Could not restart service! Error: %s\n", err) } else if msg, ok := returnedJsonData["success"]; ok {
fmt.Println(msg)
} else {
log.Fatal("Connection returned empty string!")
} }
buf := make([]byte, 1024)
n, err := socket.Read(buf)
if err != nil {
log.Fatalf("Could not restart service! Error: %s\n", err)
}
if string(buf[:n]) != "ok" {
log.Fatalf("Could not restart service! Error: expcted 'ok' got '%s'\n", string(buf))
}
fmt.Println("Service restarted successfully!")
return return
} else if flag.Args()[1] == "enable" { } else if flag.Args()[1] == "enable" {
// Check if service exists // Check if service exists
@@ -329,12 +320,12 @@ func dialSocket() {
} }
var err error var err error
socket, err = net.Dial("unix", path.Join(runstatedir, "esvm/esvm.sock")) conn, err = net.Dial("unix", path.Join(runstatedir, "esvm/esvm.sock"))
if err != nil { if err != nil {
log.Fatalf("Failed to connect to esvm.sock! Error: %s\n", err) log.Fatalf("Failed to connect to esvm.sock! Error: %s\n", err)
} }
if err := socket.SetDeadline(time.Now().Add(5 * time.Second)); err != nil { if err := conn.SetDeadline(time.Now().Add(5 * time.Second)); err != nil {
log.Fatalf("Failed to set write deadline! Error: %s\n", err) log.Fatalf("Failed to set write deadline! Error: %s\n", err)
} }
} }
+137 -61
View File
@@ -1,18 +1,26 @@
package main package main
import ( import (
"encoding/json"
"fmt"
"io" "io"
"net" "net"
"path" "path"
"strings"
) )
var commandHandlers = make(map[string]func(conn net.Conn, jsonData map[string]any))
func initSocket() (socket net.Listener, err error) { func initSocket() (socket net.Listener, err error) {
socket, err = net.Listen("unix", path.Join(runtimeServiceDir, "esvm.sock")) socket, err = net.Listen("unix", path.Join(runtimeServiceDir, "esvm.sock"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Register command handlers
commandHandlers["start"] = handleStartServiceCommand
commandHandlers["stop"] = handleStopServiceCommand
commandHandlers["restart"] = handleRestartServiceCommand
return socket, nil return socket, nil
} }
@@ -35,68 +43,136 @@ func listenToSocket() {
return return
} }
if err != nil { if err != nil {
logger.Fatal(err) return
} }
command := string(buf[:n]) // Decoode JSON data
commandSplit := strings.Split(command, " ") var jsonData map[string]any
err = json.Unmarshal(buf[:n], &jsonData)
if len(commandSplit) >= 2 { if err != nil {
if commandSplit[0] == "start" { conn.Write(wrapErrorInJson(fmt.Errorf("Invalid JSON")))
service := GetServiceByName(commandSplit[1]) return
if service == nil {
_, err := conn.Write([]byte("service not found"))
if err != nil {
return
}
}
if err := service.StartService(); err != nil {
_, err := conn.Write([]byte("could not start service"))
if err != nil {
return
}
}
_, err := conn.Write([]byte("ok"))
if err != nil {
return
}
} else if commandSplit[0] == "stop" {
service := GetServiceByName(commandSplit[1])
if service == nil {
_, err := conn.Write([]byte("service not found"))
if err != nil {
return
}
}
if err := service.StopService(); err != nil {
_, err := conn.Write([]byte("could not stop service"))
if err != nil {
return
}
}
_, err := conn.Write([]byte("ok"))
if err != nil {
return
}
} else if commandSplit[0] == "restart" {
service := GetServiceByName(commandSplit[1])
if service == nil {
_, err := conn.Write([]byte("service not found"))
if err != nil {
return
}
}
if err := service.RestartService(); err != nil {
_, err := conn.Write([]byte("could not restart service"))
if err != nil {
return
}
}
_, err := conn.Write([]byte("ok"))
if err != nil {
return
}
}
} }
// Get command to execute
command, ok := jsonData["command"]
if !ok {
conn.Write(wrapErrorInJson(fmt.Errorf("'command' field missing")))
return
}
// Get command handler
commandHandler, ok := commandHandlers[command.(string)]
if !ok {
conn.Write(wrapErrorInJson(fmt.Errorf("command (%s) has not been implemented", command.(string))))
return
}
commandHandler(conn, jsonData)
}(conn) }(conn)
} }
func handleStartServiceCommand(conn net.Conn, jsonData map[string]any) {
// Get service name from json data
serviceName, ok := jsonData["service"]
if !ok {
conn.Write(wrapErrorInJson(fmt.Errorf("'service' field missing")))
return
}
// Ensure service exists
service := GetServiceByName(serviceName.(string))
if service == nil {
conn.Write(wrapErrorInJson(fmt.Errorf("Service (%s) not found", serviceName.(string))))
return
}
// Start the service
if err := service.StartService(); err != nil {
conn.Write(wrapErrorInJson(fmt.Errorf("Service (%s) could not be started", serviceName.(string))))
return
}
conn.Write(wrapSuccessMsgInJson(fmt.Sprintf("Service (%s) has started sucessfully", serviceName.(string))))
}
func handleStopServiceCommand(conn net.Conn, jsonData map[string]any) {
// Get service name from json data
serviceName, ok := jsonData["service"]
if !ok {
conn.Write(wrapErrorInJson(fmt.Errorf("'service' field missing")))
return
}
// Ensure service exists
service := GetServiceByName(serviceName.(string))
if service == nil {
conn.Write(wrapErrorInJson(fmt.Errorf("Service (%s) not found", serviceName.(string))))
return
}
// Stop the service
if err := service.StopService(); err != nil {
conn.Write(wrapErrorInJson(fmt.Errorf("Service (%s) could not be stopped", serviceName.(string))))
return
}
conn.Write(wrapSuccessMsgInJson(fmt.Sprintf("Service (%s) has stopped sucessfully", serviceName.(string))))
}
func handleRestartServiceCommand(conn net.Conn, jsonData map[string]any) {
// Get service name from json data
serviceName, ok := jsonData["service"]
if !ok {
conn.Write(wrapErrorInJson(fmt.Errorf("'service' field missing")))
return
}
// Ensure service exists
service := GetServiceByName(serviceName.(string))
if service == nil {
conn.Write(wrapErrorInJson(fmt.Errorf("Service (%s) not found", serviceName.(string))))
return
}
// Restart the service
if err := service.RestartService(); err != nil {
conn.Write(wrapErrorInJson(fmt.Errorf("Service (%s) could not be restarted", serviceName.(string))))
return
}
conn.Write(wrapSuccessMsgInJson(fmt.Sprintf("Service (%s) has restarted sucessfully", serviceName.(string))))
}
func wrapErrorInJson(err error) []byte {
// Wrap error in struct
type jsonErrorStruct struct {
Error string `json:"error"`
}
jsonError := jsonErrorStruct{
Error: err.Error(),
}
// Encode struct to json string
jsonData, _err := json.Marshal(jsonError)
if _err != nil {
return nil
}
return jsonData
}
func wrapSuccessMsgInJson(msg string) []byte {
// Wrap message in struct
type jsonSuccessStruct struct {
Success string `json:"success"`
}
jsonSuccess := jsonSuccessStruct{
Success: msg,
}
// Encode struct to json string
jsonData, _err := json.Marshal(jsonSuccess)
if _err != nil {
return nil
}
return jsonData
}