Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alerting: Add MQTT notifications receiver #1746

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions docs/resources/contact_point.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -212,6 +213,29 @@ Read-Only:
- `uid` (String) The UID of the contact point.


<a id="nestedblock--mqtt"></a>
### 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.


<a id="nestedblock--oncall"></a>
### Nested Schema for `oncall`

Expand Down
10 changes: 10 additions & 0 deletions examples/resources/grafana_contact_point/_acc_receiver_types.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ var (
googleChatNotifier{},
kafkaNotifier{},
lineNotifier{},
mqttNotifier{},
oncallNotifier{},
opsGenieNotifier{},
pagerDutyNotifier{},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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, &notifier, "brokerUrl", "broker_url")
packNotifierStringField(&settings, &notifier, "topic", "topic")
packNotifierStringField(&settings, &notifier, "clientId", "client_id")
packNotifierStringField(&settings, &notifier, "messageFormat", "message_format")
packNotifierStringField(&settings, &notifier, "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 {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,36 @@ func TestAccContactPoint_notifiers10_3(t *testing.T) {
})
}

func TestAccContactPoint_notifiers11_3(t *testing.T) {
testutils.CheckCloudInstanceTestsEnabled(t) // Use 11.3 when released
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should it have testutils.CheckOSSTestsEnabled(t, ">=11.3.0")?


var points models.ContactPoints

resource.ParallelTest(t, resource.TestCase{
ProtoV5ProviderFactories: testutils.ProtoV5ProviderFactories,
// Implicitly tests deletion.
CheckDestroy: alertingContactPointCheckExists.destroyed(&points, nil),
Steps: []resource.TestStep{
// Test creation.
{
Config: testutils.TestAccExample(t, "resources/grafana_contact_point/_acc_receiver_types_10_3.tf"),
Check: resource.ComposeTestCheckFunc(
checkAlertingContactPointExistsWithLength("grafana_contact_point.receiver_types", &points, 1),
// 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"),
),
},
},
})
}

func TestAccContactPoint_sensitiveData(t *testing.T) {
testutils.CheckOSSTestsEnabled(t, ">=9.1.0")

Expand Down
Loading