github.com/angdraug/packer@v1.3.2/builder/digitalocean/wait.go (about)

     1  package digitalocean
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"log"
     7  	"time"
     8  
     9  	"github.com/digitalocean/godo"
    10  )
    11  
    12  // waitForDropletUnlocked waits for the Droplet to be unlocked to
    13  // avoid "pending" errors when making state changes.
    14  func waitForDropletUnlocked(
    15  	client *godo.Client, dropletId int, timeout time.Duration) error {
    16  	done := make(chan struct{})
    17  	defer close(done)
    18  
    19  	result := make(chan error, 1)
    20  	go func() {
    21  		attempts := 0
    22  		for {
    23  			attempts += 1
    24  
    25  			log.Printf("[DEBUG] Checking droplet lock state... (attempt: %d)", attempts)
    26  			droplet, _, err := client.Droplets.Get(context.TODO(), dropletId)
    27  			if err != nil {
    28  				result <- err
    29  				return
    30  			}
    31  
    32  			if !droplet.Locked {
    33  				result <- nil
    34  				return
    35  			}
    36  
    37  			// Wait 3 seconds in between
    38  			time.Sleep(3 * time.Second)
    39  
    40  			// Verify we shouldn't exit
    41  			select {
    42  			case <-done:
    43  				// We finished, so just exit the goroutine
    44  				return
    45  			default:
    46  				// Keep going
    47  			}
    48  		}
    49  	}()
    50  
    51  	log.Printf("[DEBUG] Waiting for up to %d seconds for droplet to unlock", timeout/time.Second)
    52  	select {
    53  	case err := <-result:
    54  		return err
    55  	case <-time.After(timeout):
    56  		return fmt.Errorf(
    57  			"Timeout while waiting to for droplet to unlock")
    58  	}
    59  }
    60  
    61  // waitForDropletState simply blocks until the droplet is in
    62  // a state we expect, while eventually timing out.
    63  func waitForDropletState(
    64  	desiredState string, dropletId int,
    65  	client *godo.Client, timeout time.Duration) error {
    66  	done := make(chan struct{})
    67  	defer close(done)
    68  
    69  	result := make(chan error, 1)
    70  	go func() {
    71  		attempts := 0
    72  		for {
    73  			attempts += 1
    74  
    75  			log.Printf("Checking droplet status... (attempt: %d)", attempts)
    76  			droplet, _, err := client.Droplets.Get(context.TODO(), dropletId)
    77  			if err != nil {
    78  				result <- err
    79  				return
    80  			}
    81  
    82  			if droplet.Status == desiredState {
    83  				result <- nil
    84  				return
    85  			}
    86  
    87  			// Wait 3 seconds in between
    88  			time.Sleep(3 * time.Second)
    89  
    90  			// Verify we shouldn't exit
    91  			select {
    92  			case <-done:
    93  				// We finished, so just exit the goroutine
    94  				return
    95  			default:
    96  				// Keep going
    97  			}
    98  		}
    99  	}()
   100  
   101  	log.Printf("Waiting for up to %d seconds for droplet to become %s", timeout/time.Second, desiredState)
   102  	select {
   103  	case err := <-result:
   104  		return err
   105  	case <-time.After(timeout):
   106  		err := fmt.Errorf("Timeout while waiting to for droplet to become '%s'", desiredState)
   107  		return err
   108  	}
   109  }
   110  
   111  // waitForActionState simply blocks until the droplet action is in
   112  // a state we expect, while eventually timing out.
   113  func waitForActionState(
   114  	desiredState string, dropletId, actionId int,
   115  	client *godo.Client, timeout time.Duration) error {
   116  	done := make(chan struct{})
   117  	defer close(done)
   118  
   119  	result := make(chan error, 1)
   120  	go func() {
   121  		attempts := 0
   122  		for {
   123  			attempts += 1
   124  
   125  			log.Printf("Checking action status... (attempt: %d)", attempts)
   126  			action, _, err := client.DropletActions.Get(context.TODO(), dropletId, actionId)
   127  			if err != nil {
   128  				result <- err
   129  				return
   130  			}
   131  
   132  			if action.Status == desiredState {
   133  				result <- nil
   134  				return
   135  			}
   136  
   137  			// Wait 3 seconds in between
   138  			time.Sleep(3 * time.Second)
   139  
   140  			// Verify we shouldn't exit
   141  			select {
   142  			case <-done:
   143  				// We finished, so just exit the goroutine
   144  				return
   145  			default:
   146  				// Keep going
   147  			}
   148  		}
   149  	}()
   150  
   151  	log.Printf("Waiting for up to %d seconds for action to become %s", timeout/time.Second, desiredState)
   152  	select {
   153  	case err := <-result:
   154  		return err
   155  	case <-time.After(timeout):
   156  		err := fmt.Errorf("Timeout while waiting to for action to become '%s'", desiredState)
   157  		return err
   158  	}
   159  }
   160  
   161  // waitForImageState simply blocks until the image action is in
   162  // a state we expect, while eventually timing out.
   163  func waitForImageState(
   164  	desiredState string, imageId, actionId int,
   165  	client *godo.Client, timeout time.Duration) error {
   166  	done := make(chan struct{})
   167  	defer close(done)
   168  
   169  	result := make(chan error, 1)
   170  	go func() {
   171  		attempts := 0
   172  		for {
   173  			attempts += 1
   174  
   175  			log.Printf("Checking action status... (attempt: %d)", attempts)
   176  			action, _, err := client.ImageActions.Get(context.TODO(), imageId, actionId)
   177  			if err != nil {
   178  				result <- err
   179  				return
   180  			}
   181  
   182  			if action.Status == desiredState {
   183  				result <- nil
   184  				return
   185  			}
   186  
   187  			// Wait 3 seconds in between
   188  			time.Sleep(3 * time.Second)
   189  
   190  			// Verify we shouldn't exit
   191  			select {
   192  			case <-done:
   193  				// We finished, so just exit the goroutine
   194  				return
   195  			default:
   196  				// Keep going
   197  			}
   198  		}
   199  	}()
   200  
   201  	log.Printf("Waiting for up to %d seconds for image transfer to become %s", timeout/time.Second, desiredState)
   202  	select {
   203  	case err := <-result:
   204  		return err
   205  	case <-time.After(timeout):
   206  		err := fmt.Errorf("Timeout while waiting to for image transfer to become '%s'", desiredState)
   207  		return err
   208  	}
   209  }