예제 #1
0
        private async Task PublishPackage(string packageId, string packageDefinitionFilename, string assemblyVersion, CancellationToken token)
        {
            var versionList = await nugetCore.GetAllPackageVersions(packageId, token);

            var packageVersion = versionList.Any() ? versionList.Max() : null;

            if (!VersionTools.HasUpdates(packageVersion, assemblyVersion))
            {
                Context.Output.WriteLine($"Package '{packageId}' is up-to-date. Version {packageVersion}", ConsoleColor.DarkCyan);
                return;
            }

            await nugetCmd.RunAsync(new NuGetPackArguments {
                Filename        = packageDefinitionFilename,
                Version         = assemblyVersion,
                OutputDirectory = nugetPackageDir,
                Properties      =
                {
                    ["Configuration"]    = "Release",
                    ["Platform"]         = "AnyCPU",
                    ["frameworkVersion"] = frameworkVersion,
                },
            }, token);

            var packageFilename = Directory
                                  .GetFiles(nugetPackageDir, $"{packageId}.*.nupkg")
                                  .FirstOrDefault();

            if (string.IsNullOrEmpty(packageFilename))
            {
                throw new ApplicationException($"No package found matching package ID '{packageId}'!");
            }

            await nugetCore.PushAsync(packageFilename, token);
        }
예제 #2
0
        public async Task Run(CommandContext context)
        {
            ConsoleEx.Out
            .WriteLine($"Photon CLI {Configuration.Version}", ConsoleColor.DarkBlue)
            .WriteLine("Checking for updates...", ConsoleColor.DarkCyan);

            var index = await DownloadTools.GetLatestCliIndex();

            var latestVersion = index.Version;

            if (!VersionTools.HasUpdates(Configuration.Version, latestVersion))
            {
                ConsoleEx.Out.WriteLine("CLI is up-to-date.", ConsoleColor.DarkBlue);
                return;
            }

            ConsoleEx.Out.Write("Downloading CLI update ", ConsoleColor.DarkCyan)
            .Write(latestVersion, ConsoleColor.Cyan)
            .WriteLine("...", ConsoleColor.DarkCyan);

            updateDirectory = Path.Combine(Configuration.Directory, "Updates");
            updateFilename  = Path.Combine(updateDirectory, "Photon.Server.msi");

            await DownloadUpdate(index);

            ConsoleEx.Out
            .WriteLine("Download Complete.", ConsoleColor.DarkGreen)
            .WriteLine("Launching installer...", ConsoleColor.DarkCyan);

            StartInstaller();
        }
예제 #3
0
        public async Task PublishAsync(CancellationToken token)
        {
            client.Output?
            .Append("Checking Package ", ConsoleColor.DarkCyan)
            .Append(PackageId, ConsoleColor.Cyan)
            .AppendLine(" for updates...", ConsoleColor.DarkCyan);

            var versionList = await client.GetAllPackageVersions(PackageId, token);

            var packageVersion = versionList.Any() ? versionList.Max() : null;

            if (!VersionTools.HasUpdates(packageVersion, Version))
            {
                client.Output?
                .Append($"Package '{PackageId}' is up-to-date. Version ", ConsoleColor.DarkBlue)
                .AppendLine(packageVersion, ConsoleColor.Blue);

                return;
            }

            var cl = new NuGetCommandLine {
                ExeFilename = ExeFilename,
                ApiKey      = client.ApiKey,
                Output      = client.Output,
            };

            cl.Pack(PackageDefinition, PackageDirectory);

            var packageFilename = Directory
                                  .GetFiles(PackageDirectory, $"{PackageId}.*.nupkg")
                                  .FirstOrDefault();

            await client.PushAsync(packageFilename, token);
        }
예제 #4
0
        private async Task Reconnect(PhotonServerDefinition server, string latestVersion, TimeSpan timeout)
        {
            using (var tokenSource = new CancellationTokenSource(timeout))
                using (var client = new WebClient()) {
                    var token = tokenSource.Token;
                    while (true)
                    {
                        token.ThrowIfCancellationRequested();

                        try {
                            var url     = NetPath.Combine(server.Url, "api/version");
                            var version = await client.DownloadStringTaskAsync(url);

                            if (!VersionTools.HasUpdates(version, latestVersion))
                            {
                                break;
                            }
                        }
                        catch (Exception error) when(error is SocketException || error is WebException)
                        {
                            await Task.Delay(1000, tokenSource.Token);
                        }
                    }
                }
        }
