diff --git a/builtin/providers/datadog/resource_datadog_monitor.go b/builtin/providers/datadog/resource_datadog_monitor.go index 5697fff4a..1344c703b 100644 --- a/builtin/providers/datadog/resource_datadog_monitor.go +++ b/builtin/providers/datadog/resource_datadog_monitor.go @@ -19,7 +19,7 @@ func resourceDatadogMonitor() *schema.Resource { Delete: resourceDatadogMonitorDelete, Exists: resourceDatadogMonitorExists, Importer: &schema.ResourceImporter{ - State: resourceDatadogImport, + State: resourceDatadogMonitorImport, }, Schema: map[string]*schema.Schema{ @@ -73,7 +73,7 @@ func resourceDatadogMonitor() *schema.Resource { }, }, }, - DiffSuppressFunc: supressDataDogFloatIntDiff, + DiffSuppressFunc: suppressDataDogFloatIntDiff, }, "notify_no_data": &schema.Schema{ Type: schema.TypeBool, @@ -393,7 +393,7 @@ func resourceDatadogMonitorDelete(d *schema.ResourceData, meta interface{}) erro return nil } -func resourceDatadogImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { +func resourceDatadogMonitorImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { if err := resourceDatadogMonitorRead(d, meta); err != nil { return nil, err } @@ -402,7 +402,7 @@ func resourceDatadogImport(d *schema.ResourceData, meta interface{}) ([]*schema. // Ignore any diff that results from the mix of ints or floats returned from the // DataDog API. -func supressDataDogFloatIntDiff(k, old, new string, d *schema.ResourceData) bool { +func suppressDataDogFloatIntDiff(k, old, new string, d *schema.ResourceData) bool { oF, err := strconv.ParseFloat(old, 64) if err != nil { log.Printf("Error parsing float of old value (%s): %s", old, err) diff --git a/builtin/providers/datadog/resource_datadog_timeboard.go b/builtin/providers/datadog/resource_datadog_timeboard.go index 0597365e5..8ba5c91bf 100644 --- a/builtin/providers/datadog/resource_datadog_timeboard.go +++ b/builtin/providers/datadog/resource_datadog_timeboard.go @@ -1,6 +1,7 @@ package datadog import ( + "encoding/json" "fmt" "log" "strconv" @@ -11,7 +12,6 @@ import ( ) func resourceDatadogTimeboard() *schema.Resource { - request := &schema.Schema{ Type: schema.TypeList, Required: true, @@ -35,6 +35,91 @@ func resourceDatadogTimeboard() *schema.Resource { Type: schema.TypeMap, Optional: true, }, + "conditional_format": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "A list of conditional formatting rules.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "palette": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The palette to use if this condition is met.", + }, + "comparator": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "Comparator (<, >, etc)", + }, + "custom_bg_color": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Custom background color (e.g., #205081)", + }, + "value": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Value that is threshold for conditional format", + }, + "custom_fg_color": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Custom foreground color (e.g., #59afe1)", + }, + }, + }, + }, + "change_type": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Type of change for change graphs.", + }, + "order_direction": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Sort change graph in ascending or descending order.", + }, + "compare_to": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The time period to compare change against in change graphs.", + }, + "increase_good": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Description: "Decides whether to represent increases as good or bad in change graphs.", + }, + "order_by": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The field a change graph will be ordered by.", + }, + "extra_col": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "If set to 'present', this will include the present values in change graphs.", + }, + }, + }, + } + + marker := &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "value": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "label": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, }, }, } @@ -50,11 +135,74 @@ func resourceDatadogTimeboard() *schema.Resource { Required: true, Description: "The name of the graph.", }, + "events": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Description: "Filter for events to be overlayed on the graph.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, "viz": &schema.Schema{ Type: schema.TypeString, Required: true, }, "request": request, + "marker": marker, + "yaxis": &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + }, + "autoscale": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Description: "Automatically scale graphs", + }, + "text_align": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "How to align text", + }, + "precision": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "How many digits to show", + }, + "custom_unit": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Use a custom unit (like 'users')", + }, + "style": &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + }, + "group": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Description: "A list of groupings for hostmap type graphs.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "include_no_metric_hosts": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Description: "Include hosts without metrics in hostmap graphs", + }, + "scope": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Description: "A list of scope filters for hostmap type graphs.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "include_ungrouped_hosts": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Description: "Include ungrouped hosts in hostmap graphs", + }, }, }, } @@ -90,6 +238,9 @@ func resourceDatadogTimeboard() *schema.Resource { Read: resourceDatadogTimeboardRead, Delete: resourceDatadogTimeboardDelete, Exists: resourceDatadogTimeboardExists, + Importer: &schema.ResourceImporter{ + State: resourceDatadogTimeboardImport, + }, Schema: map[string]*schema.Schema{ "title": &schema.Schema{ @@ -113,6 +264,33 @@ func resourceDatadogTimeboard() *schema.Resource { } } +func appendConditionalFormats(datadogRequest *datadog.GraphDefinitionRequest, terraformFormats *[]interface{}) { + for _, t_ := range *terraformFormats { + t := t_.(map[string]interface{}) + d := datadog.DashboardConditionalFormat{ + Comparator: t["comparator"].(string), + } + + if palette, ok := t["palette"]; ok { + d.Palette = palette.(string) + } + + if customBgColor, ok := t["custom_bg_color"]; ok { + d.CustomBgColor = customBgColor.(string) + } + + if customFgColor, ok := t["custom_fg_color"]; ok { + d.CustomFgColor = customFgColor.(string) + } + + if value, ok := t["value"]; ok { + d.Value = json.Number(value.(string)) + } + + datadogRequest.ConditionalFormats = append(datadogRequest.ConditionalFormats, d) + } +} + func buildTemplateVariables(terraformTemplateVariables *[]interface{}) *[]datadog.TemplateVariable { datadogTemplateVariables := make([]datadog.TemplateVariable, len(*terraformTemplateVariables)) for i, t_ := range *terraformTemplateVariables { @@ -137,14 +315,84 @@ func appendRequests(datadogGraph *datadog.Graph, terraformRequests *[]interface{ } if style, ok := t["style"]; ok { s, _ := style.(map[string]interface{}) - if palette, ok := s["palette"]; ok { - d.Style.Palette = palette.(string) + + style := struct { + Palette *string `json:"palette,omitempty"` + Width *string `json:"width,omitempty"` + Type *string `json:"type,omitempty"` + }{} + + if palette_, ok := s["palette"]; ok { + palette := palette_.(string) + style.Palette = &palette } + + if width, ok := s["width"]; ok { + width := width.(string) + style.Width = &width + } + + if type_, ok := s["type"]; ok { + style_type := type_.(string) + style.Type = &style_type + } + + d.Style = &style } + + if changeType, ok := t["change_type"]; ok { + d.ChangeType = changeType.(string) + } + if compareTo, ok := t["compare_to"]; ok { + d.CompareTo = compareTo.(string) + } + if increaseGood, ok := t["increase_good"]; ok { + d.IncreaseGood = increaseGood.(bool) + } + if orderBy, ok := t["order_by"]; ok { + d.OrderBy = orderBy.(string) + } + if extraCol, ok := t["extra_col"]; ok { + d.ExtraCol = extraCol.(string) + } + if orderDirection, ok := t["order_direction"]; ok { + d.OrderDirection = orderDirection.(string) + } + + if terraformConditionalFormats, ok := t["conditional_format"]; ok { + formats := terraformConditionalFormats.([]interface{}) + appendConditionalFormats(&d, &formats) + } + datadogGraph.Definition.Requests = append(datadogGraph.Definition.Requests, d) } } +func appendEvents(datadogGraph *datadog.Graph, terraformEvents *[]interface{}) { + for _, t_ := range *terraformEvents { + d := struct { + Query string `json:"q"` + }{ + t_.(string), + } + datadogGraph.Definition.Events = append(datadogGraph.Definition.Events, d) + } +} + +func appendMarkers(datadogGraph *datadog.Graph, terraformMarkers *[]interface{}) { + for _, t_ := range *terraformMarkers { + t := t_.(map[string]interface{}) + d := datadog.GraphDefinitionMarker{ + Type: t["type"].(string), + Value: t["value"].(string), + } + if label, ok := t["label"]; ok { + d.Label = label.(string) + } + datadogGraph.Definition.Markers = append(datadogGraph.Definition.Markers, d) + } +} + func buildGraphs(terraformGraphs *[]interface{}) *[]datadog.Graph { datadogGraphs := make([]datadog.Graph, len(*terraformGraphs)) for i, t_ := range *terraformGraphs { @@ -152,6 +400,85 @@ func buildGraphs(terraformGraphs *[]interface{}) *[]datadog.Graph { datadogGraphs[i] = datadog.Graph{Title: t["title"].(string)} d := &datadogGraphs[i] d.Definition.Viz = t["viz"].(string) + + if yaxis_, ok := t["yaxis"]; ok { + yaxis := yaxis_.(map[string]interface{}) + if min_, ok := yaxis["min"]; ok { + min, _ := strconv.ParseFloat(min_.(string), 64) + d.Definition.Yaxis.Min = &min + } + if max_, ok := yaxis["max"]; ok { + max, _ := strconv.ParseFloat(max_.(string), 64) + d.Definition.Yaxis.Max = &max + } + if scale_, ok := yaxis["scale"]; ok { + scale := scale_.(string) + d.Definition.Yaxis.Scale = &scale + } + } + + if autoscale, ok := t["autoscale"]; ok { + d.Definition.Autoscale = autoscale.(bool) + } + + if textAlign, ok := t["text_align"]; ok { + d.Definition.TextAlign = textAlign.(string) + } + + if precision, ok := t["precision"]; ok { + d.Definition.Precision = precision.(string) + } + + if customUnit, ok := t["custom_unit"]; ok { + d.Definition.CustomUnit = customUnit.(string) + } + + if style, ok := t["style"]; ok { + s := style.(map[string]interface{}) + + style := struct { + Palette *string `json:"palette,omitempty"` + PaletteFlip *bool `json:"paletteFlip,omitempty"` + }{} + + if palette_, ok := s["palette"]; ok { + palette := palette_.(string) + style.Palette = &palette + } + + if paletteFlip_, ok := s["palette_flip"]; ok { + paletteFlip, _ := strconv.ParseBool(paletteFlip_.(string)) + style.PaletteFlip = &paletteFlip + } + d.Definition.Style = &style + + } + + if groups, ok := t["group"]; ok { + for _, g := range groups.(*schema.Set).List() { + d.Definition.Groups = append(d.Definition.Groups, g.(string)) + } + } + + if includeNoMetricHosts, ok := t["include_no_metric_hosts"]; ok { + d.Definition.IncludeNoMetricHosts = includeNoMetricHosts.(bool) + } + + if scopes, ok := t["scope"]; ok { + for _, s := range scopes.(*schema.Set).List() { + d.Definition.Scopes = append(d.Definition.Groups, s.(string)) + } + } + + if includeUngroupedHosts, ok := t["include_ungrouped_hosts"]; ok { + d.Definition.IncludeUngroupedHosts = includeUngroupedHosts.(bool) + } + terraformMarkers := t["marker"].([]interface{}) + appendMarkers(d, &terraformMarkers) + + terraformEvents := t["events"].(*schema.Set).List() + appendEvents(d, &terraformEvents) + terraformRequests := t["request"].([]interface{}) appendRequests(d, &terraformRequests) } @@ -203,6 +530,115 @@ func resourceDatadogTimeboardUpdate(d *schema.ResourceData, meta interface{}) er return resourceDatadogTimeboardRead(d, meta) } +func appendTerraformGraphRequests(datadogRequests []datadog.GraphDefinitionRequest, requests *[]map[string]interface{}) { + for _, datadogRequest := range datadogRequests { + request := map[string]interface{}{} + request["q"] = datadogRequest.Query + request["stacked"] = datadogRequest.Stacked + request["type"] = datadogRequest.Type + if datadogRequest.Style != nil { + style := map[string]string{} + if datadogRequest.Style.Palette != nil { + style["palette"] = *datadogRequest.Style.Palette + } + if datadogRequest.Style.Type != nil { + style["type"] = *datadogRequest.Style.Type + } + if datadogRequest.Style.Width != nil { + style["width"] = *datadogRequest.Style.Width + } + request["style"] = style + } + conditionalFormats := []map[string]interface{}{} + for _, cf := range datadogRequest.ConditionalFormats { + conditionalFormat := map[string]interface{}{ + "palette": cf.Palette, + "comparator": cf.Comparator, + "custom_bg_color": cf.CustomBgColor, + "value": cf.Value, + "custom_fg_color": cf.CustomFgColor, + } + conditionalFormats = append(conditionalFormats, conditionalFormat) + } + request["conditional_format"] = conditionalFormats + request["change_type"] = datadogRequest.ChangeType + request["order_direction"] = datadogRequest.OrderDirection + request["compare_to"] = datadogRequest.CompareTo + request["increase_good"] = datadogRequest.IncreaseGood + request["order_by"] = datadogRequest.OrderBy + request["extra_col"] = datadogRequest.ExtraCol + + *requests = append(*requests, request) + } +} + +func buildTerraformGraph(datadog_graph datadog.Graph) map[string]interface{} { + graph := map[string]interface{}{} + graph["title"] = datadog_graph.Title + + definition := datadog_graph.Definition + graph["viz"] = definition.Viz + + events := []string{} + for _, datadog_event := range definition.Events { + events = append(events, datadog_event.Query) + } + graph["events"] = events + + markers := []map[string]interface{}{} + for _, datadog_marker := range definition.Markers { + marker := map[string]interface{}{ + "type": datadog_marker.Type, + "value": datadog_marker.Value, + "label": datadog_marker.Label, + } + markers = append(markers, marker) + } + graph["marker"] = markers + + yaxis := map[string]string{} + + if definition.Yaxis.Min != nil { + yaxis["min"] = strconv.FormatFloat(*definition.Yaxis.Min, 'f', -1, 64) + } + + if definition.Yaxis.Max != nil { + yaxis["max"] = strconv.FormatFloat(*definition.Yaxis.Max, 'f', -1, 64) + } + + if definition.Yaxis.Scale != nil { + yaxis["scale"] = *definition.Yaxis.Scale + } + + graph["yaxis"] = yaxis + + graph["autoscale"] = definition.Autoscale + graph["text_align"] = definition.TextAlign + graph["precision"] = definition.Precision + graph["custom_unit"] = definition.CustomUnit + + if definition.Style != nil { + style := map[string]string{} + if definition.Style.Palette != nil { + style["palette"] = *definition.Style.Palette + } + if definition.Style.PaletteFlip != nil { + style["palette_flip"] = strconv.FormatBool(*definition.Style.PaletteFlip) + } + graph["style"] = style + } + graph["group"] = definition.Groups + graph["include_no_metric_hosts"] = definition.IncludeNoMetricHosts + graph["scope"] = definition.Scopes + graph["include_ungrouped_hosts"] = definition.IncludeUngroupedHosts + + requests := []map[string]interface{}{} + appendTerraformGraphRequests(definition.Requests, &requests) + graph["request"] = requests + + return graph +} + func resourceDatadogTimeboardRead(d *schema.ResourceData, meta interface{}) error { id, err := strconv.Atoi(d.Id()) if err != nil { @@ -215,8 +651,24 @@ func resourceDatadogTimeboardRead(d *schema.ResourceData, meta interface{}) erro log.Printf("[DEBUG] timeboard: %v", timeboard) d.Set("title", timeboard.Title) d.Set("description", timeboard.Description) - d.Set("graphs", timeboard.Graphs) - d.Set("template_variables", timeboard.TemplateVariables) + + graphs := []map[string]interface{}{} + for _, datadog_graph := range timeboard.Graphs { + graphs = append(graphs, buildTerraformGraph(datadog_graph)) + } + d.Set("graph", graphs) + + templateVariables := []map[string]string{} + for _, templateVariable := range timeboard.TemplateVariables { + tv := map[string]string{ + "name": templateVariable.Name, + "prefix": templateVariable.Prefix, + "default": templateVariable.Default, + } + templateVariables = append(templateVariables, tv) + } + d.Set("template_variable", templateVariables) + return nil } @@ -231,6 +683,13 @@ func resourceDatadogTimeboardDelete(d *schema.ResourceData, meta interface{}) er return nil } +func resourceDatadogTimeboardImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + if err := resourceDatadogTimeboardRead(d, meta); err != nil { + return nil, err + } + return []*schema.ResourceData{d}, nil +} + func resourceDatadogTimeboardExists(d *schema.ResourceData, meta interface{}) (b bool, e error) { id, err := strconv.Atoi(d.Id()) if err != nil { diff --git a/builtin/providers/datadog/resource_datadog_timeboard_test.go b/builtin/providers/datadog/resource_datadog_timeboard_test.go index bd2dc7246..385eabbc0 100644 --- a/builtin/providers/datadog/resource_datadog_timeboard_test.go +++ b/builtin/providers/datadog/resource_datadog_timeboard_test.go @@ -14,7 +14,7 @@ import ( const config1 = ` resource "datadog_timeboard" "acceptance_test" { title = "Acceptance Test Timeboard" - description = "Created using the Datadog prodivider in Terraform" + description = "Created using the Datadog provider in Terraform" read_only = true graph { title = "Top System CPU by Docker container" @@ -29,7 +29,7 @@ resource "datadog_timeboard" "acceptance_test" { const config2 = ` resource "datadog_timeboard" "acceptance_test" { title = "Acceptance Test Timeboard" - description = "Created using the Datadog prodivider in Terraform" + description = "Created using the Datadog provider in Terraform" graph { title = "Redis latency (ms)" viz = "timeseries" @@ -62,6 +62,56 @@ resource "datadog_timeboard" "acceptance_test" { } ` +const config3 = ` +resource "datadog_timeboard" "acceptance_test" { + title = "Acceptance Test Timeboard" + description = "Created using the Datadog provider in Terraform" + graph { + title = "Redis latency (ms)" + viz = "timeseries" + request { + q = "avg:redis.info.latency_ms{$host}" + } + events = ["sources:capistrano"] + + marker { + label = "High Latency" + type = "error solid" + value = "y > 100" + } + yaxis { + max = "50" + scale = "sqrt" + } + } + graph { + title = "ELB Requests" + viz = "query_value" + request { + q = "sum:aws.elb.request_count{*}.as_count()" + type = "line" + conditional_format { + comparator = ">" + value = "1000" + palette = "white_on_red" + } + conditional_format { + comparator = "<=" + value = "1000" + palette = "white_on_green" + } + } + custom_unit = "hits" + precision = "*" + text_align = "left" + } + template_variable { + name = "host" + prefix = "host" + } +} +` + func TestAccDatadogTimeboard_update(t *testing.T) { step1 := resource.TestStep{ @@ -69,7 +119,7 @@ func TestAccDatadogTimeboard_update(t *testing.T) { Check: resource.ComposeTestCheckFunc( checkExists, resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "title", "Acceptance Test Timeboard"), - resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "description", "Created using the Datadog prodivider in Terraform"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "description", "Created using the Datadog provider in Terraform"), resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "read_only", "true"), resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.0.title", "Top System CPU by Docker container"), resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.0.viz", "toplist"), @@ -82,7 +132,7 @@ func TestAccDatadogTimeboard_update(t *testing.T) { Check: resource.ComposeTestCheckFunc( checkExists, resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "title", "Acceptance Test Timeboard"), - resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "description", "Created using the Datadog prodivider in Terraform"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "description", "Created using the Datadog provider in Terraform"), resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.0.title", "Redis latency (ms)"), resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.0.viz", "timeseries"), resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.0.request.0.q", "avg:redis.info.latency_ms{$host}"), @@ -98,11 +148,44 @@ func TestAccDatadogTimeboard_update(t *testing.T) { ), } + step3 := resource.TestStep{ + Config: config3, + Check: resource.ComposeTestCheckFunc( + checkExists, + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "title", "Acceptance Test Timeboard"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "description", "Created using the Datadog provider in Terraform"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.0.title", "Redis latency (ms)"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.0.viz", "timeseries"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.0.request.0.q", "avg:redis.info.latency_ms{$host}"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.0.events.#", "1"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.0.marker.0.label", "High Latency"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.0.marker.0.type", "error solid"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.0.marker.0.value", "y > 100"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.0.yaxis.max", "50"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.0.yaxis.scale", "sqrt"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.title", "ELB Requests"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.viz", "query_value"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.0.q", "sum:aws.elb.request_count{*}.as_count()"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.0.type", "line"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.0.conditional_format.0.comparator", ">"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.0.conditional_format.0.value", "1000"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.0.conditional_format.0.palette", "white_on_red"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.0.conditional_format.1.comparator", "<="), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.0.conditional_format.1.value", "1000"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.0.conditional_format.1.palette", "white_on_green"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.custom_unit", "hits"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.precision", "*"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.text_align", "left"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "template_variable.0.name", "host"), + resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "template_variable.0.prefix", "host"), + ), + } + resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: checkDestroy, - Steps: []resource.TestStep{step1, step2}, + Steps: []resource.TestStep{step1, step2, step3}, }) } diff --git a/vendor/github.com/zorkian/go-datadog-api/checks.go b/vendor/github.com/zorkian/go-datadog-api/checks.go index bfcf80a43..3e8bce786 100644 --- a/vendor/github.com/zorkian/go-datadog-api/checks.go +++ b/vendor/github.com/zorkian/go-datadog-api/checks.go @@ -3,16 +3,16 @@ package datadog type Check struct { Check string `json:"check"` HostName string `json:"host_name"` - Status status `json:"status"` + Status Status `json:"status"` Timestamp string `json:"timestamp,omitempty"` Message string `json:"message,omitempty"` Tags []string `json:"tags,omitempty"` } -type status int +type Status int const ( - OK status = iota + OK Status = iota WARNING CRITICAL UNKNOWN diff --git a/vendor/github.com/zorkian/go-datadog-api/dashboards.go b/vendor/github.com/zorkian/go-datadog-api/dashboards.go index 5da7332cf..82b2a783a 100644 --- a/vendor/github.com/zorkian/go-datadog-api/dashboards.go +++ b/vendor/github.com/zorkian/go-datadog-api/dashboards.go @@ -9,6 +9,7 @@ package datadog import ( + "encoding/json" "fmt" ) @@ -19,18 +20,63 @@ type GraphDefinitionRequest struct { Aggregator string ConditionalFormats []DashboardConditionalFormat `json:"conditional_formats,omitempty"` Type string `json:"type,omitempty"` - Style struct { - Palette string `json:"palette,omitempty"` + Style *struct { + Palette *string `json:"palette,omitempty"` + Width *string `json:"width,omitempty"` + Type *string `json:"type,omitempty"` } `json:"style,omitempty"` + + // For change type graphs + ChangeType string `json:"change_type,omitempty"` + OrderDirection string `json:"order_dir,omitempty"` + CompareTo string `json:"compare_to,omitempty"` + IncreaseGood bool `json:"increase_good,omitempty"` + OrderBy string `json:"order_by,omitempty"` + ExtraCol string `json:"extra_col,omitempty"` +} + +type GraphDefinitionMarker struct { + Type string `json:"type"` + Value string `json:"value"` + Label string `json:"label,omitempty"` + Val json.Number `json:"val,omitempty"` + Min json.Number `json:"min,omitempty"` + Max json.Number `json:"max,omitempty"` } // Graph represents a graph that might exist on a dashboard. type Graph struct { - Title string `json:"title"` - Events []struct{} `json:"events"` + Title string `json:"title"` Definition struct { Viz string `json:"viz"` Requests []GraphDefinitionRequest `json:"requests"` + Events []struct { + Query string `json:"q"` + } `json:"events"` + Markers []GraphDefinitionMarker `json:"markers,omitempty"` + + // For timeseries type graphs + Yaxis struct { + Min *float64 `json:"min,omitempty"` + Max *float64 `json:"max,omitempty"` + Scale *string `json:"scale,omitempty"` + } `json:"yaxis,omitempty"` + + // For query value type graphs + Autoscale bool `json:"austoscale,omitempty"` + TextAlign string `json:"text_align,omitempty"` + Precision string `json:"precision,omitempty"` + CustomUnit string `json:"custom_unit,omitempty"` + + // For hostnamp type graphs + Style *struct { + Palette *string `json:"palette,omitempty"` + PaletteFlip *bool `json:"paletteFlip,omitempty"` + } + Groups []string `json:"group,omitempty"` + IncludeNoMetricHosts bool `json:"noMetricHosts,omitempty"` + Scopes []string `json:"scope,omitempty"` + IncludeUngroupedHosts bool `json:"noGroupHosts,omitempty"` } `json:"definition"` } @@ -74,12 +120,12 @@ type reqGetDashboard struct { } type DashboardConditionalFormat struct { - Palette string `json:"palette,omitempty"` - Comparator string `json:"comparator,omitempty"` - CustomBgColor string `json:"custom_bg_color,omitempty"` - Value float64 `json:"value,omitempty"` - Inverted bool `json:"invert,omitempty"` - CustomFgColor string `json:"custom_fg_color,omitempty"` + Palette string `json:"palette,omitempty"` + Comparator string `json:"comparator,omitempty"` + CustomBgColor string `json:"custom_bg_color,omitempty"` + Value json.Number `json:"value,omitempty"` + Inverted bool `json:"invert,omitempty"` + CustomFgColor string `json:"custom_fg_color,omitempty"` } // GetDashboard returns a single dashboard created on this account. diff --git a/vendor/github.com/zorkian/go-datadog-api/events.go b/vendor/github.com/zorkian/go-datadog-api/events.go index 2278a120a..37121256a 100644 --- a/vendor/github.com/zorkian/go-datadog-api/events.go +++ b/vendor/github.com/zorkian/go-datadog-api/events.go @@ -25,10 +25,11 @@ type Event struct { AlertType string `json:"alert_type,omitempty"` Host string `json:"host,omitempty"` Aggregation string `json:"aggregation_key,omitempty"` - SourceType string `json:"source_type,omitempty"` + SourceType string `json:"source_type_name,omitempty"` Tags []string `json:"tags,omitempty"` Url string `json:"url,omitempty"` Resource string `json:"resource,omitempty"` + EventType string `json:"event_type,omitempty"` } // reqGetEvent is the container for receiving a single event. diff --git a/vendor/github.com/zorkian/go-datadog-api/integration/dashboards_test.go b/vendor/github.com/zorkian/go-datadog-api/integration/dashboards_test.go deleted file mode 100644 index 272a5e161..000000000 --- a/vendor/github.com/zorkian/go-datadog-api/integration/dashboards_test.go +++ /dev/null @@ -1,138 +0,0 @@ -package integration - -import ( - "github.com/zorkian/go-datadog-api" - "testing" -) - -func init() { - client = initTest() -} - -func TestCreateAndDeleteDashboard(t *testing.T) { - expected := getTestDashboard() - // create the dashboard and compare it - actual, err := client.CreateDashboard(expected) - if err != nil { - t.Fatalf("Creating a dashboard failed when it shouldn't. (%s)", err) - } - - defer cleanUpDashboard(t, actual.Id) - - assertDashboardEquals(t, actual, expected) - - // now try to fetch it freshly and compare it again - actual, err = client.GetDashboard(actual.Id) - if err != nil { - t.Fatalf("Retrieving a dashboard failed when it shouldn't. (%s)", err) - } - assertDashboardEquals(t, actual, expected) - -} - -func TestUpdateDashboard(t *testing.T) { - expected := getTestDashboard() - board, err := client.CreateDashboard(expected) - if err != nil { - t.Fatalf("Creating a dashboard failed when it shouldn't. (%s)", err) - } - - defer cleanUpDashboard(t, board.Id) - board.Title = "___New-Test-Board___" - - if err := client.UpdateDashboard(board); err != nil { - t.Fatalf("Updating a dashboard failed when it shouldn't: %s", err) - } - - actual, err := client.GetDashboard(board.Id) - if err != nil { - t.Fatalf("Retrieving a dashboard failed when it shouldn't: %s", err) - } - - assertDashboardEquals(t, actual, board) -} - -func TestGetDashboards(t *testing.T) { - boards, err := client.GetDashboards() - if err != nil { - t.Fatalf("Retrieving dashboards failed when it shouldn't: %s", err) - } - - num := len(boards) - board := createTestDashboard(t) - defer cleanUpDashboard(t, board.Id) - - boards, err = client.GetDashboards() - if err != nil { - t.Fatalf("Retrieving dashboards failed when it shouldn't: %s", err) - } - - if num+1 != len(boards) { - t.Fatalf("Number of dashboards didn't match expected: %d != %d", len(boards), num+1) - } -} - -func getTestDashboard() *datadog.Dashboard { - return &datadog.Dashboard{ - Title: "___Test-Board___", - Description: "Testboard description", - TemplateVariables: []datadog.TemplateVariable{}, - Graphs: createGraph(), - } -} - -func createTestDashboard(t *testing.T) *datadog.Dashboard { - board := getTestDashboard() - board, err := client.CreateDashboard(board) - if err != nil { - t.Fatalf("Creating a dashboard failed when it shouldn't: %s", err) - } - - return board -} - -func cleanUpDashboard(t *testing.T, id int) { - if err := client.DeleteDashboard(id); err != nil { - t.Fatalf("Deleting a dashboard failed when it shouldn't. Manual cleanup needed. (%s)", err) - } - - deletedBoard, err := client.GetDashboard(id) - if deletedBoard != nil { - t.Fatal("Dashboard hasn't been deleted when it should have been. Manual cleanup needed.") - } - - if err == nil { - t.Fatal("Fetching deleted dashboard didn't lead to an error. Manual cleanup needed.") - } -} - -type TestGraphDefintionRequests struct { - Query string `json:"q"` - Stacked bool `json:"stacked"` -} - -func createGraph() []datadog.Graph { - graphDefinition := datadog.Graph{}.Definition - graphDefinition.Viz = "timeseries" - r := datadog.Graph{}.Definition.Requests - graphDefinition.Requests = append(r, TestGraphDefintionRequests{Query: "avg:system.mem.free{*}", Stacked: false}) - graph := datadog.Graph{Title: "Mandatory graph", Definition: graphDefinition} - graphs := []datadog.Graph{} - graphs = append(graphs, graph) - return graphs -} - -func assertDashboardEquals(t *testing.T, actual, expected *datadog.Dashboard) { - if actual.Title != expected.Title { - t.Errorf("Dashboard title does not match: %s != %s", actual.Title, expected.Title) - } - if actual.Description != expected.Description { - t.Errorf("Dashboard description does not match: %s != %s", actual.Description, expected.Description) - } - if len(actual.Graphs) != len(expected.Graphs) { - t.Errorf("Number of Dashboard graphs does not match: %d != %d", len(actual.Graphs), len(expected.Graphs)) - } - if len(actual.TemplateVariables) != len(expected.TemplateVariables) { - t.Errorf("Number of Dashboard template variables does not match: %d != %d", len(actual.TemplateVariables), len(expected.TemplateVariables)) - } -} diff --git a/vendor/github.com/zorkian/go-datadog-api/integration/downtime_test.go b/vendor/github.com/zorkian/go-datadog-api/integration/downtime_test.go deleted file mode 100644 index 026cd5857..000000000 --- a/vendor/github.com/zorkian/go-datadog-api/integration/downtime_test.go +++ /dev/null @@ -1,110 +0,0 @@ -package integration - -import ( - "github.com/stretchr/testify/assert" - "github.com/zorkian/go-datadog-api" - "testing" -) - -func init() { - client = initTest() -} - -func TestCreateAndDeleteDowntime(t *testing.T) { - expected := getTestDowntime() - // create the downtime and compare it - actual := createTestDowntime(t) - defer cleanUpDowntime(t, actual.Id) - - // Set ID of our original struct to zero we we can easily compare the results - expected.Id = actual.Id - assert.Equal(t, expected, actual) - - actual, err := client.GetDowntime(actual.Id) - if err != nil { - t.Fatalf("Retrieving a downtime failed when it shouldn't: (%s)", err) - } - assert.Equal(t, expected, actual) -} - -func TestUpdateDowntime(t *testing.T) { - - downtime := createTestDowntime(t) - - downtime.Scope = []string{"env:downtime_test", "env:downtime_test2"} - defer cleanUpDowntime(t, downtime.Id) - - if err := client.UpdateDowntime(downtime); err != nil { - t.Fatalf("Updating a downtime failed when it shouldn't: %s", err) - } - - actual, err := client.GetDowntime(downtime.Id) - if err != nil { - t.Fatalf("Retrieving a downtime failed when it shouldn't: %s", err) - } - - assert.Equal(t, downtime, actual) - -} - -func TestGetDowntime(t *testing.T) { - downtimes, err := client.GetDowntimes() - if err != nil { - t.Fatalf("Retrieving downtimes failed when it shouldn't: %s", err) - } - num := len(downtimes) - - downtime := createTestDowntime(t) - defer cleanUpDowntime(t, downtime.Id) - - downtimes, err = client.GetDowntimes() - if err != nil { - t.Fatalf("Retrieving downtimes failed when it shouldn't: %s", err) - } - - if num+1 != len(downtimes) { - t.Fatalf("Number of downtimes didn't match expected: %d != %d", len(downtimes), num+1) - } -} - -func getTestDowntime() *datadog.Downtime { - - r := &datadog.Recurrence{ - Type: "weeks", - Period: 1, - WeekDays: []string{"Mon", "Tue", "Wed", "Thu", "Fri"}, - } - - return &datadog.Downtime{ - Message: "Test downtime message", - Scope: []string{"env:downtime_test"}, - Start: 1577836800, - End: 1577840400, - Recurrence: r, - } -} - -func createTestDowntime(t *testing.T) *datadog.Downtime { - downtime := getTestDowntime() - downtime, err := client.CreateDowntime(downtime) - if err != nil { - t.Fatalf("Creating a downtime failed when it shouldn't: %s", err) - } - - return downtime -} - -func cleanUpDowntime(t *testing.T, id int) { - if err := client.DeleteDowntime(id); err != nil { - t.Fatalf("Deleting a downtime failed when it shouldn't. Manual cleanup needed. (%s)", err) - } - - deletedDowntime, err := client.GetDowntime(id) - if deletedDowntime != nil && deletedDowntime.Canceled == 0 { - t.Fatal("Downtime hasn't been deleted when it should have been. Manual cleanup needed.") - } - - if err == nil && deletedDowntime.Canceled == 0 { - t.Fatal("Fetching deleted downtime didn't lead to an error and downtime Canceled not set.") - } -} diff --git a/vendor/github.com/zorkian/go-datadog-api/integration/monitors_test.go b/vendor/github.com/zorkian/go-datadog-api/integration/monitors_test.go deleted file mode 100644 index 527fc63fa..000000000 --- a/vendor/github.com/zorkian/go-datadog-api/integration/monitors_test.go +++ /dev/null @@ -1,152 +0,0 @@ -package integration - -import ( - "github.com/stretchr/testify/assert" - "github.com/zorkian/go-datadog-api" - "testing" -) - -func init() { - client = initTest() -} - -func TestCreateAndDeleteMonitor(t *testing.T) { - expected := getTestMonitor() - // create the monitor and compare it - actual := createTestMonitor(t) - defer cleanUpMonitor(t, actual.Id) - - // Set ID of our original struct to zero we we can easily compare the results - expected.Id = actual.Id - assert.Equal(t, expected, actual) - - actual, err := client.GetMonitor(actual.Id) - if err != nil { - t.Fatalf("Retrieving a monitor failed when it shouldn't: (%s)", err) - } - assert.Equal(t, expected, actual) -} - -func TestUpdateMonitor(t *testing.T) { - - monitor := createTestMonitor(t) - defer cleanUpMonitor(t, monitor.Id) - - monitor.Name = "___New-Test-Monitor___" - if err := client.UpdateMonitor(monitor); err != nil { - t.Fatalf("Updating a monitor failed when it shouldn't: %s", err) - } - - actual, err := client.GetMonitor(monitor.Id) - if err != nil { - t.Fatalf("Retrieving a monitor failed when it shouldn't: %s", err) - } - - assert.Equal(t, monitor, actual) - -} - -func TestGetMonitor(t *testing.T) { - monitors, err := client.GetMonitors() - if err != nil { - t.Fatalf("Retrieving monitors failed when it shouldn't: %s", err) - } - num := len(monitors) - - monitor := createTestMonitor(t) - defer cleanUpMonitor(t, monitor.Id) - - monitors, err = client.GetMonitors() - if err != nil { - t.Fatalf("Retrieving monitors failed when it shouldn't: %s", err) - } - - if num+1 != len(monitors) { - t.Fatalf("Number of monitors didn't match expected: %d != %d", len(monitors), num+1) - } -} - -func TestMuteUnmuteMonitor(t *testing.T) { - monitor := createTestMonitor(t) - defer cleanUpMonitor(t, monitor.Id) - - // Mute - err := client.MuteMonitor(monitor.Id) - if err != nil { - t.Fatalf("Failed to mute monitor") - - } - - monitor, err = client.GetMonitor(monitor.Id) - if err != nil { - t.Fatalf("Retrieving monitors failed when it shouldn't: %s", err) - } - - // Mute without options will result in monitor.Options.Silenced - // to have a key of "*" with value 0 - assert.Equal(t, 0, monitor.Options.Silenced["*"]) - - // Unmute - err = client.UnmuteMonitor(monitor.Id) - if err != nil { - t.Fatalf("Failed to unmute monitor") - } - - // Update remote state - monitor, err = client.GetMonitor(monitor.Id) - if err != nil { - t.Fatalf("Retrieving monitors failed when it shouldn't: %s", err) - } - - // Assert this map is empty - assert.Equal(t, 0, len(monitor.Options.Silenced)) -} - -/* - Testing of global mute and unmuting has not been added for following reasons: - * Disabling and enabling of global monitoring does an @all mention which is noisy - * It exposes risk to users that run integration tests in their main account - * There is no endpoint to verify success -*/ - -func getTestMonitor() *datadog.Monitor { - - o := datadog.Options{ - NotifyNoData: true, - NoDataTimeframe: 60, - Silenced: map[string]int{}, - } - - return &datadog.Monitor{ - Message: "Test message", - Query: "avg(last_15m):avg:system.disk.in_use{*} by {host,device} > 0.8", - Name: "Test monitor", - Options: o, - Type: "metric alert", - } -} - -func createTestMonitor(t *testing.T) *datadog.Monitor { - monitor := getTestMonitor() - monitor, err := client.CreateMonitor(monitor) - if err != nil { - t.Fatalf("Creating a monitor failed when it shouldn't: %s", err) - } - - return monitor -} - -func cleanUpMonitor(t *testing.T, id int) { - if err := client.DeleteMonitor(id); err != nil { - t.Fatalf("Deleting a monitor failed when it shouldn't. Manual cleanup needed. (%s)", err) - } - - deletedMonitor, err := client.GetMonitor(id) - if deletedMonitor != nil { - t.Fatal("Monitor hasn't been deleted when it should have been. Manual cleanup needed.") - } - - if err == nil { - t.Fatal("Fetching deleted monitor didn't lead to an error.") - } -} diff --git a/vendor/github.com/zorkian/go-datadog-api/integration/screen_widgets_test.go b/vendor/github.com/zorkian/go-datadog-api/integration/screen_widgets_test.go deleted file mode 100644 index 6611ab090..000000000 --- a/vendor/github.com/zorkian/go-datadog-api/integration/screen_widgets_test.go +++ /dev/null @@ -1,766 +0,0 @@ -package integration - -import ( - "testing" - - "github.com/zorkian/go-datadog-api" -) - -func TestAlertValueWidget(t *testing.T) { - board := createTestScreenboard(t) - defer cleanUpScreenboard(t, board.Id) - - expected := datadog.Widget{}.AlertValueWidget - - expected.X = 1 - expected.Y = 1 - expected.Width = 5 - expected.Height = 5 - expected.TitleText = "foo" - expected.TitleAlign = "center" - expected.TitleSize = 1 - expected.Title = true - expected.TextSize = "auto" - expected.Precision = 2 - expected.AlertId = 1 - expected.Type = "alert_value" - expected.Unit = "auto" - expected.AddTimeframe = false - - w := datadog.Widget{AlertValueWidget: expected} - - board.Widgets = append(board.Widgets, w) - - if err := client.UpdateScreenboard(board); err != nil { - t.Fatalf("Updating a screenboard failed: %s", err) - } - - actual, err := client.GetScreenboard(board.Id) - if err != nil { - t.Fatalf("Retrieving a screenboard failed: %s", err) - } - - actualWidget := actual.Widgets[0].AlertValueWidget - - assertEquals(t, "x", actualWidget.X, expected.X) - assertEquals(t, "y", actualWidget.Y, expected.Y) - assertEquals(t, "height", actualWidget.Height, expected.Height) - assertEquals(t, "width", actualWidget.Width, expected.Width) - assertEquals(t, "title_text", actualWidget.TitleText, expected.TitleText) - assertEquals(t, "title_size", actualWidget.TitleSize, expected.TitleSize) - assertEquals(t, "title_align", actualWidget.TitleAlign, expected.TitleAlign) - assertEquals(t, "title", actualWidget.Title, expected.Title) - assertEquals(t, "text_size", actualWidget.TextSize, expected.TextSize) - assertEquals(t, "precision", actualWidget.Precision, expected.Precision) - assertEquals(t, "alert_id", actualWidget.AlertId, expected.AlertId) - assertEquals(t, "type", actualWidget.Type, expected.Type) - assertEquals(t, "unit", actualWidget.Unit, expected.Unit) - assertEquals(t, "add_timeframe", actualWidget.AddTimeframe, expected.AddTimeframe) -} - -func TestChangeWidget(t *testing.T) { - board := createTestScreenboard(t) - defer cleanUpScreenboard(t, board.Id) - - expected := datadog.Widget{}.ChangeWidget - - expected.X = 1 - expected.Y = 1 - expected.Width = 5 - expected.Height = 5 - expected.TitleText = "foo" - expected.TitleAlign = "center" - expected.TitleSize = 1 - expected.Title = true - expected.Aggregator = "min" - expected.TileDef = datadog.TileDef{} - - w := datadog.Widget{ChangeWidget: expected} - - board.Widgets = append(board.Widgets, w) - - if err := client.UpdateScreenboard(board); err != nil { - t.Fatalf("Updating a screenboard failed: %s", err) - } - - actual, err := client.GetScreenboard(board.Id) - if err != nil { - t.Fatalf("Retrieving a screenboard failed: %s", err) - } - - actualWidget := actual.Widgets[0].ChangeWidget - - assertEquals(t, "x", actualWidget.X, expected.X) - assertEquals(t, "y", actualWidget.Y, expected.Y) - assertEquals(t, "height", actualWidget.Height, expected.Height) - assertEquals(t, "width", actualWidget.Width, expected.Width) - assertEquals(t, "title_text", actualWidget.TitleText, expected.TitleText) - assertEquals(t, "title_size", actualWidget.TitleSize, expected.TitleSize) - assertEquals(t, "title_align", actualWidget.TitleAlign, expected.TitleAlign) - assertEquals(t, "title", actualWidget.Title, expected.Title) - assertEquals(t, "aggregator", actualWidget.Aggregator, expected.Aggregator) - assertTileDefEquals(t, actualWidget.TileDef, expected.TileDef) -} - -func TestGraphWidget(t *testing.T) { - board := createTestScreenboard(t) - defer cleanUpScreenboard(t, board.Id) - - expected := datadog.Widget{}.GraphWidget - - expected.X = 1 - expected.Y = 1 - expected.Width = 5 - expected.Height = 5 - expected.TitleText = "foo" - expected.TitleAlign = "center" - expected.TitleSize = 1 - expected.Title = true - expected.Timeframe = "1d" - expected.Type = "alert_graph" - expected.Legend = true - expected.LegendSize = 5 - expected.TileDef = datadog.TileDef{} - - w := datadog.Widget{GraphWidget: expected} - - board.Widgets = append(board.Widgets, w) - - if err := client.UpdateScreenboard(board); err != nil { - t.Fatalf("Updating a screenboard failed: %s", err) - } - - actual, err := client.GetScreenboard(board.Id) - if err != nil { - t.Fatalf("Retrieving a screenboard failed: %s", err) - } - - actualWidget := actual.Widgets[0].GraphWidget - - assertEquals(t, "x", actualWidget.X, expected.X) - assertEquals(t, "y", actualWidget.Y, expected.Y) - assertEquals(t, "height", actualWidget.Height, expected.Height) - assertEquals(t, "width", actualWidget.Width, expected.Width) - assertEquals(t, "title_text", actualWidget.TitleText, expected.TitleText) - assertEquals(t, "title_size", actualWidget.TitleSize, expected.TitleSize) - assertEquals(t, "title_align", actualWidget.TitleAlign, expected.TitleAlign) - assertEquals(t, "title", actualWidget.Title, expected.Title) - assertEquals(t, "type", actualWidget.Type, expected.Type) - assertEquals(t, "timeframe", actualWidget.Timeframe, expected.Timeframe) - assertEquals(t, "legend", actualWidget.Legend, expected.Legend) - assertEquals(t, "legend_size", actualWidget.LegendSize, expected.LegendSize) - assertTileDefEquals(t, actualWidget.TileDef, expected.TileDef) -} - -func TestEventTimelineWidget(t *testing.T) { - board := createTestScreenboard(t) - defer cleanUpScreenboard(t, board.Id) - - expected := datadog.Widget{}.EventTimelineWidget - - expected.X = 1 - expected.Y = 1 - expected.Width = 5 - expected.Height = 5 - expected.TitleText = "foo" - expected.TitleAlign = "center" - expected.TitleSize = 1 - expected.Title = true - expected.Query = "avg:system.load.1{foo} by {bar}" - expected.Timeframe = "1d" - expected.Type = "alert_graph" - - w := datadog.Widget{EventTimelineWidget: expected} - - board.Widgets = append(board.Widgets, w) - - if err := client.UpdateScreenboard(board); err != nil { - t.Fatalf("Updating a screenboard failed: %s", err) - } - - actual, err := client.GetScreenboard(board.Id) - if err != nil { - t.Fatalf("Retrieving a screenboard failed: %s", err) - } - - actualWidget := actual.Widgets[0].EventTimelineWidget - - assertEquals(t, "x", actualWidget.X, expected.X) - assertEquals(t, "y", actualWidget.Y, expected.Y) - assertEquals(t, "height", actualWidget.Height, expected.Height) - assertEquals(t, "width", actualWidget.Width, expected.Width) - assertEquals(t, "title_text", actualWidget.TitleText, expected.TitleText) - assertEquals(t, "title_size", actualWidget.TitleSize, expected.TitleSize) - assertEquals(t, "title_align", actualWidget.TitleAlign, expected.TitleAlign) - assertEquals(t, "title", actualWidget.Title, expected.Title) - assertEquals(t, "type", actualWidget.Type, expected.Type) - assertEquals(t, "query", actualWidget.Query, expected.Query) - assertEquals(t, "timeframe", actualWidget.Timeframe, expected.Timeframe) -} - -func TestAlertGraphWidget(t *testing.T) { - board := createTestScreenboard(t) - defer cleanUpScreenboard(t, board.Id) - - expected := datadog.Widget{}.AlertGraphWidget - - expected.X = 1 - expected.Y = 1 - expected.Width = 5 - expected.Height = 5 - expected.TitleText = "foo" - expected.TitleAlign = "center" - expected.TitleSize = 1 - expected.Title = true - expected.VizType = "" - expected.Timeframe = "1d" - expected.AddTimeframe = false - expected.AlertId = 1 - expected.Type = "alert_graph" - - w := datadog.Widget{AlertGraphWidget: expected} - - board.Widgets = append(board.Widgets, w) - - if err := client.UpdateScreenboard(board); err != nil { - t.Fatalf("Updating a screenboard failed: %s", err) - } - - actual, err := client.GetScreenboard(board.Id) - if err != nil { - t.Fatalf("Retrieving a screenboard failed: %s", err) - } - - actualWidget := actual.Widgets[0].AlertGraphWidget - - assertEquals(t, "x", actualWidget.X, expected.X) - assertEquals(t, "y", actualWidget.Y, expected.Y) - assertEquals(t, "height", actualWidget.Height, expected.Height) - assertEquals(t, "width", actualWidget.Width, expected.Width) - assertEquals(t, "title_text", actualWidget.TitleText, expected.TitleText) - assertEquals(t, "title_size", actualWidget.TitleSize, expected.TitleSize) - assertEquals(t, "title_align", actualWidget.TitleAlign, expected.TitleAlign) - assertEquals(t, "title", actualWidget.Title, expected.Title) - assertEquals(t, "type", actualWidget.Type, expected.Type) - assertEquals(t, "viz_type", actualWidget.VizType, expected.VizType) - assertEquals(t, "timeframe", actualWidget.Timeframe, expected.Timeframe) - assertEquals(t, "add_timeframe", actualWidget.AddTimeframe, expected.AddTimeframe) - assertEquals(t, "alert_id", actualWidget.AlertId, expected.AlertId) -} - -func TestHostMapWidget(t *testing.T) { - board := createTestScreenboard(t) - defer cleanUpScreenboard(t, board.Id) - - expected := datadog.Widget{}.HostMapWidget - - expected.X = 1 - expected.Y = 1 - expected.Width = 5 - expected.Height = 5 - expected.TitleText = "foo" - expected.TitleAlign = "center" - expected.TitleSize = 1 - expected.Title = true - expected.Type = "check_status" - expected.Query = "avg:system.load.1{foo} by {bar}" - expected.Timeframe = "1d" - expected.Legend = true - expected.LegendSize = 5 - expected.TileDef = datadog.TileDef{} - - w := datadog.Widget{HostMapWidget: expected} - - board.Widgets = append(board.Widgets, w) - - if err := client.UpdateScreenboard(board); err != nil { - t.Fatalf("Updating a screenboard failed: %s", err) - } - - actual, err := client.GetScreenboard(board.Id) - if err != nil { - t.Fatalf("Retrieving a screenboard failed: %s", err) - } - - actualWidget := actual.Widgets[0].HostMapWidget - - assertEquals(t, "x", actualWidget.X, expected.X) - assertEquals(t, "y", actualWidget.Y, expected.Y) - assertEquals(t, "height", actualWidget.Height, expected.Height) - assertEquals(t, "width", actualWidget.Width, expected.Width) - assertEquals(t, "title_text", actualWidget.TitleText, expected.TitleText) - assertEquals(t, "title_size", actualWidget.TitleSize, expected.TitleSize) - assertEquals(t, "title_align", actualWidget.TitleAlign, expected.TitleAlign) - assertEquals(t, "title", actualWidget.Title, expected.Title) - assertEquals(t, "type", actualWidget.Type, expected.Type) - assertEquals(t, "query", actualWidget.Query, expected.Query) - assertEquals(t, "timeframe", actualWidget.Timeframe, expected.Timeframe) - assertEquals(t, "query", actualWidget.Query, expected.Query) - assertEquals(t, "legend", actualWidget.Legend, expected.Legend) - assertEquals(t, "legend_size", actualWidget.LegendSize, expected.LegendSize) - assertTileDefEquals(t, actualWidget.TileDef, expected.TileDef) -} - -func TestCheckStatusWidget(t *testing.T) { - board := createTestScreenboard(t) - defer cleanUpScreenboard(t, board.Id) - - expected := datadog.Widget{}.CheckStatusWidget - - expected.X = 1 - expected.Y = 1 - expected.Width = 5 - expected.Height = 5 - expected.TitleText = "foo" - expected.TitleAlign = "center" - expected.TitleSize = 1 - expected.Title = true - expected.Type = "check_status" - expected.Tags = "foo" - expected.Timeframe = "1d" - expected.Timeframe = "1d" - expected.Check = "datadog.agent.up" - expected.Group = "foo" - expected.Grouping = "check" - - w := datadog.Widget{CheckStatusWidget: expected} - - board.Widgets = append(board.Widgets, w) - - if err := client.UpdateScreenboard(board); err != nil { - t.Fatalf("Updating a screenboard failed: %s", err) - } - - actual, err := client.GetScreenboard(board.Id) - if err != nil { - t.Fatalf("Retrieving a screenboard failed: %s", err) - } - - actualWidget := actual.Widgets[0].CheckStatusWidget - - assertEquals(t, "x", actualWidget.X, expected.X) - assertEquals(t, "y", actualWidget.Y, expected.Y) - assertEquals(t, "height", actualWidget.Height, expected.Height) - assertEquals(t, "width", actualWidget.Width, expected.Width) - assertEquals(t, "title_text", actualWidget.TitleText, expected.TitleText) - assertEquals(t, "title_size", actualWidget.TitleSize, expected.TitleSize) - assertEquals(t, "title_align", actualWidget.TitleAlign, expected.TitleAlign) - assertEquals(t, "title", actualWidget.Title, expected.Title) - assertEquals(t, "type", actualWidget.Type, expected.Type) - assertEquals(t, "tags", actualWidget.Tags, expected.Tags) - assertEquals(t, "timeframe", actualWidget.Timeframe, expected.Timeframe) - assertEquals(t, "check", actualWidget.Check, expected.Check) - assertEquals(t, "group", actualWidget.Group, expected.Group) - assertEquals(t, "grouping", actualWidget.Grouping, expected.Grouping) -} - -func TestIFrameWidget(t *testing.T) { - board := createTestScreenboard(t) - defer cleanUpScreenboard(t, board.Id) - - expected := datadog.Widget{}.IFrameWidget - - expected.X = 1 - expected.Y = 1 - expected.Width = 5 - expected.Height = 5 - expected.TitleText = "foo" - expected.TitleAlign = "center" - expected.TitleSize = 1 - expected.Title = true - expected.Url = "http://www.example.com" - expected.Type = "iframe" - - w := datadog.Widget{IFrameWidget: expected} - - board.Widgets = append(board.Widgets, w) - - if err := client.UpdateScreenboard(board); err != nil { - t.Fatalf("Updating a screenboard failed: %s", err) - } - - actual, err := client.GetScreenboard(board.Id) - if err != nil { - t.Fatalf("Retrieving a screenboard failed: %s", err) - } - - actualWidget := actual.Widgets[0].IFrameWidget - - assertEquals(t, "x", actualWidget.X, expected.X) - assertEquals(t, "y", actualWidget.Y, expected.Y) - assertEquals(t, "height", actualWidget.Height, expected.Height) - assertEquals(t, "width", actualWidget.Width, expected.Width) - assertEquals(t, "title_text", actualWidget.TitleText, expected.TitleText) - assertEquals(t, "title_size", actualWidget.TitleSize, expected.TitleSize) - assertEquals(t, "title_align", actualWidget.TitleAlign, expected.TitleAlign) - assertEquals(t, "title", actualWidget.Title, expected.Title) - assertEquals(t, "url", actualWidget.Url, expected.Url) - assertEquals(t, "type", actualWidget.Type, expected.Type) -} - -func TestNoteWidget(t *testing.T) { - board := createTestScreenboard(t) - defer cleanUpScreenboard(t, board.Id) - - expected := datadog.Widget{}.NoteWidget - - expected.X = 1 - expected.Y = 1 - expected.Width = 5 - expected.Height = 5 - expected.TitleText = "foo" - expected.TitleAlign = "center" - expected.TitleSize = 1 - expected.Title = true - expected.Color = "green" - expected.FontSize = 5 - expected.RefreshEvery = 60 - expected.TickPos = "foo" - expected.TickEdge = "bar" - expected.Html = "baz" - expected.Tick = false - expected.Note = "quz" - expected.AutoRefresh = false - - w := datadog.Widget{NoteWidget: expected} - - board.Widgets = append(board.Widgets, w) - - if err := client.UpdateScreenboard(board); err != nil { - t.Fatalf("Updating a screenboard failed: %s", err) - } - - actual, err := client.GetScreenboard(board.Id) - if err != nil { - t.Fatalf("Retrieving a screenboard failed: %s", err) - } - - actualWidget := actual.Widgets[0].NoteWidget - - assertEquals(t, "x", actualWidget.X, expected.X) - assertEquals(t, "y", actualWidget.Y, expected.Y) - assertEquals(t, "height", actualWidget.Height, expected.Height) - assertEquals(t, "width", actualWidget.Width, expected.Width) - assertEquals(t, "title_text", actualWidget.TitleText, expected.TitleText) - assertEquals(t, "title_size", actualWidget.TitleSize, expected.TitleSize) - assertEquals(t, "title_align", actualWidget.TitleAlign, expected.TitleAlign) - assertEquals(t, "title", actualWidget.Title, expected.Title) - assertEquals(t, "color", actualWidget.Color, expected.Color) - assertEquals(t, "front_size", actualWidget.FontSize, expected.FontSize) - assertEquals(t, "refresh_every", actualWidget.RefreshEvery, expected.RefreshEvery) - assertEquals(t, "tick_pos", actualWidget.TickPos, expected.TickPos) - assertEquals(t, "tick_edge", actualWidget.TickEdge, expected.TickEdge) - assertEquals(t, "tick", actualWidget.Tick, expected.Tick) - assertEquals(t, "html", actualWidget.Html, expected.Html) - assertEquals(t, "note", actualWidget.Note, expected.Note) - assertEquals(t, "auto_refresh", actualWidget.AutoRefresh, expected.AutoRefresh) -} - -func TestToplistWidget(t *testing.T) { - board := createTestScreenboard(t) - defer cleanUpScreenboard(t, board.Id) - - expected := datadog.Widget{}.ToplistWidget - expected.X = 1 - expected.Y = 1 - expected.Width = 5 - expected.Height = 5 - expected.Type = "toplist" - expected.TitleText = "foo" - expected.TitleSize.Auto = false - expected.TitleSize.Size = 5 - expected.TitleAlign = "center" - expected.Title = false - expected.Timeframe = "5m" - expected.Legend = false - expected.LegendSize = 5 - - w := datadog.Widget{ToplistWidget: expected} - - board.Widgets = append(board.Widgets, w) - - if err := client.UpdateScreenboard(board); err != nil { - t.Fatalf("Updating a screenboard failed: %s", err) - } - - actual, err := client.GetScreenboard(board.Id) - if err != nil { - t.Fatalf("Retrieving a screenboard failed: %s", err) - } - - actualWidget := actual.Widgets[0].ToplistWidget - - assertEquals(t, "x", actualWidget.X, expected.X) - assertEquals(t, "y", actualWidget.Y, expected.Y) - assertEquals(t, "height", actualWidget.Height, expected.Height) - assertEquals(t, "width", actualWidget.Width, expected.Width) - assertEquals(t, "title_text", actualWidget.TitleText, expected.TitleText) - assertEquals(t, "title_size", actualWidget.TitleSize, expected.TitleSize) - assertEquals(t, "title_align", actualWidget.TitleAlign, expected.TitleAlign) - assertEquals(t, "legend", actualWidget.Legend, expected.Legend) - assertEquals(t, "legend_size", actualWidget.LegendSize, expected.LegendSize) -} - -func TestEventSteamWidget(t *testing.T) { - board := createTestScreenboard(t) - defer cleanUpScreenboard(t, board.Id) - - expected := datadog.Widget{}.EventStreamWidget - expected.EventSize = "1" - expected.Width = 1 - expected.Height = 1 - expected.X = 1 - expected.Y = 1 - expected.Query = "foo" - expected.Timeframe = "5w" - expected.Title = false - expected.TitleAlign = "center" - expected.TitleSize.Auto = false - expected.TitleSize.Size = 5 - expected.TitleText = "bar" - expected.Type = "baz" - - w := datadog.Widget{EventStreamWidget: expected} - - board.Widgets = append(board.Widgets, w) - - if err := client.UpdateScreenboard(board); err != nil { - t.Fatalf("Updating a screenboard failed: %s", err) - } - - actual, err := client.GetScreenboard(board.Id) - if err != nil { - t.Fatalf("Retrieving a screenboard failed: %s", err) - } - - actualWidget := actual.Widgets[0].EventStreamWidget - - assertEquals(t, "event_size", actualWidget.EventSize, expected.EventSize) - assertEquals(t, "width", actualWidget.Width, expected.Width) - assertEquals(t, "height", actualWidget.Height, expected.Height) - assertEquals(t, "x", actualWidget.X, expected.X) - assertEquals(t, "y", actualWidget.Y, expected.Y) - assertEquals(t, "query", actualWidget.Query, expected.Query) - assertEquals(t, "timeframe", actualWidget.Timeframe, expected.Timeframe) - assertEquals(t, "title", actualWidget.Title, expected.Title) - assertEquals(t, "title_align", actualWidget.TitleAlign, expected.TitleAlign) - assertEquals(t, "title_size", actualWidget.TitleSize, expected.TitleSize) - assertEquals(t, "title_text", actualWidget.TitleText, expected.TitleText) - assertEquals(t, "type", actualWidget.Type, expected.Type) -} - -func TestImageWidget(t *testing.T) { - board := createTestScreenboard(t) - defer cleanUpScreenboard(t, board.Id) - - expected := datadog.Widget{}.ImageWidget - - expected.Width = 1 - expected.Height = 1 - expected.X = 1 - expected.Y = 1 - expected.Title = false - expected.TitleAlign = "center" - expected.TitleSize.Auto = false - expected.TitleSize.Size = 5 - expected.TitleText = "bar" - expected.Type = "baz" - expected.Url = "qux" - expected.Sizing = "quuz" - - w := datadog.Widget{ImageWidget: expected} - - board.Widgets = append(board.Widgets, w) - - if err := client.UpdateScreenboard(board); err != nil { - t.Fatalf("Updating a screenboard failed: %s", err) - } - - actual, err := client.GetScreenboard(board.Id) - if err != nil { - t.Fatalf("Retrieving a screenboard failed: %s", err) - } - - actualWidget := actual.Widgets[0].ImageWidget - - assertEquals(t, "width", actualWidget.Width, expected.Width) - assertEquals(t, "height", actualWidget.Height, expected.Height) - assertEquals(t, "x", actualWidget.X, expected.X) - assertEquals(t, "y", actualWidget.Y, expected.Y) - assertEquals(t, "title", actualWidget.Title, expected.Title) - assertEquals(t, "title_align", actualWidget.TitleAlign, expected.TitleAlign) - assertEquals(t, "title_size", actualWidget.TitleSize, expected.TitleSize) - assertEquals(t, "title_text", actualWidget.TitleText, expected.TitleText) - assertEquals(t, "type", actualWidget.Type, expected.Type) - assertEquals(t, "url", actualWidget.Url, expected.Url) - assertEquals(t, "sizing", actualWidget.Sizing, expected.Sizing) -} - -func TestFreeTextWidget(t *testing.T) { - board := createTestScreenboard(t) - defer cleanUpScreenboard(t, board.Id) - - expected := datadog.Widget{}.FreeTextWidget - - expected.X = 1 - expected.Y = 1 - expected.Height = 10 - expected.Width = 10 - expected.Text = "Test" - expected.FontSize = "16" - expected.TextAlign = "center" - - w := datadog.Widget{FreeTextWidget: expected} - - board.Widgets = append(board.Widgets, w) - - if err := client.UpdateScreenboard(board); err != nil { - t.Fatalf("Updating a screenboard failed: %s", err) - } - - actual, err := client.GetScreenboard(board.Id) - if err != nil { - t.Fatalf("Retrieving a screenboard failed: %s", err) - } - - actualWidget := actual.Widgets[0].FreeTextWidget - - assertEquals(t, "font-size", actualWidget.FontSize, expected.FontSize) - assertEquals(t, "height", actualWidget.Height, expected.Height) - assertEquals(t, "width", actualWidget.Width, expected.Width) - assertEquals(t, "x", actualWidget.X, expected.X) - assertEquals(t, "y", actualWidget.Y, expected.Y) - assertEquals(t, "text", actualWidget.Text, expected.Text) - assertEquals(t, "text-align", actualWidget.TextAlign, expected.TextAlign) - assertEquals(t, "type", actualWidget.Type, expected.Type) -} - -func TestTimeseriesWidget(t *testing.T) { - board := createTestScreenboard(t) - defer cleanUpScreenboard(t, board.Id) - - expected := datadog.Widget{}.TimeseriesWidget - expected.X = 1 - expected.Y = 1 - expected.Width = 20 - expected.Height = 30 - expected.Title = true - expected.TitleAlign = "centre" - expected.TitleSize = datadog.TextSize{Size: 16} - expected.TitleText = "Test" - expected.Timeframe = "1m" - - w := datadog.Widget{TimeseriesWidget: expected} - - board.Widgets = append(board.Widgets, w) - if err := client.UpdateScreenboard(board); err != nil { - t.Fatalf("Updating a screenboard failed: %s", err) - } - - actual, err := client.GetScreenboard(board.Id) - if err != nil { - t.Fatalf("Retrieving a screenboard failed: %s", err) - } - - actualWidget := actual.Widgets[0].TimeseriesWidget - - assertEquals(t, "height", actualWidget.Height, expected.Height) - assertEquals(t, "width", actualWidget.Width, expected.Width) - assertEquals(t, "x", actualWidget.X, expected.X) - assertEquals(t, "y", actualWidget.Y, expected.Y) - assertEquals(t, "title", actualWidget.Title, expected.Title) - assertEquals(t, "title-align", actualWidget.TitleAlign, expected.TitleAlign) - assertEquals(t, "title-size.size", actualWidget.TitleSize.Size, expected.TitleSize.Size) - assertEquals(t, "title-size.auto", actualWidget.TitleSize.Auto, expected.TitleSize.Auto) - assertEquals(t, "title-text", actualWidget.TitleText, expected.TitleText) - assertEquals(t, "type", actualWidget.Type, expected.Type) - assertEquals(t, "timeframe", actualWidget.Timeframe, expected.Timeframe) - assertEquals(t, "legend", actualWidget.Legend, expected.Legend) - assertTileDefEquals(t, actualWidget.TileDef, expected.TileDef) -} - -func TestQueryValueWidget(t *testing.T) { - board := createTestScreenboard(t) - defer cleanUpScreenboard(t, board.Id) - - expected := datadog.Widget{}.QueryValueWidget - expected.X = 1 - expected.Y = 1 - expected.Width = 20 - expected.Height = 30 - expected.Title = true - expected.TitleAlign = "centre" - expected.TitleSize = datadog.TextSize{Size: 16} - expected.TitleText = "Test" - expected.Timeframe = "1m" - expected.TimeframeAggregator = "sum" - expected.Aggregator = "min" - expected.Query = "docker.containers.running" - expected.MetricType = "standard" - /* TODO: add test for conditional formats - "conditional_formats": [{ - "comparator": ">", - "color": "white_on_red", - "custom_bg_color": null, - "value": 1, - "invert": false, - "custom_fg_color": null}], - */ - expected.IsValidQuery = true - expected.ResultCalcFunc = "raw" - expected.Aggregator = "avg" - expected.CalcFunc = "raw" - - w := datadog.Widget{QueryValueWidget: expected} - - board.Widgets = append(board.Widgets, w) - if err := client.UpdateScreenboard(board); err != nil { - t.Fatalf("Updating a screenboard failed: %s", err) - } - - actual, err := client.GetScreenboard(board.Id) - if err != nil { - t.Fatalf("Retrieving a screenboard failed: %s", err) - } - - actualWidget := actual.Widgets[0].QueryValueWidget - - assertEquals(t, "height", actualWidget.Height, expected.Height) - assertEquals(t, "width", actualWidget.Width, expected.Width) - assertEquals(t, "x", actualWidget.X, expected.X) - assertEquals(t, "y", actualWidget.Y, expected.Y) - assertEquals(t, "title", actualWidget.Title, expected.Title) - assertEquals(t, "title-align", actualWidget.TitleAlign, expected.TitleAlign) - assertEquals(t, "title-size.size", actualWidget.TitleSize.Size, expected.TitleSize.Size) - assertEquals(t, "title-size.auto", actualWidget.TitleSize.Auto, expected.TitleSize.Auto) - assertEquals(t, "title-text", actualWidget.TitleText, expected.TitleText) - assertEquals(t, "type", actualWidget.Type, expected.Type) - assertEquals(t, "timeframe", actualWidget.Timeframe, expected.Timeframe) - assertEquals(t, "timeframe-aggregator", actualWidget.TimeframeAggregator, expected.TimeframeAggregator) - assertEquals(t, "aggregator", actualWidget.Aggregator, expected.Aggregator) - assertEquals(t, "query", actualWidget.Query, expected.Query) - assertEquals(t, "is_valid_query", actualWidget.IsValidQuery, expected.IsValidQuery) - assertEquals(t, "res_calc_func", actualWidget.ResultCalcFunc, expected.ResultCalcFunc) - assertEquals(t, "aggr", actualWidget.Aggregator, expected.Aggregator) -} - -func assertTileDefEquals(t *testing.T, actual datadog.TileDef, expected datadog.TileDef) { - assertEquals(t, "num-events", len(actual.Events), len(expected.Events)) - assertEquals(t, "num-requests", len(actual.Requests), len(expected.Requests)) - assertEquals(t, "viz", actual.Viz, expected.Viz) - - for i, event := range actual.Events { - assertEquals(t, "event-query", event.Query, expected.Events[i].Query) - } - - for i, request := range actual.Requests { - assertEquals(t, "request-query", request.Query, expected.Requests[i].Query) - assertEquals(t, "request-type", request.Type, expected.Requests[i].Type) - } -} - -func assertEquals(t *testing.T, attribute string, a, b interface{}) { - if a != b { - t.Errorf("The two %s values '%v' and '%v' are not equal", attribute, a, b) - } -} diff --git a/vendor/github.com/zorkian/go-datadog-api/integration/screenboards_test.go b/vendor/github.com/zorkian/go-datadog-api/integration/screenboards_test.go deleted file mode 100644 index 654d45f18..000000000 --- a/vendor/github.com/zorkian/go-datadog-api/integration/screenboards_test.go +++ /dev/null @@ -1,143 +0,0 @@ -package integration - -import ( - "github.com/zorkian/go-datadog-api" - "testing" -) - -func init() { - client = initTest() -} - -func TestCreateAndDeleteScreenboard(t *testing.T) { - expected := getTestScreenboard() - // create the screenboard and compare it - actual, err := client.CreateScreenboard(expected) - if err != nil { - t.Fatalf("Creating a screenboard failed when it shouldn't. (%s)", err) - } - - defer cleanUpScreenboard(t, actual.Id) - - assertScreenboardEquals(t, actual, expected) - - // now try to fetch it freshly and compare it again - actual, err = client.GetScreenboard(actual.Id) - if err != nil { - t.Fatalf("Retrieving a screenboard failed when it shouldn't. (%s)", err) - } - - assertScreenboardEquals(t, actual, expected) - -} - -func TestShareAndRevokeScreenboard(t *testing.T) { - expected := getTestScreenboard() - // create the screenboard - actual, err := client.CreateScreenboard(expected) - if err != nil { - t.Fatalf("Creating a screenboard failed when it shouldn't: %s", err) - } - - defer cleanUpScreenboard(t, actual.Id) - - // share screenboard and verify it was shared - var response datadog.ScreenShareResponse - err = client.ShareScreenboard(actual.Id, &response) - if err != nil { - t.Fatalf("Failed to share screenboard: %s", err) - } - - // revoke screenboard - err = client.RevokeScreenboard(actual.Id) - if err != nil { - t.Fatalf("Failed to revoke sharing of screenboard: %s", err) - } -} - -func TestUpdateScreenboard(t *testing.T) { - board := createTestScreenboard(t) - defer cleanUpScreenboard(t, board.Id) - - board.Title = "___New-Test-Board___" - if err := client.UpdateScreenboard(board); err != nil { - t.Fatalf("Updating a screenboard failed when it shouldn't: %s", err) - } - - actual, err := client.GetScreenboard(board.Id) - if err != nil { - t.Fatalf("Retrieving a screenboard failed when it shouldn't: %s", err) - } - - assertScreenboardEquals(t, actual, board) - -} - -func TestGetScreenboards(t *testing.T) { - boards, err := client.GetScreenboards() - if err != nil { - t.Fatalf("Retrieving screenboards failed when it shouldn't: %s", err) - } - num := len(boards) - - board := createTestScreenboard(t) - defer cleanUpScreenboard(t, board.Id) - - boards, err = client.GetScreenboards() - if err != nil { - t.Fatalf("Retrieving screenboards failed when it shouldn't: %s", err) - } - - if num+1 != len(boards) { - t.Fatalf("Number of screenboards didn't match expected: %d != %d", len(boards), num+1) - } -} - -func getTestScreenboard() *datadog.Screenboard { - return &datadog.Screenboard{ - Title: "___Test-Board___", - Height: "600", - Width: "800", - Widgets: []datadog.Widget{}, - } -} - -func createTestScreenboard(t *testing.T) *datadog.Screenboard { - board := getTestScreenboard() - board, err := client.CreateScreenboard(board) - if err != nil { - t.Fatalf("Creating a screenboard failed when it shouldn't: %s", err) - } - - return board -} - -func cleanUpScreenboard(t *testing.T, id int) { - if err := client.DeleteScreenboard(id); err != nil { - t.Fatalf("Deleting a screenboard failed when it shouldn't. Manual cleanup needed. (%s)", err) - } - - deletedBoard, err := client.GetScreenboard(id) - if deletedBoard != nil { - t.Fatal("Screenboard hasn't been deleted when it should have been. Manual cleanup needed.") - } - - if err == nil { - t.Fatal("Fetching deleted screenboard didn't lead to an error. Manual cleanup needed.") - } -} - -func assertScreenboardEquals(t *testing.T, actual, expected *datadog.Screenboard) { - if actual.Title != expected.Title { - t.Errorf("Screenboard title does not match: %s != %s", actual.Title, expected.Title) - } - if actual.Width != expected.Width { - t.Errorf("Screenboard width does not match: %s != %s", actual.Width, expected.Width) - } - if actual.Height != expected.Height { - t.Errorf("Screenboard width does not match: %s != %s", actual.Height, expected.Height) - } - if len(actual.Widgets) != len(expected.Widgets) { - t.Errorf("Number of Screenboard widgets does not match: %d != %d", len(actual.Widgets), len(expected.Widgets)) - } -} diff --git a/vendor/github.com/zorkian/go-datadog-api/monitors.go b/vendor/github.com/zorkian/go-datadog-api/monitors.go index b28cd5f7e..8be9b1cbb 100644 --- a/vendor/github.com/zorkian/go-datadog-api/monitors.go +++ b/vendor/github.com/zorkian/go-datadog-api/monitors.go @@ -11,7 +11,9 @@ package datadog import ( "encoding/json" "fmt" + "net/url" "strconv" + "strings" ) type ThresholdCount struct { @@ -104,6 +106,36 @@ func (self *Client) GetMonitor(id int) (*Monitor, error) { return &out, nil } +// GetMonitor retrieves monitors by name +func (self *Client) GetMonitorsByName(name string) ([]Monitor, error) { + var out reqMonitors + query, err := url.ParseQuery(fmt.Sprintf("name=%v", name)) + if err != nil { + return nil, err + } + + err = self.doJsonRequest("GET", fmt.Sprintf("/v1/monitor?%v", query.Encode()), nil, &out.Monitors) + if err != nil { + return nil, err + } + return out.Monitors, nil +} + +// GetMonitor retrieves monitors by a slice of tags +func (self *Client) GetMonitorsByTags(tags []string) ([]Monitor, error) { + var out reqMonitors + query, err := url.ParseQuery(fmt.Sprintf("monitor_tags=%v", strings.Join(tags, ","))) + if err != nil { + return nil, err + } + + err = self.doJsonRequest("GET", fmt.Sprintf("/v1/monitor?%v", query.Encode()), nil, &out.Monitors) + if err != nil { + return nil, err + } + return out.Monitors, nil +} + // DeleteMonitor removes a monitor from the system func (self *Client) DeleteMonitor(id int) error { return self.doJsonRequest("DELETE", fmt.Sprintf("/v1/monitor/%d", id), diff --git a/vendor/vendor.json b/vendor/vendor.json index 7d22438a1..72b83023b 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -2296,10 +2296,10 @@ "revision": "75ce5fbba34b1912a3641adbd58cf317d7315821" }, { - "checksumSHA1": "jBiNbkwHKwnuGfkaccnLc/1rzto=", + "checksumSHA1": "U817qc0NaamC2zeUcZknLpnkrOw=", "path": "github.com/zorkian/go-datadog-api", - "revision": "f9f89391f35f5c8eafed4b75b5797b9b23851908", - "revisionTime": "2016-10-04T18:54:04Z" + "revision": "73d5b59ca18ee5e94fb449e001ed3f724fa0634e", + "revisionTime": "2016-11-30T17:19:56Z" }, { "path": "golang.org/x/crypto/curve25519", diff --git a/website/source/docs/providers/datadog/r/timeboard.html.markdown b/website/source/docs/providers/datadog/r/timeboard.html.markdown index d4b4b90a6..de2c70930 100644 --- a/website/source/docs/providers/datadog/r/timeboard.html.markdown +++ b/website/source/docs/providers/datadog/r/timeboard.html.markdown @@ -28,7 +28,7 @@ resource "datadog_timeboard" "redis" { type = "bars" } } - + graph { title = "Redis memory usage" viz = "timeseries" @@ -76,6 +76,33 @@ Nested `graph` blocks have the following structure: * `title` - (Required) The name of the graph. * `viz` - (Required) The type of visualization to use for the graph. Valid choices are "change", "distribution", "heatmap", "hostmap", "query_value", timeseries", and "toplist". * `request` - Nested block describing a graph definition request (a metric query to plot on the graph). The structure of this block is described below. Multiple request blocks are allowed within a graph block. +* `events` - (Optional) A list of event filter strings. Note that, while supported by the Datadog API, the Datadog UI does not (currently) support multiple event filters very well, so use at your own risk. +* `autoscale` - (Optional) Boolean that determines whether to autoscale graphs. +* `precision` - (Optional) Number of digits displayed, use `*` for full precision. +* `custom_unit` - (Optional) Display a custom unit on the graph (such as 'hertz') +* `text_align` - (Optional) How to align text in the graph, can be one of 'left', 'center', or 'right'. +* `style` - (Optional) Nested block describing hostmaps. The structure of this block is described below. +* `group` - (Optional) List of groups for hostmaps (shown as 'group by' in the UI). +* `include_no_metric_hosts` - (Optional) If set to true, will display hosts on hostmap that have no reported metrics. +* `include_ungrouped_hosts` - (Optional) If set to true, will display hosts without groups on hostmaps. +* `scope` - (Optional) List of scopes for hostmaps (shown as 'filter by' in the UI). +* `yaxis` - (Optional) Nested block describing modifications to the yaxis rendering. The structure of this block is described below. +* `marker` - (Optional) Nested block describing lines / ranges added to graph for formatting. The structure of this block is described below. Multiple marker blocks are allowed within a graph block. + +#### Nested `graph` `marker` blocks + +Nested `graph` `marker` blocks have the following structure: + +* `type` - (Required) How the marker lines will look. Possible values are {"error", "warning", "info", "ok"} {"dashed", "solid", "bold"}. Example: "error dashed". +* `value` - (Required) Mathematical expression describing the marker. Examples: "y > 1", "-5 < y < 0", "y = 19". +* `label` - (Optional) A label for the line or range. + +{error, warning, info, ok} {dashed, solid, bold} + +#### Nested `graph` `yaxis` block +* `min` - (Optional) Minimum bound for the graph's yaxis, a string. +* `max` - (Optional) Maximum bound for the graph's yaxis, a string. +* `scale` - (Optional) How to scale the yaxis. Possible values are: "linear", "log", "sqrt", "pow##" (eg. pow2, pow0.5, 2 is used if only "pow" was provided). Default: "linear". #### Nested `graph` `request` blocks @@ -86,11 +113,19 @@ Nested `graph` `request` blocks have the following structure: * `type` - (Optional) Choose how to draw the graph. For example: "lines", "bars" or "areas". Default: "lines". * `style` - (Optional) Nested block to customize the graph style. -### Nested `style` block +### Nested `graph` `style` block +The nested `style` block is used specifically for styling `hostmap` graphs, and has the following structure: -The nested `style` blocks has the following structure (only `palette` is supported right now): +* `palette` - (Optional) Spectrum of colors to use when styling a hostmap. For example: "green_to_orange", "yellow_to_green", "YlOrRd", or "hostmap_blues". Default: "green_to_orange". +* `palette_flip` - (Optional) Flip how the hostmap is rendered. For example, with the default palette, low values are represented as green, with high values as orange. If palette_flip is "true", then low values will be orange, and high values will be green. + +### Nested `graph` `request` `style` block + +The nested `style` blocks has the following structure: * `palette` - (Optional) Color of the line drawn. For example: "classic", "cool", "warm", "purple", "orange" or "gray". Default: "classic". +* `width` - (Optional) Line width. Possible values: "thin", "normal", "thick". Default: "normal". +* `type` - (Optional) Type of line drawn. Possible values: "dashed", "solid", "dotted". Default: "solid". ### Nested `template_variable` blocks