Merge pull request 'vars: raise error when shared generators differ between machines' (#5425) from dave into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5425
This commit is contained in:
@@ -1335,6 +1335,46 @@ def test_cache_misses_for_vars_operations(
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.with_core
|
||||
def test_shared_generator_conflicting_definition_raises_error(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
flake_with_sops: ClanFlake,
|
||||
) -> None:
|
||||
"""Test that vars generation raises an error when two machines have different
|
||||
definitions for the same shared generator.
|
||||
"""
|
||||
flake = flake_with_sops
|
||||
|
||||
# Create machine1 with a shared generator
|
||||
machine1_config = flake.machines["machine1"] = create_test_machine_config()
|
||||
shared_gen1 = machine1_config["clan"]["core"]["vars"]["generators"][
|
||||
"shared_generator"
|
||||
]
|
||||
shared_gen1["share"] = True
|
||||
shared_gen1["files"]["file1"]["secret"] = False
|
||||
shared_gen1["script"] = 'echo "test" > "$out"/file1'
|
||||
|
||||
# Create machine2 with the same shared generator but different files
|
||||
machine2_config = flake.machines["machine2"] = create_test_machine_config()
|
||||
shared_gen2 = machine2_config["clan"]["core"]["vars"]["generators"][
|
||||
"shared_generator"
|
||||
]
|
||||
shared_gen2["share"] = True
|
||||
shared_gen2["files"]["file2"]["secret"] = False # Different file name
|
||||
shared_gen2["script"] = 'echo "test" > "$out"/file2'
|
||||
|
||||
flake.refresh()
|
||||
monkeypatch.chdir(flake.path)
|
||||
|
||||
# Attempting to generate vars for both machines should raise an error
|
||||
# because they have conflicting definitions for the same shared generator
|
||||
with pytest.raises(
|
||||
ClanError,
|
||||
match=".*differ.*",
|
||||
):
|
||||
cli.run(["vars", "generate", "--flake", str(flake.path)])
|
||||
|
||||
|
||||
@pytest.mark.with_core
|
||||
def test_dynamic_invalidation(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
|
||||
@@ -144,6 +144,9 @@ class Generator:
|
||||
flake.precache(cls.get_machine_selectors(machine_names))
|
||||
|
||||
generators = []
|
||||
shared_generators_raw: dict[
|
||||
str, tuple[str, dict, dict]
|
||||
] = {} # name -> (machine_name, gen_data, files_data)
|
||||
|
||||
for machine_name in machine_names:
|
||||
# Get all generator metadata in one select (safe fields only)
|
||||
@@ -165,6 +168,38 @@ class Generator:
|
||||
sec_store = machine.secret_vars_store
|
||||
|
||||
for gen_name, gen_data in generators_data.items():
|
||||
# Check for conflicts in shared generator definitions using raw data
|
||||
if gen_data["share"]:
|
||||
if gen_name in shared_generators_raw:
|
||||
prev_machine, prev_gen_data, prev_files_data = (
|
||||
shared_generators_raw[gen_name]
|
||||
)
|
||||
# Compare raw data
|
||||
prev_gen_files = prev_files_data.get(gen_name, {})
|
||||
curr_gen_files = files_data.get(gen_name, {})
|
||||
# Build list of differences with details
|
||||
differences = []
|
||||
if prev_gen_files != curr_gen_files:
|
||||
differences.append("files")
|
||||
if prev_gen_data.get("prompts") != gen_data.get("prompts"):
|
||||
differences.append("prompts")
|
||||
if prev_gen_data.get("dependencies") != gen_data.get(
|
||||
"dependencies"
|
||||
):
|
||||
differences.append("dependencies")
|
||||
if prev_gen_data.get("validationHash") != gen_data.get(
|
||||
"validationHash"
|
||||
):
|
||||
differences.append("validation_hash")
|
||||
if differences:
|
||||
msg = f"Machines {prev_machine} and {machine_name} have different definitions for shared generator '{gen_name}' (differ in: {', '.join(differences)})"
|
||||
raise ClanError(msg)
|
||||
else:
|
||||
shared_generators_raw[gen_name] = (
|
||||
machine_name,
|
||||
gen_data,
|
||||
files_data,
|
||||
)
|
||||
# Build files from the files_data
|
||||
files = []
|
||||
gen_files = files_data.get(gen_name, {})
|
||||
@@ -216,6 +251,7 @@ class Generator:
|
||||
_public_store=pub_store,
|
||||
_secret_store=sec_store,
|
||||
)
|
||||
|
||||
generators.append(generator)
|
||||
|
||||
# TODO: This should be done in a non-mutable way.
|
||||
|
||||
Reference in New Issue
Block a user