Add screenshots and update gitignore for alpha release
- Fixed gitignore to allow Screenshots/*.png files - Added all screenshots for README documentation - Fixed gitignore to be less restrictive with image files - Includes dashboard, agent, updates, and docker screenshots
This commit is contained in:
@@ -12,7 +12,9 @@ import (
|
||||
"github.com/aggregator-project/aggregator-agent/internal/client"
|
||||
"github.com/aggregator-project/aggregator-agent/internal/config"
|
||||
"github.com/aggregator-project/aggregator-agent/internal/display"
|
||||
"github.com/aggregator-project/aggregator-agent/internal/installer"
|
||||
"github.com/aggregator-project/aggregator-agent/internal/scanner"
|
||||
"github.com/aggregator-project/aggregator-agent/internal/system"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
@@ -41,8 +43,16 @@ func main() {
|
||||
if err := registerAgent(cfg, *serverURL); err != nil {
|
||||
log.Fatal("Registration failed:", err)
|
||||
}
|
||||
fmt.Println("✓ Agent registered successfully!")
|
||||
fmt.Printf("Agent ID: %s\n", cfg.AgentID)
|
||||
fmt.Println("==================================================================")
|
||||
fmt.Println("🎉 AGENT REGISTRATION SUCCESSFUL!")
|
||||
fmt.Println("==================================================================")
|
||||
fmt.Printf("📋 Agent ID: %s\n", cfg.AgentID)
|
||||
fmt.Printf("🌐 Server: %s\n", cfg.ServerURL)
|
||||
fmt.Printf("⏱️ Check-in Interval: %ds\n", cfg.CheckInInterval)
|
||||
fmt.Println("==================================================================")
|
||||
fmt.Println("💡 Save this Agent ID for your records!")
|
||||
fmt.Println("🚀 You can now start the agent without flags")
|
||||
fmt.Println("")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -82,20 +92,64 @@ func main() {
|
||||
}
|
||||
|
||||
func registerAgent(cfg *config.Config, serverURL string) error {
|
||||
hostname, _ := os.Hostname()
|
||||
osType, osVersion, osArch := client.DetectSystem()
|
||||
// Get detailed system information
|
||||
sysInfo, err := system.GetSystemInfo(AgentVersion)
|
||||
if err != nil {
|
||||
log.Printf("Warning: Failed to get detailed system info: %v\n", err)
|
||||
// Fall back to basic detection
|
||||
hostname, _ := os.Hostname()
|
||||
osType, osVersion, osArch := client.DetectSystem()
|
||||
sysInfo = &system.SystemInfo{
|
||||
Hostname: hostname,
|
||||
OSType: osType,
|
||||
OSVersion: osVersion,
|
||||
OSArchitecture: osArch,
|
||||
AgentVersion: AgentVersion,
|
||||
Metadata: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
apiClient := client.NewClient(serverURL, "")
|
||||
|
||||
// Create metadata with system information
|
||||
metadata := map[string]string{
|
||||
"installation_time": time.Now().Format(time.RFC3339),
|
||||
}
|
||||
|
||||
// Add system info to metadata
|
||||
if sysInfo.CPUInfo.ModelName != "" {
|
||||
metadata["cpu_model"] = sysInfo.CPUInfo.ModelName
|
||||
}
|
||||
if sysInfo.CPUInfo.Cores > 0 {
|
||||
metadata["cpu_cores"] = fmt.Sprintf("%d", sysInfo.CPUInfo.Cores)
|
||||
}
|
||||
if sysInfo.MemoryInfo.Total > 0 {
|
||||
metadata["memory_total"] = fmt.Sprintf("%d", sysInfo.MemoryInfo.Total)
|
||||
}
|
||||
if sysInfo.RunningProcesses > 0 {
|
||||
metadata["processes"] = fmt.Sprintf("%d", sysInfo.RunningProcesses)
|
||||
}
|
||||
if sysInfo.Uptime != "" {
|
||||
metadata["uptime"] = sysInfo.Uptime
|
||||
}
|
||||
|
||||
// Add disk information
|
||||
for i, disk := range sysInfo.DiskInfo {
|
||||
if i == 0 {
|
||||
metadata["disk_mount"] = disk.Mountpoint
|
||||
metadata["disk_total"] = fmt.Sprintf("%d", disk.Total)
|
||||
metadata["disk_used"] = fmt.Sprintf("%d", disk.Used)
|
||||
break // Only add primary disk info
|
||||
}
|
||||
}
|
||||
|
||||
req := client.RegisterRequest{
|
||||
Hostname: hostname,
|
||||
OSType: osType,
|
||||
OSVersion: osVersion,
|
||||
OSArchitecture: osArch,
|
||||
AgentVersion: AgentVersion,
|
||||
Metadata: map[string]string{
|
||||
"installation_time": time.Now().Format(time.RFC3339),
|
||||
},
|
||||
Hostname: sysInfo.Hostname,
|
||||
OSType: sysInfo.OSType,
|
||||
OSVersion: sysInfo.OSVersion,
|
||||
OSArchitecture: sysInfo.OSArchitecture,
|
||||
AgentVersion: sysInfo.AgentVersion,
|
||||
Metadata: metadata,
|
||||
}
|
||||
|
||||
resp, err := apiClient.Register(req)
|
||||
@@ -121,14 +175,19 @@ func registerAgent(cfg *config.Config, serverURL string) error {
|
||||
|
||||
func runAgent(cfg *config.Config) error {
|
||||
log.Printf("🚩 RedFlag Agent v%s starting...\n", AgentVersion)
|
||||
log.Printf("Agent ID: %s\n", cfg.AgentID)
|
||||
log.Printf("Server: %s\n", cfg.ServerURL)
|
||||
log.Printf("Check-in interval: %ds\n", cfg.CheckInInterval)
|
||||
log.Printf("==================================================================")
|
||||
log.Printf("📋 AGENT ID: %s", cfg.AgentID)
|
||||
log.Printf("🌐 SERVER: %s", cfg.ServerURL)
|
||||
log.Printf("⏱️ CHECK-IN INTERVAL: %ds", cfg.CheckInInterval)
|
||||
log.Printf("==================================================================")
|
||||
log.Printf("💡 Tip: Use this Agent ID to identify this agent in the web UI")
|
||||
log.Printf("")
|
||||
|
||||
apiClient := client.NewClient(cfg.ServerURL, cfg.Token)
|
||||
|
||||
// Initialize scanners
|
||||
aptScanner := scanner.NewAPTScanner()
|
||||
dnfScanner := scanner.NewDNFScanner()
|
||||
dockerScanner, _ := scanner.NewDockerScanner()
|
||||
|
||||
// Main check-in loop
|
||||
@@ -153,7 +212,7 @@ func runAgent(cfg *config.Config) error {
|
||||
|
||||
switch cmd.Type {
|
||||
case "scan_updates":
|
||||
if err := handleScanUpdates(apiClient, cfg, aptScanner, dockerScanner, cmd.ID); err != nil {
|
||||
if err := handleScanUpdates(apiClient, cfg, aptScanner, dnfScanner, dockerScanner, cmd.ID); err != nil {
|
||||
log.Printf("Error scanning updates: %v\n", err)
|
||||
}
|
||||
|
||||
@@ -161,7 +220,9 @@ func runAgent(cfg *config.Config) error {
|
||||
log.Println("Spec collection not yet implemented")
|
||||
|
||||
case "install_updates":
|
||||
log.Println("Update installation not yet implemented")
|
||||
if err := handleInstallUpdates(apiClient, cfg, cmd.ID, cmd.Params); err != nil {
|
||||
log.Printf("Error installing updates: %v\n", err)
|
||||
}
|
||||
|
||||
default:
|
||||
log.Printf("Unknown command type: %s\n", cmd.Type)
|
||||
@@ -173,7 +234,7 @@ func runAgent(cfg *config.Config) error {
|
||||
}
|
||||
}
|
||||
|
||||
func handleScanUpdates(apiClient *client.Client, cfg *config.Config, aptScanner *scanner.APTScanner, dockerScanner *scanner.DockerScanner, commandID string) error {
|
||||
func handleScanUpdates(apiClient *client.Client, cfg *config.Config, aptScanner *scanner.APTScanner, dnfScanner *scanner.DNFScanner, dockerScanner *scanner.DockerScanner, commandID string) error {
|
||||
log.Println("Scanning for updates...")
|
||||
|
||||
var allUpdates []client.UpdateReportItem
|
||||
@@ -190,6 +251,18 @@ func handleScanUpdates(apiClient *client.Client, cfg *config.Config, aptScanner
|
||||
}
|
||||
}
|
||||
|
||||
// Scan DNF updates
|
||||
if dnfScanner.IsAvailable() {
|
||||
log.Println(" - Scanning DNF packages...")
|
||||
updates, err := dnfScanner.Scan()
|
||||
if err != nil {
|
||||
log.Printf(" DNF scan failed: %v\n", err)
|
||||
} else {
|
||||
log.Printf(" Found %d DNF updates\n", len(updates))
|
||||
allUpdates = append(allUpdates, updates...)
|
||||
}
|
||||
}
|
||||
|
||||
// Scan Docker updates
|
||||
if dockerScanner != nil && dockerScanner.IsAvailable() {
|
||||
log.Println(" - Scanning Docker images...")
|
||||
@@ -226,6 +299,7 @@ func handleScanUpdates(apiClient *client.Client, cfg *config.Config, aptScanner
|
||||
func handleScanCommand(cfg *config.Config, exportFormat string) error {
|
||||
// Initialize scanners
|
||||
aptScanner := scanner.NewAPTScanner()
|
||||
dnfScanner := scanner.NewDNFScanner()
|
||||
dockerScanner, _ := scanner.NewDockerScanner()
|
||||
|
||||
fmt.Println("🔍 Scanning for updates...")
|
||||
@@ -243,6 +317,18 @@ func handleScanCommand(cfg *config.Config, exportFormat string) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Scan DNF updates
|
||||
if dnfScanner.IsAvailable() {
|
||||
fmt.Println(" - Scanning DNF packages...")
|
||||
updates, err := dnfScanner.Scan()
|
||||
if err != nil {
|
||||
fmt.Printf(" ⚠️ DNF scan failed: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf(" ✓ Found %d DNF updates\n", len(updates))
|
||||
allUpdates = append(allUpdates, updates...)
|
||||
}
|
||||
}
|
||||
|
||||
// Scan Docker updates
|
||||
if dockerScanner != nil && dockerScanner.IsAvailable() {
|
||||
fmt.Println(" - Scanning Docker images...")
|
||||
@@ -345,6 +431,128 @@ func handleListUpdatesCommand(cfg *config.Config, exportFormat string) error {
|
||||
return display.PrintDetailedUpdates(localCache.Updates, exportFormat)
|
||||
}
|
||||
|
||||
// handleInstallUpdates handles install_updates command
|
||||
func handleInstallUpdates(apiClient *client.Client, cfg *config.Config, commandID string, params map[string]interface{}) error {
|
||||
log.Println("Installing updates...")
|
||||
|
||||
// Parse parameters
|
||||
packageType := ""
|
||||
packageName := ""
|
||||
targetVersion := ""
|
||||
|
||||
if pt, ok := params["package_type"].(string); ok {
|
||||
packageType = pt
|
||||
}
|
||||
if pn, ok := params["package_name"].(string); ok {
|
||||
packageName = pn
|
||||
}
|
||||
if tv, ok := params["target_version"].(string); ok {
|
||||
targetVersion = tv
|
||||
}
|
||||
|
||||
// Validate package type
|
||||
if packageType == "" {
|
||||
return fmt.Errorf("package_type parameter is required")
|
||||
}
|
||||
|
||||
// Create installer based on package type
|
||||
inst, err := installer.InstallerFactory(packageType)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create installer for package type %s: %w", packageType, err)
|
||||
}
|
||||
|
||||
// Check if installer is available
|
||||
if !inst.IsAvailable() {
|
||||
return fmt.Errorf("%s installer is not available on this system", packageType)
|
||||
}
|
||||
|
||||
var result *installer.InstallResult
|
||||
var action string
|
||||
|
||||
// Perform installation based on what's specified
|
||||
if packageName != "" {
|
||||
action = "install"
|
||||
log.Printf("Installing package: %s (type: %s)", packageName, packageType)
|
||||
result, err = inst.Install(packageName)
|
||||
} else if len(params) > 1 {
|
||||
// Multiple packages might be specified in various ways
|
||||
var packageNames []string
|
||||
for key, value := range params {
|
||||
if key != "package_type" && key != "target_version" {
|
||||
if name, ok := value.(string); ok && name != "" {
|
||||
packageNames = append(packageNames, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(packageNames) > 0 {
|
||||
action = "install_multiple"
|
||||
log.Printf("Installing multiple packages: %v (type: %s)", packageNames, packageType)
|
||||
result, err = inst.InstallMultiple(packageNames)
|
||||
} else {
|
||||
// Upgrade all packages if no specific packages named
|
||||
action = "upgrade"
|
||||
log.Printf("Upgrading all packages (type: %s)", packageType)
|
||||
result, err = inst.Upgrade()
|
||||
}
|
||||
} else {
|
||||
// Upgrade all packages if no specific packages named
|
||||
action = "upgrade"
|
||||
log.Printf("Upgrading all packages (type: %s)", packageType)
|
||||
result, err = inst.Upgrade()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
// Report installation failure
|
||||
logReport := client.LogReport{
|
||||
CommandID: commandID,
|
||||
Action: action,
|
||||
Result: "failed",
|
||||
Stdout: "",
|
||||
Stderr: fmt.Sprintf("Installation error: %v", err),
|
||||
ExitCode: 1,
|
||||
DurationSeconds: 0,
|
||||
}
|
||||
|
||||
if reportErr := apiClient.ReportLog(cfg.AgentID, logReport); reportErr != nil {
|
||||
log.Printf("Failed to report installation failure: %v\n", reportErr)
|
||||
}
|
||||
|
||||
return fmt.Errorf("installation failed: %w", err)
|
||||
}
|
||||
|
||||
// Report installation success
|
||||
logReport := client.LogReport{
|
||||
CommandID: commandID,
|
||||
Action: result.Action,
|
||||
Result: "success",
|
||||
Stdout: result.Stdout,
|
||||
Stderr: result.Stderr,
|
||||
ExitCode: result.ExitCode,
|
||||
DurationSeconds: result.DurationSeconds,
|
||||
}
|
||||
|
||||
// Add additional metadata to the log report
|
||||
if len(result.PackagesInstalled) > 0 {
|
||||
logReport.Stdout += fmt.Sprintf("\nPackages installed: %v", result.PackagesInstalled)
|
||||
}
|
||||
|
||||
if reportErr := apiClient.ReportLog(cfg.AgentID, logReport); reportErr != nil {
|
||||
log.Printf("Failed to report installation success: %v\n", reportErr)
|
||||
}
|
||||
|
||||
if result.Success {
|
||||
log.Printf("✓ Installation completed successfully in %d seconds\n", result.DurationSeconds)
|
||||
if len(result.PackagesInstalled) > 0 {
|
||||
log.Printf(" Packages installed: %v\n", result.PackagesInstalled)
|
||||
}
|
||||
} else {
|
||||
log.Printf("✗ Installation failed after %d seconds\n", result.DurationSeconds)
|
||||
log.Printf(" Error: %s\n", result.ErrorMessage)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// formatTimeSince formats a duration as "X time ago"
|
||||
func formatTimeSince(t time.Time) string {
|
||||
duration := time.Since(t)
|
||||
|
||||
Reference in New Issue
Block a user