Esempio n. 1
0
def test_carbon_success_value_metric_from_topic_with_leading_slash(
        srv, caplog):

    item = Item(
        target="test",
        addrs=["localhost", 2003],
        message="42.42",
        data={"topic": "/foo/bar"},
    )

    with caplog.at_level(logging.DEBUG):

        module = load_module_from_file("mqttwarn/services/carbon.py")

        socket_mock = mock.MagicMock()
        module.socket.socket = socket_mock

        outcome = module.plugin(srv, item)
        assert socket_mock.mock_calls == [
            call(),
            call().connect(("localhost", 2003)),
            call().sendall(mock.ANY),
            call().close(),
        ]

        assert outcome is True
        assert "Sending to carbon: foo.bar 42.42" in caplog.text
Esempio n. 2
0
def test_carbon_success_metric_value_timestamp(srv, caplog):

    item = Item(
        target="test",
        addrs=["localhost", 2003],
        message="foo 42.42 1623887596",
        data={},
    )

    with caplog.at_level(logging.DEBUG):

        module = load_module_from_file("mqttwarn/services/carbon.py")

        socket_mock = mock.MagicMock()
        module.socket.socket = socket_mock

        outcome = module.plugin(srv, item)
        assert socket_mock.mock_calls == [
            call(),
            call().connect(("localhost", 2003)),
            call().sendall("foo 42.42 1623887596\n"),
            call().close(),
        ]

        assert outcome is True
        assert "Sending to carbon: foo 42.42 1623887596" in caplog.text
Esempio n. 3
0
def test_pushover_success_with_imagebase64(srv, caplog):

    module = load_module_from_file("mqttwarn/services/pushover.py")

    image = open("./assets/pushover.png", "rb").read()
    item = Item(
        config={},
        target="test",
        addrs=["userkey2", "appkey2"],
        message="⚽ Notification message ⚽",
        data={"imagebase64": base64.encodebytes(image)},
    )

    with caplog.at_level(logging.DEBUG):

        add_successful_mock_response()
        outcome = module.plugin(srv, item)

        # Check response status.
        assert responses.calls[0].response.status_code == 200
        assert responses.calls[0].response.text == '{"status": 1}'

        # Decode multipart request.
        request = responses.calls[0].request
        decoder = MultipartDecoder(request.body, request.headers["Content-Type"])

        content_disposition_headers = []
        contents = {}
        for part in decoder.parts:
            content_disposition_headers.append(part.headers[b"Content-Disposition"])

            key = part.headers[b"Content-Disposition"]
            contents[key] = part.content

        # Proof request has all body parts.
        assert content_disposition_headers == [
            b'form-data; name="user"',
            b'form-data; name="token"',
            b'form-data; name="retry"',
            b'form-data; name="expire"',
            b'form-data; name="message"',
            b'form-data; name="attachment"; filename="image.jpg"',
        ]

        # Proof parameter body parts, modulo image content, have correct values.
        assert list(contents.values())[:-1] == [
            b"userkey2",
            b"appkey2",
            b"60",
            b"3600",
            b"\xe2\x9a\xbd Notification message \xe2\x9a\xbd",
        ]

        # Proof image has content.
        assert len(decoder.parts[-1].content) == 45628

        assert outcome is True
        assert "Sending pushover notification to test" in caplog.text
        assert "Successfully sent pushover notification" in caplog.text
Esempio n. 4
0
def test_carbon_failure_invalid_configuration(srv, caplog):

    item = Item(target="test", addrs=["172.16.153.110", "foobar"])

    with caplog.at_level(logging.DEBUG):

        module = load_module_from_file("mqttwarn/services/carbon.py")

        outcome = module.plugin(srv, item)

        assert outcome is False
        assert "Configuration for target `carbon' is incorrect" in caplog.text
Esempio n. 5
0
def test_alexa_notify_me_real_auth_failure(srv, caplog):
    module = load_module_from_file("mqttwarn/services/alexa-notify-me.py")

    accessCode = "myToken"
    item = Item(addrs=[accessCode], message="⚽ Notification message ⚽")

    with caplog.at_level(logging.DEBUG):
        outcome = module.plugin(srv, item)

        assert outcome is False
        assert "Sending to NotifyMe service" in caplog.text
        assert "Failed to send message to NotifyMe service" in caplog.text
