fix(seeder): skip catalog sync for installed apps on diverged host ports
The catalog sync added in the supply depot work overwrites container_config and ui_location for any curated service not flagged is_user_modified. Apps installed on an alternate host port before that flag existed (e.g. because the catalog default port was already taken on the host) have their record reset to the catalog port on the next boot, desyncing it from the running container and breaking the app's open link. Compare the published host ports of the existing record against the catalog and leave the row alone when an installed app diverges. Only host ports are compared, so catalog corrections to internal container ports (Meshtastic 80->8080) and ui_location scheme changes (Vaultwarden https:8480) still reach existing installs.
This commit is contained in:
parent
bcee7529a0
commit
8f79d429de
|
|
@ -517,6 +517,8 @@ export default class ServiceSeeder extends BaseSeeder {
|
|||
'service_name',
|
||||
'is_custom',
|
||||
'is_user_modified',
|
||||
'installed',
|
||||
'container_config',
|
||||
])
|
||||
const existingServiceMap = new Map(existingServices.map((s) => [s.service_name, s]))
|
||||
|
||||
|
|
@ -536,14 +538,51 @@ export default class ServiceSeeder extends BaseSeeder {
|
|||
for (const service of ServiceSeeder.DEFAULT_SERVICES) {
|
||||
const existing = existingServiceMap.get(service.service_name)
|
||||
if (existing && !existing.is_custom && !existing.is_user_modified) {
|
||||
await Service.query().where('service_name', service.service_name).update({
|
||||
container_config: service.container_config,
|
||||
container_command: service.container_command ?? null,
|
||||
metadata: (service as any).metadata ?? null,
|
||||
category: service.category,
|
||||
ui_location: service.ui_location,
|
||||
})
|
||||
// An installed app whose published host ports differ from the catalog was deployed on
|
||||
// an alternate port (e.g. the default was already taken on that host) before the
|
||||
// is_user_modified flag could record it. Adopting the catalog values would desync the
|
||||
// record from the running container and break the app's link, so leave the row alone.
|
||||
// Only host ports are compared: catalog corrections to internal container ports or the
|
||||
// ui_location scheme still sync.
|
||||
if (
|
||||
existing.installed &&
|
||||
hostPortsDiffer(existing.container_config, service.container_config)
|
||||
) {
|
||||
continue
|
||||
}
|
||||
await Service.query()
|
||||
.where('service_name', service.service_name)
|
||||
.update({
|
||||
container_config: service.container_config,
|
||||
container_command: service.container_command ?? null,
|
||||
metadata: (service as any).metadata ?? null,
|
||||
category: service.category,
|
||||
ui_location: service.ui_location,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Whether two serialized container configs publish a different set of host ports. */
|
||||
function hostPortsDiffer(existingConfig: string | null, catalogConfig: string | null): boolean {
|
||||
const hostPorts = (raw: string | null): string | null => {
|
||||
if (!raw) return null
|
||||
try {
|
||||
const bindings = JSON.parse(raw)?.HostConfig?.PortBindings ?? {}
|
||||
return Object.values(bindings)
|
||||
.flat()
|
||||
.map((b: any) => b?.HostPort)
|
||||
.filter(Boolean)
|
||||
.sort()
|
||||
.join(',')
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
const existing = hostPorts(existingConfig)
|
||||
const catalog = hostPorts(catalogConfig)
|
||||
// If either side is absent or unparseable, divergence can't be established — let the sync run.
|
||||
if (existing === null || catalog === null) return false
|
||||
return existing !== catalog
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue