Fix getting remote instance logs

This commit is contained in:
2025-10-09 20:22:32 +02:00
parent 9684a8a09b
commit 8a16a195de
4 changed files with 55 additions and 30 deletions

View File

@@ -26,7 +26,7 @@ type InstanceManager interface {
StopInstance(name string) (*instance.Process, error)
EvictLRUInstance() error
RestartInstance(name string) (*instance.Process, error)
GetInstanceLogs(name string) (string, error)
GetInstanceLogs(name string, numLines int) (string, error)
Shutdown()
}
@@ -39,7 +39,7 @@ type RemoteManager interface {
StartRemoteInstance(node *config.NodeConfig, name string) (*instance.Process, error)
StopRemoteInstance(node *config.NodeConfig, name string) (*instance.Process, error)
RestartRemoteInstance(node *config.NodeConfig, name string) (*instance.Process, error)
GetRemoteInstanceLogs(node *config.NodeConfig, name string) (string, error)
GetRemoteInstanceLogs(node *config.NodeConfig, name string, numLines int) (string, error)
}
type instanceManager struct {

View File

@@ -13,15 +13,33 @@ import (
type MaxRunningInstancesError error
// ListInstances returns a list of all instances managed by the instance manager.
// For remote instances, this fetches the live state from remote nodes and updates local stubs.
func (im *instanceManager) ListInstances() ([]*instance.Process, error) {
im.mu.RLock()
defer im.mu.RUnlock()
instances := make([]*instance.Process, 0, len(im.instances))
localInstances := make([]*instance.Process, 0, len(im.instances))
for _, inst := range im.instances {
instances = append(instances, inst)
localInstances = append(localInstances, inst)
}
return instances, nil
im.mu.RUnlock()
// Update remote instances with live state
for _, inst := range localInstances {
if node := im.getNodeForInstance(inst); node != nil {
remoteInst, err := im.GetRemoteInstance(node, inst.Name)
if err != nil {
// Log error but continue with stale data
// Don't fail the entire list operation due to one remote failure
continue
}
// Update the local stub's status to reflect remote state
im.mu.Lock()
inst.Status = remoteInst.Status
im.mu.Unlock()
}
}
return localInstances, nil
}
// CreateInstance creates a new instance with the given options and returns it.
@@ -115,6 +133,7 @@ func (im *instanceManager) CreateInstance(name string, options *instance.CreateI
}
// GetInstance retrieves an instance by its name.
// For remote instances, this fetches the live state from the remote node and updates the local stub.
func (im *instanceManager) GetInstance(name string) (*instance.Process, error) {
im.mu.RLock()
inst, exists := im.instances[name]
@@ -124,9 +143,20 @@ func (im *instanceManager) GetInstance(name string) (*instance.Process, error) {
return nil, fmt.Errorf("instance with name %s not found", name)
}
// Check if instance is remote and delegate to remote operation
// Check if instance is remote and fetch live state
if node := im.getNodeForInstance(inst); node != nil {
return im.GetRemoteInstance(node, name)
remoteInst, err := im.GetRemoteInstance(node, name)
if err != nil {
return nil, err
}
// Update the local stub's status to reflect remote state
im.mu.Lock()
inst.Status = remoteInst.Status
im.mu.Unlock()
// Return the local stub (preserving Nodes field)
return inst, nil
}
return inst, nil
@@ -401,7 +431,7 @@ func (im *instanceManager) RestartInstance(name string) (*instance.Process, erro
}
// GetInstanceLogs retrieves the logs for a specific instance by its name.
func (im *instanceManager) GetInstanceLogs(name string) (string, error) {
func (im *instanceManager) GetInstanceLogs(name string, numLines int) (string, error) {
im.mu.RLock()
inst, exists := im.instances[name]
im.mu.RUnlock()
@@ -412,11 +442,11 @@ func (im *instanceManager) GetInstanceLogs(name string) (string, error) {
// Check if instance is remote and delegate to remote operation
if node := im.getNodeForInstance(inst); node != nil {
return im.GetRemoteInstanceLogs(node, name)
return im.GetRemoteInstanceLogs(node, name, numLines)
}
// TODO: Implement actual log retrieval logic
return fmt.Sprintf("Logs for instance %s", name), nil
// Get logs from the local instance
return inst.GetLogs(numLines)
}
// getPortFromOptions extracts the port from backend-specific options

View File

@@ -211,8 +211,8 @@ func (im *instanceManager) RestartRemoteInstance(nodeConfig *config.NodeConfig,
}
// GetRemoteInstanceLogs retrieves logs for an instance from the remote node
func (im *instanceManager) GetRemoteInstanceLogs(nodeConfig *config.NodeConfig, name string) (string, error) {
path := fmt.Sprintf("/api/v1/instances/%s/logs", name)
func (im *instanceManager) GetRemoteInstanceLogs(nodeConfig *config.NodeConfig, name string, numLines int) (string, error) {
path := fmt.Sprintf("/api/v1/instances/%s/logs?lines=%d", name, numLines)
resp, err := im.makeRemoteRequest(nodeConfig, "GET", path, nil)
if err != nil {
return "", err

View File

@@ -308,23 +308,18 @@ func (h *Handler) GetInstanceLogs() http.HandlerFunc {
}
lines := r.URL.Query().Get("lines")
if lines == "" {
lines = "-1"
}
num_lines, err := strconv.Atoi(lines)
numLines := -1 // Default to all lines
if lines != "" {
parsedLines, err := strconv.Atoi(lines)
if err != nil {
http.Error(w, "Invalid lines parameter: "+err.Error(), http.StatusBadRequest)
return
}
inst, err := h.InstanceManager.GetInstance(name)
if err != nil {
http.Error(w, "Failed to get instance: "+err.Error(), http.StatusInternalServerError)
return
numLines = parsedLines
}
logs, err := inst.GetLogs(num_lines)
// Use the instance manager which handles both local and remote instances
logs, err := h.InstanceManager.GetInstanceLogs(name, numLines)
if err != nil {
http.Error(w, "Failed to get logs: "+err.Error(), http.StatusInternalServerError)
return