File indexing completed on 2026-07-22 09:42:03
0001 import json
0002
0003 from django.core.management.base import BaseCommand, CommandError
0004 from django.db import transaction
0005
0006 from monitor_app.models import Entry, EntryContext, EntryVersion
0007
0008
0009 ALARM_CONTEXTS = {'swf-alarms', 'teams'}
0010
0011
0012 class Command(BaseCommand):
0013 help = 'Import alarm Entry/EntryContext/EntryVersion state exported from swf-remote.'
0014
0015 def add_arguments(self, parser):
0016 parser.add_argument('path', help='Path to swf-alarms-export.json')
0017 parser.add_argument(
0018 '--replace',
0019 action='store_true',
0020 help='Replace existing monitor swf-alarms and teams contexts.',
0021 )
0022
0023 def handle(self, *args, **options):
0024 path = options['path']
0025 try:
0026 with open(path) as f:
0027 payload = json.load(f)
0028 except OSError as e:
0029 raise CommandError(f'Cannot read {path}: {e}') from e
0030 except json.JSONDecodeError as e:
0031 raise CommandError(f'Invalid JSON in {path}: {e}') from e
0032
0033 contexts = payload.get('contexts') or []
0034 entries = payload.get('entries') or []
0035 versions = payload.get('versions') or []
0036
0037 context_names = {c.get('name') for c in contexts}
0038 if not context_names <= ALARM_CONTEXTS:
0039 raise CommandError(
0040 f'Unexpected context(s): {sorted(context_names - ALARM_CONTEXTS)}'
0041 )
0042 for row in entries:
0043 if row.get('context_id') not in ALARM_CONTEXTS:
0044 raise CommandError(f"Unexpected entry context: {row.get('context_id')}")
0045
0046 existing = Entry.objects.filter(context_id__in=ALARM_CONTEXTS).exists()
0047 if existing and not options['replace']:
0048 raise CommandError(
0049 'Alarm/team entries already exist. Re-run with --replace to '
0050 'replace monitor alarm state.'
0051 )
0052
0053 with transaction.atomic():
0054 if options['replace']:
0055 EntryVersion.objects.filter(entry__context_id__in=ALARM_CONTEXTS).delete()
0056 Entry.objects.filter(context_id__in=ALARM_CONTEXTS).delete()
0057 EntryContext.objects.filter(name__in=ALARM_CONTEXTS).delete()
0058
0059 for row in contexts:
0060 EntryContext.objects.create(
0061 name=row['name'],
0062 title=row.get('title') or '',
0063 description=row.get('description') or '',
0064 timestamp_created=row.get('timestamp_created') or 0,
0065 timestamp_modified=row.get('timestamp_modified') or 0,
0066 data=row.get('data') or {},
0067 )
0068
0069 pending_parents = []
0070 for row in entries:
0071 pending_parents.append((row['id'], row.get('parent_id')))
0072 Entry.objects.create(
0073 id=row['id'],
0074 title=row.get('title') or '',
0075 content=row.get('content') or '',
0076 kind=row['kind'],
0077 context_id=row.get('context_id'),
0078 name=row.get('name'),
0079 data=row.get('data'),
0080 priority=row.get('priority'),
0081 status=row.get('status'),
0082 archived=bool(row.get('archived')),
0083 parent_id=None,
0084 timestamp_created=row.get('timestamp_created') or 0,
0085 timestamp_modified=row.get('timestamp_modified') or 0,
0086 deleted_at=row.get('deleted_at'),
0087 )
0088
0089 for entry_id, parent_id in pending_parents:
0090 if parent_id:
0091 Entry.objects.filter(id=entry_id).update(parent_id=parent_id)
0092
0093 for row in versions:
0094 EntryVersion.objects.create(
0095 entry_id=row['entry_id'],
0096 version_num=row['version_num'],
0097 title=row.get('title') or '',
0098 content=row.get('content') or '',
0099 data=row.get('data'),
0100 changed_by=row.get('changed_by') or 'unknown',
0101 timestamp=row.get('timestamp') or 0,
0102 )
0103
0104 self.stdout.write(
0105 self.style.SUCCESS(
0106 f"Imported {len(contexts)} contexts, {len(entries)} entries, "
0107 f"and {len(versions)} versions."
0108 )
0109 )