first commit

This commit is contained in:
2026-03-02 20:53:28 +01:00
commit d27c205106
63 changed files with 4593 additions and 0 deletions

112
Tui/OnboardTui.cs Normal file
View File

@@ -0,0 +1,112 @@
using HanaToolbox.Config;
using HanaToolbox.Logging;
using HanaToolbox.Services;
using HanaToolbox.Services.Interfaces;
using Spectre.Console;
namespace HanaToolbox.Tui;
/// <summary>
/// Full guided onboarding wizard.
/// Walks through every setting, creates hdbuserstore keys, and writes hanatoolbox.json.
/// </summary>
public sealed class OnboardTui(
KeyManagerTui keyManagerTui,
CronSetupTui cronSetupTui,
FirewallTui firewallTui,
AppLogger _logger)
{
public async Task RunAsync(CancellationToken ct = default)
{
AnsiConsole.Clear();
AnsiConsole.Write(new FigletText("HanaToolbox").Color(Color.Cyan1));
AnsiConsole.Write(new Rule("[cyan]Initial Setup Wizard[/]").RuleStyle("cyan"));
AnsiConsole.MarkupLine("[grey]This wizard will configure HanaToolbox for this system.[/]\n");
// Root check
if (Environment.UserName != "root")
{
AnsiConsole.MarkupLine("[red]Warning: Not running as root. Some operations may fail.[/]");
if (!AnsiConsole.Confirm("Continue anyway?", defaultValue: false)) return;
}
var config = ConfigService.Exists() ? ConfigService.Load() : new AppConfig();
// Step 1: HANA global settings
AnsiConsole.Write(new Rule("[blue]Step 1 of 7 — HANA Settings[/]").RuleStyle("blue"));
config.Hana.Sid = AnsiConsole.Prompt(new TextPrompt<string>("HANA SID:").DefaultValue(config.Hana.Sid));
config.Hana.InstanceNumber = AnsiConsole.Prompt(new TextPrompt<string>("Instance number:").DefaultValue(config.Hana.InstanceNumber));
AnsiConsole.WriteLine();
// Step 2: hdbuserstore keys
AnsiConsole.Write(new Rule("[blue]Step 2 of 7 — Key Manager[/]").RuleStyle("blue"));
AnsiConsole.MarkupLine("[grey]Set up hdbuserstore keys needed for automated operations.[/]");
if (AnsiConsole.Confirm("Open Key Manager now?", defaultValue: true))
await keyManagerTui.RunAsync(config.Hana, config.Hana.Sid, ct);
AnsiConsole.WriteLine();
// Step 3: Cron tasks
AnsiConsole.Write(new Rule("[blue]Step 3 of 7 — Cron Task Settings[/]").RuleStyle("blue"));
config = cronSetupTui.Run(config);
// Step 4: Firewall
AnsiConsole.Write(new Rule("[blue]Step 4 of 7 — Firewall[/]").RuleStyle("blue"));
if (AnsiConsole.Confirm("Configure firewall rules now?", defaultValue: true))
{
var updated = await firewallTui.RunAsync(config.Firewall, ct);
if (updated != null) config.Firewall = updated;
}
AnsiConsole.WriteLine();
// Step 5: Binary paths (optional overrides)
AnsiConsole.Write(new Rule("[blue]Step 5 of 7 — Binary Paths (optional)[/]").RuleStyle("blue"));
AnsiConsole.MarkupLine("[grey]Leave empty to use auto-detection (which, /usr/sap/hdbclient, etc.)[/]");
var hdbsqlOverride = AnsiConsole.Prompt(
new TextPrompt<string>("hdbsql path override (empty = auto):").AllowEmpty().DefaultValue(""));
var hdbusOverride = AnsiConsole.Prompt(
new TextPrompt<string>("hdbuserstore path override (empty = auto):").AllowEmpty().DefaultValue(""));
if (!string.IsNullOrWhiteSpace(hdbsqlOverride)) config.Hana.HdbsqlPath = hdbsqlOverride;
if (!string.IsNullOrWhiteSpace(hdbusOverride)) config.Hana.HdbuserstorePath = hdbusOverride;
AnsiConsole.WriteLine();
// Step 6: ntfy notifications
AnsiConsole.Write(new Rule("[blue]Step 6 of 7 — Notifications (ntfy)[/]").RuleStyle("blue"));
AnsiConsole.MarkupLine("[grey]HanaToolbox sends alerts via ntfy.sh (or a self-hosted ntfy server).[/]");
AnsiConsole.MarkupLine("[grey]Leave the token empty to disable notifications.[/]");
AnsiConsole.WriteLine();
config.Ntfy.Url = AnsiConsole.Prompt(
new TextPrompt<string>("ntfy server URL (topic included):")
.DefaultValue(config.Ntfy.Url));
config.Ntfy.Token = AnsiConsole.Prompt(
new TextPrompt<string>("ntfy access token (empty = no auth):")
.Secret()
.AllowEmpty()
.DefaultValue(string.IsNullOrWhiteSpace(config.Ntfy.Token) ? string.Empty : "(existing)"));
// If user accepted "(existing)" prompt without typing, keep the real token
if (config.Ntfy.Token == "(existing)")
config.Ntfy.Token = ConfigService.Exists() ? ConfigService.Load().Ntfy.Token : string.Empty;
AnsiConsole.WriteLine();
// Step 7: Save
AnsiConsole.Write(new Rule("[blue]Step 7 of 7 — Finalize[/]").RuleStyle("blue"));
var crontabLine = $"* * * * * root /usr/local/bin/hanatoolbox cron";
AnsiConsole.MarkupLine("[grey]Add the following line to your system crontab ([cyan]/etc/crontab[/] or [cyan]/etc/cron.d/hanatoolbox[/]):[/]");
AnsiConsole.MarkupLine($"[cyan]{crontabLine}[/]");
AnsiConsole.WriteLine();
if (!AnsiConsole.Confirm("Save configuration to /etc/hanatoolbox/hanatoolbox.json?", defaultValue: true))
{
AnsiConsole.MarkupLine("[yellow]Aborted. No changes saved.[/]");
return;
}
ConfigService.Save(config);
AnsiConsole.MarkupLine("[green]✅ Configuration saved successfully![/]");
AnsiConsole.MarkupLine($"[grey]Config file: /etc/hanatoolbox/hanatoolbox.json[/]");
}
}