github.com/minamijoyo/terraform@v0.7.8-0.20161029001309-18b3736ba44b/builtin/providers/aws/resource_aws_autoscaling_group_waiting.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strings"
     7  	"time"
     8  
     9  	"github.com/hashicorp/terraform/helper/resource"
    10  	"github.com/hashicorp/terraform/helper/schema"
    11  )
    12  
    13  // waitForASGCapacityTimeout gathers the current numbers of healthy instances
    14  // in the ASG and its attached ELBs and yields these numbers to a
    15  // capacitySatifiedFunction. Loops for up to wait_for_capacity_timeout until
    16  // the capacitySatisfiedFunc returns true.
    17  //
    18  // See "Waiting for Capacity" in docs for more discussion of the feature.
    19  func waitForASGCapacity(
    20  	d *schema.ResourceData,
    21  	meta interface{},
    22  	satisfiedFunc capacitySatisfiedFunc) error {
    23  	wait, err := time.ParseDuration(d.Get("wait_for_capacity_timeout").(string))
    24  	if err != nil {
    25  		return err
    26  	}
    27  
    28  	if wait == 0 {
    29  		log.Printf("[DEBUG] Capacity timeout set to 0, skipping capacity waiting.")
    30  		return nil
    31  	}
    32  
    33  	log.Printf("[DEBUG] Waiting on %s for capacity...", d.Id())
    34  
    35  	return resource.Retry(wait, func() *resource.RetryError {
    36  		g, err := getAwsAutoscalingGroup(d.Id(), meta.(*AWSClient).autoscalingconn)
    37  		if err != nil {
    38  			return resource.NonRetryableError(err)
    39  		}
    40  		if g == nil {
    41  			log.Printf("[INFO] Autoscaling Group %q not found", d.Id())
    42  			d.SetId("")
    43  			return nil
    44  		}
    45  		lbis, err := getLBInstanceStates(g, meta)
    46  		if err != nil {
    47  			return resource.NonRetryableError(err)
    48  		}
    49  
    50  		haveASG := 0
    51  		haveELB := 0
    52  
    53  		for _, i := range g.Instances {
    54  			if i.HealthStatus == nil || i.InstanceId == nil || i.LifecycleState == nil {
    55  				continue
    56  			}
    57  
    58  			if !strings.EqualFold(*i.HealthStatus, "Healthy") {
    59  				continue
    60  			}
    61  
    62  			if !strings.EqualFold(*i.LifecycleState, "InService") {
    63  				continue
    64  			}
    65  
    66  			haveASG++
    67  
    68  			inAllLbs := true
    69  			for _, states := range lbis {
    70  				state, ok := states[*i.InstanceId]
    71  				if !ok || !strings.EqualFold(state, "InService") {
    72  					inAllLbs = false
    73  				}
    74  			}
    75  			if inAllLbs {
    76  				haveELB++
    77  			}
    78  		}
    79  
    80  		satisfied, reason := satisfiedFunc(d, haveASG, haveELB)
    81  
    82  		log.Printf("[DEBUG] %q Capacity: %d ASG, %d ELB, satisfied: %t, reason: %q",
    83  			d.Id(), haveASG, haveELB, satisfied, reason)
    84  
    85  		if satisfied {
    86  			return nil
    87  		}
    88  
    89  		return resource.RetryableError(
    90  			fmt.Errorf("%q: Waiting up to %s: %s", d.Id(), wait, reason))
    91  	})
    92  }
    93  
    94  type capacitySatisfiedFunc func(*schema.ResourceData, int, int) (bool, string)
    95  
    96  // capacitySatisfiedCreate treats all targets as minimums
    97  func capacitySatisfiedCreate(d *schema.ResourceData, haveASG, haveELB int) (bool, string) {
    98  	minASG := d.Get("min_size").(int)
    99  	if wantASG := d.Get("desired_capacity").(int); wantASG > 0 {
   100  		minASG = wantASG
   101  	}
   102  	if haveASG < minASG {
   103  		return false, fmt.Sprintf(
   104  			"Need at least %d healthy instances in ASG, have %d", minASG, haveASG)
   105  	}
   106  	minELB := d.Get("min_elb_capacity").(int)
   107  	if wantELB := d.Get("wait_for_elb_capacity").(int); wantELB > 0 {
   108  		minELB = wantELB
   109  	}
   110  	if haveELB < minELB {
   111  		return false, fmt.Sprintf(
   112  			"Need at least %d healthy instances in ELB, have %d", minELB, haveELB)
   113  	}
   114  	return true, ""
   115  }
   116  
   117  // capacitySatisfiedUpdate only cares about specific targets
   118  func capacitySatisfiedUpdate(d *schema.ResourceData, haveASG, haveELB int) (bool, string) {
   119  	if wantASG := d.Get("desired_capacity").(int); wantASG > 0 {
   120  		if haveASG != wantASG {
   121  			return false, fmt.Sprintf(
   122  				"Need exactly %d healthy instances in ASG, have %d", wantASG, haveASG)
   123  		}
   124  	}
   125  	if wantELB := d.Get("wait_for_elb_capacity").(int); wantELB > 0 {
   126  		if haveELB != wantELB {
   127  			return false, fmt.Sprintf(
   128  				"Need exactly %d healthy instances in ELB, have %d", wantELB, haveELB)
   129  		}
   130  	}
   131  	return true, ""
   132  }