github.com/amanya/packer@v0.12.1-0.20161117214323-902ac5ab2eb6/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  // waitForDropletState 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  }
   109  
   110  // waitForActionState simply blocks until the droplet action is in
   111  // a state we expect, while eventually timing out.
   112  func waitForActionState(
   113  	desiredState string, dropletId, actionId int,
   114  	client *godo.Client, timeout time.Duration) error {
   115  	done := make(chan struct{})
   116  	defer close(done)
   117  
   118  	result := make(chan error, 1)
   119  	go func() {
   120  		attempts := 0
   121  		for {
   122  			attempts += 1
   123  
   124  			log.Printf("Checking action status... (attempt: %d)", attempts)
   125  			action, _, err := client.DropletActions.Get(dropletId, actionId)
   126  			if err != nil {
   127  				result <- err
   128  				return
   129  			}
   130  
   131  			if action.Status == desiredState {
   132  				result <- nil
   133  				return
   134  			}
   135  
   136  			// Wait 3 seconds in between
   137  			time.Sleep(3 * time.Second)
   138  
   139  			// Verify we shouldn't exit
   140  			select {
   141  			case <-done:
   142  				// We finished, so just exit the goroutine
   143  				return
   144  			default:
   145  				// Keep going
   146  			}
   147  		}
   148  	}()
   149  
   150  	log.Printf("Waiting for up to %d seconds for action to become %s", timeout/time.Second, desiredState)
   151  	select {
   152  	case err := <-result:
   153  		return err
   154  	case <-time.After(timeout):
   155  		err := fmt.Errorf("Timeout while waiting to for action to become '%s'", desiredState)
   156  		return err
   157  	}
   158  }