WIP - Add VirtualDDNSRouter.Client
project with Docker support, YAML settings handling, and example configuration
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -5,3 +5,5 @@ riderModule.iml
|
|||||||
/_ReSharper.Caches/
|
/_ReSharper.Caches/
|
||||||
.idea
|
.idea
|
||||||
rules.yaml
|
rules.yaml
|
||||||
|
/VirtualDDNSRouter.Client/settings.yaml
|
||||||
|
settings.yaml
|
21
VirtualDDNSRouter.Client/Dockerfile
Normal file
21
VirtualDDNSRouter.Client/Dockerfile
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
FROM mcr.microsoft.com/dotnet/runtime:10.0 AS base
|
||||||
|
USER $APP_UID
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
||||||
|
ARG BUILD_CONFIGURATION=Release
|
||||||
|
WORKDIR /src
|
||||||
|
COPY ["VirtualDDNSRouter.Client/VirtualDDNSRouter.Client.csproj", "VirtualDDNSRouter.Client/"]
|
||||||
|
RUN dotnet restore "VirtualDDNSRouter.Client/VirtualDDNSRouter.Client.csproj"
|
||||||
|
COPY . .
|
||||||
|
WORKDIR "/src/VirtualDDNSRouter.Client"
|
||||||
|
RUN dotnet build "./VirtualDDNSRouter.Client.csproj" -c $BUILD_CONFIGURATION -o /app/build
|
||||||
|
|
||||||
|
FROM build AS publish
|
||||||
|
ARG BUILD_CONFIGURATION=Release
|
||||||
|
RUN dotnet publish "./VirtualDDNSRouter.Client.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
|
||||||
|
|
||||||
|
FROM base AS final
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=publish /app/publish .
|
||||||
|
ENTRYPOINT ["dotnet", "VirtualDDNSRouter.Client.dll"]
|
39
VirtualDDNSRouter.Client/Helpers/YamlParser.cs
Normal file
39
VirtualDDNSRouter.Client/Helpers/YamlParser.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using YamlDotNet.Serialization;
|
||||||
|
using YamlDotNet.Serialization.NamingConventions;
|
||||||
|
using Settings = VirtualDDNSRouter.Client.Models.Settings;
|
||||||
|
|
||||||
|
namespace VirtualDDNSRouter.Client.Helpers;
|
||||||
|
|
||||||
|
public class Helpers
|
||||||
|
{
|
||||||
|
private static readonly string YamlFilePath = "settings.yaml";
|
||||||
|
|
||||||
|
public static async Task<Settings> GetSettings()
|
||||||
|
{
|
||||||
|
if (!File.Exists(YamlFilePath))
|
||||||
|
throw new FileNotFoundException($"Settings file not found: {YamlFilePath}");
|
||||||
|
|
||||||
|
var yamlContent = await File.ReadAllTextAsync(YamlFilePath).ConfigureAwait(false);
|
||||||
|
|
||||||
|
// Build the deserializer with explicit naming convention
|
||||||
|
var deserializer = new StaticDeserializerBuilder(new YamlStaticContext())
|
||||||
|
.WithNamingConvention(UnderscoredNamingConvention.Instance)
|
||||||
|
.IgnoreUnmatchedProperties()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
// Deserialize into Settings
|
||||||
|
var settings = deserializer.Deserialize<Settings>(yamlContent);
|
||||||
|
|
||||||
|
if (settings is null || string.IsNullOrWhiteSpace(settings.Host) || string.IsNullOrWhiteSpace(settings.Path) ||
|
||||||
|
string.IsNullOrWhiteSpace(settings.ApiKey))
|
||||||
|
throw new Exception("Invalid settings file");
|
||||||
|
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
[YamlStaticContext]
|
||||||
|
[YamlSerializable(typeof(Settings))]
|
||||||
|
private partial class YamlStaticContext : StaticContext
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
10
VirtualDDNSRouter.Client/Models/Settings.cs
Normal file
10
VirtualDDNSRouter.Client/Models/Settings.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace VirtualDDNSRouter.Client.Models;
|
||||||
|
|
||||||
|
public class Settings
|
||||||
|
{
|
||||||
|
public string Host { get; set; } = string.Empty;
|
||||||
|
public string Path { get; set; } = string.Empty;
|
||||||
|
public ushort DestinationPort { get; set; } = 80;
|
||||||
|
public string ApiKey { get; set; } = string.Empty;
|
||||||
|
public ushort RefreshIntervalMinutes { get; set; } = 5;
|
||||||
|
}
|
26
VirtualDDNSRouter.Client/Program.cs
Normal file
26
VirtualDDNSRouter.Client/Program.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using VirtualDDNSRouter.Client.Helpers;
|
||||||
|
|
||||||
|
var settings = await Helpers.GetSettings();
|
||||||
|
|
||||||
|
using var cts = new CancellationTokenSource();
|
||||||
|
Console.CancelKeyPress += (s, e) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine("Shutdown requested…");
|
||||||
|
e.Cancel = true;
|
||||||
|
cts.Cancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
var timer = new PeriodicTimer(TimeSpan.FromMinutes(settings.RefreshIntervalMinutes));
|
||||||
|
|
||||||
|
var client = new HttpClient { Timeout = TimeSpan.FromSeconds(10) };
|
||||||
|
var request = new HttpRequestMessage(HttpMethod.Get,
|
||||||
|
new Uri($"{settings.Host}/setip/{settings.Path}/{settings.DestinationPort}/{settings.ApiKey}"));
|
||||||
|
while (await timer.WaitForNextTickAsync())
|
||||||
|
{
|
||||||
|
if (cts.IsCancellationRequested) break;
|
||||||
|
var response = await client.SendAsync(request, cts.Token);
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
Console.WriteLine("[INFO] IP address updated at " + DateTime.Now.ToString("HH:mm:ss"));
|
||||||
|
else
|
||||||
|
Console.WriteLine("[ERROR] IP address update failed at " + DateTime.Now.ToString("HH:mm:ss"));
|
||||||
|
}
|
23
VirtualDDNSRouter.Client/VirtualDDNSRouter.Client.csproj
Normal file
23
VirtualDDNSRouter.Client/VirtualDDNSRouter.Client.csproj
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<PublishAot>true</PublishAot>
|
||||||
|
<InvariantGlobalization>true</InvariantGlobalization>
|
||||||
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="..\.dockerignore">
|
||||||
|
<Link>.dockerignore</Link>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="YamlDotNet" Version="16.3.0"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
5
VirtualDDNSRouter.Client/settings.example.yaml
Normal file
5
VirtualDDNSRouter.Client/settings.example.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
host: example.com
|
||||||
|
path: odoo
|
||||||
|
destination_port: 8081
|
||||||
|
api_key: abc123XYZ
|
||||||
|
refresh_interval_minutes: 3
|
@@ -10,7 +10,7 @@ public record Rule
|
|||||||
|
|
||||||
public Rule()
|
public Rule()
|
||||||
{
|
{
|
||||||
} // Needed for AOT static deserializer
|
} // Needed for AOT static deserializer - AI
|
||||||
}
|
}
|
||||||
|
|
||||||
public record Route
|
public record Route
|
||||||
|
@@ -7,6 +7,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||||||
compose.yaml = compose.yaml
|
compose.yaml = compose.yaml
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VirtualDDNSRouter.Client", "VirtualDDNSRouter.Client\VirtualDDNSRouter.Client.csproj", "{68BC4818-F3A1-4862-BAE6-6F43D3237E63}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -17,5 +19,9 @@ Global
|
|||||||
{6101BFD3-C31C-41CB-9402-A8B9F3EBEE22}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{6101BFD3-C31C-41CB-9402-A8B9F3EBEE22}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{6101BFD3-C31C-41CB-9402-A8B9F3EBEE22}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{6101BFD3-C31C-41CB-9402-A8B9F3EBEE22}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{6101BFD3-C31C-41CB-9402-A8B9F3EBEE22}.Release|Any CPU.Build.0 = Release|Any CPU
|
{6101BFD3-C31C-41CB-9402-A8B9F3EBEE22}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{68BC4818-F3A1-4862-BAE6-6F43D3237E63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{68BC4818-F3A1-4862-BAE6-6F43D3237E63}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{68BC4818-F3A1-4862-BAE6-6F43D3237E63}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{68BC4818-F3A1-4862-BAE6-6F43D3237E63}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
@@ -5,3 +5,9 @@
|
|||||||
context: .
|
context: .
|
||||||
dockerfile: VirtualDDNSRouter.Server/Dockerfile
|
dockerfile: VirtualDDNSRouter.Server/Dockerfile
|
||||||
|
|
||||||
|
virtualddnsrouter.client:
|
||||||
|
image: virtualddnsrouter.client
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: VirtualDDNSRouter.Client/Dockerfile
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user