public void WhenInitializedWithNoParameters()
        {
            MultiSourceKeyValueConfiguration multiSourceKeyValueConfiguration =
                ConfigurationInitialization.InitializeConfiguration();

            Assert.NotNull(multiSourceKeyValueConfiguration);
        }
コード例 #2
0
        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;
        }
コード例 #3
0
        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"]);
        }
コード例 #5
0
        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"]);
        }
コード例 #8
0
        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));
        }
コード例 #9
0
 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;
 }
コード例 #10
0
        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);
        }
コード例 #11
0
        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();
コード例 #12
0
        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);
        }
コード例 #13
0
 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;
 }
コード例 #14
0
        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);
        }
コード例 #15
0
        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;
        }
コード例 #16
0
        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);
        }
コード例 #17
0
        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 { })
コード例 #18
0
        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);
        }
コード例 #19
0
        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);
        }
コード例 #20
0
 public KeyValueConfigurationModule([NotNull] MultiSourceKeyValueConfiguration configuration, ILogger logger)
 {
     _multiSourceKeyValueConfiguration = configuration ?? throw new ArgumentNullException(nameof(configuration));
     _logger = logger;
 }
コード例 #21
0
        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);
        }
コード例 #22
0
        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;
            }
        }
コード例 #23
0
        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);
        }