-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(config): Add options for secrets and environment variables on `f…
…etcharr.yaml` BREAKING CHANGE: `config.yaml` has been renamed to `fetcharr.yaml`
- Loading branch information
Showing
37 changed files
with
824 additions
and
83 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,5 +31,9 @@ | |
}, | ||
"[markdown]": { | ||
"editor.wordWrap": "wordWrapColumn" | ||
} | ||
}, | ||
"yaml.customTags": [ | ||
"env_var", | ||
"secret", | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
45 changes: 45 additions & 0 deletions
45
src/Configuration/src/EnvironmentVariables/EnvironmentVariableDeserializer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
using Fetcharr.Configuration.EnvironmentVariables.Exceptions; | ||
using Fetcharr.Models; | ||
|
||
using YamlDotNet.Core; | ||
using YamlDotNet.Core.Events; | ||
using YamlDotNet.Serialization; | ||
|
||
namespace Fetcharr.Configuration.EnvironmentVariables | ||
{ | ||
public record EnvironmentVariableValue; | ||
|
||
public class EnvironmentVariableDeserializer( | ||
IEnvironment environment) | ||
: INodeDeserializer | ||
{ | ||
public bool Deserialize( | ||
IParser reader, | ||
Type expectedType, | ||
Func<IParser, Type, object?> nestedObjectDeserializer, | ||
out object? value, | ||
ObjectDeserializer rootDeserializer) | ||
{ | ||
if(expectedType != typeof(EnvironmentVariableValue)) | ||
{ | ||
value = null; | ||
return false; | ||
} | ||
|
||
Scalar scalar = reader.Consume<Scalar>(); | ||
string[] segments = scalar.Value.Trim().Split(' ', count: 2); | ||
|
||
string environmentVariableName = segments[0]; | ||
string? environmentVariableDefault = segments.ElementAtOrDefault(1)?.Trim(); | ||
string? environmentVariableValue = environment.GetEnvironmentVariable(environmentVariableName); | ||
|
||
if(string.IsNullOrEmpty(environmentVariableValue)) | ||
{ | ||
environmentVariableValue = environmentVariableDefault; | ||
} | ||
|
||
value = environmentVariableValue ?? throw new EnvironmentVariableNotFoundException(environmentVariableName); | ||
return true; | ||
} | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
...Configuration/src/EnvironmentVariables/Exceptions/EnvironmentVariableNotFoundException.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
namespace Fetcharr.Configuration.EnvironmentVariables.Exceptions | ||
{ | ||
public class EnvironmentVariableNotFoundException : Exception | ||
{ | ||
private const string ExceptionFormat = "Environment variable '{0}' was referenced, but was not defined and has no default value."; | ||
|
||
public EnvironmentVariableNotFoundException(string variable) | ||
: base(string.Format(ExceptionFormat, variable)) | ||
{ | ||
|
||
} | ||
|
||
public EnvironmentVariableNotFoundException(string variable, Exception innerException) | ||
: base(string.Format(ExceptionFormat, variable), innerException) | ||
{ | ||
|
||
} | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
src/Configuration/src/EnvironmentVariables/Extensions/DeserializerBuilderExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
using YamlDotNet.Serialization; | ||
|
||
namespace Fetcharr.Configuration.EnvironmentVariables.Extensions | ||
{ | ||
public static partial class DeserializerBuilderExtensions | ||
{ | ||
public static DeserializerBuilder WithEnvironmentVariables( | ||
this DeserializerBuilder builder, | ||
IServiceProvider provider) => builder | ||
.WithNodeDeserializer(ActivatorUtilities.CreateInstance<EnvironmentVariableDeserializer>(provider)) | ||
.WithTagMapping("!env_var", typeof(EnvironmentVariableValue)); | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
src/Configuration/src/Exceptions/DuplicateServiceKeyException.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
namespace Fetcharr.Configuration.Exceptions | ||
{ | ||
public class DuplicateServiceKeyException(string name, string service) | ||
: Exception($"Duplicate {service} name in configuration: '{name}'") | ||
{ | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
src/Configuration/src/Extensions/IServiceCollectionExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
using Fetcharr.Configuration.Parsing; | ||
using Fetcharr.Configuration.Secrets; | ||
using Fetcharr.Models.Configuration; | ||
|
||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.Options; | ||
|
||
namespace Fetcharr.Configuration.Extensions | ||
{ | ||
public static partial class IServiceCollectionExtensions | ||
{ | ||
/// <summary> | ||
/// Registers configuration services onto the given <see cref="IServiceCollection"/>. | ||
/// </summary> | ||
public static IServiceCollection AddConfiguration(this IServiceCollection services) | ||
{ | ||
services.AddScoped<IConfigurationLocator, ConfigurationLocator>(); | ||
services.AddScoped<IConfigurationParser, ConfigurationParser>(); | ||
services.AddScoped<ISecretsProvider, SecretsProvider>(); | ||
|
||
services.AddTransient<IOptions<FetcharrConfiguration>>(provider => | ||
{ | ||
IConfigurationParser parser = provider.GetRequiredService<IConfigurationParser>(); | ||
FetcharrConfiguration configuration = parser.ReadConfig(); | ||
|
||
return Options.Create(configuration); | ||
}); | ||
|
||
return services; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<PackageId>Fetcharr.Configuration</PackageId> | ||
<AssemblyName>Fetcharr.Configuration</AssemblyName> | ||
<RootNamespace>Fetcharr.Configuration</RootNamespace> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="YamlDotNet" Version="16.0.0" /> | ||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> | ||
|
||
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="../../Models/src/Fetcharr.Models.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
using Fetcharr.Models.Configuration; | ||
|
||
namespace Fetcharr.Configuration.Parsing | ||
{ | ||
/// <summary> | ||
/// Defines a mechanism for locating configuration files. | ||
/// </summary> | ||
public interface IConfigurationLocator | ||
{ | ||
/// <summary> | ||
/// Locates the configuration file of name <paramref name="name"/> and returns it, if found; otherwise, <see langword="null" /> | ||
/// </summary> | ||
/// <param name="name">Name of the configuration file. Can be with or without extension.</param> | ||
FileInfo? Get(string name); | ||
|
||
/// <summary> | ||
/// Locate and return all files within the default, or configured, configuration directory. | ||
/// </summary> | ||
/// <exception cref="DirectoryNotFoundException">Thrown if the configuration directory is unreachable or doesn't exist.</exception> | ||
IEnumerable<FileInfo> GetAll(); | ||
} | ||
|
||
/// <summary> | ||
/// Default implementation of the <see cref="IConfigurationLocator" /> interface. | ||
/// </summary> | ||
public class ConfigurationLocator( | ||
IAppDataSetup appDataSetup) | ||
: IConfigurationLocator | ||
{ | ||
private readonly string[] _configSearchPatterns = ["*.yml", "*.yaml"]; | ||
|
||
/// <inheritdoc /> | ||
public FileInfo? Get(string name) | ||
{ | ||
name = Path.GetFileNameWithoutExtension(name); | ||
|
||
foreach(FileInfo file in this.GetAll()) | ||
{ | ||
if(Path.GetFileNameWithoutExtension(file.Name).Equals(name, StringComparison.InvariantCultureIgnoreCase)) | ||
{ | ||
return file; | ||
} | ||
} | ||
|
||
return null; | ||
} | ||
|
||
/// <inheritdoc /> | ||
public IEnumerable<FileInfo> GetAll() | ||
{ | ||
DirectoryInfo directory = new(appDataSetup.ConfigDirectory); | ||
if(!directory.Exists) | ||
{ | ||
throw new DirectoryNotFoundException($"Configuration directory could not be found: '{appDataSetup.ConfigDirectory}'"); | ||
} | ||
|
||
return this._configSearchPatterns.SelectMany(directory.EnumerateFiles); | ||
} | ||
} | ||
} |
Oops, something went wrong.