@samitouri / QOSAMI-WSL / commits / 8544b7b0

wslc: alias -f to --format on inspect commands for docker parity (#41463)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

ggarzia-MSFT committed Sep 1, 2026 at 10:31 UTC 8544b7b0b23163df3e05d08c5e822f088328c3d5
4 files changed +56 -1
src/windows/wslc/arguments/ArgumentDefinitions.h
+1 -1
@@ -82,7 +82,7 @@ _(ImageId, "image", NO_ALIAS, Kind::Positional,
82 _(ImportFile, "file", NO_ALIAS, Kind::Positional, NoConversion, Localization::WSLCCLI_ImportFileArgDescription()) \
83 _(IidFile, "iidfile", NO_ALIAS, Kind::Value, NoConversion, Localization::WSLCCLI_IidFileArgDescription()) \
84 _(Input, "input", L"i", Kind::Value, NoConversion, Localization::WSLCCLI_InputArgDescription()) \
85 -_(InspectFormat, "format", NO_ALIAS, Kind::Value, JsonIndent, Localization::WSLCCLI_InspectFormatArgDescription()) \
85 +_(InspectFormat, "format", L"f", Kind::Value, JsonIndent, Localization::WSLCCLI_InspectFormatArgDescription()) \
86 _(Interactive, "interactive", L"i", Kind::Flag, NoConversion, Localization::WSLCCLI_InteractiveArgDescription()) \
87 _(Internal, "internal", NO_ALIAS, Kind::Flag, NoConversion, Localization::WSLCCLI_NetworkInternalArgDescription()) \
88 _(IpAddress, "ip", NO_ALIAS, Kind::Value, NoConversion, Localization::WSLCCLI_IpAddressArgDescription()) \
test/windows/wslc/CommandLineTestCases.h
+16
@@ -199,6 +199,16 @@ COMMAND_LINE_TEST_CASE(L"inspect --format badformat cont1", L"inspect", false)
199 COMMAND_LINE_TEST_CASE(L"container inspect --format json cont1", L"inspect", true)
200 COMMAND_LINE_TEST_CASE(L"container inspect --format table cont1", L"inspect", false)
201 COMMAND_LINE_TEST_CASE(L"container inspect --format badformat cont1", L"inspect", false)
202 +// The inspect family aliases -f to --format, matching `docker inspect -f`. The alias accepts the
203 +// same values as the long name and rejects the same ones.
204 +COMMAND_LINE_TEST_CASE(L"inspect -f json cont1", L"inspect", true)
205 +COMMAND_LINE_TEST_CASE(L"inspect -f=json cont1", L"inspect", true)
206 +COMMAND_LINE_TEST_CASE(L"inspect -f table cont1", L"inspect", false)
207 +COMMAND_LINE_TEST_CASE(L"inspect -f badformat cont1", L"inspect", false)
208 +COMMAND_LINE_TEST_CASE(L"inspect -f", L"inspect", false) // Missing value for -f
209 +COMMAND_LINE_TEST_CASE(L"inspect --type container -f json cont1", L"inspect", true)
210 +COMMAND_LINE_TEST_CASE(L"container inspect -f json cont1", L"inspect", true)
211 +COMMAND_LINE_TEST_CASE(L"container inspect -f table cont1", L"inspect", false)
212 COMMAND_LINE_TEST_CASE(L"remove cont1", L"remove", true)
213 COMMAND_LINE_TEST_CASE(L"container remove cont1 cont2", L"remove", true)
214 COMMAND_LINE_TEST_CASE(L"rm cont1", L"remove", true)
@@ -336,6 +346,12 @@ COMMAND_LINE_TEST_CASE(L"network inspect --format badformat net1", L"inspect", f
346 COMMAND_LINE_TEST_CASE(L"volume inspect --format json vol1", L"inspect", true)
347 COMMAND_LINE_TEST_CASE(L"volume inspect --format table vol1", L"inspect", false)
348 COMMAND_LINE_TEST_CASE(L"volume inspect --format badformat vol1", L"inspect", false)
349 +COMMAND_LINE_TEST_CASE(L"image inspect -f json img1", L"inspect", true)
350 +COMMAND_LINE_TEST_CASE(L"image inspect -f table img1", L"inspect", false)
351 +COMMAND_LINE_TEST_CASE(L"network inspect -f json net1", L"inspect", true)
352 +COMMAND_LINE_TEST_CASE(L"network inspect -f table net1", L"inspect", false)
353 +COMMAND_LINE_TEST_CASE(L"volume inspect -f json vol1", L"inspect", true)
354 +COMMAND_LINE_TEST_CASE(L"volume inspect -f table vol1", L"inspect", false)
355
356 // Version command tests
357 COMMAND_LINE_TEST_CASE(L"version", L"version", true)
test/windows/wslc/WSLCCLICommandUnitTests.cpp
+24
@@ -21,9 +21,13 @@ Abstract:
21 #include "Command.h"
22 #include "RootCommand.h"
23 #include "ContainerCommand.h"
24 +#include "ImageCommand.h"
25 +#include "InspectCommand.h"
26 +#include "NetworkCommand.h"
27 #include "SessionCommand.h"
28 #include "SystemCommand.h"
29 #include "VersionCommand.h"
30 +#include "VolumeCommand.h"
31 #include "EnvironmentOptions.h"
32
33 using namespace wsl::windows::wslc;
@@ -245,6 +249,26 @@ class WSLCCLICommandUnitTests
249 }
250 }
251
252 + // Every command in the inspect family exposes docker's `-f` alias for --format
253 + // (docker/cli cli/command/system/inspect.go: flags.StringVarP(&opts.format, "format", "f", ...)).
254 + TEST_METHOD(InspectCommands_FormatArgumentHasDockerAlias)
255 + {
256 + const auto VerifyFormatAlias = [](const Command& command) {
257 + const auto args = command.GetArguments();
258 + const auto found = std::ranges::find_if(args, [](const auto& arg) { return arg.Type() == ArgType::InspectFormat; });
259 +
260 + VERIFY_IS_TRUE(found != args.end(), std::format(L"Command '{}' does not register --format", command.FullName()).c_str());
261 + VERIFY_ARE_EQUAL(std::wstring(L"format"), found->Name());
262 + VERIFY_ARE_EQUAL(std::wstring(L"f"), found->Alias());
263 + };
264 +
265 + VerifyFormatAlias(InspectCommand(L""));
266 + VerifyFormatAlias(ContainerInspectCommand(L"container"));
267 + VerifyFormatAlias(ImageInspectCommand(L"image"));
268 + VerifyFormatAlias(NetworkInspectCommand(L"network"));
269 + VerifyFormatAlias(VolumeInspectCommand(L"volume"));
270 + }
271 +
272 // Walk every command in the root tree and verify no argument collisions.
273 TEST_METHOD(AllCommands_NoAmbiguousArgumentNamesOrAliases)
274 {
test/windows/wslc/WSLCCLIParserUnitTests.cpp
+15
@@ -661,6 +661,21 @@ class WSLCCLIParserUnitTests
661 VERIFY_ARE_EQUAL(std::wstring(L"true"), args.GetValue<ArgType::ContainerId>());
662 }
663
664 + // A value argument's alias carries its value exactly like the long name, including the
665 + // adjoined form. The inspect family depends on this for docker's `-f json`.
666 + TEST_METHOD(Value_AliasCarriesValue)
667 + {
668 + std::vector<Argument> defs = {Argument::Create(ArgType::InspectFormat), Argument::Create(ArgType::ObjectId, false, Limit::Unlimited)};
669 +
670 + VERIFY_ARE_EQUAL(wsl::shared::c_jsonCompactIndent, ParseFlags(L"wslc -f json cont1", defs).GetValue<ArgType::InspectFormat>());
671 + VERIFY_ARE_EQUAL(wsl::shared::c_jsonCompactIndent, ParseFlags(L"wslc -f=json cont1", defs).GetValue<ArgType::InspectFormat>());
672 +
673 + // The positional still lands where it belongs once the alias has taken its value.
674 + auto args = ParseFlags(L"wslc -f json cont1", defs);
675 + VERIFY_ARE_EQUAL(1u, args.Count(ArgType::ObjectId));
676 + VERIFY_ARE_EQUAL(std::wstring(L"cont1"), args.GetValue<ArgType::ObjectId>());
677 + }
678 +
679 // Alias forms honor adjoined booleans just like the long name.
680 TEST_METHOD(Flag_AliasAdjoinedBoolean)
681 {