mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-28 23:52:36 +01:00
Merge pull request #1162 from tgstation/DowngradeMigrations [TGSDeploy]
Fix bad downgrade migrations for the last time
This commit is contained in:
+1
-1
@@ -3,7 +3,7 @@
|
||||
<!-- Integration tests will ensure they match across the board -->
|
||||
<Import Project="ControlPanelVersion.props" />
|
||||
<PropertyGroup>
|
||||
<TgsCoreVersion>4.6.1</TgsCoreVersion>
|
||||
<TgsCoreVersion>4.6.2</TgsCoreVersion>
|
||||
<TgsConfigVersion>2.1.1</TgsConfigVersion>
|
||||
<TgsApiVersion>7.4.0</TgsApiVersion>
|
||||
<TgsClientVersion>8.4.0</TgsClientVersion>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -59,33 +60,41 @@ namespace Tgstation.Server.Host.Core
|
||||
.ToListAsync(cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
for (var I = basePort; I < UInt16.MaxValue; ++I)
|
||||
var exceptions = new List<Exception>();
|
||||
ushort I = 0;
|
||||
try
|
||||
{
|
||||
if (checkOne && I != basePort)
|
||||
break;
|
||||
|
||||
if (I == serverPortProvider.HttpApiPort
|
||||
|| ddPorts.Contains(I)
|
||||
|| dmPorts.Contains(I))
|
||||
continue;
|
||||
|
||||
try
|
||||
for (I = basePort; I < UInt16.MaxValue; ++I)
|
||||
{
|
||||
logger.LogTrace("Bind test: {0}", I);
|
||||
SocketExtensions.BindTest(I, false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogDebug(ex, "Not using port {0}", I);
|
||||
continue;
|
||||
if (checkOne && I != basePort)
|
||||
break;
|
||||
|
||||
if (I == serverPortProvider.HttpApiPort
|
||||
|| ddPorts.Contains(I)
|
||||
|| dmPorts.Contains(I))
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
SocketExtensions.BindTest(I, false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exceptions.Add(ex);
|
||||
continue;
|
||||
}
|
||||
|
||||
logger.LogInformation("Allocated port {0}", I);
|
||||
return I;
|
||||
}
|
||||
|
||||
logger.LogInformation("Allocated port {0}", I);
|
||||
return I;
|
||||
logger.LogWarning("Unable to allocate port >= {0}!", basePort);
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
logger.LogDebug(new AggregateException(exceptions), "Failed to allocate ports {0}-{1}!", basePort, I - 1);
|
||||
}
|
||||
|
||||
logger.LogWarning("Unable to allocate port >= {0}!", basePort);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,30 +315,112 @@ namespace Tgstation.Server.Host.Database
|
||||
return wasEmpty;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Used by unit tests to remind us to setup the correct MSSQL migration downgrades.
|
||||
/// </summary>
|
||||
public static readonly Type MSLatestMigration = typeof(MSAddAdditionalDDParameters);
|
||||
|
||||
/// <summary>
|
||||
/// Used by unit tests to remind us to setup the correct MSSQL migration downgrades.
|
||||
/// </summary>
|
||||
public static readonly Type MYLatestMigration = typeof(MYAddAdditionalDDParameters);
|
||||
|
||||
/// <summary>
|
||||
/// Used by unit tests to remind us to setup the correct MSSQL migration downgrades.
|
||||
/// </summary>
|
||||
public static readonly Type PGLatestMigration = typeof(PGAddAdditionalDDParameters);
|
||||
|
||||
/// <summary>
|
||||
/// Used by unit tests to remind us to setup the correct MSSQL migration downgrades.
|
||||
/// </summary>
|
||||
public static readonly Type SLLatestMigration = typeof(SLAddAdditionalDDParameters);
|
||||
#endif
|
||||
|
||||
/// <inheritdoc />
|
||||
#pragma warning disable CA1502 // TODO: Decomplexify
|
||||
public async Task SchemaDowngradeForServerVersion(
|
||||
ILogger<DatabaseContext> logger,
|
||||
Version version,
|
||||
Version targetVersion,
|
||||
DatabaseType currentDatabaseType,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if(logger == null)
|
||||
throw new ArgumentNullException(nameof(logger));
|
||||
if (version == null)
|
||||
throw new ArgumentNullException(nameof(version));
|
||||
if (version < new Version(4, 0))
|
||||
throw new ArgumentOutOfRangeException(nameof(version), version, "Not a valid V4 version!");
|
||||
if (targetVersion == null)
|
||||
throw new ArgumentNullException(nameof(targetVersion));
|
||||
if (targetVersion < new Version(4, 0))
|
||||
throw new ArgumentOutOfRangeException(nameof(targetVersion), targetVersion, "Not a valid V4 version!");
|
||||
|
||||
if (currentDatabaseType == DatabaseType.PostgresSql && targetVersion < new Version(4, 3, 0))
|
||||
throw new NotSupportedException("Cannot migrate below version 4.3.0 with PostgresSql!");
|
||||
|
||||
if (targetVersion < new Version(4, 1, 0))
|
||||
throw new NotSupportedException("Cannot migrate below version 4.1.0!");
|
||||
|
||||
// Update this with new migrations as they are made
|
||||
string targetMigration = null;
|
||||
if (targetVersion < new Version(4, 7, 0))
|
||||
switch (currentDatabaseType)
|
||||
{
|
||||
case DatabaseType.MariaDB:
|
||||
case DatabaseType.MySql:
|
||||
targetMigration = nameof(MYAddAdditionalDDParameters);
|
||||
break;
|
||||
case DatabaseType.PostgresSql:
|
||||
targetMigration = nameof(PGAddAdditionalDDParameters);
|
||||
break;
|
||||
case DatabaseType.SqlServer:
|
||||
targetMigration = nameof(MSAddAdditionalDDParameters);
|
||||
break;
|
||||
case DatabaseType.Sqlite:
|
||||
targetMigration = nameof(SLAddAdditionalDDParameters);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"Invalid DatabaseType: {currentDatabaseType}", nameof(currentDatabaseType));
|
||||
}
|
||||
|
||||
if (currentDatabaseType == DatabaseType.PostgresSql && version < new Version(4, 3, 0))
|
||||
throw new NotSupportedException("Cannot migrate below version 4.3.0 with PostgresSql!");
|
||||
if (targetVersion < new Version(4, 6, 0))
|
||||
switch (currentDatabaseType)
|
||||
{
|
||||
case DatabaseType.MariaDB:
|
||||
case DatabaseType.MySql:
|
||||
targetMigration = nameof(MYAddDeploymentColumns);
|
||||
break;
|
||||
case DatabaseType.PostgresSql:
|
||||
targetMigration = nameof(PGAddDeploymentColumns);
|
||||
break;
|
||||
case DatabaseType.SqlServer:
|
||||
targetMigration = nameof(MSAddDeploymentColumns);
|
||||
break;
|
||||
case DatabaseType.Sqlite:
|
||||
targetMigration = nameof(SLAddDeploymentColumns);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"Invalid DatabaseType: {currentDatabaseType}", nameof(currentDatabaseType));
|
||||
}
|
||||
|
||||
if (version < new Version(4, 1, 0))
|
||||
throw new NotSupportedException("Cannot migrate below version 4.1.0!");
|
||||
if (targetVersion < new Version(4, 5, 0))
|
||||
switch (currentDatabaseType)
|
||||
{
|
||||
case DatabaseType.MariaDB:
|
||||
case DatabaseType.MySql:
|
||||
targetMigration = nameof(MYAllowNullDMApi);
|
||||
break;
|
||||
case DatabaseType.PostgresSql:
|
||||
targetMigration = nameof(PGAllowNullDMApi);
|
||||
break;
|
||||
case DatabaseType.SqlServer:
|
||||
targetMigration = nameof(MSAllowNullDMApi);
|
||||
break;
|
||||
case DatabaseType.Sqlite:
|
||||
targetMigration = nameof(SLAllowNullDMApi);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"Invalid DatabaseType: {currentDatabaseType}", nameof(currentDatabaseType));
|
||||
}
|
||||
|
||||
if(version < new Version(4, 4, 0))
|
||||
if (targetVersion < new Version(4, 4, 0))
|
||||
switch (currentDatabaseType)
|
||||
{
|
||||
case DatabaseType.MariaDB:
|
||||
@@ -349,14 +431,16 @@ namespace Tgstation.Server.Host.Database
|
||||
targetMigration = nameof(PGCreate);
|
||||
break;
|
||||
case DatabaseType.SqlServer:
|
||||
case DatabaseType.Sqlite:
|
||||
targetMigration = nameof(MSRemoveSoftColumns);
|
||||
break;
|
||||
case DatabaseType.Sqlite:
|
||||
targetMigration = nameof(SLRemoveSoftColumns);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"Invalid DatabaseType: {currentDatabaseType}", nameof(currentDatabaseType));
|
||||
}
|
||||
|
||||
if (version < new Version(4, 2, 0))
|
||||
if (targetVersion < new Version(4, 2, 0))
|
||||
targetMigration = currentDatabaseType == DatabaseType.Sqlite ? nameof(SLRebuild) : nameof(MSFixCascadingDelete);
|
||||
|
||||
if (targetMigration == null)
|
||||
@@ -393,7 +477,7 @@ namespace Tgstation.Server.Host.Database
|
||||
var dbServiceProvider = ((IInfrastructure<IServiceProvider>)Database).Instance;
|
||||
var migrator = dbServiceProvider.GetRequiredService<IMigrator>();
|
||||
|
||||
logger.LogInformation("Migrating down to version {0}. Target: {1}", version, targetMigration);
|
||||
logger.LogInformation("Migrating down to version {0}. Target: {1}", targetVersion, targetMigration);
|
||||
try
|
||||
{
|
||||
await migrator.MigrateAsync(targetMigration, cancellationToken).ConfigureAwait(false);
|
||||
@@ -403,5 +487,6 @@ namespace Tgstation.Server.Host.Database
|
||||
logger.LogCritical(e, "Failed to migrate!");
|
||||
}
|
||||
}
|
||||
#pragma warning restore CA1502
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,7 +295,11 @@ namespace Tgstation.Server.Host.Database
|
||||
if (downgradeVersion == null)
|
||||
throw new ArgumentNullException(nameof(downgradeVersion));
|
||||
|
||||
return databaseContext.SchemaDowngradeForServerVersion(databaseLogger, downgradeVersion, databaseConfiguration.DatabaseType, cancellationToken);
|
||||
return databaseContext.SchemaDowngradeForServerVersion(
|
||||
databaseLogger,
|
||||
downgradeVersion,
|
||||
databaseConfiguration.DatabaseType,
|
||||
cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Threading;
|
||||
@@ -96,16 +96,16 @@ namespace Tgstation.Server.Host.Database
|
||||
Task<bool> Migrate(ILogger<DatabaseContext> logger, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to downgrade the schema to the migration used for a given server <paramref name="version"/>
|
||||
/// Attempt to downgrade the schema to the migration used for a given server <paramref name="targetVersion"/>
|
||||
/// </summary>
|
||||
/// <param name="logger">The <see cref="DatabaseContext"/> <see cref="ILogger"/> to use.</param>
|
||||
/// <param name="version">The tgstation-server <see cref="Version"/> that the schema should downgrade for</param>
|
||||
/// <param name="targetVersion">The tgstation-server <see cref="Version"/> that the schema should downgrade for</param>
|
||||
/// <param name="currentDatabaseType">The <see cref="DatabaseType"/> in use.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task"/> representing the running operation</returns>
|
||||
Task SchemaDowngradeForServerVersion(
|
||||
ILogger<DatabaseContext> logger,
|
||||
Version version,
|
||||
Version targetVersion,
|
||||
DatabaseType currentDatabaseType,
|
||||
CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
@@ -10,6 +11,7 @@ using Tgstation.Server.Client;
|
||||
using Tgstation.Server.Host;
|
||||
using Tgstation.Server.Host.Components.Interop;
|
||||
using Tgstation.Server.Host.Configuration;
|
||||
using Tgstation.Server.Host.Database;
|
||||
|
||||
namespace Tgstation.Server.Tests
|
||||
{
|
||||
@@ -143,5 +145,62 @@ namespace Tgstation.Server.Tests
|
||||
var line = scriptLines.FirstOrDefault(x => x.Trim().Contains($"SCRIPT_VERSION=\"{expected.Semver()}\""));
|
||||
Assert.IsNotNull(line);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
[TestMethod]
|
||||
public void TestDowngradeMigrations()
|
||||
{
|
||||
static string GetMigrationTimestampString(Type type) => type
|
||||
?.GetCustomAttributes(typeof(MigrationAttribute), false)
|
||||
.OfType<MigrationAttribute>()
|
||||
.SingleOrDefault()
|
||||
?.Id
|
||||
.Split('_')
|
||||
.First()
|
||||
?? String.Empty;
|
||||
|
||||
var allTypesWithMigrationAttributes = typeof(Program)
|
||||
.Assembly
|
||||
.GetTypes()
|
||||
.ToDictionary(
|
||||
x => x,
|
||||
x => GetMigrationTimestampString(x));
|
||||
|
||||
Type latestMigrationMS = null;
|
||||
Type latestMigrationMY = null;
|
||||
Type latestMigrationPG = null;
|
||||
Type latestMigrationSL = null;
|
||||
foreach (var kvp in allTypesWithMigrationAttributes)
|
||||
{
|
||||
var migrationType = kvp.Key;
|
||||
var migrationTimestamp = kvp.Value;
|
||||
|
||||
switch(migrationType.Name.Substring(0, 2))
|
||||
{
|
||||
case "MS":
|
||||
if (String.Compare(GetMigrationTimestampString(latestMigrationMS), migrationTimestamp) < 0)
|
||||
latestMigrationMS = migrationType;
|
||||
break;
|
||||
case "MY":
|
||||
if (String.Compare(GetMigrationTimestampString(latestMigrationMY), migrationTimestamp) < 0)
|
||||
latestMigrationMY = migrationType;
|
||||
break;
|
||||
case "PG":
|
||||
if (String.Compare(GetMigrationTimestampString(latestMigrationPG), migrationTimestamp) < 0)
|
||||
latestMigrationPG = migrationType;
|
||||
break;
|
||||
case "SL":
|
||||
if (String.Compare(GetMigrationTimestampString(latestMigrationSL), migrationTimestamp) < 0)
|
||||
latestMigrationSL = migrationType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.AreEqual(latestMigrationMS, DatabaseContext.MSLatestMigration);
|
||||
Assert.AreEqual(latestMigrationMY, DatabaseContext.MYLatestMigration);
|
||||
Assert.AreEqual(latestMigrationPG, DatabaseContext.PGLatestMigration);
|
||||
Assert.AreEqual(latestMigrationSL, DatabaseContext.SLLatestMigration);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user