import pytest from agebd.subs import SubstitutionError, Substitutions, UnknownTokenError from agebd.utils import get_git_root from ci.render_subs import main, render REPO_ROOT = get_git_root(__file__) CONFIG_DIR = REPO_ROOT / "config" @pytest.fixture def service_tree(tmp_path): ioc = tmp_path / "ioc" ioc.mkdir() (ioc / "AGEBD-CPCL-TUNE_main.subs").write_text("{ AGEBD-TUNE@@agebd_env_suffix_upper@@ }\n") (ioc / "AGEBD-CPCL-TUNE_parameters.yaml").write_text( "ioc_host: sls-vserv-bd-01@@agebd_env_suffix_lower@@\nioc_port: @@ioc_port@@\n" ) systemd = tmp_path / "systemd" systemd.mkdir() (systemd / "AGEBD-SERVICE-TUNE.service").write_text("Environment=AGEBD_ENV=@@agebd_env@@\n") return tmp_path def test_renders_a_whole_service_for_dev(service_tree): subs = Substitutions.for_service("dev", "tune", config_dir=CONFIG_DIR) changed = render(subs, [service_tree / "ioc", service_tree / "systemd"]) assert len(changed) == 3 assert "AGEBD-TUNE-DEV" in (service_tree / "ioc/AGEBD-CPCL-TUNE_main.subs").read_text() assert (service_tree / "ioc/AGEBD-CPCL-TUNE_parameters.yaml").read_text() == ( "ioc_host: sls-vserv-bd-01-dev\nioc_port: 50007\n" ) assert (service_tree / "systemd/AGEBD-SERVICE-TUNE.service").read_text() == ( "Environment=AGEBD_ENV=dev\n" ) def test_renders_a_whole_service_for_prod(service_tree): subs = Substitutions.for_service("prod", "tune", config_dir=CONFIG_DIR) render(subs, [service_tree / "ioc", service_tree / "systemd"]) assert "{ AGEBD-TUNE }" in (service_tree / "ioc/AGEBD-CPCL-TUNE_main.subs").read_text() assert "sls-vserv-bd-01\n" in (service_tree / "ioc/AGEBD-CPCL-TUNE_parameters.yaml").read_text() def test_missing_path_is_skipped_not_fatal(service_tree, capsys): subs = Substitutions.for_service("dev", "tune", config_dir=CONFIG_DIR) render(subs, [service_tree / "systemd", service_tree / "does-not-exist"]) assert "skipped (does not exist)" in capsys.readouterr().out def test_leaves_nothing_unrendered(service_tree): subs = Substitutions.for_service("dev", "tune", config_dir=CONFIG_DIR) render(subs, [service_tree]) for path in service_tree.rglob("*"): if path.is_file(): assert "@@" not in path.read_text(), path def test_rendering_is_idempotent(service_tree): subs = Substitutions.for_service("dev", "tune", config_dir=CONFIG_DIR) assert len(render(subs, [service_tree])) == 3 assert render(subs, [service_tree]) == [] def test_per_service_token_without_service_fails_loudly(service_tree): """Without --service there is no ioc_port, and that must not pass silently.""" subs = Substitutions.for_env("dev", config_dir=CONFIG_DIR) with pytest.raises(UnknownTokenError, match="ioc_port"): render(subs, [service_tree / "ioc"]) def test_main_renders_via_the_command_line(service_tree): exit_code = main(["--env", "dev", "--service", "tune", str(service_tree / "systemd")]) assert exit_code == 0 assert (service_tree / "systemd/AGEBD-SERVICE-TUNE.service").read_text() == ( "Environment=AGEBD_ENV=dev\n" ) def test_main_rejects_an_undeclared_environment(service_tree): with pytest.raises(SubstitutionError, match="staging"): main(["--env", "staging", "--service", "tune", str(service_tree / "systemd")])