Init network commands

Co-authored-by: AmelBawa-msft <104940545+AmelBawa-msft@users.noreply.github.com>
This commit is contained in:
AmirMS
2026-04-24 11:15:02 -07:00
committed by GitHub
parent 10dca9a9dd
commit 35ff35f165
24 changed files with 1545 additions and 0 deletions

View File

@@ -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

View File

@@ -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()) \

View 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

View 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

View 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

View 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

View 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

View 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

View File

@@ -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()));

View File

@@ -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>

View 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

View 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

View 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

View 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

View 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