github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/builtin/providers/aws/resource_aws_route53_health_check.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strings"
     7  
     8  	"github.com/hashicorp/terraform/helper/resource"
     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  			"reference_name": &schema.Schema{
   114  				Type:     schema.TypeString,
   115  				Optional: true,
   116  				ForceNew: true,
   117  			},
   118  			"enable_sni": &schema.Schema{
   119  				Type:     schema.TypeBool,
   120  				Optional: true,
   121  				Computed: true,
   122  			},
   123  
   124  			"tags": tagsSchema(),
   125  		},
   126  	}
   127  }
   128  
   129  func resourceAwsRoute53HealthCheckUpdate(d *schema.ResourceData, meta interface{}) error {
   130  	conn := meta.(*AWSClient).r53conn
   131  
   132  	updateHealthCheck := &route53.UpdateHealthCheckInput{
   133  		HealthCheckId: aws.String(d.Id()),
   134  	}
   135  
   136  	if d.HasChange("failure_threshold") {
   137  		updateHealthCheck.FailureThreshold = aws.Int64(int64(d.Get("failure_threshold").(int)))
   138  	}
   139  
   140  	if d.HasChange("fqdn") {
   141  		updateHealthCheck.FullyQualifiedDomainName = aws.String(d.Get("fqdn").(string))
   142  	}
   143  
   144  	if d.HasChange("port") {
   145  		updateHealthCheck.Port = aws.Int64(int64(d.Get("port").(int)))
   146  	}
   147  
   148  	if d.HasChange("resource_path") {
   149  		updateHealthCheck.ResourcePath = aws.String(d.Get("resource_path").(string))
   150  	}
   151  
   152  	if d.HasChange("invert_healthcheck") {
   153  		updateHealthCheck.Inverted = aws.Bool(d.Get("invert_healthcheck").(bool))
   154  	}
   155  
   156  	if d.HasChange("child_healthchecks") {
   157  		updateHealthCheck.ChildHealthChecks = expandStringList(d.Get("child_healthchecks").(*schema.Set).List())
   158  
   159  	}
   160  	if d.HasChange("child_health_threshold") {
   161  		updateHealthCheck.HealthThreshold = aws.Int64(int64(d.Get("child_health_threshold").(int)))
   162  	}
   163  
   164  	if d.HasChange("search_string") {
   165  		updateHealthCheck.SearchString = aws.String(d.Get("search_string").(string))
   166  	}
   167  
   168  	if d.HasChange("cloudwatch_alarm_name") || d.HasChange("cloudwatch_alarm_region") {
   169  		cloudwatchAlarm := &route53.AlarmIdentifier{
   170  			Name:   aws.String(d.Get("cloudwatch_alarm_name").(string)),
   171  			Region: aws.String(d.Get("cloudwatch_alarm_region").(string)),
   172  		}
   173  
   174  		updateHealthCheck.AlarmIdentifier = cloudwatchAlarm
   175  	}
   176  
   177  	if d.HasChange("insufficient_data_health_status") {
   178  		updateHealthCheck.InsufficientDataHealthStatus = aws.String(d.Get("insufficient_data_health_status").(string))
   179  	}
   180  
   181  	if d.HasChange("enable_sni") {
   182  		updateHealthCheck.EnableSNI = aws.Bool(d.Get("enable_sni").(bool))
   183  	}
   184  
   185  	_, err := conn.UpdateHealthCheck(updateHealthCheck)
   186  	if err != nil {
   187  		return err
   188  	}
   189  
   190  	if err := setTagsR53(conn, d, "healthcheck"); err != nil {
   191  		return err
   192  	}
   193  
   194  	return resourceAwsRoute53HealthCheckRead(d, meta)
   195  }
   196  
   197  func resourceAwsRoute53HealthCheckCreate(d *schema.ResourceData, meta interface{}) error {
   198  	conn := meta.(*AWSClient).r53conn
   199  
   200  	healthConfig := &route53.HealthCheckConfig{
   201  		Type: aws.String(d.Get("type").(string)),
   202  	}
   203  
   204  	if v, ok := d.GetOk("request_interval"); ok {
   205  		healthConfig.RequestInterval = aws.Int64(int64(v.(int)))
   206  	}
   207  
   208  	if v, ok := d.GetOk("failure_threshold"); ok {
   209  		healthConfig.FailureThreshold = aws.Int64(int64(v.(int)))
   210  	}
   211  
   212  	if v, ok := d.GetOk("fqdn"); ok {
   213  		healthConfig.FullyQualifiedDomainName = aws.String(v.(string))
   214  	}
   215  
   216  	if v, ok := d.GetOk("search_string"); ok {
   217  		healthConfig.SearchString = aws.String(v.(string))
   218  	}
   219  
   220  	if v, ok := d.GetOk("ip_address"); ok {
   221  		healthConfig.IPAddress = aws.String(v.(string))
   222  	}
   223  
   224  	if v, ok := d.GetOk("port"); ok {
   225  		healthConfig.Port = aws.Int64(int64(v.(int)))
   226  	}
   227  
   228  	if v, ok := d.GetOk("resource_path"); ok {
   229  		healthConfig.ResourcePath = aws.String(v.(string))
   230  	}
   231  
   232  	if *healthConfig.Type != route53.HealthCheckTypeCalculated && *healthConfig.Type != route53.HealthCheckTypeCloudwatchMetric {
   233  		if v, ok := d.GetOk("measure_latency"); ok {
   234  			healthConfig.MeasureLatency = aws.Bool(v.(bool))
   235  		}
   236  	}
   237  
   238  	if v, ok := d.GetOk("invert_healthcheck"); ok {
   239  		healthConfig.Inverted = aws.Bool(v.(bool))
   240  	}
   241  
   242  	if v, ok := d.GetOk("enable_sni"); ok {
   243  		healthConfig.EnableSNI = aws.Bool(v.(bool))
   244  	}
   245  
   246  	if *healthConfig.Type == route53.HealthCheckTypeCalculated {
   247  		if v, ok := d.GetOk("child_healthchecks"); ok {
   248  			healthConfig.ChildHealthChecks = expandStringList(v.(*schema.Set).List())
   249  		}
   250  
   251  		if v, ok := d.GetOk("child_health_threshold"); ok {
   252  			healthConfig.HealthThreshold = aws.Int64(int64(v.(int)))
   253  		}
   254  	}
   255  
   256  	if *healthConfig.Type == route53.HealthCheckTypeCloudwatchMetric {
   257  		cloudwatchAlarmIdentifier := &route53.AlarmIdentifier{}
   258  
   259  		if v, ok := d.GetOk("cloudwatch_alarm_name"); ok {
   260  			cloudwatchAlarmIdentifier.Name = aws.String(v.(string))
   261  		}
   262  
   263  		if v, ok := d.GetOk("cloudwatch_alarm_region"); ok {
   264  			cloudwatchAlarmIdentifier.Region = aws.String(v.(string))
   265  		}
   266  
   267  		healthConfig.AlarmIdentifier = cloudwatchAlarmIdentifier
   268  
   269  		if v, ok := d.GetOk("insufficient_data_health_status"); ok {
   270  			healthConfig.InsufficientDataHealthStatus = aws.String(v.(string))
   271  		}
   272  	}
   273  
   274  	callerRef := resource.UniqueId()
   275  	if v, ok := d.GetOk("reference_name"); ok {
   276  		callerRef = fmt.Sprintf("%s-%s", v.(string), callerRef)
   277  	}
   278  
   279  	input := &route53.CreateHealthCheckInput{
   280  		CallerReference:   aws.String(callerRef),
   281  		HealthCheckConfig: healthConfig,
   282  	}
   283  
   284  	resp, err := conn.CreateHealthCheck(input)
   285  
   286  	if err != nil {
   287  		return err
   288  	}
   289  
   290  	d.SetId(*resp.HealthCheck.Id)
   291  
   292  	if err := setTagsR53(conn, d, "healthcheck"); err != nil {
   293  		return err
   294  	}
   295  
   296  	return resourceAwsRoute53HealthCheckRead(d, meta)
   297  }
   298  
   299  func resourceAwsRoute53HealthCheckRead(d *schema.ResourceData, meta interface{}) error {
   300  	conn := meta.(*AWSClient).r53conn
   301  
   302  	read, err := conn.GetHealthCheck(&route53.GetHealthCheckInput{HealthCheckId: aws.String(d.Id())})
   303  	if err != nil {
   304  		if r53err, ok := err.(awserr.Error); ok && r53err.Code() == "NoSuchHealthCheck" {
   305  			d.SetId("")
   306  			return nil
   307  
   308  		}
   309  		return err
   310  	}
   311  
   312  	if read == nil {
   313  		return nil
   314  	}
   315  
   316  	updated := read.HealthCheck.HealthCheckConfig
   317  	d.Set("type", updated.Type)
   318  	d.Set("failure_threshold", updated.FailureThreshold)
   319  	d.Set("request_interval", updated.RequestInterval)
   320  	d.Set("fqdn", updated.FullyQualifiedDomainName)
   321  	d.Set("search_string", updated.SearchString)
   322  	d.Set("ip_address", updated.IPAddress)
   323  	d.Set("port", updated.Port)
   324  	d.Set("resource_path", updated.ResourcePath)
   325  	d.Set("measure_latency", updated.MeasureLatency)
   326  	d.Set("invert_healthcheck", updated.Inverted)
   327  	d.Set("child_healthchecks", updated.ChildHealthChecks)
   328  	d.Set("child_health_threshold", updated.HealthThreshold)
   329  	d.Set("insufficient_data_health_status", updated.InsufficientDataHealthStatus)
   330  	d.Set("enable_sni", updated.EnableSNI)
   331  
   332  	if updated.AlarmIdentifier != nil {
   333  		d.Set("cloudwatch_alarm_name", updated.AlarmIdentifier.Name)
   334  		d.Set("cloudwatch_alarm_region", updated.AlarmIdentifier.Region)
   335  	}
   336  
   337  	// read the tags
   338  	req := &route53.ListTagsForResourceInput{
   339  		ResourceId:   aws.String(d.Id()),
   340  		ResourceType: aws.String("healthcheck"),
   341  	}
   342  
   343  	resp, err := conn.ListTagsForResource(req)
   344  	if err != nil {
   345  		return err
   346  	}
   347  
   348  	var tags []*route53.Tag
   349  	if resp.ResourceTagSet != nil {
   350  		tags = resp.ResourceTagSet.Tags
   351  	}
   352  
   353  	if err := d.Set("tags", tagsToMapR53(tags)); err != nil {
   354  		return err
   355  	}
   356  
   357  	return nil
   358  }
   359  
   360  func resourceAwsRoute53HealthCheckDelete(d *schema.ResourceData, meta interface{}) error {
   361  	conn := meta.(*AWSClient).r53conn
   362  
   363  	log.Printf("[DEBUG] Deleteing Route53 health check: %s", d.Id())
   364  	_, err := conn.DeleteHealthCheck(&route53.DeleteHealthCheckInput{HealthCheckId: aws.String(d.Id())})
   365  	if err != nil {
   366  		return err
   367  	}
   368  
   369  	return nil
   370  }
   371  
   372  func createChildHealthCheckList(s *schema.Set) (nl []*string) {
   373  	l := s.List()
   374  	for _, n := range l {
   375  		nl = append(nl, aws.String(n.(string)))
   376  	}
   377  
   378  	return nl
   379  }