/// <summary>
        /// Updates PollingState from GET operations.
        /// </summary>
        /// <typeparam name="TBody">Type of the resource body.</typeparam>
        /// <typeparam name="THeader">Type of the resource header.</typeparam>
        /// <param name="client">IAzureClient</param>
        /// <param name="pollingState">Current polling state.</param>
        /// <param name="getOperationUri">Uri for the get operation</param>
        /// <param name="customHeaders">Headers that will be added to request</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>Task.</returns>
        private static async Task UpdateStateFromGetResourceOperation <TBody, THeader>(
            IAzureClient client,
            PollingState <TBody, THeader> pollingState,
            Uri getOperationUri,
            Dictionary <string, List <string> > customHeaders,
            CancellationToken cancellationToken,
            HttpMethod initialRequestMethod) where TBody : class where THeader : class
        {
            AzureAsyncOperation asyncOperation = null;

            AzureOperationResponse <JObject, JObject> responseWithResource = await GetRawAsync(client,
                                                                                               getOperationUri.AbsoluteUri, customHeaders, cancellationToken).ConfigureAwait(false);

            if (responseWithResource.Body == null)
            {
                throw new CloudException(Resources.NoBody);
            }

            string responseContent = await responseWithResource.Response.Content.ReadAsStringAsync().ConfigureAwait(false);

            pollingState.Response = responseWithResource.Response;
            pollingState.Request  = responseWithResource.Request;
            pollingState.Resource = responseWithResource.Body.ToObject <TBody>(JsonSerializer
                                                                               .Create(client.DeserializationSettings));
            pollingState.ResourceHeaders = responseWithResource.Headers.ToObject <THeader>(JsonSerializer
                                                                                           .Create(client.DeserializationSettings));

            // In 202 pattern on PUT ProvisioningState may not be present in
            // the response. In that case the assumption is the status is Succeeded.

            // We try to check if the response had status/error returned
            // the reason we deserialize it as AsyncOperation is simply because we are trying to reuse the AsyncOperation model for deserialization (which has Error, Code and Message model types)
            // which is how the response is returned
            // Ideally the response body should be provided as a type TBody, but TBody is a type defined in the swagger and so we cannot provide that type in the constraint hence we end up using a generic
            // JBody type
            try
            {
                asyncOperation = responseWithResource.Body.ToObject <AzureAsyncOperation>(JsonSerializer.Create(client.DeserializationSettings));
            }
            catch { }

            pollingState = GetUpdatedPollingStatus <TBody, THeader>(asyncOperation, responseWithResource, pollingState, responseContent, initialRequestMethod);
        }
        /// <summary>
        /// Updates PollingState from Location header.
        /// </summary>
        /// <typeparam name="TBody">Type of the resource body.</typeparam>
        /// <typeparam name="THeader">Type of the resource header.</typeparam>
        /// <param name="client">IAzureClient</param>
        /// <param name="pollingState">Current polling state.</param>
        /// <param name="customHeaders">Headers that will be added to request</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <param name="initialRequestMethod">Http method of the initial long running operation request</param>
        /// <returns>Task.</returns>
        private static async Task UpdateStateFromLocationHeader <TBody, THeader>(
            IAzureClient client,
            PollingState <TBody, THeader> pollingState,
            Dictionary <string, List <string> > customHeaders,
            CancellationToken cancellationToken,
            HttpMethod initialRequestMethod) where TBody : class where THeader : class
        {
            AzureAsyncOperation asyncOperation = null;

            AzureOperationResponse <JObject, JObject> responseWithResource = await client.GetRawAsync(
                pollingState.LocationHeaderLink,
                customHeaders,
                cancellationToken).ConfigureAwait(false);

            string responseContent = await responseWithResource.Response.Content.ReadAsStringAsync().ConfigureAwait(false);

            pollingState.Status   = responseWithResource.Response.StatusCode.ToString();
            pollingState.Response = responseWithResource.Response;
            pollingState.Request  = responseWithResource.Request;
            pollingState.Resource = responseWithResource.Body == null ? null : responseWithResource.Body.ToObject <TBody>(JsonSerializer
                                                                                                                          .Create(client.DeserializationSettings));
            pollingState.ResourceHeaders = responseWithResource.Headers.ToObject <THeader>(JsonSerializer
                                                                                           .Create(client.DeserializationSettings));

            // We try to check if the response had status/error returned
            // the reason we deserialize it as AsyncOperation is simply because we are trying to reuse the AsyncOperation model for deserialization (which has Error, Code and Message model types)
            // which is how the response is returned
            // Ideally the response body should be provided as a type TBody, but TBody is a type defined in the swagger and so we cannot provide that type in the constraint hence we end up using a generic
            // JBody type
            try
            {
                asyncOperation = responseWithResource.Body.ToObject <AzureAsyncOperation>(JsonSerializer.Create(client.DeserializationSettings));
            }
            catch { }

            pollingState = GetUpdatedPollingStatus <TBody, THeader>(asyncOperation, responseWithResource, pollingState, responseContent, initialRequestMethod);
        }
