public override void ExecuteCmdlet() { if (ShouldProcess(Instance, Resources.SynchronizingAnalysisServicesServer)) { correlationId = Guid.NewGuid(); WriteObject(string.Format("Sending sync request for database '{0}' to server '{1}'. Correlation Id: '{2}'.", Database, Instance, correlationId.ToString())); var context = AsAzureClientSession.Instance.Profile.Context; AsAzureClientSession.Instance.Login(context); WriteProgress(new ProgressRecord(0, "Sync-AzureAnalysisServicesInstance.", string.Format("Authenticating user for '{0}' environment.", context.Environment.Name))); var clusterResolveResult = ClusterResolve(context, serverName); var virtualServerName = clusterResolveResult.CoreServerName.Split(":".ToCharArray())[0]; if (!serverName.Equals(virtualServerName) && !clusterResolveResult.CoreServerName.EndsWith(":rw")) { throw new SynchronizationFailedException("Sync request can only be sent to the management endpoint"); } this.clusterResolveResult = clusterResolveResult; Uri clusterBaseUri = new Uri(string.Format("{0}{1}{2}", Uri.UriSchemeHttps, Uri.SchemeDelimiter, clusterResolveResult.ClusterFQDN)); var accessToken = this.TokenCacheItemProvider.GetTokenFromTokenCache(AsAzureClientSession.TokenCache, context.Account.UniqueId, context.Environment.Name); ScaleOutServerDatabaseSyncDetails syncResult = null; try { WriteProgress(new ProgressRecord(0, "Sync-AzureAnalysisServicesInstance.", string.Format("Successfully authenticated for '{0}' environment.", context.Environment.Name))); syncResult = SynchronizeDatabaseAsync(context, clusterBaseUri, Database, accessToken).GetAwaiter().GetResult(); } catch (AggregateException aex) { foreach (var innerException in aex.Flatten().InnerExceptions) { WriteExceptionError(innerException); } } catch (Exception ex) { WriteExceptionError(ex); } if (syncResult == null) { throw new SynchronizationFailedException(string.Format(Resources.SyncASPollStatusUnknownMessage.FormatInvariant( this.clusterResolveResult.CoreServerName, correlationId, DateTime.Now.ToString(CultureInfo.InvariantCulture), string.Format("RootActivityId: {0}, Date Time UTC: {1}", syncRequestRootActivityId, syncRequestTimeStamp)))); } if (syncResult.SyncState != DatabaseSyncState.Completed) { var serializedDetails = JsonConvert.SerializeObject(syncResult); throw new SynchronizationFailedException(serializedDetails); } if (PassThru.IsPresent) { WriteObject(syncResult, true); } } }
/// <summary> /// Resolves the cluster to which the request needs to be sent for the current environment /// </summary> /// <param name="context"></param> /// <param name="serverName"></param> /// <returns></returns> private ClusterResolutionResult ClusterResolve(AsAzureContext context, string serverName) { Uri clusterResolveBaseUri = new Uri(string.Format("{0}{1}{2}", Uri.UriSchemeHttps, Uri.SchemeDelimiter, context.Environment.Name)); UriBuilder resolvedUriBuilder = new UriBuilder(clusterResolveBaseUri); string rolloutAccessToken = this.TokenCacheItemProvider.GetTokenFromTokenCache(AsAzureClientSession.TokenCache, context.Account.UniqueId, context.Environment.Name); var resolveEndpoint = "/webapi/clusterResolve"; var content = new StringContent($"ServerName={serverName}"); content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded"); this.AsAzureHttpClient.resetHttpClient(); using (HttpResponseMessage message = AsAzureHttpClient.CallPostAsync( clusterResolveBaseUri, resolveEndpoint, rolloutAccessToken, content).Result) { message.EnsureSuccessStatusCode(); var rawResult = message.Content.ReadAsStringAsync().Result; ClusterResolutionResult result = JsonConvert.DeserializeObject <ClusterResolutionResult>(rawResult); return(result); } }
public void SynchronizeAzureASInstance_FailsAfterTooManyRetries() { Mock <ICommandRuntime> commandRuntimeMock = new Mock <ICommandRuntime>(); // Setup // Clear the the current profile AsAzureClientSession.Instance.Profile.Environments.Clear(); var mockAuthenticationProvider = new Mock <IAsAzureAuthenticationProvider>(); mockAuthenticationProvider.Setup( authProvider => authProvider.GetAadAuthenticatedToken( It.IsAny <AsAzureContext>(), It.IsAny <SecureString>(), #if NETSTANDARD It.IsAny <Action <string> >(), #else It.IsAny <PromptBehavior>(), #endif It.IsAny <string>(), It.IsAny <string>(), It.IsAny <Uri>())).Returns(testToken); AsAzureClientSession.Instance.SetAsAzureAuthenticationProvider(mockAuthenticationProvider.Object); commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny <string>(), It.IsAny <string>())).Returns(true); // Set up AsAzureHttpClient mock var mockAsAzureHttpClient = new Mock <IAsAzureHttpClient>(); // set up cluster resolve respnose ClusterResolutionResult resolveResult = new ClusterResolutionResult() { ClusterFQDN = "resolved.westcentralus.asazure.windows.net", CoreServerName = testServer + ":rw", TenantId = Guid.NewGuid().ToString() }; mockAsAzureHttpClient .Setup(obj => obj.CallPostAsync( It.IsAny <Uri>(), It.Is <string>(s => s.Contains("clusterResolve")), It.IsAny <string>(), It.IsAny <HttpContent>())) .Returns(Task <HttpResponseMessage> .FromResult( new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(JsonConvert.SerializeObject(resolveResult)) })); // set up sync respnose var postResponse = new HttpResponseMessage(HttpStatusCode.Accepted); postResponse.Headers.Location = new Uri("https://1"); postResponse.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromMilliseconds(500)); postResponse.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); postResponse.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); mockAsAzureHttpClient .Setup(obj => obj.CallPostAsync( It.IsAny <Uri>(), It.Is <string>(s => s.Contains("sync")), It.IsAny <string>(), It.IsAny <Guid>(), null)) .Returns(Task <Mock <HttpResponseMessage> > .FromResult(postResponse)); var getResponse1 = new HttpResponseMessage(HttpStatusCode.SeeOther); getResponse1.Headers.Location = new Uri("https://done"); getResponse1.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromMilliseconds(500)); getResponse1.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); getResponse1.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); mockAsAzureHttpClient .Setup(obj => obj.CallGetAsync( It.Is <Uri>(u => u.OriginalString.Contains("1")), It.IsAny <string>(), It.IsAny <string>(), It.IsAny <Guid>())) .Returns(Task <HttpResponseMessage> .FromResult(getResponse1)); var getResponseSucceed = new HttpResponseMessage { StatusCode = HttpStatusCode.OK, Content = new StringContent( "{\n\"database\":\"db0\",\n\"syncstate\":\"Completed\"\n}", Encoding.UTF8, "application/json") }; getResponseSucceed.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); getResponseSucceed.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); var getResponseError = new HttpResponseMessage(HttpStatusCode.InternalServerError); getResponseError.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); getResponseError.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); var finalResponses = new Queue <HttpResponseMessage>(new[] { getResponseError, getResponseError, getResponseError, getResponseSucceed }); mockAsAzureHttpClient .Setup(obj => obj.CallGetAsync( It.Is <Uri>(u => u.OriginalString.Contains("done")), It.IsAny <string>(), It.IsAny <string>(), It.IsAny <Guid>())) .Returns(() => Task.FromResult(finalResponses.Dequeue())); var mockTokenCacheItemProvider = new Mock <ITokenCacheItemProvider>(); mockTokenCacheItemProvider .Setup(obj => obj.GetTokenFromTokenCache(It.IsAny <TokenCache>(), It.IsAny <string>())) .Returns(testToken); var syncCmdlet = new SynchronizeAzureAzureAnalysisServer(mockAsAzureHttpClient.Object, mockTokenCacheItemProvider.Object) { CommandRuntime = commandRuntimeMock.Object }; var addAmdlet = new AddAzureASAccountCommand() { CommandRuntime = commandRuntimeMock.Object }; DoLogin(addAmdlet); syncCmdlet.Instance = testServer + ":rw"; syncCmdlet.Database = "db0"; // Act syncCmdlet.InvokeBeginProcessing(); Assert.Throws <SynchronizationFailedException>(() => syncCmdlet.ExecuteCmdlet()); syncCmdlet.InvokeEndProcessing(); }