github.com/rothwerx/packer@v0.9.0/builder/digitalocean/wait.go (about) 1 package digitalocean 2 3 import ( 4 "fmt" 5 "log" 6 "time" 7 8 "github.com/digitalocean/godo" 9 ) 10 11 // waitForDropletUnlocked waits for the Droplet to be unlocked to 12 // avoid "pending" errors when making state changes. 13 func waitForDropletUnlocked( 14 client *godo.Client, dropletId int, timeout time.Duration) error { 15 done := make(chan struct{}) 16 defer close(done) 17 18 result := make(chan error, 1) 19 go func() { 20 attempts := 0 21 for { 22 attempts += 1 23 24 log.Printf("[DEBUG] Checking droplet lock state... (attempt: %d)", attempts) 25 droplet, _, err := client.Droplets.Get(dropletId) 26 if err != nil { 27 result <- err 28 return 29 } 30 31 if !droplet.Locked { 32 result <- nil 33 return 34 } 35 36 // Wait 3 seconds in between 37 time.Sleep(3 * time.Second) 38 39 // Verify we shouldn't exit 40 select { 41 case <-done: 42 // We finished, so just exit the goroutine 43 return 44 default: 45 // Keep going 46 } 47 } 48 }() 49 50 log.Printf("[DEBUG] Waiting for up to %d seconds for droplet to unlock", timeout/time.Second) 51 select { 52 case err := <-result: 53 return err 54 case <-time.After(timeout): 55 return fmt.Errorf( 56 "Timeout while waiting to for droplet to unlock") 57 } 58 } 59 60 // waitForState simply blocks until the droplet is in 61 // a state we expect, while eventually timing out. 62 func waitForDropletState( 63 desiredState string, dropletId int, 64 client *godo.Client, timeout time.Duration) error { 65 done := make(chan struct{}) 66 defer close(done) 67 68 result := make(chan error, 1) 69 go func() { 70 attempts := 0 71 for { 72 attempts += 1 73 74 log.Printf("Checking droplet status... (attempt: %d)", attempts) 75 droplet, _, err := client.Droplets.Get(dropletId) 76 if err != nil { 77 result <- err 78 return 79 } 80 81 if droplet.Status == desiredState { 82 result <- nil 83 return 84 } 85 86 // Wait 3 seconds in between 87 time.Sleep(3 * time.Second) 88 89 // Verify we shouldn't exit 90 select { 91 case <-done: 92 // We finished, so just exit the goroutine 93 return 94 default: 95 // Keep going 96 } 97 } 98 }() 99 100 log.Printf("Waiting for up to %d seconds for droplet to become %s", timeout/time.Second, desiredState) 101 select { 102 case err := <-result: 103 return err 104 case <-time.After(timeout): 105 err := fmt.Errorf("Timeout while waiting to for droplet to become '%s'", desiredState) 106 return err 107 } 108 }