provider/datadog: Add `query` parameter to `metric_alert`

`query` is used when it is specified by the user, if not
`metric`/`tags`/`keys`/`time_aggr`/`window` is used instead.
This commit is contained in:
Kelvin Law 2016-01-23 17:51:53 +11:00 committed by James Nugent
parent f407eea3f7
commit 775a3f8826
2 changed files with 101 additions and 21 deletions

View File

@ -24,8 +24,9 @@ func resourceDatadogMetricAlert() *schema.Resource {
Required: true,
},
"metric": &schema.Schema{
Type: schema.TypeString,
Required: true,
Type: schema.TypeString,
Optional: true,
ConflictsWith: []string{"query"},
},
"tags": &schema.Schema{
Type: schema.TypeList,
@ -33,21 +34,25 @@ func resourceDatadogMetricAlert() *schema.Resource {
Elem: &schema.Schema{Type: schema.TypeString},
},
"keys": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
ConflictsWith: []string{"query"},
},
"time_aggr": &schema.Schema{
Type: schema.TypeString,
Required: true,
Type: schema.TypeString,
Optional: true,
ConflictsWith: []string{"query"},
},
"time_window": &schema.Schema{
Type: schema.TypeString,
Required: true,
Type: schema.TypeString,
Optional: true,
ConflictsWith: []string{"query"},
},
"space_aggr": &schema.Schema{
Type: schema.TypeString,
Required: true,
Type: schema.TypeString,
Optional: true,
ConflictsWith: []string{"query"},
},
"operator": &schema.Schema{
Type: schema.TypeString,
@ -58,6 +63,14 @@ func resourceDatadogMetricAlert() *schema.Resource {
Required: true,
},
// Optional Query for custom monitors
"query": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ConflictsWith: []string{"time_aggr", "time_window", "space_aggr", "metric", "keys"},
},
"thresholds": thresholdSchema(),
// Additional Settings
@ -89,6 +102,7 @@ func buildMetricAlertStruct(d *schema.ResourceData) *datadog.Monitor {
timeWindow := d.Get("time_window").(string)
spaceAggr := d.Get("space_aggr").(string)
metric := d.Get("metric").(string)
query := d.Get("query").(string)
// Tags are are no separate resource/gettable, so some trickery is needed
var buffer bytes.Buffer
@ -127,16 +141,23 @@ func buildMetricAlertStruct(d *schema.ResourceData) *datadog.Monitor {
threshold, thresholds := getThresholds(d)
operator := d.Get("operator").(string)
query := fmt.Sprintf("%s(%s):%s:%s{%s} %s %s %s", timeAggr,
timeWindow,
spaceAggr,
metric,
tagsParsed,
keys,
operator,
threshold)
log.Print(fmt.Sprintf("[DEBUG] submitting query: %s", query))
var q string
if query == "" {
q = fmt.Sprintf("%s(%s):%s:%s{%s} %s %s %s", timeAggr,
timeWindow,
spaceAggr,
metric,
tagsParsed,
keys,
operator,
threshold)
} else {
q = fmt.Sprintf("%s %s %s", query, operator, threshold)
}
log.Print(fmt.Sprintf("[DEBUG] submitting query: %s", q))
o := datadog.Options{
NotifyNoData: d.Get("notify_no_data").(bool),
@ -147,7 +168,7 @@ func buildMetricAlertStruct(d *schema.ResourceData) *datadog.Monitor {
m := datadog.Monitor{
Type: "metric alert",
Query: query,
Query: q,
Name: name,
Message: message,
Options: o,

View File

@ -61,6 +61,43 @@ func TestAccDatadogMetricAlert_Basic(t *testing.T) {
})
}
func TestAccDatadogMetricAlert_Query(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckDatadogMetricAlertDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCheckDatadogMetricAlertConfigQuery,
Check: resource.ComposeTestCheckFunc(
testAccCheckDatadogMetricAlertExists("datadog_metric_alert.foo"),
resource.TestCheckResourceAttr(
"datadog_metric_alert.foo", "name", "name for metric_alert foo"),
resource.TestCheckResourceAttr(
"datadog_metric_alert.foo", "message", "{{#is_alert}}Metric alert foo is critical"+
"{{/is_alert}}\n{{#is_warning}}Metric alert foo is at warning "+
"level{{/is_warning}}\n{{#is_recovery}}Metric alert foo has "+
"recovered{{/is_recovery}}\nNotify: @hipchat-channel\n"),
resource.TestCheckResourceAttr(
"datadog_metric_alert.foo", "query", "avg(last_1h):avg:aws.ec2.cpu{environment:foo,host:foo} by {host}"),
resource.TestCheckResourceAttr(
"datadog_metric_alert.foo", "operator", ">"),
resource.TestCheckResourceAttr(
"datadog_metric_alert.foo", "notify_no_data", "false"),
resource.TestCheckResourceAttr(
"datadog_metric_alert.foo", "renotify_interval", "60"),
resource.TestCheckResourceAttr(
"datadog_metric_alert.foo", "thresholds.ok", "0"),
resource.TestCheckResourceAttr(
"datadog_metric_alert.foo", "thresholds.warning", "1"),
resource.TestCheckResourceAttr(
"datadog_metric_alert.foo", "thresholds.critical", "2"),
),
},
},
})
}
func testAccCheckDatadogMetricAlertDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*datadog.Client)
@ -109,3 +146,25 @@ EOF
renotify_interval = 60
}
`
const testAccCheckDatadogMetricAlertConfigQuery = `
resource "datadog_metric_alert" "foo" {
name = "name for metric_alert foo"
message = <<EOF
{{#is_alert}}Metric alert foo is critical{{/is_alert}}
{{#is_warning}}Metric alert foo is at warning level{{/is_warning}}
{{#is_recovery}}Metric alert foo has recovered{{/is_recovery}}
Notify: @hipchat-channel
EOF
operator = ">" // <, <=, >, >=, ==, or !=
query = "avg(last_1h):avg:aws.ec2.cpu{environment:foo,host:foo} by {host}"
thresholds {
ok = 0
warning = 1
critical = 2
}
notify_no_data = false
renotify_interval = 60
}
`