Add validate_compose_external_state() for env_file/external-network checks
Separate from load_compose_file() (which stays pure YAML validation with no host-state dependency): checks every env_file exists as a readable regular file, and every network marked external: true already exists in the real persistent.yaml. Fail-fast, same convention as load_compose_file()'s own cross-validation. Bind-mount host directories are deliberately not checked here, since resolve_volume_mount() already auto-creates a missing one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gv3s5jckJKzh6JkMoi2Akz
This commit is contained in:
@@ -528,3 +528,53 @@ TEST_CASE("compose file: service volumes -- bind mounts (absolute-resolved, ro),
|
||||
" - ./scripts:relative/path\n");
|
||||
CHECK_FALSE(load_compose_file(relative_target).has_value());
|
||||
}
|
||||
|
||||
TEST_CASE("compose file: validate_compose_external_state -- env_file existence, external network existence",
|
||||
"[unit]") {
|
||||
ScratchXdgDirs scratch;
|
||||
|
||||
auto path = write_compose(scratch.path(),
|
||||
"services:\n"
|
||||
" web:\n"
|
||||
" image: busybox:latest\n"
|
||||
" env_file: ./web.env\n"
|
||||
"networks:\n"
|
||||
" net-managed:\n"
|
||||
" internal: false\n"
|
||||
" net-preexisting:\n"
|
||||
" external: true\n");
|
||||
auto loaded = load_compose_file(path);
|
||||
REQUIRE(loaded.has_value());
|
||||
|
||||
// env_file doesn't exist yet, and the external network isn't declared
|
||||
// anywhere in persistent_config -- both must fail, one at a time
|
||||
// (fail-fast, same convention load_compose_file()'s own cross-validation
|
||||
// already uses).
|
||||
AppConfig empty_persistent;
|
||||
CHECK_FALSE(validate_compose_external_state(*loaded, empty_persistent));
|
||||
|
||||
// Create the env_file -- still fails, since the external network still
|
||||
// isn't declared.
|
||||
{
|
||||
std::ofstream env_file(scratch.path() / "web.env");
|
||||
env_file << "FOO=bar\n";
|
||||
}
|
||||
CHECK_FALSE(validate_compose_external_state(*loaded, empty_persistent));
|
||||
|
||||
// Declare the external network -- now both checks pass. A managed
|
||||
// (non-external) network, net-managed, is never checked against
|
||||
// persistent_config at all, so its absence there doesn't matter.
|
||||
AppConfig with_network;
|
||||
with_network.networks.push_back({"net-preexisting", NetworkKind::intern, "10.169.10.0/24", false, "", true});
|
||||
CHECK(validate_compose_external_state(*loaded, with_network));
|
||||
|
||||
// A directory in place of the env_file still fails -- not a regular file.
|
||||
auto dir_env_file = write_compose(scratch.path(), "services:\n"
|
||||
" web:\n"
|
||||
" image: busybox:latest\n"
|
||||
" env_file: ./a-directory\n");
|
||||
auto loaded_dir = load_compose_file(dir_env_file);
|
||||
REQUIRE(loaded_dir.has_value());
|
||||
std::filesystem::create_directory(scratch.path() / "a-directory");
|
||||
CHECK_FALSE(validate_compose_external_state(*loaded_dir, AppConfig{}));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user