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

53 lines
2.2 KiB
C#

using System.Net.Http.Json;
using System.Reflection;
using System.Runtime.InteropServices;
namespace Zcbot.WindowsNode;
internal static class EnrollmentClient
{
private static readonly string[] Capabilities = ["origin.plot@v2"];
internal static async Task EnrollAsync(
EnrollOptions options, NodeConfigStore store, CancellationToken cancellationToken)
{
if (store.Exists)
{
throw new NodeConfigurationException(
$"Node is already registered. Remove {store.ConfigPath} through the administrator recovery procedure before re-enrolling.");
}
var installId = Guid.NewGuid();
var request = new EnrollRequest(
options.EnrollmentCode,
options.NodeName,
installId,
Assembly.GetExecutingAssembly().GetName().Version?.ToString(3) ?? "0.1.0",
RuntimeInformation.OSDescription,
Capabilities);
using var client = new HttpClient { BaseAddress = options.ServerUrl, Timeout = TimeSpan.FromSeconds(30) };
using var response = await client.PostAsJsonAsync(
"v1/software-nodes/enroll", request, cancellationToken);
if (!response.IsSuccessStatusCode)
{
var detail = await response.Content.ReadAsStringAsync(cancellationToken);
throw new NodeConfigurationException(
$"Registration failed with HTTP {(int)response.StatusCode}: {Limit(detail, 300)}");
}
var enrolled = await response.Content.ReadFromJsonAsync<EnrollResponse>(cancellationToken)
?? throw new NodeConfigurationException("Registration response was empty.");
if (enrolled.NodeId == Guid.Empty || string.IsNullOrWhiteSpace(enrolled.NodeToken))
{
throw new NodeConfigurationException("Registration response did not contain a valid node identity.");
}
store.Save(new NodeConfig(
options.ServerUrl, enrolled.NodeId, installId, options.NodeName,
enrolled.NodeToken, Math.Clamp(enrolled.HeartbeatSeconds, 5, 300), Capabilities));
}
private static string Limit(string value, int maxLength) =>
value.Length <= maxLength ? value : value[..maxLength];
}