Confirm applied Link state in Windows client
This commit is contained in:
parent
0f6dd31646
commit
b19e3e8b31
3 changed files with 26 additions and 10 deletions
|
|
@ -51,9 +51,9 @@
|
||||||
- [x] политики по целевому `/32`, TCP/UDP и порту;
|
- [x] политики по целевому `/32`, TCP/UDP и порту;
|
||||||
- [x] TTL и автоматическое истечение;
|
- [x] TTL и автоматическое истечение;
|
||||||
- [ ] состояния Connecting, Active, Disconnecting, Partial, Disabled и Failed;
|
- [ ] состояния Connecting, Active, Disconnecting, Partial, Disabled и Failed;
|
||||||
- [ ] версия политики и подтверждение применения;
|
- [x] версия политики и подтверждение применения на Hub;
|
||||||
- [ ] обязательное отключение после reconnect;
|
- [ ] обязательное отключение после reconnect;
|
||||||
- [ ] append-only аудит;
|
- [x] локальный append-only JSONL-аудит операций Link;
|
||||||
- [ ] интеграционные тесты kill switch и частичных отказов.
|
- [ ] интеграционные тесты kill switch и частичных отказов.
|
||||||
|
|
||||||
## Этап 5 — мониторинг и терминал
|
## Этап 5 — мониторинг и терминал
|
||||||
|
|
|
||||||
|
|
@ -306,9 +306,10 @@ public sealed partial class MainPage : Page
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var fields = line[5..].Split('|');
|
var fields = line[5..].Split('|');
|
||||||
if (fields.Length >= 7
|
if (fields.Length >= 8
|
||||||
&& int.TryParse(fields[4], CultureInfo.InvariantCulture, out var port)
|
&& int.TryParse(fields[4], CultureInfo.InvariantCulture, out var port)
|
||||||
&& long.TryParse(fields[5], CultureInfo.InvariantCulture, out var expiresUnix))
|
&& long.TryParse(fields[5], CultureInfo.InvariantCulture, out var expiresUnix)
|
||||||
|
&& long.TryParse(fields[7], CultureInfo.InvariantCulture, out var version))
|
||||||
{
|
{
|
||||||
MeshLinks.Add(new MeshLinkViewModel(
|
MeshLinks.Add(new MeshLinkViewModel(
|
||||||
fields[0],
|
fields[0],
|
||||||
|
|
@ -316,7 +317,9 @@ public sealed partial class MainPage : Page
|
||||||
fields[2],
|
fields[2],
|
||||||
fields[3],
|
fields[3],
|
||||||
port,
|
port,
|
||||||
expiresUnix));
|
expiresUnix,
|
||||||
|
fields[6],
|
||||||
|
version));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -411,14 +414,21 @@ public sealed partial class MainPage : Page
|
||||||
? $"{protocol} {port} {ttlMinutes}"
|
? $"{protocol} {port} {ttlMinutes}"
|
||||||
: $"{protocol} {port}";
|
: $"{protocol} {port}";
|
||||||
using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(15));
|
using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(15));
|
||||||
await _ssh.RunRestrictedCommandAsync(
|
var commandOutput = await _ssh.RunRestrictedCommandAsync(
|
||||||
hub.Profile,
|
hub.Profile,
|
||||||
$"mesh {action} {source.Name} {target.Name} {policyArguments}",
|
$"mesh {action} {source.Name} {target.Name} {policyArguments}",
|
||||||
timeout.Token);
|
timeout.Token);
|
||||||
|
var confirmation = commandOutput
|
||||||
|
.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries)
|
||||||
|
.FirstOrDefault(line => line.StartsWith("LINK_STATE=", StringComparison.Ordinal));
|
||||||
|
if (confirmation is null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Hub не подтвердил фактическое состояние Link.");
|
||||||
|
}
|
||||||
await RefreshMeshAsync(showSuccess: false);
|
await RefreshMeshAsync(showSuccess: false);
|
||||||
ShowInfo(
|
ShowInfo(
|
||||||
enable ? "Связь включена" : "Связь отключена",
|
enable ? "Hub подтвердил Active" : "Hub подтвердил Disabled",
|
||||||
$"{source.Name} → {target.Name} · {protocol.ToUpperInvariant()}/{port}",
|
$"{source.Name} → {target.Name} · {protocol.ToUpperInvariant()}/{port} · {confirmation[11..]}",
|
||||||
enable ? InfoBarSeverity.Success : InfoBarSeverity.Warning);
|
enable ? InfoBarSeverity.Success : InfoBarSeverity.Warning);
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,9 @@ public sealed class MeshLinkViewModel
|
||||||
string cidr,
|
string cidr,
|
||||||
string protocol,
|
string protocol,
|
||||||
int port,
|
int port,
|
||||||
long expiresUnix)
|
long expiresUnix,
|
||||||
|
string state,
|
||||||
|
long version)
|
||||||
{
|
{
|
||||||
Source = source;
|
Source = source;
|
||||||
Target = target;
|
Target = target;
|
||||||
|
|
@ -33,6 +35,8 @@ public sealed class MeshLinkViewModel
|
||||||
Protocol = protocol;
|
Protocol = protocol;
|
||||||
Port = port;
|
Port = port;
|
||||||
ExpiresUnix = expiresUnix;
|
ExpiresUnix = expiresUnix;
|
||||||
|
State = state;
|
||||||
|
Version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Source { get; set; }
|
public string Source { get; set; }
|
||||||
|
|
@ -41,8 +45,10 @@ public sealed class MeshLinkViewModel
|
||||||
public string Protocol { get; set; }
|
public string Protocol { get; set; }
|
||||||
public int Port { get; set; }
|
public int Port { get; set; }
|
||||||
public long ExpiresUnix { get; set; }
|
public long ExpiresUnix { get; set; }
|
||||||
|
public string State { get; set; }
|
||||||
|
public long Version { get; set; }
|
||||||
public string ExpirationText => ExpiresUnix == 0
|
public string ExpirationText => ExpiresUnix == 0
|
||||||
? "вручную"
|
? "вручную"
|
||||||
: $"до {DateTimeOffset.FromUnixTimeSeconds(ExpiresUnix).ToLocalTime():dd.MM HH:mm}";
|
: $"до {DateTimeOffset.FromUnixTimeSeconds(ExpiresUnix).ToLocalTime():dd.MM HH:mm}";
|
||||||
public string Label => $"{Source} → {Target} · {Protocol.ToUpperInvariant()}/{Port} · {Cidr} · {ExpirationText}";
|
public string Label => $"{Source} → {Target} · {Protocol.ToUpperInvariant()}/{Port} · {Cidr} · {ExpirationText} · {State} v{Version}";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue