package main import ( "context" "database/sql" "encoding/base64" "encoding/json" "fmt" "log" "net/http" "time" _ "github.com/mattn/go-sqlite3" ) // Test-Skript für Renewal-Funktion // Erstellt Test-Queue-Einträge mit vergangenen Zeitstempeln, um sofortige Tests zu ermöglichen func main() { // Konfiguration // Datenbankpfad relativ zum backend-Verzeichnis (2 Ebenen höher) dbPath := "../../spaces.db" apiURL := "http://localhost:8080" username := "admin" password := "admin" // Öffne Datenbank db, err := sql.Open("sqlite3", dbPath+"?_foreign_keys=1&_journal_mode=WAL") if err != nil { log.Fatalf("Fehler beim Öffnen der Datenbank: %v", err) } defer db.Close() // Teste Verbindung ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := db.PingContext(ctx); err != nil { log.Fatalf("Fehler beim Verbinden mit der Datenbank: %v", err) } fmt.Println("=== Renewal Test-Skript ===") fmt.Println() // 1. Hole existierende FQDNs mit Zertifikaten fmt.Println("1. Suche nach FQDNs mit Zertifikaten...") rows, err := db.QueryContext(ctx, ` SELECT DISTINCT f.id as fqdn_id, f.space_id, f.fqdn, c.id as cert_id FROM fqdns f INNER JOIN certificates c ON c.fqdn_id = f.id WHERE f.acme_provider_id = 'certigo-acmeproxy' LIMIT 5 `) if err != nil { log.Fatalf("Fehler beim Abfragen der FQDNs: %v", err) } defer rows.Close() var fqdns []map[string]string for rows.Next() { var fqdnID, spaceID, fqdn, certID string if err := rows.Scan(&fqdnID, &spaceID, &fqdn, &certID); err != nil { log.Printf("Fehler beim Scannen: %v", err) continue } fqdns = append(fqdns, map[string]string{ "fqdnId": fqdnID, "spaceId": spaceID, "fqdn": fqdn, "certId": certID, }) } if len(fqdns) == 0 { log.Fatal("Keine FQDNs mit Zertifikaten gefunden. Bitte erstelle zuerst ein Zertifikat.") } fmt.Printf(" Gefunden: %d FQDNs\n", len(fqdns)) for _, f := range fqdns { fmt.Printf(" - %s (FQDN ID: %s, Cert ID: %s)\n", f["fqdn"], f["fqdnId"], f["certId"]) } fmt.Println() // 2. Erstelle Test-Queue-Einträge mit vergangenen Zeitstempeln fmt.Println("2. Erstelle Test-Queue-Einträge...") now := time.Now().UTC() // Erstelle Einträge mit verschiedenen Zeitstempeln: // - Einer sofort fällig (vor 1 Minute) // - Einer in 5 Minuten // - Einer in 10 Minuten testTimes := []time.Time{ now.Add(-1 * time.Minute), // Sofort fällig now.Add(5 * time.Minute), // In 5 Minuten now.Add(10 * time.Minute), // In 10 Minuten } createdCount := 0 for i, fqdn := range fqdns { if i >= len(testTimes) { break } scheduledAt := testTimes[i] scheduledAtStr := scheduledAt.Format("2006-01-02 15:04:05") queueID := fmt.Sprintf("test-%d-%d", time.Now().Unix(), i) createdAt := now.Format("2006-01-02 15:04:05") // Prüfe ob Eintrag bereits existiert var exists bool err = db.QueryRowContext(ctx, "SELECT EXISTS(SELECT 1 FROM renewal_queue WHERE id = ?)", queueID).Scan(&exists) if err != nil { log.Printf("Fehler beim Prüfen: %v", err) continue } if exists { // Lösche existierenden Eintrag _, err = db.ExecContext(ctx, "DELETE FROM renewal_queue WHERE id = ?", queueID) if err != nil { log.Printf("Fehler beim Löschen: %v", err) continue } } // Erstelle neuen Eintrag _, err = db.ExecContext(ctx, ` INSERT INTO renewal_queue (id, certificate_id, fqdn_id, space_id, scheduled_at, status, created_at) VALUES (?, ?, ?, ?, ?, 'pending', ?) `, queueID, fqdn["certId"], fqdn["fqdnId"], fqdn["spaceId"], scheduledAtStr, createdAt) if err != nil { log.Printf("Fehler beim Erstellen des Queue-Eintrags: %v", err) continue } fmt.Printf(" ✓ Queue-Eintrag erstellt: %s für %s (geplant: %s)\n", queueID, fqdn["fqdn"], scheduledAtStr) createdCount++ } fmt.Printf("\n %d Queue-Einträge erstellt\n", createdCount) fmt.Println() // 3. Zeige Queue-Status fmt.Println("3. Aktuelle Queue-Status:") queueRows, err := db.QueryContext(ctx, ` SELECT rq.id, rq.scheduled_at, rq.status, f.fqdn FROM renewal_queue rq LEFT JOIN fqdns f ON rq.fqdn_id = f.id WHERE rq.id LIKE 'test-%' ORDER BY rq.scheduled_at ASC `) if err != nil { log.Printf("Fehler beim Abfragen der Queue: %v", err) } else { defer queueRows.Close() for queueRows.Next() { var id, scheduledAt, status, fqdn string if err := queueRows.Scan(&id, &scheduledAt, &status, &fqdn); err != nil { continue } fmt.Printf(" - %s: %s (Status: %s, FQDN: %s)\n", id, scheduledAt, status, fqdn) } } fmt.Println() // 4. Teste API-Endpunkt (manueller Trigger) fmt.Println("4. Teste manuellen Queue-Trigger über API...") fmt.Println(" (Dies würde normalerweise automatisch vom Scheduler ausgeführt)") fmt.Println() // Erstelle Basic Auth Header auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password))) // Teste Queue-Status über API client := &http.Client{Timeout: 10 * time.Second} req, err := http.NewRequest("GET", apiURL+"/api/renewal-queue", nil) if err != nil { log.Printf("Fehler beim Erstellen des Requests: %v", err) } else { req.Header.Set("Authorization", fmt.Sprintf("Basic %s", auth)) resp, err := client.Do(req) if err != nil { log.Printf("Fehler beim Abrufen der Queue: %v", err) } else { defer resp.Body.Close() if resp.StatusCode == http.StatusOK { var result struct { Success bool `json:"success"` Queue []map[string]interface{} `json:"queue"` } if err := json.NewDecoder(resp.Body).Decode(&result); err == nil { fmt.Printf(" ✓ API-Antwort erhalten: %d Einträge in der Queue\n", len(result.Queue)) for _, item := range result.Queue { if id, ok := item["id"].(string); ok && len(id) > 5 && id[:5] == "test-" { fmt.Printf(" - Test-Eintrag: %s (Status: %v, Scheduled: %v)\n", id, item["status"], item["scheduledAt"]) } } } } } } fmt.Println() fmt.Println("=== Test abgeschlossen ===") fmt.Println() fmt.Println("Nächste Schritte:") fmt.Println("1. Der Scheduler sollte automatisch die fälligen Einträge verarbeiten (alle 5 Minuten)") fmt.Println("2. Oder warte auf die nächste Scheduler-Ausführung") fmt.Println("3. Prüfe die Logs für Verarbeitungsdetails") fmt.Println() fmt.Println("Zum Aufräumen der Test-Einträge:") fmt.Println(" DELETE FROM renewal_queue WHERE id LIKE 'test-%';") }