You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

209 lines
5.9 KiB

  1. using System;
  2. using System.IO;
  3. using System.Linq;
  4. using System.Net.Http;
  5. using System.Net.Http.Headers;
  6. using System.Text;
  7. using System.Threading;
  8. using System.Threading.Tasks;
  9. using Tgstation.Server.Api.Models;
  10. using Tgstation.Server.Client;
  11. using Tgstation.Server.Client.Components;
  12. namespace SetupProgram
  13. {
  14. class Program
  15. {
  16. public static async Task<int> Main()
  17. {
  18. var repo = Environment.GetEnvironmentVariable("TGS_REPO")?.Trim();
  19. if (String.IsNullOrWhiteSpace(repo))
  20. {
  21. Console.WriteLine("ERROR: Environment variable TGS_REPO not set to a git url!");
  22. return 1;
  23. }
  24. var byondStr = Environment.GetEnvironmentVariable("TGS_BYOND")?.Trim();
  25. if (String.IsNullOrWhiteSpace(byondStr) || !Version.TryParse(byondStr, out Version byond) || byond.Build != -1)
  26. {
  27. Console.WriteLine("ERROR: Environment variable TGS_BYOND not set to a valid BYOND version!");
  28. return 2;
  29. }
  30. var clientFactory = new ServerClientFactory(new ProductHeaderValue("LinuxOneShot", "1.0.0"));
  31. IServerClient serverClient = null;
  32. Instance instance = null;
  33. IInstanceClient instanceClient;
  34. void CreateInstanceClient() => instanceClient = serverClient.Instances.CreateClient(instance);
  35. async Task CreateAdminClient()
  36. {
  37. Console.WriteLine("Attempting to reestablish connection to TGS (120s max wait)...");
  38. var giveUpAt = DateTimeOffset.Now.AddSeconds(60);
  39. do
  40. {
  41. try
  42. {
  43. serverClient = await clientFactory.CreateServerClient(new Uri("http://tgs:80"), User.AdminName, User.DefaultAdminPassword, default, default);
  44. if (instance != null)
  45. CreateInstanceClient();
  46. break;
  47. }
  48. catch (HttpRequestException)
  49. {
  50. //migrating, to be expected
  51. if (DateTimeOffset.Now > giveUpAt)
  52. throw;
  53. await Task.Delay(TimeSpan.FromSeconds(1));
  54. }
  55. catch (ServiceUnavailableException)
  56. {
  57. // migrating, to be expected
  58. if (DateTimeOffset.Now > giveUpAt)
  59. throw;
  60. await Task.Delay(TimeSpan.FromSeconds(1));
  61. }
  62. } while (true);
  63. }
  64. async Task WaitForJob(Job originalJob, CancellationToken cancellationToken)
  65. {
  66. var job = originalJob;
  67. int? lastProgress = null;
  68. do
  69. {
  70. try
  71. {
  72. await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
  73. job = await instanceClient.Jobs.GetId(job, cancellationToken).ConfigureAwait(false);
  74. if (job.Progress != lastProgress)
  75. {
  76. Console.WriteLine($"Progress: {job.Progress}");
  77. lastProgress = job.Progress;
  78. }
  79. }
  80. catch (UnauthorizedException)
  81. {
  82. await CreateAdminClient();
  83. }
  84. }
  85. while (!job.StoppedAt.HasValue);
  86. if (job.ExceptionDetails != null)
  87. {
  88. Console.WriteLine(job.ExceptionDetails);
  89. Environment.Exit(3);
  90. }
  91. }
  92. await CreateAdminClient();
  93. Console.WriteLine("Listing instances...");
  94. var instances = await serverClient.Instances.List(default);
  95. if (instances.Any())
  96. {
  97. Console.WriteLine("One or more instances already exist, aborting!");
  98. return 3;
  99. }
  100. Console.WriteLine("Creating instance...");
  101. instance = await serverClient.Instances.CreateOrAttach(new Instance
  102. {
  103. ConfigurationType = ConfigurationType.HostWrite,
  104. Name = "AutoInstance",
  105. Path = "/tgs4_instances/main"
  106. }, default);
  107. Console.WriteLine("Onlining instance...");
  108. instance.Online = true;
  109. instance = await serverClient.Instances.Update(instance, default);
  110. CreateInstanceClient();
  111. Console.WriteLine("Starting repo clone...");
  112. var cloneJobTask = instanceClient.Repository.Clone(new Repository
  113. {
  114. Origin = repo
  115. }, default);
  116. Console.WriteLine($"Starting BYOND install {byond}...");
  117. var byondInstallTask = instanceClient.Byond.SetActiveVersion(new Byond
  118. {
  119. Version = byond
  120. }, default);
  121. Console.WriteLine("Setting DD Settings to Ultrasafe|Startup Timeout=120|AutoStart=true|HeartbeatSeconds=120...");
  122. var ddUpdateTask = instanceClient.DreamDaemon.Update(new DreamDaemon
  123. {
  124. AutoStart = true,
  125. SecurityLevel = DreamDaemonSecurity.Ultrasafe,
  126. HeartbeatSeconds = 120,
  127. StartupTimeout = 120
  128. }, default);
  129. Console.WriteLine("Setting API validation security level to trusted...");
  130. var dmUpdateTask = instanceClient.DreamMaker.Update(new DreamMaker
  131. {
  132. ApiValidationSecurityLevel = DreamDaemonSecurity.Trusted
  133. }, default);
  134. Console.WriteLine("Uploading EventScripts/PreCompile.sh...");
  135. var configurationTask = instanceClient.Configuration.Write(new ConfigurationFile
  136. {
  137. Path = "/EventScripts/PreCompile.sh",
  138. Content = File.ReadAllBytes("PreCompile.sh")
  139. }, default);
  140. Console.WriteLine("Creating GameStaticFiles/data...");
  141. var configTask2 = instanceClient.Configuration.CreateDirectory(new ConfigurationFile
  142. {
  143. IsDirectory = true,
  144. Path = "/GameStaticFiles/data"
  145. }, default);
  146. Console.WriteLine("Waiting for previous requests...");
  147. await Task.WhenAll(
  148. cloneJobTask,
  149. byondInstallTask,
  150. ddUpdateTask,
  151. dmUpdateTask,
  152. configurationTask,
  153. configTask2);
  154. Console.WriteLine("Waiting for BYOND install...");
  155. var installJob = await byondInstallTask;
  156. await WaitForJob(installJob.InstallJob, default);
  157. Console.WriteLine("Waiting for Repo clone...");
  158. var cloneJob = await cloneJobTask;
  159. await WaitForJob(cloneJob.ActiveJob, default);
  160. await CreateAdminClient();
  161. Console.WriteLine("Starting deployment...");
  162. var deployJobTask = instanceClient.DreamMaker.Compile(default);
  163. Console.WriteLine("Enabling auto updates every hour...");
  164. instance.AutoUpdateInterval = 60;
  165. await serverClient.Instances.Update(instance, default);
  166. Console.WriteLine("Waiting for deployment job...");
  167. var deployJob = await deployJobTask;
  168. await WaitForJob(deployJob, default);
  169. await CreateAdminClient();
  170. Console.WriteLine("Launching watchdog...");
  171. var launchJob = await instanceClient.DreamDaemon.Start(default);
  172. await WaitForJob(launchJob, default);
  173. Console.WriteLine("Complete!");
  174. return 0;
  175. }
  176. }
  177. }