terraform/builtin/providers/aws/resource_aws_route53_health...

380 lines
9.7 KiB
Go

package aws
import (
"fmt"
"log"
"strings"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/route53"
)
func resourceAwsRoute53HealthCheck() *schema.Resource {
return &schema.Resource{
Create: resourceAwsRoute53HealthCheckCreate,
Read: resourceAwsRoute53HealthCheckRead,
Update: resourceAwsRoute53HealthCheckUpdate,
Delete: resourceAwsRoute53HealthCheckDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"type": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
StateFunc: func(val interface{}) string {
return strings.ToUpper(val.(string))
},
},
"failure_threshold": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
},
"request_interval": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
ForceNew: true, // todo this should be updateable but the awslabs route53 service doesnt have the ability
},
"ip_address": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"fqdn": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"port": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
},
"invert_healthcheck": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
},
"resource_path": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"search_string": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"measure_latency": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Default: false,
ForceNew: true,
},
"child_healthchecks": &schema.Schema{
Type: schema.TypeSet,
Elem: &schema.Schema{Type: schema.TypeString},
Optional: true,
Set: schema.HashString,
},
"child_health_threshold": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
value := v.(int)
if value > 256 {
es = append(es, fmt.Errorf(
"Child HealthThreshold cannot be more than 256"))
}
return
},
},
"cloudwatch_alarm_name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"cloudwatch_alarm_region": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"insufficient_data_health_status": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"reference_name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"enable_sni": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"tags": tagsSchema(),
},
}
}
func resourceAwsRoute53HealthCheckUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).r53conn
updateHealthCheck := &route53.UpdateHealthCheckInput{
HealthCheckId: aws.String(d.Id()),
}
if d.HasChange("failure_threshold") {
updateHealthCheck.FailureThreshold = aws.Int64(int64(d.Get("failure_threshold").(int)))
}
if d.HasChange("fqdn") {
updateHealthCheck.FullyQualifiedDomainName = aws.String(d.Get("fqdn").(string))
}
if d.HasChange("port") {
updateHealthCheck.Port = aws.Int64(int64(d.Get("port").(int)))
}
if d.HasChange("resource_path") {
updateHealthCheck.ResourcePath = aws.String(d.Get("resource_path").(string))
}
if d.HasChange("invert_healthcheck") {
updateHealthCheck.Inverted = aws.Bool(d.Get("invert_healthcheck").(bool))
}
if d.HasChange("child_healthchecks") {
updateHealthCheck.ChildHealthChecks = expandStringList(d.Get("child_healthchecks").(*schema.Set).List())
}
if d.HasChange("child_health_threshold") {
updateHealthCheck.HealthThreshold = aws.Int64(int64(d.Get("child_health_threshold").(int)))
}
if d.HasChange("search_string") {
updateHealthCheck.SearchString = aws.String(d.Get("search_string").(string))
}
if d.HasChange("cloudwatch_alarm_name") || d.HasChange("cloudwatch_alarm_region") {
cloudwatchAlarm := &route53.AlarmIdentifier{
Name: aws.String(d.Get("cloudwatch_alarm_name").(string)),
Region: aws.String(d.Get("cloudwatch_alarm_region").(string)),
}
updateHealthCheck.AlarmIdentifier = cloudwatchAlarm
}
if d.HasChange("insufficient_data_health_status") {
updateHealthCheck.InsufficientDataHealthStatus = aws.String(d.Get("insufficient_data_health_status").(string))
}
if d.HasChange("enable_sni") {
updateHealthCheck.EnableSNI = aws.Bool(d.Get("enable_sni").(bool))
}
_, err := conn.UpdateHealthCheck(updateHealthCheck)
if err != nil {
return err
}
if err := setTagsR53(conn, d, "healthcheck"); err != nil {
return err
}
return resourceAwsRoute53HealthCheckRead(d, meta)
}
func resourceAwsRoute53HealthCheckCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).r53conn
healthConfig := &route53.HealthCheckConfig{
Type: aws.String(d.Get("type").(string)),
}
if v, ok := d.GetOk("request_interval"); ok {
healthConfig.RequestInterval = aws.Int64(int64(v.(int)))
}
if v, ok := d.GetOk("failure_threshold"); ok {
healthConfig.FailureThreshold = aws.Int64(int64(v.(int)))
}
if v, ok := d.GetOk("fqdn"); ok {
healthConfig.FullyQualifiedDomainName = aws.String(v.(string))
}
if v, ok := d.GetOk("search_string"); ok {
healthConfig.SearchString = aws.String(v.(string))
}
if v, ok := d.GetOk("ip_address"); ok {
healthConfig.IPAddress = aws.String(v.(string))
}
if v, ok := d.GetOk("port"); ok {
healthConfig.Port = aws.Int64(int64(v.(int)))
}
if v, ok := d.GetOk("resource_path"); ok {
healthConfig.ResourcePath = aws.String(v.(string))
}
if *healthConfig.Type != route53.HealthCheckTypeCalculated && *healthConfig.Type != route53.HealthCheckTypeCloudwatchMetric {
if v, ok := d.GetOk("measure_latency"); ok {
healthConfig.MeasureLatency = aws.Bool(v.(bool))
}
}
if v, ok := d.GetOk("invert_healthcheck"); ok {
healthConfig.Inverted = aws.Bool(v.(bool))
}
if v, ok := d.GetOk("enable_sni"); ok {
healthConfig.EnableSNI = aws.Bool(v.(bool))
}
if *healthConfig.Type == route53.HealthCheckTypeCalculated {
if v, ok := d.GetOk("child_healthchecks"); ok {
healthConfig.ChildHealthChecks = expandStringList(v.(*schema.Set).List())
}
if v, ok := d.GetOk("child_health_threshold"); ok {
healthConfig.HealthThreshold = aws.Int64(int64(v.(int)))
}
}
if *healthConfig.Type == route53.HealthCheckTypeCloudwatchMetric {
cloudwatchAlarmIdentifier := &route53.AlarmIdentifier{}
if v, ok := d.GetOk("cloudwatch_alarm_name"); ok {
cloudwatchAlarmIdentifier.Name = aws.String(v.(string))
}
if v, ok := d.GetOk("cloudwatch_alarm_region"); ok {
cloudwatchAlarmIdentifier.Region = aws.String(v.(string))
}
healthConfig.AlarmIdentifier = cloudwatchAlarmIdentifier
if v, ok := d.GetOk("insufficient_data_health_status"); ok {
healthConfig.InsufficientDataHealthStatus = aws.String(v.(string))
}
}
callerRef := resource.UniqueId()
if v, ok := d.GetOk("reference_name"); ok {
callerRef = fmt.Sprintf("%s-%s", v.(string), callerRef)
}
input := &route53.CreateHealthCheckInput{
CallerReference: aws.String(callerRef),
HealthCheckConfig: healthConfig,
}
resp, err := conn.CreateHealthCheck(input)
if err != nil {
return err
}
d.SetId(*resp.HealthCheck.Id)
if err := setTagsR53(conn, d, "healthcheck"); err != nil {
return err
}
return resourceAwsRoute53HealthCheckRead(d, meta)
}
func resourceAwsRoute53HealthCheckRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).r53conn
read, err := conn.GetHealthCheck(&route53.GetHealthCheckInput{HealthCheckId: aws.String(d.Id())})
if err != nil {
if r53err, ok := err.(awserr.Error); ok && r53err.Code() == "NoSuchHealthCheck" {
d.SetId("")
return nil
}
return err
}
if read == nil {
return nil
}
updated := read.HealthCheck.HealthCheckConfig
d.Set("type", updated.Type)
d.Set("failure_threshold", updated.FailureThreshold)
d.Set("request_interval", updated.RequestInterval)
d.Set("fqdn", updated.FullyQualifiedDomainName)
d.Set("search_string", updated.SearchString)
d.Set("ip_address", updated.IPAddress)
d.Set("port", updated.Port)
d.Set("resource_path", updated.ResourcePath)
d.Set("measure_latency", updated.MeasureLatency)
d.Set("invert_healthcheck", updated.Inverted)
d.Set("child_healthchecks", updated.ChildHealthChecks)
d.Set("child_health_threshold", updated.HealthThreshold)
d.Set("insufficient_data_health_status", updated.InsufficientDataHealthStatus)
d.Set("enable_sni", updated.EnableSNI)
if updated.AlarmIdentifier != nil {
d.Set("cloudwatch_alarm_name", updated.AlarmIdentifier.Name)
d.Set("cloudwatch_alarm_region", updated.AlarmIdentifier.Region)
}
// read the tags
req := &route53.ListTagsForResourceInput{
ResourceId: aws.String(d.Id()),
ResourceType: aws.String("healthcheck"),
}
resp, err := conn.ListTagsForResource(req)
if err != nil {
return err
}
var tags []*route53.Tag
if resp.ResourceTagSet != nil {
tags = resp.ResourceTagSet.Tags
}
if err := d.Set("tags", tagsToMapR53(tags)); err != nil {
return err
}
return nil
}
func resourceAwsRoute53HealthCheckDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).r53conn
log.Printf("[DEBUG] Deleteing Route53 health check: %s", d.Id())
_, err := conn.DeleteHealthCheck(&route53.DeleteHealthCheckInput{HealthCheckId: aws.String(d.Id())})
if err != nil {
return err
}
return nil
}
func createChildHealthCheckList(s *schema.Set) (nl []*string) {
l := s.List()
for _, n := range l {
nl = append(nl, aws.String(n.(string)))
}
return nl
}