github.com/nathanielks/terraform@v0.6.1-0.20170509030759-13e1a62319dc/builtin/providers/aws/resource_aws_cloudwatch_metric_alarm.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  
     7  	"github.com/hashicorp/terraform/helper/schema"
     8  
     9  	"github.com/aws/aws-sdk-go/aws"
    10  	"github.com/aws/aws-sdk-go/service/cloudwatch"
    11  	"github.com/hashicorp/terraform/helper/validation"
    12  )
    13  
    14  func resourceAwsCloudWatchMetricAlarm() *schema.Resource {
    15  	return &schema.Resource{
    16  		Create:        resourceAwsCloudWatchMetricAlarmCreate,
    17  		Read:          resourceAwsCloudWatchMetricAlarmRead,
    18  		Update:        resourceAwsCloudWatchMetricAlarmUpdate,
    19  		Delete:        resourceAwsCloudWatchMetricAlarmDelete,
    20  		SchemaVersion: 1,
    21  		MigrateState:  resourceAwsCloudWatchMetricAlarmMigrateState,
    22  
    23  		Importer: &schema.ResourceImporter{
    24  			State: schema.ImportStatePassthrough,
    25  		},
    26  
    27  		Schema: map[string]*schema.Schema{
    28  			"alarm_name": {
    29  				Type:     schema.TypeString,
    30  				Required: true,
    31  				ForceNew: true,
    32  			},
    33  			"comparison_operator": {
    34  				Type:     schema.TypeString,
    35  				Required: true,
    36  			},
    37  			"evaluation_periods": {
    38  				Type:     schema.TypeInt,
    39  				Required: true,
    40  			},
    41  			"metric_name": {
    42  				Type:     schema.TypeString,
    43  				Required: true,
    44  			},
    45  			"namespace": {
    46  				Type:     schema.TypeString,
    47  				Required: true,
    48  			},
    49  			"period": {
    50  				Type:     schema.TypeInt,
    51  				Required: true,
    52  			},
    53  			"statistic": {
    54  				Type:          schema.TypeString,
    55  				Optional:      true,
    56  				ConflictsWith: []string{"extended_statistic"},
    57  			},
    58  			"threshold": {
    59  				Type:     schema.TypeFloat,
    60  				Required: true,
    61  			},
    62  			"actions_enabled": {
    63  				Type:     schema.TypeBool,
    64  				Optional: true,
    65  				Default:  true,
    66  			},
    67  			"alarm_actions": {
    68  				Type:     schema.TypeSet,
    69  				Optional: true,
    70  				Elem:     &schema.Schema{Type: schema.TypeString},
    71  				Set:      schema.HashString,
    72  			},
    73  			"alarm_description": {
    74  				Type:     schema.TypeString,
    75  				Optional: true,
    76  			},
    77  			"dimensions": {
    78  				Type:     schema.TypeMap,
    79  				Optional: true,
    80  			},
    81  			"insufficient_data_actions": {
    82  				Type:     schema.TypeSet,
    83  				Optional: true,
    84  				Elem:     &schema.Schema{Type: schema.TypeString},
    85  				Set:      schema.HashString,
    86  			},
    87  			"ok_actions": {
    88  				Type:     schema.TypeSet,
    89  				Optional: true,
    90  				Elem:     &schema.Schema{Type: schema.TypeString},
    91  				Set:      schema.HashString,
    92  			},
    93  			"unit": {
    94  				Type:     schema.TypeString,
    95  				Optional: true,
    96  			},
    97  			"extended_statistic": {
    98  				Type:          schema.TypeString,
    99  				Optional:      true,
   100  				ConflictsWith: []string{"statistic"},
   101  			},
   102  			"treat_missing_data": {
   103  				Type:         schema.TypeString,
   104  				Optional:     true,
   105  				Default:      "missing",
   106  				ValidateFunc: validation.StringInSlice([]string{"breaching", "notBreaching", "ignore", "missing"}, true),
   107  			},
   108  			"evaluate_low_sample_count_percentiles": {
   109  				Type:         schema.TypeString,
   110  				Optional:     true,
   111  				Computed:     true,
   112  				ValidateFunc: validation.StringInSlice([]string{"evaluate", "ignore"}, true),
   113  			},
   114  		},
   115  	}
   116  }
   117  
   118  func resourceAwsCloudWatchMetricAlarmCreate(d *schema.ResourceData, meta interface{}) error {
   119  	conn := meta.(*AWSClient).cloudwatchconn
   120  
   121  	_, statisticOk := d.GetOk("statistic")
   122  	_, extendedStatisticOk := d.GetOk("extended_statistic")
   123  
   124  	if !statisticOk && !extendedStatisticOk {
   125  		return fmt.Errorf("One of `statistic` or `extended_statistic` must be set for a cloudwatch metric alarm")
   126  	}
   127  
   128  	params := getAwsCloudWatchPutMetricAlarmInput(d)
   129  
   130  	log.Printf("[DEBUG] Creating CloudWatch Metric Alarm: %#v", params)
   131  	_, err := conn.PutMetricAlarm(&params)
   132  	if err != nil {
   133  		return fmt.Errorf("Creating metric alarm failed: %s", err)
   134  	}
   135  	d.SetId(d.Get("alarm_name").(string))
   136  	log.Println("[INFO] CloudWatch Metric Alarm created")
   137  
   138  	return resourceAwsCloudWatchMetricAlarmRead(d, meta)
   139  }
   140  
   141  func resourceAwsCloudWatchMetricAlarmRead(d *schema.ResourceData, meta interface{}) error {
   142  	a, err := getAwsCloudWatchMetricAlarm(d, meta)
   143  	if err != nil {
   144  		return err
   145  	}
   146  	if a == nil {
   147  		d.SetId("")
   148  		return nil
   149  	}
   150  
   151  	log.Printf("[DEBUG] Reading CloudWatch Metric Alarm: %s", d.Get("alarm_name"))
   152  
   153  	d.Set("actions_enabled", a.ActionsEnabled)
   154  
   155  	if err := d.Set("alarm_actions", _strArrPtrToList(a.AlarmActions)); err != nil {
   156  		log.Printf("[WARN] Error setting Alarm Actions: %s", err)
   157  	}
   158  	d.Set("alarm_description", a.AlarmDescription)
   159  	d.Set("alarm_name", a.AlarmName)
   160  	d.Set("comparison_operator", a.ComparisonOperator)
   161  	if err := d.Set("dimensions", flattenDimensions(a.Dimensions)); err != nil {
   162  		return err
   163  	}
   164  	d.Set("evaluation_periods", a.EvaluationPeriods)
   165  
   166  	if err := d.Set("insufficient_data_actions", _strArrPtrToList(a.InsufficientDataActions)); err != nil {
   167  		log.Printf("[WARN] Error setting Insufficient Data Actions: %s", err)
   168  	}
   169  	d.Set("metric_name", a.MetricName)
   170  	d.Set("namespace", a.Namespace)
   171  
   172  	if err := d.Set("ok_actions", _strArrPtrToList(a.OKActions)); err != nil {
   173  		log.Printf("[WARN] Error setting OK Actions: %s", err)
   174  	}
   175  	d.Set("period", a.Period)
   176  	d.Set("statistic", a.Statistic)
   177  	d.Set("threshold", a.Threshold)
   178  	d.Set("unit", a.Unit)
   179  	d.Set("extended_statistic", a.ExtendedStatistic)
   180  	d.Set("treat_missing_data", a.TreatMissingData)
   181  	d.Set("evaluate_low_sample_count_percentiles", a.EvaluateLowSampleCountPercentile)
   182  
   183  	return nil
   184  }
   185  
   186  func resourceAwsCloudWatchMetricAlarmUpdate(d *schema.ResourceData, meta interface{}) error {
   187  	conn := meta.(*AWSClient).cloudwatchconn
   188  	params := getAwsCloudWatchPutMetricAlarmInput(d)
   189  
   190  	log.Printf("[DEBUG] Updating CloudWatch Metric Alarm: %#v", params)
   191  	_, err := conn.PutMetricAlarm(&params)
   192  	if err != nil {
   193  		return fmt.Errorf("Updating metric alarm failed: %s", err)
   194  	}
   195  	log.Println("[INFO] CloudWatch Metric Alarm updated")
   196  
   197  	return resourceAwsCloudWatchMetricAlarmRead(d, meta)
   198  }
   199  
   200  func resourceAwsCloudWatchMetricAlarmDelete(d *schema.ResourceData, meta interface{}) error {
   201  	p, err := getAwsCloudWatchMetricAlarm(d, meta)
   202  	if err != nil {
   203  		return err
   204  	}
   205  	if p == nil {
   206  		log.Printf("[DEBUG] CloudWatch Metric Alarm %s is already gone", d.Id())
   207  		return nil
   208  	}
   209  
   210  	log.Printf("[INFO] Deleting CloudWatch Metric Alarm: %s", d.Id())
   211  
   212  	conn := meta.(*AWSClient).cloudwatchconn
   213  	params := cloudwatch.DeleteAlarmsInput{
   214  		AlarmNames: []*string{aws.String(d.Id())},
   215  	}
   216  
   217  	if _, err := conn.DeleteAlarms(&params); err != nil {
   218  		return fmt.Errorf("Error deleting CloudWatch Metric Alarm: %s", err)
   219  	}
   220  	log.Println("[INFO] CloudWatch Metric Alarm deleted")
   221  
   222  	d.SetId("")
   223  	return nil
   224  }
   225  
   226  func getAwsCloudWatchPutMetricAlarmInput(d *schema.ResourceData) cloudwatch.PutMetricAlarmInput {
   227  	params := cloudwatch.PutMetricAlarmInput{
   228  		AlarmName:          aws.String(d.Get("alarm_name").(string)),
   229  		ComparisonOperator: aws.String(d.Get("comparison_operator").(string)),
   230  		EvaluationPeriods:  aws.Int64(int64(d.Get("evaluation_periods").(int))),
   231  		MetricName:         aws.String(d.Get("metric_name").(string)),
   232  		Namespace:          aws.String(d.Get("namespace").(string)),
   233  		Period:             aws.Int64(int64(d.Get("period").(int))),
   234  		Threshold:          aws.Float64(d.Get("threshold").(float64)),
   235  		TreatMissingData:   aws.String(d.Get("treat_missing_data").(string)),
   236  	}
   237  
   238  	if v := d.Get("actions_enabled"); v != nil {
   239  		params.ActionsEnabled = aws.Bool(v.(bool))
   240  	}
   241  
   242  	if v, ok := d.GetOk("alarm_description"); ok {
   243  		params.AlarmDescription = aws.String(v.(string))
   244  	}
   245  
   246  	if v, ok := d.GetOk("unit"); ok {
   247  		params.Unit = aws.String(v.(string))
   248  	}
   249  
   250  	if v, ok := d.GetOk("statistic"); ok {
   251  		params.Statistic = aws.String(v.(string))
   252  	}
   253  
   254  	if v, ok := d.GetOk("extended_statistic"); ok {
   255  		params.ExtendedStatistic = aws.String(v.(string))
   256  	}
   257  
   258  	if v, ok := d.GetOk("evaluate_low_sample_count_percentiles"); ok {
   259  		params.EvaluateLowSampleCountPercentile = aws.String(v.(string))
   260  	}
   261  
   262  	var alarmActions []*string
   263  	if v := d.Get("alarm_actions"); v != nil {
   264  		for _, v := range v.(*schema.Set).List() {
   265  			str := v.(string)
   266  			alarmActions = append(alarmActions, aws.String(str))
   267  		}
   268  		params.AlarmActions = alarmActions
   269  	}
   270  
   271  	var insufficientDataActions []*string
   272  	if v := d.Get("insufficient_data_actions"); v != nil {
   273  		for _, v := range v.(*schema.Set).List() {
   274  			str := v.(string)
   275  			insufficientDataActions = append(insufficientDataActions, aws.String(str))
   276  		}
   277  		params.InsufficientDataActions = insufficientDataActions
   278  	}
   279  
   280  	var okActions []*string
   281  	if v := d.Get("ok_actions"); v != nil {
   282  		for _, v := range v.(*schema.Set).List() {
   283  			str := v.(string)
   284  			okActions = append(okActions, aws.String(str))
   285  		}
   286  		params.OKActions = okActions
   287  	}
   288  
   289  	a := d.Get("dimensions").(map[string]interface{})
   290  	dimensions := make([]*cloudwatch.Dimension, 0, len(a))
   291  	for k, v := range a {
   292  		dimensions = append(dimensions, &cloudwatch.Dimension{
   293  			Name:  aws.String(k),
   294  			Value: aws.String(v.(string)),
   295  		})
   296  	}
   297  	params.Dimensions = dimensions
   298  
   299  	return params
   300  }
   301  
   302  func getAwsCloudWatchMetricAlarm(d *schema.ResourceData, meta interface{}) (*cloudwatch.MetricAlarm, error) {
   303  	conn := meta.(*AWSClient).cloudwatchconn
   304  
   305  	params := cloudwatch.DescribeAlarmsInput{
   306  		AlarmNames: []*string{aws.String(d.Id())},
   307  	}
   308  
   309  	resp, err := conn.DescribeAlarms(&params)
   310  	if err != nil {
   311  		return nil, err
   312  	}
   313  
   314  	// Find it and return it
   315  	for idx, ma := range resp.MetricAlarms {
   316  		if *ma.AlarmName == d.Id() {
   317  			return resp.MetricAlarms[idx], nil
   318  		}
   319  	}
   320  
   321  	return nil, nil
   322  }
   323  
   324  func _strArrPtrToList(strArrPtr []*string) []string {
   325  	var result []string
   326  	for _, elem := range strArrPtr {
   327  		result = append(result, *elem)
   328  	}
   329  	return result
   330  }
   331  
   332  func flattenDimensions(dims []*cloudwatch.Dimension) map[string]interface{} {
   333  	flatDims := make(map[string]interface{})
   334  	for _, d := range dims {
   335  		flatDims[*d.Name] = *d.Value
   336  	}
   337  	return flatDims
   338  }