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

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strings"
     7  	"time"
     8  
     9  	"github.com/hashicorp/terraform/helper/schema"
    10  
    11  	"github.com/aws/aws-sdk-go/aws"
    12  	"github.com/aws/aws-sdk-go/aws/awserr"
    13  	"github.com/aws/aws-sdk-go/service/route53"
    14  )
    15  
    16  func resourceAwsRoute53HealthCheck() *schema.Resource {
    17  	return &schema.Resource{
    18  		Create: resourceAwsRoute53HealthCheckCreate,
    19  		Read:   resourceAwsRoute53HealthCheckRead,
    20  		Update: resourceAwsRoute53HealthCheckUpdate,
    21  		Delete: resourceAwsRoute53HealthCheckDelete,
    22  		Importer: &schema.ResourceImporter{
    23  			State: schema.ImportStatePassthrough,
    24  		},
    25  
    26  		Schema: map[string]*schema.Schema{
    27  			"type": &schema.Schema{
    28  				Type:     schema.TypeString,
    29  				Required: true,
    30  				ForceNew: true,
    31  				StateFunc: func(val interface{}) string {
    32  					return strings.ToUpper(val.(string))
    33  				},
    34  			},
    35  			"failure_threshold": &schema.Schema{
    36  				Type:     schema.TypeInt,
    37  				Optional: true,
    38  			},
    39  			"request_interval": &schema.Schema{
    40  				Type:     schema.TypeInt,
    41  				Optional: true,
    42  				ForceNew: true, // todo this should be updateable but the awslabs route53 service doesnt have the ability
    43  			},
    44  			"ip_address": &schema.Schema{
    45  				Type:     schema.TypeString,
    46  				Optional: true,
    47  				ForceNew: true,
    48  			},
    49  			"fqdn": &schema.Schema{
    50  				Type:     schema.TypeString,
    51  				Optional: true,
    52  			},
    53  			"port": &schema.Schema{
    54  				Type:     schema.TypeInt,
    55  				Optional: true,
    56  			},
    57  
    58  			"invert_healthcheck": &schema.Schema{
    59  				Type:     schema.TypeBool,
    60  				Optional: true,
    61  			},
    62  
    63  			"resource_path": &schema.Schema{
    64  				Type:     schema.TypeString,
    65  				Optional: true,
    66  			},
    67  
    68  			"search_string": &schema.Schema{
    69  				Type:     schema.TypeString,
    70  				Optional: true,
    71  			},
    72  
    73  			"measure_latency": &schema.Schema{
    74  				Type:     schema.TypeBool,
    75  				Optional: true,
    76  				Default:  false,
    77  				ForceNew: true,
    78  			},
    79  
    80  			"child_healthchecks": &schema.Schema{
    81  				Type:     schema.TypeSet,
    82  				Elem:     &schema.Schema{Type: schema.TypeString},
    83  				Optional: true,
    84  				Set:      schema.HashString,
    85  			},
    86  			"child_health_threshold": &schema.Schema{
    87  				Type:     schema.TypeInt,
    88  				Optional: true,
    89  				ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
    90  					value := v.(int)
    91  					if value > 256 {
    92  						es = append(es, fmt.Errorf(
    93  							"Child HealthThreshold cannot be more than 256"))
    94  					}
    95  					return
    96  				},
    97  			},
    98  
    99  			"cloudwatch_alarm_name": &schema.Schema{
   100  				Type:     schema.TypeString,
   101  				Optional: true,
   102  			},
   103  
   104  			"cloudwatch_alarm_region": &schema.Schema{
   105  				Type:     schema.TypeString,
   106  				Optional: true,
   107  			},
   108  
   109  			"insufficient_data_health_status": &schema.Schema{
   110  				Type:     schema.TypeString,
   111  				Optional: true,
   112  			},
   113  
   114  			"tags": tagsSchema(),
   115  		},
   116  	}
   117  }
   118  
   119  func resourceAwsRoute53HealthCheckUpdate(d *schema.ResourceData, meta interface{}) error {
   120  	conn := meta.(*AWSClient).r53conn
   121  
   122  	updateHealthCheck := &route53.UpdateHealthCheckInput{
   123  		HealthCheckId: aws.String(d.Id()),
   124  	}
   125  
   126  	if d.HasChange("failure_threshold") {
   127  		updateHealthCheck.FailureThreshold = aws.Int64(int64(d.Get("failure_threshold").(int)))
   128  	}
   129  
   130  	if d.HasChange("fqdn") {
   131  		updateHealthCheck.FullyQualifiedDomainName = aws.String(d.Get("fqdn").(string))
   132  	}
   133  
   134  	if d.HasChange("port") {
   135  		updateHealthCheck.Port = aws.Int64(int64(d.Get("port").(int)))
   136  	}
   137  
   138  	if d.HasChange("resource_path") {
   139  		updateHealthCheck.ResourcePath = aws.String(d.Get("resource_path").(string))
   140  	}
   141  
   142  	if d.HasChange("invert_healthcheck") {
   143  		updateHealthCheck.Inverted = aws.Bool(d.Get("invert_healthcheck").(bool))
   144  	}
   145  
   146  	if d.HasChange("child_healthchecks") {
   147  		updateHealthCheck.ChildHealthChecks = expandStringList(d.Get("child_healthchecks").(*schema.Set).List())
   148  
   149  	}
   150  	if d.HasChange("child_health_threshold") {
   151  		updateHealthCheck.HealthThreshold = aws.Int64(int64(d.Get("child_health_threshold").(int)))
   152  	}
   153  
   154  	if d.HasChange("search_string") {
   155  		updateHealthCheck.SearchString = aws.String(d.Get("search_string").(string))
   156  	}
   157  
   158  	if d.HasChange("cloudwatch_alarm_name") || d.HasChange("cloudwatch_alarm_region") {
   159  		cloudwatchAlarm := &route53.AlarmIdentifier{
   160  			Name:   aws.String(d.Get("cloudwatch_alarm_name").(string)),
   161  			Region: aws.String(d.Get("cloudwatch_alarm_region").(string)),
   162  		}
   163  
   164  		updateHealthCheck.AlarmIdentifier = cloudwatchAlarm
   165  	}
   166  
   167  	if d.HasChange("insufficient_data_health_status") {
   168  		updateHealthCheck.InsufficientDataHealthStatus = aws.String(d.Get("insufficient_data_health_status").(string))
   169  	}
   170  
   171  	_, err := conn.UpdateHealthCheck(updateHealthCheck)
   172  	if err != nil {
   173  		return err
   174  	}
   175  
   176  	if err := setTagsR53(conn, d, "healthcheck"); err != nil {
   177  		return err
   178  	}
   179  
   180  	return resourceAwsRoute53HealthCheckRead(d, meta)
   181  }
   182  
   183  func resourceAwsRoute53HealthCheckCreate(d *schema.ResourceData, meta interface{}) error {
   184  	conn := meta.(*AWSClient).r53conn
   185  
   186  	healthConfig := &route53.HealthCheckConfig{
   187  		Type: aws.String(d.Get("type").(string)),
   188  	}
   189  
   190  	if v, ok := d.GetOk("request_interval"); ok {
   191  		healthConfig.RequestInterval = aws.Int64(int64(v.(int)))
   192  	}
   193  
   194  	if v, ok := d.GetOk("failure_threshold"); ok {
   195  		healthConfig.FailureThreshold = aws.Int64(int64(v.(int)))
   196  	}
   197  
   198  	if v, ok := d.GetOk("fqdn"); ok {
   199  		healthConfig.FullyQualifiedDomainName = aws.String(v.(string))
   200  	}
   201  
   202  	if v, ok := d.GetOk("search_string"); ok {
   203  		healthConfig.SearchString = aws.String(v.(string))
   204  	}
   205  
   206  	if v, ok := d.GetOk("ip_address"); ok {
   207  		healthConfig.IPAddress = aws.String(v.(string))
   208  	}
   209  
   210  	if v, ok := d.GetOk("port"); ok {
   211  		healthConfig.Port = aws.Int64(int64(v.(int)))
   212  	}
   213  
   214  	if v, ok := d.GetOk("resource_path"); ok {
   215  		healthConfig.ResourcePath = aws.String(v.(string))
   216  	}
   217  
   218  	if *healthConfig.Type != route53.HealthCheckTypeCalculated && *healthConfig.Type != route53.HealthCheckTypeCloudwatchMetric {
   219  		if v, ok := d.GetOk("measure_latency"); ok {
   220  			healthConfig.MeasureLatency = aws.Bool(v.(bool))
   221  		}
   222  	}
   223  
   224  	if v, ok := d.GetOk("invert_healthcheck"); ok {
   225  		healthConfig.Inverted = aws.Bool(v.(bool))
   226  	}
   227  
   228  	if *healthConfig.Type == route53.HealthCheckTypeCalculated {
   229  		if v, ok := d.GetOk("child_healthchecks"); ok {
   230  			healthConfig.ChildHealthChecks = expandStringList(v.(*schema.Set).List())
   231  		}
   232  
   233  		if v, ok := d.GetOk("child_health_threshold"); ok {
   234  			healthConfig.HealthThreshold = aws.Int64(int64(v.(int)))
   235  		}
   236  	}
   237  
   238  	if *healthConfig.Type == route53.HealthCheckTypeCloudwatchMetric {
   239  		cloudwatchAlarmIdentifier := &route53.AlarmIdentifier{}
   240  
   241  		if v, ok := d.GetOk("cloudwatch_alarm_name"); ok {
   242  			cloudwatchAlarmIdentifier.Name = aws.String(v.(string))
   243  		}
   244  
   245  		if v, ok := d.GetOk("cloudwatch_alarm_region"); ok {
   246  			cloudwatchAlarmIdentifier.Region = aws.String(v.(string))
   247  		}
   248  
   249  		healthConfig.AlarmIdentifier = cloudwatchAlarmIdentifier
   250  
   251  		if v, ok := d.GetOk("insufficient_data_health_status"); ok {
   252  			healthConfig.InsufficientDataHealthStatus = aws.String(v.(string))
   253  		}
   254  	}
   255  
   256  	input := &route53.CreateHealthCheckInput{
   257  		CallerReference:   aws.String(time.Now().Format(time.RFC3339Nano)),
   258  		HealthCheckConfig: healthConfig,
   259  	}
   260  
   261  	resp, err := conn.CreateHealthCheck(input)
   262  
   263  	if err != nil {
   264  		return err
   265  	}
   266  
   267  	d.SetId(*resp.HealthCheck.Id)
   268  
   269  	if err := setTagsR53(conn, d, "healthcheck"); err != nil {
   270  		return err
   271  	}
   272  
   273  	return resourceAwsRoute53HealthCheckRead(d, meta)
   274  }
   275  
   276  func resourceAwsRoute53HealthCheckRead(d *schema.ResourceData, meta interface{}) error {
   277  	conn := meta.(*AWSClient).r53conn
   278  
   279  	read, err := conn.GetHealthCheck(&route53.GetHealthCheckInput{HealthCheckId: aws.String(d.Id())})
   280  	if err != nil {
   281  		if r53err, ok := err.(awserr.Error); ok && r53err.Code() == "NoSuchHealthCheck" {
   282  			d.SetId("")
   283  			return nil
   284  
   285  		}
   286  		return err
   287  	}
   288  
   289  	if read == nil {
   290  		return nil
   291  	}
   292  
   293  	updated := read.HealthCheck.HealthCheckConfig
   294  	d.Set("type", updated.Type)
   295  	d.Set("failure_threshold", updated.FailureThreshold)
   296  	d.Set("request_interval", updated.RequestInterval)
   297  	d.Set("fqdn", updated.FullyQualifiedDomainName)
   298  	d.Set("search_string", updated.SearchString)
   299  	d.Set("ip_address", updated.IPAddress)
   300  	d.Set("port", updated.Port)
   301  	d.Set("resource_path", updated.ResourcePath)
   302  	d.Set("measure_latency", updated.MeasureLatency)
   303  	d.Set("invert_healthcheck", updated.Inverted)
   304  	d.Set("child_healthchecks", updated.ChildHealthChecks)
   305  	d.Set("child_health_threshold", updated.HealthThreshold)
   306  	d.Set("insufficient_data_health_status", updated.InsufficientDataHealthStatus)
   307  
   308  	if updated.AlarmIdentifier != nil {
   309  		d.Set("cloudwatch_alarm_name", updated.AlarmIdentifier.Name)
   310  		d.Set("cloudwatch_alarm_region", updated.AlarmIdentifier.Region)
   311  	}
   312  
   313  	// read the tags
   314  	req := &route53.ListTagsForResourceInput{
   315  		ResourceId:   aws.String(d.Id()),
   316  		ResourceType: aws.String("healthcheck"),
   317  	}
   318  
   319  	resp, err := conn.ListTagsForResource(req)
   320  	if err != nil {
   321  		return err
   322  	}
   323  
   324  	var tags []*route53.Tag
   325  	if resp.ResourceTagSet != nil {
   326  		tags = resp.ResourceTagSet.Tags
   327  	}
   328  
   329  	if err := d.Set("tags", tagsToMapR53(tags)); err != nil {
   330  		return err
   331  	}
   332  
   333  	return nil
   334  }
   335  
   336  func resourceAwsRoute53HealthCheckDelete(d *schema.ResourceData, meta interface{}) error {
   337  	conn := meta.(*AWSClient).r53conn
   338  
   339  	log.Printf("[DEBUG] Deleteing Route53 health check: %s", d.Id())
   340  	_, err := conn.DeleteHealthCheck(&route53.DeleteHealthCheckInput{HealthCheckId: aws.String(d.Id())})
   341  	if err != nil {
   342  		return err
   343  	}
   344  
   345  	return nil
   346  }
   347  
   348  func createChildHealthCheckList(s *schema.Set) (nl []*string) {
   349  	l := s.List()
   350  	for _, n := range l {
   351  		nl = append(nl, aws.String(n.(string)))
   352  	}
   353  
   354  	return nl
   355  }