/// <summary> /// Waits for the operation to complete. /// </summary> /// <param name="operationResult">The operation result.</param> internal string WaitOnOperation(OperationResult operationResult) { // TODO: Re-factor this mess. this.ProgressTrackerObject.UpdateProgress("Starting", 0); var trackingResult = this.HandleOperationResponse(operationResult, this.IsResourceCreateOrUpdate ? operationResult.OperationUri : operationResult.LocationUri); while (trackingResult != null && trackingResult.ShouldWait) { operationResult = this.GetResourcesClient() .GetOperationResult<JToken>(trackingResult.TrackingUri, this.CancellationToken) .Result; trackingResult = this.HandleOperationResponse(operationResult, trackingResult.TrackingUri); if (trackingResult.ShouldWait && trackingResult.RetryAfter != null) { Task.Delay(delay: trackingResult.RetryAfter.Value, cancellationToken: this.CancellationToken).Wait(cancellationToken: this.CancellationToken); } } this.ProgressTrackerObject.UpdateProgress("Complete", 100); return operationResult.Value; }
/// <summary> /// Gets the azure async operation state. /// </summary> /// <param name="operationResult">The operation result.</param> private string GetAzureAsyncOperationState(OperationResult operationResult) { try { var result = this.ResourcesClientFactory() .GetAzureAsyncOperationResource(operationResult.AzureAsyncOperationUri, this.CancellationToken) .Result; return result == null ? null : result.Status; } catch (Exception e) { if (e.IsFatal()) { throw; } return null; } }
/// <summary> /// Gets the state from the resource. /// </summary> /// <param name="operationResult">The operation result.</param> private static string GetResourceState(OperationResult operationResult) { Resource<InsensitiveDictionary<JToken>> resource; if (!operationResult.Value.TryConvertTo<Resource<InsensitiveDictionary<JToken>>>(out resource)) { return null; } if (resource == null) { return null; } resource.Properties = resource.Properties ?? new InsensitiveDictionary<JToken>(); JToken provisioningStateJToken; return resource.Properties.TryGetValue("provisioningState", out provisioningStateJToken) ? provisioningStateJToken.ToString() : null; }
/// <summary> /// Indicates a failed terminal state. /// </summary> /// <param name="operationResult">The result of the operation.</param> /// <param name="message">The exception message.</param> private void FailedResult(OperationResult operationResult, string message) { var result = new TrackingOperationResult { ShouldWait = false, Failed = true, RetryAfter = operationResult.RetryAfter ?? LongRunningOperationHelper.DefaultRetryAfter, TrackingUri = operationResult.LocationUri ?? operationResult.OperationUri, OperationResult = operationResult, }; this.UpdateProgress(result); throw new InvalidOperationException(message); }
/// <summary> /// Extra code for handling resource create/update calls. /// </summary> /// <param name="operationResult">The result of the operation.</param> private string GetOperationState(OperationResult operationResult) { return operationResult.AzureAsyncOperationUri != null ? this.GetAzureAsyncOperationState(operationResult) : ProgressTracker.GetResourceState(operationResult); }
/// <summary> /// Indicates an in-progress state. /// </summary> /// <param name="operationResult">The result of the operation.</param> private TrackingOperationResult WaitResult(OperationResult operationResult) { var result = new TrackingOperationResult { ShouldWait = true, Failed = false, RetryAfter = operationResult.RetryAfter ?? LongRunningOperationHelper.DefaultRetryAfter, TrackingUri = operationResult.LocationUri ?? operationResult.OperationUri, OperationResult = operationResult, }; this.UpdateProgress(result); return result; }
/// <summary> /// Extra code for handling resource create/update calls. /// </summary> /// <param name="operationResult">The result of the operation.</param> private TrackingOperationResult HandleCreateOrUpdateResponse(OperationResult operationResult) { Resource<InsensitiveDictionary<JToken>> resource; if (!operationResult.Value.TryConvertTo<Resource<InsensitiveDictionary<JToken>>>(out resource)) { return null; } if (resource == null && operationResult.HttpStatusCode == HttpStatusCode.Created) { return this.SuccessfulResult(operationResult); } if (resource == null) { this.FailedResult( operationResult, "The operation failed because resource could not be de-serialized."); } resource.Properties = resource.Properties ?? new InsensitiveDictionary<JToken>(); JToken provisioningStateJToken; if (resource.Properties.TryGetValue("provisioningState", out provisioningStateJToken)) { TerminalProvisioningStates resourceProvisioningState; if (Enum.TryParse(value: provisioningStateJToken.ToString(), ignoreCase: true, result: out resourceProvisioningState)) { if (resourceProvisioningState == TerminalProvisioningStates.Succeeded || resourceProvisioningState == TerminalProvisioningStates.Ready) { return this.SuccessfulResult(operationResult); } if (resourceProvisioningState == TerminalProvisioningStates.Failed || resourceProvisioningState == TerminalProvisioningStates.Canceled) { this.FailedResult( operationResult, string.Format("The operation failed because resource is in the: '{0}' state. Please check the logs for more details.", provisioningStateJToken)); } } else { return this.WaitResult(operationResult); } } return this.SuccessfulResult(operationResult); }
/// <summary> /// Handles the operation response/ /// </summary> /// <param name="operationResult">The result of the operation.</param> /// <param name="lastRequestUri">The last <see cref="Uri"/> that was used to request operation state.</param> private TrackingOperationResult HandleOperationResponse(OperationResult operationResult, Uri lastRequestUri) { if (!operationResult.HttpStatusCode.IsSuccessfulRequest()) { if (operationResult.HttpStatusCode.IsServerFailureRequest() || operationResult.HttpStatusCode == HttpStatusCodeExt.TooManyRequests) { var result = new TrackingOperationResult { ShouldWait = true, Failed = false, RetryAfter = operationResult.RetryAfter ?? LongRunningOperationHelper.DefaultRetryAfter, TrackingUri = lastRequestUri, OperationResult = operationResult, }; this.UpdateProgress(result); return result; } else { this.FailedResult( operationResult, string.Format("The operation failed because the resource provider returned an unexpected HTTP status code of: '{0}'.", (int)operationResult.HttpStatusCode)); } } if (operationResult.HttpStatusCode == HttpStatusCode.Accepted) { return this.WaitResult(operationResult); } if (operationResult.HttpStatusCode != HttpStatusCode.OK && operationResult.HttpStatusCode != HttpStatusCode.Created && (!this.IsResourceCreateOrUpdate && operationResult.HttpStatusCode != HttpStatusCode.NoContent)) { this.FailedResult( operationResult, string.Format("The operation failed because the resource provider returned an unexpected HTTP status code of: '{0}'.", (int)operationResult.HttpStatusCode)); } return this.IsResourceCreateOrUpdate ? this.HandleCreateOrUpdateResponse(operationResult) : this.SuccessfulResult(operationResult); }
/// <summary> /// Gets the state from the resource. /// </summary> /// <param name="operationResult">The operation result.</param> private static string GetResourceState(OperationResult operationResult) { var resource = operationResult.Value == null ? null : operationResult.Value .ToObject<Resource<InsensitiveDictionary<JToken>>>(JsonExtensions.JsonObjectTypeSerializer); if (resource == null) { return null; } resource.Properties = resource.Properties ?? new InsensitiveDictionary<JToken>(); JToken provisioningStateJToken; return resource.Properties.TryGetValue("provisioningState", out provisioningStateJToken) ? provisioningStateJToken.ToString() : null; }
/// <summary> /// Extra code for handling resource create/update calls. /// </summary> /// <param name="operationResult">The result of the operation.</param> private string GetOperationState(OperationResult operationResult) { return(operationResult.AzureAsyncOperationUri != null ? this.GetAzureAsyncOperationState(operationResult) : ProgressTracker.GetResourceState(operationResult)); }