github.com/mohanarpit/terraform@v0.6.16-0.20160909104007-291f29853544/builtin/providers/google/compute_operation.go (about) 1 package google 2 3 import ( 4 "bytes" 5 "fmt" 6 "log" 7 "time" 8 9 "github.com/hashicorp/terraform/helper/resource" 10 "google.golang.org/api/compute/v1" 11 ) 12 13 // OperationWaitType is an enum specifying what type of operation 14 // we're waiting on. 15 type ComputeOperationWaitType byte 16 17 const ( 18 ComputeOperationWaitInvalid ComputeOperationWaitType = iota 19 ComputeOperationWaitGlobal 20 ComputeOperationWaitRegion 21 ComputeOperationWaitZone 22 ) 23 24 type ComputeOperationWaiter struct { 25 Service *compute.Service 26 Op *compute.Operation 27 Project string 28 Region string 29 Type ComputeOperationWaitType 30 Zone string 31 } 32 33 func (w *ComputeOperationWaiter) RefreshFunc() resource.StateRefreshFunc { 34 return func() (interface{}, string, error) { 35 var op *compute.Operation 36 var err error 37 38 switch w.Type { 39 case ComputeOperationWaitGlobal: 40 op, err = w.Service.GlobalOperations.Get( 41 w.Project, w.Op.Name).Do() 42 case ComputeOperationWaitRegion: 43 op, err = w.Service.RegionOperations.Get( 44 w.Project, w.Region, w.Op.Name).Do() 45 case ComputeOperationWaitZone: 46 op, err = w.Service.ZoneOperations.Get( 47 w.Project, w.Zone, w.Op.Name).Do() 48 default: 49 return nil, "bad-type", fmt.Errorf( 50 "Invalid wait type: %#v", w.Type) 51 } 52 53 if err != nil { 54 return nil, "", err 55 } 56 57 log.Printf("[DEBUG] Got %q when asking for operation %q", op.Status, w.Op.Name) 58 59 return op, op.Status, nil 60 } 61 } 62 63 func (w *ComputeOperationWaiter) Conf() *resource.StateChangeConf { 64 return &resource.StateChangeConf{ 65 Pending: []string{"PENDING", "RUNNING"}, 66 Target: []string{"DONE"}, 67 Refresh: w.RefreshFunc(), 68 } 69 } 70 71 // ComputeOperationError wraps compute.OperationError and implements the 72 // error interface so it can be returned. 73 type ComputeOperationError compute.OperationError 74 75 func (e ComputeOperationError) Error() string { 76 var buf bytes.Buffer 77 78 for _, err := range e.Errors { 79 buf.WriteString(err.Message + "\n") 80 } 81 82 return buf.String() 83 } 84 85 func computeOperationWaitGlobal(config *Config, op *compute.Operation, project string, activity string) error { 86 w := &ComputeOperationWaiter{ 87 Service: config.clientCompute, 88 Op: op, 89 Project: project, 90 Type: ComputeOperationWaitGlobal, 91 } 92 93 state := w.Conf() 94 state.Delay = 10 * time.Second 95 state.Timeout = 4 * time.Minute 96 state.MinTimeout = 2 * time.Second 97 opRaw, err := state.WaitForState() 98 if err != nil { 99 return fmt.Errorf("Error waiting for %s: %s", activity, err) 100 } 101 102 op = opRaw.(*compute.Operation) 103 if op.Error != nil { 104 return ComputeOperationError(*op.Error) 105 } 106 107 return nil 108 } 109 110 func computeOperationWaitRegion(config *Config, op *compute.Operation, project string, region, activity string) error { 111 w := &ComputeOperationWaiter{ 112 Service: config.clientCompute, 113 Op: op, 114 Project: project, 115 Type: ComputeOperationWaitRegion, 116 Region: region, 117 } 118 119 state := w.Conf() 120 state.Delay = 10 * time.Second 121 state.Timeout = 4 * time.Minute 122 state.MinTimeout = 2 * time.Second 123 opRaw, err := state.WaitForState() 124 if err != nil { 125 return fmt.Errorf("Error waiting for %s: %s", activity, err) 126 } 127 128 op = opRaw.(*compute.Operation) 129 if op.Error != nil { 130 return ComputeOperationError(*op.Error) 131 } 132 133 return nil 134 } 135 136 func computeOperationWaitZone(config *Config, op *compute.Operation, project string, zone, activity string) error { 137 return computeOperationWaitZoneTime(config, op, project, zone, 4, activity) 138 } 139 140 func computeOperationWaitZoneTime(config *Config, op *compute.Operation, project string, zone string, minutes int, activity string) error { 141 w := &ComputeOperationWaiter{ 142 Service: config.clientCompute, 143 Op: op, 144 Project: project, 145 Zone: zone, 146 Type: ComputeOperationWaitZone, 147 } 148 state := w.Conf() 149 state.Delay = 10 * time.Second 150 state.Timeout = time.Duration(minutes) * time.Minute 151 state.MinTimeout = 2 * time.Second 152 opRaw, err := state.WaitForState() 153 if err != nil { 154 return fmt.Errorf("Error waiting for %s: %s", activity, err) 155 } 156 op = opRaw.(*compute.Operation) 157 if op.Error != nil { 158 // Return the error 159 return ComputeOperationError(*op.Error) 160 } 161 return nil 162 }