/// <inheritdoc />
        public async Task <byte[]> DownloadVersion(Version version, CancellationToken cancellationToken)
        {
            var ourVersion = version;
            //lummox is annoying and doesn't like to post linux versions if nothing changed in DreamDaemon/DM
            //if this for's exit condition ever triggers, i get to say I told you so
            Exception lastException = null;

            for (var I = 0; I < 5 && ourVersion.Minor >= 1; ++I, ourVersion = new Version(ourVersion.Major, ourVersion.Minor))
            {
                try
                {
                    var url = String.Format(CultureInfo.InvariantCulture, ByondRevisionsURL, ourVersion.Major, ourVersion.Minor);

                    return(await ioManager.DownloadFile(new Uri(url), cancellationToken).ConfigureAwait(false));
                }
                catch (WebException e)
                {
                    if (!(e.Status == WebExceptionStatus.ProtocolError && e.Response is HttpWebResponse response && response.StatusCode == HttpStatusCode.NotFound))
                    {
                        throw;
                    }
                    lastException = e;
                }
            }
            throw lastException;
        }
        /// <inheritdoc />
        public async Task <byte[]> DownloadVersion(Version version, CancellationToken cancellationToken)
        {
            if (version == null)
            {
                throw new ArgumentNullException(nameof(version));
            }

            var url = String.Format(CultureInfo.InvariantCulture, ByondRevisionsURLTemplate, version.Major, version.Minor);

            return(await ioManager.DownloadFile(new Uri(url), cancellationToken).ConfigureAwait(false));
        }
Beispiel #3
0
        /// <inheritdoc />
        public bool ApplyUpdate(Version version, Uri updateZipUrl, IIOManager ioManager)
        {
            if (version == null)
            {
                throw new ArgumentNullException(nameof(version));
            }
            if (updateZipUrl == null)
            {
                throw new ArgumentNullException(nameof(updateZipUrl));
            }
            if (ioManager == null)
            {
                throw new ArgumentNullException(nameof(ioManager));
            }

            CheckSanity(true);

            logger.LogTrace("Begin ApplyUpdate...");

            lock (this)
            {
                if (updating || RestartRequested)
                {
                    logger.LogTrace("Aborted due to concurrency conflict!");
                    return(false);
                }

                updating = true;
            }

            async void RunUpdate()
            {
                try
                {
                    logger.LogInformation("Updating server to version {0} ({1})...", version, updateZipUrl);

                    if (cancellationTokenSource == null)
                    {
                        throw new InvalidOperationException("Tried to update a non-running Server!");
                    }
                    var cancellationToken = cancellationTokenSource.Token;

                    logger.LogTrace("Downloading zip package...");
                    var updateZipData = await ioManager.DownloadFile(updateZipUrl, cancellationToken).ConfigureAwait(false);

                    try
                    {
                        logger.LogTrace("Exctracting zip package to {0}...", updatePath);
                        await ioManager.ZipToDirectory(updatePath, updateZipData, cancellationToken).ConfigureAwait(false);
                    }
                    catch (Exception e)
                    {
                        updating = false;
                        try
                        {
                            // important to not leave this directory around if possible
                            await ioManager.DeleteDirectory(updatePath, default).ConfigureAwait(false);
                        }
                        catch (Exception e2)
                        {
                            throw new AggregateException(e, e2);
                        }

                        throw;
                    }

                    await Restart(version, null).ConfigureAwait(false);
                }
                catch (OperationCanceledException)
                {
                    logger.LogInformation("Server update cancelled!");
                }
                catch (Exception e)
                {
                    logger.LogError("Error updating server! Exception: {0}", e);
                }
                finally
                {
                    updating = false;
                }
            }

            RunUpdate();
            return(true);
        }
        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));
        }
Beispiel #5
0
        /// <inheritdoc />
        public Task <byte[]> DownloadVersion(Version version, CancellationToken cancellationToken)
        {
            var url = String.Format(CultureInfo.InvariantCulture, ByondRevisionsURLTemplate, version.Major, version.Minor);

            return(ioManager.DownloadFile(new Uri(url), cancellationToken));
        }