goosebit 0.2.9__tar.gz → 0.2.10__tar.gz

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.
Files changed (137) hide show
  1. {goosebit-0.2.9 → goosebit-0.2.10}/PKG-INFO +4 -4
  2. {goosebit-0.2.9 → goosebit-0.2.10}/README.md +3 -3
  3. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/schema/devices.py +3 -23
  4. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/schema/rollouts.py +2 -12
  5. goosebit-0.2.10/goosebit/ui/bff/common/columns.py +207 -0
  6. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/devices/routes.py +4 -0
  7. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/rollouts/routes.py +6 -1
  8. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/software/responses.py +2 -2
  9. {goosebit-0.2.9 → goosebit-0.2.10}/pyproject.toml +1 -1
  10. goosebit-0.2.9/goosebit/ui/bff/common/columns.py +0 -50
  11. {goosebit-0.2.9 → goosebit-0.2.10}/LICENSE +0 -0
  12. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/__init__.py +0 -0
  13. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/__main__.py +0 -0
  14. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/__init__.py +0 -0
  15. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/responses.py +0 -0
  16. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/routes.py +0 -0
  17. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/telemetry/__init__.py +0 -0
  18. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/telemetry/metrics.py +0 -0
  19. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/telemetry/prometheus/__init__.py +0 -0
  20. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/telemetry/prometheus/readers.py +0 -0
  21. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/telemetry/prometheus/routes.py +0 -0
  22. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/telemetry/routes.py +0 -0
  23. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/__init__.py +0 -0
  24. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/devices/__init__.py +0 -0
  25. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/devices/device/__init__.py +0 -0
  26. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/devices/device/responses.py +0 -0
  27. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/devices/device/routes.py +0 -0
  28. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/devices/requests.py +0 -0
  29. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/devices/responses.py +0 -0
  30. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/devices/routes.py +0 -0
  31. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/download/__init__.py +0 -0
  32. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/download/routes.py +0 -0
  33. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/rollouts/__init__.py +0 -0
  34. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/rollouts/requests.py +0 -0
  35. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/rollouts/responses.py +0 -0
  36. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/rollouts/routes.py +0 -0
  37. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/routes.py +0 -0
  38. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/settings/__init__.py +0 -0
  39. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/settings/routes.py +0 -0
  40. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/settings/users/__init__.py +0 -0
  41. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/settings/users/requests.py +0 -0
  42. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/settings/users/responses.py +0 -0
  43. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/settings/users/routes.py +0 -0
  44. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/software/__init__.py +0 -0
  45. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/software/requests.py +0 -0
  46. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/software/responses.py +0 -0
  47. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/software/routes.py +0 -0
  48. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/auth/__init__.py +0 -0
  49. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/auth/permissions.py +0 -0
  50. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/__init__.py +0 -0
  51. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/config.py +0 -0
  52. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/migrations/models/0_20240830054046_init.py +0 -0
  53. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/migrations/models/1_20241109151811_update.py +0 -0
  54. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/migrations/models/2_20241121113728_update.py +0 -0
  55. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/migrations/models/3_20241121140210_update.py +0 -0
  56. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/migrations/models/4_20250324110331_update.py +0 -0
  57. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/migrations/models/4_20250402085235_rename_uuid_to_id.py +0 -0
  58. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/migrations/models/5_20250619090242_null_feed.py +0 -0
  59. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/migrations/models/6_20250904081506_add_image_format.py +0 -0
  60. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/models.py +0 -0
  61. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/pg_ssl_context.py +0 -0
  62. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/device_manager.py +0 -0
  63. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/plugins/__init__.py +0 -0
  64. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/schema/__init__.py +0 -0
  65. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/schema/plugins.py +0 -0
  66. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/schema/software.py +0 -0
  67. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/schema/updates.py +0 -0
  68. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/schema/users.py +0 -0
  69. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/settings/__init__.py +0 -0
  70. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/settings/const.py +0 -0
  71. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/settings/schema.py +0 -0
  72. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/storage/__init__.py +0 -0
  73. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/storage/base.py +0 -0
  74. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/storage/filesystem.py +0 -0
  75. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/storage/s3.py +0 -0
  76. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/__init__.py +0 -0
  77. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/__init__.py +0 -0
  78. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/common/__init__.py +0 -0
  79. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/common/requests.py +0 -0
  80. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/common/responses.py +0 -0
  81. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/common/util.py +0 -0
  82. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/devices/__init__.py +0 -0
  83. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/devices/device/__init__.py +0 -0
  84. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/devices/device/routes.py +0 -0
  85. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/devices/requests.py +0 -0
  86. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/devices/responses.py +0 -0
  87. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/download/__init__.py +0 -0
  88. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/download/routes.py +0 -0
  89. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/rollouts/__init__.py +0 -0
  90. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/rollouts/responses.py +0 -0
  91. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/routes.py +0 -0
  92. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/settings/__init__.py +0 -0
  93. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/settings/routes.py +0 -0
  94. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/settings/users/__init__.py +0 -0
  95. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/settings/users/responses.py +0 -0
  96. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/settings/users/routes.py +0 -0
  97. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/software/__init__.py +0 -0
  98. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/software/routes.py +0 -0
  99. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/nav.py +0 -0
  100. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/routes.py +0 -0
  101. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/__init__.py +0 -0
  102. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/favicon.ico +0 -0
  103. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/favicon.svg +0 -0
  104. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/js/devices.js +0 -0
  105. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/js/login.js +0 -0
  106. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/js/logs.js +0 -0
  107. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/js/rollouts.js +0 -0
  108. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/js/settings.js +0 -0
  109. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/js/setup.js +0 -0
  110. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/js/software.js +0 -0
  111. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/js/util.js +0 -0
  112. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/svg/goosebit-logo.svg +0 -0
  113. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/templates/__init__.py +0 -0
  114. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/templates/devices.html.jinja +0 -0
  115. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/templates/login.html.jinja +0 -0
  116. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/templates/logs.html.jinja +0 -0
  117. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/templates/nav.html.jinja +0 -0
  118. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/templates/rollouts.html.jinja +0 -0
  119. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/templates/settings.html.jinja +0 -0
  120. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/templates/setup.html.jinja +0 -0
  121. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/templates/software.html.jinja +0 -0
  122. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updater/__init__.py +0 -0
  123. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updater/controller/__init__.py +0 -0
  124. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updater/controller/routes.py +0 -0
  125. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updater/controller/v1/__init__.py +0 -0
  126. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updater/controller/v1/routes.py +0 -0
  127. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updater/controller/v1/schema.py +0 -0
  128. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updater/routes.py +0 -0
  129. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updates/__init__.py +0 -0
  130. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updates/swdesc/__init__.py +0 -0
  131. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updates/swdesc/func.py +0 -0
  132. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updates/swdesc/rauc.py +0 -0
  133. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updates/swdesc/swu.py +0 -0
  134. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/users/__init__.py +0 -0
  135. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/util/__init__.py +0 -0
  136. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/util/path.py +0 -0
  137. {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/util/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: goosebit
3
- Version: 0.2.9
3
+ Version: 0.2.10
4
4
  Summary: A simplistic, opinionated remote update server implementing hawkBit™'s DDI API
5
5
  Author: Brett Rowan
6
6
  Author-email: 121075405+b-rowan@users.noreply.github.com
@@ -98,8 +98,8 @@ The software packages managed by gooseBit are either stored on the local filesys
98
98
 
99
99
  ## Assumptions
100
100
 
101
- - Devices use [SWUpdate](https://swupdate.org) or [RAUC](https://github.com/rauc/rauc) + [RAUC hawkBit Updater](https://github.com/rauc/rauc-hawkbit-updater) for managing software updates.
102
- - Devices send certain attributes (`sw_version`, `hw_model`, `hw_revision`).
101
+ - Devices use [SWUpdate](https://swupdate.org) or [RAUC](https://rauc.io) + [RAUC hawkBit Updater](https://rauc-hawkbit-updater.readthedocs.io) for managing software updates.
102
+ - Devices send certain attributes (`sw_version`, `hw_boardname`, `hw_revision`).
103
103
  - Semantic versions are used.
104
104
  - With RAUC and multiple hardware revisions, `compatible` in `manifest.raucm` is set to something like `my-board-rev4.2` or `Some Board 2b`.
105
105
 
@@ -109,7 +109,7 @@ The software packages managed by gooseBit are either stored on the local filesys
109
109
 
110
110
  When a device connects to gooseBit for the first time, it is automatically added to the device registry. The server will then request the device's configuration data, including:
111
111
 
112
- - `hw_model` and `hw_revision`: Used to match compatible software.
112
+ - `hw_boardname` and `hw_revision`: Used to match compatible software.
113
113
  - `sw_version`: Indicates the currently installed software version.
114
114
 
115
115
  The registry tracks each device's status, including the last online timestamp, installed software version, update state, and more.
@@ -63,8 +63,8 @@ The software packages managed by gooseBit are either stored on the local filesys
63
63
 
64
64
  ## Assumptions
65
65
 
66
- - Devices use [SWUpdate](https://swupdate.org) or [RAUC](https://github.com/rauc/rauc) + [RAUC hawkBit Updater](https://github.com/rauc/rauc-hawkbit-updater) for managing software updates.
67
- - Devices send certain attributes (`sw_version`, `hw_model`, `hw_revision`).
66
+ - Devices use [SWUpdate](https://swupdate.org) or [RAUC](https://rauc.io) + [RAUC hawkBit Updater](https://rauc-hawkbit-updater.readthedocs.io) for managing software updates.
67
+ - Devices send certain attributes (`sw_version`, `hw_boardname`, `hw_revision`).
68
68
  - Semantic versions are used.
69
69
  - With RAUC and multiple hardware revisions, `compatible` in `manifest.raucm` is set to something like `my-board-rev4.2` or `Some Board 2b`.
70
70
 
@@ -74,7 +74,7 @@ The software packages managed by gooseBit are either stored on the local filesys
74
74
 
75
75
  When a device connects to gooseBit for the first time, it is automatically added to the device registry. The server will then request the device's configuration data, including:
76
76
 
77
- - `hw_model` and `hw_revision`: Used to match compatible software.
77
+ - `hw_boardname` and `hw_revision`: Used to match compatible software.
78
78
  - `sw_version`: Indicates the currently installed software version.
79
79
 
80
80
  The registry tracks each device's status, including the last online timestamp, installed software version, update state, and more.
@@ -5,7 +5,7 @@ from datetime import datetime
5
5
  from enum import Enum, IntEnum, StrEnum
6
6
  from typing import Annotated
7
7
 
8
- from pydantic import BaseModel, BeforeValidator, ConfigDict, Field, computed_field
8
+ from pydantic import BaseModel, BeforeValidator, ConfigDict, computed_field
9
9
 
10
10
  from goosebit.db.models import UpdateModeEnum, UpdateStateEnum
11
11
  from goosebit.schema.software import HardwareSchema, SoftwareSchema
@@ -34,8 +34,8 @@ class DeviceSchema(BaseModel):
34
34
  name: str | None
35
35
  sw_version: str | None
36
36
 
37
- assigned_software: SoftwareSchema | None = Field(exclude=True)
38
- hardware: HardwareSchema | None = Field(exclude=True)
37
+ assigned_software: SoftwareSchema | None
38
+ hardware: HardwareSchema | None
39
39
 
40
40
  feed: str | None
41
41
  progress: int | None
@@ -53,26 +53,6 @@ class DeviceSchema(BaseModel):
53
53
  def polling(self) -> bool | None:
54
54
  return self.last_seen < (self.poll_seconds + 10) if self.last_seen is not None else None
55
55
 
56
- @computed_field # type: ignore[misc]
57
- @property
58
- def sw_target_version(self) -> str | None:
59
- return self.assigned_software.version if self.assigned_software is not None else None
60
-
61
- @computed_field # type: ignore[misc]
62
- @property
63
- def sw_assigned(self) -> int | None:
64
- return self.assigned_software.id if self.assigned_software is not None else None
65
-
66
- @computed_field # type: ignore[misc]
67
- @property
68
- def hw_model(self) -> str | None:
69
- return self.hardware.model if self.hardware is not None else None
70
-
71
- @computed_field # type: ignore[misc]
72
- @property
73
- def hw_revision(self) -> str | None:
74
- return self.hardware.revision if self.hardware is not None else None
75
-
76
56
  @computed_field # type: ignore[misc]
77
57
  @property
78
58
  def poll_seconds(self) -> int:
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from datetime import datetime
4
4
 
5
- from pydantic import BaseModel, ConfigDict, Field, computed_field, field_serializer
5
+ from pydantic import BaseModel, ConfigDict, field_serializer
6
6
 
7
7
  from goosebit.schema.software import SoftwareSchema
8
8
 
@@ -14,21 +14,11 @@ class RolloutSchema(BaseModel):
14
14
  created_at: datetime
15
15
  name: str | None
16
16
  feed: str
17
- software: SoftwareSchema = Field(exclude=True)
17
+ software: SoftwareSchema
18
18
  paused: bool
19
19
  success_count: int
20
20
  failure_count: int
21
21
 
22
- @computed_field # type: ignore[misc]
23
- @property
24
- def sw_version(self) -> str:
25
- return self.software.version
26
-
27
- @computed_field # type: ignore[misc]
28
- @property
29
- def sw_file(self) -> str:
30
- return self.software.path.name
31
-
32
22
  @field_serializer("created_at")
33
23
  def serialize_created_at(self, created_at: datetime, _info):
34
24
  return int(created_at.timestamp() * 1000)
@@ -0,0 +1,207 @@
1
+ from .responses import DTColumnDescription
2
+
3
+
4
+ class DeviceColumns:
5
+ id = DTColumnDescription(
6
+ title="ID",
7
+ data="id",
8
+ name="id",
9
+ searchable=True,
10
+ orderable=True,
11
+ )
12
+ name = DTColumnDescription(
13
+ title="Name",
14
+ data="name",
15
+ name="name",
16
+ searchable=True,
17
+ orderable=True,
18
+ )
19
+ hw_model = DTColumnDescription(
20
+ title="Model",
21
+ data="hardware.model",
22
+ name="hardware__model",
23
+ searchable=True,
24
+ orderable=True,
25
+ )
26
+ hw_revision = DTColumnDescription(
27
+ title="Revision",
28
+ data="hardware.revision",
29
+ name="hardware__revision",
30
+ searchable=True,
31
+ orderable=True,
32
+ )
33
+ feed = DTColumnDescription(
34
+ title="Feed",
35
+ data="feed",
36
+ name="feed",
37
+ searchable=True,
38
+ orderable=True,
39
+ )
40
+ sw_version = DTColumnDescription(
41
+ title="Installed Software",
42
+ data="sw_version",
43
+ name="sw_version",
44
+ searchable=True,
45
+ orderable=True,
46
+ )
47
+ sw_target_version = DTColumnDescription(
48
+ title="Target Software",
49
+ data="assigned_software.version",
50
+ name="assigned_software__version",
51
+ searchable=True,
52
+ orderable=True,
53
+ )
54
+ update_mode = DTColumnDescription(
55
+ title="Update Mode",
56
+ data="update_mode",
57
+ name="update_mode",
58
+ searchable=True,
59
+ orderable=True,
60
+ )
61
+ last_state = DTColumnDescription(
62
+ title="State",
63
+ data="last_state",
64
+ name="last_state",
65
+ searchable=True,
66
+ orderable=True,
67
+ )
68
+ force_update = DTColumnDescription(
69
+ title="Force Update",
70
+ data="force_update",
71
+ name="force_update",
72
+ orderable=True,
73
+ )
74
+ progress = DTColumnDescription(
75
+ title="Progress",
76
+ data="progress",
77
+ name="progress",
78
+ orderable=True,
79
+ )
80
+ last_ip = DTColumnDescription(
81
+ title="Last IP",
82
+ data="last_ip",
83
+ name="last_ip",
84
+ searchable=True,
85
+ orderable=True,
86
+ )
87
+ polling = DTColumnDescription(
88
+ title="Polling",
89
+ data="polling",
90
+ )
91
+ last_seen = DTColumnDescription(
92
+ title="Last Seen",
93
+ data="last_seen",
94
+ name="last_seen",
95
+ orderable=True,
96
+ )
97
+
98
+
99
+ class RolloutColumns:
100
+ id = DTColumnDescription(
101
+ title="ID",
102
+ data="id",
103
+ visible=False,
104
+ )
105
+ created_at = DTColumnDescription(
106
+ title="Created",
107
+ data="created_at",
108
+ name="created_at",
109
+ orderable=True,
110
+ )
111
+ name = DTColumnDescription(
112
+ title="Name",
113
+ data="name",
114
+ name="name",
115
+ searchable=True,
116
+ orderable=True,
117
+ )
118
+ feed = DTColumnDescription(
119
+ title="Feed",
120
+ data="feed",
121
+ name="feed",
122
+ searchable=True,
123
+ orderable=True,
124
+ )
125
+ sw_file = DTColumnDescription(
126
+ title="Software File",
127
+ data="software.name",
128
+ name="software__uri", # May cause strange orderings sorting by uri instead of the end of the path
129
+ searchable=True,
130
+ orderable=True,
131
+ )
132
+ sw_version = DTColumnDescription(
133
+ title="Software Version",
134
+ data="software.version",
135
+ name="software__version",
136
+ searchable=True,
137
+ orderable=True,
138
+ )
139
+ paused = DTColumnDescription(
140
+ title="Paused",
141
+ name="paused",
142
+ data="paused",
143
+ orderable=True,
144
+ )
145
+ success_count = DTColumnDescription(
146
+ title="Success Count",
147
+ data="success_count",
148
+ name="success_count",
149
+ orderable=True,
150
+ )
151
+ failure_count = DTColumnDescription(
152
+ title="Failure Count",
153
+ data="failure_count",
154
+ name="failure_count",
155
+ orderable=True,
156
+ )
157
+
158
+
159
+ class SoftwareColumns:
160
+ id = DTColumnDescription(
161
+ title="ID",
162
+ data="id",
163
+ visible=False,
164
+ )
165
+ name = DTColumnDescription(
166
+ title="Name",
167
+ data="name",
168
+ name="uri", # May cause strange orderings sorting by uri instead of the end of the path
169
+ searchable=True,
170
+ orderable=True,
171
+ )
172
+ version = DTColumnDescription(
173
+ title="Version",
174
+ data="version",
175
+ name="version",
176
+ searchable=True,
177
+ orderable=True,
178
+ )
179
+ compatibility = DTColumnDescription(
180
+ title="Compatibility",
181
+ name="compatibility",
182
+ data="compatibility",
183
+ )
184
+ size = DTColumnDescription(
185
+ title="Size",
186
+ name="size",
187
+ data="size",
188
+ orderable=True,
189
+ )
190
+
191
+
192
+ class SettingsUsersColumns:
193
+ username = DTColumnDescription(
194
+ title="Username",
195
+ data="username",
196
+ searchable=True,
197
+ orderable=True,
198
+ )
199
+ enabled = DTColumnDescription(
200
+ title="Enabled",
201
+ data="enabled",
202
+ orderable=True,
203
+ )
204
+ permissions = DTColumnDescription(
205
+ title="Permissions",
206
+ data="permissions",
207
+ )
@@ -37,10 +37,14 @@ async def devices_get(dt_query: Annotated[DataTableRequest, Depends(parse_datata
37
37
  return (
38
38
  Q(id__icontains=search_value)
39
39
  | Q(name__icontains=search_value)
40
+ | Q(hardware__model__icontains=search_value)
41
+ | Q(hardware__revision__icontains=search_value)
40
42
  | Q(feed__icontains=search_value)
41
43
  | Q(sw_version__icontains=search_value)
44
+ | Q(assigned_software__version__icontains=search_value)
42
45
  | Q(update_mode=int(UpdateModeEnum.from_str(search_value)))
43
46
  | Q(last_state=int(UpdateStateEnum.from_str(search_value)))
47
+ | Q(last_ip__icontains=search_value)
44
48
  )
45
49
 
46
50
  query = Device.all().prefetch_related("assigned_software", "hardware", "assigned_software__compatibility")
@@ -23,7 +23,12 @@ router = APIRouter(prefix="/rollouts")
23
23
  )
24
24
  async def rollouts_get(dt_query: Annotated[DataTableRequest, Depends(parse_datatables_query)]) -> BFFRolloutsResponse:
25
25
  def search_filter(search_value):
26
- return Q(name__icontains=search_value) | Q(feed__icontains=search_value)
26
+ return (
27
+ Q(name__icontains=search_value)
28
+ | Q(feed__icontains=search_value)
29
+ | Q(software__uri__icontains=search_value)
30
+ | Q(software__version__icontains=search_value)
31
+ )
27
32
 
28
33
  query = Rollout.all().prefetch_related("software", "software__compatibility")
29
34
 
@@ -5,7 +5,8 @@ from tortoise.expressions import Q
5
5
  from tortoise.queryset import QuerySet
6
6
 
7
7
  from goosebit.schema.software import SoftwareSchema
8
- from goosebit.ui.bff.common.requests import DataTableOrderDirection, DataTableRequest
8
+
9
+ from ..common.requests import DataTableOrderDirection, DataTableRequest
9
10
 
10
11
 
11
12
  class BFFSoftwareResponse(BaseModel):
@@ -41,7 +42,6 @@ class BFFSoftwareResponse(BaseModel):
41
42
  query = query.limit(dt_query.length)
42
43
 
43
44
  software = await query.offset(dt_query.start).all()
44
-
45
45
  data = [SoftwareSchema.model_validate(s) for s in software]
46
46
 
47
47
  return cls(data=data, draw=dt_query.draw, records_total=total_records, records_filtered=filtered_records)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "goosebit"
3
- version = "0.2.9"
3
+ version = "0.2.10"
4
4
  description = "A simplistic, opinionated remote update server implementing hawkBit™'s DDI API"
5
5
  authors = [
6
6
  {name = "Brett Rowan", email = "121075405+b-rowan@users.noreply.github.com"}
@@ -1,50 +0,0 @@
1
- from .responses import DTColumnDescription
2
-
3
-
4
- class DeviceColumns:
5
- id = DTColumnDescription(title="ID", data="id", name="id", searchable=True, orderable=True)
6
- name = DTColumnDescription(title="Name", data="name", name="name", searchable=True, orderable=True)
7
- hw_model = DTColumnDescription(title="Model", data="hw_model")
8
- hw_revision = DTColumnDescription(title="Revision", data="hw_revision")
9
- feed = DTColumnDescription(title="Feed", data="feed", name="feed", searchable=True, orderable=True)
10
- sw_version = DTColumnDescription(
11
- title="Installed Software", data="sw_version", name="sw_version", searchable=True, orderable=True
12
- )
13
- sw_target_version = DTColumnDescription(title="Target Software", data="sw_target_version")
14
- update_mode = DTColumnDescription(
15
- title="Update Mode", data="update_mode", name="update_mode", searchable=True, orderable=True
16
- )
17
- last_state = DTColumnDescription(
18
- title="State", data="last_state", name="last_state", searchable=True, orderable=True
19
- )
20
- force_update = DTColumnDescription(title="Force Update", data="force_update")
21
- progress = DTColumnDescription(title="Progress", data="progress")
22
- last_ip = DTColumnDescription(title="Last IP", data="last_ip")
23
- polling = DTColumnDescription(title="Polling", data="polling")
24
- last_seen = DTColumnDescription(title="Last Seen", data="last_seen")
25
-
26
-
27
- class RolloutColumns:
28
- id = DTColumnDescription(title="ID", data="id", visible=False)
29
- created_at = DTColumnDescription(title="Created", data="created_at", name="created_at", orderable=True)
30
- name = DTColumnDescription(title="Name", data="name", name="name", searchable=True, orderable=True)
31
- feed = DTColumnDescription(title="Feed", data="feed", name="feed", searchable=True, orderable=True)
32
- sw_file = DTColumnDescription(title="Software File", data="sw_file", name="sw_file")
33
- sw_version = DTColumnDescription(title="Software Version", data="sw_version", name="sw_version")
34
- paused = DTColumnDescription(title="Paused", name="paused", data="paused")
35
- success_count = DTColumnDescription(title="Success Count", data="success_count", name="success_count")
36
- failure_count = DTColumnDescription(title="Failure Count", data="failure_count", name="failure_count")
37
-
38
-
39
- class SoftwareColumns:
40
- id = DTColumnDescription(title="ID", data="id", visible=False)
41
- name = DTColumnDescription(title="Name", data="name", name="name")
42
- version = DTColumnDescription(title="Version", data="version", name="version", searchable=True, orderable=True)
43
- compatibility = DTColumnDescription(title="Compatibility", name="compatibility", data="compatibility")
44
- size = DTColumnDescription(title="Size", name="size", data="size")
45
-
46
-
47
- class SettingsUsersColumns:
48
- username = DTColumnDescription(title="Username", data="username", searchable=True, orderable=True)
49
- enabled = DTColumnDescription(title="Enabled", data="enabled")
50
- permissions = DTColumnDescription(title="Permissions", data="permissions")
File without changes
File without changes
File without changes
File without changes