provider/datadog: Add aggregator method to timeboard graph resource

Adds aggregator argument to the timeboard graph resource.

Ex:
```
request {
  q = "top(avg:docker.cpu.system{*} by {container_name}, 10, 'mean', 'desc')"
  aggregator = "sum"
}
```

```
$ make testacc TEST=./builtin/providers/datadog TESTARGS='-run=TestAccDatadogTimeboard_update'
==> Checking that code complies with gofmt requirements...
go generate $(go list ./... | grep -v /terraform/vendor/)
2017/01/13 17:52:50 Generated command/internal_plugin_list.go
TF_ACC=1 go test ./builtin/providers/datadog -v -run=TestAccDatadogTimeboard_update -timeout 120m
=== RUN   TestAccDatadogTimeboard_update
--- PASS: TestAccDatadogTimeboard_update (82.60s)
PASS
ok      github.com/hashicorp/terraform/builtin/providers/datadog        82.619s
```

Fixes: #11168
This commit is contained in:
Jake Champlin 2017-01-13 18:08:41 -05:00
parent 6ac39683ec
commit 8fdc6518c8
No known key found for this signature in database
GPG Key ID: DC31F41958EF4AC2
3 changed files with 61 additions and 3 deletions

View File

@ -31,6 +31,11 @@ func resourceDatadogTimeboard() *schema.Resource {
Optional: true, Optional: true,
Default: "line", Default: "line",
}, },
"aggregator": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validateAggregatorMethod,
},
"style": &schema.Schema{ "style": &schema.Schema{
Type: schema.TypeMap, Type: schema.TypeMap,
Optional: true, Optional: true,
@ -307,8 +312,9 @@ func appendRequests(datadogGraph *datadog.Graph, terraformRequests *[]interface{
for _, t_ := range *terraformRequests { for _, t_ := range *terraformRequests {
t := t_.(map[string]interface{}) t := t_.(map[string]interface{})
d := datadog.GraphDefinitionRequest{ d := datadog.GraphDefinitionRequest{
Query: t["q"].(string), Query: t["q"].(string),
Type: t["type"].(string), Type: t["type"].(string),
Aggregator: t["aggregator"].(string),
} }
if stacked, ok := t["stacked"]; ok { if stacked, ok := t["stacked"]; ok {
d.Stacked = stacked.(bool) d.Stacked = stacked.(bool)
@ -703,3 +709,18 @@ func resourceDatadogTimeboardExists(d *schema.ResourceData, meta interface{}) (b
} }
return true, nil return true, nil
} }
func validateAggregatorMethod(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
validMethods := map[string]struct{}{
"average": {},
"max": {},
"min": {},
"sum": {},
}
if _, ok := validMethods[value]; !ok {
errors = append(errors, fmt.Errorf(
`%q contains an invalid method %q. Valid methods are either "average", "max", "min", or "sum"`))
}
return
}

View File

@ -42,6 +42,7 @@ resource "datadog_timeboard" "acceptance_test" {
viz = "timeseries" viz = "timeseries"
request { request {
q = "avg:redis.mem.used{$host} - avg:redis.mem.lua{$host}, avg:redis.mem.lua{$host}" q = "avg:redis.mem.used{$host} - avg:redis.mem.lua{$host}, avg:redis.mem.lua{$host}"
aggregator = "sum"
stacked = true stacked = true
} }
request { request {
@ -53,6 +54,7 @@ resource "datadog_timeboard" "acceptance_test" {
style { style {
palette = "warm" palette = "warm"
} }
aggregator = "max"
} }
} }
template_variable { template_variable {
@ -90,6 +92,7 @@ resource "datadog_timeboard" "acceptance_test" {
request { request {
q = "sum:aws.elb.request_count{*}.as_count()" q = "sum:aws.elb.request_count{*}.as_count()"
type = "line" type = "line"
aggregator = "min"
conditional_format { conditional_format {
comparator = ">" comparator = ">"
value = "1000" value = "1000"
@ -139,11 +142,14 @@ func TestAccDatadogTimeboard_update(t *testing.T) {
resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.title", "Redis memory usage"), resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.title", "Redis memory usage"),
resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.viz", "timeseries"), resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.viz", "timeseries"),
resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.0.q", "avg:redis.mem.used{$host} - avg:redis.mem.lua{$host}, avg:redis.mem.lua{$host}"), resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.0.q", "avg:redis.mem.used{$host} - avg:redis.mem.lua{$host}, avg:redis.mem.lua{$host}"),
resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.0.aggregator", "sum"),
resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.0.stacked", "true"), resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.0.stacked", "true"),
resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.1.q", "avg:redis.mem.rss{$host}"), resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.1.q", "avg:redis.mem.rss{$host}"),
resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "template_variable.0.name", "host"), resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "template_variable.0.name", "host"),
resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "template_variable.0.prefix", "host"), resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "template_variable.0.prefix", "host"),
resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.2.type", "bars"), resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.2.type", "bars"),
resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.2.q", "avg:redis.mem.rss{$host}"),
resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.2.aggregator", "max"),
resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.2.style.palette", "warm"), resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.2.style.palette", "warm"),
), ),
} }
@ -166,6 +172,7 @@ func TestAccDatadogTimeboard_update(t *testing.T) {
resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.title", "ELB Requests"), 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.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.q", "sum:aws.elb.request_count{*}.as_count()"),
resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.0.aggregator", "min"),
resource.TestCheckResourceAttr("datadog_timeboard.acceptance_test", "graph.1.request.0.type", "line"), 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.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.value", "1000"),
@ -214,3 +221,32 @@ func checkDestroy(s *terraform.State) error {
} }
return nil return nil
} }
func TestValidateAggregatorMethod(t *testing.T) {
validMethods := []string{
"average",
"max",
"min",
"sum",
}
for _, v := range validMethods {
_, errors := validateAggregatorMethod(v, "request")
if len(errors) != 0 {
t.Fatalf("%q should be a valid aggregator method: %q", v, errors)
}
}
invalidMethods := []string{
"avg",
"suM",
"m",
"foo",
}
for _, v := range invalidMethods {
_, errors := validateAggregatorMethod(v, "request")
if len(errors) == 0 {
t.Fatalf("%q should be an invalid aggregator method", v)
}
}
}

View File

@ -109,7 +109,8 @@ Nested `graph` `marker` blocks have the following structure:
Nested `graph` `request` blocks have the following structure: Nested `graph` `request` blocks have the following structure:
* `q` - (Required) The query of the request. Pro tip: Use the JSON tab inside the Datadog UI to help build you query strings. * `q` - (Required) The query of the request. Pro tip: Use the JSON tab inside the Datadog UI to help build you query strings.
* `stacked` - (Optional) Boolean value to determin if this is this a stacked area graph. Default: false (line chart). * `aggregator` - (Optional) The aggregation method used when the number of data points outnumbers the max that can be shown.
* `stacked` - (Optional) Boolean value to determine if this is this a stacked area graph. Default: false (line chart).
* `type` - (Optional) Choose how to draw the graph. For example: "lines", "bars" or "areas". Default: "lines". * `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. * `style` - (Optional) Nested block to customize the graph style.