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

feat(service): add mqtt service #149

Closed

Conversation

Eugeniosales
Copy link

@Eugeniosales Eugeniosales commented Mar 15, 2021

This adds a custom mqtt service as notification options that just publishes the message to a mqtt server such as mosquitto. This feature aims to contribute with the Issue 86 and Issue 710

url := "mqtt://example.com:1083?topic=custom_topic"
err := shoutrrr.Send(url, "Message published through mqtt")

The TLS connection option still needs to be added and some tests, but we would like to get a feedback and keep working on it. Thanks!

@codecov
Copy link

codecov bot commented Mar 15, 2021

Codecov Report

Merging #149 (8c17b96) into main (e156cfd) will increase coverage by 1.09%.
The diff coverage is 100.00%.

❗ Current head 8c17b96 differs from pull request most recent head 37c66fa. Consider uploading reports for the commit 37c66fa to get more accurate results
Impacted file tree graph

@@            Coverage Diff             @@
##             main     #149      +/-   ##
==========================================
+ Coverage   63.08%   64.17%   +1.09%     
==========================================
  Files          79       70       -9     
  Lines        2487     2010     -477     
==========================================
- Hits         1569     1290     -279     
+ Misses        780      606     -174     
+ Partials      138      114      -24     
Impacted Files Coverage Δ
pkg/router/servicemap.go 100.00% <100.00%> (ø)
pkg/format/format.go 0.00% <0.00%> (-100.00%) ⬇️
pkg/format/format_query.go 0.00% <0.00%> (-78.13%) ⬇️
pkg/format/prop_key_resolver.go 0.00% <0.00%> (-76.93%) ⬇️
pkg/format/field_info.go 52.50% <0.00%> (-11.95%) ⬇️
pkg/format/enum_formatter.go 60.00% <0.00%> (-10.00%) ⬇️
pkg/format/formatter.go 63.33% <0.00%> (-3.34%) ⬇️
pkg/services/teams/teams_config.go 79.24% <0.00%> (-1.46%) ⬇️
pkg/format/node.go 90.44% <0.00%> (-0.74%) ⬇️
pkg/router/router.go 66.30% <0.00%> (-0.02%) ⬇️
... and 34 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update e156cfd...37c66fa. Read the comment docs.

Copy link
Member

@piksel piksel left a comment

Choose a reason for hiding this comment

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

Yeah, there are some things that needs addressing. I know that this isn't the easiest API to implement, so don't be too disheartened😄

As a global comment, you probably need to run go fmt on the code, since it's not formatted.
Also, you do still have a lot of code copied from the telegram service that probably shouldn't be used (I added a comment about it as well, since you are now sending telegram API messages to MQTT)

pkg/services/mqtt/mqtt.go Outdated Show resolved Hide resolved
pkg/services/mqtt/mqtt.go Outdated Show resolved Hide resolved
pkg/services/mqtt/mqtt_config.go Outdated Show resolved Hide resolved
pkg/services/mqtt/mqtt_config.go Outdated Show resolved Hide resolved
pkg/services/mqtt/mqtt_config.go Outdated Show resolved Hide resolved
pkg/services/mqtt/mqtt_config.go Outdated Show resolved Hide resolved
pkg/services/mqtt/mqtt.go Outdated Show resolved Hide resolved
pkg/services/mqtt/mqtt_json.go Outdated Show resolved Hide resolved
@piksel piksel marked this pull request as draft March 15, 2021 17:58
@Eugeniosales
Copy link
Author

Eugeniosales commented Apr 7, 2021

@piksel , in this update, we solved the issues that you pointed out. Also, we added the TLS option and some docs.

@Eugeniosales Eugeniosales marked this pull request as ready for review April 7, 2021 02:15
@piksel piksel self-requested a review April 7, 2021 07:59
Copy link
Member

@simskij simskij left a comment

Choose a reason for hiding this comment

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

Could you please complement your implementation with some tests verifying the intended behavior? Thanks

When generating a config object with/without optional arguments
@simskij
Copy link
Member

simskij commented May 9, 2021

I have nothing more to add. @piksel, if you feel that your feedback has been addressed, feel free to merge. Thank you @Mexazonic and @Eugeniosales for your contributions! 🔥

@Eugeniosales Eugeniosales requested a review from simskij May 17, 2021 20:36
@Eugeniosales
Copy link
Author

Is there anything more to be addressed, @piksel? If so, we'd like to get a feedback and keep working on it.

@piksel
Copy link
Member

piksel commented Jun 17, 2021

Sorry, I have just been busy with other projects. Will get to it soon, I promise!

Copy link
Member

@piksel piksel left a comment

Choose a reason for hiding this comment

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

Nice work! The username and password ought to be specified using URL user:pass fields, both for conistency and some planned logging features (hiding credentials by default in logging). I have marked these suggestions with (URL creds) so that they can be batch-merged if you want.
There is also some concern regarding the TLS configuration, but it should be fairly easy to fix!