Esempio n. 6
0
def test_carbon_failure_empty_message(srv, caplog):

    item = Item(target="test", addrs=["172.16.153.110", 2003])

    with caplog.at_level(logging.DEBUG):

        module = load_module_from_file("mqttwarn/services/carbon.py")

        outcome = module.plugin(srv, item)

        assert outcome is False
        assert "target `carbon': cannot split string" in caplog.text
Esempio n. 7
0
def test_pushover_failure_invalid_configuration(srv, caplog):

    module = load_module_from_file("mqttwarn/services/pushover.py")

    item = Item(
        config={},
        target="test",
        addrs=[None],
    )

    with caplog.at_level(logging.DEBUG):
        outcome = module.plugin(srv, item)

        assert outcome is False
        assert "Invalid address configuration for target `test'" in caplog.text
Esempio n. 8
0
def test_apprise_error(srv, caplog):

    with caplog.at_level(logging.DEBUG):

        mock_connection = mock.MagicMock()

        # Make the call to `notify` raise an exception.
        def error(*args, **kwargs):
            raise Exception("something failed")

        mock_connection.notify = error

        with mock.patch("apprise.Apprise",
                        side_effect=[mock_connection],
                        create=True) as mock_client:
            with mock.patch("apprise.AppriseAsset", create=True) as mock_asset:
                module = load_module_from_file(
                    "mqttwarn/services/apprise_single.py")

                item = Item(
                    config={
                        "baseuri":
                        "mailtos://*****:*****@mail.example.org"
                    },
                    target="test",
                    addrs=["*****@*****.**", "*****@*****.**"],
                    title="⚽ Message title ⚽",
                    message="⚽ Notification message ⚽",
                )

                outcome = module.plugin(srv, item)

                assert mock_client.mock_calls == [
                    mock.call(asset=mock.ANY),
                ]
                assert mock_connection.mock_calls == [
                    call.add(
                        "mailtos://*****:*****@mail.example.org?to=foo%40example.org%2Cbar%40example.org"
                    ),
                ]

                assert outcome is False
                assert (
                    "Sending notification to Apprise. target=test, addresses=['*****@*****.**', '*****@*****.**']"
                    in caplog.messages)
                assert (
                    "Sending message using Apprise failed. target=test, error=something failed"
                    in caplog.messages)
Esempio n. 9
0
def test_pushover_failure_missing_credentials(srv, caplog):

    module = load_module_from_file("mqttwarn/services/pushover.py")

    item = Item(
        config={},
        target="test",
        addrs=[None, None],
        data={},
    )

    with caplog.at_level(logging.DEBUG):
        outcome = module.plugin(srv, item)

        assert outcome is False
        assert "No pushover credentials configured for target `test'" in caplog.text
Esempio n. 10
0
def test_apns_failure_invalid_config(mock_apns_payload, mock_apns, srv, caplog):

    with caplog.at_level(logging.DEBUG):

        module = load_module_from_file("mqttwarn/services/apns.py")

        item = Item(
            target="test",
            addrs=[None],
            message="⚽ Notification message ⚽",
            data={"apns_token": "foobar", "payload": "{}"},
        )

        outcome = module.plugin(srv, item)

        assert outcome is False
        assert "Incorrect service configuration" in caplog.text
Esempio n. 11
0
def test_azure_iot_failure_wrong_qos(srv, caplog):

    item = Item(
        config={"iothubname": "acmehub", "qos": 999},
        target="test",
        addrs=["device-id", "SharedAccessSignature sr=..."],
        message="⚽ Notification message ⚽",
    )

    with caplog.at_level(logging.DEBUG):

        module = load_module_from_file("mqttwarn/services/azure_iot.py")

        outcome = module.plugin(srv, item)

        assert outcome is False
        assert "Only QoS 0 or 1 allowed for Azure IoT Hub, not '999'" in caplog.text
