github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/provider/azure/async.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package azure 5 6 import ( 7 "bytes" 8 "encoding/json" 9 "io/ioutil" 10 "net/http" 11 12 "github.com/Azure/go-autorest/autorest" 13 ) 14 15 // asyncCreationRespondDecorator returns an autorest.RespondDecorator 16 // that replaces non-failure provisioning states with "Succeeded", to 17 // prevent the autorest code from blocking until the resource is completely 18 // provisioned. 19 func asyncCreationRespondDecorator(original autorest.RespondDecorator) autorest.RespondDecorator { 20 return func(r autorest.Responder) autorest.Responder { 21 return autorest.ResponderFunc(func(resp *http.Response) error { 22 if resp.Body != nil { 23 if err := overrideProvisioningState(resp); err != nil { 24 return err 25 } 26 } 27 return original(r).Respond(resp) 28 }) 29 } 30 } 31 32 func overrideProvisioningState(resp *http.Response) error { 33 var buf bytes.Buffer 34 if _, err := buf.ReadFrom(resp.Body); err != nil { 35 return err 36 } 37 if err := resp.Body.Close(); err != nil { 38 return err 39 } 40 resp.Body = ioutil.NopCloser(&buf) 41 42 body := make(map[string]interface{}) 43 if err := json.Unmarshal(buf.Bytes(), &body); err != nil { 44 // Don't treat failure to decode the body as an error, 45 // or we may get in the way of response handling. 46 return nil 47 } 48 properties, ok := body["properties"].(map[string]interface{}) 49 if !ok { 50 // No properties, nothing to do. 51 return nil 52 } 53 provisioningState, ok := properties["provisioningState"] 54 if !ok { 55 // No provisioningState, nothing to do. 56 return nil 57 } 58 59 switch provisioningState { 60 case "Canceled", "Failed", "Succeeded": 61 // In any of these cases, pass on the body untouched. 62 default: 63 properties["provisioningState"] = "Succeeded" 64 buf.Reset() 65 if err := json.NewEncoder(&buf).Encode(body); err != nil { 66 return err 67 } 68 } 69 return nil 70 }