zcbot/windows-node/Zcbot.WindowsNode/EnrollOptions.cs

62 lines
2.2 KiB
C#

namespace Zcbot.WindowsNode;
internal sealed record EnrollOptions(Uri ServerUrl, string NodeName, string EnrollmentCode)
{
internal static EnrollOptions Parse(string[] args)
{
var values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
for (var index = 0; index < args.Length; index += 2)
{
if (index + 1 >= args.Length || !args[index].StartsWith("--", StringComparison.Ordinal))
{
throw Usage();
}
values[args[index][2..]] = args[index + 1];
}
if (!values.TryGetValue("server", out var server)
|| !values.TryGetValue("name", out var name)
|| !values.TryGetValue("code", out var code))
{
throw Usage();
}
var serverUrl = NodeUri.NormalizeServerUrl(server);
name = name.Trim();
code = code.Trim();
if (name.Length is < 1 or > 100 || code.Length is < 16 or > 100)
{
throw new NodeConfigurationException("Node name or enrollment code has an invalid length.");
}
return new EnrollOptions(serverUrl, name, code);
}
private static NodeConfigurationException Usage() => new(
"Usage: Zcbot.WindowsNode enroll --server http://host:8765 --name win-origin-01 --code ZCN-...");
}
internal static class NodeUri
{
internal static Uri NormalizeServerUrl(string raw)
{
if (!Uri.TryCreate(raw.Trim(), UriKind.Absolute, out var uri)
|| (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps)
|| !string.IsNullOrEmpty(uri.UserInfo)
|| !string.IsNullOrEmpty(uri.Query)
|| !string.IsNullOrEmpty(uri.Fragment))
{
throw new NodeConfigurationException("Server URL must be an absolute HTTP or HTTPS URL without credentials, query, or fragment.");
}
return new Uri(uri.GetLeftPart(UriPartial.Path).TrimEnd('/') + "/", UriKind.Absolute);
}
internal static Uri WebSocketEndpoint(Uri serverUrl)
{
var builder = new UriBuilder(new Uri(serverUrl, "v1/compute/nodes/connect"))
{
Scheme = serverUrl.Scheme == Uri.UriSchemeHttps ? "wss" : "ws"
};
return builder.Uri;
}
}