tgstation-server 6.12.0
The /tg/station 13 server suite
Loading...
Searching...
No Matches
InstanceController.cs
Go to the documentation of this file.
1using System;
4using System.IO;
5using System.Linq;
10
15
16using NCrontab;
17
35
37{
42#pragma warning disable CA1506 // TODO: Decomplexify
44 {
48 public const string InstanceAttachFileName = "TGS4_ALLOW_INSTANCE_ATTACH";
49
54
59
64
69
74
79
84
130
139 [HttpPut]
144 {
145 ArgumentNullException.ThrowIfNull(model);
146
147 if (String.IsNullOrWhiteSpace(model.Name) || String.IsNullOrWhiteSpace(model.Path))
148 return BadRequest(new ErrorMessageResponse(ErrorCode.InstanceWhitespaceNameOrPath));
149
151 if (earlyOut != null)
152 return earlyOut;
153
156
159 return Conflict(new ErrorMessageResponse(ErrorCode.InstanceAtConflictingPath));
160
161 // Validate it's not a child of any other instance
163 .Instances
164 .AsQueryable()
165 .Where(x => x.SwarmIdentifer == swarmConfiguration.Identifier)
166 .Select(x => new Models.Instance
167 {
168 Path = x.Path,
169 })
170 .ToListAsync(cancellationToken);
171
173 return Conflict(new ErrorMessageResponse(ErrorCode.InstanceLimitReached));
174
177 .ToArray();
178
179 await Task.WhenAll(instancePathChecks);
180
181 if (instancePathChecks.Any(task => task.Result))
182 return Conflict(new ErrorMessageResponse(ErrorCode.InstanceAtConflictingPath));
183
184 // Last test, ensure it's in the list of valid paths
187 .ToArray()
188 ?? Enumerable.Empty<Task<bool>>();
189 await Task.WhenAll(pathChecks);
190 if (!pathChecks.All(task => task.Result))
191 return BadRequest(new ErrorMessageResponse(ErrorCode.InstanceNotAtWhitelistedPath));
192
194 {
196 return false;
197
200
203
204 return files.Concat(dirs).Any();
205 }
206
208 bool attached = false;
211 return Conflict(new ErrorMessageResponse(ErrorCode.InstanceAtExistingPath));
212 else
213 attached = true;
214
216 if (newInstance == null)
217 return Conflict(new ErrorMessageResponse(ErrorCode.NoPortsAvailable));
218
220 try
221 {
223
224 try
225 {
226 // actually reserve it now
229 }
230 catch
231 {
232 // oh shit delete the model
234
235 // DCT: Operation must always run
236 await DatabaseContext.Save(CancellationToken.None);
237 throw;
238 }
239 }
240 catch (IOException e)
241 {
242 return Conflict(new ErrorMessageResponse(ErrorCode.IOError)
243 {
244 AdditionalData = e.Message,
245 });
246 }
247
248 Logger.LogInformation(
249 "{userName} {attachedOrCreated} instance {instanceName}: {instanceId} ({instancePath})",
251 attached ? "attached" : "created",
252 newInstance.Name,
253 newInstance.Id,
254 newInstance.Path);
255
257 newInstance.InstancePermissionSets.First(),
259
260 var api = newInstance.ToApi();
261 api.Accessible = true; // instances are always accessible by their creator
262 return attached ? Json(api) : this.Created(api);
263 }
264
273 [HttpDelete("{id}")]
277 public async ValueTask<IActionResult> Delete(long id, CancellationToken cancellationToken)
278 {
280 .Instances
281 .AsQueryable()
282 .Where(x => x.Id == id && x.SwarmIdentifer == swarmConfiguration.Identifier)
283 .FirstOrDefaultAsync(cancellationToken);
284 if (originalModel == default)
285 return this.Gone();
286 if (originalModel.Online!.Value)
287 return Conflict(new ErrorMessageResponse(ErrorCode.InstanceDetachOnline));
288
291 try
292 {
295 }
297 {
298 // DCT: Operation must always run
299 await ioManager.DeleteFile(attachFileName, CancellationToken.None);
300 throw;
301 }
302
303 try
304 {
305 // yes this is racy af. I hate it
306 // there's a bug where removing the root instance doesn't work sometimes
309 .AsQueryable()
310 .Where(x => x.Job!.Instance!.Id == id)
311 .ExecuteDeleteAsync(cancellationToken);
314 .AsQueryable()
315 .Where(x => x.RevisionInformation.InstanceId == id)
316 .ExecuteDeleteAsync(cancellationToken);
319 .AsQueryable()
320 .Where(x => x.InstanceId == id)
321 .ExecuteDeleteAsync(cancellationToken);
322
324 await DatabaseContext.Save(cancellationToken); // cascades everything else
325 }
326 catch
327 {
328 await ioManager.DeleteFile(attachFileName, CancellationToken.None); // DCT: Shouldn't be cancelled
329 throw;
330 }
331
332 return NoContent();
333 }
334
344 [HttpPost]
346 InstanceManagerRights.Relocate
347 | InstanceManagerRights.Rename
348 | InstanceManagerRights.SetAutoUpdate
349 | InstanceManagerRights.SetConfiguration
350 | InstanceManagerRights.SetOnline
351 | InstanceManagerRights.SetChatBotLimit
352 | InstanceManagerRights.SetAutoStart
353 | InstanceManagerRights.SetAutoStop)]
357#pragma warning disable CA1502 // TODO: Decomplexify
359 {
360 ArgumentNullException.ThrowIfNull(model);
361
362 IQueryable<Models.Instance> InstanceQuery() => DatabaseContext
363 .Instances
364 .AsQueryable()
365 .Where(x => x.Id == model.Id && x.SwarmIdentifer == swarmConfiguration.Identifier);
366
368 .SelectMany(x => x.Jobs)
369 .Where(x => !x.StoppedAt.HasValue && x.JobCode == JobCode.Move)
370 .Select(x => new Job(x.Id!.Value))
371 .FirstOrDefaultAsync(cancellationToken);
372
373 if (moveJob != null)
374 {
375 // don't allow them to cancel it if they can't start it.
377 return Forbid();
379 }
380
382 .Include(x => x.RepositorySettings)
383 .Include(x => x.ChatSettings)
384 .ThenInclude(x => x.Channels)
385 .Include(x => x.DreamDaemonSettings) // need these for onlining
386 .FirstOrDefaultAsync(cancellationToken);
387 if (originalModel == default(Models.Instance))
388 return this.Gone();
389
392
395 {
397 var property = (PropertyInfo)memberSelectorExpression.Member;
398
399 var newVal = property.GetValue(model);
400 if (newVal == null)
401 return false;
402 if (!userRights.HasFlag(requiredRight) && property.GetValue(originalModel) != newVal)
403 return true;
404
405 property.SetValue(originalModel, newVal);
406 return false;
407 }
408
409 string? originalModelPath = null;
410 string? normalizedPath = null;
411 var originalOnline = originalModel.Online!.Value;
412 if (model.Path != null)
413 {
415
416 if (normalizedPath != originalModel.Path)
417 {
418 if (!userRights.HasFlag(InstanceManagerRights.Relocate))
419 return Forbid();
420 if (originalOnline && model.Online != true)
421 return Conflict(new ErrorMessageResponse(ErrorCode.InstanceRelocateOnline));
422
425 return Conflict(new ErrorMessageResponse(ErrorCode.InstanceAtExistingPath));
426
429 }
430 }
431
432 var oldAutoUpdateInterval = originalModel.AutoUpdateInterval!.Value;
433 var oldAutoUpdateCron = originalModel.AutoUpdateCron;
434 var oldAutoStartCron = originalModel.AutoStartCron;
435 var oldAutoStopCron = originalModel.AutoStopCron;
436
438 if (earlyOut != null)
439 return earlyOut;
440
443
444 var changedAutoStart = model.AutoStartCron != null && oldAutoStartCron != model.AutoStartCron;
445 var changedAutoStop = model.AutoStopCron != null && oldAutoStopCron != model.AutoStopCron;
446
447 var renamed = model.Name != null && originalModel.Name != model.Name;
448
449 if (CheckModified(x => x.AutoUpdateInterval, InstanceManagerRights.SetAutoUpdate)
450 || CheckModified(x => x.AutoUpdateCron, InstanceManagerRights.SetAutoUpdate)
451 || CheckModified(x => x.ConfigurationType, InstanceManagerRights.SetConfiguration)
452 || CheckModified(x => x.Name, InstanceManagerRights.Rename)
453 || CheckModified(x => x.Online, InstanceManagerRights.SetOnline)
454 || CheckModified(x => x.ChatBotLimit, InstanceManagerRights.SetChatBotLimit)
455 || CheckModified(x => x.AutoStartCron, InstanceManagerRights.SetAutoStart)
456 || CheckModified(x => x.AutoStopCron, InstanceManagerRights.SetAutoStop))
457 return Forbid();
458
459 if (model.ChatBotLimit.HasValue)
460 {
462 .ChatBots
463 .AsQueryable()
464 .Where(x => x.InstanceId == originalModel.Id)
465 .CountAsync(cancellationToken);
466
467 if (countOfExistingChatBots > model.ChatBotLimit.Value)
468 return Conflict(new ErrorMessageResponse(ErrorCode.ChatBotMax));
469 }
470
475
477
478 if (renamed)
479 {
480 // ignoring retval because we don't care if it's offline
483 {
485 return null;
486 },
488 }
489
490 var oldAutoStart = originalModel.DreamDaemonSettings!.AutoStart;
491 try
492 {
493 if (originalOnline && model.Online == false)
495 else if (!originalOnline && model.Online == true)
496 {
497 // force autostart false here because we don't want any long running jobs right now
498 // remember to document this
501 }
502 }
503 catch (Exception e)
504 {
506 Logger.LogError(e, "Error changing instance online state!");
509 if (originalModelPath != null)
511
512 // DCT: Operation must always run
513 await DatabaseContext.Save(CancellationToken.None);
514 throw;
515 }
516
517 var api = (AuthenticationContext.GetRight(RightsType.InstanceManager) & (ulong)InstanceManagerRights.Read) != 0 ? originalModel.ToApi() : new InstanceResponse
518 {
519 Id = originalModel.Id,
520 };
521
522 var moving = originalModelPath != null;
523 if (moving)
524 {
525 var description = $"Move instance ID {originalModel.Id} from {originalModelPath} to {normalizedPath}";
528
530 job,
531 (core, databaseContextFactory, paramJob, progressHandler, ct) // core will be null here since the instance is offline
534 api.MoveJob = job.ToApi();
535 }
536
539 {
540 // ignoring retval because we don't care if it's offline
543 {
544 var autoUpdateTask = changedAutoUpdate
545 ? componentInstance.ScheduleAutoUpdate(model.AutoUpdateInterval!.Value, model.AutoUpdateCron)
546 : ValueTask.CompletedTask;
547
548 var autoStartTask = changedAutoStart
549 ? componentInstance.ScheduleServerStart(model.AutoStartCron)
550 : ValueTask.CompletedTask;
551
552 var autoStopTask = changedAutoStop
553 ? componentInstance.ScheduleServerStop(model.AutoStopCron)
554 : ValueTask.CompletedTask;
555
556 await ValueTaskExtensions.WhenAll(autoUpdateTask, autoStartTask, autoStopTask);
557
558 return null;
559 },
561 }
562
564 return moving ? Accepted(api) : Json(api);
565 }
566#pragma warning restore CA1502
567
580 [FromQuery] int? page,
581 [FromQuery] int? pageSize,
582 CancellationToken cancellationToken)
583 {
584 IQueryable<Models.Instance> GetBaseQuery()
585 {
587 .Instances
588 .AsQueryable()
589 .Where(x => x.SwarmIdentifer == swarmConfiguration.Identifier);
591 query = query
592 .Where(x => x.InstancePermissionSets.Any(y => y.PermissionSetId == AuthenticationContext.PermissionSet.Id))
593 .Where(x => x.InstancePermissionSets.Any(instanceUser =>
594 instanceUser.EngineRights != EngineRights.None ||
595 instanceUser.ChatBotRights != ChatBotRights.None ||
596 instanceUser.ConfigurationRights != ConfigurationRights.None ||
597 instanceUser.DreamDaemonRights != DreamDaemonRights.None ||
598 instanceUser.DreamMakerRights != DreamMakerRights.None ||
599 instanceUser.InstancePermissionSetRights != InstancePermissionSetRights.None));
600
601 // Hack for EF IAsyncEnumerable BS
602 return query.Select(x => x);
603 }
604
606 .SelectMany(x => x.Jobs)
607 .Where(x => !x.StoppedAt.HasValue && x.JobCode == JobCode.Move)
608 .Include(x => x.StartedBy!)
609 .ThenInclude(x => x.CreatedBy)
610 .Include(x => x.Instance)
611 .ToListAsync(cancellationToken);
612
613 var needsUpdate = false;
614 var result = await Paginated<Models.Instance, InstanceResponse>(
615 () => ValueTask.FromResult(
618 .OrderBy(x => x.Id))),
619 async instance =>
620 {
622 instance.MoveJob = moveJobs.FirstOrDefault(x => x.Instance!.Id == instance.Id)?.ToApi();
624 },
625 page,
626 pageSize,
628
629 if (needsUpdate)
631
632 return result;
633 }
634
643 [HttpGet("{id}")]
647 public async ValueTask<IActionResult> GetId(long id, CancellationToken cancellationToken)
648 {
650 IQueryable<Models.Instance> QueryForUser()
651 {
653 .Instances
654 .AsQueryable()
655 .Where(x => x.Id == id && x.SwarmIdentifer == swarmConfiguration.Identifier);
656
657 if (cantList)
658 query = query.Include(x => x.InstancePermissionSets);
659 return query;
660 }
661
662 var instance = await QueryForUser().FirstOrDefaultAsync(cancellationToken);
663
664 if (instance == null)
665 return this.Gone();
666
667 if (ValidateInstanceOnlineStatus(instance))
669
670 if (cantList && !instance.InstancePermissionSets.Any(instanceUser => instanceUser.PermissionSetId == AuthenticationContext.PermissionSet.Require(x => x.Id)
671 && (instanceUser.RepositoryRights != RepositoryRights.None ||
672 instanceUser.EngineRights != EngineRights.None ||
673 instanceUser.ChatBotRights != ChatBotRights.None ||
674 instanceUser.ConfigurationRights != ConfigurationRights.None ||
675 instanceUser.DreamDaemonRights != DreamDaemonRights.None ||
676 instanceUser.DreamMakerRights != DreamMakerRights.None ||
677 instanceUser.InstancePermissionSetRights != InstancePermissionSetRights.None)))
678 return Forbid();
679
680 var api = instance.ToApi();
681
683 .SelectMany(x => x.Jobs)
684 .Where(x => !x.StoppedAt.HasValue && x.JobCode == JobCode.Move)
685 .Include(x => x.StartedBy!)
686 .ThenInclude(x => x.CreatedBy)
687 .Include(x => x.Instance)
688 .FirstOrDefaultAsync(cancellationToken);
689 api.MoveJob = moveJob?.ToApi();
691 return Json(api);
692 }
693
701 [HttpPatch("{id}")]
702 [TgsAuthorize(InstanceManagerRights.GrantPermissions)]
706 {
707 IQueryable<Models.Instance> BaseQuery() => DatabaseContext
708 .Instances
709 .AsQueryable()
710 .Where(x => x.Id == id && x.SwarmIdentifer == swarmConfiguration.Identifier);
711
712 // ensure the current user has write privilege on the instance
714 .SelectMany(x => x.InstancePermissionSets)
715 .Where(x => x.PermissionSetId == AuthenticationContext.PermissionSet.Id)
716 .FirstOrDefaultAsync(cancellationToken);
717 if (usersInstancePermissionSet == default)
718 {
719 // does the instance actually exist?
721 .AnyAsync(cancellationToken);
722
723 if (!instanceExists)
724 return this.Gone();
725
729 }
730 else
732
734
735 return NoContent();
736 }
737
745 {
747 if (!ddPort.HasValue)
748 return null;
749
750 // try to use the old default if possible
751 const ushort DefaultDreamDaemonPort = 1337;
752 if (ddPort.Value < DefaultDreamDaemonPort)
754
755 const ushort DefaultApiValidationPort = 1339;
758 Math.Min((ushort)(ddPort.Value + 1), DefaultApiValidationPort),
759 false,
761 if (!dmPort.HasValue)
762 return null;
763
764 // try to use the old default if possible
767
768 return new Models.Instance
769 {
772 {
773 AllowWebClient = false,
774 AutoStart = false,
775 Port = ddPort,
776 OpenDreamTopicPort = 0,
777 SecurityLevel = DreamDaemonSecurity.Safe,
778 Visibility = DreamDaemonVisibility.Public,
779 StartupTimeout = 60,
780 HealthCheckSeconds = 60,
781 DumpOnHealthCheckRestart = false,
782 TopicRequestTimeout = generalConfiguration.ByondTopicTimeout,
783 AdditionalParameters = String.Empty,
784 StartProfiler = false,
785 LogOutput = false,
786 MapThreads = 0,
787 Minidumps = true,
788 },
790 {
791 ApiValidationPort = dmPort,
792 ApiValidationSecurityLevel = DreamDaemonSecurity.Safe,
794 Timeout = TimeSpan.FromHours(1),
795 CompilerAdditionalArguments = null,
796 },
797 Name = initialSettings.Name,
798 Online = false,
799 Path = initialSettings.Path,
800 AutoUpdateInterval = initialSettings.AutoUpdateInterval ?? 0,
801 AutoUpdateCron = initialSettings.AutoUpdateCron ?? String.Empty,
802 AutoStartCron = initialSettings.AutoStartCron ?? String.Empty,
803 AutoStopCron = initialSettings.AutoStopCron ?? String.Empty,
806 {
807 CommitterEmail = Components.Repository.Repository.DefaultCommitterEmail,
808 CommitterName = Components.Repository.Repository.DefaultCommitterName,
809 PushTestMergeCommits = false,
810 ShowTestMergeCommitters = false,
811 AutoUpdatesKeepTestMerges = false,
812 AutoUpdatesSynchronize = false,
813 PostTestMergeComment = false,
814 CreateGitHubDeployments = false,
815 UpdateSubmodules = true,
816 },
817 InstancePermissionSets = new List<InstancePermissionSet> // give this user full privileges on the instance
818 {
820 },
821 SwarmIdentifer = swarmConfiguration.Identifier,
822 };
823 }
824
846
852 [return: NotNullIfNotNull(nameof(path))]
853 string? NormalizePath(string? path)
854 {
855 if (path == null)
856 return null;
857
860
861 return path;
862 }
863
871 {
874 .AsQueryable()
875 .Where(x => x.InstanceId == instanceResponse.Id && x.PermissionSetId == AuthenticationContext.PermissionSet.Id)
876 .AnyAsync(cancellationToken);
877 }
878
885 {
886 if (!String.IsNullOrWhiteSpace(instance.AutoUpdateCron))
887 {
888 if ((instance.AutoUpdateInterval.HasValue && instance.AutoUpdateInterval.Value != 0)
889 || (CrontabSchedule.TryParse(
890 instance.AutoUpdateCron,
891 new CrontabSchedule.ParseOptions
892 {
893 IncludingSeconds = true,
894 }) == null))
895 return BadRequest(new ErrorMessageResponse(ErrorCode.ModelValidationFailure));
896
898 }
899 else
901
902 return null;
903 }
904 }
905}
List< string >? ValidInstancePaths
Limits the locations instances may be created or attached from.
uint InstanceLimit
The maximum number of Instances allowed.
string? Identifier
The server's identifier.
Represents a set of server permissions.
InstanceManagerRights? InstanceManagerRights
The Rights.InstanceManagerRights for the user.
Represents configurable settings for a git repository.
Represents an error message returned by the server.
Routes to a server actions.
Definition Routes.cs:9
const string InstanceManager
The Models.Instance controller.
Definition Routes.cs:48
const string List
The postfix for list operations.
Definition Routes.cs:113
Extension methods for the ValueTask and ValueTask<TResult> classes.
static async ValueTask WhenAll(IEnumerable< ValueTask > tasks)
Fully await a given list of tasks .
uint ByondTopicTimeout
The timeout in milliseconds for sending and receiving topics to/from DreamDaemon. Note that a single ...
Configuration for the server swarm system.
ILogger< ApiController > Logger
The ILogger for the ApiController.
async ValueTask< IActionResult?> WithComponentInstanceNullable(Func< IInstanceCore, ValueTask< IActionResult?> > action, Models.Instance? instance=null)
Run a given action with the relevant IInstance.
IInstanceOperations InstanceOperations
Access the IInstanceOperations instance.
readonly IInstanceManager instanceManager
The IInstanceManager for the ComponentInterfacingController.
bool ValidateInstanceOnlineStatus(Api.Models.Instance metadata)
Corrects discrepencies between the Api.Models.Instance.Online status of IInstances in the database vs...
ApiController for managing Components.Instances.
async ValueTask< Models.Instance?> CreateDefaultInstance(InstanceCreateRequest initialSettings, CancellationToken cancellationToken)
Creates a default Models.Instance from initialSettings .
async ValueTask< IActionResult > GetId(long id, CancellationToken cancellationToken)
Get a specific Api.Models.Instance.
InstanceController(IDatabaseContext databaseContext, IAuthenticationContext authenticationContext, ILogger< InstanceController > logger, IInstanceManager instanceManager, IJobManager jobManager, IIOManager ioManager, IPlatformIdentifier platformIdentifier, IPortAllocator portAllocator, IPermissionsUpdateNotifyee permissionsUpdateNotifyee, IOptions< GeneralConfiguration > generalConfigurationOptions, IOptions< SwarmConfiguration > swarmConfigurationOptions, IApiHeadersProvider apiHeaders)
Initializes a new instance of the InstanceController class.
readonly IJobManager jobManager
The IJobManager for the InstanceController.
readonly GeneralConfiguration generalConfiguration
The GeneralConfiguration for the InstanceController.
BadRequestObjectResult? ValidateCronSetting(Api.Models.Instance instance)
Validates a given instance 's Api.Models.Instance.AutoUpdateCron setting.
string? NormalizePath(string? path)
Normalize a given path for an instance.
readonly IPortAllocator portAllocator
The IPortAllocator for the InstanceController.
async ValueTask< IActionResult > Update([FromBody] InstanceUpdateRequest model, CancellationToken cancellationToken)
Modify an Api.Models.Instance's settings.
InstancePermissionSet InstanceAdminPermissionSet(InstancePermissionSet? permissionSetToModify)
Generate an InstancePermissionSet with full rights.
readonly SwarmConfiguration swarmConfiguration
The SwarmConfiguration for the InstanceController.
async ValueTask< IActionResult > List([FromQuery] int? page, [FromQuery] int? pageSize, CancellationToken cancellationToken)
List Api.Models.Instances.
const string InstanceAttachFileName
File name to allow attaching instances.
async ValueTask< IActionResult > Create([FromBody] InstanceCreateRequest model, CancellationToken cancellationToken)
Create or attach an Api.Models.Instance.
readonly IPlatformIdentifier platformIdentifier
The IPlatformIdentifier for the InstanceController.
readonly IPermissionsUpdateNotifyee permissionsUpdateNotifyee
The IPermissionsUpdateNotifyee for the InstanceController.
async ValueTask< IActionResult > Delete(long id, CancellationToken cancellationToken)
Detach an Api.Models.Instance with the given id .
async ValueTask CheckAccessible(InstanceResponse instanceResponse, CancellationToken cancellationToken)
Populate the InstanceResponse.Accessible property of a given instanceResponse .
readonly IIOManager ioManager
The IIOManager for the InstanceController.
async ValueTask< IActionResult > GrantPermissions(long id, CancellationToken cancellationToken)
Gives the current user full permissions on a given instance id .
Backend abstract implementation of IDatabaseContext.
DbSet< Instance > Instances
The Instances in the DatabaseContext.
DbSet< InstancePermissionSet > InstancePermissionSets
The InstancePermissionSets in the DatabaseContext.
DbSet< CompileJob > CompileJobs
The CompileJobs in the DatabaseContext.
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext.A Task representing the running operation.
DbSet< ChatBot > ChatBots
The ChatBots in the DatabaseContext.
DbSet< RevInfoTestMerge > RevInfoTestMerges
The RevInfoTestMerges in the DatabaseContext.
DbSet< RevisionInformation > RevisionInformations
The RevisionInformations in the DatabaseContext.
IIOManager that resolves paths to Environment.CurrentDirectory.
const string CurrentDirectory
Path to the current working directory for the IIOManager.
Instance? Instance
The parent Models.Instance.
Represents an Api.Models.Instance in the database.
Definition Instance.cs:11
const ushort DefaultChatBotLimit
Default for Api.Models.Instance.ChatBotLimit.
Definition Instance.cs:15
static Job Create(JobCode code, User? startedBy, Api.Models.Instance instance)
Creates a new job for registering in the Jobs.IJobService.
PermissionSet PermissionSet
The User's effective PermissionSet.
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType .The value of rightsType . Note that if InstancePermissionSet is ...
ValueTask OnlineInstance(Models.Instance metadata, CancellationToken cancellationToken)
Online an IInstance.
ValueTask MoveInstance(Models.Instance metadata, string oldPath, CancellationToken cancellationToken)
Move an IInstance.
ValueTask OfflineInstance(Models.Instance metadata, User user, CancellationToken cancellationToken)
Offline an IInstance.
Interface for using filesystems.
Definition IIOManager.cs:13
Task< IReadOnlyList< string > > GetFiles(string path, CancellationToken cancellationToken)
Returns full file names in a given path .
Task< bool > PathIsChildOf(string parentPath, string childPath, CancellationToken cancellationToken)
Check if a given parentPath is a parent of a given parentPath .
string ResolvePath()
Retrieve the full path of the current working directory.
string ConcatPath(params string[] paths)
Combines an array of strings into a path.
Task< IReadOnlyList< string > > GetDirectories(string path, CancellationToken cancellationToken)
Returns full directory names in a given path .
Task CreateDirectory(string path, CancellationToken cancellationToken)
Create a directory at path .
Task DeleteFile(string path, CancellationToken cancellationToken)
Deletes a file at path .
ValueTask WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
Writes some contents to a file at path overwriting previous content.
Task< bool > FileExists(string path, CancellationToken cancellationToken)
Check that the file at path exists.
Task< bool > DirectoryExists(string path, CancellationToken cancellationToken)
Check that the directory at path exists.
Manages the runtime of Jobs.
ValueTask< Job?> CancelJob(Job job, User? user, bool blocking, CancellationToken cancellationToken)
Cancels a give job .
ValueTask RegisterOperation(Job job, JobEntrypoint operation, CancellationToken cancellationToken)
Registers a given Job and begins running it.
For creating and accessing authentication contexts.
Receives notifications about permissions updates.
ValueTask InstancePermissionSetCreated(InstancePermissionSet instancePermissionSet, CancellationToken cancellationToken)
Called when a given instancePermissionSet is successfully created.
For identifying the current platform.
string NormalizePath(string path)
Normalize a path for consistency.
Gets unassigned ports for use by TGS.
ValueTask< ushort?> GetAvailablePort(ushort basePort, bool checkOne, CancellationToken cancellationToken)
Gets a port not currently in use by TGS.
ErrorCode
Types of Response.ErrorMessageResponses that the API may return.
Definition ErrorCode.cs:12
DreamDaemonVisibility
The visibility setting for DreamDaemon.
JobCode
The different types of Response.JobResponse.
Definition JobCode.cs:9
ConfigurationType
The type of configuration allowed on an Instance.
@ Online
The watchdog is online and DreamDaemon is running.
DreamDaemonSecurity
DreamDaemon's security level.
DMApiValidationMode
The DMAPI validation setting for deployments.
ChatBotRights
Rights for chat bots.
ConfigurationRights
Rights for Models.IConfigurationFiles.
@ List
User may list files if the Models.Instance allows it.
DreamMakerRights
Rights for deployment.
RightsType
The type of rights a model uses.
Definition RightsType.cs:7
EngineRights
Rights for engine version management.
RepositoryRights
Rights for the git repository.
InstancePermissionSetRights
Rights for an Models.Instance.
DreamDaemonRights
Rights for managing DreamDaemon.
InstanceManagerRights
Rights for managing Models.Instances.
@ Api
The ApiHeaders.ApiVersionHeader header is missing or invalid.