2016-06-15 18:44:49 +02:00
|
|
|
package datadog
|
|
|
|
|
|
|
|
import (
|
2016-12-05 14:16:47 +01:00
|
|
|
"encoding/json"
|
2016-06-15 18:44:49 +02:00
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/hashicorp/terraform/helper/schema"
|
2017-02-20 13:48:32 +01:00
|
|
|
"gopkg.in/zorkian/go-datadog-api.v2"
|
2016-06-15 18:44:49 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
func resourceDatadogTimeboard() *schema.Resource {
|
|
|
|
request := &schema.Schema{
|
|
|
|
Type: schema.TypeList,
|
|
|
|
Required: true,
|
|
|
|
Elem: &schema.Resource{
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
|
|
"q": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
"stacked": &schema.Schema{
|
|
|
|
Type: schema.TypeBool,
|
|
|
|
Optional: true,
|
|
|
|
Default: false,
|
|
|
|
},
|
2016-10-03 17:18:18 +02:00
|
|
|
"type": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Default: "line",
|
|
|
|
},
|
2017-01-14 00:08:41 +01:00
|
|
|
"aggregator": {
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
ValidateFunc: validateAggregatorMethod,
|
|
|
|
},
|
2016-10-03 17:18:18 +02:00
|
|
|
"style": &schema.Schema{
|
|
|
|
Type: schema.TypeMap,
|
|
|
|
Optional: true,
|
|
|
|
},
|
2016-12-05 14:16:47 +01:00
|
|
|
"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,
|
|
|
|
},
|
2016-06-15 18:44:49 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
graph := &schema.Schema{
|
|
|
|
Type: schema.TypeList,
|
|
|
|
Required: true,
|
|
|
|
Description: "A list of graph definitions.",
|
|
|
|
Elem: &schema.Resource{
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
|
|
"title": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
Description: "The name of the graph.",
|
|
|
|
},
|
2016-12-05 14:16:47 +01:00
|
|
|
"events": &schema.Schema{
|
|
|
|
Type: schema.TypeSet,
|
|
|
|
Optional: true,
|
|
|
|
Description: "Filter for events to be overlayed on the graph.",
|
|
|
|
Elem: &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
},
|
|
|
|
},
|
2016-06-15 18:44:49 +02:00
|
|
|
"viz": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
"request": request,
|
2016-12-05 14:16:47 +01:00
|
|
|
"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",
|
|
|
|
},
|
2016-06-15 18:44:49 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
template_variable := &schema.Schema{
|
|
|
|
Type: schema.TypeList,
|
|
|
|
Optional: true,
|
|
|
|
Description: "A list of template variables for using Dashboard templating.",
|
|
|
|
Elem: &schema.Resource{
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
|
|
"name": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
Description: "The name of the variable.",
|
|
|
|
},
|
|
|
|
"prefix": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Description: "The tag prefix associated with the variable. Only tags with this prefix will appear in the variable dropdown.",
|
|
|
|
},
|
|
|
|
"default": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Description: "The default value for the template variable on dashboard load.",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
return &schema.Resource{
|
|
|
|
Create: resourceDatadogTimeboardCreate,
|
|
|
|
Update: resourceDatadogTimeboardUpdate,
|
|
|
|
Read: resourceDatadogTimeboardRead,
|
|
|
|
Delete: resourceDatadogTimeboardDelete,
|
|
|
|
Exists: resourceDatadogTimeboardExists,
|
2016-12-05 14:16:47 +01:00
|
|
|
Importer: &schema.ResourceImporter{
|
|
|
|
State: resourceDatadogTimeboardImport,
|
|
|
|
},
|
2016-06-15 18:44:49 +02:00
|
|
|
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
|
|
"title": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
Description: "The name of the dashboard.",
|
|
|
|
},
|
|
|
|
"description": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
Description: "A description of the dashboard's content.",
|
|
|
|
},
|
|
|
|
"read_only": &schema.Schema{
|
|
|
|
Type: schema.TypeBool,
|
|
|
|
Optional: true,
|
|
|
|
Default: false,
|
|
|
|
},
|
|
|
|
"graph": graph,
|
|
|
|
"template_variable": template_variable,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-05 14:16:47 +01:00
|
|
|
func appendConditionalFormats(datadogRequest *datadog.GraphDefinitionRequest, terraformFormats *[]interface{}) {
|
|
|
|
for _, t_ := range *terraformFormats {
|
|
|
|
t := t_.(map[string]interface{})
|
|
|
|
d := datadog.DashboardConditionalFormat{
|
2017-02-20 13:48:32 +01:00
|
|
|
Comparator: datadog.String(t["comparator"].(string)),
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := t["palette"]; ok {
|
|
|
|
d.SetPalette(v.(string))
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := t["custom_bg_color"]; ok {
|
|
|
|
d.SetCustomBgColor(v.(string))
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := t["custom_fg_color"]; ok {
|
|
|
|
d.SetCustomFgColor(v.(string))
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := t["value"]; ok {
|
|
|
|
d.SetValue(json.Number(v.(string)))
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
datadogRequest.ConditionalFormats = append(datadogRequest.ConditionalFormats, d)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-15 18:44:49 +02:00
|
|
|
func buildTemplateVariables(terraformTemplateVariables *[]interface{}) *[]datadog.TemplateVariable {
|
|
|
|
datadogTemplateVariables := make([]datadog.TemplateVariable, len(*terraformTemplateVariables))
|
|
|
|
for i, t_ := range *terraformTemplateVariables {
|
|
|
|
t := t_.(map[string]interface{})
|
|
|
|
datadogTemplateVariables[i] = datadog.TemplateVariable{
|
2017-02-20 13:48:32 +01:00
|
|
|
Name: datadog.String(t["name"].(string)),
|
|
|
|
Prefix: datadog.String(t["prefix"].(string)),
|
|
|
|
Default: datadog.String(t["default"].(string)),
|
|
|
|
}
|
2016-06-15 18:44:49 +02:00
|
|
|
}
|
|
|
|
return &datadogTemplateVariables
|
|
|
|
}
|
|
|
|
|
|
|
|
func appendRequests(datadogGraph *datadog.Graph, terraformRequests *[]interface{}) {
|
|
|
|
for _, t_ := range *terraformRequests {
|
|
|
|
t := t_.(map[string]interface{})
|
2016-10-03 13:15:01 +02:00
|
|
|
d := datadog.GraphDefinitionRequest{
|
2017-02-20 13:48:32 +01:00
|
|
|
Query: datadog.String(t["q"].(string)),
|
|
|
|
Type: datadog.String(t["type"].(string)),
|
|
|
|
Aggregator: datadog.String(t["aggregator"].(string)),
|
2016-10-03 13:15:01 +02:00
|
|
|
}
|
2016-06-15 18:44:49 +02:00
|
|
|
if stacked, ok := t["stacked"]; ok {
|
2017-02-20 13:48:32 +01:00
|
|
|
d.SetStacked(stacked.(bool))
|
2016-06-15 18:44:49 +02:00
|
|
|
}
|
2016-10-03 17:18:18 +02:00
|
|
|
if style, ok := t["style"]; ok {
|
|
|
|
s, _ := style.(map[string]interface{})
|
2016-12-05 14:16:47 +01:00
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
style := datadog.GraphDefinitionRequestStyle{}
|
2016-12-05 14:16:47 +01:00
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := s["palette"]; ok {
|
|
|
|
style.SetPalette(v.(string))
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := s["width"]; ok {
|
|
|
|
style.SetWidth(v.(string))
|
2016-10-03 17:18:18 +02:00
|
|
|
}
|
2016-12-05 14:16:47 +01:00
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := s["type"]; ok {
|
|
|
|
style.SetType(v.(string))
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
d.SetStyle(style)
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := t["change_type"]; ok {
|
|
|
|
d.SetChangeType(v.(string))
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := t["compare_to"]; ok {
|
|
|
|
d.SetCompareTo(v.(string))
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := t["increase_good"]; ok {
|
|
|
|
d.SetIncreaseGood(v.(bool))
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := t["order_by"]; ok {
|
|
|
|
d.SetOrderBy(v.(string))
|
2016-10-03 17:18:18 +02:00
|
|
|
}
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := t["extra_col"]; ok {
|
|
|
|
d.SetExtraCol(v.(string))
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := t["order_direction"]; ok {
|
|
|
|
d.SetOrderDirection(v.(string))
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := t["conditional_format"]; ok {
|
|
|
|
v_ := v.([]interface{})
|
|
|
|
appendConditionalFormats(&d, &v_)
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
|
2016-06-15 18:44:49 +02:00
|
|
|
datadogGraph.Definition.Requests = append(datadogGraph.Definition.Requests, d)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-05 14:16:47 +01:00
|
|
|
func appendEvents(datadogGraph *datadog.Graph, terraformEvents *[]interface{}) {
|
|
|
|
for _, t_ := range *terraformEvents {
|
2017-02-20 13:48:32 +01:00
|
|
|
datadogGraph.Definition.Events = append(datadogGraph.Definition.Events, datadog.GraphEvent{
|
|
|
|
Query: datadog.String(t_.(string)),
|
|
|
|
})
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func appendMarkers(datadogGraph *datadog.Graph, terraformMarkers *[]interface{}) {
|
|
|
|
for _, t_ := range *terraformMarkers {
|
|
|
|
t := t_.(map[string]interface{})
|
|
|
|
d := datadog.GraphDefinitionMarker{
|
2017-02-20 13:48:32 +01:00
|
|
|
Type: datadog.String(t["type"].(string)),
|
|
|
|
Value: datadog.String(t["value"].(string)),
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := t["label"]; ok {
|
|
|
|
d.SetLabel(v.(string))
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
datadogGraph.Definition.Markers = append(datadogGraph.Definition.Markers, d)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-15 18:44:49 +02:00
|
|
|
func buildGraphs(terraformGraphs *[]interface{}) *[]datadog.Graph {
|
|
|
|
datadogGraphs := make([]datadog.Graph, len(*terraformGraphs))
|
|
|
|
for i, t_ := range *terraformGraphs {
|
|
|
|
t := t_.(map[string]interface{})
|
2016-12-05 14:16:47 +01:00
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
datadogGraphs[i] = datadog.Graph{
|
|
|
|
Title: datadog.String(t["title"].(string)),
|
|
|
|
}
|
|
|
|
|
|
|
|
d := &datadogGraphs[i]
|
|
|
|
d.Definition = &datadog.GraphDefinition{}
|
|
|
|
d.Definition.SetViz(t["viz"].(string))
|
|
|
|
|
|
|
|
if v, ok := t["yaxis"]; ok {
|
|
|
|
yaxis := v.(map[string]interface{})
|
|
|
|
if v, ok := yaxis["min"]; ok {
|
|
|
|
min, _ := strconv.ParseFloat(v.(string), 64)
|
|
|
|
d.Definition.Yaxis.SetMin(min)
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := yaxis["max"]; ok {
|
|
|
|
max, _ := strconv.ParseFloat(v.(string), 64)
|
|
|
|
d.Definition.Yaxis.SetMax(max)
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := yaxis["scale"]; ok {
|
|
|
|
d.Definition.Yaxis.SetScale(v.(string))
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := t["autoscale"]; ok {
|
|
|
|
d.Definition.SetAutoscale(v.(bool))
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := t["text_align"]; ok {
|
|
|
|
d.Definition.SetTextAlign(v.(string))
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if precision, ok := t["precision"]; ok {
|
2017-02-20 13:48:32 +01:00
|
|
|
d.Definition.SetPrecision(precision.(string))
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := t["custom_unit"]; ok {
|
|
|
|
d.Definition.SetCustomUnit(v.(string))
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if style, ok := t["style"]; ok {
|
|
|
|
s := style.(map[string]interface{})
|
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
gs := datadog.Style{}
|
2016-12-05 14:16:47 +01:00
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := s["palette"]; ok {
|
|
|
|
gs.SetPalette(v.(string))
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := s["palette_flip"]; ok {
|
|
|
|
pf, _ := strconv.ParseBool(v.(string))
|
|
|
|
gs.SetPaletteFlip(pf)
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
2017-02-20 13:48:32 +01:00
|
|
|
d.Definition.SetStyle(gs)
|
2016-12-05 14:16:47 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := t["group"]; ok {
|
|
|
|
for _, g := range v.(*schema.Set).List() {
|
2016-12-05 14:16:47 +01:00
|
|
|
d.Definition.Groups = append(d.Definition.Groups, g.(string))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if includeNoMetricHosts, ok := t["include_no_metric_hosts"]; ok {
|
2017-02-20 13:48:32 +01:00
|
|
|
d.Definition.SetIncludeNoMetricHosts(includeNoMetricHosts.(bool))
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := t["scope"]; ok {
|
|
|
|
for _, s := range v.(*schema.Set).List() {
|
2016-12-05 14:16:47 +01:00
|
|
|
d.Definition.Scopes = append(d.Definition.Groups, s.(string))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := t["include_ungrouped_hosts"]; ok {
|
|
|
|
d.Definition.SetIncludeUngroupedHosts(v.(bool))
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
2017-02-20 13:48:32 +01:00
|
|
|
v := t["marker"].([]interface{})
|
|
|
|
appendMarkers(d, &v)
|
2016-12-05 14:16:47 +01:00
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
v = t["events"].(*schema.Set).List()
|
|
|
|
appendEvents(d, &v)
|
2016-12-05 14:16:47 +01:00
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
v = t["request"].([]interface{})
|
|
|
|
appendRequests(d, &v)
|
2016-06-15 18:44:49 +02:00
|
|
|
}
|
|
|
|
return &datadogGraphs
|
|
|
|
}
|
|
|
|
|
|
|
|
func buildTimeboard(d *schema.ResourceData) (*datadog.Dashboard, error) {
|
|
|
|
var id int
|
|
|
|
if d.Id() != "" {
|
|
|
|
var err error
|
|
|
|
id, err = strconv.Atoi(d.Id())
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
terraformGraphs := d.Get("graph").([]interface{})
|
|
|
|
terraformTemplateVariables := d.Get("template_variable").([]interface{})
|
|
|
|
return &datadog.Dashboard{
|
2017-02-20 13:48:32 +01:00
|
|
|
Id: datadog.Int(id),
|
|
|
|
Title: datadog.String(d.Get("title").(string)),
|
|
|
|
Description: datadog.String(d.Get("description").(string)),
|
|
|
|
ReadOnly: datadog.Bool(d.Get("read_only").(bool)),
|
2016-06-15 18:44:49 +02:00
|
|
|
Graphs: *buildGraphs(&terraformGraphs),
|
|
|
|
TemplateVariables: *buildTemplateVariables(&terraformTemplateVariables),
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceDatadogTimeboardCreate(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
timeboard, err := buildTimeboard(d)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Failed to parse resource configuration: %s", err.Error())
|
|
|
|
}
|
|
|
|
timeboard, err = meta.(*datadog.Client).CreateDashboard(timeboard)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Failed to create timeboard using Datadog API: %s", err.Error())
|
|
|
|
}
|
2017-02-20 13:48:32 +01:00
|
|
|
d.SetId(strconv.Itoa(timeboard.GetId()))
|
2016-06-15 18:44:49 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceDatadogTimeboardUpdate(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
timeboard, err := buildTimeboard(d)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Failed to parse resource configuration: %s", err.Error())
|
|
|
|
}
|
|
|
|
if err = meta.(*datadog.Client).UpdateDashboard(timeboard); err != nil {
|
|
|
|
return fmt.Errorf("Failed to update timeboard using Datadog API: %s", err.Error())
|
|
|
|
}
|
|
|
|
return resourceDatadogTimeboardRead(d, meta)
|
|
|
|
}
|
|
|
|
|
2016-12-05 14:16:47 +01:00
|
|
|
func appendTerraformGraphRequests(datadogRequests []datadog.GraphDefinitionRequest, requests *[]map[string]interface{}) {
|
|
|
|
for _, datadogRequest := range datadogRequests {
|
|
|
|
request := map[string]interface{}{}
|
2017-02-20 13:48:32 +01:00
|
|
|
request["q"] = datadogRequest.GetQuery()
|
|
|
|
request["stacked"] = datadogRequest.GetStacked()
|
|
|
|
request["type"] = datadogRequest.GetType()
|
|
|
|
if v, ok := datadogRequest.GetStyleOk(); ok {
|
2016-12-05 14:16:47 +01:00
|
|
|
style := map[string]string{}
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := v.GetPaletteOk(); ok {
|
|
|
|
style["palette"] = v
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := v.GetTypeOk(); ok {
|
|
|
|
style["type"] = v
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := v.GetWidthOk(); ok {
|
|
|
|
style["width"] = v
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
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
|
2017-02-20 13:48:32 +01:00
|
|
|
request["change_type"] = datadogRequest.GetChangeType()
|
|
|
|
request["order_direction"] = datadogRequest.GetOrderDirection()
|
|
|
|
request["compare_to"] = datadogRequest.GetCompareTo()
|
|
|
|
request["increase_good"] = datadogRequest.GetIncreaseGood()
|
|
|
|
request["order_by"] = datadogRequest.GetOrderBy()
|
|
|
|
request["extra_col"] = datadogRequest.GetExtraCol()
|
2016-12-05 14:16:47 +01:00
|
|
|
|
|
|
|
*requests = append(*requests, request)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func buildTerraformGraph(datadog_graph datadog.Graph) map[string]interface{} {
|
|
|
|
graph := map[string]interface{}{}
|
2017-02-20 13:48:32 +01:00
|
|
|
graph["title"] = datadog_graph.GetTitle()
|
2016-12-05 14:16:47 +01:00
|
|
|
|
|
|
|
definition := datadog_graph.Definition
|
2017-02-20 13:48:32 +01:00
|
|
|
graph["viz"] = definition.GetViz()
|
2016-12-05 14:16:47 +01:00
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
events := []*string{}
|
2016-12-05 14:16:47 +01:00
|
|
|
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{}
|
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := definition.Yaxis.GetMinOk(); ok {
|
|
|
|
yaxis["min"] = strconv.FormatFloat(v, 'f', -1, 64)
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := definition.Yaxis.GetMaxOk(); ok {
|
|
|
|
yaxis["max"] = strconv.FormatFloat(v, 'f', -1, 64)
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := definition.Yaxis.GetScaleOk(); ok {
|
|
|
|
yaxis["scale"] = v
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
graph["yaxis"] = yaxis
|
|
|
|
|
|
|
|
graph["autoscale"] = definition.Autoscale
|
|
|
|
graph["text_align"] = definition.TextAlign
|
|
|
|
graph["precision"] = definition.Precision
|
|
|
|
graph["custom_unit"] = definition.CustomUnit
|
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := definition.GetStyleOk(); ok {
|
2016-12-05 14:16:47 +01:00
|
|
|
style := map[string]string{}
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := v.GetPaletteOk(); ok {
|
|
|
|
style["palette"] = v
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
2017-02-20 13:48:32 +01:00
|
|
|
if v, ok := v.GetPaletteFlipOk(); ok {
|
|
|
|
style["palette_flip"] = strconv.FormatBool(v)
|
2016-12-05 14:16:47 +01:00
|
|
|
}
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2016-06-15 18:44:49 +02:00
|
|
|
func resourceDatadogTimeboardRead(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
id, err := strconv.Atoi(d.Id())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
timeboard, err := meta.(*datadog.Client).GetDashboard(id)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
log.Printf("[DEBUG] timeboard: %v", timeboard)
|
2017-02-20 13:48:32 +01:00
|
|
|
d.Set("title", timeboard.GetTitle())
|
|
|
|
d.Set("description", timeboard.GetDescription())
|
2016-12-05 14:16:47 +01:00
|
|
|
|
|
|
|
graphs := []map[string]interface{}{}
|
|
|
|
for _, datadog_graph := range timeboard.Graphs {
|
|
|
|
graphs = append(graphs, buildTerraformGraph(datadog_graph))
|
|
|
|
}
|
|
|
|
d.Set("graph", graphs)
|
|
|
|
|
2017-02-20 13:48:32 +01:00
|
|
|
templateVariables := []map[string]*string{}
|
2016-12-05 14:16:47 +01:00
|
|
|
for _, templateVariable := range timeboard.TemplateVariables {
|
2017-02-20 13:48:32 +01:00
|
|
|
tv := map[string]*string{
|
2016-12-05 14:16:47 +01:00
|
|
|
"name": templateVariable.Name,
|
|
|
|
"prefix": templateVariable.Prefix,
|
|
|
|
"default": templateVariable.Default,
|
|
|
|
}
|
|
|
|
templateVariables = append(templateVariables, tv)
|
|
|
|
}
|
|
|
|
d.Set("template_variable", templateVariables)
|
|
|
|
|
2016-06-15 18:44:49 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceDatadogTimeboardDelete(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
id, err := strconv.Atoi(d.Id())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err = meta.(*datadog.Client).DeleteDashboard(id); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-12-05 14:16:47 +01:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2016-06-15 18:44:49 +02:00
|
|
|
func resourceDatadogTimeboardExists(d *schema.ResourceData, meta interface{}) (b bool, e error) {
|
|
|
|
id, err := strconv.Atoi(d.Id())
|
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
if _, err = meta.(*datadog.Client).GetDashboard(id); err != nil {
|
|
|
|
if strings.Contains(err.Error(), "404 Not Found") {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
return true, nil
|
|
|
|
}
|
2017-01-14 00:08:41 +01:00
|
|
|
|
|
|
|
func validateAggregatorMethod(v interface{}, k string) (ws []string, errors []error) {
|
|
|
|
value := v.(string)
|
|
|
|
validMethods := map[string]struct{}{
|
2017-05-12 12:37:32 +02:00
|
|
|
"avg": {},
|
|
|
|
"max": {},
|
|
|
|
"min": {},
|
|
|
|
"sum": {},
|
|
|
|
"last": {},
|
2017-01-14 00:08:41 +01:00
|
|
|
}
|
|
|
|
if _, ok := validMethods[value]; !ok {
|
|
|
|
errors = append(errors, fmt.Errorf(
|
2017-05-12 12:37:32 +02:00
|
|
|
`%q contains an invalid method %q. Valid methods are either "avg", "max", "min", "sum", or "last"`, k, value))
|
2017-01-14 00:08:41 +01:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|