Skip to content

Commit

Permalink
Merge pull request #201 from tosuke/query-monitor
Browse files Browse the repository at this point in the history
Added support for monitors with PromQL
  • Loading branch information
azukiazusa1 authored May 16, 2024
2 parents 8038e70 + 585e8ed commit 75cb7e1
Show file tree
Hide file tree
Showing 7 changed files with 315 additions and 7 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.18
require (
github.com/golangci/golangci-lint v1.50.1
github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.0
github.com/mackerelio/mackerel-client-go v0.26.0
github.com/mackerelio/mackerel-client-go v0.31.0
)

require (
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,8 @@ github.com/lufeee/execinquery v1.2.1 h1:hf0Ems4SHcUGBxpGN7Jz78z1ppVkP/837ZlETPCE
github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM=
github.com/mackerelio/mackerel-client-go v0.26.0 h1:72hj2zw/rqTUNMNokenRxs6KfJ1aVxRHpZT8X4eOUuA=
github.com/mackerelio/mackerel-client-go v0.26.0/go.mod h1:b4qVMQi+w4rxtKQIFycLWXNBtIi9d0r571RzYmg/aXo=
github.com/mackerelio/mackerel-client-go v0.31.0 h1:oUBwuJzZkvhSFf7C7zpOBej8jM0kITUz7eVMAINIfO4=
github.com/mackerelio/mackerel-client-go v0.31.0/go.mod h1:b4qVMQi+w4rxtKQIFycLWXNBtIi9d0r571RzYmg/aXo=
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI=
Expand Down
28 changes: 28 additions & 0 deletions mackerel/data_source_mackerel_monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,34 @@ func dataSourceMackerelMonitor() *schema.Resource {
},
},
},
"query": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"query": {
Type: schema.TypeString,
Computed: true,
},
"legend": {
Type: schema.TypeString,
Computed: true,
},
"operator": {
Type: schema.TypeString,
Computed: true,
},
"warning": {
Type: schema.TypeString,
Computed: true,
},
"critical": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
},
}
}
Expand Down
65 changes: 65 additions & 0 deletions mackerel/data_source_mackerel_monitor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func TestAccDataSourceMackerelMonitorHostMetric(t *testing.T) {
resource.TestCheckResourceAttr(dsName, "external.#", "0"),
resource.TestCheckResourceAttr(dsName, "expression.#", "0"),
resource.TestCheckResourceAttr(dsName, "anomaly_detection.#", "0"),
resource.TestCheckResourceAttr(dsName, "query.#", "0"),
),
},
},
Expand Down Expand Up @@ -74,6 +75,7 @@ func TestAccDataSourceMackerelMonitorConnectivity(t *testing.T) {
resource.TestCheckResourceAttr(dsName, "external.#", "0"),
resource.TestCheckResourceAttr(dsName, "expression.#", "0"),
resource.TestCheckResourceAttr(dsName, "anomaly_detection.#", "0"),
resource.TestCheckResourceAttr(dsName, "query.#", "0"),
),
},
},
Expand Down Expand Up @@ -115,6 +117,7 @@ func TestAccDataSourceMackerelMonitorServiceMetric(t *testing.T) {
resource.TestCheckResourceAttr(dsName, "external.#", "0"),
resource.TestCheckResourceAttr(dsName, "expression.#", "0"),
resource.TestCheckResourceAttr(dsName, "anomaly_detection.#", "0"),
resource.TestCheckResourceAttr(dsName, "query.#", "0"),
),
},
},
Expand Down Expand Up @@ -162,6 +165,7 @@ func TestAccDataSourceMackerelMonitorExternal(t *testing.T) {
),
resource.TestCheckResourceAttr(dsName, "expression.#", "0"),
resource.TestCheckResourceAttr(dsName, "anomaly_detection.#", "0"),
resource.TestCheckResourceAttr(dsName, "query.#", "0"),
),
},
},
Expand Down Expand Up @@ -197,6 +201,7 @@ func TestAccDataSourceMackerelMonitorExpression(t *testing.T) {
resource.TestCheckResourceAttr(dsName, "expression.0.critical", "0.9"),
),
resource.TestCheckResourceAttr(dsName, "anomaly_detection.#", "0"),
resource.TestCheckResourceAttr(dsName, "query.#", "0"),
),
},
},
Expand Down Expand Up @@ -233,6 +238,44 @@ func TestAccDataSourceMackerelMonitorAnomalyDetection(t *testing.T) {
resource.TestCheckResourceAttr(dsName, "anomaly_detection.0.training_period_from", "1577836800"),
resource.TestCheckResourceAttr(dsName, "anomaly_detection.0.scopes.#", "1"),
),
resource.TestCheckResourceAttr(dsName, "query.#", "0"),
),
},
},
})
}

