updates2mqtt 1.3.7__py3-none-any.whl → 1.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- updates2mqtt/config.py +1 -0
- updates2mqtt/integrations/docker.py +1 -1
- updates2mqtt/integrations/git_utils.py +3 -1
- updates2mqtt/mqtt.py +48 -4
- {updates2mqtt-1.3.7.dist-info → updates2mqtt-1.4.0.dist-info}/METADATA +65 -23
- updates2mqtt-1.4.0.dist-info/RECORD +16 -0
- {updates2mqtt-1.3.7.dist-info → updates2mqtt-1.4.0.dist-info}/WHEEL +1 -1
- updates2mqtt-1.3.7.dist-info/RECORD +0 -16
- {updates2mqtt-1.3.7.dist-info → updates2mqtt-1.4.0.dist-info}/entry_points.txt +0 -0
- {updates2mqtt-1.3.7.dist-info → updates2mqtt-1.4.0.dist-info}/licenses/LICENSE +0 -0
updates2mqtt/config.py
CHANGED
|
@@ -287,7 +287,7 @@ class DockerProvider(ReleaseProvider):
|
|
|
287
287
|
logger.info(f"Shutdown detected, aborting scan at {c}")
|
|
288
288
|
break
|
|
289
289
|
containers = containers + 1
|
|
290
|
-
result = self.analyze(
|
|
290
|
+
result = self.analyze(c, session)
|
|
291
291
|
if result:
|
|
292
292
|
self.discoveries[result.name] = result
|
|
293
293
|
results = results + 1
|
|
@@ -28,8 +28,10 @@ def git_timestamp(repo_path: Path, git_path: Path) -> datetime.datetime | None:
|
|
|
28
28
|
check=True,
|
|
29
29
|
)
|
|
30
30
|
return datetime.datetime.fromisoformat(result.stdout.strip())
|
|
31
|
+
except subprocess.CalledProcessError as cpe:
|
|
32
|
+
log.warn("GIT No result from git log at %s: %s", repo_path, cpe)
|
|
31
33
|
except Exception as e:
|
|
32
|
-
log.
|
|
34
|
+
log.error("GIT Unable to parse timestamp at %s - %s: %s", repo_path, result.stdout if result else "<NO RESULT>", e)
|
|
33
35
|
return None
|
|
34
36
|
|
|
35
37
|
|
updates2mqtt/mqtt.py
CHANGED
|
@@ -9,8 +9,8 @@ from typing import Any
|
|
|
9
9
|
import paho.mqtt.client as mqtt
|
|
10
10
|
import paho.mqtt.subscribeoptions
|
|
11
11
|
import structlog
|
|
12
|
-
from paho.mqtt.client import MQTTMessage
|
|
13
|
-
from paho.mqtt.enums import CallbackAPIVersion, MQTTErrorCode
|
|
12
|
+
from paho.mqtt.client import MQTT_CLEAN_START_FIRST_ONLY, MQTTMessage
|
|
13
|
+
from paho.mqtt.enums import CallbackAPIVersion, MQTTErrorCode, MQTTProtocolVersion
|
|
14
14
|
from paho.mqtt.properties import Properties
|
|
15
15
|
from paho.mqtt.reasoncodes import ReasonCode
|
|
16
16
|
|
|
@@ -42,19 +42,39 @@ class MqttClient:
|
|
|
42
42
|
def start(self, event_loop: asyncio.AbstractEventLoop | None = None) -> None:
|
|
43
43
|
logger = self.log.bind(action="start")
|
|
44
44
|
try:
|
|
45
|
+
protocol: MQTTProtocolVersion
|
|
46
|
+
if self.cfg.protocol in ("3", "3.11"):
|
|
47
|
+
protocol = MQTTProtocolVersion.MQTTv311
|
|
48
|
+
elif self.cfg.protocol == "3.1":
|
|
49
|
+
protocol = MQTTProtocolVersion.MQTTv31
|
|
50
|
+
elif self.cfg.protocol in ("5", "5.0"):
|
|
51
|
+
protocol = MQTTProtocolVersion.MQTTv5
|
|
52
|
+
else:
|
|
53
|
+
self.log.info("No valid MQTT protocol version found (%s), setting to default v3.11", self.cfg.protocol)
|
|
54
|
+
protocol = MQTTProtocolVersion.MQTTv311
|
|
55
|
+
self.log.debug("MQTT protocol set to %r", protocol)
|
|
56
|
+
|
|
45
57
|
self.event_loop = event_loop or asyncio.get_event_loop()
|
|
46
58
|
self.client = mqtt.Client(
|
|
47
59
|
callback_api_version=CallbackAPIVersion.VERSION2,
|
|
48
60
|
client_id=f"updates2mqtt_{self.node_cfg.name}",
|
|
49
|
-
clean_session=True,
|
|
61
|
+
clean_session=True if protocol != MQTTProtocolVersion.MQTTv5 else None,
|
|
62
|
+
protocol=protocol,
|
|
50
63
|
)
|
|
51
64
|
self.client.username_pw_set(self.cfg.user, password=self.cfg.password)
|
|
52
|
-
rc: MQTTErrorCode = self.client.connect(
|
|
65
|
+
rc: MQTTErrorCode = self.client.connect(
|
|
66
|
+
host=self.cfg.host,
|
|
67
|
+
port=self.cfg.port,
|
|
68
|
+
keepalive=60,
|
|
69
|
+
clean_start=MQTT_CLEAN_START_FIRST_ONLY,
|
|
70
|
+
)
|
|
53
71
|
self.log.info("Client connection requested", result_code=rc)
|
|
54
72
|
|
|
55
73
|
self.client.on_connect = self.on_connect
|
|
56
74
|
self.client.on_disconnect = self.on_disconnect
|
|
57
75
|
self.client.on_message = self.on_message
|
|
76
|
+
self.client.on_subscribe = self.on_subscribe
|
|
77
|
+
self.client.on_unsubscribe = self.on_unsubscribe
|
|
58
78
|
|
|
59
79
|
self.client.loop_start()
|
|
60
80
|
|
|
@@ -223,6 +243,30 @@ class MqttClient:
|
|
|
223
243
|
)
|
|
224
244
|
self.handle_message(msg)
|
|
225
245
|
|
|
246
|
+
def on_subscribe(
|
|
247
|
+
self,
|
|
248
|
+
_client: mqtt.Client,
|
|
249
|
+
userdata: Any,
|
|
250
|
+
mid: int,
|
|
251
|
+
reason_code_list: list[ReasonCode],
|
|
252
|
+
properties: Properties | None = None,
|
|
253
|
+
) -> None:
|
|
254
|
+
self.log.debug(
|
|
255
|
+
"on_subscribe, userdata=%s, mid=%s, reasons=%s, properties=%s", userdata, mid, reason_code_list, properties
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
def on_unsubscribe(
|
|
259
|
+
self,
|
|
260
|
+
_client: mqtt.Client,
|
|
261
|
+
userdata: Any,
|
|
262
|
+
mid: int,
|
|
263
|
+
reason_code_list: list[ReasonCode],
|
|
264
|
+
properties: Properties | None = None,
|
|
265
|
+
) -> None:
|
|
266
|
+
self.log.debug(
|
|
267
|
+
"on_unsubscribe, userdata=%s, mid=%s, reasons=%s, properties=%s", userdata, mid, reason_code_list, properties
|
|
268
|
+
)
|
|
269
|
+
|
|
226
270
|
def on_message(self, _client: mqtt.Client, _userdata: Any, msg: mqtt.MQTTMessage) -> None:
|
|
227
271
|
"""Callback for incoming MQTT messages""" # noqa: D401
|
|
228
272
|
if msg.topic in self.providers_by_topic:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: updates2mqtt
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
4
4
|
Summary: System update and docker image notification and execution over MQTT
|
|
5
5
|
Project-URL: Homepage, https://updates2mqtt.rhizomatics.org.uk
|
|
6
6
|
Project-URL: Repository, https://github.com/rhizomatics/updates2mqtt
|
|
@@ -49,9 +49,14 @@ Description-Content-Type: text/markdown
|
|
|
49
49
|
|
|
50
50
|
## Summary
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
Let Home Assistant tell you about new updates to Docker images for your containers.
|
|
53
|
+
|
|
54
|
+

|
|
55
|
+
|
|
56
|
+
Read the release notes, and optionally click *Update* to trigger a Docker *pull* (or optionally *build*) and *update*.
|
|
57
|
+
|
|
58
|
+
{width=480}
|
|
53
59
|
|
|
54
|
-

|
|
55
60
|
|
|
56
61
|
## Description
|
|
57
62
|
|
|
@@ -59,7 +64,7 @@ updates2mqtt perioidically checks for new versions of components being available
|
|
|
59
64
|
|
|
60
65
|
Currently only Docker containers are supported, either via an image registry check, or a git repo for source (see [Local Builds](local_builds.md)). The design is modular, so other update sources can be added, at least for notification. The next anticipated is **apt** for Debian based systems.
|
|
61
66
|
|
|
62
|
-
Components can also be updated, either automatically or triggered via MQTT, for example by hitting the *Install* button in the HomeAssistant update dialog. Icons and release notes can be specified for a better HA experience.
|
|
67
|
+
Components can also be updated, either automatically or triggered via MQTT, for example by hitting the *Install* button in the HomeAssistant update dialog. Icons and release notes can be specified for a better HA experience. See [Home Assistant Integration](home_assistant.md) for details.
|
|
63
68
|
|
|
64
69
|
To get started, read the [Installation](installation.md) and [Configuration](configuration.md) pages.
|
|
65
70
|
|
|
@@ -71,8 +76,7 @@ docker run -e MQTT_USER=user1 -e MQTT_PASS=pass1 -e MQTT_HOST=192.168.1.5 ghcr.i
|
|
|
71
76
|
|
|
72
77
|
## Release Support
|
|
73
78
|
|
|
74
|
-
Presently only Docker containers are supported, although others are planned,
|
|
75
|
-
probably with priority for `apt`.
|
|
79
|
+
Presently only Docker containers are supported, although others are planned, probably with priority for `apt`.
|
|
76
80
|
|
|
77
81
|
| Ecosystem | Support | Comments |
|
|
78
82
|
|-----------|-------------|----------------------------------------------------------------------------------------------------|
|
|
@@ -82,31 +86,57 @@ probably with priority for `apt`.
|
|
|
82
86
|
|
|
83
87
|
A heartbeat JSON payload is optionally published periodically to a configurable MQTT topic, defaulting to `healthcheck/{node_name}/updates2mqtt`. It contains the current version of updates2mqtt, the node name, a timestamp, and some basic stats.
|
|
84
88
|
|
|
85
|
-
A `healthcheck.sh` script is included in the Docker image, and can be used as a Docker healthcheck, if the container environment variables are set for `MQTT_HOST`, `MQTT_PORT`, `MQTT_USER` and `MQTT_PASS`.
|
|
89
|
+
A `healthcheck.sh` script is included in the Docker image, and can be used as a Docker healthcheck, if the container environment variables are set for `MQTT_HOST`, `MQTT_PORT`, `MQTT_USER` and `MQTT_PASS`. It uses the `mosquitto-clients` Linux package which provides `mosquitto_sub` command to subscribe to topics.
|
|
86
90
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
91
|
+
!!! tip
|
|
92
|
+
|
|
93
|
+
Check healthcheck is working using `docker inspect --format "{{json .State.Health }}" updates2mqtt | jq`
|
|
94
|
+
|
|
95
|
+
Another approach is using a restarter service directly in Docker Compose to force a restart, in this case once a day:
|
|
90
96
|
|
|
91
|
-
|
|
92
|
-
|
|
97
|
+
```yaml title="Example Compose Service"
|
|
98
|
+
restarter:
|
|
99
|
+
image: docker:cli
|
|
100
|
+
volumes: ["/var/run/docker.sock:/var/run/docker.sock"]
|
|
101
|
+
command: ["/bin/sh", "-c", "while true; do sleep 86400; docker restart updates2mqtt; done"]
|
|
102
|
+
restart: unless-stopped
|
|
103
|
+
environment:
|
|
104
|
+
- UPD2MQTT_UPDATE=AUTO
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Target Containers
|
|
108
|
+
|
|
109
|
+
While `updates2mqtt` will discover and monitor all containers running under the Docker daemon,
|
|
110
|
+
there are some options to make to those containers to tune how it works.
|
|
93
111
|
|
|
94
|
-
|
|
112
|
+
These happen by adding environment variables to the containers, typically inside an `.env`
|
|
113
|
+
file, or as `environment` options inside `docker-compose.yaml`.
|
|
95
114
|
|
|
96
|
-
|
|
115
|
+
### Automated updates
|
|
97
116
|
|
|
98
|
-
|
|
117
|
+
If Docker containers should be immediately updated, without any confirmation
|
|
118
|
+
or trigger, *e.g.* from the HomeAssistant update dialog, then set an environment variable `UPD2MQTT_UPDATE` in the target container to `Auto` ( it defaults to `Passive`)
|
|
99
119
|
|
|
100
|
-
|
|
120
|
+
```yaml title="Example Compose Snippet"
|
|
121
|
+
restarter:
|
|
122
|
+
image: docker:cli
|
|
123
|
+
command: ["/bin/sh", "-c", "while true; do sleep 86400; docker restart mailserver; done"]
|
|
124
|
+
environment:
|
|
125
|
+
- UPD2MQTT_UPDATE=AUTO
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Environment Variables
|
|
101
129
|
|
|
102
|
-
|
|
130
|
+
The following environment variables can be used to configure containers for `updates2mqtt`:
|
|
103
131
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
132
|
+
| Env Var | Description | Default |
|
|
133
|
+
|---------| ------------|----------|
|
|
134
|
+
| `UPD2MQTT_UPDATE` | Update mode, either `Passive` or `Auto`. If `Auto`, updates will be installed automatically. | `Passive` |
|
|
135
|
+
| `UPD2MQTT_PICTURE` | URL to an icon to use in Home Assistant. | Docker logo URL |
|
|
136
|
+
| `UPD2MQTT_RELNOTES` | URL to release notes for the package. | |
|
|
137
|
+
| `UPD2MQTT_GIT_REPO_PATH` | Relative path to a local git repo if the image is built locally. | |
|
|
138
|
+
| `UPD2MQTT_IGNORE` | If set to `True`, the container will be ignored by updates2mqtt. | False |
|
|
107
139
|
|
|
108
|
-
If the package supports automated update, then *Skip* and *Install* buttons will appear on the Home Assistant
|
|
109
|
-
interface, and the package can be remotely fetched and the component restarted.
|
|
110
140
|
|
|
111
141
|
## Related Projects
|
|
112
142
|
|
|
@@ -114,6 +144,18 @@ Other apps useful for self-hosting with the help of MQTT:
|
|
|
114
144
|
|
|
115
145
|
- [psmqtt](https://github.com/eschava/psmqtt) - Report system health and metrics via MQTT
|
|
116
146
|
|
|
147
|
+
Find more at [awesome-mqtt](https://github.com/rhizomatics/awesome-mqtt)
|
|
148
|
+
|
|
117
149
|
## Development
|
|
118
150
|
|
|
119
|
-
|
|
151
|
+
This component relies on several open source packages:
|
|
152
|
+
|
|
153
|
+
- [docker-py](https://docker-py.readthedocs.io/en/stable/) SDK for Python for access to Docker APIs
|
|
154
|
+
- [Eclipse Paho](https://eclipse.dev/paho/files/paho.mqtt.python/html/client.html) MQTT client
|
|
155
|
+
- [OmegaConf](https://omegaconf.readthedocs.io) for configuration and validation
|
|
156
|
+
- [structlog](https://www.structlog.org/en/stable/) for structured logging and [rich](https://rich.readthedocs.io/en/stable/) for better exception reporting
|
|
157
|
+
- [hishel](https://hishel.com/1.0/) for caching metadata
|
|
158
|
+
- [httpx](https://www.python-httpx.org) for retrieving metadata
|
|
159
|
+
- The Astral [uv](https://docs.astral.sh/uv/) and [ruff](https://docs.astral.sh/ruff/) tools for development and build
|
|
160
|
+
- [pytest](https://docs.pytest.org/en/stable/) and supporting add-ins for automated testing
|
|
161
|
+
- [usingversion](https://pypi.org/project/usingversion/) to log current version info
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
updates2mqtt/__init__.py,sha256=gnmHrLOSYc-N1-c5VG46OpNpoXEybKzYhEvFMm955P8,237
|
|
2
|
+
updates2mqtt/__main__.py,sha256=HBF00oH5fhS33sI_CdbxNlaUvbIzuuGxwnRYdhHqx0M,194
|
|
3
|
+
updates2mqtt/app.py,sha256=7jnmtIkXlX4e4lIt8WCzV19IYrICkA7cU4m9u9QXvRU,8229
|
|
4
|
+
updates2mqtt/config.py,sha256=SK6uhDyUb9C2JYVd0j6KBHzSAfaCFcOUbmmgsq6VSs0,5027
|
|
5
|
+
updates2mqtt/hass_formatter.py,sha256=Ulfj8F0e_1QMmRuJzHsNM2WxHbz9sIkWOWjRq3kQZzs,2772
|
|
6
|
+
updates2mqtt/model.py,sha256=5tWlj3appGGZjkuBeYR2lb-kXoy5mzCn4P_EJQjnwok,3676
|
|
7
|
+
updates2mqtt/mqtt.py,sha256=LDy9x7Mmq_Em6lV-w9J3TjzBCuu8eehI8PK4E0i015A,14468
|
|
8
|
+
updates2mqtt/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
updates2mqtt/integrations/__init__.py,sha256=KmNTUxvVWvqI7rl4I0xZg7XaCmcMS2O4OSv-ClsWM4Q,109
|
|
10
|
+
updates2mqtt/integrations/docker.py,sha256=c1y3Xkv57_frxZOlq9LoYQRnfX-1XeedCjDcBLx1it0,18849
|
|
11
|
+
updates2mqtt/integrations/git_utils.py,sha256=bPCmQiZpKpMcrGI7xAVmePXHFn8WwjcPNkf7xqDsGQA,2319
|
|
12
|
+
updates2mqtt-1.4.0.dist-info/METADATA,sha256=0wYbNmGsu4nQF5C49M0pegMkpmMgW7rNR5n6FTbTwlA,8916
|
|
13
|
+
updates2mqtt-1.4.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
14
|
+
updates2mqtt-1.4.0.dist-info/entry_points.txt,sha256=Hc6NZ2dBevYSUKTJU6NOs8Mw7Vt0S-9lq5FuKb76NCc,54
|
|
15
|
+
updates2mqtt-1.4.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
16
|
+
updates2mqtt-1.4.0.dist-info/RECORD,,
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
updates2mqtt/__init__.py,sha256=gnmHrLOSYc-N1-c5VG46OpNpoXEybKzYhEvFMm955P8,237
|
|
2
|
-
updates2mqtt/__main__.py,sha256=HBF00oH5fhS33sI_CdbxNlaUvbIzuuGxwnRYdhHqx0M,194
|
|
3
|
-
updates2mqtt/app.py,sha256=7jnmtIkXlX4e4lIt8WCzV19IYrICkA7cU4m9u9QXvRU,8229
|
|
4
|
-
updates2mqtt/config.py,sha256=NiaFdMTXXAjZIbtW7LHYjSqu-ONEoouT2uUu506CTtM,5000
|
|
5
|
-
updates2mqtt/hass_formatter.py,sha256=Ulfj8F0e_1QMmRuJzHsNM2WxHbz9sIkWOWjRq3kQZzs,2772
|
|
6
|
-
updates2mqtt/model.py,sha256=5tWlj3appGGZjkuBeYR2lb-kXoy5mzCn4P_EJQjnwok,3676
|
|
7
|
-
updates2mqtt/mqtt.py,sha256=i2l1BlEmnkp3Ie2qeAPVmdhIO1I_mH8Zxbm84cIYtGI,12741
|
|
8
|
-
updates2mqtt/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
updates2mqtt/integrations/__init__.py,sha256=KmNTUxvVWvqI7rl4I0xZg7XaCmcMS2O4OSv-ClsWM4Q,109
|
|
10
|
-
updates2mqtt/integrations/docker.py,sha256=OX_sXtWVgUJfRSFi_tTBib4gvP_foQI4MoeTkTeLbZc,18868
|
|
11
|
-
updates2mqtt/integrations/git_utils.py,sha256=SkAp6XcvCHwaiy17t6F97kcWTjBd7RyEmfhz6M_EhP0,2196
|
|
12
|
-
updates2mqtt-1.3.7.dist-info/METADATA,sha256=yFJy-VGcnmHYdFksLx2teBHbuPi-B3J7pObaE5-XVEk,7990
|
|
13
|
-
updates2mqtt-1.3.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
14
|
-
updates2mqtt-1.3.7.dist-info/entry_points.txt,sha256=Hc6NZ2dBevYSUKTJU6NOs8Mw7Vt0S-9lq5FuKb76NCc,54
|
|
15
|
-
updates2mqtt-1.3.7.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
16
|
-
updates2mqtt-1.3.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|