Пример #1
0
        public static ExecutionResult LoadModule(CommandContext commandContext, string moduleName, string[] moduleSettingOverrides, string[] pluginListOverride, bool forceCompilation, out Module module)
        {
            module = null;

            ModuleConfiguration moduleConfiguration;

            try
            {
                moduleConfiguration = ModuleConfigurationLoader.LoadModuleConfiguration(commandContext, moduleName, moduleSettingOverrides, pluginListOverride);
                if (moduleConfiguration == null)
                {
                    return(ExecutionResult.ModuleConfigurationError);
                }
            }
            catch (Exception ex)
            {
                var msg = ex.FormatExceptionWithDetails(false);
                Console.WriteLine("error during initialization:");
                Console.WriteLine(msg);
                if (Debugger.IsAttached)
                {
                    Console.WriteLine("press any key to exit...");
                    Console.ReadKey();
                }
                else
                {
                    Thread.Sleep(3000);
                }

                return(ExecutionResult.ModuleConfigurationError);
            }

            if (moduleConfiguration.ConnectionStrings.All.Any())
            {
                commandContext.Logger.Information("relevant connection strings");

                foreach (var connectionString in moduleConfiguration.ConnectionStrings.All)
                {
                    var knownFields = connectionString.GetKnownConnectionStringFields();
                    if (knownFields == null)
                    {
                        commandContext.Logger.Information("\t{ConnectionStringName} ({Provider})",
                                                          connectionString.Name, connectionString.GetFriendlyProviderName());
                    }
                    else
                    {
                        var message = "\t{ConnectionStringName} ({Provider})";
                        var args    = new List <object>()
                        {
                            connectionString.Name,
                            connectionString.GetFriendlyProviderName(),
                        };

                        if (knownFields.Server != null)
                        {
                            message += ", server: {Server}";
                            args.Add(knownFields.Server);
                        }

                        if (knownFields.Port != null)
                        {
                            message += ", port: {Port}";
                            args.Add(knownFields.Port);
                        }

                        if (knownFields.Database != null)
                        {
                            message += ", database: {Database}";
                            args.Add(knownFields.Database);
                        }

                        if (knownFields.IntegratedSecurity != null)
                        {
                            message += ", integrated security: {IntegratedSecurity}";
                            args.Add(knownFields.IntegratedSecurity);
                        }

                        if (knownFields.UserId != null)
                        {
                            message += ", user: {UserId}";
                            args.Add(knownFields.UserId);
                        }

                        commandContext.Logger.Information(message, args.ToArray());
                    }
                }
            }

            var sharedFolder         = Path.Combine(commandContext.HostConfiguration.ModulesFolder, "Shared");
            var sharedConfigFileName = Path.Combine(sharedFolder, "shared-configuration.json");

            var startedOn = Stopwatch.StartNew();

            var useAppDomain = !forceCompilation &&
                               (commandContext.HostConfiguration.DynamicCompilationMode == DynamicCompilationMode.Never ||
                                (commandContext.HostConfiguration.DynamicCompilationMode == DynamicCompilationMode.Default && Debugger.IsAttached));

            if (useAppDomain)
            {
                commandContext.Logger.Information("loading plugins directly from AppDomain if namespace ends with '{Module}'", moduleName);
                var appDomainPlugins = LoadPluginsFromAppDomain(moduleName);
                commandContext.Logger.Debug("finished in {Elapsed}", startedOn.Elapsed);
                module = new Module()
                {
                    ModuleConfiguration = moduleConfiguration,
                    Plugins             = appDomainPlugins,
                    EnabledPlugins      = GetEnabledPlugins(moduleConfiguration, appDomainPlugins),
                };

                foreach (var unknownPluginName in GetUnknownPlugins(moduleConfiguration, appDomainPlugins))
                {
                    commandContext.Logger.Warning("unknown plugin '{PluginName}'", unknownPluginName);
                }

                commandContext.Logger.Debug("{PluginCount} plugin(s) found: {PluginNames}",
                                            module.EnabledPlugins.Count, module.EnabledPlugins.Select(plugin => plugin.GetType().GetFriendlyTypeName()).ToArray());

                return(ExecutionResult.Success);
            }

            commandContext.Logger.Information("compiling plugins from {Folder} using shared files from {SharedFolder}", PathHelpers.GetFriendlyPathName(moduleConfiguration.ModuleFolder), PathHelpers.GetFriendlyPathName(sharedFolder));
            var selfFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

            var referenceAssemblyFolder = commandContext.HostConfiguration.CustomReferenceAssemblyFolder;

            if (string.IsNullOrEmpty(referenceAssemblyFolder))
            {
                referenceAssemblyFolder = Directory.GetDirectories(@"c:\Program Files\dotnet\shared\Microsoft.NETCore.App\", "5.*")
                                          .OrderByDescending(x => new DirectoryInfo(x).CreationTime)
                                          .FirstOrDefault();
            }

            commandContext.Logger.Information("using assemblies from {ReferenceAssemblyFolder}", referenceAssemblyFolder);

            var referenceDllFileNames = new List <string>();

            referenceDllFileNames.AddRange(Directory.GetFiles(referenceAssemblyFolder, "System*.dll", SearchOption.TopDirectoryOnly));
            referenceDllFileNames.AddRange(Directory.GetFiles(referenceAssemblyFolder, "netstandard.dll", SearchOption.TopDirectoryOnly));

            var referenceFileNames = new List <string>();

            referenceFileNames.AddRange(referenceDllFileNames);

            var localDllFileNames = Directory.GetFiles(selfFolder, "*.dll", SearchOption.TopDirectoryOnly);

            referenceFileNames.AddRange(localDllFileNames);

            var metadataReferences = referenceFileNames
                                     .Distinct()
                                     .Select(fn => MetadataReference.CreateFromFile(fn))
                                     .ToArray();

            var csFileNames = Directory.GetFiles(moduleConfiguration.ModuleFolder, "*.cs", SearchOption.AllDirectories);

            if (Directory.Exists(sharedFolder))
            {
                csFileNames = csFileNames
                              .Concat(Directory.GetFiles(sharedFolder, "*.cs", SearchOption.AllDirectories))
                              .ToArray();
            }

            var options = CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp8);

            var syntaxTrees = csFileNames
                              .Select(fn => SyntaxFactory.ParseSyntaxTree(SourceText.From(File.ReadAllText(fn)), options, fn))
                              .ToArray();

            using (var assemblyStream = new MemoryStream())
            {
                var id          = Interlocked.Increment(ref _moduleAutoincrementId);
                var compilation = CSharpCompilation.Create("compiled_" + id.ToString("D", CultureInfo.InvariantCulture) + ".dll", syntaxTrees, metadataReferences, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary,
                                                                                                                                                                                                optimizationLevel: OptimizationLevel.Release,
                                                                                                                                                                                                assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default));

                var result = compilation.Emit(assemblyStream);
                if (!result.Success)
                {
                    var failures = result.Diagnostics.Where(diagnostic => diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error);
                    foreach (var error in failures)
                    {
                        // DiagnosticFormatter can be used for custom formatting
                        commandContext.Logger.Write(LogEventLevel.Fatal, "syntax error in plugin: {ErrorMessage}", error.ToString());
                        commandContext.OpsLogger.Write(LogEventLevel.Fatal, "syntax error in plugin: {ErrorMessage}", error.GetMessage());
                    }

                    return(ExecutionResult.ModuleLoadError);
                }

                assemblyStream.Seek(0, SeekOrigin.Begin);

                var assemblyLoadContext = new AssemblyLoadContext("loader", false);
                var assembly            = assemblyLoadContext.LoadFromStream(assemblyStream);

                var compiledPlugins = LoadPluginsFromAssembly(assembly);
                commandContext.Logger.Debug("compilation finished in {Elapsed}", startedOn.Elapsed);
                module = new Module()
                {
                    ModuleConfiguration = moduleConfiguration,
                    Plugins             = compiledPlugins,
                    EnabledPlugins      = GetEnabledPlugins(moduleConfiguration, compiledPlugins),
                };

                foreach (var unknownPluginName in GetUnknownPlugins(moduleConfiguration, compiledPlugins))
                {
                    commandContext.Logger.Warning("unknown plugin '{PluginName}'", unknownPluginName);
                }


                commandContext.Logger.Debug("{PluginCount} plugin(s) found: {PluginNames}",
                                            module.EnabledPlugins.Count, module.EnabledPlugins.Select(plugin => plugin.GetType().GetFriendlyTypeName()).ToArray());

                return(ExecutionResult.Success);
            }
        }
