goosebit 0.1.0__py3-none-any.whl → 0.1.1__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.
@@ -0,0 +1,38 @@
1
+ import dataclasses
2
+ from datetime import datetime
3
+ from pathlib import Path
4
+ from typing import Callable, Literal
5
+
6
+ from semver import Version as SemanticVersion
7
+
8
+
9
+ @dataclasses.dataclass
10
+ class DatetimeVersion:
11
+ timestamp: int
12
+
13
+ @classmethod
14
+ def parse(cls, version: str):
15
+ firmware_date = datetime.strptime(version, "%Y%m%d-%H%M%S")
16
+ return cls(timestamp=int(firmware_date.timestamp()))
17
+
18
+ def __gt__(self, other):
19
+ return self.timestamp > other.timestamp
20
+
21
+ def __lt__(self, other):
22
+ return self.timestamp < other.timestamp
23
+
24
+
25
+ @dataclasses.dataclass
26
+ class UpdateVersionParser:
27
+ parser: Callable
28
+
29
+ def parse(self, filename: Path):
30
+ _, _, version = filename.stem.split("_")
31
+ return self.parser(version)
32
+
33
+ @classmethod
34
+ def create(cls, parse_mode: Literal["semantic", "datetime"]):
35
+ if parse_mode == "semantic":
36
+ return cls(parser=SemanticVersion.parse)
37
+ if parse_mode == "datetime":
38
+ return cls(parser=DatetimeVersion.parse)
@@ -0,0 +1,73 @@
1
+ Metadata-Version: 2.1
2
+ Name: goosebit
3
+ Version: 0.1.1
4
+ Summary:
5
+ Author: Upstream Data
6
+ Author-email: brett@upstreamdata.ca
7
+ Requires-Python: >=3.11,<4.0
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Requires-Dist: aerich (>=0.7.2,<0.8.0)
12
+ Requires-Dist: aiofiles (>=24.1.0,<25.0.0)
13
+ Requires-Dist: argon2-cffi (>=23.1.0,<24.0.0)
14
+ Requires-Dist: fastapi[uvicorn] (>=0.111.0,<0.112.0)
15
+ Requires-Dist: itsdangerous (>=2.2.0,<3.0.0)
16
+ Requires-Dist: jinja2 (>=3.1.4,<4.0.0)
17
+ Requires-Dist: joserfc (>=1.0.0,<2.0.0)
18
+ Requires-Dist: python-multipart (>=0.0.9,<0.0.10)
19
+ Requires-Dist: semver (>=3.0.2,<4.0.0)
20
+ Requires-Dist: tortoise-orm (>=0.21.4,<0.22.0)
21
+ Requires-Dist: websockets (>=12.0,<13.0)
22
+ Description-Content-Type: text/markdown
23
+
24
+ # gooseBit
25
+ <img src="docs/img/goosebit-logo.png" style="width: 100px; height: 100px; display: block;">
26
+
27
+ ---
28
+
29
+ A simplistic, opinionated remote update server implementing hawkBit™'s [DDI API](https://eclipse.dev/hawkbit/apis/ddi_api/).
30
+
31
+ ## Setup
32
+
33
+ To set up, install the dependencies in `pyproject.toml` with `poetry install`. Then you can run gooseBit by running `main.py`.
34
+
35
+ ## Initial Startup
36
+
37
+ The first time you start gooseBit, you should change the default username and password inside `settings.yaml`.
38
+ The default login credentials for testing are `admin@goosebit.local`, `admin`.
39
+
40
+ ## Assumptions
41
+ - [SWUpdate](https://swupdate.org) used on device side.
42
+
43
+ ## Current Feature Set
44
+
45
+ ### Firmware repository
46
+ Uploading firmware images through frontend. All files should follow the format `{model}_{revision}_{version}`, where
47
+ `version` is either a semantic version or a datetime version in the format `YYYYMMDD-HHmmSS`.
48
+
49
+ ### Automatic device registration
50
+ First time a new device connects, its configuration data is requested. `hw_model` and `hw_revision` are captured from
51
+ the configuration data (both fall back to `default` if not provided) which allows to distinguish different device
52
+ types and their revisions.
53
+
54
+ ### Automatically update device to newest firmware
55
+ Once a device is registered it will get the newest available firmware from the repository based on model and revision.
56
+
57
+ ### Manually update device to specific firmware
58
+ Frontend allows to assign specific firmware to be rolled out.
59
+
60
+ ### Firmware rollout
61
+ Rollouts allow a fine-grained assignment of firmwares to devices. The reported device model and revision is combined
62
+ with the manually set feed and flavor values on a device to determine a matching rollout.
63
+
64
+ The feed is meant to model either different environments (like: dev, qa, live) or update channels (like. candidate,
65
+ fast, stable).
66
+
67
+ The flavor can be used for different type of builds (like: debug, prod).
68
+
69
+ ### Pause updates
70
+ Device can be pinned to its current firmware.
71
+
72
+ ### Realtime update logs
73
+ While an update is running, the update logs are captured and visualized in the frontend.
@@ -0,0 +1,53 @@
1
+ goosebit/__init__.py,sha256=95cV9cH6zMXpS9UIOT10DOSZKSQM89ui1E_iEWhs_vk,1890
2
+ goosebit/api/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
3
+ goosebit/api/devices.py,sha256=ZoooxjkPECfoItpSeOiik5LrdEitxCXV18c3y5aHeMg,3358
4
+ goosebit/api/download.py,sha256=I9aL3ZkT2T5hfyTsuwwR5vFF5XjqnjHV0WjK0p-oToQ,607
5
+ goosebit/api/firmware.py,sha256=GXrLZcIospqAr8eqBf7RsW334hNELMXrnA1JJ9BrXIE,1410
6
+ goosebit/api/rollouts.py,sha256=dWYUcqBOPZoEIcKZOxHGiLfTjxUHXvAGn-At4K4yRZY,1027
7
+ goosebit/api/routes.py,sha256=k8xzSMd4UCerQxEdljoOXzlKZHHHBQndmY805RJv7AA,414
8
+ goosebit/auth/__init__.py,sha256=5s-aZ_p1M7qz2DwN-Oq3NivbR39FCIzxKdRfgokm-4Q,3837
9
+ goosebit/db.py,sha256=lIQR3s290qZX54NL1J-85Ge6l98xbV9_oRaCO48vdTY,787
10
+ goosebit/models.py,sha256=a3QmFXgBK5wBXMO7-lR0R83N9wbXj7gc89SYY2i0udI,1764
11
+ goosebit/permissions.py,sha256=WQwJYBWwAbUT5y6-s0STPdRI25XvAhqZ_22xEJDYESY,1702
12
+ goosebit/realtime/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
13
+ goosebit/realtime/logs.py,sha256=EKZaHGw3QqiLnW9gXodhNosM7ORJO4I8ZPSVjzggQhs,1266
14
+ goosebit/realtime/routes.py,sha256=DzL1xBsdSc4SF2FiOAeuVKmcAq3m4DYo6KqD_pCNMww,269
15
+ goosebit/settings.py,sha256=a3UB5AuB2LQrCtNSX4PtB9y-hT3o1P6zryFr7WggYAI,1659
16
+ goosebit/ui/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
17
+ goosebit/ui/routes.py,sha256=dmAqLKtolbFx0G5fgpYuS_jKOoosRanf7B14JyqlT7o,2992
18
+ goosebit/ui/static/__init__.py,sha256=AsZiM3h9chQ_YaBbAD6TVFf0244Q9DetkDMl70q8swQ,135
19
+ goosebit/ui/static/favicon.ico,sha256=FLzKyAkMvQcMg58nzCJxQOfPFxT4yYbP7S82pdY6zng,4286
20
+ goosebit/ui/static/favicon.svg,sha256=2iEZocLSave4QTjaR3GxGVT1zaDNl6T_GtN61YHsvJU,6595
21
+ goosebit/ui/static/js/devices.js,sha256=f3iDHa4j7u2vDYhrbiCU8L1WwpYlY3zFje4BKdPEC6M,13107
22
+ goosebit/ui/static/js/firmware.js,sha256=NGjatiXNPxo8cjeREKImfPuHIjPkTDykFJqY1KeUYKU,4450
23
+ goosebit/ui/static/js/index.js,sha256=vZi8QQSDLy2gtQw67eRIK5DtoEgUmwS-O6uQ2Ysd1iQ,6040
24
+ goosebit/ui/static/js/logs.js,sha256=0cFbe0_nrc6SIvfqGg567cwKUi-dV8JKAbEQQfPNLqg,794
25
+ goosebit/ui/static/js/rollouts.js,sha256=7VLU22Yu5Q0hNOAITj58ctf_IQGOZ2hNkQdVAOIU2EM,1543
26
+ goosebit/ui/static/svg/goosebit-logo.svg,sha256=2iEZocLSave4QTjaR3GxGVT1zaDNl6T_GtN61YHsvJU,6595
27
+ goosebit/ui/templates/__init__.py,sha256=M-F9UIAOVyRdsVIjU-19cCiXh48-LZBAKvl8R4CLlkM,140
28
+ goosebit/ui/templates/devices.html,sha256=Ys0BAuQy-ap_dXjJG3xkWboZfyeE2XdgOI0pPdYpiS8,3310
29
+ goosebit/ui/templates/firmware.html,sha256=rCVgI4oLct6eXbVWsfJndUTEV4K1QPkXzrRV9t3DgtE,2155
30
+ goosebit/ui/templates/index.html,sha256=ea5Mpz9IMZwmue1xqydCORKarlPaImsPaDqPed8INyE,1192
31
+ goosebit/ui/templates/login.html,sha256=Ip_-p3DbRyCkIjAfEBO2MyzEynQk1m9eKVGpuPLEF3c,1862
32
+ goosebit/ui/templates/logs.html,sha256=s8amkmbzwb5WhgEc5bhMhvsQnl5fuVzlgSvM5ZZoxU4,1014
33
+ goosebit/ui/templates/nav.html,sha256=EHsPzb0V-gFzA4VJaW7JHpxiHXHZa6Bh1AXW874HIxI,3786
34
+ goosebit/ui/templates/rollouts.html,sha256=QiVKPPYRH33nTfINhWHZaN6mGj7l2griFqL3pdzRw4c,1588
35
+ goosebit/updater/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
36
+ goosebit/updater/controller/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
37
+ goosebit/updater/controller/routes.py,sha256=8CnLb-kDuO-yFeWdu4apIyctCf9OzvJ011Az3QDGemU,123
38
+ goosebit/updater/controller/v1/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
39
+ goosebit/updater/controller/v1/routes.py,sha256=LroX2TeNERhed9DVaort2ERSFcX4EfJ7psYc3TO_xCk,4937
40
+ goosebit/updater/download/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
41
+ goosebit/updater/download/routes.py,sha256=HNvpdlZvEeVfpY-JLhvUKHDd9eGKCAOFjh1EN98J9T0,121
42
+ goosebit/updater/download/v1/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
43
+ goosebit/updater/download/v1/routes.py,sha256=ZeOHyw9rxIsEMnPqvSmtPE7RlF0u0EQcNN2jT4NAkG8,416
44
+ goosebit/updater/manager.py,sha256=-hrcHslzKszCLinKZhZdyM6RQ45ZsTbB8_Dpk6j_WU0,7551
45
+ goosebit/updater/misc.py,sha256=SWTp2basygNmqoQrtrlWEJb-qtrcHxr_4S_gnsqRbXc,1550
46
+ goosebit/updater/routes.py,sha256=HN_UTO7msMSqhruwwXVm-Je7jOjm5mSvisW-X9F3Vgc,822
47
+ goosebit/updates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
+ goosebit/updates/artifacts.py,sha256=1pvJ271gFgQA8gJTxaMIISOO9l6_3w7Qm9LUo1Stm0g,2676
49
+ goosebit/updates/version.py,sha256=TIjepIYi5R6h2m-cOpeOg8FAdjT5mnai0oHflkkEnOc,1022
50
+ goosebit-0.1.1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
51
+ goosebit-0.1.1.dist-info/METADATA,sha256=iIaFlJlWSfu_zZ2fl-yTTnyDDJW2Sp-c2zQLzIisohw,2931
52
+ goosebit-0.1.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
53
+ goosebit-0.1.1.dist-info/RECORD,,
@@ -1,37 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: goosebit
3
- Version: 0.1.0
4
- Summary:
5
- Author: Upstream Data
6
- Author-email: brett@upstreamdata.ca
7
- Requires-Python: >=3.12,<4.0
8
- Classifier: Programming Language :: Python :: 3
9
- Classifier: Programming Language :: Python :: 3.12
10
- Requires-Dist: aerich (>=0.7.2,<0.8.0)
11
- Requires-Dist: aiofiles (>=24.1.0,<25.0.0)
12
- Requires-Dist: fastapi[uvicorn] (>=0.111.0,<0.112.0)
13
- Requires-Dist: itsdangerous (>=2.2.0,<3.0.0)
14
- Requires-Dist: jinja2 (>=3.1.4,<4.0.0)
15
- Requires-Dist: passlib[bcrypt] (>=1.7.4,<2.0.0)
16
- Requires-Dist: python-jose (>=3.3.0,<4.0.0)
17
- Requires-Dist: python-multipart (>=0.0.9,<0.0.10)
18
- Requires-Dist: tortoise-orm (>=0.21.4,<0.22.0)
19
- Requires-Dist: websockets (>=12.0,<13.0)
20
- Description-Content-Type: text/markdown
21
-
22
- # goosebit
23
- <img src="docs/img/goosebit-logo.png?raw=true" style="width: 100px; height: 100px; display: block;">
24
-
25
- ---
26
-
27
- A simplistic remote update server.
28
-
29
-
30
- ## Setup
31
-
32
- To set up, install the dependencies in `pyproject.toml` with `poetry install`. Then you can run GooseBit by running `main.py`.
33
-
34
- ## Initial Startup
35
-
36
- The first time you start GooseBit, you should change the default username and password inside `goosebit/settings.py`, as well as generate a new secret key.
37
- The default login credentials for testing are `admin@goosebit.local`, `admin`.
@@ -1,48 +0,0 @@
1
- goosebit/__init__.py,sha256=hfY3hKnwkJewwVT_DDFm_FjsvSUMsVDsBECL2g1gMOQ,1837
2
- goosebit/api/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
3
- goosebit/api/devices.py,sha256=PwjYuG3omM59EDQNGwyPik4wuZ_NOwfRoLBSFHoTMBM,3219
4
- goosebit/api/download.py,sha256=I9aL3ZkT2T5hfyTsuwwR5vFF5XjqnjHV0WjK0p-oToQ,607
5
- goosebit/api/firmware.py,sha256=0bvQuDX4ReiT6Xp4OA6pYQQ7u62DkOFoAnK7soZY2OQ,1778
6
- goosebit/api/routes.py,sha256=JLXWOwvOyLGcHX2nDl9ZVJSan5wdfDueYn0XGLPQ0NA,365
7
- goosebit/auth/__init__.py,sha256=47vSo8srLG_8P1gdb0mmnrxfqsvohIwdzrQbcliEo5g,3638
8
- goosebit/db.py,sha256=lIQR3s290qZX54NL1J-85Ge6l98xbV9_oRaCO48vdTY,787
9
- goosebit/models.py,sha256=7DMMZ29XnNnMjkfOiZ_lgLNf_3j_az4PlrfxfB2PTlw,765
10
- goosebit/permissions.py,sha256=Yg90HiQLfInSiP-_tUeirXrTc4CpuNSrIsBp3QYCTYI,1166
11
- goosebit/realtime/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
12
- goosebit/realtime/logs.py,sha256=hopd4zpEmTU4_De_tJwItoyyNjk1JiN5onyM8_q07S0,1207
13
- goosebit/realtime/routes.py,sha256=DzL1xBsdSc4SF2FiOAeuVKmcAq3m4DYo6KqD_pCNMww,269
14
- goosebit/settings.py,sha256=4bryUrICSDB_GDb0mNv7ix5vGH8qmZCo5KDYHqgqZuA,1163
15
- goosebit/ui/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
16
- goosebit/ui/routes.py,sha256=Iy7B1v5_Ao_KKEe_hI10C7hiQOOIiJJxAgcnW3_CW9U,2791
17
- goosebit/ui/static/__init__.py,sha256=AsZiM3h9chQ_YaBbAD6TVFf0244Q9DetkDMl70q8swQ,135
18
- goosebit/ui/static/favicon.ico,sha256=FLzKyAkMvQcMg58nzCJxQOfPFxT4yYbP7S82pdY6zng,4286
19
- goosebit/ui/static/favicon.svg,sha256=2iEZocLSave4QTjaR3GxGVT1zaDNl6T_GtN61YHsvJU,6595
20
- goosebit/ui/static/js/devices.js,sha256=IpDhT_9nm9lELVkBriKsIpEReajGfZ7bhsHfpvRaZtE,12550
21
- goosebit/ui/static/js/firmware.js,sha256=S-a8dG6JB_Qvxw0mhG0ksYuPPzk4gLs6AIR_a7suVqk,3919
22
- goosebit/ui/static/js/index.js,sha256=9Mlf679A_P2FcGx7cYfLPi3FVWJ6Yl2_vUPUpP4bEGg,5744
23
- goosebit/ui/static/js/logs.js,sha256=ajaOBtW__CToZLOo17bxNIaY6WkPyy_TDQD0Emwh0DI,611
24
- goosebit/ui/static/svg/goosebit-logo.svg,sha256=2iEZocLSave4QTjaR3GxGVT1zaDNl6T_GtN61YHsvJU,6595
25
- goosebit/ui/templates/__init__.py,sha256=M-F9UIAOVyRdsVIjU-19cCiXh48-LZBAKvl8R4CLlkM,140
26
- goosebit/ui/templates/devices.html,sha256=RQGeBnYZxTI382DuEbUyIRDyd3ZCkxo0vie4hOM905k,3025
27
- goosebit/ui/templates/firmware.html,sha256=JW6h0LxLHcvq4KIgEMXk7qyxWE0bTTbbbpjlOK_vQgE,2059
28
- goosebit/ui/templates/index.html,sha256=hzqo3o1rAqIXw-mTDxc4ah2M35oY3BJibnYNzlSEhiw,1096
29
- goosebit/ui/templates/login.html,sha256=Ip_-p3DbRyCkIjAfEBO2MyzEynQk1m9eKVGpuPLEF3c,1862
30
- goosebit/ui/templates/logs.html,sha256=ysdE8luiO8NNpeqtW2XCZKU7_4Muo13OGh9AzlmJtDg,633
31
- goosebit/ui/templates/nav.html,sha256=0ZWCkg4hJNFM64h_khcg-xs-8VixnYo35LbNi1aiF-I,3529
32
- goosebit/updater/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
33
- goosebit/updater/controller/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
34
- goosebit/updater/controller/routes.py,sha256=8CnLb-kDuO-yFeWdu4apIyctCf9OzvJ011Az3QDGemU,123
35
- goosebit/updater/controller/v1/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
36
- goosebit/updater/controller/v1/routes.py,sha256=-5sjiIRz5_rGppV9tL13ftGKDPYqNhXhzuiY7htXiLo,2290
37
- goosebit/updater/download/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
38
- goosebit/updater/download/routes.py,sha256=HNvpdlZvEeVfpY-JLhvUKHDd9eGKCAOFjh1EN98J9T0,121
39
- goosebit/updater/download/v1/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
40
- goosebit/updater/download/v1/routes.py,sha256=cwzdseHhOzfuze6r8_YuOC-YuPyu9QDvhSs1UZE5dho,840
41
- goosebit/updater/manager.py,sha256=179DJtW0hy5ztv-uM8jhTuavgVTm4JwgMjucSHTpfUU,5896
42
- goosebit/updater/misc.py,sha256=NIYdquYoH6ibGDxnIFVLzTKbb7wwc3eOIxhHXwLR4Ew,2000
43
- goosebit/updater/routes.py,sha256=pziZ15nTUV6zCkvlrdi7r5Az9U2INq3C6X_cj0yYHDw,788
44
- goosebit/updater/updates.py,sha256=OhSeRsXQgzUPffR_SJ_UGepOqScVZREoxNWx6PrxhbA,2837
45
- goosebit-0.1.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
46
- goosebit-0.1.0.dist-info/METADATA,sha256=zta3l3gBIW3roHD4lS-ow0ypntg_lz31u9AVSVbUrEs,1287
47
- goosebit-0.1.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
48
- goosebit-0.1.0.dist-info/RECORD,,