Esempio n. 12
0
def test_pushover_success_with_imageurl_and_digest_authentication(srv, caplog):

    module = load_module_from_file("mqttwarn/services/pushover.py")

    item = Item(
        config={},
        target="test",
        addrs=["userkey2", "appkey2"],
        message="⚽ Notification message ⚽",
        data={
            "imageurl": "https://example.org/image",
            "auth": "digest",
            "user": "******",
            "password": "******",
        },
    )

    with caplog.at_level(logging.DEBUG):

        add_successful_mock_response()

        image = open("./assets/pushover.png", "rb").read()
        responses.add(
            responses.GET,
            "https://example.org/image",
            body=image,
            stream=True,
            status=200,
        )

        outcome = module.plugin(srv, item)

        # Proof authentication on image request.
        # FIXME: Currently not possible because Digest auth will only work if
        #        the server answers with 4xx.
        # assert (
        #    responses.calls[0].request.headers["Authorization"] == "Digest something"
        # )

        # Check response status.
        assert responses.calls[1].response.status_code == 200
        assert responses.calls[1].response.text == '{"status": 1}'

        assert outcome is True
        assert "Sending pushover notification to test" in caplog.text
        assert "Successfully sent pushover notification" in caplog.text
Esempio n. 13
0
def test_asterisk_success_with_broken_close(asterisk_mock, srv, caplog):

    with caplog.at_level(logging.DEBUG):

        attrs = {
            "login.return_value": 42,
            "originate.return_value": 42,
            "close.side_effect": ManagerSocketException("something failed"),
        }
        asterisk_mock.return_value = mock.MagicMock(**attrs)

        module = load_module_from_file("mqttwarn/services/asterisk.py")

        item = Item(
            config={
                "host": "asterisk.example.org",
                "port": 5038,
                "username": "******",
                "password": "******",
                "extension": 2222,
                "context": "default",
            },
            target="test",
            addrs=["SIP/avaya/", "0123456789"],
            message="⚽ Notification message ⚽",
        )

        outcome = module.plugin(srv, item)

        assert asterisk_mock.mock_calls == [
            call(),
            call().connect("asterisk.example.org", 5038),
            call().login("foobar", "bazqux"),
            call().originate(
                "SIP/avaya/0123456789",
                2222,
                context="default",
                priority="1",
                caller_id=2222,
                variables={"text": "⚽ Notification message ⚽"},
            ),
            call().logoff(),
            call().close(),
        ]

        assert outcome is True
Esempio n. 14
0
def test_carbon_failure_invalid_message_format(srv, caplog):

    item = Item(
        target="test",
        addrs=["172.16.153.110", 2003],
        message="foo bar baz qux",
        data={},
    )

    with caplog.at_level(logging.DEBUG):

        module = load_module_from_file("mqttwarn/services/carbon.py")

        outcome = module.plugin(srv, item)

        assert outcome is False
        assert "target `carbon': error decoding message" in caplog.text
Esempio n. 15
0
def test_azure_iot_success_bytes(srv, caplog):

    item = Item(
        config={"iothubname": "acmehub"},
        target="test",
        addrs=["device-id", "SharedAccessSignature sr=..."],
        message=b"### Notification message ###",
    )

    with caplog.at_level(logging.DEBUG):

        module = load_module_from_file("mqttwarn/services/azure_iot.py")

        mqtt_publish_mock = mock.MagicMock()
        module.mqtt = mqtt_publish_mock

        outcome = module.plugin(srv, item)
        mqtt_publish_mock.single.assert_called_once_with(
            "devices/device-id/messages/events/",
            bytearray(b"### Notification message ###"),
            auth={
                "username": "******",
                "password": "******",
            },
            tls={
                "ca_certs": None,
                "certfile": None,
                "keyfile": None,
                "tls_version": mock.ANY,
                "ciphers": None,
                "cert_reqs": mock.ANY,
            },
            hostname="acmehub.azure-devices.net",
            port=8883,
            protocol=4,
            qos=0,
            retain=False,
            client_id="device-id",
        )

        assert outcome is True
        assert (
            "Publishing to Azure IoT Hub for target=test (device-id): devices/device-id/messages/events/ 'b'### Notification message ###''"
            in caplog.text
        )
