using HanaToolbox.Config; using Spectre.Console; namespace HanaToolbox.Tui; /// /// TUI wizard for configuring cron task schedules and settings. /// Saves results back to the provided AppConfig (caller is responsible for persisting). /// public sealed class CronSetupTui { public AppConfig Run(AppConfig current) { AnsiConsole.Clear(); AnsiConsole.Write(new Rule("[cyan]Cron Task Configuration[/]").RuleStyle("cyan")); AnsiConsole.MarkupLine("[grey]Configure which tasks run automatically and when.[/]\n"); ConfigureBackup(current.Backup); ConfigureCleaner(current.Cleaner); ConfigureAurora(current.Aurora, current.Hana); ConfigureFirewall(current.Firewall); ConfigureMonitor(current.Monitor); return current; } private static void ConfigureBackup(BackupConfig b) { AnsiConsole.Write(new Rule("[green]Backup[/]").RuleStyle("green")); b.Enabled = AnsiConsole.Confirm("Enable scheduled backup?", b.Enabled); if (!b.Enabled) { AnsiConsole.WriteLine(); return; } b.ScheduleHour = AnsiConsole.Prompt(new TextPrompt("Run hour (0-23):").DefaultValue(b.ScheduleHour)); b.ScheduleMinute = AnsiConsole.Prompt(new TextPrompt("Run minute (0-59):").DefaultValue(b.ScheduleMinute)); var typeStr = AnsiConsole.Prompt( new SelectionPrompt() .Title("Backup type:") .AddChoices("All", "Tenant", "Schema") .HighlightStyle("cyan")); b.Type = Enum.Parse(typeStr); b.UserKey = AnsiConsole.Prompt(new TextPrompt("hdbuserstore key:").DefaultValue(b.UserKey)); b.BackupBasePath = AnsiConsole.Prompt(new TextPrompt("Tenant backup path:").DefaultValue(b.BackupBasePath)); b.Compress = AnsiConsole.Confirm("Compress tenant backup?", b.Compress); if (b.Type is BackupType.Schema or BackupType.All) { b.SchemaBackupPath = AnsiConsole.Prompt(new TextPrompt("Schema backup path:").DefaultValue(b.SchemaBackupPath)); b.CompressSchema = AnsiConsole.Confirm("Compress schema backup?", b.CompressSchema); var schemas = AnsiConsole.Prompt(new TextPrompt("Schema names (comma-separated):") .DefaultValue(string.Join(",", b.SchemaNames))); b.SchemaNames = schemas.Split(',', StringSplitOptions.RemoveEmptyEntries) .Select(s => s.Trim()).ToList(); } b.BackupSystemDb = AnsiConsole.Confirm("Also backup SYSTEMDB?", b.BackupSystemDb); if (b.BackupSystemDb) b.SystemDbUserKey = AnsiConsole.Prompt( new TextPrompt("SYSTEMDB hdbuserstore key:").DefaultValue(b.SystemDbUserKey)); AnsiConsole.WriteLine(); } private static void ConfigureCleaner(CleanerConfig c) { AnsiConsole.Write(new Rule("[green]Cleaner[/]").RuleStyle("green")); c.Enabled = AnsiConsole.Confirm("Enable scheduled cleanup?", c.Enabled); if (!c.Enabled) { AnsiConsole.WriteLine(); return; } c.ScheduleHour = AnsiConsole.Prompt(new TextPrompt("Run hour (0-23):").DefaultValue(c.ScheduleHour)); c.ScheduleMinute = AnsiConsole.Prompt(new TextPrompt("Run minute (0-59):").DefaultValue(c.ScheduleMinute)); c.TenantBackupPath = AnsiConsole.Prompt(new TextPrompt("Tenant backup path:").DefaultValue(c.TenantBackupPath)); c.TenantRetentionDays = AnsiConsole.Prompt(new TextPrompt("Tenant retention (days):").DefaultValue(c.TenantRetentionDays)); c.LogRetentionDays = AnsiConsole.Prompt(new TextPrompt("Log backup retention (days):").DefaultValue(c.LogRetentionDays)); AnsiConsole.MarkupLine("[grey]Current log backup paths:[/]"); c.LogBackupPaths.ForEach(p => AnsiConsole.MarkupLine($" [grey]- {p}[/]")); while (AnsiConsole.Confirm("Add a log backup path?", defaultValue: c.LogBackupPaths.Count == 0)) { var p = AnsiConsole.Prompt(new TextPrompt("Log backup path:")); if (!string.IsNullOrWhiteSpace(p)) c.LogBackupPaths.Add(p); } AnsiConsole.WriteLine(); } private static void ConfigureAurora(AuroraConfig a, HanaConfig hana) { AnsiConsole.Write(new Rule("[green]Aurora[/]").RuleStyle("green")); a.Enabled = AnsiConsole.Confirm("Enable Aurora schema refresh?", a.Enabled); if (!a.Enabled) { AnsiConsole.WriteLine(); return; } a.ScheduleHour = AnsiConsole.Prompt(new TextPrompt("Run hour (0-23):").DefaultValue(a.ScheduleHour)); a.ScheduleMinute = AnsiConsole.Prompt(new TextPrompt("Run minute (0-59):").DefaultValue(a.ScheduleMinute)); a.AdminUserKey = AnsiConsole.Prompt(new TextPrompt("Admin hdbuserstore key:").DefaultValue(a.AdminUserKey)); a.SourceSchema = AnsiConsole.Prompt(new TextPrompt("Source schema name:").DefaultValue(a.SourceSchema)); a.AuroraUser = AnsiConsole.Prompt(new TextPrompt("Aurora target user:").DefaultValue(a.AuroraUser)); a.BackupBasePath = AnsiConsole.Prompt(new TextPrompt("Temp export base path:").DefaultValue(a.BackupBasePath)); AnsiConsole.WriteLine(); } private static void ConfigureFirewall(FirewallConfig f) { AnsiConsole.Write(new Rule("[green]Firewall[/]").RuleStyle("green")); f.Enabled = AnsiConsole.Confirm("Enable scheduled firewall rule application?", f.Enabled); if (!f.Enabled) { AnsiConsole.WriteLine(); return; } f.ScheduleHour = AnsiConsole.Prompt(new TextPrompt("Run hour (0-23):").DefaultValue(f.ScheduleHour)); f.ScheduleMinute = AnsiConsole.Prompt(new TextPrompt("Run minute (0-59):").DefaultValue(f.ScheduleMinute)); AnsiConsole.MarkupLine("[grey]Note: Firewall rules are configured via [cyan]hanatoolbox firewall[/][/]"); AnsiConsole.WriteLine(); } private static void ConfigureMonitor(MonitorConfig m) { AnsiConsole.Write(new Rule("[green]Monitor[/]").RuleStyle("green")); m.Enabled = AnsiConsole.Confirm("Enable monitor (runs every cron tick)?", m.Enabled); if (!m.Enabled) { AnsiConsole.WriteLine(); return; } m.HanaUserKey = AnsiConsole.Prompt(new TextPrompt("Monitor hdbuserstore key:").DefaultValue(m.HanaUserKey)); m.CompanyName = AnsiConsole.Prompt(new TextPrompt("Company name (for alerts):").DefaultValue(m.CompanyName)); m.SapcontrolPath = AnsiConsole.Prompt(new TextPrompt("sapcontrol path:").DefaultValue(m.SapcontrolPath)); m.DiskUsageThresholdPercent = AnsiConsole.Prompt(new TextPrompt("Disk usage alert threshold (%):").DefaultValue(m.DiskUsageThresholdPercent)); m.BackupThresholdHours = AnsiConsole.Prompt(new TextPrompt("Max backup age (hours):").DefaultValue(m.BackupThresholdHours)); AnsiConsole.MarkupLine("[grey]Current monitored directories:[/]"); m.DirectoriesToMonitor.ForEach(d => AnsiConsole.MarkupLine($" [grey]- {d}[/]")); while (AnsiConsole.Confirm("Add a directory to monitor?", defaultValue: false)) { var d = AnsiConsole.Prompt(new TextPrompt("Directory path:")); if (!string.IsNullOrWhiteSpace(d)) m.DirectoriesToMonitor.Add(d); } AnsiConsole.WriteLine(); } }