7c4781dfe3
Extract shared models, services, and application logic into JdeScoping.ConfigManager.Core library. Add JdeScoping.ConfigManager.Cli console app with validate, test-connection, and secret commands using System.CommandLine. UI project now references Core for platform-agnostic functionality while retaining Avalonia-specific dialog and clipboard services.
274 lines
9.1 KiB
C#
274 lines
9.1 KiB
C#
using System.CommandLine;
|
|
using JdeScoping.ConfigManager.Core.Services;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
namespace JdeScoping.ConfigManager.Cli.Commands;
|
|
|
|
/// <summary>
|
|
/// Validation command implementations.
|
|
/// </summary>
|
|
public static class ValidateCommand
|
|
{
|
|
/// <summary>
|
|
/// Creates the validate appsettings command.
|
|
/// </summary>
|
|
public static Command CreateAppSettingsCommand(
|
|
IServiceProvider serviceProvider,
|
|
Option<string?> configPathOption,
|
|
Option<bool> verboseOption,
|
|
Option<bool> quietOption)
|
|
{
|
|
var command = new Command("appsettings", "Validate appsettings.json");
|
|
|
|
command.SetHandler(async (string? configPath, bool verbose, bool quiet) =>
|
|
{
|
|
var exitCode = await ValidateAppSettingsAsync(serviceProvider, configPath, verbose, quiet);
|
|
Environment.ExitCode = exitCode;
|
|
}, configPathOption, verboseOption, quietOption);
|
|
|
|
return command;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates the validate pipelines command.
|
|
/// </summary>
|
|
public static Command CreatePipelinesCommand(
|
|
IServiceProvider serviceProvider,
|
|
Option<string?> configPathOption,
|
|
Option<bool> verboseOption,
|
|
Option<bool> quietOption)
|
|
{
|
|
var command = new Command("pipelines", "Validate pipeline configuration files");
|
|
|
|
command.SetHandler(async (string? configPath, bool verbose, bool quiet) =>
|
|
{
|
|
var exitCode = await ValidatePipelinesAsync(serviceProvider, configPath, verbose, quiet);
|
|
Environment.ExitCode = exitCode;
|
|
}, configPathOption, verboseOption, quietOption);
|
|
|
|
return command;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates the validate all command.
|
|
/// </summary>
|
|
public static Command CreateAllCommand(
|
|
IServiceProvider serviceProvider,
|
|
Option<string?> configPathOption,
|
|
Option<bool> verboseOption,
|
|
Option<bool> quietOption)
|
|
{
|
|
var command = new Command("all", "Validate all configuration files");
|
|
|
|
command.SetHandler(async (string? configPath, bool verbose, bool quiet) =>
|
|
{
|
|
var exitCode1 = await ValidateAppSettingsAsync(serviceProvider, configPath, verbose, quiet);
|
|
var exitCode2 = await ValidatePipelinesAsync(serviceProvider, configPath, verbose, quiet);
|
|
Environment.ExitCode = Math.Max(exitCode1, exitCode2);
|
|
}, configPathOption, verboseOption, quietOption);
|
|
|
|
return command;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates the validate runtime command.
|
|
/// </summary>
|
|
public static Command CreateRuntimeCommand(
|
|
IServiceProvider serviceProvider,
|
|
Option<string?> configPathOption,
|
|
Option<bool> verboseOption,
|
|
Option<bool> quietOption)
|
|
{
|
|
var command = new Command("runtime", "Run Infrastructure validators");
|
|
|
|
command.SetHandler(async (string? configPath, bool verbose, bool quiet) =>
|
|
{
|
|
var exitCode = await ValidateRuntimeAsync(serviceProvider, configPath, verbose, quiet);
|
|
Environment.ExitCode = exitCode;
|
|
}, configPathOption, verboseOption, quietOption);
|
|
|
|
return command;
|
|
}
|
|
|
|
private static async Task<int> ValidateAppSettingsAsync(
|
|
IServiceProvider serviceProvider,
|
|
string? configPath,
|
|
bool verbose,
|
|
bool quiet)
|
|
{
|
|
var folderPath = await GetConfigFolderAsync(serviceProvider, configPath);
|
|
if (folderPath == null)
|
|
{
|
|
Console.Error.WriteLine("Error: Could not find configuration folder. Use --config-path to specify.");
|
|
return 1;
|
|
}
|
|
|
|
var configFileService = serviceProvider.GetRequiredService<IConfigFileService>();
|
|
var validationService = serviceProvider.GetRequiredService<IValidationService>();
|
|
|
|
var appSettingsPath = Path.Combine(folderPath, "appsettings.json");
|
|
if (!File.Exists(appSettingsPath))
|
|
{
|
|
Console.Error.WriteLine($"Error: appsettings.json not found at {appSettingsPath}");
|
|
return 1;
|
|
}
|
|
|
|
try
|
|
{
|
|
var config = await configFileService.LoadAppSettingsAsync(appSettingsPath);
|
|
var result = validationService.ValidateAppSettings(config);
|
|
|
|
if (!quiet)
|
|
{
|
|
Console.WriteLine("=== AppSettings Validation ===");
|
|
Console.WriteLine($"File: {appSettingsPath}");
|
|
}
|
|
|
|
if (result.IsValid)
|
|
{
|
|
if (!quiet)
|
|
Console.WriteLine("Status: Valid");
|
|
return 0;
|
|
}
|
|
|
|
foreach (var error in result.Errors)
|
|
{
|
|
Console.Error.WriteLine($"Error: {error}");
|
|
}
|
|
|
|
foreach (var warning in result.Warnings)
|
|
{
|
|
if (!quiet)
|
|
Console.WriteLine($"Warning: {warning}");
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
catch (ConfigLoadException ex)
|
|
{
|
|
Console.Error.WriteLine($"Error loading configuration: {ex.Message}");
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
private static async Task<int> ValidatePipelinesAsync(
|
|
IServiceProvider serviceProvider,
|
|
string? configPath,
|
|
bool verbose,
|
|
bool quiet)
|
|
{
|
|
var folderPath = await GetConfigFolderAsync(serviceProvider, configPath);
|
|
if (folderPath == null)
|
|
{
|
|
Console.Error.WriteLine("Error: Could not find configuration folder. Use --config-path to specify.");
|
|
return 1;
|
|
}
|
|
|
|
var configFileService = serviceProvider.GetRequiredService<IConfigFileService>();
|
|
var validationService = serviceProvider.GetRequiredService<IValidationService>();
|
|
|
|
var pipelinesDir = Path.Combine(folderPath, "Pipelines");
|
|
|
|
try
|
|
{
|
|
var pipelines = await configFileService.LoadAllPipelinesAsync(pipelinesDir);
|
|
var result = validationService.ValidatePipelines(pipelines);
|
|
|
|
if (!quiet)
|
|
{
|
|
Console.WriteLine("=== Pipelines Validation ===");
|
|
Console.WriteLine($"Directory: {pipelinesDir}");
|
|
Console.WriteLine($"Pipelines found: {pipelines.Count}");
|
|
}
|
|
|
|
if (result.IsValid)
|
|
{
|
|
if (!quiet)
|
|
Console.WriteLine("Status: Valid");
|
|
return 0;
|
|
}
|
|
|
|
foreach (var error in result.Errors)
|
|
{
|
|
Console.Error.WriteLine($"Error: {error}");
|
|
}
|
|
|
|
foreach (var warning in result.Warnings)
|
|
{
|
|
if (!quiet)
|
|
Console.WriteLine($"Warning: {warning}");
|
|
}
|
|
|
|
return result.Errors.Count > 0 ? 1 : 0;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.Error.WriteLine($"Error validating pipelines: {ex.Message}");
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
private static async Task<int> ValidateRuntimeAsync(
|
|
IServiceProvider serviceProvider,
|
|
string? configPath,
|
|
bool verbose,
|
|
bool quiet)
|
|
{
|
|
var folderPath = await GetConfigFolderAsync(serviceProvider, configPath);
|
|
if (folderPath == null)
|
|
{
|
|
Console.Error.WriteLine("Error: Could not find configuration folder. Use --config-path to specify.");
|
|
return 1;
|
|
}
|
|
|
|
var runtimeValidationService = serviceProvider.GetRequiredService<IRuntimeConfigValidationService>();
|
|
|
|
if (!quiet)
|
|
{
|
|
Console.WriteLine("=== Runtime Configuration Validation ===");
|
|
Console.WriteLine($"Folder: {folderPath}");
|
|
}
|
|
|
|
var results = runtimeValidationService.ValidateRuntimeConfig(folderPath);
|
|
var hasErrors = false;
|
|
|
|
foreach (var result in results)
|
|
{
|
|
if (result.Errors.Count > 0)
|
|
{
|
|
hasErrors = true;
|
|
Console.Error.WriteLine($"\n[{result.ValidatorName}]");
|
|
foreach (var error in result.Errors)
|
|
{
|
|
Console.Error.WriteLine($" Error: {error}");
|
|
}
|
|
}
|
|
else if (!quiet)
|
|
{
|
|
Console.WriteLine($"[{result.ValidatorName}]: OK");
|
|
}
|
|
|
|
foreach (var warning in result.Warnings)
|
|
{
|
|
if (!quiet)
|
|
Console.WriteLine($" Warning: {warning}");
|
|
}
|
|
}
|
|
|
|
return hasErrors ? 1 : 0;
|
|
}
|
|
|
|
private static async Task<string?> GetConfigFolderAsync(IServiceProvider serviceProvider, string? configPath)
|
|
{
|
|
if (!string.IsNullOrEmpty(configPath))
|
|
{
|
|
if (Directory.Exists(configPath))
|
|
return configPath;
|
|
return null;
|
|
}
|
|
|
|
var autoDiscoveryService = serviceProvider.GetRequiredService<IAutoDiscoveryService>();
|
|
return await autoDiscoveryService.FindConfigFolderAsync();
|
|
}
|
|
}
|