Esempio n. 16
0
def test_apns_failure_apns_token_missing(mock_apns_payload, mock_apns, srv, caplog):

    with caplog.at_level(logging.DEBUG):

        module = load_module_from_file("mqttwarn/services/apns.py")

        cert_file, key_file = ["cert_file", "key_file"]
        item = Item(
            target="test",
            addrs=[cert_file, key_file],
            message="⚽ Notification message ⚽",
            data={},
        )

        outcome = module.plugin(srv, item)

        assert outcome is False
        assert "Cannot notify via APNS: apns_token is missing" in caplog.text
Esempio n. 17
0
def test_alexa_notify_me_success(srv, caplog):

    module = load_module_from_file("mqttwarn/services/alexa-notify-me.py")

    accessCode = "myToken"
    item = Item(addrs=[accessCode], message="⚽ Notification message ⚽")

    with caplog.at_level(logging.DEBUG):
        with mock.patch("requests.post") as requests_mock:
            outcome = module.plugin(srv, item)
            requests_mock.assert_called_once_with(
                url="https://api.notifymyecho.com/v1/NotifyMe",
                data=
                '{"notification": "\\u26bd Notification message \\u26bd", "accessCode": "myToken"}',
            )

        assert outcome is True
        assert "Sending to NotifyMe service" in caplog.text
        assert "Successfully sent to NotifyMe service" in caplog.text
Esempio n. 18
0
def test_azure_iot_failure_invalid_message(srv, caplog):

    item = Item(
        config={"iothubname": "acmehub"},
        target="test",
        addrs=["device-id", "SharedAccessSignature sr=..."],
    )

    with mock.patch.object(Item, "message", new_callable=PropertyMock) as msg_mock:
        msg_mock.side_effect = Exception("something failed")

        with caplog.at_level(logging.DEBUG):

            module = load_module_from_file("mqttwarn/services/azure_iot.py")

            outcome = module.plugin(srv, item)

            assert outcome is False
            assert "Unable to prepare message for target=test: something failed" in caplog.text
Esempio n. 19
0
def test_apprise_multi_error(srv, caplog):

    with caplog.at_level(logging.DEBUG):

        mock_connection = mock.MagicMock()

        # Make the call to `notify` raise an exception.
        def error(*args, **kwargs):
            raise Exception("something failed")

        mock_connection.notify = error

        with mock.patch("apprise.Apprise",
                        side_effect=[mock_connection],
                        create=True) as mock_client:
            with mock.patch("apprise.AppriseAsset", create=True) as mock_asset:
                module = load_module_by_name("mqttwarn.services.apprise_multi")

                item = Item(
                    addrs=[{
                        "baseuri": "json://localhost:1234/mqtthook"
                    }],
                    title="⚽ Message title ⚽",
                    message="⚽ Notification message ⚽",
                )

                outcome = module.plugin(srv, item)

                assert mock_client.mock_calls == [
                    mock.call(asset=mock.ANY),
                ]
                assert mock_connection.mock_calls == [
                    call.add("json://localhost:1234/mqtthook"),
                ]

                assert outcome is False
                assert (
                    "Sending notification to Apprise. target=None, addresses=[{'baseuri': 'json://localhost:1234/mqtthook'}]"
                    in caplog.messages)
                assert (
                    "Sending message using Apprise failed. target=None, error=something failed"
                    in caplog.messages)
Esempio n. 20
0
def test_amqp_failure(srv, caplog):
    module = load_module_by_name("mqttwarn.services.amqp")

    exchange, routing_key = ["name_of_exchange", "my_routing_key"]
    item = Item(
        config={"uri": "amqp://*****:*****@localhost:5672/"},
        target="test",
        addrs=[exchange, routing_key],
        message="⚽ Notification message ⚽",
    )

    with caplog.at_level(logging.DEBUG):

        mock_connection = mock.MagicMock()

        # Make the call to `basic_publish` raise an exception.
        def error(*args, **kwargs):
            raise Exception("something failed")

        mock_connection.basic_publish = error

        with mock.patch("puka.Client",
                        side_effect=[mock_connection],
                        create=True) as mock_client:

            outcome = module.plugin(srv, item)

            assert mock_client.mock_calls == [
                mock.call("amqp://*****:*****@localhost:5672/"),
            ]
            assert mock_connection.mock_calls == [
                call.connect(),
                call.wait(mock.ANY),
            ]

            assert outcome is False
            assert ("AMQP publish to test [name_of_exchange/my_routing_key]"
                    in caplog.text)
            assert (
                "Error on AMQP publish to test [name_of_exchange/my_routing_key]: something failed"
                in caplog.text)