Exemplo n.º 3
0
        public async Task Run()
        {
            var op = new AzureAsyncOperation();
            var restOp = new RestException();

            var files = Settings.Instance.FileSystem.GetFiles(Settings.Instance.OutputDirectory, "*.cs",
                    SearchOption.AllDirectories).
                ToDictionary(each => each, each => Settings.Instance.FileSystem.ReadFileAsText(each));

            var projectId = ProjectId.CreateNewId();
            var solution = new AdhocWorkspace().CurrentSolution
                .AddProject(projectId, "MyProject", "MyProject", LanguageNames.CSharp)
                .AddMetadataReference(projectId, Mscorlib)
                .AddMetadataReference(projectId, AppDomain.CurrentDomain.GetAssemblies()
                    .Where(
                        a =>
                            string.Compare(a.GetName().Name, "Microsoft.Rest.ClientRuntime.Azure",
                                StringComparison.OrdinalIgnoreCase) == 0)
                    .Select(a => MetadataReference.CreateFromFile(a.Location)).Single())
                .AddMetadataReference(projectId, AppDomain.CurrentDomain.GetAssemblies()
                    .Where(
                        a =>
                            string.Compare(a.GetName().Name, "Microsoft.Rest.ClientRuntime",
                                StringComparison.OrdinalIgnoreCase) == 0)
                    .Select(a => MetadataReference.CreateFromFile(a.Location)).Single())
                .AddMetadataReference(projectId, AppDomain.CurrentDomain.GetAssemblies()
                    .Where(a => string.Compare(a.GetName().Name, "System", StringComparison.OrdinalIgnoreCase) == 0)
                    .Select(a => MetadataReference.CreateFromFile(a.Location)).Single());

            // Add existing files
            foreach (var file in files.Keys)
            {
                var documentId = DocumentId.CreateNewId(projectId);
                solution = solution.AddDocument(documentId, file, SourceText.From(files[file]));
            }

            // Simplify docs and add to 
            foreach (var proj in solution.Projects)
            {
                foreach (var document in proj.Documents)
                {
                    var newRoot = await document.GetSyntaxRootAsync();

                    // get the namespaces used in the file
                    var names = new GetQualifiedNames().GetNames(newRoot);

                    // add the usings that we found
                    newRoot = new AddUsingsRewriter(names).Visit(newRoot);

                    // tell roslyn to simplify where it can
                    newRoot = new SimplifyNamesRewriter().Visit(newRoot);
                    var doc = document.WithSyntaxRoot(newRoot);

                    // reduce the code 
                    var text = Simplifier.ReduceAsync(doc)
                        .Result.GetTextAsync()
                        .Result.ToString()
                        // get rid of any BOMs 
                        .Trim('\x00EF', '\x00BB', '\x00BF', '\uFEFF', '\u200B');


                    // special cases the simplifier can't handle.
                    text = text.
                        Replace("[Newtonsoft.Json.JsonConverter(", "[JsonConverter(").
                        Replace("[System.Runtime.Serialization.EnumMember(", "[EnumMember(").
                        Replace("[Newtonsoft.Json.JsonProperty(", "[JsonProperty(").
                        Replace("[Newtonsoft.Json.JsonProperty]", "[JsonProperty]").
                        Replace("[Newtonsoft.Json.JsonObject]", "[JsonObject]").
                        Replace("[Microsoft.Rest.Serialization.JsonTransformation]", "[JsonTransformation]").
                        Replace("[Newtonsoft.Json.JsonExtensionData]", "[JsonExtensionData]");

                        // Write out the files back to their original location
                        var output = Path.Combine(Settings.Instance.FileSystem.CurrentDirectory, document.Name);
                        Settings.Instance.FileSystem.WriteFile(output, text);
                }
            }
        }
        /// <summary>
        /// The primary purpose for this function is to get status and if there is any error
        /// Update error information to pollingState.Error and pollingState.Exception
        ///
        /// We have on a very high level two cases
        /// 1) Regardless what kind of LRO operation it is (AzureAsync, locaiton header) either we get error or we dont
        /// 2) If we get error object, this function expects that information in the form of AzureAsyncOperation model type
        /// 3) We get status and error information from AzureAsyncOperation modele and update PollingState accordingly.
        /// 3) If AzureAsyncOperation is null, we assume there was no error retruned in the response
        /// 4) And we get the status from provisioningState and update pollingState accordinly
        /// </summary>
        /// <typeparam name="TBody"></typeparam>
        /// <typeparam name="THeader"></typeparam>
        /// <param name="asyncOperation"></param>
        /// <param name="azureResponse"></param>
        /// <param name="pollState"></param>
        /// <param name="responseContent"></param>
        /// <param name="initialRequestMethod"></param>
        /// <returns></returns>
        private static PollingState <TBody, THeader> GetUpdatedPollingStatus <TBody, THeader>(
            AzureAsyncOperation asyncOperation,
            AzureOperationResponse <JObject, JObject> azureResponse,
            PollingState <TBody, THeader> pollState,
            string responseContent,
            HttpMethod initialRequestMethod)
            where TBody : class
            where THeader : class
        {
            PollingState <TBody, THeader> pollingState = pollState;
            HttpStatusCode statusCode;

            // We are only interested if we see the status as one of the failed states and we have a valid error body
            if (AzureAsyncOperation.FailedStatuses.Any(
                    s => s.Equals(pollingState.Status, StringComparison.OrdinalIgnoreCase)))
            {
                if (asyncOperation?.Error == null)
                {
                    // we need this check until service teams starts implementing v2.2 Azure REST API guidlines, when error will be mandatory on Failed/Canceled status
                    // in Az async operation, it's not madatory currently to send error body on failed/cancelled status
                    if (string.IsNullOrEmpty(pollingState.AzureAsyncOperationHeaderLink))
                    {
                        asyncOperation = null;
                    }
                    //else
                    //{
                    //    // there is no error body, so asynOperation is of no use for us at this stage, we will continue analyzing the response and try to find provisioning state etc
                    //    asyncOperation = null;
                    //}
                }
            }
            else
            {
                // also if the status is a non-standard terminal states (RP provided state e.g. TestFailed, TestSucceeded etc)
                // we again assume this is a response that RP provided for their LRO will continue analyzing the response accordingly
                asyncOperation = null;
            }


            if (asyncOperation != null)
            {
                string errorMessage = string.Empty;
                string errorCode    = string.Empty;

                pollingState.Status = asyncOperation.Status;

                if (asyncOperation?.Error == null)
                {
                    errorMessage = string.Format(
                        CultureInfo.InvariantCulture,
                        Resources.LongRunningOperationFailed,
                        asyncOperation.Status);
                }
                else
                {
                    errorMessage = string.Format(
                        CultureInfo.InvariantCulture,
                        Resources.LROOperationFailedAdditionalInfo,
                        asyncOperation.Status, asyncOperation.Error?.Message);
                    errorCode = asyncOperation.Error.Code;
                }

                pollingState.Error = new CloudError()
                {
                    Code    = errorCode,
                    Message = errorMessage
                };

                pollingState.CloudException = new CloudException(errorMessage)
                {
                    Body     = asyncOperation?.Error,
                    Request  = new HttpRequestMessageWrapper(pollingState.Request, null),
                    Response = new HttpResponseMessageWrapper(pollingState.Response, responseContent)
                };
            }
            else if (azureResponse != null)
            {
                statusCode = azureResponse.Response.StatusCode;
                var resource = azureResponse.Body;

                if (statusCode == HttpStatusCode.Accepted)
                {
                    pollingState.Status = AzureAsyncOperation.InProgressStatus;
                }
                else if (statusCode == HttpStatusCode.OK ||
                         (statusCode == HttpStatusCode.Created && initialRequestMethod == HttpMethod.Put) ||
                         (statusCode == HttpStatusCode.NoContent && (initialRequestMethod == HttpMethod.Delete || initialRequestMethod == HttpMethod.Post)))
                {
                    // We check if we got provisionState and we get the status from provisioning state

                    // In 202 pattern on PUT ProvisioningState may not be present in
                    // the response. In that case the assumption is the status is Succeeded.
                    if (resource != null &&
                        resource["properties"] != null &&
                        resource["properties"]["provisioningState"] != null)
                    {
                        pollingState.Status = (string)resource["properties"]["provisioningState"];
                    }
                    else
                    {
                        pollingState.Status = AzureAsyncOperation.SuccessStatus;
                    }
                }
                else
                {
                    throw new CloudException("The response from long running operation does not have a valid status code.");
                }
            }
            else
            {
                throw new CloudException("The response from long running operation does not have a valid status code.");
            }

            return(pollingState);
        }