mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-08-24 20:52:11 +00:00
Renamed the plugin root of enterprise configurations to say what it holds
This commit is contained in:
parent
357eadd12d
commit
d4f0c650fc
@ -269,12 +269,13 @@ public static partial class ManagedConfiguration
|
|||||||
/// change it at all.
|
/// change it at all.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="availablePlugins">The collection of available plugins to check against.</param>
|
/// <param name="availablePlugins">The collection of available plugins to check against.</param>
|
||||||
/// <param name="deployedConfigPluginIds">
|
/// <param name="deployedEnterpriseConfigPluginIds">
|
||||||
/// The IDs of all configuration plugins which are deployed on this machine, including those which
|
/// The IDs of the configuration plugins which an organization deployed on this machine, including
|
||||||
/// could not be loaded. A deployed plugin was not removed, so its settings must stay untouched.
|
/// those which could not be loaded. A deployed plugin was not removed, so its settings must stay
|
||||||
|
/// untouched.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>True when at least one setting was changed, otherwise false.</returns>
|
/// <returns>True when at least one setting was changed, otherwise false.</returns>
|
||||||
public static bool CleanupLeftOverManagedConfigurations(IReadOnlyCollection<IAvailablePlugin> availablePlugins, IReadOnlySet<Guid> deployedConfigPluginIds)
|
public static bool CleanupLeftOverManagedConfigurations(IReadOnlyCollection<IAvailablePlugin> availablePlugins, IReadOnlySet<Guid> deployedEnterpriseConfigPluginIds)
|
||||||
{
|
{
|
||||||
var wasChanged = false;
|
var wasChanged = false;
|
||||||
var registeredSettingNames = new HashSet<string>(StringComparer.Ordinal);
|
var registeredSettingNames = new HashSet<string>(StringComparer.Ordinal);
|
||||||
@ -293,7 +294,7 @@ public static partial class ManagedConfiguration
|
|||||||
configMeta.RestoreLockedConfiguration();
|
configMeta.RestoreLockedConfiguration();
|
||||||
|
|
||||||
// Check the locked state:
|
// Check the locked state:
|
||||||
if (configMeta.IsLocked && configMeta.LockedByConfigPluginId != Guid.Empty && !IsPluginPresent(configMeta.LockedByConfigPluginId, availablePlugins, deployedConfigPluginIds))
|
if (configMeta.IsLocked && configMeta.LockedByConfigPluginId != Guid.Empty && !IsPluginPresent(configMeta.LockedByConfigPluginId, availablePlugins, deployedEnterpriseConfigPluginIds))
|
||||||
{
|
{
|
||||||
Log.LogInformation($"Resetting the setting '{configMeta.SettingName}': it was locked by the configuration plugin '{configMeta.LockedByConfigPluginId}', which is not available anymore.");
|
Log.LogInformation($"Resetting the setting '{configMeta.SettingName}': it was locked by the configuration plugin '{configMeta.LockedByConfigPluginId}', which is not available anymore.");
|
||||||
configMeta.ResetLockedConfiguration();
|
configMeta.ResetLockedConfiguration();
|
||||||
@ -301,11 +302,11 @@ public static partial class ManagedConfiguration
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check the editable default state:
|
// Check the editable default state:
|
||||||
if (CleanupEditableDefaultState(configMeta, availablePlugins, deployedConfigPluginIds))
|
if (CleanupEditableDefaultState(configMeta, availablePlugins, deployedEnterpriseConfigPluginIds))
|
||||||
wasChanged = true;
|
wasChanged = true;
|
||||||
|
|
||||||
// Check the additive plugin contribution:
|
// Check the additive plugin contribution:
|
||||||
if (configMeta.HasPluginContribution && configMeta.PluginContributionByConfigPluginId != Guid.Empty && !IsPluginPresent(configMeta.PluginContributionByConfigPluginId, availablePlugins, deployedConfigPluginIds))
|
if (configMeta.HasPluginContribution && configMeta.PluginContributionByConfigPluginId != Guid.Empty && !IsPluginPresent(configMeta.PluginContributionByConfigPluginId, availablePlugins, deployedEnterpriseConfigPluginIds))
|
||||||
{
|
{
|
||||||
Log.LogInformation($"Clearing the plugin contribution for the setting '{configMeta.SettingName}': the configuration plugin '{configMeta.PluginContributionByConfigPluginId}' is not available anymore.");
|
Log.LogInformation($"Clearing the plugin contribution for the setting '{configMeta.SettingName}': the configuration plugin '{configMeta.PluginContributionByConfigPluginId}' is not available anymore.");
|
||||||
configMeta.ClearPluginContribution();
|
configMeta.ClearPluginContribution();
|
||||||
@ -328,7 +329,7 @@ public static partial class ManagedConfiguration
|
|||||||
/// The latter matters for organizations: a broken configuration plugin is still in charge, so we
|
/// The latter matters for organizations: a broken configuration plugin is still in charge, so we
|
||||||
/// must not treat its settings as left over.
|
/// must not treat its settings as left over.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
private static bool IsPluginPresent(Guid configPluginId, IReadOnlyCollection<IAvailablePlugin> availablePlugins, IReadOnlySet<Guid> deployedConfigPluginIds) => deployedConfigPluginIds.Contains(configPluginId) || availablePlugins.Any(x => x.Id == configPluginId);
|
private static bool IsPluginPresent(Guid configPluginId, IReadOnlyCollection<IAvailablePlugin> availablePlugins, IReadOnlySet<Guid> deployedEnterpriseConfigPluginIds) => deployedEnterpriseConfigPluginIds.Contains(configPluginId) || availablePlugins.Any(x => x.Id == configPluginId);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes persisted managed states which belong to settings that are not registered anymore.
|
/// Removes persisted managed states which belong to settings that are not registered anymore.
|
||||||
@ -390,7 +391,7 @@ public static partial class ManagedConfiguration
|
|||||||
|
|
||||||
private static bool ClearEditableDefaultState(string settingName) => SettingsManagerAccess.ConfigurationData.ManagedEditableDefaults.Remove(settingName);
|
private static bool ClearEditableDefaultState(string settingName) => SettingsManagerAccess.ConfigurationData.ManagedEditableDefaults.Remove(settingName);
|
||||||
|
|
||||||
private static bool CleanupEditableDefaultState(ConfigMetaBase configMeta, IReadOnlyCollection<IAvailablePlugin> availablePlugins, IReadOnlySet<Guid> deployedConfigPluginIds)
|
private static bool CleanupEditableDefaultState(ConfigMetaBase configMeta, IReadOnlyCollection<IAvailablePlugin> availablePlugins, IReadOnlySet<Guid> deployedEnterpriseConfigPluginIds)
|
||||||
{
|
{
|
||||||
if (!TryGetEditableDefaultState(configMeta.SettingName, out var editableDefaultState))
|
if (!TryGetEditableDefaultState(configMeta.SettingName, out var editableDefaultState))
|
||||||
{
|
{
|
||||||
@ -401,7 +402,7 @@ public static partial class ManagedConfiguration
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsPluginPresent(editableDefaultState.ConfigPluginId, availablePlugins, deployedConfigPluginIds))
|
if (IsPluginPresent(editableDefaultState.ConfigPluginId, availablePlugins, deployedEnterpriseConfigPluginIds))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Log.LogInformation($"Clearing the editable default of the setting '{configMeta.SettingName}': the configuration plugin '{editableDefaultState.ConfigPluginId}' is not available anymore.");
|
Log.LogInformation($"Clearing the editable default of the setting '{configMeta.SettingName}': the configuration plugin '{editableDefaultState.ConfigPluginId}' is not available anymore.");
|
||||||
|
|||||||
@ -255,10 +255,10 @@ public sealed record PluginConfigurationObject
|
|||||||
/// <param name="configObjectType">The type of configuration object to process.</param>
|
/// <param name="configObjectType">The type of configuration object to process.</param>
|
||||||
/// <param name="configObjectSelection">A selection expression to retrieve the configuration objects from the main configuration.</param>
|
/// <param name="configObjectSelection">A selection expression to retrieve the configuration objects from the main configuration.</param>
|
||||||
/// <param name="availablePlugins">A list of currently available plugins.</param>
|
/// <param name="availablePlugins">A list of currently available plugins.</param>
|
||||||
/// <param name="deployedConfigPluginIds">
|
/// <param name="deployedEnterpriseConfigPluginIds">
|
||||||
/// The IDs of all configuration plugins which are deployed on this machine, including those which
|
/// The IDs of the configuration plugins which an organization deployed on this machine, including
|
||||||
/// could not be loaded. Objects of a deployed plugin are never removed, because the plugin was not
|
/// those which could not be loaded. Objects of a deployed plugin are never removed, because the
|
||||||
/// removed either.
|
/// plugin was not removed either.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="configObjectList">A list of all existing configuration objects.</param>
|
/// <param name="configObjectList">A list of all existing configuration objects.</param>
|
||||||
/// <param name="secretStoreType">An optional parameter specifying the type of secret store to use for deleting associated API keys from the OS keyring, if applicable.</param>
|
/// <param name="secretStoreType">An optional parameter specifying the type of secret store to use for deleting associated API keys from the OS keyring, if applicable.</param>
|
||||||
@ -268,7 +268,7 @@ public sealed record PluginConfigurationObject
|
|||||||
PluginConfigurationObjectType configObjectType,
|
PluginConfigurationObjectType configObjectType,
|
||||||
Expression<Func<Data, List<TClass>>> configObjectSelection,
|
Expression<Func<Data, List<TClass>>> configObjectSelection,
|
||||||
IList<IAvailablePlugin> availablePlugins,
|
IList<IAvailablePlugin> availablePlugins,
|
||||||
IReadOnlySet<Guid> deployedConfigPluginIds,
|
IReadOnlySet<Guid> deployedEnterpriseConfigPluginIds,
|
||||||
IList<PluginConfigurationObject> configObjectList,
|
IList<PluginConfigurationObject> configObjectList,
|
||||||
SecretStoreType? secretStoreType = null,
|
SecretStoreType? secretStoreType = null,
|
||||||
bool deleteSecret = false) where TClass : IConfigurationObject
|
bool deleteSecret = false) where TClass : IConfigurationObject
|
||||||
@ -295,7 +295,7 @@ public sealed record PluginConfigurationObject
|
|||||||
// the organization's providers and data sources, including their secrets, although the
|
// the organization's providers and data sources, including their secrets, although the
|
||||||
// organization still manages this AI Studio instance:
|
// organization still manages this AI Studio instance:
|
||||||
//
|
//
|
||||||
if(deployedConfigPluginIds.Contains(configObjectSourcePluginId) && availablePlugins.All(plugin => plugin.Id != configObjectSourcePluginId))
|
if(deployedEnterpriseConfigPluginIds.Contains(configObjectSourcePluginId) && availablePlugins.All(plugin => plugin.Id != configObjectSourcePluginId))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Is the source plugin still available? If not, we can be pretty sure that this configuration object is left
|
// Is the source plugin still available? If not, we can be pretty sure that this configuration object is left
|
||||||
|
|||||||
@ -45,7 +45,7 @@ public static partial class PluginFactory
|
|||||||
|
|
||||||
LOG.LogInformation($"Try to download configuration plugin with ID='{configPlugId}' from server='{configServerUrl}' (GET {downloadUrl})");
|
LOG.LogInformation($"Try to download configuration plugin with ID='{configPlugId}' from server='{configServerUrl}' (GET {downloadUrl})");
|
||||||
var tempDownloadFile = Path.GetTempFileName();
|
var tempDownloadFile = Path.GetTempFileName();
|
||||||
var stagedDirectory = Path.Join(CONFIGURATION_PLUGINS_ROOT, $"{configPlugId}.staging-{Guid.NewGuid():N}");
|
var stagedDirectory = Path.Join(ENTERPRISE_CONFIGURATION_PLUGINS_ROOT, $"{configPlugId}.staging-{Guid.NewGuid():N}");
|
||||||
string? backupDirectory = null;
|
string? backupDirectory = null;
|
||||||
var wasSuccessful = false;
|
var wasSuccessful = false;
|
||||||
try
|
try
|
||||||
@ -66,10 +66,10 @@ public static partial class PluginFactory
|
|||||||
|
|
||||||
ExtractConfigPluginArchive(tempDownloadFile, stagedDirectory);
|
ExtractConfigPluginArchive(tempDownloadFile, stagedDirectory);
|
||||||
|
|
||||||
var configDirectory = Path.Join(CONFIGURATION_PLUGINS_ROOT, configPlugId.ToString());
|
var configDirectory = Path.Join(ENTERPRISE_CONFIGURATION_PLUGINS_ROOT, configPlugId.ToString());
|
||||||
if (Directory.Exists(configDirectory))
|
if (Directory.Exists(configDirectory))
|
||||||
{
|
{
|
||||||
backupDirectory = Path.Join(CONFIGURATION_PLUGINS_ROOT, $"{configPlugId}.backup-{Guid.NewGuid():N}");
|
backupDirectory = Path.Join(ENTERPRISE_CONFIGURATION_PLUGINS_ROOT, $"{configPlugId}.backup-{Guid.NewGuid():N}");
|
||||||
Directory.Move(configDirectory, backupDirectory);
|
Directory.Move(configDirectory, backupDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ public static partial class PluginFactory
|
|||||||
{
|
{
|
||||||
LOG.LogError(e, "An error occurred while downloading or extracting the enterprise configuration plugin.");
|
LOG.LogError(e, "An error occurred while downloading or extracting the enterprise configuration plugin.");
|
||||||
|
|
||||||
var configDirectory = Path.Join(CONFIGURATION_PLUGINS_ROOT, configPlugId.ToString());
|
var configDirectory = Path.Join(ENTERPRISE_CONFIGURATION_PLUGINS_ROOT, configPlugId.ToString());
|
||||||
if (!string.IsNullOrWhiteSpace(backupDirectory) && Directory.Exists(backupDirectory) && !Directory.Exists(configDirectory))
|
if (!string.IsNullOrWhiteSpace(backupDirectory) && Directory.Exists(backupDirectory) && !Directory.Exists(configDirectory))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@ -140,7 +140,7 @@ public static partial class PluginFactory
|
|||||||
else if (isConfigurationPluginInConfigDirectory)
|
else if (isConfigurationPluginInConfigDirectory)
|
||||||
{
|
{
|
||||||
isManagedByConfigServer = true;
|
isManagedByConfigServer = true;
|
||||||
LOG.LogWarning($"The configuration plugin '{plugin.Id}' does not define 'DEPLOYED_USING_CONFIG_SERVER'. Falling back to the plugin path and treating it as managed because it is stored under '{CONFIGURATION_PLUGINS_ROOT}'.");
|
LOG.LogWarning($"The configuration plugin '{plugin.Id}' does not define 'DEPLOYED_USING_CONFIG_SERVER'. Falling back to the plugin path and treating it as managed because it is stored under '{ENTERPRISE_CONFIGURATION_PLUGINS_ROOT}'.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (plugin is PluginAssistants assistantPlugin)
|
else if (plugin is PluginAssistants assistantPlugin)
|
||||||
@ -192,40 +192,40 @@ public static partial class PluginFactory
|
|||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
// Configuration plugins which are deployed but could not be loaded count as present: they
|
// Enterprise configuration plugins which are deployed but could not be loaded count as
|
||||||
// were not removed, so everything they manage must stay as it is. Otherwise, one broken
|
// present: they were not removed, so everything they manage must stay as it is. Otherwise,
|
||||||
// configuration plugin would wipe the entire organization configuration:
|
// one broken configuration plugin would wipe the entire organization configuration:
|
||||||
//
|
//
|
||||||
var deployedConfigPluginIds = GetDeployedConfigPluginIds();
|
var deployedEnterpriseConfigPluginIds = GetDeployedEnterpriseConfigPluginIds();
|
||||||
var unloadedConfigPluginIds = deployedConfigPluginIds.Where(x => AVAILABLE_PLUGINS.All(plugin => plugin.Id != x)).ToList();
|
var unloadedEnterpriseConfigPluginIds = deployedEnterpriseConfigPluginIds.Where(x => AVAILABLE_PLUGINS.All(plugin => plugin.Id != x)).ToList();
|
||||||
foreach (var unloadedConfigPluginId in unloadedConfigPluginIds)
|
foreach (var unloadedEnterpriseConfigPluginId in unloadedEnterpriseConfigPluginIds)
|
||||||
LOG.LogWarning($"The configuration plugin '{unloadedConfigPluginId}' is deployed, but was not loaded. Everything it manages stays unchanged, because the plugin was not removed. Please check the errors above and fix the plugin.");
|
LOG.LogWarning($"The configuration plugin '{unloadedEnterpriseConfigPluginId}' is deployed, but was not loaded. Everything it manages stays unchanged, because the plugin was not removed. Please check the errors above and fix the plugin.");
|
||||||
|
|
||||||
// Check LLM providers:
|
// Check LLM providers:
|
||||||
var wasConfigurationChanged = await PluginConfigurationObject.CleanLeftOverConfigurationObjects(PluginConfigurationObjectType.LLM_PROVIDER, x => x.Providers, AVAILABLE_PLUGINS, deployedConfigPluginIds, configObjectList, SecretStoreType.LLM_PROVIDER);
|
var wasConfigurationChanged = await PluginConfigurationObject.CleanLeftOverConfigurationObjects(PluginConfigurationObjectType.LLM_PROVIDER, x => x.Providers, AVAILABLE_PLUGINS, deployedEnterpriseConfigPluginIds, configObjectList, SecretStoreType.LLM_PROVIDER);
|
||||||
|
|
||||||
// Check transcription providers:
|
// Check transcription providers:
|
||||||
if(await PluginConfigurationObject.CleanLeftOverConfigurationObjects(PluginConfigurationObjectType.TRANSCRIPTION_PROVIDER, x => x.TranscriptionProviders, AVAILABLE_PLUGINS, deployedConfigPluginIds, configObjectList, SecretStoreType.TRANSCRIPTION_PROVIDER))
|
if(await PluginConfigurationObject.CleanLeftOverConfigurationObjects(PluginConfigurationObjectType.TRANSCRIPTION_PROVIDER, x => x.TranscriptionProviders, AVAILABLE_PLUGINS, deployedEnterpriseConfigPluginIds, configObjectList, SecretStoreType.TRANSCRIPTION_PROVIDER))
|
||||||
wasConfigurationChanged = true;
|
wasConfigurationChanged = true;
|
||||||
|
|
||||||
// Check embedding providers:
|
// Check embedding providers:
|
||||||
if(await PluginConfigurationObject.CleanLeftOverConfigurationObjects(PluginConfigurationObjectType.EMBEDDING_PROVIDER, x => x.EmbeddingProviders, AVAILABLE_PLUGINS, deployedConfigPluginIds, configObjectList, SecretStoreType.EMBEDDING_PROVIDER))
|
if(await PluginConfigurationObject.CleanLeftOverConfigurationObjects(PluginConfigurationObjectType.EMBEDDING_PROVIDER, x => x.EmbeddingProviders, AVAILABLE_PLUGINS, deployedEnterpriseConfigPluginIds, configObjectList, SecretStoreType.EMBEDDING_PROVIDER))
|
||||||
wasConfigurationChanged = true;
|
wasConfigurationChanged = true;
|
||||||
|
|
||||||
// Check data sources:
|
// Check data sources:
|
||||||
if(await PluginConfigurationObject.CleanLeftOverConfigurationObjects(PluginConfigurationObjectType.DATA_SOURCE, x => x.DataSources, AVAILABLE_PLUGINS, deployedConfigPluginIds, configObjectList, SecretStoreType.DATA_SOURCE, deleteSecret: true))
|
if(await PluginConfigurationObject.CleanLeftOverConfigurationObjects(PluginConfigurationObjectType.DATA_SOURCE, x => x.DataSources, AVAILABLE_PLUGINS, deployedEnterpriseConfigPluginIds, configObjectList, SecretStoreType.DATA_SOURCE, deleteSecret: true))
|
||||||
wasConfigurationChanged = true;
|
wasConfigurationChanged = true;
|
||||||
|
|
||||||
// Check chat templates:
|
// Check chat templates:
|
||||||
if(await PluginConfigurationObject.CleanLeftOverConfigurationObjects(PluginConfigurationObjectType.CHAT_TEMPLATE, x => x.ChatTemplates, AVAILABLE_PLUGINS, deployedConfigPluginIds, configObjectList))
|
if(await PluginConfigurationObject.CleanLeftOverConfigurationObjects(PluginConfigurationObjectType.CHAT_TEMPLATE, x => x.ChatTemplates, AVAILABLE_PLUGINS, deployedEnterpriseConfigPluginIds, configObjectList))
|
||||||
wasConfigurationChanged = true;
|
wasConfigurationChanged = true;
|
||||||
|
|
||||||
// Check profiles:
|
// Check profiles:
|
||||||
if(await PluginConfigurationObject.CleanLeftOverConfigurationObjects(PluginConfigurationObjectType.PROFILE, x => x.Profiles, AVAILABLE_PLUGINS, deployedConfigPluginIds, configObjectList))
|
if(await PluginConfigurationObject.CleanLeftOverConfigurationObjects(PluginConfigurationObjectType.PROFILE, x => x.Profiles, AVAILABLE_PLUGINS, deployedEnterpriseConfigPluginIds, configObjectList))
|
||||||
wasConfigurationChanged = true;
|
wasConfigurationChanged = true;
|
||||||
|
|
||||||
// Check document analysis policies:
|
// Check document analysis policies:
|
||||||
if(await PluginConfigurationObject.CleanLeftOverConfigurationObjects(PluginConfigurationObjectType.DOCUMENT_ANALYSIS_POLICY, x => x.DocumentAnalysis.Policies, AVAILABLE_PLUGINS, deployedConfigPluginIds, configObjectList))
|
if(await PluginConfigurationObject.CleanLeftOverConfigurationObjects(PluginConfigurationObjectType.DOCUMENT_ANALYSIS_POLICY, x => x.DocumentAnalysis.Policies, AVAILABLE_PLUGINS, deployedEnterpriseConfigPluginIds, configObjectList))
|
||||||
wasConfigurationChanged = true;
|
wasConfigurationChanged = true;
|
||||||
|
|
||||||
// Check left-over mandatory info acceptances:
|
// Check left-over mandatory info acceptances:
|
||||||
@ -234,11 +234,11 @@ public static partial class PluginFactory
|
|||||||
|
|
||||||
// Check all managed settings, i.e. settings which a configuration plugin can lock,
|
// Check all managed settings, i.e. settings which a configuration plugin can lock,
|
||||||
// provide as an editable default, or contribute to:
|
// provide as an editable default, or contribute to:
|
||||||
if(ManagedConfiguration.CleanupLeftOverManagedConfigurations(AVAILABLE_PLUGINS, deployedConfigPluginIds))
|
if(ManagedConfiguration.CleanupLeftOverManagedConfigurations(AVAILABLE_PLUGINS, deployedEnterpriseConfigPluginIds))
|
||||||
wasConfigurationChanged = true;
|
wasConfigurationChanged = true;
|
||||||
|
|
||||||
// Compatibility shim, see documentation/compatibility-shims/2026-08-orphaned-config-locks.md (remove after 2027-08-06):
|
// Compatibility shim, see documentation/compatibility-shims/2026-08-orphaned-config-locks.md (remove after 2027-08-06):
|
||||||
if (RepairLegacyConfigOnlySettings(unloadedConfigPluginIds.Count > 0))
|
if (RepairLegacyConfigOnlySettings(unloadedEnterpriseConfigPluginIds.Count > 0))
|
||||||
wasConfigurationChanged = true;
|
wasConfigurationChanged = true;
|
||||||
|
|
||||||
if (wasConfigurationChanged)
|
if (wasConfigurationChanged)
|
||||||
@ -249,9 +249,11 @@ public static partial class PluginFactory
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines the IDs of all configuration plugins which are deployed on this machine.
|
/// Determines the IDs of all configuration plugins which an organization deployed on this machine.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
|
/// Local configuration plugins are not part of this: they belong to the user, not to an
|
||||||
|
/// organization, and they can live in any directory below the plugins root.<br/><br/>
|
||||||
/// We read these IDs from the file system instead of taking them from the loaded plugins. A
|
/// We read these IDs from the file system instead of taking them from the loaded plugins. A
|
||||||
/// configuration plugin might be present but not loadable, e.g. due to invalid Lua code, a
|
/// configuration plugin might be present but not loadable, e.g. due to invalid Lua code, a
|
||||||
/// missing `plugin.lua`, or an incomplete download. Such a plugin still manages this AI Studio
|
/// missing `plugin.lua`, or an incomplete download. Such a plugin still manages this AI Studio
|
||||||
@ -259,13 +261,13 @@ public static partial class PluginFactory
|
|||||||
/// configuration server live in a directory named after their ID, which is the only information
|
/// configuration server live in a directory named after their ID, which is the only information
|
||||||
/// left when the plugin itself cannot be read.
|
/// left when the plugin itself cannot be read.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
private static HashSet<Guid> GetDeployedConfigPluginIds()
|
private static HashSet<Guid> GetDeployedEnterpriseConfigPluginIds()
|
||||||
{
|
{
|
||||||
var deployedConfigPluginIds = new HashSet<Guid>();
|
var deployedEnterpriseConfigPluginIds = new HashSet<Guid>();
|
||||||
if (!Directory.Exists(CONFIGURATION_PLUGINS_ROOT))
|
if (!Directory.Exists(ENTERPRISE_CONFIGURATION_PLUGINS_ROOT))
|
||||||
return deployedConfigPluginIds;
|
return deployedEnterpriseConfigPluginIds;
|
||||||
|
|
||||||
foreach (var configPluginDirectory in Directory.EnumerateDirectories(CONFIGURATION_PLUGINS_ROOT))
|
foreach (var configPluginDirectory in Directory.EnumerateDirectories(ENTERPRISE_CONFIGURATION_PLUGINS_ROOT))
|
||||||
{
|
{
|
||||||
if (!Guid.TryParse(Path.GetFileName(configPluginDirectory), out var configPluginId) || configPluginId == Guid.Empty)
|
if (!Guid.TryParse(Path.GetFileName(configPluginDirectory), out var configPluginId) || configPluginId == Guid.Empty)
|
||||||
continue;
|
continue;
|
||||||
@ -274,10 +276,10 @@ public static partial class PluginFactory
|
|||||||
if (!Directory.EnumerateFileSystemEntries(configPluginDirectory).Any())
|
if (!Directory.EnumerateFileSystemEntries(configPluginDirectory).Any())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
deployedConfigPluginIds.Add(configPluginId);
|
deployedEnterpriseConfigPluginIds.Add(configPluginId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return deployedConfigPluginIds;
|
return deployedEnterpriseConfigPluginIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <param name="pluginPath">The directory the plugin is located in, or null when the code has no directory yet.</param>
|
/// <param name="pluginPath">The directory the plugin is located in, or null when the code has no directory yet.</param>
|
||||||
|
|||||||
@ -22,9 +22,9 @@ public static partial class PluginFactory
|
|||||||
|
|
||||||
// Case 2: Startup cleanup before the initial plugin load.
|
// Case 2: Startup cleanup before the initial plugin load.
|
||||||
// In this case, we inspect the .config directories directly.
|
// In this case, we inspect the .config directories directly.
|
||||||
if (Directory.Exists(CONFIGURATION_PLUGINS_ROOT))
|
if (Directory.Exists(ENTERPRISE_CONFIGURATION_PLUGINS_ROOT))
|
||||||
{
|
{
|
||||||
foreach (var pluginDirectory in Directory.EnumerateDirectories(CONFIGURATION_PLUGINS_ROOT))
|
foreach (var pluginDirectory in Directory.EnumerateDirectories(ENTERPRISE_CONFIGURATION_PLUGINS_ROOT))
|
||||||
{
|
{
|
||||||
var directoryName = Path.GetFileName(pluginDirectory);
|
var directoryName = Path.GetFileName(pluginDirectory);
|
||||||
if (!Guid.TryParse(directoryName, out var pluginId))
|
if (!Guid.TryParse(directoryName, out var pluginId))
|
||||||
@ -36,7 +36,7 @@ public static partial class PluginFactory
|
|||||||
var deployFlag = ReadDeployFlagFromPluginFile(pluginDirectory);
|
var deployFlag = ReadDeployFlagFromPluginFile(pluginDirectory);
|
||||||
var isManagedByConfigServer = deployFlag ?? true;
|
var isManagedByConfigServer = deployFlag ?? true;
|
||||||
if (!deployFlag.HasValue)
|
if (!deployFlag.HasValue)
|
||||||
LOG.LogWarning($"Configuration plugin '{pluginId}' does not define 'DEPLOYED_USING_CONFIG_SERVER'. Falling back to the plugin path and treating it as managed because it is stored under '{CONFIGURATION_PLUGINS_ROOT}'.");
|
LOG.LogWarning($"Configuration plugin '{pluginId}' does not define 'DEPLOYED_USING_CONFIG_SERVER'. Falling back to the plugin path and treating it as managed because it is stored under '{ENTERPRISE_CONFIGURATION_PLUGINS_ROOT}'.");
|
||||||
|
|
||||||
if (isManagedByConfigServer)
|
if (isManagedByConfigServer)
|
||||||
pluginIdsToRemove.Add(pluginId);
|
pluginIdsToRemove.Add(pluginId);
|
||||||
@ -106,7 +106,7 @@ public static partial class PluginFactory
|
|||||||
|
|
||||||
private static void DeleteConfigurationPluginDirectory(Guid pluginId)
|
private static void DeleteConfigurationPluginDirectory(Guid pluginId)
|
||||||
{
|
{
|
||||||
var pluginDirectory = Path.Join(CONFIGURATION_PLUGINS_ROOT, pluginId.ToString());
|
var pluginDirectory = Path.Join(ENTERPRISE_CONFIGURATION_PLUGINS_ROOT, pluginId.ToString());
|
||||||
if (!Directory.Exists(pluginDirectory))
|
if (!Directory.Exists(pluginDirectory))
|
||||||
{
|
{
|
||||||
LOG.LogWarning($"Plugin directory '{pluginDirectory}' does not exist.");
|
LOG.LogWarning($"Plugin directory '{pluginDirectory}' does not exist.");
|
||||||
|
|||||||
@ -11,7 +11,16 @@ public static partial class PluginFactory
|
|||||||
private static string DATA_DIR = string.Empty;
|
private static string DATA_DIR = string.Empty;
|
||||||
private static string PLUGINS_ROOT = string.Empty;
|
private static string PLUGINS_ROOT = string.Empty;
|
||||||
private static string INTERNAL_PLUGINS_ROOT = string.Empty;
|
private static string INTERNAL_PLUGINS_ROOT = string.Empty;
|
||||||
private static string CONFIGURATION_PLUGINS_ROOT = string.Empty;
|
|
||||||
|
/// <summary>
|
||||||
|
/// The directory the config server downloads the configuration plugins of an organization into.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This is not the home of configuration plugins in general: a local configuration plugin can
|
||||||
|
/// live in any directory below the plugins root. Only the IT department of an organization
|
||||||
|
/// deploys plugins here, each in a directory named after its configuration ID.
|
||||||
|
/// </remarks>
|
||||||
|
private static string ENTERPRISE_CONFIGURATION_PLUGINS_ROOT = string.Empty;
|
||||||
private static string HOT_RELOAD_LOCK_FILE = string.Empty;
|
private static string HOT_RELOAD_LOCK_FILE = string.Empty;
|
||||||
private static FileSystemWatcher HOT_RELOAD_WATCHER = null!;
|
private static FileSystemWatcher HOT_RELOAD_WATCHER = null!;
|
||||||
|
|
||||||
@ -65,7 +74,7 @@ public static partial class PluginFactory
|
|||||||
PLUGINS_ROOT = Path.Join(DATA_DIR, "plugins");
|
PLUGINS_ROOT = Path.Join(DATA_DIR, "plugins");
|
||||||
HOT_RELOAD_LOCK_FILE = Path.Join(PLUGINS_ROOT, ".lock");
|
HOT_RELOAD_LOCK_FILE = Path.Join(PLUGINS_ROOT, ".lock");
|
||||||
INTERNAL_PLUGINS_ROOT = Path.Join(PLUGINS_ROOT, ".internal");
|
INTERNAL_PLUGINS_ROOT = Path.Join(PLUGINS_ROOT, ".internal");
|
||||||
CONFIGURATION_PLUGINS_ROOT = Path.Join(PLUGINS_ROOT, ".config");
|
ENTERPRISE_CONFIGURATION_PLUGINS_ROOT = Path.Join(PLUGINS_ROOT, ".config");
|
||||||
|
|
||||||
if (!Directory.Exists(PLUGINS_ROOT))
|
if (!Directory.Exists(PLUGINS_ROOT))
|
||||||
Directory.CreateDirectory(PLUGINS_ROOT);
|
Directory.CreateDirectory(PLUGINS_ROOT);
|
||||||
@ -89,12 +98,12 @@ public static partial class PluginFactory
|
|||||||
/// <returns>True when the directory is nested in the enterprise configuration directory.</returns>
|
/// <returns>True when the directory is nested in the enterprise configuration directory.</returns>
|
||||||
private static bool IsEnterpriseConfigurationPath(string? pluginPath)
|
private static bool IsEnterpriseConfigurationPath(string? pluginPath)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(pluginPath) || string.IsNullOrWhiteSpace(CONFIGURATION_PLUGINS_ROOT))
|
if (string.IsNullOrWhiteSpace(pluginPath) || string.IsNullOrWhiteSpace(ENTERPRISE_CONFIGURATION_PLUGINS_ROOT))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var configurationRoot = Path.GetFullPath(CONFIGURATION_PLUGINS_ROOT).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + Path.DirectorySeparatorChar;
|
var configurationRoot = Path.GetFullPath(ENTERPRISE_CONFIGURATION_PLUGINS_ROOT).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + Path.DirectorySeparatorChar;
|
||||||
var pluginDirectory = Path.GetFullPath(pluginPath).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + Path.DirectorySeparatorChar;
|
var pluginDirectory = Path.GetFullPath(pluginPath).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + Path.DirectorySeparatorChar;
|
||||||
return pluginDirectory.StartsWith(configurationRoot, StringComparison.OrdinalIgnoreCase);
|
return pluginDirectory.StartsWith(configurationRoot, StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user