github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/newrelic/resource_newrelic_alert_condition.go (about)

     1  package newrelic
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strconv"
     7  
     8  	"github.com/hashicorp/terraform/helper/schema"
     9  	"github.com/hashicorp/terraform/helper/validation"
    10  	newrelic "github.com/paultyng/go-newrelic/api"
    11  )
    12  
    13  var alertConditionTypes = map[string][]string{
    14  	"apm_app_metric": []string{
    15  		"apdex",
    16  		"error_percentage",
    17  		"response_time_background",
    18  		"response_time_web",
    19  		"throughput_background",
    20  		"throughput_web",
    21  		"user_defined",
    22  	},
    23  	"apm_kt_metric": []string{
    24  		"apdex",
    25  		"error_count",
    26  		"error_percentage",
    27  		"response_time",
    28  		"throughput",
    29  	},
    30  	"browser_metric": []string{
    31  		"ajax_response_time",
    32  		"ajax_throughput",
    33  		"dom_processing",
    34  		"end_user_apdex",
    35  		"network",
    36  		"page_rendering",
    37  		"page_view_throughput",
    38  		"page_views_with_js_errors",
    39  		"request_queuing",
    40  		"total_page_load",
    41  		"user_defined",
    42  		"web_application",
    43  	},
    44  	"mobile_metric": []string{
    45  		"database",
    46  		"images",
    47  		"json",
    48  		"mobile_crash_rate",
    49  		"network_error_percentage",
    50  		"network",
    51  		"status_error_percentage",
    52  		"user_defined",
    53  		"view_loading",
    54  	},
    55  	"servers_metric": []string{
    56  		"cpu_percentage",
    57  		"disk_io_percentage",
    58  		"fullest_disk_percentage",
    59  		"load_average_one_minute",
    60  		"memory_percentage",
    61  		"user_defined",
    62  	},
    63  }
    64  
    65  func resourceNewRelicAlertCondition() *schema.Resource {
    66  	validAlertConditionTypes := make([]string, 0, len(alertConditionTypes))
    67  	for k := range alertConditionTypes {
    68  		validAlertConditionTypes = append(validAlertConditionTypes, k)
    69  	}
    70  
    71  	return &schema.Resource{
    72  		Create: resourceNewRelicAlertConditionCreate,
    73  		Read:   resourceNewRelicAlertConditionRead,
    74  		Update: resourceNewRelicAlertConditionUpdate,
    75  		Delete: resourceNewRelicAlertConditionDelete,
    76  		Importer: &schema.ResourceImporter{
    77  			State: schema.ImportStatePassthrough,
    78  		},
    79  		Schema: map[string]*schema.Schema{
    80  			"policy_id": {
    81  				Type:     schema.TypeInt,
    82  				Required: true,
    83  				ForceNew: true,
    84  			},
    85  			"name": {
    86  				Type:     schema.TypeString,
    87  				Required: true,
    88  			},
    89  			"type": {
    90  				Type:         schema.TypeString,
    91  				Required:     true,
    92  				ValidateFunc: validation.StringInSlice(validAlertConditionTypes, false),
    93  			},
    94  			"entities": {
    95  				Type:     schema.TypeList,
    96  				Elem:     &schema.Schema{Type: schema.TypeInt},
    97  				Required: true,
    98  				MinItems: 1,
    99  			},
   100  			"metric": {
   101  				Type:     schema.TypeString,
   102  				Required: true,
   103  				//TODO: ValidateFunc from map
   104  			},
   105  			"runbook_url": {
   106  				Type:     schema.TypeString,
   107  				Optional: true,
   108  			},
   109  			"condition_scope": {
   110  				Type:     schema.TypeString,
   111  				Optional: true,
   112  			},
   113  			"term": {
   114  				Type: schema.TypeList,
   115  				Elem: &schema.Resource{
   116  					Schema: map[string]*schema.Schema{
   117  						"duration": {
   118  							Type:         schema.TypeInt,
   119  							Required:     true,
   120  							ValidateFunc: intInSlice([]int{5, 10, 15, 30, 60, 120}),
   121  						},
   122  						"operator": {
   123  							Type:         schema.TypeString,
   124  							Optional:     true,
   125  							Default:      "equal",
   126  							ValidateFunc: validation.StringInSlice([]string{"above", "below", "equal"}, false),
   127  						},
   128  						"priority": {
   129  							Type:         schema.TypeString,
   130  							Optional:     true,
   131  							Default:      "critical",
   132  							ValidateFunc: validation.StringInSlice([]string{"critical", "warning"}, false),
   133  						},
   134  						"threshold": {
   135  							Type:         schema.TypeFloat,
   136  							Required:     true,
   137  							ValidateFunc: float64Gte(0.0),
   138  						},
   139  						"time_function": {
   140  							Type:         schema.TypeString,
   141  							Required:     true,
   142  							ValidateFunc: validation.StringInSlice([]string{"all", "any"}, false),
   143  						},
   144  					},
   145  				},
   146  				Required: true,
   147  				MinItems: 1,
   148  			},
   149  			"user_defined_metric": {
   150  				Type:     schema.TypeString,
   151  				Optional: true,
   152  			},
   153  			"user_defined_value_function": {
   154  				Type:         schema.TypeString,
   155  				Optional:     true,
   156  				ValidateFunc: validation.StringInSlice([]string{"average", "min", "max", "total", "sample_size"}, false),
   157  			},
   158  		},
   159  	}
   160  }
   161  
   162  func buildAlertConditionStruct(d *schema.ResourceData) *newrelic.AlertCondition {
   163  	entitySet := d.Get("entities").([]interface{})
   164  	entities := make([]string, len(entitySet))
   165  
   166  	for i, entity := range entitySet {
   167  		entities[i] = strconv.Itoa(entity.(int))
   168  	}
   169  
   170  	termSet := d.Get("term").([]interface{})
   171  	terms := make([]newrelic.AlertConditionTerm, len(termSet))
   172  
   173  	for i, termI := range termSet {
   174  		termM := termI.(map[string]interface{})
   175  
   176  		terms[i] = newrelic.AlertConditionTerm{
   177  			Duration:     termM["duration"].(int),
   178  			Operator:     termM["operator"].(string),
   179  			Priority:     termM["priority"].(string),
   180  			Threshold:    termM["threshold"].(float64),
   181  			TimeFunction: termM["time_function"].(string),
   182  		}
   183  	}
   184  
   185  	condition := newrelic.AlertCondition{
   186  		Type:     d.Get("type").(string),
   187  		Name:     d.Get("name").(string),
   188  		Enabled:  true,
   189  		Entities: entities,
   190  		Metric:   d.Get("metric").(string),
   191  		Terms:    terms,
   192  		PolicyID: d.Get("policy_id").(int),
   193  		Scope:    d.Get("condition_scope").(string),
   194  	}
   195  
   196  	if attr, ok := d.GetOk("runbook_url"); ok {
   197  		condition.RunbookURL = attr.(string)
   198  	}
   199  
   200  	if attrM, ok := d.GetOk("user_defined_metric"); ok {
   201  		if attrVF, ok := d.GetOk("user_defined_value_function"); ok {
   202  			condition.UserDefined = newrelic.AlertConditionUserDefined{
   203  				Metric:        attrM.(string),
   204  				ValueFunction: attrVF.(string),
   205  			}
   206  		}
   207  	}
   208  
   209  	return &condition
   210  }
   211  
   212  func readAlertConditionStruct(condition *newrelic.AlertCondition, d *schema.ResourceData) error {
   213  	ids, err := parseIDs(d.Id(), 2)
   214  	if err != nil {
   215  		return err
   216  	}
   217  
   218  	policyID := ids[0]
   219  
   220  	entities := make([]int, len(condition.Entities))
   221  	for i, entity := range condition.Entities {
   222  		v, err := strconv.ParseInt(entity, 10, 32)
   223  		if err != nil {
   224  			return err
   225  		}
   226  		entities[i] = int(v)
   227  	}
   228  
   229  	d.Set("policy_id", policyID)
   230  	d.Set("name", condition.Name)
   231  	d.Set("type", condition.Type)
   232  	d.Set("metric", condition.Metric)
   233  	d.Set("runbook_url", condition.RunbookURL)
   234  	d.Set("condition_scope", condition.Scope)
   235  	d.Set("user_defined_metric", condition.UserDefined.Metric)
   236  	d.Set("user_defined_value_function", condition.UserDefined.ValueFunction)
   237  	if err := d.Set("entities", entities); err != nil {
   238  		return fmt.Errorf("[DEBUG] Error setting alert condition entities: %#v", err)
   239  	}
   240  
   241  	var terms []map[string]interface{}
   242  
   243  	for _, src := range condition.Terms {
   244  		dst := map[string]interface{}{
   245  			"duration":      src.Duration,
   246  			"operator":      src.Operator,
   247  			"priority":      src.Priority,
   248  			"threshold":     src.Threshold,
   249  			"time_function": src.TimeFunction,
   250  		}
   251  		terms = append(terms, dst)
   252  	}
   253  
   254  	if err := d.Set("term", terms); err != nil {
   255  		return fmt.Errorf("[DEBUG] Error setting alert condition terms: %#v", err)
   256  	}
   257  
   258  	return nil
   259  }
   260  
   261  func resourceNewRelicAlertConditionCreate(d *schema.ResourceData, meta interface{}) error {
   262  	client := meta.(*newrelic.Client)
   263  	condition := buildAlertConditionStruct(d)
   264  
   265  	log.Printf("[INFO] Creating New Relic alert condition %s", condition.Name)
   266  
   267  	condition, err := client.CreateAlertCondition(*condition)
   268  	if err != nil {
   269  		return err
   270  	}
   271  
   272  	d.SetId(serializeIDs([]int{condition.PolicyID, condition.ID}))
   273  
   274  	return nil
   275  }
   276  
   277  func resourceNewRelicAlertConditionRead(d *schema.ResourceData, meta interface{}) error {
   278  	client := meta.(*newrelic.Client)
   279  
   280  	log.Printf("[INFO] Reading New Relic alert condition %s", d.Id())
   281  
   282  	ids, err := parseIDs(d.Id(), 2)
   283  	if err != nil {
   284  		return err
   285  	}
   286  
   287  	policyID := ids[0]
   288  	id := ids[1]
   289  
   290  	condition, err := client.GetAlertCondition(policyID, id)
   291  	if err != nil {
   292  		if err == newrelic.ErrNotFound {
   293  			d.SetId("")
   294  			return nil
   295  		}
   296  
   297  		return err
   298  	}
   299  
   300  	return readAlertConditionStruct(condition, d)
   301  }
   302  
   303  func resourceNewRelicAlertConditionUpdate(d *schema.ResourceData, meta interface{}) error {
   304  	client := meta.(*newrelic.Client)
   305  	condition := buildAlertConditionStruct(d)
   306  
   307  	ids, err := parseIDs(d.Id(), 2)
   308  	if err != nil {
   309  		return err
   310  	}
   311  
   312  	policyID := ids[0]
   313  	id := ids[1]
   314  
   315  	condition.PolicyID = policyID
   316  	condition.ID = id
   317  
   318  	log.Printf("[INFO] Updating New Relic alert condition %d", id)
   319  
   320  	updatedCondition, err := client.UpdateAlertCondition(*condition)
   321  	if err != nil {
   322  		return err
   323  	}
   324  
   325  	return readAlertConditionStruct(updatedCondition, d)
   326  }
   327  
   328  func resourceNewRelicAlertConditionDelete(d *schema.ResourceData, meta interface{}) error {
   329  	client := meta.(*newrelic.Client)
   330  
   331  	ids, err := parseIDs(d.Id(), 2)
   332  	if err != nil {
   333  		return err
   334  	}
   335  
   336  	policyID := ids[0]
   337  	id := ids[1]
   338  
   339  	log.Printf("[INFO] Deleting New Relic alert condition %d", id)
   340  
   341  	if err := client.DeleteAlertCondition(policyID, id); err != nil {
   342  		return err
   343  	}
   344  
   345  	d.SetId("")
   346  
   347  	return nil
   348  }