mirror of
https://github.com/crazy-max/diun.git
synced 2026-01-04 20:15:01 +01:00
Add MQTT notification (#192)
This commit is contained in:
@@ -205,6 +205,7 @@ Can be transposed to:
|
||||
* [gotify](../notif/gotify.md)
|
||||
* [mail](../notif/mail.md)
|
||||
* [matrix](../notif/matrix.md)
|
||||
* [mqtt](../notif/mqtt.md)
|
||||
* [rocketchat](../notif/rocketchat.md)
|
||||
* [script](../notif/script.md)
|
||||
* [slack](../notif/slack.md)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* [`gotify`](../notif/gotify.md)
|
||||
* [`mail`](../notif/mail.md)
|
||||
* [`matrix`](../notif/matrix.md)
|
||||
* [`mqtt`](../notif/mqtt.md)
|
||||
* [`rocketchat`](../notif/rocketchat.md)
|
||||
* [`script`](../notif/script.md)
|
||||
* [`slack`](../notif/slack.md)
|
||||
|
||||
51
docs/notif/mqtt.md
Normal file
51
docs/notif/mqtt.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Mqtt notifications
|
||||
|
||||
You can send notifications to any mqtt compatible server with the following settings.
|
||||
|
||||
## Configuration
|
||||
|
||||
!!! example "File"
|
||||
```yaml
|
||||
notif:
|
||||
mqtt:
|
||||
host: localhost
|
||||
port: 1883
|
||||
username: guest
|
||||
password: guest
|
||||
topic: docker/diun
|
||||
client: diun
|
||||
qos: 0
|
||||
```
|
||||
|
||||
| Name | Default | Description |
|
||||
|--------------------|---------------|---------------|
|
||||
| `host`[^1] | `localhost` | MQTT server host |
|
||||
| `port`[^1] | `1883` | MQTT server port |
|
||||
| `client`[^1] | `diun-client` | Name of the client which connects to the server |
|
||||
| `topic`[^1] | `docker/diun` | Topic the message will be sent to |
|
||||
| `username` | | MQTT username |
|
||||
| `usernameFile` | | Use content of secret file as MQTT username if `username` not defined |
|
||||
| `password` | | MQTT password |
|
||||
| `passwordFile` | | Use content of secret file as MQTT password if `password` not defined |
|
||||
| `qos` | `0` | Topic the message will be sent to |
|
||||
|
||||
## Sample
|
||||
|
||||
The JSON response will look like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"diun_version": "0.3.0",
|
||||
"hostname": "myserver",
|
||||
"status": "new",
|
||||
"provider": "file",
|
||||
"image": "docker.io/crazymax/swarm-cronjob:0.2.1",
|
||||
"hub_link": "https://hub.docker.com/r/crazymax/swarm-cronjob",
|
||||
"mime_type": "application/vnd.docker.distribution.manifest.v2+json",
|
||||
"digest": "sha256:5913d4b5e8dc15430c2f47f40e43ab2ca7f2b8df5eee5db4d5c42311e08dfb79",
|
||||
"created": "2019-01-24T10:26:49.152006005Z",
|
||||
"platform": "linux/amd64"
|
||||
}
|
||||
```
|
||||
|
||||
[^1]: Value required
|
||||
1
go.mod
1
go.mod
@@ -9,6 +9,7 @@ require (
|
||||
github.com/crazy-max/gonfig v0.3.0
|
||||
github.com/docker/docker v1.4.2-0.20200204220554-5f6d6f3f2203
|
||||
github.com/docker/go-connections v0.4.0
|
||||
github.com/eclipse/paho.mqtt.golang v1.2.0
|
||||
github.com/go-gomail/gomail v0.0.0-20160411212932-81ebce5c23df
|
||||
github.com/go-playground/validator/v10 v10.4.1
|
||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible
|
||||
|
||||
2
go.sum
2
go.sum
@@ -111,6 +111,8 @@ github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU
|
||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
|
||||
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||
github.com/eclipse/paho.mqtt.golang v1.2.0 h1:1F8mhG9+aO5/xpdtFkW4SxOJB67ukuDC3t2y2qayIX0=
|
||||
github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts=
|
||||
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
|
||||
@@ -29,6 +29,7 @@ type Notif struct {
|
||||
Gotify *NotifGotify `yaml:"gotify,omitempty" json:"gotify,omitempty"`
|
||||
Mail *NotifMail `yaml:"mail,omitempty" json:"mail,omitempty"`
|
||||
Matrix *NotifMatrix `yaml:"matrix,omitempty" json:"matrix,omitempty"`
|
||||
Mqtt *NotifMqtt `yaml:"mqtt,omitempty" json:"mqtt,omitempty"`
|
||||
RocketChat *NotifRocketChat `yaml:"rocketchat,omitempty" json:"rocketchat,omitempty"`
|
||||
Script *NotifScript `yaml:"script,omitempty" json:"script,omitempty"`
|
||||
Slack *NotifSlack `yaml:"slack,omitempty" json:"slack,omitempty"`
|
||||
|
||||
29
internal/model/notif_mqtt.go
Normal file
29
internal/model/notif_mqtt.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package model
|
||||
|
||||
type NotifMqtt struct {
|
||||
Username string `yaml:"username,omitempty" json:"username,omitempty" validate:"omitempty"`
|
||||
UsernameFile string `yaml:"usernameFile,omitempty" json:"usernameFile,omitempty" validate:"omitempty,file"`
|
||||
Password string `yaml:"password,omitempty" json:"password,omitempty" validate:"omitempty"`
|
||||
PasswordFile string `yaml:"passwordFile,omitempty" json:"passwordFile,omitempty" validate:"omitempty,file"`
|
||||
Host string `yaml:"host,omitempty" json:"host,omitempty" validate:"required"`
|
||||
Port int `yaml:"port,omitempty" json:"port,omitempty" validate:"required,min=1"`
|
||||
Topic string `yaml:"topic,omitempty" json:"topic,omitempty" validate:"required"`
|
||||
Client string `yaml:"client,omitempty" json:"client,omitempty" validate:"required"`
|
||||
QoS int `yaml:"qos,omitempty" json:"qos,omitempty" validate:"omitempty"`
|
||||
}
|
||||
|
||||
// GetDefaults gets the default values
|
||||
func (s *NotifMqtt) GetDefaults() *NotifMqtt {
|
||||
n := &NotifMqtt{}
|
||||
n.SetDefaults()
|
||||
return n
|
||||
}
|
||||
|
||||
// SetDefaults sets the default values
|
||||
func (s *NotifMqtt) SetDefaults() {
|
||||
s.Host = "localhost"
|
||||
s.Port = 1883
|
||||
s.Topic = "docker/diun"
|
||||
s.Client = "diun-client"
|
||||
s.QoS = 0
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package notif
|
||||
|
||||
import (
|
||||
"github.com/crazy-max/diun/v4/internal/notif/mqtt"
|
||||
"strings"
|
||||
|
||||
"github.com/crazy-max/diun/v4/internal/model"
|
||||
@@ -55,6 +56,9 @@ func New(config *model.Notif, meta model.Meta) (*Client, error) {
|
||||
if config.Matrix != nil {
|
||||
c.notifiers = append(c.notifiers, matrix.New(config.Matrix, meta))
|
||||
}
|
||||
if config.Mqtt != nil {
|
||||
c.notifiers = append(c.notifiers, mqtt.New(config.Mqtt, meta))
|
||||
}
|
||||
if config.RocketChat != nil {
|
||||
c.notifiers = append(c.notifiers, rocketchat.New(config.RocketChat, meta))
|
||||
}
|
||||
|
||||
94
internal/notif/mqtt/client.go
Normal file
94
internal/notif/mqtt/client.go
Normal file
@@ -0,0 +1,94 @@
|
||||
package mqtt
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/crazy-max/diun/v4/pkg/utl"
|
||||
"time"
|
||||
|
||||
"github.com/crazy-max/diun/v4/internal/model"
|
||||
"github.com/crazy-max/diun/v4/internal/notif/notifier"
|
||||
MQTT "github.com/eclipse/paho.mqtt.golang"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// Client represents an active mqtt notification object
|
||||
type Client struct {
|
||||
*notifier.Notifier
|
||||
cfg *model.NotifMqtt
|
||||
meta model.Meta
|
||||
logger zerolog.Logger
|
||||
}
|
||||
|
||||
// New creates a new mqtt notification instance
|
||||
func New(config *model.NotifMqtt, meta model.Meta) notifier.Notifier {
|
||||
return notifier.Notifier{
|
||||
Handler: &Client{
|
||||
cfg: config,
|
||||
meta: meta,
|
||||
logger: log.With().Str("notif", "mqtt").Logger(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Name returns notifier's name
|
||||
func (c *Client) Name() string {
|
||||
return "mqtt"
|
||||
}
|
||||
|
||||
// Send creates and sends a mqtt notification with an entry
|
||||
func (c *Client) Send(entry model.NotifEntry) error {
|
||||
username, err := utl.GetSecret(c.cfg.Username, c.cfg.UsernameFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
password, err := utl.GetSecret(c.cfg.Password, c.cfg.PasswordFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
broker := fmt.Sprintf("tcp://%s:%d", c.cfg.Host, c.cfg.Port)
|
||||
opts := MQTT.NewClientOptions().AddBroker(broker).SetClientID(c.cfg.Client)
|
||||
opts.Username = username
|
||||
opts.Password = password
|
||||
|
||||
var client = MQTT.NewClient(opts)
|
||||
if token := client.Connect(); token.Wait() && token.Error() != nil {
|
||||
return token.Error()
|
||||
}
|
||||
|
||||
log.Debug().Msgf("Connected to broker: %s", broker)
|
||||
|
||||
message, err := json.Marshal(struct {
|
||||
Version string `json:"diun_version"`
|
||||
Hostname string `json:"hostname"`
|
||||
Status string `json:"status"`
|
||||
Provider string `json:"provider"`
|
||||
Image string `json:"image"`
|
||||
HubLink string `json:"hub_link"`
|
||||
MIMEType string `json:"mime_type"`
|
||||
Created *time.Time `json:"created"`
|
||||
Platform string `json:"platform"`
|
||||
}{
|
||||
Version: c.meta.Version,
|
||||
Hostname: c.meta.Hostname,
|
||||
Status: string(entry.Status),
|
||||
Provider: entry.Provider,
|
||||
Image: entry.Image.String(),
|
||||
HubLink: entry.Image.HubLink,
|
||||
MIMEType: entry.Manifest.MIMEType,
|
||||
Created: entry.Manifest.Created,
|
||||
Platform: entry.Manifest.Platform,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debug().Msgf("Publishing to topic: %s", c.cfg.Topic)
|
||||
token := client.Publish(c.cfg.Topic, byte(c.cfg.QoS), false, message)
|
||||
token.Wait()
|
||||
|
||||
return token.Error()
|
||||
}
|
||||
Reference in New Issue
Block a user