예제 #5
0
        private async Task <MessageClient> Reconnect(ServerAgent agent, TimeSpan timeout)
        {
            var client = new MessageClient(PhotonServer.Instance.MessageRegistry);

            client.ThreadException += (o, e) => {
                var error = (Exception)e.ExceptionObject;
                Output.AppendLine("An error occurred while messaging the client!", ConsoleColor.DarkRed)
                .AppendLine(error.UnfoldMessages());

                Log.Error("Message Client error after update!", error);
            };

            var tokenSource = new CancellationTokenSource(timeout);

            var token = tokenSource.Token;

            while (true)
            {
                token.ThrowIfCancellationRequested();

                try {
                    await client.ConnectAsync(agent.TcpHost, agent.TcpPort, tokenSource.Token);

                    var handshakeRequest = new HandshakeRequest {
                        Key           = Guid.NewGuid().ToString(),
                        ServerVersion = Configuration.Version,
                    };

                    var handshakeTimeout  = TimeSpan.FromSeconds(HandshakeTimeoutSec);
                    var handshakeResponse = await client.Handshake <HandshakeResponse>(handshakeRequest, handshakeTimeout, TokenSource.Token);

                    if (!string.Equals(handshakeRequest.Key, handshakeResponse.Key, StringComparison.Ordinal))
                    {
                        throw new ApplicationException("Handshake Failed! An invalid key was returned.");
                    }

                    if (!handshakeResponse.PasswordMatch)
                    {
                        throw new ApplicationException("Handshake Failed! Unauthorized.");
                    }

                    var versionRequest = new AgentGetVersionRequest();

                    var versionResponse = await client.Send(versionRequest)
                                          .GetResponseAsync <AgentGetVersionResponse>(token);

                    if (!VersionTools.HasUpdates(versionResponse.Version, UpdateVersion))
                    {
                        break;
                    }
                }
                catch (SocketException) {
                    await Task.Delay(1000, tokenSource.Token);
                }
            }

            return(client);
        }
예제 #6
0
        private async Task <MessageClient> Reconnect(ServerAgent agent, TimeSpan timeout, CancellationToken token)
        {
            using (var timeoutTokenSource = new CancellationTokenSource(timeout))
                using (var mergedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(timeoutTokenSource.Token, token)) {
                    while (true)
                    {
                        mergedTokenSource.Token.ThrowIfCancellationRequested();

                        var client = new MessageClient(PhotonServer.Instance.MessageRegistry);

                        try {
                            using (var connectionTimeoutTokenSource = new CancellationTokenSource(20_000))
                                using (var connectTokenSource = CancellationTokenSource.CreateLinkedTokenSource(mergedTokenSource.Token, connectionTimeoutTokenSource.Token)) {
                                    await client.ConnectAsync(agent.TcpHost, agent.TcpPort, connectTokenSource.Token);

                                    await ClientHandshake.Verify(client, connectTokenSource.Token);

                                    var versionRequest = new AgentGetVersionRequest();

                                    var versionResponse = await client.Send(versionRequest)
                                                          .GetResponseAsync <AgentGetVersionResponse>(connectTokenSource.Token);

                                    if (string.IsNullOrEmpty(versionResponse.Version))
                                    {
                                        Log.Warn("An empty version response was received!");
                                        continue;
                                    }

                                    if (!VersionTools.HasUpdates(versionResponse.Version, UpdateVersion))
                                    {
                                        return(client);
                                    }
                                }
                        }
                        catch (SocketException) {}
                        catch (OperationCanceledException) {}
                        catch (Exception error) {
                            Log.Warn("An unhandled exception occurred while attempting to reconnect to an updating agent.", error);
                        }

                        client.Dispose();

                        await Task.Delay(3_000, mergedTokenSource.Token);
                    }
                }
        }
예제 #7
0
        public async Task Run(CommandContext context)
        {
            var server = context.Servers.Get(ServerName);

            ConsoleEx.Out.WriteLine("Checking server version...", ConsoleColor.DarkCyan);

            string currentVersion = null;

            await AuthRetryAsync(async() => {
                currentVersion = await WebClient(server, async client => {
                    return((await client.DownloadStringTaskAsync("api/version")).Trim());
                });
            });

            ConsoleEx.Out
            .WriteLine($"Photon Server {currentVersion}", ConsoleColor.DarkBlue)
            .WriteLine("Checking for updates...", ConsoleColor.DarkCyan);

            var serverIndex = await DownloadTools.GetLatestServerIndex();

            if (!VersionTools.HasUpdates(currentVersion, serverIndex.Version))
            {
                ConsoleEx.Out.WriteLine("Server is up-to-date.", ConsoleColor.DarkBlue);

                return;
            }

            await BeginServerUpdate(server, serverIndex);

            ConsoleEx.Out.WriteLine("Server update started. Waiting for restart...", ConsoleColor.Cyan);

            await Task.Delay(3000);

            var timeout = TimeSpan.FromMinutes(2);

            try {
                await Reconnect(server, serverIndex.Version, timeout);

                ConsoleEx.Out.WriteLine("Update completed successfully.", ConsoleColor.DarkGreen);
            }
            catch (TaskCanceledException) {
                throw new ApplicationException($"Server failed to restart within timeout '{timeout}'.");
            }
        }
