feat: scaffold windows agent host
This commit is contained in:
parent
0bf6185f90
commit
b825249a7e
20
apps/windows_agent/src/TermRemoteCtl.Agent/AppPaths.cs
Normal file
20
apps/windows_agent/src/TermRemoteCtl.Agent/AppPaths.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System.IO;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace TermRemoteCtl.Agent;
|
||||
|
||||
internal static class AppPaths
|
||||
{
|
||||
public static string ResolveDataRoot(IConfiguration configuration)
|
||||
{
|
||||
var configuredPath = configuration["Agent:DataRoot"];
|
||||
if (!string.IsNullOrWhiteSpace(configuredPath))
|
||||
{
|
||||
return configuredPath;
|
||||
}
|
||||
|
||||
return Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
|
||||
"TermRemoteCtl");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
namespace TermRemoteCtl.Agent.Configuration;
|
||||
|
||||
public sealed class AgentOptions
|
||||
{
|
||||
public const string SectionName = "Agent";
|
||||
|
||||
public string DataRoot { get; set; } = string.Empty;
|
||||
|
||||
public string BindAddress { get; set; } = "0.0.0.0";
|
||||
|
||||
public int HttpsPort { get; set; }
|
||||
|
||||
public int WebSocketFrameFlushMilliseconds { get; set; }
|
||||
|
||||
public int RingBufferLineLimit { get; set; }
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace TermRemoteCtl.Agent.Configuration;
|
||||
|
||||
public sealed class AgentOptionsValidator : IValidateOptions<AgentOptions>
|
||||
{
|
||||
public ValidateOptionsResult Validate(string? name, AgentOptions options)
|
||||
{
|
||||
var failures = new List<string>();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(options.DataRoot))
|
||||
{
|
||||
failures.Add("Agent:DataRoot must be configured.");
|
||||
}
|
||||
|
||||
if (options.HttpsPort is < 1 or > 65535)
|
||||
{
|
||||
failures.Add("Agent:HttpsPort must be between 1 and 65535.");
|
||||
}
|
||||
|
||||
if (options.WebSocketFrameFlushMilliseconds <= 0)
|
||||
{
|
||||
failures.Add("Agent:WebSocketFrameFlushMilliseconds must be positive.");
|
||||
}
|
||||
|
||||
return failures.Count > 0
|
||||
? ValidateOptionsResult.Fail(failures)
|
||||
: ValidateOptionsResult.Success;
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,26 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
using TermRemoteCtl.Agent;
|
||||
using TermRemoteCtl.Agent.Configuration;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
var agentSection = builder.Configuration.GetSection(AgentOptions.SectionName);
|
||||
var bindAddress = agentSection[nameof(AgentOptions.BindAddress)] ?? "0.0.0.0";
|
||||
var httpsPort = agentSection.GetValue<int?>(nameof(AgentOptions.HttpsPort)) ?? 9443;
|
||||
|
||||
builder.WebHost.UseUrls($"http://{bindAddress}:{httpsPort}");
|
||||
builder.Services.AddSingleton<IValidateOptions<AgentOptions>, AgentOptionsValidator>();
|
||||
builder.Services
|
||||
.AddOptions<AgentOptions>()
|
||||
.Bind(agentSection)
|
||||
.PostConfigure(options => options.DataRoot = AppPaths.ResolveDataRoot(builder.Configuration))
|
||||
.ValidateOnStart();
|
||||
|
||||
var app = builder.Build();
|
||||
var agentOptions = app.Services.GetRequiredService<IOptions<AgentOptions>>().Value;
|
||||
|
||||
Directory.CreateDirectory(agentOptions.DataRoot);
|
||||
|
||||
app.MapGet("/health", () => Results.Json(new { status = "ok" }));
|
||||
|
||||
app.Run();
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
"Agent": {
|
||||
"DataRoot": "C:\\ProgramData\\TermRemoteCtl",
|
||||
"BindAddress": "0.0.0.0",
|
||||
"HttpsPort": 9443,
|
||||
"WebSocketFrameFlushMilliseconds": 33,
|
||||
"RingBufferLineLimit": 4000
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
using TermRemoteCtl.Agent.Configuration;
|
||||
|
||||
namespace TermRemoteCtl.Agent.Tests.Configuration;
|
||||
|
||||
public class AgentOptionsValidatorTests
|
||||
{
|
||||
[Fact]
|
||||
public void Validate_Fails_When_DataRoot_Is_Missing()
|
||||
{
|
||||
var options = new AgentOptions
|
||||
{
|
||||
DataRoot = "",
|
||||
BindAddress = "0.0.0.0",
|
||||
HttpsPort = 9443
|
||||
};
|
||||
|
||||
var validator = new AgentOptionsValidator();
|
||||
|
||||
var result = validator.Validate("Agent", options);
|
||||
|
||||
Assert.True(result.Failed);
|
||||
Assert.Contains(result.Failures, failure => failure.Contains("DataRoot"));
|
||||
}
|
||||
}
|
||||
@ -20,4 +20,8 @@
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\\..\\src\\TermRemoteCtl.Agent\\TermRemoteCtl.Agent.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user