Warning, file /swf-monitor/src/monitor_app/viewdir/declared_api.py was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 """GET /api/declared/ — the declared record as its out-of-process readers
0002 take it (swf-epicprod docs/CONTINUOUS_PRODUCTION.md, Declared downtime):
0003 per queue and per endpoint, the rule in force now with its line, the
0004 next window coming, the spans the target was declared over (each to its
0005 end or clearing plus the pilot's cache lag) and the latest span end.
0006 The site canary's provider reads this (site-canary canary/declared.py),
0007 so a standalone process needs no ORM. Anonymous, read-only.
0008 """
0009 from django.utils import timezone
0010 from rest_framework.decorators import api_view, authentication_classes, permission_classes
0011 from rest_framework.permissions import AllowAny
0012 from rest_framework.response import Response
0013
0014 from ..declared import _dt, _iso, canary_declared, declared_for, summary_line
0015
0016
0017 @api_view(['GET'])
0018 @authentication_classes([])
0019 @permission_classes([AllowAny])
0020 def declared_state(request):
0021 now = timezone.now()
0022 out = {'now': _iso(now), 'queues': {}, 'endpoints': {}}
0023 for kind, key in (('queue', 'queues'), ('endpoint', 'endpoints')):
0024 current = declared_for(kind, now=now)
0025 names = sorted(current)
0026 spans = canary_declared(None, now) if kind == 'queue' else {}
0027 for target in names:
0028 slot = current[target]
0029 coming = slot['future'][0] if slot['future'] else None
0030 out[key][target] = {
0031 'in_force': summary_line(slot['active'][0]) if slot['active'] else '',
0032 'coming': summary_line(coming) if coming else '',
0033 'coming_at': _iso(_dt(coming.get('start'))) if coming else None,
0034 'line': slot.get('line', ''),
0035 'spans': (spans.get(target) or {}).get('spans', []),
0036 'last_end': (spans.get(target) or {}).get('last_end'),
0037 }
0038 if kind == 'queue':
0039
0040
0041 for target, info in spans.items():
0042 out[key].setdefault(target, {
0043 'in_force': '', 'coming': '', 'coming_at': None, 'line': '',
0044 'spans': info.get('spans', []), 'last_end': info.get('last_end')})
0045 return Response(out)
0046
0047
0048 @api_view(['GET'])
0049 @authentication_classes([])
0050 @permission_classes([AllowAny])
0051 def storage_doors(request):
0052 """GET /api/storage-doors/ — the storage door canary's record as the
0053 last cycle stored it (site-canary docs/STORAGE_DOORS.md): every door,
0054 its verdict and evidence, the certificate it serves, and a
0055 valid_until so a reader can tell a current reading from a stale one.
0056 Anonymous, read-only; a 503 until a cycle has run. Nothing acts on
0057 this record — it is read by people and by the node guard, which uses
0058 it only to excuse a node for a door's failures."""
0059 from monitor_app.models import CachedProduct
0060 from monitor_app.panda.storage_doors import STATE_KEY
0061 row = CachedProduct.objects.filter(key=STATE_KEY).first()
0062 if row is None or not row.value:
0063 return Response({'error': 'no storage door record stored yet'}, status=503)
0064 return Response(row.value)
0065
0066
0067 @api_view(['GET'])
0068 @authentication_classes([])
0069 @permission_classes([AllowAny])
0070 def node_guard_exclusion(request):
0071 """GET /api/node-guard/exclusion/ — the node guard's published
0072 exclusion as the last cycle stored it (site-canary docs/NODE_GUARD.md,
0073 Actuation): the same document the cycle puts on the bucket's pilot
0074 prefix. Anonymous, read-only; a 503 until a cycle has run."""
0075 from monitor_app.models import CachedProduct
0076 from monitor_app.panda.node_guard import EXCLUSION_KEY
0077 row = CachedProduct.objects.filter(key=EXCLUSION_KEY).first()
0078 if row is None or not row.value:
0079 return Response({'error': 'no exclusion document stored yet'}, status=503)
0080 return Response(row.value)