From c4626d0c3a871067dfd5bf43a8ceb344514f8cf6 Mon Sep 17 00:00:00 2001 From: Tingluo Huang Date: Wed, 3 Jun 2020 23:24:53 -0400 Subject: [PATCH] Remove SPS/Token migration code. Remove GHES url manipulate code. (#513) * Remove SPS/Token migration code. Remove GHES url manipulate code. * feedback. --- src/Runner.Common/ConfigurationStore.cs | 22 +- src/Runner.Common/RunnerServer.cs | 4 - src/Runner.Common/Terminal.cs | 10 +- .../Configuration/ConfigurationManager.cs | 43 +- .../Configuration/CredentialManager.cs | 20 +- src/Runner.Listener/MessageListener.cs | 224 +-- src/Runner.Listener/Program.cs | 4 +- src/Runner.Worker/JobRunner.cs | 15 - src/Test/L0/Listener/MessageListenerL0.cs | 1253 +---------------- 9 files changed, 50 insertions(+), 1545 deletions(-) diff --git a/src/Runner.Common/ConfigurationStore.cs b/src/Runner.Common/ConfigurationStore.cs index fc32ad436..0ae270420 100644 --- a/src/Runner.Common/ConfigurationStore.cs +++ b/src/Runner.Common/ConfigurationStore.cs @@ -108,9 +108,9 @@ namespace GitHub.Runner.Common CredentialData GetMigratedCredentials(); RunnerSettings GetSettings(); void SaveCredential(CredentialData credential); - void SaveMigratedCredential(CredentialData credential); void SaveSettings(RunnerSettings settings); void DeleteCredential(); + void DeleteMigratedCredential(); void DeleteSettings(); } @@ -232,21 +232,6 @@ namespace GitHub.Runner.Common File.SetAttributes(_credFilePath, File.GetAttributes(_credFilePath) | FileAttributes.Hidden); } - public void SaveMigratedCredential(CredentialData credential) - { - Trace.Info("Saving {0} migrated credential @ {1}", credential.Scheme, _migratedCredFilePath); - if (File.Exists(_migratedCredFilePath)) - { - // Delete existing credential file first, since the file is hidden and not able to overwrite. - Trace.Info("Delete exist runner migrated credential file."); - IOUtil.DeleteFile(_migratedCredFilePath); - } - - IOUtil.SaveObject(credential, _migratedCredFilePath); - Trace.Info("Migrated Credentials Saved."); - File.SetAttributes(_migratedCredFilePath, File.GetAttributes(_migratedCredFilePath) | FileAttributes.Hidden); - } - public void SaveSettings(RunnerSettings settings) { Trace.Info("Saving runner settings."); @@ -268,6 +253,11 @@ namespace GitHub.Runner.Common IOUtil.Delete(_migratedCredFilePath, default(CancellationToken)); } + public void DeleteMigratedCredential() + { + IOUtil.Delete(_migratedCredFilePath, default(CancellationToken)); + } + public void DeleteSettings() { IOUtil.Delete(_configFilePath, default(CancellationToken)); diff --git a/src/Runner.Common/RunnerServer.cs b/src/Runner.Common/RunnerServer.cs index cbdcb898c..5e284a175 100644 --- a/src/Runner.Common/RunnerServer.cs +++ b/src/Runner.Common/RunnerServer.cs @@ -50,10 +50,6 @@ namespace GitHub.Runner.Common // agent update Task UpdateAgentUpdateStateAsync(int agentPoolId, int agentId, string currentState); - - // runner authorization url - Task GetRunnerAuthUrlAsync(int runnerPoolId, int runnerId); - Task ReportRunnerAuthUrlErrorAsync(int runnerPoolId, int runnerId, string error); } public sealed class RunnerServer : RunnerService, IRunnerServer diff --git a/src/Runner.Common/Terminal.cs b/src/Runner.Common/Terminal.cs index f35a2220d..2ad873b98 100644 --- a/src/Runner.Common/Terminal.cs +++ b/src/Runner.Common/Terminal.cs @@ -96,13 +96,14 @@ namespace GitHub.Runner.Common Trace.Info($"WRITE: {message}"); if (!Silent) { - if(colorCode != null) + if (colorCode != null) { Console.ForegroundColor = colorCode.Value; Console.Write(message); Console.ResetColor(); } - else { + else + { Console.Write(message); } } @@ -120,13 +121,14 @@ namespace GitHub.Runner.Common Trace.Info($"WRITE LINE: {line}"); if (!Silent) { - if(colorCode != null) + if (colorCode != null) { Console.ForegroundColor = colorCode.Value; Console.WriteLine(line); Console.ResetColor(); } - else { + else + { Console.WriteLine(line); } } diff --git a/src/Runner.Listener/Configuration/ConfigurationManager.cs b/src/Runner.Listener/Configuration/ConfigurationManager.cs index 9a98c7d65..7d634067f 100644 --- a/src/Runner.Listener/Configuration/ConfigurationManager.cs +++ b/src/Runner.Listener/Configuration/ConfigurationManager.cs @@ -119,6 +119,19 @@ namespace GitHub.Runner.Listener.Configuration // Determine the service deployment type based on connection data. (Hosted/OnPremises) runnerSettings.IsHostedServer = runnerSettings.GitHubUrl == null || IsHostedServer(new UriBuilder(runnerSettings.GitHubUrl)); + // Warn if the Actions server url and GHES server url has different Host + if (!runnerSettings.IsHostedServer) + { + // Example actionsServerUrl is https://my-ghes/_services/pipelines/[...] + // Example githubServerUrl is https://my-ghes + var actionsServerUrl = new Uri(runnerSettings.ServerUrl); + var githubServerUrl = new Uri(runnerSettings.GitHubUrl); + if (!string.Equals(actionsServerUrl.Authority, githubServerUrl.Authority, StringComparison.OrdinalIgnoreCase)) + { + throw new InvalidOperationException($"GitHub Actions is not properly configured in GHES. GHES url: {runnerSettings.GitHubUrl}, Actions url: {runnerSettings.ServerUrl}."); + } + } + // Validate can connect. await _runnerServer.ConnectAsync(new Uri(runnerSettings.ServerUrl), creds); @@ -221,36 +234,11 @@ namespace GitHub.Runner.Listener.Configuration // Add Agent Id to settings runnerSettings.AgentId = agent.Id; - // respect the serverUrl resolve by server. - // in case of agent configured using collection url instead of account url. - string agentServerUrl; - if (agent.Properties.TryGetValidatedValue("ServerUrl", out agentServerUrl) && - !string.IsNullOrEmpty(agentServerUrl)) - { - Trace.Info($"Agent server url resolve by server: '{agentServerUrl}'."); - - // we need make sure the Schema/Host/Port component of the url remain the same. - UriBuilder inputServerUrl = new UriBuilder(runnerSettings.ServerUrl); - UriBuilder serverReturnedServerUrl = new UriBuilder(agentServerUrl); - if (Uri.Compare(inputServerUrl.Uri, serverReturnedServerUrl.Uri, UriComponents.SchemeAndServer, UriFormat.Unescaped, StringComparison.OrdinalIgnoreCase) != 0) - { - inputServerUrl.Path = serverReturnedServerUrl.Path; - Trace.Info($"Replace server returned url's scheme://host:port component with user input server url's scheme://host:port: '{inputServerUrl.Uri.AbsoluteUri}'."); - runnerSettings.ServerUrl = inputServerUrl.Uri.AbsoluteUri; - } - else - { - runnerSettings.ServerUrl = agentServerUrl; - } - } - // See if the server supports our OAuth key exchange for credentials if (agent.Authorization != null && agent.Authorization.ClientId != Guid.Empty && agent.Authorization.AuthorizationUrl != null) { - UriBuilder configServerUrl = new UriBuilder(runnerSettings.ServerUrl); - UriBuilder oauthEndpointUrlBuilder = new UriBuilder(agent.Authorization.AuthorizationUrl); var credentialData = new CredentialData { Scheme = Constants.Configuration.OAuth, @@ -258,7 +246,6 @@ namespace GitHub.Runner.Listener.Configuration { { "clientId", agent.Authorization.ClientId.ToString("D") }, { "authorizationUrl", agent.Authorization.AuthorizationUrl.AbsoluteUri }, - { "oauthEndpointUrl", oauthEndpointUrlBuilder.Uri.AbsoluteUri }, }, }; @@ -464,7 +451,7 @@ namespace GitHub.Runner.Listener.Configuration // update should replace the existing labels agent.Version = BuildConstants.RunnerPackage.Version; agent.OSDescription = RuntimeInformation.OSDescription; - + agent.Labels.Clear(); agent.Labels.Add(new AgentLabel("self-hosted", LabelType.System)); @@ -475,7 +462,7 @@ namespace GitHub.Runner.Listener.Configuration { agent.Labels.Add(new AgentLabel(userLabel, LabelType.User)); } - + return agent; } diff --git a/src/Runner.Listener/Configuration/CredentialManager.cs b/src/Runner.Listener/Configuration/CredentialManager.cs index 871aae4de..ee459abe7 100644 --- a/src/Runner.Listener/Configuration/CredentialManager.cs +++ b/src/Runner.Listener/Configuration/CredentialManager.cs @@ -13,7 +13,7 @@ namespace GitHub.Runner.Listener.Configuration public interface ICredentialManager : IRunnerService { ICredentialProvider GetCredentialProvider(string credType); - VssCredentials LoadCredentials(bool preferMigrated = true); + VssCredentials LoadCredentials(); } public class CredentialManager : RunnerService, ICredentialManager @@ -40,7 +40,7 @@ namespace GitHub.Runner.Listener.Configuration return creds; } - public VssCredentials LoadCredentials(bool preferMigrated = true) + public VssCredentials LoadCredentials() { IConfigurationStore store = HostContext.GetService(); @@ -50,14 +50,16 @@ namespace GitHub.Runner.Listener.Configuration } CredentialData credData = store.GetCredentials(); - - if (preferMigrated) + var migratedCred = store.GetMigratedCredentials(); + if (migratedCred != null) { - var migratedCred = store.GetMigratedCredentials(); - if (migratedCred != null) - { - credData = migratedCred; - } + credData = migratedCred; + + // Re-write .credentials with Token URL + store.SaveCredential(credData); + + // Delete .credentials_migrated + store.DeleteMigratedCredential(); } ICredentialProvider credProv = GetCredentialProvider(credData.Scheme); diff --git a/src/Runner.Listener/MessageListener.cs b/src/Runner.Listener/MessageListener.cs index 5718654b7..0ad22e87d 100644 --- a/src/Runner.Listener/MessageListener.cs +++ b/src/Runner.Listener/MessageListener.cs @@ -13,10 +13,7 @@ using System.Diagnostics; using System.Runtime.InteropServices; using GitHub.Runner.Common; using GitHub.Runner.Sdk; -using GitHub.Services.WebApi; -using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("Test")] namespace GitHub.Runner.Listener { [ServiceLocator(Default = typeof(MessageListener))] @@ -35,30 +32,18 @@ namespace GitHub.Runner.Listener private ITerminal _term; private IRunnerServer _runnerServer; private TaskAgentSession _session; - private ICredentialManager _credMgr; - private IConfigurationStore _configStore; private TimeSpan _getNextMessageRetryInterval; private readonly TimeSpan _sessionCreationRetryInterval = TimeSpan.FromSeconds(30); private readonly TimeSpan _sessionConflictRetryLimit = TimeSpan.FromMinutes(4); private readonly TimeSpan _clockSkewRetryLimit = TimeSpan.FromMinutes(30); private readonly Dictionary _sessionCreationExceptionTracker = new Dictionary(); - // Whether load credentials from .credentials_migrated file - internal bool _useMigratedCredentials; - - // need to check auth url if there is only .credentials and auth schema is OAuth - internal bool _needToCheckAuthorizationUrlUpdate; - internal Task _authorizationUrlMigrationBackgroundTask; - internal Task _authorizationUrlRollbackReattemptDelayBackgroundTask; - public override void Initialize(IHostContext hostContext) { base.Initialize(hostContext); _term = HostContext.GetService(); _runnerServer = HostContext.GetService(); - _credMgr = HostContext.GetService(); - _configStore = HostContext.GetService(); } public async Task CreateSessionAsync(CancellationToken token) @@ -73,8 +58,8 @@ namespace GitHub.Runner.Listener // Create connection. Trace.Info("Loading Credentials"); - _useMigratedCredentials = !StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_SPSAUTHURL")); - VssCredentials creds = _credMgr.LoadCredentials(_useMigratedCredentials); + var credMgr = HostContext.GetService(); + VssCredentials creds = credMgr.LoadCredentials(); var agent = new TaskAgentReference { @@ -89,17 +74,6 @@ namespace GitHub.Runner.Listener string errorMessage = string.Empty; bool encounteringError = false; - var originalCreds = _configStore.GetCredentials(); - var migratedCreds = _configStore.GetMigratedCredentials(); - if (migratedCreds == null) - { - _useMigratedCredentials = false; - if (originalCreds.Scheme == Constants.Configuration.OAuth) - { - _needToCheckAuthorizationUrlUpdate = true; - } - } - while (true) { token.ThrowIfCancellationRequested(); @@ -127,12 +101,6 @@ namespace GitHub.Runner.Listener encounteringError = false; } - if (_needToCheckAuthorizationUrlUpdate) - { - // start background task try to get new authorization url - _authorizationUrlMigrationBackgroundTask = GetNewOAuthAuthorizationSetting(token); - } - return true; } catch (OperationCanceledException) when (token.IsCancellationRequested) @@ -164,44 +132,10 @@ namespace GitHub.Runner.Listener } } - if (ex is TaskAgentSessionConflictException) - { - try - { - var newCred = await GetNewOAuthAuthorizationSetting(token, true); - if (newCred != null) - { - await _runnerServer.ConnectAsync(new Uri(_settings.ServerUrl), newCred); - Trace.Info("Updated connection to use migrated credential for next CreateSession call."); - _useMigratedCredentials = true; - _authorizationUrlMigrationBackgroundTask = null; - _needToCheckAuthorizationUrlUpdate = false; - } - } - catch (Exception e) - { - Trace.Error("Fail to refresh connection with new authorization url."); - Trace.Error(e); - } - } - if (!IsSessionCreationExceptionRetriable(ex)) { - if (_useMigratedCredentials && !(ex is TaskAgentSessionConflictException)) - { - // migrated credentials might cause lose permission during permission check, - // we will force to use original credential and try again - _useMigratedCredentials = false; - var reattemptBackoff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromHours(24), TimeSpan.FromHours(36)); - _authorizationUrlRollbackReattemptDelayBackgroundTask = HostContext.Delay(reattemptBackoff, token); // retry migrated creds in 24-36 hours. - creds = _credMgr.LoadCredentials(false); - Trace.Error("Fallback to original credentials and try again."); - } - else - { - _term.WriteError($"Failed to create session. {ex.Message}"); - return false; - } + _term.WriteError($"Failed to create session. {ex.Message}"); + return false; } if (!encounteringError) //print the message only on the first error @@ -262,51 +196,6 @@ namespace GitHub.Runner.Listener encounteringError = false; continuousError = 0; } - - if (_needToCheckAuthorizationUrlUpdate && - _authorizationUrlMigrationBackgroundTask?.IsCompleted == true) - { - if (HostContext.GetService().Busy || - HostContext.GetService().Busy) - { - Trace.Info("Job or runner updates in progress, update credentials next time."); - } - else - { - try - { - var newCred = await _authorizationUrlMigrationBackgroundTask; - await _runnerServer.ConnectAsync(new Uri(_settings.ServerUrl), newCred); - Trace.Info("Updated connection to use migrated credential for next GetMessage call."); - _useMigratedCredentials = true; - _authorizationUrlMigrationBackgroundTask = null; - _needToCheckAuthorizationUrlUpdate = false; - } - catch (Exception ex) - { - Trace.Error("Fail to refresh connection with new authorization url."); - Trace.Error(ex); - } - } - } - - if (_authorizationUrlRollbackReattemptDelayBackgroundTask?.IsCompleted == true) - { - try - { - // we rolled back to use original creds about 2 days before, now it's a good time to try migrated creds again. - Trace.Info("Re-attempt to use migrated credential"); - var migratedCreds = _credMgr.LoadCredentials(); - await _runnerServer.ConnectAsync(new Uri(_settings.ServerUrl), migratedCreds); - _useMigratedCredentials = true; - _authorizationUrlRollbackReattemptDelayBackgroundTask = null; - } - catch (Exception ex) - { - Trace.Error("Fail to refresh connection with new authorization url on rollback reattempt."); - Trace.Error(ex); - } - } } catch (OperationCanceledException) when (token.IsCancellationRequested) { @@ -330,21 +219,7 @@ namespace GitHub.Runner.Listener } else if (!IsGetNextMessageExceptionRetriable(ex)) { - if (_useMigratedCredentials) - { - // migrated credentials might cause lose permission during permission check, - // we will force to use original credential and try again - _useMigratedCredentials = false; - var reattemptBackoff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromHours(24), TimeSpan.FromHours(36)); - _authorizationUrlRollbackReattemptDelayBackgroundTask = HostContext.Delay(reattemptBackoff, token); // retry migrated creds in 24-36 hours. - var originalCreds = _credMgr.LoadCredentials(false); - await _runnerServer.ConnectAsync(new Uri(_settings.ServerUrl), originalCreds); - Trace.Error("Fallback to original credentials and try again."); - } - else - { - throw; - } + throw; } else { @@ -536,94 +411,5 @@ namespace GitHub.Runner.Listener return true; } } - - private async Task GetNewOAuthAuthorizationSetting(CancellationToken token, bool adhoc = false) - { - Trace.Info("Start checking oauth authorization url update."); - while (true) - { - try - { - var migratedAuthorizationUrl = await _runnerServer.GetRunnerAuthUrlAsync(_settings.PoolId, _settings.AgentId); - if (!string.IsNullOrEmpty(migratedAuthorizationUrl)) - { - var credData = _configStore.GetCredentials(); - var clientId = credData.Data.GetValueOrDefault("clientId", null); - var currentAuthorizationUrl = credData.Data.GetValueOrDefault("authorizationUrl", null); - Trace.Info($"Current authorization url: {currentAuthorizationUrl}, new authorization url: {migratedAuthorizationUrl}"); - - if (string.Equals(currentAuthorizationUrl, migratedAuthorizationUrl, StringComparison.OrdinalIgnoreCase)) - { - // We don't need to update credentials. - Trace.Info("No needs to update authorization url"); - if (adhoc) - { - return null; - } - else - { - await Task.Delay(TimeSpan.FromMilliseconds(-1), token); - } - } - - var keyManager = HostContext.GetService(); - var signingCredentials = VssSigningCredentials.Create(() => keyManager.GetKey()); - - var migratedClientCredential = new VssOAuthJwtBearerClientCredential(clientId, migratedAuthorizationUrl, signingCredentials); - var migratedRunnerCredential = new VssOAuthCredential(new Uri(migratedAuthorizationUrl, UriKind.Absolute), VssOAuthGrant.ClientCredentials, migratedClientCredential); - - Trace.Info("Try connect service with Token Service OAuth endpoint."); - var runnerServer = HostContext.CreateService(); - await runnerServer.ConnectAsync(new Uri(_settings.ServerUrl), migratedRunnerCredential); - await runnerServer.GetAgentPoolsAsync(); - Trace.Info($"Successfully connected service with new authorization url."); - - var migratedCredData = new CredentialData - { - Scheme = Constants.Configuration.OAuth, - Data = - { - { "clientId", clientId }, - { "authorizationUrl", migratedAuthorizationUrl }, - { "oauthEndpointUrl", migratedAuthorizationUrl }, - }, - }; - - _configStore.SaveMigratedCredential(migratedCredData); - return migratedRunnerCredential; - } - else - { - Trace.Verbose("No authorization url updates"); - } - } - catch (Exception ex) when (!token.IsCancellationRequested) - { - Trace.Error("Fail to get/test new authorization url."); - Trace.Error(ex); - - try - { - await _runnerServer.ReportRunnerAuthUrlErrorAsync(_settings.PoolId, _settings.AgentId, ex.ToString()); - } - catch (Exception e) - { - // best effort - Trace.Error("Fail to report the migration error"); - Trace.Error(e); - } - } - - if (adhoc) - { - return null; - } - else - { - var backoff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromMinutes(30), TimeSpan.FromMinutes(45)); - await HostContext.Delay(backoff, token); - } - } - } } } diff --git a/src/Runner.Listener/Program.cs b/src/Runner.Listener/Program.cs index 3181680f0..a24224dad 100644 --- a/src/Runner.Listener/Program.cs +++ b/src/Runner.Listener/Program.cs @@ -102,7 +102,9 @@ namespace GitHub.Runner.Listener IRunner runner = context.GetService(); try { - return await runner.ExecuteCommand(command); + var returnCode = await runner.ExecuteCommand(command); + trace.Info($"Runner execution has finished with return code {returnCode}"); + return returnCode; } catch (OperationCanceledException) when (context.RunnerShutdownToken.IsCancellationRequested) { diff --git a/src/Runner.Worker/JobRunner.cs b/src/Runner.Worker/JobRunner.cs index 58cf26bf4..31dfb1714 100644 --- a/src/Runner.Worker/JobRunner.cs +++ b/src/Runner.Worker/JobRunner.cs @@ -5,21 +5,13 @@ using GitHub.Services.Common; using GitHub.Services.WebApi; using System; using System.Collections.Generic; -using System.Globalization; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Net.Http; -using System.Text; -using System.IO.Compression; -using System.Diagnostics; -using Newtonsoft.Json.Linq; -using GitHub.DistributedTask.ObjectTemplating.Tokens; using GitHub.Runner.Common; using GitHub.Runner.Sdk; -using GitHub.DistributedTask.Pipelines.ContextData; -using GitHub.DistributedTask.ObjectTemplating; namespace GitHub.Runner.Worker { @@ -122,13 +114,6 @@ namespace GitHub.Runner.Worker _tempDirectoryManager = HostContext.GetService(); _tempDirectoryManager.InitializeTempDirectory(jobContext); - // // Expand container properties - // jobContext.Container?.ExpandProperties(jobContext.Variables); - // foreach (var sidecar in jobContext.SidecarContainers) - // { - // sidecar.ExpandProperties(jobContext.Variables); - // } - // Get the job extension. Trace.Info("Getting job extension."); IJobExtension jobExtension = HostContext.CreateService(); diff --git a/src/Test/L0/Listener/MessageListenerL0.cs b/src/Test/L0/Listener/MessageListenerL0.cs index ba0f0ee77..a830e9c99 100644 --- a/src/Test/L0/Listener/MessageListenerL0.cs +++ b/src/Test/L0/Listener/MessageListenerL0.cs @@ -63,7 +63,7 @@ namespace GitHub.Runner.Common.Tests.Listener tokenSource.Token)) .Returns(Task.FromResult(expectedSession)); - _credMgr.Setup(x => x.LoadCredentials(true)).Returns(new VssCredentials()); + _credMgr.Setup(x => x.LoadCredentials()).Returns(new VssCredentials()); _store.Setup(x => x.GetCredentials()).Returns(new CredentialData() { Scheme = Constants.Configuration.OAuthAccessToken }); _store.Setup(x => x.GetMigratedCredentials()).Returns(default(CredentialData)); @@ -107,7 +107,7 @@ namespace GitHub.Runner.Common.Tests.Listener tokenSource.Token)) .Returns(Task.FromResult(expectedSession)); - _credMgr.Setup(x => x.LoadCredentials(true)).Returns(new VssCredentials()); + _credMgr.Setup(x => x.LoadCredentials()).Returns(new VssCredentials()); _store.Setup(x => x.GetCredentials()).Returns(new CredentialData() { Scheme = Constants.Configuration.OAuthAccessToken }); _store.Setup(x => x.GetMigratedCredentials()).Returns(default(CredentialData)); @@ -154,7 +154,7 @@ namespace GitHub.Runner.Common.Tests.Listener tokenSource.Token)) .Returns(Task.FromResult(expectedSession)); - _credMgr.Setup(x => x.LoadCredentials(true)).Returns(new VssCredentials()); + _credMgr.Setup(x => x.LoadCredentials()).Returns(new VssCredentials()); _store.Setup(x => x.GetCredentials()).Returns(new CredentialData() { Scheme = Constants.Configuration.OAuthAccessToken }); _store.Setup(x => x.GetMigratedCredentials()).Returns(default(CredentialData)); @@ -231,17 +231,7 @@ namespace GitHub.Runner.Common.Tests.Listener tokenSource.Token)) .Returns(Task.FromResult(expectedSession)); - _runnerServer - .Setup(x => x.GetRunnerAuthUrlAsync( - _settings.PoolId, - _settings.AgentId)) - .Returns(async () => - { - await Task.Delay(10); - return ""; - }); - - _credMgr.Setup(x => x.LoadCredentials(true)).Returns(new VssCredentials()); + _credMgr.Setup(x => x.LoadCredentials()).Returns(new VssCredentials()); var originalCred = new CredentialData() { Scheme = Constants.Configuration.OAuth }; originalCred.Data["authorizationUrl"] = "https://s.server"; @@ -264,1241 +254,6 @@ namespace GitHub.Runner.Common.Tests.Listener _settings.PoolId, It.Is(y => y != null), tokenSource.Token), Times.Once()); - - Assert.False(listener._useMigratedCredentials); - Assert.True(listener._needToCheckAuthorizationUrlUpdate); - Assert.Null(listener._authorizationUrlRollbackReattemptDelayBackgroundTask); - Assert.NotNull(listener._authorizationUrlMigrationBackgroundTask); - } - } - - [Fact] - [Trait("Level", "L0")] - [Trait("Category", "Runner")] - public async void CreateSessionWithMigratedCredential() - { - using (TestHostContext tc = CreateTestContext()) - using (var tokenSource = new CancellationTokenSource()) - { - Tracing trace = tc.GetTrace(); - - // Arrange. - var expectedSession = new TaskAgentSession(); - _runnerServer - .Setup(x => x.CreateAgentSessionAsync( - _settings.PoolId, - It.Is(y => y != null), - tokenSource.Token)) - .Returns(Task.FromResult(expectedSession)); - - _credMgr.Setup(x => x.LoadCredentials(true)).Returns(new VssCredentials()); - - var originalCred = new CredentialData() { Scheme = Constants.Configuration.OAuth }; - originalCred.Data["authorizationUrl"] = "https://s.server"; - originalCred.Data["clientId"] = "d842fd7b-61b0-4a80-96b4-f2797c353897"; - - var migratedCred = new CredentialData() { Scheme = Constants.Configuration.OAuth }; - migratedCred.Data["authorizationUrl"] = "https://t.server"; - migratedCred.Data["clientId"] = "d842fd7b-61b0-4a80-96b4-f2797c353897"; - - _store.Setup(x => x.GetCredentials()).Returns(originalCred); - _store.Setup(x => x.GetMigratedCredentials()).Returns(migratedCred); - - // Act. - MessageListener listener = new MessageListener(); - listener.Initialize(tc); - - bool result = await listener.CreateSessionAsync(tokenSource.Token); - trace.Info("result: {0}", result); - - // Assert. - Assert.True(result); - _runnerServer - .Verify(x => x.CreateAgentSessionAsync( - _settings.PoolId, - It.Is(y => y != null), - tokenSource.Token), Times.Once()); - - Assert.True(listener._useMigratedCredentials); - Assert.False(listener._needToCheckAuthorizationUrlUpdate); - Assert.Null(listener._authorizationUrlRollbackReattemptDelayBackgroundTask); - Assert.Null(listener._authorizationUrlMigrationBackgroundTask); - } - } - - [Fact] - [Trait("Level", "L0")] - [Trait("Category", "Runner")] - public async void CreateSessionWithHostedCredential() - { - using (TestHostContext tc = CreateTestContext()) - using (var tokenSource = new CancellationTokenSource()) - { - Tracing trace = tc.GetTrace(); - - // Arrange. - var expectedSession = new TaskAgentSession(); - _runnerServer - .Setup(x => x.CreateAgentSessionAsync( - _settings.PoolId, - It.Is(y => y != null), - tokenSource.Token)) - .Returns(Task.FromResult(expectedSession)); - - _credMgr.Setup(x => x.LoadCredentials(true)).Returns(new VssCredentials()); - - _store.Setup(x => x.GetCredentials()).Returns(new CredentialData() { Scheme = Constants.Configuration.OAuthAccessToken }); - _store.Setup(x => x.GetMigratedCredentials()).Returns(default(CredentialData)); - - // Act. - MessageListener listener = new MessageListener(); - listener.Initialize(tc); - - bool result = await listener.CreateSessionAsync(tokenSource.Token); - trace.Info("result: {0}", result); - - // Assert. - Assert.True(result); - _runnerServer - .Verify(x => x.CreateAgentSessionAsync( - _settings.PoolId, - It.Is(y => y != null), - tokenSource.Token), Times.Once()); - - Assert.False(listener._useMigratedCredentials); - Assert.False(listener._needToCheckAuthorizationUrlUpdate); - Assert.Null(listener._authorizationUrlRollbackReattemptDelayBackgroundTask); - Assert.Null(listener._authorizationUrlMigrationBackgroundTask); - } - } - - [Fact] - [Trait("Level", "L0")] - [Trait("Category", "Runner")] - public async void CreateSessionWithMigratedCredentialFallBackOriginalSucceed() - { - using (TestHostContext tc = CreateTestContext()) - using (var tokenSource = new CancellationTokenSource()) - { - Tracing trace = tc.GetTrace(); - - // Arrange. - var expectedSession = new TaskAgentSession(); - _runnerServer - .Setup(x => x.CreateAgentSessionAsync( - 123, - It.Is(y => y != null), - tokenSource.Token)) - .Callback(() => { _settings.PoolId = 1234; }) - .Throws(new TaskAgentPoolNotFoundException("L0 Pool not found")); - - _runnerServer - .Setup(x => x.CreateAgentSessionAsync( - 1234, - It.Is(y => y != null), - tokenSource.Token)) - .Returns(Task.FromResult(expectedSession)); - - var originalVssCred = new VssCredentials(); - var migratedVssCred = new VssCredentials(); - _credMgr.Setup(x => x.LoadCredentials(true)).Returns(migratedVssCred); - _credMgr.Setup(x => x.LoadCredentials(false)).Returns(originalVssCred); - - var originalCred = new CredentialData() { Scheme = Constants.Configuration.OAuth }; - originalCred.Data["authorizationUrl"] = "https://s.server"; - originalCred.Data["clientId"] = "d842fd7b-61b0-4a80-96b4-f2797c353897"; - - var migratedCred = new CredentialData() { Scheme = Constants.Configuration.OAuth }; - migratedCred.Data["authorizationUrl"] = "https://t.server"; - migratedCred.Data["clientId"] = "d842fd7b-61b0-4a80-96b4-f2797c353897"; - - _store.Setup(x => x.GetCredentials()).Returns(originalCred); - _store.Setup(x => x.GetMigratedCredentials()).Returns(migratedCred); - - // Act. - MessageListener listener = new MessageListener(); - listener.Initialize(tc); - - bool result = await listener.CreateSessionAsync(tokenSource.Token); - trace.Info("result: {0}", result); - - // Assert. - Assert.True(result); - _runnerServer - .Verify(x => x.CreateAgentSessionAsync( - It.IsAny(), - It.Is(y => y != null), - tokenSource.Token), Times.Exactly(2)); - _runnerServer - .Verify(x => x.ConnectAsync( - It.IsAny(), - originalVssCred), Times.Once); - _runnerServer - .Verify(x => x.ConnectAsync( - It.IsAny(), - migratedVssCred), Times.Once); - - Assert.False(listener._useMigratedCredentials); - Assert.False(listener._needToCheckAuthorizationUrlUpdate); - Assert.NotNull(listener._authorizationUrlRollbackReattemptDelayBackgroundTask); - Assert.Null(listener._authorizationUrlMigrationBackgroundTask); - } - } - - [Fact] - [Trait("Level", "L0")] - [Trait("Category", "Runner")] - public async void CreateSessionWithMigratedCredentialFallBackOriginalStillFailed() - { - using (TestHostContext tc = CreateTestContext()) - using (var tokenSource = new CancellationTokenSource()) - { - Tracing trace = tc.GetTrace(); - - // Arrange. - var expectedSession = new TaskAgentSession(); - _runnerServer - .Setup(x => x.CreateAgentSessionAsync( - _settings.PoolId, - It.Is(y => y != null), - tokenSource.Token)) - .Throws(new TaskAgentPoolNotFoundException("L0 Pool not found")); - - var originalVssCred = new VssCredentials(); - var migratedVssCred = new VssCredentials(); - _credMgr.Setup(x => x.LoadCredentials(true)).Returns(migratedVssCred); - _credMgr.Setup(x => x.LoadCredentials(false)).Returns(originalVssCred); - - var originalCred = new CredentialData() { Scheme = Constants.Configuration.OAuth }; - originalCred.Data["authorizationUrl"] = "https://s.server"; - originalCred.Data["clientId"] = "d842fd7b-61b0-4a80-96b4-f2797c353897"; - - var migratedCred = new CredentialData() { Scheme = Constants.Configuration.OAuth }; - migratedCred.Data["authorizationUrl"] = "https://t.server"; - migratedCred.Data["clientId"] = "d842fd7b-61b0-4a80-96b4-f2797c353897"; - - _store.Setup(x => x.GetCredentials()).Returns(originalCred); - _store.Setup(x => x.GetMigratedCredentials()).Returns(migratedCred); - - // Act. - MessageListener listener = new MessageListener(); - listener.Initialize(tc); - - bool result = await listener.CreateSessionAsync(tokenSource.Token); - trace.Info("result: {0}", result); - - // Assert. - Assert.False(result); - _runnerServer - .Verify(x => x.CreateAgentSessionAsync( - _settings.PoolId, - It.Is(y => y != null), - tokenSource.Token), Times.Exactly(2)); - _runnerServer - .Verify(x => x.ConnectAsync( - It.IsAny(), - originalVssCred), Times.Once); - _runnerServer - .Verify(x => x.ConnectAsync( - It.IsAny(), - migratedVssCred), Times.Once); - - Assert.False(listener._useMigratedCredentials); - Assert.False(listener._needToCheckAuthorizationUrlUpdate); - Assert.NotNull(listener._authorizationUrlRollbackReattemptDelayBackgroundTask); - Assert.Null(listener._authorizationUrlMigrationBackgroundTask); - } - } - - [Fact] - [Trait("Level", "L0")] - [Trait("Category", "Runner")] - public async void CreateSessionWithOriginalGetMessageWaitForMigtateToMigrated() - { - using (TestHostContext tc = CreateTestContext()) - using (var tokenSource = new CancellationTokenSource()) - { - Tracing trace = tc.GetTrace(); - - // Arrange. - var expectedSession = new TaskAgentSession(); - _runnerServer - .Setup(x => x.CreateAgentSessionAsync( - _settings.PoolId, - It.Is(y => y != null), - tokenSource.Token)) - .Returns(Task.FromResult(expectedSession)); - - _runnerServer - .Setup(x => x.GetRunnerAuthUrlAsync( - _settings.PoolId, - _settings.AgentId)) - .Returns(async () => - { - await Task.Delay(10); - return ""; - }); - - _credMgr.Setup(x => x.LoadCredentials(true)).Returns(new VssCredentials()); - - var originalCred = new CredentialData() { Scheme = Constants.Configuration.OAuth }; - originalCred.Data["authorizationUrl"] = "https://s.server"; - originalCred.Data["clientId"] = "d842fd7b-61b0-4a80-96b4-f2797c353897"; - - _store.Setup(x => x.GetCredentials()).Returns(originalCred); - _store.Setup(x => x.GetMigratedCredentials()).Returns(default(CredentialData)); - - // Act. - MessageListener listener = new MessageListener(); - listener.Initialize(tc); - - bool result = await listener.CreateSessionAsync(tokenSource.Token); - trace.Info("result: {0}", result); - - // Assert. - Assert.True(result); - _runnerServer - .Verify(x => x.CreateAgentSessionAsync( - _settings.PoolId, - It.Is(y => y != null), - tokenSource.Token), Times.Once()); - - Assert.False(listener._useMigratedCredentials); - Assert.True(listener._needToCheckAuthorizationUrlUpdate); - - Assert.Null(listener._authorizationUrlRollbackReattemptDelayBackgroundTask); - Assert.NotNull(listener._authorizationUrlMigrationBackgroundTask); - - var arMessages = new TaskAgentMessage[] - { - new TaskAgentMessage - { - Body = "somebody1", - MessageId = 4234, - MessageType = JobRequestMessageTypes.PipelineAgentJobRequest - }, - new TaskAgentMessage - { - Body = "somebody2", - MessageId = 4235, - MessageType = JobCancelMessage.MessageType - }, - null, //should be skipped by GetNextMessageAsync implementation - null, - new TaskAgentMessage - { - Body = "somebody3", - MessageId = 4236, - MessageType = JobRequestMessageTypes.PipelineAgentJobRequest - } - }; - var messages = new Queue(arMessages); - - _runnerServer - .Setup(x => x.GetAgentMessageAsync( - _settings.PoolId, expectedSession.SessionId, It.IsAny(), tokenSource.Token)) - .Returns(async (Int32 poolId, Guid sessionId, Int64? lastMessageId, CancellationToken cancellationToken) => - { - await Task.Delay(200); - return messages.Dequeue(); - }); - - TaskAgentMessage message1 = await listener.GetNextMessageAsync(tokenSource.Token); - TaskAgentMessage message2 = await listener.GetNextMessageAsync(tokenSource.Token); - TaskAgentMessage message3 = await listener.GetNextMessageAsync(tokenSource.Token); - Assert.Equal(arMessages[0], message1); - Assert.Equal(arMessages[1], message2); - Assert.Equal(arMessages[4], message3); - - //Assert - _runnerServer - .Verify(x => x.GetAgentMessageAsync( - _settings.PoolId, expectedSession.SessionId, It.IsAny(), tokenSource.Token), Times.Exactly(arMessages.Length)); - - _runnerServer - .Verify(x => x.GetRunnerAuthUrlAsync(_settings.PoolId, _settings.AgentId), Times.AtLeast(2)); - - _runnerServer - .Verify(x => x.ConnectAsync( - It.IsAny(), - It.IsAny()), Times.Once); - - var tempLog = Path.GetTempFileName(); - File.Copy(tc.TraceFileName, tempLog, true); - var traceContent = File.ReadAllLines(tempLog); - Assert.DoesNotContain(traceContent, x => x.Contains("Try connect service with migrated OAuth endpoint.")); - - Assert.False(listener._useMigratedCredentials); - Assert.True(listener._needToCheckAuthorizationUrlUpdate); - Assert.Null(listener._authorizationUrlRollbackReattemptDelayBackgroundTask); - Assert.NotNull(listener._authorizationUrlMigrationBackgroundTask); - } - } - - [Fact] - [Trait("Level", "L0")] - [Trait("Category", "Runner")] - public async void CreateSessionWithOriginalGetMessageMigtateToMigrated() - { - using (TestHostContext tc = CreateTestContext()) - using (var tokenSource = new CancellationTokenSource()) - { - Tracing trace = tc.GetTrace(); - - // Arrange. - var expectedSession = new TaskAgentSession(); - _runnerServer - .Setup(x => x.CreateAgentSessionAsync( - _settings.PoolId, - It.Is(y => y != null), - tokenSource.Token)) - .Returns(Task.FromResult(expectedSession)); - - _runnerServer - .Setup(x => x.GetRunnerAuthUrlAsync( - _settings.PoolId, - _settings.AgentId)) - .Returns(async () => - { - await Task.Delay(100); - return "https://t.server"; - }); - - _credMgr.Setup(x => x.LoadCredentials(true)).Returns(new VssCredentials()); - - var originalCred = new CredentialData() { Scheme = Constants.Configuration.OAuth }; - originalCred.Data["authorizationUrl"] = "https://s.server"; - originalCred.Data["clientId"] = "d842fd7b-61b0-4a80-96b4-f2797c353897"; - - _store.Setup(x => x.GetCredentials()).Returns(originalCred); - _store.Setup(x => x.GetMigratedCredentials()).Returns(default(CredentialData)); - - // Act. - MessageListener listener = new MessageListener(); - listener.Initialize(tc); - - bool result = await listener.CreateSessionAsync(tokenSource.Token); - trace.Info("result: {0}", result); - - // Assert. - Assert.True(result); - _runnerServer - .Verify(x => x.CreateAgentSessionAsync( - _settings.PoolId, - It.Is(y => y != null), - tokenSource.Token), Times.Once()); - - Assert.False(listener._useMigratedCredentials); - Assert.True(listener._needToCheckAuthorizationUrlUpdate); - Assert.Null(listener._authorizationUrlRollbackReattemptDelayBackgroundTask); - Assert.NotNull(listener._authorizationUrlMigrationBackgroundTask); - - var arMessages = new TaskAgentMessage[] - { - new TaskAgentMessage - { - Body = "somebody1", - MessageId = 4234, - MessageType = JobRequestMessageTypes.PipelineAgentJobRequest - }, - new TaskAgentMessage - { - Body = "somebody2", - MessageId = 4235, - MessageType = JobCancelMessage.MessageType - }, - null, //should be skipped by GetNextMessageAsync implementation - null, - new TaskAgentMessage - { - Body = "somebody3", - MessageId = 4236, - MessageType = JobRequestMessageTypes.PipelineAgentJobRequest - } - }; - var messages = new Queue(arMessages); - - _runnerServer - .Setup(x => x.GetAgentMessageAsync( - _settings.PoolId, expectedSession.SessionId, It.IsAny(), tokenSource.Token)) - .Returns(async (Int32 poolId, Guid sessionId, Int64? lastMessageId, CancellationToken cancellationToken) => - { - await Task.Delay(200); - return messages.Dequeue(); - }); - - var newRunnerServer = new Mock(); - tc.EnqueueInstance(newRunnerServer.Object); - - var keyManager = new Mock(); - keyManager.Setup(x => x.GetKey()).Returns(new RSACryptoServiceProvider(2048)); - tc.SetSingleton(keyManager.Object); - - tc.SetSingleton(new Mock().Object); - tc.SetSingleton(new Mock().Object); - - TaskAgentMessage message1 = await listener.GetNextMessageAsync(tokenSource.Token); - TaskAgentMessage message2 = await listener.GetNextMessageAsync(tokenSource.Token); - TaskAgentMessage message3 = await listener.GetNextMessageAsync(tokenSource.Token); - Assert.Equal(arMessages[0], message1); - Assert.Equal(arMessages[1], message2); - Assert.Equal(arMessages[4], message3); - - //Assert - _runnerServer - .Verify(x => x.GetAgentMessageAsync( - _settings.PoolId, expectedSession.SessionId, It.IsAny(), tokenSource.Token), Times.Exactly(arMessages.Length)); - - _runnerServer - .Verify(x => x.GetRunnerAuthUrlAsync(_settings.PoolId, _settings.AgentId), Times.Once); - - _runnerServer - .Verify(x => x.ConnectAsync( - It.IsAny(), - It.IsAny()), Times.Exactly(2)); - - newRunnerServer - .Verify(x => x.ConnectAsync( - It.IsAny(), - It.IsAny()), Times.Once); - - newRunnerServer - .Verify(x => x.GetAgentPoolsAsync(null, TaskAgentPoolType.Automation), Times.Once); - - var tempLog = Path.GetTempFileName(); - File.Copy(tc.TraceFileName, tempLog, true); - var traceContent = File.ReadAllLines(tempLog); - Assert.Contains(traceContent, x => x.Contains("Try connect service with Token Service OAuth endpoint.")); - - Assert.True(listener._useMigratedCredentials); - Assert.False(listener._needToCheckAuthorizationUrlUpdate); - Assert.Null(listener._authorizationUrlRollbackReattemptDelayBackgroundTask); - Assert.Null(listener._authorizationUrlMigrationBackgroundTask); - } - } - - [Fact] - [Trait("Level", "L0")] - [Trait("Category", "Runner")] - public async void CreateSessionWithOriginalGetMessageMigtateToMigratedWaitForIdle() - { - using (TestHostContext tc = CreateTestContext()) - using (var tokenSource = new CancellationTokenSource()) - { - Tracing trace = tc.GetTrace(); - - // Arrange. - var expectedSession = new TaskAgentSession(); - _runnerServer - .Setup(x => x.CreateAgentSessionAsync( - _settings.PoolId, - It.Is(y => y != null), - tokenSource.Token)) - .Returns(Task.FromResult(expectedSession)); - - _runnerServer - .Setup(x => x.GetRunnerAuthUrlAsync( - _settings.PoolId, - _settings.AgentId)) - .Returns(async () => - { - await Task.Delay(10); - return "https://t.server"; - }); - - _credMgr.Setup(x => x.LoadCredentials(true)).Returns(new VssCredentials()); - - var originalCred = new CredentialData() { Scheme = Constants.Configuration.OAuth }; - originalCred.Data["authorizationUrl"] = "https://s.server"; - originalCred.Data["clientId"] = "d842fd7b-61b0-4a80-96b4-f2797c353897"; - - _store.Setup(x => x.GetCredentials()).Returns(originalCred); - _store.Setup(x => x.GetMigratedCredentials()).Returns(default(CredentialData)); - - // Act. - MessageListener listener = new MessageListener(); - listener.Initialize(tc); - - bool result = await listener.CreateSessionAsync(tokenSource.Token); - trace.Info("result: {0}", result); - - // Assert. - Assert.True(result); - _runnerServer - .Verify(x => x.CreateAgentSessionAsync( - _settings.PoolId, - It.Is(y => y != null), - tokenSource.Token), Times.Once()); - - Assert.False(listener._useMigratedCredentials); - Assert.True(listener._needToCheckAuthorizationUrlUpdate); - Assert.Null(listener._authorizationUrlRollbackReattemptDelayBackgroundTask); - Assert.NotNull(listener._authorizationUrlMigrationBackgroundTask); - - var arMessages = new TaskAgentMessage[] - { - new TaskAgentMessage - { - Body = "somebody1", - MessageId = 4234, - MessageType = JobRequestMessageTypes.PipelineAgentJobRequest - }, - new TaskAgentMessage - { - Body = "somebody2", - MessageId = 4235, - MessageType = JobCancelMessage.MessageType - }, - null, //should be skipped by GetNextMessageAsync implementation - null, - new TaskAgentMessage - { - Body = "somebody3", - MessageId = 4236, - MessageType = JobRequestMessageTypes.PipelineAgentJobRequest - } - }; - var messages = new Queue(arMessages); - - var busy = true; - var counter = 0; - _runnerServer - .Setup(x => x.GetAgentMessageAsync( - _settings.PoolId, expectedSession.SessionId, It.IsAny(), tokenSource.Token)) - .Returns(async (Int32 poolId, Guid sessionId, Int64? lastMessageId, CancellationToken cancellationToken) => - { - await Task.Delay(200); - if (++counter == 4) - { - busy = false; - } - return messages.Dequeue(); - }); - - var newRunnerServer = new Mock(); - tc.EnqueueInstance(newRunnerServer.Object); - - var keyManager = new Mock(); - keyManager.Setup(x => x.GetKey()).Returns(new RSACryptoServiceProvider(2048)); - tc.SetSingleton(keyManager.Object); - - var jobDispatcher = new Mock(); - - jobDispatcher.Setup(x => x.Busy).Returns(() => - { - return busy; - }); - tc.SetSingleton(jobDispatcher.Object); - tc.SetSingleton(new Mock().Object); - - TaskAgentMessage message1 = await listener.GetNextMessageAsync(tokenSource.Token); - TaskAgentMessage message2 = await listener.GetNextMessageAsync(tokenSource.Token); - TaskAgentMessage message3 = await listener.GetNextMessageAsync(tokenSource.Token); - Assert.Equal(arMessages[0], message1); - Assert.Equal(arMessages[1], message2); - Assert.Equal(arMessages[4], message3); - - //Assert - _runnerServer - .Verify(x => x.GetAgentMessageAsync( - _settings.PoolId, expectedSession.SessionId, It.IsAny(), tokenSource.Token), Times.Exactly(arMessages.Length)); - - _runnerServer - .Verify(x => x.GetRunnerAuthUrlAsync(_settings.PoolId, _settings.AgentId), Times.Once); - - _runnerServer - .Verify(x => x.ConnectAsync( - It.IsAny(), - It.IsAny()), Times.Exactly(2)); - - newRunnerServer - .Verify(x => x.ConnectAsync( - It.IsAny(), - It.IsAny()), Times.Once); - - newRunnerServer - .Verify(x => x.GetAgentPoolsAsync(null, TaskAgentPoolType.Automation), Times.Once); - - var tempLog = Path.GetTempFileName(); - File.Copy(tc.TraceFileName, tempLog, true); - var traceContent = File.ReadAllLines(tempLog); - Assert.Contains(traceContent, x => x.Contains("Job or runner updates in progress, update credentials next time.")); - Assert.Contains(traceContent, x => x.Contains("Try connect service with Token Service OAuth endpoint.")); - - Assert.True(listener._useMigratedCredentials); - Assert.False(listener._needToCheckAuthorizationUrlUpdate); - Assert.Null(listener._authorizationUrlRollbackReattemptDelayBackgroundTask); - Assert.Null(listener._authorizationUrlMigrationBackgroundTask); - } - } - - [Fact] - [Trait("Level", "L0")] - [Trait("Category", "Runner")] - public async void CreateSessionWithMigratedGetMessageNotMigrateAgain() - { - using (TestHostContext tc = CreateTestContext()) - using (var tokenSource = new CancellationTokenSource()) - { - Tracing trace = tc.GetTrace(); - - // Arrange. - var expectedSession = new TaskAgentSession(); - _runnerServer - .Setup(x => x.CreateAgentSessionAsync( - _settings.PoolId, - It.Is(y => y != null), - tokenSource.Token)) - .Returns(Task.FromResult(expectedSession)); - - _runnerServer - .Setup(x => x.GetRunnerAuthUrlAsync( - _settings.PoolId, - _settings.AgentId)) - .Returns(async () => - { - await Task.Delay(10); - return "https://t.server"; - }); - - _credMgr.Setup(x => x.LoadCredentials(true)).Returns(new VssCredentials()); - - var migratedCred = new CredentialData() { Scheme = Constants.Configuration.OAuth }; - migratedCred.Data["authorizationUrl"] = "https://t.server"; - migratedCred.Data["clientId"] = "d842fd7b-61b0-4a80-96b4-f2797c353897"; - - _store.Setup(x => x.GetCredentials()).Returns(migratedCred); - _store.Setup(x => x.GetMigratedCredentials()).Returns(default(CredentialData)); - - // Act. - MessageListener listener = new MessageListener(); - listener.Initialize(tc); - - bool result = await listener.CreateSessionAsync(tokenSource.Token); - trace.Info("result: {0}", result); - - // Assert. - Assert.True(result); - _runnerServer - .Verify(x => x.CreateAgentSessionAsync( - _settings.PoolId, - It.Is(y => y != null), - tokenSource.Token), Times.Once()); - - Assert.False(listener._useMigratedCredentials); - Assert.True(listener._needToCheckAuthorizationUrlUpdate); - Assert.Null(listener._authorizationUrlRollbackReattemptDelayBackgroundTask); - Assert.NotNull(listener._authorizationUrlMigrationBackgroundTask); - - var arMessages = new TaskAgentMessage[] - { - new TaskAgentMessage - { - Body = "somebody1", - MessageId = 4234, - MessageType = JobRequestMessageTypes.PipelineAgentJobRequest - }, - new TaskAgentMessage - { - Body = "somebody2", - MessageId = 4235, - MessageType = JobCancelMessage.MessageType - }, - null, //should be skipped by GetNextMessageAsync implementation - null, - new TaskAgentMessage - { - Body = "somebody3", - MessageId = 4236, - MessageType = JobRequestMessageTypes.PipelineAgentJobRequest - } - }; - var messages = new Queue(arMessages); - - _runnerServer - .Setup(x => x.GetAgentMessageAsync( - _settings.PoolId, expectedSession.SessionId, It.IsAny(), tokenSource.Token)) - .Returns(async (Int32 poolId, Guid sessionId, Int64? lastMessageId, CancellationToken cancellationToken) => - { - await Task.Delay(200); - return messages.Dequeue(); - }); - - var newRunnerServer = new Mock(); - tc.EnqueueInstance(newRunnerServer.Object); - - var keyManager = new Mock(); - keyManager.Setup(x => x.GetKey()).Returns(new RSACryptoServiceProvider(2048)); - tc.SetSingleton(keyManager.Object); - - tc.SetSingleton(new Mock().Object); - tc.SetSingleton(new Mock().Object); - - TaskAgentMessage message1 = await listener.GetNextMessageAsync(tokenSource.Token); - TaskAgentMessage message2 = await listener.GetNextMessageAsync(tokenSource.Token); - TaskAgentMessage message3 = await listener.GetNextMessageAsync(tokenSource.Token); - Assert.Equal(arMessages[0], message1); - Assert.Equal(arMessages[1], message2); - Assert.Equal(arMessages[4], message3); - - //Assert - _runnerServer - .Verify(x => x.GetAgentMessageAsync( - _settings.PoolId, expectedSession.SessionId, It.IsAny(), tokenSource.Token), Times.Exactly(arMessages.Length)); - - _runnerServer - .Verify(x => x.GetRunnerAuthUrlAsync(_settings.PoolId, _settings.AgentId), Times.Once); - - _runnerServer - .Verify(x => x.ConnectAsync( - It.IsAny(), - It.IsAny()), Times.Once); - - newRunnerServer - .Verify(x => x.ConnectAsync( - It.IsAny(), - It.IsAny()), Times.Never); - - newRunnerServer - .Verify(x => x.GetAgentPoolsAsync(null, TaskAgentPoolType.Automation), Times.Never); - - var tempLog = Path.GetTempFileName(); - File.Copy(tc.TraceFileName, tempLog, true); - var traceContent = File.ReadAllLines(tempLog); - Assert.Contains(traceContent, x => x.Contains("No needs to update authorization url")); - - Assert.False(listener._useMigratedCredentials); - Assert.True(listener._needToCheckAuthorizationUrlUpdate); - Assert.Null(listener._authorizationUrlRollbackReattemptDelayBackgroundTask); - Assert.NotNull(listener._authorizationUrlMigrationBackgroundTask); - } - } - - [Fact] - [Trait("Level", "L0")] - [Trait("Category", "Runner")] - public async void CreateSessionWithOriginalGetMessageMigrateToMigratedFallbackToOriginal() - { - using (TestHostContext tc = CreateTestContext()) - using (var tokenSource = new CancellationTokenSource()) - { - Tracing trace = tc.GetTrace(); - - // Arrange. - var expectedSession = new TaskAgentSession(); - _runnerServer - .Setup(x => x.CreateAgentSessionAsync( - _settings.PoolId, - It.Is(y => y != null), - tokenSource.Token)) - .Returns(Task.FromResult(expectedSession)); - - var originalVssCred = new VssCredentials(); - var migratedVssCred = new VssCredentials(); - _credMgr.Setup(x => x.LoadCredentials(true)).Returns(migratedVssCred); - _credMgr.Setup(x => x.LoadCredentials(false)).Returns(originalVssCred); - - var originalCred = new CredentialData() { Scheme = Constants.Configuration.OAuth }; - originalCred.Data["authorizationUrl"] = "https://s.server"; - originalCred.Data["clientId"] = "d842fd7b-61b0-4a80-96b4-f2797c353897"; - - var migratedCred = new CredentialData() { Scheme = Constants.Configuration.OAuth }; - migratedCred.Data["authorizationUrl"] = "https://t.server"; - migratedCred.Data["clientId"] = "d842fd7b-61b0-4a80-96b4-f2797c353897"; - - _store.Setup(x => x.GetCredentials()).Returns(originalCred); - _store.Setup(x => x.GetMigratedCredentials()).Returns(migratedCred); - - // Act. - MessageListener listener = new MessageListener(); - listener.Initialize(tc); - - bool result = await listener.CreateSessionAsync(tokenSource.Token); - trace.Info("result: {0}", result); - - // Assert. - Assert.True(result); - _runnerServer - .Verify(x => x.CreateAgentSessionAsync( - _settings.PoolId, - It.Is(y => y != null), - tokenSource.Token), Times.Once()); - - Assert.True(listener._useMigratedCredentials); - Assert.False(listener._needToCheckAuthorizationUrlUpdate); - Assert.Null(listener._authorizationUrlRollbackReattemptDelayBackgroundTask); - Assert.Null(listener._authorizationUrlMigrationBackgroundTask); - - var arMessages = new TaskAgentMessage[] - { - new TaskAgentMessage - { - Body = "somebody1", - MessageId = 4234, - MessageType = JobRequestMessageTypes.PipelineAgentJobRequest - }, - new TaskAgentMessage - { - Body = "somebody2", - MessageId = 4235, - MessageType = JobCancelMessage.MessageType - }, - null, //should be skipped by GetNextMessageAsync implementation - null, - new TaskAgentMessage - { - Body = "somebody3", - MessageId = 4236, - MessageType = JobRequestMessageTypes.PipelineAgentJobRequest - } - }; - var messages = new Queue(arMessages); - - var counter = 0; - _runnerServer - .Setup(x => x.GetAgentMessageAsync( - _settings.PoolId, expectedSession.SessionId, It.IsAny(), tokenSource.Token)) - .Returns(async (Int32 poolId, Guid sessionId, Int64? lastMessageId, CancellationToken cancellationToken) => - { - await Task.Delay(200); - counter++; - - if (counter == 5) - { - throw new TaskAgentNotFoundException("L0 runner not found"); - } - - if (counter == 6) - { - Assert.NotNull(listener._authorizationUrlRollbackReattemptDelayBackgroundTask); - Assert.False(listener._useMigratedCredentials); - } - - return messages.Dequeue(); - }); - - var newRunnerServer = new Mock(); - tc.EnqueueInstance(newRunnerServer.Object); - - var keyManager = new Mock(); - keyManager.Setup(x => x.GetKey()).Returns(new RSACryptoServiceProvider(2048)); - tc.SetSingleton(keyManager.Object); - - tc.SetSingleton(new Mock().Object); - tc.SetSingleton(new Mock().Object); - - TaskAgentMessage message1 = await listener.GetNextMessageAsync(tokenSource.Token); - TaskAgentMessage message2 = await listener.GetNextMessageAsync(tokenSource.Token); - TaskAgentMessage message3 = await listener.GetNextMessageAsync(tokenSource.Token); - Assert.Equal(arMessages[0], message1); - Assert.Equal(arMessages[1], message2); - Assert.Equal(arMessages[4], message3); - - //Assert - _runnerServer - .Verify(x => x.GetAgentMessageAsync( - _settings.PoolId, expectedSession.SessionId, It.IsAny(), tokenSource.Token), Times.Exactly(arMessages.Length + 1)); - - _runnerServer - .Verify(x => x.GetRunnerAuthUrlAsync(_settings.PoolId, _settings.AgentId), Times.Never); - - _runnerServer - .Verify(x => x.ConnectAsync( - It.IsAny(), - It.IsAny()), Times.AtLeast(2)); - - newRunnerServer - .Verify(x => x.ConnectAsync( - It.IsAny(), - It.IsAny()), Times.Never); - - newRunnerServer - .Verify(x => x.GetAgentPoolsAsync(null, TaskAgentPoolType.Automation), Times.Never); - - var tempLog = Path.GetTempFileName(); - File.Copy(tc.TraceFileName, tempLog, true); - var traceContent = File.ReadAllLines(tempLog); - Assert.Contains(traceContent, x => x.Contains("Fallback to original credentials and try again.")); - - Assert.False(listener._needToCheckAuthorizationUrlUpdate); - Assert.Null(listener._authorizationUrlMigrationBackgroundTask); - } - } - - [Fact] - [Trait("Level", "L0")] - [Trait("Category", "Runner")] - public async void CreateSessionWithOriginalGetMessageMigrateToMigratedFallbackToOriginalReattemptMigrated() - { - using (TestHostContext tc = CreateTestContext()) - using (var tokenSource = new CancellationTokenSource()) - { - Tracing trace = tc.GetTrace(); - - // Arrange. - var expectedSession = new TaskAgentSession(); - _runnerServer - .Setup(x => x.CreateAgentSessionAsync( - _settings.PoolId, - It.Is(y => y != null), - tokenSource.Token)) - .Returns(Task.FromResult(expectedSession)); - - var originalVssCred = new VssCredentials(); - var migratedVssCred = new VssCredentials(); - _credMgr.Setup(x => x.LoadCredentials(true)).Returns(migratedVssCred); - _credMgr.Setup(x => x.LoadCredentials(false)).Returns(originalVssCred); - - var originalCred = new CredentialData() { Scheme = Constants.Configuration.OAuth }; - originalCred.Data["authorizationUrl"] = "https://s.server"; - originalCred.Data["clientId"] = "d842fd7b-61b0-4a80-96b4-f2797c353897"; - - var migratedCred = new CredentialData() { Scheme = Constants.Configuration.OAuth }; - migratedCred.Data["authorizationUrl"] = "https://t.server"; - migratedCred.Data["clientId"] = "d842fd7b-61b0-4a80-96b4-f2797c353897"; - - _store.Setup(x => x.GetCredentials()).Returns(originalCred); - _store.Setup(x => x.GetMigratedCredentials()).Returns(migratedCred); - - // Act. - MessageListener listener = new MessageListener(); - listener.Initialize(tc); - - bool result = await listener.CreateSessionAsync(tokenSource.Token); - trace.Info("result: {0}", result); - - // Assert. - Assert.True(result); - _runnerServer - .Verify(x => x.CreateAgentSessionAsync( - _settings.PoolId, - It.Is(y => y != null), - tokenSource.Token), Times.Once()); - - Assert.True(listener._useMigratedCredentials); - Assert.False(listener._needToCheckAuthorizationUrlUpdate); - Assert.Null(listener._authorizationUrlRollbackReattemptDelayBackgroundTask); - Assert.Null(listener._authorizationUrlMigrationBackgroundTask); - - var arMessages = new TaskAgentMessage[] - { - new TaskAgentMessage - { - Body = "somebody1", - MessageId = 4234, - MessageType = JobRequestMessageTypes.PipelineAgentJobRequest - }, - new TaskAgentMessage - { - Body = "somebody2", - MessageId = 4235, - MessageType = JobCancelMessage.MessageType - }, - null, //should be skipped by GetNextMessageAsync implementation - null, - new TaskAgentMessage - { - Body = "somebody3", - MessageId = 4236, - MessageType = JobRequestMessageTypes.PipelineAgentJobRequest - } - }; - var messages = new Queue(arMessages); - - var counter = 0; - _runnerServer - .Setup(x => x.GetAgentMessageAsync( - _settings.PoolId, expectedSession.SessionId, It.IsAny(), tokenSource.Token)) - .Returns(async (Int32 poolId, Guid sessionId, Int64? lastMessageId, CancellationToken cancellationToken) => - { - await Task.Delay(200); - counter++; - - if (counter == 2) - { - throw new TaskAgentNotFoundException("L0 runner not found"); - } - - if (counter == 3) - { - Assert.NotNull(listener._authorizationUrlRollbackReattemptDelayBackgroundTask); - } - - return messages.Dequeue(); - }); - - var newRunnerServer = new Mock(); - tc.EnqueueInstance(newRunnerServer.Object); - - var keyManager = new Mock(); - keyManager.Setup(x => x.GetKey()).Returns(new RSACryptoServiceProvider(2048)); - tc.SetSingleton(keyManager.Object); - - tc.SetSingleton(new Mock().Object); - tc.SetSingleton(new Mock().Object); - - TaskAgentMessage message1 = await listener.GetNextMessageAsync(tokenSource.Token); - TaskAgentMessage message2 = await listener.GetNextMessageAsync(tokenSource.Token); - TaskAgentMessage message3 = await listener.GetNextMessageAsync(tokenSource.Token); - Assert.Equal(arMessages[0], message1); - Assert.Equal(arMessages[1], message2); - Assert.Equal(arMessages[4], message3); - - //Assert - _runnerServer - .Verify(x => x.GetAgentMessageAsync( - _settings.PoolId, expectedSession.SessionId, It.IsAny(), tokenSource.Token), Times.Exactly(arMessages.Length + 1)); - - _runnerServer - .Verify(x => x.GetRunnerAuthUrlAsync(_settings.PoolId, _settings.AgentId), Times.Never); - - _runnerServer - .Verify(x => x.ConnectAsync( - It.IsAny(), - It.IsAny()), Times.Exactly(3)); - - newRunnerServer - .Verify(x => x.ConnectAsync( - It.IsAny(), - It.IsAny()), Times.Never); - - newRunnerServer - .Verify(x => x.GetAgentPoolsAsync(null, TaskAgentPoolType.Automation), Times.Never); - - var tempLog = Path.GetTempFileName(); - File.Copy(tc.TraceFileName, tempLog, true); - var traceContent = File.ReadAllLines(tempLog); - Assert.Contains(traceContent, x => x.Contains("Fallback to original credentials and try again.")); - Assert.Contains(traceContent, x => x.Contains("Re-attempt to use migrated credential")); - - Assert.True(listener._useMigratedCredentials); - Assert.False(listener._needToCheckAuthorizationUrlUpdate); - Assert.Null(listener._authorizationUrlRollbackReattemptDelayBackgroundTask); - Assert.Null(listener._authorizationUrlMigrationBackgroundTask); - } - } - - [Fact] - [Trait("Level", "L0")] - [Trait("Category", "Runner")] - public async void CreateSessionWithOriginalGetMessageWithOriginalEnvOverwrite() - { - try - { - Environment.SetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_SPSAUTHURL", "1"); - using (TestHostContext tc = CreateTestContext()) - using (var tokenSource = new CancellationTokenSource()) - { - Tracing trace = tc.GetTrace(); - - // Arrange. - var expectedSession = new TaskAgentSession(); - _runnerServer - .Setup(x => x.CreateAgentSessionAsync( - _settings.PoolId, - It.Is(y => y != null), - tokenSource.Token)) - .Returns(Task.FromResult(expectedSession)); - - var originalVssCred = new VssCredentials(); - var migratedVssCred = new VssCredentials(); - _credMgr.Setup(x => x.LoadCredentials(false)).Returns(originalVssCred); - _credMgr.Setup(x => x.LoadCredentials(true)).Returns(migratedVssCred); - - var originalCred = new CredentialData() { Scheme = Constants.Configuration.OAuth }; - originalCred.Data["authorizationUrl"] = "https://s.server"; - originalCred.Data["clientId"] = "d842fd7b-61b0-4a80-96b4-f2797c353897"; - - var migratedCred = new CredentialData() { Scheme = Constants.Configuration.OAuth }; - migratedCred.Data["authorizationUrl"] = "https://t.server"; - migratedCred.Data["clientId"] = "d842fd7b-61b0-4a80-96b4-f2797c353897"; - - _store.Setup(x => x.GetCredentials()).Returns(originalCred); - _store.Setup(x => x.GetMigratedCredentials()).Returns(migratedCred); - - // Act. - MessageListener listener = new MessageListener(); - listener.Initialize(tc); - - bool result = await listener.CreateSessionAsync(tokenSource.Token); - trace.Info("result: {0}", result); - - // Assert. - Assert.True(result); - _runnerServer - .Verify(x => x.CreateAgentSessionAsync( - _settings.PoolId, - It.Is(y => y != null), - tokenSource.Token), Times.Once()); - - Assert.False(listener._useMigratedCredentials); - Assert.False(listener._needToCheckAuthorizationUrlUpdate); - Assert.Null(listener._authorizationUrlRollbackReattemptDelayBackgroundTask); - Assert.Null(listener._authorizationUrlMigrationBackgroundTask); - - var arMessages = new TaskAgentMessage[] - { - new TaskAgentMessage - { - Body = "somebody1", - MessageId = 4234, - MessageType = JobRequestMessageTypes.PipelineAgentJobRequest - }, - new TaskAgentMessage - { - Body = "somebody2", - MessageId = 4235, - MessageType = JobCancelMessage.MessageType - }, - null, //should be skipped by GetNextMessageAsync implementation - null, - new TaskAgentMessage - { - Body = "somebody3", - MessageId = 4236, - MessageType = JobRequestMessageTypes.PipelineAgentJobRequest - } - }; - var messages = new Queue(arMessages); - - _runnerServer - .Setup(x => x.GetAgentMessageAsync( - _settings.PoolId, expectedSession.SessionId, It.IsAny(), tokenSource.Token)) - .Returns(async (Int32 poolId, Guid sessionId, Int64? lastMessageId, CancellationToken cancellationToken) => - { - await Task.Delay(1); - return messages.Dequeue(); - }); - - TaskAgentMessage message1 = await listener.GetNextMessageAsync(tokenSource.Token); - TaskAgentMessage message2 = await listener.GetNextMessageAsync(tokenSource.Token); - TaskAgentMessage message3 = await listener.GetNextMessageAsync(tokenSource.Token); - Assert.Equal(arMessages[0], message1); - Assert.Equal(arMessages[1], message2); - Assert.Equal(arMessages[4], message3); - - //Assert - _runnerServer - .Verify(x => x.GetAgentMessageAsync( - _settings.PoolId, expectedSession.SessionId, It.IsAny(), tokenSource.Token), Times.Exactly(arMessages.Length)); - - _runnerServer - .Verify(x => x.GetRunnerAuthUrlAsync(_settings.PoolId, _settings.AgentId), Times.Never); - - _runnerServer - .Verify(x => x.ConnectAsync( - It.IsAny(), - It.IsAny()), Times.Once); - - Assert.False(listener._useMigratedCredentials); - Assert.False(listener._needToCheckAuthorizationUrlUpdate); - Assert.Null(listener._authorizationUrlRollbackReattemptDelayBackgroundTask); - Assert.Null(listener._authorizationUrlMigrationBackgroundTask); - } - } - finally - { - Environment.SetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_SPSAUTHURL", null); } } }