func (config *Config) getURL(resolver types.ConfigQueryResolver) *url.URL {

return &url.URL{
Host: fmt.Sprintf("%s:%d", config.Host, config.Port),
Copy link
Member

Choose a reason for hiding this comment

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

(URL creds)

Suggested change
Host: fmt.Sprintf("%s:%d", config.Host, config.Port),
User: util.URLUserPassword(config.Username, config.Password),
Host: fmt.Sprintf("%s:%d", config.Host, config.Port),

"strconv"

"github.com/containrrr/shoutrrr/pkg/format"
"github.com/containrrr/shoutrrr/pkg/types"
Copy link
Member

Choose a reason for hiding this comment

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

(URL creds)

Suggested change
"github.com/containrrr/shoutrrr/pkg/types"
"github.com/containrrr/shoutrrr/pkg/types"
"github.com/containrrr/shoutrrr/pkg/util"

Comment on lines +23 to +24
Username string `key:"username" default:"" desc:"username for auth"`
Password string `key:"password" default:"" desc:"password for auth"`
Copy link
Member

Choose a reason for hiding this comment

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

(URL creds)

Suggested change
Username string `key:"username" default:"" desc:"username for auth"`
Password string `key:"password" default:"" desc:"password for auth"`
Username string `key:"username" default:"" desc:"username for auth" url:"User"`
Password string `key:"password" default:"" desc:"password for auth" url:"Pass"`

// GetTLSConfig returns the configuration with the certificates for TLS
func (config *Config) GetTLSConfig() *tls.Config {
certpool := x509.NewCertPool()
ca, err := ioutil.ReadFile("ca.crt")
Copy link
Member

Choose a reason for hiding this comment

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

Requiring the files to have this specific name and be in the working directory of the consuming app makes this really hard to use. Ideally, we should add some kind of generic way to add files/blobs to services (mostly for TLS, so perhaps even a specific TLS-cert interface...)
Right now, this should at least be configurable in the config struct.

Copy link
Member

Choose a reason for hiding this comment

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

Implemented in #185

RootCAs: certpool,
ClientAuth: tls.NoClientCert,
ClientCAs: nil,
InsecureSkipVerify: true,
Copy link
Member

Choose a reason for hiding this comment

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

What is the point of loading custom certs when verification is disabled? This should absolutely not be the default.

Comment on lines +12 to +38
## Parameters Description

- **Host** - MQTT broker server hostname or IP address (**Required**)
Default: _empty_
Aliases: `host`

- **Port** - MQTT server port, common ones are 8883 for TCP/TLS and 1883 for TCP (**Required**)
Default: `8883`

- **Topic** - Topic where the message is sent (**Required**)
Default: _empty_
Aliases: `Topic`

- **DisableTLS** - disable TLS/SSL Configurations
Default: `false`

- **ClientID** - The client identifier (ClientID) identifies each MQTT client that connects to an MQTT
Default: _empty_
Aliases: `clientID`

- **Username** - name of the sender to auth
Default: _empty_
Aliases: `clientID`

- **Password** - authentication password or hash
Default: _empty_
Aliases: `password`
Copy link
Member

Choose a reason for hiding this comment

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

This can auto-generated from the config tags

Suggested change
## Parameters Description
- **Host** - MQTT broker server hostname or IP address (**Required**)
Default: _empty_
Aliases: `host`
- **Port** - MQTT server port, common ones are 8883 for TCP/TLS and 1883 for TCP (**Required**)
Default: `8883`
- **Topic** - Topic where the message is sent (**Required**)
Default: _empty_
Aliases: `Topic`
- **DisableTLS** - disable TLS/SSL Configurations
Default: `false`
- **ClientID** - The client identifier (ClientID) identifies each MQTT client that connects to an MQTT
Default: _empty_
Aliases: `clientID`
- **Username** - name of the sender to auth
Default: _empty_
Aliases: `clientID`
- **Password** - authentication password or hash
Default: _empty_
Aliases: `password`
--8<-- "docs/services/mqtt/config.md"

## Optional parameters

You can optionally specify the **`disableTLS`**, **`clientID`**, **`username`** and **`password`** parameters in the URL:
_mqtt://**`host`**:**`port`**?topic=**`topic`**&disableTLS=true&clientID=**`clientID`**&username=**`username`**&password:**`password`**_
Copy link
Member

Choose a reason for hiding this comment

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

(URL creds)

Suggested change
_mqtt://**`host`**:**`port`**?topic=**`topic`**&disableTLS=true&clientID=**`clientID`**&username=**`username`**&password:**`password`**_
_mqtt://**`username`**:**`password`**@**`host`**:**`port`**?topic=**`topic`**&disableTLS=true&clientID=**`clientID`**&username=**`username`**&password:**`password`**_


func (config *Config) setURL(resolver types.ConfigQueryResolver, url *url.URL) error {

config.Host = url.Hostname()
Copy link
Member

Choose a reason for hiding this comment

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

(URL creds)

Suggested change
config.Host = url.Hostname()
config.Host = url.Hostname()
config.Username = url.User.Username()
password, _ := url.User.Password()
config.Password = password

@piksel piksel added the Type: Enhancement New feature or request label Aug 31, 2021
@lokanx
Copy link

lokanx commented Dec 14, 2021

Any progress on this?
Would be an awesome feature to have.

@simskij
Copy link
Member

simskij commented May 26, 2022

This has been untouched for so long that I wouldn't want to merge it. If anyone wants to pick it up again, or provide a completely different implementation, feel free to open a new PR. Closing.

@simskij simskij closed this May 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants