public void WhenInitializedWithNoParameters() { MultiSourceKeyValueConfiguration multiSourceKeyValueConfiguration = ConfigurationInitialization.InitializeConfiguration(); Assert.NotNull(multiSourceKeyValueConfiguration); }
public DiagnosticsViewHandler( [NotNull] IDeploymentTargetReadService deploymentTargetReadService, [NotNull] MultiSourceKeyValueConfiguration configuration, [NotNull] IConfiguration aspNetConfiguration, [NotNull] LoggingLevelSwitch loggingLevelSwitch, [NotNull] EnvironmentConfiguration environmentConfiguration, IServiceProvider serviceProvider, ServiceDiagnostics serviceDiagnostics, ConfigurationInstanceHolder configurationInstanceHolder, ILogger logger, IApplicationSettingsStore settingsStore, IApplicationAssemblyResolver applicationAssemblyResolver, IDistributedCache distributedCache) { _deploymentTargetReadService = deploymentTargetReadService ?? throw new ArgumentNullException(nameof(deploymentTargetReadService)); _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); _aspNetConfiguration = aspNetConfiguration ?? throw new ArgumentNullException(nameof(aspNetConfiguration)); _loggingLevelSwitch = loggingLevelSwitch ?? throw new ArgumentNullException(nameof(loggingLevelSwitch)); _environmentConfiguration = environmentConfiguration; _serviceProvider = serviceProvider; _serviceDiagnostics = serviceDiagnostics; _configurationInstanceHolder = configurationInstanceHolder; _logger = logger; _settingsStore = settingsStore; _applicationAssemblyResolver = applicationAssemblyResolver; _distributedCache = distributedCache; }
private static IReadOnlyList <IModule> GetConfigurationModules( MultiSourceKeyValueConfiguration configuration, [NotNull] CancellationTokenSource cancellationTokenSource, ILogger logger, ImmutableArray <Assembly> scanAssemblies) { var modules = new List <IModule>(); if (cancellationTokenSource == null) { throw new ArgumentNullException(nameof(cancellationTokenSource)); } var loggingModule = new LoggingModule(logger); var module = new KeyValueConfigurationModule(configuration, logger); var urnModule = new UrnConfigurationModule(configuration, logger, scanAssemblies); modules.Add(loggingModule); modules.Add(module); modules.Add(urnModule); modules.Add(new MediatRModule(scanAssemblies)); return(modules); }
public void WhenInitializedWithCommandLineArg() { string[] args = { "urn:abc:123=hello world" }; MultiSourceKeyValueConfiguration multiSourceKeyValueConfiguration = ConfigurationInitialization.InitializeConfiguration(args: args); Assert.NotNull(multiSourceKeyValueConfiguration); Assert.Equal("hello world", multiSourceKeyValueConfiguration["urn:abc:123"]); }
public static void SetTempPath(MultiSourceKeyValueConfiguration configuration, ILogger logger) { string tempDirectory = configuration[ApplicationConstants.ApplicationTempDirectory]; if (!string.IsNullOrWhiteSpace(tempDirectory)) { SetTempPath(new DirectoryInfo(tempDirectory), logger); } }
public void WhenInitializedWithEnvironmentVariable() { var args = new Dictionary <string, string> { ["urn:abc:123"] = "hello world" }; MultiSourceKeyValueConfiguration multiSourceKeyValueConfiguration = ConfigurationInitialization.InitializeConfiguration(environmentVariables: args); Assert.NotNull(multiSourceKeyValueConfiguration); Assert.Equal("hello world", multiSourceKeyValueConfiguration["urn:abc:123"]); }
public void WhenInitializedWithEnvironmentVariableAndCommandLineArgs() { string[] args = { "urn:abc:123=hello arg world" }; var environmentVariables = new Dictionary <string, string> { ["urn:abc:123"] = "hello environment world" }; MultiSourceKeyValueConfiguration multiSourceKeyValueConfiguration = ConfigurationInitialization.InitializeConfiguration(environmentVariables: environmentVariables, args: args); Assert.NotNull(multiSourceKeyValueConfiguration); Assert.Equal("hello arg world", multiSourceKeyValueConfiguration["urn:abc:123"]); }
public async Task <ActionResult <SettingsViewModel> > Index( [FromServices] MultiSourceKeyValueConfiguration configuration, [FromServices] IMediator mediator) { if (!configuration[SettingsConstants.DiagnosticsEnabled].ParseAsBooleanOrDefault()) { return(new StatusCodeResult(403)); } SettingsViewModel settingsViewModel = await mediator.Send(new SettingsViewRequest()); return(View(settingsViewModel)); }
public App( [NotNull] IWebHostBuilder webHost, [NotNull] CancellationTokenSource cancellationTokenSource, [NotNull] ILogger appLogger, MultiSourceKeyValueConfiguration configuration) { CancellationTokenSource = cancellationTokenSource ?? throw new ArgumentNullException(nameof(cancellationTokenSource)); Logger = appLogger ?? throw new ArgumentNullException(nameof(appLogger)); Configuration = configuration; HostBuilder = webHost ?? throw new ArgumentNullException(nameof(webHost)); _instanceId = Guid.NewGuid(); AppInstance = ApplicationConstants.ApplicationName + " " + _instanceId; }
public void ItShouldUseValuesDefined() { IConfigurationRoot configurationRoot = new ConfigurationBuilder() .AddInMemoryCollection(new Dictionary <string, string> { ["a:b:c"] = "123" }).Build(); MultiSourceKeyValueConfiguration multiSourceKeyValueConfiguration = KeyValueConfigurationManager .Add(new KeyValueConfigurationAdapter(configurationRoot)).Build(); string actual = multiSourceKeyValueConfiguration["a:b:c"]; Assert.Equal("123", actual); }
private static Task <App <T> > BuildAppAsync(CancellationTokenSource cancellationTokenSource, string[] commandLineArgs, IReadOnlyDictionary <string, string> environmentVariables, IReadOnlyCollection <Assembly> scanAssemblies, params object[] instances) { MultiSourceKeyValueConfiguration startupConfiguration = ConfigurationInitialization.InitializeStartupConfiguration(commandLineArgs, environmentVariables, scanAssemblies); ConfigurationInstanceHolder configurationInstanceHolder = GetConfigurationRegistrations(startupConfiguration, scanAssemblies); var assemblyResolver = new InstanceApplicationAssemblyResolver(scanAssemblies.SafeToImmutableArray()); configurationInstanceHolder.AddInstance(assemblyResolver); configurationInstanceHolder.AddInstance(configurationInstanceHolder); foreach (object instance in instances.NotNull()) { configurationInstanceHolder.AddInstance(instance); } var loggingLevelSwitch = new LoggingLevelSwitch(); configurationInstanceHolder.AddInstance(loggingLevelSwitch); configurationInstanceHolder.AddInstance(cancellationTokenSource); ApplicationPaths paths = configurationInstanceHolder.GetInstances <ApplicationPaths>().SingleOrDefault().Value ?? new ApplicationPaths(); AppPathHelper.SetApplicationPaths(paths, commandLineArgs); if (paths.BasePath is null) { throw new InvalidOperationException("Base path is not set"); } var startupLoggerConfigurationHandlers = assemblyResolver.GetAssemblies() .GetLoadablePublicConcreteTypesImplementing < IStartupLoggerConfigurationHandler>() .Select(type => configurationInstanceHolder.Create(type) as IStartupLoggerConfigurationHandler) .Where(item => item is { }).ToImmutableArray();
public void ItShouldResolveSingleInstanceFromUrn() { IConfigurationRoot configurationRoot = new ConfigurationBuilder() .AddInMemoryCollection(new Dictionary <string, string> { ["urn:test:simple:instance:name"] = "John", ["urn:test:simple:instance:age"] = "42" }).Build(); MultiSourceKeyValueConfiguration multiSourceKeyValueConfiguration = KeyValueConfigurationManager .Add(new KeyValueConfigurationAdapter(configurationRoot)).Build(); SimpleCtorType actual = multiSourceKeyValueConfiguration.GetInstance <SimpleCtorType>() ?? throw new InvalidOperationException( $"Could not get {nameof(SimpleCtorType)}"); Assert.Equal(new SimpleCtorType("John", 42), actual, SimpleCtorType.NameAgeComparer); }
public DiagnosticsViewHandler( [NotNull] IDeploymentTargetReadService deploymentTargetReadService, [NotNull] MultiSourceKeyValueConfiguration configuration, [NotNull] Scope scope, [NotNull] IConfiguration aspNetConfiguration, [NotNull] LoggingLevelSwitch loggingLevelSwitch, [NotNull] EnvironmentConfiguration environmentConfiguration) { _deploymentTargetReadService = deploymentTargetReadService ?? throw new ArgumentNullException(nameof(deploymentTargetReadService)); _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); _scope = scope ?? throw new ArgumentNullException(nameof(scope)); _aspNetConfiguration = aspNetConfiguration ?? throw new ArgumentNullException(nameof(aspNetConfiguration)); _loggingLevelSwitch = loggingLevelSwitch ?? throw new ArgumentNullException(nameof(loggingLevelSwitch)); _environmentConfiguration = environmentConfiguration; }
private static App BuildApp( CancellationTokenSource cancellationTokenSource, string[] args) { ImmutableArray <Assembly> scanAssemblies = AppDomain.CurrentDomain.FilteredAssemblies(); string basePathFromArg = args.SingleOrDefault(arg => arg.StartsWith("urn:arbor:syslogserver:base-path", StringComparison.OrdinalIgnoreCase)); string basePath = basePathFromArg?.Split('=').LastOrDefault() ?? AppDomain.CurrentDomain.BaseDirectory; ILogger startupLogger = SerilogApiInitialization.InitializeStartupLogging(file => GetBaseDirectoryFile(basePath, file)); MultiSourceKeyValueConfiguration configuration = ConfigurationInitialization.InitializeConfiguration(file => GetBaseDirectoryFile(basePath, file), startupLogger); ILogger appLogger = SerilogApiInitialization.InitializeAppLogging(configuration, startupLogger); appLogger.Debug("Started with command line args, {Args}", args); IReadOnlyList <IModule> modules = GetConfigurationModules(configuration, cancellationTokenSource, appLogger, scanAssemblies); IContainer container = Bootstrapper.Start(basePathFromArg, modules, appLogger, scanAssemblies); ILifetimeScope webHostScope = container.BeginLifetimeScope(builder => { builder.RegisterType <Startup>().AsSelf(); }); IWebHostBuilder webHostBuilder = CustomWebHostBuilder.GetWebHostBuilder(container, webHostScope, appLogger); var buildApp = new App(webHostBuilder, cancellationTokenSource, appLogger) { Container = container, WebHostScope = webHostScope }; return(buildApp); }
public App(IHostBuilder hostBuilder, CancellationTokenSource cancellationTokenSource, ILogger appLogger, MultiSourceKeyValueConfiguration configuration, IReadOnlyCollection <Assembly> scanAssemblies, ConfigurationInstanceHolder configurationInstanceHolder) { CancellationTokenSource = cancellationTokenSource ?? throw new ArgumentNullException(nameof(cancellationTokenSource)); Logger = appLogger ?? throw new ArgumentNullException(nameof(appLogger)); Configuration = configuration; ScanAssemblies = scanAssemblies.SafeToImmutableArray(); ConfigurationInstanceHolder = configurationInstanceHolder; HostBuilder = hostBuilder ?? throw new ArgumentNullException(nameof(hostBuilder)); _instanceId = Guid.NewGuid(); ApplicationName = configuration.GetApplicationName(); AppInstance = ApplicationName + " " + _instanceId; }
public static MultiSourceKeyValueConfiguration InitializeConfiguration( [NotNull] Func <string, string> basePath, ILogger logger) { if (basePath == null) { throw new ArgumentNullException(nameof(basePath)); } string environmentBasedSettingsPath = Environment.GetEnvironmentVariable(Configuration.ConfigurationConstants.JsonSettingsFile); string environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"; AppSettingsBuilder appSettingsBuilder = KeyValueConfigurationManager .Add(new ReflectionKeyValueConfiguration(typeof(ConfigurationInitialization).Assembly)) .Add(new JsonKeyValueConfiguration(basePath("settings.json"), false)) .Add(new JsonKeyValueConfiguration(basePath($"settings.{environmentName}.json"), false)) .Add(new JsonKeyValueConfiguration(basePath($"settings.{Environment.MachineName}.json"), false)); if (environmentBasedSettingsPath.HasValue() && File.Exists(environmentBasedSettingsPath)) { appSettingsBuilder = appSettingsBuilder.Add(new JsonKeyValueConfiguration(environmentBasedSettingsPath, true)); logger.Information("Added environment based configuration from key '{Key}', file '{File}'", Configuration.ConfigurationConstants.JsonSettingsFile, environmentBasedSettingsPath); } MultiSourceKeyValueConfiguration multiSourceKeyValueConfiguration = appSettingsBuilder .Add(new EnvironmentVariableKeyValueConfigurationSource()) .Add(new UserConfiguration()) .DecorateWith(new ExpandKeyValueConfigurationDecorator()) .Build(); logger.Information("Configuration done using chain {Chain}", multiSourceKeyValueConfiguration.SourceChain); return(multiSourceKeyValueConfiguration); }
public static ILogger InitializeAppLogging( [NotNull] MultiSourceKeyValueConfiguration multiSourceKeyValueConfiguration, ILogger logger, IEnumerable <ILoggerConfigurationHandler> loggerConfigurationHandlers, LoggingLevelSwitch loggingLevelSwitch, SerilogConfiguration?serilogConfiguration = null, string?applicationName = null) { if (multiSourceKeyValueConfiguration is null) { throw new ArgumentNullException(nameof(multiSourceKeyValueConfiguration)); } logger.Verbose("Getting Serilog configuration"); var serilogConfigurations = multiSourceKeyValueConfiguration.GetInstances <SerilogConfiguration>(); if (serilogConfigurations.Length > 1) { logger.Warning("Found multiple Serilog configurations {Configurations}", serilogConfigurations); } if (serilogConfiguration is { })
private static async Task <App> BuildAppAsync( CancellationTokenSource cancellationTokenSource, Action <LoggerConfiguration> loggerConfigurationAction, string[] args) { ImmutableArray <Assembly> scanAssemblies = Assemblies.FilteredAssemblies(); string basePathFromArg = args.ParseParameter(ConfigurationConstants.ApplicationBasePath); string contentBasePathFromArg = args.ParseParameter(ConfigurationConstants.ContentBasePath); bool IsRunningAsService() { bool hasRunAsServiceArgument = args.Any(arg => arg.Equals(ApplicationConstants.RunAsService, StringComparison.OrdinalIgnoreCase)); if (hasRunAsServiceArgument) { return(true); } FileInfo processFileInfo; using (Process currentProcess = Process.GetCurrentProcess()) { processFileInfo = new FileInfo(currentProcess.MainModule.FileName); } if (processFileInfo.Name.Equals("Milou.Deployer.Web.WindowsService.exe", StringComparison.OrdinalIgnoreCase)) { return(true); } return(false); } string currentDomainBaseDirectory = AppDomain.CurrentDomain.BaseDirectory; if (IsRunningAsService()) { Console.WriteLine($"Switching current directory from {Directory.GetCurrentDirectory()} to {currentDomainBaseDirectory}"); Directory.SetCurrentDirectory(currentDomainBaseDirectory); } string basePath = basePathFromArg ?? currentDomainBaseDirectory; string contentBasePath = contentBasePathFromArg ?? Directory.GetCurrentDirectory(); ILogger startupLogger = SerilogApiInitialization.InitializeStartupLogging(file => GetBaseDirectoryFile(basePath, file)); startupLogger.Information("Using application root directory {Directory}", basePath); MultiSourceKeyValueConfiguration configuration = ConfigurationInitialization.InitializeConfiguration(args, file => GetBaseDirectoryFile(basePath, file), startupLogger, scanAssemblies, contentBasePath); string tempDirectory = configuration[ApplicationConstants.ApplicationTempDirectory]; if (!string.IsNullOrWhiteSpace(tempDirectory)) { if (tempDirectory.TryEnsureDirectoryExists(out DirectoryInfo tempDirectoryInfo)) { Environment.SetEnvironmentVariable(TempConstants.Tmp, tempDirectoryInfo.FullName); Environment.SetEnvironmentVariable(TempConstants.Temp, tempDirectoryInfo.FullName); startupLogger.Debug("Using specified temp directory {TempDirectory} {AppName}", tempDirectory, ApplicationConstants.ApplicationName); } else { startupLogger.Warning("Could not use specified temp directory {TempDirectory}, {AppName}", tempDirectory, ApplicationConstants.ApplicationName); } } var loggingLevelSwitch = new LoggingLevelSwitch(LogEventLevel.Debug); ILogger appLogger = SerilogApiInitialization.InitializeAppLogging(configuration, startupLogger, loggerConfigurationAction, loggingLevelSwitch); if (args.Length > 0) { appLogger.Debug("Application started with command line args, {Args}, {AppName}", args, ApplicationConstants.ApplicationName); } else if (appLogger.IsEnabled(LogEventLevel.Verbose)) { appLogger.Verbose("Application started with no command line args, {AppName}", ApplicationConstants.ApplicationName); } IReadOnlyList <IModule> modules = GetConfigurationModules(configuration, cancellationTokenSource, appLogger, scanAssemblies); Type[] excludedModuleTypes = { typeof(AppServiceModule) }; var environmentConfiguration = new EnvironmentConfiguration { ApplicationBasePath = basePath, ContentBasePath = contentBasePath }; var singletons = new object[] { loggingLevelSwitch, environmentConfiguration }; Scope rootScope = Bootstrapper.Start(configuration, modules, appLogger, scanAssemblies, excludedModuleTypes, singletons); DeploymentTargetIds deploymentTargetIds = await GetDeploymentWorkerIdsAsync(rootScope.Deepest().Lifetime, appLogger, cancellationTokenSource.Token); ILifetimeScope webHostScope = rootScope.Deepest().Lifetime.BeginLifetimeScope(builder => { builder.RegisterInstance(deploymentTargetIds).AsSelf().SingleInstance(); builder.RegisterType <Startup>().AsSelf(); }); var webHostScopeWrapper = new Scope(Scope.WebHostScope, webHostScope); rootScope.Deepest().SubScope = webHostScopeWrapper; EnvironmentConfigurator.ConfigureEnvironment(rootScope.Deepest().Lifetime); IWebHostBuilder webHostBuilder = CustomWebHostBuilder.GetWebHostBuilder(configuration, rootScope, webHostScopeWrapper, appLogger, rootScope.Top()); var app = new App(webHostBuilder, cancellationTokenSource, appLogger, configuration) { AppRootScope = rootScope.SubScope }; return(app); }
public static ILogger InitializeAppLogging( [NotNull] MultiSourceKeyValueConfiguration multiSourceKeyValueConfiguration, ILogger logger, Action <LoggerConfiguration> loggerConfigurationAction, LoggingLevelSwitch loggingLevelSwitch) { if (multiSourceKeyValueConfiguration == null) { throw new ArgumentNullException(nameof(multiSourceKeyValueConfiguration)); } SerilogConfiguration serilogConfiguration = multiSourceKeyValueConfiguration.GetInstances <SerilogConfiguration>().FirstOrDefault(); if (!serilogConfiguration.HasValue()) { logger.Error("Could not get any instance of type {Type}", typeof(SerilogConfiguration)); return(logger); } if (serilogConfiguration.RollingLogFilePathEnabled && !serilogConfiguration.RollingLogFilePath.HasValue()) { const string message = "Serilog rolling file log path is not set"; logger.Error(message); throw new DeployerAppException(message); } LoggerConfiguration loggerConfiguration = new LoggerConfiguration() .MinimumLevel.ControlledBy(loggingLevelSwitch) .Enrich.WithProperty("Application", ApplicationConstants.ApplicationName); if (serilogConfiguration.DebugConsoleEnabled) { loggerConfiguration = loggerConfiguration.WriteTo.Debug(); } if (serilogConfiguration.SeqEnabled && serilogConfiguration.IsValid) { if (!string.IsNullOrWhiteSpace(serilogConfiguration.SeqUrl) && Uri.TryCreate(serilogConfiguration.SeqUrl, UriKind.Absolute, out Uri serilogUrl)) { logger.Debug("Serilog configured to use Seq with URL {Url}", serilogUrl.AbsoluteUri); loggerConfiguration = loggerConfiguration.WriteTo.Seq(serilogUrl.AbsoluteUri); } } if (serilogConfiguration.RollingLogFilePathEnabled) { string logFilePath = Path.IsPathRooted(serilogConfiguration.RollingLogFilePath) ? serilogConfiguration.RollingLogFilePath : Path.Combine(AppDomain.CurrentDomain.BaseDirectory, serilogConfiguration.RollingLogFilePath); var fileInfo = new FileInfo(logFilePath); if (fileInfo.Directory != null) { string rollingLoggingFile = Path.Combine(fileInfo.Directory.FullName, $"{Path.GetFileNameWithoutExtension(fileInfo.Name)}.{{Date}}{Path.GetExtension(fileInfo.Name)}"); logger.Debug("Serilog configured to use rolling file with file path {LogFilePath}", rollingLoggingFile); loggerConfiguration = loggerConfiguration .WriteTo.File(rollingLoggingFile); } } loggerConfiguration = loggerConfiguration.WriteTo.Console(); LoggerConfiguration finalConfiguration = loggerConfiguration .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) .Enrich.FromLogContext(); loggerConfigurationAction?.Invoke(loggerConfiguration); Logger appLogger = finalConfiguration .CreateLogger(); appLogger.Debug("Initialized app logging"); return(appLogger); }
public KeyValueConfigurationModule([NotNull] MultiSourceKeyValueConfiguration configuration, ILogger logger) { _multiSourceKeyValueConfiguration = configuration ?? throw new ArgumentNullException(nameof(configuration)); _logger = logger; }
public static MultiSourceKeyValueConfiguration InitializeConfiguration( IReadOnlyList <string> args, [NotNull] Func <string, string> basePath, ILogger logger, IReadOnlyCollection <Assembly> scanAssemblies, string contentBasePath) { if (basePath == null) { throw new ArgumentNullException(nameof(basePath)); } string environmentBasedSettingsPath = Environment.GetEnvironmentVariable(ConfigurationConstants.JsonSettingsFile); string environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"; AppSettingsBuilder appSettingsBuilder = KeyValueConfigurationManager .Add(new InMemoryKeyValueConfiguration(new NameValueCollection())); foreach (Assembly currentAssembly in scanAssemblies.OrderBy(assembly => assembly.FullName)) { appSettingsBuilder = appSettingsBuilder.Add( new ReflectionKeyValueConfiguration(currentAssembly)); } var loggingSettings = new NameValueCollection { { "Logging:LogLevel:Default", "Warning" }, { "Logging:LogLevel:System.Net.Http.HttpClient", "Warning" }, { "LogLevel:System.Net.Http.HttpClient", "Warning" } }; FileInfo MachineSpecificConfig(DirectoryInfo directoryInfo) { return(directoryInfo.GetFiles($"settings.{Environment.MachineName}.json").SingleOrDefault()); } string MachineSpecificFile() { var baseDirectory = new DirectoryInfo(basePath(null)); FileInfo machineSpecificConfig = null; DirectoryInfo currentDirectory = baseDirectory; while (machineSpecificConfig is null && currentDirectory != null) { try { machineSpecificConfig = MachineSpecificConfig(currentDirectory); currentDirectory = currentDirectory.Parent; } catch (Exception ex) when(!ex.IsFatal()) { logger.Warning(ex, "Could not find machine specific config file in any parent directory starting with base directory {BaseDirectory}", baseDirectory.FullName); return(null); } } return(machineSpecificConfig?.FullName); } appSettingsBuilder = appSettingsBuilder .Add(new InMemoryKeyValueConfiguration(loggingSettings)) .Add(new JsonKeyValueConfiguration(basePath("settings.json"), false)) .Add(new JsonKeyValueConfiguration(basePath($"settings.{environmentName}.json"), false)); string machineSpecificFile = MachineSpecificFile(); if (!string.IsNullOrWhiteSpace(machineSpecificFile)) { appSettingsBuilder = appSettingsBuilder.Add(new JsonKeyValueConfiguration(machineSpecificFile)); } if (environmentBasedSettingsPath.HasValue() && File.Exists(environmentBasedSettingsPath)) { appSettingsBuilder = appSettingsBuilder.Add(new JsonKeyValueConfiguration(environmentBasedSettingsPath, true)); logger.Information("Added environment based configuration from key '{Key}', file '{File}'", ConfigurationConstants.JsonSettingsFile, environmentBasedSettingsPath); } var nameValueCollection = new NameValueCollection(StringComparer.OrdinalIgnoreCase); const char variableAssignmentCharacter = '='; foreach (string arg in args.Where(a => a.Count(c => c == variableAssignmentCharacter) == 1 && a.Length >= 3)) { string[] parts = arg.Split(variableAssignmentCharacter, StringSplitOptions.RemoveEmptyEntries); if (parts.Length != 2) { Console.WriteLine($"arg {arg} has length {parts.Length}"); continue; } string key = parts[0]; string value = parts[1]; nameValueCollection.Add(key, value); } var inMemoryKeyValueConfiguration = new InMemoryKeyValueConfiguration(nameValueCollection); MultiSourceKeyValueConfiguration multiSourceKeyValueConfiguration = appSettingsBuilder .Add(new JsonKeyValueConfiguration(Path.Combine(contentBasePath, "config.user"), throwWhenNotExists: false)) .Add(new EnvironmentVariableKeyValueConfigurationSource()) .Add(inMemoryKeyValueConfiguration) .DecorateWith(new ExpandKeyValueConfigurationDecorator()) .Build(); logger.Information("Configuration done using chain {Chain}", multiSourceKeyValueConfiguration.SourceChain); return(multiSourceKeyValueConfiguration); }
public static async Task <DeployerApp> BuildAppAsync([NotNull] string[] inputArgs, ILogger?logger = null, CancellationToken cancellationToken = default) { if (inputArgs is null) { throw new ArgumentNullException(nameof(inputArgs)); } var args = inputArgs.ToImmutableArray(); bool hasDefinedLogger = logger is {}; string outputTemplate = GetOutputTemplate(args); var levelSwitch = new LoggingLevelSwitch(); logger ??= new LoggerConfiguration() .WriteTo.Console(outputTemplate: outputTemplate, standardErrorFromLevel: LogEventLevel.Error) .MinimumLevel.ControlledBy(levelSwitch) .CreateLogger(); logger.Verbose("Using output template {Template}", outputTemplate); try { string?machineSettings = GetMachineSettingsFile(new DirectoryInfo(Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "tools", "Milou.Deployer"))); AppSettingsBuilder appSettingsBuilder; try { appSettingsBuilder = KeyValueConfigurationManager .Add(new ReflectionKeyValueConfiguration(typeof(AppBuilder).Assembly)) .Add(new ReflectionKeyValueConfiguration(typeof(ConfigurationKeys).Assembly)); } catch (Exception ex) when(!ex.IsFatal()) { logger.Error(ex, "Could note create settings"); throw; } if (!string.IsNullOrWhiteSpace(machineSettings)) { logger.Information("Using machine specific configuration file '{Settings}'", machineSettings); appSettingsBuilder = appSettingsBuilder.Add(new JsonKeyValueConfiguration(machineSettings, false)); } string?configurationFile = Environment.GetEnvironmentVariable(ConfigurationKeys.KeyValueConfigurationFile); if (!string.IsNullOrWhiteSpace(configurationFile) && File.Exists(configurationFile)) { logger.Information("Using configuration values from file '{ConfigurationFile}'", configurationFile); appSettingsBuilder = appSettingsBuilder.Add(new JsonKeyValueConfiguration(configurationFile, false)); } var argsAsParameters = args .Where(arg => arg.StartsWith("-", StringComparison.OrdinalIgnoreCase)) .Select(arg => arg.TrimStart('-')) .ToImmutableArray(); MultiSourceKeyValueConfiguration configuration = appSettingsBuilder .Add(new EnvironmentVariableKeyValueConfigurationSource()) .AddCommandLineArgsSettings(argsAsParameters) .Add(new UserJsonConfiguration()) .Build(); logger.Debug("Using configuration: {Configuration}", configuration.SourceChain); string logPath = configuration[ConsoleConfigurationKeys.LoggingFilePath]; string environmentLogLevel = configuration[ConfigurationKeys.LogLevelEnvironmentVariable]; string configurationLogLevel = configuration[ConfigurationKeys.LogLevel]; var logLevel = Arbor.App.Extensions.Logging.LogEventLevelExtensions.ParseOrDefault( environmentLogLevel.WithDefault(configurationLogLevel)); levelSwitch.MinimumLevel = logLevel; LoggerConfiguration loggerConfiguration = new LoggerConfiguration() .WriteTo.Console(outputTemplate: outputTemplate); if (!string.IsNullOrWhiteSpace(logPath)) { loggerConfiguration = loggerConfiguration.WriteTo.File(logPath); } if (!hasDefinedLogger) { if (logger is IDisposable disposable) { disposable.Dispose(); } logger = loggerConfiguration .MinimumLevel.ControlledBy(levelSwitch) .CreateLogger(); } if (!string.IsNullOrWhiteSpace(machineSettings)) { logger.Information("Using machine specific configuration file '{Settings}'", machineSettings); } string?nugetSource = args.GetArgumentValueOrDefault("nuget-source"); string?nugetConfig = args.GetArgumentValueOrDefault("nuget-config"); var webDeployConfig = new WebDeployConfig(new WebDeployRulesConfig( true, true, false, true, true)); bool allowPreReleaseEnabled = configuration[ConfigurationKeys.AllowPreReleaseEnvironmentVariable] .ParseAsBooleanOrDefault() || (Debugger.IsAttached && configuration[ConfigurationKeys.ForceAllowPreRelease] .ParseAsBooleanOrDefault()); string?nuGetExePath = configuration[ConfigurationKeys.NuGetExePath]; if (string.IsNullOrWhiteSpace(nuGetExePath)) { logger.Debug("nuget.exe is not specified, downloading with {Tool}", nameof(NuGetDownloadClient)); using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30))) { var nuGetDownloadClient = new NuGetDownloadClient(); NuGetDownloadResult nuGetDownloadResult; using (var httpClient = new HttpClient()) { nuGetDownloadResult = await nuGetDownloadClient .DownloadNuGetAsync(NuGetDownloadSettings.Default, logger, httpClient, cts.Token) .ConfigureAwait(false); } if (!nuGetDownloadResult.Succeeded) { throw new InvalidOperationException( Resources.NuGetExeCouldNotBeDownloaded); } nuGetExePath = nuGetDownloadResult.NuGetExePath; } logger.Debug("Successfully downloaded nuget.exe to '{DownloadedPath}'", nuGetExePath); } var deployerConfiguration = new DeployerConfiguration(webDeployConfig) { NuGetExePath = nuGetExePath, NuGetConfig = nugetConfig.WithDefault(configuration[ConfigurationKeys.NuGetConfig]), NuGetSource = nugetSource.WithDefault(configuration[ConfigurationKeys.NuGetSource]), AllowPreReleaseEnabled = allowPreReleaseEnabled, StopStartIisWebSiteEnabled = configuration[ConfigurationKeys.StopStartIisWebSiteEnabled] .ParseAsBooleanOrDefault(true) }; var nuGetCliSettings = new NuGetCliSettings( deployerConfiguration.NuGetSource, nuGetExePath: deployerConfiguration.NuGetExePath, nugetConfigFile: deployerConfiguration.NuGetConfig); var nuGetPackageInstaller = new NuGetPackageInstaller(logger: logger, nugetCliSettings: nuGetCliSettings); var deploymentService = new DeploymentService( deployerConfiguration, logger, configuration, new WebDeployHelper(logger), deploymentExecutionDefinition => IisManager.Create(deployerConfiguration, logger, deploymentExecutionDefinition), nuGetPackageInstaller, new FtpHandlerFactory()); string temp = configuration[ConfigurationKeys.TempDirectory]; const string tempEnvironmentVariableName = "temp"; if (!string.IsNullOrWhiteSpace(temp) && Directory.Exists(temp)) { Environment.SetEnvironmentVariable(tempEnvironmentVariableName, temp); Environment.SetEnvironmentVariable("tmp", temp); } var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); return(new DeployerApp(logger, deploymentService, configuration, levelSwitch, cancellationTokenSource)); } catch (Exception ex) when(!ex.IsFatal()) { logger.Error("Could not build application"); throw; } }
public async Task <ExitCode> RunAsync(string[] args) { MultiSourceKeyValueConfiguration multiSourceKeyValueConfiguration = KeyValueConfigurationManager.Add(new UserConfiguration()) .Add(new AppSettingsKeyValueConfiguration()) .Build(); StaticKeyValueConfigurationManager.Initialize(multiSourceKeyValueConfiguration); bool simulateDebug = bool.TryParse(Environment.GetEnvironmentVariable("SimulateDebug"), out bool parsed) && parsed; bool debugLoggerEnabled = false; if (Debugger.IsAttached || simulateDebug) { if (simulateDebug) { _logger.Write("Simulating debug"); } await StartWithDebuggerAsync(args).ConfigureAwait(false); if (debugLoggerEnabled) { _logger = new DebugLogger(_logger); } } _container = await BuildBootstrapper.StartAsync(); _logger.Write($"Using logger '{_logger.GetType()}' with log level {_logger.LogLevel}"); _cancellationToken = CancellationToken.None; ExitCode exitCode; var stopwatch = new Stopwatch(); stopwatch.Start(); try { ExitCode systemToolsResult = await RunSystemToolsAsync(); if (!systemToolsResult.IsSuccess) { const string ToolsMessage = "All system tools did not succeed"; _logger.WriteError(ToolsMessage); exitCode = systemToolsResult; } else { exitCode = ExitCode.Success; _logger.Write("All tools succeeded"); } } catch (Exception ex) { _logger.WriteError(ex.ToString()); exitCode = ExitCode.Failure; } stopwatch.Stop(); _logger.Write($"Arbor.X.Build total elapsed time in seconds: {stopwatch.Elapsed.TotalSeconds:F}"); ParseResult <int> exitDelayInMilliseconds = Environment.GetEnvironmentVariable(WellKnownVariables.BuildApplicationExitDelayInMilliseconds) .TryParseInt32(0); if (exitDelayInMilliseconds > 0) { _logger.Write( $"Delaying build application exit with {exitDelayInMilliseconds} milliseconds specified in '{WellKnownVariables.BuildApplicationExitDelayInMilliseconds}'"); await Task.Delay(TimeSpan.FromMilliseconds(exitDelayInMilliseconds), _cancellationToken); } if (Debugger.IsAttached) { WriteDebug($"Exiting build application with exit code {exitCode}"); if (!debugLoggerEnabled) { Debugger.Break(); } } return(exitCode); }