audit work, doctors work
This commit is contained in:
@@ -6,6 +6,7 @@ using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using StellaOps.Cli.Extensions;
|
||||
using StellaOps.Doctor.Engine;
|
||||
using StellaOps.Doctor.Export;
|
||||
using StellaOps.Doctor.Models;
|
||||
using StellaOps.Doctor.Output;
|
||||
|
||||
@@ -26,6 +27,7 @@ internal static class DoctorCommandGroup
|
||||
// Sub-commands
|
||||
doctor.Add(BuildRunCommand(services, verboseOption, cancellationToken));
|
||||
doctor.Add(BuildListCommand(services, verboseOption, cancellationToken));
|
||||
doctor.Add(BuildExportCommand(services, verboseOption, cancellationToken));
|
||||
|
||||
return doctor;
|
||||
}
|
||||
@@ -162,6 +164,141 @@ internal static class DoctorCommandGroup
|
||||
return list;
|
||||
}
|
||||
|
||||
private static Command BuildExportCommand(
|
||||
IServiceProvider services,
|
||||
Option<bool> verboseOption,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var outputOption = new Option<string>("--output", new[] { "-o" })
|
||||
{
|
||||
Description = "Output ZIP file path",
|
||||
IsRequired = true
|
||||
};
|
||||
|
||||
var includeLogsOption = new Option<bool>("--include-logs")
|
||||
{
|
||||
Description = "Include recent log files in the bundle (default: true)"
|
||||
};
|
||||
includeLogsOption.SetDefaultValue(true);
|
||||
|
||||
var logDurationOption = new Option<string?>("--log-duration")
|
||||
{
|
||||
Description = "Duration of logs to include (e.g., 1h, 4h, 24h). Default: 1h"
|
||||
};
|
||||
|
||||
var noConfigOption = new Option<bool>("--no-config")
|
||||
{
|
||||
Description = "Exclude configuration from the bundle"
|
||||
};
|
||||
|
||||
var export = new Command("export", "Generate diagnostic bundle for support")
|
||||
{
|
||||
outputOption,
|
||||
includeLogsOption,
|
||||
logDurationOption,
|
||||
noConfigOption,
|
||||
verboseOption
|
||||
};
|
||||
|
||||
export.SetAction(async (parseResult, ct) =>
|
||||
{
|
||||
var output = parseResult.GetValue(outputOption)!;
|
||||
var includeLogs = parseResult.GetValue(includeLogsOption);
|
||||
var logDuration = parseResult.GetValue(logDurationOption);
|
||||
var noConfig = parseResult.GetValue(noConfigOption);
|
||||
var verbose = parseResult.GetValue(verboseOption);
|
||||
|
||||
await ExportDiagnosticBundleAsync(
|
||||
services,
|
||||
output,
|
||||
includeLogs,
|
||||
logDuration,
|
||||
noConfig,
|
||||
verbose,
|
||||
cancellationToken);
|
||||
});
|
||||
|
||||
return export;
|
||||
}
|
||||
|
||||
private static async Task ExportDiagnosticBundleAsync(
|
||||
IServiceProvider services,
|
||||
string outputPath,
|
||||
bool includeLogs,
|
||||
string? logDuration,
|
||||
bool noConfig,
|
||||
bool verbose,
|
||||
CancellationToken ct)
|
||||
{
|
||||
var generator = services.GetRequiredService<DiagnosticBundleGenerator>();
|
||||
|
||||
var duration = ParseDuration(logDuration) ?? TimeSpan.FromHours(1);
|
||||
|
||||
var options = new DiagnosticBundleOptions
|
||||
{
|
||||
IncludeConfig = !noConfig,
|
||||
IncludeLogs = includeLogs,
|
||||
LogDuration = duration
|
||||
};
|
||||
|
||||
Console.WriteLine("Generating diagnostic bundle...");
|
||||
|
||||
var bundle = await generator.GenerateAsync(options, ct);
|
||||
|
||||
// Ensure output path has .zip extension
|
||||
if (!outputPath.EndsWith(".zip", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
outputPath += ".zip";
|
||||
}
|
||||
|
||||
await generator.ExportToZipAsync(bundle, outputPath, ct);
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"Diagnostic bundle created: {outputPath}");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"Summary:");
|
||||
Console.WriteLine($" Passed: {bundle.DoctorReport.Summary.Passed}");
|
||||
Console.WriteLine($" Warnings: {bundle.DoctorReport.Summary.Warnings}");
|
||||
Console.WriteLine($" Failed: {bundle.DoctorReport.Summary.Failed}");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Share this bundle with Stella Ops support for assistance.");
|
||||
}
|
||||
|
||||
private static TimeSpan? ParseDuration(string? duration)
|
||||
{
|
||||
if (string.IsNullOrEmpty(duration))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Parse duration strings like "1h", "4h", "30m", "24h"
|
||||
if (duration.EndsWith("h", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (double.TryParse(duration.AsSpan(0, duration.Length - 1), NumberStyles.Float, CultureInfo.InvariantCulture, out var hours))
|
||||
{
|
||||
return TimeSpan.FromHours(hours);
|
||||
}
|
||||
}
|
||||
|
||||
if (duration.EndsWith("m", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (double.TryParse(duration.AsSpan(0, duration.Length - 1), NumberStyles.Float, CultureInfo.InvariantCulture, out var minutes))
|
||||
{
|
||||
return TimeSpan.FromMinutes(minutes);
|
||||
}
|
||||
}
|
||||
|
||||
if (duration.EndsWith("d", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (double.TryParse(duration.AsSpan(0, duration.Length - 1), NumberStyles.Float, CultureInfo.InvariantCulture, out var days))
|
||||
{
|
||||
return TimeSpan.FromDays(days);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static async Task RunDoctorAsync(
|
||||
IServiceProvider services,
|
||||
string format,
|
||||
|
||||
@@ -0,0 +1,471 @@
|
||||
// <copyright file="DoctorCommandGroupTests.cs" company="Stella Operations">
|
||||
// Copyright (c) Stella Operations. Licensed under AGPL-3.0-or-later.
|
||||
// </copyright>
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// DoctorCommandGroupTests.cs
|
||||
// Sprint: SPRINT_20260112_001_006_CLI_doctor_command
|
||||
// Task: CLI-DOC-001 - Unit tests for stella doctor command
|
||||
// Description: Tests for the doctor command structure and options.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using System.CommandLine;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using StellaOps.Cli.Commands;
|
||||
using StellaOps.Doctor.DependencyInjection;
|
||||
using StellaOps.Doctor.Engine;
|
||||
using StellaOps.Doctor.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Cli.Tests.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for DoctorCommandGroup and related functionality.
|
||||
/// </summary>
|
||||
[Trait("Category", "Unit")]
|
||||
public sealed class DoctorCommandGroupTests
|
||||
{
|
||||
#region Command Structure Tests
|
||||
|
||||
[Fact]
|
||||
public void BuildDoctorCommand_ReturnsCommandWithCorrectName()
|
||||
{
|
||||
// Arrange
|
||||
var services = CreateTestServices();
|
||||
var verboseOption = new Option<bool>("--verbose");
|
||||
|
||||
// Act
|
||||
var command = DoctorCommandGroup.BuildDoctorCommand(services, verboseOption, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
command.Name.Should().Be("doctor");
|
||||
command.Description.Should().Contain("diagnostic");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildDoctorCommand_HasRunSubcommand()
|
||||
{
|
||||
// Arrange
|
||||
var services = CreateTestServices();
|
||||
var verboseOption = new Option<bool>("--verbose");
|
||||
|
||||
// Act
|
||||
var command = DoctorCommandGroup.BuildDoctorCommand(services, verboseOption, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
var runCommand = command.Subcommands.FirstOrDefault(c => c.Name == "run");
|
||||
runCommand.Should().NotBeNull();
|
||||
runCommand!.Description.Should().Contain("Execute");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildDoctorCommand_HasListSubcommand()
|
||||
{
|
||||
// Arrange
|
||||
var services = CreateTestServices();
|
||||
var verboseOption = new Option<bool>("--verbose");
|
||||
|
||||
// Act
|
||||
var command = DoctorCommandGroup.BuildDoctorCommand(services, verboseOption, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
var listCommand = command.Subcommands.FirstOrDefault(c => c.Name == "list");
|
||||
listCommand.Should().NotBeNull();
|
||||
listCommand!.Description.Should().Contain("List");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Run Subcommand Options Tests
|
||||
|
||||
[Fact]
|
||||
public void RunCommand_HasFormatOption()
|
||||
{
|
||||
// Arrange
|
||||
var services = CreateTestServices();
|
||||
var verboseOption = new Option<bool>("--verbose");
|
||||
|
||||
// Act
|
||||
var command = DoctorCommandGroup.BuildDoctorCommand(services, verboseOption, CancellationToken.None);
|
||||
var runCommand = command.Subcommands.First(c => c.Name == "run");
|
||||
|
||||
// Assert
|
||||
var formatOption = runCommand.Options.FirstOrDefault(o =>
|
||||
o.Name == "format" || o.Aliases.Contains("--format") || o.Aliases.Contains("-f"));
|
||||
formatOption.Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RunCommand_HasModeOption()
|
||||
{
|
||||
// Arrange
|
||||
var services = CreateTestServices();
|
||||
var verboseOption = new Option<bool>("--verbose");
|
||||
|
||||
// Act
|
||||
var command = DoctorCommandGroup.BuildDoctorCommand(services, verboseOption, CancellationToken.None);
|
||||
var runCommand = command.Subcommands.First(c => c.Name == "run");
|
||||
|
||||
// Assert
|
||||
var modeOption = runCommand.Options.FirstOrDefault(o =>
|
||||
o.Name == "mode" || o.Aliases.Contains("--mode") || o.Aliases.Contains("-m"));
|
||||
modeOption.Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RunCommand_HasCategoryOption()
|
||||
{
|
||||
// Arrange
|
||||
var services = CreateTestServices();
|
||||
var verboseOption = new Option<bool>("--verbose");
|
||||
|
||||
// Act
|
||||
var command = DoctorCommandGroup.BuildDoctorCommand(services, verboseOption, CancellationToken.None);
|
||||
var runCommand = command.Subcommands.First(c => c.Name == "run");
|
||||
|
||||
// Assert
|
||||
var categoryOption = runCommand.Options.FirstOrDefault(o =>
|
||||
o.Name == "category" || o.Aliases.Contains("--category") || o.Aliases.Contains("-c"));
|
||||
categoryOption.Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RunCommand_HasTagOption()
|
||||
{
|
||||
// Arrange
|
||||
var services = CreateTestServices();
|
||||
var verboseOption = new Option<bool>("--verbose");
|
||||
|
||||
// Act
|
||||
var command = DoctorCommandGroup.BuildDoctorCommand(services, verboseOption, CancellationToken.None);
|
||||
var runCommand = command.Subcommands.First(c => c.Name == "run");
|
||||
|
||||
// Assert
|
||||
var tagOption = runCommand.Options.FirstOrDefault(o =>
|
||||
o.Name == "tag" || o.Aliases.Contains("--tag") || o.Aliases.Contains("-t"));
|
||||
tagOption.Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RunCommand_HasCheckOption()
|
||||
{
|
||||
// Arrange
|
||||
var services = CreateTestServices();
|
||||
var verboseOption = new Option<bool>("--verbose");
|
||||
|
||||
// Act
|
||||
var command = DoctorCommandGroup.BuildDoctorCommand(services, verboseOption, CancellationToken.None);
|
||||
var runCommand = command.Subcommands.First(c => c.Name == "run");
|
||||
|
||||
// Assert - System.CommandLine stores option name without leading dashes
|
||||
var checkOption = runCommand.Options.FirstOrDefault(o =>
|
||||
o.Name == "--check" || o.Name == "check" || o.Aliases.Any(a => a == "--check"));
|
||||
checkOption.Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RunCommand_HasParallelOption()
|
||||
{
|
||||
// Arrange
|
||||
var services = CreateTestServices();
|
||||
var verboseOption = new Option<bool>("--verbose");
|
||||
|
||||
// Act
|
||||
var command = DoctorCommandGroup.BuildDoctorCommand(services, verboseOption, CancellationToken.None);
|
||||
var runCommand = command.Subcommands.First(c => c.Name == "run");
|
||||
|
||||
// Assert
|
||||
var parallelOption = runCommand.Options.FirstOrDefault(o =>
|
||||
o.Name == "parallel" || o.Aliases.Contains("--parallel") || o.Aliases.Contains("-p"));
|
||||
parallelOption.Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RunCommand_HasTimeoutOption()
|
||||
{
|
||||
// Arrange
|
||||
var services = CreateTestServices();
|
||||
var verboseOption = new Option<bool>("--verbose");
|
||||
|
||||
// Act
|
||||
var command = DoctorCommandGroup.BuildDoctorCommand(services, verboseOption, CancellationToken.None);
|
||||
var runCommand = command.Subcommands.First(c => c.Name == "run");
|
||||
|
||||
// Assert - System.CommandLine stores option name without leading dashes
|
||||
var timeoutOption = runCommand.Options.FirstOrDefault(o =>
|
||||
o.Name == "timeout" || o.Name == "--timeout" || o.Aliases.Contains("--timeout"));
|
||||
timeoutOption.Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RunCommand_HasOutputOption()
|
||||
{
|
||||
// Arrange
|
||||
var services = CreateTestServices();
|
||||
var verboseOption = new Option<bool>("--verbose");
|
||||
|
||||
// Act
|
||||
var command = DoctorCommandGroup.BuildDoctorCommand(services, verboseOption, CancellationToken.None);
|
||||
var runCommand = command.Subcommands.First(c => c.Name == "run");
|
||||
|
||||
// Assert
|
||||
var outputOption = runCommand.Options.FirstOrDefault(o =>
|
||||
o.Name == "output" || o.Aliases.Contains("--output") || o.Aliases.Contains("-o"));
|
||||
outputOption.Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RunCommand_HasFailOnWarnOption()
|
||||
{
|
||||
// Arrange
|
||||
var services = CreateTestServices();
|
||||
var verboseOption = new Option<bool>("--verbose");
|
||||
|
||||
// Act
|
||||
var command = DoctorCommandGroup.BuildDoctorCommand(services, verboseOption, CancellationToken.None);
|
||||
var runCommand = command.Subcommands.First(c => c.Name == "run");
|
||||
|
||||
// Assert - System.CommandLine stores option name without leading dashes
|
||||
var failOnWarnOption = runCommand.Options.FirstOrDefault(o =>
|
||||
o.Name == "fail-on-warn" || o.Name == "--fail-on-warn" || o.Aliases.Contains("--fail-on-warn"));
|
||||
failOnWarnOption.Should().NotBeNull();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region List Subcommand Options Tests
|
||||
|
||||
[Fact]
|
||||
public void ListCommand_HasCategoryOption()
|
||||
{
|
||||
// Arrange
|
||||
var services = CreateTestServices();
|
||||
var verboseOption = new Option<bool>("--verbose");
|
||||
|
||||
// Act
|
||||
var command = DoctorCommandGroup.BuildDoctorCommand(services, verboseOption, CancellationToken.None);
|
||||
var listCommand = command.Subcommands.First(c => c.Name == "list");
|
||||
|
||||
// Assert
|
||||
var categoryOption = listCommand.Options.FirstOrDefault(o =>
|
||||
o.Name == "category" || o.Aliases.Contains("--category") || o.Aliases.Contains("-c"));
|
||||
categoryOption.Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListCommand_HasTagOption()
|
||||
{
|
||||
// Arrange
|
||||
var services = CreateTestServices();
|
||||
var verboseOption = new Option<bool>("--verbose");
|
||||
|
||||
// Act
|
||||
var command = DoctorCommandGroup.BuildDoctorCommand(services, verboseOption, CancellationToken.None);
|
||||
var listCommand = command.Subcommands.First(c => c.Name == "list");
|
||||
|
||||
// Assert
|
||||
var tagOption = listCommand.Options.FirstOrDefault(o =>
|
||||
o.Name == "tag" || o.Aliases.Contains("--tag") || o.Aliases.Contains("-t"));
|
||||
tagOption.Should().NotBeNull();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Exit Codes Tests
|
||||
|
||||
[Fact]
|
||||
public void CliExitCodes_SuccessIsZero()
|
||||
{
|
||||
CliExitCodes.Success.Should().Be(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CliExitCodes_DoctorFailedIs100()
|
||||
{
|
||||
CliExitCodes.DoctorFailed.Should().Be(100);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CliExitCodes_DoctorWarningIs101()
|
||||
{
|
||||
CliExitCodes.DoctorWarning.Should().Be(101);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CliExitCodes_DoctorCodesAreUnique()
|
||||
{
|
||||
var codes = new[]
|
||||
{
|
||||
CliExitCodes.DoctorFailed,
|
||||
CliExitCodes.DoctorWarning
|
||||
};
|
||||
|
||||
codes.Should().OnlyHaveUniqueItems();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CliExitCodes_DoctorCodesDoNotOverlapWithGeneralCodes()
|
||||
{
|
||||
var generalCodes = new[]
|
||||
{
|
||||
CliExitCodes.Success,
|
||||
CliExitCodes.InputFileNotFound,
|
||||
CliExitCodes.MissingRequiredOption,
|
||||
CliExitCodes.ServiceNotConfigured,
|
||||
CliExitCodes.SigningFailed,
|
||||
CliExitCodes.VerificationFailed,
|
||||
CliExitCodes.PolicyViolation,
|
||||
CliExitCodes.FileNotFound,
|
||||
CliExitCodes.GeneralError,
|
||||
CliExitCodes.NotImplemented,
|
||||
CliExitCodes.UnexpectedError
|
||||
};
|
||||
|
||||
var doctorCodes = new[]
|
||||
{
|
||||
CliExitCodes.DoctorFailed,
|
||||
CliExitCodes.DoctorWarning
|
||||
};
|
||||
|
||||
generalCodes.Should().NotIntersectWith(doctorCodes);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DoctorRunOptions Tests
|
||||
|
||||
[Fact]
|
||||
public void DoctorRunOptions_DefaultModeIsNormal()
|
||||
{
|
||||
var options = new DoctorRunOptions();
|
||||
|
||||
options.Mode.Should().Be(DoctorRunMode.Normal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoctorRunOptions_DefaultParallelismIsFour()
|
||||
{
|
||||
var options = new DoctorRunOptions();
|
||||
|
||||
options.Parallelism.Should().Be(4);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoctorRunOptions_DefaultTimeoutIsThirtySeconds()
|
||||
{
|
||||
var options = new DoctorRunOptions();
|
||||
|
||||
options.Timeout.Should().Be(TimeSpan.FromSeconds(30));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoctorRunOptions_DefaultCategoriesIsNull()
|
||||
{
|
||||
var options = new DoctorRunOptions();
|
||||
|
||||
options.Categories.Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoctorRunOptions_DefaultTagsIsNull()
|
||||
{
|
||||
var options = new DoctorRunOptions();
|
||||
|
||||
options.Tags.Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoctorRunOptions_DefaultCheckIdsIsNull()
|
||||
{
|
||||
var options = new DoctorRunOptions();
|
||||
|
||||
options.CheckIds.Should().BeNull();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DoctorSeverity Tests
|
||||
|
||||
[Fact]
|
||||
public void DoctorSeverity_PassIsZero()
|
||||
{
|
||||
((int)DoctorSeverity.Pass).Should().Be(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoctorSeverity_InfoIsOne()
|
||||
{
|
||||
((int)DoctorSeverity.Info).Should().Be(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoctorSeverity_WarnIsTwo()
|
||||
{
|
||||
((int)DoctorSeverity.Warn).Should().Be(2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoctorSeverity_FailIsThree()
|
||||
{
|
||||
((int)DoctorSeverity.Fail).Should().Be(3);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoctorSeverity_SkipIsFour()
|
||||
{
|
||||
((int)DoctorSeverity.Skip).Should().Be(4);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DoctorRunMode Tests
|
||||
|
||||
[Fact]
|
||||
public void DoctorRunMode_QuickIsZero()
|
||||
{
|
||||
((int)DoctorRunMode.Quick).Should().Be(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoctorRunMode_NormalIsOne()
|
||||
{
|
||||
((int)DoctorRunMode.Normal).Should().Be(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoctorRunMode_FullIsTwo()
|
||||
{
|
||||
((int)DoctorRunMode.Full).Should().Be(2);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper Methods
|
||||
|
||||
private static IServiceProvider CreateTestServices()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
|
||||
// Add configuration
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(new Dictionary<string, string?>())
|
||||
.Build();
|
||||
services.AddSingleton<IConfiguration>(configuration);
|
||||
|
||||
// Add time provider
|
||||
services.AddSingleton(TimeProvider.System);
|
||||
|
||||
// Add logging
|
||||
services.AddLogging();
|
||||
|
||||
// Add doctor services
|
||||
services.AddDoctorEngine();
|
||||
|
||||
return services.BuildServiceProvider();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../StellaOps.Cli/StellaOps.Cli.csproj" />
|
||||
<ProjectReference Include="../../../__Libraries/StellaOps.Doctor/StellaOps.Doctor.csproj" />
|
||||
<ProjectReference Include="../../__Libraries/StellaOps.Cli.Plugins.Aoc/StellaOps.Cli.Plugins.Aoc.csproj" />
|
||||
<ProjectReference Include="../../__Libraries/StellaOps.Cli.Plugins.NonCore/StellaOps.Cli.Plugins.NonCore.csproj" />
|
||||
<ProjectReference Include="../../__Libraries/StellaOps.Cli.Plugins.Symbols/StellaOps.Cli.Plugins.Symbols.csproj" />
|
||||
|
||||
Reference in New Issue
Block a user