Esempio n. 21
0
def test_irccat_config_invalid(srv, caplog):

    item = Item(
        target="test",
        addrs=["localhost", 12345],
        message="⚽ Notification message ⚽",
        data={},
    )

    with caplog.at_level(logging.DEBUG):

        module = load_module_from_file("mqttwarn/services/irccat.py")

        socket_mock = mock.MagicMock()
        module.socket.socket = socket_mock

        outcome = module.plugin(srv, item)
        assert socket_mock.mock_calls == []

        assert outcome is False
        assert "Incorrect target configuration" in caplog.messages
Esempio n. 22
0
def test_file_failure(fake_filesystem, srv, caplog):
    """
    When `io.open` fails, prove that the corresponding error code path is
    invoked.
    """

    item = Item(
        target="test",
        addrs=["/tmp/testdrive.log"],
        message="⚽ Notification message ⚽",
        data={},
    )

    with caplog.at_level(logging.DEBUG):

        module = mqttwarn.services.file

        outcome = module.plugin(srv, item)
        assert not os.path.exists("/tmp/testdrive.log")

        assert outcome is False
        assert "Cannot write to file `/tmp/testdrive.log': something failed" in caplog.messages
Esempio n. 23
0
def test_pushover_failure_request_error(srv, caplog):

    module = load_module_from_file("mqttwarn/services/pushover.py")

    item = Item(
        config={},
        target="test",
        addrs=["userkey2", "appkey2"],
        message="⚽ Notification message ⚽",
        data={},
    )

    with caplog.at_level(logging.DEBUG):

        # Make remote call bail out.
        module.pushover = mock.MagicMock(side_effect=Exception("something failed"))

        outcome = module.plugin(srv, item)

        assert outcome is False
        assert "Sending pushover notification to test" in caplog.text
        assert "Error sending pushover notification: something failed" in caplog.text
Esempio n. 24
0
def test_azure_iot_failure_mqtt_publish(srv, caplog):

    item = Item(
        config={"iothubname": "acmehub"},
        target="test",
        addrs=["device-id", "SharedAccessSignature sr=..."],
        message="⚽ Notification message ⚽",
    )

    with caplog.at_level(logging.DEBUG):

        module = load_module_from_file("mqttwarn/services/azure_iot.py")

        mqtt_publish_mock = mock.MagicMock(side_effect=Exception("something failed"))
        module.mqtt.single = mqtt_publish_mock

        outcome = module.plugin(srv, item)

        assert outcome is False
        assert (
            "Unable to publish to Azure IoT Hub for target=test (device-id): something failed"
            in caplog.text
        )
Esempio n. 25
0
def test_apns_success_custom_payload(mock_apns_payload, mock_apns, srv,
                                     caplog):

    with caplog.at_level(logging.DEBUG):

        module = load_module_from_file("mqttwarn/services/apns.py")

        cert_file, key_file = ["cert_file", "key_file"]
        item = Item(
            target="test",
            addrs=[cert_file, key_file],
            message="⚽ Notification message ⚽",
            data={
                "apns_token": "foobar",
                "payload": '{"custom": {"baz": "qux"}}',
            },
        )

        outcome = module.plugin(srv, item)

        assert mock_apns_payload.mock_calls == [
            call(
                alert="⚽ Notification message ⚽",
                custom={"baz": "qux"},
                sound="default",
                badge=1,
            ),
        ]
        assert mock_apns.mock_calls == [
            mock.call(use_sandbox=False,
                      cert_file="cert_file",
                      key_file="key_file"),
            call().gateway_server.send_notification("foobar", mock.ANY),
        ]

        assert outcome is True
        assert "Successfully published APNS notification to foobar" in caplog.text
