feat(gateway): GatewayConfig env (NATS/gRPC/certs/write flags)
This commit is contained in:
13
.env.example
13
.env.example
@@ -15,3 +15,16 @@ MONGODB_USERNAME="mongo_user"
|
|||||||
MONGODB_PASSWORD="mongo_password"
|
MONGODB_PASSWORD="mongo_password"
|
||||||
MONGODB_DATABASE="sientia"
|
MONGODB_DATABASE="sientia"
|
||||||
|
|
||||||
|
# OPC Gateway
|
||||||
|
NATS_URL="nats://localhost:4222"
|
||||||
|
NATS_WRITE_SUBJECT="opc.write"
|
||||||
|
NATS_QUEUE="gateway-writers"
|
||||||
|
GRPC_ENABLED="false"
|
||||||
|
GRPC_PORT="50051"
|
||||||
|
CERT_BUCKET="sientia-dataops"
|
||||||
|
CERT_CACHE_DIR="/tmp/opc-certs"
|
||||||
|
WRITE_TIMESTAMP="true"
|
||||||
|
WRITE_QUALITY="true"
|
||||||
|
WRITE_MIN_PAUSE_S="0.0"
|
||||||
|
IDLE_CONN_MAX_S="300.0"
|
||||||
|
|
||||||
|
|||||||
46
ingestor/config.py
Normal file
46
ingestor/config.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
"""Gateway-specific env config (NATS/gRPC/certs/write flags).
|
||||||
|
|
||||||
|
Separate from ingestor.py's inline os.getenv (Redis/Mongo/TTLs) — this module
|
||||||
|
covers only the new gateway wiring consumed by app.py in Task 18.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from os import getenv
|
||||||
|
|
||||||
|
|
||||||
|
def _env_bool(name: str, default: bool) -> bool:
|
||||||
|
value = getenv(name)
|
||||||
|
if value is None:
|
||||||
|
return default
|
||||||
|
return value.strip().lower() in ('true', '1', 'yes')
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class GatewayConfig:
|
||||||
|
nats_url: str = 'nats://localhost:4222'
|
||||||
|
nats_write_subject: str = 'opc.write'
|
||||||
|
nats_queue: str = 'gateway-writers'
|
||||||
|
grpc_enabled: bool = False
|
||||||
|
grpc_port: int = 50051
|
||||||
|
cert_bucket: str = 'sientia-dataops'
|
||||||
|
cert_cache_dir: str = '/tmp/opc-certs' # noqa: S108 - default is spec'd, overridable via env
|
||||||
|
write_timestamp: bool = True
|
||||||
|
write_quality: bool = True
|
||||||
|
write_min_pause_s: float = 0.0
|
||||||
|
idle_conn_max_s: float = 300.0
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_env(cls) -> 'GatewayConfig':
|
||||||
|
return cls(
|
||||||
|
nats_url=getenv('NATS_URL', cls.nats_url),
|
||||||
|
nats_write_subject=getenv('NATS_WRITE_SUBJECT', cls.nats_write_subject),
|
||||||
|
nats_queue=getenv('NATS_QUEUE', cls.nats_queue),
|
||||||
|
grpc_enabled=_env_bool('GRPC_ENABLED', cls.grpc_enabled),
|
||||||
|
grpc_port=int(getenv('GRPC_PORT', cls.grpc_port)),
|
||||||
|
cert_bucket=getenv('CERT_BUCKET', cls.cert_bucket),
|
||||||
|
cert_cache_dir=getenv('CERT_CACHE_DIR', cls.cert_cache_dir),
|
||||||
|
write_timestamp=_env_bool('WRITE_TIMESTAMP', cls.write_timestamp),
|
||||||
|
write_quality=_env_bool('WRITE_QUALITY', cls.write_quality),
|
||||||
|
write_min_pause_s=float(getenv('WRITE_MIN_PAUSE_S', cls.write_min_pause_s)),
|
||||||
|
idle_conn_max_s=float(getenv('IDLE_CONN_MAX_S', cls.idle_conn_max_s)),
|
||||||
|
)
|
||||||
60
tests/unit/test_config.py
Normal file
60
tests/unit/test_config.py
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from ingestor.config import GatewayConfig
|
||||||
|
|
||||||
|
_ENV_VARS = (
|
||||||
|
'NATS_URL', 'NATS_WRITE_SUBJECT', 'NATS_QUEUE', 'GRPC_ENABLED', 'GRPC_PORT',
|
||||||
|
'CERT_BUCKET', 'CERT_CACHE_DIR', 'WRITE_TIMESTAMP', 'WRITE_QUALITY',
|
||||||
|
'WRITE_MIN_PAUSE_S', 'IDLE_CONN_MAX_S',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def clean_env(monkeypatch):
|
||||||
|
for var in _ENV_VARS:
|
||||||
|
monkeypatch.delenv(var, raising=False)
|
||||||
|
|
||||||
|
|
||||||
|
def test_from_env_defaults():
|
||||||
|
cfg = GatewayConfig.from_env()
|
||||||
|
|
||||||
|
assert cfg.nats_url == 'nats://localhost:4222'
|
||||||
|
assert cfg.nats_write_subject == 'opc.write'
|
||||||
|
assert cfg.nats_queue == 'gateway-writers'
|
||||||
|
assert cfg.grpc_enabled is False
|
||||||
|
assert cfg.grpc_port == 50051
|
||||||
|
assert cfg.cert_bucket == 'sientia-dataops'
|
||||||
|
assert cfg.cert_cache_dir == '/tmp/opc-certs' # noqa: S108
|
||||||
|
assert cfg.write_timestamp is True
|
||||||
|
assert cfg.write_quality is True
|
||||||
|
assert cfg.write_min_pause_s == 0.0
|
||||||
|
assert cfg.idle_conn_max_s == 300.0
|
||||||
|
|
||||||
|
|
||||||
|
def test_from_env_overrides(monkeypatch):
|
||||||
|
monkeypatch.setenv('GRPC_ENABLED', 'true')
|
||||||
|
monkeypatch.setenv('GRPC_PORT', '6000')
|
||||||
|
monkeypatch.setenv('WRITE_MIN_PAUSE_S', '0.5')
|
||||||
|
monkeypatch.setenv('WRITE_QUALITY', 'false')
|
||||||
|
|
||||||
|
cfg = GatewayConfig.from_env()
|
||||||
|
|
||||||
|
assert cfg.grpc_enabled is True
|
||||||
|
assert cfg.grpc_port == 6000
|
||||||
|
assert cfg.write_min_pause_s == 0.5
|
||||||
|
assert cfg.write_quality is False
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('value,expected', [
|
||||||
|
('0', False),
|
||||||
|
('no', False),
|
||||||
|
('FALSE', False),
|
||||||
|
('1', True),
|
||||||
|
('YES', True),
|
||||||
|
])
|
||||||
|
def test_bool_parsing_edge_cases(monkeypatch, value, expected):
|
||||||
|
monkeypatch.setenv('GRPC_ENABLED', value)
|
||||||
|
|
||||||
|
cfg = GatewayConfig.from_env()
|
||||||
|
|
||||||
|
assert cfg.grpc_enabled is expected
|
||||||
Reference in New Issue
Block a user