From 99baac333eb7bb548da25f3644bd6593b666941a Mon Sep 17 00:00:00 2001 From: Jordan Dominion Date: Thu, 12 Sep 2024 18:34:53 -0400 Subject: [PATCH] Version Swarm API separately from core version. Allow slight differences. --- build/Version.props | 1 + .../Controllers/SwarmController.cs | 17 ++++++------- .../Database/DatabaseContext.cs | 2 ++ .../Properties/MasterVersionsAttribute.cs | 10 +++++++- .../Swarm/SwarmRegistrationRequest.cs | 2 +- .../Swarm/SwarmService.cs | 5 +++- .../Tgstation.Server.Host.csproj | 1 + .../Swarm/TestableSwarmNode.cs | 24 ++++++++++++++++++- 8 files changed, 48 insertions(+), 14 deletions(-) diff --git a/build/Version.props b/build/Version.props index 26c9fcf515..35126b239a 100644 --- a/build/Version.props +++ b/build/Version.props @@ -12,6 +12,7 @@ 7.3.0 5.10.0 1.5.0 + 7.0.0 1.2.1 2.0.0 netstandard2.0 diff --git a/src/Tgstation.Server.Host/Controllers/SwarmController.cs b/src/Tgstation.Server.Host/Controllers/SwarmController.cs index cdaa834d46..dd57e45138 100644 --- a/src/Tgstation.Server.Host/Controllers/SwarmController.cs +++ b/src/Tgstation.Server.Host/Controllers/SwarmController.cs @@ -14,8 +14,8 @@ using Serilog.Context; using Tgstation.Server.Host.Configuration; using Tgstation.Server.Host.Extensions; +using Tgstation.Server.Host.Properties; using Tgstation.Server.Host.Swarm; -using Tgstation.Server.Host.System; using Tgstation.Server.Host.Transfer; using Tgstation.Server.Host.Utils; @@ -44,11 +44,6 @@ namespace Tgstation.Server.Host.Controllers /// readonly IFileTransferStreamHandler transferService; - /// - /// The for the . - /// - readonly IAssemblyInformationProvider assemblyInformationProvider; - /// /// The for the . /// @@ -63,19 +58,16 @@ namespace Tgstation.Server.Host.Controllers /// Initializes a new instance of the class. /// /// The value of . - /// The value of . /// The value of . /// The containing the value of . /// The value of . public SwarmController( ISwarmOperations swarmOperations, - IAssemblyInformationProvider assemblyInformationProvider, IFileTransferStreamHandler transferService, IOptions swarmConfigurationOptions, ILogger logger) { this.swarmOperations = swarmOperations ?? throw new ArgumentNullException(nameof(swarmOperations)); - this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider)); this.transferService = transferService ?? throw new ArgumentNullException(nameof(transferService)); swarmConfiguration = swarmConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(swarmConfigurationOptions)); this.logger = logger; @@ -92,12 +84,17 @@ namespace Tgstation.Server.Host.Controllers { ArgumentNullException.ThrowIfNull(registrationRequest); - if (registrationRequest.ServerVersion != assemblyInformationProvider.Version) + var swarmProtocolVersion = Version.Parse(MasterVersionsAttribute.Instance.RawSwarmProtocolVersion); + if (registrationRequest.ServerVersion?.Major != swarmProtocolVersion.Major) return StatusCode((int)HttpStatusCode.UpgradeRequired); var registrationResult = await swarmOperations.RegisterNode(registrationRequest, RequestRegistrationId, cancellationToken); if (registrationResult == null) return Conflict(); + + if (registrationRequest.ServerVersion != swarmProtocolVersion) + logger.LogWarning("Allowed node {identifier} to register despite having a slightly different swarm protocol version!", registrationRequest.Identifier); + return Json(registrationResult); } diff --git a/src/Tgstation.Server.Host/Database/DatabaseContext.cs b/src/Tgstation.Server.Host/Database/DatabaseContext.cs index dbf724e45d..d79bb709f9 100644 --- a/src/Tgstation.Server.Host/Database/DatabaseContext.cs +++ b/src/Tgstation.Server.Host/Database/DatabaseContext.cs @@ -445,6 +445,7 @@ namespace Tgstation.Server.Host.Database // HEY YOU // IF YOU HAVE A TEST THAT'S CREATING ERRORS BECAUSE THESE VALUES AREN'T SET CORRECTLY THERE'S MORE TO FIXING IT THAN JUST UPDATING THEM // IN THE FUNCTION BELOW YOU ALSO NEED TO CORRECTLY SET THE RIGHT MIGRATION TO DOWNGRADE TO FOR THE LAST TGS VERSION + // YOU ALSO NEED TO UPDATE THE SWARM PROTOCOL MAJOR VERSION // IF THIS BREAKS AGAIN I WILL PERSONALLY HAUNT YOUR ASS WHEN I DIE /// @@ -480,6 +481,7 @@ namespace Tgstation.Server.Host.Database string BadDatabaseType() => throw new ArgumentException($"Invalid DatabaseType: {currentDatabaseType}", nameof(currentDatabaseType)); + // !!! DON'T FORGET TO UPDATE THE SWARM PROTOCOL MAJOR VERSION !!! if (targetVersion < new Version(6, 7, 0)) targetMigration = currentDatabaseType switch { diff --git a/src/Tgstation.Server.Host/Properties/MasterVersionsAttribute.cs b/src/Tgstation.Server.Host/Properties/MasterVersionsAttribute.cs index d77bcd349b..8212c4ffee 100644 --- a/src/Tgstation.Server.Host/Properties/MasterVersionsAttribute.cs +++ b/src/Tgstation.Server.Host/Properties/MasterVersionsAttribute.cs @@ -41,6 +41,11 @@ namespace Tgstation.Server.Host.Properties /// public string RawMariaDBRedistVersion { get; } + /// + /// The of the MariaDB server bundled with TGS installs. + /// + public string RawSwarmProtocolVersion { get; } + /// /// Initializes a new instance of the class. /// @@ -49,18 +54,21 @@ namespace Tgstation.Server.Host.Properties /// The value of . /// The value of . /// The value of . + /// The value of . public MasterVersionsAttribute( string rawConfigurationVersion, string rawInteropVersion, string rawWebpanelVersion, string rawHostWatchdogVersion, - string rawMariaDBRedistVersion) + string rawMariaDBRedistVersion, + string rawSwarmProtocolVersion) { RawConfigurationVersion = rawConfigurationVersion ?? throw new ArgumentNullException(nameof(rawConfigurationVersion)); RawInteropVersion = rawInteropVersion ?? throw new ArgumentNullException(nameof(rawInteropVersion)); RawWebpanelVersion = rawWebpanelVersion ?? throw new ArgumentNullException(nameof(rawWebpanelVersion)); RawHostWatchdogVersion = rawHostWatchdogVersion ?? throw new ArgumentNullException(nameof(rawHostWatchdogVersion)); RawMariaDBRedistVersion = rawMariaDBRedistVersion ?? throw new ArgumentNullException(nameof(rawMariaDBRedistVersion)); + RawSwarmProtocolVersion = rawSwarmProtocolVersion ?? throw new ArgumentNullException(nameof(rawSwarmProtocolVersion)); } } } diff --git a/src/Tgstation.Server.Host/Swarm/SwarmRegistrationRequest.cs b/src/Tgstation.Server.Host/Swarm/SwarmRegistrationRequest.cs index 229d4d28d2..f6bda1ac47 100644 --- a/src/Tgstation.Server.Host/Swarm/SwarmRegistrationRequest.cs +++ b/src/Tgstation.Server.Host/Swarm/SwarmRegistrationRequest.cs @@ -11,7 +11,7 @@ namespace Tgstation.Server.Host.Swarm public sealed class SwarmRegistrationRequest : SwarmServer { /// - /// The TGS of the sending server. + /// The swarm protocol of the sending server. Named this way due to legacy reasons. /// [Required] public Version ServerVersion { get; } diff --git a/src/Tgstation.Server.Host/Swarm/SwarmService.cs b/src/Tgstation.Server.Host/Swarm/SwarmService.cs index c62148b4be..82b2a9140d 100644 --- a/src/Tgstation.Server.Host/Swarm/SwarmService.cs +++ b/src/Tgstation.Server.Host/Swarm/SwarmService.cs @@ -24,6 +24,7 @@ using Tgstation.Server.Host.Configuration; using Tgstation.Server.Host.Core; using Tgstation.Server.Host.Database; using Tgstation.Server.Host.IO; +using Tgstation.Server.Host.Properties; using Tgstation.Server.Host.Security; using Tgstation.Server.Host.System; using Tgstation.Server.Host.Transfer; @@ -34,7 +35,9 @@ namespace Tgstation.Server.Host.Swarm /// /// Helps keep servers connected to the same database in sync by coordinating updates. /// +#pragma warning disable CA1506 // TODO: Decomplexify sealed class SwarmService : ISwarmService, ISwarmServiceController, ISwarmOperations, IDisposable +#pragma warning restore CA1506 { /// public bool ExpectedNumberOfNodesConnected @@ -1282,7 +1285,7 @@ namespace Tgstation.Server.Host.Swarm null, HttpMethod.Post, SwarmConstants.RegisterRoute, - new SwarmRegistrationRequest(assemblyInformationProvider.Version) + new SwarmRegistrationRequest(Version.Parse(MasterVersionsAttribute.Instance.RawSwarmProtocolVersion)) { Identifier = swarmConfiguration.Identifier, Address = swarmConfiguration.Address, diff --git a/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj b/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj index 9d41344040..49c85ec6e3 100644 --- a/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj +++ b/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj @@ -56,6 +56,7 @@ <_Parameter3>$(TgsWebpanelVersion) <_Parameter4>$(TgsHostWatchdogVersion) <_Parameter5>$(TgsMariaDBRedistVersion) + <_Parameter6>$(TgsSwarmProtocolVersion) diff --git a/tests/Tgstation.Server.Host.Tests/Swarm/TestableSwarmNode.cs b/tests/Tgstation.Server.Host.Tests/Swarm/TestableSwarmNode.cs index c293318381..664729e966 100644 --- a/tests/Tgstation.Server.Host.Tests/Swarm/TestableSwarmNode.cs +++ b/tests/Tgstation.Server.Host.Tests/Swarm/TestableSwarmNode.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using Microsoft.IdentityModel.Tokens; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -20,6 +21,7 @@ using Tgstation.Server.Host.Controllers; using Tgstation.Server.Host.Core; using Tgstation.Server.Host.Database; using Tgstation.Server.Host.IO; +using Tgstation.Server.Host.Models; using Tgstation.Server.Host.Security; using Tgstation.Server.Host.System; using Tgstation.Server.Host.Transfer; @@ -75,6 +77,24 @@ namespace Tgstation.Server.Host.Swarm.Tests } } + private class MockTokenFactory : ITokenFactory + { + public ReadOnlySpan SigningKey + { + get => [0, 1, 2, 3, 4]; + set + { + } + } + + public TokenValidationParameters ValidationParameters => throw new NotSupportedException(); + + public TokenResponse CreateToken(User user, bool oAuth) + { + throw new NotSupportedException(); + } + } + public TestableSwarmNode( ILoggerFactory loggerFactory, SwarmConfiguration swarmConfiguration, @@ -138,7 +158,6 @@ namespace Tgstation.Server.Host.Swarm.Tests RpcMapper = new SwarmRpcMapper( (targetService, targetTransfer) => new SwarmController( targetService, - mockAssemblyInformationProvider.Object, targetTransfer, mockOptions.Object, loggerFactory.CreateLogger()), @@ -154,6 +173,8 @@ namespace Tgstation.Server.Host.Swarm.Tests logger = loggerFactory.CreateLogger($"TestableSwarmNode-{swarmConfiguration.Identifier}"); + var mockTokenFactory = new MockTokenFactory(); + var runCount = 0; void RecreateControllerAndService() { @@ -180,6 +201,7 @@ namespace Tgstation.Server.Host.Swarm.Tests mockAsyncDelayer.Object, mockServerUpdater.Object, TransferService, + mockTokenFactory, mockOptions.Object, serviceLogger); }