mirror of
https://github.com/microsoft/WSL.git
synced 2026-06-01 01:02:31 -05:00
Init network commands
Co-authored-by: AmelBawa-msft <104940545+AmelBawa-msft@users.noreply.github.com>
This commit is contained in:
@@ -2920,6 +2920,43 @@ On first run, creates the file with all settings commented out at their defaults
|
||||
<data name="WSLCCLI_ImageLoadNoInputError" xml:space="preserve">
|
||||
<value>Requested load but no input provided.</value>
|
||||
</data>
|
||||
<data name="WSLCCLI_NetworkCommandDesc" xml:space="preserve">
|
||||
<value>Manage networks.</value>
|
||||
</data>
|
||||
<data name="WSLCCLI_NetworkCommandLongDesc" xml:space="preserve">
|
||||
<value>Manage the lifecycle of WSL networks, including creating, inspecting, listing, and deleting them.</value>
|
||||
<comment>{Locked="WSL"}Product names should not be translated</comment>
|
||||
</data>
|
||||
<data name="WSLCCLI_NetworkCreateDesc" xml:space="preserve">
|
||||
<value>Create a network.</value>
|
||||
</data>
|
||||
<data name="WSLCCLI_NetworkCreateLongDesc" xml:space="preserve">
|
||||
<value>Creates a new network.</value>
|
||||
</data>
|
||||
<data name="WSLCCLI_NetworkRemoveDesc" xml:space="preserve">
|
||||
<value>Remove one or more networks.</value>
|
||||
</data>
|
||||
<data name="WSLCCLI_NetworkRemoveLongDesc" xml:space="preserve">
|
||||
<value>Removes one or more networks. A network cannot be removed if it has active endpoints.</value>
|
||||
</data>
|
||||
<data name="WSLCCLI_NetworkInspectDesc" xml:space="preserve">
|
||||
<value>Display detailed information on one or more networks.</value>
|
||||
</data>
|
||||
<data name="WSLCCLI_NetworkInspectLongDesc" xml:space="preserve">
|
||||
<value>Display detailed information on one or more networks.</value>
|
||||
</data>
|
||||
<data name="WSLCCLI_NetworkListDesc" xml:space="preserve">
|
||||
<value>List networks.</value>
|
||||
</data>
|
||||
<data name="WSLCCLI_NetworkListLongDesc" xml:space="preserve">
|
||||
<value>Lists all networks in the session.</value>
|
||||
</data>
|
||||
<data name="WSLCCLI_NetworkNameArgDescription" xml:space="preserve">
|
||||
<value>Network name</value>
|
||||
</data>
|
||||
<data name="WSLCCLI_NetworkListQuietArgDesc" xml:space="preserve">
|
||||
<value>Outputs the network names only</value>
|
||||
</data>
|
||||
<data name="WSLCCLI_VolumeCommandDesc" xml:space="preserve">
|
||||
<value>Manage volumes.</value>
|
||||
</data>
|
||||
|
||||
@@ -190,6 +190,26 @@ struct adl_serializer<WSLCVolumeInformation>
|
||||
strncpy_s(volume.Driver, sizeof(volume.Driver), driver.c_str(), _TRUNCATE);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct adl_serializer<WSLCNetworkInformation>
|
||||
{
|
||||
static void to_json(json& j, const WSLCNetworkInformation& network)
|
||||
{
|
||||
j = json{{"Name", std::string(network.Name)}, {"Id", std::string(network.Id)}, {"Driver", std::string(network.Driver)}};
|
||||
}
|
||||
|
||||
static void from_json(const json& j, WSLCNetworkInformation& network)
|
||||
{
|
||||
std::string name = j.at("Name").get<std::string>();
|
||||
std::string id = j.at("Id").get<std::string>();
|
||||
std::string driver = j.at("Driver").get<std::string>();
|
||||
|
||||
strncpy_s(network.Name, sizeof(network.Name), name.c_str(), _TRUNCATE);
|
||||
strncpy_s(network.Id, sizeof(network.Id), id.c_str(), _TRUNCATE);
|
||||
strncpy_s(network.Driver, sizeof(network.Driver), driver.c_str(), _TRUNCATE);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace nlohmann
|
||||
@@ -70,6 +70,7 @@ _(Label, "label", L"l", Kind::Value, L
|
||||
_(Last, "last", L"n", Kind::Value, Localization::WSLCCLI_LastArgDescription()) \
|
||||
_(Latest, "latest", L"l", Kind::Flag, Localization::WSLCCLI_LatestArgDescription()) \
|
||||
_(Name, "name", NO_ALIAS, Kind::Value, Localization::WSLCCLI_NameArgDescription()) \
|
||||
_(NetworkName, "network-name", NO_ALIAS, Kind::Positional, Localization::WSLCCLI_NetworkNameArgDescription()) \
|
||||
/*_(NoDNS, "no-dns", NO_ALIAS, Kind::Flag, Localization::WSLCCLI_NoDNSArgDescription())*/ \
|
||||
_(NoCache, "no-cache", NO_ALIAS, Kind::Flag, Localization::WSLCCLI_NoCacheArgDescription()) \
|
||||
_(NoPrune, "no-prune", NO_ALIAS, Kind::Flag, Localization::WSLCCLI_NoPruneArgDescription()) \
|
||||
|
||||
51
src/windows/wslc/commands/NetworkCommand.cpp
Normal file
51
src/windows/wslc/commands/NetworkCommand.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
NetworkCommand.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Implementation of command execution logic.
|
||||
|
||||
--*/
|
||||
#include "CLIExecutionContext.h"
|
||||
#include "NetworkCommand.h"
|
||||
|
||||
using namespace wsl::windows::wslc::execution;
|
||||
using namespace wsl::shared;
|
||||
|
||||
namespace wsl::windows::wslc {
|
||||
// Network Root Command
|
||||
std::vector<std::unique_ptr<Command>> NetworkCommand::GetCommands() const
|
||||
{
|
||||
std::vector<std::unique_ptr<Command>> commands;
|
||||
commands.push_back(std::make_unique<NetworkCreateCommand>(FullName()));
|
||||
commands.push_back(std::make_unique<NetworkRemoveCommand>(FullName()));
|
||||
commands.push_back(std::make_unique<NetworkInspectCommand>(FullName()));
|
||||
commands.push_back(std::make_unique<NetworkListCommand>(FullName()));
|
||||
return commands;
|
||||
}
|
||||
|
||||
std::vector<Argument> NetworkCommand::GetArguments() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::wstring NetworkCommand::ShortDescription() const
|
||||
{
|
||||
return Localization::WSLCCLI_NetworkCommandDesc();
|
||||
}
|
||||
|
||||
std::wstring NetworkCommand::LongDescription() const
|
||||
{
|
||||
return Localization::WSLCCLI_NetworkCommandLongDesc();
|
||||
}
|
||||
|
||||
void NetworkCommand::ExecuteInternal(CLIExecutionContext& context) const
|
||||
{
|
||||
OutputHelp();
|
||||
}
|
||||
} // namespace wsl::windows::wslc
|
||||
95
src/windows/wslc/commands/NetworkCommand.h
Normal file
95
src/windows/wslc/commands/NetworkCommand.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
NetworkCommand.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Declaration of command classes and interfaces.
|
||||
|
||||
--*/
|
||||
#pragma once
|
||||
#include "Command.h"
|
||||
|
||||
namespace wsl::windows::wslc {
|
||||
// Root Network Command
|
||||
struct NetworkCommand final : public Command
|
||||
{
|
||||
constexpr static std::wstring_view CommandName = L"network";
|
||||
NetworkCommand(const std::wstring& parent) : Command(CommandName, parent)
|
||||
{
|
||||
}
|
||||
std::vector<Argument> GetArguments() const override;
|
||||
std::wstring ShortDescription() const override;
|
||||
std::wstring LongDescription() const override;
|
||||
|
||||
std::vector<std::unique_ptr<Command>> GetCommands() const override;
|
||||
|
||||
protected:
|
||||
void ExecuteInternal(CLIExecutionContext& context) const override;
|
||||
};
|
||||
|
||||
// Create Command
|
||||
struct NetworkCreateCommand final : public Command
|
||||
{
|
||||
constexpr static std::wstring_view CommandName = L"create";
|
||||
NetworkCreateCommand(const std::wstring& parent) : Command(CommandName, parent)
|
||||
{
|
||||
}
|
||||
std::vector<Argument> GetArguments() const override;
|
||||
std::wstring ShortDescription() const override;
|
||||
std::wstring LongDescription() const override;
|
||||
|
||||
protected:
|
||||
void ExecuteInternal(CLIExecutionContext& context) const override;
|
||||
};
|
||||
|
||||
// Remove Command
|
||||
struct NetworkRemoveCommand final : public Command
|
||||
{
|
||||
constexpr static std::wstring_view CommandName = L"remove";
|
||||
NetworkRemoveCommand(const std::wstring& parent) : Command(CommandName, {L"delete", L"rm"}, parent)
|
||||
{
|
||||
}
|
||||
std::vector<Argument> GetArguments() const override;
|
||||
std::wstring ShortDescription() const override;
|
||||
std::wstring LongDescription() const override;
|
||||
|
||||
protected:
|
||||
void ExecuteInternal(CLIExecutionContext& context) const override;
|
||||
};
|
||||
|
||||
// Inspect Command
|
||||
struct NetworkInspectCommand final : public Command
|
||||
{
|
||||
constexpr static std::wstring_view CommandName = L"inspect";
|
||||
NetworkInspectCommand(const std::wstring& parent) : Command(CommandName, parent)
|
||||
{
|
||||
}
|
||||
std::vector<Argument> GetArguments() const override;
|
||||
std::wstring ShortDescription() const override;
|
||||
std::wstring LongDescription() const override;
|
||||
|
||||
protected:
|
||||
void ExecuteInternal(CLIExecutionContext& context) const override;
|
||||
};
|
||||
|
||||
// List Command
|
||||
struct NetworkListCommand final : public Command
|
||||
{
|
||||
constexpr static std::wstring_view CommandName = L"list";
|
||||
NetworkListCommand(const std::wstring& parent) : Command(CommandName, {L"ls"}, parent)
|
||||
{
|
||||
}
|
||||
std::vector<Argument> GetArguments() const override;
|
||||
std::wstring ShortDescription() const override;
|
||||
std::wstring LongDescription() const override;
|
||||
|
||||
protected:
|
||||
void ValidateArgumentsInternal(const ArgMap& execArgs) const override;
|
||||
void ExecuteInternal(CLIExecutionContext& context) const override;
|
||||
};
|
||||
} // namespace wsl::windows::wslc
|
||||
53
src/windows/wslc/commands/NetworkCreateCommand.cpp
Normal file
53
src/windows/wslc/commands/NetworkCreateCommand.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
NetworkCreateCommand.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Implementation of command execution logic.
|
||||
|
||||
--*/
|
||||
|
||||
#include "NetworkCommand.h"
|
||||
#include "CLIExecutionContext.h"
|
||||
#include "SessionTasks.h"
|
||||
#include "NetworkTasks.h"
|
||||
#include "Task.h"
|
||||
|
||||
using namespace wsl::windows::wslc::execution;
|
||||
using namespace wsl::windows::wslc::task;
|
||||
using namespace wsl::shared;
|
||||
|
||||
namespace wsl::windows::wslc {
|
||||
// Network Create Command
|
||||
std::vector<Argument> NetworkCreateCommand::GetArguments() const
|
||||
{
|
||||
return {
|
||||
Argument::Create(ArgType::NetworkName, true),
|
||||
Argument::Create(ArgType::Driver),
|
||||
Argument::Create(ArgType::Options, false, NO_LIMIT),
|
||||
Argument::Create(ArgType::Label, false, NO_LIMIT),
|
||||
Argument::Create(ArgType::Session),
|
||||
};
|
||||
}
|
||||
|
||||
std::wstring NetworkCreateCommand::ShortDescription() const
|
||||
{
|
||||
return Localization::WSLCCLI_NetworkCreateDesc();
|
||||
}
|
||||
|
||||
std::wstring NetworkCreateCommand::LongDescription() const
|
||||
{
|
||||
return Localization::WSLCCLI_NetworkCreateLongDesc();
|
||||
}
|
||||
|
||||
void NetworkCreateCommand::ExecuteInternal(CLIExecutionContext& context) const
|
||||
{
|
||||
context << CreateSession //
|
||||
<< CreateNetwork;
|
||||
}
|
||||
} // namespace wsl::windows::wslc
|
||||
50
src/windows/wslc/commands/NetworkInspectCommand.cpp
Normal file
50
src/windows/wslc/commands/NetworkInspectCommand.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
NetworkInspectCommand.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Implementation of command execution logic.
|
||||
|
||||
--*/
|
||||
|
||||
#include "NetworkCommand.h"
|
||||
#include "CLIExecutionContext.h"
|
||||
#include "SessionTasks.h"
|
||||
#include "NetworkTasks.h"
|
||||
#include "Task.h"
|
||||
|
||||
using namespace wsl::windows::wslc::execution;
|
||||
using namespace wsl::windows::wslc::task;
|
||||
using namespace wsl::shared;
|
||||
|
||||
namespace wsl::windows::wslc {
|
||||
// Network Inspect Command
|
||||
std::vector<Argument> NetworkInspectCommand::GetArguments() const
|
||||
{
|
||||
return {
|
||||
Argument::Create(ArgType::NetworkName, true, NO_LIMIT),
|
||||
Argument::Create(ArgType::Session),
|
||||
};
|
||||
}
|
||||
|
||||
std::wstring NetworkInspectCommand::ShortDescription() const
|
||||
{
|
||||
return Localization::WSLCCLI_NetworkInspectDesc();
|
||||
}
|
||||
|
||||
std::wstring NetworkInspectCommand::LongDescription() const
|
||||
{
|
||||
return Localization::WSLCCLI_NetworkInspectLongDesc();
|
||||
}
|
||||
|
||||
void NetworkInspectCommand::ExecuteInternal(CLIExecutionContext& context) const
|
||||
{
|
||||
context << CreateSession //
|
||||
<< InspectNetworks;
|
||||
}
|
||||
} // namespace wsl::windows::wslc
|
||||
65
src/windows/wslc/commands/NetworkListCommand.cpp
Normal file
65
src/windows/wslc/commands/NetworkListCommand.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
NetworkListCommand.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Implementation of command execution logic.
|
||||
|
||||
--*/
|
||||
|
||||
#include "NetworkCommand.h"
|
||||
#include "CLIExecutionContext.h"
|
||||
#include "SessionTasks.h"
|
||||
#include "NetworkTasks.h"
|
||||
#include "Task.h"
|
||||
|
||||
using namespace wsl::windows::wslc::execution;
|
||||
using namespace wsl::windows::wslc::task;
|
||||
using namespace wsl::shared;
|
||||
using namespace wsl::shared::string;
|
||||
|
||||
namespace wsl::windows::wslc {
|
||||
// Network List Command
|
||||
std::vector<Argument> NetworkListCommand::GetArguments() const
|
||||
{
|
||||
return {
|
||||
Argument::Create(ArgType::Format),
|
||||
Argument::Create(ArgType::Quiet, false, std::nullopt, Localization::WSLCCLI_NetworkListQuietArgDesc()),
|
||||
Argument::Create(ArgType::Session),
|
||||
};
|
||||
}
|
||||
|
||||
std::wstring NetworkListCommand::ShortDescription() const
|
||||
{
|
||||
return Localization::WSLCCLI_NetworkListDesc();
|
||||
}
|
||||
|
||||
std::wstring NetworkListCommand::LongDescription() const
|
||||
{
|
||||
return Localization::WSLCCLI_NetworkListLongDesc();
|
||||
}
|
||||
|
||||
void NetworkListCommand::ValidateArgumentsInternal(const ArgMap& execArgs) const
|
||||
{
|
||||
if (execArgs.Contains(ArgType::Format))
|
||||
{
|
||||
auto format = execArgs.Get<ArgType::Format>();
|
||||
if (!IsEqual(format, L"json") && !IsEqual(format, L"table"))
|
||||
{
|
||||
throw CommandException(Localization::WSLCCLI_InvalidFormatError());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkListCommand::ExecuteInternal(CLIExecutionContext& context) const
|
||||
{
|
||||
context << CreateSession //
|
||||
<< GetNetworks //
|
||||
<< ListNetworks;
|
||||
}
|
||||
} // namespace wsl::windows::wslc
|
||||
50
src/windows/wslc/commands/NetworkRemoveCommand.cpp
Normal file
50
src/windows/wslc/commands/NetworkRemoveCommand.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
NetworkRemoveCommand.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Implementation of command execution logic.
|
||||
|
||||
--*/
|
||||
|
||||
#include "NetworkCommand.h"
|
||||
#include "CLIExecutionContext.h"
|
||||
#include "SessionTasks.h"
|
||||
#include "NetworkTasks.h"
|
||||
#include "Task.h"
|
||||
|
||||
using namespace wsl::windows::wslc::execution;
|
||||
using namespace wsl::windows::wslc::task;
|
||||
using namespace wsl::shared;
|
||||
|
||||
namespace wsl::windows::wslc {
|
||||
// Network Remove Command
|
||||
std::vector<Argument> NetworkRemoveCommand::GetArguments() const
|
||||
{
|
||||
return {
|
||||
Argument::Create(ArgType::NetworkName, true, NO_LIMIT),
|
||||
Argument::Create(ArgType::Session),
|
||||
};
|
||||
}
|
||||
|
||||
std::wstring NetworkRemoveCommand::ShortDescription() const
|
||||
{
|
||||
return Localization::WSLCCLI_NetworkRemoveDesc();
|
||||
}
|
||||
|
||||
std::wstring NetworkRemoveCommand::LongDescription() const
|
||||
{
|
||||
return Localization::WSLCCLI_NetworkRemoveLongDesc();
|
||||
}
|
||||
|
||||
void NetworkRemoveCommand::ExecuteInternal(CLIExecutionContext& context) const
|
||||
{
|
||||
context << CreateSession //
|
||||
<< DeleteNetworks;
|
||||
}
|
||||
} // namespace wsl::windows::wslc
|
||||
@@ -16,6 +16,7 @@ Abstract:
|
||||
// Include all commands that parent to the root.
|
||||
#include "ContainerCommand.h"
|
||||
#include "ImageCommand.h"
|
||||
#include "NetworkCommand.h"
|
||||
#include "RegistryCommand.h"
|
||||
#include "SettingsCommand.h"
|
||||
#include "SystemCommand.h"
|
||||
@@ -32,6 +33,7 @@ std::vector<std::unique_ptr<Command>> RootCommand::GetCommands() const
|
||||
std::vector<std::unique_ptr<Command>> commands;
|
||||
commands.push_back(std::make_unique<ContainerCommand>(FullName()));
|
||||
commands.push_back(std::make_unique<ImageCommand>(FullName()));
|
||||
commands.push_back(std::make_unique<NetworkCommand>(FullName()));
|
||||
commands.push_back(std::make_unique<RegistryCommand>(FullName()));
|
||||
commands.push_back(std::make_unique<SettingsCommand>(FullName()));
|
||||
commands.push_back(std::make_unique<SystemCommand>(FullName()));
|
||||
|
||||
@@ -38,6 +38,7 @@ enum class Data : size_t
|
||||
ContainerOptions,
|
||||
Images,
|
||||
Volumes,
|
||||
Networks,
|
||||
|
||||
Max
|
||||
};
|
||||
@@ -53,6 +54,7 @@ namespace details {
|
||||
DEFINE_DATA_MAPPING(ContainerOptions, wsl::windows::wslc::models::ContainerOptions);
|
||||
DEFINE_DATA_MAPPING(Images, std::vector<wsl::windows::wslc::models::ImageInformation>);
|
||||
DEFINE_DATA_MAPPING(Volumes, std::vector<WSLCVolumeInformation>);
|
||||
DEFINE_DATA_MAPPING(Networks, std::vector<WSLCNetworkInformation>);
|
||||
} // namespace details
|
||||
|
||||
struct DataMap : wsl::windows::wslc::EnumBasedVariantMap<Data, wsl::windows::wslc::execution::details::DataMapping>
|
||||
|
||||
30
src/windows/wslc/services/NetworkModel.h
Normal file
30
src/windows/wslc/services/NetworkModel.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
NetworkModel.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This file contains the NetworkModel definitions
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonUtils.h"
|
||||
#include <string>
|
||||
|
||||
namespace wsl::windows::wslc::models {
|
||||
|
||||
struct CreateNetworkOptions
|
||||
{
|
||||
std::string Name;
|
||||
std::optional<std::string> Driver;
|
||||
std::vector<std::pair<std::string, std::string>> DriverOpts{};
|
||||
std::vector<std::pair<std::string, std::string>> Labels{};
|
||||
};
|
||||
|
||||
} // namespace wsl::windows::wslc::models
|
||||
82
src/windows/wslc/services/NetworkService.cpp
Normal file
82
src/windows/wslc/services/NetworkService.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
NetworkService.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This file contains the NetworkService implementation
|
||||
|
||||
--*/
|
||||
#include "NetworkService.h"
|
||||
#include <wslutil.h>
|
||||
#include <wslc.h>
|
||||
|
||||
using namespace wsl::shared;
|
||||
using namespace wsl::shared::string;
|
||||
using namespace wsl::windows::common::wslutil;
|
||||
|
||||
namespace wsl::windows::wslc::services {
|
||||
|
||||
void NetworkService::Create(models::Session& session, const models::CreateNetworkOptions& createOptions)
|
||||
{
|
||||
WSLCNetworkOptions options{};
|
||||
options.Name = createOptions.Name.c_str();
|
||||
if (createOptions.Driver.has_value())
|
||||
{
|
||||
options.Driver = createOptions.Driver->c_str();
|
||||
}
|
||||
|
||||
// Set driver options
|
||||
std::vector<KeyValuePair> driverOpts;
|
||||
for (const auto& option : createOptions.DriverOpts)
|
||||
{
|
||||
driverOpts.push_back({.Key = option.first.c_str(), .Value = option.second.c_str()});
|
||||
}
|
||||
|
||||
// Set labels
|
||||
std::vector<KeyValuePair> labels;
|
||||
for (const auto& label : createOptions.Labels)
|
||||
{
|
||||
labels.push_back({.Key = label.first.c_str(), .Value = label.second.c_str()});
|
||||
}
|
||||
|
||||
options.DriverOpts = driverOpts.data();
|
||||
options.DriverOptsCount = static_cast<ULONG>(driverOpts.size());
|
||||
options.Labels = labels.data();
|
||||
options.LabelsCount = static_cast<ULONG>(labels.size());
|
||||
|
||||
THROW_IF_FAILED(session.Get()->CreateNetwork(&options));
|
||||
}
|
||||
|
||||
void NetworkService::Delete(models::Session& session, const std::string& name)
|
||||
{
|
||||
THROW_IF_FAILED(session.Get()->DeleteNetwork(name.c_str()));
|
||||
}
|
||||
|
||||
std::vector<WSLCNetworkInformation> NetworkService::List(models::Session& session)
|
||||
{
|
||||
wil::unique_cotaskmem_array_ptr<WSLCNetworkInformation> rawNetworks;
|
||||
ULONG count = 0;
|
||||
THROW_IF_FAILED(session.Get()->ListNetworks(&rawNetworks, &count));
|
||||
|
||||
std::vector<WSLCNetworkInformation> networks;
|
||||
networks.reserve(count);
|
||||
for (auto ptr = rawNetworks.get(), end = rawNetworks.get() + count; ptr != end; ++ptr)
|
||||
{
|
||||
networks.push_back(*ptr);
|
||||
}
|
||||
|
||||
return networks;
|
||||
}
|
||||
|
||||
wsl::windows::common::wslc_schema::InspectNetwork NetworkService::Inspect(models::Session& session, const std::string& name)
|
||||
{
|
||||
wil::unique_cotaskmem_ansistring output;
|
||||
THROW_IF_FAILED(session.Get()->InspectNetwork(name.c_str(), &output));
|
||||
return FromJson<wsl::windows::common::wslc_schema::InspectNetwork>(output.get());
|
||||
}
|
||||
} // namespace wsl::windows::wslc::services
|
||||
28
src/windows/wslc/services/NetworkService.h
Normal file
28
src/windows/wslc/services/NetworkService.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
NetworkService.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This file contains the NetworkService definition
|
||||
|
||||
--*/
|
||||
#pragma once
|
||||
|
||||
#include "SessionModel.h"
|
||||
#include "NetworkModel.h"
|
||||
#include <wslc_schema.h>
|
||||
|
||||
namespace wsl::windows::wslc::services {
|
||||
struct NetworkService
|
||||
{
|
||||
static void Create(models::Session& session, const models::CreateNetworkOptions& createOptions);
|
||||
static void Delete(models::Session& session, const std::string& name);
|
||||
static std::vector<WSLCNetworkInformation> List(models::Session& session);
|
||||
static wsl::windows::common::wslc_schema::InspectNetwork Inspect(models::Session& session, const std::string& name);
|
||||
};
|
||||
} // namespace wsl::windows::wslc::services
|
||||
205
src/windows/wslc/tasks/NetworkTasks.cpp
Normal file
205
src/windows/wslc/tasks/NetworkTasks.cpp
Normal file
@@ -0,0 +1,205 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
NetworkTasks.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Implementation of network command related execution logic.
|
||||
|
||||
--*/
|
||||
#include "Argument.h"
|
||||
#include "ArgumentValidation.h"
|
||||
#include "CLIExecutionContext.h"
|
||||
#include "NetworkModel.h"
|
||||
#include "NetworkService.h"
|
||||
#include "NetworkTasks.h"
|
||||
#include "TableOutput.h"
|
||||
#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 std::pair<std::string, std::string> OptionsToKeyValue(const std::wstring& option)
|
||||
{
|
||||
auto pos = option.find('=');
|
||||
if (pos == std::wstring::npos)
|
||||
{
|
||||
return {WideToMultiByte(option), std::string()};
|
||||
}
|
||||
|
||||
return {WideToMultiByte(option.substr(0, pos)), WideToMultiByte(option.substr(pos + 1))};
|
||||
}
|
||||
|
||||
static bool TryInspectNetwork(Session& session, const std::string& networkName, std::optional<wslc_schema::InspectNetwork>& inspectData)
|
||||
{
|
||||
try
|
||||
{
|
||||
inspectData = NetworkService::Inspect(session, networkName);
|
||||
return true;
|
||||
}
|
||||
catch (const wil::ResultException& ex)
|
||||
{
|
||||
if (ex.GetErrorCode() == WSLC_E_NETWORK_NOT_FOUND)
|
||||
{
|
||||
PrintMessage(Localization::MessageWslcNetworkNotFound(networkName.c_str()), stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
static bool TryDeleteNetwork(Session& session, const std::string& networkName)
|
||||
{
|
||||
try
|
||||
{
|
||||
NetworkService::Delete(session, networkName);
|
||||
return true;
|
||||
}
|
||||
catch (const wil::ResultException& ex)
|
||||
{
|
||||
if (ex.GetErrorCode() == WSLC_E_NETWORK_NOT_FOUND)
|
||||
{
|
||||
PrintMessage(Localization::MessageWslcNetworkNotFound(networkName.c_str()), stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void CreateNetwork(CLIExecutionContext& context)
|
||||
{
|
||||
WI_ASSERT(context.Data.Contains(Data::Session));
|
||||
WI_ASSERT(context.Args.Contains(ArgType::NetworkName));
|
||||
|
||||
models::CreateNetworkOptions options{};
|
||||
options.Name = WideToMultiByte(context.Args.Get<ArgType::NetworkName>());
|
||||
|
||||
for (const auto& option : context.Args.GetAll<ArgType::Options>())
|
||||
{
|
||||
options.DriverOpts.push_back(OptionsToKeyValue(option));
|
||||
}
|
||||
|
||||
for (const auto& label : context.Args.GetAll<ArgType::Label>())
|
||||
{
|
||||
options.Labels.push_back(OptionsToKeyValue(label));
|
||||
}
|
||||
|
||||
if (context.Args.Contains(ArgType::Driver))
|
||||
{
|
||||
options.Driver = WideToMultiByte(context.Args.Get<ArgType::Driver>());
|
||||
}
|
||||
|
||||
NetworkService::Create(context.Data.Get<Data::Session>(), options);
|
||||
PrintMessage(MultiByteToWide(options.Name));
|
||||
}
|
||||
|
||||
void DeleteNetworks(CLIExecutionContext& context)
|
||||
{
|
||||
WI_ASSERT(context.Data.Contains(Data::Session));
|
||||
auto& session = context.Data.Get<Data::Session>();
|
||||
auto networkNames = context.Args.GetAll<ArgType::NetworkName>();
|
||||
for (const auto& name : networkNames)
|
||||
{
|
||||
if (TryDeleteNetwork(session, WideToMultiByte(name)))
|
||||
{
|
||||
PrintMessage(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.ExitCode = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GetNetworks(CLIExecutionContext& context)
|
||||
{
|
||||
WI_ASSERT(context.Data.Contains(Data::Session));
|
||||
auto& session = context.Data.Get<Data::Session>();
|
||||
context.Data.Add<Data::Networks>(NetworkService::List(session));
|
||||
}
|
||||
|
||||
void InspectNetworks(CLIExecutionContext& context)
|
||||
{
|
||||
WI_ASSERT(context.Data.Contains(Data::Session));
|
||||
auto& session = context.Data.Get<Data::Session>();
|
||||
auto networkNames = context.Args.GetAll<ArgType::NetworkName>();
|
||||
std::vector<wsl::windows::common::wslc_schema::InspectNetwork> result;
|
||||
for (const auto& name : networkNames)
|
||||
{
|
||||
std::optional<wslc_schema::InspectNetwork> inspectData;
|
||||
if (TryInspectNetwork(session, WideToMultiByte(name), inspectData))
|
||||
{
|
||||
result.push_back(*inspectData);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.ExitCode = 1;
|
||||
}
|
||||
}
|
||||
|
||||
auto json = ToJson(result, c_jsonPrettyPrintIndent);
|
||||
PrintMessage(MultiByteToWide(json));
|
||||
}
|
||||
|
||||
void ListNetworks(CLIExecutionContext& context)
|
||||
{
|
||||
WI_ASSERT(context.Data.Contains(Data::Networks));
|
||||
auto& networks = context.Data.Get<Data::Networks>();
|
||||
|
||||
if (context.Args.Contains(ArgType::Quiet))
|
||||
{
|
||||
for (const auto& network : networks)
|
||||
{
|
||||
PrintMessage(MultiByteToWide(network.Name));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
FormatType format = FormatType::Table;
|
||||
if (context.Args.Contains(ArgType::Format))
|
||||
{
|
||||
format = validation::GetFormatTypeFromString(context.Args.Get<ArgType::Format>());
|
||||
}
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case FormatType::Json:
|
||||
{
|
||||
auto json = ToJson(networks, c_jsonPrettyPrintIndent);
|
||||
PrintMessage(MultiByteToWide(json));
|
||||
break;
|
||||
}
|
||||
case FormatType::Table:
|
||||
{
|
||||
auto table = wsl::windows::wslc::TableOutput<3>({L"NETWORK ID", L"NAME", L"DRIVER"});
|
||||
for (const auto& network : networks)
|
||||
{
|
||||
table.OutputLine({
|
||||
MultiByteToWide(TruncateId(network.Id)),
|
||||
MultiByteToWide(network.Name),
|
||||
MultiByteToWide(network.Driver),
|
||||
});
|
||||
}
|
||||
|
||||
table.Complete();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
THROW_HR(E_UNEXPECTED);
|
||||
}
|
||||
}
|
||||
} // namespace wsl::windows::wslc::task
|
||||
24
src/windows/wslc/tasks/NetworkTasks.h
Normal file
24
src/windows/wslc/tasks/NetworkTasks.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
NetworkTasks.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Declaration of network command execution tasks.
|
||||
|
||||
--*/
|
||||
#pragma once
|
||||
#include "CLIExecutionContext.h"
|
||||
|
||||
namespace wsl::windows::wslc::task {
|
||||
|
||||
void CreateNetwork(wsl::windows::wslc::execution::CLIExecutionContext& context);
|
||||
void DeleteNetworks(wsl::windows::wslc::execution::CLIExecutionContext& context);
|
||||
void GetNetworks(wsl::windows::wslc::execution::CLIExecutionContext& context);
|
||||
void InspectNetworks(wsl::windows::wslc::execution::CLIExecutionContext& context);
|
||||
void ListNetworks(wsl::windows::wslc::execution::CLIExecutionContext& context);
|
||||
} // namespace wsl::windows::wslc::task
|
||||
@@ -525,6 +525,7 @@ private:
|
||||
std::vector<std::pair<std::wstring_view, std::wstring>> entries = {
|
||||
{L"container", Localization::WSLCCLI_ContainerCommandDesc()},
|
||||
{L"image", Localization::WSLCCLI_ImageCommandDesc()},
|
||||
{L"network", Localization::WSLCCLI_NetworkCommandDesc()},
|
||||
{L"registry", Localization::WSLCCLI_RegistryCommandDesc()},
|
||||
{L"settings", Localization::WSLCCLI_SettingsCommandDesc()},
|
||||
{L"system", Localization::WSLCCLI_SystemCommandDesc()},
|
||||
|
||||
@@ -244,6 +244,36 @@ void VerifyVolumeIsNotListed(const std::wstring& volumeName)
|
||||
}
|
||||
}
|
||||
|
||||
void VerifyNetworkIsListed(const std::wstring& networkName)
|
||||
{
|
||||
auto result = RunWslc(L"network list --format json");
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
auto networks = wsl::shared::FromJson<std::vector<WSLCNetworkInformation>>(result.Stdout.value().c_str());
|
||||
for (const auto& net : networks)
|
||||
{
|
||||
if (net.Name == wsl::shared::string::WideToMultiByte(networkName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
VERIFY_FAIL(std::format(L"Network '{}' not found in network list output", networkName).c_str());
|
||||
}
|
||||
|
||||
void VerifyNetworkIsNotListed(const std::wstring& networkName)
|
||||
{
|
||||
auto result = RunWslc(L"network list --format json");
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
auto networks = wsl::shared::FromJson<std::vector<WSLCNetworkInformation>>(result.Stdout.value().c_str());
|
||||
for (const auto& net : networks)
|
||||
{
|
||||
if (net.Name == wsl::shared::string::WideToMultiByte(networkName))
|
||||
{
|
||||
VERIFY_FAIL(std::format(L"Network '{}' found in network list output", networkName).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetHashId(const std::string& id, bool fullId)
|
||||
{
|
||||
return wsl::windows::common::string::TruncateId(id, !fullId);
|
||||
@@ -422,6 +452,31 @@ void EnsureVolumeDoesNotExist(const std::wstring& volumeName)
|
||||
}
|
||||
}
|
||||
|
||||
void EnsureNetworkDoesNotExist(const std::wstring& networkName)
|
||||
{
|
||||
auto result = RunWslc(L"network list --format json");
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
auto networks = wsl::shared::FromJson<std::vector<WSLCNetworkInformation>>(result.Stdout.value().c_str());
|
||||
for (const auto& net : networks)
|
||||
{
|
||||
if (net.Name == wsl::shared::string::WideToMultiByte(networkName))
|
||||
{
|
||||
auto deleteResult = RunWslc(std::format(L"network rm {}", networkName));
|
||||
deleteResult.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wslc_schema::InspectNetwork InspectNetwork(const std::wstring& networkName)
|
||||
{
|
||||
auto result = RunWslc(std::format(L"network inspect {}", networkName));
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
auto inspectData = wsl::shared::FromJson<std::vector<wslc_schema::InspectNetwork>>(result.Stdout.value().c_str());
|
||||
VERIFY_ARE_EQUAL(1u, inspectData.size());
|
||||
return inspectData[0];
|
||||
}
|
||||
|
||||
wil::com_ptr<IWSLCSession> OpenDefaultElevatedSession()
|
||||
{
|
||||
// Ensure the default elevated session exists before opening it via COM.
|
||||
|
||||
@@ -123,11 +123,14 @@ void VerifyImageIsNotUsed(const TestImage& image);
|
||||
void VerifyImageIsListed(const TestImage& image);
|
||||
void VerifyVolumeIsListed(const std::wstring& volumeName);
|
||||
void VerifyVolumeIsNotListed(const std::wstring& volumeName);
|
||||
void VerifyNetworkIsListed(const std::wstring& networkName);
|
||||
void VerifyNetworkIsNotListed(const std::wstring& networkName);
|
||||
|
||||
std::string GetHashId(const std::string& id, bool fullId = false);
|
||||
wsl::windows::common::wslc_schema::InspectContainer InspectContainer(const std::wstring& containerName);
|
||||
wsl::windows::common::wslc_schema::InspectImage InspectImage(const std::wstring& imageName);
|
||||
wsl::windows::common::wslc_schema::InspectVolume InspectVolume(const std::wstring& volumeName);
|
||||
wsl::windows::common::wslc_schema::InspectNetwork InspectNetwork(const std::wstring& networkName);
|
||||
std::vector<wsl::windows::wslc::models::ContainerInformation> ListAllContainers();
|
||||
|
||||
void EnsureContainerDoesNotExist(const std::wstring& containerName);
|
||||
@@ -136,6 +139,7 @@ void EnsureImageIsDeleted(const TestImage& image);
|
||||
void EnsureImageContainersAreDeleted(const TestImage& image);
|
||||
void EnsureSessionIsTerminated(const std::wstring& sessionName = L"");
|
||||
void EnsureVolumeDoesNotExist(const std::wstring& volumeName);
|
||||
void EnsureNetworkDoesNotExist(const std::wstring& networkName);
|
||||
|
||||
void WriteTestFile(const std::filesystem::path& filePath, const std::vector<std::string>& envVariableLines);
|
||||
std::wstring GetPythonHttpServerScript(uint16_t port);
|
||||
|
||||
143
test/windows/wslc/e2e/WSLCE2ENetworkCreateTests.cpp
Normal file
143
test/windows/wslc/e2e/WSLCE2ENetworkCreateTests.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
WSLCE2ENetworkCreateTests.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This file contains end-to-end tests for WSLC.
|
||||
--*/
|
||||
|
||||
#include "precomp.h"
|
||||
#include "windows/Common.h"
|
||||
#include "WSLCExecutor.h"
|
||||
#include "WSLCE2EHelpers.h"
|
||||
|
||||
namespace WSLCE2ETests {
|
||||
using namespace wsl::shared;
|
||||
|
||||
class WSLCE2ENetworkCreateTests
|
||||
{
|
||||
WSLC_TEST_CLASS(WSLCE2ENetworkCreateTests)
|
||||
|
||||
TEST_METHOD_SETUP(MethodSetup)
|
||||
{
|
||||
EnsureNetworkDoesNotExist(TestNetworkName);
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST_CLASS_CLEANUP(ClassCleanup)
|
||||
{
|
||||
EnsureNetworkDoesNotExist(TestNetworkName);
|
||||
return true;
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_Create_HelpCommand)
|
||||
{
|
||||
auto result = RunWslc(L"network create --help");
|
||||
result.Verify({.Stdout = GetHelpMessage(), .Stderr = L"", .ExitCode = 0});
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_Create_MissingName)
|
||||
{
|
||||
auto result = RunWslc(L"network create");
|
||||
result.Verify({.Stdout = GetHelpMessage(), .Stderr = L"Required argument not provided: 'network-name'\r\n", .ExitCode = 1});
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_Create_Success)
|
||||
{
|
||||
auto result = RunWslc(std::format(L"network create --driver bridge {}", TestNetworkName));
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
VERIFY_ARE_EQUAL(TestNetworkName, result.GetStdoutOneLine());
|
||||
|
||||
VerifyNetworkIsListed(TestNetworkName);
|
||||
auto inspect = InspectNetwork(TestNetworkName);
|
||||
VERIFY_ARE_EQUAL("bridge", inspect.Driver);
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_Create_WithLabels_Success)
|
||||
{
|
||||
auto result = RunWslc(std::format(L"network create --driver bridge --label env=test --label app=wslc {}", TestNetworkName));
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
VERIFY_ARE_EQUAL(TestNetworkName, result.GetStdoutOneLine());
|
||||
|
||||
VerifyNetworkIsListed(TestNetworkName);
|
||||
auto inspect = InspectNetwork(TestNetworkName);
|
||||
VERIFY_ARE_EQUAL("bridge", inspect.Driver);
|
||||
VERIFY_ARE_EQUAL("test", inspect.Labels["env"]);
|
||||
VERIFY_ARE_EQUAL("wslc", inspect.Labels["app"]);
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_Create_InvalidDriver_Fail)
|
||||
{
|
||||
auto result = RunWslc(std::format(L"network create --driver invalid_driver {}", TestNetworkName));
|
||||
result.Verify(
|
||||
{.Stdout = L"",
|
||||
.Stderr = std::format(L"Unsupported network driver: 'invalid_driver'\r\nError code: E_INVALIDARG\r\n"),
|
||||
.ExitCode = 1});
|
||||
|
||||
VerifyNetworkIsNotListed(TestNetworkName);
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_Create_Duplicate_Fail)
|
||||
{
|
||||
auto result = RunWslc(std::format(L"network create --driver bridge {}", TestNetworkName));
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
|
||||
result = RunWslc(std::format(L"network create --driver bridge {}", TestNetworkName));
|
||||
result.Verify(
|
||||
{.Stdout = L"",
|
||||
.Stderr = std::format(L"Network '{}' already exists.\r\nError code: ERROR_ALREADY_EXISTS\r\n", TestNetworkName),
|
||||
.ExitCode = 1});
|
||||
}
|
||||
|
||||
private:
|
||||
const std::wstring TestNetworkName = L"wslc-e2e-network-create";
|
||||
|
||||
std::wstring GetHelpMessage() const
|
||||
{
|
||||
std::wstringstream output;
|
||||
output << GetWslcHeader() //
|
||||
<< GetDescription() //
|
||||
<< GetUsage() //
|
||||
<< GetAvailableCommands() //
|
||||
<< GetAvailableOptions();
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::wstring GetDescription() const
|
||||
{
|
||||
return std::format(L"{}\r\n\r\n", Localization::WSLCCLI_NetworkCreateLongDesc());
|
||||
}
|
||||
|
||||
std::wstring GetUsage() const
|
||||
{
|
||||
return L"Usage: wslc network create [<options>] <network-name>\r\n\r\n";
|
||||
}
|
||||
|
||||
std::wstring GetAvailableCommands() const
|
||||
{
|
||||
std::wstringstream commands;
|
||||
commands << L"The following arguments are available:\r\n" //
|
||||
<< L" network-name Network name\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" -d,--driver Specify volume driver name (default guest)\r\n" //
|
||||
<< L" -o,--opt Set driver specific options\r\n" //
|
||||
<< L" --label Volume metadata setting\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
|
||||
160
test/windows/wslc/e2e/WSLCE2ENetworkInspectTests.cpp
Normal file
160
test/windows/wslc/e2e/WSLCE2ENetworkInspectTests.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
WSLCE2ENetworkInspectTests.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This file contains end-to-end tests for WSLC.
|
||||
--*/
|
||||
|
||||
#include "precomp.h"
|
||||
#include "windows/Common.h"
|
||||
#include "WSLCExecutor.h"
|
||||
#include "WSLCE2EHelpers.h"
|
||||
|
||||
namespace WSLCE2ETests {
|
||||
using namespace wsl::shared;
|
||||
using namespace wsl::shared::string;
|
||||
|
||||
class WSLCE2ENetworkInspectTests
|
||||
{
|
||||
WSLC_TEST_CLASS(WSLCE2ENetworkInspectTests)
|
||||
|
||||
TEST_METHOD_SETUP(MethodSetup)
|
||||
{
|
||||
EnsureNetworkDoesNotExist(TestNetworkName1);
|
||||
EnsureNetworkDoesNotExist(TestNetworkName2);
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST_CLASS_CLEANUP(ClassCleanup)
|
||||
{
|
||||
EnsureNetworkDoesNotExist(TestNetworkName1);
|
||||
EnsureNetworkDoesNotExist(TestNetworkName2);
|
||||
return true;
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_Inspect_HelpCommand)
|
||||
{
|
||||
auto result = RunWslc(L"network inspect --help");
|
||||
result.Verify({.Stdout = GetHelpMessage(), .Stderr = L"", .ExitCode = 0});
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_Inspect_MissingNetworkName)
|
||||
{
|
||||
auto result = RunWslc(L"network inspect");
|
||||
result.Verify({.Stdout = GetHelpMessage(), .Stderr = L"Required argument not provided: 'network-name'\r\n", .ExitCode = 1});
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_Inspect_Success)
|
||||
{
|
||||
auto result = RunWslc(std::format(L"network create --driver bridge {}", TestNetworkName1));
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
VERIFY_ARE_EQUAL(TestNetworkName1, result.GetStdoutOneLine());
|
||||
|
||||
result = RunWslc(std::format(L"network inspect {}", TestNetworkName1));
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
auto inspectData =
|
||||
wsl::shared::FromJson<std::vector<wsl::windows::common::wslc_schema::InspectNetwork>>(result.Stdout.value().c_str());
|
||||
VERIFY_ARE_EQUAL(1u, inspectData.size());
|
||||
auto inspect = inspectData[0];
|
||||
|
||||
VERIFY_ARE_EQUAL(WideToMultiByte(TestNetworkName1), inspect.Name);
|
||||
VERIFY_ARE_EQUAL("bridge", inspect.Driver);
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_InspectMultiple_Success)
|
||||
{
|
||||
auto result = RunWslc(std::format(L"network create --driver bridge {}", TestNetworkName1));
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
VERIFY_ARE_EQUAL(TestNetworkName1, result.GetStdoutOneLine());
|
||||
result = RunWslc(std::format(L"network create --driver bridge {}", TestNetworkName2));
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
VERIFY_ARE_EQUAL(TestNetworkName2, result.GetStdoutOneLine());
|
||||
|
||||
result = RunWslc(std::format(L"network inspect {} {}", TestNetworkName1, TestNetworkName2));
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
auto inspectData =
|
||||
wsl::shared::FromJson<std::vector<wsl::windows::common::wslc_schema::InspectNetwork>>(result.Stdout.value().c_str());
|
||||
VERIFY_ARE_EQUAL(2u, inspectData.size());
|
||||
|
||||
auto inspect1 = inspectData[0];
|
||||
VERIFY_ARE_EQUAL(WideToMultiByte(TestNetworkName1), inspect1.Name);
|
||||
VERIFY_ARE_EQUAL("bridge", inspect1.Driver);
|
||||
|
||||
auto inspect2 = inspectData[1];
|
||||
VERIFY_ARE_EQUAL(WideToMultiByte(TestNetworkName2), inspect2.Name);
|
||||
VERIFY_ARE_EQUAL("bridge", inspect2.Driver);
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_Inspect_NotFound)
|
||||
{
|
||||
auto result = RunWslc(std::format(L"network inspect {}", TestNetworkName1));
|
||||
result.Verify({.Stdout = L"[]\r\n", .Stderr = std::format(L"Network not found: '{}'\r\n", TestNetworkName1), .ExitCode = 1});
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_Inspect_MixedFoundNotFound)
|
||||
{
|
||||
auto result = RunWslc(std::format(L"network create --driver bridge {}", TestNetworkName1));
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
VERIFY_ARE_EQUAL(TestNetworkName1, result.GetStdoutOneLine());
|
||||
|
||||
result = RunWslc(std::format(L"network inspect {} {}", TestNetworkName1, TestNetworkName2));
|
||||
result.Verify({.Stderr = std::format(L"Network not found: '{}'\r\n", TestNetworkName2), .ExitCode = 1});
|
||||
|
||||
auto inspectData =
|
||||
wsl::shared::FromJson<std::vector<wsl::windows::common::wslc_schema::InspectNetwork>>(result.Stdout.value().c_str());
|
||||
VERIFY_ARE_EQUAL(1u, inspectData.size());
|
||||
auto inspect = inspectData[0];
|
||||
VERIFY_ARE_EQUAL(WideToMultiByte(TestNetworkName1), inspect.Name);
|
||||
}
|
||||
|
||||
private:
|
||||
const std::wstring TestNetworkName1 = L"wslc-e2e-network-inspect-1";
|
||||
const std::wstring TestNetworkName2 = L"wslc-e2e-network-inspect-2";
|
||||
|
||||
std::wstring GetHelpMessage() const
|
||||
{
|
||||
std::wstringstream output;
|
||||
output << GetWslcHeader() //
|
||||
<< GetDescription() //
|
||||
<< GetUsage() //
|
||||
<< GetAvailableCommands() //
|
||||
<< GetAvailableOptions();
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::wstring GetDescription() const
|
||||
{
|
||||
return std::format(L"{}\r\n\r\n", Localization::WSLCCLI_NetworkInspectLongDesc());
|
||||
}
|
||||
|
||||
std::wstring GetUsage() const
|
||||
{
|
||||
return L"Usage: wslc network inspect [<options>] <network-name>\r\n\r\n";
|
||||
}
|
||||
|
||||
std::wstring GetAvailableCommands() const
|
||||
{
|
||||
std::wstringstream commands;
|
||||
commands << L"The following arguments are available:\r\n" //
|
||||
<< L" network-name Network name\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
|
||||
134
test/windows/wslc/e2e/WSLCE2ENetworkListTests.cpp
Normal file
134
test/windows/wslc/e2e/WSLCE2ENetworkListTests.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
WSLCE2ENetworkListTests.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This file contains end-to-end tests for WSLC.
|
||||
--*/
|
||||
|
||||
#include "precomp.h"
|
||||
#include "windows/Common.h"
|
||||
#include "WSLCExecutor.h"
|
||||
#include "WSLCE2EHelpers.h"
|
||||
|
||||
namespace WSLCE2ETests {
|
||||
using namespace wsl::shared;
|
||||
using namespace wsl::shared::string;
|
||||
|
||||
class WSLCE2ENetworkListTests
|
||||
{
|
||||
WSLC_TEST_CLASS(WSLCE2ENetworkListTests)
|
||||
|
||||
TEST_METHOD_SETUP(MethodSetup)
|
||||
{
|
||||
EnsureNetworkDoesNotExist(TestNetworkName);
|
||||
EnsureNetworkDoesNotExist(TestNetworkName2);
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST_CLASS_CLEANUP(ClassCleanup)
|
||||
{
|
||||
EnsureNetworkDoesNotExist(TestNetworkName);
|
||||
EnsureNetworkDoesNotExist(TestNetworkName2);
|
||||
return true;
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_List_HelpCommand)
|
||||
{
|
||||
auto result = RunWslc(L"network list --help");
|
||||
result.Verify({.Stdout = GetHelpMessage(), .Stderr = L"", .ExitCode = 0});
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_List_InvalidFormatOption)
|
||||
{
|
||||
auto result = RunWslc(L"network list --format invalid");
|
||||
result.Verify({.Stderr = L"Invalid format value: invalid is not a recognized format type. Supported format types are: json, table.\r\n", .ExitCode = 1});
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_List_QuietOption_OutputsNamesOnly)
|
||||
{
|
||||
auto result = RunWslc(std::format(L"network create --driver bridge {}", TestNetworkName));
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
result = RunWslc(std::format(L"network create --driver bridge {}", TestNetworkName2));
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
|
||||
result = RunWslc(L"network list --quiet");
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
|
||||
auto lines = result.GetStdoutLines();
|
||||
VERIFY_ARE_NOT_EQUAL(lines.end(), std::find(lines.begin(), lines.end(), TestNetworkName));
|
||||
VERIFY_ARE_NOT_EQUAL(lines.end(), std::find(lines.begin(), lines.end(), TestNetworkName2));
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_List_JsonFormat)
|
||||
{
|
||||
auto result = RunWslc(std::format(L"network create --driver bridge {}", TestNetworkName));
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
result = RunWslc(std::format(L"network create --driver bridge {}", TestNetworkName2));
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
|
||||
result = RunWslc(L"network list --format json");
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
|
||||
auto networks = FromJson<std::vector<WSLCNetworkInformation>>(result.Stdout.value().c_str());
|
||||
VERIFY_IS_TRUE(networks.size() >= 2U);
|
||||
|
||||
std::vector<std::string> names;
|
||||
names.reserve(networks.size());
|
||||
for (const auto& network : networks)
|
||||
{
|
||||
names.push_back(network.Name);
|
||||
}
|
||||
|
||||
VERIFY_ARE_NOT_EQUAL(names.end(), std::find(names.begin(), names.end(), WideToMultiByte(TestNetworkName)));
|
||||
VERIFY_ARE_NOT_EQUAL(names.end(), std::find(names.begin(), names.end(), WideToMultiByte(TestNetworkName2)));
|
||||
}
|
||||
|
||||
private:
|
||||
const std::wstring TestNetworkName = L"wslc-e2e-network-list";
|
||||
const std::wstring TestNetworkName2 = L"wslc-e2e-network-list-2";
|
||||
|
||||
std::wstring GetHelpMessage() const
|
||||
{
|
||||
std::wstringstream output;
|
||||
output << GetWslcHeader() //
|
||||
<< GetDescription() //
|
||||
<< GetUsage() //
|
||||
<< GetAvailableCommandAliases() //
|
||||
<< GetAvailableOptions();
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::wstring GetDescription() const
|
||||
{
|
||||
return std::format(L"{}\r\n\r\n", Localization::WSLCCLI_NetworkListLongDesc());
|
||||
}
|
||||
|
||||
std::wstring GetUsage() const
|
||||
{
|
||||
return L"Usage: wslc network list [<options>]\r\n\r\n";
|
||||
}
|
||||
|
||||
std::wstring GetAvailableCommandAliases() const
|
||||
{
|
||||
return L"The following command aliases are available: ls\r\n\r\n";
|
||||
}
|
||||
|
||||
std::wstring GetAvailableOptions() const
|
||||
{
|
||||
std::wstringstream options;
|
||||
options << L"The following options are available:\r\n" //
|
||||
<< L" --format Output formatting (json or table) (Default: table)\r\n" //
|
||||
<< L" -q,--quiet Outputs the network names only\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
|
||||
152
test/windows/wslc/e2e/WSLCE2ENetworkRemoveTests.cpp
Normal file
152
test/windows/wslc/e2e/WSLCE2ENetworkRemoveTests.cpp
Normal file
@@ -0,0 +1,152 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
WSLCE2ENetworkRemoveTests.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This file contains end-to-end tests for WSLC.
|
||||
--*/
|
||||
|
||||
#include "precomp.h"
|
||||
#include "windows/Common.h"
|
||||
#include "WSLCExecutor.h"
|
||||
#include "WSLCE2EHelpers.h"
|
||||
|
||||
namespace WSLCE2ETests {
|
||||
using namespace wsl::shared;
|
||||
|
||||
class WSLCE2ENetworkRemoveTests
|
||||
{
|
||||
WSLC_TEST_CLASS(WSLCE2ENetworkRemoveTests)
|
||||
|
||||
TEST_METHOD_SETUP(MethodSetup)
|
||||
{
|
||||
EnsureNetworkDoesNotExist(TestNetworkName);
|
||||
EnsureNetworkDoesNotExist(TestNetworkName2);
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST_CLASS_CLEANUP(ClassCleanup)
|
||||
{
|
||||
EnsureNetworkDoesNotExist(TestNetworkName);
|
||||
EnsureNetworkDoesNotExist(TestNetworkName2);
|
||||
return true;
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_Remove_HelpCommand)
|
||||
{
|
||||
auto result = RunWslc(L"network remove --help");
|
||||
result.Verify({.Stdout = GetHelpMessage(), .Stderr = L"", .ExitCode = 0});
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_Remove_MissingNetworkName)
|
||||
{
|
||||
auto result = RunWslc(L"network remove");
|
||||
result.Verify({.Stdout = GetHelpMessage(), .Stderr = L"Required argument not provided: 'network-name'\r\n", .ExitCode = 1});
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_Remove_Valid)
|
||||
{
|
||||
auto result = RunWslc(std::format(L"network create --driver bridge {}", TestNetworkName));
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
|
||||
VerifyNetworkIsListed(TestNetworkName);
|
||||
|
||||
result = RunWslc(std::format(L"network remove {}", TestNetworkName));
|
||||
result.Verify({.Stdout = std::format(L"{}\r\n", TestNetworkName), .Stderr = L"", .ExitCode = 0});
|
||||
|
||||
VerifyNetworkIsNotListed(TestNetworkName);
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_Remove_Multiple_Valid)
|
||||
{
|
||||
auto result = RunWslc(std::format(L"network create --driver bridge {}", TestNetworkName));
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
result = RunWslc(std::format(L"network create --driver bridge {}", TestNetworkName2));
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
|
||||
VerifyNetworkIsListed(TestNetworkName);
|
||||
VerifyNetworkIsListed(TestNetworkName2);
|
||||
|
||||
result = RunWslc(std::format(L"network remove {} {}", TestNetworkName, TestNetworkName2));
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
|
||||
VerifyNetworkIsNotListed(TestNetworkName);
|
||||
VerifyNetworkIsNotListed(TestNetworkName2);
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_Remove_NotFound)
|
||||
{
|
||||
auto result = RunWslc(std::format(L"network remove {}", TestNetworkName));
|
||||
result.Verify({.Stdout = L"", .Stderr = std::format(L"Network not found: '{}'\r\n", TestNetworkName), .ExitCode = 1});
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_Remove_MixedFoundNotFound)
|
||||
{
|
||||
auto result = RunWslc(std::format(L"network create --driver bridge {}", TestNetworkName));
|
||||
result.Verify({.Stderr = L"", .ExitCode = 0});
|
||||
VerifyNetworkIsListed(TestNetworkName);
|
||||
|
||||
result = RunWslc(std::format(L"network remove {} {}", TestNetworkName, TestNetworkName2));
|
||||
result.Verify(
|
||||
{.Stdout = std::format(L"{}\r\n", TestNetworkName),
|
||||
.Stderr = std::format(L"Network not found: '{}'\r\n", TestNetworkName2),
|
||||
.ExitCode = 1});
|
||||
VerifyNetworkIsNotListed(TestNetworkName);
|
||||
}
|
||||
|
||||
private:
|
||||
const std::wstring TestNetworkName = L"wslc-e2e-network-remove";
|
||||
const std::wstring TestNetworkName2 = L"wslc-e2e-network-remove-2";
|
||||
|
||||
std::wstring GetHelpMessage() const
|
||||
{
|
||||
std::wstringstream output;
|
||||
output << GetWslcHeader() //
|
||||
<< GetDescription() //
|
||||
<< GetUsage() //
|
||||
<< GetAvailableCommandAliases() //
|
||||
<< GetAvailableCommands() //
|
||||
<< GetAvailableOptions();
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::wstring GetDescription() const
|
||||
{
|
||||
return Localization::WSLCCLI_NetworkRemoveLongDesc() + L"\r\n\r\n";
|
||||
}
|
||||
|
||||
std::wstring GetUsage() const
|
||||
{
|
||||
return L"Usage: wslc network remove [<options>] <network-name>\r\n\r\n";
|
||||
}
|
||||
|
||||
std::wstring GetAvailableCommandAliases() const
|
||||
{
|
||||
return L"The following command aliases are available: delete rm\r\n\r\n";
|
||||
}
|
||||
|
||||
std::wstring GetAvailableCommands() const
|
||||
{
|
||||
std::wstringstream commands;
|
||||
commands << L"The following arguments are available:\r\n" //
|
||||
<< L" network-name Network name\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
|
||||
101
test/windows/wslc/e2e/WSLCE2ENetworkTests.cpp
Normal file
101
test/windows/wslc/e2e/WSLCE2ENetworkTests.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
WSLCE2ENetworkTests.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 "Argument.h"
|
||||
|
||||
namespace WSLCE2ETests {
|
||||
using namespace wsl::shared;
|
||||
|
||||
class WSLCE2ENetworkTests
|
||||
{
|
||||
WSLC_TEST_CLASS(WSLCE2ENetworkTests)
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_HelpCommand)
|
||||
{
|
||||
auto result = RunWslc(L"network --help");
|
||||
result.Verify({.Stdout = GetHelpMessage(), .Stderr = L"", .ExitCode = 0});
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_NoSubcommand_ShowsHelp)
|
||||
{
|
||||
auto result = RunWslc(L"network");
|
||||
result.Verify({.Stdout = GetHelpMessage(), .Stderr = L"", .ExitCode = 0});
|
||||
}
|
||||
|
||||
WSLC_TEST_METHOD(WSLCE2E_Network_InvalidCommand_DisplaysErrorMessage)
|
||||
{
|
||||
auto result = RunWslc(L"network INVALID_CMD");
|
||||
result.Verify({.Stdout = GetHelpMessage(), .Stderr = L"Unrecognized command: 'INVALID_CMD'\r\n", .ExitCode = 1});
|
||||
}
|
||||
|
||||
private:
|
||||
std::wstring GetHelpMessage() const
|
||||
{
|
||||
std::wstringstream output;
|
||||
output << GetWslcHeader() //
|
||||
<< GetDescription() //
|
||||
<< GetUsage() //
|
||||
<< GetAvailableCommands() //
|
||||
<< GetAvailableOptions();
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::wstring GetDescription() const
|
||||
{
|
||||
return Localization::WSLCCLI_NetworkCommandLongDesc() + L"\r\n\r\n";
|
||||
}
|
||||
|
||||
std::wstring GetUsage() const
|
||||
{
|
||||
return L"Usage: wslc network [<command>] [<options>]\r\n\r\n";
|
||||
}
|
||||
|
||||
std::wstring GetAvailableCommands() const
|
||||
{
|
||||
std::vector<std::pair<std::wstring_view, std::wstring>> entries = {
|
||||
{L"create", Localization::WSLCCLI_NetworkCreateDesc()},
|
||||
{L"remove", Localization::WSLCCLI_NetworkRemoveDesc()},
|
||||
{L"inspect", Localization::WSLCCLI_NetworkInspectDesc()},
|
||||
{L"list", Localization::WSLCCLI_NetworkListDesc()},
|
||||
};
|
||||
|
||||
size_t maxLen = 0;
|
||||
for (const auto& [name, _] : entries)
|
||||
{
|
||||
maxLen = (std::max)(maxLen, name.size());
|
||||
}
|
||||
|
||||
std::wstringstream commands;
|
||||
commands << Localization::WSLCCLI_AvailableSubcommands() << L"\r\n";
|
||||
for (const auto& [name, desc] : entries)
|
||||
{
|
||||
commands << L" " << name << std::wstring(maxLen - name.size() + 2, L' ') << desc << L"\r\n";
|
||||
}
|
||||
commands << L"\r\n" << Localization::WSLCCLI_HelpForDetails() << L" [" << WSLC_CLI_HELP_ARG_STRING << L"]\r\n\r\n";
|
||||
return commands.str();
|
||||
}
|
||||
|
||||
std::wstring GetAvailableOptions() const
|
||||
{
|
||||
std::wstringstream options;
|
||||
options << L"The following options are available:\r\n"
|
||||
<< L" -?,--help Shows help about the selected command\r\n"
|
||||
<< L"\r\n";
|
||||
return options.str();
|
||||
}
|
||||
};
|
||||
} // namespace WSLCE2ETests
|
||||
Reference in New Issue
Block a user