automate the 2.1.0 upgrade
This commit is contained in:
		
							
								
								
									
										102
									
								
								Oqtane.Server/Infrastructure/ConfigManager.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								Oqtane.Server/Infrastructure/ConfigManager.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,102 @@ | ||||
| using System; | ||||
| using System.IO; | ||||
| using Microsoft.Extensions.Configuration; | ||||
| using Newtonsoft.Json; | ||||
| using Newtonsoft.Json.Linq; | ||||
|  | ||||
| namespace Oqtane.Infrastructure | ||||
| { | ||||
|     public class ConfigManager : IConfigManager | ||||
|     { | ||||
|         private readonly IConfigurationRoot _config; | ||||
|  | ||||
|         public ConfigManager(IConfigurationRoot config) | ||||
|         { | ||||
|             _config = config; | ||||
|         } | ||||
|  | ||||
|         public IConfigurationSection GetSection(string key) | ||||
|         { | ||||
|             return _config.GetSection(key); | ||||
|         } | ||||
|  | ||||
|         public string GetSetting(string sectionKey, string settingKey, string defaultValue) | ||||
|         { | ||||
|             var value = _config.GetSection(sectionKey).GetValue(settingKey, defaultValue); | ||||
|             if (string.IsNullOrEmpty(value)) value = defaultValue; | ||||
|             return value; | ||||
|         } | ||||
|  | ||||
|         public void AddOrUpdateSetting<T>(string key, T value, bool reload) | ||||
|         { | ||||
|             AddOrUpdateSetting("appsettings.json", key, value, reload); | ||||
|         } | ||||
|  | ||||
|         public void AddOrUpdateSetting<T>(string file, string key, T value, bool reload) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 var path = Path.Combine(Directory.GetCurrentDirectory(), file); | ||||
|                 dynamic jsonObj = JsonConvert.DeserializeObject(File.ReadAllText(path)); | ||||
|                 SetValueRecursively(key, jsonObj, value, "set"); | ||||
|                 File.WriteAllText(path, JsonConvert.SerializeObject(jsonObj, Formatting.Indented)); | ||||
|                 if (reload) Reload(); | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Console.WriteLine("Error modifying app settings {0}", ex); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public void RemoveSetting(string key, bool reload) | ||||
|         { | ||||
|             RemoveSetting("appsettings.json", key, reload); | ||||
|         } | ||||
|  | ||||
|         public void RemoveSetting(string file, string key, bool reload) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 var path = Path.Combine(Directory.GetCurrentDirectory(), file); | ||||
|                 dynamic jsonObj = JsonConvert.DeserializeObject(File.ReadAllText(path)); | ||||
|                 SetValueRecursively(key, jsonObj, "", "remove"); | ||||
|                 File.WriteAllText(path, JsonConvert.SerializeObject(jsonObj, Formatting.Indented)); | ||||
|                 if (reload) Reload(); | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Console.WriteLine("Error modifying app settings {0}", ex); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private void SetValueRecursively<T>(string key, dynamic jsonObj, T value, string action) | ||||
|         { | ||||
|             var remainingSections = key.Split(":", 2); | ||||
|  | ||||
|             var currentSection = remainingSections[0]; | ||||
|             if (remainingSections.Length > 1) | ||||
|             { | ||||
|                 var nextSection = remainingSections[1]; | ||||
|                 jsonObj[currentSection] ??= new JObject(); | ||||
|                 SetValueRecursively(nextSection, jsonObj[currentSection], value, action); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 switch (action) | ||||
|                 { | ||||
|                     case "set": | ||||
|                         jsonObj[currentSection] = value; | ||||
|                         break; | ||||
|                     case "remove": | ||||
|                         jsonObj.Property(currentSection).Remove(); | ||||
|                         break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public void Reload() | ||||
|         { | ||||
|             _config.Reload(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -10,14 +10,13 @@ using Microsoft.EntityFrameworkCore; | ||||
| using Microsoft.Extensions.Caching.Memory; | ||||
| using Microsoft.Extensions.Configuration; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Newtonsoft.Json; | ||||
| using Oqtane.Databases.Interfaces; | ||||
| using Oqtane.Extensions; | ||||
| using Oqtane.Models; | ||||
| using Oqtane.Repository; | ||||
| using Oqtane.Shared; | ||||
| using Oqtane.Enums; | ||||
| using File = System.IO.File; | ||||
| using Newtonsoft.Json; | ||||
|  | ||||
| // ReSharper disable MemberCanBePrivate.Global | ||||
| // ReSharper disable ConvertToUsingDeclaration | ||||
| @ -32,18 +31,23 @@ namespace Oqtane.Infrastructure | ||||
|         private readonly IServiceScopeFactory _serviceScopeFactory; | ||||
|         private readonly IWebHostEnvironment _environment; | ||||
|         private readonly IMemoryCache _cache; | ||||
|         private readonly IConfigManager _configManager; | ||||
|  | ||||
|         public DatabaseManager(IConfigurationRoot config, IServiceScopeFactory serviceScopeFactory, IWebHostEnvironment environment, IMemoryCache cache) | ||||
|         public DatabaseManager(IConfigurationRoot config, IServiceScopeFactory serviceScopeFactory, IWebHostEnvironment environment, IMemoryCache cache, IConfigManager configManager) | ||||
|         { | ||||
|             _config = config; | ||||
|             _serviceScopeFactory = serviceScopeFactory; | ||||
|             _environment = environment; | ||||
|             _cache = cache; | ||||
|             _configManager = configManager; | ||||
|         } | ||||
|  | ||||
|         public Installation IsInstalled() | ||||
|         { | ||||
|             var result = new Installation { Success = false, Message = string.Empty }; | ||||
|  | ||||
|             ValidateConfiguration(); | ||||
|  | ||||
|             if (!string.IsNullOrEmpty(_config.GetConnectionString(SettingKeys.ConnectionStringKey))) | ||||
|             { | ||||
|                 result.Success = true; | ||||
| @ -97,7 +101,6 @@ namespace Oqtane.Infrastructure | ||||
|                     if (string.IsNullOrEmpty(install.DatabaseType)) | ||||
|                     { | ||||
|                         install.DatabaseType = Constants.DefaultDBType; | ||||
|                         install.DatabasePackage = Constants.DefaultDBType.Substring(Constants.DefaultDBType.IndexOf(",") + 2); | ||||
|                         InstallDatabase(install); | ||||
|                         UpdateDatabaseType(install.DatabaseType); | ||||
|                     } | ||||
| @ -106,7 +109,6 @@ namespace Oqtane.Infrastructure | ||||
|                         // if database type does not exist, install the associated Nuget package | ||||
|                         if (Type.GetType(install.DatabaseType) == null) | ||||
|                         { | ||||
|                             install.DatabasePackage = install.DatabaseType.Substring(install.DatabaseType.IndexOf(",") + 2); | ||||
|                             InstallDatabase(install); | ||||
|                         } | ||||
|                     } | ||||
| @ -220,7 +222,7 @@ namespace Oqtane.Infrastructure | ||||
|                     // iterate through Nuget packages in source folder | ||||
|                     foreach (var package in packagesFolder.GetFiles("*.nupkg.bak")) | ||||
|                     { | ||||
|                         if (package.Name.StartsWith(install.DatabasePackage)) | ||||
|                         if (package.Name.StartsWith(Utilities.GetAssemblyName(install.DatabaseType))) | ||||
|                         { | ||||
|                             //rename file | ||||
|                             var packageName = Path.Combine(package.DirectoryName, package.Name); | ||||
| @ -237,7 +239,7 @@ namespace Oqtane.Infrastructure | ||||
|  | ||||
|                         var assemblyPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location); | ||||
|                         var assembliesFolder = new DirectoryInfo(assemblyPath); | ||||
|                         var assemblyFile = new FileInfo($"{assembliesFolder}/{install.DatabasePackage}.dll"); | ||||
|                         var assemblyFile = new FileInfo($"{assembliesFolder}/{Utilities.GetAssemblyName(install.DatabaseType)}.dll"); | ||||
|  | ||||
|                         AssemblyLoadContext.Default.LoadOqtaneAssembly(assemblyFile); | ||||
|  | ||||
| @ -644,25 +646,6 @@ namespace Oqtane.Infrastructure | ||||
|             return result; | ||||
|         } | ||||
|  | ||||
|         public void AddOrUpdateAppSetting<T>(string sectionPathKey, T value) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 var filePath = Path.Combine(Directory.GetCurrentDirectory(), "appsettings.json"); | ||||
|                 var json = File.ReadAllText(filePath); | ||||
|                 dynamic jsonObj = JsonConvert.DeserializeObject(json); | ||||
|  | ||||
|                 SetValueRecursively(sectionPathKey, jsonObj, value); | ||||
|  | ||||
|                 string output = JsonConvert.SerializeObject(jsonObj, Formatting.Indented); | ||||
|                 File.WriteAllText(filePath, output); | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Console.WriteLine("Error writing app settings | {0}", ex); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private string DenormalizeConnectionString(string connectionString) | ||||
|         { | ||||
|             var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString(); | ||||
| @ -687,10 +670,7 @@ namespace Oqtane.Infrastructure | ||||
|  | ||||
|         private string GetInstallationConfig(string key, string defaultValue) | ||||
|         { | ||||
|             var value = _config.GetSection(SettingKeys.InstallationSection).GetValue(key, defaultValue); | ||||
|             // double fallback to default value - allow hold sample keys in config | ||||
|             if (string.IsNullOrEmpty(value)) value = defaultValue; | ||||
|             return value; | ||||
|             return _configManager.GetSetting(SettingKeys.InstallationSection, key, defaultValue); | ||||
|         } | ||||
|  | ||||
|         private string NormalizeConnectionString(string connectionString) | ||||
| @ -700,39 +680,18 @@ namespace Oqtane.Infrastructure | ||||
|             return connectionString; | ||||
|         } | ||||
|  | ||||
|         private void SetValueRecursively<T>(string sectionPathKey, dynamic jsonObj, T value) | ||||
|         { | ||||
|             // split the string at the first ':' character | ||||
|             var remainingSections = sectionPathKey.Split(":", 2); | ||||
|  | ||||
|             var currentSection = remainingSections[0]; | ||||
|             if (remainingSections.Length > 1) | ||||
|             { | ||||
|                 // continue with the process, moving down the tree | ||||
|                 var nextSection = remainingSections[1]; | ||||
|                 SetValueRecursively(nextSection, jsonObj[currentSection], value); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 // we've got to the end of the tree, set the value | ||||
|                 jsonObj[currentSection] = value; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public void UpdateConnectionString(string connectionString) | ||||
|         { | ||||
|             connectionString = DenormalizeConnectionString(connectionString); | ||||
|             if (_config.GetConnectionString(SettingKeys.ConnectionStringKey) != connectionString) | ||||
|             { | ||||
|                 AddOrUpdateAppSetting($"{SettingKeys.ConnectionStringsSection}:{SettingKeys.ConnectionStringKey}", connectionString); | ||||
|                 _config.Reload(); | ||||
|                 _configManager.AddOrUpdateSetting($"{SettingKeys.ConnectionStringsSection}:{SettingKeys.ConnectionStringKey}", connectionString, true); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public void UpdateDatabaseType(string databaseType) | ||||
|         { | ||||
|             AddOrUpdateAppSetting($"{SettingKeys.DatabaseSection}:{SettingKeys.DatabaseTypeKey}", databaseType); | ||||
|             _config.Reload(); | ||||
|             _configManager.AddOrUpdateSetting($"{SettingKeys.DatabaseSection}:{SettingKeys.DatabaseTypeKey}", databaseType, true); | ||||
|         } | ||||
|  | ||||
|         public void UpgradeSqlServer(ISqlRepository sql, string connectionString, string databaseType, bool isMaster) | ||||
| @ -744,5 +703,24 @@ namespace Oqtane.Infrastructure | ||||
|  | ||||
|             sql.ExecuteNonQuery(connectionString, databaseType, query); | ||||
|         } | ||||
|  | ||||
|         private void ValidateConfiguration() | ||||
|         { | ||||
|             if (_configManager.GetSetting(SettingKeys.DatabaseSection, SettingKeys.DatabaseTypeKey, "") == "") | ||||
|             { | ||||
|                 _configManager.AddOrUpdateSetting($"{SettingKeys.DatabaseSection}:{SettingKeys.DatabaseTypeKey}", Constants.DefaultDBType, true); | ||||
|             } | ||||
|             if (!_configManager.GetSection(SettingKeys.AvailableDatabasesSection).Exists()) | ||||
|             { | ||||
|                 string databases = "["; | ||||
|                 databases += "{ \"Name\": \"LocalDB\", \"ControlType\": \"Oqtane.Installer.Controls.LocalDBConfig, Oqtane.Client\", \"DBTYpe\": \"Oqtane.Database.SqlServer.SqlServerDatabase, Oqtane.Database.SqlServer\" },"; | ||||
|                 databases += "{ \"Name\": \"SQL Server\", \"ControlType\": \"Oqtane.Installer.Controls.SqlServerConfig, Oqtane.Client\", \"DBTYpe\": \"Oqtane.Database.SqlServer.SqlServerDatabase, Oqtane.Database.SqlServer\" },"; | ||||
|                 databases += "{ \"Name\": \"SQLite\", \"ControlType\": \"Oqtane.Installer.Controls.SqliteConfig, Oqtane.Client\", \"DBTYpe\": \"Oqtane.Database.Sqlite.SqliteDatabase, Oqtane.Database.Sqlite\" },"; | ||||
|                 databases += "{ \"Name\": \"MySQL\", \"ControlType\": \"Oqtane.Installer.Controls.MySQLConfig, Oqtane.Client\", \"DBTYpe\": \"Oqtane.Database.MySQL.SqlServerDatabase, Oqtane.Database.MySQL\" },"; | ||||
|                 databases += "{ \"Name\": \"PostgreSQL\", \"ControlType\": \"Oqtane.Installer.Controls.PostgreSQLConfig, Oqtane.Client\", \"DBTYpe\": \"Oqtane.Database.PostgreSQL.PostgreSQLDatabase, Oqtane.Database.PostgreSQL\" }"; | ||||
|                 databases += "]"; | ||||
|                 _configManager.AddOrUpdateSetting(SettingKeys.AvailableDatabasesSection, JsonConvert.DeserializeObject<dynamic>(databases), true); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										15
									
								
								Oqtane.Server/Infrastructure/Interfaces/IConfigManager.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								Oqtane.Server/Infrastructure/Interfaces/IConfigManager.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| using Microsoft.Extensions.Configuration; | ||||
|  | ||||
| namespace Oqtane.Infrastructure | ||||
| { | ||||
|     public interface IConfigManager | ||||
|     { | ||||
|         public IConfigurationSection GetSection(string sectionKey); | ||||
|         public string GetSetting(string sectionKey, string settingKey, string defaultValue); | ||||
|         void AddOrUpdateSetting<T>(string key, T value, bool reload); | ||||
|         void AddOrUpdateSetting<T>(string file, string key, T value, bool reload); | ||||
|         void RemoveSetting(string key, bool reload); | ||||
|         void RemoveSetting(string file, string key, bool reload); | ||||
|         void Reload(); | ||||
|     } | ||||
| } | ||||
| @ -1,5 +1,7 @@ | ||||
| using Microsoft.AspNetCore.Hosting; | ||||
| using Microsoft.Extensions.Configuration; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Newtonsoft.Json; | ||||
| using Oqtane.Models; | ||||
| using Oqtane.Repository; | ||||
| using Oqtane.Shared; | ||||
| @ -11,15 +13,15 @@ namespace Oqtane.Infrastructure | ||||
| { | ||||
|     public class UpgradeManager : IUpgradeManager | ||||
|     { | ||||
|         private readonly IAliasRepository _aliases; | ||||
|         private readonly IServiceScopeFactory _serviceScopeFactory; | ||||
|         private readonly IWebHostEnvironment _environment; | ||||
|         private readonly IConfigManager _configManager; | ||||
|  | ||||
|         public UpgradeManager(IAliasRepository aliases, IServiceScopeFactory serviceScopeFactory, IWebHostEnvironment environment) | ||||
|         public UpgradeManager(IServiceScopeFactory serviceScopeFactory, IWebHostEnvironment environment, IConfigManager configManager) | ||||
|         { | ||||
|             _aliases = aliases; | ||||
|             _serviceScopeFactory = serviceScopeFactory; | ||||
|             _environment = environment; | ||||
|             _configManager = configManager; | ||||
|         } | ||||
|  | ||||
|         public void Upgrade(Tenant tenant, string version) | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Shaun Walker
					Shaun Walker