Пример #2
0
        public void ValidateConnectionStrings(
            [Operand(Name = "names", Description = "The space-separated list of module names.")] List <string> moduleNames,
            [Option(LongName = "all", ShortName = "a")] bool all)
        {
            if (moduleNames == null || moduleNames.Count == 0)
            {
                if (!all)
                {
                    CommandLineHandler.DisplayHelp("test connection-strings");
                    return;
                }
            }
            else if (all)
            {
                CommandLineHandler.DisplayHelp("test connection-strings");
                return;
            }

            var commandContext = CommandLineHandler.Context;

            if (all)
            {
                moduleNames = ModuleLister.GetAllModules(commandContext);
            }

            var allConnectionStrings = new List <NamedConnectionString>();
            var index = 0;

            foreach (var moduleName in moduleNames)
            {
                var moduleConfiguration = ModuleConfigurationLoader.LoadModuleConfiguration(commandContext, moduleName, null, null);
                if (moduleConfiguration == null)
                {
                    continue;
                }

                if (index == 0)
                {
                    var sharedCs = new ConnectionStringCollection();
                    sharedCs.LoadFromConfiguration(moduleConfiguration.Configuration, "ConnectionStrings:Shared", commandContext.HostConfiguration.SecretProtector);
                    if (sharedCs.All.Any())
                    {
                        commandContext.Logger.Information("connection strings for: {Module}", "Shared");
                        foreach (var cs in sharedCs.All)
                        {
                            commandContext.Logger.Information("\t{ConnectionStringName} ({Provider})", cs.Name, cs.GetFriendlyProviderName());
                            allConnectionStrings.Add(cs);
                        }
                    }
                }

                commandContext.Logger.Information("connection strings for: {Module}", moduleName);

                var connectionStrings = new ConnectionStringCollection();
                connectionStrings.LoadFromConfiguration(moduleConfiguration.Configuration, "ConnectionStrings:Module", commandContext.HostConfiguration.SecretProtector);
                foreach (var cs in connectionStrings.All)
                {
                    commandContext.Logger.Information("\t{ConnectionStringName} ({Provider})", cs.Name, cs.GetFriendlyProviderName());
                    allConnectionStrings.RemoveAll(x => x.Name == cs.Name);
                    allConnectionStrings.Add(cs);
                }

                index++;
            }

            commandContext.Logger.Information("relevant connection strings");
            var originalNames = allConnectionStrings
                                .Select(x => x.Name.Split('-')[0])
                                .Distinct()
                                .ToList();

            foreach (var originalName in originalNames)
            {
                var connectionString = allConnectionStrings.Find(x => string.Equals(x.Name, originalName + "-" + Environment.MachineName, StringComparison.InvariantCultureIgnoreCase))
                                       ?? allConnectionStrings.Find(x => string.Equals(x.Name, originalName, StringComparison.InvariantCultureIgnoreCase));

                var knownFields = connectionString.GetKnownConnectionStringFields();
                if (knownFields == null)
                {
                    commandContext.Logger.Information("\ttesting: {ConnectionStringName} ({Provider})",
                                                      connectionString.Name, connectionString.GetFriendlyProviderName());
                }
                else
                {
                    var message = "\ttesting: {ConnectionStringName} ({Provider})";
                    var args    = new List <object>()
                    {
                        connectionString.Name,
                        connectionString.GetFriendlyProviderName(),
                    };

                    if (knownFields.Server != null)
                    {
                        message += ", server: {Server}";
                        args.Add(knownFields.Server);
                    }

                    if (knownFields.Port != null)
                    {
                        message += ", port: {Port}";
                        args.Add(knownFields.Port);
                    }

                    if (knownFields.Database != null)
                    {
                        message += ", database: {Database}";
                        args.Add(knownFields.Database);
                    }

                    if (knownFields.IntegratedSecurity != null)
                    {
                        message += ", integrated security: {IntegratedSecurity}";
                        args.Add(knownFields.IntegratedSecurity);
                    }

                    if (knownFields.UserId != null)
                    {
                        message += ", user: {UserId}";
                        args.Add(knownFields.UserId);
                    }

                    commandContext.Logger.Information(message, args.ToArray());
                }

                try
                {
                    EtlConnectionManager.TestConnection(connectionString);
                    commandContext.Logger.Information("\t\tPASSED");
                }
                catch (Exception ex)
                {
                    commandContext.Logger.Write(LogEventLevel.Fatal, "\t\t{ErrorMessage}", ex.FormatExceptionWithDetails(false));
                }
            }

            commandContext.Logger.Information("connection string test(s) finished");
        }