Restructure solution layout by module
This commit is contained in:
141
src/Cli/StellaOps.Cli/Program.cs
Normal file
141
src/Cli/StellaOps.Cli/Program.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StellaOps.Auth.Client;
|
||||
using StellaOps.Cli.Commands;
|
||||
using StellaOps.Cli.Configuration;
|
||||
using StellaOps.Cli.Services;
|
||||
using StellaOps.Cli.Telemetry;
|
||||
|
||||
namespace StellaOps.Cli;
|
||||
|
||||
internal static class Program
|
||||
{
|
||||
internal static async Task<int> Main(string[] args)
|
||||
{
|
||||
var (options, configuration) = CliBootstrapper.Build(args);
|
||||
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton(configuration);
|
||||
services.AddSingleton(options);
|
||||
|
||||
var verbosityState = new VerbosityState();
|
||||
services.AddSingleton(verbosityState);
|
||||
|
||||
services.AddLogging(builder =>
|
||||
{
|
||||
builder.ClearProviders();
|
||||
builder.AddSimpleConsole(logOptions =>
|
||||
{
|
||||
logOptions.TimestampFormat = "HH:mm:ss ";
|
||||
logOptions.SingleLine = true;
|
||||
});
|
||||
builder.AddFilter((category, level) => level >= verbosityState.MinimumLevel);
|
||||
});
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(options.Authority.Url))
|
||||
{
|
||||
services.AddStellaOpsAuthClient(clientOptions =>
|
||||
{
|
||||
clientOptions.Authority = options.Authority.Url;
|
||||
clientOptions.ClientId = options.Authority.ClientId ?? string.Empty;
|
||||
clientOptions.ClientSecret = options.Authority.ClientSecret;
|
||||
clientOptions.DefaultScopes.Clear();
|
||||
clientOptions.DefaultScopes.Add(string.IsNullOrWhiteSpace(options.Authority.Scope)
|
||||
? StellaOps.Auth.Abstractions.StellaOpsScopes.ConcelierJobsTrigger
|
||||
: options.Authority.Scope);
|
||||
|
||||
var resilience = options.Authority.Resilience ?? new StellaOpsCliAuthorityResilienceOptions();
|
||||
clientOptions.EnableRetries = resilience.EnableRetries ?? true;
|
||||
|
||||
if (resilience.RetryDelays is { Count: > 0 })
|
||||
{
|
||||
clientOptions.RetryDelays.Clear();
|
||||
foreach (var delay in resilience.RetryDelays)
|
||||
{
|
||||
if (delay > TimeSpan.Zero)
|
||||
{
|
||||
clientOptions.RetryDelays.Add(delay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (resilience.AllowOfflineCacheFallback.HasValue)
|
||||
{
|
||||
clientOptions.AllowOfflineCacheFallback = resilience.AllowOfflineCacheFallback.Value;
|
||||
}
|
||||
|
||||
if (resilience.OfflineCacheTolerance.HasValue && resilience.OfflineCacheTolerance.Value >= TimeSpan.Zero)
|
||||
{
|
||||
clientOptions.OfflineCacheTolerance = resilience.OfflineCacheTolerance.Value;
|
||||
}
|
||||
});
|
||||
|
||||
var cacheDirectory = options.Authority.TokenCacheDirectory;
|
||||
if (!string.IsNullOrWhiteSpace(cacheDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(cacheDirectory);
|
||||
services.AddStellaOpsFileTokenCache(cacheDirectory);
|
||||
}
|
||||
|
||||
services.AddHttpClient<IAuthorityRevocationClient, AuthorityRevocationClient>(client =>
|
||||
{
|
||||
client.Timeout = TimeSpan.FromMinutes(2);
|
||||
if (Uri.TryCreate(options.Authority.Url, UriKind.Absolute, out var authorityUri))
|
||||
{
|
||||
client.BaseAddress = authorityUri;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
services.AddHttpClient<IBackendOperationsClient, BackendOperationsClient>(client =>
|
||||
{
|
||||
client.Timeout = TimeSpan.FromMinutes(5);
|
||||
if (!string.IsNullOrWhiteSpace(options.BackendUrl) &&
|
||||
Uri.TryCreate(options.BackendUrl, UriKind.Absolute, out var backendUri))
|
||||
{
|
||||
client.BaseAddress = backendUri;
|
||||
}
|
||||
});
|
||||
|
||||
services.AddHttpClient<IConcelierObservationsClient, ConcelierObservationsClient>(client =>
|
||||
{
|
||||
client.Timeout = TimeSpan.FromSeconds(30);
|
||||
if (!string.IsNullOrWhiteSpace(options.ConcelierUrl) &&
|
||||
Uri.TryCreate(options.ConcelierUrl, UriKind.Absolute, out var concelierUri))
|
||||
{
|
||||
client.BaseAddress = concelierUri;
|
||||
}
|
||||
});
|
||||
|
||||
services.AddSingleton<IScannerExecutor, ScannerExecutor>();
|
||||
services.AddSingleton<IScannerInstaller, ScannerInstaller>();
|
||||
|
||||
await using var serviceProvider = services.BuildServiceProvider();
|
||||
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
|
||||
var startupLogger = loggerFactory.CreateLogger("StellaOps.Cli.Startup");
|
||||
AuthorityDiagnosticsReporter.Emit(configuration, startupLogger);
|
||||
using var cts = new CancellationTokenSource();
|
||||
Console.CancelKeyPress += (_, eventArgs) =>
|
||||
{
|
||||
eventArgs.Cancel = true;
|
||||
cts.Cancel();
|
||||
};
|
||||
|
||||
var rootCommand = CommandFactory.Create(serviceProvider, options, cts.Token, loggerFactory);
|
||||
var commandConfiguration = new CommandLineConfiguration(rootCommand);
|
||||
var commandExit = await commandConfiguration.InvokeAsync(args, cts.Token).ConfigureAwait(false);
|
||||
|
||||
var finalExit = Environment.ExitCode != 0 ? Environment.ExitCode : commandExit;
|
||||
if (cts.IsCancellationRequested && finalExit == 0)
|
||||
{
|
||||
finalExit = 130; // Typical POSIX cancellation exit code
|
||||
}
|
||||
|
||||
return finalExit;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user