예제 #8
0
        private async Task <bool> PreCheckUsingCore(CancellationToken token)
        {
            context.Output.WriteBlock()
            .Write("Checking Package ", ConsoleColor.DarkCyan)
            .Write(PackageId, ConsoleColor.Cyan)
            .WriteLine(" for updates...", ConsoleColor.DarkCyan)
            .Post();

            var versionList = await Client.GetAllPackageVersions(PackageId, token);

            var packageVersion = versionList.Any() ? versionList.Max() : null;

            if (VersionTools.HasUpdates(packageVersion, Version))
            {
                return(true);
            }

            context.Output.WriteBlock()
            .Write($"Package '{PackageId}' is up-to-date. Version ", ConsoleColor.DarkBlue)
            .WriteLine(packageVersion, ConsoleColor.Blue)
            .Post();

            return(false);
        }
예제 #9
0
        private async Task Reconnect(PhotonServerDefinition server, string latestVersion, TimeSpan timeout)
        {
            using (var tokenSource = new CancellationTokenSource(timeout))
                using (var webClient = WebClientFactory.Create(server, Username, Password)) {
                    var token = tokenSource.Token;
                    while (true)
                    {
                        token.ThrowIfCancellationRequested();

                        try {
                            var version = await webClient.DownloadStringTaskAsync("api/version");

                            if (!VersionTools.HasUpdates(version, latestVersion))
                            {
                                break;
                            }
                        }
                        catch (Exception error) when(error is SocketException || error is WebException)
                        {
                            await Task.Delay(1000, tokenSource.Token);
                        }
                    }
                }
        }
예제 #10
0
        public async Task Run(CommandContext context)
        {
            var server = context.Servers.Get(ServerName);

            ConsoleEx.Out.WriteLine("Retrieving latest agent version...", ConsoleColor.DarkCyan);

            var agentIndex = await DownloadTools.GetLatestAgentIndex();

            var latestVersion = agentIndex.Version;

            ConsoleEx.Out
            .Write("Found Latest Version ", ConsoleColor.DarkCyan)
            .WriteLine(latestVersion, ConsoleColor.Cyan)
            .WriteLine("Checking agent versions...", ConsoleColor.DarkCyan);

            HttpAgentVersionListResponse agentVersionResponse = null;

            await AuthRetryAsync(async() => {
                agentVersionResponse = await WebClient(server, async client => {
                    var json = (await client.DownloadStringTaskAsync("api/agent/versions")).Trim();
                    return(JsonConvert.DeserializeObject <HttpAgentVersionListResponse>(json));
                });
            });

            var updateAgents = new List <string>();

            foreach (var agentVersion in agentVersionResponse.VersionList.OrderBy(x => x.AgentName))
            {
                if (!string.IsNullOrEmpty(agentVersion.Exception))
                {
                    ConsoleEx.Out.Write("Failed to get version of agent ", ConsoleColor.DarkYellow)
                    .Write(agentVersion.AgentName, ConsoleColor.Yellow)
                    .WriteLine($"! {agentVersion.Exception}", ConsoleColor.DarkYellow);

                    continue;
                }

                if (!VersionTools.HasUpdates(agentVersion.AgentVersion, latestVersion))
                {
                    ConsoleEx.Out.Write("Agent ", ConsoleColor.DarkBlue)
                    .Write(agentVersion.AgentName, ConsoleColor.Blue)
                    .WriteLine(" is up-to-date.", ConsoleColor.DarkBlue);

                    continue;
                }

                ConsoleEx.Out.Write("Updating ", ConsoleColor.DarkCyan)
                .Write(agentVersion.AgentName, ConsoleColor.Cyan)
                .Write(" from version ", ConsoleColor.DarkCyan)
                .Write(agentVersion.AgentVersion, ConsoleColor.Cyan)
                .WriteLine(".", ConsoleColor.DarkCyan);

                updateAgents.Add(agentVersion.AgentId);
            }

            if (!updateAgents.Any())
            {
                ConsoleEx.Out.WriteLine("All agents are up-to-date.", ConsoleColor.DarkGreen);
                return;
            }

            // Download update msi

            ConsoleEx.Out.Write("Downloading Agent update ", ConsoleColor.DarkCyan)
            .Write(agentIndex.Version, ConsoleColor.Cyan)
            .WriteLine("...", ConsoleColor.DarkCyan);

            var url = NetPath.Combine(Configuration.DownloadUrl, "agent", agentIndex.Version, agentIndex.MsiFilename);

            var updateDirectory = Path.Combine(Configuration.Directory, "Updates");
            var updateFilename  = Path.Combine(updateDirectory, "Photon.Agent.msi");

            PathEx.CreatePath(updateDirectory);

            using (var client = new WebClient()) {
                await client.DownloadFileTaskAsync(url, updateFilename);
            }

            ConsoleEx.Out.WriteLine("Download Complete.", ConsoleColor.DarkBlue);

            // Perform updates

            var agentIdList = updateAgents.ToArray();

            var startResult = await StartSession(server, agentIdList, updateFilename);

            var sessionId = startResult?.SessionId;

            if (string.IsNullOrEmpty(sessionId))
            {
                throw new ApplicationException($"An invalid session-id was returned! [{sessionId}]");
            }

            var position = 0;

            while (true)
            {
                var data = await UpdateOutput(server, sessionId, position);

                if (data == null)
                {
                    throw new ApplicationException("An empty session-output response was returned!");
                }

                if (data.IsComplete)
                {
                    break;
                }

                if (!data.IsModified)
                {
                    await Task.Delay(PollIntervalMs);

                    continue;
                }

                position = data.NewLength;

                ConsoleEx.Out.WriteLine(data.NewText, ConsoleColor.Gray);
            }

            Result = await GetResult(server, sessionId);

            ConsoleEx.Out.WriteLine("Update completed successfully.", ConsoleColor.DarkGreen);
        }
