diff --git a/localization/strings/en-US/Resources.resw b/localization/strings/en-US/Resources.resw
index 462c7b36a..6d072ab24 100644
--- a/localization/strings/en-US/Resources.resw
+++ b/localization/strings/en-US/Resources.resw
@@ -2118,6 +2118,10 @@ For privacy information about this product please visit https://aka.ms/privacy.<
Failed to open '{}': {}
{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated
+
+ Failed to write to '{}': {}
+ {FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated
+
No Containerfile or Dockerfile found in '{}'
{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated
@@ -2426,7 +2430,7 @@ On first run, creates the file with all settings commented out at their defaults
Working directory inside the container
- Write the container ID to the provided path.
+ Write the container ID to the provided path
IP address of the DNS nameserver in resolv.conf
@@ -2491,6 +2495,10 @@ On first run, creates the file with all settings commented out at their defaults
Invalid {} value: {} is out of valid range ({}-{}).
{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated
+
+ CID file '{}' already exists
+ {FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated
+
Image '{}' not found, pulling
{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated
diff --git a/src/windows/wslc/arguments/ArgumentDefinitions.h b/src/windows/wslc/arguments/ArgumentDefinitions.h
index 3748a95cd..96729e0ec 100644
--- a/src/windows/wslc/arguments/ArgumentDefinitions.h
+++ b/src/windows/wslc/arguments/ArgumentDefinitions.h
@@ -36,7 +36,7 @@ Module Name:
_(All, "all", L"a", Kind::Flag, Localization::WSLCCLI_AllArgDescription()) \
_(Attach, "attach", L"a", Kind::Flag, Localization::WSLCCLI_AttachArgDescription()) \
_(BuildArg, "build-arg", NO_ALIAS, Kind::Value, Localization::WSLCCLI_BuildArgDescription()) \
-/*_(CIDFile, "cidfile", NO_ALIAS, Kind::Value, Localization::WSLCCLI_CIDFileArgDescription())*/ \
+_(CIDFile, "cidfile", NO_ALIAS, Kind::Value, Localization::WSLCCLI_CIDFileArgDescription()) \
_(Command, "command", NO_ALIAS, Kind::Positional, Localization::WSLCCLI_CommandArgDescription()) \
_(ContainerId, "container-id", NO_ALIAS, Kind::Positional, Localization::WSLCCLI_ContainerIdArgDescription()) \
_(Force, "force", L"f", Kind::Flag, Localization::WSLCCLI_ForceArgDescription()) \
diff --git a/src/windows/wslc/arguments/ArgumentValidation.cpp b/src/windows/wslc/arguments/ArgumentValidation.cpp
index ea47a5f55..8729b29ee 100644
--- a/src/windows/wslc/arguments/ArgumentValidation.cpp
+++ b/src/windows/wslc/arguments/ArgumentValidation.cpp
@@ -58,6 +58,12 @@ void Argument::Validate(const ArgMap& execArgs) const
break;
}
+ case ArgType::CIDFile:
+ {
+ validation::ValidateCidFile(execArgs.Get());
+ break;
+ }
+
default:
break;
}
@@ -97,6 +103,21 @@ void ValidateVolumeMount(const std::vector& values)
}
}
+void ValidateCidFile(const std::wstring& cidFile)
+{
+ std::error_code ec;
+ if (std::filesystem::exists(std::filesystem::path{cidFile}, ec))
+ {
+ THROW_HR_WITH_USER_ERROR(HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS), Localization::WSLCCLI_CIDFileAlreadyExistsError(cidFile));
+ }
+
+ if (ec)
+ {
+ const auto errorMessage = MultiByteToWide(ec.message());
+ THROW_HR_WITH_USER_ERROR(HRESULT_FROM_WIN32(ec.value()), Localization::MessageWslcFailedToOpenFile(cidFile, errorMessage));
+ }
+}
+
// Convert string to WSLCSignal enum - accepts either signal name (e.g., "SIGKILL") or number (e.g., "9")
WSLCSignal GetWSLCSignalFromString(const std::wstring& input, const std::wstring& argName)
{
diff --git a/src/windows/wslc/arguments/ArgumentValidation.h b/src/windows/wslc/arguments/ArgumentValidation.h
index 23208699c..b1e7d8d71 100644
--- a/src/windows/wslc/arguments/ArgumentValidation.h
+++ b/src/windows/wslc/arguments/ArgumentValidation.h
@@ -62,4 +62,6 @@ FormatType GetFormatTypeFromString(const std::wstring& input, const std::wstring
void ValidateVolumeMount(const std::vector& values);
+void ValidateCidFile(const std::wstring& cidFile);
+
} // namespace wsl::windows::wslc::validation
\ No newline at end of file
diff --git a/src/windows/wslc/commands/ContainerCreateCommand.cpp b/src/windows/wslc/commands/ContainerCreateCommand.cpp
index 4150d0af5..b2d1af395 100644
--- a/src/windows/wslc/commands/ContainerCreateCommand.cpp
+++ b/src/windows/wslc/commands/ContainerCreateCommand.cpp
@@ -31,7 +31,7 @@ std::vector ContainerCreateCommand::GetArguments() const
Argument::Create(ArgType::ImageId, true),
Argument::Create(ArgType::Command),
Argument::Create(ArgType::ForwardArgs),
- // Argument::Create(ArgType::CIDFile),
+ Argument::Create(ArgType::CIDFile),
// Argument::Create(ArgType::DNS),
// Argument::Create(ArgType::DNSDomain),
// Argument::Create(ArgType::DNSOption),
diff --git a/src/windows/wslc/commands/ContainerRunCommand.cpp b/src/windows/wslc/commands/ContainerRunCommand.cpp
index e2810cd5f..751ad92db 100644
--- a/src/windows/wslc/commands/ContainerRunCommand.cpp
+++ b/src/windows/wslc/commands/ContainerRunCommand.cpp
@@ -31,7 +31,7 @@ std::vector ContainerRunCommand::GetArguments() const
Argument::Create(ArgType::ImageId, true),
Argument::Create(ArgType::Command),
Argument::Create(ArgType::ForwardArgs),
- // Argument::Create(ArgType::CIDFile),
+ Argument::Create(ArgType::CIDFile),
Argument::Create(ArgType::Detach),
// Argument::Create(ArgType::DNS),
// Argument::Create(ArgType::DNSDomain),
diff --git a/src/windows/wslc/services/ContainerModel.h b/src/windows/wslc/services/ContainerModel.h
index c4da81fab..ff03c5b87 100644
--- a/src/windows/wslc/services/ContainerModel.h
+++ b/src/windows/wslc/services/ContainerModel.h
@@ -42,6 +42,7 @@ struct ContainerOptions
std::vector Entrypoint;
std::optional User{};
std::vector Tmpfs;
+ std::optional CidFile{};
};
struct CreateContainerResult
diff --git a/src/windows/wslc/services/ContainerService.cpp b/src/windows/wslc/services/ContainerService.cpp
index 05a5cc295..737a20c6a 100644
--- a/src/windows/wslc/services/ContainerService.cpp
+++ b/src/windows/wslc/services/ContainerService.cpp
@@ -20,6 +20,8 @@ Module Name:
#include
#include
#include
+#include
+#include
#include
#include
@@ -37,6 +39,40 @@ static void SetContainerArguments(WSLCProcessOptions& options, std::vector(argsStorage.size())};
}
+static void WriteContainerIdToFile(const std::optional& cidFilePath, const std::string& containerId)
+{
+ if (!cidFilePath.has_value())
+ {
+ return;
+ }
+
+ const auto path = std::filesystem::path(cidFilePath.value());
+ HANDLE file = ::CreateFileW(path.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr);
+ if (file == INVALID_HANDLE_VALUE)
+ {
+ const auto error = ::GetLastError();
+ if (error == ERROR_FILE_EXISTS || error == ERROR_ALREADY_EXISTS)
+ {
+ THROW_HR_WITH_USER_ERROR(HRESULT_FROM_WIN32(error), Localization::WSLCCLI_CIDFileAlreadyExistsError(*cidFilePath));
+ }
+
+ const auto errorMessage = wsl::shared::string::MultiByteToWide(std::system_category().message(error));
+ THROW_HR_WITH_USER_ERROR(HRESULT_FROM_WIN32(error), Localization::MessageWslcFailedToOpenFile(*cidFilePath, errorMessage));
+ }
+
+ DWORD bytesWritten{};
+ const bool writeSuccess = ::WriteFile(file, containerId.data(), static_cast(containerId.size()), &bytesWritten, nullptr) != FALSE;
+ const HRESULT closeResult = ::CloseHandle(file) ? S_OK : HRESULT_FROM_WIN32(GetLastError());
+ if (!writeSuccess || bytesWritten != containerId.size())
+ {
+ const auto error = writeSuccess ? ERROR_WRITE_FAULT : ::GetLastError();
+ const auto errorMessage = wsl::shared::string::MultiByteToWide(std::system_category().message(error));
+ THROW_HR_WITH_USER_ERROR(HRESULT_FROM_WIN32(error), Localization::MessageWslcFailedToWriteFile(*cidFilePath, errorMessage));
+ }
+
+ THROW_IF_FAILED(closeResult);
+}
+
static wsl::windows::common::RunningWSLCContainer CreateInternal(Session& session, const std::string& image, const ContainerOptions& options)
{
auto processFlags = WSLCProcessFlagsNone;
@@ -294,6 +330,10 @@ int ContainerService::Run(Session& session, const std::string& image, ContainerO
runningContainer.SetDeleteOnClose(false);
auto& container = runningContainer.Get();
+ WSLCContainerId containerId{};
+ THROW_IF_FAILED(container.GetId(containerId));
+ WriteContainerIdToFile(runOptions.CidFile, containerId);
+
// Start the created container
WSLCContainerStartFlags startFlags{};
WI_SetFlagIf(startFlags, WSLCContainerStartFlagsAttach, !runOptions.Detach);
@@ -306,8 +346,6 @@ int ContainerService::Run(Session& session, const std::string& image, ContainerO
return consoleService.AttachToCurrentConsole(runningContainer.GetInitProcess());
}
- WSLCContainerId containerId{};
- THROW_IF_FAILED(container.GetId(containerId));
PrintMessage(L"%hs", stdout, containerId);
return 0;
}
@@ -319,6 +357,7 @@ CreateContainerResult ContainerService::Create(Session& session, const std::stri
auto& container = runningContainer.Get();
WSLCContainerId id{};
THROW_IF_FAILED(container.GetId(id));
+ WriteContainerIdToFile(runOptions.CidFile, id);
return {.Id = id};
}
diff --git a/src/windows/wslc/tasks/ContainerTasks.cpp b/src/windows/wslc/tasks/ContainerTasks.cpp
index 55e19e478..309379b51 100644
--- a/src/windows/wslc/tasks/ContainerTasks.cpp
+++ b/src/windows/wslc/tasks/ContainerTasks.cpp
@@ -197,6 +197,11 @@ void SetContainerOptionsFromArgs(CLIExecutionContext& context)
{
ContainerOptions options;
+ if (context.Args.Contains(ArgType::CIDFile))
+ {
+ options.CidFile = context.Args.Get();
+ }
+
if (context.Args.Contains(ArgType::Name))
{
options.Name = WideToMultiByte(context.Args.Get());
diff --git a/test/windows/wslc/CommandLineTestCases.h b/test/windows/wslc/CommandLineTestCases.h
index d615328d6..48fc48020 100644
--- a/test/windows/wslc/CommandLineTestCases.h
+++ b/test/windows/wslc/CommandLineTestCases.h
@@ -70,6 +70,7 @@ COMMAND_LINE_TEST_CASE(
true)
COMMAND_LINE_TEST_CASE(L"container run ubuntu bash -c 'echo Hello World'", L"run", true)
COMMAND_LINE_TEST_CASE(L"container run ubuntu", L"run", true)
+COMMAND_LINE_TEST_CASE(L"container run --cidfile C:\\temp\\cidfile ubuntu", L"run", true)
COMMAND_LINE_TEST_CASE(L"container run -it --name foo ubuntu", L"run", true)
COMMAND_LINE_TEST_CASE(L"container run --rm -it --name foo ubuntu", L"run", true)
COMMAND_LINE_TEST_CASE(L"stop", L"stop", true)
@@ -83,6 +84,7 @@ COMMAND_LINE_TEST_CASE(L"container start --attach cont", L"start", true)
COMMAND_LINE_TEST_CASE(L"container start -a cont", L"start", true)
COMMAND_LINE_TEST_CASE(L"create ubuntu:latest", L"create", true)
COMMAND_LINE_TEST_CASE(L"container create --name foo ubuntu", L"create", true)
+COMMAND_LINE_TEST_CASE(L"container create --cidfile C:\\temp\\cidfile --name foo ubuntu", L"create", true)
COMMAND_LINE_TEST_CASE(L"exec cont1 echo Hello", L"exec", true)
COMMAND_LINE_TEST_CASE(L"exec cont1", L"exec", false) // Missing required command argument
COMMAND_LINE_TEST_CASE(L"container exec -it cont1 sh -c \"echo a && echo b\"", L"exec", true) // docker exec example
diff --git a/test/windows/wslc/e2e/WSLCE2EContainerCreateTests.cpp b/test/windows/wslc/e2e/WSLCE2EContainerCreateTests.cpp
index ad08e4bcb..b5178225e 100644
--- a/test/windows/wslc/e2e/WSLCE2EContainerCreateTests.cpp
+++ b/test/windows/wslc/e2e/WSLCE2EContainerCreateTests.cpp
@@ -116,6 +116,36 @@ class WSLCE2EContainerCreateTests
VerifyContainerIsListed(containerId, L"created");
}
+ WSLC_TEST_METHOD(WSLCE2E_Container_Create_CIDFile_Valid)
+ {
+ // Prepare a CID file path that does not exist
+ const auto cidFilePath = wsl::windows::common::filesystem::GetTempFilename();
+ VERIFY_IS_TRUE(DeleteFileW(cidFilePath.c_str()));
+ auto deleteCidFile = wil::scope_exit([&]() { VERIFY_IS_TRUE(DeleteFileW(cidFilePath.c_str())); });
+
+ auto result = RunWslc(std::format(
+ L"container create --cidfile \"{}\" --name {} {}", EscapePath(cidFilePath.wstring()), WslcContainerName, DebianImage.NameAndTag()));
+ result.Verify({.Stderr = L"", .ExitCode = S_OK});
+
+ const auto containerId = result.GetStdoutOneLine();
+ VERIFY_IS_TRUE(std::filesystem::exists(cidFilePath));
+ VERIFY_ARE_EQUAL(containerId, ReadFileContent(cidFilePath.wstring()));
+ }
+
+ WSLC_TEST_METHOD(WSLCE2E_Container_Create_CIDFile_AlreadyExists)
+ {
+ const auto cidFilePath = wsl::windows::common::filesystem::GetTempFilename();
+ auto deleteCidFile = wil::scope_exit([&]() { VERIFY_IS_TRUE(DeleteFileW(cidFilePath.c_str())); });
+
+ auto result = RunWslc(std::format(
+ L"container create --cidfile \"{}\" --name {} {}", EscapePath(cidFilePath.wstring()), WslcContainerName, DebianImage.NameAndTag()));
+ result.Verify(
+ {.Stderr = std::format(L"CID file '{}' already exists\r\nError code: ERROR_ALREADY_EXISTS\r\n", EscapePath(cidFilePath.wstring())),
+ .ExitCode = 1});
+
+ VerifyContainerIsNotListed(WslcContainerName);
+ }
+
WSLC_TEST_METHOD(WSLCE2E_Container_Create_DuplicateContainerName)
{
VerifyContainerIsNotListed(WslcContainerName);
@@ -1028,10 +1058,8 @@ class WSLCE2EContainerCreateTests
result.Verify({.Stdout = L"unable to find group badgid: no matching entries in group file\r\n", .ExitCode = 126});
}
- TEST_METHOD(WSLCE2E_Container_Create_Tmpfs)
+ WSLC_TEST_METHOD(WSLCE2E_Container_Create_Tmpfs)
{
- WSL2_TEST_ONLY();
-
auto result = RunWslc(std::format(
L"container create --name {} --tmpfs /wslc-tmpfs {} sh -c \"echo -n 'tmpfs_test' > /wslc-tmpfs/data && cat "
L"/wslc-tmpfs/data\"",
@@ -1043,10 +1071,8 @@ class WSLCE2EContainerCreateTests
result.Verify({.Stdout = L"tmpfs_test", .Stderr = L"", .ExitCode = 0});
}
- TEST_METHOD(WSLCE2E_Container_Create_Tmpfs_With_Options)
+ WSLC_TEST_METHOD(WSLCE2E_Container_Create_Tmpfs_With_Options)
{
- WSL2_TEST_ONLY();
-
auto result = RunWslc(std::format(
L"container create --name {} --tmpfs /wslc-tmpfs:size=64k {} sh -c \"mount | grep -q ' on /wslc-tmpfs type tmpfs ' "
L"&& echo mounted\"",
@@ -1058,10 +1084,8 @@ class WSLCE2EContainerCreateTests
result.Verify({.Stdout = L"mounted\n", .Stderr = L"", .ExitCode = 0});
}
- TEST_METHOD(WSLCE2E_Container_Create_Tmpfs_Multiple_With_Options)
+ WSLC_TEST_METHOD(WSLCE2E_Container_Create_Tmpfs_Multiple_With_Options)
{
- WSL2_TEST_ONLY();
-
auto result = RunWslc(std::format(
L"container create --name {} --tmpfs /wslc-tmpfs1:size=64k --tmpfs /wslc-tmpfs2:size=128k {} sh -c \"mount | grep -q "
L"' on /wslc-tmpfs1 type tmpfs ' && mount | grep -q ' on /wslc-tmpfs2 type tmpfs ' && echo mounted\"",
@@ -1073,19 +1097,15 @@ class WSLCE2EContainerCreateTests
result.Verify({.Stdout = L"mounted\n", .Stderr = L"", .ExitCode = 0});
}
- TEST_METHOD(WSLCE2E_Container_Create_Tmpfs_RelativePath_Fails)
+ WSLC_TEST_METHOD(WSLCE2E_Container_Create_Tmpfs_RelativePath_Fails)
{
- WSL2_TEST_ONLY();
-
auto result =
RunWslc(std::format(L"container create --name {} --tmpfs wslc-tmpfs {}", WslcContainerName, DebianImage.NameAndTag()));
result.Verify({.Stderr = L"invalid mount path: 'wslc-tmpfs' mount path must be absolute\r\nError code: E_FAIL\r\n", .ExitCode = 1});
}
- TEST_METHOD(WSLCE2E_Container_Create_Tmpfs_EmptyDestination_Fails)
+ WSLC_TEST_METHOD(WSLCE2E_Container_Create_Tmpfs_EmptyDestination_Fails)
{
- WSL2_TEST_ONLY();
-
auto result =
RunWslc(std::format(L"container create --name {} --tmpfs :size=64k {}", WslcContainerName, DebianImage.NameAndTag()));
result.Verify({.Stderr = L"invalid mount path: '' mount path must be absolute\r\nError code: E_FAIL\r\n", .ExitCode = 1});
@@ -1156,6 +1176,7 @@ class WSLCE2EContainerCreateTests
{
std::wstringstream options;
options << L"The following options are available:\r\n" //
+ << L" --cidfile Write the container ID to the provided path\r\n"
<< L" --entrypoint Specifies the container init process executable\r\n"
<< L" -e,--env Key=Value pairs for environment variables\r\n"
<< L" --env-file File containing key=value pairs of env variables\r\n"
diff --git a/test/windows/wslc/e2e/WSLCE2EContainerRunTests.cpp b/test/windows/wslc/e2e/WSLCE2EContainerRunTests.cpp
index bf0ebc36d..a25e83488 100644
--- a/test/windows/wslc/e2e/WSLCE2EContainerRunTests.cpp
+++ b/test/windows/wslc/e2e/WSLCE2EContainerRunTests.cpp
@@ -58,6 +58,39 @@ class WSLCE2EContainerRunTests
VerifyContainerIsListed(WslcContainerName, L"exited");
}
+ WSLC_TEST_METHOD(WSLCE2E_Container_Run_CIDFile_Valid)
+ {
+ // Prepare a CID file path that does not exist
+ const auto cidFilePath = wsl::windows::common::filesystem::GetTempFilename();
+ VERIFY_IS_TRUE(DeleteFileW(cidFilePath.c_str()));
+ auto deleteCidFile = wil::scope_exit([&]() { VERIFY_IS_TRUE(DeleteFileW(cidFilePath.c_str())); });
+
+ auto result = RunWslc(std::format(
+ L"container run -d --cidfile \"{}\" --name {} {} sleep infinity",
+ EscapePath(cidFilePath.wstring()),
+ WslcContainerName,
+ DebianImage.NameAndTag()));
+ result.Verify({.Stderr = L"", .ExitCode = 0});
+
+ const auto containerId = result.GetStdoutOneLine();
+ VERIFY_IS_TRUE(std::filesystem::exists(cidFilePath));
+ VERIFY_ARE_EQUAL(containerId, ReadFileContent(cidFilePath.wstring()));
+ }
+
+ WSLC_TEST_METHOD(WSLCE2E_Container_Run_CIDFile_AlreadyExists)
+ {
+ const auto cidFilePath = wsl::windows::common::filesystem::GetTempFilename();
+ auto deleteCidFile = wil::scope_exit([&]() { VERIFY_IS_TRUE(DeleteFileW(cidFilePath.c_str())); });
+
+ auto result = RunWslc(std::format(
+ L"container run --cidfile \"{}\" --name {} {}", EscapePath(cidFilePath.wstring()), WslcContainerName, DebianImage.NameAndTag()));
+ result.Verify(
+ {.Stderr = std::format(L"CID file '{}' already exists\r\nError code: ERROR_ALREADY_EXISTS\r\n", EscapePath(cidFilePath.wstring())),
+ .ExitCode = 1});
+
+ VerifyContainerIsNotListed(WslcContainerName);
+ }
+
WSLC_TEST_METHOD(WSLCE2E_Container_Run_Entrypoint)
{
auto result = RunWslc(std::format(L"container run --rm --entrypoint /bin/whoami {}", DebianImage.NameAndTag()));
@@ -131,10 +164,8 @@ class WSLCE2EContainerRunTests
result.Verify({.Stdout = L"nobody\n65534\n65534\n", .Stderr = L"", .ExitCode = 0});
}
- TEST_METHOD(WSLCE2E_Container_Run_Tmpfs)
+ WSLC_TEST_METHOD(WSLCE2E_Container_Run_Tmpfs)
{
- WSL2_TEST_ONLY();
-
auto result = RunWslc(std::format(
L"container run --rm --tmpfs /wslc-tmpfs {} sh -c \"echo -n 'tmpfs_test' > /wslc-tmpfs/data && cat "
L"/wslc-tmpfs/data\"",
@@ -142,10 +173,8 @@ class WSLCE2EContainerRunTests
result.Verify({.Stdout = L"tmpfs_test", .Stderr = L"", .ExitCode = 0});
}
- TEST_METHOD(WSLCE2E_Container_Run_Tmpfs_With_Options)
+ WSLC_TEST_METHOD(WSLCE2E_Container_Run_Tmpfs_With_Options)
{
- WSL2_TEST_ONLY();
-
auto result = RunWslc(std::format(
L"container run --rm --tmpfs /wslc-tmpfs:size=64k {} sh -c \"mount | grep -q ' on /wslc-tmpfs type tmpfs ' && echo "
L"mounted\"",
@@ -153,10 +182,8 @@ class WSLCE2EContainerRunTests
result.Verify({.Stdout = L"mounted\n", .Stderr = L"", .ExitCode = 0});
}
- TEST_METHOD(WSLCE2E_Container_Run_Tmpfs_Multiple_With_Options)
+ WSLC_TEST_METHOD(WSLCE2E_Container_Run_Tmpfs_Multiple_With_Options)
{
- WSL2_TEST_ONLY();
-
auto result = RunWslc(std::format(
L"container run --rm --tmpfs /wslc-tmpfs1:size=64k --tmpfs /wslc-tmpfs2:size=128k {} sh -c \"mount | grep -q ' on "
L"/wslc-tmpfs1 type tmpfs ' && mount | grep -q ' on /wslc-tmpfs2 type tmpfs ' && echo mounted\"",
@@ -164,18 +191,14 @@ class WSLCE2EContainerRunTests
result.Verify({.Stdout = L"mounted\n", .Stderr = L"", .ExitCode = 0});
}
- TEST_METHOD(WSLCE2E_Container_Run_Tmpfs_RelativePath_Fails)
+ WSLC_TEST_METHOD(WSLCE2E_Container_Run_Tmpfs_RelativePath_Fails)
{
- WSL2_TEST_ONLY();
-
auto result = RunWslc(std::format(L"container run --rm --tmpfs wslc-tmpfs {}", DebianImage.NameAndTag()));
result.Verify({.Stderr = L"invalid mount path: 'wslc-tmpfs' mount path must be absolute\r\nError code: E_FAIL\r\n", .ExitCode = 1});
}
- TEST_METHOD(WSLCE2E_Container_Run_Tmpfs_EmptyDestination_Fails)
+ WSLC_TEST_METHOD(WSLCE2E_Container_Run_Tmpfs_EmptyDestination_Fails)
{
- WSL2_TEST_ONLY();
-
auto result = RunWslc(std::format(L"container run --rm --tmpfs :size=64k {}", DebianImage.NameAndTag()));
result.Verify({.Stderr = L"invalid mount path: '' mount path must be absolute\r\nError code: E_FAIL\r\n", .ExitCode = 1});
}
@@ -221,6 +244,7 @@ class WSLCE2EContainerRunTests
{
std::wstringstream options;
options << L"The following options are available:\r\n"
+ << L" --cidfile Write the container ID to the provided path\r\n"
<< L" -d,--detach Run container in detached mode\r\n"
<< L" --entrypoint Specifies the container init process executable\r\n"
<< L" -e,--env Key=Value pairs for environment variables\r\n"