using System.Text.Json; namespace RackPeek.Domain.Discovery; /// /// The engine host's own account of itself, from GET /info. This is what makes /// a remote engine discoverable without user intervention: the daemon id gives the /// services an identity seed that does not depend on which machine ran the command, /// and the name is the hostname rpk discover system would report on that box. /// public sealed record DockerEngineInfo { /// /// The daemon's persisted unique id (kept under /var/lib/docker). Survives /// reboots; changes only on an engine reinstall — the same failure mode /// /etc/machine-id has for local discovery. /// public string? Id { get; init; } /// The engine host's hostname. public string? Hostname { get; init; } } /// Parses the Docker Engine GET /info response. Pure, so it tests from a fixture. public static class DockerEngineInfoParser { public static DockerEngineInfo? Parse(string json) { try { using var document = JsonDocument.Parse(json); if (document.RootElement.ValueKind != JsonValueKind.Object) return null; return new DockerEngineInfo { Id = GetString(document.RootElement, "ID"), Hostname = GetString(document.RootElement, "Name") }; } catch (JsonException) { return null; } } private static string? GetString(JsonElement element, string property) => element.TryGetProperty(property, out JsonElement value) && value.ValueKind == JsonValueKind.String && !string.IsNullOrWhiteSpace(value.GetString()) ? value.GetString() : null; }