diff --git a/.github/workflows/check-pr-has-milestone.yml b/.github/workflows/check-pr-has-milestone.yml index ebf3832622..056ddc7b82 100644 --- a/.github/workflows/check-pr-has-milestone.yml +++ b/.github/workflows/check-pr-has-milestone.yml @@ -14,6 +14,7 @@ concurrency: jobs: fail-on-bad-milestone: + if: github.event.pull_request.draft != true name: Fail if Pull Request has no Associated Version Milestone runs-on: ubuntu-latest steps: diff --git a/.github/workflows/ci-security.yml b/.github/workflows/ci-security.yml index eb7806f7d1..279b8bc2b4 100644 --- a/.github/workflows/ci-security.yml +++ b/.github/workflows/ci-security.yml @@ -24,7 +24,7 @@ concurrency: jobs: security-checkpoint: name: Check CI Clearance - if: github.event_name == 'pull_request_target' && (github.event.pull_request.head.repo.id != github.event.pull_request.base.repo.id || github.event.pull_request.user.id == 49699333) && github.event.pull_request.state == 'open' + if: github.event_name == 'pull_request_target' && (github.event.pull_request.head.repo.id != github.event.pull_request.base.repo.id || github.event.pull_request.user.id == 49699333) && github.event.pull_request.state == 'open' && github.event.pull_request.draft != true runs-on: ubuntu-latest steps: - name: Generate App Token @@ -62,7 +62,7 @@ jobs: ci-pipline-workflow-call: name: CI Pipeline needs: security-checkpoint - if: (!(cancelled() || failure()) && (needs.security-checkpoint.result == 'success' || (github.event_name != 'pull_request_target' && github.event.pull_request.head.repo.id == github.event.pull_request.base.repo.id && github.event.pull_request.user.id != 49699333))) + if: (!(cancelled() || failure()) && (needs.security-checkpoint.result == 'success' || (github.event_name != 'pull_request_target' && github.event.pull_request.head.repo.id == github.event.pull_request.base.repo.id && github.event.pull_request.user.id != 49699333)) && github.event.pull_request.draft != true) uses: ./.github/workflows/ci-pipeline.yml secrets: inherit with: diff --git a/src/Tgstation.Server.Client.GraphQL/Tgstation.Server.Client.GraphQL.csproj b/src/Tgstation.Server.Client.GraphQL/Tgstation.Server.Client.GraphQL.csproj index 8317c28ea0..d3d3c14f2c 100644 --- a/src/Tgstation.Server.Client.GraphQL/Tgstation.Server.Client.GraphQL.csproj +++ b/src/Tgstation.Server.Client.GraphQL/Tgstation.Server.Client.GraphQL.csproj @@ -16,23 +16,19 @@ + - - - - - - + - + $(IntermediateOutputPath)berry/GraphQLClient.Client.cs $(IntermediateOutputPath)berry/GraphQLClient.Client.cs diff --git a/src/Tgstation.Server.Host/Authority/LoginAuthority.cs b/src/Tgstation.Server.Host/Authority/LoginAuthority.cs index 363744fbf1..f0286767e4 100644 --- a/src/Tgstation.Server.Host/Authority/LoginAuthority.cs +++ b/src/Tgstation.Server.Host/Authority/LoginAuthority.cs @@ -62,9 +62,9 @@ namespace Tgstation.Server.Host.Authority readonly ISessionInvalidationTracker sessionInvalidationTracker; /// - /// The for the . + /// The containing the for the . /// - readonly SecurityConfiguration securityConfiguration; + readonly IOptionsSnapshot securityConfigurationOptions; /// /// Generate an for a given . @@ -113,7 +113,7 @@ namespace Tgstation.Server.Host.Authority /// The value of . /// The value of . /// The value of . - /// The containing the value of . + /// The value of . public LoginAuthority( IDatabaseContext databaseContext, ILogger logger, @@ -124,7 +124,7 @@ namespace Tgstation.Server.Host.Authority ICryptographySuite cryptographySuite, IIdentityCache identityCache, ISessionInvalidationTracker sessionInvalidationTracker, - IOptions securityConfigurationOptions) + IOptionsSnapshot securityConfigurationOptions) : base( databaseContext, logger) @@ -136,7 +136,7 @@ namespace Tgstation.Server.Host.Authority this.cryptographySuite = cryptographySuite ?? throw new ArgumentNullException(nameof(cryptographySuite)); this.identityCache = identityCache ?? throw new ArgumentNullException(nameof(identityCache)); this.sessionInvalidationTracker = sessionInvalidationTracker ?? throw new ArgumentNullException(nameof(sessionInvalidationTracker)); - securityConfiguration = securityConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(securityConfigurationOptions)); + this.securityConfigurationOptions = securityConfigurationOptions ?? throw new ArgumentNullException(nameof(securityConfigurationOptions)); } /// @@ -181,7 +181,7 @@ namespace Tgstation.Server.Host.Authority private async ValueTask> AttemptLoginImpl(CancellationToken cancellationToken) { // password and oauth logins disabled - if (securityConfiguration.OidcStrictMode) + if (securityConfigurationOptions.Value.OidcStrictMode) return Unauthorized(); var headers = apiHeadersProvider.ApiHeaders; @@ -208,7 +208,7 @@ namespace Tgstation.Server.Host.Authority using (systemIdentity) { // Get the user from the database - IQueryable query = DatabaseContext.Users.AsQueryable(); + IQueryable query = DatabaseContext.Users; if (oAuthLogin) { var oAuthProvider = headers.OAuthProvider!.Value; diff --git a/src/Tgstation.Server.Host/Authority/PermissionSetAuthority.cs b/src/Tgstation.Server.Host/Authority/PermissionSetAuthority.cs index 1fcfee647c..a4c0aaade9 100644 --- a/src/Tgstation.Server.Host/Authority/PermissionSetAuthority.cs +++ b/src/Tgstation.Server.Host/Authority/PermissionSetAuthority.cs @@ -119,13 +119,11 @@ namespace Tgstation.Server.Host.Authority var groupIdQuery = DatabaseContext .Users - .AsQueryable() .Where(user => user.Id == userId) .Select(user => user.GroupId); var permissionSetId = await DatabaseContext .PermissionSets - .AsQueryable() .Where(permissionSet => permissionSet.UserId == userId || groupIdQuery.Contains(permissionSet.GroupId)) .Select(permissionSet => permissionSet.Id!.Value) diff --git a/src/Tgstation.Server.Host/Authority/UserAuthority.cs b/src/Tgstation.Server.Host/Authority/UserAuthority.cs index 416df9ff7c..1022e79e28 100644 --- a/src/Tgstation.Server.Host/Authority/UserAuthority.cs +++ b/src/Tgstation.Server.Host/Authority/UserAuthority.cs @@ -85,9 +85,9 @@ namespace Tgstation.Server.Host.Authority readonly IOptionsSnapshot generalConfigurationOptions; /// - /// The of for the . + /// The of for the . /// - readonly IOptions securityConfigurationOptions; + readonly IOptionsSnapshot securityConfigurationOptions; /// /// Implements the . @@ -107,7 +107,6 @@ namespace Tgstation.Server.Host.Authority return databaseContext .Users - .AsQueryable() .Where(x => ids.Contains(x.Id!.Value)) .ToDictionaryAsync(user => user.Id!.Value, cancellationToken); } @@ -130,7 +129,6 @@ namespace Tgstation.Server.Host.Authority var list = await databaseContext .OAuthConnections - .AsQueryable() .Where(x => userIds.Contains(x.User!.Id!.Value)) .ToListAsync(cancellationToken); @@ -161,7 +159,6 @@ namespace Tgstation.Server.Host.Authority var list = await databaseContext .OidcConnections - .AsQueryable() .Where(x => userIds.Contains(x.User!.Id!.Value)) .ToListAsync(cancellationToken); @@ -221,7 +218,7 @@ namespace Tgstation.Server.Host.Authority ITopicEventSender topicEventSender, IClaimsPrincipalAccessor claimsPrincipalAccessor, IOptionsSnapshot generalConfigurationOptions, - IOptions securityConfigurationOptions) + IOptionsSnapshot securityConfigurationOptions) : base( databaseContext, logger) @@ -371,7 +368,6 @@ namespace Tgstation.Server.Host.Authority var totalUsers = await DatabaseContext .Users - .AsQueryable() .CountAsync(cancellationToken); if (totalUsers >= generalConfigurationOptions.Value.UserLimit) return Conflict(ErrorCode.UserLimitReached); @@ -473,7 +469,6 @@ namespace Tgstation.Server.Host.Authority var userQuery = DatabaseContext .Users - .AsQueryable() .Where(x => x.Id == model.Id) .Include(x => x.CreatedBy) .Include(x => x.OAuthConnections) @@ -574,7 +569,6 @@ namespace Tgstation.Server.Host.Authority originalUser.Group = await DatabaseContext .Groups - .AsQueryable() .Where(x => x.Id == model.Group.Id) .Include(x => x.PermissionSet) .FirstOrDefaultAsync(cancellationToken); @@ -759,9 +753,8 @@ namespace Tgstation.Server.Host.Authority IQueryable Queryable(bool includeJoins, bool allowSystemUser) { var tgsUserCanonicalName = User.CanonicalizeName(User.TgsSystemUserName); - var queryable = DatabaseContext - .Users - .AsQueryable(); + IQueryable queryable = DatabaseContext + .Users; if (!allowSystemUser) queryable = queryable @@ -792,7 +785,6 @@ namespace Tgstation.Server.Host.Authority if (model.Group != null) group = await DatabaseContext .Groups - .AsQueryable() .Where(x => x.Id == model.Group.Id) .Include(x => x.PermissionSet) .FirstOrDefaultAsync(cancellationToken); diff --git a/src/Tgstation.Server.Host/Authority/UserGroupAuthority.cs b/src/Tgstation.Server.Host/Authority/UserGroupAuthority.cs index 080406c97a..00089a6a9c 100644 --- a/src/Tgstation.Server.Host/Authority/UserGroupAuthority.cs +++ b/src/Tgstation.Server.Host/Authority/UserGroupAuthority.cs @@ -122,7 +122,6 @@ namespace Tgstation.Server.Host.Authority var userId = claimsPrincipalAccessor.User.GetTgsUserId(); var group = await DatabaseContext .Users - .AsQueryable() .Where(user => user.Id == userId) .Select(user => user.Group) .FirstOrDefaultAsync(cancellationToken); @@ -149,7 +148,6 @@ namespace Tgstation.Server.Host.Authority { var totalGroups = await DatabaseContext .Groups - .AsQueryable() .CountAsync(cancellationToken); if (totalGroups >= generalConfigurationOptions.Value.UserGroupLimit) return Conflict(ErrorCode.UserGroupLimitReached); @@ -184,7 +182,6 @@ namespace Tgstation.Server.Host.Authority { var currentGroup = await DatabaseContext .Groups - .AsQueryable() .Where(x => x.Id == id) .Include(x => x.PermissionSet) .FirstOrDefaultAsync(cancellationToken); @@ -213,7 +210,6 @@ namespace Tgstation.Server.Host.Authority { var numDeleted = await DatabaseContext .Groups - .AsQueryable() .Where(x => x.Id == id && x.Users!.Count == 0) .ExecuteDeleteAsync(cancellationToken); @@ -223,7 +219,6 @@ namespace Tgstation.Server.Host.Authority // find out how we failed var groupExists = await DatabaseContext .Groups - .AsQueryable() .Where(x => x.Id == id) .AnyAsync(cancellationToken); @@ -243,9 +238,8 @@ namespace Tgstation.Server.Host.Authority /// An of s. IQueryable QueryableImpl(bool includeJoins) { - var queryable = DatabaseContext - .Groups - .AsQueryable(); + IQueryable queryable = DatabaseContext + .Groups; if (includeJoins) queryable = queryable diff --git a/src/Tgstation.Server.Host/Components/Chat/Commands/PullRequestsCommand.cs b/src/Tgstation.Server.Host/Components/Chat/Commands/PullRequestsCommand.cs index 5cc52d2b83..573473c2f6 100644 --- a/src/Tgstation.Server.Host/Components/Chat/Commands/PullRequestsCommand.cs +++ b/src/Tgstation.Server.Host/Components/Chat/Commands/PullRequestsCommand.cs @@ -116,7 +116,6 @@ namespace Tgstation.Server.Host.Components.Chat.Commands await databaseContextFactory.UseContext( async db => results = await db .RevisionInformations - .AsQueryable() .Where(x => x.Instance!.Id == instance.Id && x.CommitSha == head) .SelectMany(x => x.ActiveTestMerges!) .Select(x => x.TestMerge) diff --git a/src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs b/src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs index f76ee34517..63f8c166f5 100644 --- a/src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs +++ b/src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Remora.Discord.API.Abstractions.Gateway.Commands; using Remora.Discord.API.Abstractions.Gateway.Events; @@ -72,9 +73,9 @@ namespace Tgstation.Server.Host.Components.Chat.Providers readonly IAssemblyInformationProvider assemblyInformationProvider; /// - /// The for the . + /// The for the . /// - readonly GeneralConfiguration generalConfiguration; + readonly IOptionsMonitor generalConfigurationOptions; /// /// The containing Discord services. @@ -141,18 +142,18 @@ namespace Tgstation.Server.Host.Components.Chat.Providers /// The for the . /// The value of . /// The for the . - /// The value of . + /// The value of . public DiscordProvider( IJobManager jobManager, IAsyncDelayer asyncDelayer, ILogger logger, IAssemblyInformationProvider assemblyInformationProvider, - ChatBot chatBot, - GeneralConfiguration generalConfiguration) + IOptionsMonitor generalConfigurationOptions, + ChatBot chatBot) : base(jobManager, asyncDelayer, logger, chatBot) { this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider)); - this.generalConfiguration = generalConfiguration ?? throw new ArgumentNullException(nameof(generalConfiguration)); + this.generalConfigurationOptions = generalConfigurationOptions ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); mappedChannels = new List(); connectDisconnectLock = new object(); @@ -924,7 +925,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers true), EngineType.OpenDream => new EmbedField( "OpenDream Version", - $"[{engineVersion.SourceSHA![..7]}]({generalConfiguration.OpenDreamGitUrl}/commit/{engineVersion.SourceSHA})", + $"[{engineVersion.SourceSHA![..7]}]({generalConfigurationOptions.CurrentValue.OpenDreamGitUrl}/commit/{engineVersion.SourceSHA})", true), _ => throw new InvalidOperationException($"Invaild EngineType: {engineVersion.Engine.Value}"), }; diff --git a/src/Tgstation.Server.Host/Components/Chat/Providers/IrcProvider.cs b/src/Tgstation.Server.Host/Components/Chat/Providers/IrcProvider.cs index 560390201d..0a947c85e2 100644 --- a/src/Tgstation.Server.Host/Components/Chat/Providers/IrcProvider.cs +++ b/src/Tgstation.Server.Host/Components/Chat/Providers/IrcProvider.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using Meebey.SmartIrc4net; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Newtonsoft.Json; @@ -92,7 +93,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers /// /// The for the . /// - readonly FileLoggingConfiguration loggingConfiguration; + readonly IOptionsMonitor loggingConfigurationOptions; /// /// The client. @@ -117,18 +118,18 @@ namespace Tgstation.Server.Host.Components.Chat.Providers /// The for the . /// The to get the from. /// The for the . - /// The for the . + /// The value of . public IrcProvider( IJobManager jobManager, IAsyncDelayer asyncDelayer, ILogger logger, - IAssemblyInformationProvider assemblyInformationProvider, Models.ChatBot chatBot, - FileLoggingConfiguration loggingConfiguration) + IAssemblyInformationProvider assemblyInformationProvider, + IOptionsMonitor loggingConfigurationOptions) : base(jobManager, asyncDelayer, logger, chatBot) { ArgumentNullException.ThrowIfNull(assemblyInformationProvider); - ArgumentNullException.ThrowIfNull(loggingConfiguration); + ArgumentNullException.ThrowIfNull(loggingConfigurationOptions); var builder = chatBot.CreateConnectionStringBuilder(); if (builder == null || !builder.Valid || builder is not IrcConnectionStringBuilder ircBuilder) @@ -143,7 +144,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers passwordType = ircBuilder.PasswordType; assemblyInfo = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider)); - this.loggingConfiguration = loggingConfiguration ?? throw new ArgumentNullException(nameof(loggingConfiguration)); + this.loggingConfigurationOptions = loggingConfigurationOptions ?? throw new ArgumentNullException(nameof(loggingConfigurationOptions)); client = InstantiateClient(); @@ -758,7 +759,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers newClient.OnChannelMessage += Client_OnChannelMessage; newClient.OnQueryMessage += Client_OnQueryMessage; - if (loggingConfiguration.ProviderNetworkDebug) + if (loggingConfigurationOptions.CurrentValue.ProviderNetworkDebug) { newClient.OnReadLine += (sender, e) => Logger.LogTrace("READ: {line}", e.Line); newClient.OnWriteLine += (sender, e) => Logger.LogTrace("WRITE: {line}", e.Line); diff --git a/src/Tgstation.Server.Host/Components/Chat/Providers/ProviderFactory.cs b/src/Tgstation.Server.Host/Components/Chat/Providers/ProviderFactory.cs index 41113d196f..f8b3be51d0 100644 --- a/src/Tgstation.Server.Host/Components/Chat/Providers/ProviderFactory.cs +++ b/src/Tgstation.Server.Host/Components/Chat/Providers/ProviderFactory.cs @@ -36,14 +36,14 @@ namespace Tgstation.Server.Host.Components.Chat.Providers readonly ILoggerFactory loggerFactory; /// - /// The for the . + /// The for the . /// - readonly GeneralConfiguration generalConfiguration; + readonly IOptionsMonitor generalConfigurationOptions; /// - /// The for the . + /// The for the . /// - readonly FileLoggingConfiguration loggingConfiguration; + readonly IOptionsMonitor loggingConfigurationOptions; /// /// Initializes a new instance of the class. @@ -52,22 +52,22 @@ namespace Tgstation.Server.Host.Components.Chat.Providers /// The value of . /// The value of . /// The value of . - /// The containing the value of . - /// The containing the value of . + /// The value of . + /// The value of . public ProviderFactory( IJobManager jobManager, IAssemblyInformationProvider assemblyInformationProvider, IAsyncDelayer asyncDelayer, ILoggerFactory loggerFactory, - IOptions generalConfigurationOptions, - IOptions loggingConfigurationOptions) + IOptionsMonitor generalConfigurationOptions, + IOptionsMonitor loggingConfigurationOptions) { this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager)); this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer)); this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider)); - generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); - loggingConfiguration = loggingConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(loggingConfigurationOptions)); + this.generalConfigurationOptions = generalConfigurationOptions ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); + this.loggingConfigurationOptions = loggingConfigurationOptions ?? throw new ArgumentNullException(nameof(loggingConfigurationOptions)); } /// @@ -80,16 +80,16 @@ namespace Tgstation.Server.Host.Components.Chat.Providers jobManager, asyncDelayer, loggerFactory.CreateLogger(), - assemblyInformationProvider, settings, - loggingConfiguration), + assemblyInformationProvider, + loggingConfigurationOptions), ChatProvider.Discord => new DiscordProvider( jobManager, asyncDelayer, loggerFactory.CreateLogger(), assemblyInformationProvider, - settings, - generalConfiguration), + generalConfigurationOptions, + settings), _ => throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid ChatProvider: {0}", settings.Provider)), }; } diff --git a/src/Tgstation.Server.Host/Components/Deployment/DmbFactory.cs b/src/Tgstation.Server.Host/Components/Deployment/DmbFactory.cs index c6ff9808a3..8c920d0cbb 100644 --- a/src/Tgstation.Server.Host/Components/Deployment/DmbFactory.cs +++ b/src/Tgstation.Server.Host/Components/Deployment/DmbFactory.cs @@ -207,7 +207,6 @@ namespace Tgstation.Server.Host.Components.Deployment async (db) => cj = await db .CompileJobs - .AsQueryable() .Where(x => x.Job.Instance!.Id == metadata.Id) .OrderByDescending(x => x.Job.StoppedAt) .FirstOrDefaultAsync(cancellationToken)); @@ -277,7 +276,6 @@ namespace Tgstation.Server.Host.Components.Deployment { jobUidsToNotErase = (await db .CompileJobs - .AsQueryable() .Where( x => x.Job.Instance!.Id == metadata.Id && jobIdsToSkip.Contains(x.Id!.Value)) @@ -364,7 +362,6 @@ namespace Tgstation.Server.Host.Components.Deployment await databaseContextFactory.UseContext( async db => compileJob = await db .CompileJobs - .AsQueryable() .Where(x => x!.Id == compileJobId) .Include(x => x.Job!) .ThenInclude(x => x.StartedBy) diff --git a/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs b/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs index 145604228f..307961b634 100644 --- a/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs +++ b/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Prometheus; @@ -31,6 +32,7 @@ namespace Tgstation.Server.Host.Components.Deployment { #pragma warning disable CA1506 // TODO: Decomplexify /// +#pragma warning disable CA1506 // TODO: Decomplexify sealed class DreamMaker : IDreamMaker #pragma warning restore CA1506 { @@ -94,16 +96,16 @@ namespace Tgstation.Server.Host.Components.Deployment /// readonly IAsyncDelayer asyncDelayer; + /// + /// The of for . + /// + readonly IOptionsMonitor sessionConfigurationOptions; + /// /// The for . /// readonly ILogger logger; - /// - /// The for . - /// - readonly SessionConfiguration sessionConfiguration; - /// /// The belongs to. /// @@ -169,8 +171,8 @@ namespace Tgstation.Server.Host.Components.Deployment /// The value of . /// The value of . /// The to use. + /// The value of . /// The value of . - /// The value of . /// The value of . public DreamMaker( IEngineManager engineManager, @@ -185,8 +187,8 @@ namespace Tgstation.Server.Host.Components.Deployment IRemoteDeploymentManagerFactory remoteDeploymentManagerFactory, IAsyncDelayer asyncDelayer, IMetricFactory metricFactory, + IOptionsMonitor sessionConfigurationOptions, ILogger logger, - SessionConfiguration sessionConfiguration, Api.Models.Instance metadata) { this.engineManager = engineManager ?? throw new ArgumentNullException(nameof(engineManager)); @@ -201,8 +203,8 @@ namespace Tgstation.Server.Host.Components.Deployment this.remoteDeploymentManagerFactory = remoteDeploymentManagerFactory ?? throw new ArgumentNullException(nameof(remoteDeploymentManagerFactory)); this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer)); ArgumentNullException.ThrowIfNull(metricFactory); + this.sessionConfigurationOptions = sessionConfigurationOptions ?? throw new ArgumentNullException(nameof(sessionConfigurationOptions)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); - this.sessionConfiguration = sessionConfiguration ?? throw new ArgumentNullException(nameof(sessionConfiguration)); this.metadata = metadata ?? throw new ArgumentNullException(nameof(metadata)); successfulDeployments = metricFactory.CreateCounter("tgs_successful_deployments", "The number of deployments that have completed successfully"); @@ -255,7 +257,6 @@ namespace Tgstation.Server.Host.Components.Deployment ddSettings = await databaseContext .DreamDaemonSettings - .AsQueryable() .Where(x => x.InstanceId == metadata.Id) .Select(x => new Models.DreamDaemonSettings { @@ -268,7 +269,6 @@ namespace Tgstation.Server.Host.Components.Deployment dreamMakerSettings = await databaseContext .DreamMakerSettings - .AsQueryable() .Where(x => x.InstanceId == metadata.Id) .FirstAsync(cancellationToken); if (dreamMakerSettings == default) @@ -276,7 +276,6 @@ namespace Tgstation.Server.Host.Components.Deployment repositorySettings = await databaseContext .RepositorySettings - .AsQueryable() .Where(x => x.InstanceId == metadata.Id) .Select(x => new Models.RepositorySettings { @@ -304,7 +303,6 @@ namespace Tgstation.Server.Host.Components.Deployment repoName = repo.RemoteRepositoryName; revInfo = await databaseContext .RevisionInformations - .AsQueryable() .Where(x => x.CommitSha == repoSha && x.InstanceId == metadata.Id) .Include(x => x.ActiveTestMerges!) .ThenInclude(x => x.TestMerge!) @@ -458,7 +456,6 @@ namespace Tgstation.Server.Host.Components.Deployment { var previousCompileJobs = await databaseContext .CompileJobs - .AsQueryable() .Where(x => x.Job.Instance!.Id == metadata.Id) .OrderByDescending(x => x.Job.StoppedAt) .Take(10) @@ -929,7 +926,7 @@ namespace Tgstation.Server.Host.Components.Deployment readStandardHandles: true, noShellExecute: true); - if (sessionConfiguration.LowPriorityDeploymentProcesses) + if (sessionConfigurationOptions.CurrentValue.LowPriorityDeploymentProcesses) dm.AdjustPriority(false); int exitCode; @@ -1020,7 +1017,7 @@ namespace Tgstation.Server.Host.Components.Deployment { async ValueTask CleanDir() { - if (sessionConfiguration.DelayCleaningFailedDeployments) + if (sessionConfigurationOptions.CurrentValue.DelayCleaningFailedDeployments) { logger.LogDebug("Not cleaning up errored deployment directory {guid} due to config.", job.DirectoryName); return; diff --git a/src/Tgstation.Server.Host/Components/Deployment/Remote/GitHubRemoteDeploymentManager.cs b/src/Tgstation.Server.Host/Components/Deployment/Remote/GitHubRemoteDeploymentManager.cs index 790b9ea1d3..a023910f6f 100644 --- a/src/Tgstation.Server.Host/Components/Deployment/Remote/GitHubRemoteDeploymentManager.cs +++ b/src/Tgstation.Server.Host/Components/Deployment/Remote/GitHubRemoteDeploymentManager.cs @@ -70,7 +70,6 @@ namespace Tgstation.Server.Host.Components.Deployment.Remote async databaseContext => repositorySettings = await databaseContext .RepositorySettings - .AsQueryable() .Where(x => x.InstanceId == Metadata.Id) .FirstAsync(cancellationToken)); @@ -376,7 +375,6 @@ namespace Tgstation.Server.Host.Components.Deployment.Remote async databaseContext => gitHubAccessToken = await databaseContext .RepositorySettings - .AsQueryable() .Where(x => x.InstanceId == Metadata.Id) .Select(x => x.AccessToken) .FirstAsync(cancellationToken)); diff --git a/src/Tgstation.Server.Host/Components/Engine/OpenDreamInstaller.cs b/src/Tgstation.Server.Host/Components/Engine/OpenDreamInstaller.cs index e7a53e3cd8..071fcbaab4 100644 --- a/src/Tgstation.Server.Host/Components/Engine/OpenDreamInstaller.cs +++ b/src/Tgstation.Server.Host/Components/Engine/OpenDreamInstaller.cs @@ -52,14 +52,14 @@ namespace Tgstation.Server.Host.Components.Engine protected IProcessExecutor ProcessExecutor { get; } /// - /// The for the . + /// The for the . /// - protected GeneralConfiguration GeneralConfiguration { get; } + protected IOptionsMonitor GeneralConfigurationOptions { get; } /// /// The for the . /// - protected SessionConfiguration SessionConfiguration { get; } + protected IOptionsMonitor SessionConfigurationOptions { get; } /// /// The for the . @@ -91,8 +91,8 @@ namespace Tgstation.Server.Host.Components.Engine /// The value of . /// The value of . /// The value of . - /// The containing value of . - /// The containing value of . + /// The value of . + /// The value of . public OpenDreamInstaller( IIOManager ioManager, ILogger logger, @@ -101,8 +101,8 @@ namespace Tgstation.Server.Host.Components.Engine IRepositoryManager repositoryManager, IAsyncDelayer asyncDelayer, IHttpClientFactory httpClientFactory, - IOptions generalConfigurationOptions, - IOptions sessionConfigurationOptions) + IOptionsMonitor generalConfigurationOptions, + IOptionsMonitor sessionConfigurationOptions) : base(ioManager, logger) { this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier)); @@ -110,8 +110,8 @@ namespace Tgstation.Server.Host.Components.Engine this.repositoryManager = repositoryManager ?? throw new ArgumentNullException(nameof(repositoryManager)); this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer)); this.httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory)); - GeneralConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); - SessionConfiguration = sessionConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(sessionConfigurationOptions)); + GeneralConfigurationOptions = generalConfigurationOptions ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); + SessionConfigurationOptions = sessionConfigurationOptions ?? throw new ArgumentNullException(nameof(sessionConfigurationOptions)); } /// @@ -147,10 +147,11 @@ namespace Tgstation.Server.Host.Components.Engine var progressSection1 = jobProgressReporter.CreateSection("Updating OpenDream git repository", 0.5f); IRepository? repo; + var generalConfig = GeneralConfigurationOptions.CurrentValue; try { repo = await repositoryManager.CloneRepository( - GeneralConfiguration.OpenDreamGitUrl, + generalConfig.OpenDreamGitUrl, null, null, null, @@ -187,7 +188,7 @@ namespace Tgstation.Server.Host.Components.Engine using (var progressSection2 = jobProgressReporter.CreateSection("Checking out OpenDream version", 0.5f)) { var committish = version.SourceSHA - ?? $"{GeneralConfiguration.OpenDreamGitTagPrefix}{version.Version!.Semver()}"; + ?? $"{generalConfig.OpenDreamGitTagPrefix}{version.Version!.Semver()}"; await repo.CheckoutObject( committish, @@ -279,6 +280,7 @@ namespace Tgstation.Server.Host.Components.Engine async shortenedPath => { var shortenedDeployPath = IOManager.ConcatPath(shortenedPath, DeployDir); + var generalConfig = GeneralConfigurationOptions.CurrentValue; await using var buildProcess = await ProcessExecutor.LaunchProcess( dotnetPath, shortenedPath, @@ -286,17 +288,17 @@ namespace Tgstation.Server.Host.Components.Engine cancellationToken, null, null, - !GeneralConfiguration.OpenDreamSuppressInstallOutput, - !GeneralConfiguration.OpenDreamSuppressInstallOutput); + !generalConfig.OpenDreamSuppressInstallOutput, + !generalConfig.OpenDreamSuppressInstallOutput); - if (deploymentPipelineProcesses && SessionConfiguration.LowPriorityDeploymentProcesses) + if (deploymentPipelineProcesses && SessionConfigurationOptions.CurrentValue.LowPriorityDeploymentProcesses) buildProcess.AdjustPriority(false); using (cancellationToken.Register(() => buildProcess.Terminate())) buildExitCode = await buildProcess.Lifetime; string? output; - if (!GeneralConfiguration.OpenDreamSuppressInstallOutput) + if (!GeneralConfigurationOptions.CurrentValue.OpenDreamSuppressInstallOutput) { var buildOutputTask = buildProcess.GetCombinedOutput(cancellationToken); if (!buildOutputTask.IsCompleted) diff --git a/src/Tgstation.Server.Host/Components/Engine/WindowsByondInstaller.cs b/src/Tgstation.Server.Host/Components/Engine/WindowsByondInstaller.cs index 0c0f345dfd..8b04370c78 100644 --- a/src/Tgstation.Server.Host/Components/Engine/WindowsByondInstaller.cs +++ b/src/Tgstation.Server.Host/Components/Engine/WindowsByondInstaller.cs @@ -79,7 +79,7 @@ namespace Tgstation.Server.Host.Components.Engine /// /// The for the . /// - readonly SessionConfiguration sessionConfiguration; + readonly IOptionsMonitor sessionConfigurationOptions; /// /// The for the . @@ -96,7 +96,7 @@ namespace Tgstation.Server.Host.Components.Engine /// /// The value of . /// The containing the . - /// The containing the value of . + /// The value of . /// The for the . /// The for the . /// The for the . @@ -105,12 +105,12 @@ namespace Tgstation.Server.Host.Components.Engine IIOManager ioManager, IFileDownloader fileDownloader, IOptionsMonitor generalConfigurationOptions, - IOptions sessionConfigurationOptions, + IOptionsMonitor sessionConfigurationOptions, ILogger logger) : base(ioManager, logger, fileDownloader, generalConfigurationOptions) { this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor)); - sessionConfiguration = sessionConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(sessionConfigurationOptions)); + this.sessionConfigurationOptions = sessionConfigurationOptions ?? throw new ArgumentNullException(nameof(sessionConfigurationOptions)); var useServiceSpecialTactics = Environment.Is64BitProcess && Environment.UserName == $"{Environment.MachineName}$"; @@ -215,7 +215,7 @@ namespace Tgstation.Server.Host.Components.Engine /// protected override string GetDreamDaemonName(Version byondVersion, out bool supportsCli) { - supportsCli = byondVersion >= DDExeVersion && !sessionConfiguration.ForceUseDreamDaemonExe; + supportsCli = byondVersion >= DDExeVersion && !sessionConfigurationOptions.CurrentValue.ForceUseDreamDaemonExe; return supportsCli ? "dd.exe" : "dreamdaemon.exe"; } @@ -327,7 +327,7 @@ namespace Tgstation.Server.Host.Components.Engine Logger, ruleName, dreamDaemonPath, - deploymentPipelineProcesses && sessionConfiguration.LowPriorityDeploymentProcesses, + deploymentPipelineProcesses && sessionConfigurationOptions.CurrentValue.LowPriorityDeploymentProcesses, cancellationToken); } catch (Exception ex) diff --git a/src/Tgstation.Server.Host/Components/Engine/WindowsOpenDreamInstaller.cs b/src/Tgstation.Server.Host/Components/Engine/WindowsOpenDreamInstaller.cs index adcf6ae443..9ee684d1cf 100644 --- a/src/Tgstation.Server.Host/Components/Engine/WindowsOpenDreamInstaller.cs +++ b/src/Tgstation.Server.Host/Components/Engine/WindowsOpenDreamInstaller.cs @@ -37,8 +37,8 @@ namespace Tgstation.Server.Host.Components.Engine /// The for the . /// The for the . /// The for the . - /// The of for the . - /// The of for the . + /// The of for the . + /// The of for the . /// The value of . public WindowsOpenDreamInstaller( IIOManager ioManager, @@ -48,8 +48,8 @@ namespace Tgstation.Server.Host.Components.Engine IRepositoryManager repositoryManager, IAsyncDelayer asyncDelayer, IHttpClientFactory httpClientFactory, - IOptions generalConfigurationOptions, - IOptions sessionConfigurationOptions, + IOptionsMonitor generalConfigurationOptions, + IOptionsMonitor sessionConfigurationOptions, IFilesystemLinkFactory linkFactory) : base( ioManager, @@ -108,7 +108,7 @@ namespace Tgstation.Server.Host.Components.Engine /// A representing the running operation. async ValueTask AddServerFirewallException(EngineVersion version, string path, bool deploymentPipelineProcesses, CancellationToken cancellationToken) { - if (GeneralConfiguration.SkipAddingByondFirewallException) + if (GeneralConfigurationOptions.CurrentValue.SkipAddingByondFirewallException) return; GetExecutablePaths(path, out var serverExePath, out _); @@ -126,7 +126,7 @@ namespace Tgstation.Server.Host.Components.Engine Logger, ruleName, serverExePath, - deploymentPipelineProcesses && SessionConfiguration.LowPriorityDeploymentProcesses, + deploymentPipelineProcesses && SessionConfigurationOptions.CurrentValue.LowPriorityDeploymentProcesses, cancellationToken); } catch (Exception ex) diff --git a/src/Tgstation.Server.Host/Components/Instance.cs b/src/Tgstation.Server.Host/Components/Instance.cs index 37454b7dbc..164d2c2e7d 100644 --- a/src/Tgstation.Server.Host/Components/Instance.cs +++ b/src/Tgstation.Server.Host/Components/Instance.cs @@ -389,7 +389,6 @@ namespace Tgstation.Server.Host.Components // assume 5 steps with synchronize var repositorySettingsTask = databaseContext .RepositorySettings - .AsQueryable() .Where(x => x.InstanceId == metadata.Id) .FirstAsync(cancellationToken); @@ -433,7 +432,6 @@ namespace Tgstation.Server.Host.Components logger.LogTrace("Loading revision info for commit {sha}...", startSha[..7]); currentRevInfo = await databaseContext .RevisionInformations - .AsQueryable() .Where(x => x.CommitSha == startSha && x.InstanceId == metadata.Id) .Include(x => x.ActiveTestMerges!) .ThenInclude(x => x.TestMerge) @@ -550,8 +548,8 @@ namespace Tgstation.Server.Host.Components var currentHead = repo.Head; - currentRevInfo = await databaseContext.RevisionInformations - .AsQueryable() + currentRevInfo = await databaseContext + .RevisionInformations .Where(x => x.CommitSha == currentHead && x.InstanceId == metadata.Id) .FirstOrDefaultAsync(cancellationToken); diff --git a/src/Tgstation.Server.Host/Components/InstanceFactory.cs b/src/Tgstation.Server.Host/Components/InstanceFactory.cs index 2a12c9e409..3cd53c6edd 100644 --- a/src/Tgstation.Server.Host/Components/InstanceFactory.cs +++ b/src/Tgstation.Server.Host/Components/InstanceFactory.cs @@ -144,14 +144,14 @@ namespace Tgstation.Server.Host.Components readonly IMetricFactory metricFactory; /// - /// The for the . + /// The of for the . /// - readonly GeneralConfiguration generalConfiguration; + readonly IOptionsMonitor generalConfigurationOptions; /// - /// The for the . + /// The of for the . /// - readonly SessionConfiguration sessionConfiguration; + readonly IOptionsMonitor sessionConfigurationOptions; /// /// Create the pointing to the "Game" directory of a given . @@ -186,8 +186,8 @@ namespace Tgstation.Server.Host.Components /// The value of . /// The value of . /// The value of . - /// The containing the value of . - /// The containing the value of . + /// The value of . + /// The value of . public InstanceFactory( IIOManager ioManager, IDatabaseContextFactory databaseContextFactory, @@ -211,8 +211,8 @@ namespace Tgstation.Server.Host.Components IAsyncDelayer asyncDelayer, IDotnetDumpService dotnetDumpService, IMetricFactory metricFactory, - IOptions generalConfigurationOptions, - IOptions sessionConfigurationOptions) + IOptionsMonitor generalConfigurationOptions, + IOptionsMonitor sessionConfigurationOptions) { this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager)); this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory)); @@ -236,8 +236,8 @@ namespace Tgstation.Server.Host.Components this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer)); this.dotnetDumpService = dotnetDumpService ?? throw new ArgumentNullException(nameof(dotnetDumpService)); this.metricFactory = metricFactory ?? throw new ArgumentNullException(nameof(metricFactory)); - generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); - sessionConfiguration = sessionConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(sessionConfigurationOptions)); + this.generalConfigurationOptions = generalConfigurationOptions ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); + this.sessionConfigurationOptions = sessionConfigurationOptions ?? throw new ArgumentNullException(nameof(sessionConfigurationOptions)); } #pragma warning restore CA1502 @@ -282,10 +282,10 @@ namespace Tgstation.Server.Host.Components postWriteHandler, platformIdentifier, fileTransferService, + generalConfigurationOptions, + sessionConfigurationOptions, loggerFactory.CreateLogger(), - metadata, - generalConfiguration, - sessionConfiguration); + metadata); var eventConsumer = new EventConsumer(configuration); var repoManager = repositoryManagerFactory.CreateRepositoryManager(repoIoManager, eventConsumer); try @@ -337,8 +337,8 @@ namespace Tgstation.Server.Host.Components dotnetDumpService, metricFactory, loggerFactory, + sessionConfigurationOptions, loggerFactory.CreateLogger(), - sessionConfiguration, metadata); var watchdog = watchdogFactory.CreateWatchdog( @@ -372,8 +372,8 @@ namespace Tgstation.Server.Host.Components remoteDeploymentManagerFactory, asyncDelayer, metricFactory, + sessionConfigurationOptions, loggerFactory.CreateLogger(), - sessionConfiguration, metadata); instance = new Instance( diff --git a/src/Tgstation.Server.Host/Components/InstanceManager.cs b/src/Tgstation.Server.Host/Components/InstanceManager.cs index 52d31cf2d0..7f1c50fe21 100644 --- a/src/Tgstation.Server.Host/Components/InstanceManager.cs +++ b/src/Tgstation.Server.Host/Components/InstanceManager.cs @@ -100,6 +100,26 @@ namespace Tgstation.Server.Host.Components /// readonly IPlatformIdentifier platformIdentifier; + /// + /// The of for the . + /// + readonly IOptions generalConfigurationOptions; + + /// + /// The of for the . + /// + readonly IOptions swarmConfigurationOptions; + + /// + /// The of for the . + /// + readonly IOptions internalConfigurationOptions; + + /// + /// The of for the . + /// + readonly IOptions sessionConfigurationOptions; + /// /// The for the . /// @@ -120,26 +140,6 @@ namespace Tgstation.Server.Host.Components /// readonly SemaphoreSlim instanceStateChangeSemaphore; - /// - /// The for the . - /// - readonly GeneralConfiguration generalConfiguration; - - /// - /// The for the . - /// - readonly SwarmConfiguration swarmConfiguration; - - /// - /// The for the . - /// - readonly InternalConfiguration internalConfiguration; - - /// - /// The for the . - /// - readonly SessionConfiguration sessionConfiguration; - /// /// The for . /// @@ -191,10 +191,10 @@ namespace Tgstation.Server.Host.Components /// The value of . /// The used to create metrics. /// The to use. - /// The containing the value of . - /// The containing the value of . - /// The containing the value of . - /// The containing the value of . + /// The value of . + /// The value of . + /// The value of . + /// The value of . /// The value of . public InstanceManager( IInstanceFactory instanceFactory, @@ -229,10 +229,10 @@ namespace Tgstation.Server.Host.Components this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier)); ArgumentNullException.ThrowIfNull(metricFactory); ArgumentNullException.ThrowIfNull(collectorRegistry); - generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); - swarmConfiguration = swarmConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(swarmConfigurationOptions)); - internalConfiguration = internalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(internalConfigurationOptions)); - sessionConfiguration = sessionConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(sessionConfigurationOptions)); + this.generalConfigurationOptions = generalConfigurationOptions ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); + this.swarmConfigurationOptions = swarmConfigurationOptions ?? throw new ArgumentNullException(nameof(swarmConfigurationOptions)); + this.internalConfigurationOptions = internalConfigurationOptions ?? throw new ArgumentNullException(nameof(internalConfigurationOptions)); + this.sessionConfigurationOptions = sessionConfigurationOptions ?? throw new ArgumentNullException(nameof(sessionConfigurationOptions)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); originalConsoleTitle = console.Title; @@ -390,7 +390,6 @@ namespace Tgstation.Server.Host.Components { var jobs = await db .Jobs - .AsQueryable() .Where(x => x.Instance!.Id == metadata.Id && !x.StoppedAt.HasValue) .Select(x => new Job(x.Id!.Value)) .ToListAsync(cancellationToken); @@ -641,8 +640,7 @@ namespace Tgstation.Server.Host.Components async ValueTask EnumerateInstances(IDatabaseContext databaseContext) => dbInstances = await databaseContext .Instances - .AsQueryable() - .Where(x => x.Online!.Value && x.SwarmIdentifer == swarmConfiguration.Identifier) + .Where(x => x.Online!.Value && x.SwarmIdentifer == swarmConfigurationOptions.Value.Identifier) .Include(x => x.RepositorySettings) .Include(x => x.ChatSettings) .ThenInclude(x => x.Channels) @@ -703,14 +701,14 @@ namespace Tgstation.Server.Host.Components { logger.LogDebug("Running as user: {username}", Environment.UserName); - generalConfiguration.CheckCompatibility(logger, ioManager); + generalConfigurationOptions.Value.CheckCompatibility(logger, ioManager); using (var systemIdentity = systemIdentityFactory.GetCurrent()) { if (!systemIdentity.CanCreateSymlinks) throw new InvalidOperationException($"The user running {Constants.CanonicalPackageName} cannot create symlinks! Please try running as an administrative user!"); - if (!platformIdentifier.IsWindows && systemIdentity.IsSuperUser && !internalConfiguration.UsingDocker) + if (!platformIdentifier.IsWindows && systemIdentity.IsSuperUser && !internalConfigurationOptions.Value.UsingDocker) { logger.LogWarning("TGS is being run as the root account. This is not recommended."); } @@ -718,8 +716,8 @@ namespace Tgstation.Server.Host.Components // This runs before the real sockets are opened, ensures we don't perform reattaches unless we're fairly certain the bind won't fail // If it does fail, DD will be killed. - SocketExtensions.BindTest(platformIdentifier, new IPEndPoint(IPAddress.Loopback, sessionConfiguration.BridgePort), false); - var allHostingSpecs = generalConfiguration.ApiEndPoints.Concat(generalConfiguration.MetricsEndPoints).Concat(swarmConfiguration.EndPoints); + SocketExtensions.BindTest(platformIdentifier, new IPEndPoint(IPAddress.Loopback, sessionConfigurationOptions.Value.BridgePort), false); + var allHostingSpecs = generalConfigurationOptions.Value.ApiEndPoints.Concat(generalConfigurationOptions.Value.MetricsEndPoints).Concat(swarmConfigurationOptions.Value.EndPoints); foreach (var hostingSpec in allHostingSpecs) SocketExtensions.BindTest(platformIdentifier, hostingSpec.ParseIPEndPoint(), false); } diff --git a/src/Tgstation.Server.Host/Components/Repository/Repository.cs b/src/Tgstation.Server.Host/Components/Repository/Repository.cs index 636321b5c7..3addf35ea9 100644 --- a/src/Tgstation.Server.Host/Components/Repository/Repository.cs +++ b/src/Tgstation.Server.Host/Components/Repository/Repository.cs @@ -9,6 +9,7 @@ using LibGit2Sharp; using LibGit2Sharp.Handlers; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Tgstation.Server.Api.Models; using Tgstation.Server.Host.Components.Events; @@ -115,16 +116,16 @@ namespace Tgstation.Server.Host.Components.Repository /// readonly ILibGit2RepositoryFactory submoduleFactory; + /// + /// The of for the . + /// + readonly IOptionsMonitor generalConfigurationOptions; + /// /// The for the . /// readonly ILogger logger; - /// - /// The for the . - /// - readonly GeneralConfiguration generalConfiguration; - /// /// Initializes a new instance of the class. /// @@ -136,8 +137,8 @@ namespace Tgstation.Server.Host.Components.Repository /// The value of . /// The to provide the value of . /// The value of . + /// The value of . /// The value of . - /// The value of . /// The action for the . public Repository( LibGit2Sharp.IRepository libGitRepo, @@ -148,8 +149,8 @@ namespace Tgstation.Server.Host.Components.Repository IPostWriteHandler postWriteHandler, IGitRemoteFeaturesFactory gitRemoteFeaturesFactory, ILibGit2RepositoryFactory submoduleFactory, + IOptionsMonitor generalConfigurationOptions, ILogger logger, - GeneralConfiguration generalConfiguration, Action disposeAction) : base(disposeAction) { @@ -161,9 +162,8 @@ namespace Tgstation.Server.Host.Components.Repository this.postWriteHandler = postWriteHandler ?? throw new ArgumentNullException(nameof(postWriteHandler)); ArgumentNullException.ThrowIfNull(gitRemoteFeaturesFactory); this.submoduleFactory = submoduleFactory ?? throw new ArgumentNullException(nameof(submoduleFactory)); - + this.generalConfigurationOptions = generalConfigurationOptions ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); - this.generalConfiguration = generalConfiguration ?? throw new ArgumentNullException(nameof(generalConfiguration)); gitRemoteFeatures = gitRemoteFeaturesFactory.CreateGitRemoteFeatures(this); } @@ -539,7 +539,7 @@ namespace Tgstation.Server.Host.Components.Repository }, ioManager.ResolvePath(), path, - generalConfiguration.GetCopyDirectoryTaskThrottle(), + generalConfigurationOptions.CurrentValue.GetCopyDirectoryTaskThrottle(), cancellationToken); } diff --git a/src/Tgstation.Server.Host/Components/Repository/RepositoryManager.cs b/src/Tgstation.Server.Host/Components/Repository/RepositoryManager.cs index 74a6bc6751..ddf05a7856 100644 --- a/src/Tgstation.Server.Host/Components/Repository/RepositoryManager.cs +++ b/src/Tgstation.Server.Host/Components/Repository/RepositoryManager.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using LibGit2Sharp; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Tgstation.Server.Api.Models; using Tgstation.Server.Host.Components.Events; @@ -55,6 +56,11 @@ namespace Tgstation.Server.Host.Components.Repository /// readonly IGitRemoteFeaturesFactory gitRemoteFeaturesFactory; + /// + /// The of for the . + /// + readonly IOptionsMonitor generalConfigurationOptions; + /// /// The created s. /// @@ -65,11 +71,6 @@ namespace Tgstation.Server.Host.Components.Repository /// readonly ILogger logger; - /// - /// The for the . - /// - readonly GeneralConfiguration generalConfiguration; - /// /// Used for controlling single access to the . /// @@ -85,8 +86,8 @@ namespace Tgstation.Server.Host.Components.Repository /// The value of . /// The value of . /// The value of . + /// The value of . /// The value of . - /// The value of . public RepositoryManager( ILibGit2RepositoryFactory repositoryFactory, ILibGit2Commands commands, @@ -94,9 +95,9 @@ namespace Tgstation.Server.Host.Components.Repository IEventConsumer eventConsumer, IPostWriteHandler postWriteHandler, IGitRemoteFeaturesFactory gitRemoteFeaturesFactory, + IOptionsMonitor generalConfigurationOptions, ILogger repositoryLogger, - ILogger logger, - GeneralConfiguration generalConfiguration) + ILogger logger) { this.repositoryFactory = repositoryFactory ?? throw new ArgumentNullException(nameof(repositoryFactory)); this.commands = commands ?? throw new ArgumentNullException(nameof(commands)); @@ -105,8 +106,8 @@ namespace Tgstation.Server.Host.Components.Repository this.postWriteHandler = postWriteHandler ?? throw new ArgumentNullException(nameof(postWriteHandler)); this.gitRemoteFeaturesFactory = gitRemoteFeaturesFactory ?? throw new ArgumentNullException(nameof(gitRemoteFeaturesFactory)); this.repositoryLogger = repositoryLogger ?? throw new ArgumentNullException(nameof(repositoryLogger)); + this.generalConfigurationOptions = generalConfigurationOptions ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); - this.generalConfiguration = generalConfiguration ?? throw new ArgumentNullException(nameof(generalConfiguration)); semaphore = new SemaphoreSlim(1); } @@ -232,8 +233,8 @@ namespace Tgstation.Server.Host.Components.Repository postWriteHandler, gitRemoteFeaturesFactory, repositoryFactory, + generalConfigurationOptions, repositoryLogger, - generalConfiguration, () => { logger.LogTrace("Releasing semaphore due to Repository disposal..."); diff --git a/src/Tgstation.Server.Host/Components/Repository/RepositoryUpdateService.cs b/src/Tgstation.Server.Host/Components/Repository/RepositoryUpdateService.cs index cb15e878f1..de3feb5d08 100644 --- a/src/Tgstation.Server.Host/Components/Repository/RepositoryUpdateService.cs +++ b/src/Tgstation.Server.Host/Components/Repository/RepositoryUpdateService.cs @@ -90,7 +90,10 @@ namespace Tgstation.Server.Host.Components.Repository .ThenInclude(x => x.TestMerge) .ThenInclude(x => x.MergedBy); - var revisionInfo = await ApplyQuery(databaseContext.RevisionInformations).FirstOrDefaultAsync(cancellationToken); + var revisionInfo = await ApplyQuery( + databaseContext + .RevisionInformations) + .FirstOrDefaultAsync(cancellationToken); // If the DB doesn't have it, check the local set if (revisionInfo == default) @@ -400,8 +403,8 @@ namespace Tgstation.Server.Host.Components.Repository await databaseContextFactory.UseContext( async databaseContext => - dbPull = await databaseContext.RevisionInformations - .AsQueryable() + dbPull = await databaseContext + .RevisionInformations .Where(x => x.InstanceId == instanceId && x.OriginCommitSha == lastRevisionInfo.OriginCommitSha && x.ActiveTestMerges!.Count <= newTestMergeModels.Count diff --git a/src/Tgstation.Server.Host/Components/Repository/RepostoryManagerFactory.cs b/src/Tgstation.Server.Host/Components/Repository/RepostoryManagerFactory.cs index cba66ff69a..c48ba8702e 100644 --- a/src/Tgstation.Server.Host/Components/Repository/RepostoryManagerFactory.cs +++ b/src/Tgstation.Server.Host/Components/Repository/RepostoryManagerFactory.cs @@ -34,16 +34,16 @@ namespace Tgstation.Server.Host.Components.Repository /// readonly IGitRemoteFeaturesFactory gitRemoteFeaturesFactory; + /// + /// The of for the . + /// + readonly IOptionsMonitor generalConfigurationOptions; + /// /// The for the . /// readonly ILoggerFactory loggerFactory; - /// - /// The for the . - /// - readonly GeneralConfiguration generalConfiguration; - /// /// Initializes a new instance of the class. /// @@ -52,21 +52,21 @@ namespace Tgstation.Server.Host.Components.Repository /// The value of . /// The value of . /// The value of . - /// The containing the value of . + /// The value of . public RepostoryManagerFactory( ILibGit2RepositoryFactory repositoryFactory, ILibGit2Commands repositoryCommands, IPostWriteHandler postWriteHandler, IGitRemoteFeaturesFactory gitRemoteFeaturesFactory, ILoggerFactory loggerFactory, - IOptions generalConfigurationOptions) + IOptionsMonitor generalConfigurationOptions) { this.repositoryFactory = repositoryFactory ?? throw new ArgumentNullException(nameof(repositoryFactory)); this.repositoryCommands = repositoryCommands ?? throw new ArgumentNullException(nameof(repositoryCommands)); this.postWriteHandler = postWriteHandler ?? throw new ArgumentNullException(nameof(postWriteHandler)); this.gitRemoteFeaturesFactory = gitRemoteFeaturesFactory ?? throw new ArgumentNullException(nameof(gitRemoteFeaturesFactory)); this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); - generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); + this.generalConfigurationOptions = generalConfigurationOptions ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); } /// @@ -78,9 +78,9 @@ namespace Tgstation.Server.Host.Components.Repository eventConsumer, postWriteHandler, gitRemoteFeaturesFactory, + generalConfigurationOptions, loggerFactory.CreateLogger(), - loggerFactory.CreateLogger(), - generalConfiguration); + loggerFactory.CreateLogger()); /// public Task StartAsync(CancellationToken cancellationToken) diff --git a/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs b/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs index 69f5805fbb..388973823c 100644 --- a/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs +++ b/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs @@ -9,6 +9,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Prometheus; @@ -114,16 +115,16 @@ namespace Tgstation.Server.Host.Components.Session /// readonly ILoggerFactory loggerFactory; + /// + /// The of for the . + /// + readonly IOptionsMonitor sessionConfigurationOptions; + /// /// The for the . /// readonly ILogger logger; - /// - /// The for the . - /// - readonly SessionConfiguration sessionConfiguration; - /// /// The number of sessions launched. /// @@ -192,9 +193,9 @@ namespace Tgstation.Server.Host.Components.Session /// The value of . /// The value of . /// The used to create metrics. + /// The value of . /// The value of . /// The value of . - /// The value of . public SessionControllerFactory( IProcessExecutor processExecutor, IEngineManager engineManager, @@ -212,8 +213,8 @@ namespace Tgstation.Server.Host.Components.Session IDotnetDumpService dotnetDumpService, IMetricFactory metricFactory, ILoggerFactory loggerFactory, + IOptionsMonitor sessionConfigurationOptions, ILogger logger, - SessionConfiguration sessionConfiguration, Api.Models.Instance instance) { this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor)); @@ -231,9 +232,9 @@ namespace Tgstation.Server.Host.Components.Session this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer)); this.dotnetDumpService = dotnetDumpService ?? throw new ArgumentNullException(nameof(dotnetDumpService)); ArgumentNullException.ThrowIfNull(metricFactory); + this.sessionConfigurationOptions = sessionConfigurationOptions ?? throw new ArgumentNullException(nameof(sessionConfigurationOptions)); this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); - this.sessionConfiguration = sessionConfiguration ?? throw new ArgumentNullException(nameof(sessionConfiguration)); this.instance = instance ?? throw new ArgumentNullException(nameof(instance)); sessionsLaunched = metricFactory.CreateCounter("tgs_sessions_launched", "The number of game server processes created"); @@ -321,10 +322,12 @@ namespace Tgstation.Server.Host.Components.Session logger.LogDebug("Session will have no DMAPI support!"); // launch dd + var sessionConfiguration = sessionConfigurationOptions.CurrentValue; var process = await CreateGameServerProcess( dmbProvider, engineLock, launchParameters, + sessionConfiguration, accessIdentifier, outputFilePath, apiValidate, @@ -341,6 +344,7 @@ namespace Tgstation.Server.Host.Components.Session chatTrackingContext, launchParameters.SecurityLevel!.Value, launchParameters.Visibility!.Value, + sessionConfiguration.BridgePort, apiValidate); var reattachInformation = new ReattachInformation( @@ -449,6 +453,7 @@ namespace Tgstation.Server.Host.Components.Session chatTrackingContext, reattachInformation.LaunchSecurityLevel, reattachInformation.LaunchVisibility, + sessionConfigurationOptions.CurrentValue.BridgePort, false); reattachInformation.SetRuntimeInformation(runtimeInformation); @@ -504,6 +509,7 @@ namespace Tgstation.Server.Host.Components.Session /// The . /// The . /// The . + /// The current . /// The secure string to use for the session. /// The optional full path to log DreamDaemon output to. /// If we are only validating the DMAPI then exiting. @@ -513,6 +519,7 @@ namespace Tgstation.Server.Host.Components.Session IDmbProvider dmbProvider, IEngineExecutableLock engineLock, DreamDaemonLaunchParameters launchParameters, + SessionConfiguration sessionConfiguration, string accessIdentifier, string? logFilePath, bool apiValidate, @@ -653,6 +660,7 @@ namespace Tgstation.Server.Host.Components.Session /// The . /// The the server was launched with. /// The the server was launched with. + /// The active bridge requests port. /// The value of . /// A new class. RuntimeInformation CreateRuntimeInformation( @@ -660,6 +668,7 @@ namespace Tgstation.Server.Host.Components.Session IChatTrackingContext chatTrackingContext, DreamDaemonSecurity securityLevel, DreamDaemonVisibility visibility, + ushort bridgePort, bool apiValidateOnly) => new( chatTrackingContext, @@ -668,7 +677,7 @@ namespace Tgstation.Server.Host.Components.Session instance.Name!, securityLevel, visibility, - sessionConfiguration.BridgePort, + bridgePort, apiValidateOnly); /// diff --git a/src/Tgstation.Server.Host/Components/Session/SessionPersistor.cs b/src/Tgstation.Server.Host/Components/Session/SessionPersistor.cs index edfc6a5145..d82d4937b1 100644 --- a/src/Tgstation.Server.Host/Components/Session/SessionPersistor.cs +++ b/src/Tgstation.Server.Host/Components/Session/SessionPersistor.cs @@ -158,7 +158,6 @@ namespace Tgstation.Server.Host.Components.Session { var dbReattachInfos = await db .ReattachInformations - .AsQueryable() .Where(x => x.CompileJob!.Job.Instance!.Id == metadata.Id) .Include(x => x.CompileJob) .Include(x => x.InitialCompileJob) @@ -169,7 +168,6 @@ namespace Tgstation.Server.Host.Components.Session var timeoutMilliseconds = await db .Instances - .AsQueryable() .Where(x => x.Id == metadata.Id) .Select(x => x.DreamDaemonSettings!.TopicRequestTimeout) .FirstOrDefaultAsync(cancellationToken); @@ -217,7 +215,6 @@ namespace Tgstation.Server.Host.Components.Session logger.LogTrace("Deleting ReattachInformation {id}...", result.Id); await db .ReattachInformations - .AsQueryable() .Where(x => x.Id == result.Id) .ExecuteDeleteAsync(cancellationToken); }); @@ -264,7 +261,6 @@ namespace Tgstation.Server.Host.Components.Session { var baseQuery = databaseContext .ReattachInformations - .AsQueryable() .Where(x => x.CompileJob!.Job.Instance!.Id == metadata.Id); if (instant) diff --git a/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs b/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs index 449f0608df..faf1388319 100644 --- a/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs +++ b/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs @@ -9,6 +9,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Tgstation.Server.Api.Models; using Tgstation.Server.Api.Models.Response; @@ -119,6 +120,16 @@ namespace Tgstation.Server.Host.Components.StaticFiles /// > readonly IFileTransferTicketProvider fileTransferService; + /// + /// The of for . + /// + readonly IOptionsMonitor generalConfigurationOptions; + + /// + /// The of for . + /// + readonly IOptionsMonitor sessionConfigurationOptions; + /// /// The for . /// @@ -129,16 +140,6 @@ namespace Tgstation.Server.Host.Components.StaticFiles /// readonly Models.Instance metadata; - /// - /// The for . - /// - readonly GeneralConfiguration generalConfiguration; - - /// - /// The for . - /// - readonly SessionConfiguration sessionConfiguration; - /// /// The for . Also used as a . /// @@ -166,8 +167,8 @@ namespace Tgstation.Server.Host.Components.StaticFiles /// The value of . /// The value of . /// The value of . - /// The value of . - /// The value of . + /// The value of . + /// The value of . public Configuration( IIOManager ioManager, ISynchronousIOManager synchronousIOManager, @@ -176,10 +177,10 @@ namespace Tgstation.Server.Host.Components.StaticFiles IPostWriteHandler postWriteHandler, IPlatformIdentifier platformIdentifier, IFileTransferTicketProvider fileTransferService, + IOptionsMonitor generalConfigurationOptions, + IOptionsMonitor sessionConfigurationOptions, ILogger logger, - Models.Instance metadata, - GeneralConfiguration generalConfiguration, - SessionConfiguration sessionConfiguration) + Models.Instance metadata) { this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager)); this.synchronousIOManager = synchronousIOManager ?? throw new ArgumentNullException(nameof(synchronousIOManager)); @@ -188,10 +189,10 @@ namespace Tgstation.Server.Host.Components.StaticFiles this.postWriteHandler = postWriteHandler ?? throw new ArgumentNullException(nameof(postWriteHandler)); this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier)); this.fileTransferService = fileTransferService ?? throw new ArgumentNullException(nameof(fileTransferService)); + this.generalConfigurationOptions = generalConfigurationOptions ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); + this.sessionConfigurationOptions = sessionConfigurationOptions ?? throw new ArgumentNullException(nameof(sessionConfigurationOptions)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); this.metadata = metadata ?? throw new ArgumentNullException(nameof(metadata)); - this.generalConfiguration = generalConfiguration ?? throw new ArgumentNullException(nameof(generalConfiguration)); - this.sessionConfiguration = sessionConfiguration ?? throw new ArgumentNullException(nameof(sessionConfiguration)); semaphore = new SemaphoreSlim(1, 1); stoppingCts = new CancellationTokenSource(); @@ -223,7 +224,7 @@ namespace Tgstation.Server.Host.Components.StaticFiles null, CodeModificationsSubdirectory, destination, - generalConfiguration.GetCopyDirectoryTaskThrottle(), + generalConfigurationOptions.CurrentValue.GetCopyDirectoryTaskThrottle(), cancellationToken); await Task.WhenAll(dmeExistsTask, headFileExistsTask, tailFileExistsTask, copyTask.AsTask()); @@ -795,7 +796,8 @@ namespace Tgstation.Server.Host.Components.StaticFiles // always execute in serial using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken, logger)) { - var directories = generalConfiguration.AdditionalEventScriptsDirectories?.ToList() ?? new List(); + var sessionConfiguration = sessionConfigurationOptions.CurrentValue; + var directories = generalConfigurationOptions.CurrentValue.AdditionalEventScriptsDirectories?.ToList() ?? new List(); directories.Add(EventScriptsSubdirectory); var allScripts = new List(); diff --git a/src/Tgstation.Server.Host/Components/Watchdog/PosixWatchdog.cs b/src/Tgstation.Server.Host/Components/Watchdog/PosixWatchdog.cs index b97517d0f7..6b99878466 100644 --- a/src/Tgstation.Server.Host/Components/Watchdog/PosixWatchdog.cs +++ b/src/Tgstation.Server.Host/Components/Watchdog/PosixWatchdog.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Prometheus; @@ -28,9 +29,9 @@ namespace Tgstation.Server.Host.Components.Watchdog sealed class PosixWatchdog : AdvancedWatchdog { /// - /// The for the . + /// The of for the . /// - readonly GeneralConfiguration generalConfiguration; + readonly IOptionsMonitor generalConfigurationOptions; /// /// Initializes a new instance of the class. @@ -48,10 +49,10 @@ namespace Tgstation.Server.Host.Components.Watchdog /// The for the . /// The pointing to the game directory for the .. /// The for the . + /// The value of . /// The for the . /// The for the . /// The for the . - /// The value of . /// The autostart value for the . public PosixWatchdog( IChatManager chat, @@ -67,10 +68,10 @@ namespace Tgstation.Server.Host.Components.Watchdog IMetricFactory metricFactory, IIOManager gameIOManager, IFilesystemLinkFactory linkFactory, + IOptionsMonitor generalConfigurationOptions, ILogger logger, DreamDaemonLaunchParameters initialLaunchParameters, Api.Models.Instance instance, - GeneralConfiguration generalConfiguration, bool autoStart) : base( chat, @@ -91,7 +92,7 @@ namespace Tgstation.Server.Host.Components.Watchdog instance, autoStart) { - this.generalConfiguration = generalConfiguration ?? throw new ArgumentNullException(nameof(generalConfiguration)); + this.generalConfigurationOptions = generalConfigurationOptions ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); } /// @@ -100,6 +101,12 @@ namespace Tgstation.Server.Host.Components.Watchdog /// protected override SwappableDmbProvider CreateSwappableDmbProvider(IDmbProvider dmbProvider) - => new HardLinkDmbProvider(dmbProvider, GameIOManager, LinkFactory, Logger, generalConfiguration, ActiveLaunchParameters.SecurityLevel!.Value); + => new HardLinkDmbProvider( + dmbProvider, + GameIOManager, + LinkFactory, + Logger, + generalConfigurationOptions.CurrentValue, + ActiveLaunchParameters.SecurityLevel!.Value); } } diff --git a/src/Tgstation.Server.Host/Components/Watchdog/PosixWatchdogFactory.cs b/src/Tgstation.Server.Host/Components/Watchdog/PosixWatchdogFactory.cs index 23539d34ac..19f7344089 100644 --- a/src/Tgstation.Server.Host/Components/Watchdog/PosixWatchdogFactory.cs +++ b/src/Tgstation.Server.Host/Components/Watchdog/PosixWatchdogFactory.cs @@ -34,14 +34,14 @@ namespace Tgstation.Server.Host.Components.Watchdog /// The for the . /// The for the . /// The for the . - /// The for for the . + /// The of for the . public PosixWatchdogFactory( IServerControl serverControl, ILoggerFactory loggerFactory, IJobManager jobManager, IAsyncDelayer asyncDelayer, IFilesystemLinkFactory linkFactory, - IOptions generalConfigurationOptions) + IOptionsMonitor generalConfigurationOptions) : base( serverControl, loggerFactory, @@ -79,10 +79,10 @@ namespace Tgstation.Server.Host.Components.Watchdog metricFactory, gameIOManager, LinkFactory, + GeneralConfigurationOptions, LoggerFactory.CreateLogger(), settings, instance, - GeneralConfiguration, settings.AutoStart ?? throw new ArgumentNullException(nameof(settings))); } } diff --git a/src/Tgstation.Server.Host/Components/Watchdog/WatchdogFactory.cs b/src/Tgstation.Server.Host/Components/Watchdog/WatchdogFactory.cs index d052001900..c2fd1c981e 100644 --- a/src/Tgstation.Server.Host/Components/Watchdog/WatchdogFactory.cs +++ b/src/Tgstation.Server.Host/Components/Watchdog/WatchdogFactory.cs @@ -43,9 +43,9 @@ namespace Tgstation.Server.Host.Components.Watchdog protected IAsyncDelayer AsyncDelayer { get; } /// - /// The for the . + /// The of for the . /// - protected GeneralConfiguration GeneralConfiguration { get; } + protected IOptionsMonitor GeneralConfigurationOptions { get; } /// /// Initializes a new instance of the class. @@ -54,19 +54,19 @@ namespace Tgstation.Server.Host.Components.Watchdog /// The value of . /// The value of . /// The value of . - /// The containing the value of . + /// The containing the value of . public WatchdogFactory( IServerControl serverControl, ILoggerFactory loggerFactory, IJobManager jobManager, IAsyncDelayer asyncDelayer, - IOptions generalConfigurationOptions) + IOptionsMonitor generalConfigurationOptions) { ServerControl = serverControl ?? throw new ArgumentNullException(nameof(serverControl)); LoggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); JobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager)); AsyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer)); - GeneralConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); + GeneralConfigurationOptions = generalConfigurationOptions ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); } /// diff --git a/src/Tgstation.Server.Host/Components/Watchdog/WindowsWatchdogFactory.cs b/src/Tgstation.Server.Host/Components/Watchdog/WindowsWatchdogFactory.cs index 5639219021..7f41d39ef7 100644 --- a/src/Tgstation.Server.Host/Components/Watchdog/WindowsWatchdogFactory.cs +++ b/src/Tgstation.Server.Host/Components/Watchdog/WindowsWatchdogFactory.cs @@ -37,14 +37,14 @@ namespace Tgstation.Server.Host.Components.Watchdog /// The for the . /// The for the . /// The value of . - /// The for for the . + /// The for for the . public WindowsWatchdogFactory( IServerControl serverControl, ILoggerFactory loggerFactory, IJobManager jobManager, IAsyncDelayer asyncDelayer, IFilesystemLinkFactory symlinkFactory, - IOptions generalConfigurationOptions) + IOptionsMonitor generalConfigurationOptions) : base( serverControl, loggerFactory, diff --git a/src/Tgstation.Server.Host/Controllers/AdministrationController.cs b/src/Tgstation.Server.Host/Controllers/AdministrationController.cs index b886f40feb..1b9b20f198 100644 --- a/src/Tgstation.Server.Host/Controllers/AdministrationController.cs +++ b/src/Tgstation.Server.Host/Controllers/AdministrationController.cs @@ -21,7 +21,6 @@ using Tgstation.Server.Host.Database; using Tgstation.Server.Host.IO; using Tgstation.Server.Host.Security; using Tgstation.Server.Host.System; -using Tgstation.Server.Host.Transfer; using Tgstation.Server.Host.Utils; namespace Tgstation.Server.Host.Controllers @@ -54,14 +53,9 @@ namespace Tgstation.Server.Host.Controllers readonly IPlatformIdentifier platformIdentifier; /// - /// The for the . + /// The for the . /// - readonly IFileTransferTicketProvider fileTransferService; - - /// - /// The for the . - /// - readonly FileLoggingConfiguration fileLoggingConfiguration; + readonly IOptions fileLoggingConfigurationOptions; /// /// Initializes a new instance of the class. @@ -74,8 +68,7 @@ namespace Tgstation.Server.Host.Controllers /// The value of . /// The value of . /// The value of . - /// The value of . - /// The containing value of . + /// The containing value of . public AdministrationController( IDatabaseContext databaseContext, IAuthenticationContext authenticationContext, @@ -85,7 +78,6 @@ namespace Tgstation.Server.Host.Controllers IAssemblyInformationProvider assemblyInformationProvider, IIOManager ioManager, IPlatformIdentifier platformIdentifier, - IFileTransferTicketProvider fileTransferService, IOptions fileLoggingConfigurationOptions) : base( databaseContext, @@ -98,8 +90,7 @@ namespace Tgstation.Server.Host.Controllers this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider)); this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager)); this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier)); - this.fileTransferService = fileTransferService ?? throw new ArgumentNullException(nameof(fileTransferService)); - fileLoggingConfiguration = fileLoggingConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(fileLoggingConfigurationOptions)); + this.fileLoggingConfigurationOptions = fileLoggingConfigurationOptions ?? throw new ArgumentNullException(nameof(fileLoggingConfigurationOptions)); } /// @@ -185,7 +176,7 @@ namespace Tgstation.Server.Host.Controllers => Paginated( async () => { - var path = fileLoggingConfiguration.GetFullLogDirectory(ioManager, assemblyInformationProvider, platformIdentifier); + var path = fileLoggingConfigurationOptions.Value.GetFullLogDirectory(ioManager, assemblyInformationProvider, platformIdentifier); try { var files = await ioManager.GetFiles(path, cancellationToken); diff --git a/src/Tgstation.Server.Host/Controllers/ApiRootController.cs b/src/Tgstation.Server.Host/Controllers/ApiRootController.cs index d7dd5c092a..148f5bbc7b 100644 --- a/src/Tgstation.Server.Host/Controllers/ApiRootController.cs +++ b/src/Tgstation.Server.Host/Controllers/ApiRootController.cs @@ -65,14 +65,14 @@ namespace Tgstation.Server.Host.Controllers readonly IRestAuthorityInvoker loginAuthority; /// - /// The for the . + /// The of for the . /// - readonly GeneralConfiguration generalConfiguration; + readonly IOptionsSnapshot generalConfigurationOptions; /// - /// The for the . + /// The of for the . /// - readonly SecurityConfiguration securityConfiguration; + readonly IOptionsSnapshot securityConfigurationOptions; /// /// Initializes a new instance of the class. @@ -84,8 +84,8 @@ namespace Tgstation.Server.Host.Controllers /// The value of . /// The value of . /// The value of . - /// The containing the value of . - /// The containing the value of . + /// The value of . + /// The value of . /// The for the . /// The for the . /// The value of . @@ -97,7 +97,7 @@ namespace Tgstation.Server.Host.Controllers IPlatformIdentifier platformIdentifier, ISwarmService swarmService, IServerControl serverControl, - IOptions generalConfigurationOptions, + IOptionsSnapshot generalConfigurationOptions, IOptionsSnapshot securityConfigurationOptions, ILogger logger, IApiHeadersProvider apiHeadersProvider, @@ -114,8 +114,8 @@ namespace Tgstation.Server.Host.Controllers this.oAuthProviders = oAuthProviders ?? throw new ArgumentNullException(nameof(oAuthProviders)); this.swarmService = swarmService ?? throw new ArgumentNullException(nameof(swarmService)); this.serverControl = serverControl ?? throw new ArgumentNullException(nameof(serverControl)); - generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); - securityConfiguration = securityConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(securityConfigurationOptions)); + this.generalConfigurationOptions = generalConfigurationOptions ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); + this.securityConfigurationOptions = securityConfigurationOptions ?? throw new ArgumentNullException(nameof(securityConfigurationOptions)); this.loginAuthority = loginAuthority ?? throw new ArgumentNullException(nameof(loginAuthority)); } @@ -157,20 +157,20 @@ namespace Tgstation.Server.Host.Controllers Version = assemblyInformationProvider.Version, ApiVersion = ApiHeaders.Version, DMApiVersion = DMApiConstants.InteropVersion, - MinimumPasswordLength = generalConfiguration.MinimumPasswordLength, - InstanceLimit = generalConfiguration.InstanceLimit, - UserLimit = generalConfiguration.UserLimit, - UserGroupLimit = generalConfiguration.UserGroupLimit, - ValidInstancePaths = generalConfiguration.ValidInstancePaths, + MinimumPasswordLength = generalConfigurationOptions.Value.MinimumPasswordLength, + InstanceLimit = generalConfigurationOptions.Value.InstanceLimit, + UserLimit = generalConfigurationOptions.Value.UserLimit, + UserGroupLimit = generalConfigurationOptions.Value.UserGroupLimit, + ValidInstancePaths = generalConfigurationOptions.Value.ValidInstancePaths, WindowsHost = platformIdentifier.IsWindows, SwarmServers = swarmService .GetSwarmServers() ?.Select(swarmServerInfo => new SwarmServerResponse(swarmServerInfo)) .ToList(), OAuthProviderInfos = oAuthProviders.ProviderInfos(), - OidcProviderInfos = securityConfiguration.OidcProviderInfos().ToList(), + OidcProviderInfos = securityConfigurationOptions.Value.OidcProviderInfos().ToList(), UpdateInProgress = serverControl.UpdateInProgress, - OidcStrictMode = securityConfiguration.OidcStrictMode, + OidcStrictMode = securityConfigurationOptions.Value.OidcStrictMode, }); } diff --git a/src/Tgstation.Server.Host/Controllers/ChatController.cs b/src/Tgstation.Server.Host/Controllers/ChatController.cs index 1c52faf09f..def3c14f1e 100644 --- a/src/Tgstation.Server.Host/Controllers/ChatController.cs +++ b/src/Tgstation.Server.Host/Controllers/ChatController.cs @@ -160,7 +160,6 @@ namespace Tgstation.Server.Host.Controllers instance.Chat.DeleteConnection(id, cancellationToken), DatabaseContext .ChatBots - .AsQueryable() .Where(x => x.Id == id) .ExecuteDeleteAsync(cancellationToken)); return null; @@ -187,7 +186,6 @@ namespace Tgstation.Server.Host.Controllers new PaginatableResult( DatabaseContext .ChatBots - .AsQueryable() .Where(x => x.InstanceId == Instance.Id) .Include(x => x.Channels) .OrderBy(x => x.Id))), @@ -217,8 +215,8 @@ namespace Tgstation.Server.Host.Controllers [ProducesResponseType(typeof(ErrorMessageResponse), 410)] public async ValueTask GetId(long id, CancellationToken cancellationToken) { - var query = DatabaseContext.ChatBots - .AsQueryable() + var query = DatabaseContext + .ChatBots .Where(x => x.Id == id && x.InstanceId == Instance.Id) .Include(x => x.Channels); @@ -260,7 +258,6 @@ namespace Tgstation.Server.Host.Controllers var query = DatabaseContext .ChatBots - .AsQueryable() .Where(x => x.InstanceId == Instance.Id && x.Id == model.Id) .Include(x => x.Channels); diff --git a/src/Tgstation.Server.Host/Controllers/ControlPanelController.cs b/src/Tgstation.Server.Host/Controllers/ControlPanelController.cs index ec763dd955..2a89fcd33f 100644 --- a/src/Tgstation.Server.Host/Controllers/ControlPanelController.cs +++ b/src/Tgstation.Server.Host/Controllers/ControlPanelController.cs @@ -45,29 +45,29 @@ namespace Tgstation.Server.Host.Controllers /// readonly IWebHostEnvironment hostEnvironment; + /// + /// The for the . + /// + readonly IOptionsSnapshot controlPanelConfigurationOptions; + /// /// The for the . /// readonly ILogger logger; - /// - /// The for the . - /// - readonly ControlPanelConfiguration controlPanelConfiguration; - /// /// Initializes a new instance of the class. /// /// The value of . - /// The containing the value of . + /// The value of . /// The value of . public ControlPanelController( IWebHostEnvironment hostEnvironment, - IOptions controlPanelConfigurationOptions, + IOptionsSnapshot controlPanelConfigurationOptions, ILogger logger) { this.hostEnvironment = hostEnvironment ?? throw new ArgumentNullException(nameof(hostEnvironment)); - controlPanelConfiguration = controlPanelConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(controlPanelConfigurationOptions)); + this.controlPanelConfigurationOptions = controlPanelConfigurationOptions ?? throw new ArgumentNullException(nameof(controlPanelConfigurationOptions)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); } @@ -79,13 +79,13 @@ namespace Tgstation.Server.Host.Controllers [HttpGet] public IActionResult GetChannelJson() { - if (!controlPanelConfiguration.Enable) + if (!controlPanelConfigurationOptions.Value.Enable) { logger.LogDebug("Not serving channel.json as control panel is disabled."); return NotFound(); } - var controlPanelChannel = controlPanelConfiguration.Channel; + var controlPanelChannel = controlPanelConfigurationOptions.Value.Channel; logger.LogTrace("Generating channel.json for channel \"{channel}\"...", controlPanelChannel); if (controlPanelChannel == "local") @@ -102,7 +102,7 @@ namespace Tgstation.Server.Host.Controllers { FormatVersion = 1, Channel = controlPanelChannel, - controlPanelConfiguration.PublicPath, + controlPanelConfigurationOptions.Value.PublicPath, }); } @@ -132,7 +132,7 @@ namespace Tgstation.Server.Host.Controllers [HttpGet] public IActionResult Get([FromRoute] string appRoute) { - if (!controlPanelConfiguration.Enable) + if (!controlPanelConfigurationOptions.Value.Enable) { logger.LogDebug("Not serving static files as control panel is disabled."); return NotFound(); diff --git a/src/Tgstation.Server.Host/Controllers/DreamDaemonController.cs b/src/Tgstation.Server.Host/Controllers/DreamDaemonController.cs index cf4811bc78..4bf09a03ff 100644 --- a/src/Tgstation.Server.Host/Controllers/DreamDaemonController.cs +++ b/src/Tgstation.Server.Host/Controllers/DreamDaemonController.cs @@ -165,7 +165,6 @@ namespace Tgstation.Server.Host.Controllers // alias for changing DD settings var current = await DatabaseContext .Instances - .AsQueryable() .Where(x => x.Id == Instance.Id) .Select(x => x.DreamDaemonSettings) .FirstOrDefaultAsync(cancellationToken); @@ -330,7 +329,6 @@ namespace Tgstation.Server.Host.Controllers { settings = await DatabaseContext .Instances - .AsQueryable() .Where(x => x.Id == Instance.Id) .Select(x => x.DreamDaemonSettings!) .FirstOrDefaultAsync(cancellationToken); diff --git a/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs b/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs index 59e44772f8..4ab9d54f9d 100644 --- a/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs +++ b/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs @@ -81,7 +81,6 @@ namespace Tgstation.Server.Host.Controllers { var dreamMakerSettings = await DatabaseContext .DreamMakerSettings - .AsQueryable() .Where(x => x.InstanceId == Instance.Id) .FirstOrDefaultAsync(cancellationToken); @@ -186,7 +185,6 @@ namespace Tgstation.Server.Host.Controllers var hostModel = await DatabaseContext .DreamMakerSettings - .AsQueryable() .Where(x => x.InstanceId == Instance.Id) .FirstOrDefaultAsync(cancellationToken); if (hostModel == null) @@ -295,7 +293,6 @@ namespace Tgstation.Server.Host.Controllers /// An of with all the inclusions. IQueryable BaseCompileJobsQuery() => DatabaseContext .CompileJobs - .AsQueryable() .Include(x => x.Job!) .ThenInclude(x => x.StartedBy) .Include(x => x.Job!) diff --git a/src/Tgstation.Server.Host/Controllers/InstanceController.cs b/src/Tgstation.Server.Host/Controllers/InstanceController.cs index 633b0d2ecb..3c880c02e0 100644 --- a/src/Tgstation.Server.Host/Controllers/InstanceController.cs +++ b/src/Tgstation.Server.Host/Controllers/InstanceController.cs @@ -67,21 +67,21 @@ namespace Tgstation.Server.Host.Controllers /// readonly IPortAllocator portAllocator; + /// + /// The of for the . + /// + readonly IOptions swarmConfigurationOptions; + + /// + /// The of for the . + /// + readonly IOptionsSnapshot generalConfigurationOptions; + /// /// The for the . /// readonly IPermissionsUpdateNotifyee permissionsUpdateNotifyee; - /// - /// The for the . - /// - readonly GeneralConfiguration generalConfiguration; - - /// - /// The for the . - /// - readonly SwarmConfiguration swarmConfiguration; - /// /// Initializes a new instance of the class. /// @@ -94,8 +94,8 @@ namespace Tgstation.Server.Host.Controllers /// The value of . /// The value of . /// The value of . - /// The containing the value of . - /// The containing the value of . + /// The value of . + /// The value of . /// The for the . public InstanceController( IDatabaseContext databaseContext, @@ -107,8 +107,8 @@ namespace Tgstation.Server.Host.Controllers IPlatformIdentifier platformIdentifier, IPortAllocator portAllocator, IPermissionsUpdateNotifyee permissionsUpdateNotifyee, - IOptions generalConfigurationOptions, IOptions swarmConfigurationOptions, + IOptionsSnapshot generalConfigurationOptions, IApiHeadersProvider apiHeaders) : base( databaseContext, @@ -124,8 +124,8 @@ namespace Tgstation.Server.Host.Controllers this.portAllocator = portAllocator ?? throw new ArgumentNullException(nameof(portAllocator)); this.permissionsUpdateNotifyee = permissionsUpdateNotifyee ?? throw new ArgumentNullException(nameof(permissionsUpdateNotifyee)); - generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); - swarmConfiguration = swarmConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(swarmConfigurationOptions)); + this.swarmConfigurationOptions = swarmConfigurationOptions ?? throw new ArgumentNullException(nameof(swarmConfigurationOptions)); + this.generalConfigurationOptions = generalConfigurationOptions ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); } /// @@ -161,14 +161,14 @@ namespace Tgstation.Server.Host.Controllers // Validate it's not a child of any other instance var instancePaths = await DatabaseContext .Instances - .AsQueryable() - .Where(x => x.SwarmIdentifer == swarmConfiguration.Identifier) + .Where(x => x.SwarmIdentifer == swarmConfigurationOptions.Value.Identifier) .Select(x => new Models.Instance { Path = x.Path, }) .ToListAsync(cancellationToken); + var generalConfiguration = generalConfigurationOptions.Value; if ((instancePaths.Count + 1) >= generalConfiguration.InstanceLimit) return Conflict(new ErrorMessageResponse(ErrorCode.InstanceLimitReached)); @@ -278,8 +278,7 @@ namespace Tgstation.Server.Host.Controllers { var originalModel = await DatabaseContext .Instances - .AsQueryable() - .Where(x => x.Id == id && x.SwarmIdentifer == swarmConfiguration.Identifier) + .Where(x => x.Id == id && x.SwarmIdentifer == swarmConfigurationOptions.Value.Identifier) .FirstOrDefaultAsync(cancellationToken); if (originalModel == default) return this.Gone(); @@ -306,17 +305,14 @@ namespace Tgstation.Server.Host.Controllers // there's a bug where removing the root instance doesn't work sometimes await DatabaseContext .CompileJobs - .AsQueryable() .Where(x => x.Job!.Instance!.Id == id) .ExecuteDeleteAsync(cancellationToken); await DatabaseContext .RevInfoTestMerges - .AsQueryable() .Where(x => x.RevisionInformation.InstanceId == id) .ExecuteDeleteAsync(cancellationToken); await DatabaseContext .RevisionInformations - .AsQueryable() .Where(x => x.InstanceId == id) .ExecuteDeleteAsync(cancellationToken); @@ -361,8 +357,7 @@ namespace Tgstation.Server.Host.Controllers IQueryable InstanceQuery() => DatabaseContext .Instances - .AsQueryable() - .Where(x => x.Id == model.Id && x.SwarmIdentifer == swarmConfiguration.Identifier); + .Where(x => x.Id == model.Id && x.SwarmIdentifer == swarmConfigurationOptions.Value.Identifier); var moveJob = await InstanceQuery() .SelectMany(x => x.Jobs) @@ -460,7 +455,6 @@ namespace Tgstation.Server.Host.Controllers { var countOfExistingChatBots = await DatabaseContext .ChatBots - .AsQueryable() .Where(x => x.InstanceId == originalModel.Id) .CountAsync(cancellationToken); @@ -585,8 +579,7 @@ namespace Tgstation.Server.Host.Controllers { var query = DatabaseContext .Instances - .AsQueryable() - .Where(x => x.SwarmIdentifer == swarmConfiguration.Identifier); + .Where(x => x.SwarmIdentifer == swarmConfigurationOptions.Value.Identifier); if (!AuthenticationContext.PermissionSet.InstanceManagerRights!.Value.HasFlag(InstanceManagerRights.List)) query = query .Where(x => x.InstancePermissionSets.Any(y => y.PermissionSetId == AuthenticationContext.PermissionSet.Id)) @@ -651,8 +644,7 @@ namespace Tgstation.Server.Host.Controllers { var query = DatabaseContext .Instances - .AsQueryable() - .Where(x => x.Id == id && x.SwarmIdentifer == swarmConfiguration.Identifier); + .Where(x => x.Id == id && x.SwarmIdentifer == swarmConfigurationOptions.Value.Identifier); if (cantList) query = query.Include(x => x.InstancePermissionSets); @@ -706,8 +698,7 @@ namespace Tgstation.Server.Host.Controllers { IQueryable BaseQuery() => DatabaseContext .Instances - .AsQueryable() - .Where(x => x.Id == id && x.SwarmIdentifer == swarmConfiguration.Identifier); + .Where(x => x.Id == id && x.SwarmIdentifer == swarmConfigurationOptions.Value.Identifier); // ensure the current user has write privilege on the instance var usersInstancePermissionSet = await BaseQuery() @@ -779,7 +770,7 @@ namespace Tgstation.Server.Host.Controllers StartupTimeout = 60, HealthCheckSeconds = 60, DumpOnHealthCheckRestart = false, - TopicRequestTimeout = generalConfiguration.ByondTopicTimeout, + TopicRequestTimeout = generalConfigurationOptions.Value.ByondTopicTimeout, AdditionalParameters = String.Empty, StartProfiler = false, LogOutput = false, @@ -818,7 +809,7 @@ namespace Tgstation.Server.Host.Controllers { InstanceAdminPermissionSet(null), }, - SwarmIdentifer = swarmConfiguration.Identifier, + SwarmIdentifer = swarmConfigurationOptions.Value.Identifier, }; } @@ -871,7 +862,6 @@ namespace Tgstation.Server.Host.Controllers { instanceResponse.Accessible = await DatabaseContext .InstancePermissionSets - .AsQueryable() .Where(x => x.InstanceId == instanceResponse.Id && x.PermissionSetId == AuthenticationContext.PermissionSet.Id) .AnyAsync(cancellationToken); } diff --git a/src/Tgstation.Server.Host/Controllers/InstancePermissionSetController.cs b/src/Tgstation.Server.Host/Controllers/InstancePermissionSetController.cs index 01f51bdc0c..6d6b99339c 100644 --- a/src/Tgstation.Server.Host/Controllers/InstancePermissionSetController.cs +++ b/src/Tgstation.Server.Host/Controllers/InstancePermissionSetController.cs @@ -78,7 +78,6 @@ namespace Tgstation.Server.Host.Controllers var existingPermissionSet = await DatabaseContext .PermissionSets - .AsQueryable() .Where(x => x.Id == model.PermissionSetId) .Select(x => new Models.PermissionSet { @@ -94,7 +93,6 @@ namespace Tgstation.Server.Host.Controllers { var userCanonicalName = await DatabaseContext .Users - .AsQueryable() .Where(x => x.Id == existingPermissionSet.UserId.Value) .Select(x => x.CanonicalName) .FirstAsync(cancellationToken); @@ -146,7 +144,6 @@ namespace Tgstation.Server.Host.Controllers var originalPermissionSet = await DatabaseContext .Instances - .AsQueryable() .Where(x => x.Id == Instance.Id) .SelectMany(x => x.InstancePermissionSets) .Where(x => x.PermissionSetId == model.PermissionSetId) @@ -201,7 +198,6 @@ namespace Tgstation.Server.Host.Controllers new PaginatableResult( DatabaseContext .Instances - .AsQueryable() .Where(x => x.Id == Instance.Id) .SelectMany(x => x.InstancePermissionSets) .OrderBy(x => x.PermissionSetId))), @@ -227,7 +223,6 @@ namespace Tgstation.Server.Host.Controllers // this functions as userId var permissionSet = await DatabaseContext .Instances - .AsQueryable() .Where(x => x.Id == Instance.Id) .SelectMany(x => x.InstancePermissionSets) .Where(x => x.PermissionSetId == id) @@ -253,7 +248,6 @@ namespace Tgstation.Server.Host.Controllers { var numDeleted = await DatabaseContext .Instances - .AsQueryable() .Where(x => x.Id == Instance.Id) .SelectMany(x => x.InstancePermissionSets) .Where(x => x.PermissionSetId == id) diff --git a/src/Tgstation.Server.Host/Controllers/JobController.cs b/src/Tgstation.Server.Host/Controllers/JobController.cs index 2cfb962891..5ba72b71c6 100644 --- a/src/Tgstation.Server.Host/Controllers/JobController.cs +++ b/src/Tgstation.Server.Host/Controllers/JobController.cs @@ -75,7 +75,6 @@ namespace Tgstation.Server.Host.Controllers new PaginatableResult( DatabaseContext .Jobs - .AsQueryable() .Include(x => x.StartedBy) .Include(x => x.CancelledBy) .Include(x => x.Instance) @@ -103,7 +102,6 @@ namespace Tgstation.Server.Host.Controllers new PaginatableResult( DatabaseContext .Jobs - .AsQueryable() .Include(x => x.StartedBy) .Include(x => x.CancelledBy) .Include(x => x.Instance) @@ -132,7 +130,6 @@ namespace Tgstation.Server.Host.Controllers // don't care if an instance post or not at this point var job = await DatabaseContext .Jobs - .AsQueryable() .Include(x => x.StartedBy) .Include(x => x.Instance) .Where(x => x.Id == id && x.Instance!.Id == Instance.Id) @@ -166,7 +163,6 @@ namespace Tgstation.Server.Host.Controllers { var job = await DatabaseContext .Jobs - .AsQueryable() .Where(x => x.Id == id && x.Instance!.Id == Instance.Id) .Include(x => x.StartedBy) .Include(x => x.CancelledBy) diff --git a/src/Tgstation.Server.Host/Controllers/RepositoryController.cs b/src/Tgstation.Server.Host/Controllers/RepositoryController.cs index e99a801607..f64440c919 100644 --- a/src/Tgstation.Server.Host/Controllers/RepositoryController.cs +++ b/src/Tgstation.Server.Host/Controllers/RepositoryController.cs @@ -122,7 +122,6 @@ namespace Tgstation.Server.Host.Controllers var currentModel = await DatabaseContext .RepositorySettings - .AsQueryable() .Where(x => x.InstanceId == Instance.Id) .FirstOrDefaultAsync(cancellationToken); @@ -225,7 +224,6 @@ namespace Tgstation.Server.Host.Controllers { var currentModel = await DatabaseContext .RepositorySettings - .AsQueryable() .Where(x => x.InstanceId == Instance.Id) .FirstOrDefaultAsync(cancellationToken); @@ -264,7 +262,6 @@ namespace Tgstation.Server.Host.Controllers { var currentModel = await DatabaseContext .RepositorySettings - .AsQueryable() .Where(x => x.InstanceId == Instance.Id) .FirstOrDefaultAsync(cancellationToken); @@ -302,7 +299,6 @@ namespace Tgstation.Server.Host.Controllers { var currentModel = await DatabaseContext .RepositorySettings - .AsQueryable() .Where(x => x.InstanceId == Instance.Id) .FirstOrDefaultAsync(cancellationToken); @@ -388,7 +384,6 @@ namespace Tgstation.Server.Host.Controllers var currentModel = await DatabaseContext .RepositorySettings - .AsQueryable() .Where(x => x.InstanceId == Instance.Id) .FirstOrDefaultAsync(cancellationToken); diff --git a/src/Tgstation.Server.Host/Controllers/RootController.cs b/src/Tgstation.Server.Host/Controllers/RootController.cs index fcf2bd239b..ccb9bc7ced 100644 --- a/src/Tgstation.Server.Host/Controllers/RootController.cs +++ b/src/Tgstation.Server.Host/Controllers/RootController.cs @@ -48,26 +48,26 @@ namespace Tgstation.Server.Host.Controllers /// readonly IWebHostEnvironment hostEnvironment; + /// + /// The of for the . + /// + readonly IOptions generalConfigurationOptions; + + /// + /// The of for the . + /// + readonly IOptions controlPanelConfigurationOptions; + + /// + /// The of for the . + /// + readonly IOptions internalConfigurationOptions; + /// /// The for the . /// readonly ILogger logger; - /// - /// The for the . - /// - readonly GeneralConfiguration generalConfiguration; - - /// - /// The for the . - /// - readonly ControlPanelConfiguration controlPanelConfiguration; - - /// - /// The for the . - /// - readonly InternalConfiguration internalConfiguration; - /// /// Gets a giving the and action names for a given . /// @@ -96,9 +96,9 @@ namespace Tgstation.Server.Host.Controllers /// The value of . /// The value of . /// The value of . - /// The containing the value of . - /// The containing the value of . - /// The containing the value of . + /// The containing the value of . + /// The containing the value of . + /// The containing the value of . public RootController( IAssemblyInformationProvider assemblyInformationProvider, IPlatformIdentifier platformIdentifier, @@ -106,15 +106,15 @@ namespace Tgstation.Server.Host.Controllers ILogger logger, IOptions generalConfigurationOptions, IOptions controlPanelConfigurationOptions, - IOptionsSnapshot internalConfigurationOptions) + IOptions internalConfigurationOptions) { this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider)); this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier)); this.hostEnvironment = hostEnvironment ?? throw new ArgumentNullException(nameof(hostEnvironment)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); - generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); - controlPanelConfiguration = controlPanelConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(controlPanelConfigurationOptions)); - internalConfiguration = internalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(internalConfigurationOptions)); + this.generalConfigurationOptions = generalConfigurationOptions ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); + this.controlPanelConfigurationOptions = controlPanelConfigurationOptions ?? throw new ArgumentNullException(nameof(controlPanelConfigurationOptions)); + this.internalConfigurationOptions = internalConfigurationOptions ?? throw new ArgumentNullException(nameof(internalConfigurationOptions)); } /// @@ -125,8 +125,8 @@ namespace Tgstation.Server.Host.Controllers [AllowAnonymous] public IActionResult Index() { - var panelEnabled = controlPanelConfiguration.Enable; - var apiDocsEnabled = generalConfiguration.HostApiDocumentation; + var panelEnabled = controlPanelConfigurationOptions.Value.Enable; + var apiDocsEnabled = generalConfigurationOptions.Value.HostApiDocumentation; var controlPanelRoute = $"{ControlPanelController.ControlPanelRoute.TrimStart('/')}/"; if (panelEnabled && !apiDocsEnabled) @@ -143,7 +143,7 @@ namespace Tgstation.Server.Host.Controllers if (apiDocsEnabled) { - if (internalConfiguration.EnableGraphQL) + if (internalConfigurationOptions.Value.EnableGraphQL) links.Add("GraphQL API Documentation", Routes.GraphQL); links.Add("REST API Documentation", SwaggerConfiguration.DocumentationSiteRouteExtension); diff --git a/src/Tgstation.Server.Host/Core/Application.cs b/src/Tgstation.Server.Host/Core/Application.cs index 3fab7f503b..dfa4a75526 100644 --- a/src/Tgstation.Server.Host/Core/Application.cs +++ b/src/Tgstation.Server.Host/Core/Application.cs @@ -372,7 +372,7 @@ namespace Tgstation.Server.Host.Core services.AddSingleton(); // configure other security services - services.AddSingleton(); + services.AddScoped(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); @@ -541,12 +541,12 @@ namespace Tgstation.Server.Host.Core ArgumentNullException.ThrowIfNull(assemblyInformationProvider); - var controlPanelConfiguration = controlPanelConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(controlPanelConfigurationOptions)); - var generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); - var databaseConfiguration = databaseConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(databaseConfigurationOptions)); - var swarmConfiguration = swarmConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(swarmConfigurationOptions)); - var internalConfiguration = internalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(internalConfigurationOptions)); - var sessionConfiguration = sessionConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(sessionConfigurationOptions)); + var controlPanelConfiguration = (controlPanelConfigurationOptions ?? throw new ArgumentNullException(nameof(controlPanelConfigurationOptions))).Value; + var generalConfiguration = (generalConfigurationOptions ?? throw new ArgumentNullException(nameof(generalConfigurationOptions))).Value; + var databaseConfiguration = (databaseConfigurationOptions ?? throw new ArgumentNullException(nameof(databaseConfigurationOptions))).Value; + var swarmConfiguration = (swarmConfigurationOptions ?? throw new ArgumentNullException(nameof(swarmConfigurationOptions))).Value; + var internalConfiguration = (internalConfigurationOptions ?? throw new ArgumentNullException(nameof(internalConfigurationOptions))).Value; + var sessionConfiguration = (sessionConfigurationOptions ?? throw new ArgumentNullException(nameof(sessionConfigurationOptions))).Value; ArgumentNullException.ThrowIfNull(logger); diff --git a/src/Tgstation.Server.Host/Core/CommandPipeManager.cs b/src/Tgstation.Server.Host/Core/CommandPipeManager.cs index 6a5c6325c6..f3534c9bea 100644 --- a/src/Tgstation.Server.Host/Core/CommandPipeManager.cs +++ b/src/Tgstation.Server.Host/Core/CommandPipeManager.cs @@ -30,22 +30,22 @@ namespace Tgstation.Server.Host.Core /// readonly IInstanceManager instanceManager; + /// + /// The of for the . + /// + readonly IOptions internalConfigurationOptions; + /// /// The for the . /// readonly ILogger logger; - /// - /// The for the . - /// - readonly InternalConfiguration internalConfiguration; - /// /// Initializes a new instance of the class. /// /// The value of . /// The value of . - /// The containing the value of . + /// The containing the value of . /// The value of . public CommandPipeManager( IServerControl serverControl, @@ -55,7 +55,7 @@ namespace Tgstation.Server.Host.Core { this.serverControl = serverControl ?? throw new ArgumentNullException(nameof(serverControl)); this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager)); - internalConfiguration = internalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(internalConfigurationOptions)); + this.internalConfigurationOptions = internalConfigurationOptions ?? throw new ArgumentNullException(nameof(internalConfigurationOptions)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); } @@ -65,7 +65,7 @@ namespace Tgstation.Server.Host.Core logger.LogTrace("Starting..."); // grab both pipes asap so we can close them on error - var commandPipe = internalConfiguration.CommandPipe; + var commandPipe = internalConfigurationOptions.Value.CommandPipe; var supportsPipeCommands = !String.IsNullOrWhiteSpace(commandPipe); await using var commandPipeClient = supportsPipeCommands ? new AnonymousPipeClientStream( @@ -76,7 +76,7 @@ namespace Tgstation.Server.Host.Core if (!supportsPipeCommands) logger.LogDebug("No command pipe name specified in configuration"); - var readyPipe = internalConfiguration.ReadyPipe; + var readyPipe = internalConfigurationOptions.Value.ReadyPipe; var supportsReadyNotification = !String.IsNullOrWhiteSpace(readyPipe); if (supportsReadyNotification) { diff --git a/src/Tgstation.Server.Host/Core/ServerUpdater.cs b/src/Tgstation.Server.Host/Core/ServerUpdater.cs index 1170537a12..2caee4d944 100644 --- a/src/Tgstation.Server.Host/Core/ServerUpdater.cs +++ b/src/Tgstation.Server.Host/Core/ServerUpdater.cs @@ -36,21 +36,21 @@ namespace Tgstation.Server.Host.Core /// readonly IServerControl serverControl; + /// + /// The of for the . + /// + readonly IOptionsMonitor generalConfigurationOptions; + + /// + /// The of for the . + /// + readonly IOptionsMonitor updatesConfigurationOptions; + /// /// The for the . /// readonly ILogger logger; - /// - /// The for the . - /// - readonly GeneralConfiguration generalConfiguration; - - /// - /// The for the . - /// - readonly UpdatesConfiguration updatesConfiguration; - /// /// Lock used when initiating an update. /// @@ -69,24 +69,24 @@ namespace Tgstation.Server.Host.Core /// The value of . /// The value of . /// The value of . - /// The containing the value of . - /// The containing the value of . + /// The value of . + /// The value of . public ServerUpdater( IGitHubServiceFactory gitHubServiceFactory, IIOManager ioManager, IFileDownloader fileDownloader, IServerControl serverControl, ILogger logger, - IOptions generalConfigurationOptions, - IOptions updatesConfigurationOptions) + IOptionsMonitor generalConfigurationOptions, + IOptionsMonitor updatesConfigurationOptions) { this.gitHubServiceFactory = gitHubServiceFactory ?? throw new ArgumentNullException(nameof(gitHubServiceFactory)); this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager)); this.fileDownloader = fileDownloader ?? throw new ArgumentNullException(nameof(fileDownloader)); this.serverControl = serverControl ?? throw new ArgumentNullException(nameof(serverControl)); + this.generalConfigurationOptions = generalConfigurationOptions ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); + this.updatesConfigurationOptions = updatesConfigurationOptions ?? throw new ArgumentNullException(nameof(updatesConfigurationOptions)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); - generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); - updatesConfiguration = updatesConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(updatesConfigurationOptions)); updateInitiationLock = new object(); } @@ -290,6 +290,9 @@ namespace Tgstation.Server.Host.Core var gitHubService = await gitHubServiceFactory.CreateService(cancellationToken); var releases = await gitHubService.GetTgsReleases(cancellationToken); + + var updatesConfiguration = updatesConfigurationOptions.CurrentValue; + var generalConfiguration = generalConfigurationOptions.CurrentValue; foreach (var kvp in releases) { var version = kvp.Key; diff --git a/src/Tgstation.Server.Host/Database/DatabaseCollection.cs b/src/Tgstation.Server.Host/Database/DatabaseCollection.cs index b2dafa719d..94d5ef90e8 100644 --- a/src/Tgstation.Server.Host/Database/DatabaseCollection.cs +++ b/src/Tgstation.Server.Host/Database/DatabaseCollection.cs @@ -3,7 +3,6 @@ using System.Collections; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using System.Threading; using Microsoft.EntityFrameworkCore; @@ -48,9 +47,6 @@ namespace Tgstation.Server.Host.Database /// public void Attach(TModel model) => dbSet.Attach(model); - /// - public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) => dbSet.AsAsyncEnumerable().GetAsyncEnumerator(cancellationToken); - /// public IEnumerator GetEnumerator() => dbSet.AsQueryable().GetEnumerator(); diff --git a/src/Tgstation.Server.Host/Database/DatabaseSeeder.cs b/src/Tgstation.Server.Host/Database/DatabaseSeeder.cs index 4eaf4e21b9..03d89a64eb 100644 --- a/src/Tgstation.Server.Host/Database/DatabaseSeeder.cs +++ b/src/Tgstation.Server.Host/Database/DatabaseSeeder.cs @@ -216,7 +216,6 @@ namespace Tgstation.Server.Host.Database { var tgsUser = await databaseContext .Users - .AsQueryable() .Where(x => x.CanonicalName == User.CanonicalizeName(User.TgsSystemUserName)) .FirstOrDefaultAsync(cancellationToken); @@ -232,7 +231,6 @@ namespace Tgstation.Server.Host.Database // normalize backslashes to forward slashes var allInstances = await databaseContext .Instances - .AsQueryable() .Where(instance => instance.SwarmIdentifer == swarmConfiguration.Identifier) .ToListAsync(cancellationToken); foreach (var instance in allInstances) @@ -242,7 +240,6 @@ namespace Tgstation.Server.Host.Database { var ids = await databaseContext .DreamDaemonSettings - .AsQueryable() .Where(x => x.TopicRequestTimeout == 0) .Select(x => x.Id) .ToListAsync(cancellationToken); @@ -311,7 +308,6 @@ namespace Tgstation.Server.Host.Database { var admin = await databaseContext .Users - .AsQueryable() .Where(x => x.CanonicalName == User.CanonicalizeName(DefaultCredentials.AdminUserName)) .Include(x => x.CreatedBy) .Include(x => x.PermissionSet) diff --git a/src/Tgstation.Server.Host/Database/IDatabaseCollection.cs b/src/Tgstation.Server.Host/Database/IDatabaseCollection.cs index a9e1fe0e03..52ca1796af 100644 --- a/src/Tgstation.Server.Host/Database/IDatabaseCollection.cs +++ b/src/Tgstation.Server.Host/Database/IDatabaseCollection.cs @@ -7,7 +7,7 @@ namespace Tgstation.Server.Host.Database /// Represents a database table. /// /// The type of model. - public interface IDatabaseCollection : IQueryable, IAsyncEnumerable + public interface IDatabaseCollection : IQueryable { /// /// An of s prioritizing in the working set. diff --git a/src/Tgstation.Server.Host/Extensions/DatabaseCollectionExtensions.cs b/src/Tgstation.Server.Host/Extensions/DatabaseCollectionExtensions.cs index ea50a7af17..856b74a9f0 100644 --- a/src/Tgstation.Server.Host/Extensions/DatabaseCollectionExtensions.cs +++ b/src/Tgstation.Server.Host/Extensions/DatabaseCollectionExtensions.cs @@ -33,7 +33,6 @@ namespace Tgstation.Server.Host.Extensions ArgumentNullException.ThrowIfNull(selector); return databaseCollection - .AsQueryable() .Where(x => x.CanonicalName == User.CanonicalizeName(User.TgsSystemUserName)) .Select(selector) .FirstAsync(cancellationToken); diff --git a/src/Tgstation.Server.Host/GraphQL/Types/UsersRepository.cs b/src/Tgstation.Server.Host/GraphQL/Types/UsersRepository.cs index 1cf53baabc..d735684565 100644 --- a/src/Tgstation.Server.Host/GraphQL/Types/UsersRepository.cs +++ b/src/Tgstation.Server.Host/GraphQL/Types/UsersRepository.cs @@ -26,10 +26,10 @@ namespace Tgstation.Server.Host.GraphQL.Types /// /// If only OIDC logins and registration is allowed. /// - /// The containing the . + /// The containing the . /// if OIDC strict mode is enabled, otherwise. public bool OidcStrictMode( - [Service] IOptions securityConfigurationOptions) + [Service] IOptionsSnapshot securityConfigurationOptions) { ArgumentNullException.ThrowIfNull(securityConfigurationOptions); return securityConfigurationOptions.Value.OidcStrictMode; diff --git a/src/Tgstation.Server.Host/Jobs/JobService.cs b/src/Tgstation.Server.Host/Jobs/JobService.cs index c36b5ca825..4c1f5e2c90 100644 --- a/src/Tgstation.Server.Host/Jobs/JobService.cs +++ b/src/Tgstation.Server.Host/Jobs/JobService.cs @@ -213,7 +213,6 @@ namespace Tgstation.Server.Host.Jobs // mark all jobs as cancelled var badJobIds = await databaseContext .Jobs - .AsQueryable() .Where(y => !y.StoppedAt.HasValue) .Select(y => y.Id!.Value) .ToListAsync(cancellationToken); @@ -535,7 +534,6 @@ namespace Tgstation.Server.Host.Jobs // DCT: Cancellation token is for job, operation should always run var finalJob = await databaseContext .Jobs - .AsQueryable() .Include(x => x.Instance) .Include(x => x.StartedBy) .Include(x => x.CancelledBy) diff --git a/src/Tgstation.Server.Host/Jobs/JobsHubGroupMapper.cs b/src/Tgstation.Server.Host/Jobs/JobsHubGroupMapper.cs index 10ddbd950f..2cd00aebf8 100644 --- a/src/Tgstation.Server.Host/Jobs/JobsHubGroupMapper.cs +++ b/src/Tgstation.Server.Host/Jobs/JobsHubGroupMapper.cs @@ -128,7 +128,6 @@ namespace Tgstation.Server.Host.Jobs async databaseContext => permedInstanceIds = await databaseContext .InstancePermissionSets - .AsQueryable() .Where(ips => ips.PermissionSetId == pid) .Select(ips => ips.InstanceId) .ToListAsync(cancellationToken)); @@ -164,7 +163,6 @@ namespace Tgstation.Server.Host.Jobs .ToListAsync(cancellationToken); var permissionSetAccessibleInstanceIds = await databaseContext .InstancePermissionSets - .AsQueryable() .Where(ips => ips.PermissionSetId == permissionSetId) .Select(ips => ips.InstanceId) .ToListAsync(cancellationToken); diff --git a/src/Tgstation.Server.Host/Security/AuthenticationContextFactory.cs b/src/Tgstation.Server.Host/Security/AuthenticationContextFactory.cs index ed9651f2a7..947baa3120 100644 --- a/src/Tgstation.Server.Host/Security/AuthenticationContextFactory.cs +++ b/src/Tgstation.Server.Host/Security/AuthenticationContextFactory.cs @@ -45,21 +45,21 @@ namespace Tgstation.Server.Host.Security /// readonly IIdentityCache identityCache; + /// + /// The of for the . + /// + readonly IOptions swarmConfigurationOptions; + + /// + /// The of for the . + /// + readonly IOptionsSnapshot securityConfigurationOptions; + /// /// The for the . /// readonly ILogger logger; - /// - /// The for the . - /// - readonly SwarmConfiguration swarmConfiguration; - - /// - /// The for the . - /// - readonly SecurityConfiguration securityConfiguration; - /// /// Backing field for . /// @@ -81,15 +81,15 @@ namespace Tgstation.Server.Host.Security /// The value of . /// The value of . /// The containing the value of . - /// The containing the value of . - /// The containing the value of . + /// The value of . + /// The value of . /// The value of . public AuthenticationContextFactory( IDatabaseContext databaseContext, IIdentityCache identityCache, IApiHeadersProvider apiHeadersProvider, IOptions swarmConfigurationOptions, - IOptions securityConfigurationOptions, + IOptionsSnapshot securityConfigurationOptions, ILogger logger) { this.databaseContext = databaseContext ?? throw new ArgumentNullException(nameof(databaseContext)); @@ -97,8 +97,8 @@ namespace Tgstation.Server.Host.Security ArgumentNullException.ThrowIfNull(apiHeadersProvider); apiHeaders = apiHeadersProvider.ApiHeaders; - swarmConfiguration = swarmConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(swarmConfigurationOptions)); - securityConfiguration = securityConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(securityConfigurationOptions)); + this.swarmConfigurationOptions = swarmConfigurationOptions ?? throw new ArgumentNullException(nameof(swarmConfigurationOptions)); + this.securityConfigurationOptions = securityConfigurationOptions ?? throw new ArgumentNullException(nameof(securityConfigurationOptions)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); @@ -129,7 +129,6 @@ namespace Tgstation.Server.Host.Security var user = await databaseContext .Users - .AsQueryable() .Where(x => x.Id == userId) .Include(x => x.CreatedBy) .Include(x => x.PermissionSet) @@ -164,9 +163,9 @@ namespace Tgstation.Server.Host.Security var instanceId = apiHeaders?.InstanceId; if (instanceId.HasValue) { - instancePermissionSet = await databaseContext.InstancePermissionSets - .AsQueryable() - .Where(x => x.PermissionSetId == userPermissionSet!.Id && x.InstanceId == instanceId && x.Instance!.SwarmIdentifer == swarmConfiguration.Identifier) + instancePermissionSet = await databaseContext + .InstancePermissionSets + .Where(x => x.PermissionSetId == userPermissionSet!.Id && x.InstanceId == instanceId && x.Instance!.SwarmIdentifer == swarmConfigurationOptions.Value.Identifier) .Include(x => x.Instance) .FirstOrDefaultAsync(cancellationToken); @@ -208,7 +207,6 @@ namespace Tgstation.Server.Host.Security var deprefixedScheme = scheme.Substring(OpenIDConnectAuthenticationSchemePrefix.Length); var connection = await databaseContext .OidcConnections - .AsQueryable() .Where(oidcConnection => oidcConnection.ExternalUserId == userId && oidcConnection.SchemeKey == deprefixedScheme) .Include(oidcConnection => oidcConnection.User) .ThenInclude(user => user!.Group) @@ -216,7 +214,7 @@ namespace Tgstation.Server.Host.Security .FirstOrDefaultAsync(cancellationToken); User user; - if (!securityConfiguration.OidcStrictMode) + if (!securityConfigurationOptions.Value.OidcStrictMode) { if (connection == default) { @@ -243,7 +241,6 @@ namespace Tgstation.Server.Host.Security UserGroup? group = groupId.HasValue ? await databaseContext .Groups - .AsQueryable() .Where(group => group.Id == groupId.Value) .Include(group => group.PermissionSet) .FirstOrDefaultAsync(cancellationToken) diff --git a/src/Tgstation.Server.Host/Security/AuthorizationHandler.cs b/src/Tgstation.Server.Host/Security/AuthorizationHandler.cs index ed76938c29..95774ee803 100644 --- a/src/Tgstation.Server.Host/Security/AuthorizationHandler.cs +++ b/src/Tgstation.Server.Host/Security/AuthorizationHandler.cs @@ -106,7 +106,6 @@ namespace Tgstation.Server.Host.Security { var sessionData = await databaseContext .Users - .AsQueryable() .Where(user => user.Id == userId) .Select(user => new { @@ -151,8 +150,7 @@ namespace Tgstation.Server.Host.Security return databaseContextFactory.UseContext(async databaseContext => { var queryableUsers = databaseContext - .Users - .AsQueryable(); + .Users; var matchingUniquePermissionSetIds = queryableUsers .Where(user => user.Id == userId && user.PermissionSet != null) @@ -170,7 +168,6 @@ namespace Tgstation.Server.Host.Security permissionSet = await databaseContext .InstancePermissionSets - .AsQueryable() .Where(ips => ips.InstanceId == instanceId && (matchingUniquePermissionSetIds.Contains(ips.PermissionSetId) || matchingGroupPermissionSetIds.Contains(ips.PermissionSetId))) .TagWith("rights_authorization_handler_instance_permission_set") @@ -179,7 +176,6 @@ namespace Tgstation.Server.Host.Security else permissionSet = await databaseContext .PermissionSets - .AsQueryable() .Where(permissionSet => matchingUniquePermissionSetIds.Contains(permissionSet.Id) || matchingGroupPermissionSetIds.Contains(permissionSet.Id)) .TagWith("rights_authorization_handler_permission_set") .FirstOrDefaultAsync(cancellationToken); diff --git a/src/Tgstation.Server.Host/Security/OAuth/OAuthProviders.cs b/src/Tgstation.Server.Host/Security/OAuth/OAuthProviders.cs index f514094e01..6233b79157 100644 --- a/src/Tgstation.Server.Host/Security/OAuth/OAuthProviders.cs +++ b/src/Tgstation.Server.Host/Security/OAuth/OAuthProviders.cs @@ -31,11 +31,12 @@ namespace Tgstation.Server.Host.Security.OAuth IGitHubServiceFactory gitHubServiceFactory, IHttpClientFactory httpClientFactory, ILoggerFactory loggerFactory, - IOptions securityConfigurationOptions) + IOptionsSnapshot securityConfigurationOptions) { ArgumentNullException.ThrowIfNull(loggerFactory); + ArgumentNullException.ThrowIfNull(securityConfigurationOptions); - var securityConfiguration = securityConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(securityConfigurationOptions)); + var securityConfiguration = securityConfigurationOptions.Value; var validatorsBuilder = new List(); validators = validatorsBuilder; @@ -66,9 +67,7 @@ namespace Tgstation.Server.Host.Security.OAuth loggerFactory.CreateLogger(), keyCloakConfig)); -#pragma warning disable CS0618 // Type or member is obsolete if (securityConfiguration.OAuth.TryGetValue(OAuthProvider.InvisionCommunity, out var invisionConfig)) -#pragma warning restore CS0618 // Type or member is obsolete validatorsBuilder.Add( new InvisionCommunityOAuthValidator( httpClientFactory, diff --git a/src/Tgstation.Server.Host/Security/TokenFactory.cs b/src/Tgstation.Server.Host/Security/TokenFactory.cs index 6081aeb42f..9e2b18e668 100644 --- a/src/Tgstation.Server.Host/Security/TokenFactory.cs +++ b/src/Tgstation.Server.Host/Security/TokenFactory.cs @@ -39,9 +39,9 @@ namespace Tgstation.Server.Host.Security } /// - /// The for the . + /// The of for the . /// - readonly SecurityConfiguration securityConfiguration; + readonly IOptions securityConfigurationOptions; /// /// The used to generate s. @@ -63,7 +63,7 @@ namespace Tgstation.Server.Host.Security /// /// The used for generating the . /// The used to generate the issuer name. - /// The containing the value of . + /// The value of . public TokenFactory( ICryptographySuite cryptographySuite, IAssemblyInformationProvider assemblyInformationProvider, @@ -72,11 +72,11 @@ namespace Tgstation.Server.Host.Security ArgumentNullException.ThrowIfNull(cryptographySuite); ArgumentNullException.ThrowIfNull(assemblyInformationProvider); - securityConfiguration = securityConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(securityConfigurationOptions)); + this.securityConfigurationOptions = securityConfigurationOptions ?? throw new ArgumentNullException(nameof(securityConfigurationOptions)); - SigningKeyBytes = String.IsNullOrWhiteSpace(securityConfiguration.CustomTokenSigningKeyBase64) - ? cryptographySuite.GetSecureBytes(securityConfiguration.TokenSigningKeyByteCount) - : Convert.FromBase64String(securityConfiguration.CustomTokenSigningKeyBase64); + SigningKeyBytes = string.IsNullOrWhiteSpace(securityConfigurationOptions.Value.CustomTokenSigningKeyBase64) + ? cryptographySuite.GetSecureBytes(securityConfigurationOptions.Value.TokenSigningKeyByteCount) + : Convert.FromBase64String(securityConfigurationOptions.Value.CustomTokenSigningKeyBase64); ValidationParameters = new TokenValidationParameters { @@ -90,7 +90,7 @@ namespace Tgstation.Server.Host.Security ValidateAudience = true, ValidAudience = typeof(TokenResponse).Assembly.GetName().Name, - ClockSkew = TimeSpan.FromMinutes(securityConfiguration.TokenClockSkewMinutes), + ClockSkew = TimeSpan.FromMinutes(securityConfigurationOptions.Value.TokenClockSkewMinutes), RequireSignedTokens = true, @@ -122,8 +122,8 @@ namespace Tgstation.Server.Host.Security notBefore = now; var expiry = now.AddMinutes(serviceLogin - ? securityConfiguration.OAuthTokenExpiryMinutes - : securityConfiguration.TokenExpiryMinutes); + ? securityConfigurationOptions.Value.OAuthTokenExpiryMinutes + : securityConfigurationOptions.Value.TokenExpiryMinutes); var securityToken = new JwtSecurityToken( tokenHeader, diff --git a/src/Tgstation.Server.Host/Server.cs b/src/Tgstation.Server.Host/Server.cs index 6f4a10c7d4..73249c3d87 100644 --- a/src/Tgstation.Server.Host/Server.cs +++ b/src/Tgstation.Server.Host/Server.cs @@ -68,16 +68,16 @@ namespace Tgstation.Server.Host /// readonly object restartLock; + /// + /// The of for the . + /// + IOptionsMonitor? generalConfigurationOptions; + /// /// The for the . /// ILogger? logger; - /// - /// The for the . - /// - GeneralConfiguration? generalConfiguration; - /// /// The for the . /// @@ -151,8 +151,7 @@ namespace Tgstation.Server.Host if (await DumpGraphQLSchemaIfRequested(Host.Services, cancellationToken)) return; - var generalConfigurationOptions = Host.Services.GetRequiredService>(); - generalConfiguration = generalConfigurationOptions.Value; + generalConfigurationOptions = Host.Services.GetRequiredService>(); await Host.RunAsync(cancellationTokenSource.Token); } @@ -389,8 +388,8 @@ namespace Tgstation.Server.Host using var cts = new CancellationTokenSource( TimeSpan.FromMinutes( giveHandlersTimeToWaitAround - ? generalConfiguration!.ShutdownTimeoutMinutes - : generalConfiguration!.RestartTimeoutMinutes)); + ? generalConfigurationOptions!.CurrentValue.ShutdownTimeoutMinutes + : generalConfigurationOptions!.CurrentValue.RestartTimeoutMinutes)); var cancellationToken = cts.Token; try { diff --git a/src/Tgstation.Server.Host/Swarm/SwarmService.cs b/src/Tgstation.Server.Host/Swarm/SwarmService.cs index c9fbe62f90..d40c880fc5 100644 --- a/src/Tgstation.Server.Host/Swarm/SwarmService.cs +++ b/src/Tgstation.Server.Host/Swarm/SwarmService.cs @@ -49,7 +49,7 @@ namespace Tgstation.Server.Host.Swarm return true; lock (swarmServers) - return swarmServers.Count - 1 >= swarmConfigurationOptions.CurrentValue.UpdateRequiredNodeCount; + return swarmServers.Count - 1 >= swarmConfigurationOptions.Value.UpdateRequiredNodeCount; } } @@ -57,7 +57,7 @@ namespace Tgstation.Server.Host.Swarm /// If the swarm system is enabled. /// [MemberNotNullWhen(true, nameof(serverHealthCheckTask), nameof(forceHealthCheckTcs), nameof(serverHealthCheckCancellationTokenSource), nameof(swarmServers))] - bool SwarmMode => swarmConfigurationOptions.CurrentValue.PrivateKey != null; + bool SwarmMode => swarmConfigurationOptions.Value.PrivateKey != null; /// /// The for the . @@ -104,16 +104,16 @@ namespace Tgstation.Server.Host.Swarm /// readonly ICallInvokerFactory grpcChannelFactory; + /// + /// The of for the . + /// + readonly IOptions swarmConfigurationOptions; + /// /// The for the . /// readonly ILogger logger; - /// - /// The for the . - /// - readonly IOptionsMonitor swarmConfigurationOptions; - /// /// The for . /// @@ -186,7 +186,7 @@ namespace Tgstation.Server.Host.Swarm /// The value of . /// The value of . /// The value of . - /// The containing the value of . + /// The value of . /// The value of . public SwarmService( IDatabaseContextFactory databaseContextFactory, @@ -198,7 +198,7 @@ namespace Tgstation.Server.Host.Swarm IFileTransferTicketProvider transferService, ITokenFactory tokenFactory, ICallInvokerFactory grpcChannelFactory, - IOptionsMonitor swarmConfigurationOptions, + IOptions swarmConfigurationOptions, ILogger logger) { this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory)); @@ -216,14 +216,13 @@ namespace Tgstation.Server.Host.Swarm nodeCallInvokers = new Dictionary(); if (SwarmMode) { - var currentSwarmOptions = swarmConfigurationOptions.CurrentValue; - if (currentSwarmOptions.Address == null) + if (this.swarmConfigurationOptions.Value.Address == null) throw new InvalidOperationException("Swarm configuration missing Address!"); - if (string.IsNullOrWhiteSpace(currentSwarmOptions.Identifier)) + if (string.IsNullOrWhiteSpace(this.swarmConfigurationOptions.Value.Identifier)) throw new InvalidOperationException("Swarm configuration missing Identifier!"); - swarmController = currentSwarmOptions.ControllerAddress == null; + swarmController = this.swarmConfigurationOptions.Value.ControllerAddress == null; if (swarmController) registrationIdsAndTimes = new(); @@ -234,10 +233,10 @@ namespace Tgstation.Server.Host.Swarm { new() { - Address = currentSwarmOptions.Address, - PublicAddress = currentSwarmOptions.PublicAddress, + Address = swarmConfigurationOptions.Value.Address, + PublicAddress = swarmConfigurationOptions.Value.PublicAddress, Controller = swarmController, - Identifier = currentSwarmOptions.Identifier, + Identifier = swarmConfigurationOptions.Value.Identifier, }, }; } @@ -427,22 +426,21 @@ namespace Tgstation.Server.Host.Swarm /// public async ValueTask Initialize(CancellationToken cancellationToken) { - var currentSwarmConfiguration = swarmConfigurationOptions.CurrentValue; if (SwarmMode) logger.LogInformation( "Swarm mode enabled: {nodeType} {nodeId}", swarmController ? "Controller" : "Node", - currentSwarmConfiguration.Identifier); + swarmConfigurationOptions.Value.Identifier); else logger.LogTrace("Swarm mode disabled"); SwarmRegistrationResult result; if (swarmController) { - if (currentSwarmConfiguration.UpdateRequiredNodeCount > 0) - logger.LogInformation("Expecting connections from {expectedNodeCount} nodes", currentSwarmConfiguration.UpdateRequiredNodeCount); + if (swarmConfigurationOptions.Value.UpdateRequiredNodeCount > 0) + logger.LogInformation("Expecting connections from {expectedNodeCount} nodes", swarmConfigurationOptions.Value.UpdateRequiredNodeCount); await databaseContextFactory.UseContext( databaseContext => databaseSeeder.Initialize(databaseContext, cancellationToken)); @@ -786,7 +784,7 @@ namespace Tgstation.Server.Host.Swarm try { - request.Headers.Authorization = new AuthenticationHeaderValue(SwarmConstants.AuthenticationSchemeAndPolicy, swarmConfigurationOptions.CurrentValue.PrivateKey); + request.Headers.Authorization = new AuthenticationHeaderValue(SwarmConstants.AuthenticationSchemeAndPolicy, swarmConfigurationOptions.Value.PrivateKey); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Octet)); return new RequestFileStreamProvider(httpClient, request); } @@ -878,7 +876,7 @@ namespace Tgstation.Server.Host.Swarm { Registration = registration, UpdateVersion = new GrpcVersion(version), - SourceNodeIdentifier = swarmConfigurationOptions.CurrentValue.Identifier, + SourceNodeIdentifier = swarmConfigurationOptions.Value.Identifier, }; request.DownloadTicketsByNodeIdentifier.Add(downloadTickets.ToDictionary(x => x.Key, x => new DownloadTicket(x.Value))); @@ -911,7 +909,7 @@ namespace Tgstation.Server.Host.Swarm return SwarmPrepareResult.Failure; } - if (!updateRequest.DownloadTicketsByNodeIdentifier.TryGetValue(swarmConfigurationOptions.CurrentValue.Identifier!, out var ticket)) + if (!updateRequest.DownloadTicketsByNodeIdentifier.TryGetValue(swarmConfigurationOptions.Value.Identifier!, out var ticket)) { logger.Log( swarmController @@ -993,12 +991,11 @@ namespace Tgstation.Server.Host.Swarm { logger.LogInformation("Sending remote prepare to nodes..."); - var currentSwarmConfiguration = swarmConfigurationOptions.CurrentValue; - if (currentUpdateOperation.InvolvedServers.Count - 1 < currentSwarmConfiguration.UpdateRequiredNodeCount) + if (currentUpdateOperation.InvolvedServers.Count - 1 < swarmConfigurationOptions.Value.UpdateRequiredNodeCount) { logger.LogWarning( "Aborting update, controller expects to be in sync with {requiredNodeCount} nodes but currently only has {currentNodeCount}!", - currentSwarmConfiguration.UpdateRequiredNodeCount, + swarmConfigurationOptions.Value.UpdateRequiredNodeCount, currentUpdateOperation.InvolvedServers.Count - 1); abortUpdate = true; return SwarmPrepareResult.Failure; @@ -1031,7 +1028,7 @@ namespace Tgstation.Server.Host.Swarm : updateRequest.DownloadTicketsByNodeIdentifier.ToDictionary(x => x.Key, x => x.Value.ToFileTicketResponse()); var sourceNode = weAreInitiator - ? currentSwarmConfiguration.Identifier + ? swarmConfigurationOptions.Value.Identifier : updateRequest.SourceNodeIdentifier; using var transferSemaphore = new SemaphoreSlim(1); @@ -1152,7 +1149,7 @@ namespace Tgstation.Server.Host.Swarm false); var serversRequiringTickets = involvedServers - .Where(node => node.Identifier != swarmConfigurationOptions.CurrentValue.Identifier) + .Where(node => node.Identifier != swarmConfigurationOptions.Value.Identifier) .ToList(); logger.LogTrace("Creating {n} download tickets for other nodes...", serversRequiringTickets.Count); @@ -1308,8 +1305,7 @@ namespace Tgstation.Server.Host.Swarm /// A resulting in the . async ValueTask RegisterWithController(CancellationToken cancellationToken) { - var currentSwarmConfiguration = swarmConfigurationOptions.CurrentValue; - logger.LogInformation("Attempting to register with swarm controller at {controllerAddress}...", currentSwarmConfiguration.ControllerAddress); + logger.LogInformation("Attempting to register with swarm controller at {controllerAddress}...", swarmConfigurationOptions.Value.ControllerAddress); var callInvoker = GetCallInvokerForNode(null, out _); var client = new GrpcSwarmControllerService.GrpcSwarmControllerServiceClient(callInvoker); @@ -1322,9 +1318,9 @@ namespace Tgstation.Server.Host.Swarm { RegisteringNode = new Grpc.SwarmServer { - Address = currentSwarmConfiguration.Address!.ToString(), - PublicAddress = currentSwarmConfiguration.PublicAddress?.ToString(), - Identifier = currentSwarmConfiguration.Identifier, + Address = swarmConfigurationOptions.Value.Address!.ToString(), + PublicAddress = swarmConfigurationOptions.Value.PublicAddress?.ToString(), + Identifier = swarmConfigurationOptions.Value.Identifier, }, SwarmProtocolVersion = new GrpcVersion( Version.Parse( @@ -1535,7 +1531,7 @@ namespace Tgstation.Server.Host.Swarm /// The to use for calling the target . CallInvoker GetCallInvokerForNode(Api.Models.Internal.SwarmServer? swarmServer, out SwarmRegistration? swarmRegistration) { - string CreateSwarmAuthorizationHeader() => $"{SwarmConstants.AuthenticationSchemeAndPolicy} {swarmConfigurationOptions.CurrentValue.PrivateKey}"; + string CreateSwarmAuthorizationHeader() => $"{SwarmConstants.AuthenticationSchemeAndPolicy} {swarmConfigurationOptions.Value.PrivateKey}"; lock (nodeCallInvokers) { @@ -1544,7 +1540,7 @@ namespace Tgstation.Server.Host.Swarm { if (controllerCallInvoker == null) { - var controllerAddress = swarmConfigurationOptions.CurrentValue.ControllerAddress; + var controllerAddress = swarmConfigurationOptions.Value.ControllerAddress; if (controllerAddress == null) throw new InvalidOperationException("Controller address was null!"); diff --git a/src/Tgstation.Server.Host/Utils/GitHub/GitHubClientFactory.cs b/src/Tgstation.Server.Host/Utils/GitHub/GitHubClientFactory.cs index 00a99c6330..88922870f8 100644 --- a/src/Tgstation.Server.Host/Utils/GitHub/GitHubClientFactory.cs +++ b/src/Tgstation.Server.Host/Utils/GitHub/GitHubClientFactory.cs @@ -50,16 +50,16 @@ namespace Tgstation.Server.Host.Utils.GitHub /// readonly IHttpMessageHandlerFactory httpMessageHandlerFactory; + /// + /// The of for the . + /// + readonly IOptionsMonitor generalConfigurationOptions; + /// /// The for the . /// readonly ILogger logger; - /// - /// The for the . - /// - readonly GeneralConfiguration generalConfiguration; - /// /// Cache of created s and last used/expiry times, keyed by access token. /// @@ -76,17 +76,17 @@ namespace Tgstation.Server.Host.Utils.GitHub /// The value of . /// The value of . /// The value of . - /// The containing the value of . + /// The containing the value of . public GitHubClientFactory( IAssemblyInformationProvider assemblyInformationProvider, IHttpMessageHandlerFactory httpMessageHandlerFactory, - ILogger logger, - IOptions generalConfigurationOptions) + IOptionsMonitor generalConfigurationOptions, + ILogger logger) { this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider)); this.httpMessageHandlerFactory = httpMessageHandlerFactory ?? throw new ArgumentNullException(nameof(httpMessageHandlerFactory)); + this.generalConfigurationOptions = generalConfigurationOptions ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); - generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); clientCache = new Dictionary(); clientCacheSemaphore = new SemaphoreSlim(1, 1); @@ -98,7 +98,7 @@ namespace Tgstation.Server.Host.Utils.GitHub /// public async ValueTask CreateClient(CancellationToken cancellationToken) => (await GetOrCreateClient( - generalConfiguration.GitHubAccessToken, + generalConfigurationOptions.CurrentValue.GitHubAccessToken, null, cancellationToken))!; diff --git a/src/Tgstation.Server.Host/Utils/GitHub/GitHubServiceFactory.cs b/src/Tgstation.Server.Host/Utils/GitHub/GitHubServiceFactory.cs index 1d5fb5ef31..f7c1c43d9f 100644 --- a/src/Tgstation.Server.Host/Utils/GitHub/GitHubServiceFactory.cs +++ b/src/Tgstation.Server.Host/Utils/GitHub/GitHubServiceFactory.cs @@ -27,22 +27,22 @@ namespace Tgstation.Server.Host.Utils.GitHub /// /// The for the . /// - readonly UpdatesConfiguration updatesConfiguration; + readonly IOptionsMonitor updatesConfigurationOptions; /// /// Initializes a new instance of the class. /// /// The value of . /// The value of . - /// The containing value of . + /// The value of . public GitHubServiceFactory( IGitHubClientFactory gitHubClientFactory, ILoggerFactory loggerFactory, - IOptions updatesConfigurationOptions) + IOptionsMonitor updatesConfigurationOptions) { this.gitHubClientFactory = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory)); this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); - updatesConfiguration = updatesConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(updatesConfigurationOptions)); + this.updatesConfigurationOptions = updatesConfigurationOptions ?? throw new ArgumentNullException(nameof(updatesConfigurationOptions)); } /// @@ -79,6 +79,6 @@ namespace Tgstation.Server.Host.Utils.GitHub => new( gitHubClient, loggerFactory.CreateLogger(), - updatesConfiguration); + updatesConfigurationOptions.CurrentValue); } } diff --git a/src/Tgstation.Server.Host/Utils/PortAllocator.cs b/src/Tgstation.Server.Host/Utils/PortAllocator.cs index d200e424ac..84c01a9d79 100644 --- a/src/Tgstation.Server.Host/Utils/PortAllocator.cs +++ b/src/Tgstation.Server.Host/Utils/PortAllocator.cs @@ -29,26 +29,26 @@ namespace Tgstation.Server.Host.Utils /// readonly IPlatformIdentifier platformIdentifier; + /// + /// The of for the . + /// + readonly IOptions swarmConfigurationOptions; + + /// + /// The of for the . + /// + readonly IOptionsMonitor generalConfigurationOptions; + + /// + /// The of for the . + /// + readonly IOptionsMonitor sessionConfigurationOptions; + /// /// The for the . /// readonly ILogger logger; - /// - /// The for the . - /// - readonly GeneralConfiguration generalConfiguration; - - /// - /// The for the . - /// - readonly SessionConfiguration sessionConfiguration; - - /// - /// The for the . - /// - readonly SwarmConfiguration swarmConfiguration; - /// /// The used to serialized port requisition requests. /// @@ -59,23 +59,23 @@ namespace Tgstation.Server.Host.Utils /// /// The value of . /// The value of . - /// The containing the value of . - /// The containing the value of . - /// The containing the value of . + /// The value of . + /// The value of . + /// The value of . /// The value of . public PortAllocator( IDatabaseContextFactory databaseContextFactory, IPlatformIdentifier platformIdentifier, - IOptions generalConfigurationOptions, - IOptions sessionConfigurationOptions, IOptions swarmConfigurationOptions, + IOptionsMonitor generalConfigurationOptions, + IOptionsMonitor sessionConfigurationOptions, ILogger logger) { this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory)); this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier)); - generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); - sessionConfiguration = sessionConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(sessionConfigurationOptions)); - swarmConfiguration = swarmConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(swarmConfigurationOptions)); + this.swarmConfigurationOptions = swarmConfigurationOptions ?? throw new ArgumentNullException(nameof(swarmConfigurationOptions)); + this.generalConfigurationOptions = generalConfigurationOptions ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); + this.sessionConfigurationOptions = sessionConfigurationOptions ?? throw new ArgumentNullException(nameof(sessionConfigurationOptions)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); allocatorLock = new SemaphoreSlim(1); @@ -107,8 +107,7 @@ namespace Tgstation.Server.Host.Utils logger.LogTrace("Port allocation >= {basePort} requested...", basePort); var ddPorts = await databaseContext .DreamDaemonSettings - .AsQueryable() - .Where(x => x.Instance!.SwarmIdentifer == swarmConfiguration.Identifier) + .Where(x => x.Instance!.SwarmIdentifer == swarmConfigurationOptions.Value.Identifier) .Select(x => new { Port = x.Port!.Value, @@ -118,8 +117,7 @@ namespace Tgstation.Server.Host.Utils var dmPorts = await databaseContext .DreamMakerSettings - .AsQueryable() - .Where(x => x.Instance!.SwarmIdentifer == swarmConfiguration.Identifier) + .Where(x => x.Instance!.SwarmIdentifer == swarmConfigurationOptions.Value.Identifier) .Select(x => new { ApiValidationPort = x.ApiValidationPort!.Value, @@ -138,25 +136,25 @@ namespace Tgstation.Server.Host.Utils bool SpecsMatchPort(IReadOnlyList specs) => specs.Any(spec => spec.Port == port); - if (SpecsMatchPort(generalConfiguration.ApiEndPoints)) + if (SpecsMatchPort(generalConfigurationOptions.CurrentValue.ApiEndPoints)) { logger.LogWarning("Cannot allocate port {port} as it is a TGS API port!", port); continue; } - if (SpecsMatchPort(generalConfiguration.MetricsEndPoints)) + if (SpecsMatchPort(generalConfigurationOptions.CurrentValue.MetricsEndPoints)) { logger.LogWarning("Cannot allocate port {port} as it is a metrics port!", port); continue; } - if (SpecsMatchPort(swarmConfiguration.EndPoints)) + if (SpecsMatchPort(swarmConfigurationOptions.Value.EndPoints)) { logger.LogWarning("Cannot allocate port {port} as it is a swarm API port!", port); continue; } - if (port == sessionConfiguration.BridgePort) + if (port == sessionConfigurationOptions.CurrentValue.BridgePort) { logger.LogWarning("Cannot allocate port {port} as it is the bridge request port!", port); continue; diff --git a/tests/Tgstation.Server.Host.Tests/Components/Chat/Providers/TestDiscordProvider.cs b/tests/Tgstation.Server.Host.Tests/Components/Chat/Providers/TestDiscordProvider.cs index deb77fd538..da872d6f63 100644 --- a/tests/Tgstation.Server.Host.Tests/Components/Chat/Providers/TestDiscordProvider.cs +++ b/tests/Tgstation.Server.Host.Tests/Components/Chat/Providers/TestDiscordProvider.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -64,9 +65,9 @@ namespace Tgstation.Server.Host.Components.Chat.Providers.Tests Assert.ThrowsExactly(() => new DiscordProvider(mockJobManager, mockDel, mockLogger, null, null, null)); var mockAss = Mock.Of(); Assert.ThrowsExactly(() => new DiscordProvider(mockJobManager, mockDel, mockLogger, mockAss, null, null)); - Assert.ThrowsExactly(() => new DiscordProvider(mockJobManager, mockDel, mockLogger, mockAss, bot, null)); - var mockGen = new GeneralConfiguration(); - await new DiscordProvider(mockJobManager, mockDel, mockLogger, mockAss, bot, mockGen).DisposeAsync(); + var mockGen = Mock.Of>(); + Assert.ThrowsExactly(() => new DiscordProvider(mockJobManager, mockDel, mockLogger, mockAss, mockGen, null)); + await new DiscordProvider(mockJobManager, mockDel, mockLogger, mockAss, mockGen, bot).DisposeAsync(); } static ValueTask InvokeConnect(IProvider provider, CancellationToken cancellationToken = default) => (ValueTask)provider.GetType().GetMethod("Connect", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(provider, new object[] { cancellationToken }); @@ -75,12 +76,12 @@ namespace Tgstation.Server.Host.Components.Chat.Providers.Tests public async Task TestConnectWithFakeTokenFails() { var mockLogger = new Mock>(); - await using var provider = new DiscordProvider(mockJobManager, Mock.Of(), mockLogger.Object, Mock.Of(), new ChatBot + await using var provider = new DiscordProvider(mockJobManager, Mock.Of(), mockLogger.Object, Mock.Of(), Mock.Of>(), new ChatBot { ReconnectionInterval = 1, ConnectionString = "asdf", Instance = new Models.Instance(), - }, new GeneralConfiguration()); + }); await Assert.ThrowsExactlyAsync(async () => await InvokeConnect(provider)); Assert.IsFalse(provider.Connected); } @@ -95,7 +96,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers.Tests Assert.Fail("TGS_TEST_DISCORD_TOKEN is not a valid Discord connection string!"); var mockLogger = new Mock>(); - await using var provider = new DiscordProvider(mockJobManager, Mock.Of(), mockLogger.Object, Mock.Of(), testToken1, new GeneralConfiguration()); + await using var provider = new DiscordProvider(mockJobManager, Mock.Of(), mockLogger.Object, Mock.Of(), Mock.Of>(), testToken1); Assert.IsFalse(provider.Connected); await InvokeConnect(provider); Assert.IsTrue(provider.Connected); diff --git a/tests/Tgstation.Server.Host.Tests/Components/Chat/Providers/TestIrcProvider.cs b/tests/Tgstation.Server.Host.Tests/Components/Chat/Providers/TestIrcProvider.cs index 83b2e7956f..400bbbb563 100644 --- a/tests/Tgstation.Server.Host.Tests/Components/Chat/Providers/TestIrcProvider.cs +++ b/tests/Tgstation.Server.Host.Tests/Components/Chat/Providers/TestIrcProvider.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -30,8 +31,6 @@ namespace Tgstation.Server.Host.Components.Chat.Providers.Tests Assert.ThrowsExactly(() => new IrcProvider(mockJobManager.Object, mockAsyncDelayer.Object, null, null, null, null)); var mockLogger = new Mock>(); Assert.ThrowsExactly(() => new IrcProvider(mockJobManager.Object, mockAsyncDelayer.Object, mockLogger.Object, null, null, null)); - var mockAss = new Mock(); - Assert.ThrowsExactly(() => new IrcProvider(mockJobManager.Object, mockAsyncDelayer.Object, mockLogger.Object, mockAss.Object, null, null)); var mockBot = new ChatBot { @@ -39,10 +38,14 @@ namespace Tgstation.Server.Host.Components.Chat.Providers.Tests Instance = new Models.Instance(), Provider = ChatProvider.Irc }; - Assert.ThrowsExactly(() => new IrcProvider(mockJobManager.Object, mockAsyncDelayer.Object, mockLogger.Object, mockAss.Object, mockBot, null)); + Assert.ThrowsExactly(() => new IrcProvider(mockJobManager.Object, mockAsyncDelayer.Object, mockLogger.Object, mockBot, null, null)); - var mockLogConf = new FileLoggingConfiguration(); - Assert.ThrowsExactly(() => new IrcProvider(mockJobManager.Object, mockAsyncDelayer.Object, mockLogger.Object, mockAss.Object, mockBot, mockLogConf)); + var mockAss = new Mock(); + Assert.ThrowsExactly(() => new IrcProvider(mockJobManager.Object, mockAsyncDelayer.Object, mockLogger.Object, mockBot, mockAss.Object, null)); + + var mockLogConf = new Mock>(); + mockLogConf.SetupGet(x => x.CurrentValue).Returns(new FileLoggingConfiguration()); + Assert.ThrowsExactly(() => new IrcProvider(mockJobManager.Object, mockAsyncDelayer.Object, mockLogger.Object, mockBot, mockAss.Object, mockLogConf.Object)); mockBot.ConnectionString = new IrcConnectionStringBuilder { @@ -52,7 +55,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers.Tests Port = 6667 }.ToString(); - await new IrcProvider(mockJobManager.Object, mockAsyncDelayer.Object, mockLogger.Object, mockAss.Object, mockBot, mockLogConf).DisposeAsync(); + await new IrcProvider(mockJobManager.Object, mockAsyncDelayer.Object, mockLogger.Object, mockBot, mockAss.Object, mockLogConf.Object).DisposeAsync(); } static ValueTask InvokeConnect(IProvider provider, CancellationToken cancellationToken = default) => (ValueTask)provider.GetType().GetMethod("Connect", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(provider, new object[] { cancellationToken }); @@ -89,7 +92,9 @@ namespace Tgstation.Server.Host.Components.Chat.Providers.Tests Instance = new Models.Instance(), }; - await using var provider = new IrcProvider(mockJobManager, new AsyncDelayer(loggerFactory.CreateLogger()), loggerFactory.CreateLogger(), Mock.Of(), chatBot, new FileLoggingConfiguration()); + var mockLogConf = new Mock>(); + mockLogConf.SetupGet(x => x.CurrentValue).Returns(new FileLoggingConfiguration()); + await using var provider = new IrcProvider(mockJobManager, new AsyncDelayer(loggerFactory.CreateLogger()), loggerFactory.CreateLogger(), chatBot, Mock.Of(), mockLogConf.Object); Assert.IsFalse(provider.Connected); await InvokeConnect(provider); Assert.IsTrue(provider.Connected); diff --git a/tests/Tgstation.Server.Host.Tests/Components/Engine/TestOpenDreamInstaller.cs b/tests/Tgstation.Server.Host.Tests/Components/Engine/TestOpenDreamInstaller.cs index e2ded03c84..01a53b348e 100644 --- a/tests/Tgstation.Server.Host.Tests/Components/Engine/TestOpenDreamInstaller.cs +++ b/tests/Tgstation.Server.Host.Tests/Components/Engine/TestOpenDreamInstaller.cs @@ -35,13 +35,13 @@ namespace Tgstation.Server.Host.Components.Engine.Tests static async Task RepoDownloadTest(bool needsClone) { - var mockGeneralConfigOptions = new Mock>(); + var mockGeneralConfigOptions = new Mock>(); var generalConfig = new GeneralConfiguration(); - var mockSessionConfigOptions = new Mock>(); + var mockSessionConfigOptions = new Mock>(); var sessionConfig = new SessionConfiguration(); Assert.IsNotNull(generalConfig.OpenDreamGitUrl); - mockGeneralConfigOptions.SetupGet(x => x.Value).Returns(generalConfig); - mockSessionConfigOptions.SetupGet(x => x.Value).Returns(sessionConfig); + mockGeneralConfigOptions.SetupGet(x => x.CurrentValue).Returns(generalConfig); + mockSessionConfigOptions.SetupGet(x => x.CurrentValue).Returns(sessionConfig); var cloneAttempts = 0; var mockRepository = new Mock(); diff --git a/tests/Tgstation.Server.Host.Tests/Components/Repository/TestRepositoryManager.cs b/tests/Tgstation.Server.Host.Tests/Components/Repository/TestRepositoryManager.cs index 2cdd59d19b..317798e10f 100644 --- a/tests/Tgstation.Server.Host.Tests/Components/Repository/TestRepositoryManager.cs +++ b/tests/Tgstation.Server.Host.Tests/Components/Repository/TestRepositoryManager.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using LibGit2Sharp; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -47,9 +48,9 @@ namespace Tgstation.Server.Host.Components.Repository.Tests Mock.Of(), Mock.Of(), mockGitRemoteFeaturesFactory.Object, + Mock.Of>(), Mock.Of>(), - Mock.Of>(), - new GeneralConfiguration()); + Mock.Of>()); } [TestCleanup] diff --git a/tests/Tgstation.Server.Host.Tests/Components/StaticFiles/TestConfiguration.cs b/tests/Tgstation.Server.Host.Tests/Components/StaticFiles/TestConfiguration.cs index 7314b0783a..1eeb0bdb30 100644 --- a/tests/Tgstation.Server.Host.Tests/Components/StaticFiles/TestConfiguration.cs +++ b/tests/Tgstation.Server.Host.Tests/Components/StaticFiles/TestConfiguration.cs @@ -6,6 +6,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -56,13 +57,13 @@ namespace Tgstation.Server.Host.Components.StaticFiles.Tests Mock.Of(), Mock.Of(), Mock.Of(), + Mock.Of>(), + Mock.Of>(), loggerFactory.CreateLogger(), new Models.Instance { Path = "Some path", - }, - new GeneralConfiguration(), - new SessionConfiguration()); + }); await configuration.StartAsync(CancellationToken.None); diff --git a/tests/Tgstation.Server.Host.Tests/Swarm/TestableSwarmNode.cs b/tests/Tgstation.Server.Host.Tests/Swarm/TestableSwarmNode.cs index 3d4a47fca1..f9ccf317f6 100644 --- a/tests/Tgstation.Server.Host.Tests/Swarm/TestableSwarmNode.cs +++ b/tests/Tgstation.Server.Host.Tests/Swarm/TestableSwarmNode.cs @@ -110,8 +110,8 @@ namespace Tgstation.Server.Host.Swarm.Tests { this.Config = swarmConfiguration; - var mockOptions = new Mock>(); - mockOptions.SetupGet(x => x.CurrentValue).Returns(swarmConfiguration); + var mockOptions = new Mock>(); + mockOptions.SetupGet(x => x.Value).Returns(swarmConfiguration); var realVersion = new AssemblyInformationProvider().Version; var mockAssemblyInformationProvider = new Mock(); diff --git a/tests/Tgstation.Server.Host.Tests/Utils/GitHub/TestGitHubClientFactory.cs b/tests/Tgstation.Server.Host.Tests/Utils/GitHub/TestGitHubClientFactory.cs index 56126a1df7..046c1b061f 100644 --- a/tests/Tgstation.Server.Host.Tests/Utils/GitHub/TestGitHubClientFactory.cs +++ b/tests/Tgstation.Server.Host.Tests/Utils/GitHub/TestGitHubClientFactory.cs @@ -47,7 +47,7 @@ namespace Tgstation.Server.Host.Utils.GitHub.Tests Assert.ThrowsExactly(() => new GitHubClientFactory(null, null, null, null)); Assert.ThrowsExactly(() => new GitHubClientFactory(Mock.Of(), null, null, null)); Assert.ThrowsExactly(() => new GitHubClientFactory(Mock.Of(), Mock.Of(), null, null)); - Assert.ThrowsExactly(() => new GitHubClientFactory(Mock.Of(), Mock.Of(), Mock.Of>(), null)); + Assert.ThrowsExactly(() => new GitHubClientFactory(Mock.Of(), Mock.Of(), Mock.Of>(), null)); } [TestMethod] @@ -56,12 +56,12 @@ namespace Tgstation.Server.Host.Utils.GitHub.Tests var mockApp = new Mock(); mockApp.SetupGet(x => x.ProductInfoHeaderValue).Returns(new ProductInfoHeaderValue("TGSTests", "1.2.3")).Verifiable(); - var mockOptions = new Mock>(); + var mockOptions = new Mock>(); var gc = new GeneralConfiguration(); Assert.IsNull(gc.GitHubAccessToken); - mockOptions.SetupGet(x => x.Value).Returns(gc); - var factory = new GitHubClientFactory(mockApp.Object, new BasicHttpMessageHandlerFactory(), loggerFactory.CreateLogger(), mockOptions.Object); + mockOptions.SetupGet(x => x.CurrentValue).Returns(gc); + var factory = new GitHubClientFactory(mockApp.Object, new BasicHttpMessageHandlerFactory(), mockOptions.Object, loggerFactory.CreateLogger()); var client = await factory.CreateClient(CancellationToken.None); Assert.IsNotNull(client); @@ -85,9 +85,9 @@ namespace Tgstation.Server.Host.Utils.GitHub.Tests var mockApp = new Mock(); mockApp.SetupGet(x => x.ProductInfoHeaderValue).Returns(new ProductInfoHeaderValue("TGSTests", "1.2.3")).Verifiable(); - var mockOptions = new Mock>(); - mockOptions.SetupGet(x => x.Value).Returns(new GeneralConfiguration()); - var factory = new GitHubClientFactory(mockApp.Object, new BasicHttpMessageHandlerFactory(), loggerFactory.CreateLogger(), mockOptions.Object); + var mockOptions = new Mock>(); + mockOptions.SetupGet(x => x.CurrentValue).Returns(new GeneralConfiguration()); + var factory = new GitHubClientFactory(mockApp.Object, new BasicHttpMessageHandlerFactory(), mockOptions.Object, loggerFactory.CreateLogger()); await Assert.ThrowsExactlyAsync(() => factory.CreateClient(null, CancellationToken.None).AsTask()); @@ -107,9 +107,9 @@ namespace Tgstation.Server.Host.Utils.GitHub.Tests var mockApp = new Mock(); mockApp.SetupGet(x => x.ProductInfoHeaderValue).Returns(new ProductInfoHeaderValue("TGSTests", "1.2.3")).Verifiable(); - var mockOptions = new Mock>(); - mockOptions.SetupGet(x => x.Value).Returns(new GeneralConfiguration()); - var factory = new GitHubClientFactory(mockApp.Object, new BasicHttpMessageHandlerFactory(), loggerFactory.CreateLogger(), mockOptions.Object); + var mockOptions = new Mock>(); + mockOptions.SetupGet(x => x.CurrentValue).Returns(new GeneralConfiguration()); + var factory = new GitHubClientFactory(mockApp.Object, new BasicHttpMessageHandlerFactory(), mockOptions.Object, loggerFactory.CreateLogger()); var appID = Environment.GetEnvironmentVariable("TGS_TEST_APP_ID"); var privateKey = Environment.GetEnvironmentVariable("TGS_TEST_APP_PRIVATE_KEY"); @@ -145,9 +145,9 @@ namespace Tgstation.Server.Host.Utils.GitHub.Tests var mockApp = new Mock(); mockApp.SetupGet(x => x.ProductInfoHeaderValue).Returns(new ProductInfoHeaderValue("TGSTests", "1.2.3")).Verifiable(); - var mockOptions = new Mock>(); - mockOptions.SetupGet(x => x.Value).Returns(new GeneralConfiguration()); - var factory = new GitHubClientFactory(mockApp.Object, new BasicHttpMessageHandlerFactory(), loggerFactory.CreateLogger(), mockOptions.Object); + var mockOptions = new Mock>(); + mockOptions.SetupGet(x => x.CurrentValue).Returns(new GeneralConfiguration()); + var factory = new GitHubClientFactory(mockApp.Object, new BasicHttpMessageHandlerFactory(), mockOptions.Object, loggerFactory.CreateLogger()); await Assert.ThrowsExactlyAsync(() => factory.CreateClient(null, CancellationToken.None).AsTask()); @@ -193,9 +193,9 @@ vTdVAoGBAI/jjUMdjkY43zhe3w2piwT0fhGfqm9ikdAB9IcgcptuS0ML0ZaWV/eO var mockApp = new Mock(); mockApp.SetupGet(x => x.ProductInfoHeaderValue).Returns(new ProductInfoHeaderValue("TGSTests", "1.2.3")).Verifiable(); - var mockOptions = new Mock>(); - mockOptions.SetupGet(x => x.Value).Returns(new GeneralConfiguration()); - var factory = new GitHubClientFactory(mockApp.Object, new BasicHttpMessageHandlerFactory(), loggerFactory.CreateLogger(), mockOptions.Object); + var mockOptions = new Mock>(); + mockOptions.SetupGet(x => x.CurrentValue).Returns(new GeneralConfiguration()); + var factory = new GitHubClientFactory(mockApp.Object, new BasicHttpMessageHandlerFactory(), mockOptions.Object, loggerFactory.CreateLogger()); var client1 = await factory.CreateClient(CancellationToken.None); var client2 = await factory.CreateClient("asdf", CancellationToken.None); diff --git a/tests/Tgstation.Server.Host.Tests/Utils/GitHub/TestGitHubServiceFactory.cs b/tests/Tgstation.Server.Host.Tests/Utils/GitHub/TestGitHubServiceFactory.cs index cef5f6c738..0bef83a84a 100644 --- a/tests/Tgstation.Server.Host.Tests/Utils/GitHub/TestGitHubServiceFactory.cs +++ b/tests/Tgstation.Server.Host.Tests/Utils/GitHub/TestGitHubServiceFactory.cs @@ -23,8 +23,8 @@ namespace Tgstation.Server.Host.Utils.GitHub.Tests Assert.ThrowsExactly(() => new GitHubServiceFactory(null, null, null)); Assert.ThrowsExactly(() => new GitHubServiceFactory(Mock.Of(), null, null)); Assert.ThrowsExactly(() => new GitHubServiceFactory(Mock.Of(), Mock.Of(), null)); - var mockOptions = new Mock>(); - mockOptions.SetupGet(x => x.Value).Returns(new UpdatesConfiguration()); + var mockOptions = new Mock>(); + mockOptions.SetupGet(x => x.CurrentValue).Returns(new UpdatesConfiguration()); _ = new GitHubServiceFactory(Mock.Of(), Mock.Of(), mockOptions.Object); } @@ -41,8 +41,8 @@ namespace Tgstation.Server.Host.Utils.GitHub.Tests mockFactory.Setup(x => x.CreateClient(mockToken, It.IsAny())).Returns(ValueTask.FromResult(Mock.Of())).Verifiable(); #pragma warning restore CA2012 // Use ValueTasks correctly - var mockOptions = new Mock>(); - mockOptions.SetupGet(x => x.Value).Returns(new UpdatesConfiguration()); + var mockOptions = new Mock>(); + mockOptions.SetupGet(x => x.CurrentValue).Returns(new UpdatesConfiguration()); var factory = new GitHubServiceFactory(mockFactory.Object, Mock.Of(), mockOptions.Object); diff --git a/tests/Tgstation.Server.Tests/Live/Instance/EngineTest.cs b/tests/Tgstation.Server.Tests/Live/Instance/EngineTest.cs index 3dcc508e50..fe058f519a 100644 --- a/tests/Tgstation.Server.Tests/Live/Instance/EngineTest.cs +++ b/tests/Tgstation.Server.Tests/Live/Instance/EngineTest.cs @@ -270,8 +270,8 @@ namespace Tgstation.Server.Tests.Live.Instance { ByondZipDownloadTemplate = TestingUtils.ByondZipDownloadTemplate, }); - var sessionConfigOptionsMock = new Mock>(); - sessionConfigOptionsMock.SetupGet(x => x.Value).Returns(new SessionConfiguration()); + var sessionConfigOptionsMock = new Mock>(); + sessionConfigOptionsMock.SetupGet(x => x.CurrentValue).Returns(new SessionConfiguration()); var assemblyInformationProvider = new AssemblyInformationProvider(); diff --git a/tests/Tgstation.Server.Tests/Live/Instance/InstanceTest.cs b/tests/Tgstation.Server.Tests/Live/Instance/InstanceTest.cs index 86d83cbbc5..b493522bdb 100644 --- a/tests/Tgstation.Server.Tests/Live/Instance/InstanceTest.cs +++ b/tests/Tgstation.Server.Tests/Live/Instance/InstanceTest.cs @@ -122,20 +122,20 @@ namespace Tgstation.Server.Tests.Live.Instance new NoopEventConsumer(), Mock.Of(), Mock.Of(), + mockOptionsMonitor.Object, Mock.Of>(), - Mock.Of>(), - genConfig), + Mock.Of>()), Mock.Of(), Mock.Of(), - Options.Create(genConfig), - Options.Create(new SessionConfiguration())) + mockOptionsMonitor.Object, + Mock.Of>()) : new PlatformIdentifier().IsWindows ? new WindowsByondInstaller( Mock.Of(), Mock.Of(), fileDownloader, mockOptionsMonitor.Object, - Options.Create(new SessionConfiguration()), + Mock.Of>(), Mock.Of>()) : new PosixByondInstaller( Mock.Of(), diff --git a/tests/Tgstation.Server.Tests/Live/TestLiveServer.cs b/tests/Tgstation.Server.Tests/Live/TestLiveServer.cs index 1cc92108a7..c1bf4e44e5 100644 --- a/tests/Tgstation.Server.Tests/Live/TestLiveServer.cs +++ b/tests/Tgstation.Server.Tests/Live/TestLiveServer.cs @@ -1674,7 +1674,7 @@ namespace Tgstation.Server.Tests.Live async Task RunInstanceTests() { - var testSerialized = true || TestingUtils.RunningInGitHubActions; // they only have 2 cores, can't handle intense parallelization + var testSerialized = TestingUtils.RunningInGitHubActions; // they only have 2 cores, can't handle intense parallelization async Task ODCompatTests() { var fileDownloader = await GetFileDownloader(); diff --git a/tests/Tgstation.Server.Tests/Live/TestingGitHubService.cs b/tests/Tgstation.Server.Tests/Live/TestingGitHubService.cs index 731e653a4c..d420bea426 100644 --- a/tests/Tgstation.Server.Tests/Live/TestingGitHubService.cs +++ b/tests/Tgstation.Server.Tests/Live/TestingGitHubService.cs @@ -34,13 +34,13 @@ namespace Tgstation.Server.Tests.Live static TestingGitHubService() { - var mockOptions = new Mock>(); - mockOptions.SetupGet(x => x.Value).Returns(new GeneralConfiguration + var mockOptions = new Mock>(); + mockOptions.SetupGet(x => x.CurrentValue).Returns(new GeneralConfiguration { GitHubAccessToken = Environment.GetEnvironmentVariable("TGS_TEST_GITHUB_TOKEN") }); - var gitHubClientFactory = new GitHubClientFactory(new AssemblyInformationProvider(), new BasicHttpMessageHandlerFactory(), Mock.Of>(), mockOptions.Object); + var gitHubClientFactory = new GitHubClientFactory(new AssemblyInformationProvider(), new BasicHttpMessageHandlerFactory(), mockOptions.Object, Mock.Of>()); RealClient = gitHubClientFactory.CreateClient(CancellationToken.None).GetAwaiter().GetResult(); } diff --git a/tests/Tgstation.Server.Tests/TestRepository.cs b/tests/Tgstation.Server.Tests/TestRepository.cs index 96a2349bea..e5c04e6cff 100644 --- a/tests/Tgstation.Server.Tests/TestRepository.cs +++ b/tests/Tgstation.Server.Tests/TestRepository.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using LibGit2Sharp; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -41,8 +42,8 @@ namespace Tgstation.Server.Tests Mock.Of(), Mock.Of(), Mock.Of(), + Mock.Of>(), Mock.Of>(), - new GeneralConfiguration(), () => { }); const string StartSha = "af4da8beb9f9b374b04a3cc4d65acca662e8cc1a"; @@ -81,9 +82,9 @@ namespace Tgstation.Server.Tests Mock.Of(), new WindowsPostWriteHandler(), Mock.Of(), + Mock.Of>(), Mock.Of>(), - Mock.Of>(), - new GeneralConfiguration()); + Mock.Of>()); try { using (await manager.CloneRepository( diff --git a/tests/Tgstation.Server.Tests/TestVersions.cs b/tests/Tgstation.Server.Tests/TestVersions.cs index c4d0524f16..cb372e3b40 100644 --- a/tests/Tgstation.Server.Tests/TestVersions.cs +++ b/tests/Tgstation.Server.Tests/TestVersions.cs @@ -112,8 +112,8 @@ namespace Tgstation.Server.Tests { ByondZipDownloadTemplate = TestingUtils.ByondZipDownloadTemplate, }); - var mockSessionConfigurationOptions = new Mock>(); - mockSessionConfigurationOptions.SetupGet(x => x.Value).Returns(new SessionConfiguration()); + var mockSessionConfigurationOptions = new Mock>(); + mockSessionConfigurationOptions.SetupGet(x => x.CurrentValue).Returns(new SessionConfiguration()); using var loggerFactory = LoggerFactory.Create(builder => { @@ -179,8 +179,8 @@ namespace Tgstation.Server.Tests SkipAddingByondFirewallException = true, ByondZipDownloadTemplate = TestingUtils.ByondZipDownloadTemplate, }); - var mockSessionConfigurationOptions = new Mock>(); - mockSessionConfigurationOptions.SetupGet(x => x.Value).Returns(new SessionConfiguration()); + var mockSessionConfigurationOptions = new Mock>(); + mockSessionConfigurationOptions.SetupGet(x => x.CurrentValue).Returns(new SessionConfiguration()); using var loggerFactory = LoggerFactory.Create(builder => {