feat(secrets-cli): target config reader — operate on the app's own composed Secrets config
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using ZB.MOM.WW.Secrets.MasterKey;
|
||||
using ZB.MOM.WW.Secrets.Replicator.SqlServer;
|
||||
|
||||
namespace ZB.MOM.WW.Secrets.Cli.Interactive;
|
||||
|
||||
/// <summary>
|
||||
/// Composes a deployment target's Secrets configuration the same way the target app would at
|
||||
/// startup — base <c>appsettings.json</c>, optional per-environment overlay, and environment
|
||||
/// variables — so the interactive console operates on exactly the store the app reads.
|
||||
/// </summary>
|
||||
public sealed class TargetConfigReader
|
||||
{
|
||||
/// <summary>
|
||||
/// Loads the target app's config exactly the way the app would (base json + optional environment
|
||||
/// overlay + environment variables) and binds the Secrets options out of it.
|
||||
/// </summary>
|
||||
/// <param name="appSettingsPath">Absolute or relative path to the target app's base <c>appsettings.json</c>.</param>
|
||||
/// <param name="environment">
|
||||
/// Optional ASP.NET environment name; when non-empty an <c>appsettings.{environment}.json</c>
|
||||
/// overlay is layered on top of the base file (optional — absent overlays are ignored).
|
||||
/// </param>
|
||||
/// <param name="sectionPath">The configuration section the Secrets options bind from. Defaults to <c>Secrets</c>.</param>
|
||||
/// <returns>The resolved <see cref="StoreTarget"/>, with the SQLite path made absolute against the app directory.</returns>
|
||||
/// <exception cref="FileNotFoundException">The base <paramref name="appSettingsPath"/> does not exist.</exception>
|
||||
public StoreTarget Read(string appSettingsPath, string? environment = null, string sectionPath = "Secrets")
|
||||
{
|
||||
string fullPath = Path.GetFullPath(appSettingsPath);
|
||||
if (!File.Exists(fullPath))
|
||||
{
|
||||
throw new FileNotFoundException(
|
||||
$"Target appsettings file not found: {fullPath}", fullPath);
|
||||
}
|
||||
|
||||
string dir = Path.GetDirectoryName(fullPath)!;
|
||||
string fileName = Path.GetFileName(fullPath);
|
||||
|
||||
ConfigurationBuilder builder = new();
|
||||
builder.SetBasePath(dir)
|
||||
.AddJsonFile(fileName, optional: false);
|
||||
|
||||
if (!string.IsNullOrEmpty(environment))
|
||||
{
|
||||
builder.AddJsonFile($"appsettings.{environment}.json", optional: true);
|
||||
}
|
||||
|
||||
builder.AddEnvironmentVariables();
|
||||
|
||||
IConfigurationRoot config = builder.Build();
|
||||
|
||||
SecretsOptions secrets = config.GetSection(sectionPath).Get<SecretsOptions>() ?? new SecretsOptions();
|
||||
secrets.SqlitePath = Path.GetFullPath(secrets.SqlitePath, dir);
|
||||
|
||||
SqlServerSecretsOptions? sqlServer = null;
|
||||
IConfigurationSection sqlSection = config.GetSection(sectionPath + ":SqlServer");
|
||||
if (sqlSection.GetChildren().Any())
|
||||
{
|
||||
sqlServer = sqlSection.Get<SqlServerSecretsOptions>();
|
||||
}
|
||||
|
||||
string name = new DirectoryInfo(dir).Name;
|
||||
|
||||
return new StoreTarget(name, fullPath, secrets, sqlServer, config);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds a manual target from an explicit db path + master-key options, with no backing
|
||||
/// appsettings file (for ad-hoc stores the console operates on directly).
|
||||
/// </summary>
|
||||
/// <param name="sqlitePath">Path to the SQLite store; made absolute against the current directory.</param>
|
||||
/// <param name="masterKey">The master-key resolution options for this manual store.</param>
|
||||
/// <returns>A <see cref="StoreTarget"/> named <c>manual</c> with an empty composed configuration and no SQL-Server hub.</returns>
|
||||
public StoreTarget Manual(string sqlitePath, MasterKeyOptions masterKey)
|
||||
{
|
||||
SecretsOptions secrets = new()
|
||||
{
|
||||
SqlitePath = Path.GetFullPath(sqlitePath),
|
||||
MasterKey = masterKey,
|
||||
};
|
||||
|
||||
IConfigurationRoot config = new ConfigurationBuilder().Build();
|
||||
|
||||
return new StoreTarget("manual", AppSettingsPath: null, secrets, SqlServer: null, config);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user