Fix misalignments with network list and docker (#41350)

David Bennett committed Aug 13, 2026 at 14:59 UTC d92d4a1976711331198c50ca6a4bf796653076dc
5 files changed +85 -18
localization/strings/en-US/Resources.resw
+1 -1
@@ -3405,7 +3405,7 @@ On first run, creates the file with all settings commented out at their defaults
3405 <value>Network name</value>
3406 </data>
3407 <data name="WSLCCLI_NetworkListQuietArgDesc" xml:space="preserve">
3408 - <value>Outputs the network names only</value>
3408 + <value>Only display network IDs</value>
3409 </data>
3410 <data name="WSLCCLI_NetworkPruneDesc" xml:space="preserve">
3411 <value>Remove all unused networks.</value>
src/shared/inc/JsonUtils.h
+2 -2
@@ -209,13 +209,13 @@ struct adl_serializer<WSLCNetworkInformation>
209 {
210 static void to_json(json& j, const WSLCNetworkInformation& network)
211 {
212 - j = json{{"Name", std::string(network.Name)}, {"Id", std::string(network.Id)}, {"Driver", std::string(network.Driver)}};
212 + j = json{{"Name", std::string(network.Name)}, {"ID", std::string(network.Id)}, {"Driver", std::string(network.Driver)}};
213 }
214
215 static void from_json(const json& j, WSLCNetworkInformation& network)
216 {
217 std::string name = j.at("Name").get<std::string>();
218 - std::string id = j.at("Id").get<std::string>();
218 + std::string id = j.at("ID").get<std::string>();
219 std::string driver = j.at("Driver").get<std::string>();
220
221 strncpy_s(network.Name, sizeof(network.Name), name.c_str(), _TRUNCATE);
src/windows/wslc/commands/NetworkListCommand.cpp
+1
@@ -28,6 +28,7 @@ std::vector<Argument> NetworkListCommand::GetArguments() const
28 {
29 return {
30 Argument::Create(ArgType::Format),
31 + Argument::Create(ArgType::NoTrunc),
32 Argument::Create(ArgType::Quiet, false, std::nullopt, Localization::WSLCCLI_NetworkListQuietArgDesc()),
33 };
34 }
src/windows/wslc/tasks/NetworkTasks.cpp
+9 -6
@@ -170,25 +170,28 @@ void ListNetworks(CLIExecutionContext& context)
170 WI_ASSERT(context.Data.Contains(Data::Networks));
171 auto& networks = context.Data.Get<Data::Networks>();
172
173 - if (context.Args.GetValue<ArgType::Quiet>())
173 + const auto format = context.Args.GetValue<ArgType::Format>(FormatType::Table);
174 + const bool quiet = context.Args.GetValue<ArgType::Quiet>();
175 + const bool trunc = !context.Args.GetValue<ArgType::NoTrunc>();
176 + if (format == FormatType::Table && quiet)
177 {
178 for (const auto& network : networks)
179 {
177 - context.Terminal.Output(L"{}\n", MultiByteToWide(network.Name));
180 + context.Terminal.Output(L"{}\n", MultiByteToWide(TruncateId(network.Id, trunc)));
181 }
182
183 return;
184 }
185
183 - const auto format = context.Args.GetValue<ArgType::Format>(FormatType::Table);
184 -
186 switch (format)
187 {
188 case FormatType::Json:
189 {
190 for (const auto& network : networks)
191 {
191 - context.Terminal.Output(L"{}\n", ToJsonW(network, c_jsonCompactIndent));
192 + auto json = nlohmann::json(network);
193 + json["ID"] = TruncateId(network.Id, trunc);
194 + context.Terminal.Output(L"{}\n", ToJsonW(json, c_jsonCompactIndent));
195 }
196
197 break;
@@ -199,7 +202,7 @@ void ListNetworks(CLIExecutionContext& context)
202 for (const auto& network : networks)
203 {
204 table.WriteRow({
202 - MultiByteToWide(TruncateId(network.Id)),
205 + MultiByteToWide(TruncateId(network.Id, trunc)),
206 MultiByteToWide(network.Name),
207 MultiByteToWide(network.Driver),
208 });
test/windows/wslc/e2e/WSLCE2ENetworkListTests.cpp
+72 -9
@@ -53,19 +53,55 @@ class WSLCE2ENetworkListTests
53 L"Invalid format value: invalid is not a recognized format type. Supported format types are: json, table."));
54 }
55
56 - WSLC_TEST_METHOD(WSLCE2E_Network_List_QuietOption_OutputsNamesOnly)
56 + WSLC_TEST_METHOD(WSLCE2E_Network_List_QuietOption_OutputsIdsOnly)
57 {
58 auto result = RunWslc(std::format(L"network create --driver bridge {}", TestNetworkName));
59 result.Verify({.Stderr = L"", .ExitCode = 0});
60 result = RunWslc(std::format(L"network create --driver bridge {}", TestNetworkName2));
61 result.Verify({.Stderr = L"", .ExitCode = 0});
62
63 + result = RunWslc(L"network list --format json");
64 + result.Verify({.Stderr = L"", .ExitCode = 0});
65 +
66 + std::vector<std::wstring> expectedIds;
67 + for (const auto& network : ParseNdjsonOutput(result))
68 + {
69 + expectedIds.push_back(MultiByteToWide(network.at("ID").get<std::string>()));
70 + }
71 +
72 result = RunWslc(L"network list --quiet");
73 result.Verify({.Stderr = L"", .ExitCode = 0});
74
75 auto lines = result.GetStdoutLines();
67 - VERIFY_ARE_NOT_EQUAL(lines.end(), std::find(lines.begin(), lines.end(), TestNetworkName));
68 - VERIFY_ARE_NOT_EQUAL(lines.end(), std::find(lines.begin(), lines.end(), TestNetworkName2));
76 + VERIFY_ARE_EQUAL(expectedIds.size(), lines.size());
77 + for (const auto& id : expectedIds)
78 + {
79 + VerifyIdOutput(id, true);
80 + VERIFY_ARE_NOT_EQUAL(lines.end(), std::find(lines.begin(), lines.end(), id));
81 + }
82 +
83 + VERIFY_ARE_EQUAL(lines.end(), std::find(lines.begin(), lines.end(), TestNetworkName));
84 + VERIFY_ARE_EQUAL(lines.end(), std::find(lines.begin(), lines.end(), TestNetworkName2));
85 +
86 + result = RunWslc(L"network list --format json --no-trunc");
87 + result.Verify({.Stderr = L"", .ExitCode = 0});
88 +
89 + expectedIds.clear();
90 + for (const auto& network : ParseNdjsonOutput(result))
91 + {
92 + expectedIds.push_back(MultiByteToWide(network.at("ID").get<std::string>()));
93 + }
94 +
95 + result = RunWslc(L"network list --quiet --no-trunc");
96 + result.Verify({.Stderr = L"", .ExitCode = 0});
97 +
98 + lines = result.GetStdoutLines();
99 + VERIFY_ARE_EQUAL(expectedIds.size(), lines.size());
100 + for (const auto& id : expectedIds)
101 + {
102 + VerifyIdOutput(id, false);
103 + VERIFY_ARE_NOT_EQUAL(lines.end(), std::find(lines.begin(), lines.end(), id));
104 + }
105 }
106
107 WSLC_TEST_METHOD(WSLCE2E_Network_List_JsonFormat)
@@ -77,19 +113,46 @@ class WSLCE2ENetworkListTests
113
114 result = RunWslc(L"network list --format json");
115 result.Verify({.Stderr = L"", .ExitCode = 0});
80 -
81 - auto networks = ParseNdjsonOutputAs<WSLCNetworkInformation>(result);
82 - VERIFY_ARE_EQUAL(2U, networks.size());
116 + auto networks = ParseNdjsonOutput(result);
117
118 std::vector<std::string> names;
119 names.reserve(networks.size());
120 for (const auto& network : networks)
121 {
88 - names.push_back(network.Name);
122 + VERIFY_ARE_EQUAL(3u, network.size());
123 + VERIFY_IS_TRUE(network.contains("ID"));
124 + VERIFY_IS_FALSE(network.contains("Id"));
125 + VERIFY_IS_TRUE(network.contains("Name"));
126 + VERIFY_IS_TRUE(network.contains("Driver"));
127 + VerifyIdOutput(MultiByteToWide(network.at("ID").get<std::string>()), true);
128 + names.push_back(network.at("Name").get<std::string>());
129 + }
130 +
131 + VERIFY_ARE_EQUAL(1u, static_cast<size_t>(std::count(names.begin(), names.end(), WideToMultiByte(TestNetworkName))));
132 + VERIFY_ARE_EQUAL(1u, static_cast<size_t>(std::count(names.begin(), names.end(), WideToMultiByte(TestNetworkName2))));
133 +
134 + auto quietResult = RunWslc(L"network list --format json --quiet");
135 + quietResult.Verify({.Stderr = L"", .ExitCode = 0});
136 + VERIFY_ARE_EQUAL(result.Stdout.value(), quietResult.Stdout.value());
137 +
138 + auto fullResult = RunWslc(L"network list --format json --no-trunc");
139 + fullResult.Verify({.Stderr = L"", .ExitCode = 0});
140 + for (const auto& network : ParseNdjsonOutput(fullResult))
141 + {
142 + VerifyIdOutput(MultiByteToWide(network.at("ID").get<std::string>()), false);
143 }
144
91 - VERIFY_ARE_NOT_EQUAL(names.end(), std::find(names.begin(), names.end(), WideToMultiByte(TestNetworkName)));
92 - VERIFY_ARE_NOT_EQUAL(names.end(), std::find(names.begin(), names.end(), WideToMultiByte(TestNetworkName2)));
145 + auto fullQuietResult = RunWslc(L"network list --format json --quiet --no-trunc");
146 + fullQuietResult.Verify({.Stderr = L"", .ExitCode = 0});
147 + VERIFY_ARE_EQUAL(fullResult.Stdout.value(), fullQuietResult.Stdout.value());
148 +
149 + auto fullTableResult = RunWslc(L"network list --no-trunc");
150 + fullTableResult.Verify({.Stderr = L"", .ExitCode = 0});
151 + for (const auto& network : ParseNdjsonOutput(fullResult))
152 + {
153 + const auto id = MultiByteToWide(network.at("ID").get<std::string>());
154 + VERIFY_IS_TRUE(fullTableResult.StdoutContainsSubstring(id));
155 + }
156 }
157
158 private: