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.
- {goosebit-0.2.9 → goosebit-0.2.10}/PKG-INFO +4 -4
- {goosebit-0.2.9 → goosebit-0.2.10}/README.md +3 -3
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/schema/devices.py +3 -23
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/schema/rollouts.py +2 -12
- goosebit-0.2.10/goosebit/ui/bff/common/columns.py +207 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/devices/routes.py +4 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/rollouts/routes.py +6 -1
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/software/responses.py +2 -2
- {goosebit-0.2.9 → goosebit-0.2.10}/pyproject.toml +1 -1
- goosebit-0.2.9/goosebit/ui/bff/common/columns.py +0 -50
- {goosebit-0.2.9 → goosebit-0.2.10}/LICENSE +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/__main__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/responses.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/routes.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/telemetry/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/telemetry/metrics.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/telemetry/prometheus/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/telemetry/prometheus/readers.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/telemetry/prometheus/routes.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/telemetry/routes.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/devices/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/devices/device/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/devices/device/responses.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/devices/device/routes.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/devices/requests.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/devices/responses.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/devices/routes.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/download/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/download/routes.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/rollouts/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/rollouts/requests.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/rollouts/responses.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/rollouts/routes.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/routes.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/settings/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/settings/routes.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/settings/users/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/settings/users/requests.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/settings/users/responses.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/settings/users/routes.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/software/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/software/requests.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/software/responses.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/api/v1/software/routes.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/auth/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/auth/permissions.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/config.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/migrations/models/0_20240830054046_init.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/migrations/models/1_20241109151811_update.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/migrations/models/2_20241121113728_update.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/migrations/models/3_20241121140210_update.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/migrations/models/4_20250324110331_update.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/migrations/models/4_20250402085235_rename_uuid_to_id.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/migrations/models/5_20250619090242_null_feed.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/migrations/models/6_20250904081506_add_image_format.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/models.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/pg_ssl_context.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/device_manager.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/plugins/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/schema/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/schema/plugins.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/schema/software.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/schema/updates.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/schema/users.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/settings/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/settings/const.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/settings/schema.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/storage/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/storage/base.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/storage/filesystem.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/storage/s3.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/common/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/common/requests.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/common/responses.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/common/util.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/devices/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/devices/device/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/devices/device/routes.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/devices/requests.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/devices/responses.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/download/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/download/routes.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/rollouts/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/rollouts/responses.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/routes.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/settings/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/settings/routes.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/settings/users/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/settings/users/responses.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/settings/users/routes.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/software/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/bff/software/routes.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/nav.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/routes.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/favicon.ico +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/favicon.svg +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/js/devices.js +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/js/login.js +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/js/logs.js +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/js/rollouts.js +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/js/settings.js +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/js/setup.js +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/js/software.js +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/js/util.js +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/static/svg/goosebit-logo.svg +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/templates/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/templates/devices.html.jinja +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/templates/login.html.jinja +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/templates/logs.html.jinja +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/templates/nav.html.jinja +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/templates/rollouts.html.jinja +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/templates/settings.html.jinja +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/templates/setup.html.jinja +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/ui/templates/software.html.jinja +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updater/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updater/controller/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updater/controller/routes.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updater/controller/v1/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updater/controller/v1/routes.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updater/controller/v1/schema.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updater/routes.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updates/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updates/swdesc/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updates/swdesc/func.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updates/swdesc/rauc.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/updates/swdesc/swu.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/users/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/util/__init__.py +0 -0
- {goosebit-0.2.9 → goosebit-0.2.10}/goosebit/util/path.py +0 -0
- {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.
|
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://
|
102
|
-
- Devices send certain attributes (`sw_version`, `
|
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
|
-
- `
|
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://
|
67
|
-
- Devices send certain attributes (`sw_version`, `
|
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
|
-
- `
|
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,
|
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
|
38
|
-
hardware: HardwareSchema | None
|
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,
|
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
|
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
|
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
|
-
|
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,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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{goosebit-0.2.9 → goosebit-0.2.10}/goosebit/db/migrations/models/5_20250619090242_null_feed.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|