provider/datadog: Replace separate monitors with one generic monitor with read functionality.
This commit is contained in:
parent
775a3f8826
commit
eb2407fccf
|
@ -7,7 +7,6 @@ import (
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Provider returns a terraform.ResourceProvider.
|
|
||||||
func Provider() terraform.ResourceProvider {
|
func Provider() terraform.ResourceProvider {
|
||||||
return &schema.Provider{
|
return &schema.Provider{
|
||||||
Schema: map[string]*schema.Schema{
|
Schema: map[string]*schema.Schema{
|
||||||
|
@ -24,16 +23,13 @@ func Provider() terraform.ResourceProvider {
|
||||||
},
|
},
|
||||||
|
|
||||||
ResourcesMap: map[string]*schema.Resource{
|
ResourcesMap: map[string]*schema.Resource{
|
||||||
"datadog_service_check": resourceDatadogServiceCheck(),
|
"datadog_monitor": resourceDatadogMonitor(),
|
||||||
"datadog_metric_alert": resourceDatadogMetricAlert(),
|
|
||||||
"datadog_outlier_alert": resourceDatadogOutlierAlert(),
|
|
||||||
},
|
},
|
||||||
|
|
||||||
ConfigureFunc: providerConfigure,
|
ConfigureFunc: providerConfigure,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProviderConfigure returns a configured client.
|
|
||||||
func providerConfigure(d *schema.ResourceData) (interface{}, error) {
|
func providerConfigure(d *schema.ResourceData) (interface{}, error) {
|
||||||
|
|
||||||
config := Config{
|
config := Config{
|
||||||
|
|
|
@ -1,201 +0,0 @@
|
||||||
package datadog
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
|
||||||
"github.com/zorkian/go-datadog-api"
|
|
||||||
)
|
|
||||||
|
|
||||||
// resourceDatadogMetricAlert is a Datadog monitor resource
|
|
||||||
func resourceDatadogMetricAlert() *schema.Resource {
|
|
||||||
return &schema.Resource{
|
|
||||||
Create: resourceDatadogMetricAlertCreate,
|
|
||||||
Read: resourceDatadogGenericRead,
|
|
||||||
Update: resourceDatadogMetricAlertUpdate,
|
|
||||||
Delete: resourceDatadogGenericDelete,
|
|
||||||
Exists: resourceDatadogGenericExists,
|
|
||||||
|
|
||||||
Schema: map[string]*schema.Schema{
|
|
||||||
"name": &schema.Schema{
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
"metric": &schema.Schema{
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Optional: true,
|
|
||||||
ConflictsWith: []string{"query"},
|
|
||||||
},
|
|
||||||
"tags": &schema.Schema{
|
|
||||||
Type: schema.TypeList,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &schema.Schema{Type: schema.TypeString},
|
|
||||||
},
|
|
||||||
"keys": &schema.Schema{
|
|
||||||
Type: schema.TypeList,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &schema.Schema{Type: schema.TypeString},
|
|
||||||
ConflictsWith: []string{"query"},
|
|
||||||
},
|
|
||||||
"time_aggr": &schema.Schema{
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Optional: true,
|
|
||||||
ConflictsWith: []string{"query"},
|
|
||||||
},
|
|
||||||
"time_window": &schema.Schema{
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Optional: true,
|
|
||||||
ConflictsWith: []string{"query"},
|
|
||||||
},
|
|
||||||
"space_aggr": &schema.Schema{
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Optional: true,
|
|
||||||
ConflictsWith: []string{"query"},
|
|
||||||
},
|
|
||||||
"operator": &schema.Schema{
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
"message": &schema.Schema{
|
|
||||||
Type: schema.TypeString,
|
|
||||||
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
|
|
||||||
"notify_no_data": &schema.Schema{
|
|
||||||
Type: schema.TypeBool,
|
|
||||||
Optional: true,
|
|
||||||
Default: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
"no_data_timeframe": &schema.Schema{
|
|
||||||
Type: schema.TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
"renotify_interval": &schema.Schema{
|
|
||||||
Type: schema.TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
Default: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildMonitorStruct returns a monitor struct
|
|
||||||
func buildMetricAlertStruct(d *schema.ResourceData) *datadog.Monitor {
|
|
||||||
name := d.Get("name").(string)
|
|
||||||
message := d.Get("message").(string)
|
|
||||||
timeAggr := d.Get("time_aggr").(string)
|
|
||||||
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
|
|
||||||
if raw, ok := d.GetOk("tags"); ok {
|
|
||||||
list := raw.([]interface{})
|
|
||||||
length := (len(list) - 1)
|
|
||||||
for i, v := range list {
|
|
||||||
buffer.WriteString(fmt.Sprintf("%s", v))
|
|
||||||
if i != length {
|
|
||||||
buffer.WriteString(",")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tagsParsed := buffer.String()
|
|
||||||
|
|
||||||
// Keys are used for multi alerts
|
|
||||||
var b bytes.Buffer
|
|
||||||
if raw, ok := d.GetOk("keys"); ok {
|
|
||||||
list := raw.([]interface{})
|
|
||||||
b.WriteString("by {")
|
|
||||||
length := (len(list) - 1)
|
|
||||||
for i, v := range list {
|
|
||||||
b.WriteString(fmt.Sprintf("%s", v))
|
|
||||||
if i != length {
|
|
||||||
b.WriteString(",")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
b.WriteString("}")
|
|
||||||
}
|
|
||||||
|
|
||||||
keys := b.String()
|
|
||||||
|
|
||||||
threshold, thresholds := getThresholds(d)
|
|
||||||
|
|
||||||
operator := d.Get("operator").(string)
|
|
||||||
|
|
||||||
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),
|
|
||||||
NoDataTimeframe: d.Get("no_data_timeframe").(int),
|
|
||||||
RenotifyInterval: d.Get("renotify_interval").(int),
|
|
||||||
Thresholds: thresholds,
|
|
||||||
}
|
|
||||||
|
|
||||||
m := datadog.Monitor{
|
|
||||||
Type: "metric alert",
|
|
||||||
Query: q,
|
|
||||||
Name: name,
|
|
||||||
Message: message,
|
|
||||||
Options: o,
|
|
||||||
}
|
|
||||||
|
|
||||||
return &m
|
|
||||||
}
|
|
||||||
|
|
||||||
// resourceDatadogMetricAlertCreate creates a monitor.
|
|
||||||
func resourceDatadogMetricAlertCreate(d *schema.ResourceData, meta interface{}) error {
|
|
||||||
|
|
||||||
m := buildMetricAlertStruct(d)
|
|
||||||
if err := monitorCreator(d, meta, m); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// resourceDatadogMetricAlertUpdate updates a monitor.
|
|
||||||
func resourceDatadogMetricAlertUpdate(d *schema.ResourceData, meta interface{}) error {
|
|
||||||
log.Printf("[DEBUG] running update.")
|
|
||||||
|
|
||||||
m := buildMetricAlertStruct(d)
|
|
||||||
if err := monitorUpdater(d, meta, m); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,170 +0,0 @@
|
||||||
package datadog
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/helper/resource"
|
|
||||||
"github.com/hashicorp/terraform/terraform"
|
|
||||||
"github.com/zorkian/go-datadog-api"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestAccDatadogMetricAlert_Basic(t *testing.T) {
|
|
||||||
resource.Test(t, resource.TestCase{
|
|
||||||
PreCheck: func() { testAccPreCheck(t) },
|
|
||||||
Providers: testAccProviders,
|
|
||||||
CheckDestroy: testAccCheckDatadogMetricAlertDestroy,
|
|
||||||
Steps: []resource.TestStep{
|
|
||||||
resource.TestStep{
|
|
||||||
Config: testAccCheckDatadogMetricAlertConfigBasic,
|
|
||||||
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", "metric", "aws.ec2.cpu"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_metric_alert.foo", "tags.0", "environment:foo"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_metric_alert.foo", "tags.1", "host:foo"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_metric_alert.foo", "tags.#", "2"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_metric_alert.foo", "keys.0", "host"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_metric_alert.foo", "keys.#", "1"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_metric_alert.foo", "time_aggr", "avg"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_metric_alert.foo", "time_window", "last_1h"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_metric_alert.foo", "space_aggr", "avg"),
|
|
||||||
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 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)
|
|
||||||
|
|
||||||
if err := destroyHelper(s, client); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func testAccCheckDatadogMetricAlertExists(n string) resource.TestCheckFunc {
|
|
||||||
return func(s *terraform.State) error {
|
|
||||||
client := testAccProvider.Meta().(*datadog.Client)
|
|
||||||
if err := existsHelper(s, client); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const testAccCheckDatadogMetricAlertConfigBasic = `
|
|
||||||
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
|
|
||||||
|
|
||||||
metric = "aws.ec2.cpu"
|
|
||||||
tags = ["environment:foo", "host:foo"]
|
|
||||||
keys = ["host"]
|
|
||||||
|
|
||||||
time_aggr = "avg" // avg, sum, max, min, change, or pct_change
|
|
||||||
time_window = "last_1h" // last_#m (5, 10, 15, 30), last_#h (1, 2, 4), or last_1d
|
|
||||||
space_aggr = "avg" // avg, sum, min, or max
|
|
||||||
operator = ">" // <, <=, >, >=, ==, or !=
|
|
||||||
|
|
||||||
thresholds {
|
|
||||||
ok = 0
|
|
||||||
warning = 1
|
|
||||||
critical = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
notify_no_data = false
|
|
||||||
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
|
|
||||||
}
|
|
||||||
`
|
|
|
@ -0,0 +1,318 @@
|
||||||
|
package datadog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"github.com/zorkian/go-datadog-api"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceDatadogMonitor() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceDatadogMonitorCreate,
|
||||||
|
Read: resourceDatadogMonitorRead,
|
||||||
|
Update: resourceDatadogMonitorUpdate,
|
||||||
|
Delete: resourceDatadogMonitorDelete,
|
||||||
|
Exists: resourceDatadogMonitorExists,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"message": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"escalation_message": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"query": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"type": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Options
|
||||||
|
"thresholds": &schema.Schema{
|
||||||
|
Type: schema.TypeMap,
|
||||||
|
Required: true,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"ok": &schema.Schema{
|
||||||
|
Type: schema.TypeFloat,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"warning": &schema.Schema{
|
||||||
|
Type: schema.TypeFloat,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"critical": &schema.Schema{
|
||||||
|
Type: schema.TypeFloat,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"notify_no_data": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
Default: true,
|
||||||
|
},
|
||||||
|
"no_data_timeframe": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"renotify_interval": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"notify_audit": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"timeout_h": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
// TODO should actually be map[string]int
|
||||||
|
"silenced": &schema.Schema{
|
||||||
|
Type: schema.TypeMap,
|
||||||
|
Optional: true,
|
||||||
|
Elem: &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Elem: &schema.Schema{
|
||||||
|
Type: schema.TypeInt},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"include_tags": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildMonitorStruct(d *schema.ResourceData) *datadog.Monitor {
|
||||||
|
|
||||||
|
var thresholds datadog.ThresholdCount
|
||||||
|
|
||||||
|
if r, ok := d.GetOk("thresholds.ok"); ok {
|
||||||
|
thresholds.Ok = json.Number(r.(string))
|
||||||
|
}
|
||||||
|
if r, ok := d.GetOk("thresholds.warning"); ok {
|
||||||
|
thresholds.Warning = json.Number(r.(string))
|
||||||
|
}
|
||||||
|
if r, ok := d.GetOk("thresholds.critical"); ok {
|
||||||
|
thresholds.Critical = json.Number(r.(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
o := datadog.Options{
|
||||||
|
Thresholds: thresholds,
|
||||||
|
}
|
||||||
|
if attr, ok := d.GetOk("silenced"); ok {
|
||||||
|
s := make(map[string]int)
|
||||||
|
// TODO: this is not very defensive, test if we can fail on non int input
|
||||||
|
for k, v := range attr.(map[string]interface{}) {
|
||||||
|
s[k], _ = strconv.Atoi(v.(string))
|
||||||
|
}
|
||||||
|
o.Silenced = s
|
||||||
|
}
|
||||||
|
if attr, ok := d.GetOk("notify_data"); ok {
|
||||||
|
o.NotifyNoData = attr.(bool)
|
||||||
|
}
|
||||||
|
if attr, ok := d.GetOk("no_data_timeframe"); ok {
|
||||||
|
o.NoDataTimeframe = attr.(int)
|
||||||
|
}
|
||||||
|
if attr, ok := d.GetOk("renotify_interval"); ok {
|
||||||
|
o.RenotifyInterval = attr.(int)
|
||||||
|
}
|
||||||
|
if attr, ok := d.GetOk("notify_audit"); ok {
|
||||||
|
o.NotifyAudit = attr.(bool)
|
||||||
|
}
|
||||||
|
if attr, ok := d.GetOk("timeout_h"); ok {
|
||||||
|
o.TimeoutH = attr.(int)
|
||||||
|
}
|
||||||
|
if attr, ok := d.GetOk("escalation_message"); ok {
|
||||||
|
o.EscalationMessage = attr.(string)
|
||||||
|
}
|
||||||
|
if attr, ok := d.GetOk("escalation_message"); ok {
|
||||||
|
o.EscalationMessage = attr.(string)
|
||||||
|
}
|
||||||
|
if attr, ok := d.GetOk("include_tags"); ok {
|
||||||
|
o.IncludeTags = attr.(bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
m := datadog.Monitor{
|
||||||
|
Type: d.Get("type").(string),
|
||||||
|
Query: d.Get("query").(string),
|
||||||
|
Name: d.Get("name").(string),
|
||||||
|
Message: d.Get("message").(string),
|
||||||
|
Options: o,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &m
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceDatadogMonitorExists(d *schema.ResourceData, meta interface{}) (b bool, e error) {
|
||||||
|
// Exists - This is called to verify a resource still exists. It is called prior to Read,
|
||||||
|
// and lowers the burden of Read to be able to assume the resource exists.
|
||||||
|
client := meta.(*datadog.Client)
|
||||||
|
|
||||||
|
i, err := strconv.Atoi(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = client.GetMonitor(i); err != nil {
|
||||||
|
if strings.Contains(err.Error(), "404 Not Found") {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceDatadogMonitorCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
|
||||||
|
client := meta.(*datadog.Client)
|
||||||
|
|
||||||
|
m := buildMonitorStruct(d)
|
||||||
|
m, err := client.CreateMonitor(m)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error updating montor: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(strconv.Itoa(m.Id))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceDatadogMonitorRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
client := meta.(*datadog.Client)
|
||||||
|
|
||||||
|
i, err := strconv.Atoi(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
m, err := client.GetMonitor(i)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] monitor: %v", m)
|
||||||
|
d.Set("name", m.Name)
|
||||||
|
d.Set("message", m.Message)
|
||||||
|
d.Set("query", m.Query)
|
||||||
|
d.Set("type", m.Type)
|
||||||
|
d.Set("thresholds", m.Options.Thresholds)
|
||||||
|
d.Set("notify_no_data", m.Options.NotifyNoData)
|
||||||
|
d.Set("notify_no_data_timeframe", m.Options.NoDataTimeframe)
|
||||||
|
d.Set("renotify_interval", m.Options.RenotifyInterval)
|
||||||
|
d.Set("notify_audit", m.Options.NotifyAudit)
|
||||||
|
d.Set("timeout_h", m.Options.TimeoutH)
|
||||||
|
d.Set("escalation_message", m.Options.EscalationMessage)
|
||||||
|
d.Set("silenced", m.Options.Silenced)
|
||||||
|
d.Set("include_tags", m.Options.IncludeTags)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceDatadogMonitorUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
client := meta.(*datadog.Client)
|
||||||
|
|
||||||
|
m := &datadog.Monitor{}
|
||||||
|
|
||||||
|
i, err := strconv.Atoi(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Id = i
|
||||||
|
if attr, ok := d.GetOk("name"); ok {
|
||||||
|
m.Name = attr.(string)
|
||||||
|
}
|
||||||
|
if attr, ok := d.GetOk("message"); ok {
|
||||||
|
m.Message = attr.(string)
|
||||||
|
}
|
||||||
|
if attr, ok := d.GetOk("query"); ok {
|
||||||
|
m.Query = attr.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
o := datadog.Options{}
|
||||||
|
if attr, ok := d.GetOk("thresholds"); ok {
|
||||||
|
thresholds := attr.(map[string]interface{})
|
||||||
|
if thresholds["ok"] != nil {
|
||||||
|
o.Thresholds.Ok = json.Number(thresholds["ok"].(string))
|
||||||
|
}
|
||||||
|
if thresholds["warning"] != nil {
|
||||||
|
o.Thresholds.Warning = json.Number(thresholds["warning"].(string))
|
||||||
|
}
|
||||||
|
if thresholds["critical"] != nil {
|
||||||
|
o.Thresholds.Critical = json.Number(thresholds["critical"].(string))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if attr, ok := d.GetOk("notify_no_data"); ok {
|
||||||
|
o.NotifyNoData = attr.(bool)
|
||||||
|
}
|
||||||
|
if attr, ok := d.GetOk("notify_no_data_timeframe"); ok {
|
||||||
|
o.NoDataTimeframe = attr.(int)
|
||||||
|
}
|
||||||
|
if attr, ok := d.GetOk("renotify_interval"); ok {
|
||||||
|
o.RenotifyInterval = attr.(int)
|
||||||
|
}
|
||||||
|
if attr, ok := d.GetOk("notify_audit"); ok {
|
||||||
|
o.NotifyAudit = attr.(bool)
|
||||||
|
}
|
||||||
|
if attr, ok := d.GetOk("timeout_h"); ok {
|
||||||
|
o.TimeoutH = attr.(int)
|
||||||
|
}
|
||||||
|
if attr, ok := d.GetOk("escalation_message"); ok {
|
||||||
|
o.EscalationMessage = attr.(string)
|
||||||
|
}
|
||||||
|
if attr, ok := d.GetOk("silenced"); ok {
|
||||||
|
// TODO: this is not very defensive, test if we can fail non int input
|
||||||
|
s := make(map[string]int)
|
||||||
|
for k, v := range attr.(map[string]interface{}) {
|
||||||
|
s[k], _ = strconv.Atoi(v.(string))
|
||||||
|
}
|
||||||
|
o.Silenced = s
|
||||||
|
}
|
||||||
|
if attr, ok := d.GetOk("include_tags"); ok {
|
||||||
|
o.IncludeTags = attr.(bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Options = o
|
||||||
|
|
||||||
|
if err = client.UpdateMonitor(m); err != nil {
|
||||||
|
return fmt.Errorf("error updating montor: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceDatadogMonitorRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceDatadogMonitorDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
client := meta.(*datadog.Client)
|
||||||
|
|
||||||
|
i, err := strconv.Atoi(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = client.DeleteMonitor(i); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,216 @@
|
||||||
|
package datadog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
"github.com/zorkian/go-datadog-api"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccDatadogMonitor_Basic(t *testing.T) {
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckDatadogMonitorDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccCheckDatadogMonitorConfig,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckDatadogMonitorExists("datadog_monitor.foo"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "name", "name for monitor foo"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "message", "some message Notify: @hipchat-channel"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "type", "metric alert"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "query", "avg(last_1h):avg:aws.ec2.cpu{environment:foo,host:foo} by {host} > 2"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "notify_no_data", "false"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "renotify_interval", "60"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "thresholds.ok", "0"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "thresholds.warning", "1"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "thresholds.critical", "2"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccDatadogMonitor_Updated(t *testing.T) {
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckDatadogMonitorDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccCheckDatadogMonitorConfig,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckDatadogMonitorExists("datadog_monitor.foo"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "name", "name for monitor foo"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "message", "some message Notify: @hipchat-channel"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "escalation_message", "the situation has escalated @pagerduty"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "query", "avg(last_1h):avg:aws.ec2.cpu{environment:foo,host:foo} by {host} > 2"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "type", "metric alert"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "notify_no_data", "false"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "renotify_interval", "60"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "thresholds.ok", "0"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "thresholds.warning", "1"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "thresholds.critical", "2"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "notify_audit", "false"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "timeout_h", "60"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "include_tags", "true"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccCheckDatadogMonitorConfigUpdated,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckDatadogMonitorExists("datadog_monitor.foo"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "name", "name for monitor bar"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "message", "a different message Notify: @hipchat-channel"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "query", "avg(last_1h):avg:aws.ec2.cpu{environment:bar,host:bar} by {host} > 3"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "escalation_message", "the situation has escalated! @pagerduty"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "type", "metric alert"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "notify_no_data", "true"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "renotify_interval", "40"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "thresholds.ok", "0"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "thresholds.warning", "1"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "thresholds.critical", "3"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "notify_audit", "true"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "timeout_h", "70"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "include_tags", "false"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"datadog_monitor.foo", "silenced.*", "0"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckDatadogMonitorDestroy(s *terraform.State) error {
|
||||||
|
client := testAccProvider.Meta().(*datadog.Client)
|
||||||
|
|
||||||
|
if err := destroyHelper(s, client); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckDatadogMonitorExists(n string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
client := testAccProvider.Meta().(*datadog.Client)
|
||||||
|
if err := existsHelper(s, client); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccCheckDatadogMonitorConfig = `
|
||||||
|
resource "datadog_monitor" "foo" {
|
||||||
|
name = "name for monitor foo"
|
||||||
|
type = "metric alert"
|
||||||
|
message = "some message Notify: @hipchat-channel"
|
||||||
|
escalation_message = "the situation has escalated @pagerduty"
|
||||||
|
|
||||||
|
query = "avg(last_1h):avg:aws.ec2.cpu{environment:foo,host:foo} by {host} > 2"
|
||||||
|
|
||||||
|
thresholds {
|
||||||
|
ok = 0
|
||||||
|
warning = 1
|
||||||
|
critical = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
notify_no_data = false
|
||||||
|
renotify_interval = 60
|
||||||
|
|
||||||
|
notify_audit = false
|
||||||
|
timeout_h = 60
|
||||||
|
include_tags = true
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const testAccCheckDatadogMonitorConfigUpdated = `
|
||||||
|
resource "datadog_monitor" "foo" {
|
||||||
|
name = "name for monitor bar"
|
||||||
|
type = "metric alert"
|
||||||
|
message = "a different message Notify: @hipchat-channel"
|
||||||
|
escalation_message = "the situation has escalated @pagerduty"
|
||||||
|
|
||||||
|
query = "avg(last_1h):avg:aws.ec2.cpu{environment:bar,host:bar} by {host} > 3"
|
||||||
|
|
||||||
|
thresholds {
|
||||||
|
ok = 0
|
||||||
|
warning = 1
|
||||||
|
critical = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
notify_no_data = true
|
||||||
|
renotify_interval = 40
|
||||||
|
escalation_message = "the situation has escalated! @pagerduty"
|
||||||
|
notify_audit = true
|
||||||
|
timeout_h = 70
|
||||||
|
include_tags = false
|
||||||
|
silenced {
|
||||||
|
"*" = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
func destroyHelper(s *terraform.State, client *datadog.Client) error {
|
||||||
|
for _, r := range s.RootModule().Resources {
|
||||||
|
i, _ := strconv.Atoi(r.Primary.ID)
|
||||||
|
if _, err := client.GetMonitor(i); err != nil {
|
||||||
|
if strings.Contains(err.Error(), "404 Not Found") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return fmt.Errorf("Received an error retrieving monitor %s", err)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("Monitor still exists")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func existsHelper(s *terraform.State, client *datadog.Client) error {
|
||||||
|
for _, r := range s.RootModule().Resources {
|
||||||
|
i, _ := strconv.Atoi(r.Primary.ID)
|
||||||
|
if _, err := client.GetMonitor(i); err != nil {
|
||||||
|
return fmt.Errorf("Received an error retrieving monitor %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -1,184 +0,0 @@
|
||||||
package datadog
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
|
||||||
"github.com/zorkian/go-datadog-api"
|
|
||||||
)
|
|
||||||
|
|
||||||
// resourceDatadogOutlierAlert is a Datadog monitor resource
|
|
||||||
func resourceDatadogOutlierAlert() *schema.Resource {
|
|
||||||
return &schema.Resource{
|
|
||||||
Create: resourceDatadogOutlierAlertCreate,
|
|
||||||
Read: resourceDatadogGenericRead,
|
|
||||||
Update: resourceDatadogOutlierAlertUpdate,
|
|
||||||
Delete: resourceDatadogGenericDelete,
|
|
||||||
Exists: resourceDatadogGenericExists,
|
|
||||||
|
|
||||||
Schema: map[string]*schema.Schema{
|
|
||||||
"name": &schema.Schema{
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
"metric": &schema.Schema{
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
"tags": &schema.Schema{
|
|
||||||
Type: schema.TypeList,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &schema.Schema{Type: schema.TypeString},
|
|
||||||
},
|
|
||||||
"keys": &schema.Schema{
|
|
||||||
Type: schema.TypeList,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &schema.Schema{Type: schema.TypeString},
|
|
||||||
},
|
|
||||||
"time_aggr": &schema.Schema{
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
"time_window": &schema.Schema{
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
"space_aggr": &schema.Schema{
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
"message": &schema.Schema{
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
"threshold": &schema.Schema{
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
// Additional Settings
|
|
||||||
"notify_no_data": &schema.Schema{
|
|
||||||
Type: schema.TypeBool,
|
|
||||||
Optional: true,
|
|
||||||
Default: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
"no_data_timeframe": &schema.Schema{
|
|
||||||
Type: schema.TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
"algorithm": &schema.Schema{
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Optional: true,
|
|
||||||
Default: "dbscan",
|
|
||||||
},
|
|
||||||
|
|
||||||
"renotify_interval": &schema.Schema{
|
|
||||||
Type: schema.TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
Default: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildMonitorStruct returns a monitor struct
|
|
||||||
func buildOutlierAlertStruct(d *schema.ResourceData) *datadog.Monitor {
|
|
||||||
name := d.Get("name").(string)
|
|
||||||
message := d.Get("message").(string)
|
|
||||||
timeAggr := d.Get("time_aggr").(string)
|
|
||||||
timeWindow := d.Get("time_window").(string)
|
|
||||||
spaceAggr := d.Get("space_aggr").(string)
|
|
||||||
metric := d.Get("metric").(string)
|
|
||||||
algorithm := d.Get("algorithm").(string)
|
|
||||||
|
|
||||||
// Tags are are no separate resource/gettable, so some trickery is needed
|
|
||||||
var buffer bytes.Buffer
|
|
||||||
if raw, ok := d.GetOk("tags"); ok {
|
|
||||||
list := raw.([]interface{})
|
|
||||||
length := (len(list) - 1)
|
|
||||||
for i, v := range list {
|
|
||||||
if length > 1 && v == "*" {
|
|
||||||
log.Print(fmt.Sprintf("[DEBUG] found wildcard, this is not supported for this type: %s", v))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
buffer.WriteString(fmt.Sprintf("%s", v))
|
|
||||||
if i != length {
|
|
||||||
buffer.WriteString(",")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tagsParsed := buffer.String()
|
|
||||||
|
|
||||||
// Keys are used for multi alerts
|
|
||||||
var b bytes.Buffer
|
|
||||||
if raw, ok := d.GetOk("keys"); ok {
|
|
||||||
list := raw.([]interface{})
|
|
||||||
b.WriteString("by {")
|
|
||||||
length := (len(list) - 1)
|
|
||||||
for i, v := range list {
|
|
||||||
b.WriteString(fmt.Sprintf("%s", v))
|
|
||||||
if i != length {
|
|
||||||
b.WriteString(",")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
b.WriteString("}")
|
|
||||||
}
|
|
||||||
|
|
||||||
keys := b.String()
|
|
||||||
|
|
||||||
query := fmt.Sprintf("%s(%s):outliers(%s:%s{%s} %s, '%s',%s) > 0", timeAggr,
|
|
||||||
timeWindow,
|
|
||||||
spaceAggr,
|
|
||||||
metric,
|
|
||||||
tagsParsed,
|
|
||||||
keys,
|
|
||||||
algorithm,
|
|
||||||
d.Get("threshold"))
|
|
||||||
|
|
||||||
log.Print(fmt.Sprintf("[DEBUG] submitting query: %s", query))
|
|
||||||
|
|
||||||
o := datadog.Options{
|
|
||||||
NotifyNoData: d.Get("notify_no_data").(bool),
|
|
||||||
NoDataTimeframe: d.Get("no_data_timeframe").(int),
|
|
||||||
RenotifyInterval: d.Get("renotify_interval").(int),
|
|
||||||
}
|
|
||||||
|
|
||||||
m := datadog.Monitor{
|
|
||||||
Type: "query alert",
|
|
||||||
Query: query,
|
|
||||||
Name: name,
|
|
||||||
Message: message,
|
|
||||||
Options: o,
|
|
||||||
}
|
|
||||||
|
|
||||||
return &m
|
|
||||||
}
|
|
||||||
|
|
||||||
// resourceDatadogOutlierAlertCreate creates a monitor.
|
|
||||||
func resourceDatadogOutlierAlertCreate(d *schema.ResourceData, meta interface{}) error {
|
|
||||||
|
|
||||||
m := buildOutlierAlertStruct(d)
|
|
||||||
if err := monitorCreator(d, meta, m); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// resourceDatadogOutlierAlertUpdate updates a monitor.
|
|
||||||
func resourceDatadogOutlierAlertUpdate(d *schema.ResourceData, meta interface{}) error {
|
|
||||||
log.Printf("[DEBUG] running update.")
|
|
||||||
|
|
||||||
m := buildOutlierAlertStruct(d)
|
|
||||||
if err := monitorUpdater(d, meta, m); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,97 +0,0 @@
|
||||||
package datadog
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/helper/resource"
|
|
||||||
"github.com/hashicorp/terraform/terraform"
|
|
||||||
"github.com/zorkian/go-datadog-api"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestAccDatadogOutlierAlert_Basic(t *testing.T) {
|
|
||||||
resource.Test(t, resource.TestCase{
|
|
||||||
PreCheck: func() { testAccPreCheck(t) },
|
|
||||||
Providers: testAccProviders,
|
|
||||||
CheckDestroy: testAccCheckDatadogOutlierAlertDestroy,
|
|
||||||
Steps: []resource.TestStep{
|
|
||||||
resource.TestStep{
|
|
||||||
Config: testAccCheckDatadogOutlierAlertConfigBasic,
|
|
||||||
Check: resource.ComposeTestCheckFunc(
|
|
||||||
testAccCheckDatadogOutlierAlertExists("datadog_outlier_alert.foo"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_outlier_alert.foo", "name", "name for outlier_alert foo"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_outlier_alert.foo", "message", "description for outlier_alert foo @hipchat-name"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_outlier_alert.foo", "metric", "system.load.5"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_outlier_alert.foo", "tags.0", "environment:foo"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_outlier_alert.foo", "tags.1", "host:foo"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_outlier_alert.foo", "tags.#", "2"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_outlier_alert.foo", "keys.0", "host"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_outlier_alert.foo", "keys.#", "1"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_outlier_alert.foo", "time_aggr", "avg"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_outlier_alert.foo", "time_window", "last_1h"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_outlier_alert.foo", "space_aggr", "avg"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_outlier_alert.foo", "notify_no_data", "false"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_outlier_alert.foo", "algorithm", "mad"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_outlier_alert.foo", "renotify_interval", "60"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_outlier_alert.foo", "threshold", "2"),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func testAccCheckDatadogOutlierAlertDestroy(s *terraform.State) error {
|
|
||||||
client := testAccProvider.Meta().(*datadog.Client)
|
|
||||||
|
|
||||||
if err := destroyHelper(s, client); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func testAccCheckDatadogOutlierAlertExists(n string) resource.TestCheckFunc {
|
|
||||||
return func(s *terraform.State) error {
|
|
||||||
client := testAccProvider.Meta().(*datadog.Client)
|
|
||||||
if err := existsHelper(s, client); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const testAccCheckDatadogOutlierAlertConfigBasic = `
|
|
||||||
resource "datadog_outlier_alert" "foo" {
|
|
||||||
name = "name for outlier_alert foo"
|
|
||||||
message = "description for outlier_alert foo @hipchat-name"
|
|
||||||
|
|
||||||
algorithm = "mad"
|
|
||||||
|
|
||||||
metric = "system.load.5"
|
|
||||||
tags = ["environment:foo", "host:foo"]
|
|
||||||
keys = ["host"]
|
|
||||||
|
|
||||||
time_aggr = "avg" // avg, sum, max, min, change, or pct_change
|
|
||||||
time_window = "last_1h" // last_#m (5, 10, 15, 30), last_#h (1, 2, 4), or last_1d
|
|
||||||
space_aggr = "avg" // avg, sum, min, or max
|
|
||||||
|
|
||||||
threshold = 2.0
|
|
||||||
|
|
||||||
notify_no_data = false
|
|
||||||
renotify_interval = 60
|
|
||||||
|
|
||||||
}
|
|
||||||
`
|
|
|
@ -1,163 +0,0 @@
|
||||||
package datadog
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
|
||||||
"github.com/zorkian/go-datadog-api"
|
|
||||||
)
|
|
||||||
|
|
||||||
// resourceDatadogServiceCheck is a Datadog monitor resource
|
|
||||||
func resourceDatadogServiceCheck() *schema.Resource {
|
|
||||||
return &schema.Resource{
|
|
||||||
Create: resourceDatadogServiceCheckCreate,
|
|
||||||
Read: resourceDatadogGenericRead,
|
|
||||||
Update: resourceDatadogServiceCheckUpdate,
|
|
||||||
Delete: resourceDatadogGenericDelete,
|
|
||||||
Exists: resourceDatadogGenericExists,
|
|
||||||
|
|
||||||
Schema: map[string]*schema.Schema{
|
|
||||||
"name": &schema.Schema{
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
"check": &schema.Schema{
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
"thresholds": thresholdSchema(),
|
|
||||||
|
|
||||||
"tags": &schema.Schema{
|
|
||||||
Type: schema.TypeList,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &schema.Schema{Type: schema.TypeString},
|
|
||||||
},
|
|
||||||
"keys": &schema.Schema{
|
|
||||||
Type: schema.TypeList,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &schema.Schema{Type: schema.TypeString},
|
|
||||||
},
|
|
||||||
"message": &schema.Schema{
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
// Additional Settings
|
|
||||||
"notify_no_data": &schema.Schema{
|
|
||||||
Type: schema.TypeBool,
|
|
||||||
Optional: true,
|
|
||||||
Default: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
"no_data_timeframe": &schema.Schema{
|
|
||||||
Type: schema.TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
"renotify_interval": &schema.Schema{
|
|
||||||
Type: schema.TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
Default: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildServiceCheckStruct returns a monitor struct
|
|
||||||
func buildServiceCheckStruct(d *schema.ResourceData) *datadog.Monitor {
|
|
||||||
log.Print("[DEBUG] building monitor struct")
|
|
||||||
name := d.Get("name").(string)
|
|
||||||
message := d.Get("message").(string)
|
|
||||||
|
|
||||||
// Tags are are no separate resource/gettable, so some trickery is needed
|
|
||||||
var buffer bytes.Buffer
|
|
||||||
if raw, ok := d.GetOk("tags"); ok {
|
|
||||||
list := raw.([]interface{})
|
|
||||||
length := (len(list) - 1)
|
|
||||||
for i, v := range list {
|
|
||||||
buffer.WriteString(fmt.Sprintf("\"%s\"", v))
|
|
||||||
if i != length {
|
|
||||||
buffer.WriteString(",")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tagsParsed := buffer.String()
|
|
||||||
|
|
||||||
// Keys are used for multi alerts
|
|
||||||
var b bytes.Buffer
|
|
||||||
if raw, ok := d.GetOk("keys"); ok {
|
|
||||||
list := raw.([]interface{})
|
|
||||||
b.WriteString(".by(")
|
|
||||||
length := (len(list) - 1)
|
|
||||||
for i, v := range list {
|
|
||||||
b.WriteString(fmt.Sprintf("\"%s\"", v))
|
|
||||||
if i != length {
|
|
||||||
b.WriteString(",")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
b.WriteString(")")
|
|
||||||
}
|
|
||||||
|
|
||||||
keys := b.String()
|
|
||||||
|
|
||||||
var monitorName string
|
|
||||||
var query string
|
|
||||||
|
|
||||||
check := d.Get("check").(string)
|
|
||||||
|
|
||||||
// Examples queries
|
|
||||||
// "http.can_connect".over("instance:buildeng_http","production").last(2).count_by_status()
|
|
||||||
// "http.can_connect".over("*").by("host","instance","url").last(2).count_by_status()
|
|
||||||
|
|
||||||
checkCount, thresholds := getThresholds(d)
|
|
||||||
|
|
||||||
query = fmt.Sprintf("\"%s\".over(%s)%s.last(%s).count_by_status()", check, tagsParsed, keys, checkCount)
|
|
||||||
log.Print(fmt.Sprintf("[DEBUG] submitting query: %s", query))
|
|
||||||
monitorName = name
|
|
||||||
|
|
||||||
o := datadog.Options{
|
|
||||||
NotifyNoData: d.Get("notify_no_data").(bool),
|
|
||||||
NoDataTimeframe: d.Get("no_data_timeframe").(int),
|
|
||||||
RenotifyInterval: d.Get("renotify_interval").(int),
|
|
||||||
Thresholds: thresholds,
|
|
||||||
}
|
|
||||||
|
|
||||||
m := datadog.Monitor{
|
|
||||||
Type: "service check",
|
|
||||||
Query: query,
|
|
||||||
Name: monitorName,
|
|
||||||
Message: message,
|
|
||||||
Options: o,
|
|
||||||
}
|
|
||||||
|
|
||||||
return &m
|
|
||||||
}
|
|
||||||
|
|
||||||
// resourceDatadogServiceCheckCreate creates a monitor.
|
|
||||||
func resourceDatadogServiceCheckCreate(d *schema.ResourceData, meta interface{}) error {
|
|
||||||
log.Print("[DEBUG] creating monitor")
|
|
||||||
|
|
||||||
m := buildServiceCheckStruct(d)
|
|
||||||
if err := monitorCreator(d, meta, m); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// resourceDatadogServiceCheckUpdate updates a monitor.
|
|
||||||
func resourceDatadogServiceCheckUpdate(d *schema.ResourceData, meta interface{}) error {
|
|
||||||
log.Printf("[DEBUG] running update.")
|
|
||||||
|
|
||||||
m := buildServiceCheckStruct(d)
|
|
||||||
if err := monitorUpdater(d, meta, m); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,96 +0,0 @@
|
||||||
package datadog
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/helper/resource"
|
|
||||||
"github.com/hashicorp/terraform/terraform"
|
|
||||||
"github.com/zorkian/go-datadog-api"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestAccDatadogServiceCheck_Basic(t *testing.T) {
|
|
||||||
resource.Test(t, resource.TestCase{
|
|
||||||
PreCheck: func() { testAccPreCheck(t) },
|
|
||||||
Providers: testAccProviders,
|
|
||||||
CheckDestroy: testAccCheckDatadogServiceCheckDestroy,
|
|
||||||
Steps: []resource.TestStep{
|
|
||||||
resource.TestStep{
|
|
||||||
Config: testAccCheckDatadogServiceCheckConfigBasic,
|
|
||||||
Check: resource.ComposeTestCheckFunc(
|
|
||||||
testAccCheckDatadogServiceCheckExists("datadog_service_check.bar"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_service_check.bar", "name", "name for service check bar"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_service_check.bar", "message", "{{#is_alert}}Service check bar is critical"+
|
|
||||||
"{{/is_alert}}\n{{#is_warning}}Service check bar is at warning "+
|
|
||||||
"level{{/is_warning}}\n{{#is_recovery}}Service check bar has "+
|
|
||||||
"recovered{{/is_recovery}}\nNotify: @hipchat-channel\n"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_service_check.bar", "check", "datadog.agent.up"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_service_check.bar", "notify_no_data", "false"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_service_check.bar", "tags.0", "environment:foo"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_service_check.bar", "tags.1", "host:bar"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_service_check.bar", "tags.#", "2"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_service_check.bar", "keys.0", "foo"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_service_check.bar", "keys.1", "bar"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_service_check.bar", "keys.#", "2"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_service_check.bar", "thresholds.ok", "0"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_service_check.bar", "thresholds.warning", "1"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"datadog_service_check.bar", "thresholds.critical", "2"),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func testAccCheckDatadogServiceCheckDestroy(s *terraform.State) error {
|
|
||||||
client := testAccProvider.Meta().(*datadog.Client)
|
|
||||||
|
|
||||||
if err := destroyHelper(s, client); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func testAccCheckDatadogServiceCheckExists(n string) resource.TestCheckFunc {
|
|
||||||
return func(s *terraform.State) error {
|
|
||||||
client := testAccProvider.Meta().(*datadog.Client)
|
|
||||||
if err := existsHelper(s, client); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const testAccCheckDatadogServiceCheckConfigBasic = `
|
|
||||||
resource "datadog_service_check" "bar" {
|
|
||||||
name = "name for service check bar"
|
|
||||||
message = <<EOF
|
|
||||||
{{#is_alert}}Service check bar is critical{{/is_alert}}
|
|
||||||
{{#is_warning}}Service check bar is at warning level{{/is_warning}}
|
|
||||||
{{#is_recovery}}Service check bar has recovered{{/is_recovery}}
|
|
||||||
Notify: @hipchat-channel
|
|
||||||
EOF
|
|
||||||
tags = ["environment:foo", "host:bar"]
|
|
||||||
keys = ["foo", "bar"]
|
|
||||||
check = "datadog.agent.up"
|
|
||||||
|
|
||||||
thresholds {
|
|
||||||
ok = 0
|
|
||||||
warning = 1
|
|
||||||
critical = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
notify_no_data = false
|
|
||||||
}
|
|
||||||
`
|
|
|
@ -1,138 +0,0 @@
|
||||||
package datadog
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
|
||||||
"github.com/zorkian/go-datadog-api"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func thresholdSchema() *schema.Schema {
|
|
||||||
return &schema.Schema{
|
|
||||||
Type: schema.TypeMap,
|
|
||||||
Required: true,
|
|
||||||
Elem: &schema.Resource{
|
|
||||||
Schema: map[string]*schema.Schema{
|
|
||||||
"ok": &schema.Schema{
|
|
||||||
Type: schema.TypeFloat,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
"warning": &schema.Schema{
|
|
||||||
Type: schema.TypeFloat,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
"critical": &schema.Schema{
|
|
||||||
Type: schema.TypeFloat,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getThresholds(d *schema.ResourceData) (string, datadog.ThresholdCount) {
|
|
||||||
t := datadog.ThresholdCount{}
|
|
||||||
|
|
||||||
var threshold string
|
|
||||||
|
|
||||||
if r, ok := d.GetOk("thresholds.ok"); ok {
|
|
||||||
t.Ok = json.Number(r.(string))
|
|
||||||
}
|
|
||||||
|
|
||||||
if r, ok := d.GetOk("thresholds.warning"); ok {
|
|
||||||
t.Warning = json.Number(r.(string))
|
|
||||||
}
|
|
||||||
|
|
||||||
if r, ok := d.GetOk("thresholds.critical"); ok {
|
|
||||||
threshold = r.(string)
|
|
||||||
t.Critical = json.Number(r.(string))
|
|
||||||
}
|
|
||||||
|
|
||||||
return threshold, t
|
|
||||||
}
|
|
||||||
|
|
||||||
func resourceDatadogGenericDelete(d *schema.ResourceData, meta interface{}) error {
|
|
||||||
client := meta.(*datadog.Client)
|
|
||||||
|
|
||||||
i, err := strconv.Atoi(d.Id())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = client.DeleteMonitor(i); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func resourceDatadogGenericExists(d *schema.ResourceData, meta interface{}) (b bool, e error) {
|
|
||||||
// Exists - This is called to verify a resource still exists. It is called prior to Read,
|
|
||||||
// and lowers the burden of Read to be able to assume the resource exists.
|
|
||||||
client := meta.(*datadog.Client)
|
|
||||||
|
|
||||||
// Workaround to handle upgrades from < 0.0.4
|
|
||||||
if strings.Contains(d.Id(), "__") {
|
|
||||||
return false, fmt.Errorf("Monitor ID contains __, which is pre v0.0.4 old behaviour.\n You have the following options:\n" +
|
|
||||||
" * Run https://github.com/ojongerius/terraform-provider-datadog/blob/master/scripts/migration_helper.py to generate a new statefile and clean up monitors\n" +
|
|
||||||
" * Mannualy fix this by deleting all your metric_check resources and recreate them, " +
|
|
||||||
"or manually remove half of the resources and hack the state file.\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
i, err := strconv.Atoi(d.Id())
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err = client.GetMonitor(i); err != nil {
|
|
||||||
if strings.Contains(err.Error(), "404 Not Found") {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func resourceDatadogGenericRead(d *schema.ResourceData, meta interface{}) error {
|
|
||||||
// TODO: Add support for read function.
|
|
||||||
/* Read - This is called to resync the local state with the remote state.
|
|
||||||
Terraform guarantees that an existing ID will be set. This ID should be
|
|
||||||
used to look up the resource. Any remote data should be updated into the
|
|
||||||
local data. No changes to the remote resource are to be made.
|
|
||||||
*/
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func monitorCreator(d *schema.ResourceData, meta interface{}, m *datadog.Monitor) error {
|
|
||||||
client := meta.(*datadog.Client)
|
|
||||||
|
|
||||||
m, err := client.CreateMonitor(m)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error updating montor: %s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
d.SetId(strconv.Itoa(m.Id))
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func monitorUpdater(d *schema.ResourceData, meta interface{}, m *datadog.Monitor) error {
|
|
||||||
client := meta.(*datadog.Client)
|
|
||||||
|
|
||||||
i, err := strconv.Atoi(d.Id())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Id = i
|
|
||||||
|
|
||||||
if err = client.UpdateMonitor(m); err != nil {
|
|
||||||
return fmt.Errorf("error updating montor: %s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
package datadog
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/terraform"
|
|
||||||
"github.com/zorkian/go-datadog-api"
|
|
||||||
)
|
|
||||||
|
|
||||||
func destroyHelper(s *terraform.State, client *datadog.Client) error {
|
|
||||||
for _, r := range s.RootModule().Resources {
|
|
||||||
i, _ := strconv.Atoi(r.Primary.ID)
|
|
||||||
if _, err := client.GetMonitor(i); err != nil {
|
|
||||||
if strings.Contains(err.Error(), "404 Not Found") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return fmt.Errorf("Received an error retrieving monitor %s", err)
|
|
||||||
}
|
|
||||||
return fmt.Errorf("Monitor still exists")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func existsHelper(s *terraform.State, client *datadog.Client) error {
|
|
||||||
for _, r := range s.RootModule().Resources {
|
|
||||||
i, _ := strconv.Atoi(r.Primary.ID)
|
|
||||||
if _, err := client.GetMonitor(i); err != nil {
|
|
||||||
return fmt.Errorf("Received an error retrieving monitor %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
Loading…
Reference in New Issue