// WithOdataErrorUnlessStatusCode returns a RespondDecorator that emits an // azure.RequestError by reading the response body unless the response HTTP status code // is among the set passed. // // If there is a chance service may return responses other than the Azure error // format and the response cannot be parsed into an error, a decoding error will // be returned containing the response body. In any case, the Responder will // return an error if the status code is not satisfied. // // If this Responder returns an error, the response body will be replaced with // an in-memory reader, which needs no further closing. // // NOTE(axw) this function is based on go-autorest/autorest/azure.WithErrorUnlessStatusCode. // The only difference is that we extract "odata.error", instead of "error", // from the response body; and we do not extract the message, which is in a // different format for odata.error, and irrelevant to us. func WithOdataErrorUnlessStatusCode(codes ...int) autorest.RespondDecorator { return func(r autorest.Responder) autorest.Responder { return autorest.ResponderFunc(func(resp *http.Response) error { err := r.Respond(resp) if err == nil && !autorest.ResponseHasStatusCode(resp, codes...) { var oe odataRequestError defer resp.Body.Close() // Copy and replace the Body in case it does not contain an error object. // This will leave the Body available to the caller. b, decodeErr := autorest.CopyAndDecode(autorest.EncodedAsJSON, resp.Body, &oe) resp.Body = ioutil.NopCloser(&b) if decodeErr != nil { return fmt.Errorf("ad: error response cannot be parsed: %q error: %v", b.String(), decodeErr) } else if oe.ServiceError == nil { oe.ServiceError = &odataServiceError{Code: "Unknown"} } e := azure.RequestError{ ServiceError: &azure.ServiceError{Code: oe.ServiceError.Code}, RequestID: azure.ExtractRequestID(resp), } if e.StatusCode == nil { e.StatusCode = resp.StatusCode } err = &e } return err }) } }
func (mi *mockInspector) ByInspecting() autorest.RespondDecorator { return func(r autorest.Responder) autorest.Responder { return autorest.ResponderFunc(func(resp *http.Response) error { mi.wasInvoked = true return r.Respond(resp) }) } }
func byInspecting() autorest.RespondDecorator { return func(r autorest.Responder) autorest.Responder { return autorest.ResponderFunc(func(resp *http.Response) error { fmt.Printf("Inspecting Response: %s for %s %s\n", resp.Status, resp.Request.Method, resp.Request.URL) return r.Respond(resp) }) } }
// ByUnmarshallingTime returns a RespondDecorator that decodes the http.Response Body into a Time // pointed to by t. func ByUnmarshallingTime(t *Time) autorest.RespondDecorator { return func(r autorest.Responder) autorest.Responder { return autorest.ResponderFunc(func(resp *http.Response) error { err := r.Respond(resp) if err == nil { *t, err = readTime(resp.Body) } return err }) } }
// asyncCreationRespondDecorator returns an autorest.RespondDecorator // that replaces non-failure provisioning states with "Succeeded", to // prevent the autorest code from blocking until the resource is completely // provisioned. func asyncCreationRespondDecorator(original autorest.RespondDecorator) autorest.RespondDecorator { return func(r autorest.Responder) autorest.Responder { return autorest.ResponderFunc(func(resp *http.Response) error { if resp.Body != nil { if err := overrideProvisioningState(resp); err != nil { return err } } return original(r).Respond(resp) }) } }
func byInspecting() autorest.RespondDecorator { return func(r autorest.Responder) autorest.Responder { return autorest.ResponderFunc(func(resp *http.Response) error { log.Debug("Azure response", logutil.Fields{ "status": resp.Status, "method": resp.Request.Method, "request": resp.Request.URL.String(), "x-ms-request-id": azure.ExtractRequestID(resp), }) return r.Respond(resp) }) } }
func byUnmarshallingTime(t *Time, format string) autorest.RespondDecorator { return func(r autorest.Responder) autorest.Responder { return autorest.ResponderFunc(func(resp *http.Response) error { err := r.Respond(resp) if err == nil { var b []byte b, err = ioutil.ReadAll(resp.Body) if err == nil { *t, err = parseTime(string(b), format) } } return err }) } }
// HACK(chrboum): This method is a hack. It was written to work around this issue // (https://github.com/Azure/azure-sdk-for-go/issues/307) and to an extent this // issue (https://github.com/Azure/azure-rest-api-specs/issues/188). // // Capturing a VM is a long running operation that requires polling. There are // couple different forms of polling, and the end result of a poll operation is // discarded by the SDK. It is expected that any discarded data can be re-fetched, // so discarding it has minimal impact. Unfortunately, there is no way to re-fetch // the template returned by a capture call that I am aware of. // // If the second issue were fixed the VM ID would be included when GET'ing a VM. The // VM ID could be used to locate the captured VHD, and captured template. // Unfortunately, the VM ID is not included so this method cannot be used either. // // This code captures the template and saves it to the client (the AzureClient type). // It expects that the capture API is called only once, or rather you only care that the // last call's value is important because subsequent requests are not persisted. There // is no care given to multiple threads writing this value because for our use case // it does not matter. func templateCapture(client *AzureClient) autorest.RespondDecorator { return func(r autorest.Responder) autorest.Responder { return autorest.ResponderFunc(func(resp *http.Response) error { body, bodyString := handleBody(resp.Body, math.MaxInt64) resp.Body = body captureTemplate := getCaptureResponse(bodyString) if captureTemplate != nil { client.Template = captureTemplate } return r.Respond(resp) }) } }
// RespondDecorator returns an autorest.RespondDecorator that // logs responses at trace level. func RespondDecorator(logger loggo.Logger) autorest.RespondDecorator { return func(r autorest.Responder) autorest.Responder { return autorest.ResponderFunc(func(resp *http.Response) error { if logger.IsTraceEnabled() { dump, err := httputil.DumpResponse(resp, true) if err != nil { logger.Tracef("failed to dump response: %v", err) logger.Tracef("%+v", resp) } else { logger.Tracef("%s", dump) } } return r.Respond(resp) }) } }
func byInspecting(maxlen int64) autorest.RespondDecorator { return func(r autorest.Responder) autorest.Responder { return autorest.ResponderFunc(func(resp *http.Response) error { body, bodyString := handleBody(resp.Body, maxlen) resp.Body = body log.Print("Azure response", logutil.Fields{ "status": resp.Status, "method": resp.Request.Method, "request": resp.Request.URL.String(), "x-ms-request-id": azure.ExtractRequestID(resp), "body": bodyString, }) return r.Respond(resp) }) } }
// WithErrorUnlessStatusCode returns a RespondDecorator that emits an // azure.RequestError by reading the response body unless the response HTTP status code // is among the set passed. // // If there is a chance service may return responses other than the Azure error // format and the response cannot be parsed into an error, a decoding error will // be returned containing the response body. In any case, the Responder will // return an error if the status code is not satisfied. // // If this Responder returns an error, the response body will be replaced with // an in-memory reader, which needs no further closing. func WithErrorUnlessStatusCode(codes ...int) autorest.RespondDecorator { return func(r autorest.Responder) autorest.Responder { return autorest.ResponderFunc(func(resp *http.Response) error { err := r.Respond(resp) if err == nil && !autorest.ResponseHasStatusCode(resp, codes...) { var e RequestError defer resp.Body.Close() b, decodeErr := autorest.CopyAndDecode(autorest.EncodedAsJSON, resp.Body, &e) resp.Body = ioutil.NopCloser(&b) // replace body with in-memory reader if decodeErr != nil || e.ServiceError == nil { return fmt.Errorf("autorest/azure: error response cannot be parsed: %q error: %v", b.String(), err) } e.RequestID = ExtractRequestID(resp) e.StatusCode = resp.StatusCode err = &e } return err }) } }