Skip to content

Commit 1866a69

Browse files
b-rowaneasybe
authored andcommitted
feature: remove feed when swapping away from rollout
1 parent b98de21 commit 1866a69

6 files changed

Lines changed: 98 additions & 9 deletions

File tree

goosebit/api/v1/devices/routes.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ async def devices_patch(_: Request, config: DevicesPatchRequest) -> StatusRespon
5959
if await Device.get_or_none(id=dev_id) is None:
6060
raise HTTPException(404, f"Device with ID {dev_id} not found")
6161
device = await DeviceManager.get_device(dev_id)
62+
if config.feed is not None:
63+
await DeviceManager.update_feed(device, config.feed)
6264
if config.software is not None:
6365
if config.software == "rollout":
6466
await DeviceManager.update_update(device, UpdateModeEnum.ROLLOUT, None)
@@ -71,8 +73,6 @@ async def devices_patch(_: Request, config: DevicesPatchRequest) -> StatusRespon
7173
await DeviceManager.update_update(device, UpdateModeEnum.PINNED, None)
7274
if config.name is not None:
7375
await DeviceManager.update_name(device, config.name)
74-
if config.feed is not None:
75-
await DeviceManager.update_feed(device, config.feed)
7676
if config.force_update is not None:
7777
await DeviceManager.update_force_update(device, config.force_update)
7878
if config.auth_token is not None:
@@ -87,6 +87,8 @@ async def devices_patch(_: Request, config: DevicesPatchRequest) -> StatusRespon
8787
async def devices_put(_: Request, config: DevicesPutRequest) -> StatusResponse:
8888
for dev_id in config.devices:
8989
device = await DeviceManager.get_device(dev_id)
90+
if config.feed is not None:
91+
await DeviceManager.update_feed(device, config.feed)
9092
if config.software is not None:
9193
if config.software == "rollout":
9294
await DeviceManager.update_update(device, UpdateModeEnum.ROLLOUT, None)
@@ -99,8 +101,6 @@ async def devices_put(_: Request, config: DevicesPutRequest) -> StatusResponse:
99101
await DeviceManager.update_update(device, UpdateModeEnum.PINNED, None)
100102
if config.name is not None:
101103
await DeviceManager.update_name(device, config.name)
102-
if config.feed is not None:
103-
await DeviceManager.update_feed(device, config.feed)
104104
if config.force_update is not None:
105105
await DeviceManager.update_force_update(device, config.force_update)
106106
if config.auth_token is not None:
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
from tortoise import BaseDBAsyncClient
2+
3+
4+
async def upgrade(db: BaseDBAsyncClient) -> str:
5+
dialect = db.schema_generator.DIALECT
6+
7+
if dialect == "postgres":
8+
return """
9+
ALTER TABLE "device" ALTER COLUMN "feed" DROP NOT NULL;"""
10+
11+
return """PRAGMA foreign_keys=off;
12+
13+
CREATE TABLE "device_new" (
14+
"id" CHAR(255) NOT NULL PRIMARY KEY,
15+
"name" CHAR(255),
16+
"assigned_software_id" INT,
17+
"force_update" INT NOT NULL DEFAULT 0,
18+
"sw_version" CHAR(255),
19+
"hardware_id" INT NOT NULL,
20+
"feed" CHAR(255) DEFAULT 'default', -- NULL allowed here
21+
"update_mode" INT NOT NULL DEFAULT 0,
22+
"last_state" INT NOT NULL DEFAULT 0,
23+
"progress" INT,
24+
"last_log" TEXT,
25+
"last_seen" BIGINT,
26+
"last_ip" CHAR(15),
27+
"last_ipv6" CHAR(40),
28+
"auth_token" CHAR(32)
29+
);
30+
31+
INSERT INTO "device_new" SELECT
32+
id, name, assigned_software_id, force_update, sw_version,
33+
hardware_id, feed, update_mode, last_state, progress,
34+
last_log, last_seen, last_ip, last_ipv6, auth_token
35+
FROM "device";
36+
37+
DROP TABLE "device";
38+
39+
ALTER TABLE "device_new" RENAME TO "device";
40+
41+
PRAGMA foreign_keys=on;
42+
"""
43+
44+
45+
async def downgrade(db: BaseDBAsyncClient) -> str:
46+
dialect = db.schema_generator.DIALECT
47+
48+
if dialect == "postgres":
49+
return """
50+
ALTER TABLE "device" ALTER COLUMN "feed" SET NOT NULL;"""
51+
52+
return """PRAGMA foreign_keys=off;
53+
54+
CREATE TABLE "device_old" (
55+
"id" CHAR(255) NOT NULL PRIMARY KEY,
56+
"name" CHAR(255),
57+
"assigned_software_id" INT,
58+
"force_update" INT NOT NULL DEFAULT 0,
59+
"sw_version" CHAR(255),
60+
"hardware_id" INT NOT NULL,
61+
"feed" CHAR(255) NOT NULL DEFAULT 'default', -- NOT NULL again
62+
"update_mode" INT NOT NULL DEFAULT 0,
63+
"last_state" INT NOT NULL DEFAULT 0,
64+
"progress" INT,
65+
"last_log" TEXT,
66+
"last_seen" BIGINT,
67+
"last_ip" CHAR(15),
68+
"last_ipv6" CHAR(40),
69+
"auth_token" CHAR(32)
70+
);
71+
72+
INSERT INTO "device_old" SELECT
73+
id, name, assigned_software_id, force_update, sw_version,
74+
hardware_id, feed, update_mode, last_state, progress,
75+
last_log, last_seen, last_ip, last_ipv6, auth_token
76+
FROM "device";
77+
78+
DROP TABLE "device";
79+
80+
ALTER TABLE "device_old" RENAME TO "device";
81+
82+
PRAGMA foreign_keys=on;
83+
"""

