Merge pull request #1931 from tgstation/IOptionsSnapshot

Switch from `IOptions` to `IOptionsSnapshot` and `IOptionsMonitor`
This commit is contained in:
Jordan Dominion
2025-08-16 11:22:48 -04:00
committed by GitHub
76 changed files with 527 additions and 597 deletions
@@ -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:
+2 -2
View File
@@ -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:
@@ -14,23 +14,19 @@
<ItemGroup>
<ProjectReference Include="..\Tgstation.Server.Client\Tgstation.Server.Client.csproj" />
<ProjectReference Include="..\Tgstation.Server.Host\Tgstation.Server.Host.csproj" PrivateAssets="all" ReferenceOutputAssembly="false" />
</ItemGroup>
<!-- https://github.com/dotnet/msbuild/issues/2661#issuecomment-338808147 -->
<Target Name="WorkaroundSdk939" BeforeTargets="ImportGraphQLApiSchema">
<MSBuild Projects="..\Tgstation.Server.Host\Tgstation.Server.Host.csproj" />
</Target>
<Target Name="DeleteGeneratedFiles" BeforeTargets="ImportGraphQLApiSchema">
<RemoveDir Directories="$(IntermediateOutputPath)berry" />
</Target>
<!-- https://github.com/ChilliCream/graphql-platform/blob/c0c8df525ca0f47bf3b3b409a8b22cbe37f7a9c0/src/StrawberryShake/MetaPackages/Common/MSBuild/StrawberryShake.targets#L20 -->
<Target Name="ImportGraphQLApiSchema" BeforeTargets="_GraphQLCodeGenerationRoot" Inputs="../../artifacts/tgs-api.graphql" Outputs="schema.graphql">
<Target Name="ImportGraphQLApiSchema" BeforeTargets="_GraphQLCodeGenerationRoot" DependsOnTargets="ResolveProjectReferences" Inputs="../../artifacts/tgs-api.graphql" Outputs="schema.graphql">
<Copy SkipUnchangedFiles="true" SourceFiles="../../artifacts/tgs-api.graphql" DestinationFiles="schema.graphql" />
</Target>
<Target Name="FixWarningsInGeneratedSchema" AfterTargets="GenerateGraphQLCode">
<Target Name="FixWarningsInGeneratedSchema" AfterTargets="GenerateGraphQLCode" BeforeTargets="CoreCompile">
<PropertyGroup>
<InputFile>$(IntermediateOutputPath)berry/GraphQLClient.Client.cs</InputFile>
<OutputFile>$(IntermediateOutputPath)berry/GraphQLClient.Client.cs</OutputFile>
@@ -62,9 +62,9 @@ namespace Tgstation.Server.Host.Authority
readonly ISessionInvalidationTracker sessionInvalidationTracker;
/// <summary>
/// The <see cref="SecurityConfiguration"/> for the <see cref="LoginAuthority"/>.
/// The <see cref="IOptionsSnapshot{TOptions}"/> containing the <see cref="SecurityConfiguration"/> for the <see cref="LoginAuthority"/>.
/// </summary>
readonly SecurityConfiguration securityConfiguration;
readonly IOptionsSnapshot<SecurityConfiguration> securityConfigurationOptions;
/// <summary>
/// Generate an <see cref="AuthorityResponse{TResult}"/> for a given <paramref name="headersException"/>.
@@ -113,7 +113,7 @@ namespace Tgstation.Server.Host.Authority
/// <param name="cryptographySuite">The value of <see cref="cryptographySuite"/>.</param>
/// <param name="identityCache">The value of <see cref="identityCache"/>.</param>
/// <param name="sessionInvalidationTracker">The value of <see cref="sessionInvalidationTracker"/>.</param>
/// <param name="securityConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="securityConfiguration"/>.</param>
/// <param name="securityConfigurationOptions">The value of <see cref="securityConfigurationOptions"/>.</param>
public LoginAuthority(
IDatabaseContext databaseContext,
ILogger<LoginAuthority> logger,
@@ -124,7 +124,7 @@ namespace Tgstation.Server.Host.Authority
ICryptographySuite cryptographySuite,
IIdentityCache identityCache,
ISessionInvalidationTracker sessionInvalidationTracker,
IOptions<SecurityConfiguration> securityConfigurationOptions)
IOptionsSnapshot<SecurityConfiguration> 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));
}
/// <inheritdoc />
@@ -181,7 +181,7 @@ namespace Tgstation.Server.Host.Authority
private async ValueTask<AuthorityResponse<LoginResult>> AttemptLoginImpl(CancellationToken cancellationToken)
{
// password and oauth logins disabled
if (securityConfiguration.OidcStrictMode)
if (securityConfigurationOptions.Value.OidcStrictMode)
return Unauthorized<LoginResult>();
var headers = apiHeadersProvider.ApiHeaders;
@@ -208,7 +208,7 @@ namespace Tgstation.Server.Host.Authority
using (systemIdentity)
{
// Get the user from the database
IQueryable<User> query = DatabaseContext.Users.AsQueryable();
IQueryable<User> query = DatabaseContext.Users;
if (oAuthLogin)
{
var oAuthProvider = headers.OAuthProvider!.Value;
@@ -118,13 +118,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)
@@ -85,9 +85,9 @@ namespace Tgstation.Server.Host.Authority
readonly IOptionsSnapshot<GeneralConfiguration> generalConfigurationOptions;
/// <summary>
/// The <see cref="IOptions{TOptions}"/> of <see cref="SecurityConfiguration"/> for the <see cref="UserAuthority"/>.
/// The <see cref="IOptionsSnapshot{TOptions}"/> of <see cref="SecurityConfiguration"/> for the <see cref="UserAuthority"/>.
/// </summary>
readonly IOptions<SecurityConfiguration> securityConfigurationOptions;
readonly IOptionsSnapshot<SecurityConfiguration> securityConfigurationOptions;
/// <summary>
/// Implements the <see cref="usersDataLoader"/>.
@@ -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<GeneralConfiguration> generalConfigurationOptions,
IOptions<SecurityConfiguration> securityConfigurationOptions)
IOptionsSnapshot<SecurityConfiguration> 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<UpdatedUser>(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<User> Queryable(bool includeJoins, bool allowSystemUser)
{
var tgsUserCanonicalName = User.CanonicalizeName(User.TgsSystemUserName);
var queryable = DatabaseContext
.Users
.AsQueryable();
IQueryable<User> 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);
@@ -121,7 +121,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);
@@ -148,7 +147,6 @@ namespace Tgstation.Server.Host.Authority
{
var totalGroups = await DatabaseContext
.Groups
.AsQueryable()
.CountAsync(cancellationToken);
if (totalGroups >= generalConfigurationOptions.Value.UserGroupLimit)
return Conflict<UserGroup>(ErrorCode.UserGroupLimitReached);
@@ -183,7 +181,6 @@ namespace Tgstation.Server.Host.Authority
{
var currentGroup = await DatabaseContext
.Groups
.AsQueryable()
.Where(x => x.Id == id)
.Include(x => x.PermissionSet)
.FirstOrDefaultAsync(cancellationToken);
@@ -212,7 +209,6 @@ namespace Tgstation.Server.Host.Authority
{
var numDeleted = await DatabaseContext
.Groups
.AsQueryable()
.Where(x => x.Id == id && x.Users!.Count == 0)
.ExecuteDeleteAsync(cancellationToken);
@@ -222,7 +218,6 @@ namespace Tgstation.Server.Host.Authority
// find out how we failed
var groupExists = await DatabaseContext
.Groups
.AsQueryable()
.Where(x => x.Id == id)
.AnyAsync(cancellationToken);
@@ -242,9 +237,8 @@ namespace Tgstation.Server.Host.Authority
/// <returns>An <see cref="IQueryable{T}"/> of <see cref="UserGroup"/>s.</returns>
IQueryable<UserGroup> QueryableImpl(bool includeJoins)
{
var queryable = DatabaseContext
.Groups
.AsQueryable();
IQueryable<UserGroup> queryable = DatabaseContext
.Groups;
if (includeJoins)
queryable = queryable
@@ -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)
@@ -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;
/// <summary>
/// The <see cref="GeneralConfiguration"/> for the <see cref="DiscordProvider"/>.
/// The <see cref="GeneralConfiguration"/> <see cref="IOptionsMonitor{TOptions}"/> for the <see cref="DiscordProvider"/>.
/// </summary>
readonly GeneralConfiguration generalConfiguration;
readonly IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions;
/// <summary>
/// The <see cref="ServiceProvider"/> containing Discord services.
@@ -141,18 +142,18 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
/// <param name="logger">The <see cref="ILogger"/> for the <see cref="Provider"/>.</param>
/// <param name="assemblyInformationProvider">The value of <see cref="assemblyInformationProvider"/>.</param>
/// <param name="chatBot">The <see cref="ChatBot"/> for the <see cref="Provider"/>.</param>
/// <param name="generalConfiguration">The value of <see cref="generalConfiguration"/>.</param>
/// <param name="generalConfigurationOptions">The value of <see cref="generalConfigurationOptions"/>.</param>
public DiscordProvider(
IJobManager jobManager,
IAsyncDelayer asyncDelayer,
ILogger<DiscordProvider> logger,
IAssemblyInformationProvider assemblyInformationProvider,
ChatBot chatBot,
GeneralConfiguration generalConfiguration)
IOptionsMonitor<GeneralConfiguration> 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<ulong>();
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}"),
};
@@ -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
/// <summary>
/// The <see cref="FileLoggingConfiguration"/> for the <see cref="IrcProvider"/>.
/// </summary>
readonly FileLoggingConfiguration loggingConfiguration;
readonly IOptionsMonitor<FileLoggingConfiguration> loggingConfigurationOptions;
/// <summary>
/// The <see cref="IrcFeatures"/> client.
@@ -117,18 +118,18 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
/// <param name="logger">The <see cref="ILogger"/> for the <see cref="Provider"/>.</param>
/// <param name="assemblyInformationProvider">The <see cref="IAssemblyInformationProvider"/> to get the <see cref="IAssemblyInformationProvider.VersionString"/> from.</param>
/// <param name="chatBot">The <see cref="Models.ChatBot"/> for the <see cref="Provider"/>.</param>
/// <param name="loggingConfiguration">The <see cref="FileLoggingConfiguration"/> for the <see cref="Provider"/>.</param>
/// <param name="loggingConfigurationOptions">The value of <see cref="loggingConfigurationOptions"/>.</param>
public IrcProvider(
IJobManager jobManager,
IAsyncDelayer asyncDelayer,
ILogger<IrcProvider> logger,
IAssemblyInformationProvider assemblyInformationProvider,
Models.ChatBot chatBot,
FileLoggingConfiguration loggingConfiguration)
IAssemblyInformationProvider assemblyInformationProvider,
IOptionsMonitor<FileLoggingConfiguration> 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);
@@ -36,14 +36,14 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
readonly ILoggerFactory loggerFactory;
/// <summary>
/// The <see cref="GeneralConfiguration"/> for the <see cref="ProviderFactory"/>.
/// The <see cref="GeneralConfiguration"/> <see cref="IOptionsMonitor{TOptions}"/> for the <see cref="ProviderFactory"/>.
/// </summary>
readonly GeneralConfiguration generalConfiguration;
readonly IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions;
/// <summary>
/// The <see cref="FileLoggingConfiguration"/> for the <see cref="ProviderFactory"/>.
/// The <see cref="FileLoggingConfiguration"/> <see cref="IOptionsMonitor{TOptions}"/> for the <see cref="ProviderFactory"/>.
/// </summary>
readonly FileLoggingConfiguration loggingConfiguration;
readonly IOptionsMonitor<FileLoggingConfiguration> loggingConfigurationOptions;
/// <summary>
/// Initializes a new instance of the <see cref="ProviderFactory"/> class.
@@ -52,22 +52,22 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
/// <param name="assemblyInformationProvider">The value of <see cref="assemblyInformationProvider"/>.</param>
/// <param name="asyncDelayer">The value of <see cref="asyncDelayer"/>.</param>
/// <param name="loggerFactory">The value of <see cref="loggerFactory"/>.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="generalConfiguration"/>.</param>
/// <param name="loggingConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="loggingConfiguration"/>.</param>
/// <param name="generalConfigurationOptions">The value of <see cref="generalConfigurationOptions"/>.</param>
/// <param name="loggingConfigurationOptions">The value of <see cref="loggingConfigurationOptions"/>.</param>
public ProviderFactory(
IJobManager jobManager,
IAssemblyInformationProvider assemblyInformationProvider,
IAsyncDelayer asyncDelayer,
ILoggerFactory loggerFactory,
IOptions<GeneralConfiguration> generalConfigurationOptions,
IOptions<FileLoggingConfiguration> loggingConfigurationOptions)
IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions,
IOptionsMonitor<FileLoggingConfiguration> 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));
}
/// <inheritdoc />
@@ -80,16 +80,16 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
jobManager,
asyncDelayer,
loggerFactory.CreateLogger<IrcProvider>(),
assemblyInformationProvider,
settings,
loggingConfiguration),
assemblyInformationProvider,
loggingConfigurationOptions),
ChatProvider.Discord => new DiscordProvider(
jobManager,
asyncDelayer,
loggerFactory.CreateLogger<DiscordProvider>(),
assemblyInformationProvider,
settings,
generalConfiguration),
generalConfigurationOptions,
settings),
_ => throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid ChatProvider: {0}", settings.Provider)),
};
}
@@ -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)
@@ -7,6 +7,7 @@ using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Prometheus;
@@ -30,7 +31,9 @@ using Tgstation.Server.Host.Utils;
namespace Tgstation.Server.Host.Components.Deployment
{
/// <inheritdoc />
#pragma warning disable CA1506 // TODO: Decomplexify
sealed class DreamMaker : IDreamMaker
#pragma warning restore CA1506
{
/// <summary>
/// Extension for .dmes.
@@ -92,16 +95,16 @@ namespace Tgstation.Server.Host.Components.Deployment
/// </summary>
readonly IAsyncDelayer asyncDelayer;
/// <summary>
/// The <see cref="IOptionsMonitor{TOptions}"/> of <see cref="SessionConfiguration"/> for <see cref="DreamMaker"/>.
/// </summary>
readonly IOptionsMonitor<SessionConfiguration> sessionConfigurationOptions;
/// <summary>
/// The <see cref="ILogger"/> for <see cref="DreamMaker"/>.
/// </summary>
readonly ILogger<DreamMaker> logger;
/// <summary>
/// The <see cref="SessionConfiguration"/> for <see cref="DreamMaker"/>.
/// </summary>
readonly SessionConfiguration sessionConfiguration;
/// <summary>
/// The <see cref="Instance"/> <see cref="DreamMaker"/> belongs to.
/// </summary>
@@ -167,8 +170,8 @@ namespace Tgstation.Server.Host.Components.Deployment
/// <param name="remoteDeploymentManagerFactory">The value of <see cref="remoteDeploymentManagerFactory"/>.</param>
/// <param name="asyncDelayer">The value of <see cref="asyncDelayer"/>.</param>
/// <param name="metricFactory">The <see cref="IMetricFactory"/> to use.</param>
/// <param name="sessionConfigurationOptions">The value of <see cref="sessionConfigurationOptions"/>.</param>
/// <param name="logger">The value of <see cref="logger"/>.</param>
/// <param name="sessionConfiguration">The value of <see cref="sessionConfiguration"/>.</param>
/// <param name="metadata">The value of <see cref="metadata"/>.</param>
public DreamMaker(
IEngineManager engineManager,
@@ -183,8 +186,8 @@ namespace Tgstation.Server.Host.Components.Deployment
IRemoteDeploymentManagerFactory remoteDeploymentManagerFactory,
IAsyncDelayer asyncDelayer,
IMetricFactory metricFactory,
IOptionsMonitor<SessionConfiguration> sessionConfigurationOptions,
ILogger<DreamMaker> logger,
SessionConfiguration sessionConfiguration,
Api.Models.Instance metadata)
{
this.engineManager = engineManager ?? throw new ArgumentNullException(nameof(engineManager));
@@ -199,8 +202,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");
@@ -253,7 +256,6 @@ namespace Tgstation.Server.Host.Components.Deployment
ddSettings = await databaseContext
.DreamDaemonSettings
.AsQueryable()
.Where(x => x.InstanceId == metadata.Id)
.Select(x => new Models.DreamDaemonSettings
{
@@ -266,7 +268,6 @@ namespace Tgstation.Server.Host.Components.Deployment
dreamMakerSettings = await databaseContext
.DreamMakerSettings
.AsQueryable()
.Where(x => x.InstanceId == metadata.Id)
.FirstAsync(cancellationToken);
if (dreamMakerSettings == default)
@@ -274,7 +275,6 @@ namespace Tgstation.Server.Host.Components.Deployment
repositorySettings = await databaseContext
.RepositorySettings
.AsQueryable()
.Where(x => x.InstanceId == metadata.Id)
.Select(x => new Models.RepositorySettings
{
@@ -302,7 +302,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!)
@@ -456,7 +455,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)
@@ -927,7 +925,7 @@ namespace Tgstation.Server.Host.Components.Deployment
readStandardHandles: true,
noShellExecute: true);
if (sessionConfiguration.LowPriorityDeploymentProcesses)
if (sessionConfigurationOptions.CurrentValue.LowPriorityDeploymentProcesses)
dm.AdjustPriority(false);
int exitCode;
@@ -1018,7 +1016,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;
@@ -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));
@@ -52,14 +52,14 @@ namespace Tgstation.Server.Host.Components.Engine
protected IProcessExecutor ProcessExecutor { get; }
/// <summary>
/// The <see cref="GeneralConfiguration"/> for the <see cref="OpenDreamInstaller"/>.
/// The <see cref="GeneralConfigurationOptions"/> for the <see cref="OpenDreamInstaller"/>.
/// </summary>
protected GeneralConfiguration GeneralConfiguration { get; }
protected IOptionsMonitor<GeneralConfiguration> GeneralConfigurationOptions { get; }
/// <summary>
/// The <see cref="Configuration.SessionConfiguration"/> for the <see cref="OpenDreamInstaller"/>.
/// </summary>
protected SessionConfiguration SessionConfiguration { get; }
protected IOptionsMonitor<SessionConfiguration> SessionConfigurationOptions { get; }
/// <summary>
/// The <see cref="IPlatformIdentifier"/> for the <see cref="OpenDreamInstaller"/>.
@@ -91,8 +91,8 @@ namespace Tgstation.Server.Host.Components.Engine
/// <param name="repositoryManager">The value of <see cref="repositoryManager"/>.</param>
/// <param name="asyncDelayer">The value of <see cref="asyncDelayer"/>.</param>
/// <param name="httpClientFactory">The value of <see cref="httpClientFactory"/>.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing value of <see cref="GeneralConfiguration"/>.</param>
/// <param name="sessionConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing value of <see cref="SessionConfiguration"/>.</param>
/// <param name="generalConfigurationOptions">The value of <see cref="GeneralConfigurationOptions"/>.</param>
/// <param name="sessionConfigurationOptions">The value of <see cref="SessionConfigurationOptions"/>.</param>
public OpenDreamInstaller(
IIOManager ioManager,
ILogger<OpenDreamInstaller> logger,
@@ -101,8 +101,8 @@ namespace Tgstation.Server.Host.Components.Engine
IRepositoryManager repositoryManager,
IAsyncDelayer asyncDelayer,
IHttpClientFactory httpClientFactory,
IOptions<GeneralConfiguration> generalConfigurationOptions,
IOptions<SessionConfiguration> sessionConfigurationOptions)
IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions,
IOptionsMonitor<SessionConfiguration> 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));
}
/// <inheritdoc />
@@ -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)
@@ -79,7 +79,7 @@ namespace Tgstation.Server.Host.Components.Engine
/// <summary>
/// The <see cref="SessionConfiguration"/> for the <see cref="WindowsByondInstaller"/>.
/// </summary>
readonly SessionConfiguration sessionConfiguration;
readonly IOptionsMonitor<SessionConfiguration> sessionConfigurationOptions;
/// <summary>
/// The <see cref="SemaphoreSlim"/> for the <see cref="WindowsByondInstaller"/>.
@@ -96,7 +96,7 @@ namespace Tgstation.Server.Host.Components.Engine
/// </summary>
/// <param name="processExecutor">The value of <see cref="processExecutor"/>.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptionsMonitor{TOptions}"/> containing the <see cref="GeneralConfiguration"/>.</param>
/// <param name="sessionConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="sessionConfiguration"/>.</param>
/// <param name="sessionConfigurationOptions">The value of <see cref="sessionConfigurationOptions"/>.</param>
/// <param name="ioManager">The <see cref="IIOManager"/> for the <see cref="ByondInstallerBase"/>.</param>
/// <param name="fileDownloader">The <see cref="IFileDownloader"/> for the <see cref="ByondInstallerBase"/>.</param>
/// <param name="logger">The <see cref="ILogger"/> for the <see cref="ByondInstallerBase"/>.</param>
@@ -105,12 +105,12 @@ namespace Tgstation.Server.Host.Components.Engine
IIOManager ioManager,
IFileDownloader fileDownloader,
IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions,
IOptions<SessionConfiguration> sessionConfigurationOptions,
IOptionsMonitor<SessionConfiguration> sessionConfigurationOptions,
ILogger<WindowsByondInstaller> 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
/// <inheritdoc />
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)
@@ -37,8 +37,8 @@ namespace Tgstation.Server.Host.Components.Engine
/// <param name="repositoryManager">The <see cref="IRepositoryManager"/> for the <see cref="OpenDreamInstaller"/>.</param>
/// <param name="asyncDelayer">The <see cref="IAsyncDelayer"/> for the <see cref="OpenDreamInstaller"/>.</param>
/// <param name="httpClientFactory">The <see cref="IHttpClientFactory"/> for the <see cref="OpenDreamInstaller"/>.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> of <see cref="GeneralConfiguration"/> for the <see cref="OpenDreamInstaller"/>.</param>
/// <param name="sessionConfigurationOptions">The <see cref="IOptions{TOptions}"/> of <see cref="SessionConfiguration"/> for the <see cref="OpenDreamInstaller"/>.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptionsMonitor{TOptions}"/> of <see cref="GeneralConfiguration"/> for the <see cref="OpenDreamInstaller"/>.</param>
/// <param name="sessionConfigurationOptions">The <see cref="IOptionsMonitor{TOptions}"/> of <see cref="SessionConfiguration"/> for the <see cref="OpenDreamInstaller"/>.</param>
/// <param name="linkFactory">The value of <see cref="linkFactory"/>.</param>
public WindowsOpenDreamInstaller(
IIOManager ioManager,
@@ -48,8 +48,8 @@ namespace Tgstation.Server.Host.Components.Engine
IRepositoryManager repositoryManager,
IAsyncDelayer asyncDelayer,
IHttpClientFactory httpClientFactory,
IOptions<GeneralConfiguration> generalConfigurationOptions,
IOptions<SessionConfiguration> sessionConfigurationOptions,
IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions,
IOptionsMonitor<SessionConfiguration> sessionConfigurationOptions,
IFilesystemLinkFactory linkFactory)
: base(
ioManager,
@@ -108,7 +108,7 @@ namespace Tgstation.Server.Host.Components.Engine
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
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)
@@ -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);
@@ -150,14 +150,14 @@ namespace Tgstation.Server.Host.Components
readonly IMetricFactory metricFactory;
/// <summary>
/// The <see cref="GeneralConfiguration"/> for the <see cref="InstanceFactory"/>.
/// The <see cref="IOptionsMonitor{TOptions}"/> of <see cref="GeneralConfiguration"/> for the <see cref="InstanceFactory"/>.
/// </summary>
readonly GeneralConfiguration generalConfiguration;
readonly IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions;
/// <summary>
/// The <see cref="SessionConfiguration"/> for the <see cref="InstanceFactory"/>.
/// The <see cref="IOptionsMonitor{TOptions}"/> of <see cref="SessionConfiguration"/> for the <see cref="InstanceFactory"/>.
/// </summary>
readonly SessionConfiguration sessionConfiguration;
readonly IOptionsMonitor<SessionConfiguration> sessionConfigurationOptions;
/// <summary>
/// Create the <see cref="IIOManager"/> pointing to the "Game" directory of a given <paramref name="instanceIOManager"/>.
@@ -193,8 +193,8 @@ namespace Tgstation.Server.Host.Components
/// <param name="asyncDelayer">The value of <see cref="asyncDelayer"/>.</param>
/// <param name="dotnetDumpService">The value of <see cref="dotnetDumpService"/>.</param>
/// <param name="metricFactory">The value of <see cref="metricFactory"/>.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="generalConfiguration"/>.</param>
/// <param name="sessionConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="sessionConfiguration"/>.</param>
/// <param name="generalConfigurationOptions">The value of <see cref="generalConfigurationOptions"/>.</param>
/// <param name="sessionConfigurationOptions">The value of <see cref="sessionConfigurationOptions"/>.</param>
public InstanceFactory(
IIOManager ioManager,
IDatabaseContextFactory databaseContextFactory,
@@ -219,8 +219,8 @@ namespace Tgstation.Server.Host.Components
IAsyncDelayer asyncDelayer,
IDotnetDumpService dotnetDumpService,
IMetricFactory metricFactory,
IOptions<GeneralConfiguration> generalConfigurationOptions,
IOptions<SessionConfiguration> sessionConfigurationOptions)
IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions,
IOptionsMonitor<SessionConfiguration> sessionConfigurationOptions)
{
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
@@ -245,8 +245,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
@@ -291,10 +291,10 @@ namespace Tgstation.Server.Host.Components
postWriteHandler,
platformIdentifier,
fileTransferService,
generalConfigurationOptions,
sessionConfigurationOptions,
loggerFactory.CreateLogger<StaticFiles.Configuration>(),
metadata,
generalConfiguration,
sessionConfiguration);
metadata);
var eventConsumer = new EventConsumer(configuration);
var repoManager = repositoryManagerFactory.CreateRepositoryManager(repoIoManager, eventConsumer);
try
@@ -347,8 +347,8 @@ namespace Tgstation.Server.Host.Components
dotnetDumpService,
metricFactory,
loggerFactory,
sessionConfigurationOptions,
loggerFactory.CreateLogger<SessionControllerFactory>(),
sessionConfiguration,
metadata);
var watchdog = watchdogFactory.CreateWatchdog(
@@ -382,8 +382,8 @@ namespace Tgstation.Server.Host.Components
remoteDeploymentManagerFactory,
asyncDelayer,
metricFactory,
sessionConfigurationOptions,
loggerFactory.CreateLogger<DreamMaker>(),
sessionConfiguration,
metadata);
instance = new Instance(
@@ -102,6 +102,21 @@ namespace Tgstation.Server.Host.Components
/// </summary>
readonly IPlatformIdentifier platformIdentifier;
/// <summary>
/// The <see cref="IOptions{TOptions}"/> of <see cref="GeneralConfiguration"/> for the <see cref="InstanceManager"/>.
/// </summary>
readonly IOptions<GeneralConfiguration> generalConfigurationOptions;
/// <summary>
/// The <see cref="IOptions{TOptions}"/> of <see cref="SwarmConfiguration"/> for the <see cref="InstanceManager"/>.
/// </summary>
readonly IOptions<SwarmConfiguration> swarmConfigurationOptions;
/// <summary>
/// The <see cref="IOptions{TOptions}"/> of <see cref="InternalConfiguration"/> for the <see cref="InstanceManager"/>.
/// </summary>
readonly IOptions<InternalConfiguration> internalConfigurationOptions;
/// <summary>
/// The <see cref="ILogger"/> for the <see cref="InstanceManager"/>.
/// </summary>
@@ -122,21 +137,6 @@ namespace Tgstation.Server.Host.Components
/// </summary>
readonly SemaphoreSlim instanceStateChangeSemaphore;
/// <summary>
/// The <see cref="GeneralConfiguration"/> for the <see cref="InstanceManager"/>.
/// </summary>
readonly GeneralConfiguration generalConfiguration;
/// <summary>
/// The <see cref="SwarmConfiguration"/> for the <see cref="InstanceManager"/>.
/// </summary>
readonly SwarmConfiguration swarmConfiguration;
/// <summary>
/// The <see cref="InternalConfiguration"/> for the <see cref="InstanceManager"/>.
/// </summary>
readonly InternalConfiguration internalConfiguration;
/// <summary>
/// The <see cref="TaskCompletionSource"/> for <see cref="Ready"/>.
/// </summary>
@@ -189,9 +189,9 @@ namespace Tgstation.Server.Host.Components
/// <param name="platformIdentifier">The value of <see cref="platformIdentifier"/>.</param>
/// <param name="metricFactory">The <see cref="IMetricFactory"/> used to create metrics.</param>
/// <param name="collectorRegistry">The <see cref="ICollectorRegistry"/> to use.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="generalConfiguration"/>.</param>
/// <param name="swarmConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="swarmConfiguration"/>.</param>
/// <param name="internalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="internalConfiguration"/>.</param>
/// <param name="generalConfigurationOptions">The value of <see cref="generalConfigurationOptions"/>.</param>
/// <param name="swarmConfigurationOptions">The value of <see cref="swarmConfigurationOptions"/>.</param>
/// <param name="internalConfigurationOptions">The value of <see cref="internalConfigurationOptions"/>.</param>
/// <param name="logger">The value of <see cref="logger"/>.</param>
public InstanceManager(
IInstanceFactory instanceFactory,
@@ -227,9 +227,9 @@ 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));
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.logger = logger ?? throw new ArgumentNullException(nameof(logger));
originalConsoleTitle = console.Title;
@@ -387,7 +387,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);
@@ -638,8 +637,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)
@@ -700,14 +698,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.");
}
@@ -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
/// </summary>
readonly ILibGit2RepositoryFactory submoduleFactory;
/// <summary>
/// The <see cref="IOptionsMonitor{TOptions}"/> of <see cref="GeneralConfiguration"/> for the <see cref="Repository"/>.
/// </summary>
readonly IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions;
/// <summary>
/// The <see cref="ILogger"/> for the <see cref="Repository"/>.
/// </summary>
readonly ILogger<Repository> logger;
/// <summary>
/// The <see cref="GeneralConfiguration"/> for the <see cref="Repository"/>.
/// </summary>
readonly GeneralConfiguration generalConfiguration;
/// <summary>
/// Initializes a new instance of the <see cref="Repository"/> class.
/// </summary>
@@ -136,8 +137,8 @@ namespace Tgstation.Server.Host.Components.Repository
/// <param name="postWriteHandler">The value of <see cref="postWriteHandler"/>.</param>
/// <param name="gitRemoteFeaturesFactory">The <see cref="IGitRemoteFeaturesFactory"/> to provide the value of <see cref="gitRemoteFeatures"/>.</param>
/// <param name="submoduleFactory">The value of <see cref="submoduleFactory"/>.</param>
/// <param name="generalConfigurationOptions">The value of <see cref="generalConfigurationOptions"/>.</param>
/// <param name="logger">The value of <see cref="logger"/>.</param>
/// <param name="generalConfiguration">The value of <see cref="generalConfiguration"/>.</param>
/// <param name="disposeAction">The <see cref="IDisposable.Dispose"/> action for the <see cref="DisposeInvoker"/>.</param>
public Repository(
LibGit2Sharp.IRepository libGitRepo,
@@ -148,8 +149,8 @@ namespace Tgstation.Server.Host.Components.Repository
IPostWriteHandler postWriteHandler,
IGitRemoteFeaturesFactory gitRemoteFeaturesFactory,
ILibGit2RepositoryFactory submoduleFactory,
IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions,
ILogger<Repository> 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);
}
@@ -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
/// </summary>
readonly IGitRemoteFeaturesFactory gitRemoteFeaturesFactory;
/// <summary>
/// The <see cref="IOptionsMonitor{TOptions}"/> of <see cref="GeneralConfiguration"/> for the <see cref="RepositoryManager"/>.
/// </summary>
readonly IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions;
/// <summary>
/// The <see cref="ILogger"/> created <see cref="Repository"/>s.
/// </summary>
@@ -65,11 +71,6 @@ namespace Tgstation.Server.Host.Components.Repository
/// </summary>
readonly ILogger<RepositoryManager> logger;
/// <summary>
/// The <see cref="GeneralConfiguration"/> for the <see cref="RepositoryManager"/>.
/// </summary>
readonly GeneralConfiguration generalConfiguration;
/// <summary>
/// Used for controlling single access to the <see cref="IRepository"/>.
/// </summary>
@@ -85,8 +86,8 @@ namespace Tgstation.Server.Host.Components.Repository
/// <param name="postWriteHandler">The value of <see cref="postWriteHandler"/>.</param>
/// <param name="gitRemoteFeaturesFactory">The value of <see cref="gitRemoteFeaturesFactory"/>.</param>
/// <param name="repositoryLogger">The value of <see cref="repositoryLogger"/>.</param>
/// <param name="generalConfigurationOptions">The value of <see cref="generalConfigurationOptions"/>.</param>
/// <param name="logger">The value of <see cref="logger"/>.</param>
/// <param name="generalConfiguration">The value of <see cref="generalConfiguration"/>.</param>
public RepositoryManager(
ILibGit2RepositoryFactory repositoryFactory,
ILibGit2Commands commands,
@@ -94,9 +95,9 @@ namespace Tgstation.Server.Host.Components.Repository
IEventConsumer eventConsumer,
IPostWriteHandler postWriteHandler,
IGitRemoteFeaturesFactory gitRemoteFeaturesFactory,
IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions,
ILogger<Repository> repositoryLogger,
ILogger<RepositoryManager> logger,
GeneralConfiguration generalConfiguration)
ILogger<RepositoryManager> 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...");
@@ -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
@@ -34,16 +34,16 @@ namespace Tgstation.Server.Host.Components.Repository
/// </summary>
readonly IGitRemoteFeaturesFactory gitRemoteFeaturesFactory;
/// <summary>
/// The <see cref="IOptionsMonitor{TOptions}"/> of <see cref="GeneralConfiguration"/> for the <see cref="RepostoryManagerFactory"/>.
/// </summary>
readonly IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions;
/// <summary>
/// The <see cref="ILoggerFactory"/> for the <see cref="RepostoryManagerFactory"/>.
/// </summary>
readonly ILoggerFactory loggerFactory;
/// <summary>
/// The <see cref="GeneralConfiguration"/> for the <see cref="RepostoryManagerFactory"/>.
/// </summary>
readonly GeneralConfiguration generalConfiguration;
/// <summary>
/// Initializes a new instance of the <see cref="RepostoryManagerFactory"/> class.
/// </summary>
@@ -52,21 +52,21 @@ namespace Tgstation.Server.Host.Components.Repository
/// <param name="postWriteHandler">The value of <see cref="postWriteHandler"/>.</param>
/// <param name="gitRemoteFeaturesFactory">The value of <see cref="gitRemoteFeaturesFactory"/>.</param>
/// <param name="loggerFactory">The value of <see cref="loggerFactory"/>.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="generalConfiguration"/>.</param>
/// <param name="generalConfigurationOptions">The value of <see cref="generalConfigurationOptions"/>.</param>
public RepostoryManagerFactory(
ILibGit2RepositoryFactory repositoryFactory,
ILibGit2Commands repositoryCommands,
IPostWriteHandler postWriteHandler,
IGitRemoteFeaturesFactory gitRemoteFeaturesFactory,
ILoggerFactory loggerFactory,
IOptions<GeneralConfiguration> generalConfigurationOptions)
IOptionsMonitor<GeneralConfiguration> 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));
}
/// <inheritdoc />
@@ -78,9 +78,9 @@ namespace Tgstation.Server.Host.Components.Repository
eventConsumer,
postWriteHandler,
gitRemoteFeaturesFactory,
generalConfigurationOptions,
loggerFactory.CreateLogger<Repository>(),
loggerFactory.CreateLogger<RepositoryManager>(),
generalConfiguration);
loggerFactory.CreateLogger<RepositoryManager>());
/// <inheritdoc />
public Task StartAsync(CancellationToken cancellationToken)
@@ -8,6 +8,7 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Prometheus;
@@ -119,16 +120,16 @@ namespace Tgstation.Server.Host.Components.Session
/// </summary>
readonly ILoggerFactory loggerFactory;
/// <summary>
/// The <see cref="IOptionsMonitor{TOptions}"/> of <see cref="SessionConfiguration"/> for the <see cref="SessionControllerFactory"/>.
/// </summary>
readonly IOptionsMonitor<SessionConfiguration> sessionConfigurationOptions;
/// <summary>
/// The <see cref="ILogger"/> for the <see cref="SessionControllerFactory"/>.
/// </summary>
readonly ILogger<SessionControllerFactory> logger;
/// <summary>
/// The <see cref="SessionConfiguration"/> for the <see cref="SessionControllerFactory"/>.
/// </summary>
readonly SessionConfiguration sessionConfiguration;
/// <summary>
/// The number of sessions launched.
/// </summary>
@@ -198,9 +199,9 @@ namespace Tgstation.Server.Host.Components.Session
/// <param name="asyncDelayer">The value of <see cref="asyncDelayer"/>.</param>
/// <param name="dotnetDumpService">The value of <see cref="dotnetDumpService"/>.</param>
/// <param name="metricFactory">The <see cref="IMetricFactory"/> used to create metrics.</param>
/// <param name="sessionConfigurationOptions">The value of <see cref="sessionConfigurationOptions"/>.</param>
/// <param name="loggerFactory">The value of <see cref="loggerFactory"/>.</param>
/// <param name="logger">The value of <see cref="logger"/>.</param>
/// <param name="sessionConfiguration">The value of <see cref="sessionConfiguration"/>.</param>
public SessionControllerFactory(
IProcessExecutor processExecutor,
IEngineManager engineManager,
@@ -219,8 +220,8 @@ namespace Tgstation.Server.Host.Components.Session
IDotnetDumpService dotnetDumpService,
IMetricFactory metricFactory,
ILoggerFactory loggerFactory,
IOptionsMonitor<SessionConfiguration> sessionConfigurationOptions,
ILogger<SessionControllerFactory> logger,
SessionConfiguration sessionConfiguration,
Api.Models.Instance instance)
{
this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor));
@@ -239,9 +240,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");
@@ -567,6 +568,7 @@ namespace Tgstation.Server.Host.Components.Session
try
{
var sessionConfiguration = sessionConfigurationOptions.CurrentValue;
if (!apiValidate)
{
if (sessionConfiguration.HighPriorityLiveDreamDaemon)
@@ -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)
@@ -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
/// </summary>>
readonly IFileTransferTicketProvider fileTransferService;
/// <summary>
/// The <see cref="IOptionsMonitor{TOptions}"/> of <see cref="GeneralConfiguration"/> for <see cref="Configuration"/>.
/// </summary>
readonly IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions;
/// <summary>
/// The <see cref="IOptionsMonitor{TOptions}"/> of <see cref="SessionConfiguration"/> for <see cref="Configuration"/>.
/// </summary>
readonly IOptionsMonitor<SessionConfiguration> sessionConfigurationOptions;
/// <summary>
/// The <see cref="ILogger"/> for <see cref="Configuration"/>.
/// </summary>
@@ -129,16 +140,6 @@ namespace Tgstation.Server.Host.Components.StaticFiles
/// </summary>
readonly Models.Instance metadata;
/// <summary>
/// The <see cref="GeneralConfiguration"/> for <see cref="Configuration"/>.
/// </summary>
readonly GeneralConfiguration generalConfiguration;
/// <summary>
/// The <see cref="SessionConfiguration"/> for <see cref="Configuration"/>.
/// </summary>
readonly SessionConfiguration sessionConfiguration;
/// <summary>
/// The <see cref="SemaphoreSlim"/> for <see cref="Configuration"/>. Also used as a <see langword="lock"/> <see cref="object"/>.
/// </summary>
@@ -166,8 +167,8 @@ namespace Tgstation.Server.Host.Components.StaticFiles
/// <param name="fileTransferService">The value of <see cref="fileTransferService"/>.</param>
/// <param name="metadata">The value of <see cref="metadata"/>.</param>
/// <param name="logger">The value of <see cref="logger"/>.</param>
/// <param name="generalConfiguration">The value of <see cref="generalConfiguration"/>.</param>
/// <param name="sessionConfiguration">The value of <see cref="sessionConfiguration"/>.</param>
/// <param name="generalConfigurationOptions">The value of <see cref="generalConfigurationOptions"/>.</param>
/// <param name="sessionConfigurationOptions">The value of <see cref="sessionConfigurationOptions"/>.</param>
public Configuration(
IIOManager ioManager,
ISynchronousIOManager synchronousIOManager,
@@ -176,10 +177,10 @@ namespace Tgstation.Server.Host.Components.StaticFiles
IPostWriteHandler postWriteHandler,
IPlatformIdentifier platformIdentifier,
IFileTransferTicketProvider fileTransferService,
IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions,
IOptionsMonitor<SessionConfiguration> sessionConfigurationOptions,
ILogger<Configuration> 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<string>();
var sessionConfiguration = sessionConfigurationOptions.CurrentValue;
var directories = generalConfigurationOptions.CurrentValue.AdditionalEventScriptsDirectories?.ToList() ?? new List<string>();
directories.Add(EventScriptsSubdirectory);
var allScripts = new List<string>();
@@ -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
{
/// <summary>
/// The <see cref="GeneralConfiguration"/> for the <see cref="PosixWatchdog"/>.
/// The <see cref="IOptionsMonitor{TOptions}"/> of <see cref="GeneralConfiguration"/> for the <see cref="PosixWatchdog"/>.
/// </summary>
readonly GeneralConfiguration generalConfiguration;
readonly IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions;
/// <summary>
/// Initializes a new instance of the <see cref="PosixWatchdog"/> class.
@@ -48,10 +49,10 @@ namespace Tgstation.Server.Host.Components.Watchdog
/// <param name="metricFactory">The <see cref="IMetricFactory"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="gameIOManager">The <see cref="IIOManager"/> pointing to the game directory for the <see cref="AdvancedWatchdog"/>..</param>
/// <param name="linkFactory">The <see cref="IFilesystemLinkFactory"/> for the <see cref="AdvancedWatchdog"/>.</param>
/// <param name="generalConfigurationOptions">The value of <see cref="generalConfigurationOptions"/>.</param>
/// <param name="logger">The <see cref="ILogger"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="initialLaunchParameters">The <see cref="DreamDaemonLaunchParameters"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="instance">The <see cref="Api.Models.Instance"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="generalConfiguration">The value of <see cref="GeneralConfiguration"/>.</param>
/// <param name="autoStart">The autostart value for the <see cref="WatchdogBase"/>.</param>
public PosixWatchdog(
IChatManager chat,
@@ -67,10 +68,10 @@ namespace Tgstation.Server.Host.Components.Watchdog
IMetricFactory metricFactory,
IIOManager gameIOManager,
IFilesystemLinkFactory linkFactory,
IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions,
ILogger<PosixWatchdog> 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));
}
/// <inheritdoc />
@@ -100,6 +101,12 @@ namespace Tgstation.Server.Host.Components.Watchdog
/// <inheritdoc />
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);
}
}
@@ -34,14 +34,14 @@ namespace Tgstation.Server.Host.Components.Watchdog
/// <param name="jobManager">The <see cref="IJobManager"/> for the <see cref="WatchdogFactory"/>.</param>
/// <param name="asyncDelayer">The <see cref="IAsyncDelayer"/> for the <see cref="WatchdogFactory"/>.</param>
/// <param name="linkFactory">The <see cref="IFilesystemLinkFactory"/> for the <see cref="WindowsWatchdogFactory"/>.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> for <see cref="GeneralConfiguration"/> for the <see cref="WatchdogFactory"/>.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptionsMonitor{TOptions}"/> of <see cref="GeneralConfiguration"/> for the <see cref="WatchdogFactory"/>.</param>
public PosixWatchdogFactory(
IServerControl serverControl,
ILoggerFactory loggerFactory,
IJobManager jobManager,
IAsyncDelayer asyncDelayer,
IFilesystemLinkFactory linkFactory,
IOptions<GeneralConfiguration> generalConfigurationOptions)
IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions)
: base(
serverControl,
loggerFactory,
@@ -79,10 +79,10 @@ namespace Tgstation.Server.Host.Components.Watchdog
metricFactory,
gameIOManager,
LinkFactory,
GeneralConfigurationOptions,
LoggerFactory.CreateLogger<PosixWatchdog>(),
settings,
instance,
GeneralConfiguration,
settings.AutoStart ?? throw new ArgumentNullException(nameof(settings)));
}
}
@@ -43,9 +43,9 @@ namespace Tgstation.Server.Host.Components.Watchdog
protected IAsyncDelayer AsyncDelayer { get; }
/// <summary>
/// The <see cref="Configuration.GeneralConfiguration"/> for the <see cref="WatchdogFactory"/>.
/// The <see cref="IOptionsMonitor{TOptions}"/> of <see cref="GeneralConfiguration"/> for the <see cref="WatchdogFactory"/>.
/// </summary>
protected GeneralConfiguration GeneralConfiguration { get; }
protected IOptionsMonitor<GeneralConfiguration> GeneralConfigurationOptions { get; }
/// <summary>
/// Initializes a new instance of the <see cref="WatchdogFactory"/> class.
@@ -54,19 +54,19 @@ namespace Tgstation.Server.Host.Components.Watchdog
/// <param name="loggerFactory">The value of <see cref="LoggerFactory"/>.</param>
/// <param name="jobManager">The value of <see cref="JobManager"/>.</param>
/// <param name="asyncDelayer">The value of <see cref="AsyncDelayer"/>.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="GeneralConfiguration"/>.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="GeneralConfigurationOptions"/>.</param>
public WatchdogFactory(
IServerControl serverControl,
ILoggerFactory loggerFactory,
IJobManager jobManager,
IAsyncDelayer asyncDelayer,
IOptions<GeneralConfiguration> generalConfigurationOptions)
IOptionsMonitor<GeneralConfiguration> 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));
}
/// <inheritdoc />
@@ -37,14 +37,14 @@ namespace Tgstation.Server.Host.Components.Watchdog
/// <param name="jobManager">The <see cref="IJobManager"/> for the <see cref="WatchdogFactory"/>.</param>
/// <param name="asyncDelayer">The <see cref="IAsyncDelayer"/> for the <see cref="WatchdogFactory"/>.</param>
/// <param name="symlinkFactory">The value of <see cref="LinkFactory"/>.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> for <see cref="GeneralConfiguration"/> for the <see cref="WatchdogFactory"/>.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptionsMonitor{TOptions}"/> for <see cref="GeneralConfiguration"/> for the <see cref="WatchdogFactory"/>.</param>
public WindowsWatchdogFactory(
IServerControl serverControl,
ILoggerFactory loggerFactory,
IJobManager jobManager,
IAsyncDelayer asyncDelayer,
IFilesystemLinkFactory symlinkFactory,
IOptions<GeneralConfiguration> generalConfigurationOptions)
IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions)
: base(
serverControl,
loggerFactory,
@@ -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;
/// <summary>
/// The <see cref="IFileTransferTicketProvider"/> for the <see cref="AdministrationController"/>.
/// The <see cref="IOptions{TOptions}"/> <see cref="FileLoggingConfiguration"/> for the <see cref="AdministrationController"/>.
/// </summary>
readonly IFileTransferTicketProvider fileTransferService;
/// <summary>
/// The <see cref="FileLoggingConfiguration"/> for the <see cref="AdministrationController"/>.
/// </summary>
readonly FileLoggingConfiguration fileLoggingConfiguration;
readonly IOptions<FileLoggingConfiguration> fileLoggingConfigurationOptions;
/// <summary>
/// Initializes a new instance of the <see cref="AdministrationController"/> class.
@@ -74,8 +68,7 @@ namespace Tgstation.Server.Host.Controllers
/// <param name="assemblyInformationProvider">The value of <see cref="assemblyInformationProvider"/>.</param>
/// <param name="ioManager">The value of <see cref="ioManager"/>.</param>
/// <param name="platformIdentifier">The value of <see cref="platformIdentifier"/>.</param>
/// <param name="fileTransferService">The value of <see cref="fileTransferService"/>.</param>
/// <param name="fileLoggingConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing value of <see cref="fileLoggingConfiguration"/>.</param>
/// <param name="fileLoggingConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing value of <see cref="fileLoggingConfigurationOptions"/>.</param>
public AdministrationController(
IDatabaseContext databaseContext,
IAuthenticationContext authenticationContext,
@@ -85,7 +78,6 @@ namespace Tgstation.Server.Host.Controllers
IAssemblyInformationProvider assemblyInformationProvider,
IIOManager ioManager,
IPlatformIdentifier platformIdentifier,
IFileTransferTicketProvider fileTransferService,
IOptions<FileLoggingConfiguration> 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));
}
/// <summary>
@@ -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);
@@ -65,14 +65,14 @@ namespace Tgstation.Server.Host.Controllers
readonly IRestAuthorityInvoker<ILoginAuthority> loginAuthority;
/// <summary>
/// The <see cref="GeneralConfiguration"/> for the <see cref="ApiRootController"/>.
/// The <see cref="IOptionsSnapshot{TOptions}"/> of <see cref="GeneralConfiguration"/> for the <see cref="ApiRootController"/>.
/// </summary>
readonly GeneralConfiguration generalConfiguration;
readonly IOptionsSnapshot<GeneralConfiguration> generalConfigurationOptions;
/// <summary>
/// The <see cref="SecurityConfiguration"/> for the <see cref="ApiRootController"/>.
/// The <see cref="IOptionsSnapshot{TOptions}"/> of <see cref="SecurityConfiguration"/> for the <see cref="ApiRootController"/>.
/// </summary>
readonly SecurityConfiguration securityConfiguration;
readonly IOptionsSnapshot<SecurityConfiguration> securityConfigurationOptions;
/// <summary>
/// Initializes a new instance of the <see cref="ApiRootController"/> class.
@@ -84,8 +84,8 @@ namespace Tgstation.Server.Host.Controllers
/// <param name="platformIdentifier">The value of <see cref="platformIdentifier"/>.</param>
/// <param name="swarmService">The value of <see cref="swarmService"/>.</param>
/// <param name="serverControl">The value of <see cref="serverControl"/>.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="generalConfiguration"/>.</param>
/// <param name="securityConfigurationOptions">The <see cref="IOptionsSnapshot{TOptions}"/> containing the value of <see cref="securityConfiguration"/>.</param>
/// <param name="generalConfigurationOptions">The value of <see cref="generalConfigurationOptions"/>.</param>
/// <param name="securityConfigurationOptions">The value of <see cref="securityConfigurationOptions"/>.</param>
/// <param name="logger">The <see cref="ILogger"/> for the <see cref="ApiController"/>.</param>
/// <param name="apiHeadersProvider">The <see cref="IApiHeadersProvider"/> for the <see cref="ApiController"/>.</param>
/// <param name="loginAuthority">The value of <see cref="loginAuthority"/>.</param>
@@ -97,7 +97,7 @@ namespace Tgstation.Server.Host.Controllers
IPlatformIdentifier platformIdentifier,
ISwarmService swarmService,
IServerControl serverControl,
IOptions<GeneralConfiguration> generalConfigurationOptions,
IOptionsSnapshot<GeneralConfiguration> generalConfigurationOptions,
IOptionsSnapshot<SecurityConfiguration> securityConfigurationOptions,
ILogger<ApiRootController> 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,
});
}
@@ -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<ChatBot>(
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<IActionResult> 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);
@@ -45,29 +45,29 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
readonly IWebHostEnvironment hostEnvironment;
/// <summary>
/// The <see cref="ControlPanelConfiguration"/> for the <see cref="ControlPanelController"/>.
/// </summary>
readonly IOptionsSnapshot<ControlPanelConfiguration> controlPanelConfigurationOptions;
/// <summary>
/// The <see cref="ILogger"/> for the <see cref="ControlPanelController"/>.
/// </summary>
readonly ILogger<ControlPanelController> logger;
/// <summary>
/// The <see cref="ControlPanelConfiguration"/> for the <see cref="ControlPanelController"/>.
/// </summary>
readonly ControlPanelConfiguration controlPanelConfiguration;
/// <summary>
/// Initializes a new instance of the <see cref="ControlPanelController"/> class.
/// </summary>
/// <param name="hostEnvironment">The value of <see cref="hostEnvironment"/>.</param>
/// <param name="controlPanelConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="controlPanelConfiguration"/>.</param>
/// <param name="controlPanelConfigurationOptions">The value of <see cref="controlPanelConfigurationOptions"/>.</param>
/// <param name="logger">The value of <see cref="logger"/>.</param>
public ControlPanelController(
IWebHostEnvironment hostEnvironment,
IOptions<ControlPanelConfiguration> controlPanelConfigurationOptions,
IOptionsSnapshot<ControlPanelConfiguration> controlPanelConfigurationOptions,
ILogger<ControlPanelController> 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();
@@ -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);
@@ -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
/// <returns>An <see cref="IQueryable{T}"/> of <see cref="CompileJob"/> with all the inclusions.</returns>
IQueryable<CompileJob> BaseCompileJobsQuery() => DatabaseContext
.CompileJobs
.AsQueryable()
.Include(x => x.Job!)
.ThenInclude(x => x.StartedBy)
.Include(x => x.Job!)
@@ -67,21 +67,21 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
readonly IPortAllocator portAllocator;
/// <summary>
/// The <see cref="IOptions{TOptions}"/> of <see cref="SwarmConfiguration"/> for the <see cref="InstanceController"/>.
/// </summary>
readonly IOptions<SwarmConfiguration> swarmConfigurationOptions;
/// <summary>
/// The <see cref="IOptionsSnapshot{TOptions}"/> of <see cref="GeneralConfiguration"/> for the <see cref="InstanceController"/>.
/// </summary>
readonly IOptionsSnapshot<GeneralConfiguration> generalConfigurationOptions;
/// <summary>
/// The <see cref="IPermissionsUpdateNotifyee"/> for the <see cref="InstanceController"/>.
/// </summary>
readonly IPermissionsUpdateNotifyee permissionsUpdateNotifyee;
/// <summary>
/// The <see cref="GeneralConfiguration"/> for the <see cref="InstanceController"/>.
/// </summary>
readonly GeneralConfiguration generalConfiguration;
/// <summary>
/// The <see cref="SwarmConfiguration"/> for the <see cref="InstanceController"/>.
/// </summary>
readonly SwarmConfiguration swarmConfiguration;
/// <summary>
/// Initializes a new instance of the <see cref="InstanceController"/> class.
/// </summary>
@@ -94,8 +94,8 @@ namespace Tgstation.Server.Host.Controllers
/// <param name="platformIdentifier">The value of <see cref="platformIdentifier"/>.</param>
/// <param name="portAllocator">The value of <see cref="portAllocator"/>.</param>
/// <param name="permissionsUpdateNotifyee">The value of <see cref="permissionsUpdateNotifyee"/>.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="generalConfiguration"/>.</param>
/// <param name="swarmConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="swarmConfiguration"/>.</param>
/// <param name="swarmConfigurationOptions">The value of <see cref="swarmConfigurationOptions"/>.</param>
/// <param name="generalConfigurationOptions">The value of <see cref="generalConfigurationOptions"/>.</param>
/// <param name="apiHeaders">The <see cref="IApiHeadersProvider"/> for the <see cref="ComponentInterfacingController"/>.</param>
public InstanceController(
IDatabaseContext databaseContext,
@@ -107,8 +107,8 @@ namespace Tgstation.Server.Host.Controllers
IPlatformIdentifier platformIdentifier,
IPortAllocator portAllocator,
IPermissionsUpdateNotifyee permissionsUpdateNotifyee,
IOptions<GeneralConfiguration> generalConfigurationOptions,
IOptions<SwarmConfiguration> swarmConfigurationOptions,
IOptionsSnapshot<GeneralConfiguration> 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));
}
/// <summary>
@@ -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<Models.Instance> 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<Models.Instance> 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);
}
@@ -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<InstancePermissionSet>(
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)
@@ -75,7 +75,6 @@ namespace Tgstation.Server.Host.Controllers
new PaginatableResult<Job>(
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<Job>(
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)
@@ -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);
@@ -48,26 +48,26 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
readonly IWebHostEnvironment hostEnvironment;
/// <summary>
/// The <see cref="IOptions{TOptions}"/> of <see cref="GeneralConfiguration"/> for the <see cref="RootController"/>.
/// </summary>
readonly IOptions<GeneralConfiguration> generalConfigurationOptions;
/// <summary>
/// The <see cref="IOptions{TOptions}"/> of <see cref="ControlPanelConfiguration"/> for the <see cref="RootController"/>.
/// </summary>
readonly IOptions<ControlPanelConfiguration> controlPanelConfigurationOptions;
/// <summary>
/// The <see cref="IOptions{TOptions}"/> of <see cref="InternalConfiguration"/> for the <see cref="RootController"/>.
/// </summary>
readonly IOptions<InternalConfiguration> internalConfigurationOptions;
/// <summary>
/// The <see cref="ILogger"/> for the <see cref="RootController"/>.
/// </summary>
readonly ILogger<RootController> logger;
/// <summary>
/// The <see cref="GeneralConfiguration"/> for the <see cref="RootController"/>.
/// </summary>
readonly GeneralConfiguration generalConfiguration;
/// <summary>
/// The <see cref="ControlPanelConfiguration"/> for the <see cref="RootController"/>.
/// </summary>
readonly ControlPanelConfiguration controlPanelConfiguration;
/// <summary>
/// The <see cref="InternalConfiguration"/> for the <see cref="RootController"/>.
/// </summary>
readonly InternalConfiguration internalConfiguration;
/// <summary>
/// Gets a <see cref="Tuple{T1, T2}"/> giving the <see cref="ControlPanelController"/> and action names for a given <paramref name="actionExpression"/>.
/// </summary>
@@ -96,9 +96,9 @@ namespace Tgstation.Server.Host.Controllers
/// <param name="platformIdentifier">The value of <see cref="platformIdentifier"/>.</param>
/// <param name="hostEnvironment">The value of <see cref="hostEnvironment"/>.</param>
/// <param name="logger">The value of <see cref="logger"/>.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="generalConfiguration"/>.</param>
/// <param name="controlPanelConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="controlPanelConfiguration"/>.</param>
/// <param name="internalConfigurationOptions">The <see cref="IOptionsSnapshot{TOptions}"/> containing the value of <see cref="controlPanelConfiguration"/>.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="generalConfigurationOptions"/>.</param>
/// <param name="controlPanelConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="controlPanelConfigurationOptions"/>.</param>
/// <param name="internalConfigurationOptions">The <see cref="IOptionsSnapshot{TOptions}"/> containing the value of <see cref="controlPanelConfigurationOptions"/>.</param>
public RootController(
IAssemblyInformationProvider assemblyInformationProvider,
IPlatformIdentifier platformIdentifier,
@@ -106,15 +106,15 @@ namespace Tgstation.Server.Host.Controllers
ILogger<RootController> logger,
IOptions<GeneralConfiguration> generalConfigurationOptions,
IOptions<ControlPanelConfiguration> controlPanelConfigurationOptions,
IOptionsSnapshot<InternalConfiguration> internalConfigurationOptions)
IOptions<InternalConfiguration> 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));
}
/// <summary>
@@ -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);
@@ -44,22 +44,22 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
readonly IFileTransferStreamHandler transferService;
/// <summary>
/// The <see cref="IOptions{TOptions}"/> of <see cref="SwarmConfiguration"/> for the <see cref="SwarmController"/>.
/// </summary>
readonly IOptions<SwarmConfiguration> swarmConfigurationOptions;
/// <summary>
/// The <see cref="ILogger"/> for the <see cref="SwarmController"/>.
/// </summary>
readonly ILogger<SwarmController> logger;
/// <summary>
/// The <see cref="SwarmConfiguration"/> for the <see cref="SwarmController"/>.
/// </summary>
readonly SwarmConfiguration swarmConfiguration;
/// <summary>
/// Initializes a new instance of the <see cref="SwarmController"/> class.
/// </summary>
/// <param name="swarmOperations">The value of <see cref="swarmOperations"/>.</param>
/// <param name="transferService">The value of <see cref="transferService"/>.</param>
/// <param name="swarmConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="swarmConfiguration"/>.</param>
/// <param name="swarmConfigurationOptions">The value of <see cref="swarmConfigurationOptions"/>.</param>
/// <param name="logger">The value of <see cref="logger"/>.</param>
public SwarmController(
ISwarmOperations swarmOperations,
@@ -69,7 +69,7 @@ namespace Tgstation.Server.Host.Controllers
{
this.swarmOperations = swarmOperations ?? throw new ArgumentNullException(nameof(swarmOperations));
this.transferService = transferService ?? throw new ArgumentNullException(nameof(transferService));
swarmConfiguration = swarmConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(swarmConfigurationOptions));
this.swarmConfigurationOptions = swarmConfigurationOptions ?? throw new ArgumentNullException(nameof(swarmConfigurationOptions));
this.logger = logger;
}
@@ -215,7 +215,7 @@ namespace Tgstation.Server.Host.Controllers
using (LogContext.PushProperty(SerilogContextHelper.RequestPathContextProperty, $"{Request.Method} {Request.Path}"))
{
logger.LogTrace("Swarm request from {remoteIP}...", Request.HttpContext.Connection.RemoteIpAddress);
if (swarmConfiguration.PrivateKey == null)
if (swarmConfigurationOptions.Value.PrivateKey == null)
{
logger.LogDebug("Attempted swarm request without private key configured!");
return Forbid();
@@ -223,7 +223,7 @@ namespace Tgstation.Server.Host.Controllers
if (!(Request.Headers.TryGetValue(SwarmConstants.ApiKeyHeader, out var apiKeyHeaderValues)
&& apiKeyHeaderValues.Count == 1
&& apiKeyHeaderValues.First() == swarmConfiguration.PrivateKey))
&& apiKeyHeaderValues.First() == swarmConfigurationOptions.Value.PrivateKey))
{
logger.LogDebug("Unauthorized swarm request!");
return Unauthorized();
@@ -378,7 +378,7 @@ namespace Tgstation.Server.Host.Core
services.AddSingleton<IDatabaseSeeder, DatabaseSeeder>();
// configure other security services
services.AddSingleton<IOAuthProviders, OAuthProviders>();
services.AddScoped<IOAuthProviders, OAuthProviders>();
services.AddSingleton<IIdentityCache, IdentityCache>();
services.AddSingleton<ICryptographySuite, CryptographySuite>();
services.AddSingleton<ITokenFactory, TokenFactory>();
@@ -542,11 +542,11 @@ namespace Tgstation.Server.Host.Core
ArgumentNullException.ThrowIfNull(serverPortProvider);
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 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;
ArgumentNullException.ThrowIfNull(logger);
@@ -30,22 +30,22 @@ namespace Tgstation.Server.Host.Core
/// </summary>
readonly IInstanceManager instanceManager;
/// <summary>
/// The <see cref="IOptions{TOptions}"/> of <see cref="InternalConfiguration"/> for the <see cref="CommandPipeManager"/>.
/// </summary>
readonly IOptions<InternalConfiguration> internalConfigurationOptions;
/// <summary>
/// The <see cref="ILogger"/> for the <see cref="CommandPipeManager"/>.
/// </summary>
readonly ILogger<CommandPipeManager> logger;
/// <summary>
/// The <see cref="InternalConfiguration"/> for the <see cref="CommandPipeManager"/>.
/// </summary>
readonly InternalConfiguration internalConfiguration;
/// <summary>
/// Initializes a new instance of the <see cref="CommandPipeManager"/> class.
/// </summary>
/// <param name="serverControl">The value of <see cref="serverControl"/>.</param>
/// <param name="instanceManager">The value of <see cref="instanceManager"/>.</param>
/// <param name="internalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="internalConfiguration"/>.</param>
/// <param name="internalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="internalConfigurationOptions"/>.</param>
/// <param name="logger">The value of <see cref="logger"/>.</param>
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)
{
@@ -13,28 +13,28 @@ namespace Tgstation.Server.Host.Core
sealed class ServerPortProivder : IServerPortProvider
{
/// <inheritdoc />
public ushort HttpApiPort => generalConfiguration.ApiPort;
public ushort HttpApiPort => generalConfigurationOptions.Value.ApiPort;
/// <summary>
/// The <see cref="GeneralConfiguration"/> for the <see cref="ServerPortProivder"/>.
/// The <see cref="IOptions{TOptions}"/> of <see cref="GeneralConfiguration"/> for the <see cref="ServerPortProivder"/>.
/// </summary>
readonly GeneralConfiguration generalConfiguration;
readonly IOptions<GeneralConfiguration> generalConfigurationOptions;
/// <summary>
/// Initializes a new instance of the <see cref="ServerPortProivder"/> class.
/// </summary>
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="generalConfiguration"/>.</param>
/// <param name="configuration">The <see cref="IConfiguration"/> to use.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="generalConfigurationOptions"/>.</param>
/// <param name="logger">The <see cref="ILogger"/> to use.</param>
public ServerPortProivder(
IOptions<GeneralConfiguration> generalConfigurationOptions,
IConfiguration configuration,
IOptions<GeneralConfiguration> generalConfigurationOptions,
ILogger<ServerPortProivder> logger)
{
generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions));
ArgumentNullException.ThrowIfNull(configuration);
this.generalConfigurationOptions = generalConfigurationOptions ?? throw new ArgumentNullException(nameof(generalConfigurationOptions));
var usingDefaultPort = generalConfiguration.ApiPort == default;
var usingDefaultPort = generalConfigurationOptions.Value.ApiPort == default;
if (!usingDefaultPort)
return;
@@ -55,7 +55,7 @@ namespace Tgstation.Server.Host.Core
if (!UInt16.TryParse(portString, out var result))
throw new InvalidOperationException($"Failed to parse HTTP EndPoint port: {httpEndpoint}");
generalConfiguration.ApiPort = result;
this.generalConfigurationOptions.Value.ApiPort = result;
}
}
}
+19 -16
View File
@@ -36,21 +36,21 @@ namespace Tgstation.Server.Host.Core
/// </summary>
readonly IServerControl serverControl;
/// <summary>
/// The <see cref="IOptionsMonitor{TOptions}"/> of <see cref="GeneralConfiguration"/> for the <see cref="ServerUpdater"/>.
/// </summary>
readonly IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions;
/// <summary>
/// The <see cref="IOptionsMonitor{TOptions}"/> of <see cref="UpdatesConfiguration"/> for the <see cref="ServerUpdater"/>.
/// </summary>
readonly IOptionsMonitor<UpdatesConfiguration> updatesConfigurationOptions;
/// <summary>
/// The <see cref="ILogger"/> for the <see cref="ServerUpdater"/>.
/// </summary>
readonly ILogger<ServerUpdater> logger;
/// <summary>
/// The <see cref="GeneralConfiguration"/> for the <see cref="ServerUpdater"/>.
/// </summary>
readonly GeneralConfiguration generalConfiguration;
/// <summary>
/// The <see cref="UpdatesConfiguration"/> for the <see cref="ServerUpdater"/>.
/// </summary>
readonly UpdatesConfiguration updatesConfiguration;
/// <summary>
/// Lock <see cref="object"/> used when initiating an update.
/// </summary>
@@ -69,24 +69,24 @@ namespace Tgstation.Server.Host.Core
/// <param name="fileDownloader">The value of <see cref="fileDownloader"/>.</param>
/// <param name="serverControl">The value of <see cref="serverControl"/>.</param>
/// <param name="logger">The value of <see cref="logger"/>.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="generalConfiguration"/>.</param>
/// <param name="updatesConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="updatesConfiguration"/>.</param>
/// <param name="generalConfigurationOptions">The value of <see cref="generalConfigurationOptions"/>.</param>
/// <param name="updatesConfigurationOptions">The value of <see cref="updatesConfigurationOptions"/>.</param>
public ServerUpdater(
IGitHubServiceFactory gitHubServiceFactory,
IIOManager ioManager,
IFileDownloader fileDownloader,
IServerControl serverControl,
ILogger<ServerUpdater> logger,
IOptions<GeneralConfiguration> generalConfigurationOptions,
IOptions<UpdatesConfiguration> updatesConfigurationOptions)
IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions,
IOptionsMonitor<UpdatesConfiguration> 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;
@@ -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
/// <inheritdoc />
public void Attach(TModel model) => dbSet.Attach(model);
/// <inheritdoc />
public IAsyncEnumerator<TModel> GetAsyncEnumerator(CancellationToken cancellationToken = default) => dbSet.AsAsyncEnumerable().GetAsyncEnumerator(cancellationToken);
/// <inheritdoc />
public IEnumerator<TModel> GetEnumerator() => dbSet.AsQueryable().GetEnumerator();
@@ -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)
@@ -7,7 +7,7 @@ namespace Tgstation.Server.Host.Database
/// Represents a database table.
/// </summary>
/// <typeparam name="TModel">The type of model.</typeparam>
public interface IDatabaseCollection<TModel> : IQueryable<TModel>, IAsyncEnumerable<TModel>
public interface IDatabaseCollection<TModel> : IQueryable<TModel>
{
/// <summary>
/// An <see cref="IEnumerable{T}"/> of <typeparamref name="TModel"/>s prioritizing in the working set.
@@ -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);
@@ -26,10 +26,10 @@ namespace Tgstation.Server.Host.GraphQL.Types
/// <summary>
/// If only OIDC logins and registration is allowed.
/// </summary>
/// <param name="securityConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the <see cref="SecurityConfiguration"/>.</param>
/// <param name="securityConfigurationOptions">The <see cref="IOptionsSnapshot{TOptions}"/> containing the <see cref="SecurityConfiguration"/>.</param>
/// <returns><see langword="true"/> if OIDC strict mode is enabled, <see langword="false"/> otherwise.</returns>
public bool OidcStrictMode(
[Service] IOptions<SecurityConfiguration> securityConfigurationOptions)
[Service] IOptionsSnapshot<SecurityConfiguration> securityConfigurationOptions)
{
ArgumentNullException.ThrowIfNull(securityConfigurationOptions);
return securityConfigurationOptions.Value.OidcStrictMode;
@@ -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)
@@ -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));
@@ -162,7 +161,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);
@@ -45,21 +45,21 @@ namespace Tgstation.Server.Host.Security
/// </summary>
readonly IIdentityCache identityCache;
/// <summary>
/// The <see cref="IOptions{TOptions}"/> of <see cref="SwarmConfiguration"/> for the <see cref="AuthenticationContextFactory"/>.
/// </summary>
readonly IOptions<SwarmConfiguration> swarmConfigurationOptions;
/// <summary>
/// The <see cref="IOptionsSnapshot{TOptions}"/> of <see cref="SecurityConfiguration"/> for the <see cref="AuthenticationContextFactory"/>.
/// </summary>
readonly IOptionsSnapshot<SecurityConfiguration> securityConfigurationOptions;
/// <summary>
/// The <see cref="ILogger"/> for the <see cref="AuthenticationContextFactory"/>.
/// </summary>
readonly ILogger<AuthenticationContextFactory> logger;
/// <summary>
/// The <see cref="SwarmConfiguration"/> for the <see cref="AuthenticationContextFactory"/>.
/// </summary>
readonly SwarmConfiguration swarmConfiguration;
/// <summary>
/// The <see cref="SecurityConfiguration"/> for the <see cref="AuthenticationContextFactory"/>.
/// </summary>
readonly SecurityConfiguration securityConfiguration;
/// <summary>
/// Backing field for <see cref="CurrentAuthenticationContext"/>.
/// </summary>
@@ -81,15 +81,15 @@ namespace Tgstation.Server.Host.Security
/// <param name="databaseContext">The value of <see cref="databaseContext"/>.</param>
/// <param name="identityCache">The value of <see cref="identityCache"/>.</param>
/// <param name="apiHeadersProvider">The <see cref="IApiHeadersProvider"/> containing the value of <see cref="apiHeaders"/>.</param>
/// <param name="swarmConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="swarmConfiguration"/>.</param>
/// <param name="securityConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="securityConfiguration"/>.</param>
/// <param name="swarmConfigurationOptions">The value of <see cref="swarmConfigurationOptions"/>.</param>
/// <param name="securityConfigurationOptions">The value of <see cref="securityConfigurationOptions"/>.</param>
/// <param name="logger">The value of <see cref="logger"/>.</param>
public AuthenticationContextFactory(
IDatabaseContext databaseContext,
IIdentityCache identityCache,
IApiHeadersProvider apiHeadersProvider,
IOptions<SwarmConfiguration> swarmConfigurationOptions,
IOptions<SecurityConfiguration> securityConfigurationOptions,
IOptionsSnapshot<SecurityConfiguration> securityConfigurationOptions,
ILogger<AuthenticationContextFactory> 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)
@@ -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);
@@ -31,11 +31,12 @@ namespace Tgstation.Server.Host.Security.OAuth
IGitHubServiceFactory gitHubServiceFactory,
IHttpClientFactory httpClientFactory,
ILoggerFactory loggerFactory,
IOptions<SecurityConfiguration> securityConfigurationOptions)
IOptionsSnapshot<SecurityConfiguration> securityConfigurationOptions)
{
ArgumentNullException.ThrowIfNull(loggerFactory);
ArgumentNullException.ThrowIfNull(securityConfigurationOptions);
var securityConfiguration = securityConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(securityConfigurationOptions));
var securityConfiguration = securityConfigurationOptions.Value;
var validatorsBuilder = new List<IOAuthValidator>();
validators = validatorsBuilder;
@@ -66,9 +67,7 @@ namespace Tgstation.Server.Host.Security.OAuth
loggerFactory.CreateLogger<KeycloakOAuthValidator>(),
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,
@@ -39,9 +39,9 @@ namespace Tgstation.Server.Host.Security
}
/// <summary>
/// The <see cref="SecurityConfiguration"/> for the <see cref="TokenFactory"/>.
/// The <see cref="IOptions{TOptions}"/> of <see cref="SecurityConfiguration"/> for the <see cref="TokenFactory"/>.
/// </summary>
readonly SecurityConfiguration securityConfiguration;
readonly IOptions<SecurityConfiguration> securityConfigurationOptions;
/// <summary>
/// The <see cref="JwtSecurityTokenHandler"/> used to generate <see cref="TokenResponse.Bearer"/> <see cref="string"/>s.
@@ -63,7 +63,7 @@ namespace Tgstation.Server.Host.Security
/// </summary>
/// <param name="cryptographySuite">The <see cref="ICryptographySuite"/> used for generating the <see cref="ValidationParameters"/>.</param>
/// <param name="assemblyInformationProvider">The <see cref="IAssemblyInformationProvider"/> used to generate the issuer name.</param>
/// <param name="securityConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="securityConfiguration"/>.</param>
/// <param name="securityConfigurationOptions">The value of <see cref="securityConfigurationOptions"/>.</param>
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,
+8 -9
View File
@@ -68,16 +68,16 @@ namespace Tgstation.Server.Host
/// </summary>
readonly object restartLock;
/// <summary>
/// The <see cref="IOptionsMonitor{TOptions}"/> of <see cref="GeneralConfiguration"/> for the <see cref="Server"/>.
/// </summary>
IOptionsMonitor<GeneralConfiguration>? generalConfigurationOptions;
/// <summary>
/// The <see cref="ILogger"/> for the <see cref="Server"/>.
/// </summary>
ILogger<Server>? logger;
/// <summary>
/// The <see cref="GeneralConfiguration"/> for the <see cref="Server"/>.
/// </summary>
GeneralConfiguration? generalConfiguration;
/// <summary>
/// The <see cref="cancellationTokenSource"/> for the <see cref="Server"/>.
/// </summary>
@@ -151,8 +151,7 @@ namespace Tgstation.Server.Host
if (await DumpGraphQLSchemaIfRequested(Host.Services, cancellationToken))
return;
var generalConfigurationOptions = Host.Services.GetRequiredService<IOptions<GeneralConfiguration>>();
generalConfiguration = generalConfigurationOptions.Value;
generalConfigurationOptions = Host.Services.GetRequiredService<IOptionsMonitor<GeneralConfiguration>>();
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
{
+31 -31
View File
@@ -47,7 +47,7 @@ namespace Tgstation.Server.Host.Swarm
return true;
lock (swarmServers)
return swarmServers.Count - 1 >= swarmConfiguration.UpdateRequiredNodeCount;
return swarmServers.Count - 1 >= swarmConfigurationOptions.Value.UpdateRequiredNodeCount;
}
}
@@ -55,7 +55,7 @@ namespace Tgstation.Server.Host.Swarm
/// If the swarm system is enabled.
/// </summary>
[MemberNotNullWhen(true, nameof(serverHealthCheckTask), nameof(forceHealthCheckTcs), nameof(serverHealthCheckCancellationTokenSource), nameof(swarmServers))]
bool SwarmMode => swarmConfiguration.PrivateKey != null;
bool SwarmMode => swarmConfigurationOptions.Value.PrivateKey != null;
/// <summary>
/// The <see cref="IDatabaseContextFactory"/> for the <see cref="SwarmService"/>.
@@ -97,16 +97,16 @@ namespace Tgstation.Server.Host.Swarm
/// </summary>
readonly ITokenFactory tokenFactory;
/// <summary>
/// The <see cref="IOptions{TOptions}"/> of <see cref="SwarmConfiguration"/> for the <see cref="SwarmService"/>.
/// </summary>
readonly IOptions<SwarmConfiguration> swarmConfigurationOptions;
/// <summary>
/// The <see cref="ILogger"/> for the <see cref="SwarmService"/>.
/// </summary>
readonly ILogger<SwarmService> logger;
/// <summary>
/// The <see cref="SwarmConfiguration"/> for the <see cref="SwarmService"/>.
/// </summary>
readonly SwarmConfiguration swarmConfiguration;
/// <summary>
/// The <see cref="CancellationTokenSource"/> for <see cref="serverHealthCheckTask"/>.
/// </summary>
@@ -168,7 +168,7 @@ namespace Tgstation.Server.Host.Swarm
/// <param name="asyncDelayer">The value of <see cref="asyncDelayer"/>.</param>
/// <param name="transferService">The value of <see cref="transferService"/>.</param>
/// <param name="tokenFactory">The value of <see cref="tokenFactory"/>.</param>
/// <param name="swarmConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="swarmConfiguration"/>.</param>
/// <param name="swarmConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="swarmConfigurationOptions"/>.</param>
/// <param name="logger">The value of <see cref="logger"/>.</param>
public SwarmService(
IDatabaseContextFactory databaseContextFactory,
@@ -190,18 +190,18 @@ namespace Tgstation.Server.Host.Swarm
this.serverUpdater = serverUpdater ?? throw new ArgumentNullException(nameof(serverUpdater));
this.transferService = transferService ?? throw new ArgumentNullException(nameof(transferService));
this.tokenFactory = tokenFactory ?? throw new ArgumentNullException(nameof(tokenFactory));
swarmConfiguration = swarmConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(swarmConfigurationOptions));
this.swarmConfigurationOptions = swarmConfigurationOptions ?? throw new ArgumentNullException(nameof(swarmConfigurationOptions));
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
if (SwarmMode)
{
if (swarmConfiguration.Address == null)
if (this.swarmConfigurationOptions.Value.Address == null)
throw new InvalidOperationException("Swarm configuration missing Address!");
if (String.IsNullOrWhiteSpace(swarmConfiguration.Identifier))
if (string.IsNullOrWhiteSpace(this.swarmConfigurationOptions.Value.Identifier))
throw new InvalidOperationException("Swarm configuration missing Identifier!");
swarmController = swarmConfiguration.ControllerAddress == null;
swarmController = this.swarmConfigurationOptions.Value.ControllerAddress == null;
if (swarmController)
registrationIdsAndTimes = new();
@@ -212,10 +212,10 @@ namespace Tgstation.Server.Host.Swarm
{
new()
{
Address = swarmConfiguration.Address,
PublicAddress = swarmConfiguration.PublicAddress,
Address = this.swarmConfigurationOptions.Value.Address,
PublicAddress = this.swarmConfigurationOptions.Value.PublicAddress,
Controller = swarmController,
Identifier = swarmConfiguration.Identifier,
Identifier = this.swarmConfigurationOptions.Value.Identifier,
},
};
}
@@ -410,15 +410,15 @@ namespace Tgstation.Server.Host.Swarm
swarmController
? "Controller"
: "Node",
swarmConfiguration.Identifier);
swarmConfigurationOptions.Value.Identifier);
else
logger.LogTrace("Swarm mode disabled");
SwarmRegistrationResult result;
if (swarmController)
{
if (swarmConfiguration.UpdateRequiredNodeCount > 0)
logger.LogInformation("Expecting connections from {expectedNodeCount} nodes", swarmConfiguration.UpdateRequiredNodeCount);
if (swarmConfigurationOptions.Value.UpdateRequiredNodeCount > 0)
logger.LogInformation("Expecting connections from {expectedNodeCount} nodes", swarmConfigurationOptions.Value.UpdateRequiredNodeCount);
await databaseContextFactory.UseContext(
databaseContext => databaseSeeder.Initialize(databaseContext, cancellationToken));
@@ -738,7 +738,7 @@ namespace Tgstation.Server.Host.Swarm
if (!swarmController)
return SendRemoteAbort(new SwarmServerInformation
{
Address = swarmConfiguration.ControllerAddress,
Address = swarmConfigurationOptions.Value.ControllerAddress,
});
lock (swarmServers!)
@@ -856,7 +856,7 @@ namespace Tgstation.Server.Host.Swarm
new SwarmUpdateRequest
{
UpdateVersion = version,
SourceNode = swarmConfiguration.Identifier,
SourceNode = swarmConfigurationOptions.Value.Identifier,
DownloadTickets = downloadTickets,
});
@@ -891,7 +891,7 @@ namespace Tgstation.Server.Host.Swarm
return SwarmPrepareResult.Failure;
}
if (!updateRequest.DownloadTickets.TryGetValue(swarmConfiguration.Identifier!, out var ticket))
if (!updateRequest.DownloadTickets.TryGetValue(swarmConfigurationOptions.Value.Identifier!, out var ticket))
{
logger.Log(
swarmController
@@ -971,11 +971,11 @@ namespace Tgstation.Server.Host.Swarm
{
logger.LogInformation("Sending remote prepare to nodes...");
if (currentUpdateOperation.InvolvedServers.Count - 1 < swarmConfiguration.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}!",
swarmConfiguration.UpdateRequiredNodeCount,
swarmConfigurationOptions.Value.UpdateRequiredNodeCount,
currentUpdateOperation.InvolvedServers.Count - 1);
abortUpdate = true;
return SwarmPrepareResult.Failure;
@@ -1008,7 +1008,7 @@ namespace Tgstation.Server.Host.Swarm
: updateRequest.DownloadTickets!;
var sourceNode = weAreInitiator
? swarmConfiguration.Identifier
? swarmConfigurationOptions.Value.Identifier
: updateRequest.SourceNode;
using var httpClient = httpClientFactory.CreateClient();
@@ -1119,7 +1119,7 @@ namespace Tgstation.Server.Host.Swarm
false);
var serversRequiringTickets = involvedServers
.Where(node => node.Identifier != swarmConfiguration.Identifier)
.Where(node => node.Identifier != swarmConfigurationOptions.Value.Identifier)
.ToList();
logger.LogTrace("Creating {n} download tickets for other nodes...", serversRequiringTickets.Count);
@@ -1276,7 +1276,7 @@ namespace Tgstation.Server.Host.Swarm
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="SwarmRegistrationResult"/>.</returns>
async ValueTask<SwarmRegistrationResult> RegisterWithController(CancellationToken cancellationToken)
{
logger.LogInformation("Attempting to register with swarm controller at {controllerAddress}...", swarmConfiguration.ControllerAddress);
logger.LogInformation("Attempting to register with swarm controller at {controllerAddress}...", swarmConfigurationOptions.Value.ControllerAddress);
var requestedRegistrationId = Guid.NewGuid();
using var httpClient = httpClientFactory.CreateClient();
@@ -1286,9 +1286,9 @@ namespace Tgstation.Server.Host.Swarm
SwarmConstants.RegisterRoute,
new SwarmRegistrationRequest(Version.Parse(MasterVersionsAttribute.Instance.RawSwarmProtocolVersion))
{
Identifier = swarmConfiguration.Identifier,
Address = swarmConfiguration.Address,
PublicAddress = swarmConfiguration.PublicAddress,
Identifier = swarmConfigurationOptions.Value.Identifier,
Address = swarmConfigurationOptions.Value.Address,
PublicAddress = swarmConfigurationOptions.Value.PublicAddress,
},
requestedRegistrationId);
@@ -1436,7 +1436,7 @@ namespace Tgstation.Server.Host.Swarm
{
swarmServer ??= new SwarmServerInformation
{
Address = swarmConfiguration.ControllerAddress,
Address = swarmConfigurationOptions.Value.ControllerAddress,
};
var fullRoute = $"{SwarmConstants.ControllerRoute}/{route}";
@@ -1454,7 +1454,7 @@ namespace Tgstation.Server.Host.Swarm
request.Headers.Accept.Clear();
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json));
request.Headers.Add(SwarmConstants.ApiKeyHeader, swarmConfiguration.PrivateKey);
request.Headers.Add(SwarmConstants.ApiKeyHeader, swarmConfigurationOptions.Value.PrivateKey);
if (registrationIdOverride.HasValue)
request.Headers.Add(SwarmConstants.RegistrationIdHeader, registrationIdOverride.Value.ToString());
else if (swarmController)
@@ -50,16 +50,16 @@ namespace Tgstation.Server.Host.Utils.GitHub
/// </summary>
readonly IHttpMessageHandlerFactory httpMessageHandlerFactory;
/// <summary>
/// The <see cref="IOptionsMonitor{TOptions}"/> of <see cref="GeneralConfiguration"/> for the <see cref="GitHubClientFactory"/>.
/// </summary>
readonly IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions;
/// <summary>
/// The <see cref="ILogger"/> for the <see cref="GitHubClientFactory"/>.
/// </summary>
readonly ILogger<GitHubClientFactory> logger;
/// <summary>
/// The <see cref="GeneralConfiguration"/> for the <see cref="GitHubClientFactory"/>.
/// </summary>
readonly GeneralConfiguration generalConfiguration;
/// <summary>
/// Cache of created <see cref="GitHubClient"/>s and last used/expiry times, keyed by access token.
/// </summary>
@@ -76,17 +76,17 @@ namespace Tgstation.Server.Host.Utils.GitHub
/// <param name="assemblyInformationProvider">The value of <see cref="assemblyInformationProvider"/>.</param>
/// <param name="httpMessageHandlerFactory">The value of <see cref="httpMessageHandlerFactory"/>.</param>
/// <param name="logger">The value of <see cref="logger"/>.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="generalConfiguration"/>.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="generalConfigurationOptions"/>.</param>
public GitHubClientFactory(
IAssemblyInformationProvider assemblyInformationProvider,
IHttpMessageHandlerFactory httpMessageHandlerFactory,
ILogger<GitHubClientFactory> logger,
IOptions<GeneralConfiguration> generalConfigurationOptions)
IOptionsMonitor<GeneralConfiguration> generalConfigurationOptions,
ILogger<GitHubClientFactory> 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<string, (GitHubClient, DateTimeOffset, DateTimeOffset?)>();
clientCacheSemaphore = new SemaphoreSlim(1, 1);
@@ -98,7 +98,7 @@ namespace Tgstation.Server.Host.Utils.GitHub
/// <inheritdoc />
public async ValueTask<IGitHubClient> CreateClient(CancellationToken cancellationToken)
=> (await GetOrCreateClient(
generalConfiguration.GitHubAccessToken,
generalConfigurationOptions.CurrentValue.GitHubAccessToken,
null,
cancellationToken))!;
@@ -27,22 +27,22 @@ namespace Tgstation.Server.Host.Utils.GitHub
/// <summary>
/// The <see cref="UpdatesConfiguration"/> for the <see cref="GitHubServiceFactory"/>.
/// </summary>
readonly UpdatesConfiguration updatesConfiguration;
readonly IOptionsMonitor<UpdatesConfiguration> updatesConfigurationOptions;
/// <summary>
/// Initializes a new instance of the <see cref="GitHubServiceFactory"/> class.
/// </summary>
/// <param name="gitHubClientFactory">The value of <see cref="gitHubClientFactory"/>.</param>
/// <param name="loggerFactory">The value of <see cref="loggerFactory"/>.</param>
/// <param name="updatesConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing value of <see cref="updatesConfiguration"/>.</param>
/// <param name="updatesConfigurationOptions">The value of <see cref="updatesConfigurationOptions"/>.</param>
public GitHubServiceFactory(
IGitHubClientFactory gitHubClientFactory,
ILoggerFactory loggerFactory,
IOptions<UpdatesConfiguration> updatesConfigurationOptions)
IOptionsMonitor<UpdatesConfiguration> 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));
}
/// <inheritdoc />
@@ -79,6 +79,6 @@ namespace Tgstation.Server.Host.Utils.GitHub
=> new(
gitHubClient,
loggerFactory.CreateLogger<GitHubService>(),
updatesConfiguration);
updatesConfigurationOptions.CurrentValue);
}
}
@@ -34,16 +34,16 @@ namespace Tgstation.Server.Host.Utils
/// </summary>
readonly IPlatformIdentifier platformIdentifier;
/// <summary>
/// The <see cref="IOptions{TOptions}"/> of <see cref="SwarmConfiguration"/> for the <see cref="PortAllocator"/>.
/// </summary>
readonly IOptions<SwarmConfiguration> swarmConfigurationOptions;
/// <summary>
/// The <see cref="ILogger"/> for the <see cref="PortAllocator"/>.
/// </summary>
readonly ILogger<PortAllocator> logger;
/// <summary>
/// The <see cref="SwarmConfiguration"/> for the <see cref="PortAllocator"/>.
/// </summary>
readonly SwarmConfiguration swarmConfiguration;
/// <summary>
/// The <see cref="SemaphoreSlim"/> used to serialized port requisition requests.
/// </summary>
@@ -55,7 +55,7 @@ namespace Tgstation.Server.Host.Utils
/// <param name="serverPortProvider">The value of <see cref="serverPortProvider"/>.</param>
/// <param name="databaseContextFactory">The value of <see cref="databaseContextFactory"/>.</param>
/// <param name="platformIdentifier">The value of <see cref="platformIdentifier"/>.</param>
/// <param name="swarmConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="swarmConfiguration"/>.</param>
/// <param name="swarmConfigurationOptions">The value of <see cref="swarmConfigurationOptions"/>.</param>
/// <param name="logger">The value of <see cref="logger"/>.</param>
public PortAllocator(
IServerPortProvider serverPortProvider,
@@ -67,7 +67,7 @@ namespace Tgstation.Server.Host.Utils
this.serverPortProvider = serverPortProvider ?? throw new ArgumentNullException(nameof(serverPortProvider));
this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
swarmConfiguration = swarmConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(swarmConfigurationOptions));
this.swarmConfigurationOptions = swarmConfigurationOptions ?? throw new ArgumentNullException(nameof(swarmConfigurationOptions));
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
allocatorLock = new SemaphoreSlim(1);
@@ -99,8 +99,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,
@@ -110,8 +109,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,
@@ -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<ArgumentNullException>(() => new DiscordProvider(mockJobManager, mockDel, mockLogger, null, null, null));
var mockAss = Mock.Of<IAssemblyInformationProvider>();
Assert.ThrowsExactly<ArgumentNullException>(() => new DiscordProvider(mockJobManager, mockDel, mockLogger, mockAss, null, null));
Assert.ThrowsExactly<ArgumentNullException>(() => 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<IOptionsMonitor<GeneralConfiguration>>();
Assert.ThrowsExactly<ArgumentNullException>(() => 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<ILogger<DiscordProvider>>();
await using var provider = new DiscordProvider(mockJobManager, Mock.Of<IAsyncDelayer>(), mockLogger.Object, Mock.Of<IAssemblyInformationProvider>(), new ChatBot
await using var provider = new DiscordProvider(mockJobManager, Mock.Of<IAsyncDelayer>(), mockLogger.Object, Mock.Of<IAssemblyInformationProvider>(), Mock.Of<IOptionsMonitor<GeneralConfiguration>>(), new ChatBot
{
ReconnectionInterval = 1,
ConnectionString = "asdf",
Instance = new Models.Instance(),
}, new GeneralConfiguration());
});
await Assert.ThrowsExactlyAsync<JobException>(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<ILogger<DiscordProvider>>();
await using var provider = new DiscordProvider(mockJobManager, Mock.Of<IAsyncDelayer>(), mockLogger.Object, Mock.Of<IAssemblyInformationProvider>(), testToken1, new GeneralConfiguration());
await using var provider = new DiscordProvider(mockJobManager, Mock.Of<IAsyncDelayer>(), mockLogger.Object, Mock.Of<IAssemblyInformationProvider>(), Mock.Of<IOptionsMonitor<GeneralConfiguration>>(), testToken1);
Assert.IsFalse(provider.Connected);
await InvokeConnect(provider);
Assert.IsTrue(provider.Connected);
@@ -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<ArgumentNullException>(() => new IrcProvider(mockJobManager.Object, mockAsyncDelayer.Object, null, null, null, null));
var mockLogger = new Mock<ILogger<IrcProvider>>();
Assert.ThrowsExactly<ArgumentNullException>(() => new IrcProvider(mockJobManager.Object, mockAsyncDelayer.Object, mockLogger.Object, null, null, null));
var mockAss = new Mock<IAssemblyInformationProvider>();
Assert.ThrowsExactly<ArgumentNullException>(() => 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<ArgumentNullException>(() => new IrcProvider(mockJobManager.Object, mockAsyncDelayer.Object, mockLogger.Object, mockAss.Object, mockBot, null));
Assert.ThrowsExactly<ArgumentNullException>(() => new IrcProvider(mockJobManager.Object, mockAsyncDelayer.Object, mockLogger.Object, mockBot, null, null));
var mockLogConf = new FileLoggingConfiguration();
Assert.ThrowsExactly<InvalidOperationException>(() => new IrcProvider(mockJobManager.Object, mockAsyncDelayer.Object, mockLogger.Object, mockAss.Object, mockBot, mockLogConf));
var mockAss = new Mock<IAssemblyInformationProvider>();
Assert.ThrowsExactly<ArgumentNullException>(() => new IrcProvider(mockJobManager.Object, mockAsyncDelayer.Object, mockLogger.Object, mockBot, mockAss.Object, null));
var mockLogConf = new Mock<IOptionsMonitor<FileLoggingConfiguration>>();
mockLogConf.SetupGet(x => x.CurrentValue).Returns(new FileLoggingConfiguration());
Assert.ThrowsExactly<InvalidOperationException>(() => 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<AsyncDelayer>()), loggerFactory.CreateLogger<IrcProvider>(), Mock.Of<IAssemblyInformationProvider>(), chatBot, new FileLoggingConfiguration());
var mockLogConf = new Mock<IOptionsMonitor<FileLoggingConfiguration>>();
mockLogConf.SetupGet(x => x.CurrentValue).Returns(new FileLoggingConfiguration());
await using var provider = new IrcProvider(mockJobManager, new AsyncDelayer(loggerFactory.CreateLogger<AsyncDelayer>()), loggerFactory.CreateLogger<IrcProvider>(), chatBot, Mock.Of<IAssemblyInformationProvider>(), mockLogConf.Object);
Assert.IsFalse(provider.Connected);
await InvokeConnect(provider);
Assert.IsTrue(provider.Connected);
@@ -35,13 +35,13 @@ namespace Tgstation.Server.Host.Components.Engine.Tests
static async Task RepoDownloadTest(bool needsClone)
{
var mockGeneralConfigOptions = new Mock<IOptions<GeneralConfiguration>>();
var mockGeneralConfigOptions = new Mock<IOptionsMonitor<GeneralConfiguration>>();
var generalConfig = new GeneralConfiguration();
var mockSessionConfigOptions = new Mock<IOptions<SessionConfiguration>>();
var mockSessionConfigOptions = new Mock<IOptionsMonitor<SessionConfiguration>>();
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<IRepository>();
@@ -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<IEventConsumer>(),
Mock.Of<IPostWriteHandler>(),
mockGitRemoteFeaturesFactory.Object,
Mock.Of<IOptionsMonitor<GeneralConfiguration>>(),
Mock.Of<ILogger<Repository>>(),
Mock.Of<ILogger<RepositoryManager>>(),
new GeneralConfiguration());
Mock.Of<ILogger<RepositoryManager>>());
}
[TestCleanup]
@@ -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<IPostWriteHandler>(),
Mock.Of<IPlatformIdentifier>(),
Mock.Of<IFileTransferTicketProvider>(),
Mock.Of<IOptionsMonitor<GeneralConfiguration>>(),
Mock.Of<IOptionsMonitor<SessionConfiguration>>(),
loggerFactory.CreateLogger<Configuration>(),
new Models.Instance
{
Path = "Some path",
},
new GeneralConfiguration(),
new SessionConfiguration());
});
await configuration.StartAsync(CancellationToken.None);
@@ -47,7 +47,7 @@ namespace Tgstation.Server.Host.Utils.GitHub.Tests
Assert.ThrowsExactly<ArgumentNullException>(() => new GitHubClientFactory(null, null, null, null));
Assert.ThrowsExactly<ArgumentNullException>(() => new GitHubClientFactory(Mock.Of<IAssemblyInformationProvider>(), null, null, null));
Assert.ThrowsExactly<ArgumentNullException>(() => new GitHubClientFactory(Mock.Of<IAssemblyInformationProvider>(), Mock.Of<IHttpMessageHandlerFactory>(), null, null));
Assert.ThrowsExactly<ArgumentNullException>(() => new GitHubClientFactory(Mock.Of<IAssemblyInformationProvider>(), Mock.Of<IHttpMessageHandlerFactory>(), Mock.Of<ILogger<GitHubClientFactory>>(), null));
Assert.ThrowsExactly<ArgumentNullException>(() => new GitHubClientFactory(Mock.Of<IAssemblyInformationProvider>(), Mock.Of<IHttpMessageHandlerFactory>(), Mock.Of<IOptionsMonitor<GeneralConfiguration>>(), null));
}
[TestMethod]
@@ -56,12 +56,12 @@ namespace Tgstation.Server.Host.Utils.GitHub.Tests
var mockApp = new Mock<IAssemblyInformationProvider>();
mockApp.SetupGet(x => x.ProductInfoHeaderValue).Returns(new ProductInfoHeaderValue("TGSTests", "1.2.3")).Verifiable();
var mockOptions = new Mock<IOptions<GeneralConfiguration>>();
var mockOptions = new Mock<IOptionsMonitor<GeneralConfiguration>>();
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<GitHubClientFactory>(), mockOptions.Object);
mockOptions.SetupGet(x => x.CurrentValue).Returns(gc);
var factory = new GitHubClientFactory(mockApp.Object, new BasicHttpMessageHandlerFactory(), mockOptions.Object, loggerFactory.CreateLogger<GitHubClientFactory>());
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<IAssemblyInformationProvider>();
mockApp.SetupGet(x => x.ProductInfoHeaderValue).Returns(new ProductInfoHeaderValue("TGSTests", "1.2.3")).Verifiable();
var mockOptions = new Mock<IOptions<GeneralConfiguration>>();
mockOptions.SetupGet(x => x.Value).Returns(new GeneralConfiguration());
var factory = new GitHubClientFactory(mockApp.Object, new BasicHttpMessageHandlerFactory(), loggerFactory.CreateLogger<GitHubClientFactory>(), mockOptions.Object);
var mockOptions = new Mock<IOptionsMonitor<GeneralConfiguration>>();
mockOptions.SetupGet(x => x.CurrentValue).Returns(new GeneralConfiguration());
var factory = new GitHubClientFactory(mockApp.Object, new BasicHttpMessageHandlerFactory(), mockOptions.Object, loggerFactory.CreateLogger<GitHubClientFactory>());
await Assert.ThrowsExactlyAsync<ArgumentNullException>(() => factory.CreateClient(null, CancellationToken.None).AsTask());
@@ -107,9 +107,9 @@ namespace Tgstation.Server.Host.Utils.GitHub.Tests
var mockApp = new Mock<IAssemblyInformationProvider>();
mockApp.SetupGet(x => x.ProductInfoHeaderValue).Returns(new ProductInfoHeaderValue("TGSTests", "1.2.3")).Verifiable();
var mockOptions = new Mock<IOptions<GeneralConfiguration>>();
mockOptions.SetupGet(x => x.Value).Returns(new GeneralConfiguration());
var factory = new GitHubClientFactory(mockApp.Object, new BasicHttpMessageHandlerFactory(), loggerFactory.CreateLogger<GitHubClientFactory>(), mockOptions.Object);
var mockOptions = new Mock<IOptionsMonitor<GeneralConfiguration>>();
mockOptions.SetupGet(x => x.CurrentValue).Returns(new GeneralConfiguration());
var factory = new GitHubClientFactory(mockApp.Object, new BasicHttpMessageHandlerFactory(), mockOptions.Object, loggerFactory.CreateLogger<GitHubClientFactory>());
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<IAssemblyInformationProvider>();
mockApp.SetupGet(x => x.ProductInfoHeaderValue).Returns(new ProductInfoHeaderValue("TGSTests", "1.2.3")).Verifiable();
var mockOptions = new Mock<IOptions<GeneralConfiguration>>();
mockOptions.SetupGet(x => x.Value).Returns(new GeneralConfiguration());
var factory = new GitHubClientFactory(mockApp.Object, new BasicHttpMessageHandlerFactory(), loggerFactory.CreateLogger<GitHubClientFactory>(), mockOptions.Object);
var mockOptions = new Mock<IOptionsMonitor<GeneralConfiguration>>();
mockOptions.SetupGet(x => x.CurrentValue).Returns(new GeneralConfiguration());
var factory = new GitHubClientFactory(mockApp.Object, new BasicHttpMessageHandlerFactory(), mockOptions.Object, loggerFactory.CreateLogger<GitHubClientFactory>());
await Assert.ThrowsExactlyAsync<ArgumentNullException>(() => factory.CreateClient(null, CancellationToken.None).AsTask());
@@ -193,9 +193,9 @@ vTdVAoGBAI/jjUMdjkY43zhe3w2piwT0fhGfqm9ikdAB9IcgcptuS0ML0ZaWV/eO
var mockApp = new Mock<IAssemblyInformationProvider>();
mockApp.SetupGet(x => x.ProductInfoHeaderValue).Returns(new ProductInfoHeaderValue("TGSTests", "1.2.3")).Verifiable();
var mockOptions = new Mock<IOptions<GeneralConfiguration>>();
mockOptions.SetupGet(x => x.Value).Returns(new GeneralConfiguration());
var factory = new GitHubClientFactory(mockApp.Object, new BasicHttpMessageHandlerFactory(), loggerFactory.CreateLogger<GitHubClientFactory>(), mockOptions.Object);
var mockOptions = new Mock<IOptionsMonitor<GeneralConfiguration>>();
mockOptions.SetupGet(x => x.CurrentValue).Returns(new GeneralConfiguration());
var factory = new GitHubClientFactory(mockApp.Object, new BasicHttpMessageHandlerFactory(), mockOptions.Object, loggerFactory.CreateLogger<GitHubClientFactory>());
var client1 = await factory.CreateClient(CancellationToken.None);
var client2 = await factory.CreateClient("asdf", CancellationToken.None);
@@ -23,8 +23,8 @@ namespace Tgstation.Server.Host.Utils.GitHub.Tests
Assert.ThrowsExactly<ArgumentNullException>(() => new GitHubServiceFactory(null, null, null));
Assert.ThrowsExactly<ArgumentNullException>(() => new GitHubServiceFactory(Mock.Of<IGitHubClientFactory>(), null, null));
Assert.ThrowsExactly<ArgumentNullException>(() => new GitHubServiceFactory(Mock.Of<IGitHubClientFactory>(), Mock.Of<ILoggerFactory>(), null));
var mockOptions = new Mock<IOptions<UpdatesConfiguration>>();
mockOptions.SetupGet(x => x.Value).Returns(new UpdatesConfiguration());
var mockOptions = new Mock<IOptionsMonitor<UpdatesConfiguration>>();
mockOptions.SetupGet(x => x.CurrentValue).Returns(new UpdatesConfiguration());
_ = new GitHubServiceFactory(Mock.Of<IGitHubClientFactory>(), Mock.Of<ILoggerFactory>(), mockOptions.Object);
}
@@ -41,8 +41,8 @@ namespace Tgstation.Server.Host.Utils.GitHub.Tests
mockFactory.Setup(x => x.CreateClient(mockToken, It.IsAny<CancellationToken>())).Returns(ValueTask.FromResult(Mock.Of<IGitHubClient>())).Verifiable();
#pragma warning restore CA2012 // Use ValueTasks correctly
var mockOptions = new Mock<IOptions<UpdatesConfiguration>>();
mockOptions.SetupGet(x => x.Value).Returns(new UpdatesConfiguration());
var mockOptions = new Mock<IOptionsMonitor<UpdatesConfiguration>>();
mockOptions.SetupGet(x => x.CurrentValue).Returns(new UpdatesConfiguration());
var factory = new GitHubServiceFactory(mockFactory.Object, Mock.Of<ILoggerFactory>(), mockOptions.Object);
@@ -270,8 +270,8 @@ namespace Tgstation.Server.Tests.Live.Instance
{
ByondZipDownloadTemplate = TestingUtils.ByondZipDownloadTemplate,
});
var sessionConfigOptionsMock = new Mock<IOptions<SessionConfiguration>>();
sessionConfigOptionsMock.SetupGet(x => x.Value).Returns(new SessionConfiguration());
var sessionConfigOptionsMock = new Mock<IOptionsMonitor<SessionConfiguration>>();
sessionConfigOptionsMock.SetupGet(x => x.CurrentValue).Returns(new SessionConfiguration());
var assemblyInformationProvider = new AssemblyInformationProvider();
@@ -122,20 +122,20 @@ namespace Tgstation.Server.Tests.Live.Instance
new NoopEventConsumer(),
Mock.Of<IPostWriteHandler>(),
Mock.Of<IGitRemoteFeaturesFactory>(),
mockOptionsMonitor.Object,
Mock.Of<ILogger<Repository>>(),
Mock.Of<ILogger<RepositoryManager>>(),
genConfig),
Mock.Of<ILogger<RepositoryManager>>()),
Mock.Of<IAsyncDelayer>(),
Mock.Of<IHttpClientFactory>(),
Options.Create(genConfig),
Options.Create(new SessionConfiguration()))
mockOptionsMonitor.Object,
Mock.Of<IOptionsMonitor<SessionConfiguration>>())
: new PlatformIdentifier().IsWindows
? new WindowsByondInstaller(
Mock.Of<IProcessExecutor>(),
Mock.Of<IIOManager>(),
fileDownloader,
mockOptionsMonitor.Object,
Options.Create(new SessionConfiguration()),
Mock.Of<IOptionsMonitor<SessionConfiguration>>(),
Mock.Of<ILogger<WindowsByondInstaller>>())
: new PosixByondInstaller(
Mock.Of<IPostWriteHandler>(),
@@ -1613,7 +1613,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();
@@ -34,13 +34,13 @@ namespace Tgstation.Server.Tests.Live
static TestingGitHubService()
{
var mockOptions = new Mock<IOptions<GeneralConfiguration>>();
mockOptions.SetupGet(x => x.Value).Returns(new GeneralConfiguration
var mockOptions = new Mock<IOptionsMonitor<GeneralConfiguration>>();
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<ILogger<GitHubClientFactory>>(), mockOptions.Object);
var gitHubClientFactory = new GitHubClientFactory(new AssemblyInformationProvider(), new BasicHttpMessageHandlerFactory(), mockOptions.Object, Mock.Of<ILogger<GitHubClientFactory>>());
RealClient = gitHubClientFactory.CreateClient(CancellationToken.None).GetAwaiter().GetResult();
}
@@ -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<IPostWriteHandler>(),
Mock.Of<IGitRemoteFeaturesFactory>(),
Mock.Of<ILibGit2RepositoryFactory>(),
Mock.Of<IOptionsMonitor<GeneralConfiguration>>(),
Mock.Of<ILogger<Host.Components.Repository.Repository>>(),
new GeneralConfiguration(),
() => { });
const string StartSha = "af4da8beb9f9b374b04a3cc4d65acca662e8cc1a";
@@ -81,9 +82,9 @@ namespace Tgstation.Server.Tests
Mock.Of<IEventConsumer>(),
new WindowsPostWriteHandler(),
Mock.Of<IGitRemoteFeaturesFactory>(),
Mock.Of<IOptionsMonitor<GeneralConfiguration>>(),
Mock.Of<ILogger<Host.Components.Repository.Repository>>(),
Mock.Of<ILogger<RepositoryManager>>(),
new GeneralConfiguration());
Mock.Of<ILogger<RepositoryManager>>());
try
{
using (await manager.CloneRepository(
+4 -4
View File
@@ -112,8 +112,8 @@ namespace Tgstation.Server.Tests
{
ByondZipDownloadTemplate = TestingUtils.ByondZipDownloadTemplate,
});
var mockSessionConfigurationOptions = new Mock<IOptions<SessionConfiguration>>();
mockSessionConfigurationOptions.SetupGet(x => x.Value).Returns(new SessionConfiguration());
var mockSessionConfigurationOptions = new Mock<IOptionsMonitor<SessionConfiguration>>();
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<IOptions<SessionConfiguration>>();
mockSessionConfigurationOptions.SetupGet(x => x.Value).Returns(new SessionConfiguration());
var mockSessionConfigurationOptions = new Mock<IOptionsMonitor<SessionConfiguration>>();
mockSessionConfigurationOptions.SetupGet(x => x.CurrentValue).Returns(new SessionConfiguration());
using var loggerFactory = LoggerFactory.Create(builder =>
{