Select Git revision
Program.cs

Petar Hristov authored and
Sandra Westerhoff
committed
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
Program.cs 5.75 KiB
using CommandLine;
using Coscine.GraphDeployer.Models.ConfigurationModels;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NLog;
using NLog.Extensions.Logging;
using Winton.Extensions.Configuration.Consul;
using static Coscine.GraphDeployer.Utils.CommandLineOptions;
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
namespace Coscine.GraphDeployer;
public class Program
{
private static IServiceProvider _serviceProvider = null!;
public static int Main(string[] args)
{
InitializeServices();
var logger = _serviceProvider.GetRequiredService<ILogger<Program>>();
try
{
var parserResult = Parser.Default.ParseArguments<GraphDeployerOptions>(args);
var result = parserResult.MapResult(
(opts) => _serviceProvider.GetRequiredService<Deployer>().RunAsync(opts).Result,
HandleParseError
);
if (result)
{
logger.LogInformation("Finished.");
return 0; // Exit Code 0 for Success
}
else
{
logger.LogInformation("Program execution was interrupted.");
return -1; // Exit Code -1 for Failure
}
}
catch (Exception ex)
{
logger.LogError(ex, "Exception: {message}", ex.Message);
return -1; // Exit Code -1 for Failure
}
finally
{
DisposeServices();
}
}
private static void InitializeServices()
{
// Create a new instance of ConfigurationBuilder
var configBuilder = new ConfigurationBuilder();
// Define the Consul URL
var consulUrl = Environment.GetEnvironmentVariable("CONSUL_URL") ?? "http://localhost:8500";
// Remove the default sources
configBuilder.Sources.Clear();
// Add Consul as a configuration source
var configuration = configBuilder
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddConsul(
"coscine/Coscine.Infrastructure/GraphDeployer/appsettings",
options =>
{
options.ConsulConfigurationOptions =
cco => cco.Address = new Uri(consulUrl);
options.Optional = true;
options.ReloadOnChange = true;
options.PollWaitTime = TimeSpan.FromSeconds(5);
options.OnLoadException = exceptionContext => exceptionContext.Ignore = true;
}
)
.AddEnvironmentVariables()
.Build();
var services = new ServiceCollection()
.AddSingleton<IConfiguration>(configuration);
// Add the configuration to the service collection
services.Configure<GraphDeployerConfiguration>(config =>
{
configuration.GetSection(GraphDeployerConfiguration.Section).Bind(config);
});
// Add logging
services.AddLogging(builder =>
{
builder.ClearProviders();
builder.SetMinimumLevel(LogLevel.Trace);
builder.AddNLog();
});
var graphDeployerConfiguration = new GraphDeployerConfiguration();
configuration.Bind(GraphDeployerConfiguration.Section, graphDeployerConfiguration);
// Set the default LogLevel
LogManager.Configuration.Variables["logLevel"] = graphDeployerConfiguration.Logger?.LogLevel ?? "Trace";
// Set the log location
LogManager.Configuration.Variables["logHome"] = graphDeployerConfiguration.Logger?.LogHome ?? Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
// Register the HTTP client
services.AddHttpClient();
// Add services for reporting
services.AddTransient<Deployer>();
_serviceProvider = services.BuildServiceProvider();
}
private static void DisposeServices()
{
if (_serviceProvider == null)
{
return;
}
if (_serviceProvider is IDisposable disposable)
{
disposable.Dispose();
}
}
private static bool HandleParseError(IEnumerable<Error> errs)
{
var logger = _serviceProvider.GetService<ILogger<Program>>();
foreach (var err in errs)
{
if (err is HelpRequestedError || err is VersionRequestedError)
{
// Handle the display of help or version information
// Usually, the library will automatically display the help/version info,
// but you can customize it if needed.
}
else
{
// For other types of errors, you can log them or write them to the console
logger?.LogError("Error encountered parsing command-line options: {Error}", err.ToString());
Console.Error.WriteLine($"Error: {err}");
}
}
// Since there were errors, we typically return false to indicate that the program should not proceed
return false;
}
public static TResult SanitizeOptions<TResult>(TResult unsanitizedOptions)
{
// Sanitize all input that accepts an array or is a list of inputs.
if (unsanitizedOptions is not null)
{
var type = unsanitizedOptions.GetType();
if (type == typeof(GraphDeployerOptions))
{
var options = unsanitizedOptions as GraphDeployerOptions;
if (options is not null)
{
// Sanitize options here
return (TResult)(object)options;
}
}
}
return unsanitizedOptions;
}
}