예제 #11
0
        public async Task PublishAsync(string packageName, string packageId, CancellationToken token = default(CancellationToken))
        {
            context.Output.WriteBlock()
            .Write("Updating Application ", ConsoleColor.DarkCyan)
            .Write(packageName, ConsoleColor.Cyan)
            .WriteLine("...", ConsoleColor.DarkCyan)
            .Post();

            var photonVars = context.ServerVariables["photon"];

            if (photonVars == null)
            {
                throw new ApplicationException("Photon Variables were not found!");
            }

            var assemblyVersion = AssemblyTools.GetVersion(AssemblyFilename);

            var webVersion = await GetWebVersion();

            if (!VersionTools.HasUpdates(webVersion, assemblyVersion))
            {
                context.Output.WriteBlock()
                .Write("Application ", ConsoleColor.DarkBlue)
                .Write(packageName, ConsoleColor.Blue)
                .Write(" is up-to-date. Version ", ConsoleColor.DarkBlue)
                .WriteLine(assemblyVersion, ConsoleColor.Blue)
                .Post();

                return;
            }

            // Publish

            // Create ZIP
            PathEx.CreatePath(PackagePath);

            var zipFilename = Path.Combine(PackagePath, $"{packageId}.zip");

            await CreateZip(BinPath, zipFilename);

            // Create Version Directory
            try {
                await CreateWebPath(assemblyVersion, token);
            }
            catch (WebException) {
                //...
            }

            var webMsiName = $"{packageId}.{assemblyVersion}.msi";
            var webZipName = $"{packageId}.{assemblyVersion}.zip";
            var msiWebUrl  = NetPath.Combine(UploadPath, assemblyVersion, webMsiName);
            var zipWebUrl  = NetPath.Combine(UploadPath, assemblyVersion, webZipName);

            await UploadFile(MsiFilename, msiWebUrl, token);
            await UploadFile(zipFilename, zipWebUrl, token);

            var index = new {
                version     = assemblyVersion,
                msiFilename = webMsiName,
                zipFilename = webZipName,
                notes       = "...",
            };

            await UploadIndex(index, assemblyVersion, token);

            await UpdateLatest(assemblyVersion, token);

            context.Output.WriteBlock()
            .Write("Application ", ConsoleColor.DarkGreen)
            .Write(packageName, ConsoleColor.Green)
            .Write(" updated successfully. ", ConsoleColor.DarkGreen)
            .Write("Version ", ConsoleColor.DarkCyan)
            .WriteLine(assemblyVersion, ConsoleColor.Cyan)
            .Post();
        }