-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
19 changed files
with
270 additions
and
254 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
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
15 changes: 9 additions & 6 deletions
15
Source/Sholo.CommandLine.Containers/ApplicationNameAndVersion.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 |
---|---|---|
@@ -1,8 +1,11 @@ | ||
namespace Sholo.CommandLine.Containers | ||
using System.ComponentModel.DataAnnotations; | ||
|
||
namespace Sholo.CommandLine.Containers; | ||
|
||
public class ApplicationNameAndVersion | ||
{ | ||
public class ApplicationNameAndVersion | ||
{ | ||
public string Name { get; set; } | ||
public string Version { get; set; } | ||
} | ||
[Required] | ||
public string Name { get; set; } | ||
|
||
public string Version { get; set; } | ||
} |
11 changes: 5 additions & 6 deletions
11
Source/Sholo.CommandLine.Containers/ContainerizedAppOptions.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 |
---|---|---|
@@ -1,10 +1,9 @@ | ||
using CommandLine; | ||
|
||
namespace Sholo.CommandLine.Containers | ||
namespace Sholo.CommandLine.Containers; | ||
|
||
public class ContainerizedAppOptions | ||
{ | ||
public class ContainerizedAppOptions | ||
{ | ||
[Option('c', "configfile", Required = false, HelpText = "The config file to load (.yaml or .json extension)")] | ||
public string ConfigFile { get; set; } | ||
} | ||
[Option('c', "configfile", Required = false, HelpText = "The config file to load (.yaml or .json extension)")] | ||
public string ConfigFile { get; set; } | ||
} |
183 changes: 109 additions & 74 deletions
183
Source/Sholo.CommandLine.Containers/ContainerizedHostBuilder.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 |
---|---|---|
@@ -1,94 +1,129 @@ | ||
using System; | ||
using System.IO; | ||
using System.Reflection; | ||
using JetBrains.Annotations; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.Hosting; | ||
using Sholo.CommandLine.Containers.SplashService; | ||
using Sholo.Utils.Logging; | ||
using Sholo.Utils.Validation; | ||
|
||
namespace Sholo.CommandLine.Containers | ||
namespace Sholo.CommandLine.Containers; | ||
|
||
[PublicAPI] | ||
public static class ContainerizedHostBuilder | ||
{ | ||
[PublicAPI] | ||
public static class ContainerizedHostBuilder | ||
{ | ||
public static IHostBuilder Create(string[] args, string applicationName = null) | ||
=> ConfigureHostBuilder<Splash>(new HostBuilder().UseOptions<ContainerizedAppOptions>(args), applicationName); | ||
public static IHostBuilder Create(string[] args, string applicationName = null) | ||
=> ConfigureHostBuilder<Splash>(new HostBuilder().UseOptions<ContainerizedAppOptions>(args), applicationName); | ||
|
||
public static IHostBuilder Create<TOptions>(string[] args, string applicationName = null) | ||
where TOptions : ContainerizedAppOptions | ||
=> ConfigureHostBuilder<Splash>(new HostBuilder().UseOptions<TOptions>(args), applicationName); | ||
public static IHostBuilder Create<TOptions>(string[] args, string applicationName = null) | ||
where TOptions : ContainerizedAppOptions | ||
=> ConfigureHostBuilder<Splash>(new HostBuilder().UseOptions<TOptions>(args), applicationName); | ||
|
||
public static IHostBuilder Create<TOptions, TSplash>(string[] args, string applicationName = null) | ||
where TOptions : ContainerizedAppOptions | ||
where TSplash : class, ISplash | ||
=> ConfigureHostBuilder<TSplash>(new HostBuilder().UseOptions<TOptions>(args), applicationName); | ||
public static IHostBuilder Create<TOptions, TSplash>(string[] args, string applicationName = null) | ||
where TOptions : ContainerizedAppOptions | ||
where TSplash : class, ISplash | ||
=> ConfigureHostBuilder<TSplash>(new HostBuilder().UseOptions<TOptions>(args), applicationName); | ||
|
||
public static IHostBuilder ConfigureHostBuilder<TSplash>(IHostBuilder hostBuilder, string applicationName) | ||
where TSplash : class, ISplash | ||
=> hostBuilder | ||
.UseVersionResource(applicationName) | ||
.UseEnvironment(Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production") | ||
.ConfigureAppConfiguration((ctx, cb) => | ||
public static IHostBuilder ConfigureHostBuilder<TSplash>(IHostBuilder hostBuilder, string applicationName) | ||
where TSplash : class, ISplash | ||
=> hostBuilder | ||
.UseVersionResource(applicationName) | ||
.UseEnvironment(Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production") | ||
.UseDefaultServiceProvider((ctx, options) => { options.ValidateScopes = ctx.HostingEnvironment.IsDevelopment(); }) | ||
.ConfigureHostConfiguration(cb => | ||
{ | ||
if (hostBuilder.Properties.TryGetValue(HostBuilderExtensions.ContextPropertyName, out var optionsObj) && optionsObj is ContainerizedAppOptions options && !string.IsNullOrEmpty(options.ConfigFile)) | ||
{ | ||
var configFile = options.ConfigFile; | ||
if (!File.Exists(configFile)) | ||
{ | ||
if (ctx.TryGetOptions<ContainerizedAppOptions>(out var options) && !string.IsNullOrEmpty(options?.ConfigFile)) | ||
{ | ||
var configFile = options.ConfigFile; | ||
if (!File.Exists(configFile)) | ||
{ | ||
throw new Exception("The config file specified does not exist"); | ||
} | ||
throw new Exception("The config file specified does not exist"); | ||
} | ||
var configFileExtension = Path.GetExtension(configFile); | ||
var configFileExtension = Path.GetExtension(configFile); | ||
if (configFileExtension.Equals(".yaml", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
cb.AddYamlFile(configFile, false); | ||
} | ||
else if (configFileExtension.Equals(".json", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
cb.AddJsonFile(configFile, false); | ||
} | ||
else | ||
{ | ||
throw new Exception($"Unsupported config file extension: {configFileExtension}. Expecting .yaml or .json"); | ||
} | ||
} | ||
else | ||
{ | ||
cb.AddYamlFile("config.yaml", true); | ||
cb.AddYamlFile("config.yml", true); | ||
cb.AddJsonFile("config.json", true); | ||
} | ||
if (configFileExtension.Equals(".yaml", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
cb.AddYamlFile(configFile, false); | ||
} | ||
else if (configFileExtension.Equals(".json", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
cb.AddJsonFile(configFile, false); | ||
} | ||
else | ||
{ | ||
throw new Exception($"Unsupported config file extension: {configFileExtension}. Expecting .yaml or .json"); | ||
} | ||
} | ||
else | ||
{ | ||
cb.AddYamlFile("config.yaml", true); | ||
cb.AddYamlFile("config.yml", true); | ||
cb.AddJsonFile("config.json", true); | ||
cb.AddEnvironmentVariables(); | ||
cb.AddYamlFile("secrets.yaml", true); | ||
cb.AddYamlFile("secrets.yml", true); | ||
cb.AddJsonFile("secrets.json", true); | ||
} | ||
if (ctx.HostingEnvironment.IsDevelopment()) | ||
{ | ||
try | ||
{ | ||
cb.AddUserSecrets(Assembly.GetEntryAssembly()); | ||
} | ||
catch | ||
{ | ||
// We tried | ||
} | ||
} | ||
}) | ||
.ConfigureServices((ctx, services) => | ||
cb.AddEnvironmentVariables(); | ||
}) | ||
.ConfigureAppConfiguration((ctx, cb) => | ||
{ | ||
if (ctx.TryGetOptions<ContainerizedAppOptions>(out var options) && !string.IsNullOrEmpty(options?.ConfigFile)) | ||
{ | ||
var configFile = options.ConfigFile; | ||
if (!File.Exists(configFile)) | ||
{ | ||
throw new Exception("The config file specified does not exist"); | ||
} | ||
var configFileExtension = Path.GetExtension(configFile); | ||
if (configFileExtension.Equals(".yaml", StringComparison.OrdinalIgnoreCase) || configFileExtension.Equals(".yml", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
cb.AddYamlFile(configFile, false); | ||
} | ||
else if (configFileExtension.Equals(".json", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
services.AddOptions<ApplicationNameAndVersion>() | ||
.Configure(opt => | ||
{ | ||
opt.Name = ctx.Properties?["ApplicationName"]?.ToString() ?? string.Empty; | ||
opt.Version = ctx.Properties?["ApplicationVersion"]?.ToString() ?? string.Empty; | ||
}); | ||
cb.AddJsonFile(configFile, false); | ||
} | ||
else | ||
{ | ||
throw new Exception($"Unsupported config file extension: {configFileExtension}. Expecting .yaml, .yml, or .json"); | ||
} | ||
} | ||
else | ||
{ | ||
cb.AddYamlFile("config.yaml", true, true); | ||
cb.AddYamlFile("config.yml", true, true); | ||
cb.AddJsonFile("config.json", true, true); | ||
} | ||
services.AddSingleton<ISplash, TSplash>(); | ||
services.AddHostedService<SplashService.SplashService>(); | ||
services.AddLogging(); | ||
cb.AddEnvironmentVariables(); | ||
}) | ||
.ConfigureServices((ctx, services) => | ||
{ | ||
services.AddOptions<ApplicationNameAndVersion>() | ||
.Configure(opt => | ||
{ | ||
opt.Name = ctx.Properties?["ApplicationName"]?.ToString() ?? string.Empty; | ||
opt.Version = ctx.Properties?["ApplicationVersion"]?.ToString() ?? string.Empty; | ||
}) | ||
.ConfigureLogging((ctx, lb) => { lb.AddSerilogConsole(); }) | ||
.UseConsoleLifetime(c => { c.SuppressStatusMessages = true; }); | ||
} | ||
.PostConfigure(opt => | ||
{ | ||
opt.Name ??= Assembly.GetEntryAssembly()?.GetName().Name ?? "Unknown"; | ||
}) | ||
.ValidateDataAnnotations(true) | ||
.ValidateOnStart(); | ||
services.AddSingleton<ISplash, TSplash>(); | ||
services.AddHostedService<SplashService>(); | ||
services.AddLogging(); | ||
}) | ||
.ConfigureLogging((c, lb) => | ||
{ | ||
lb.AddSerilogConsole(c.Configuration); | ||
}) | ||
.UseConsoleLifetime(c => { c.SuppressStatusMessages = true; }); | ||
} |
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,3 @@ | ||
// Global using directives | ||
|
||
global using JetBrains.Annotations; |
25 changes: 12 additions & 13 deletions
25
Source/Sholo.CommandLine.Containers/HostBuilderContextExtensions.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 |
---|---|---|
@@ -1,23 +1,22 @@ | ||
using Microsoft.Extensions.Hosting; | ||
|
||
namespace Sholo.CommandLine.Containers | ||
namespace Sholo.CommandLine.Containers; | ||
|
||
public static class HostBuilderContextExtensions | ||
{ | ||
public static class HostBuilderContextExtensions | ||
public static bool TryGetOptions<TOptions>(this HostBuilderContext context, out TOptions options) | ||
where TOptions : ContainerizedAppOptions | ||
{ | ||
public static bool TryGetOptions<TOptions>(this HostBuilderContext context, out TOptions options) | ||
where TOptions : ContainerizedAppOptions | ||
if (context.Properties.TryGetValue(HostBuilderExtensions.ContextPropertyName, out var optionsObject)) | ||
{ | ||
if (context.Properties.TryGetValue(HostBuilderExtensions.ContextPropertyName, out var optionsObject)) | ||
if (optionsObject is TOptions optionsResult) | ||
{ | ||
if (optionsObject is TOptions optionsResult) | ||
{ | ||
options = optionsResult; | ||
return true; | ||
} | ||
options = optionsResult; | ||
return true; | ||
} | ||
|
||
options = default; | ||
return false; | ||
} | ||
|
||
options = default; | ||
return false; | ||
} | ||
} |
Oops, something went wrong.