/// <summary> /// Try to download and apply an update with a given <paramref name="newVersion"/>. /// </summary> /// <param name="newVersion">The version of the server to update to.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param> /// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns> async Task <IActionResult> CheckReleasesAndApplyUpdate(Version newVersion, CancellationToken cancellationToken) { Logger.LogDebug("Looking for GitHub releases version {0}...", newVersion); IEnumerable <Release> releases; try { var gitHubClient = GetGitHubClient(); releases = await gitHubClient .Repository .Release .GetAll(updatesConfiguration.GitHubRepositoryId) .WithToken(cancellationToken) .ConfigureAwait(false); } catch (RateLimitExceededException e) { return(RateLimit(e)); } catch (ApiException e) { Logger.LogWarning(e, OctokitException); return(StatusCode(HttpStatusCode.FailedDependency)); } releases = releases.Where(x => x.TagName.StartsWith(updatesConfiguration.GitTagPrefix, StringComparison.InvariantCulture)); Logger.LogTrace("Release query complete!"); foreach (var release in releases) { if (Version.TryParse( release.TagName.Replace( updatesConfiguration.GitTagPrefix, String.Empty, StringComparison.Ordinal), out var version) && version == newVersion) { var asset = release.Assets.Where(x => x.Name.Equals(updatesConfiguration.UpdatePackageAssetName, StringComparison.Ordinal)).FirstOrDefault(); if (asset == default) { continue; } if (!serverUpdater.ApplyUpdate(version, new Uri(asset.BrowserDownloadUrl), ioManager)) { return(Conflict(new ErrorMessage(ErrorCode.ServerUpdateInProgress))); } return(Accepted(new Administration { WindowsHost = platformIdentifier.IsWindows, NewVersion = newVersion })); // gtfo of here before all the cancellation tokens fire } } return(Gone()); }
/// <inheritdoc /> public async Task <ServerUpdateResult> BeginUpdate(Version newVersion, CancellationToken cancellationToken) { logger.LogDebug("Looking for GitHub releases version {0}...", newVersion); IEnumerable <Release> releases; var gitHubClient = gitHubClientFactory.CreateClient(); releases = await gitHubClient .Repository .Release .GetAll(updatesConfiguration.GitHubRepositoryId) .WithToken(cancellationToken) .ConfigureAwait(false); releases = releases.Where(x => x.TagName.StartsWith(updatesConfiguration.GitTagPrefix, StringComparison.InvariantCulture)); logger.LogTrace("Release query complete!"); foreach (var release in releases) { if (Version.TryParse( release.TagName.Replace( updatesConfiguration.GitTagPrefix, String.Empty, StringComparison.Ordinal), out var version) && version == newVersion) { var asset = release.Assets.Where(x => x.Name.Equals(updatesConfiguration.UpdatePackageAssetName, StringComparison.Ordinal)).FirstOrDefault(); if (asset == default) { continue; } if (!serverControl.ApplyUpdate(version, new Uri(asset.BrowserDownloadUrl), ioManager)) { return(ServerUpdateResult.UpdateInProgress); } return(ServerUpdateResult.Started); } } return(ServerUpdateResult.ReleaseMissing); }
public override async Task <IActionResult> Update([FromBody] Administration model, CancellationToken cancellationToken) { if (model == null) { throw new ArgumentNullException(nameof(model)); } if (model.NewVersion == null) { return(BadRequest(new ErrorMessage { Message = "Missing new version!" })); } if (model.NewVersion.Major != application.Version.Major) { return(BadRequest(new ErrorMessage { Message = "Cannot update to a different suite version!" })); } IEnumerable <Release> releases; try { releases = (await gitHubClient.Repository.Release.GetAll(updatesConfiguration.GitHubRepositoryId).ConfigureAwait(false)).Where(x => x.TagName.StartsWith(updatesConfiguration.GitTagPrefix, StringComparison.InvariantCulture)); } catch (RateLimitExceededException e) { return(RateLimit(e)); } foreach (var release in releases) { if (Version.TryParse(release.TagName.Replace(updatesConfiguration.GitTagPrefix, String.Empty, StringComparison.Ordinal), out var version) && version == model.NewVersion) { var asset = release.Assets.Where(x => x.Name == updatesConfiguration.UpdatePackageAssetName).FirstOrDefault(); if (asset == default) { continue; } var assetBytes = await ioManager.DownloadFile(new Uri(asset.BrowserDownloadUrl), cancellationToken).ConfigureAwait(false); try { if (!await serverUpdater.ApplyUpdate(assetBytes, ioManager, cancellationToken).ConfigureAwait(false)) { return(UnprocessableEntity(new ErrorMessage { Message = RestartNotSupportedException })); //unprocessable entity } } catch (InvalidOperationException) { return(StatusCode((int)HttpStatusCode.ServiceUnavailable)); //we were beat to the punch, really shouldn't happen but heat death of the universe and what not } return(Accepted()); //gtfo of here before all the cancellation tokens fire } } return(StatusCode((int)HttpStatusCode.Gone)); }
public override async Task <IActionResult> Update([FromBody] Administration model, CancellationToken cancellationToken) { if (model == null) { throw new ArgumentNullException(nameof(model)); } if (model.NewVersion == null) { return(BadRequest(new ErrorMessage { Message = "Missing new version!" })); } if (model.NewVersion.Major != application.Version.Major) { return(BadRequest(new ErrorMessage { Message = "Cannot update to a different suite version!" })); } if (!serverUpdater.WatchdogPresent) { return(UnprocessableEntity(new ErrorMessage { Message = RestartNotSupportedException })); } Logger.LogDebug("Looking for GitHub releases version {0}...", model.NewVersion); IEnumerable <Release> releases; try { var gitHubClient = GetGitHubClient(); releases = (await gitHubClient.Repository.Release.GetAll(updatesConfiguration.GitHubRepositoryId).ConfigureAwait(false)).Where(x => x.TagName.StartsWith(updatesConfiguration.GitTagPrefix, StringComparison.InvariantCulture)); cancellationToken.ThrowIfCancellationRequested(); } catch (RateLimitExceededException e) { return(RateLimit(e)); } catch (ApiException e) { Logger.LogWarning(OctokitException, e); return(StatusCode((int)HttpStatusCode.FailedDependency)); } Logger.LogTrace("Release query complete!"); foreach (var release in releases) { if (Version.TryParse(release.TagName.Replace(updatesConfiguration.GitTagPrefix, String.Empty, StringComparison.Ordinal), out var version) && version == model.NewVersion) { var asset = release.Assets.Where(x => x.Name == updatesConfiguration.UpdatePackageAssetName).FirstOrDefault(); if (asset == default) { continue; } if (!serverUpdater.ApplyUpdate(version, new Uri(asset.BrowserDownloadUrl), ioManager)) { return(Conflict(new ErrorMessage { Message = "An update operation is already in progress!" })); } return(Accepted()); //gtfo of here before all the cancellation tokens fire } } return(StatusCode((int)HttpStatusCode.Gone)); }