master
cpp 132 lines 4.5 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 InspectTasks.cpp
8
9 Abstract:
10
11 Implementation of inspection command related execution logic.
12 --*/
13
14 #include "Argument.h"
15 #include "ArgumentConvertedTypes.h"
16 #include "InspectTasks.h"
17 #include "InspectModel.h"
18 #include "ImageService.h"
19 #include "NetworkService.h"
20 #include "VolumeService.h"
21 #include "ContainerService.h"
22
23 namespace wsl::windows::wslc::task {
24
25 using namespace wsl::shared;
26 using namespace wsl::windows::common;
27 using namespace wsl::windows::common::string;
28 using namespace wsl::windows::common::wslutil;
29 using namespace wsl::windows::wslc::models;
30
31 template <typename TInspectFn>
32 static bool TryInspect(TInspectFn&& fn, HRESULT notFoundError)
33 {
34 try
35 {
36 fn();
37 return true;
38 }
39 catch (const wil::ResultException& ex)
40 {
41 auto errorCode = ex.GetErrorCode();
42 if (errorCode == notFoundError || errorCode == HRESULT_FROM_WIN32(ERROR_BAD_ARGUMENTS) || errorCode == E_INVALIDARG)
43 {
44 return false;
45 }
46
47 throw;
48 }
49 }
50
51 static bool TryInspectImage(wsl::windows::wslc::models::Session& session, const std::string& image, std::optional<wslc_schema::InspectImage>& result)
52 {
53 return TryInspect([&]() { result = services::ImageService::Inspect(session, image); }, WSLC_E_IMAGE_NOT_FOUND);
54 }
55
56 static bool TryInspectContainer(
57 wsl::windows::wslc::models::Session& session, const std::string& containerId, std::optional<wslc_schema::InspectContainer>& result, bool size)
58 {
59 return TryInspect([&]() { result = services::ContainerService::Inspect(session, containerId, size); }, WSLC_E_CONTAINER_NOT_FOUND);
60 }
61
62 static bool TryInspectNetwork(wsl::windows::wslc::models::Session& session, const std::string& networkName, std::optional<wslc_schema::Network>& result)
63 {
64 return TryInspect([&]() { result = services::NetworkService::Inspect(session, networkName); }, WSLC_E_NETWORK_NOT_FOUND);
65 }
66
67 static bool TryInspectVolume(wsl::windows::wslc::models::Session& session, const std::string& volumeId, std::optional<wslc_schema::InspectVolume>& result)
68 {
69 return TryInspect([&]() { result = services::VolumeService::Inspect(session, volumeId); }, WSLC_E_VOLUME_NOT_FOUND);
70 }
71
72 void Inspect(CLIExecutionContext& context)
73 {
74 WI_ASSERT(context.Data.Contains(Data::Session));
75 auto& session = context.Data.Get<Data::Session>();
76 auto objectIds = context.Args.GetAllValues<ArgType::ObjectId>();
77
78 nlohmann::json array = nlohmann::json::array();
79 auto type = InspectType::All;
80 if (context.Args.Contains(ArgType::Type))
81 {
82 type = context.Args.GetValue<ArgType::Type>();
83 }
84
85 const bool size = context.Args.GetValue<ArgType::Size>();
86
87 // Only containers carry file size information; every other type warns and continues.
88 const auto warnSizeIgnored = [&](const wchar_t* objectType) {
89 if (size)
90 {
91 context.Terminal.Error(L"{}\n", Localization::WSLCCLI_InspectSizeIgnoredWarning(objectType));
92 }
93 };
94
95 for (const auto& objectId : objectIds)
96 {
97 auto id = WideToMultiByte(objectId);
98 std::optional<wslc_schema::InspectContainer> container;
99 std::optional<wslc_schema::InspectImage> image;
100 std::optional<wslc_schema::Network> network;
101 std::optional<wslc_schema::InspectVolume> volume;
102
103 if (WI_IsFlagSet(type, InspectType::Container) && TryInspectContainer(session, id, container, size))
104 {
105 array.push_back(wslc_schema::ToInspectJson(*container));
106 }
107 else if (WI_IsFlagSet(type, InspectType::Image) && TryInspectImage(session, id, image))
108 {
109 warnSizeIgnored(L"image");
110 array.push_back(std::move(*image));
111 }
112 else if (WI_IsFlagSet(type, InspectType::Network) && TryInspectNetwork(session, id, network))
113 {
114 warnSizeIgnored(L"network");
115 array.push_back(std::move(*network));
116 }
117 else if (WI_IsFlagSet(type, InspectType::Volume) && TryInspectVolume(session, id, volume))
118 {
119 warnSizeIgnored(L"volume");
120 array.push_back(std::move(*volume));
121 }
122 else
123 {
124 context.Terminal.Error(L"{}\n", Localization::WSLCCLI_ObjectNotFoundError(objectId));
125 context.ExitCode = 1;
126 }
127 }
128
129 // Always print the array, even if it's empty or an error was encountered
130 context.Terminal.Output(L"{}\n", MultiByteToWide(array.dump(context.Args.GetValue<ArgType::InspectFormat>(c_jsonPrettyPrintIndent))));
131 }
132 } // namespace wsl::windows::wslc::task