"""Tests for Settings / node_name fail-fast. Regression coverage for the evt-unknown-* poison bug: a node_name of "unknown" (or empty) produced event files that pinned the observer checkpoint and blocked PIHA for ~34 days (see fix d5139c9). The agent must now refuse to start rather than ever emit such a file. """ from __future__ import annotations import os from pathlib import Path import pytest from pydantic import ValidationError from ha_diag import config from ha_diag.config import Settings @pytest.fixture(autouse=True) def _isolate_environ(): """Snapshot os.environ — Settings.load() mutates it via setdefault().""" saved = dict(os.environ) yield os.environ.clear() os.environ.update(saved) # --------------------------------------------------------------------------- # node_name loaded from env NODE_NAME # --------------------------------------------------------------------------- def test_node_name_from_env(monkeypatch): monkeypatch.setenv("NODE_NAME", "piha") settings = Settings() assert settings.node_name == "piha" def test_node_name_from_env_case_insensitive_var(monkeypatch): # BaseSettings is case-insensitive: lowercase env var maps to the field too. monkeypatch.delenv("NODE_NAME", raising=False) monkeypatch.setenv("node_name", "chelsty-infra") settings = Settings() assert settings.node_name == "chelsty-infra" def test_node_name_whitespace_is_stripped(monkeypatch): monkeypatch.setenv("NODE_NAME", " piha ") settings = Settings() assert settings.node_name == "piha" # --------------------------------------------------------------------------- # fail-fast: unknown / empty node_name refuses to start # --------------------------------------------------------------------------- def test_explicit_unknown_node_name_refuses(monkeypatch): monkeypatch.delenv("NODE_NAME", raising=False) with pytest.raises(ValidationError) as exc: Settings(node_name="unknown") assert "refusing to start" in str(exc.value) def test_unknown_case_insensitive_refuses(monkeypatch): monkeypatch.delenv("NODE_NAME", raising=False) with pytest.raises(ValidationError): Settings(node_name="UNKNOWN") def test_empty_node_name_refuses(monkeypatch): monkeypatch.delenv("NODE_NAME", raising=False) with pytest.raises(ValidationError): Settings(node_name="") def test_whitespace_only_node_name_refuses(monkeypatch): monkeypatch.delenv("NODE_NAME", raising=False) with pytest.raises(ValidationError): Settings(node_name=" ") def test_env_unknown_refuses(monkeypatch): monkeypatch.setenv("NODE_NAME", "unknown") with pytest.raises(ValidationError): Settings() def test_default_without_env_refuses(monkeypatch): # No NODE_NAME anywhere → the "unknown" default must be rejected, not used. monkeypatch.delenv("NODE_NAME", raising=False) monkeypatch.delenv("node_name", raising=False) with pytest.raises(ValidationError): Settings() # --------------------------------------------------------------------------- # precedence: env wins over YAML for node_name # --------------------------------------------------------------------------- def test_env_wins_over_yaml(monkeypatch, tmp_path: Path): yaml_file = tmp_path / "ha-diag-agent.yaml" yaml_file.write_text("node_name: solaria\n") monkeypatch.setattr(config, "_CONFIG_YAML", yaml_file) monkeypatch.setenv("NODE_NAME", "piha") settings = Settings.load() # env value must win; YAML only supplies a default when env is absent. assert settings.node_name == "piha" def test_yaml_supplies_node_name_when_env_absent(monkeypatch, tmp_path: Path): yaml_file = tmp_path / "ha-diag-agent.yaml" yaml_file.write_text("node_name: chelsty-infra\n") monkeypatch.setattr(config, "_CONFIG_YAML", yaml_file) monkeypatch.delenv("NODE_NAME", raising=False) monkeypatch.delenv("node_name", raising=False) settings = Settings.load() assert settings.node_name == "chelsty-infra" def test_yaml_unknown_still_refuses(monkeypatch, tmp_path: Path): # Even if YAML carries the poison value, fail-fast must still fire. yaml_file = tmp_path / "ha-diag-agent.yaml" yaml_file.write_text("node_name: unknown\n") monkeypatch.setattr(config, "_CONFIG_YAML", yaml_file) monkeypatch.delenv("NODE_NAME", raising=False) monkeypatch.delenv("node_name", raising=False) with pytest.raises(ValidationError): Settings.load() def test_load_valid_node_name(monkeypatch, tmp_path: Path): monkeypatch.setattr(config, "_CONFIG_YAML", tmp_path / "does-not-exist.yaml") monkeypatch.setenv("NODE_NAME", "piha") settings = Settings.load() assert settings.node_name == "piha"