master
h 368 lines 8.31 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 ContainerModel.h
8
9 Abstract:
10
11 This file contains the ContainerModel definitions
12
13 --*/
14
15 #pragma once
16
17 #include "MountSpecParsing.h"
18 #include <wslservice.h>
19 #include <wslc.h>
20 #include <optional>
21 #include <string>
22 #include <vector>
23
24 namespace wsl::windows::wslc::models {
25
26 namespace mount = wsl::windows::common::mount;
27
28 // Valid formats for container list output.
29 enum class FormatType
30 {
31 Table,
32 Json,
33 };
34
35 struct ContainerNetwork
36 {
37 std::string Name;
38 std::vector<std::string> Aliases;
39 };
40
41 enum class PullPolicy
42 {
43 Missing,
44 Always,
45 Never,
46 };
47
48 // Progress output style for `wslc build`. Auto resolves to Tty when progress output is an
49 // interactive VT console and Plain otherwise.
50 enum class ProgressMode
51 {
52 Auto,
53 Tty,
54 Plain,
55 Quiet,
56 };
57
58 struct ContainerOptions
59 {
60 std::vector<std::string> Arguments;
61 std::vector<std::string> EnvironmentVariables;
62 bool Detach = false;
63 bool Interactive = false;
64 std::string Name;
65 bool Remove = false;
66 bool TTY = false;
67 bool PublishAll = false;
68 WSLCSignal StopSignal = WSLCSignalNone;
69 std::optional<int> StopTimeout{};
70 std::optional<int64_t> ShmSize{};
71 std::optional<std::string> HealthCmd{};
72 std::optional<int64_t> HealthInterval{}; // nanoseconds
73 std::optional<int64_t> HealthTimeout{}; // nanoseconds
74 std::optional<int64_t> HealthStartPeriod{}; // nanoseconds
75 std::optional<int> HealthRetries{};
76 bool NoHealthcheck = false;
77 bool Gpu = false;
78 std::vector<std::string> Ports;
79 std::vector<mount::Spec> Mounts;
80 std::string WorkingDirectory;
81 std::vector<std::string> Entrypoint;
82 std::optional<std::string> User{};
83 std::optional<std::string> Hostname{};
84 std::optional<std::string> Domainname{};
85 std::vector<std::string> DnsServers;
86 std::vector<std::string> DnsSearchDomains;
87 std::vector<std::string> DnsOptions;
88 std::vector<ContainerNetwork> Networks;
89 std::vector<std::string> NetworkAliases;
90 std::optional<std::string> IpAddress{};
91 std::vector<std::string> Tmpfs;
92 std::vector<std::pair<std::string, std::string>> Labels;
93 std::optional<std::wstring> CidFile{};
94 std::optional<int64_t> MemoryBytes{};
95 std::optional<int64_t> NanoCpus{};
96 std::vector<std::tuple<std::string, int64_t, int64_t>> Ulimits;
97 PullPolicy Pull = PullPolicy::Missing;
98 };
99
100 struct CreateContainerResult
101 {
102 std::string Id;
103 };
104
105 struct StopContainerOptions
106 {
107 WSLCSignal Signal = WSLCSignalNone;
108 LONG Timeout = WSLC_STOP_TIMEOUT_DEFAULT;
109 };
110
111 struct PruneContainersResult
112 {
113 std::vector<std::string> PrunedContainers;
114 ULONGLONG SpaceReclaimed{};
115 };
116
117 struct KillContainerOptions
118 {
119 int Signal = WSLCSignalSIGKILL;
120 };
121
122 struct PortInformation
123 {
124 uint16_t HostPort{};
125 uint16_t ContainerPort{};
126 int Protocol{}; // IP protocol number (e.g., IPPROTO_TCP or IPPROTO_UDP)
127 std::string BindingAddress;
128
129 NLOHMANN_DEFINE_TYPE_INTRUSIVE(PortInformation, HostPort, ContainerPort, Protocol, BindingAddress);
130 };
131
132 struct ContainerInformation
133 {
134 std::string Id;
135 std::string Name;
136 std::string Image;
137 // Command and runtime supplied status description.
138 std::string Command;
139 std::string Status;
140 std::string Labels;
141 std::string Networks;
142 std::string Mounts;
143 ULONG LocalVolumes{};
144 WSLCContainerState State;
145 LONGLONG StateChangedAt{};
146 LONGLONG CreatedAt{};
147 std::vector<PortInformation> Ports;
148 };
149
150 // The platform a container runs on. Emitted as a nested object to match docker.
151 struct ContainerPlatform
152 {
153 std::string architecture;
154 std::string os;
155
156 NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(ContainerPlatform, architecture, os);
157 };
158
159 // The shape emitted by "container list --format json".
160 struct ContainerOutputInformation
161 {
162 std::string Command;
163 std::string CreatedAt;
164 std::string HealthStatus;
165 std::string ID;
166 std::string Image;
167 std::string Labels;
168 std::string LocalVolumes;
169 std::string Mounts;
170 std::string Names;
171 std::string Networks;
172 ContainerPlatform Platform;
173 std::string Ports;
174 std::string RunningFor;
175 std::string Size;
176 std::string State;
177 std::string Status;
178
179 NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
180 ContainerOutputInformation, Command, CreatedAt, HealthStatus, ID, Image, Labels, LocalVolumes, Mounts, Names, Networks, Platform, Ports, RunningFor, Size, State, Status);
181 };
182
183 struct EnvironmentVariable
184 {
185 static std::optional<std::wstring> Parse(const std::wstring& entry);
186 static std::vector<std::wstring> ParseFile(const std::wstring& filePath);
187 };
188
189 struct PublishPort
190 {
191 enum class Protocol
192 {
193 UDP,
194 TCP,
195 };
196
197 struct PortRange
198 {
199 PortRange(uint16_t start, uint16_t end) : m_start(start), m_end(end)
200 {
201 }
202
203 uint16_t Start() const
204 {
205 return m_start;
206 }
207
208 uint16_t End() const
209 {
210 return m_end;
211 }
212
213 constexpr uint16_t Count() const noexcept
214 {
215 return (m_end >= m_start) ? (m_end - m_start + 1) : 0;
216 }
217
218 constexpr bool IsSingle() const noexcept
219 {
220 return Count() == 1;
221 }
222
223 constexpr bool IsValid() const noexcept
224 {
225 return Count() > 0 && IsValidPort(m_start) && IsValidPort(m_end);
226 }
227
228 constexpr bool IsEphemeral() const noexcept
229 {
230 return m_start == WSLC_EPHEMERAL_PORT && m_end == WSLC_EPHEMERAL_PORT;
231 }
232
233 static PublishPort::PortRange ParsePortPart(const std::string& portPart);
234 static PublishPort::PortRange Ephemeral() noexcept
235 {
236 return {WSLC_EPHEMERAL_PORT, WSLC_EPHEMERAL_PORT};
237 }
238
239 private:
240 uint16_t m_start{};
241 uint16_t m_end{};
242 };
243
244 struct IPAddress
245 {
246 explicit IPAddress(std::string ip) : m_ip(std::move(ip))
247 {
248 if (!m_ip.empty() && m_ip.front() == '[' && m_ip.back() == ']')
249 {
250 m_isIPv6 = true;
251 m_ip = m_ip.substr(1, m_ip.size() - 2);
252 }
253 }
254
255 std::string IP() const
256 {
257 return m_ip;
258 }
259
260 bool IsIPv6() const
261 {
262 return m_isIPv6;
263 }
264
265 private:
266 bool m_isIPv6 = false;
267 std::string m_ip{};
268 };
269
270 static constexpr uint16_t MAX_PORT = std::numeric_limits<uint16_t>::max();
271 static constexpr uint16_t MIN_PORT = 1;
272
273 std::optional<IPAddress> HostIP() const noexcept
274 {
275 return m_hostIP;
276 }
277
278 PortRange HostPort() const noexcept
279 {
280 return m_hostPort;
281 }
282
283 PortRange ContainerPort() const noexcept
284 {
285 return m_containerPort;
286 }
287
288 Protocol PortProtocol() const noexcept
289 {
290 return m_protocol;
291 }
292
293 std::string Original() const noexcept
294 {
295 return m_original;
296 }
297
298 bool IsRangeMapping() const noexcept
299 {
300 return !m_containerPort.IsSingle();
301 }
302
303 static PublishPort Parse(const std::string& value);
304
305 private:
306 std::optional<IPAddress> m_hostIP;
307 PortRange m_hostPort = PortRange::Ephemeral();
308 PortRange m_containerPort = PortRange::Ephemeral();
309 Protocol m_protocol = Protocol::TCP;
310 std::string m_original;
311 void Validate() const;
312 PublishPort() = default;
313 static constexpr bool IsValidPort(unsigned long port) noexcept
314 {
315 return port >= MIN_PORT && port <= MAX_PORT;
316 }
317 };
318
319 struct VolumeMount
320 {
321 std::wstring Host() const
322 {
323 return m_host;
324 }
325
326 std::string ContainerPath() const
327 {
328 return m_containerPath;
329 }
330
331 bool IsReadOnly() const
332 {
333 return m_isReadOnlyMode;
334 }
335
336 bool IsNamedVolume() const
337 {
338 return m_isNamedVolume;
339 }
340
341 static bool IsValidNamedVolumeName(const std::wstring& name);
342
343 static VolumeMount Parse(const std::wstring& value);
344
345 private:
346 std::wstring m_host;
347 std::string m_containerPath;
348 bool m_isReadOnlyMode = false;
349 bool m_isNamedVolume = false;
350 };
351
352 class CidFile
353 {
354 public:
355 explicit CidFile(const std::optional<std::wstring>& path);
356 ~CidFile();
357
358 NON_COPYABLE(CidFile);
359 NON_MOVABLE(CidFile);
360
361 void Commit(const std::string& containerId);
362
363 private:
364 std::optional<std::wstring> m_path{};
365 wil::unique_hfile m_file;
366 bool m_committed = false;
367 };
368 } // namespace wsl::windows::wslc::models