Update README with current features and screenshots
- Cross-platform support (Windows/Linux) with Windows Updates and Winget - Added dependency confirmation workflow and refresh token authentication - New screenshots: History, Live Operations, Windows Agent Details - Local CLI features with terminal output and cache system - Updated known limitations - Proxmox integration is broken - Organized docs to docs/ folder and updated .gitignore - Probably introduced a dozen bugs with Windows agents - stay tuned
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package queries
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/aggregator-project/aggregator-server/internal/models"
|
||||
@@ -77,3 +78,168 @@ func (q *CommandQueries) MarkCommandFailed(id uuid.UUID, result models.JSONB) er
|
||||
_, err := q.db.Exec(query, now, result, id)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetCommandsByStatus retrieves commands with a specific status
|
||||
func (q *CommandQueries) GetCommandsByStatus(status string) ([]models.AgentCommand, error) {
|
||||
var commands []models.AgentCommand
|
||||
query := `
|
||||
SELECT * FROM agent_commands
|
||||
WHERE status = $1
|
||||
ORDER BY created_at DESC
|
||||
`
|
||||
err := q.db.Select(&commands, query, status)
|
||||
return commands, err
|
||||
}
|
||||
|
||||
// UpdateCommandStatus updates only the status of a command
|
||||
func (q *CommandQueries) UpdateCommandStatus(id uuid.UUID, status string) error {
|
||||
query := `
|
||||
UPDATE agent_commands
|
||||
SET status = $1
|
||||
WHERE id = $2
|
||||
`
|
||||
_, err := q.db.Exec(query, status, id)
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateCommandResult updates only the result of a command
|
||||
func (q *CommandQueries) UpdateCommandResult(id uuid.UUID, result interface{}) error {
|
||||
query := `
|
||||
UPDATE agent_commands
|
||||
SET result = $1
|
||||
WHERE id = $2
|
||||
`
|
||||
_, err := q.db.Exec(query, result, id)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetCommandByID retrieves a specific command by ID
|
||||
func (q *CommandQueries) GetCommandByID(id uuid.UUID) (*models.AgentCommand, error) {
|
||||
var command models.AgentCommand
|
||||
query := `
|
||||
SELECT * FROM agent_commands
|
||||
WHERE id = $1
|
||||
`
|
||||
err := q.db.Get(&command, query, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &command, nil
|
||||
}
|
||||
|
||||
// CancelCommand marks a command as cancelled
|
||||
func (q *CommandQueries) CancelCommand(id uuid.UUID) error {
|
||||
now := time.Now()
|
||||
query := `
|
||||
UPDATE agent_commands
|
||||
SET status = 'cancelled', completed_at = $1
|
||||
WHERE id = $2 AND status IN ('pending', 'sent')
|
||||
`
|
||||
_, err := q.db.Exec(query, now, id)
|
||||
return err
|
||||
}
|
||||
|
||||
// RetryCommand creates a new command based on a failed/timed_out/cancelled command
|
||||
func (q *CommandQueries) RetryCommand(originalID uuid.UUID) (*models.AgentCommand, error) {
|
||||
// Get the original command
|
||||
original, err := q.GetCommandByID(originalID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Only allow retry of failed, timed_out, or cancelled commands
|
||||
if original.Status != "failed" && original.Status != "timed_out" && original.Status != "cancelled" {
|
||||
return nil, fmt.Errorf("command must be failed, timed_out, or cancelled to retry")
|
||||
}
|
||||
|
||||
// Create new command with same parameters
|
||||
newCommand := &models.AgentCommand{
|
||||
ID: uuid.New(),
|
||||
AgentID: original.AgentID,
|
||||
CommandType: original.CommandType,
|
||||
Params: original.Params,
|
||||
Status: models.CommandStatusPending,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
|
||||
// Store the new command
|
||||
if err := q.CreateCommand(newCommand); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newCommand, nil
|
||||
}
|
||||
|
||||
// GetActiveCommands retrieves commands that are not in a final/terminal state
|
||||
// Shows anything that's in progress or can be retried (excludes completed and cancelled)
|
||||
func (q *CommandQueries) GetActiveCommands() ([]models.ActiveCommandInfo, error) {
|
||||
var commands []models.ActiveCommandInfo
|
||||
|
||||
query := `
|
||||
SELECT
|
||||
c.id,
|
||||
c.agent_id,
|
||||
c.command_type,
|
||||
c.status,
|
||||
c.created_at,
|
||||
c.sent_at,
|
||||
c.result,
|
||||
a.hostname as agent_hostname,
|
||||
COALESCE(ups.package_name, 'N/A') as package_name,
|
||||
COALESCE(ups.package_type, 'N/A') as package_type
|
||||
FROM agent_commands c
|
||||
LEFT JOIN agents a ON c.agent_id = a.id
|
||||
LEFT JOIN current_package_state ups ON (
|
||||
c.params->>'update_id' = ups.id::text OR
|
||||
(c.params->>'package_name' = ups.package_name AND c.params->>'package_type' = ups.package_type)
|
||||
)
|
||||
WHERE c.status NOT IN ('completed', 'cancelled')
|
||||
ORDER BY c.created_at DESC
|
||||
`
|
||||
|
||||
err := q.db.Select(&commands, query)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get active commands: %w", err)
|
||||
}
|
||||
|
||||
return commands, nil
|
||||
}
|
||||
|
||||
// GetRecentCommands retrieves recent commands (including failed, completed, etc.) for retry functionality
|
||||
func (q *CommandQueries) GetRecentCommands(limit int) ([]models.ActiveCommandInfo, error) {
|
||||
var commands []models.ActiveCommandInfo
|
||||
|
||||
if limit == 0 {
|
||||
limit = 50 // Default limit
|
||||
}
|
||||
|
||||
query := `
|
||||
SELECT
|
||||
c.id,
|
||||
c.agent_id,
|
||||
c.command_type,
|
||||
c.status,
|
||||
c.created_at,
|
||||
c.sent_at,
|
||||
c.completed_at,
|
||||
c.result,
|
||||
a.hostname as agent_hostname,
|
||||
COALESCE(ups.package_name, 'N/A') as package_name,
|
||||
COALESCE(ups.package_type, 'N/A') as package_type
|
||||
FROM agent_commands c
|
||||
LEFT JOIN agents a ON c.agent_id = a.id
|
||||
LEFT JOIN current_package_state ups ON (
|
||||
c.params->>'update_id' = ups.id::text OR
|
||||
(c.params->>'package_name' = ups.package_name AND c.params->>'package_type' = ups.package_type)
|
||||
)
|
||||
ORDER BY c.created_at DESC
|
||||
LIMIT $1
|
||||
`
|
||||
|
||||
err := q.db.Select(&commands, query, limit)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get recent commands: %w", err)
|
||||
}
|
||||
|
||||
return commands, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user