wip: Windows desktop app scaffold (WinUI 3/.NET 8) + NSIS installer + docs
Owner decision pending (STATE.md DC-100 tick): adopt/ship/park. Preserved from fragile git stash to named branch 2026-08-23. NOTE: requires a Windows build machine (WinUI XAML compiler + MSIX do not cross-build on Linux) — see WINDOWS_APP_BUILD.md in this tree. Secret-scanned clean 2026-08-23 (no keys/tokens/PEM in tree).
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
using Docker.DotNet;
|
||||
using Docker.DotNet.Models;
|
||||
using DashCaddy.Desktop.Models;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace DashCaddy.Desktop.Services;
|
||||
|
||||
public class DockerService
|
||||
{
|
||||
private readonly DockerClient _client;
|
||||
|
||||
public DockerService(string endpoint)
|
||||
{
|
||||
_client = new DockerClientConfiguration(new Uri(endpoint)).CreateClient();
|
||||
}
|
||||
|
||||
public async Task<List<ContainerListResponse>> GetContainersAsync(string labelFilter = null)
|
||||
{
|
||||
var parameters = new ContainersListParameters
|
||||
{
|
||||
All = true,
|
||||
Filters = new Dictionary<string, IDictionary<string, bool>>
|
||||
{
|
||||
["label"] = new Dictionary<string, bool> { ["dashcaddy.managed"] = true }
|
||||
}
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(labelFilter))
|
||||
{
|
||||
parameters.Filters["name"] = new Dictionary<string, bool> { [labelFilter] = true };
|
||||
}
|
||||
|
||||
return await _client.Containers.ListContainersAsync(parameters);
|
||||
}
|
||||
|
||||
public async Task<ContainerInspectResponse> GetContainerAsync(string id)
|
||||
{
|
||||
return await _client.Containers.InspectContainerAsync(id);
|
||||
}
|
||||
|
||||
public async Task StartContainerAsync(string id)
|
||||
{
|
||||
await _client.Containers.StartContainerAsync(id, null);
|
||||
}
|
||||
|
||||
public async Task StopContainerAsync(string id)
|
||||
{
|
||||
await _client.Containers.StopContainerAsync(id, new ContainerStopParameters { WaitBeforeKillSeconds = 10 });
|
||||
}
|
||||
|
||||
public async Task RestartContainerAsync(string id)
|
||||
{
|
||||
await _client.Containers.RestartContainerAsync(id, new ContainerRestartParameters { WaitBeforeKillSeconds = 10 });
|
||||
}
|
||||
|
||||
public async Task RemoveContainerAsync(string id)
|
||||
{
|
||||
await _client.Containers.RemoveContainerAsync(id, new ContainerRemoveParameters { Force = true, RemoveVolumes = false });
|
||||
}
|
||||
|
||||
public async Task CreateContainerAsync(ServiceModel service)
|
||||
{
|
||||
var createParams = new CreateContainerParameters
|
||||
{
|
||||
Image = service.Image,
|
||||
Name = $"dashcaddy-{service.Id}",
|
||||
Labels = new Dictionary<string, string>
|
||||
{
|
||||
["dashcaddy.managed"] = "true",
|
||||
["dashcaddy.service-id"] = service.Id,
|
||||
["dashcaddy.service-name"] = service.Name
|
||||
},
|
||||
Env = service.Environment.Select(kvp => $"{kvp.Key}={kvp.Value}").ToList(),
|
||||
HostConfig = new HostConfig
|
||||
{
|
||||
PortBindings = service.Environment.TryGetValue("PORT", out var port) && int.TryParse(port, out var p)
|
||||
? new Dictionary<string, IList<PortBinding>>
|
||||
{
|
||||
[$"{p}/tcp"] = new List<PortBinding> { new PortBinding { HostPort = p.ToString() } }
|
||||
}
|
||||
: new Dictionary<string, IList<PortBinding>>(),
|
||||
RestartPolicy = new RestartPolicy { Name = "unless-stopped" }
|
||||
}
|
||||
};
|
||||
|
||||
if (service.Volumes != null)
|
||||
{
|
||||
createParams.HostConfig.Binds = service.Volumes.ToList();
|
||||
}
|
||||
|
||||
await _client.Containers.CreateContainerAsync(createParams);
|
||||
}
|
||||
|
||||
public async Task<string> GetContainerLogsAsync(string id, int tailLines = 100)
|
||||
{
|
||||
var parameters = new ContainerLogsParameters
|
||||
{
|
||||
ShowStdout = true,
|
||||
ShowStderr = true,
|
||||
Tail = tailLines.ToString()
|
||||
};
|
||||
|
||||
using var stream = await _client.Containers.GetContainerLogsAsync(id, false, parameters);
|
||||
using var reader = new StreamReader(stream);
|
||||
return await reader.ReadToEndAsync();
|
||||
}
|
||||
|
||||
public async Task<bool> IsDockerRunningAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
await _client.System.PingAsync();
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<VersionResponse> GetVersionAsync()
|
||||
{
|
||||
return await _client.System.GetVersionAsync();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user