fires: resolve FIRMS_MAP_KEY from Postgres keystore, not just env
All checks were successful
build-and-deploy / build (push) Successful in 1m40s
All checks were successful
build-and-deploy / build (push) Successful in 1m40s
Key saved via the dashboard Keys page sat unused in api_keys while ingest_fires only checked the env var. Now env first, keystore fallback, picked up on next poll without a restart.
This commit is contained in:
parent
b1c611d4c4
commit
e6648ec1ed
2 changed files with 72 additions and 6 deletions
|
|
@ -25,12 +25,14 @@ import csv
|
|||
import io
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
from datetime import datetime, timezone
|
||||
|
||||
import httpx
|
||||
import nats
|
||||
|
||||
from config import FIRMS_MAP_KEY, FIRMS_DATASET, FIRMS_BBOX, FIRMS_TIMEOUT, NATS_URL
|
||||
from config import FIRMS_DATASET, FIRMS_BBOX, FIRMS_TIMEOUT, NATS_URL
|
||||
from keystore import get_api_key
|
||||
|
||||
logger = logging.getLogger("osint.firms")
|
||||
|
||||
|
|
@ -159,16 +161,21 @@ async def ingest_fires(bbox: str | None = None) -> int:
|
|||
warning when FIRMS_MAP_KEY is not set, so the ingester keeps running for
|
||||
the other sources.
|
||||
"""
|
||||
if not FIRMS_MAP_KEY:
|
||||
# Key resolution: env var first (12-factor), then the shared Postgres
|
||||
# api_keys table so a key saved via the dashboard Keys page is picked up
|
||||
# on the next poll without a restart.
|
||||
map_key = os.getenv("FIRMS_MAP_KEY", "") or await get_api_key("FIRMS_MAP_KEY")
|
||||
if not map_key:
|
||||
logger.warning(
|
||||
"FIRMS_MAP_KEY not set — fire ingest disabled. "
|
||||
"Get a free key at https://firms.modaps.eosdis.nasa.gov/api/map_key_info/"
|
||||
"Set it in the dashboard Keys page or .env. "
|
||||
"Free key: https://firms.modaps.eosdis.nasa.gov/api/map_key_info/"
|
||||
)
|
||||
return 0
|
||||
|
||||
area = bbox or FIRMS_BBOX
|
||||
url = FIRMS_AREA_CSV.format(
|
||||
key=FIRMS_MAP_KEY, dataset=FIRMS_DATASET, bbox=area
|
||||
key=map_key, dataset=FIRMS_DATASET, bbox=area
|
||||
)
|
||||
|
||||
async with httpx.AsyncClient(timeout=FIRMS_TIMEOUT) as client:
|
||||
|
|
|
|||
|
|
@ -73,6 +73,65 @@ def test_parse_firms_csv_empty_and_garbage():
|
|||
|
||||
|
||||
def test_ingest_fires_idles_without_map_key(monkeypatch):
|
||||
# No key -> returns 0 without attempting a network call.
|
||||
monkeypatch.setattr("fire_sources.FIRMS_MAP_KEY", "")
|
||||
# No key anywhere -> returns 0 without attempting a network call.
|
||||
monkeypatch.setenv("FIRMS_MAP_KEY", "")
|
||||
monkeypatch.setattr(
|
||||
"fire_sources.get_api_key", lambda name: _async_none()
|
||||
)
|
||||
assert asyncio.run(ingest_fires()) == 0
|
||||
|
||||
|
||||
def test_ingest_fires_uses_keystore_key(monkeypatch):
|
||||
# Key saved via the dashboard Keys page (Postgres) is picked up.
|
||||
monkeypatch.setenv("FIRMS_MAP_KEY", "")
|
||||
monkeypatch.setattr(
|
||||
"fire_sources.get_api_key",
|
||||
lambda name: _async_return("a" * 32),
|
||||
)
|
||||
|
||||
captured = {}
|
||||
|
||||
class FakeResp:
|
||||
status_code = 200
|
||||
text = SAMPLE_CSV
|
||||
|
||||
def raise_for_status(self):
|
||||
pass
|
||||
|
||||
class FakeClient:
|
||||
def __init__(self, **kw):
|
||||
pass
|
||||
|
||||
async def __aenter__(self):
|
||||
return self
|
||||
|
||||
async def __aexit__(self, *exc):
|
||||
return False
|
||||
|
||||
async def get(self, url):
|
||||
captured["url"] = url
|
||||
return FakeResp()
|
||||
|
||||
monkeypatch.setattr("fire_sources.httpx.AsyncClient", FakeClient)
|
||||
|
||||
published = []
|
||||
|
||||
async def fake_publish(points):
|
||||
published.extend(points)
|
||||
return len(points)
|
||||
|
||||
monkeypatch.setattr("fire_sources.publish_fire_batch", fake_publish)
|
||||
|
||||
assert asyncio.run(ingest_fires()) == 5
|
||||
assert "a" * 32 in captured["url"]
|
||||
|
||||
|
||||
def _async_return(value):
|
||||
async def inner():
|
||||
return value
|
||||
|
||||
return inner()
|
||||
|
||||
|
||||
def _async_none():
|
||||
return _async_return(None)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue