a69ca1e402
Unit Tests / test (push) Successful in 11m20s
Email, calendar, files, webmail (rainloop), and the file manager (filegator) are removed from the main docker-compose stack. They install as independent per-service compose projects via ServiceComposer. On startup, _cleanup_legacy_builtin_containers() stops and removes any of the 5 legacy containers still running from the old main stack (guarded by a one-shot sentinel in _meta.legacy_builtins_cleaned so it never runs twice). Per-service installs (com.docker.compose.project != 'pic') are left untouched. Changes: - docker-compose.yml: remove mail, radicale, webdav, rainloop, filegator blocks; fix dhcp + ntp to profiles: ["core","full"] so they start with --profile core - Makefile: replace all --profile full with --profile core (6 occurrences); remove mailserver.env conditional from update: target - api/legacy_cleanup.py: new module with cleanup_legacy_builtin_containers() - api/app.py: import and call cleanup at startup before reapply_on_startup() - tests/test_legacy_cleanup.py: 7 tests covering sentinel, absent containers, per-service project skip, main-stack removal, exception safety Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
54 lines
2.0 KiB
Python
54 lines
2.0 KiB
Python
"""One-shot cleanup of legacy builtin containers from the old main compose stack."""
|
|
import logging
|
|
import subprocess
|
|
|
|
logger = logging.getLogger('picell')
|
|
|
|
_LEGACY_BUILTIN_CONTAINERS = [
|
|
'cell-mail', 'cell-rainloop', 'cell-radicale', 'cell-webdav', 'cell-filegator',
|
|
]
|
|
|
|
|
|
def cleanup_legacy_builtin_containers(config_manager) -> None:
|
|
"""Remove legacy containers whose compose project is 'pic' (main stack).
|
|
|
|
Idempotent — guarded by _meta.legacy_builtins_cleaned in cell_config.json.
|
|
Containers from per-service installs (project != 'pic') are left untouched.
|
|
"""
|
|
try:
|
|
already_done = config_manager.configs.get('_meta', {}).get('legacy_builtins_cleaned', False)
|
|
if already_done:
|
|
return
|
|
except Exception:
|
|
return
|
|
|
|
removed = []
|
|
for cname in _LEGACY_BUILTIN_CONTAINERS:
|
|
try:
|
|
inspect = subprocess.run(
|
|
['docker', 'inspect', cname,
|
|
'--format', '{{index .Config.Labels "com.docker.compose.project"}}'],
|
|
capture_output=True, text=True, timeout=10,
|
|
)
|
|
if inspect.returncode != 0:
|
|
continue
|
|
project = inspect.stdout.strip()
|
|
if project != 'pic':
|
|
continue
|
|
subprocess.run(['docker', 'stop', cname], capture_output=True, timeout=30)
|
|
subprocess.run(['docker', 'rm', cname], capture_output=True, timeout=30)
|
|
removed.append(cname)
|
|
except Exception as exc:
|
|
logger.warning('cleanup_legacy_builtin_containers: %s: %s', cname, exc)
|
|
|
|
try:
|
|
meta = dict(config_manager.configs.get('_meta', {}))
|
|
meta['legacy_builtins_cleaned'] = True
|
|
config_manager.configs['_meta'] = meta
|
|
config_manager._save_all_configs()
|
|
except Exception as exc:
|
|
logger.warning('cleanup_legacy_builtin_containers: failed to set sentinel: %s', exc)
|
|
|
|
if removed:
|
|
logger.info('Removed legacy builtin containers: %s', ', '.join(removed))
|