Skip to content

Commit 8a19f44

Browse files
committed
Add configuration as code
1 parent 203f1e5 commit 8a19f44

10 files changed

Lines changed: 175 additions & 4 deletions

File tree

.runsettings

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<RunSettings>
3+
<DataCollectionRunSettings>
4+
<DataCollectors>
5+
<!-- https://stackoverflow.com/a/72642304 -->
6+
<!-- https://learn.microsoft.com/en-us/visualstudio/test/configure-unit-tests-by-using-a-dot-runsettings-file -->
7+
<DataCollector friendlyName="XPlat code coverage">
8+
<Configuration>
9+
<ModulePaths>
10+
<Exclude>
11+
<ModulePath>.*ConfigurationAsCode.*</ModulePath>
12+
</Exclude>
13+
</ModulePaths>
14+
</Configuration>
15+
</DataCollector>
16+
</DataCollectors>
17+
</DataCollectionRunSettings>
18+
</RunSettings>

EnergySavingMode.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
2323
EndProject
2424
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleWebAPI.Tests", "sample\SampleWebAPI.Tests\SampleWebAPI.Tests.csproj", "{08B62430-5A23-4A55-BCB1-C1B055587734}"
2525
EndProject
26+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConfigurationAsCode", "sample\ConfigurationAsCode\ConfigurationAsCode.csproj", "{F6A6B0B2-C8CF-4F12-8EF8-5B47F21631C6}"
27+
EndProject
2628
Global
2729
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2830
Debug|Any CPU = Debug|Any CPU
@@ -45,6 +47,10 @@ Global
4547
{08B62430-5A23-4A55-BCB1-C1B055587734}.Debug|Any CPU.Build.0 = Debug|Any CPU
4648
{08B62430-5A23-4A55-BCB1-C1B055587734}.Release|Any CPU.ActiveCfg = Release|Any CPU
4749
{08B62430-5A23-4A55-BCB1-C1B055587734}.Release|Any CPU.Build.0 = Release|Any CPU
50+
{F6A6B0B2-C8CF-4F12-8EF8-5B47F21631C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
51+
{F6A6B0B2-C8CF-4F12-8EF8-5B47F21631C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
52+
{F6A6B0B2-C8CF-4F12-8EF8-5B47F21631C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
53+
{F6A6B0B2-C8CF-4F12-8EF8-5B47F21631C6}.Release|Any CPU.Build.0 = Release|Any CPU
4854
EndGlobalSection
4955
GlobalSection(SolutionProperties) = preSolution
5056
HideSolutionNode = FALSE
@@ -54,6 +60,7 @@ Global
5460
{1114F389-AFDA-4AED-9A6B-ECB5F36AE99F} = {074A2E59-CA5E-4FDD-874A-4AFE130E8610}
5561
{B5C214A1-D6DE-4E02-842B-79AE9CD16FC6} = {2EB00856-234E-4F6D-9D69-55BE7E85186C}
5662
{08B62430-5A23-4A55-BCB1-C1B055587734} = {074A2E59-CA5E-4FDD-874A-4AFE130E8610}
63+
{F6A6B0B2-C8CF-4F12-8EF8-5B47F21631C6} = {074A2E59-CA5E-4FDD-874A-4AFE130E8610}
5764
EndGlobalSection
5865
GlobalSection(ExtensibilityGlobals) = postSolution
5966
SolutionGuid = {61F924BA-31B0-415A-826B-D4DE42F93C70}

azure-pipelines.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
inputs:
2727
command: 'test'
2828
projects: '*.sln'
29-
arguments: '--configuration Release --no-build --no-restore --collect:"XPlat Code Coverage"'
29+
arguments: '--configuration Release --no-build --no-restore --collect:"XPlat Code Coverage" --settings:.runsettings'
3030
- task: PublishCodeCoverageResults@2
3131
inputs:
3232
summaryFileLocation: $(Agent.TempDirectory)/**/coverage.cobertura.xml
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<TreatWarningsAsErrors></TreatWarningsAsErrors>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<ProjectReference Include="..\..\src\EnergySavingMode\EnergySavingMode.csproj" />
12+
</ItemGroup>
13+
14+
</Project>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@ConfigurationAsCode_HostAddress = http://localhost:5103
2+
3+
GET {{ConfigurationAsCode_HostAddress}}/
4+
Accept: application/json
5+
6+
###
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
using EnergySavingMode;
2+
using EnergySavingMode.Services;
3+
4+
var builder = WebApplication.CreateBuilder(args);
5+
6+
builder.Services.AddEnergySavingMode(
7+
enabled =>
8+
{
9+
enabled[DayOfWeek.Monday] =
10+
[new(new(0, 0), new(07, 59)), new(new(20, 00), new(23, 59))];
11+
enabled[DayOfWeek.Tuesday] =
12+
[new(new(0, 0), new(07, 59)), new(new(20, 00), new(23, 59))];
13+
enabled[DayOfWeek.Wednesday] =
14+
[new(new(0, 0), new(07, 59)), new(new(20, 00), new(23, 59))];
15+
enabled[DayOfWeek.Thursday] =
16+
[new(new(0, 0), new(07, 59)), new(new(20, 00), new(23, 59))];
17+
enabled[DayOfWeek.Friday] =
18+
[new(new(0, 0), new(07, 59)), new(new(20, 00), new(23, 59))];
19+
enabled[DayOfWeek.Saturday] =
20+
[new(new(0, 0), new(23, 59))];
21+
enabled[DayOfWeek.Sunday] =
22+
[new(new(0, 0), new(23, 59))];
23+
}
24+
);
25+
26+
builder.Services.AddHostedService<EnergySavingModeEventHandler>();
27+
28+
var app = builder.Build();
29+
30+
app.UseHttpsRedirection();
31+
32+
app.MapGet("/", (IEnergySavingModeStatus energySavingModeStatus) =>
33+
{
34+
var status = new
35+
{
36+
energySavingMode = energySavingModeStatus.Current.IsEnabled ? "Enabled" : "Disabled",
37+
timestamp = energySavingModeStatus.Current.Timestamp.ToString("o")
38+
};
39+
return status;
40+
});
41+
42+
app.Run();
43+
44+
45+
46+
47+
internal class EnergySavingModeEventHandler(
48+
IEnergySavingModeEvents energySavingMode,
49+
ILogger<EnergySavingModeEventHandler> logger) : BackgroundService
50+
{
51+
protected override async Task ExecuteAsync(CancellationToken _)
52+
{
53+
await Task.Yield();
54+
55+
energySavingMode.OnEnabled(EnergySavingMode_Enabled);
56+
energySavingMode.OnDisabled(EnergySavingMode_Disabled);
57+
}
58+
59+
private Task EnergySavingMode_Enabled(CancellationToken _)
60+
{
61+
logger.LogInformation("Energy Saving Mode is Enabled...");
62+
return Task.CompletedTask;
63+
}
64+
65+
private Task EnergySavingMode_Disabled(CancellationToken _)
66+
{
67+
logger.LogInformation("Energy Saving Mode is Disabled...");
68+
return Task.CompletedTask;
69+
}
70+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"$schema": "http://json.schemastore.org/launchsettings.json",
3+
"profiles": {
4+
"default": {
5+
"commandName": "Project",
6+
"dotnetRunMessages": true,
7+
"launchBrowser": false,
8+
"launchUrl": "",
9+
"applicationUrl": "http://localhost:5103",
10+
"environmentVariables": {
11+
"ASPNETCORE_ENVIRONMENT": "Development"
12+
}
13+
}
14+
}
15+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning"
6+
}
7+
},
8+
"AllowedHosts": "*"
9+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
@SampleWebAPI_HostAddress = http://localhost:5175
22

3-
GET {{SampleWebAPI_HostAddress}}/weatherforecast/
3+
GET {{SampleWebAPI_HostAddress}}/
44
Accept: application/json
55

66
###

src/EnergySavingMode/IServicesCollectionExtensions.cs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,48 @@ public static IServiceCollection AddEnergySavingMode(
1717
return services;
1818
}
1919

20+
public static IServiceCollection AddEnergySavingMode(
21+
this IServiceCollection services,
22+
Action<IDictionary<DayOfWeek, ICollection<Options.TimeRange>>> configureSchedule)
23+
{
24+
services.AddEnergySavingModeOptions(configureSchedule);
25+
services.AddEnergySavingModeServices();
26+
27+
return services;
28+
}
29+
2030
private static IServiceCollection AddEnergySavingModeOptions(
2131
this IServiceCollection services,
2232
IConfigurationSection configurationSection)
2333
{
2434
services.AddOptions();
2535

2636
services.Configure<Options.Settings>(configurationSection);
27-
services.AddSingleton<IValidateOptions<Options.Settings>, Options.SettingsValidation>();
28-
2937
services.ConfigureOptions<Options.ConfigureFromAppSettings>();
38+
39+
services.AddEnergySavingModeOptionValidation();
40+
41+
return services;
42+
}
43+
44+
private static IServiceCollection AddEnergySavingModeOptions(
45+
this IServiceCollection services,
46+
Action<IDictionary<DayOfWeek, ICollection<Options.TimeRange>>> configureSchedule)
47+
{
48+
services.AddOptions();
49+
50+
services.AddOptions<Options.Settings>();
51+
services.Configure<Options.Configuration>(options => configureSchedule(options.Schedule));
52+
53+
services.AddEnergySavingModeOptionValidation();
54+
55+
return services;
56+
}
57+
58+
private static IServiceCollection AddEnergySavingModeOptionValidation(
59+
this IServiceCollection services)
60+
{
61+
services.AddSingleton<IValidateOptions<Options.Settings>, Options.SettingsValidation>();
3062
services.AddSingleton<IValidateOptions<Options.Configuration>, Options.ConfigurationValidation>();
3163

3264
services.AddOptionsWithValidateOnStart<Options.Settings>();

0 commit comments

Comments
 (0)