func TestAccDataSourceMackerelMonitorQuery(t *testing.T) {
dsName := "data.mackerel_monitor.foo"
rand := acctest.RandString(5)
name := fmt.Sprintf("tf-monitor-%s", rand)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: testAccProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccDataSourceMackerelMonitorConfigQuery(name),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet(dsName, "id"),
resource.TestCheckResourceAttr(dsName, "name", name),
resource.TestCheckResourceAttr(dsName, "memo", "This monitor is managed by Terraform."),
resource.TestCheckResourceAttr(dsName, "is_mute", "true"),
resource.TestCheckResourceAttr(dsName, "notification_interval", "30"),
resource.TestCheckResourceAttr(dsName, "host_metric.#", "0"),
resource.TestCheckResourceAttr(dsName, "connectivity.#", "0"),
resource.TestCheckResourceAttr(dsName, "service_metric.#", "0"),
resource.TestCheckResourceAttr(dsName, "external.#", "0"),
resource.TestCheckResourceAttr(dsName, "expression.#", "0"),
resource.TestCheckResourceAttr(dsName, "anomaly_detection.#", "0"),
resource.TestCheckResourceAttr(dsName, "query.#", "1"),
resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(dsName, "query.0.query", "container.cpu.utilization{k8s.deployment.name=\"httpbin\"}"),
resource.TestCheckResourceAttr(dsName, "query.0.legend", "cpu.utilization {{k8s.node.name}}"),
resource.TestCheckResourceAttr(dsName, "query.0.operator", ">"),
resource.TestCheckResourceAttr(dsName, "query.0.warning", "70"),
resource.TestCheckResourceAttr(dsName, "query.0.critical", "90"),
),
),
},
},
Expand Down Expand Up @@ -445,3 +488,25 @@ data "mackerel_monitor" "foo" {
}
`, rand, rand, name)
}

func testAccDataSourceMackerelMonitorConfigQuery(name string) string {
return fmt.Sprintf(`
resource "mackerel_monitor" "foo" {
name = "%s"
memo = "This monitor is managed by Terraform."
is_mute = true
notification_interval = 30
query {
query = "container.cpu.utilization{k8s.deployment.name=\"httpbin\"}"
legend = "cpu.utilization {{k8s.node.name}}"
operator = ">"
warning = "70"
critical = "90"
}
}
data "mackerel_monitor" "foo" {
id = mackerel_monitor.foo.id
}
`, name)
}
89 changes: 83 additions & 6 deletions mackerel/resource_mackerel_monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@ import (
"github.com/mackerelio/mackerel-client-go"
)

var (
monitorTypes = []string{
"host_metric",
"connectivity",
"service_metric",
"external",
"expression",
"anomaly_detection",
"query",
}
)

func resourceMackerelMonitor() *schema.Resource {
return &schema.Resource{
CreateContext: resourceMackerelMonitorCreate,
Expand Down Expand Up @@ -42,7 +54,7 @@ func resourceMackerelMonitor() *schema.Resource {
"host_metric": {
Type: schema.TypeList,
Optional: true,
ExactlyOneOf: []string{"host_metric", "connectivity", "service_metric", "external", "expression", "anomaly_detection"},
ExactlyOneOf: monitorTypes,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
Expand Down Expand Up @@ -95,7 +107,7 @@ func resourceMackerelMonitor() *schema.Resource {
"connectivity": {
Type: schema.TypeList,
Optional: true,
ExactlyOneOf: []string{"host_metric", "connectivity", "service_metric", "external", "expression", "anomaly_detection"},
ExactlyOneOf: monitorTypes,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
Expand All @@ -115,7 +127,7 @@ func resourceMackerelMonitor() *schema.Resource {
"service_metric": {
Type: schema.TypeList,
Optional: true,
ExactlyOneOf: []string{"host_metric", "connectivity", "service_metric", "external", "expression", "anomaly_detection"},
ExactlyOneOf: monitorTypes,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
Expand Down Expand Up @@ -177,7 +189,7 @@ func resourceMackerelMonitor() *schema.Resource {
"external": {
Type: schema.TypeList,
Optional: true,
ExactlyOneOf: []string{"host_metric", "connectivity", "service_metric", "external", "expression", "anomaly_detection"},
ExactlyOneOf: monitorTypes,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
Expand Down Expand Up @@ -254,7 +266,7 @@ func resourceMackerelMonitor() *schema.Resource {
"expression": {
Type: schema.TypeList,
Optional: true,
ExactlyOneOf: []string{"host_metric", "connectivity", "service_metric", "external", "expression", "anomaly_detection"},
ExactlyOneOf: monitorTypes,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
Expand Down Expand Up @@ -285,7 +297,7 @@ func resourceMackerelMonitor() *schema.Resource {
"anomaly_detection": {
Type: schema.TypeList,
Optional: true,
ExactlyOneOf: []string{"host_metric", "connectivity", "service_metric", "external", "expression", "anomaly_detection"},
ExactlyOneOf: monitorTypes,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
Expand Down Expand Up @@ -319,6 +331,42 @@ func resourceMackerelMonitor() *schema.Resource {
},
},
},
"query": {
Type: schema.TypeList,
Optional: true,
ExactlyOneOf: monitorTypes,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"query": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"legend": {
Type: schema.TypeString,
Required: true,
},
"operator": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{">", "<"}, false),
},
"warning": {
Type: schema.TypeString,
Optional: true,
AtLeastOneOf: []string{"query.0.warning", "query.0.critical"},
ValidateFunc: ValidateFloatString,
},
"critical": {
Type: schema.TypeString,
Optional: true,
AtLeastOneOf: []string{"query.0.warning", "query.0.critical"},
ValidateFunc: ValidateFloatString,
},
},
},
},
},
}
}
Expand Down Expand Up @@ -382,6 +430,9 @@ func expandMonitor(d *schema.ResourceData) mackerel.Monitor {
if _, ok := d.GetOk("anomaly_detection"); ok {
monitor = expandMonitorAnomalyDetection(d)
}
if _, ok := d.GetOk("query"); ok {
monitor = expandMonitorQuery(d)
}
return monitor
}

Expand Down Expand Up @@ -559,3 +610,29 @@ func expandMonitorAnomalyDetection(d *schema.ResourceData) *mackerel.MonitorAnom
}
return monitor
}

func expandMonitorQuery(d *schema.ResourceData) *mackerel.MonitorQuery {
monitor := &mackerel.MonitorQuery{
Name: d.Get("name").(string),
Memo: d.Get("memo").(string),
Type: "query",
IsMute: d.Get("is_mute").(bool),
NotificationInterval: uint64(d.Get("notification_interval").(int)),
Query: d.Get("query.0.query").(string),
Legend: d.Get("query.0.legend").(string),
Operator: d.Get("query.0.operator").(string),
Warning: nil,
Critical: nil,
}
if warning, ok := d.GetOkExists("query.0.warning"); ok {
if w, err := strconv.ParseFloat(warning.(string), 64); err == nil {
monitor.Warning = &w
}
}
if critical, ok := d.GetOkExists("query.0.critical"); ok {
if c, err := strconv.ParseFloat(critical.(string), 64); err == nil {
monitor.Critical = &c
}
}
return monitor
}
Loading

0 comments on commit 75cb7e1

Please sign in to comment.