Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions localization/strings/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -2124,6 +2124,10 @@ For privacy information about this product please visit https://aka.ms/privacy.<
<value>Volume not found: '{}'</value>
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
</data>
<data name="MessageWslcImageNotFound" xml:space="preserve">
Comment thread
AmelBawa-msft marked this conversation as resolved.
<value>Image '{}' not found.</value>
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
</data>
<data name = "MessageWslcMissingVolumeOption" xml:space = "preserve" >
<value>Missing required option: '{}'</value>
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
Expand Down
32 changes: 30 additions & 2 deletions src/windows/wslc/tasks/ContainerTasks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,34 @@ Module Name:
#include <wslc_schema.h>

using namespace wsl::shared;
using namespace wsl::windows::common;
using namespace wsl::windows::common::string;
using namespace wsl::windows::common::wslutil;
using namespace wsl::windows::wslc::execution;
using namespace wsl::windows::wslc::models;
using namespace wsl::windows::wslc::services;

namespace wsl::windows::wslc::task {

static bool TryInspectContainer(Session& session, const std::string& containerId, std::optional<wslc_schema::InspectContainer>& inspectData)
{
try
{
inspectData = ContainerService::Inspect(session, containerId);
return true;
}
catch (const wil::ResultException& ex)
{
if (ex.GetErrorCode() == WSLC_E_CONTAINER_NOT_FOUND)
{
PrintMessage(Localization::MessageWslcContainerNotFound(containerId.c_str()), stderr);
return false;
}

throw;
}
}

void AttachContainer::operator()(CLIExecutionContext& context) const
{
WI_ASSERT(context.Data.Contains(Data::Session));
Expand Down Expand Up @@ -71,8 +92,15 @@ void InspectContainers(CLIExecutionContext& context)
std::vector<wsl::windows::common::wslc_schema::InspectContainer> result;
for (const auto& id : containerIds)
{
auto inspectData = ContainerService::Inspect(session, WideToMultiByte(id));
result.push_back(inspectData);
std::optional<wslc_schema::InspectContainer> inspectData;
if (TryInspectContainer(session, WideToMultiByte(id), inspectData))
{
result.push_back(*inspectData);
}
else
{
context.ExitCode = 1;
}
}

auto json = ToJson(result, c_jsonPrettyPrintIndent);
Expand Down
33 changes: 31 additions & 2 deletions src/windows/wslc/tasks/ImageTasks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,34 @@ Module Name:
#include <wslutil.h>

using namespace wsl::shared;
using namespace wsl::windows::common;
using namespace wsl::windows::common::string;
using namespace wsl::windows::common::wslutil;
using namespace wsl::windows::wslc::execution;
using namespace wsl::windows::wslc::models;
using namespace wsl::windows::wslc::services;

namespace wsl::windows::wslc::task {

static bool TryInspectImage(Session& session, const std::string& imageId, std::optional<wslc_schema::InspectImage>& inspectData)
{
try
{
inspectData = ImageService::Inspect(session, imageId);
return true;
}
catch (const wil::ResultException& ex)
{
if (ex.GetErrorCode() == WSLC_E_IMAGE_NOT_FOUND)
{
PrintMessage(Localization::MessageWslcImageNotFound(imageId.c_str()), stderr);
return false;
}

throw;
}
}

void BuildImage(CLIExecutionContext& context)
{
WI_ASSERT(context.Data.Contains(Data::Session));
Expand Down Expand Up @@ -197,8 +219,15 @@ void InspectImages(CLIExecutionContext& context)
std::vector<wsl::windows::common::wslc_schema::InspectImage> result;
for (const auto& id : imageIds)
{
auto inspectData = ImageService::Inspect(session, WideToMultiByte(id));
result.push_back(inspectData);
std::optional<wslc_schema::InspectImage> inspectData;
if (TryInspectImage(session, WideToMultiByte(id), inspectData))
{
result.push_back(*inspectData);
}
else
{
context.ExitCode = 1;
}
}

auto json = ToJson(result, c_jsonPrettyPrintIndent);
Expand Down
160 changes: 160 additions & 0 deletions test/windows/wslc/e2e/WSLCE2EContainerInspectTests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*++

Copyright (c) Microsoft. All rights reserved.

Module Name:

WSLCE2EContainerInspectTests.cpp

Abstract:

This file contains end-to-end tests for WSLC.
--*/

#include "precomp.h"
#include "windows/Common.h"
#include "WSLCExecutor.h"
#include "WSLCE2EHelpers.h"
#include <wslc_schema.h>

namespace WSLCE2ETests {
using namespace wsl::shared;
using namespace wsl::shared::string;

class WSLCE2EContainerInspectTests
{
WSLC_TEST_CLASS(WSLCE2EContainerInspectTests)

TEST_CLASS_SETUP(ClassSetup)
{
EnsureImageIsLoaded(DebianImage);
return true;
}

TEST_CLASS_CLEANUP(ClassCleanup)
{
EnsureContainerDoesNotExist(TestContainerName1);
EnsureContainerDoesNotExist(TestContainerName2);
EnsureImageIsDeleted(DebianImage);
return true;
}

TEST_METHOD_SETUP(MethodSetup)
{
EnsureContainerDoesNotExist(TestContainerName1);
EnsureContainerDoesNotExist(TestContainerName2);
return true;
}

WSLC_TEST_METHOD(WSLCE2E_Container_Inspect_HelpCommand)
{
auto result = RunWslc(L"container inspect --help");
result.Verify({.Stdout = GetHelpMessage(), .Stderr = L"", .ExitCode = 0});
}

WSLC_TEST_METHOD(WSLCE2E_Container_Inspect_MissingContainerId)
{
auto result = RunWslc(L"container inspect");
result.Verify({.Stdout = GetHelpMessage(), .Stderr = L"Required argument not provided: 'container-id'\r\n", .ExitCode = 1});
}

WSLC_TEST_METHOD(WSLCE2E_Container_Inspect_ContainerNotFound)
{
auto result = RunWslc(std::format(L"container inspect {}", TestContainerName1));
result.Verify({.Stdout = L"[]\r\n", .Stderr = std::format(L"Container '{}' not found.\r\n", TestContainerName1), .ExitCode = 1});
}

WSLC_TEST_METHOD(WSLCE2E_Container_Inspect_Success)
{
auto createResult = RunWslc(std::format(L"container create --name {} {}", TestContainerName1, DebianImage.NameAndTag()));
createResult.Verify({.Stderr = L"", .ExitCode = 0});

auto result = RunWslc(std::format(L"container inspect {}", TestContainerName1));
result.Verify({.Stderr = L"", .ExitCode = 0});
auto inspectData =
wsl::shared::FromJson<std::vector<wsl::windows::common::wslc_schema::InspectContainer>>(result.Stdout.value().c_str());
VERIFY_ARE_EQUAL(1u, inspectData.size());
VERIFY_ARE_EQUAL(WideToMultiByte(TestContainerName1), inspectData[0].Name);
}

WSLC_TEST_METHOD(WSLCE2E_Container_InspectMultiple_Success)
{
// Create two containers to inspect at the same time
auto result = RunWslc(std::format(L"container create --name {} {}", TestContainerName1, DebianImage.NameAndTag()));
result.Verify({.Stderr = L"", .ExitCode = 0});
result = RunWslc(std::format(L"container create --name {} {}", TestContainerName2, DebianImage.NameAndTag()));
result.Verify({.Stderr = L"", .ExitCode = 0});

// Inspect both containers in the same command
result = RunWslc(std::format(L"container inspect {} {}", TestContainerName1, TestContainerName2));
result.Verify({.Stderr = L"", .ExitCode = 0});
auto inspectData =
wsl::shared::FromJson<std::vector<wsl::windows::common::wslc_schema::InspectContainer>>(result.Stdout.value().c_str());
VERIFY_ARE_EQUAL(2u, inspectData.size());
VERIFY_ARE_EQUAL(WideToMultiByte(TestContainerName1), inspectData[0].Name);
VERIFY_ARE_EQUAL(WideToMultiByte(TestContainerName2), inspectData[1].Name);
}

WSLC_TEST_METHOD(WSLCE2E_Container_Inspect_MixedFoundNotFound)
{
// Create one container but not the other
auto result = RunWslc(std::format(L"container create --name {} {}", TestContainerName1, DebianImage.NameAndTag()));
result.Verify({.Stderr = L"", .ExitCode = 0});

// Inspect both containers in the same command, expecting one to be found and the other to not be found
result = RunWslc(std::format(L"container inspect {} {}", TestContainerName1, TestContainerName2));
result.Verify({.Stderr = std::format(L"Container '{}' not found.\r\n", TestContainerName2), .ExitCode = 1});

// Verify found container
auto inspectData =
wsl::shared::FromJson<std::vector<wsl::windows::common::wslc_schema::InspectContainer>>(result.Stdout.value().c_str());
VERIFY_ARE_EQUAL(1u, inspectData.size());
VERIFY_ARE_EQUAL(WideToMultiByte(TestContainerName1), inspectData[0].Name);
}

private:
const std::wstring TestContainerName1 = L"wslc-e2e-container-inspect-1";
const std::wstring TestContainerName2 = L"wslc-e2e-container-inspect-2";
const TestImage& DebianImage = DebianTestImage();

std::wstring GetHelpMessage() const
{
std::wstringstream output;
output << GetWslcHeader() //
<< GetDescription() //
<< GetUsage() //
<< GetAvailableCommands() //
<< GetAvailableOptions();
return output.str();
}

std::wstring GetDescription() const
{
return Localization::WSLCCLI_ContainerInspectLongDesc() + L"\r\n\r\n";
}

std::wstring GetUsage() const
{
return L"Usage: wslc container inspect [<options>] <container-id>\r\n\r\n";
}

std::wstring GetAvailableCommands() const
{
std::wstringstream commands;
commands << L"The following arguments are available:\r\n" //
<< L" container-id Container ID\r\n" //
<< L"\r\n";
return commands.str();
}

std::wstring GetAvailableOptions() const
{
std::wstringstream options;
options << L"The following options are available:\r\n" //
<< L" --session Specify the session to use\r\n" //
<< L" -?,--help Shows help about the selected command\r\n" //
<< L"\r\n";
return options.str();
}
};
} // namespace WSLCE2ETests
3 changes: 1 addition & 2 deletions test/windows/wslc/e2e/WSLCE2EImageInspectTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ class WSLCE2EImageInspectTests
WSLC_TEST_METHOD(WSLCE2E_Image_Inspect_ImageNotFound)
{
auto result = RunWslc(std::format(L"image inspect {}", InvalidImage.NameAndTag()));
auto errorMessage = std::format(L"No such image: {}\r\nError code: WSLC_E_IMAGE_NOT_FOUND\r\n", InvalidImage.NameAndTag());
result.Verify({.Stdout = L"", .Stderr = errorMessage, .ExitCode = 1});
result.Verify({.Stdout = L"[]\r\n", .Stderr = std::format(L"Image '{}' not found.\r\n", InvalidImage.NameAndTag()), .ExitCode = 1});
}

WSLC_TEST_METHOD(WSLCE2E_Image_Inspect_Success)
Expand Down