Esempio n. 26
0
def test_pushover_failure_response_error(srv, caplog):

    module = load_module_from_file("mqttwarn/services/pushover.py")

    item = Item(
        config={},
        target="test",
        addrs=["userkey2", "appkey2"],
        message="⚽ Notification message ⚽",
        data={},
    )

    with caplog.at_level(logging.DEBUG):

        add_failed_mock_response()
        outcome = module.plugin(srv, item)

        assert len(responses.calls) == 1

        assert (
            responses.calls[0].request.url == "https://api.pushover.net/1/messages.json"
        )
        assert (
            responses.calls[0].request.body
            == "user=userkey2&token=appkey2&retry=60&expire=3600&message=%E2%9A%BD+Notification+message+%E2%9A%BD"
        )
        assert responses.calls[0].request.headers["User-Agent"] == "mqttwarn"

        assert responses.calls[0].response.status_code == 400
        assert responses.calls[0].response.text == '{"status": 999}'

        assert outcome is False
        assert "Sending pushover notification to test" in caplog.text
        assert (
            "Error sending pushover notification: b'{\"status\": 999}'" in caplog.text
        )
Esempio n. 27
0
def test_apprise_multi_mailto_success(apprise_asset, apprise_mock, srv,
                                      caplog):

    with caplog.at_level(logging.DEBUG):

        module = load_module_by_name("mqttwarn.services.apprise_multi")

        item = Item(
            addrs=[{
                "baseuri":
                "mailtos://*****:*****@mail.example.org",
                "recipients": ["*****@*****.**", "*****@*****.**"],
                "sender": "*****@*****.**",
                "sender_name": "Example Monitoring",
            }],
            title="⚽ Message title ⚽",
            message="⚽ Notification message ⚽",
        )

        outcome = module.plugin(srv, item)

        assert apprise_mock.mock_calls == [
            call(asset=mock.ANY),
            call().add(
                "mailtos://*****:*****@mail.example.org?to=foo%40example.org%2Cbar%40example.org&from=monitoring%40example.org&name=Example+Monitoring"
            ),
            call().notify(body="⚽ Notification message ⚽",
                          title="⚽ Message title ⚽"),
            call().notify().__bool__(),
        ]

        assert outcome is True
        assert (
            "Sending notification to Apprise. target=None, addresses=[{'baseuri': 'mailtos://*****:*****@mail.example.org', 'recipients': ['*****@*****.**', '*****@*****.**'], 'sender': '*****@*****.**', 'sender_name': 'Example Monitoring'}]"
            in caplog.messages)
        assert "Successfully sent message using Apprise" in caplog.messages
Esempio n. 28
0
def test_amqp_success(mock_puka_client, srv, caplog):
    module = load_module_by_name("mqttwarn.services.amqp")

    exchange, routing_key = ["name_of_exchange", "my_routing_key"]
    item = Item(
        config={"uri": "amqp://*****:*****@localhost:5672/"},
        target="test",
        addrs=[exchange, routing_key],
        message="⚽ Notification message ⚽",
    )

    with caplog.at_level(logging.DEBUG):

        outcome = module.plugin(srv, item)

        assert mock_puka_client.mock_calls == [
            mock.call("amqp://*****:*****@localhost:5672/"),
            call().connect(),
            call().wait(mock.ANY),
            call().basic_publish(
                exchange="name_of_exchange",
                routing_key="my_routing_key",
                headers={
                    "content_type": "text/plain",
                    "x-agent": "mqttwarn",
                    "delivery_mode": 1,
                },
                body="⚽ Notification message ⚽",
            ),
            call().wait(mock.ANY),
            call().close(),
        ]

        assert outcome is True
        assert "AMQP publish to test [name_of_exchange/my_routing_key]" in caplog.text
        assert "Successfully published AMQP notification" in caplog.text
Esempio n. 29
0
# (c) 2021 The mqttwarn developers
import logging
import os
from unittest import mock

import mqttwarn.services.file
import pytest as pytest
from mqttwarn.model import ProcessorItem as Item


@pytest.mark.parametrize(
    "item",
    [
        Item(
            target="test",
            addrs=["/tmp/testdrive.log"],
            message="⚽ Notification message ⚽",
            data={},
        ),
        Item(
            target="test",
            addrs={"path": "/tmp/testdrive.log"},
            message="⚽ Notification message ⚽",
            data={},
        ),
    ],
    ids=["basic", "advanced"],
)
def test_file_success(fake_filesystem, srv, caplog, item):
    """
    Dispatch a single message and prove it is stored in the designated file.
    """