goosebit/db/models.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class Device(Model):
6464
force_update = fields.BooleanField(default=False)
6565
sw_version = fields.CharField(max_length=255, null=True)
6666
hardware = fields.ForeignKeyField("models.Hardware", related_name="devices")
67-
feed = fields.CharField(max_length=255, default="default")
67+
feed = fields.CharField(max_length=255, default="default", null=True)
6868
update_mode = fields.IntEnumField(UpdateModeEnum, default=UpdateModeEnum.ROLLOUT)
6969
last_state = fields.IntEnumField(UpdateStateEnum, default=UpdateStateEnum.UNKNOWN)
7070
progress = fields.IntField(null=True)
@@ -76,6 +76,10 @@ class Device(Model):
7676
tags = fields.ManyToManyField("models.Tag", related_name="devices", through="device_tags")
7777

7878
async def save(self, *args, **kwargs):
79+
# ensure if using rollout that feed is set
80+
if self.update_mode == UpdateModeEnum.ROLLOUT:
81+
if self.feed is None:
82+
raise ValidationError("Feed must be set in order to use rollout.")
7983
# Check if the software is compatible with the hardware before saving
8084
if self.assigned_software and self.hardware:
8185
# Check if the assigned software is compatible with the hardware

goosebit/device_manager.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,9 @@ async def update_last_connection(device: Device, last_seen: int, last_ip: str |
108108
async def update_update(device: Device, update_mode: UpdateModeEnum, software: Software | None):
109109
device.assigned_software = software
110110
device.update_mode = update_mode
111-
await DeviceManager.save_device(device, update_fields=["assigned_software_id", "update_mode"])
111+
if not update_mode == UpdateModeEnum.ROLLOUT:
112+
device.feed = None
113+
await DeviceManager.save_device(device, update_fields=["assigned_software_id", "update_mode", "feed"])
112114

113115
@staticmethod
114116
async def update_name(device: Device, name: str):

goosebit/schema/devices.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class DeviceSchema(BaseModel):
3737
assigned_software: SoftwareSchema | None = Field(exclude=True)
3838
hardware: HardwareSchema | None = Field(exclude=True)
3939

40-
feed: str
40+
feed: str | None
4141
progress: int | None
4242
last_state: Annotated[UpdateStateSchema, BeforeValidator(UpdateStateSchema.convert)] # type: ignore[valid-type]
4343
update_mode: Annotated[UpdateModeSchema, BeforeValidator(UpdateModeSchema.convert)] # type: ignore[valid-type]

goosebit/ui/bff/devices/routes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ async def devices_patch(_: Request, config: DevicesPatchRequest) -> StatusRespon
6868
if await Device.get_or_none(id=dev_id) is None:
6969
raise HTTPException(404, f"Device with ID {dev_id} not found")
7070
device = await get_device(dev_id)
71+
if config.feed is not None:
72+
await DeviceManager.update_feed(device, config.feed)
7173
if config.software is not None:
7274
if config.software == "rollout":
7375
await DeviceManager.update_update(device, UpdateModeEnum.ROLLOUT, None)
@@ -80,8 +82,6 @@ async def devices_patch(_: Request, config: DevicesPatchRequest) -> StatusRespon
8082
await DeviceManager.update_update(device, UpdateModeEnum.PINNED, None)
8183
if config.name is not None:
8284
await DeviceManager.update_name(device, config.name)
83-
if config.feed is not None:
84-
await DeviceManager.update_feed(device, config.feed)
8585
if config.force_update is not None:
8686
await DeviceManager.update_force_update(device, config.force_update)
8787
if config.auth_token is not None:

0 commit comments

Comments
 (0)