Add MQTT notification (#192)

This commit is contained in:
aschoelzhorn
2020-11-02 00:05:46 +01:00
committed by GitHub
parent 9065660e58
commit 4e71b0c4d2
9 changed files with 184 additions and 0 deletions

View File

@@ -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)

View File

@@ -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
View 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
View File

@@ -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
View File

@@ -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=

View File

@@ -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"`

View 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
}

View File

@@ -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))
}

View 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()
}