Skip to content
This repository was archived by the owner on Jun 4, 2023. It is now read-only.

Commit 32b94ca

Browse files
authored
Using Skidbladnir module system (#2)
Features: 1. Using modules system instead of extensions to `IServiceCollection` 2. Using `Skidbladnir.Utilities` for Retry Fixes: 1. Added retry delays in Retry.Do, so that if a request fails in Freenom, retry the operation after a while, and not immediately and run into a service error again 2. Added a check for the existence of a directory for saving certificates and creating directories along the path if they did not exist
1 parent f8a7b0b commit 32b94ca

17 files changed

+150
-116
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
using DotNetCertBot.Domain;
22
using Microsoft.Extensions.DependencyInjection;
3+
using Skidbladnir.Modules;
34

45
namespace DotNetCertBot.CloudFlareUserApi
56
{
6-
public static class ServicesExtensions
7+
public class CloudFlareDnsProviderModule : Module
78
{
8-
public static IServiceCollection AddCloudFlareDnsProvider(this IServiceCollection services)
9+
public override void Configure(IServiceCollection services)
910
{
1011
services.AddSingleton<IDnsProviderService, CloudFlareServiceSelenium>();
11-
return services;
1212
}
1313
}
1414
}

DotNetCertBot.CloudFlareUserApi/DotNetCertBot.CloudFlareUserApi.csproj

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@
55
</PropertyGroup>
66

77
<ItemGroup>
8-
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.10" />
9-
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.10" />
10-
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.10" />
8+
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.13" />
9+
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.13" />
10+
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.13" />
1111
<PackageReference Include="Selenium.WebDriver" Version="3.141.0" />
1212
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="88.0.4324.9600" />
13+
<PackageReference Include="Skidbladnir.Modules" Version="1.1.1-unstalable.0.1" />
1314
</ItemGroup>
1415

1516
<ItemGroup>

DotNetCertBot.Domain/TaskUtils.cs

Lines changed: 0 additions & 36 deletions
This file was deleted.

DotNetCertBot.FreenomDnsProvider/DotNetCertBot.FreenomDnsProvider.csproj

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
</PropertyGroup>
66

77
<ItemGroup>
8-
<PackageReference Include="Skidbladnir.Client.Freenom.Dns" Version="0.0.1-build0003" />
9-
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.10" />
10-
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.10" />
8+
<PackageReference Include="Skidbladnir.Client.Freenom.Dns" Version="1.1.1-unstalable.0.1" />
9+
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.13" />
10+
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.13" />
11+
<PackageReference Include="Skidbladnir.Modules" Version="1.1.1-unstalable.0.1" />
12+
<PackageReference Include="Skidbladnir.Utility.Common" Version="1.1.1-unstalable.0.1" />
1113
</ItemGroup>
1214

1315
<ItemGroup>

DotNetCertBot.FreenomDnsProvider/FreenomDnsProvider.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@
44
using DotNetCertBot.Domain;
55
using Microsoft.Extensions.Logging;
66
using Skidbladnir.Client.Freenom.Dns;
7+
using Skidbladnir.Utility.Common;
78

89
namespace DotNetCertBot.FreenomDnsProvider
910
{
1011
internal class FreenomDnsProvider : IDnsProviderService
1112
{
1213
private readonly ILogger<FreenomDnsProvider> _logger;
1314
private readonly IFreenomClient _client;
15+
private const int RetryCount = 5;
16+
private static readonly TimeSpan RetryDelay = TimeSpan.FromSeconds(5);
1417

1518
public FreenomDnsProvider(ILogger<FreenomDnsProvider> logger)
1619
{
@@ -20,18 +23,18 @@ public FreenomDnsProvider(ILogger<FreenomDnsProvider> logger)
2023

2124
public Task<bool> CheckAuth()
2225
{
23-
return TaskUtils.RunWithRetry(async () => await _client.IsAuthenticated());
26+
return Retry.Do(async () => await _client.IsAuthenticated(), RetryCount, RetryDelay);
2427
}
2528

2629
public async Task<bool> Login(string login, string password)
2730
{
28-
await TaskUtils.RunWithRetry(async () => await _client.SignIn(login, password));
29-
return await TaskUtils.RunWithRetry(async () => await _client.IsAuthenticated());
31+
await Retry.Do(async () => await _client.SignIn(login, password), RetryCount, RetryDelay);
32+
return await Retry.Do(async () => await _client.IsAuthenticated(), RetryCount, RetryDelay);
3033
}
3134

3235
public async Task AddChallenge(DnsChallenge challenge, string zoneName)
3336
{
34-
var zones = await TaskUtils.RunWithRetry(async () => await _client.GetZones());
37+
var zones = await Retry.Do(async () => await _client.GetZones(), RetryCount, RetryDelay);
3538
var neededZone = zones.FirstOrDefault(z => z.Name.Equals(zoneName, StringComparison.OrdinalIgnoreCase));
3639
if (neededZone == null)
3740
throw new Exception($"Zone ({zoneName}) not found");
@@ -41,7 +44,7 @@ public async Task AddChallenge(DnsChallenge challenge, string zoneName)
4144
Ttl = 3600,
4245
Value = challenge.Value
4346
};
44-
await TaskUtils.RunWithRetry(async () => await _client.AddDnsRecord(neededZone, dnsRecord));
47+
await Retry.Do(async () => await _client.AddDnsRecord(neededZone, dnsRecord), RetryCount, RetryDelay);
4548
_logger.LogInformation(
4649
"{Date}: Wait 7 minutes because freenom name servers is so buggy. (Waiting for apply dns record)",
4750
DateTime.UtcNow);
@@ -50,20 +53,20 @@ public async Task AddChallenge(DnsChallenge challenge, string zoneName)
5053

5154
public async Task ClearChallenge(string zoneName, string id)
5255
{
53-
var zones = await TaskUtils.RunWithRetry(async () => await _client.GetZones());
56+
var zones = await Retry.Do(async () => await _client.GetZones(), RetryCount, RetryDelay);
5457
var neededZone = zones.FirstOrDefault(z => z.Name.Equals(zoneName, StringComparison.OrdinalIgnoreCase));
5558
if (neededZone == null)
5659
throw new Exception($"Zone ({zoneName}) not found");
5760

58-
var records = await TaskUtils.RunWithRetry(async () => await _client.GetDnsRecords(neededZone));
61+
var records = await Retry.Do(async () => await _client.GetDnsRecords(neededZone), RetryCount, RetryDelay);
5962
var neededRecord = records.FirstOrDefault(r =>
6063
r.Name.Equals(NormalizeDnsName(id, zoneName), StringComparison.OrdinalIgnoreCase) &&
6164
r.Type == DnsRecordType.TXT);
6265

6366
if (neededRecord == null)
6467
throw new Exception($"Dns record ({id}) not found");
6568

66-
await TaskUtils.RunWithRetry(async () => await _client.RemoveDnsRecord(neededZone, neededRecord));
69+
await Retry.Do(async () => await _client.RemoveDnsRecord(neededZone, neededRecord), RetryCount, RetryDelay);
6770
}
6871

6972
public void Dispose()
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
using DotNetCertBot.Domain;
22
using Microsoft.Extensions.DependencyInjection;
3+
using Skidbladnir.Modules;
34

45
namespace DotNetCertBot.FreenomDnsProvider
56
{
6-
public static class ServicesExtensions
7+
public class FreenomDnsProviderModule : Module
78
{
8-
public static IServiceCollection AddFreenomDnsProvider(this IServiceCollection services)
9+
public override void Configure(IServiceCollection services)
910
{
1011
services.AddSingleton<IDnsProviderService, FreenomDnsProvider>();
11-
return services;
1212
}
1313
}
1414
}

DotNetCertBot.Host/ApplicationExtensions.cs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,21 @@
22
using System.IO;
33
using System.Threading.Tasks;
44
using DotNetCertBot.Domain;
5-
using Microsoft.Extensions.DependencyInjection;
6-
using Microsoft.Extensions.Logging;
75

86
namespace DotNetCertBot.Host
97
{
108
public static class ApplicationExtensions
119
{
12-
public static IServiceProvider ConfigureApp(Action<IServiceCollection> buildAction)
13-
{
14-
var collection = new ServiceCollection();
15-
collection.AddLogging(b => b.AddConsole());
16-
buildAction?.Invoke(collection);
17-
return collection.BuildServiceProvider().CreateScope().ServiceProvider;
18-
}
19-
2010
public static async Task WriteToFile(this CertificateResult certificate, string outputPath = null)
2111
{
2212
var path = "";
2313
if (!string.IsNullOrWhiteSpace(outputPath))
14+
{
2415
path = outputPath;
16+
if (!Directory.Exists(path))
17+
Directory.CreateDirectory(path);
18+
}
19+
2520
//Write Cert
2621
var certFilePath = Path.Combine(path, $"{certificate.Domain}.pem");
2722
await using (var writer = File.CreateText(certFilePath))

DotNetCertBot.Host/CertificateService.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using DotNetCertBot.Domain;
22
using System;
33
using System.Threading.Tasks;
4-
using Certes;
54
using Microsoft.Extensions.Logging;
65

76
namespace DotNetCertBot.Host

DotNetCertBot.Host/DotNetCertBot.Host.csproj

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
55
<TargetFramework>netcoreapp3.1</TargetFramework>
66
</PropertyGroup>
77

88
<ItemGroup>
9-
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.10" />
10-
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="3.1.10" />
11-
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.10" />
12-
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.10" />
9+
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.13" />
10+
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="3.1.13" />
11+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.13" />
12+
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.13" />
1313
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="88.0.4324.9600" />
14+
<PackageReference Include="Skidbladnir.Modules" Version="1.1.1-unstalable.0.1" />
1415
</ItemGroup>
1516

1617
<ItemGroup>

DotNetCertBot.Host/Program.cs

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,54 +5,60 @@
55
using DotNetCertBot.FreenomDnsProvider;
66
using DotNetCertBot.LetsEncrypt;
77
using DotNetCertBot.NoOp;
8+
using Microsoft.Extensions.Configuration;
89
using Microsoft.Extensions.DependencyInjection;
10+
using Microsoft.Extensions.Logging;
11+
using Skidbladnir.Modules;
912

1013
namespace DotNetCertBot.Host
1114
{
1215
public class Program
1316
{
14-
public static async Task Main(string[] args)
17+
public static Task Main(string[] args)
1518
{
16-
var provider = ApplicationExtensions.ConfigureApp(services =>
17-
{
18-
var configuration = args.CreateConfiguration();
19-
var certbotConfiguration = configuration.GetConfiguration();
20-
services.AddSingleton(certbotConfiguration);
21-
services.AddSingleton(configuration);
22-
services.AddSingleton<CertificateService>();
23-
switch (certbotConfiguration.NoOp)
24-
{
25-
case NoOpMode.Full:
26-
services.AddNoOpAcme();
27-
services.AddNoOpDnsProvider();
28-
break;
29-
case NoOpMode.Acme:
30-
services.AddNoOpAcme();
31-
RegisterDnsProvider(services, certbotConfiguration);
32-
break;
33-
case NoOpMode.None:
34-
default:
35-
services.AddLetsEncrypt();
36-
RegisterDnsProvider(services, certbotConfiguration);
37-
break;
38-
}
39-
});
19+
var collection = new ServiceCollection();
20+
collection.AddLogging(b => b.AddConsole()
21+
.SetMinimumLevel(LogLevel.Information));
22+
23+
var configuration = args.CreateConfiguration();
24+
ConfigureDependedModules(configuration);
25+
26+
collection.AddSkidbladnirModules<StartupModule>(configuration);
27+
var provider = collection.BuildServiceProvider();
28+
return provider.StartModules();
29+
}
4030

41-
using var scope = provider.CreateScope();
42-
var certificateService = scope.ServiceProvider.GetService<CertificateService>();
43-
await certificateService.Issue();
31+
private static void ConfigureDependedModules(IConfiguration configuration)
32+
{
33+
var certbotConfiguration = configuration.GetConfiguration();
34+
switch (certbotConfiguration.NoOp)
35+
{
36+
case NoOpMode.Full:
37+
StartupModule.DynamicDependsModules.Add(typeof(AcmeNoOpModules));
38+
StartupModule.DynamicDependsModules.Add(typeof(DnsNoOpModule));
39+
break;
40+
case NoOpMode.Acme:
41+
StartupModule.DynamicDependsModules.Add(typeof(AcmeNoOpModules));
42+
RegisterDnsProvider(certbotConfiguration);
43+
break;
44+
case NoOpMode.None:
45+
default:
46+
StartupModule.DynamicDependsModules.Add(typeof(LetsEncryptAuthorityModule));
47+
RegisterDnsProvider(certbotConfiguration);
48+
break;
49+
}
4450
}
4551

46-
private static void RegisterDnsProvider(IServiceCollection services, CertBotConfiguration configuration)
52+
private static void RegisterDnsProvider(CertBotConfiguration configuration)
4753
{
4854
switch (configuration.Provider)
4955
{
5056
case DnsProvider.Freenom:
51-
services.AddFreenomDnsProvider();
57+
StartupModule.DynamicDependsModules.Add(typeof(FreenomDnsProviderModule));
5258
break;
5359
case DnsProvider.CloudFlare:
5460
default:
55-
services.AddCloudFlareDnsProvider();
61+
StartupModule.DynamicDependsModules.Add(typeof(CloudFlareDnsProviderModule));
5662
break;
5763
}
5864
}

0 commit comments

Comments
 (0)