Made the create command require a port number
This commit is contained in:
47
daemon.go
47
daemon.go
@@ -6,6 +6,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
@@ -41,6 +42,7 @@ func StartDaemon(cfg *AppConfig, configPath string) error {
|
|||||||
mux.HandleFunc("/instances/stop", ds.handleStop)
|
mux.HandleFunc("/instances/stop", ds.handleStop)
|
||||||
mux.HandleFunc("/instances/command", ds.handleCommand)
|
mux.HandleFunc("/instances/command", ds.handleCommand)
|
||||||
mux.HandleFunc("/instances/list", ds.handleList)
|
mux.HandleFunc("/instances/list", ds.handleList)
|
||||||
|
mux.HandleFunc("/instances/logs", ds.handleGetLogs)
|
||||||
|
|
||||||
corsWrappedHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
corsWrappedHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||||
@@ -143,8 +145,15 @@ func (ds *DaemonServer) handleCreate(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
name := r.URL.Query().Get("name")
|
name := r.URL.Query().Get("name")
|
||||||
version := r.URL.Query().Get("version")
|
version := r.URL.Query().Get("version")
|
||||||
if name == "" || version == "" {
|
port := r.URL.Query().Get("port")
|
||||||
http.Error(w, "Missing name or version parameters", http.StatusBadRequest)
|
if name == "" || version == "" || port == "" {
|
||||||
|
http.Error(w, "Missing name, version, or port parameters", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
converted_port, err := strconv.Atoi(port)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Could not convert provided port to a valid port number", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,11 +165,11 @@ func (ds *DaemonServer) handleCreate(w http.ResponseWriter, r *http.Request) {
|
|||||||
options := VsServerConfigOptions{
|
options := VsServerConfigOptions{
|
||||||
Version: version,
|
Version: version,
|
||||||
ServerName: name,
|
ServerName: name,
|
||||||
Port: 42424,
|
Port: converted_port,
|
||||||
MaxClients: 10,
|
MaxClients: 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := DownloadAndExtractServer(version, ds.cfg.Storage.InstallDir)
|
err = DownloadAndExtractServer(version, ds.cfg.Storage.InstallDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, fmt.Sprintf("Installation failed: %v", err), http.StatusInternalServerError)
|
http.Error(w, fmt.Sprintf("Installation failed: %v", err), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
@@ -303,3 +312,33 @@ func (ds *DaemonServer) handleList(w http.ResponseWriter, r *http.Request) {
|
|||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
json.NewEncoder(w).Encode(responseList)
|
json.NewEncoder(w).Encode(responseList)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ds *DaemonServer) handleGetLogs(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != http.MethodGet {
|
||||||
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
name := r.URL.Query().Get("name")
|
||||||
|
if name == "" {
|
||||||
|
http.Error(w, "Missing name parameter", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ds.procManager.RLock()
|
||||||
|
buf, exists := ds.procManager.LogBuffers[name]
|
||||||
|
ds.procManager.RUnlock()
|
||||||
|
|
||||||
|
if !exists || buf == nil {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.Write([]byte("[]"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
logLines := buf.GetSnapshot()
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
if err := json.NewEncoder(w).Encode(logLines); err != nil {
|
||||||
|
http.Error(w, fmt.Sprintf("Failed encoding log matrix: %v", err), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
7
main.go
7
main.go
@@ -54,12 +54,13 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case "create":
|
case "create":
|
||||||
if len(args) < 3 {
|
if len(args) < 4 {
|
||||||
log.Fatalf("Usage: vssm create <instance_name> <version>")
|
log.Fatalf("Usage: vssm create <instance_name> <version> <port>")
|
||||||
}
|
}
|
||||||
name := args[1]
|
name := args[1]
|
||||||
version := args[2]
|
version := args[2]
|
||||||
sendIPCRequest(cfg, "POST", fmt.Sprintf("/instances/create?name=%s&version=%s", url.QueryEscape(name), url.QueryEscape(version)), nil)
|
port := args[3]
|
||||||
|
sendIPCRequest(cfg, "POST", fmt.Sprintf("/instances/create?name=%s&version=%s&port=%s", url.QueryEscape(name), url.QueryEscape(version), url.QueryEscape(port)), nil)
|
||||||
|
|
||||||
case "start":
|
case "start":
|
||||||
if len(args) < 2 {
|
if len(args) < 2 {
|
||||||
|
|||||||
51
process.go
51
process.go
@@ -15,12 +15,20 @@ type ProcessManager struct {
|
|||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
ActiveInstances map[string]*exec.Cmd
|
ActiveInstances map[string]*exec.Cmd
|
||||||
StdinPipes map[string]io.WriteCloser
|
StdinPipes map[string]io.WriteCloser
|
||||||
|
LogBuffers map[string]*InstanceLogBuffer
|
||||||
|
}
|
||||||
|
|
||||||
|
type InstanceLogBuffer struct {
|
||||||
|
sync.RWMutex
|
||||||
|
Lines []string
|
||||||
|
MaxLines int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewProcessManager() *ProcessManager {
|
func NewProcessManager() *ProcessManager {
|
||||||
return &ProcessManager{
|
return &ProcessManager{
|
||||||
ActiveInstances: make(map[string]*exec.Cmd),
|
ActiveInstances: make(map[string]*exec.Cmd),
|
||||||
StdinPipes: make(map[string]io.WriteCloser),
|
StdinPipes: make(map[string]io.WriteCloser),
|
||||||
|
LogBuffers: map[string]*InstanceLogBuffer{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,6 +74,7 @@ func (pm *ProcessManager) StartInstance(name string, version string, options VsS
|
|||||||
|
|
||||||
pm.ActiveInstances[name] = cmd
|
pm.ActiveInstances[name] = cmd
|
||||||
pm.StdinPipes[name] = stdinPipe
|
pm.StdinPipes[name] = stdinPipe
|
||||||
|
pm.LogBuffers[name] = NewInstanceLogBuffer(200)
|
||||||
|
|
||||||
go pm.streamLogs(name, stdoutPipe)
|
go pm.streamLogs(name, stdoutPipe)
|
||||||
go pm.watchProcessExit(name, cmd)
|
go pm.watchProcessExit(name, cmd)
|
||||||
@@ -79,9 +88,17 @@ func (pm *ProcessManager) streamLogs(name string, stdout io.ReadCloser) {
|
|||||||
scanner := bufio.NewScanner(stdout)
|
scanner := bufio.NewScanner(stdout)
|
||||||
|
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
//stream straight to the manager console terminal,
|
line := scanner.Text()
|
||||||
// but later dispatch payloads to our web UI or a log file
|
|
||||||
fmt.Printf("[%s]: %s\n", name, scanner.Text())
|
fmt.Printf("[%s]: %s\n", name, line)
|
||||||
|
|
||||||
|
pm.RLock()
|
||||||
|
buf, exists := pm.LogBuffers[name]
|
||||||
|
pm.RUnlock()
|
||||||
|
|
||||||
|
if exists {
|
||||||
|
buf.Append(line)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,3 +136,31 @@ func (pm *ProcessManager) SendCommand(name string, command string) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewInstanceLogBuffer(maxLines int) *InstanceLogBuffer {
|
||||||
|
return &InstanceLogBuffer{
|
||||||
|
Lines: make([]string, 0, maxLines),
|
||||||
|
MaxLines: maxLines,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lb *InstanceLogBuffer) Append(line string) {
|
||||||
|
lb.Lock()
|
||||||
|
defer lb.Unlock()
|
||||||
|
|
||||||
|
if len(lb.Lines) >= lb.MaxLines {
|
||||||
|
// Shift array out by dropping index 0
|
||||||
|
lb.Lines = lb.Lines[1:]
|
||||||
|
}
|
||||||
|
lb.Lines = append(lb.Lines, line)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lb *InstanceLogBuffer) GetSnapshot() []string {
|
||||||
|
lb.RLock()
|
||||||
|
defer lb.RUnlock()
|
||||||
|
|
||||||
|
// Return a copy so the caller can safely iterate or serialize to JSON without lock conflicts
|
||||||
|
snapshot := make([]string, len(lb.Lines))
|
||||||
|
copy(snapshot, lb.Lines)
|
||||||
|
return snapshot
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user