diff --git a/docs/resources/contact_point.md b/docs/resources/contact_point.md index 058b2f72a..3c31518a9 100644 --- a/docs/resources/contact_point.md +++ b/docs/resources/contact_point.md @@ -50,6 +50,7 @@ resource "grafana_contact_point" "my_contact_point" { - `googlechat` (Block Set) A contact point that sends notifications to Google Chat. (see [below for nested schema](#nestedblock--googlechat)) - `kafka` (Block Set) A contact point that publishes notifications to Apache Kafka topics. (see [below for nested schema](#nestedblock--kafka)) - `line` (Block Set) A contact point that sends notifications to LINE.me. (see [below for nested schema](#nestedblock--line)) +- `mqtt` (Block Set) A contact point that sends notifications to an MQTT broker. (see [below for nested schema](#nestedblock--mqtt)) - `oncall` (Block Set) A contact point that sends notifications to Grafana On-Call. (see [below for nested schema](#nestedblock--oncall)) - `opsgenie` (Block Set) A contact point that sends notifications to OpsGenie. (see [below for nested schema](#nestedblock--opsgenie)) - `org_id` (String) The Organization ID. If not set, the Org ID defined in the provider block will be used. @@ -212,6 +213,29 @@ Read-Only: - `uid` (String) The UID of the contact point. + +### Nested Schema for `mqtt` + +Required: + +- `broker_url` (String) The URL of the MQTT broker. +- `topic` (String) The topic to publish messages to. + +Optional: + +- `client_id` (String) The client ID to use when connecting to the broker. +- `disable_resolve_message` (Boolean) Whether to disable sending resolve messages. Defaults to `false`. +- `insecure_skip_verify` (Boolean) Whether to skip verification of the server's certificate chain and host name. Defaults to `false`. +- `message_format` (String) The format of the message to send. Supported values are `json` and `text`. +- `password` (String, Sensitive) The password to use when connecting to the broker. +- `settings` (Map of String, Sensitive) Additional custom properties to attach to the notifier. Defaults to `map[]`. +- `username` (String) The username to use when connecting to the broker. + +Read-Only: + +- `uid` (String) The UID of the contact point. + + ### Nested Schema for `oncall` diff --git a/examples/resources/grafana_contact_point/_acc_receiver_types.tf b/examples/resources/grafana_contact_point/_acc_receiver_types.tf index 752b5dda2..52938a087 100644 --- a/examples/resources/grafana_contact_point/_acc_receiver_types.tf +++ b/examples/resources/grafana_contact_point/_acc_receiver_types.tf @@ -54,6 +54,16 @@ resource "grafana_contact_point" "receiver_types" { description = "description" } + mqtt { + broker_url = "tcp://localhost:1883" + topic = "grafana/alerts" + client_id = "client_id" + message_format = "json" + username = "username" + password = "password" + insecure_skip_verify = false + } + opsgenie { url = "http://opsgenie-api" api_key = "token" diff --git a/internal/resources/grafana/resource_alerting_contact_point.go b/internal/resources/grafana/resource_alerting_contact_point.go index 9f43d236c..0eac8352a 100644 --- a/internal/resources/grafana/resource_alerting_contact_point.go +++ b/internal/resources/grafana/resource_alerting_contact_point.go @@ -28,6 +28,7 @@ var ( googleChatNotifier{}, kafkaNotifier{}, lineNotifier{}, + mqttNotifier{}, oncallNotifier{}, opsGenieNotifier{}, pagerDutyNotifier{}, diff --git a/internal/resources/grafana/resource_alerting_contact_point_notifiers.go b/internal/resources/grafana/resource_alerting_contact_point_notifiers.go index fee1ef7e3..16af413f8 100644 --- a/internal/resources/grafana/resource_alerting_contact_point_notifiers.go +++ b/internal/resources/grafana/resource_alerting_contact_point_notifiers.go @@ -619,6 +619,105 @@ func (o lineNotifier) unpack(raw interface{}, name string) *models.EmbeddedConta } } +type mqttNotifier struct{} + +var _ notifier = (*mqttNotifier)(nil) + +func (o mqttNotifier) meta() notifierMeta { + return notifierMeta{ + field: "mqtt", + typeStr: "mqtt", + desc: "A contact point that sends notifications to an MQTT broker.", + secureFields: []string{"password"}, + } +} + +func (o mqttNotifier) schema() *schema.Resource { + r := commonNotifierResource() + r.Schema["broker_url"] = &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The URL of the MQTT broker.", + } + r.Schema["topic"] = &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The topic to publish messages to.", + } + r.Schema["client_id"] = &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The client ID to use when connecting to the broker.", + } + r.Schema["message_format"] = &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"json", "text"}, false), + Description: "The format of the message to send. Supported values are `json` and `text`.", + } + r.Schema["username"] = &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The username to use when connecting to the broker.", + } + r.Schema["password"] = &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Sensitive: true, + Description: "The password to use when connecting to the broker.", + } + r.Schema["insecure_skip_verify"] = &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "Whether to skip verification of the server's certificate chain and host name.", + } + return r +} + +func (o mqttNotifier) pack(p *models.EmbeddedContactPoint, data *schema.ResourceData) (interface{}, error) { + notifier := packCommonNotifierFields(p) + settings := p.Settings.(map[string]interface{}) + + packNotifierStringField(&settings, ¬ifier, "brokerUrl", "broker_url") + packNotifierStringField(&settings, ¬ifier, "topic", "topic") + packNotifierStringField(&settings, ¬ifier, "clientId", "client_id") + packNotifierStringField(&settings, ¬ifier, "messageFormat", "message_format") + packNotifierStringField(&settings, ¬ifier, "username", "username") + if v, ok := settings["insecureSkipVerify"]; ok && v != nil { + notifier["insecure_skip_verify"] = v.(bool) + delete(settings, "insecureSkipVerify") + } + + packSecureFields(notifier, getNotifierConfigFromStateWithUID(data, o, p.UID), o.meta().secureFields) + + notifier["settings"] = packSettings(p) + return notifier, nil +} + +func (o mqttNotifier) unpack(raw interface{}, name string) *models.EmbeddedContactPoint { + json := raw.(map[string]interface{}) + uid, disableResolve, settings := unpackCommonNotifierFields(json) + + unpackNotifierStringField(&json, &settings, "broker_url", "brokerUrl") + unpackNotifierStringField(&json, &settings, "topic", "topic") + unpackNotifierStringField(&json, &settings, "client_id", "clientId") + unpackNotifierStringField(&json, &settings, "message_format", "messageFormat") + unpackNotifierStringField(&json, &settings, "username", "username") + unpackNotifierStringField(&json, &settings, "password", "password") + if v, ok := json["insecure_skip_verify"]; ok && v != nil { + settings["insecureSkipVerify"] = v.(bool) + } + + return &models.EmbeddedContactPoint{ + UID: uid, + Name: name, + Type: common.Ref(o.meta().typeStr), + DisableResolveMessage: disableResolve, + Settings: settings, + } +} + type oncallNotifier struct { } diff --git a/internal/resources/grafana/resource_alerting_contact_point_test.go b/internal/resources/grafana/resource_alerting_contact_point_test.go index a14c91bf4..064751387 100644 --- a/internal/resources/grafana/resource_alerting_contact_point_test.go +++ b/internal/resources/grafana/resource_alerting_contact_point_test.go @@ -203,6 +203,15 @@ func TestAccContactPoint_notifiers(t *testing.T) { resource.TestCheckResourceAttr("grafana_contact_point.receiver_types", "line.0.token", "token"), resource.TestCheckResourceAttr("grafana_contact_point.receiver_types", "line.0.title", "title"), resource.TestCheckResourceAttr("grafana_contact_point.receiver_types", "line.0.description", "description"), + // mqtt + resource.TestCheckResourceAttr("grafana_contact_point.receiver_types", "mqtt.#", "1"), + resource.TestCheckResourceAttr("grafana_contact_point.receiver_types", "mqtt.0.broker_url", "*broker_url"), + resource.TestCheckResourceAttr("grafana_contact_point.receiver_types", "mqtt.0.topic", "*topic"), + resource.TestCheckResourceAttr("grafana_contact_point.receiver_types", "mqtt.0.client_id", "client_id"), + resource.TestCheckResourceAttr("grafana_contact_point.receiver_types", "mqtt.0.message_format", "json"), + resource.TestCheckResourceAttr("grafana_contact_point.receiver_types", "mqtt.0.username", "username"), + resource.TestCheckResourceAttr("grafana_contact_point.receiver_types", "mqtt.0.password", "password"), + resource.TestCheckResourceAttr("grafana_contact_point.receiver_types", "mqtt.0.insecure_skip_verify", "true"), // opsgenie resource.TestCheckResourceAttr("grafana_contact_point.receiver_types", "opsgenie.#", "1"), resource.TestCheckResourceAttr("grafana_contact_point.receiver_types", "opsgenie.0.url", "http://opsgenie-api"),