github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/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  }