Compare commits
4719 commits
Author | SHA1 | Date | |
---|---|---|---|
|
801fd16e3e | ||
|
6667e96dad | ||
|
ee8b788538 | ||
|
96c9353e9b | ||
|
ab570ab3d6 | ||
|
7532420f3b | ||
|
a4d5b6b4d0 | ||
|
e829cca0ee | ||
|
82d8f8d6e6 | ||
|
6c68be24a2 | ||
|
b7c059886c | ||
|
745e2356ab | ||
|
29f24a828b | ||
|
0d6a1a212b | ||
|
f5209d23a8 | ||
|
442f29a699 | ||
|
f07644e17e | ||
|
d3c051318f | ||
|
5368c3a04f | ||
|
8d5d655db0 | ||
|
f51e18f58e | ||
|
57dd56726a | ||
|
f9dfd139ec | ||
|
051d587447 | ||
|
9954d7c6bd | ||
|
cd7240f6d9 | ||
|
17b8631545 | ||
|
8383c487c6 | ||
|
7a54a16740 | ||
|
2fabb28813 | ||
|
5ae5969739 | ||
|
3485cfbb1e | ||
|
3b81ca4969 | ||
|
80572929e1 | ||
|
fb92caf2aa | ||
|
61269e718f | ||
|
d25b0bd7ea | ||
|
d8b768149b | ||
|
6d30487d2e | ||
|
329d403e20 | ||
|
d66589496e | ||
|
e1ca74361b | ||
|
cf933115b6 | ||
|
9fa76786ab | ||
|
9160b9fda6 | ||
|
8599f2a3fb | ||
|
0a48d26fbc | ||
|
330a6f959f | ||
|
c4689034fd | ||
|
4eed3dcdfe | ||
|
c187f95fe1 | ||
|
a33b302d54 | ||
|
484480f56a | ||
|
aff003139c | ||
|
1014f481de | ||
|
d57b899904 | ||
|
fde80fe2e7 | ||
|
bfdb8918f9 | ||
|
83ae9927fb | ||
|
14a8fac092 | ||
|
59c5059081 | ||
|
1552e30a05 | ||
|
c64314fd55 | ||
|
61e2199b78 | ||
|
ea72f9f72c | ||
|
8b79278316 | ||
|
22726fb63b | ||
|
963e1f3eed | ||
|
3312b82515 | ||
|
ad8a5a5732 | ||
|
0c2d83b5fb | ||
|
f696e0d2a7 | ||
|
330d777c53 | ||
|
3d2a56e7cf | ||
|
4531a371f2 | ||
|
731a64069f | ||
|
dade279565 | ||
|
23e1af45c6 | ||
|
e7c60a30e6 | ||
|
641e341eed | ||
|
dd146571ea | ||
|
fe70ee9477 | ||
|
307962dbd5 | ||
|
7e56442cee | ||
|
ebf300c165 | ||
|
2e4ebf032a | ||
|
153de36b3f | ||
|
4ff655f4b8 | ||
|
1c03312378 | ||
|
f512dba037 | ||
|
89dc2860ba | ||
|
6f3892dc99 | ||
|
a9bca45e92 | ||
|
fe8fb9b9a1 | ||
|
70e46f2c7c | ||
|
23339a6147 | ||
|
4bd30829d1 | ||
|
971562b005 | ||
|
d742659877 | ||
|
4f46c44725 | ||
|
1f539a6e85 | ||
|
959c2ee6cf | ||
|
25c9e6e8df | ||
|
762ec4b60c | ||
|
979f03f9f6 | ||
|
7b414f5703 | ||
|
ff05850e7e | ||
|
cdf70c0a51 | ||
|
40c681355e | ||
|
790c3039d0 | ||
|
10bdc7136c | ||
|
a8abb67c5e | ||
|
1ca89d7eae | ||
|
f40bdf5f63 | ||
|
3f73d23ea0 | ||
|
77b05b97f4 | ||
|
e3bc82f7d4 | ||
|
342923b01c | ||
|
15122b3b1c | ||
|
388ecf65bc | ||
|
bb3ab1edb7 | ||
|
da245cab15 | ||
|
1cfd763214 | ||
|
0ce714a085 | ||
|
bcb4794eea | ||
|
0d5ef431a1 | ||
|
03cddc62f4 | ||
|
825635a5bf | ||
|
ec19fd6fed | ||
|
d19f6d4b6d | ||
|
b8165a9cd1 | ||
|
a6a445d86b | ||
|
0fb845858d | ||
|
db2263749b | ||
|
1abf17c779 | ||
|
294fc9762e | ||
|
eef352b565 | ||
|
f4c696eef1 | ||
|
5a009cdd5b | ||
|
2f1a32e3e5 | ||
|
72f1f82f28 | ||
|
52a80b40e2 | ||
|
288a14e264 | ||
|
b37ced2551 | ||
|
a535a65c4b | ||
|
582de4bc3c | ||
|
a6e7e67d3a | ||
|
1b108bdfeb | ||
|
74e2f23e1a | ||
|
e8496b1ee4 | ||
|
d66177591e | ||
|
bf30fee58a | ||
|
608d77d740 | ||
|
66adfc729a | ||
|
ab4b5a4890 | ||
|
f5a5e3f203 | ||
|
773f792b88 | ||
|
4adc40ac40 | ||
|
8921897e3b | ||
|
37545cc644 | ||
|
6c10086976 | ||
|
ef5295cda4 | ||
|
49b77753cb | ||
|
d91665a2ac | ||
|
4e53936f0a | ||
|
cb8c8e9631 | ||
|
c4fc6c3371 | ||
|
0f30791a0d | ||
|
4e8d9a4522 | ||
|
7c7e453255 | ||
|
06628e383a | ||
|
4046928978 | ||
|
21835a5696 | ||
|
b32cfc3b3a | ||
|
49fd8df9b9 | ||
|
72ec187dfe | ||
|
83cda67f73 | ||
|
460b4aebdf | ||
|
57b7ffa7f6 | ||
|
cadb124ab6 | ||
|
046827c657 | ||
|
04c9d7f6a3 | ||
|
b2921509e5 | ||
|
f04f69e366 | ||
|
7f69142aa0 | ||
|
97a5435d33 | ||
|
91d9307738 | ||
|
12dea3fa9e | ||
|
137a9d6a4c | ||
|
9f4e824a6e | ||
|
f8e6801533 | ||
|
ef681124ca | ||
|
7ebd88d2d9 | ||
|
4f30a930ad | ||
|
a580544d82 | ||
|
b8aa8579ca | ||
|
225ccc0cfd | ||
|
d19d98b136 | ||
|
ebf3f8c7fe | ||
|
a242208be3 | ||
|
2af2496c8c | ||
|
fc0e5401f2 | ||
|
8517c3386c | ||
|
6c3b3523c9 | ||
|
d40b140c08 | ||
|
81428bf11b | ||
|
230cb53d3b | ||
|
7b0ab1011c | ||
|
3ca1d751e5 | ||
|
589dc5e647 | ||
|
62b33a2604 | ||
|
5fe96e234d | ||
|
84eecc4a30 | ||
|
261dccc98a | ||
|
2c9c5e1c03 | ||
|
b649e272bb | ||
|
e4de4dea5c | ||
|
b37f8c8070 | ||
|
9be820d8ca | ||
|
f6fa6ff9ed | ||
|
220835106b | ||
|
2c25ca9dba | ||
|
94f9f39b24 | ||
|
da643c0b8a | ||
|
9083c2f10d | ||
|
44167988c3 | ||
|
2d31532a00 | ||
|
60358bfcab | ||
|
f5722da5e0 | ||
|
951e42cd60 | ||
|
e01a1c5d09 | ||
|
fa467caf4d | ||
|
59ad1690f7 | ||
|
b04a2dad6b | ||
|
bc6d88c09a | ||
|
a79bb1e832 | ||
|
e68f71259a | ||
|
dd6992617e | ||
|
31545c3b67 | ||
|
f90b03ee5d | ||
|
16aa7dd67f | ||
|
8cdb5a9070 | ||
|
ffd294ebcc | ||
|
881260148f | ||
|
432390320e | ||
|
c70d7905fb | ||
|
0eecd59153 | ||
|
6aea26b431 | ||
|
913478b428 | ||
|
901b90593d | ||
|
349abc64ed | ||
|
24fe934a7b | ||
|
05b883bdc8 | ||
|
c516804d6f | ||
|
445d500aeb | ||
|
1ffaf469ba | ||
|
842d1b3c12 | ||
|
83c02f7a11 | ||
|
14df52b709 | ||
|
ff5f780f2b | ||
|
5689dabfb3 | ||
|
7d081179e9 | ||
|
3865c63d45 | ||
|
1d473549e8 | ||
|
b2aaf5c2b0 | ||
|
cbd45e83cf | ||
|
cba87125b2 | ||
|
2a41ce93fe | ||
|
c42ae61e62 | ||
|
d9e082ff54 | ||
|
8761bffcaf | ||
|
56aeb548b2 | ||
|
38827ba290 | ||
|
9d1541526c | ||
|
7bf8d2606e | ||
|
bf053be997 | ||
|
101241c804 | ||
|
bddd892e91 | ||
|
2aa13e950d | ||
|
70a4a9c969 | ||
|
a0f12f96eb | ||
|
3d354593c9 | ||
|
9faf4855d5 | ||
|
4eb95d01bc | ||
|
7c2975d2df | ||
|
903412d0fc | ||
|
b8a71a1c44 | ||
|
443f56efb0 | ||
|
b4fbe226e8 | ||
|
5bcd2f6860 | ||
|
999f90ac1c | ||
|
a60546b084 | ||
|
ef7766304c | ||
|
6932939326 | ||
|
10a72f2504 | ||
|
a60fef0c41 | ||
|
86b86412a1 | ||
|
03a17a2887 | ||
|
a26c953b94 | ||
|
571af915d5 | ||
|
97478c99f8 | ||
|
b71c2792d2 | ||
|
57e8352c9e | ||
|
4ab11a1148 | ||
|
23d80f729e | ||
|
419f5a6372 | ||
|
475019d70a | ||
|
63c354aae2 | ||
|
9e075f3808 | ||
|
beb97f7fdf | ||
|
d2f12e6d51 | ||
|
14503ccebd | ||
|
e1897cbde4 | ||
|
0fef6e1c99 | ||
|
6b01719ffb | ||
|
19a04efa2f | ||
|
8758d08bb4 | ||
|
ffd877f948 | ||
|
b3a0ff9944 | ||
|
83f790cccc | ||
|
d1974aa492 | ||
|
ed93110e11 | ||
|
570d5a9645 | ||
|
f0dd554e3c | ||
|
dfdf2adf0c | ||
|
2970b320aa | ||
|
ef25f0aa52 | ||
|
7fa116830b | ||
|
1b1147e46b | ||
|
d26bdfe226 | ||
|
f1e6958295 | ||
|
27ac2beca0 | ||
|
9e10605e77 | ||
|
2c01d53d96 | ||
|
d69729e053 | ||
|
10d344d176 | ||
|
df57a080b6 | ||
|
8826f402f9 | ||
|
6f242f1a28 | ||
|
4d0d5ee10d | ||
|
1251982cf7 | ||
|
203ffb1c09 | ||
|
cae5d323e1 | ||
|
7f1b700227 | ||
|
f1730a6512 | ||
|
f7192bb0b4 | ||
|
2156635843 | ||
|
91ea04089b | ||
|
2ef0b53e51 | ||
|
6b83319773 | ||
|
ee3c710f22 | ||
|
74d51e8553 | ||
|
e910a79e2b | ||
|
9fcea5b933 | ||
|
e61c425cc2 | ||
|
10d6f5213a | ||
|
9c92c07acf | ||
|
0616b4190e | ||
|
89470a7114 | ||
|
701dd989f1 | ||
|
7c4828f8fb | ||
|
7964cae9e8 | ||
|
e37172c613 | ||
|
c59e93a67b | ||
|
83af50aee3 | ||
|
4d7c11c208 | ||
|
8070a9aa66 | ||
|
ca683c1c77 | ||
|
025967efd0 | ||
|
add2c4c79b | ||
|
8604cc400d | ||
|
e240ba44b7 | ||
|
82dda18898 | ||
|
dd20bf4862 | ||
|
f5cf22ca99 | ||
|
0c3b8ccda7 | ||
|
810ef4d0b6 | ||
|
2cc627932a | ||
|
968f05910a | ||
|
8c64b85fb9 | ||
|
dae33031e0 | ||
|
a2026ee442 | ||
|
5a3c463a37 | ||
|
9babc02283 | ||
|
a83557d747 | ||
|
2200c0137f | ||
|
d21d0884ae | ||
|
3e230cfdcc | ||
|
f42b8ae8db | ||
|
7a920fd275 | ||
|
584e60e820 | ||
|
8ee908e47c | ||
|
835cdcac95 | ||
|
f4a93b6993 | ||
|
b20dccba5e | ||
|
44bf407d4d | ||
|
8a81b9d35f | ||
|
ecb217cf69 | ||
|
2df4755725 | ||
|
3a8191225a | ||
|
08251978a8 | ||
|
5d396e0533 | ||
|
4a1839ef1d | ||
|
b7fd571b0a | ||
|
00a2626b56 | ||
|
e27a785f43 | ||
|
fb53ee6ba3 | ||
|
0ffddc6bb8 | ||
|
987fe37ed1 | ||
|
d53b7d7e46 | ||
|
39c5c16521 | ||
|
5792bf7ab3 | ||
|
982e777d49 | ||
|
f472dda2e9 | ||
|
ca40ac030c | ||
|
0818a476e5 | ||
|
a0b53f6fd2 | ||
|
2ddec74d59 | ||
|
794f7127ef | ||
|
5e13f54f57 | ||
|
d131f00fff | ||
|
7d4ee14147 | ||
|
0f507ef624 | ||
|
21136865ac | ||
|
a8e8a4cdad | ||
|
6ee58c2d29 | ||
|
905477c8ae | ||
|
d70fe8803c | ||
|
e94ec8068d | ||
|
71bfffdad1 | ||
|
931568032a | ||
|
ee6cbc540e | ||
|
6d34bb71a0 | ||
|
388ba9a69c | ||
|
3eb1527fdb | ||
|
93861bb5e6 | ||
|
7f94acb6ab | ||
|
97a5614d23 | ||
|
5c2eda6f71 | ||
|
96d461d27e | ||
|
877ebbe038 | ||
|
96ac22768a | ||
|
c6156dc51b | ||
|
537348763f | ||
|
c7b3cb101b | ||
|
69d2923e4e | ||
|
86198815a2 | ||
|
d864df5a1d | ||
|
bd4ff31775 | ||
|
e245fb76de | ||
|
3147a013fb | ||
|
f7ef0e9fc7 | ||
|
e8346c53d9 | ||
|
3a617e5463 | ||
|
43ffb1ee9d | ||
|
115c7673dc | ||
|
f7e2357745 | ||
|
314ea05f8d | ||
|
13f46948dd | ||
|
4b09bc2145 | ||
|
49637d0206 | ||
|
eccb1a3eb8 | ||
|
0b1921649f | ||
|
4544bedea3 | ||
|
6f44138269 | ||
|
9a41cc58d9 | ||
|
ac2a028dcc | ||
|
8906adc8d4 | ||
|
0bb84f5cef | ||
|
80c44b4b2e | ||
|
2da96d6c12 | ||
|
0b64499a24 | ||
|
9763709c05 | ||
|
250886741b | ||
|
f4beb130b0 | ||
|
df43311f3d | ||
|
9f37672ca8 | ||
|
c25773ecbf | ||
|
f19f233ca5 | ||
|
ca67dbd12c | ||
|
cac52f7173 | ||
|
00c9785e2e | ||
|
0d51cf9db8 | ||
|
1786517338 | ||
|
22a504935f | ||
|
05d952b246 | ||
|
d86d24de35 | ||
|
20bd690844 | ||
|
34668a5945 | ||
|
1090aaaedd | ||
|
c482383458 | ||
|
43bf65c174 | ||
|
a3a42c459e | ||
|
c87e0ad209 | ||
|
cd53b7380c | ||
|
fb19f1fc20 | ||
|
3602ba0afd | ||
|
f0eef50273 | ||
|
b6a5c2968b | ||
|
6100190e5c | ||
|
17fd6562bf | ||
|
4979605212 | ||
|
fcc651972e | ||
|
42a07883f7 | ||
|
5a3a101af2 | ||
|
6803dd8c90 | ||
|
82acb922cb | ||
|
e5dbe10e65 | ||
|
8528ed3409 | ||
|
570b8a794c | ||
|
5ad5334c2e | ||
|
417826376f | ||
|
e30610aaa3 | ||
|
a0466ca8e1 | ||
|
13a384a6fa | ||
|
52e3fff828 | ||
|
521123944a | ||
|
d54be2ee6d | ||
|
64a6cc3afd | ||
|
a88cd68d3e | ||
|
27e85c7b68 | ||
|
a404017a86 | ||
|
41a2aa2ee2 | ||
|
2799417da1 | ||
|
407ad89ff0 | ||
|
94b4765363 | ||
|
c5187380d8 | ||
|
0a9bc3b507 | ||
|
17c3829528 | ||
|
058b30023f | ||
|
dfdd5169a2 | ||
|
844ca49743 | ||
|
2767d9ba05 | ||
|
f16a2179a6 | ||
|
e2086b941f | ||
|
f07c45e4f2 | ||
|
307fe9c716 | ||
|
dfced4b557 | ||
|
75fd873fe6 | ||
|
c655b7dc78 | ||
|
a8f7c5ee48 | ||
|
0046b16d87 | ||
|
31ccdbb7a8 | ||
|
5bbcc41c20 | ||
|
cb1af229f2 | ||
|
349a52b279 | ||
|
42afac91d7 | ||
|
5841ed4e5e | ||
|
56bb143a4d | ||
|
3784316d46 | ||
|
9a0cde66ba | ||
|
bfb810445c | ||
|
f2e1105056 | ||
|
f07387466a | ||
|
9c8752505f | ||
|
17d80442cc | ||
|
d35e923a4c | ||
|
67de5c84d3 | ||
|
5bcbedb7ee | ||
|
35789fce99 | ||
|
7c1914411f | ||
|
5581efe7cd | ||
|
66cf6e3a7a | ||
|
4a40d10b60 | ||
|
c72e458a72 | ||
|
768146b1b0 | ||
|
615dfdf672 | ||
|
7cbf01b994 | ||
|
05695c2458 | ||
|
ae6468b4b9 | ||
|
c183fcf116 | ||
|
982f85b281 | ||
|
bd481592ff | ||
|
ed15f1d717 | ||
|
4f9c865edd | ||
|
436bf27e6c | ||
|
038729a7ab | ||
|
8b0468e9ee | ||
|
568c064795 | ||
|
e8f4bfb374 | ||
|
ec041193f9 | ||
|
66325f7271 | ||
|
0dc07ccc3a | ||
|
a1f6b64e24 | ||
|
efadb70ef8 | ||
|
641050c93f | ||
|
83de55b370 | ||
|
508a2d979a | ||
|
1fd682930a | ||
|
f7065ab207 | ||
|
84d2229ffe | ||
|
7d08d84b03 | ||
|
ae9fbcb82c | ||
|
bdc7d0c2db | ||
|
8390bc5683 | ||
|
f760cb4f97 | ||
|
a5a15c7782 | ||
|
71ebfc7c63 | ||
|
af4f6c124d | ||
|
60ed73bb91 | ||
|
d3e08fe3cf | ||
|
24da5233dd | ||
|
d22c775e04 | ||
|
fa4deb02af | ||
|
97d32bb7d7 | ||
|
2c47a6df0d | ||
|
353bccdf22 | ||
|
9045bea756 | ||
|
8afd6daa3a | ||
|
a6d9462cb1 | ||
|
5c4189e6b2 | ||
|
e954cdc188 | ||
|
4ff8436ebd | ||
|
9de132dbf6 | ||
|
f0efb90f21 | ||
|
2a02403a94 | ||
|
a42726f866 | ||
|
b12cf05c82 | ||
|
9f50e06993 | ||
|
b5a5ecf4a3 | ||
|
f5d05b43d7 | ||
|
ba86626642 | ||
|
312450d079 | ||
|
c58acf06c2 | ||
|
3eba4216e0 | ||
|
6d90f1168b | ||
|
c4d2968183 | ||
|
075e1141b8 | ||
|
87041b207f | ||
|
770271d98f | ||
|
a759acd958 | ||
|
3bcb01a84f | ||
|
36dd2f029f | ||
|
608238ead6 | ||
|
3a15c6c9d7 | ||
|
8f89f10b40 | ||
|
6e2e7641f9 | ||
|
92175dd78c | ||
|
cd1709b0d4 | ||
|
2c45df2ab4 | ||
|
0790864064 | ||
|
ac6c791880 | ||
|
a9d0128bd7 | ||
|
92cc0d6257 | ||
|
28f48ce1ac | ||
|
ef1a85ca5e | ||
|
659d7b190f | ||
|
7af5682b3c | ||
|
0fb6ba4ccc | ||
|
d7141cfd06 | ||
|
0e62dbadcd | ||
|
afc7e581e6 | ||
|
72303ef11a | ||
|
4aa1bea04a | ||
|
71c9aec834 | ||
|
e8e20c0897 | ||
|
18a0e144c2 | ||
|
e27ffdab0f | ||
|
c41f94eda3 | ||
|
22b08a10ff | ||
|
97d91aff7b | ||
|
13225400c8 | ||
|
adba0c2b63 | ||
|
782fe1fe82 | ||
|
1dd415df1a | ||
|
7082aecd54 | ||
|
e6f46e637c | ||
|
b7042cb767 | ||
|
372cd16b88 | ||
|
22597efa06 | ||
|
1f9098e7d0 | ||
|
0aa96c5512 | ||
|
03a8188a9a | ||
|
6b1baf8dd2 | ||
|
a38b5d7430 | ||
|
00a863b25e | ||
|
0f337e9c14 | ||
|
dd41f86339 | ||
|
2af17cd3f5 | ||
|
9a5393d500 | ||
|
12128189eb | ||
|
c3c1ee0150 | ||
|
07d2ad30e5 | ||
|
9cebefa717 | ||
|
8aacbb3ba9 | ||
|
e9042385ac | ||
|
b9e27acabc | ||
|
585d74bad1 | ||
|
0a26cdf344 | ||
|
12c7411b6b | ||
|
fbdc02534a | ||
|
e2b78f074b | ||
|
cc6d826fdd | ||
|
6d2c4f87af | ||
|
69c23cc0c9 | ||
|
e7001c1455 | ||
|
7df554acb0 | ||
|
08632253d9 | ||
|
ce574949f7 | ||
|
57a37ed583 | ||
|
1f6c42c678 | ||
|
f8159163c1 | ||
|
d5a3fccb06 | ||
|
7ad5396f79 | ||
|
9b184e1268 | ||
|
7b0f8122b2 | ||
|
b7ba0615d0 | ||
|
dbe86d9d37 | ||
|
0be7a1e33b | ||
|
8fa736945a | ||
|
fc8fcf85a2 | ||
|
5fa4cfcabf | ||
|
84ba2558e2 | ||
|
b8f2caa80a | ||
|
90f37f48e2 | ||
|
6fae583dba | ||
|
53d405c37f | ||
|
f714730c40 | ||
|
a5b4670c79 | ||
|
abdaf7c2b5 | ||
|
4f9db655ed | ||
|
488f2bd141 | ||
|
214ab2caef | ||
|
6ae6dcfc53 | ||
|
8712c6df22 | ||
|
341e7b35a6 | ||
|
60b7e2bbbe | ||
|
882b79b254 | ||
|
1ffc120558 | ||
|
dc23efd3a2 | ||
|
f74ca4ed36 | ||
|
46f7ab808b | ||
|
0252a6f475 | ||
|
1ea1d561c7 | ||
|
141cb65e51 | ||
|
437bc829bf | ||
|
52d9b0cb56 | ||
|
f9135cdeb5 | ||
|
7bc56c5365 | ||
|
13915f6521 | ||
|
6a2542dacf | ||
|
cf5a3bc531 | ||
|
388216fc45 | ||
|
69b7952b8b | ||
|
43a82dab90 | ||
|
c378b1bf4c | ||
|
5eaf898fcb | ||
|
1da85f7bdc | ||
|
f6a160d34e | ||
|
ae726dcd2b | ||
|
cf1ea9237c | ||
|
9603adb5b4 | ||
|
7a9b680a9c | ||
|
523b907359 | ||
|
8b7af1d0fc | ||
|
3bb13c7eb4 | ||
|
581cba2a56 | ||
|
f5cc497eac | ||
|
ab8968437b | ||
|
0c6e9121b2 | ||
|
c22fc41ddf | ||
|
0751141003 | ||
|
87c87bccb5 | ||
|
529d19bad8 | ||
|
eb9ce779f6 | ||
|
c84e889a69 | ||
|
35a51fd697 | ||
|
bb4e9c72d7 | ||
|
dc1e73cbbf | ||
|
1eb0751803 | ||
|
74cf9a0f60 | ||
|
27f3abd893 | ||
|
ba321d318b | ||
|
18b1aec0ee | ||
|
ec259ddfee | ||
|
2b0d667b14 | ||
|
e48b58e1be | ||
|
44511f9e43 | ||
|
2cdd4906ac | ||
|
d6a656cf7f | ||
|
1997933508 | ||
|
7e1c8a5be3 | ||
|
2f80a91b3e | ||
|
21334593d1 | ||
|
d90e5f283a | ||
|
aa5d1a8897 | ||
|
79c759393f | ||
|
f58f02f3e6 | ||
|
2cf230951f | ||
|
9e6d012e9c | ||
|
bd70d66a62 | ||
|
1602e2f4f1 | ||
|
d91bf690ef | ||
|
61d5e5ca9a | ||
|
f8275cb303 | ||
|
279e6658ac | ||
|
d11a772080 | ||
|
f3cc93630e | ||
|
77ea269b86 | ||
|
3b1d9f1a26 | ||
|
3a14b1235c | ||
|
30f739db44 | ||
|
cd41f655f9 | ||
|
92884c25b3 | ||
|
dbdfc71026 | ||
|
e8c72adf54 | ||
|
4d2a324fce | ||
|
7d991b6e42 | ||
|
fcf03cdfa9 | ||
|
7028a03ffa | ||
|
49ad10261e | ||
|
c14bd4f1ad | ||
|
65973c6c40 | ||
|
291eaf0a77 | ||
|
86cd6da76e | ||
|
a69ffc3e20 | ||
|
b524ed2dda | ||
|
33d2ec08ba | ||
|
c51a262e34 | ||
|
fc8d9cb8f7 | ||
|
f66f464802 | ||
|
12c70b4386 | ||
|
a0615f6839 | ||
|
312fbb6d41 | ||
|
afe281964d | ||
|
bea729c030 | ||
|
8ba8a59697 | ||
|
659e7b52df | ||
|
294274e10e | ||
|
eaaf1ea96d | ||
|
abf9d0b07f | ||
|
3b4207896d | ||
|
90dfb1c8ad | ||
|
82a318db5f | ||
|
0f9f9a132e | ||
|
1931a1bdc7 | ||
|
424ae36046 | ||
|
bc94dfc7d2 | ||
|
68eead6628 | ||
|
debcb76939 | ||
|
7cb1efebec | ||
|
a58b0a3d9c | ||
|
4046ae5e2f | ||
|
6af9204938 | ||
|
862caf826c | ||
|
0bf6ffba43 | ||
|
08e4e88482 | ||
|
4fa5a79833 | ||
|
484e6b784c | ||
|
6a810b4259 | ||
|
c786c3a974 | ||
|
d5eba1bfe5 | ||
|
2a38569337 | ||
|
713c7d49a1 | ||
|
7f68e3107e | ||
|
97549d923c | ||
|
410feab962 | ||
|
757a004a90 | ||
|
f270057e0c | ||
|
7dc5f9d0b1 | ||
|
aa2fa2caa3 | ||
|
49f3e7d233 | ||
|
df59a357ec | ||
|
bcc0315003 | ||
|
baca6cb417 | ||
|
c8134fa046 | ||
|
a189832454 | ||
|
029519a149 | ||
|
faa843fcef | ||
|
f179243876 | ||
|
028ed1bb22 | ||
|
bb99b3f02e | ||
|
d3533eee68 | ||
|
488fe76eb8 | ||
|
75546e1e46 | ||
|
ec7c2b784a | ||
|
08035dc805 | ||
|
e18f5a5304 | ||
|
c8b9dfb25e | ||
|
fcb89da9c2 | ||
|
61d94850a7 | ||
|
0f163170a7 | ||
|
faecc65cd3 | ||
|
ae6960cf91 | ||
|
3bfb6a9420 | ||
|
fd40dfaf58 | ||
|
e72c4818c4 | ||
|
8ae94cafa5 | ||
|
3a0af5ad30 | ||
|
718fafed26 | ||
|
61d8f57f2a | ||
|
e262cd38ad | ||
|
5dde37c846 | ||
|
49d088d9ce | ||
|
c3eed9fa3e | ||
|
c5ea3d595c | ||
|
f6533a1df1 | ||
|
2249db0c73 | ||
|
bcf52efbb6 | ||
|
9b399814e7 | ||
|
2ef69899de | ||
|
9709b7e458 | ||
|
65cfcc28ab | ||
|
cfb8ca520a | ||
|
4cd2654a9d | ||
|
203bac0ec4 | ||
|
964ab7158c | ||
|
05523e289b | ||
|
ce1ee98aba | ||
|
5ce8eee0a4 | ||
|
b1676a289c | ||
|
cfdca8dc1d | ||
|
d2865f1e8a | ||
|
35eba19a65 | ||
|
2f65748927 | ||
|
0fd0e8255f | ||
|
54fcd40aa4 | ||
|
b93a532bcd | ||
|
7786f8512b | ||
|
4394c61e6c | ||
|
8e84bc3931 | ||
|
f877360dc1 | ||
|
f678459593 | ||
|
681c94ca17 | ||
|
ab099ab076 | ||
|
d154421092 | ||
|
2d79f7653f | ||
|
0af1650158 | ||
|
68e73ceb67 | ||
|
2f28582b55 | ||
|
f4776ef9df | ||
|
75324c4cc8 | ||
|
604f4eed65 | ||
|
847f3060d4 | ||
|
93fffa299c | ||
|
e6ae462268 | ||
|
8641d2da3b | ||
|
0ab7267ae3 | ||
|
ba46bda149 | ||
|
f13d8c2026 | ||
|
a3fdad84ad | ||
|
6af7d6ea2d | ||
|
c89668f8e5 | ||
|
b275f95f37 | ||
|
9b02a84a5a | ||
|
fb53da508f | ||
|
15bcc707e6 | ||
|
84036d3e18 | ||
|
34e923e3e3 | ||
|
1eadfb0e28 | ||
|
3b423ea778 | ||
|
981a878cf5 | ||
|
677d41aa3b | ||
|
7c8d02d1bc | ||
|
f0b89e63b9 | ||
|
63b2a2138d | ||
|
99638f5f76 | ||
|
774e677cc8 | ||
|
524eef5d75 | ||
|
33564a0c03 | ||
|
e1d85da306 | ||
|
5bff90cea2 | ||
|
d47b3ef4c9 | ||
|
7e66d9900c | ||
|
f5a611a74c | ||
|
8074e7a437 | ||
|
5504ef7a84 | ||
|
ea729aea4a | ||
|
587d509ddd | ||
|
d06af368ad | ||
|
a7acfffea6 | ||
|
876d4e5484 | ||
|
7995e3288f | ||
|
0c0943bcdf | ||
|
58785c2932 | ||
|
c14694a424 | ||
|
49cea49cfa | ||
|
6979503a85 | ||
|
755f008c1e | ||
|
796da163f9 | ||
|
7d9d601e6d | ||
|
29ac09ee9d | ||
|
c1a289e05a | ||
|
02011af7b0 | ||
|
49e04102c1 | ||
|
3cb8e9526e | ||
|
26f63600c1 | ||
|
6fd893bd3a | ||
|
d5d41c2849 | ||
|
ed1a61dcb7 | ||
|
5b19725de2 | ||
|
0ac748a340 | ||
|
26c054edbf | ||
|
39393f651e | ||
|
587ad8845a | ||
|
c1ab6eda4b | ||
|
409ea700c7 | ||
|
050e6066af | ||
|
8068038a60 | ||
|
90cc178baa | ||
|
5baf486545 | ||
|
ec32f0db82 | ||
|
02a932d63f | ||
|
2f138d860e | ||
|
d3f4876f41 | ||
|
891241e7e7 | ||
|
3c2b06099d | ||
|
6ca1b9e4ce | ||
|
fb3cc5e716 | ||
|
217054ddea | ||
|
123ade3763 | ||
|
7257c77e19 | ||
|
60e88c873e | ||
|
d9dce8e0d0 | ||
|
4be5b4147d | ||
|
4e8ba395f2 | ||
|
0dae0f2b5e | ||
|
30cd8b8fca | ||
|
1c50526092 | ||
|
a99bb24ea8 | ||
|
e9efc0a361 | ||
|
171f153e2c | ||
|
29977d5058 | ||
|
d60de4cafd | ||
|
dcf7287d64 | ||
|
cd95cd0671 | ||
|
df34db1158 | ||
|
5a83bebf76 | ||
|
29ddf2214d | ||
|
f44b085da6 | ||
|
53ebecea7c | ||
|
ae75dafe47 | ||
|
63a9d72ee8 | ||
|
4356962c69 | ||
|
38c4ceb00a | ||
|
34f5793521 | ||
|
bd23c7729e | ||
|
205e4de3fd | ||
|
7cabe08399 | ||
|
153d7e4038 | ||
|
987f76ea78 | ||
|
27e064e7e9 | ||
|
1b9411ef77 | ||
|
e0476beb78 | ||
|
808120e5b8 | ||
|
9d578a2e6d | ||
|
fc4d035e7a | ||
|
c9ccbfad11 | ||
|
59c5f6e35b | ||
|
61c78d9438 | ||
|
ee9f0ed895 | ||
|
052562ffd5 | ||
|
98323ac114 | ||
|
4776a9e6fb | ||
|
460e1b3600 | ||
|
4f0cab3b74 | ||
|
79589354df | ||
|
44a25f31a8 | ||
|
91eee33f62 | ||
|
1f096174d6 | ||
|
a54a34ef0e | ||
|
7d5445e312 | ||
|
417018659b | ||
|
e36260f39a | ||
|
8f756fe679 | ||
|
a73dfe68d3 | ||
|
7e0cb4c46f | ||
|
f5535d516f | ||
|
dcc80204bc | ||
|
70158284b7 | ||
|
a66ddb7c59 | ||
|
d7266afc7e | ||
|
df3a321164 | ||
|
aeb8972281 | ||
|
b4a08b3b7c | ||
|
52da88201c | ||
|
c44c9dfa79 | ||
|
3cf409aa9e | ||
|
6a8a792019 | ||
|
452ca90fe5 | ||
|
f2c67ea82f | ||
|
a7b44ea10f | ||
|
0cf113e250 | ||
|
777e9f2710 | ||
|
619d98ab49 | ||
|
164167ea91 | ||
|
aad51c0b4e | ||
|
dca89c67ef | ||
|
f800215946 | ||
|
8166818791 | ||
|
c3ca4f5de0 | ||
|
74641d2006 | ||
|
4af420f978 | ||
|
4039b9c9c4 | ||
|
4f4a897dda | ||
|
4b40d82233 | ||
|
9536fabaa8 | ||
|
43dccc6c1a | ||
|
5a72ed3406 | ||
|
06115bf82c | ||
|
285ab8c861 | ||
|
e28da7686e | ||
|
a837cb444c | ||
|
5f884478e5 | ||
|
885eceba1d | ||
|
6ce6b63482 | ||
|
268e72f10f | ||
|
c388416aac | ||
|
5c297fcc09 | ||
|
7d2a6f2030 | ||
|
a4522b6a8f | ||
|
f7ddfdbae6 | ||
|
d1108b8a06 | ||
|
9c161cc65a | ||
|
f482857959 | ||
|
f1102e98bb | ||
|
ba4d491562 | ||
|
5b3086db1f | ||
|
16e4bc9827 | ||
|
89d7b77022 | ||
|
c867ac4527 | ||
|
980a5bc72a | ||
|
4292f42308 | ||
|
50062b413c | ||
|
d63cab5193 | ||
|
8e2e1f3d28 | ||
|
d3f4580519 | ||
|
58c5986f8b | ||
|
707bb9b9ed | ||
|
eafb618594 | ||
|
ba32bebd05 | ||
|
4562f07887 | ||
|
8c661b5e9a | ||
|
cf95278122 | ||
|
1baec48367 | ||
|
908821d48a | ||
|
02fd8485fa | ||
|
dbb2bd727d | ||
|
5cc978c6a0 | ||
|
86fb048e59 | ||
|
b4ff5234bd | ||
|
cdb44010c9 | ||
|
29d863d451 | ||
|
0253fedf03 | ||
|
d28bd54f2a | ||
|
e97716a95a | ||
|
5338c06c2a | ||
|
cf9073397c | ||
|
46d11bddbb | ||
|
7bb54c3dc5 | ||
|
70589b8548 | ||
|
1f965317b6 | ||
|
bcca214e36 | ||
|
33cf73f699 | ||
|
804ef16822 | ||
|
c85398b020 | ||
|
29da565133 | ||
|
0456c0db87 | ||
|
749d4abd41 | ||
|
f05dce8d3a | ||
|
e3feb05175 | ||
|
b85185e659 | ||
|
0d27579fc7 | ||
|
f6576e9a74 | ||
|
26730c891a | ||
|
91cb91a304 | ||
|
fd3066c168 | ||
|
a7dd561c4a | ||
|
79521da5cc | ||
|
6f625ae65a | ||
|
af22957b94 | ||
|
9357bcb582 | ||
|
488559a330 | ||
|
d9b5445f39 | ||
|
095d2a29a3 | ||
|
6040283f23 | ||
|
5c3d0fbc5e | ||
|
9664f33e0d | ||
|
2df698025c | ||
|
25fb4dd50d | ||
|
670bc0a46c | ||
|
96f85def5b | ||
|
2a14b6cf60 | ||
|
d7c6fd2f80 | ||
|
e260808a57 | ||
|
14d2535f13 | ||
|
4e219ebafb | ||
|
4662e9889c | ||
|
919fe72f60 | ||
|
80a9fc6d36 | ||
|
cdb3f9fb8d | ||
|
40fde69be9 | ||
|
c2aa895908 | ||
|
e1bacd18a3 | ||
|
70892220c8 | ||
|
03decbc1e6 | ||
|
bb1fb9aaad | ||
|
5a34c7c245 | ||
|
bb7408e851 | ||
|
6c1c76d02a | ||
|
e3d8e979de | ||
|
f51c5e1a5c | ||
|
b5f5987959 | ||
|
42af8795a3 | ||
|
8047b69ba3 | ||
|
f20abbc96c | ||
|
796c05ca32 | ||
|
3e43f8e9f4 | ||
|
4cbac66746 | ||
|
c279c48a0e | ||
|
0a82696d70 | ||
|
8777592397 | ||
|
adea457841 | ||
|
3205ace201 | ||
|
c5389354ac | ||
|
ebef4efb88 | ||
|
9670d9364d | ||
|
7bce33eb0f | ||
|
0f77875220 | ||
|
9498d897ab | ||
|
30f09b4a1a | ||
|
95b92b1f97 | ||
|
ec69501e94 | ||
|
5b3e6555a3 | ||
|
48cacbca24 | ||
|
aacd100a70 | ||
|
44dbbeb196 | ||
|
bcbbd9538f | ||
|
056be8b7b0 | ||
|
b33ad6fff6 | ||
|
6f6ef7906a | ||
|
bea1462f4f | ||
|
bb8bc1ffc8 | ||
|
3bc45d78c9 | ||
|
949f8c9f2a | ||
|
1800dd0876 | ||
|
1946aead21 | ||
|
0679ae984b | ||
|
bc33c27796 | ||
|
f2e163b75d | ||
|
db806533e6 | ||
|
b81b27c21f | ||
|
cff4f20c44 | ||
|
e1d0aacb6a | ||
|
d7caea206e | ||
|
2835d1f7b2 | ||
|
26c5d1ea0d | ||
|
f0698dae14 | ||
|
0cd02ab1b4 | ||
|
e78152aecb | ||
|
aca9ea42bd | ||
|
d871a665de | ||
|
a67b7554c8 | ||
|
8d21af5be3 | ||
|
fe30e5730f | ||
|
a293cd6ab9 | ||
|
f3aa9e151d | ||
|
5f062032f7 | ||
|
53345fe357 | ||
|
2edb858b18 | ||
|
87de23a6cd | ||
|
23f2e0fea7 | ||
|
37ca57e9d5 | ||
|
3149c3efe6 | ||
|
0a3fc95be6 | ||
|
fcabc48ee4 | ||
|
cbc2a71c27 | ||
|
491758a446 | ||
|
c587ba3422 | ||
|
2c4551d86d | ||
|
4de8459265 | ||
|
b8ba263099 | ||
|
25a813e924 | ||
|
f6fa56194f | ||
|
ee77ba5e49 | ||
|
f99c4ec798 | ||
|
1f6bacc486 | ||
|
28d057cb0e | ||
|
34400dd4a2 | ||
|
e0e6ae741e | ||
|
c47cdd5f39 | ||
|
bc2c8279de | ||
|
77a1411f9b | ||
|
6f27bef9fc | ||
|
77f7c83114 | ||
|
e8a7a9435f | ||
|
591c98cdbe | ||
|
5b16dd6469 | ||
|
ad877271f3 | ||
|
7d30dafd69 | ||
|
4a276afeb5 | ||
|
3d70af4ee4 | ||
|
e2c23ed57d | ||
|
1239c96413 | ||
|
c4f55b53b0 | ||
|
16063c7456 | ||
|
a4822abe37 | ||
|
f9f439763a | ||
|
4001241ccf | ||
|
9e3ed7b429 | ||
|
e465ebf2f3 | ||
|
aa282973d4 | ||
|
f66c000229 | ||
|
a1d966c492 | ||
|
7c0c525764 | ||
|
2c0ad62b24 | ||
|
2c89640ab9 | ||
|
a9fcb775e5 | ||
|
3197160114 | ||
|
f91c3cfda6 | ||
|
dcc75e1563 | ||
|
a384102fdf | ||
|
bb5402e6fb | ||
|
603f49706e | ||
|
f6e44bc0e8 | ||
|
605c8fb75d | ||
|
324cb3d08f | ||
|
f3143745b2 | ||
|
b1855bb4af | ||
|
479079c6b1 | ||
|
95aea39348 | ||
|
97e28de7e2 | ||
|
618d9b5d54 | ||
|
7cda3fb7b5 | ||
|
ca1307c56e | ||
|
a8ea752a93 | ||
|
2e60051c92 | ||
|
642cf261a8 | ||
|
e3975fba84 | ||
|
7f9cce2b50 | ||
|
430a5f8581 | ||
|
41c186c344 | ||
|
b94e88c1e2 | ||
|
42a51cb285 | ||
|
bd7b27b5c8 | ||
|
3d62ab9585 | ||
|
7f6bd671fe | ||
|
0c66111c40 | ||
|
51f0e7b0e4 | ||
|
13b775a96e | ||
|
7c202d2fa4 | ||
|
724db8650c | ||
|
1337a66130 | ||
|
3614749b55 | ||
|
90b756b2a1 | ||
|
d5b067e04a | ||
|
286704bf6f | ||
|
34e71b374b | ||
|
c8773e10b1 | ||
|
a728bd0ee9 | ||
|
221b73e23d | ||
|
2246297ae6 | ||
|
c217e3c87a | ||
|
8cd5f04ea3 | ||
|
fd6dd6935b | ||
|
79a4cbbec9 | ||
|
d7a31cfb2d | ||
|
f549aaa205 | ||
|
9249b34be8 | ||
|
4401ccac22 | ||
|
d3afa80b96 | ||
|
0e80073e01 | ||
|
0d9da7367d | ||
|
4ff252456b | ||
|
6203e3660d | ||
|
6eeef51c6a | ||
|
8b95ea4a35 | ||
|
3a520c1c0f | ||
|
e852ba55a5 | ||
|
06a640084f | ||
|
1ed5d91555 | ||
|
4dbfe7e17e | ||
|
d8a51d2887 | ||
|
093481618d | ||
|
7444b88f5d | ||
|
7c865c156f | ||
|
e061793212 | ||
|
e6907243af | ||
|
3936c57294 | ||
|
207c4d537c | ||
|
601c9b29e6 | ||
|
313a090c0e | ||
|
9d3b1f9419 | ||
|
47f9e70385 | ||
|
ee5a91e663 | ||
|
299bd58c5a | ||
|
7b96663082 | ||
|
bd17d27658 | ||
|
0b4a70ca2c | ||
|
542fe0da40 | ||
|
338fc49060 | ||
|
7cfb81ba04 | ||
|
34dc2f10b4 | ||
|
54d84229ce | ||
|
1c34831291 | ||
|
3ff75aeb07 | ||
|
2cb94ade6c | ||
|
3350f815c7 | ||
|
39fe25b69e | ||
|
68b67b3230 | ||
|
cf5657d4bb | ||
|
d5425f28ae | ||
|
bddd826d7a | ||
|
83cac3c3e3 | ||
|
5d87dc98ea | ||
|
f13065b1f7 | ||
|
a24d254397 | ||
|
07e28a968b | ||
|
2394b07bce | ||
|
563bb58c8d | ||
|
e19e541e2c | ||
|
acf825def2 | ||
|
3092b261e2 | ||
|
554036040b | ||
|
6fc3ead321 | ||
|
73041028b6 | ||
|
54dc8d2968 | ||
|
d97e4300ee | ||
|
d50585b05b | ||
|
51d8a975ab | ||
|
9670db3904 | ||
|
a046616249 | ||
|
f29155950f | ||
|
0354791147 | ||
|
87dd1de046 | ||
|
bd6cadffb0 | ||
|
6d93db06db | ||
|
171ecf8cf2 | ||
|
81ab8db1c3 | ||
|
04a47e88d2 | ||
|
19c07198b6 | ||
|
bfd8c6deb7 | ||
|
4bd0553274 | ||
|
ff503882f7 | ||
|
4c03618fab | ||
|
6c563cda82 | ||
|
0c4397deaf | ||
|
ccb37fa567 | ||
|
05c60724ed | ||
|
3bd3cdd82e | ||
|
b94f928be6 | ||
|
85769732c2 | ||
|
24405e8044 | ||
|
28861e0c47 | ||
|
bf692d47fb | ||
|
a1833d8b4d | ||
|
96faee9762 | ||
|
e598ffcdf8 | ||
|
32e2c53467 | ||
|
5a4962f80d | ||
|
30a57db97c | ||
|
bd523abd44 | ||
|
a07f6470b7 | ||
|
a33043f0e0 | ||
|
1ffbbe798a | ||
|
336e1e9b7e | ||
|
7f281907dd | ||
|
babf907bfd | ||
|
7ec9f304e9 | ||
|
5e15ed314b | ||
|
cc9c930e29 | ||
|
24102aa8ca | ||
|
bbcd662532 | ||
|
20f9635469 | ||
|
35e9d688ba | ||
|
8ae5dc4aae | ||
|
37b2ea9a8d | ||
|
62e55fd58a | ||
|
00e7ef5c3c | ||
|
01cc1cc923 | ||
|
14c5f7bf1d | ||
|
0937aef261 | ||
|
b805599ef6 | ||
|
55b664046c | ||
|
39b2bf51ca | ||
|
a232f9463c | ||
|
982e5afd1c | ||
|
9c84994830 | ||
|
f5d6af13d0 | ||
|
863909a749 | ||
|
0a8bd82a37 | ||
|
5ab8d41d9f | ||
|
de2447c2ab | ||
|
76915b16e7 | ||
|
3b04fd10e8 | ||
|
9641c90eaf | ||
|
7fbc3a9bc0 | ||
|
ff85c363a8 | ||
|
0b69c2c42f | ||
|
78479b1915 | ||
|
ff328e748d | ||
|
4f28802f09 | ||
|
75308e471c | ||
|
5fa011dc0c | ||
|
fd15ddbc30 | ||
|
4229032676 | ||
|
cdb5947316 | ||
|
5d5eeac310 | ||
|
51d647122a | ||
|
29dcf646a3 | ||
|
d0d3ddd045 | ||
|
0313544f4a | ||
|
c63a952dc9 | ||
|
9127285985 | ||
|
f22b112005 | ||
|
8832cdf6e1 | ||
|
c6bded3475 | ||
|
8c7e19c5ff | ||
|
6ebfa57364 | ||
|
c41121cc48 | ||
|
4acbf7d8c3 | ||
|
ccae064209 | ||
|
833b514d98 | ||
|
f8a4b6755d | ||
|
a8975c9042 | ||
|
12e27dfd8f | ||
|
7c0f6741eb | ||
|
cd204f1118 | ||
|
4215a1542b | ||
|
bc77104fed | ||
|
6ce5aa1cd5 | ||
|
c3ab3f1dde | ||
|
d582a26107 | ||
|
5e7eade1f7 | ||
|
b7d29c1e23 | ||
|
de27973538 | ||
|
6cc6682f5f | ||
|
97e782ee2b | ||
|
e6d9d216dd | ||
|
820f37b1a6 | ||
|
c44f8958f6 | ||
|
0434b653c8 | ||
|
fa3ddc5116 | ||
|
6dcefa3739 | ||
|
78ccd5d07c | ||
|
43740ab642 | ||
|
550e628f05 | ||
|
5728516371 | ||
|
c2004fb8c4 | ||
|
7e506f71f3 | ||
|
0c6f8f9290 | ||
|
e9ad878df6 | ||
|
9e797a6db9 | ||
|
4982c70db4 | ||
|
0f7a65e59b | ||
|
3d8b8dc09a | ||
|
c0ece8d4f3 | ||
|
081b74b97d | ||
|
152036f0aa | ||
|
5f59f7bb49 | ||
|
a4ceb0e4ac | ||
|
ee7ca6822a | ||
|
06499c52e2 | ||
|
da5ed8b35b | ||
|
ce4e325504 | ||
|
a3c97beee0 | ||
|
150b657bad | ||
|
9b7784781d | ||
|
3b4ccb2eca | ||
|
e8dc902781 | ||
|
642e9917ff | ||
|
de391bc48b | ||
|
776c376227 | ||
|
efea287b44 | ||
|
1cb45e582c | ||
|
075a2d89b9 | ||
|
b5376c7cec | ||
|
62725ab277 | ||
|
0be416dfdc | ||
|
150b1c8c73 | ||
|
2c95ddf4f3 | ||
|
791549508a | ||
|
dbb4d54e01 | ||
|
09470db089 | ||
|
1847dc4b7f | ||
|
032797ea4b | ||
|
7abd7fa739 | ||
|
1148a24e64 | ||
|
9c4e82435e | ||
|
2243046bf8 | ||
|
dffccfd0f1 | ||
|
5dbd198b53 | ||
|
4bf1a946f9 | ||
|
96516002cc | ||
|
417328e44e | ||
|
97206b7cba | ||
|
74fafbda51 | ||
|
237eb3b5f1 | ||
|
8dfaf0c780 | ||
|
0ffa3dd870 | ||
|
14af90b868 | ||
|
2004f60bd6 | ||
|
366a5f1d74 | ||
|
e9b3a16cdc | ||
|
aa9eb76b0d | ||
|
02db973460 | ||
|
536826d66f | ||
|
6fc6b9bf31 | ||
|
47a3b31ff6 | ||
|
75097cf09a | ||
|
6dd78a9ac2 | ||
|
84a4f37cf7 | ||
|
159b168eea | ||
|
ebb9fade23 | ||
|
c243efb0cd | ||
|
3a4a04e462 | ||
|
d390f86080 | ||
|
a74f1ab423 | ||
|
d864d1eb97 | ||
|
7aa0bc5790 | ||
|
823d0b3765 | ||
|
b8de6c01b5 | ||
|
c3f2bd1009 | ||
|
7ff38506ab | ||
|
32d5e6312d | ||
|
daa4618da8 | ||
|
7b7019a4da | ||
|
5380f3f0c4 | ||
|
f33370219b | ||
|
b526ce268f | ||
|
e19edd3f25 | ||
|
b9f9e20f01 | ||
|
af535233cc | ||
|
9af5484fcc | ||
|
6cf939fcc0 | ||
|
afee36d07d | ||
|
8c6a46f643 | ||
|
1dcb11f81d | ||
|
a49b71b481 | ||
|
726dbc0f29 | ||
|
a9a0ffaf51 | ||
|
f6959bc597 | ||
|
e0f171f342 | ||
|
79a0f82ca1 | ||
|
be90e5e1d4 | ||
|
77c2613d3a | ||
|
5da2dd98e9 | ||
|
f1a7028900 | ||
|
19f6f0b3db | ||
|
47bf587f84 | ||
|
a0a8d9d057 | ||
|
cc1627ae10 | ||
|
2832886761 | ||
|
2689484402 | ||
|
acdad37160 | ||
|
f1a6e16258 | ||
|
b6ba2a4f75 | ||
|
3f8cbd8ec9 | ||
|
e10eca3d1a | ||
|
aefbd49038 | ||
|
28d201feb7 | ||
|
d43e61758a | ||
|
69c19cf0b0 | ||
|
1f5322a94e | ||
|
aef703fa1b | ||
|
bea39a49bc | ||
|
bb7b7522b1 | ||
|
94e924906c | ||
|
4e4f62b6db | ||
|
aa59b0f5a2 | ||
|
14b53c6318 | ||
|
062c80199f | ||
|
0f871f8cb7 | ||
|
10a3a3bc49 | ||
|
8d404ac408 | ||
|
9331d6de1e | ||
|
a65c948e7e | ||
|
8309206160 | ||
|
51a1c5f3b4 | ||
|
7f6dda359b | ||
|
328c6159f2 | ||
|
f6f6c32138 | ||
|
333e04e84e | ||
|
fa79b5d59f | ||
|
0161aad462 | ||
|
5123ae4352 | ||
|
2928c5ae92 | ||
|
62ec14d9ec | ||
|
f443006fa2 | ||
|
70ad5b818f | ||
|
8569e8684f | ||
|
3fcb3d94c7 | ||
|
26a9d6474a | ||
|
5a02ed5e84 | ||
|
9ea50365d6 | ||
|
2f8e957713 | ||
|
32e79c464a | ||
|
5512c7e838 | ||
|
d6b8298cfd | ||
|
8b21609654 | ||
|
f8181b8875 | ||
|
6a61bacafe | ||
|
dc061d2ed3 | ||
|
40b1389917 | ||
|
15435f7293 | ||
|
9afb688f5f | ||
|
639449f84e | ||
|
b75e831567 | ||
|
5b53ddfcdd | ||
|
ebe2347ac6 | ||
|
aa764e6009 | ||
|
fa13b0715f | ||
|
79495c5b6a | ||
|
df2f25a977 | ||
|
6c036f267f | ||
|
55192de9e3 | ||
|
a3867992b7 | ||
|
f6b2e34268 | ||
|
318b3d4fe5 | ||
|
cb394a62e5 | ||
|
8f64e2e925 | ||
|
3dea2f230a | ||
|
634f6ec1d4 | ||
|
385f6429be | ||
|
350223201e | ||
|
b688af2226 | ||
|
70baaec6a5 | ||
|
12d1f4f385 | ||
|
3e5b2a6ef6 | ||
|
4824c60893 | ||
|
f6a5318f94 | ||
|
2aabd64477 | ||
|
b18e170631 | ||
|
136e86bb5c | ||
|
4862d39144 | ||
|
b249376bb0 | ||
|
cd49f9affd | ||
|
6d5204b63e | ||
|
f10e182ca7 | ||
|
cfd431d4d5 | ||
|
d52f20048d | ||
|
e9b09b49fd | ||
|
73894af9ff | ||
|
ce01d779df | ||
|
211d3a8c32 | ||
|
95e99e629c | ||
|
6c6e1fb13d | ||
|
1e579a7a2a | ||
|
263c00f27c | ||
|
b71951c70c | ||
|
87cedbe443 | ||
|
976da91fb7 | ||
|
b4d6eca9b8 | ||
|
07e6b0ac70 | ||
|
498da44aab | ||
|
79f5aac2d0 | ||
|
713066accc | ||
|
210abfaef6 | ||
|
53a6661684 | ||
|
04422f5ec1 | ||
|
dd26e6b15e | ||
|
3d94eb9bcd | ||
|
bc7f341f29 | ||
|
bd5d6480e7 | ||
|
6eaefe5bf5 | ||
|
43aa67a982 | ||
|
759698581e | ||
|
13648a0e21 | ||
|
56597db804 | ||
|
78828f9b58 | ||
|
0d9cf9e66b | ||
|
64f5d9b119 | ||
|
1fa586de52 | ||
|
b4c59d25d6 | ||
|
bd2c553870 | ||
|
143b3b2ef3 | ||
|
01214bafd2 | ||
|
b92cf68add | ||
|
b63400fa4a | ||
|
9668613541 | ||
|
c881360e88 | ||
|
b9bf407929 | ||
|
8631e69cdf | ||
|
f3d29db6a2 | ||
|
a365fb0e9d | ||
|
95abde479a | ||
|
35456d2eb1 | ||
|
aecfa55c4c | ||
|
0e3b2ec267 | ||
|
53afd2ae9f | ||
|
d74f0a47de | ||
|
71f4916357 | ||
|
4b0d38de06 | ||
|
9b9348ce86 | ||
|
e2fc596de4 | ||
|
c0568a95d8 | ||
|
2b583c0923 | ||
|
69cf2ad6a5 | ||
|
20b770237c | ||
|
405f571ae8 | ||
|
2eccf0e8d1 | ||
|
389b21a341 | ||
|
13c4eaea92 | ||
|
8f0b62e4d9 | ||
|
bb5813a93d | ||
|
cec49ba976 | ||
|
0e7186af95 | ||
|
8c3b14ee85 | ||
|
77539e7bc7 | ||
|
79fa17e181 | ||
|
18c5d863d6 | ||
|
6cbe06ff3f | ||
|
3553b4c684 | ||
|
a479b287c7 | ||
|
70ae5c13ea | ||
|
8383430946 | ||
|
bedcc94de4 | ||
|
dfaff9598c | ||
|
eb56493f4e | ||
|
3e8af0817a | ||
|
4f47013feb | ||
|
2be118379e | ||
|
b8ff8ea58e | ||
|
331854a126 | ||
|
fa517bb420 | ||
|
5d15da8290 | ||
|
3ffa00909d | ||
|
764419ed4e | ||
|
fc15e08a6c | ||
|
dff53a02ef | ||
|
d6f340e784 | ||
|
f44fbab3ec | ||
|
6dba98cf38 | ||
|
6c4153f348 | ||
|
e690cdb6a3 | ||
|
3c10db669e | ||
|
a01bcf9767 | ||
|
cc414a2012 | ||
|
3b9f4395cf | ||
|
d146e592d8 | ||
|
cf15460a3b | ||
|
219d4d9db9 | ||
|
d125823d3f | ||
|
2010f4338e | ||
|
ad91fc1b00 | ||
|
5dc44f03f0 | ||
|
fc302d7b7b | ||
|
a866e50e6e | ||
|
1c937c5816 | ||
|
6cef3c2b77 | ||
|
06e540c271 | ||
|
2afa4eba43 | ||
|
3218e26a22 | ||
|
986de11464 | ||
|
9efe6501bb | ||
|
7f965d55c7 | ||
|
678ce73907 | ||
|
01ac4892e0 | ||
|
f7ce59f7dc | ||
|
0c522c6bbf | ||
|
16f152b1ec | ||
|
73ffb48bfb | ||
|
73e47ee39c | ||
|
9aed6308d4 | ||
|
c22ec82477 | ||
|
bd0111c1f4 | ||
|
42d34e40f9 | ||
|
a64adda4e7 | ||
|
c85a33d74b | ||
|
d979d2af45 | ||
|
513063bcf9 | ||
|
d83ead8434 | ||
|
64de635626 | ||
|
cff341e5e6 | ||
|
56b62640a2 | ||
|
cbe692ffd1 | ||
|
e2f9d6c4c3 | ||
|
b325dcbff6 | ||
|
9889585a79 | ||
|
e8f0f5a4ce | ||
|
b3e249f401 | ||
|
0503cf2510 | ||
|
fc5702b284 | ||
|
a443c2b18d | ||
|
dca7544320 | ||
|
52b5b5be98 | ||
|
b9d9504df5 | ||
|
7b66ae1531 | ||
|
16cda4138d | ||
|
59aa3dce8a | ||
|
ea2d686468 | ||
|
f1240393d9 | ||
|
18a0ff2b2b | ||
|
178125ae39 | ||
|
7b28bc51e6 | ||
|
f8363690ca | ||
|
cb36f57299 | ||
|
72648f0ba6 | ||
|
17571ff199 | ||
|
917dae58e1 | ||
|
e0f5bb4820 | ||
|
225691e258 | ||
|
8376595621 | ||
|
91a3a95385 | ||
|
48ea7ec970 | ||
|
8bf62010a4 | ||
|
c0562d4eed | ||
|
8070f15966 | ||
|
014fefee1d | ||
|
a9e8110fe3 | ||
|
80d158e0de | ||
|
dffe634c19 | ||
|
896f246888 | ||
|
5fe81ef1bb | ||
|
6da42ca830 | ||
|
051d51b222 | ||
|
303e2b124e | ||
|
05deecaa45 | ||
|
d4e1c072e2 | ||
|
f661bd8ee5 | ||
|
de4ba13400 | ||
|
1e4e9161c5 | ||
|
bf1fb97575 | ||
|
b039bbc678 | ||
|
79b467808e | ||
|
74feadacf8 | ||
|
0899ba4a3f | ||
|
3cb52a6359 | ||
|
26be2bc6b9 | ||
|
e0da5cb929 | ||
|
220fba06e7 | ||
|
3c8b68c636 | ||
|
38e26c4717 | ||
|
8b69cb4482 | ||
|
435ecfe6e0 | ||
|
3d3ce9812f | ||
|
742475bc8d | ||
|
4cc796ab93 | ||
|
58dc0fcd1e | ||
|
87fff769f4 | ||
|
71da8c13e1 | ||
|
89b542b421 | ||
|
cfc117826a | ||
|
1614b534fe | ||
|
11a0c2779b | ||
|
6598cba32f | ||
|
43956e1b71 | ||
|
ae008570ff | ||
|
510cac5f5b | ||
|
2cccb1f02c | ||
|
8a1ca49657 | ||
|
16785b9b7b | ||
|
5b0fa7aaca | ||
|
972d80b596 | ||
|
0da721ec38 | ||
|
d9442aab88 | ||
|
2afe18d2ce | ||
|
8b989ac665 | ||
|
3d0a7d819c | ||
|
74354043ff | ||
|
2b449e0e65 | ||
|
36a0946aa9 | ||
|
2884018e7f | ||
|
2ef7b479a5 | ||
|
0485b8f0fb | ||
|
fd4ec26313 | ||
|
64e01c627f | ||
|
94dc10378d | ||
|
67e2c1d482 | ||
|
ad68883c5a | ||
|
32fcde6d9e | ||
|
df03357d19 | ||
|
808fed550d | ||
|
87fc8c772b | ||
|
6dbc9c1c53 | ||
|
7047964bd6 | ||
|
821ef5cbaf | ||
|
05ef5559c3 | ||
|
63d477b20e | ||
|
f9cae2acbe | ||
|
6841a53d17 | ||
|
4ab4330677 | ||
|
2aa24519da | ||
|
5d722b35d9 | ||
|
eba15fe905 | ||
|
76b736c242 | ||
|
ea5f21ceac | ||
|
8b6203b613 | ||
|
0f4ba145ee | ||
|
f2be77a5ab | ||
|
40adb4317b | ||
|
3e52785aae | ||
|
481dde8b70 | ||
|
93b5c31541 | ||
|
b663c7c5c3 | ||
|
4b19b2f4ba | ||
|
b32c7594a5 | ||
|
c8930105bc | ||
|
b1c112d35e | ||
|
4f9540f19f | ||
|
8153a7760e | ||
|
a018bb1da7 | ||
|
12d8029d56 | ||
|
d1aa1979b4 | ||
|
7a59913b1a | ||
|
0034a98eb1 | ||
|
eb3ace962d | ||
|
25be5c9cfc | ||
|
01a9c5b70e | ||
|
bbb9255562 | ||
|
3b71197fb8 | ||
|
f3e62199ea | ||
|
d7a9f15775 | ||
|
f576f568a3 | ||
|
9249e0b3f8 | ||
|
2b028dc55b | ||
|
33b4285eb1 | ||
|
ddb3d46533 | ||
|
27a27db73f | ||
|
91cab53a3e | ||
|
2cbed9d2a8 | ||
|
603547fa19 | ||
|
07f2df69c7 | ||
|
5158a33f15 | ||
|
1c6dae1291 | ||
|
cc79024761 | ||
|
45de99aa06 | ||
|
7d429125d2 | ||
|
6ce92aa523 | ||
|
9e9a17950a | ||
|
0eea8d69b2 | ||
|
8c4af5dacb | ||
|
982bc0e228 | ||
|
9bd2b7e7af | ||
|
5bd8aa5246 | ||
|
d7fb4dd170 | ||
|
584f016e99 | ||
|
0ac039f979 | ||
|
d5cb7cdeae | ||
|
69c9adb7d3 | ||
|
fced566714 | ||
|
47af265234 | ||
|
74d9850bb9 | ||
|
a1202648ff | ||
|
8d482accd1 | ||
|
971083d419 | ||
|
5e2a1195d7 | ||
|
39a13456c1 | ||
|
2f17d5fa8f | ||
|
95bbbc0418 | ||
|
97daeb0020 | ||
|
1a51898d2e | ||
|
476e788090 | ||
|
e2d400bea9 | ||
|
6df4a00bb9 | ||
|
7c13985fa1 | ||
|
d8f42ee21a | ||
|
a40d00c421 | ||
|
66b379785e | ||
|
d8cd4f6421 | ||
|
fc5c16f491 | ||
|
e9f1888560 | ||
|
eadaaa7f79 | ||
|
99ab11bb90 | ||
|
9174eb00e2 | ||
|
7c2665298a | ||
|
d9b7a5f01a | ||
|
4445169cb5 | ||
|
4269712d06 | ||
|
c203171ef6 | ||
|
6d37ab0a83 | ||
|
03db2f8c3d | ||
|
8197752d68 | ||
|
7baab8bd6c | ||
|
4d674897f3 | ||
|
935c04f33a | ||
|
975031bfcb | ||
|
5919a2944a | ||
|
5438356348 | ||
|
a908460adb | ||
|
ce053a14aa | ||
|
077208287b | ||
|
be0f4a4737 | ||
|
9200c6be90 | ||
|
6ec03d6745 | ||
|
6f2e0fac19 | ||
|
86299bbd35 | ||
|
fca38bcd0a | ||
|
70e620f791 | ||
|
490fee7d45 | ||
|
bf48d3ec29 | ||
|
a78381c399 | ||
|
0d76fc431a | ||
|
b2bde4a7d8 | ||
|
0e0c725224 | ||
|
ed9cd96bdb | ||
|
1bbc9d1ae4 | ||
|
2870559b2c | ||
|
597ab901b9 | ||
|
3e8fda0a70 | ||
|
d69b1fdb72 | ||
|
10aff57b26 | ||
|
198ba185c7 | ||
|
da9e44a620 | ||
|
c30c3f94c7 | ||
|
31d09f6ee9 | ||
|
492c09276d | ||
|
13180c1c49 | ||
|
68991ae240 | ||
|
7a44e4cde0 | ||
|
e5cffc07b3 | ||
|
1d8108b009 | ||
|
a0bba26919 | ||
|
ad2760ec80 | ||
|
4d8e3f54cc | ||
|
427f95c4e6 | ||
|
5a39bee635 | ||
|
7379d18018 | ||
|
f3b76bc1da | ||
|
a8c0b05052 | ||
|
8caf974dcd | ||
|
437ced91ec | ||
|
ca5ac19ea4 | ||
|
536e3692c6 | ||
|
5fe05d3eeb | ||
|
02dc5ea720 | ||
|
0f7bf67f83 | ||
|
e1ad4aa002 | ||
|
5bd44cf3c4 | ||
|
77c03221c9 | ||
|
d12ec5f796 | ||
|
dfd331b2c8 | ||
|
77103c7c03 | ||
|
4af4adc7ba | ||
|
a44c25c2f1 | ||
|
954d50b88a | ||
|
20889dbac6 | ||
|
a5ee0d6af8 | ||
|
b378669836 | ||
|
65978e6982 | ||
|
478f4aed63 | ||
|
37cbdeb1f2 | ||
|
e4134d5c0d | ||
|
d713b7ed45 | ||
|
8291893239 | ||
|
7e4ffa3fa9 | ||
|
b3ed92d88b | ||
|
08815cb1b9 | ||
|
1bc7a2aacd | ||
|
126a089382 | ||
|
42fa7a1951 | ||
|
d4d645d32a | ||
|
7ced56b356 | ||
|
5ef9e2632f | ||
|
48cc28e4ef | ||
|
96b473a0bd | ||
|
f70e1b315f | ||
|
704a19b25d | ||
|
d5b1e43b8f | ||
|
d16579971e | ||
|
0ec73a7892 | ||
|
afd4805278 | ||
|
24fef11e44 | ||
|
64c6f72988 | ||
|
edafcb2c39 | ||
|
e57b807a42 | ||
|
be8ff186d6 | ||
|
9484520327 | ||
|
a5f45b47a3 | ||
|
454b6a7cf5 | ||
|
483a1933a2 | ||
|
49dce504bf | ||
|
5da84141c4 | ||
|
44ab4d44e0 | ||
|
6791b8051a | ||
|
9d3590f375 | ||
|
35d180126a | ||
|
b835c28383 | ||
|
51fad48097 | ||
|
6b2ee07a26 | ||
|
203c683dff | ||
|
3cfc1ffb0a | ||
|
3b77e38b8e | ||
|
df86d855f5 | ||
|
f5e64a9eaa | ||
|
d431345bf3 | ||
|
30916df3d3 | ||
|
4f4dd2d995 | ||
|
287130a254 | ||
|
7145129f27 | ||
|
410a52b763 | ||
|
741c28ae9f | ||
|
e84b72710b | ||
|
e235763a38 | ||
|
4c30bf1667 | ||
|
cb53ce9f89 | ||
|
f463e50719 | ||
|
359ab384fd | ||
|
b11bdb9212 | ||
|
64609120d8 | ||
|
2990defea7 | ||
|
d7aa47ddb8 | ||
|
296040b1f4 | ||
|
033f882314 | ||
|
b615d195b2 | ||
|
c5c8f433e6 | ||
|
82190c7296 | ||
|
6f2a242193 | ||
|
6025938ee9 | ||
|
2659f7f740 | ||
|
a8fd1e3135 | ||
|
d78893921a | ||
|
e942499c66 | ||
|
9ba41b791e | ||
|
f3a6b0fd08 | ||
|
f061f39145 | ||
|
124b1141d7 | ||
|
6cba44277f | ||
|
f329397077 | ||
|
db7fef6e50 | ||
|
8b843732b3 | ||
|
eaf141c86a | ||
|
028eab9ebb | ||
|
7310a7cd0c | ||
|
4ecc01f3ad | ||
|
48ff8a95cc | ||
|
8e51b8b59c | ||
|
058a6e94a1 | ||
|
750c441dfd | ||
|
468d6616bf | ||
|
375c4eb31c | ||
|
034e7e153f | ||
|
0c6b616656 | ||
|
79a198bc08 | ||
|
7799f23627 | ||
|
1aa17222e7 | ||
|
29eb0be134 | ||
|
5491f9a9a9 | ||
|
a972dbd682 | ||
|
5563b09ac2 | ||
|
780e8b2332 | ||
|
12a19dcd84 | ||
|
235cd6c6b2 | ||
|
bcea83ab9b | ||
|
37dcdac218 | ||
|
ba513805d0 | ||
|
f8c0d92a22 | ||
|
75d7e053dc | ||
|
010c3718e3 | ||
|
531dbd7af5 | ||
|
3f8ca3553d | ||
|
eb68c5e747 | ||
|
e0b065cc33 | ||
|
2da589d454 | ||
|
738b16d873 | ||
|
82bb3d8d2b | ||
|
4e709e75da | ||
|
c471255153 | ||
|
ee79423124 | ||
|
0761240c43 | ||
|
ddd33c6bbd | ||
|
aad2dbb93d | ||
|
47063ca3ae | ||
|
9c2cd65c0d | ||
|
93d050f504 | ||
|
ad0c928ab5 | ||
|
1198fe8f6b | ||
|
20900b76f9 | ||
|
995da1e51d | ||
|
c74a083672 | ||
|
9f9d57590b | ||
|
534858aaed | ||
|
7c360778bb | ||
|
e21ff6c0c9 | ||
|
948f55d0b7 | ||
|
fa5c13542c | ||
|
077049d0b9 | ||
|
6846c63252 | ||
|
9d1e690751 | ||
|
6552441b46 | ||
|
8d514f4e2e | ||
|
c219b09d4a | ||
|
e11555218b | ||
|
37b908aa62 | ||
|
96635e9e18 | ||
|
41f235a2f8 | ||
|
1ead2dd35d | ||
|
dab9ffb252 | ||
|
e1db9e9848 | ||
|
6b7705d5b2 | ||
|
92975f0c11 | ||
|
2a59188760 | ||
|
f93cfb2e31 | ||
|
16e6d8af55 | ||
|
0c2699da27 | ||
|
79c72390b9 | ||
|
193f16238b | ||
|
f2c0df5cd6 | ||
|
81e7cd9339 | ||
|
509015b498 | ||
|
f9e2eed55d | ||
|
cdac084fb4 | ||
|
c395496e06 | ||
|
1370b3c679 | ||
|
f7f0a17ea2 | ||
|
d93d3e2d75 | ||
|
2cb982b506 | ||
|
b39362295a | ||
|
1d0bb72c5b | ||
|
b1ead679f3 | ||
|
ee9fe2c838 | ||
|
3379414c76 | ||
|
5e4878ed2b | ||
|
06b991f48f | ||
|
e57479dc30 | ||
|
ecfa4f5866 | ||
|
93e65a2a6c | ||
|
daa3166cb6 | ||
|
ce2e6b5cda | ||
|
0a126a85a4 | ||
|
ebcb230cff | ||
|
749d7449f9 | ||
|
8b7ec57cb4 | ||
|
6fee7c8f8b | ||
|
1686540594 | ||
|
080844b9b3 | ||
|
8c301fa933 | ||
|
43007108e6 | ||
|
e3f20f5088 | ||
|
83477ce8d0 | ||
|
e4ce676d3d | ||
|
d29240d9eb | ||
|
21dcbada2d | ||
|
93853eca94 | ||
|
c5c977855d | ||
|
68ebfa2f18 | ||
|
27698f1d13 | ||
|
462d6ef826 | ||
|
e477a57cc5 | ||
|
a0e1155b28 | ||
|
6b1b71ced4 | ||
|
49b55b220e | ||
|
079a9d4562 | ||
|
41261ea4ec | ||
|
c57097bcd4 | ||
|
5b3acc15d1 | ||
|
f9a83daebb | ||
|
8b167535db | ||
|
7366e44019 | ||
|
7d548c6c00 | ||
|
a490248f4d | ||
|
c90229ed9a | ||
|
3aef732e61 | ||
|
98d3da79ef | ||
|
d519bde5da | ||
|
1980deffae | ||
|
b60c02b065 | ||
|
a2e9ae0055 | ||
|
065b00b787 | ||
|
bf42ccfbec | ||
|
c9397ec8d4 | ||
|
c87c4b5bbf | ||
|
0066138379 | ||
|
d8056ddecd | ||
|
e4c866f387 | ||
|
2216d3ca8d | ||
|
2ab2503b6c | ||
|
914888cf8b | ||
|
51bcf5954f | ||
|
96ca669fa4 | ||
|
e77f9d2327 | ||
|
ab9ff592c5 | ||
|
a940462fc7 | ||
|
6817b3697b | ||
|
51bbcdb3c5 | ||
|
0921360133 | ||
|
98592608d4 | ||
|
126525c03e | ||
|
b216669a02 | ||
|
753c190ef9 | ||
|
d1ebe6689f | ||
|
afe8d3076f | ||
|
16f80f649b | ||
|
42653787ea | ||
|
ea4baa24b1 | ||
|
04e54c6bb0 | ||
|
829374337f | ||
|
9717734d1c | ||
|
9bb0e7a5ee | ||
|
564a13285f | ||
|
0fc6bf9a6e | ||
|
f0127f1617 | ||
|
e97492e579 | ||
|
11c6ec6eb2 | ||
|
6fb6635ceb | ||
|
cdcb7c28c5 | ||
|
ce00af8590 | ||
|
9cee34bc94 | ||
|
ba02bbb3b4 | ||
|
569e1a4b77 | ||
|
3721a525ce | ||
|
b8220f5d0d | ||
|
11abd0742e | ||
|
6944d2dddb | ||
|
2fd88c7ca4 | ||
|
cda187222e | ||
|
bc80c5d067 | ||
|
332ffe8d74 | ||
|
4c4149a09c | ||
|
4d09e60f5b | ||
|
c14a9f5b3d | ||
|
e21e802fc6 | ||
|
58d2f21dae | ||
|
a3b0181503 | ||
|
2409a36e29 | ||
|
824abbf8d9 | ||
|
e9b6965079 | ||
|
b32e41f016 | ||
|
7e7c7bbc17 | ||
|
95b96eebdd | ||
|
fb61b07bcf | ||
|
c94ccd4207 | ||
|
acfd3934a7 | ||
|
b576682bdc | ||
|
c37b58bbc3 | ||
|
e515bef423 | ||
|
a373983a86 | ||
|
05988f88b7 | ||
|
ec11aea880 | ||
|
fded42c3bd | ||
|
1da079f211 | ||
|
84000190d3 | ||
|
ddec605aef | ||
|
96a1c444cc | ||
|
0db4a32b9c | ||
|
4e69e16fde | ||
|
c3d533f37f | ||
|
02815416bb | ||
|
6331a3a346 | ||
|
2f61620339 | ||
|
202907b14c | ||
|
4ee0cf6878 | ||
|
a1c9a686b0 | ||
|
20364bd658 | ||
|
8846c7e0ae | ||
|
99a8e53573 | ||
|
6dff1b8c82 | ||
|
8ea78b34ab | ||
|
9f4acceb6a | ||
|
cffe563d4d | ||
|
6b6fed06b1 | ||
|
46c7319f02 | ||
|
c3020d8cdb | ||
|
94c975e25a | ||
|
9ffca1fedd | ||
|
754bc52a79 | ||
|
42690b6d57 | ||
|
2ea6794c97 | ||
|
f6258f70cb | ||
|
892e9f2c23 | ||
|
a4bdfb963f | ||
|
85ccb25eb8 | ||
|
aba8e04ab1 | ||
|
3e4c9d90cf | ||
|
7055244547 | ||
|
ed0dbb8518 | ||
|
b770a50dee | ||
|
18d77ff455 | ||
|
92f1ddaf0a | ||
|
70f57409c3 | ||
|
e8f206972a | ||
|
e58a60902c | ||
|
3c905d0db9 | ||
|
e4d809b2b0 | ||
|
a61494e634 | ||
|
f379af6d17 | ||
|
75ee002347 | ||
|
e638351ef9 | ||
|
a93298d4db | ||
|
a6d5db3f9b | ||
|
2b0655a71a | ||
|
a96e6044cc | ||
|
647ed1d205 | ||
|
13472c6cf1 | ||
|
b6ad25bf5e | ||
|
40908c5fcd | ||
|
97285711f3 | ||
|
a718ccd0c5 | ||
|
d547477bc2 | ||
|
264dbad43a | ||
|
ec79d0fc05 | ||
|
eaa9494b71 | ||
|
03390be5fa | ||
|
252e94f499 | ||
|
3229517b2c | ||
|
b8ac06d9d1 | ||
|
7747327561 | ||
|
60d2eeaa5b | ||
|
14de8ba4ea | ||
|
46cf8cecc8 | ||
|
fc7a3befda | ||
|
a2154e1249 | ||
|
a764cd5a40 | ||
|
210932b3bf | ||
|
e236994b76 | ||
|
9213e35011 | ||
|
4b3900a257 | ||
|
050de1e4f6 | ||
|
a083677af2 | ||
|
74db0e9339 | ||
|
48124bac18 | ||
|
011a32a4ad | ||
|
7ed5a30b5c | ||
|
bb5a1eb99d | ||
|
1437037ed2 | ||
|
f930559076 | ||
|
1216328c2d | ||
|
651086d1d9 | ||
|
1291bbfa50 | ||
|
79af23e1ea | ||
|
ac1514abf4 | ||
|
99968eec3f | ||
|
f18ac2d0bc | ||
|
b2663a0f73 | ||
|
83b2daca6a | ||
|
169fab5146 | ||
|
4175a550fd | ||
|
091991606a | ||
|
784ba59a08 | ||
|
dd5ea7e996 | ||
|
bba21735bf | ||
|
0b75c02276 | ||
|
801cd50744 | ||
|
6187ada21f | ||
|
882f7bbf1f | ||
|
32e716e848 | ||
|
65e2149b3e | ||
|
1cd937a867 | ||
|
540e150e4e | ||
|
fffcbdae4c | ||
|
6f3fcbcfe1 | ||
|
eb6437b4db | ||
|
defa8ba7b4 | ||
|
f349754b55 | ||
|
3af2963c74 | ||
|
dc17f5e613 | ||
|
485977de57 | ||
|
2cc5c2d2e6 | ||
|
e74028554e | ||
|
7b02ccda86 | ||
|
17a35bc645 | ||
|
d2a6956afb | ||
|
8d923c60b9 | ||
|
425ccb1241 | ||
|
c0edf0861b | ||
|
5cc1c6eca0 | ||
|
bb5ace2efb | ||
|
9bd3e011e1 | ||
|
89a4e6b889 | ||
|
846bcd7dd1 | ||
|
b7f5db432f | ||
|
2d12dc3a58 | ||
|
316c7331eb | ||
|
fb017754e1 | ||
|
ee2ac6c205 | ||
|
47276bdb28 | ||
|
0af6d9e291 | ||
|
3146ecbae6 | ||
|
b9833a2059 | ||
|
540d6539be | ||
|
3e0565e17c | ||
|
9d4abbbc30 | ||
|
6592646632 | ||
|
5e9a354ff1 | ||
|
2aac054f52 | ||
|
f7552f1de4 | ||
|
7c697f58f2 | ||
|
a1d2132bf6 | ||
|
225e2562c9 | ||
|
a31411c679 | ||
|
4c281fb29a | ||
|
a08abec9f8 | ||
|
d2452c2102 | ||
|
b335e3d305 | ||
|
6d3bcd8017 | ||
|
8caf63896c | ||
|
a78c06e3f0 | ||
|
5f48fc36e1 | ||
|
647c2a6cdd | ||
|
7f8b1cd7f9 | ||
|
33565f1533 | ||
|
d8bc5828cd | ||
|
fdc9b7cceb | ||
|
9f6dbbc7ea | ||
|
24ad2e5db6 | ||
|
19bd0730ef | ||
|
b1569b9c18 | ||
|
e2dad6c3ff | ||
|
8d4982ed33 | ||
|
1741771b67 | ||
|
7d7225fae6 | ||
|
e60cda7051 | ||
|
d18b89ced6 | ||
|
b873d70369 | ||
|
5d25143ef3 | ||
|
3887475971 | ||
|
8805e38398 | ||
|
ddae599cab | ||
|
dd1c95edcd | ||
|
3c1de2e667 | ||
|
ddd9665289 | ||
|
6876e45f9e | ||
|
0aca7f2a0d | ||
|
db381fb21b | ||
|
0215a62d5b | ||
|
56261fabcb | ||
|
76d8bfdff4 | ||
|
325786430b | ||
|
0fe2ac0437 | ||
|
7dd547c5ff | ||
|
74da6a6363 | ||
|
da05a2ef7f | ||
|
cdb1293eea | ||
|
165dfd6c3e | ||
|
8d070e30f5 | ||
|
5dbb5cc3e5 | ||
|
786c9adaa2 | ||
|
3b28a24e97 | ||
|
eb76c93098 | ||
|
b3843992fc | ||
|
5ff7be32f0 | ||
|
e010223186 | ||
|
21e50b89c9 | ||
|
404160ad87 | ||
|
ab60412cb4 | ||
|
21c0a54a6b | ||
|
66c497c5f1 | ||
|
3ecceafa32 | ||
|
4d831949a7 | ||
|
fc94ed0a86 | ||
|
3fae7ea16f | ||
|
19d860fa9d | ||
|
cfa08f8366 | ||
|
97455cc31f | ||
|
d2e7a6e799 | ||
|
98a44bb18e | ||
|
a9788886e6 | ||
|
3ba67ee214 | ||
|
2a6ff3c24f | ||
|
4bef3e9ed3 | ||
|
59b5c6075f | ||
|
ed798d651a | ||
|
3cc5d62f8a | ||
|
e1c92184f0 | ||
|
78cf11575d | ||
|
32acecbf5e | ||
|
71589848a0 | ||
|
2b402ff8b7 | ||
|
f139017bd0 | ||
|
a6048fc792 | ||
|
197b0b16e3 | ||
|
1f9eb9ab07 | ||
|
c7d4f2afdb | ||
|
038a361a91 | ||
|
d41d2c3751 | ||
|
32d58144fd | ||
|
8a094fe609 | ||
|
dea870f4ea | ||
|
8c4dfc9e6a | ||
|
0b1c1877c5 | ||
|
9ff169ccf4 | ||
|
1aae94074e | ||
|
ccfc2e5d8d | ||
|
0f9c8e684a | ||
|
5433b88e2d | ||
|
9aecb906fb | ||
|
800ea039ec | ||
|
49f76a34b5 | ||
|
17c99f7164 | ||
|
717cd0aaa8 | ||
|
1916c996d6 | ||
|
1910fdde81 | ||
|
4d34c1cd68 | ||
|
d63569c73d | ||
|
7bdeb1dfc1 | ||
|
ff7ca32b79 | ||
|
79c7d26495 | ||
|
4295806736 | ||
|
ff2342154b | ||
|
cc51f0b3d3 | ||
|
0f6eeecac0 | ||
|
d222bf097c | ||
|
0b592467d9 | ||
|
742ac6e275 | ||
|
038449467e | ||
|
982e4fb448 | ||
|
d099e47e00 | ||
|
a6da1480b5 | ||
|
9a1f2e6d7c | ||
|
ff40d2d787 | ||
|
eb9a5392bc | ||
|
c679da9ae1 | ||
|
90e87c4753 | ||
|
66137ae429 | ||
|
06aaf87aab | ||
|
637ca59375 | ||
|
8d67d0c1a8 | ||
|
4d3238dc0b | ||
|
b08bff8ba3 | ||
|
5210f48bfc | ||
|
fabc1d5bef | ||
|
abc05cf335 | ||
|
988f5ac342 | ||
|
d43b398746 | ||
|
a25434654e | ||
|
1178319313 | ||
|
50eb2d2782 | ||
|
18bf3aa442 | ||
|
ed32f5e241 | ||
|
2cd23ffeec | ||
|
d58df1fc6c | ||
|
098b0fd1a0 | ||
|
44124ab6b0 | ||
|
3a643154be | ||
|
5efe72415d | ||
|
fd72b134d5 | ||
|
735537d6b1 | ||
|
1eaea43581 | ||
|
7daaa00120 | ||
|
f1ca793980 | ||
|
1e55ace875 | ||
|
2ebd97dec1 | ||
|
487ea81316 | ||
|
8f7bbc39a4 | ||
|
9a692a3802 | ||
|
e410e27547 | ||
|
13fb24458c | ||
|
b42e367045 | ||
|
0db4174513 | ||
|
37d4b0bee9 | ||
|
88f6a92d22 | ||
|
a4c54362c3 | ||
|
fb7ec1555c | ||
|
79ca6630d4 | ||
|
d5dc675d37 | ||
|
10505cac52 | ||
|
5045a2de24 | ||
|
3512b04093 | ||
|
1b28b0ed5a | ||
|
02c9f038b3 | ||
|
b9b8b6597a | ||
|
f1d5385515 | ||
|
91b976ba46 | ||
|
f17c9e4aeb | ||
|
df5deab20b | ||
|
9b9c5242eb | ||
|
7e01865fb6 | ||
|
1e3cdd3512 | ||
|
53d1b12bc0 | ||
|
c5126d1435 | ||
|
a7bc65fbd8 | ||
|
1d68544fbf | ||
|
cf4df9d8ae | ||
|
6506579e18 | ||
|
a93aadc2e6 | ||
|
3a31f81838 | ||
|
4373547857 | ||
|
d3d2823edf | ||
|
86108812b8 | ||
|
ddd67b2535 | ||
|
6e98a7f2c9 | ||
|
ecbd126d6a | ||
|
7796891381 | ||
|
871cf72363 | ||
|
49f8e4f1e3 | ||
|
6d79864135 | ||
|
d4f3858a40 | ||
|
0cc6e445d7 | ||
|
411a9e1b86 | ||
|
424a1c5d21 | ||
|
ab35df454d | ||
|
87f8be8110 | ||
|
34964c2454 | ||
|
cb14534d78 | ||
|
2d3a1418c2 | ||
|
61757032da | ||
|
1545693255 | ||
|
6e4bd3bbc2 | ||
|
f8dec8f1c6 | ||
|
6690d2969c | ||
|
0cdfd5f275 | ||
|
ccd834ea25 | ||
|
41356227f2 | ||
|
1b3c2743cc | ||
|
50d2c94bd6 | ||
|
6d139e5e95 | ||
|
054add40a1 | ||
|
7a821d4c99 | ||
|
668af4be82 | ||
|
de9f12ea96 | ||
|
1be26e9f0c | ||
|
b42c65d796 | ||
|
f450ea64e6 | ||
|
f3645a2aa3 | ||
|
3b15156e4d | ||
|
2ea5c1af57 | ||
|
0d8087fbbc | ||
|
405f4589a6 | ||
|
967c7bc5d3 | ||
|
3ceb3810d7 | ||
|
ae737656f9 | ||
|
c2630c93f2 | ||
|
dedf5747cc | ||
|
7ec9561a77 | ||
|
5a200ade7c | ||
|
1371aee3cc | ||
|
9548916aa8 | ||
|
72b2469be0 | ||
|
484785456c | ||
|
be220af9fb | ||
|
bafcfdf8c5 | ||
|
5d5f2e3a93 | ||
|
348a79958d | ||
|
2f0ba0a7e5 | ||
|
9e6370819b | ||
|
46ce4ec8cf | ||
|
9983d896de | ||
|
7c43e8c45a | ||
|
f0791afade | ||
|
135d8f04f9 | ||
|
ae1ca67178 | ||
|
d922f94d93 | ||
|
3309e45ca1 | ||
|
2ad499f93e | ||
|
bd6868557d | ||
|
7821d2d788 | ||
|
e46674b6a7 | ||
|
e58c267d66 | ||
|
3b443c8cfc | ||
|
8d76acfe6c | ||
|
56fb56ccf0 | ||
|
0538cdd226 | ||
|
66ff1e063e | ||
|
685b3d820a | ||
|
f70d9933d1 | ||
|
9e817251a8 | ||
|
17882ed614 | ||
|
3f7fde76c2 | ||
|
4603b6d6b6 | ||
|
03885e1b00 | ||
|
4e0319c878 | ||
|
b07d2a3827 | ||
|
9e43c11480 | ||
|
5fee4439a0 | ||
|
563fc92dd4 | ||
|
b587c5a2f8 | ||
|
e8be792130 | ||
|
e3e715666f | ||
|
06221297bf | ||
|
a8b1ce2447 | ||
|
71d7908656 | ||
|
ecaab085db | ||
|
f445ee1e6c | ||
|
307b09e7eb | ||
|
c651a53558 | ||
|
d9d9950d8d | ||
|
2ad37e1832 | ||
|
cad97135b3 | ||
|
de363f1404 | ||
|
fb96b94ed0 | ||
|
316781be48 | ||
|
9c14f98583 | ||
|
55608d8381 | ||
|
a3b12ec420 | ||
|
dc76b90705 | ||
|
7d0488b11e | ||
|
152c482fee | ||
|
913b0f51ca | ||
|
fdc7a78652 | ||
|
88f4bf4ae4 | ||
|
fd0b109bf7 | ||
|
8d9a40a820 | ||
|
acce6043e0 | ||
|
a87313497b | ||
|
43b1afb2cf | ||
|
5f36d4af15 | ||
|
698fa85f38 | ||
|
8a4b095a94 | ||
|
0e8eea5a70 | ||
|
2b6761fd3e | ||
|
7d7749ee47 | ||
|
5c052e6c04 | ||
|
506b86773d | ||
|
3e6092f5b2 | ||
|
05cb0e5a7d | ||
|
4cadee65b3 | ||
|
2adec6c8c0 | ||
|
66cf0e3f55 | ||
|
dbb48e4b29 | ||
|
b7e8868235 | ||
|
1c2d8c8663 | ||
|
ab0377746a | ||
|
bf3c156654 | ||
|
c1d420ec60 | ||
|
0df38c3e2b | ||
|
0ea9305f99 | ||
|
8d375b44eb | ||
|
167fa429f0 | ||
|
bf5ae17c16 | ||
|
9613da63dc | ||
|
e510abbc8c | ||
|
3eebf4d162 | ||
|
e22758bfb2 | ||
|
8142051a3b | ||
|
0ea41eaa51 | ||
|
021e89d702 | ||
|
dffad6b0b7 | ||
|
3a4158e4fa | ||
|
939a4eb5c9 | ||
|
17feabcba0 | ||
|
4e2f000b3c | ||
|
3cad7f99e0 | ||
|
04f21d86cf | ||
|
44a6587608 | ||
|
1e9ebfb00c | ||
|
9d8fcb3296 | ||
|
a813d7e961 | ||
|
881fff1a2f | ||
|
e974599593 | ||
|
1845a915b0 | ||
|
4597f50deb | ||
|
751888979c | ||
|
0ffd3225d2 | ||
|
2d0e899819 | ||
|
f117aef2ea | ||
|
c80f205f86 | ||
|
31bf00d3ec | ||
|
3eca54384d | ||
|
79dd264517 | ||
|
56fbbde2ed | ||
|
820975595c | ||
|
93c7b25ccd | ||
|
43378636d0 | ||
|
73c637ad60 | ||
|
fc1e698914 | ||
|
55d18b7db9 | ||
|
630fc3839e | ||
|
489543cd25 | ||
|
8ff481b436 | ||
|
ce3ad31e2e | ||
|
12bf850c84 | ||
|
18a0ab6b3b | ||
|
520aa08d42 | ||
|
52af6d957e | ||
|
993ca8c6de | ||
|
0f3c5d3893 | ||
|
a1e1038736 | ||
|
9fe5ac6614 | ||
|
214e200f95 | ||
|
2379b49177 | ||
|
16d5d4b6e1 | ||
|
0970cb054c | ||
|
801202349a | ||
|
2d31697d82 | ||
|
d8b784a15e | ||
|
da8e07edb5 | ||
|
c0c4a16053 | ||
|
b6154189e8 | ||
|
1bc0d7080a | ||
|
5bc0832766 | ||
|
081b5e3d4e | ||
|
7665feeb52 | ||
|
5400366b90 | ||
|
a343ed13e5 | ||
|
ed7b2a64f8 | ||
|
aca8dde362 | ||
|
599a258421 | ||
|
fd03a52468 | ||
|
391f9635cc | ||
|
4ec063fade | ||
|
f66684fdeb | ||
|
c399963243 | ||
|
7d9bb170b7 | ||
|
9ff00e35f8 | ||
|
4876c09b2a | ||
|
8df3db4b97 | ||
|
117ceac82b | ||
|
e502c69140 | ||
|
9791756284 | ||
|
c33b31116c | ||
|
dc11d2a2d8 | ||
|
54a125f677 | ||
|
81359cecdf | ||
|
660c04803e | ||
|
f9ea1dac30 | ||
|
38e791fb2f | ||
|
d0df6c983c | ||
|
5745ba6a8e | ||
|
005150ed69 | ||
|
f72548956f | ||
|
bbb94fd499 | ||
|
46c27e4552 | ||
|
4ecb587eff | ||
|
a82c434447 | ||
|
1261fe69a3 | ||
|
20a1d23b39 | ||
|
eb7738221c | ||
|
7103efac9d | ||
|
e7980275c0 | ||
|
1e1efe1f61 | ||
|
ad2ab4927c | ||
|
9a9dfb1d0d | ||
|
3903f16cd6 | ||
|
5bf405b2af | ||
|
5b1282c708 | ||
|
d81e0f5789 | ||
|
2fbbd04979 | ||
|
890959eea8 | ||
|
bc37e3f830 | ||
|
d69f9fe266 | ||
|
cca3af03ac | ||
|
61656464d8 | ||
|
f846349824 | ||
|
d89590eab9 | ||
|
e6ac640d2e | ||
|
f531e3cf69 | ||
|
3886faced8 | ||
|
d0efca893b | ||
|
9bc78bdc5b | ||
|
93e5c99fff | ||
|
7fe0f73838 | ||
|
9b83875c13 | ||
|
9cb5da400c | ||
|
45483a1d0d | ||
|
86183ebf55 | ||
|
edf802956e | ||
|
a948ee9601 | ||
|
03fc3aad12 | ||
|
3d0bdfaa70 | ||
|
5a922dc162 | ||
|
49fa3d82b7 | ||
|
f696a1b3b3 | ||
|
8cf66ed732 | ||
|
c957ad0067 | ||
|
0154746b9f | ||
|
f645a6d43e | ||
|
860db986fc | ||
|
74a0fdf961 | ||
|
e5dbd28afd | ||
|
3ce6efc4dd | ||
|
106c694993 | ||
|
a5d46a15f5 | ||
|
893d28469f | ||
|
f66374f6a8 | ||
|
81e62af94a | ||
|
f691b13450 | ||
|
5c78cbd3be | ||
|
cf9a76fe8f | ||
|
790dd8cc92 | ||
|
87019144f6 | ||
|
7ca38d64d2 | ||
|
9434919f76 | ||
|
be4abf9d6e | ||
|
41a230758c | ||
|
70229b55ec | ||
|
dd3b71d17c | ||
|
1bdceb8a65 | ||
|
3f09316e3b | ||
|
b52765c8c9 | ||
|
79bf167c0d | ||
|
8ed900263e | ||
|
1d46597c8b | ||
|
f32f09e78f | ||
|
b67446a8fa | ||
|
8aa1060c34 | ||
|
e3708a89cc | ||
|
e251837445 | ||
|
644e3d4cdb | ||
|
f8b5fe5724 | ||
|
c8d2c6ea77 | ||
|
0fa873c0fe | ||
|
00037cd44b | ||
|
e0f36f9d8b | ||
|
bea751beb7 | ||
|
ba47cdcc0b | ||
|
4aa2876c75 | ||
|
58c027ac8b | ||
|
4d04068184 | ||
|
1e195acee4 | ||
|
e8a79114b8 | ||
|
f6cc8e3512 | ||
|
465cbccdaf | ||
|
be541997af | ||
|
c2c83e16a2 | ||
|
c8f8d11ac4 | ||
|
878ee341d6 | ||
|
1b178dffa3 | ||
|
2fa8f54d08 | ||
|
705cd2cabe | ||
|
36d28b73fc | ||
|
5530226366 | ||
|
750218c5e5 | ||
|
36935bd869 | ||
|
816cd9802f | ||
|
3beda17773 | ||
|
781740c19d | ||
|
92e38b6e27 | ||
|
773a9d85a1 | ||
|
00545ef4d6 | ||
|
e59f7fba6a | ||
|
d2a5948ae8 | ||
|
348f83670a | ||
|
6b9968e8b1 | ||
|
d94d51d00b | ||
|
126e212fb0 | ||
|
ae64fd8d6f | ||
|
027f70562e | ||
|
e1dd9c0396 | ||
|
4a34c501c1 | ||
|
cb788bea9c | ||
|
013e44ec5d | ||
|
c9012c798e | ||
|
0fa65ad6d5 | ||
|
f6b50d52d4 | ||
|
61a0e79ad6 | ||
|
b8e963595e | ||
|
0233029d5a | ||
|
c733cf223d | ||
|
7c93e4a09b | ||
|
a0ef2ac59c | ||
|
f537ef5746 | ||
|
0656059ae7 | ||
|
49d1e1c9b1 | ||
|
328de8442d | ||
|
ea13744e53 | ||
|
f7b6aefe0e | ||
|
9c63abbfe7 | ||
|
a75354c045 | ||
|
e7393d0fc5 | ||
|
15b9176d53 | ||
|
efc7a2abc3 | ||
|
77be7b777c | ||
|
a17029ba49 | ||
|
24804e67f5 | ||
|
845b328734 | ||
|
4c459ddabd | ||
|
e85c69e1b7 | ||
|
f09b1022aa | ||
|
d0f6fa036b | ||
|
77053da5c6 | ||
|
9e3a6ccf69 | ||
|
713c9280ca | ||
|
0d761d19b9 | ||
|
5a9201ff47 | ||
|
85f1a2809f | ||
|
4f511bd06e | ||
|
bb2c5617d6 | ||
|
cba6f2d426 | ||
|
54130b542d | ||
|
0a334ea081 | ||
|
17d94cf3b9 | ||
|
6f4ccb6832 | ||
|
988d26afe4 | ||
|
270d4ec23d | ||
|
6caaa8cadc | ||
|
bae49ff278 | ||
|
4f48a4ea2a | ||
|
0fa7a4e3b4 | ||
|
d7e6e33d07 | ||
|
965eda3b9a | ||
|
66dfc0169f | ||
|
1855a55d8c | ||
|
72dc7a0f7b | ||
|
b19dbee3f7 | ||
|
c7ccc68b15 | ||
|
be34e93f20 | ||
|
cb76638699 | ||
|
88992de283 | ||
|
fed1c96e10 | ||
|
7489b51f61 | ||
|
2cf6389142 | ||
|
f5050d4ef2 | ||
|
0ac3bf837b | ||
|
8c87641258 | ||
|
c14463d1e4 | ||
|
90e82a2c05 | ||
|
105b9834fb | ||
|
44cf27b5fc | ||
|
142f46cac1 | ||
|
0ac02ba342 | ||
|
ab131642a1 | ||
|
b98c05dc50 | ||
|
664c0d3201 | ||
|
3e4ce10342 | ||
|
0a2e3f14e7 | ||
|
bc1dec71c5 | ||
|
9752e43644 | ||
|
d4fd582fb2 | ||
|
58504620c5 | ||
|
6f0e28d024 | ||
|
53c813961e | ||
|
c76331e13f | ||
|
e828895f20 | ||
|
2d49080056 | ||
|
6a8964b75b | ||
|
a082bbcb30 | ||
|
1c84f63a40 | ||
|
889427b334 | ||
|
a050db4a6f | ||
|
09d39c023c | ||
|
3b569cc686 | ||
|
bbeaeee3c7 | ||
|
9db5dc9a46 | ||
|
d742188e3b | ||
|
3a8c97be45 | ||
|
605e8f53b1 | ||
|
34303ccd55 | ||
|
127cd9def1 | ||
|
2987393768 | ||
|
ee17ecbd39 | ||
|
5e9ecffb4f | ||
|
146df5fbd3 | ||
|
8224c74f08 | ||
|
058a31e479 | ||
|
a2c29e9128 | ||
|
7531f05c7c | ||
|
7b3acdff5d | ||
|
3991faf464 | ||
|
2fa66cfce2 | ||
|
06619763a2 | ||
|
a1f6a70522 | ||
|
1816fb66c7 | ||
|
02dec48bab | ||
|
40ff225b8e | ||
|
37a9d6aabe | ||
|
c7d2c2aa9f | ||
|
3bbffe96e1 | ||
|
6f14c8ee5a | ||
|
06d843c2c4 | ||
|
af677245fb | ||
|
8f716ca06a | ||
|
ad9d70b0e6 | ||
|
239e0a2d43 | ||
|
e528b227a6 | ||
|
e807ae4f2e | ||
|
44d0522848 | ||
|
a8f5c524a0 | ||
|
d7e5708bb4 | ||
|
45ee4d7c78 | ||
|
0bcdbbeedc | ||
|
7cda1fc4b6 | ||
|
4026148ef1 | ||
|
a0741cacef | ||
|
088aff1620 | ||
|
b3428bcf88 | ||
|
f8b468fda2 | ||
|
bba77163ff | ||
|
f61142cce5 | ||
|
c55662f247 | ||
|
b0b3c62a84 | ||
|
117cdb28ce | ||
|
6f719c74a9 | ||
|
608a122aef | ||
|
74dbb721aa | ||
|
17f17c284c | ||
|
a34060cdb4 | ||
|
168ca2dcc8 | ||
|
22f303e422 | ||
|
f52e935f36 | ||
|
f71439d527 | ||
|
669940065f | ||
|
520dc12c0e | ||
|
293c814688 | ||
|
c477cda59f | ||
|
3e4c4df664 | ||
|
324290a5eb | ||
|
de90b5e9ad | ||
|
11261594d8 | ||
|
e3215702ae | ||
|
2323f9deda | ||
|
9822185d53 | ||
|
6588b3eef0 | ||
|
a026f3be4b | ||
|
4ea1c9f8e5 | ||
|
e068c38618 | ||
|
7aa36717bb | ||
|
fb5df9722b | ||
|
a9e7360775 | ||
|
7568bbc491 | ||
|
e979518a69 | ||
|
47e9caede7 | ||
|
0c751f904f | ||
|
be39be87f6 | ||
|
91c2b12205 | ||
|
19ad4ac03d | ||
|
a48f19157a | ||
|
ef6f5367dc | ||
|
5997ad8512 | ||
|
0a6a726d26 | ||
|
248745004a | ||
|
0021339b92 | ||
|
0ffaa6c785 | ||
|
3c59ef247f | ||
|
01dbe23b6f | ||
|
8273db28f3 | ||
|
9a8b45c133 | ||
|
18ac200efe | ||
|
2f0e308c7d | ||
|
a9f17a28db | ||
|
88f6b637a0 | ||
|
855c684708 | ||
|
ca2fe6859f | ||
|
f8791db4be | ||
|
89ac2061f5 | ||
|
cd779dae46 | ||
|
d4e7a87b96 | ||
|
10a7435ebb | ||
|
3606d6a7cd | ||
|
73db49f8ef | ||
|
2f9e3cca3d | ||
|
432390c4c4 | ||
|
99a65dc93e | ||
|
8657c87c8c | ||
|
9f6649b248 | ||
|
5c1d6c957b | ||
|
68fe202f06 | ||
|
6c81e2ce3f | ||
|
bc0392af66 | ||
|
e5008ced28 | ||
|
c97db54e54 | ||
|
50d7164978 | ||
|
bb21e0f191 | ||
|
d6c4e17411 | ||
|
782a369f92 | ||
|
a4a3efb75b | ||
|
a770153af0 | ||
|
9104cd5441 | ||
|
530974e724 | ||
|
a27953f716 | ||
|
b0eed5ade6 | ||
|
4a886a3e8f | ||
|
e40c4c997e | ||
|
c030f7f40d | ||
|
f8cfd3a61f | ||
|
faaa4fdf18 | ||
|
8f5a9a741b | ||
|
25b51cad3d | ||
|
a1f7c644be | ||
|
e6258e6590 | ||
|
9cf8c4f689 | ||
|
854ec3ffb3 | ||
|
51cdd7ceac | ||
|
860e83e52f | ||
|
8a35fb0d1c | ||
|
0bd30e90bb | ||
|
92aa6e6282 | ||
|
78792eae68 | ||
|
94feb31516 | ||
|
b62445871e | ||
|
4e27640076 | ||
|
81f9f90e47 | ||
|
243a55d603 | ||
|
c4c54683a9 | ||
|
174802e15f | ||
|
93fb9db1b0 | ||
|
33eb63e380 | ||
|
efb6950299 | ||
|
dacec4ec82 | ||
|
a4e3c67e44 | ||
|
e66995d840 | ||
|
713e02e03e | ||
|
97921915a8 | ||
|
0c68b655f6 | ||
|
dea3f2b417 | ||
|
02b8412572 | ||
|
b8b68e6ea9 | ||
|
a36286cf89 | ||
|
c7de76569e | ||
|
a53b44a266 | ||
|
c910e47f53 | ||
|
c53e22af19 | ||
|
046cc9e776 | ||
|
d31fa84c7c | ||
|
3539452ef0 | ||
|
3ba527d82a | ||
|
5287b2ddbf | ||
|
2b654b37f1 | ||
|
2e19a4d56b | ||
|
7008a51449 | ||
|
b138373c6d | ||
|
0e43963acb | ||
|
eaeaa7b7fd | ||
|
335907d187 | ||
|
80f8432b52 | ||
|
5f369ff1d4 | ||
|
bedb338dad | ||
|
62be425bcc | ||
|
afc6e3fa46 | ||
|
b3a8b6b198 | ||
|
eaa56afda9 | ||
|
1ca85e835c | ||
|
7b6f71dced | ||
|
22776f8fdb | ||
|
e304e82b66 | ||
|
b5568723ce | ||
|
c132f42985 | ||
|
ab3fa46502 | ||
|
c758d8b040 | ||
|
79409e35e1 | ||
|
0137446248 | ||
|
e564932792 | ||
|
91725ddc92 | ||
|
dee7ff4a92 | ||
|
21677816a0 | ||
|
a0e8922d13 | ||
|
db11ed27bd | ||
|
3bcb350711 | ||
|
521c2b25c2 | ||
|
0de32693d0 | ||
|
4c0d75bc8e | ||
|
8413828995 | ||
|
af32603ae3 | ||
|
043dbc05df | ||
|
666334bd48 | ||
|
85169a04cf | ||
|
f97763d7b3 | ||
|
cf83842304 | ||
|
0e4d3feb94 | ||
|
843fcc96f7 | ||
|
719b08313f | ||
|
b39c255d8c | ||
|
d634ae9b60 | ||
|
5e7f42e17e | ||
|
7950abcc46 | ||
|
dd61302f5b | ||
|
0a440776e7 | ||
|
31f4ec92f6 | ||
|
c41c8c2f86 | ||
|
22098745e7 | ||
|
b54af02b51 | ||
|
a264f2dc55 | ||
|
6f08fe20e9 | ||
|
a08a254df3 | ||
|
28edc8e2d6 | ||
|
5595311209 | ||
|
d478e13639 | ||
|
13f4262354 | ||
|
6a69560847 | ||
|
27cca19c9a | ||
|
befff0e13f | ||
|
142b522946 | ||
|
52d9883812 | ||
|
6c9dd8b650 | ||
|
9900c7a348 | ||
|
e8011d7872 | ||
|
540d1e0561 | ||
|
48ad9e19e4 | ||
|
cc19eba579 | ||
|
3119b1ef7f | ||
|
a654cbfd2f | ||
|
0d68591c8e | ||
|
c07196dc2f | ||
|
2b9de2e24a | ||
|
390532cbc6 | ||
|
b3e6aa9316 | ||
|
3775939303 | ||
|
1776f72c96 | ||
|
54f0b0ec4b | ||
|
65c371ed6e | ||
|
c0eb207b76 | ||
|
89ae725d23 | ||
|
94ef26428b | ||
|
143c092187 | ||
|
c4d7294b5c | ||
|
ad03a09451 | ||
|
abdf23c6c0 | ||
|
cd2e7fafd4 | ||
|
22324ec288 | ||
|
b3c5352386 | ||
|
40cc022c70 | ||
|
67aa86f1e0 | ||
|
95e207933d | ||
|
25f95b0000 | ||
|
b34ffc99b8 | ||
|
170a1c4709 | ||
|
877baae03e | ||
|
b80f16157e | ||
|
0c008cc4f8 | ||
|
0104f8f64a | ||
|
d2d6ef431f | ||
|
ed8782fe0a | ||
|
518be73a5c | ||
|
f676dab8dc | ||
|
f481f9333d | ||
|
f49c88f1c4 | ||
|
17b2c89116 | ||
|
9b5c21309b | ||
|
596c8960b2 | ||
|
d783e7df83 | ||
|
a7a6ac112e | ||
|
4f716c731a | ||
|
65c6ba1fc4 | ||
|
ff14f8ef16 | ||
|
824dc51341 | ||
|
e66e6bb28a | ||
|
dcfe23a038 | ||
|
0b83fd3217 | ||
|
9052e33a10 | ||
|
71fa3b1337 | ||
|
945704208a | ||
|
94639eb66f | ||
|
ffd75c2e0c | ||
|
98c1140c44 | ||
|
17723691e5 | ||
|
803c21f4b2 | ||
|
eb20ed1f69 | ||
|
d62a88eb0d | ||
|
2cff71d71c | ||
|
833096ce42 | ||
|
af6b5d55db | ||
|
f53feeea8b | ||
|
219ced474d | ||
|
2504e4ad0d | ||
|
8be470eea8 | ||
|
c71555f030 | ||
|
581f005aad | ||
|
0e91d2e0e9 | ||
|
0425baf883 | ||
|
f96b9bf761 | ||
|
ae09fe3da7 | ||
|
483b03562a | ||
|
bb5cae2c94 | ||
|
868c897ad7 | ||
|
4cd84c4b13 | ||
|
228f82fcda | ||
|
5bb0e7080a | ||
|
dae48a8064 | ||
|
4c02882f8a | ||
|
6d212fa045 | ||
|
102090916e | ||
|
582dd705c1 | ||
|
d6cc02d301 | ||
|
50a4951ddc | ||
|
4733127a04 | ||
|
7037c48e58 | ||
|
0246332954 | ||
|
ffb2c1fb4a | ||
|
ef161d4aeb | ||
|
9032e6779d | ||
|
c83fce86d4 | ||
|
3a3f98b32b | ||
|
4a8c4110e3 | ||
|
566a2e4c79 | ||
|
a0572a40ab | ||
|
d3dec8fae1 | ||
|
d7deec1993 | ||
|
a254dad2e5 | ||
|
28327f10a2 | ||
|
b139a7636f | ||
|
8dbc5df952 | ||
|
155e8d7d78 | ||
|
d42495033e | ||
|
8d1e56e210 | ||
|
0867d3173c | ||
|
1dcf7d5b03 | ||
|
1e1d326b50 | ||
|
62296f9281 | ||
|
cf3ce189ab | ||
|
805aea501a | ||
|
92cbd1c69e | ||
|
fb80e8a1c4 | ||
|
9275a771bf | ||
|
4f81f9d5ea | ||
|
65aa43bf66 | ||
|
d73aba2500 | ||
|
9a8b8009f4 | ||
|
dc30785947 | ||
|
62227e1bba | ||
|
1ef0a1b1be | ||
|
5db247da9d | ||
|
214cd9d1e6 | ||
|
a558074474 | ||
|
cba3edbc37 | ||
|
bb19265ba8 | ||
|
2d397beb00 | ||
|
6ab12ec8f4 | ||
|
c1bd5e9144 | ||
|
bffe6d5670 | ||
|
eaa7b49bd6 | ||
|
89fb8b32f6 | ||
|
c12d7b6d21 | ||
|
6834304feb | ||
|
aa80c33360 | ||
|
c9d632e485 | ||
|
d3778d65fa | ||
|
3208dcabdc | ||
|
1449c82484 | ||
|
937491288e | ||
|
73e09ddecf | ||
|
8fb13036ee | ||
|
fdcab58ccf | ||
|
57af88a654 | ||
|
9353fc6a27 | ||
|
9409b5623d | ||
|
deb4910c5b | ||
|
e9275392c1 | ||
|
1616a09b61 | ||
|
bbe6e9e8d1 | ||
|
7e7b0622a6 | ||
|
b37d34307d | ||
|
1fdfd45995 | ||
|
fcb52454ac | ||
|
01fd23b625 | ||
|
b9fe30dad4 | ||
|
f15d5a0661 | ||
|
d131147a5c | ||
|
83280d44d0 | ||
|
e8a82ed24d | ||
|
113e95ec02 | ||
|
b565b496ba | ||
|
27ba1766e7 | ||
|
0b3af098e1 | ||
|
9bcf5bed05 | ||
|
491467b0b9 | ||
|
347a5f68da | ||
|
e37985f590 | ||
|
84ea9ee0f9 | ||
|
04c90b8cf5 | ||
|
8086f40123 | ||
|
722d477bc6 | ||
|
31ee158394 | ||
|
1de3966b84 | ||
|
2910163df1 | ||
|
040b5bbc52 | ||
|
456ea1bb1d | ||
|
d109e429dd | ||
|
237c15888d | ||
|
a5ebd28797 | ||
|
155e39187c | ||
|
8e69882c03 | ||
|
f5106148e3 | ||
|
eef2d20e23 | ||
|
d8e3e6d606 | ||
|
865fdf4dcd | ||
|
2f9987c816 | ||
|
5b908cfb5f | ||
|
5fed968b1d | ||
|
0e4efb15f5 | ||
|
ad8804885c | ||
|
e7d75c8db7 | ||
|
018347f802 | ||
|
61c434c030 | ||
|
ffbbe3d103 | ||
|
0eb7b49a17 | ||
|
288cf20f98 | ||
|
c5d4b6b311 | ||
|
efb97da0da | ||
|
d68b68fc43 | ||
|
42f1be8030 | ||
|
83dd99177f | ||
|
46dae0b8bb | ||
|
4e750caf96 | ||
|
a756fa60ef | ||
|
2cf09c5446 | ||
|
087369aeeb | ||
|
940730093b | ||
|
bc0885f364 | ||
|
1bd486666b | ||
|
ab5e69c442 | ||
|
e155cb4fee | ||
|
12df6024db | ||
|
598c295707 | ||
|
c42b304f62 | ||
|
2a7908c939 | ||
|
c4ed09ad4e | ||
|
ab78900e29 | ||
|
980701114f | ||
|
799cc143c9 | ||
|
205e5278c6 | ||
|
3330fc2e93 | ||
|
bcb8f69cc5 | ||
|
1eb09c8ce2 | ||
|
b97ee34947 | ||
|
bee4b80754 | ||
|
0787ea8b26 | ||
|
204cbfb68d | ||
|
e6d4475a6c | ||
|
a959487597 | ||
|
9015cb7111 | ||
|
96cfb076ce | ||
|
3a5598affa | ||
|
36151bd1d7 | ||
|
6a91e09218 | ||
|
3f935d0e2c | ||
|
f95e9b68d6 | ||
|
46f7c92c9a | ||
|
87ca9490b0 | ||
|
ff447f4fd5 | ||
|
bffb35612c | ||
|
01365cbd74 | ||
|
6059d38f21 | ||
|
451b8579ef | ||
|
774cd9a26c | ||
|
d3cd746067 | ||
|
38b0c47f37 | ||
|
ebda2fa2b5 | ||
|
39f59c3289 | ||
|
ad7f1a8dcc | ||
|
32c4c15f15 | ||
|
5008409b5c | ||
|
19cd5ff164 | ||
|
64adea1ce1 | ||
|
19db33afc9 | ||
|
59880cb855 | ||
|
604a2d67b5 | ||
|
380a2dfc3a | ||
|
7841ce781c | ||
|
ba9bcf92f6 | ||
|
6db4af7bd5 | ||
|
c545473920 | ||
|
ec878a3d89 | ||
|
09ea6744fe | ||
|
6a516acb2e | ||
|
6919b9879b | ||
|
298d3aa8b8 | ||
|
c63ea32a17 | ||
|
3314f4ef09 | ||
|
2e67c85c13 | ||
|
c4c53659f1 | ||
|
2e67c827bb | ||
|
3e39ec60da | ||
|
83d7ae76e8 | ||
|
72ea8cfb43 | ||
|
13b36ce063 | ||
|
6371675bf9 | ||
|
54512f2184 | ||
|
b10de9186c | ||
|
c766258e9c | ||
|
d20ddb6807 | ||
|
5f1938f545 | ||
|
ade06e284b | ||
|
35cbdc9661 | ||
|
9300aca2a6 | ||
|
9af68a2415 | ||
|
19f3448c21 | ||
|
ed95e1a9ff | ||
|
879b023706 | ||
|
8d9a357a67 | ||
|
a4bc2922c2 | ||
|
420591c4a2 | ||
|
f0307892ea | ||
|
5e19d7ec54 | ||
|
81d704d15d | ||
|
b19c11621a | ||
|
69c9dfd6d5 | ||
|
6cba7d22e9 | ||
|
0007490b21 | ||
|
aac5e5906d | ||
|
e19dff9285 | ||
|
32b299f63e | ||
|
07387913a8 | ||
|
ef7ab7bde8 | ||
|
6a90113e68 | ||
|
3d58b43efe | ||
|
44a4ffd96f | ||
|
186d3ba70e | ||
|
a4cbaa958d | ||
|
25c3421802 | ||
|
a449f77774 | ||
|
388fe4aea8 | ||
|
0141c6db81 | ||
|
00157a42d3 | ||
|
487fa4a469 | ||
|
7b0d2464ff | ||
|
7b13076f56 | ||
|
389dacd6e2 | ||
|
24496fe097 | ||
|
8fb71ce208 | ||
|
a8eb15eafb | ||
|
77f9c550bd | ||
|
3cfd3e626c | ||
|
0426c76142 | ||
|
18ef26761d | ||
|
e214503789 | ||
|
28382c58ec | ||
|
6549a270e9 | ||
|
94dea2018e | ||
|
da4d627e79 | ||
|
ddaba6d576 | ||
|
8c9a240597 | ||
|
d9694c27c2 | ||
|
200edf8030 | ||
|
12c76d4a15 | ||
|
4bbc37687e | ||
|
0ff5ce825c | ||
|
84f64925bc | ||
|
18f85467e7 | ||
|
d331bc3b03 | ||
|
52bc1ad744 | ||
|
0200623ef7 | ||
|
f577f31f50 | ||
|
a7b2b29b79 | ||
|
9da935629e | ||
|
42053a0fc3 | ||
|
383e23fd61 | ||
|
cc1884dc04 | ||
|
1523c78c34 | ||
|
683b076a6e | ||
|
676250adf9 | ||
|
521b8c02cc | ||
|
92e954a2f0 | ||
|
381fa4afca | ||
|
a6a539497a | ||
|
cd8a090e67 | ||
|
40408d1640 | ||
|
5d88037e37 | ||
|
57b229012a | ||
|
5fd603ce60 | ||
|
eaa74497b8 | ||
|
93fa093122 | ||
|
36a2dd36a0 | ||
|
3760b589f6 | ||
|
3d97f1e22d | ||
|
1907027b7b | ||
|
86c76aa734 | ||
|
e1c3305015 | ||
|
672383bc56 | ||
|
b94d1604a9 | ||
|
6326ad1729 | ||
|
0f0fce5dcc | ||
|
0cbe6524db | ||
|
0ef0dab2f7 | ||
|
806b4fbcad | ||
|
d178a71b7c | ||
|
05b3356631 | ||
|
08d5e3d0fa | ||
|
9e7ed25c64 | ||
|
a44f547343 | ||
|
fb77973201 | ||
|
c4872b4519 | ||
|
ad371893f2 | ||
|
9f3e5eead5 | ||
|
dec81e489f | ||
|
f7e59cbccc | ||
|
73261bb8c7 | ||
|
0e30c50648 | ||
|
85fddc0081 | ||
|
8feeaecb84 | ||
|
e854b2a459 | ||
|
5cdd6ab7cd | ||
|
1981706196 | ||
|
66ca24d3a2 | ||
|
c1756e1b63 | ||
|
c1a9e82d3e | ||
|
3910417695 | ||
|
a491d2e8a5 | ||
|
bade242ddd | ||
|
426e3926ef | ||
|
dc52e08bb5 | ||
|
b2fe29ba79 | ||
|
7c1b7842c6 | ||
|
efe17dbdb4 | ||
|
0588a83380 | ||
|
38adf7a694 | ||
|
3df160a410 | ||
|
458a29d700 | ||
|
e1058e6bc3 | ||
|
62344f515c | ||
|
e5e6480694 | ||
|
85b80ce3bb | ||
|
4769809555 | ||
|
23a27d4c8a | ||
|
64f9ea1cf5 | ||
|
a5898e3a2d | ||
|
2cc6a86fd3 | ||
|
8f1bc3a3b7 | ||
|
b0e20e1b3c | ||
|
066fb6c69e | ||
|
b41580d66e | ||
|
341c9e77a8 | ||
|
9a8b46518b | ||
|
1e48b64538 | ||
|
4113a88523 | ||
|
26c4429f7e | ||
|
b7e92237c5 | ||
|
d6d0e4c942 | ||
|
1b44e7dba2 | ||
|
052a5b0319 | ||
|
8a46a2a364 | ||
|
4f17d17009 | ||
|
61f266f660 | ||
|
af8e955e8f | ||
|
30b0cb0cd4 | ||
|
62a4a45a72 | ||
|
a2d758acc9 | ||
|
9f004830a5 | ||
|
dbd76848ca | ||
|
72568286ab | ||
|
8bb58153e7 | ||
|
40069797ef | ||
|
07ba3e35d3 | ||
|
d591710f82 | ||
|
0004a187ba | ||
|
ca807edac0 | ||
|
7f4431d2f6 | ||
|
25dc760162 | ||
|
4651269dc8 | ||
|
882ddf4b16 | ||
|
d806d0760d | ||
|
b529870558 | ||
|
454fa93113 | ||
|
2799bbc562 | ||
|
b4500c477e | ||
|
fd1912de97 | ||
|
7ca03c1a79 | ||
|
870104c36c | ||
|
a2cea992c2 | ||
|
a6cb8efd81 | ||
|
9d7bd47cb6 | ||
|
d9fb730148 | ||
|
08516af897 | ||
|
be18f92bf4 | ||
|
ec1bb21649 | ||
|
e8ad01594a | ||
|
4e5c3b82cb | ||
|
a5979a2106 | ||
|
6f4fbef827 | ||
|
06e4b7d1f8 | ||
|
5f6b0a7b00 | ||
|
40908fca45 | ||
|
6eab4f55fa | ||
|
18f8ab6fbd | ||
|
bccc3a652b | ||
|
de5ac5410d | ||
|
ef5ee6c707 | ||
|
028b3cbe15 | ||
|
079ed04a6b | ||
|
81ccfd44e4 | ||
|
6a02afa56f | ||
|
0557569947 | ||
|
7bbf2fb652 | ||
|
3b84630e14 | ||
|
79f9ffd401 | ||
|
71fa64a272 | ||
|
4965f19626 | ||
|
4bb95eef6f | ||
|
5ecb161850 | ||
|
67b9f120d5 | ||
|
b7d242f094 | ||
|
6a15f40803 | ||
|
a0f9caec99 | ||
|
010077ba0f | ||
|
7b2308980c | ||
|
c2a087a9f7 | ||
|
1b64f2e28b | ||
|
d0096bba21 | ||
|
32ace57479 | ||
|
0411336b49 | ||
|
9a0953a0a0 | ||
|
07be7b087d | ||
|
e2a89b7ad1 | ||
|
8a20564847 | ||
|
8404507b9b | ||
|
0f7c9cd27e | ||
|
6174d00c03 | ||
|
bbb1b82232 | ||
|
d43bc26717 | ||
|
57ba2df970 | ||
|
4f3c5b2568 | ||
|
781b7d4820 | ||
|
f39b83e232 | ||
|
fe6706a2ce | ||
|
cea8e9b583 | ||
|
14da1bfe40 | ||
|
7493debe26 | ||
|
7d3e1ad943 | ||
|
81945da0ac | ||
|
735e250326 | ||
|
55d15e9d05 | ||
|
9d5e754caa | ||
|
0040fb93d6 | ||
|
970ad4e3c7 | ||
|
8d6da1e100 | ||
|
6c829007cc | ||
|
e7f034fe4e | ||
|
6bb909f152 | ||
|
2006d9f7d1 | ||
|
66a0289081 | ||
|
a181a825c8 | ||
|
def549c8f6 | ||
|
4c07d58592 | ||
|
98f36bba9a | ||
|
781fd745ed | ||
|
57c2545cd5 | ||
|
2a478f9215 | ||
|
1bef9e3fbf | ||
|
be1829f63d | ||
|
e1743888ed | ||
|
b76ccfef5f | ||
|
9899820a17 | ||
|
4112481170 | ||
|
5a01c1dad1 | ||
|
8d15e7d742 | ||
|
407e3a4552 | ||
|
4386e3f7c0 | ||
|
775dcab7a2 | ||
|
8d0dc69027 | ||
|
5dd50a381a | ||
|
9fa38435aa | ||
|
952e1e62c5 | ||
|
5bc17c3e54 | ||
|
3d71555a47 | ||
|
6509ebc594 | ||
|
f9d4589976 | ||
|
1e88fe578e | ||
|
3d73d32499 | ||
|
c207947508 | ||
|
6743bf3173 | ||
|
e7904c5faa | ||
|
ef7e4ec3c6 | ||
|
346a438da8 | ||
|
aeafa2a28f | ||
|
ad4073edc1 | ||
|
dcd6c1d2e2 | ||
|
2bdc7fb0a1 | ||
|
7d23c50599 | ||
|
6750d1bac8 | ||
|
4fd91c3f37 | ||
|
84cbe29d5b | ||
|
60ee6f739f | ||
|
317d3d10b8 | ||
|
5de229644f | ||
|
f2f884a92f | ||
|
1f32e3c95d | ||
|
6c0aa5b00a | ||
|
542c735926 | ||
|
6c5ca9779b | ||
|
7b1245dc7f | ||
|
22529b81f8 | ||
|
7fc29c1435 | ||
|
d1e3705c1a | ||
|
3e2f0c7a39 | ||
|
ada6ddc794 | ||
|
a4ce46e06c | ||
|
ba31a9645c | ||
|
afa41b16ea | ||
|
caeb591fa3 | ||
|
04dc007c76 | ||
|
ac79a02ace | ||
|
4f1d1422de | ||
|
40b3fc727d | ||
|
fffa94787c | ||
|
4fdc1bb1fb | ||
|
43b8dffb83 | ||
|
b9921a5560 | ||
|
08735b4aa8 | ||
|
64cb636b06 | ||
|
4f43cb660a | ||
|
27530efedb | ||
|
92eca900b0 | ||
|
c93c9bca8e | ||
|
0f2956ab5d | ||
|
413f66f1a3 | ||
|
201fdf67ac | ||
|
0760c6f4e1 | ||
|
cfa2f9a2f2 | ||
|
67d010bd2c | ||
|
94672c89cc | ||
|
61acc9939f | ||
|
72119f5d9b | ||
|
0f7b0897cc | ||
|
8deb92d653 | ||
|
1c550c36b3 | ||
|
86ec93ccaf | ||
|
0fc17c42af | ||
|
51fe170224 | ||
|
27bd49f4bf | ||
|
2400bc66ef | ||
|
6ad1e347a3 | ||
|
8dd5dae91a | ||
|
19c5d21e6f | ||
|
17fb29c9e8 | ||
|
7ff0f654fb | ||
|
0a004fd361 | ||
|
4fa853f5de | ||
|
24e371c812 | ||
|
d4d242ba76 | ||
|
dee3f716b3 | ||
|
8a8202fcdc | ||
|
0955c88c2e | ||
|
30e5333ce3 | ||
|
d006242d73 | ||
|
69f72417f4 | ||
|
ee34a8ac29 | ||
|
bca90530fa | ||
|
d68fa0382d | ||
|
1311687d0d | ||
|
081c00c7df | ||
|
b3a6ae71c1 | ||
|
43d6eb7173 | ||
|
dd8983f96c | ||
|
4917bcc039 | ||
|
3ce2a7d026 | ||
|
a9fa147a92 | ||
|
f058afc861 | ||
|
2e66c0b6f0 | ||
|
55ceb5047c | ||
|
cfef1b11e5 | ||
|
af10b35ba9 | ||
|
96155f626d | ||
|
6b2328e5cc | ||
|
82d563243f | ||
|
40429857c3 | ||
|
ec3c08d618 | ||
|
c0309cfe69 | ||
|
f29a3eb9c7 | ||
|
264706f804 | ||
|
3246db3755 | ||
|
624daf8d9e | ||
|
3c585e6567 | ||
|
34f459423a | ||
|
6176ab5901 | ||
|
ffcddc908e | ||
|
058010187b | ||
|
75bdbf02a6 | ||
|
90431d1857 | ||
|
e35700eb50 | ||
|
b43a7ac530 | ||
|
c9d2b7df77 | ||
|
620fbb5655 | ||
|
de705907a5 | ||
|
6fd2d4e772 | ||
|
0242fef89c | ||
|
402e0b58ca | ||
|
3db11af44b | ||
|
0ee5518e76 | ||
|
ec000ce555 | ||
|
f595434abc | ||
|
8f1bc0bccc | ||
|
1870d5f4aa | ||
|
d33428f0bf | ||
|
a35bcd01c5 | ||
|
89de943401 | ||
|
9582dd10e1 | ||
|
11cceea58a | ||
|
8d5b17e939 | ||
|
2e74e307d0 | ||
|
0fc13104e7 | ||
|
c7c02eea81 | ||
|
6742f74e0e | ||
|
1ffdac4502 | ||
|
c3a5641132 | ||
|
1fccb39316 | ||
|
3b9b5842b3 | ||
|
838fc976c8 | ||
|
07b2e4cb79 | ||
|
145817a9cf | ||
|
56e64270f3 | ||
|
533ecb44b1 | ||
|
7fbf321c2a | ||
|
27aea4956c | ||
|
a19ee75bd1 | ||
|
a9c5a40087 | ||
|
ab7bc6b7d2 | ||
|
7bd051eeec | ||
|
0b8444aa0c | ||
|
2c9684e35c | ||
|
247f90c82e | ||
|
c218211012 | ||
|
e034b7b04d | ||
|
968a0bcd63 | ||
|
4347080b46 | ||
|
59c77c8f5b | ||
|
1515e02c8a | ||
|
76ce3fd9c9 | ||
|
89a9d7d650 | ||
|
c1729f876c | ||
|
ce2abb82c0 | ||
|
88c6ec40a4 | ||
|
a5e1baf3ab | ||
|
49940ab5ee | ||
|
1f22b15030 | ||
|
a8b20ed105 | ||
|
ab677c41ea | ||
|
07b1aa822c | ||
|
5b6b42162b | ||
|
26659d5eb8 | ||
|
bd6217bb74 | ||
|
0a861e68df | ||
|
109eafc3f8 | ||
|
974e4540bd | ||
|
d502ef0035 | ||
|
e4a6520d6e | ||
|
618f26ccbc | ||
|
7b4e4c08b5 | ||
|
271243d382 | ||
|
c523d6d25c | ||
|
6f435e0bb9 | ||
|
6c1df4f9c5 | ||
|
5607c4be00 | ||
|
b14d203884 | ||
|
60ace31be0 | ||
|
f0be4d126d | ||
|
50a7c67363 | ||
|
481185fb8a | ||
|
f8c7eb295f | ||
|
4c0e0979b4 | ||
|
3c69b9f2c5 | ||
|
62bc40c6e7 | ||
|
a392e6cecb | ||
|
0249afc523 | ||
|
02ee154558 | ||
|
0440ca07ba | ||
|
f73d72bfdc | ||
|
b44b3193d0 | ||
|
572ca799db | ||
|
c3a6de9ec8 | ||
|
8d193d81af | ||
|
e2114731e7 | ||
|
8a2e1245d4 | ||
|
f63dea4337 | ||
|
cd51c9fafb | ||
|
f71fe8476a | ||
|
b04f1416f6 | ||
|
ddb42f3ad2 | ||
|
05042ce472 | ||
|
0695a910c6 | ||
|
9d9cca49b4 | ||
|
0c7b930952 | ||
|
4eb9b5f20e | ||
|
188724a597 | ||
|
e9f1b83a4a | ||
|
786e6d80ba | ||
|
ecb4ed172b | ||
|
dc0c2340b8 | ||
|
31441778fa | ||
|
412c650e05 | ||
|
db1663a1e5 | ||
|
173d16b233 | ||
|
73fe903c96 | ||
|
8cd244a318 | ||
|
c78af57e21 | ||
|
0f1eeed5c2 | ||
|
e31e9180cd | ||
|
3564d03b0f | ||
|
0dde471278 | ||
|
ee5d8f43e1 | ||
|
4a8b3b8bc5 | ||
|
18ca7546f6 | ||
|
91f14e751f | ||
|
a4f3c08db4 | ||
|
1e13247d6d | ||
|
762fc76cf9 | ||
|
96355b4f1c | ||
|
5b4d930ae5 | ||
|
7f3602f1c9 | ||
|
89555e45f2 | ||
|
e3d80cfc15 | ||
|
3582c9da70 | ||
|
cf82687f23 | ||
|
5dff494b87 | ||
|
cd381aea56 | ||
|
267108e113 | ||
|
4831ff9f27 | ||
|
09cc2f9d0e | ||
|
528428919e | ||
|
571baffd59 | ||
|
46f4a45769 | ||
|
7d574f5ac6 | ||
|
a8a8bd1e42 | ||
|
67da3f7e6b | ||
|
58dd03a471 | ||
|
2f1c382a6d | ||
|
a5be811269 | ||
|
6ca4eda960 | ||
|
9ce2b30b81 | ||
|
e332c41e9d | ||
|
95824f2b5f | ||
|
be4f4644a8 | ||
|
7014c0d65d | ||
|
e37a2d1879 | ||
|
a7c8fdc55b | ||
|
fd16e003fb | ||
|
4d48c00f94 | ||
|
489e7b61bf | ||
|
8520b322aa | ||
|
e352e8deed | ||
|
323ab8ef97 | ||
|
0af7b4961a | ||
|
c5c3568573 | ||
|
1a3d8019d1 | ||
|
3e1601a980 | ||
|
49de15cdcc | ||
|
55fd77f724 | ||
|
08dccc2cb4 | ||
|
8e2fd56394 | ||
|
6d59619d6e | ||
|
6d20ea5c38 | ||
|
a39ba095eb | ||
|
511a909ae6 | ||
|
419c47a80a | ||
|
f53692a632 | ||
|
5fe640f579 | ||
|
74cc242acc | ||
|
39461732ab | ||
|
6b9d9da8ef | ||
|
5e50d002f1 | ||
|
b7af3716a1 | ||
|
8596486743 | ||
|
cd54f31984 | ||
|
a354970eaa | ||
|
fd3cf7193b | ||
|
0f2376d58e | ||
|
85fa72c599 | ||
|
82c19beec4 | ||
|
c0fa14e8af | ||
|
1d7ceb2fee | ||
|
2597a71623 | ||
|
9b428a3d33 | ||
|
7b9877bd8a | ||
|
8ad8c6d887 | ||
|
7602edfd06 | ||
|
5a98363a92 | ||
|
9b71a46899 | ||
|
3cb933db9d | ||
|
a73d78f8d5 | ||
|
924edb948c | ||
|
c7e77dba7f | ||
|
de7af816e7 | ||
|
098be5ffdd | ||
|
eb29361d9d | ||
|
f6b695d2fb | ||
|
9f8bd80487 | ||
|
dba081975a | ||
|
36688496ca | ||
|
807c849431 | ||
|
4c8af0e2f9 | ||
|
60864229b8 | ||
|
b8bf60c590 | ||
|
7860686a8d | ||
|
df731c745a | ||
|
2e04be3fb9 | ||
|
a0a16bbed6 | ||
|
4dd86a0b33 | ||
|
f3e6b7065a | ||
|
ff81dc3544 | ||
|
105eee7e24 | ||
|
779a5b3029 | ||
|
1eadbdd9fa | ||
|
58413c15cb | ||
|
9dab00a76e | ||
|
a9fe88e395 | ||
|
96929d406f | ||
|
518179f63e | ||
|
cba36a064d | ||
|
ff76e05913 | ||
|
670ce6785d | ||
|
5ba4ba0baf | ||
|
878906630b | ||
|
0f052eb4f5 | ||
|
609d87003a | ||
|
cddaa84777 | ||
|
306b8c89e8 | ||
|
31fb92c609 | ||
|
561a010161 | ||
|
a33d1f9a7c | ||
|
0670621291 | ||
|
c9c55df1f2 | ||
|
de4af86e98 | ||
|
13f99eb65f | ||
|
0db50996b7 | ||
|
52f8a4283e | ||
|
1557892c37 | ||
|
d983fa0ebe | ||
|
c543c39692 | ||
|
8b36298d7f | ||
|
d59758450b | ||
|
509f19f611 | ||
|
18bb8fee3c | ||
|
e8c4740108 | ||
|
5b9492a58e | ||
|
a4d081cc17 | ||
|
1ac44105f9 | ||
|
5cfc9c374c | ||
|
b9fd2cf605 | ||
|
6cef06b940 | ||
|
91bb776bb8 | ||
|
cc2134ea83 | ||
|
f679d8c821 | ||
|
5f114b65b4 | ||
|
1d7cd76ee9 | ||
|
939451554f | ||
|
5e0599cb6e | ||
|
2640aec0d7 | ||
|
65fdd10d4e | ||
|
3e8573a85a | ||
|
cefc89e5a5 | ||
|
80e0fc4901 | ||
|
8e8d9a3650 | ||
|
6373de3304 | ||
|
8b748bd326 | ||
|
d0731af939 | ||
|
f7277806c8 | ||
|
d52ffce38f | ||
|
bd98bf38e9 | ||
|
5dcaad0dd3 | ||
|
1808c67d53 | ||
|
c500d8824d | ||
|
6217f8001e | ||
|
0ec426a57b | ||
|
5f698d1121 | ||
|
a09f8dbe6e | ||
|
fa2799804c | ||
|
15b8e4a490 | ||
|
18e322bc7c | ||
|
6a2f385aea | ||
|
4bafaa00aa | ||
|
57d2d6ef62 | ||
|
b75246202a | ||
|
ce550fa9c2 | ||
|
92d2e12a4d | ||
|
313a7d716d | ||
|
68d7736e9e | ||
|
74b84d00b3 | ||
|
500c026818 | ||
|
0cbb92bcc5 | ||
|
c7d74a2366 | ||
|
549d24b437 | ||
|
ab37723fa2 | ||
|
ba138d6201 | ||
|
e14924570c | ||
|
7f0cf432e9 | ||
|
c3f0cd7457 | ||
|
6b7974cf16 | ||
|
23b8fcc74d | ||
|
4b84a33217 | ||
|
774e25de13 | ||
|
d8d990f2e3 | ||
|
464882e398 | ||
|
2646beac87 | ||
|
d082bbcc05 | ||
|
b6a2441eb9 | ||
|
61e5cf083a | ||
|
e6ee27a541 | ||
|
1e97933876 | ||
|
d4314f7c1f | ||
|
a4ac991d02 | ||
|
5675d3a8fe | ||
|
7b7d1132e8 | ||
|
360238e9e1 | ||
|
b58de39ca7 | ||
|
6f8ea5b26e | ||
|
d2276ff3f2 | ||
|
c6eab4077a | ||
|
8dd14509d7 | ||
|
031c731c68 | ||
|
ca52e0a244 | ||
|
f27b74f0f7 | ||
|
327c8fc52f | ||
|
2d7d81bc46 | ||
|
ff1b933d96 | ||
|
b28e66cf4f | ||
|
9d74c7ab99 | ||
|
239d9c5eda | ||
|
6ccda5a041 | ||
|
724feb898f | ||
|
9a849cc83a | ||
|
cff2b5b338 | ||
|
301fed8a45 | ||
|
a4b28e23cf | ||
|
502d3a1fcb | ||
|
54de892d1e | ||
|
af1edfd368 | ||
|
73785fff07 | ||
|
4a14453d2d | ||
|
8d9d5a3bb5 | ||
|
9162840c1e | ||
|
8925f735a1 | ||
|
3a7fda78a2 | ||
|
4d708225bd | ||
|
226e07144e | ||
|
6560e0b136 | ||
|
b6b0b0a05f | ||
|
bff3e85625 | ||
|
7a9791f096 | ||
|
89ab14a115 | ||
|
1d2a669445 | ||
|
2d511f28f2 | ||
|
7b0bd43a27 | ||
|
6b7e19ff42 | ||
|
44626eaf81 | ||
|
4f08f8df1e | ||
|
37a241768d | ||
|
c8fc98937d | ||
|
df965f51bf | ||
|
9861dd069b | ||
|
ad8d255bb9 | ||
|
88d9ab1af5 | ||
|
7797480eb0 | ||
|
acd0aa7d38 | ||
|
f0680670d2 | ||
|
33b27e2cca | ||
|
7e44b7cddd | ||
|
e05f614267 | ||
|
4e46d9f963 | ||
|
7376bf948b | ||
|
1192b468e9 | ||
|
30295c1750 | ||
|
9031de6a9b | ||
|
2279803c8c | ||
|
a263241ea1 | ||
|
68f27cdfc2 | ||
|
5c96365c94 | ||
|
50fb999bb1 | ||
|
43956c1bfc | ||
|
5371c889a8 | ||
|
e0db8207f3 | ||
|
ebf339628a | ||
|
e0286d7f4e | ||
|
dc2b34af6a | ||
|
d4579a983e | ||
|
7e8df0e2c9 | ||
|
340711db3d | ||
|
e60bddcc60 | ||
|
f1d71f7cc3 | ||
|
051e604adc | ||
|
d4d5e0ae0c | ||
|
9100e3c087 | ||
|
510beeccf4 | ||
|
0f5ac7761d | ||
|
074635002e | ||
|
69f077f1aa | ||
|
eb0edeafdd | ||
|
982f09f837 | ||
|
1000e4ee7d | ||
|
3dae8e9fc2 | ||
|
7ca66e3cfc | ||
|
7819811835 | ||
|
e3a7a1c6ae | ||
|
360d38adb1 | ||
|
2b7416ef34 | ||
|
d817f4dcee | ||
|
55d1a56826 | ||
|
04c339a12b | ||
|
a02abca49a | ||
|
39f3adc079 | ||
|
05eacf92fe | ||
|
eaf1a604f2 | ||
|
d8a43399a8 | ||
|
818ee96219 | ||
|
857cb260c7 | ||
|
6e21389917 | ||
|
f34567bf41 | ||
|
26c65447df | ||
|
71cb54cec4 | ||
|
c5d2c8fb80 | ||
|
f4c0ec8ffc | ||
|
9772c68e54 | ||
|
547da0d575 | ||
|
31f654a704 | ||
|
ba2ff69894 | ||
|
2bfc7aedab | ||
|
45f845a260 | ||
|
ef5b279887 | ||
|
e278d3f185 | ||
|
342b44bf20 | ||
|
3e8405aa82 | ||
|
7ff4b64319 | ||
|
f7fe2c2290 | ||
|
12744335c0 | ||
|
0e0b300a1c | ||
|
a61f7abf5a | ||
|
1213881712 | ||
|
6cc644abef | ||
|
7bdc0a6291 | ||
|
a1bc0a6d79 | ||
|
98d8343aa2 | ||
|
49f021ebf0 | ||
|
d515863abc | ||
|
e3a18e1990 | ||
|
f499c6b9ec | ||
|
669fbed1ac | ||
|
4d3b32bf3d | ||
|
0e9a66d35a | ||
|
7624f8aeb1 | ||
|
75577fe7a8 | ||
|
a290f5d04c | ||
|
5571d5139b | ||
|
498803bec9 | ||
|
c492105b8f | ||
|
67c36d5d6e | ||
|
2fbc30739b | ||
|
a46ce37d25 | ||
|
992961c56c | ||
|
6acf0972ec | ||
|
9c8b0b6050 | ||
|
e4cd1933c6 | ||
|
91bd9a6642 | ||
|
b529fe0995 | ||
|
b94f7157ca | ||
|
046b3fc5dd | ||
|
6b70975efc | ||
|
6e0e5d7a31 | ||
|
2527e6dd09 | ||
|
7b510fda0c | ||
|
5de77049db | ||
|
00795d55df | ||
|
0136a7c1bb | ||
|
d61c85f7df | ||
|
ff3d2eb589 | ||
|
9464898b47 | ||
|
7d74269c0d | ||
|
11b03710ed | ||
|
c7d2099ddb | ||
|
c8a0e1da12 | ||
|
2a7bd485a6 | ||
|
4f08346686 | ||
|
dc4ab45e05 | ||
|
a26d82c2f8 | ||
|
c8d18e27bd | ||
|
34b8670b1a | ||
|
e01f84538a | ||
|
68bf777ece | ||
|
494dadb8a3 | ||
|
f02cdb50be | ||
|
efb1f141a4 | ||
|
10829dd222 | ||
|
1de20b2012 | ||
|
264b41fb9e | ||
|
be628115ba | ||
|
e258d66f17 | ||
|
9cd67df5b2 | ||
|
0910306bf9 | ||
|
ea2011360c | ||
|
ee230d8fdd | ||
|
52c1a2fae8 | ||
|
e4e819b49c | ||
|
6668801d40 | ||
|
39f7b2b6d0 | ||
|
5b0eb69635 | ||
|
5daceee6ca | ||
|
755dd793b6 | ||
|
878dc898b9 | ||
|
094069adc7 | ||
|
98ce26624b | ||
|
4336271b57 | ||
|
ab6b40e5a9 | ||
|
b1a6d5388d | ||
|
aca80d1cda | ||
|
dddb4d25d2 | ||
|
1992190162 | ||
|
99bde59229 | ||
|
1a1a885423 | ||
|
4e39cdd9bb | ||
|
9f0cb20d9f | ||
|
b768d69c04 | ||
|
5d13b38479 | ||
|
798021af9f | ||
|
35cba9b1c9 | ||
|
8d067bbdb4 | ||
|
a893540b66 | ||
|
afeb4c7a6e | ||
|
d3e3d43482 | ||
|
9fba1514d2 | ||
|
aec4853498 | ||
|
33121d3d45 | ||
|
2293de1c82 | ||
|
af7236f85a | ||
|
25345f2c04 | ||
|
7b153b9e28 | ||
|
70dc392bfa | ||
|
8d5eebcc6e | ||
|
4981b04d10 | ||
|
ea4dd1bbf6 | ||
|
ec5fbce415 | ||
|
6c0e0d6250 | ||
|
b4c828e6a0 | ||
|
a0f6d0798a | ||
|
2d3c380c0f | ||
|
deb21faad0 | ||
|
2478cfa966 | ||
|
cc0ed694ee | ||
|
0dfad687a0 | ||
|
fbdb24ec6a | ||
|
dcf8828165 | ||
|
99db1f6a07 | ||
|
bf2f48aec0 | ||
|
002f9c37ca | ||
|
2a86b2bdb9 | ||
|
1f587cf86c | ||
|
3e2529e881 | ||
|
15e5d4067a | ||
|
3b5fb3ec87 | ||
|
2603af65e5 | ||
|
f06f78e638 | ||
|
0b81042dc3 | ||
|
3c89e44f3e | ||
|
7225aba3af | ||
|
1de5aa45ce | ||
|
1f9cf17713 | ||
|
79b8613c95 | ||
|
599deba8c7 | ||
|
cc9e627f8e | ||
|
81a45f92c5 | ||
|
64eb25dff9 | ||
|
29a75f0428 | ||
|
3ec6dfa346 | ||
|
b1d5d7edeb | ||
|
f817826408 | ||
|
6c6315a1b3 | ||
|
29af4e0f27 | ||
|
e908876506 | ||
|
c01507da42 | ||
|
06f01227c5 | ||
|
f26e4f4c52 | ||
|
518ab82942 | ||
|
6b43181cfa | ||
|
ebeec0dd96 | ||
|
a961b70b2b | ||
|
0dda8605e6 | ||
|
06151b8a4d | ||
|
638eb1907e | ||
|
a2d4e1c246 | ||
|
7d01dbf6fa | ||
|
fcb98254b1 | ||
|
e2061c9708 | ||
|
79c320c1cf | ||
|
48f5dca2ce | ||
|
dbc1a6fa9a |
6661 changed files with 635596 additions and 282205 deletions
21
.devcontainer/devcontainer.json
Normal file
21
.devcontainer/devcontainer.json
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"name": "moby",
|
||||||
|
"build": {
|
||||||
|
"context": "..",
|
||||||
|
"dockerfile": "../Dockerfile",
|
||||||
|
"target": "devcontainer"
|
||||||
|
},
|
||||||
|
"workspaceFolder": "/go/src/github.com/docker/docker",
|
||||||
|
"workspaceMount": "source=${localWorkspaceFolder},target=/go/src/github.com/docker/docker,type=bind,consistency=cached",
|
||||||
|
|
||||||
|
"remoteUser": "root",
|
||||||
|
"runArgs": ["--privileged"],
|
||||||
|
|
||||||
|
"customizations": {
|
||||||
|
"vscode": {
|
||||||
|
"extensions": [
|
||||||
|
"golang.go"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
|
@ -5,8 +5,6 @@
|
||||||
|
|
||||||
builder/** @tonistiigi
|
builder/** @tonistiigi
|
||||||
contrib/mkimage/** @tianon
|
contrib/mkimage/** @tianon
|
||||||
daemon/graphdriver/devmapper/** @rhvgoyal
|
|
||||||
daemon/graphdriver/overlay/** @dmcgowan
|
|
||||||
daemon/graphdriver/overlay2/** @dmcgowan
|
daemon/graphdriver/overlay2/** @dmcgowan
|
||||||
daemon/graphdriver/windows/** @johnstep
|
daemon/graphdriver/windows/** @johnstep
|
||||||
daemon/logger/awslogs/** @samuelkarp
|
daemon/logger/awslogs/** @samuelkarp
|
||||||
|
|
70
.github/ISSUE_TEMPLATE.md
vendored
70
.github/ISSUE_TEMPLATE.md
vendored
|
@ -1,70 +0,0 @@
|
||||||
<!--
|
|
||||||
If you are reporting a new issue, make sure that we do not have any duplicates
|
|
||||||
already open. You can ensure this by searching the issue list for this
|
|
||||||
repository. If there is a duplicate, please close your issue and add a comment
|
|
||||||
to the existing issue instead.
|
|
||||||
|
|
||||||
If you suspect your issue is a bug, please edit your issue description to
|
|
||||||
include the BUG REPORT INFORMATION shown below. If you fail to provide this
|
|
||||||
information within 7 days, we cannot debug your issue and will close it. We
|
|
||||||
will, however, reopen it if you later provide the information.
|
|
||||||
|
|
||||||
For more information about reporting issues, see
|
|
||||||
https://github.com/moby/moby/blob/master/CONTRIBUTING.md#reporting-other-issues
|
|
||||||
|
|
||||||
---------------------------------------------------
|
|
||||||
GENERAL SUPPORT INFORMATION
|
|
||||||
---------------------------------------------------
|
|
||||||
|
|
||||||
The GitHub issue tracker is for bug reports and feature requests.
|
|
||||||
General support for **docker** can be found at the following locations:
|
|
||||||
|
|
||||||
- Docker Support Forums - https://forums.docker.com
|
|
||||||
- Slack - community.docker.com #general channel
|
|
||||||
- Post a question on StackOverflow, using the Docker tag
|
|
||||||
|
|
||||||
General support for **moby** can be found at the following locations:
|
|
||||||
|
|
||||||
- Moby Project Forums - https://forums.mobyproject.org
|
|
||||||
- Slack - community.docker.com #moby-project channel
|
|
||||||
- Post a question on StackOverflow, using the Moby tag
|
|
||||||
|
|
||||||
---------------------------------------------------
|
|
||||||
BUG REPORT INFORMATION
|
|
||||||
---------------------------------------------------
|
|
||||||
Use the commands below to provide key information from your environment:
|
|
||||||
You do NOT have to include this information if this is a FEATURE REQUEST
|
|
||||||
-->
|
|
||||||
|
|
||||||
**Description**
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Briefly describe the problem you are having in a few paragraphs.
|
|
||||||
-->
|
|
||||||
|
|
||||||
**Steps to reproduce the issue:**
|
|
||||||
1.
|
|
||||||
2.
|
|
||||||
3.
|
|
||||||
|
|
||||||
**Describe the results you received:**
|
|
||||||
|
|
||||||
|
|
||||||
**Describe the results you expected:**
|
|
||||||
|
|
||||||
|
|
||||||
**Additional information you deem important (e.g. issue happens only occasionally):**
|
|
||||||
|
|
||||||
**Output of `docker version`:**
|
|
||||||
|
|
||||||
```
|
|
||||||
(paste your output here)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Output of `docker info`:**
|
|
||||||
|
|
||||||
```
|
|
||||||
(paste your output here)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Additional environment details (AWS, VirtualBox, physical, etc.):**
|
|
146
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
146
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
name: Bug report
|
||||||
|
description: Create a report to help us improve
|
||||||
|
labels:
|
||||||
|
- kind/bug
|
||||||
|
- status/0-triage
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thank you for taking the time to report a bug!
|
||||||
|
If this is a security issue please report it to the [Docker Security team](mailto:security@docker.com).
|
||||||
|
- type: textarea
|
||||||
|
id: description
|
||||||
|
attributes:
|
||||||
|
label: Description
|
||||||
|
description: Please give a clear and concise description of the bug
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: repro
|
||||||
|
attributes:
|
||||||
|
label: Reproduce
|
||||||
|
description: Steps to reproduce the bug
|
||||||
|
placeholder: |
|
||||||
|
1. docker run ...
|
||||||
|
2. docker kill ...
|
||||||
|
3. docker rm ...
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: expected
|
||||||
|
attributes:
|
||||||
|
label: Expected behavior
|
||||||
|
description: What is the expected behavior?
|
||||||
|
placeholder: |
|
||||||
|
E.g. "`docker rm` should remove the container and cleanup all associated data"
|
||||||
|
- type: textarea
|
||||||
|
id: version
|
||||||
|
attributes:
|
||||||
|
label: docker version
|
||||||
|
description: Output of `docker version`
|
||||||
|
render: bash
|
||||||
|
placeholder: |
|
||||||
|
Client:
|
||||||
|
Version: 20.10.17
|
||||||
|
API version: 1.41
|
||||||
|
Go version: go1.17.11
|
||||||
|
Git commit: 100c70180fde3601def79a59cc3e996aa553c9b9
|
||||||
|
Built: Mon Jun 6 21:36:39 UTC 2022
|
||||||
|
OS/Arch: linux/amd64
|
||||||
|
Context: default
|
||||||
|
Experimental: true
|
||||||
|
|
||||||
|
Server:
|
||||||
|
Engine:
|
||||||
|
Version: 20.10.17
|
||||||
|
API version: 1.41 (minimum version 1.12)
|
||||||
|
Go version: go1.17.11
|
||||||
|
Git commit: a89b84221c8560e7a3dee2a653353429e7628424
|
||||||
|
Built: Mon Jun 6 22:32:38 2022
|
||||||
|
OS/Arch: linux/amd64
|
||||||
|
Experimental: true
|
||||||
|
containerd:
|
||||||
|
Version: 1.6.6
|
||||||
|
GitCommit: 10c12954828e7c7c9b6e0ea9b0c02b01407d3ae1
|
||||||
|
runc:
|
||||||
|
Version: 1.1.2
|
||||||
|
GitCommit: a916309fff0f838eb94e928713dbc3c0d0ac7aa4
|
||||||
|
docker-init:
|
||||||
|
Version: 0.19.0
|
||||||
|
GitCommit:
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: info
|
||||||
|
attributes:
|
||||||
|
label: docker info
|
||||||
|
description: Output of `docker info`
|
||||||
|
render: bash
|
||||||
|
placeholder: |
|
||||||
|
Client:
|
||||||
|
Context: default
|
||||||
|
Debug Mode: false
|
||||||
|
Plugins:
|
||||||
|
buildx: Docker Buildx (Docker Inc., 0.8.2)
|
||||||
|
compose: Docker Compose (Docker Inc., 2.6.0)
|
||||||
|
|
||||||
|
Server:
|
||||||
|
Containers: 4
|
||||||
|
Running: 2
|
||||||
|
Paused: 0
|
||||||
|
Stopped: 2
|
||||||
|
Images: 80
|
||||||
|
Server Version: 20.10.17
|
||||||
|
Storage Driver: overlay2
|
||||||
|
Backing Filesystem: xfs
|
||||||
|
Supports d_type: true
|
||||||
|
Native Overlay Diff: false
|
||||||
|
userxattr: false
|
||||||
|
Logging Driver: local
|
||||||
|
Cgroup Driver: cgroupfs
|
||||||
|
Cgroup Version: 1
|
||||||
|
Plugins:
|
||||||
|
Volume: local
|
||||||
|
Network: bridge host ipvlan macvlan null overlay
|
||||||
|
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
|
||||||
|
Swarm: inactive
|
||||||
|
Runtimes: runc io.containerd.runc.v2 io.containerd.runtime.v1.linux
|
||||||
|
Default Runtime: runc
|
||||||
|
Init Binary: docker-init
|
||||||
|
containerd version: 10c12954828e7c7c9b6e0ea9b0c02b01407d3ae1
|
||||||
|
runc version: a916309fff0f838eb94e928713dbc3c0d0ac7aa4
|
||||||
|
init version:
|
||||||
|
Security Options:
|
||||||
|
apparmor
|
||||||
|
seccomp
|
||||||
|
Profile: default
|
||||||
|
Kernel Version: 5.13.0-1031-azure
|
||||||
|
Operating System: Ubuntu 20.04.4 LTS
|
||||||
|
OSType: linux
|
||||||
|
Architecture: x86_64
|
||||||
|
CPUs: 4
|
||||||
|
Total Memory: 15.63GiB
|
||||||
|
Name: dev
|
||||||
|
ID: UC44:2RFL:7NQ5:GGFW:34O5:DYRE:CLOH:VLGZ:64AZ:GFXC:PY6H:SAHY
|
||||||
|
Docker Root Dir: /var/lib/docker
|
||||||
|
Debug Mode: true
|
||||||
|
File Descriptors: 46
|
||||||
|
Goroutines: 134
|
||||||
|
System Time: 2022-07-06T18:07:54.812439392Z
|
||||||
|
EventsListeners: 0
|
||||||
|
Registry: https://index.docker.io/v1/
|
||||||
|
Labels:
|
||||||
|
Experimental: true
|
||||||
|
Insecure Registries:
|
||||||
|
127.0.0.0/8
|
||||||
|
Live Restore Enabled: true
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: additional
|
||||||
|
attributes:
|
||||||
|
label: Additional Info
|
||||||
|
description: Additional info you want to provide such as logs, system info, environment, etc.
|
||||||
|
validations:
|
||||||
|
required: false
|
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: Security and Vulnerabilities
|
||||||
|
url: https://github.com/moby/moby/blob/master/SECURITY.md
|
||||||
|
about: Please report any security issues or vulnerabilities responsibly to the Docker security team. Please do not use the public issue tracker.
|
||||||
|
- name: Questions and Discussions
|
||||||
|
url: https://github.com/moby/moby/discussions/new
|
||||||
|
about: Use Github Discussions to ask questions and/or open discussion topics.
|
13
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
13
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
name: Feature request
|
||||||
|
description: Missing functionality? Come tell us about it!
|
||||||
|
labels:
|
||||||
|
- kind/feature
|
||||||
|
- status/0-triage
|
||||||
|
body:
|
||||||
|
- type: textarea
|
||||||
|
id: description
|
||||||
|
attributes:
|
||||||
|
label: Description
|
||||||
|
description: What is the feature you want to see?
|
||||||
|
validations:
|
||||||
|
required: true
|
5
.github/PULL_REQUEST_TEMPLATE.md
vendored
5
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
@ -22,9 +22,12 @@ Please provide the following information:
|
||||||
**- Description for the changelog**
|
**- Description for the changelog**
|
||||||
<!--
|
<!--
|
||||||
Write a short (one line) summary that describes the changes in this
|
Write a short (one line) summary that describes the changes in this
|
||||||
pull request for inclusion in the changelog:
|
pull request for inclusion in the changelog.
|
||||||
|
It must be placed inside the below triple backticks section:
|
||||||
-->
|
-->
|
||||||
|
```markdown changelog
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
**- A picture of a cute animal (not mandatory but encouraged)**
|
**- A picture of a cute animal (not mandatory but encouraged)**
|
||||||
|
|
||||||
|
|
14
.github/actions/setup-tracing/action.yml
vendored
Normal file
14
.github/actions/setup-tracing/action.yml
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
name: 'Setup Tracing'
|
||||||
|
description: 'Composite action to set up the tracing for test jobs'
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- run: |
|
||||||
|
set -e
|
||||||
|
# Jaeger is set up on Windows through an inline run step. If you update Jaeger here, don't forget to update
|
||||||
|
# the version set in .github/workflows/.windows.yml.
|
||||||
|
docker run -d --net=host --name jaeger -e COLLECTOR_OTLP_ENABLED=true jaegertracing/all-in-one:1.46
|
||||||
|
docker0_ip="$(ip -f inet addr show docker0 | grep -Po 'inet \K[\d.]+')"
|
||||||
|
echo "OTEL_EXPORTER_OTLP_ENDPOINT=http://${docker0_ip}:4318" >> "${GITHUB_ENV}"
|
||||||
|
shell: bash
|
6
.github/workflows/.dco.yml
vendored
6
.github/workflows/.dco.yml
vendored
|
@ -15,19 +15,19 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
-
|
-
|
||||||
name: Dump context
|
name: Dump context
|
||||||
uses: actions/github-script@v6
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
console.log(JSON.stringify(context, null, 2));
|
console.log(JSON.stringify(context, null, 2));
|
||||||
-
|
-
|
||||||
name: Get base ref
|
name: Get base ref
|
||||||
id: base-ref
|
id: base-ref
|
||||||
uses: actions/github-script@v6
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
result-encoding: string
|
result-encoding: string
|
||||||
script: |
|
script: |
|
||||||
|
|
35
.github/workflows/.test-prepare.yml
vendored
Normal file
35
.github/workflows/.test-prepare.yml
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
# reusable workflow
|
||||||
|
name: .test-prepare
|
||||||
|
|
||||||
|
# TODO: hide reusable workflow from the UI. Tracked in https://github.com/community/community/discussions/12025
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
outputs:
|
||||||
|
matrix:
|
||||||
|
description: Test matrix
|
||||||
|
value: ${{ jobs.run.outputs.matrix }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
run:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
outputs:
|
||||||
|
matrix: ${{ steps.set.outputs.matrix }}
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Create matrix
|
||||||
|
id: set
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
let matrix = ['graphdriver'];
|
||||||
|
if ("${{ contains(github.event.pull_request.labels.*.name, 'containerd-integration') || github.event_name != 'pull_request' }}" == "true") {
|
||||||
|
matrix.push('snapshotter');
|
||||||
|
}
|
||||||
|
await core.group(`Set matrix`, async () => {
|
||||||
|
core.info(`matrix: ${JSON.stringify(matrix)}`);
|
||||||
|
core.setOutput('matrix', JSON.stringify(matrix));
|
||||||
|
});
|
445
.github/workflows/.test.yml
vendored
Normal file
445
.github/workflows/.test.yml
vendored
Normal file
|
@ -0,0 +1,445 @@
|
||||||
|
# reusable workflow
|
||||||
|
name: .test
|
||||||
|
|
||||||
|
# TODO: hide reusable workflow from the UI. Tracked in https://github.com/community/community/discussions/12025
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
storage:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
default: "graphdriver"
|
||||||
|
|
||||||
|
env:
|
||||||
|
GO_VERSION: "1.21.9"
|
||||||
|
GOTESTLIST_VERSION: v0.3.1
|
||||||
|
TESTSTAT_VERSION: v0.1.25
|
||||||
|
ITG_CLI_MATRIX_SIZE: 6
|
||||||
|
DOCKER_EXPERIMENTAL: 1
|
||||||
|
DOCKER_GRAPHDRIVER: ${{ inputs.storage == 'snapshotter' && 'overlayfs' || 'overlay2' }}
|
||||||
|
TEST_INTEGRATION_USE_SNAPSHOTTER: ${{ inputs.storage == 'snapshotter' && '1' || '' }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
unit:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
continue-on-error: ${{ github.event_name != 'pull_request' }}
|
||||||
|
timeout-minutes: 120
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Set up runner
|
||||||
|
uses: ./.github/actions/setup-runner
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
-
|
||||||
|
name: Build dev image
|
||||||
|
uses: docker/bake-action@v4
|
||||||
|
with:
|
||||||
|
targets: dev
|
||||||
|
set: |
|
||||||
|
dev.cache-from=type=gha,scope=dev
|
||||||
|
-
|
||||||
|
name: Test
|
||||||
|
run: |
|
||||||
|
make -o build test-unit
|
||||||
|
-
|
||||||
|
name: Prepare reports
|
||||||
|
if: always()
|
||||||
|
run: |
|
||||||
|
mkdir -p bundles /tmp/reports
|
||||||
|
find bundles -path '*/root/*overlay2' -prune -o -type f \( -name '*-report.json' -o -name '*.log' -o -name '*.out' -o -name '*.prof' -o -name '*-report.xml' \) -print | xargs sudo tar -czf /tmp/reports.tar.gz
|
||||||
|
tar -xzf /tmp/reports.tar.gz -C /tmp/reports
|
||||||
|
sudo chown -R $(id -u):$(id -g) /tmp/reports
|
||||||
|
tree -nh /tmp/reports
|
||||||
|
-
|
||||||
|
name: Send to Codecov
|
||||||
|
uses: codecov/codecov-action@v4
|
||||||
|
with:
|
||||||
|
directory: ./bundles
|
||||||
|
env_vars: RUNNER_OS
|
||||||
|
flags: unit
|
||||||
|
token: ${{ secrets.CODECOV_TOKEN }} # used to upload coverage reports: https://github.com/moby/buildkit/pull/4660#issue-2142122533
|
||||||
|
-
|
||||||
|
name: Upload reports
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: test-reports-unit-${{ inputs.storage }}
|
||||||
|
path: /tmp/reports/*
|
||||||
|
retention-days: 1
|
||||||
|
|
||||||
|
unit-report:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
continue-on-error: ${{ github.event_name != 'pull_request' }}
|
||||||
|
timeout-minutes: 10
|
||||||
|
if: always()
|
||||||
|
needs:
|
||||||
|
- unit
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: ${{ env.GO_VERSION }}
|
||||||
|
-
|
||||||
|
name: Download reports
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: test-reports-unit-${{ inputs.storage }}
|
||||||
|
path: /tmp/reports
|
||||||
|
-
|
||||||
|
name: Install teststat
|
||||||
|
run: |
|
||||||
|
go install github.com/vearutop/teststat@${{ env.TESTSTAT_VERSION }}
|
||||||
|
-
|
||||||
|
name: Create summary
|
||||||
|
run: |
|
||||||
|
find /tmp/reports -type f -name '*-go-test-report.json' -exec teststat -markdown {} \+ >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
|
docker-py:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
continue-on-error: ${{ github.event_name != 'pull_request' }}
|
||||||
|
timeout-minutes: 120
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Set up runner
|
||||||
|
uses: ./.github/actions/setup-runner
|
||||||
|
-
|
||||||
|
name: Set up tracing
|
||||||
|
uses: ./.github/actions/setup-tracing
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
-
|
||||||
|
name: Build dev image
|
||||||
|
uses: docker/bake-action@v4
|
||||||
|
with:
|
||||||
|
targets: dev
|
||||||
|
set: |
|
||||||
|
dev.cache-from=type=gha,scope=dev
|
||||||
|
-
|
||||||
|
name: Test
|
||||||
|
run: |
|
||||||
|
make -o build test-docker-py
|
||||||
|
-
|
||||||
|
name: Prepare reports
|
||||||
|
if: always()
|
||||||
|
run: |
|
||||||
|
mkdir -p bundles /tmp/reports
|
||||||
|
find bundles -path '*/root/*overlay2' -prune -o -type f \( -name '*-report.json' -o -name '*.log' -o -name '*.out' -o -name '*.prof' -o -name '*-report.xml' \) -print | xargs sudo tar -czf /tmp/reports.tar.gz
|
||||||
|
tar -xzf /tmp/reports.tar.gz -C /tmp/reports
|
||||||
|
sudo chown -R $(id -u):$(id -g) /tmp/reports
|
||||||
|
tree -nh /tmp/reports
|
||||||
|
|
||||||
|
curl -sSLf localhost:16686/api/traces?service=integration-test-client > /tmp/reports/jaeger-trace.json
|
||||||
|
-
|
||||||
|
name: Test daemon logs
|
||||||
|
if: always()
|
||||||
|
run: |
|
||||||
|
cat bundles/test-docker-py/docker.log
|
||||||
|
-
|
||||||
|
name: Upload reports
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: test-reports-docker-py-${{ inputs.storage }}
|
||||||
|
path: /tmp/reports/*
|
||||||
|
retention-days: 1
|
||||||
|
|
||||||
|
integration-flaky:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
continue-on-error: ${{ github.event_name != 'pull_request' }}
|
||||||
|
timeout-minutes: 120
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Set up runner
|
||||||
|
uses: ./.github/actions/setup-runner
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
-
|
||||||
|
name: Build dev image
|
||||||
|
uses: docker/bake-action@v4
|
||||||
|
with:
|
||||||
|
targets: dev
|
||||||
|
set: |
|
||||||
|
dev.cache-from=type=gha,scope=dev
|
||||||
|
-
|
||||||
|
name: Test
|
||||||
|
run: |
|
||||||
|
make -o build test-integration-flaky
|
||||||
|
env:
|
||||||
|
TEST_SKIP_INTEGRATION_CLI: 1
|
||||||
|
|
||||||
|
integration:
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
continue-on-error: ${{ github.event_name != 'pull_request' }}
|
||||||
|
timeout-minutes: 120
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os:
|
||||||
|
- ubuntu-20.04
|
||||||
|
- ubuntu-22.04
|
||||||
|
mode:
|
||||||
|
- ""
|
||||||
|
- rootless
|
||||||
|
- systemd
|
||||||
|
#- rootless-systemd FIXME: https://github.com/moby/moby/issues/44084
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Set up runner
|
||||||
|
uses: ./.github/actions/setup-runner
|
||||||
|
-
|
||||||
|
name: Set up tracing
|
||||||
|
uses: ./.github/actions/setup-tracing
|
||||||
|
-
|
||||||
|
name: Prepare
|
||||||
|
run: |
|
||||||
|
CACHE_DEV_SCOPE=dev
|
||||||
|
if [[ "${{ matrix.mode }}" == *"rootless"* ]]; then
|
||||||
|
echo "DOCKER_ROOTLESS=1" >> $GITHUB_ENV
|
||||||
|
fi
|
||||||
|
if [[ "${{ matrix.mode }}" == *"systemd"* ]]; then
|
||||||
|
echo "SYSTEMD=true" >> $GITHUB_ENV
|
||||||
|
CACHE_DEV_SCOPE="${CACHE_DEV_SCOPE}systemd"
|
||||||
|
fi
|
||||||
|
echo "CACHE_DEV_SCOPE=${CACHE_DEV_SCOPE}" >> $GITHUB_ENV
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
-
|
||||||
|
name: Build dev image
|
||||||
|
uses: docker/bake-action@v4
|
||||||
|
with:
|
||||||
|
targets: dev
|
||||||
|
set: |
|
||||||
|
dev.cache-from=type=gha,scope=${{ env.CACHE_DEV_SCOPE }}
|
||||||
|
-
|
||||||
|
name: Test
|
||||||
|
run: |
|
||||||
|
make -o build test-integration
|
||||||
|
env:
|
||||||
|
TEST_SKIP_INTEGRATION_CLI: 1
|
||||||
|
TESTCOVERAGE: 1
|
||||||
|
-
|
||||||
|
name: Prepare reports
|
||||||
|
if: always()
|
||||||
|
run: |
|
||||||
|
reportsName=${{ matrix.os }}
|
||||||
|
if [ -n "${{ matrix.mode }}" ]; then
|
||||||
|
reportsName="$reportsName-${{ matrix.mode }}"
|
||||||
|
fi
|
||||||
|
reportsPath="/tmp/reports/$reportsName"
|
||||||
|
echo "TESTREPORTS_NAME=$reportsName" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
mkdir -p bundles $reportsPath
|
||||||
|
find bundles -path '*/root/*overlay2' -prune -o -type f \( -name '*-report.json' -o -name '*.log' -o -name '*.out' -o -name '*.prof' -o -name '*-report.xml' \) -print | xargs sudo tar -czf /tmp/reports.tar.gz
|
||||||
|
tar -xzf /tmp/reports.tar.gz -C $reportsPath
|
||||||
|
sudo chown -R $(id -u):$(id -g) $reportsPath
|
||||||
|
tree -nh $reportsPath
|
||||||
|
|
||||||
|
curl -sSLf localhost:16686/api/traces?service=integration-test-client > $reportsPath/jaeger-trace.json
|
||||||
|
-
|
||||||
|
name: Send to Codecov
|
||||||
|
uses: codecov/codecov-action@v4
|
||||||
|
with:
|
||||||
|
directory: ./bundles/test-integration
|
||||||
|
env_vars: RUNNER_OS
|
||||||
|
flags: integration,${{ matrix.mode }}
|
||||||
|
token: ${{ secrets.CODECOV_TOKEN }} # used to upload coverage reports: https://github.com/moby/buildkit/pull/4660#issue-2142122533
|
||||||
|
-
|
||||||
|
name: Test daemon logs
|
||||||
|
if: always()
|
||||||
|
run: |
|
||||||
|
cat bundles/test-integration/docker.log
|
||||||
|
-
|
||||||
|
name: Upload reports
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: test-reports-integration-${{ inputs.storage }}-${{ env.TESTREPORTS_NAME }}
|
||||||
|
path: /tmp/reports/*
|
||||||
|
retention-days: 1
|
||||||
|
|
||||||
|
integration-report:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
continue-on-error: ${{ github.event_name != 'pull_request' }}
|
||||||
|
timeout-minutes: 10
|
||||||
|
if: always()
|
||||||
|
needs:
|
||||||
|
- integration
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: ${{ env.GO_VERSION }}
|
||||||
|
-
|
||||||
|
name: Download reports
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
path: /tmp/reports
|
||||||
|
pattern: test-reports-integration-${{ inputs.storage }}-*
|
||||||
|
merge-multiple: true
|
||||||
|
-
|
||||||
|
name: Install teststat
|
||||||
|
run: |
|
||||||
|
go install github.com/vearutop/teststat@${{ env.TESTSTAT_VERSION }}
|
||||||
|
-
|
||||||
|
name: Create summary
|
||||||
|
run: |
|
||||||
|
find /tmp/reports -type f -name '*-go-test-report.json' -exec teststat -markdown {} \+ >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
|
integration-cli-prepare:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
continue-on-error: ${{ github.event_name != 'pull_request' }}
|
||||||
|
outputs:
|
||||||
|
matrix: ${{ steps.tests.outputs.matrix }}
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: ${{ env.GO_VERSION }}
|
||||||
|
-
|
||||||
|
name: Install gotestlist
|
||||||
|
run:
|
||||||
|
go install github.com/crazy-max/gotestlist/cmd/gotestlist@${{ env.GOTESTLIST_VERSION }}
|
||||||
|
-
|
||||||
|
name: Create matrix
|
||||||
|
id: tests
|
||||||
|
working-directory: ./integration-cli
|
||||||
|
run: |
|
||||||
|
# This step creates a matrix for integration-cli tests. Tests suites
|
||||||
|
# are distributed in integration-cli job through a matrix. There is
|
||||||
|
# also overrides being added to the matrix like "./..." to run
|
||||||
|
# "Test integration" step exclusively and specific tests suites that
|
||||||
|
# take a long time to run.
|
||||||
|
matrix="$(gotestlist -d ${{ env.ITG_CLI_MATRIX_SIZE }} -o "./..." -o "DockerSwarmSuite" -o "DockerNetworkSuite|DockerExternalVolumeSuite" ./...)"
|
||||||
|
echo "matrix=$matrix" >> $GITHUB_OUTPUT
|
||||||
|
-
|
||||||
|
name: Show matrix
|
||||||
|
run: |
|
||||||
|
echo ${{ steps.tests.outputs.matrix }}
|
||||||
|
|
||||||
|
integration-cli:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
continue-on-error: ${{ github.event_name != 'pull_request' }}
|
||||||
|
timeout-minutes: 120
|
||||||
|
needs:
|
||||||
|
- integration-cli-prepare
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
test: ${{ fromJson(needs.integration-cli-prepare.outputs.matrix) }}
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Set up runner
|
||||||
|
uses: ./.github/actions/setup-runner
|
||||||
|
-
|
||||||
|
name: Set up tracing
|
||||||
|
uses: ./.github/actions/setup-tracing
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
-
|
||||||
|
name: Build dev image
|
||||||
|
uses: docker/bake-action@v4
|
||||||
|
with:
|
||||||
|
targets: dev
|
||||||
|
set: |
|
||||||
|
dev.cache-from=type=gha,scope=dev
|
||||||
|
-
|
||||||
|
name: Test
|
||||||
|
run: |
|
||||||
|
make -o build test-integration
|
||||||
|
env:
|
||||||
|
TEST_SKIP_INTEGRATION: 1
|
||||||
|
TESTCOVERAGE: 1
|
||||||
|
TESTFLAGS: "-test.run (${{ matrix.test }})/"
|
||||||
|
-
|
||||||
|
name: Prepare reports
|
||||||
|
if: always()
|
||||||
|
run: |
|
||||||
|
reportsName=$(echo -n "${{ matrix.test }}" | sha256sum | cut -d " " -f 1)
|
||||||
|
reportsPath=/tmp/reports/$reportsName
|
||||||
|
echo "TESTREPORTS_NAME=$reportsName" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
mkdir -p bundles $reportsPath
|
||||||
|
echo "${{ matrix.test }}" | tr -s '|' '\n' | tee -a "$reportsPath/tests.txt"
|
||||||
|
find bundles -path '*/root/*overlay2' -prune -o -type f \( -name '*-report.json' -o -name '*.log' -o -name '*.out' -o -name '*.prof' -o -name '*-report.xml' \) -print | xargs sudo tar -czf /tmp/reports.tar.gz
|
||||||
|
tar -xzf /tmp/reports.tar.gz -C $reportsPath
|
||||||
|
sudo chown -R $(id -u):$(id -g) $reportsPath
|
||||||
|
tree -nh $reportsPath
|
||||||
|
|
||||||
|
curl -sSLf localhost:16686/api/traces?service=integration-test-client > $reportsPath/jaeger-trace.json
|
||||||
|
-
|
||||||
|
name: Send to Codecov
|
||||||
|
uses: codecov/codecov-action@v4
|
||||||
|
with:
|
||||||
|
directory: ./bundles/test-integration
|
||||||
|
env_vars: RUNNER_OS
|
||||||
|
flags: integration-cli
|
||||||
|
token: ${{ secrets.CODECOV_TOKEN }} # used to upload coverage reports: https://github.com/moby/buildkit/pull/4660#issue-2142122533
|
||||||
|
-
|
||||||
|
name: Test daemon logs
|
||||||
|
if: always()
|
||||||
|
run: |
|
||||||
|
cat bundles/test-integration/docker.log
|
||||||
|
-
|
||||||
|
name: Upload reports
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: test-reports-integration-cli-${{ inputs.storage }}-${{ env.TESTREPORTS_NAME }}
|
||||||
|
path: /tmp/reports/*
|
||||||
|
retention-days: 1
|
||||||
|
|
||||||
|
integration-cli-report:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
continue-on-error: ${{ github.event_name != 'pull_request' }}
|
||||||
|
timeout-minutes: 10
|
||||||
|
if: always()
|
||||||
|
needs:
|
||||||
|
- integration-cli
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: ${{ env.GO_VERSION }}
|
||||||
|
-
|
||||||
|
name: Download reports
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
path: /tmp/reports
|
||||||
|
pattern: test-reports-integration-cli-${{ inputs.storage }}-*
|
||||||
|
merge-multiple: true
|
||||||
|
-
|
||||||
|
name: Install teststat
|
||||||
|
run: |
|
||||||
|
go install github.com/vearutop/teststat@${{ env.TESTSTAT_VERSION }}
|
||||||
|
-
|
||||||
|
name: Create summary
|
||||||
|
run: |
|
||||||
|
find /tmp/reports -type f -name '*-go-test-report.json' -exec teststat -markdown {} \+ >> $GITHUB_STEP_SUMMARY
|
128
.github/workflows/.windows.yml
vendored
128
.github/workflows/.windows.yml
vendored
|
@ -9,15 +9,19 @@ on:
|
||||||
os:
|
os:
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
|
storage:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
default: "graphdriver"
|
||||||
send_coverage:
|
send_coverage:
|
||||||
required: false
|
required: false
|
||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
|
|
||||||
env:
|
env:
|
||||||
GO_VERSION: "1.20.13"
|
GO_VERSION: "1.21.9"
|
||||||
GOTESTLIST_VERSION: v0.3.1
|
GOTESTLIST_VERSION: v0.3.1
|
||||||
TESTSTAT_VERSION: v0.1.3
|
TESTSTAT_VERSION: v0.1.25
|
||||||
WINDOWS_BASE_IMAGE: mcr.microsoft.com/windows/servercore
|
WINDOWS_BASE_IMAGE: mcr.microsoft.com/windows/servercore
|
||||||
WINDOWS_BASE_TAG_2019: ltsc2019
|
WINDOWS_BASE_TAG_2019: ltsc2019
|
||||||
WINDOWS_BASE_TAG_2022: ltsc2022
|
WINDOWS_BASE_TAG_2022: ltsc2022
|
||||||
|
@ -39,7 +43,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
path: ${{ env.GOPATH }}/src/github.com/docker/docker
|
path: ${{ env.GOPATH }}/src/github.com/docker/docker
|
||||||
-
|
-
|
||||||
|
@ -58,7 +62,7 @@ jobs:
|
||||||
}
|
}
|
||||||
-
|
-
|
||||||
name: Cache
|
name: Cache
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~\AppData\Local\go-build
|
~\AppData\Local\go-build
|
||||||
|
@ -75,9 +79,12 @@ jobs:
|
||||||
-
|
-
|
||||||
name: Build base image
|
name: Build base image
|
||||||
run: |
|
run: |
|
||||||
docker pull ${{ env.WINDOWS_BASE_IMAGE }}:${{ env.WINDOWS_BASE_IMAGE_TAG }}
|
& docker build `
|
||||||
docker tag ${{ env.WINDOWS_BASE_IMAGE }}:${{ env.WINDOWS_BASE_IMAGE_TAG }} microsoft/windowsservercore
|
--build-arg WINDOWS_BASE_IMAGE `
|
||||||
docker build --build-arg GO_VERSION -t ${{ env.TEST_IMAGE_NAME }} -f Dockerfile.windows .
|
--build-arg WINDOWS_BASE_IMAGE_TAG `
|
||||||
|
--build-arg GO_VERSION `
|
||||||
|
-t ${{ env.TEST_IMAGE_NAME }} `
|
||||||
|
-f Dockerfile.windows .
|
||||||
-
|
-
|
||||||
name: Build binaries
|
name: Build binaries
|
||||||
run: |
|
run: |
|
||||||
|
@ -96,9 +103,9 @@ jobs:
|
||||||
docker cp "${{ env.TEST_CTN_NAME }}`:c`:\containerd\bin\containerd-shim-runhcs-v1.exe" ${{ env.BIN_OUT }}\
|
docker cp "${{ env.TEST_CTN_NAME }}`:c`:\containerd\bin\containerd-shim-runhcs-v1.exe" ${{ env.BIN_OUT }}\
|
||||||
-
|
-
|
||||||
name: Upload artifacts
|
name: Upload artifacts
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: build-${{ inputs.os }}
|
name: build-${{ inputs.storage }}-${{ inputs.os }}
|
||||||
path: ${{ env.BIN_OUT }}/*
|
path: ${{ env.BIN_OUT }}/*
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
retention-days: 2
|
retention-days: 2
|
||||||
|
@ -115,7 +122,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
path: ${{ env.GOPATH }}/src/github.com/docker/docker
|
path: ${{ env.GOPATH }}/src/github.com/docker/docker
|
||||||
-
|
-
|
||||||
|
@ -135,7 +142,7 @@ jobs:
|
||||||
}
|
}
|
||||||
-
|
-
|
||||||
name: Cache
|
name: Cache
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~\AppData\Local\go-build
|
~\AppData\Local\go-build
|
||||||
|
@ -152,9 +159,12 @@ jobs:
|
||||||
-
|
-
|
||||||
name: Build base image
|
name: Build base image
|
||||||
run: |
|
run: |
|
||||||
docker pull ${{ env.WINDOWS_BASE_IMAGE }}:${{ env.WINDOWS_BASE_IMAGE_TAG }}
|
& docker build `
|
||||||
docker tag ${{ env.WINDOWS_BASE_IMAGE }}:${{ env.WINDOWS_BASE_IMAGE_TAG }} microsoft/windowsservercore
|
--build-arg WINDOWS_BASE_IMAGE `
|
||||||
docker build --build-arg GO_VERSION -t ${{ env.TEST_IMAGE_NAME }} -f Dockerfile.windows .
|
--build-arg WINDOWS_BASE_IMAGE_TAG `
|
||||||
|
--build-arg GO_VERSION `
|
||||||
|
-t ${{ env.TEST_IMAGE_NAME }} `
|
||||||
|
-f Dockerfile.windows .
|
||||||
-
|
-
|
||||||
name: Test
|
name: Test
|
||||||
run: |
|
run: |
|
||||||
|
@ -166,19 +176,21 @@ jobs:
|
||||||
-
|
-
|
||||||
name: Send to Codecov
|
name: Send to Codecov
|
||||||
if: inputs.send_coverage
|
if: inputs.send_coverage
|
||||||
uses: codecov/codecov-action@v3
|
uses: codecov/codecov-action@v4
|
||||||
with:
|
with:
|
||||||
working-directory: ${{ env.GOPATH }}\src\github.com\docker\docker
|
working-directory: ${{ env.GOPATH }}\src\github.com\docker\docker
|
||||||
directory: bundles
|
directory: bundles
|
||||||
env_vars: RUNNER_OS
|
env_vars: RUNNER_OS
|
||||||
flags: unit
|
flags: unit
|
||||||
|
token: ${{ secrets.CODECOV_TOKEN }} # used to upload coverage reports: https://github.com/moby/buildkit/pull/4660#issue-2142122533
|
||||||
-
|
-
|
||||||
name: Upload reports
|
name: Upload reports
|
||||||
if: always()
|
if: always()
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ inputs.os }}-unit-reports
|
name: ${{ inputs.os }}-${{ inputs.storage }}-unit-reports
|
||||||
path: ${{ env.GOPATH }}\src\github.com\docker\docker\bundles\*
|
path: ${{ env.GOPATH }}\src\github.com\docker\docker\bundles\*
|
||||||
|
retention-days: 1
|
||||||
|
|
||||||
unit-test-report:
|
unit-test-report:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -188,14 +200,14 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Set up Go
|
name: Set up Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ${{ env.GO_VERSION }}
|
go-version: ${{ env.GO_VERSION }}
|
||||||
-
|
-
|
||||||
name: Download artifacts
|
name: Download artifacts
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ inputs.os }}-unit-reports
|
name: ${{ inputs.os }}-${{ inputs.storage }}-unit-reports
|
||||||
path: /tmp/artifacts
|
path: /tmp/artifacts
|
||||||
-
|
-
|
||||||
name: Install teststat
|
name: Install teststat
|
||||||
|
@ -204,7 +216,7 @@ jobs:
|
||||||
-
|
-
|
||||||
name: Create summary
|
name: Create summary
|
||||||
run: |
|
run: |
|
||||||
teststat -markdown $(find /tmp/artifacts -type f -name '*.json' -print0 | xargs -0) >> $GITHUB_STEP_SUMMARY
|
find /tmp/artifacts -type f -name '*-go-test-report.json' -exec teststat -markdown {} \+ >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
integration-test-prepare:
|
integration-test-prepare:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -213,10 +225,10 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
-
|
-
|
||||||
name: Set up Go
|
name: Set up Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ${{ env.GO_VERSION }}
|
go-version: ${{ env.GO_VERSION }}
|
||||||
-
|
-
|
||||||
|
@ -241,6 +253,7 @@ jobs:
|
||||||
|
|
||||||
integration-test:
|
integration-test:
|
||||||
runs-on: ${{ inputs.os }}
|
runs-on: ${{ inputs.os }}
|
||||||
|
continue-on-error: ${{ inputs.storage == 'snapshotter' && github.event_name != 'pull_request' }}
|
||||||
timeout-minutes: 120
|
timeout-minutes: 120
|
||||||
needs:
|
needs:
|
||||||
- build
|
- build
|
||||||
|
@ -248,10 +261,15 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
storage:
|
||||||
|
- ${{ inputs.storage }}
|
||||||
runtime:
|
runtime:
|
||||||
- builtin
|
- builtin
|
||||||
- containerd
|
- containerd
|
||||||
test: ${{ fromJson(needs.integration-test-prepare.outputs.matrix) }}
|
test: ${{ fromJson(needs.integration-test-prepare.outputs.matrix) }}
|
||||||
|
exclude:
|
||||||
|
- storage: snapshotter
|
||||||
|
runtime: builtin
|
||||||
env:
|
env:
|
||||||
GOPATH: ${{ github.workspace }}\go
|
GOPATH: ${{ github.workspace }}\go
|
||||||
GOBIN: ${{ github.workspace }}\go\bin
|
GOBIN: ${{ github.workspace }}\go\bin
|
||||||
|
@ -262,18 +280,28 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
path: ${{ env.GOPATH }}/src/github.com/docker/docker
|
path: ${{ env.GOPATH }}/src/github.com/docker/docker
|
||||||
|
-
|
||||||
|
name: Set up Jaeger
|
||||||
|
run: |
|
||||||
|
# Jaeger is set up on Linux through the setup-tracing action. If you update Jaeger here, don't forget to
|
||||||
|
# update the version set in .github/actions/setup-tracing/action.yml.
|
||||||
|
Invoke-WebRequest -Uri "https://github.com/jaegertracing/jaeger/releases/download/v1.46.0/jaeger-1.46.0-windows-amd64.tar.gz" -OutFile ".\jaeger-1.46.0-windows-amd64.tar.gz"
|
||||||
|
tar -zxvf ".\jaeger-1.46.0-windows-amd64.tar.gz"
|
||||||
|
Start-Process '.\jaeger-1.46.0-windows-amd64\jaeger-all-in-one.exe'
|
||||||
|
echo "OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4318" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
|
||||||
|
shell: pwsh
|
||||||
-
|
-
|
||||||
name: Env
|
name: Env
|
||||||
run: |
|
run: |
|
||||||
Get-ChildItem Env: | Out-String
|
Get-ChildItem Env: | Out-String
|
||||||
-
|
-
|
||||||
name: Download artifacts
|
name: Download artifacts
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: build-${{ inputs.os }}
|
name: build-${{ inputs.storage }}-${{ inputs.os }}
|
||||||
path: ${{ env.BIN_OUT }}
|
path: ${{ env.BIN_OUT }}
|
||||||
-
|
-
|
||||||
name: Init
|
name: Init
|
||||||
|
@ -285,6 +313,9 @@ jobs:
|
||||||
echo "WINDOWS_BASE_IMAGE_TAG=${{ env.WINDOWS_BASE_TAG_2022 }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
|
echo "WINDOWS_BASE_IMAGE_TAG=${{ env.WINDOWS_BASE_TAG_2022 }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
|
||||||
}
|
}
|
||||||
Write-Output "${{ env.BIN_OUT }}" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
Write-Output "${{ env.BIN_OUT }}" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||||
|
|
||||||
|
$testName = ([System.BitConverter]::ToString((New-Object System.Security.Cryptography.SHA256Managed).ComputeHash([System.Text.Encoding]::UTF8.GetBytes("${{ matrix.test }}"))) -replace '-').ToLower()
|
||||||
|
echo "TESTREPORTS_NAME=$testName" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
|
||||||
-
|
-
|
||||||
# removes docker service that is currently installed on the runner. we
|
# removes docker service that is currently installed on the runner. we
|
||||||
# could use Uninstall-Package but not yet available on Windows runners.
|
# could use Uninstall-Package but not yet available on Windows runners.
|
||||||
|
@ -342,6 +373,11 @@ jobs:
|
||||||
"--exec-root=$env:TEMP\moby-exec", `
|
"--exec-root=$env:TEMP\moby-exec", `
|
||||||
"--pidfile=$env:TEMP\docker.pid", `
|
"--pidfile=$env:TEMP\docker.pid", `
|
||||||
"--register-service"
|
"--register-service"
|
||||||
|
If ("${{ inputs.storage }}" -eq "snapshotter") {
|
||||||
|
# Make the env-var visible to the service-managed dockerd, as there's no CLI flag for this option.
|
||||||
|
& reg add "HKLM\SYSTEM\CurrentControlSet\Services\docker" /v Environment /t REG_MULTI_SZ /s '@' /d TEST_INTEGRATION_USE_SNAPSHOTTER=1
|
||||||
|
echo "TEST_INTEGRATION_USE_SNAPSHOTTER=1" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
|
||||||
|
}
|
||||||
Write-Host "Starting service"
|
Write-Host "Starting service"
|
||||||
Start-Service -Name docker
|
Start-Service -Name docker
|
||||||
Write-Host "Service started successfully!"
|
Write-Host "Service started successfully!"
|
||||||
|
@ -390,7 +426,7 @@ jobs:
|
||||||
DOCKER_HOST: npipe:////./pipe/docker_engine
|
DOCKER_HOST: npipe:////./pipe/docker_engine
|
||||||
-
|
-
|
||||||
name: Set up Go
|
name: Set up Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ${{ env.GO_VERSION }}
|
go-version: ${{ env.GO_VERSION }}
|
||||||
-
|
-
|
||||||
|
@ -415,12 +451,13 @@ jobs:
|
||||||
-
|
-
|
||||||
name: Send to Codecov
|
name: Send to Codecov
|
||||||
if: inputs.send_coverage
|
if: inputs.send_coverage
|
||||||
uses: codecov/codecov-action@v3
|
uses: codecov/codecov-action@v4
|
||||||
with:
|
with:
|
||||||
working-directory: ${{ env.GOPATH }}\src\github.com\docker\docker
|
working-directory: ${{ env.GOPATH }}\src\github.com\docker\docker
|
||||||
directory: bundles
|
directory: bundles
|
||||||
env_vars: RUNNER_OS
|
env_vars: RUNNER_OS
|
||||||
flags: integration,${{ matrix.runtime }}
|
flags: integration,${{ matrix.runtime }}
|
||||||
|
token: ${{ secrets.CODECOV_TOKEN }} # used to upload coverage reports: https://github.com/moby/buildkit/pull/4660#issue-2142122533
|
||||||
-
|
-
|
||||||
name: Docker info
|
name: Docker info
|
||||||
run: |
|
run: |
|
||||||
|
@ -455,40 +492,55 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
Get-WinEvent -ea SilentlyContinue `
|
Get-WinEvent -ea SilentlyContinue `
|
||||||
-FilterHashtable @{ProviderName= "docker"; LogName = "application"} |
|
-FilterHashtable @{ProviderName= "docker"; LogName = "application"} |
|
||||||
Select-Object -Property TimeCreated, @{N='Detailed Message'; E={$_.Message}} |
|
|
||||||
Sort-Object @{Expression="TimeCreated";Descending=$false} |
|
Sort-Object @{Expression="TimeCreated";Descending=$false} |
|
||||||
Select-Object -ExpandProperty 'Detailed Message' | Tee-Object -file ".\bundles\daemon.log"
|
ForEach-Object {"$($_.TimeCreated.ToUniversalTime().ToString("o")) [$($_.LevelDisplayName)] $($_.Message)"} |
|
||||||
|
Tee-Object -file ".\bundles\daemon.log"
|
||||||
|
-
|
||||||
|
name: Download Jaeger traces
|
||||||
|
if: always()
|
||||||
|
run: |
|
||||||
|
Invoke-WebRequest `
|
||||||
|
-Uri "http://127.0.0.1:16686/api/traces?service=integration-test-client" `
|
||||||
|
-OutFile ".\bundles\jaeger-trace.json"
|
||||||
-
|
-
|
||||||
name: Upload reports
|
name: Upload reports
|
||||||
if: always()
|
if: always()
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ inputs.os }}-integration-reports-${{ matrix.runtime }}
|
name: ${{ inputs.os }}-${{ inputs.storage }}-integration-reports-${{ matrix.runtime }}-${{ env.TESTREPORTS_NAME }}
|
||||||
path: ${{ env.GOPATH }}\src\github.com\docker\docker\bundles\*
|
path: ${{ env.GOPATH }}\src\github.com\docker\docker\bundles\*
|
||||||
|
retention-days: 1
|
||||||
|
|
||||||
integration-test-report:
|
integration-test-report:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
continue-on-error: ${{ inputs.storage == 'snapshotter' && github.event_name != 'pull_request' }}
|
||||||
if: always()
|
if: always()
|
||||||
needs:
|
needs:
|
||||||
- integration-test
|
- integration-test
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
storage:
|
||||||
|
- ${{ inputs.storage }}
|
||||||
runtime:
|
runtime:
|
||||||
- builtin
|
- builtin
|
||||||
- containerd
|
- containerd
|
||||||
|
exclude:
|
||||||
|
- storage: snapshotter
|
||||||
|
runtime: builtin
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Set up Go
|
name: Set up Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ${{ env.GO_VERSION }}
|
go-version: ${{ env.GO_VERSION }}
|
||||||
-
|
-
|
||||||
name: Download artifacts
|
name: Download reports
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ inputs.os }}-integration-reports-${{ matrix.runtime }}
|
path: /tmp/reports
|
||||||
path: /tmp/artifacts
|
pattern: ${{ inputs.os }}-${{ inputs.storage }}-integration-reports-${{ matrix.runtime }}-*
|
||||||
|
merge-multiple: true
|
||||||
-
|
-
|
||||||
name: Install teststat
|
name: Install teststat
|
||||||
run: |
|
run: |
|
||||||
|
@ -496,4 +548,4 @@ jobs:
|
||||||
-
|
-
|
||||||
name: Create summary
|
name: Create summary
|
||||||
run: |
|
run: |
|
||||||
teststat -markdown $(find /tmp/artifacts -type f -name '*.json' -print0 | xargs -0) >> $GITHUB_STEP_SUMMARY
|
find /tmp/reports -type f -name '*-go-test-report.json' -exec teststat -markdown {} \+ >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
191
.github/workflows/bin-image.yml
vendored
Normal file
191
.github/workflows/bin-image.yml
vendored
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
name: bin-image
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'master'
|
||||||
|
- '[0-9]+.[0-9]+'
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
env:
|
||||||
|
MOBYBIN_REPO_SLUG: moby/moby-bin
|
||||||
|
DOCKER_GITCOMMIT: ${{ github.sha }}
|
||||||
|
VERSION: ${{ github.ref }}
|
||||||
|
PLATFORM: Moby Engine - Nightly
|
||||||
|
PRODUCT: moby-bin
|
||||||
|
PACKAGER_NAME: The Moby Project
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
validate-dco:
|
||||||
|
if: ${{ !startsWith(github.ref, 'refs/tags/v') }}
|
||||||
|
uses: ./.github/workflows/.dco.yml
|
||||||
|
|
||||||
|
prepare:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
outputs:
|
||||||
|
platforms: ${{ steps.platforms.outputs.matrix }}
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
${{ env.MOBYBIN_REPO_SLUG }}
|
||||||
|
### versioning strategy
|
||||||
|
## push semver tag v23.0.0
|
||||||
|
# moby/moby-bin:23.0.0
|
||||||
|
# moby/moby-bin:latest
|
||||||
|
## push semver prelease tag v23.0.0-beta.1
|
||||||
|
# moby/moby-bin:23.0.0-beta.1
|
||||||
|
## push on master
|
||||||
|
# moby/moby-bin:master
|
||||||
|
## push on 23.0 branch
|
||||||
|
# moby/moby-bin:23.0
|
||||||
|
## any push
|
||||||
|
# moby/moby-bin:sha-ad132f5
|
||||||
|
tags: |
|
||||||
|
type=semver,pattern={{version}}
|
||||||
|
type=ref,event=branch
|
||||||
|
type=ref,event=pr
|
||||||
|
type=sha
|
||||||
|
-
|
||||||
|
name: Rename meta bake definition file
|
||||||
|
# see https://github.com/docker/metadata-action/issues/381#issuecomment-1918607161
|
||||||
|
run: |
|
||||||
|
bakeFile="${{ steps.meta.outputs.bake-file }}"
|
||||||
|
mv "${bakeFile#cwd://}" "/tmp/bake-meta.json"
|
||||||
|
-
|
||||||
|
name: Upload meta bake definition
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: bake-meta
|
||||||
|
path: /tmp/bake-meta.json
|
||||||
|
if-no-files-found: error
|
||||||
|
retention-days: 1
|
||||||
|
-
|
||||||
|
name: Create platforms matrix
|
||||||
|
id: platforms
|
||||||
|
run: |
|
||||||
|
echo "matrix=$(docker buildx bake bin-image-cross --print | jq -cr '.target."bin-image-cross".platforms')" >>${GITHUB_OUTPUT}
|
||||||
|
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
needs:
|
||||||
|
- validate-dco
|
||||||
|
- prepare
|
||||||
|
if: always() && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled')
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
platform: ${{ fromJson(needs.prepare.outputs.platforms) }}
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Prepare
|
||||||
|
run: |
|
||||||
|
platform=${{ matrix.platform }}
|
||||||
|
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
-
|
||||||
|
name: Download meta bake definition
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: bake-meta
|
||||||
|
path: /tmp
|
||||||
|
-
|
||||||
|
name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
-
|
||||||
|
name: Login to Docker Hub
|
||||||
|
if: github.event_name != 'pull_request' && github.repository == 'moby/moby'
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_MOBYBIN_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_MOBYBIN_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Build
|
||||||
|
id: bake
|
||||||
|
uses: docker/bake-action@v4
|
||||||
|
with:
|
||||||
|
files: |
|
||||||
|
./docker-bake.hcl
|
||||||
|
/tmp/bake-meta.json
|
||||||
|
targets: bin-image
|
||||||
|
set: |
|
||||||
|
*.platform=${{ matrix.platform }}
|
||||||
|
*.output=type=image,name=${{ env.MOBYBIN_REPO_SLUG }},push-by-digest=true,name-canonical=true,push=${{ github.event_name != 'pull_request' && github.repository == 'moby/moby' }}
|
||||||
|
*.tags=
|
||||||
|
-
|
||||||
|
name: Export digest
|
||||||
|
if: github.event_name != 'pull_request' && github.repository == 'moby/moby'
|
||||||
|
run: |
|
||||||
|
mkdir -p /tmp/digests
|
||||||
|
digest="${{ fromJSON(steps.bake.outputs.metadata)['bin-image']['containerimage.digest'] }}"
|
||||||
|
touch "/tmp/digests/${digest#sha256:}"
|
||||||
|
-
|
||||||
|
name: Upload digest
|
||||||
|
if: github.event_name != 'pull_request' && github.repository == 'moby/moby'
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: digests-${{ env.PLATFORM_PAIR }}
|
||||||
|
path: /tmp/digests/*
|
||||||
|
if-no-files-found: error
|
||||||
|
retention-days: 1
|
||||||
|
|
||||||
|
merge:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
needs:
|
||||||
|
- build
|
||||||
|
if: always() && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') && github.event_name != 'pull_request' && github.repository == 'moby/moby'
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Download meta bake definition
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: bake-meta
|
||||||
|
path: /tmp
|
||||||
|
-
|
||||||
|
name: Download digests
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
path: /tmp/digests
|
||||||
|
pattern: digests-*
|
||||||
|
merge-multiple: true
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
-
|
||||||
|
name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_MOBYBIN_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_MOBYBIN_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Create manifest list and push
|
||||||
|
working-directory: /tmp/digests
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
docker buildx imagetools create $(jq -cr '.target."docker-metadata-action".tags | map("-t " + .) | join(" ")' /tmp/bake-meta.json) \
|
||||||
|
$(printf '${{ env.MOBYBIN_REPO_SLUG }}@sha256:%s ' *)
|
||||||
|
-
|
||||||
|
name: Inspect image
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
docker buildx imagetools inspect ${{ env.MOBYBIN_REPO_SLUG }}:$(jq -cr '.target."docker-metadata-action".args.DOCKER_META_VERSION' /tmp/bake-meta.json)
|
52
.github/workflows/buildkit.yml
vendored
52
.github/workflows/buildkit.yml
vendored
|
@ -13,6 +13,7 @@ on:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
GO_VERSION: "1.21.9"
|
||||||
DESTDIR: ./build
|
DESTDIR: ./build
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
@ -26,18 +27,18 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v3
|
||||||
-
|
-
|
||||||
name: Build
|
name: Build
|
||||||
uses: docker/bake-action@v2
|
uses: docker/bake-action@v4
|
||||||
with:
|
with:
|
||||||
targets: binary
|
targets: binary
|
||||||
-
|
-
|
||||||
name: Upload artifacts
|
name: Upload artifacts
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: binary
|
name: binary
|
||||||
path: ${{ env.DESTDIR }}
|
path: ${{ env.DESTDIR }}
|
||||||
|
@ -49,9 +50,15 @@ jobs:
|
||||||
timeout-minutes: 120
|
timeout-minutes: 120
|
||||||
needs:
|
needs:
|
||||||
- build
|
- build
|
||||||
|
env:
|
||||||
|
TEST_IMAGE_BUILD: "0"
|
||||||
|
TEST_IMAGE_ID: "buildkit-tests"
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
worker:
|
||||||
|
- dockerd
|
||||||
|
- dockerd-containerd
|
||||||
pkg:
|
pkg:
|
||||||
- client
|
- client
|
||||||
- cmd/buildctl
|
- cmd/buildctl
|
||||||
|
@ -61,9 +68,23 @@ jobs:
|
||||||
typ:
|
typ:
|
||||||
- integration
|
- integration
|
||||||
steps:
|
steps:
|
||||||
|
-
|
||||||
|
name: Prepare
|
||||||
|
run: |
|
||||||
|
disabledFeatures="cache_backend_azblob,cache_backend_s3"
|
||||||
|
if [ "${{ matrix.worker }}" = "dockerd" ]; then
|
||||||
|
disabledFeatures="${disabledFeatures},merge_diff"
|
||||||
|
fi
|
||||||
|
echo "BUILDKIT_TEST_DISABLE_FEATURES=${disabledFeatures}" >> $GITHUB_ENV
|
||||||
|
# Expose `ACTIONS_RUNTIME_TOKEN` and `ACTIONS_CACHE_URL`, which is used
|
||||||
|
# in BuildKit's test suite to skip/unskip cache exporters:
|
||||||
|
# https://github.com/moby/buildkit/blob/567a99433ca23402d5e9b9f9124005d2e59b8861/client/client_test.go#L5407-L5411
|
||||||
|
-
|
||||||
|
name: Expose GitHub Runtime
|
||||||
|
uses: crazy-max/ghaction-github-runtime@v3
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
path: moby
|
path: moby
|
||||||
-
|
-
|
||||||
|
@ -73,20 +94,20 @@ jobs:
|
||||||
working-directory: moby
|
working-directory: moby
|
||||||
-
|
-
|
||||||
name: Checkout BuildKit ${{ env.BUILDKIT_REF }}
|
name: Checkout BuildKit ${{ env.BUILDKIT_REF }}
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
repository: "moby/buildkit"
|
repository: ${{ env.BUILDKIT_REPO }}
|
||||||
ref: ${{ env.BUILDKIT_REF }}
|
ref: ${{ env.BUILDKIT_REF }}
|
||||||
path: buildkit
|
path: buildkit
|
||||||
-
|
-
|
||||||
name: Set up QEMU
|
name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v2
|
uses: docker/setup-qemu-action@v3
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v3
|
||||||
-
|
-
|
||||||
name: Download binary artifacts
|
name: Download binary artifacts
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: binary
|
name: binary
|
||||||
path: ./buildkit/build/moby/
|
path: ./buildkit/build/moby/
|
||||||
|
@ -97,6 +118,14 @@ jobs:
|
||||||
sudo service docker restart
|
sudo service docker restart
|
||||||
docker version
|
docker version
|
||||||
docker info
|
docker info
|
||||||
|
-
|
||||||
|
name: Build test image
|
||||||
|
uses: docker/bake-action@v4
|
||||||
|
with:
|
||||||
|
workdir: ./buildkit
|
||||||
|
targets: integration-tests
|
||||||
|
set: |
|
||||||
|
*.output=type=docker,name=${{ env.TEST_IMAGE_ID }}
|
||||||
-
|
-
|
||||||
name: Test
|
name: Test
|
||||||
run: |
|
run: |
|
||||||
|
@ -106,6 +135,5 @@ jobs:
|
||||||
TEST_DOCKERD: "1"
|
TEST_DOCKERD: "1"
|
||||||
TEST_DOCKERD_BINARY: "./build/moby/dockerd"
|
TEST_DOCKERD_BINARY: "./build/moby/dockerd"
|
||||||
TESTPKGS: "./${{ matrix.pkg }}"
|
TESTPKGS: "./${{ matrix.pkg }}"
|
||||||
# Diff/MergeOp tests are skipped
|
TESTFLAGS: "-v --parallel=1 --timeout=30m --run=//worker=${{ matrix.worker }}$"
|
||||||
TESTFLAGS: "-v --parallel=1 --timeout=30m --run=/^Test([^DM]|.[^ie]|..[^fr]|...[^fg])/worker=dockerd$"
|
|
||||||
working-directory: buildkit
|
working-directory: buildkit
|
||||||
|
|
32
.github/workflows/ci.yml
vendored
32
.github/workflows/ci.yml
vendored
|
@ -10,8 +10,6 @@ on:
|
||||||
branches:
|
branches:
|
||||||
- 'master'
|
- 'master'
|
||||||
- '[0-9]+.[0-9]+'
|
- '[0-9]+.[0-9]+'
|
||||||
tags:
|
|
||||||
- 'v*'
|
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
@ -34,15 +32,15 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v3
|
||||||
-
|
-
|
||||||
name: Build
|
name: Build
|
||||||
uses: docker/bake-action@v2
|
uses: docker/bake-action@v4
|
||||||
with:
|
with:
|
||||||
targets: ${{ matrix.target }}
|
targets: ${{ matrix.target }}
|
||||||
-
|
-
|
||||||
|
@ -53,14 +51,6 @@ jobs:
|
||||||
name: Check artifacts
|
name: Check artifacts
|
||||||
run: |
|
run: |
|
||||||
find ${{ env.DESTDIR }} -type f -exec file -e ascii -- {} +
|
find ${{ env.DESTDIR }} -type f -exec file -e ascii -- {} +
|
||||||
-
|
|
||||||
name: Upload artifacts
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: ${{ matrix.target }}
|
|
||||||
path: ${{ env.DESTDIR }}
|
|
||||||
if-no-files-found: error
|
|
||||||
retention-days: 7
|
|
||||||
|
|
||||||
prepare-cross:
|
prepare-cross:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -71,7 +61,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
-
|
-
|
||||||
name: Create matrix
|
name: Create matrix
|
||||||
id: platforms
|
id: platforms
|
||||||
|
@ -95,7 +85,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
-
|
-
|
||||||
|
@ -105,10 +95,10 @@ jobs:
|
||||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v3
|
||||||
-
|
-
|
||||||
name: Build
|
name: Build
|
||||||
uses: docker/bake-action@v2
|
uses: docker/bake-action@v4
|
||||||
with:
|
with:
|
||||||
targets: all
|
targets: all
|
||||||
set: |
|
set: |
|
||||||
|
@ -121,11 +111,3 @@ jobs:
|
||||||
name: Check artifacts
|
name: Check artifacts
|
||||||
run: |
|
run: |
|
||||||
find ${{ env.DESTDIR }} -type f -exec file -e ascii -- {} +
|
find ${{ env.DESTDIR }} -type f -exec file -e ascii -- {} +
|
||||||
-
|
|
||||||
name: Upload artifacts
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: cross-${{ env.PLATFORM_PAIR }}
|
|
||||||
path: ${{ env.DESTDIR }}
|
|
||||||
if-no-files-found: error
|
|
||||||
retention-days: 7
|
|
||||||
|
|
453
.github/workflows/test.yml
vendored
453
.github/workflows/test.yml
vendored
|
@ -10,17 +10,12 @@ on:
|
||||||
branches:
|
branches:
|
||||||
- 'master'
|
- 'master'
|
||||||
- '[0-9]+.[0-9]+'
|
- '[0-9]+.[0-9]+'
|
||||||
tags:
|
|
||||||
- 'v*'
|
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
GO_VERSION: "1.20.13"
|
GO_VERSION: "1.21.9"
|
||||||
GOTESTLIST_VERSION: v0.3.1
|
GIT_PAGER: "cat"
|
||||||
TESTSTAT_VERSION: v0.1.3
|
PAGER: "cat"
|
||||||
ITG_CLI_MATRIX_SIZE: 6
|
|
||||||
DOCKER_EXPERIMENTAL: 1
|
|
||||||
DOCKER_GRAPHDRIVER: overlay2
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
validate-dco:
|
validate-dco:
|
||||||
|
@ -45,13 +40,13 @@ jobs:
|
||||||
fi
|
fi
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v3
|
||||||
-
|
-
|
||||||
name: Build dev image
|
name: Build dev image
|
||||||
uses: docker/bake-action@v2
|
uses: docker/bake-action@v4
|
||||||
with:
|
with:
|
||||||
targets: dev
|
targets: dev
|
||||||
set: |
|
set: |
|
||||||
|
@ -59,6 +54,21 @@ jobs:
|
||||||
*.cache-to=type=gha,scope=dev${{ matrix.mode }},mode=max
|
*.cache-to=type=gha,scope=dev${{ matrix.mode }},mode=max
|
||||||
*.output=type=cacheonly
|
*.output=type=cacheonly
|
||||||
|
|
||||||
|
test:
|
||||||
|
needs:
|
||||||
|
- build-dev
|
||||||
|
- validate-dco
|
||||||
|
uses: ./.github/workflows/.test.yml
|
||||||
|
secrets: inherit
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
storage:
|
||||||
|
- graphdriver
|
||||||
|
- snapshotter
|
||||||
|
with:
|
||||||
|
storage: ${{ matrix.storage }}
|
||||||
|
|
||||||
validate-prepare:
|
validate-prepare:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
needs:
|
needs:
|
||||||
|
@ -68,12 +78,12 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
-
|
-
|
||||||
name: Create matrix
|
name: Create matrix
|
||||||
id: scripts
|
id: scripts
|
||||||
run: |
|
run: |
|
||||||
scripts=$(jq -ncR '[inputs]' <<< "$(ls -I .validate -I all -I default -I dco -I golangci-lint.yml -I yamllint.yaml -A ./hack/validate/)")
|
scripts=$(cd ./hack/validate && jq -nc '$ARGS.positional - ["all", "default", "dco"] | map(select(test("[.]")|not)) + ["generate-files"]' --args *)
|
||||||
echo "matrix=$scripts" >> $GITHUB_OUTPUT
|
echo "matrix=$scripts" >> $GITHUB_OUTPUT
|
||||||
-
|
-
|
||||||
name: Show matrix
|
name: Show matrix
|
||||||
|
@ -93,7 +103,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
-
|
-
|
||||||
|
@ -101,10 +111,10 @@ jobs:
|
||||||
uses: ./.github/actions/setup-runner
|
uses: ./.github/actions/setup-runner
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v3
|
||||||
-
|
-
|
||||||
name: Build dev image
|
name: Build dev image
|
||||||
uses: docker/bake-action@v2
|
uses: docker/bake-action@v4
|
||||||
with:
|
with:
|
||||||
targets: dev
|
targets: dev
|
||||||
set: |
|
set: |
|
||||||
|
@ -114,402 +124,7 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
make -o build validate-${{ matrix.script }}
|
make -o build validate-${{ matrix.script }}
|
||||||
|
|
||||||
unit:
|
smoke-prepare:
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
timeout-minutes: 120
|
|
||||||
needs:
|
|
||||||
- build-dev
|
|
||||||
steps:
|
|
||||||
-
|
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
-
|
|
||||||
name: Set up runner
|
|
||||||
uses: ./.github/actions/setup-runner
|
|
||||||
-
|
|
||||||
name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v2
|
|
||||||
-
|
|
||||||
name: Build dev image
|
|
||||||
uses: docker/bake-action@v2
|
|
||||||
with:
|
|
||||||
targets: dev
|
|
||||||
set: |
|
|
||||||
dev.cache-from=type=gha,scope=dev
|
|
||||||
-
|
|
||||||
name: Test
|
|
||||||
run: |
|
|
||||||
make -o build test-unit
|
|
||||||
-
|
|
||||||
name: Prepare reports
|
|
||||||
if: always()
|
|
||||||
run: |
|
|
||||||
mkdir -p bundles /tmp/reports
|
|
||||||
find bundles -path '*/root/*overlay2' -prune -o -type f \( -name '*-report.json' -o -name '*.log' -o -name '*.out' -o -name '*.prof' -o -name '*-report.xml' \) -print | xargs sudo tar -czf /tmp/reports.tar.gz
|
|
||||||
tar -xzf /tmp/reports.tar.gz -C /tmp/reports
|
|
||||||
sudo chown -R $(id -u):$(id -g) /tmp/reports
|
|
||||||
tree -nh /tmp/reports
|
|
||||||
-
|
|
||||||
name: Send to Codecov
|
|
||||||
uses: codecov/codecov-action@v3
|
|
||||||
with:
|
|
||||||
directory: ./bundles
|
|
||||||
env_vars: RUNNER_OS
|
|
||||||
flags: unit
|
|
||||||
-
|
|
||||||
name: Upload reports
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: unit-reports
|
|
||||||
path: /tmp/reports/*
|
|
||||||
|
|
||||||
unit-report:
|
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
timeout-minutes: 10
|
|
||||||
if: always()
|
|
||||||
needs:
|
|
||||||
- unit
|
|
||||||
steps:
|
|
||||||
-
|
|
||||||
name: Set up Go
|
|
||||||
uses: actions/setup-go@v3
|
|
||||||
with:
|
|
||||||
go-version: ${{ env.GO_VERSION }}
|
|
||||||
-
|
|
||||||
name: Download reports
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: unit-reports
|
|
||||||
path: /tmp/reports
|
|
||||||
-
|
|
||||||
name: Install teststat
|
|
||||||
run: |
|
|
||||||
go install github.com/vearutop/teststat@${{ env.TESTSTAT_VERSION }}
|
|
||||||
-
|
|
||||||
name: Create summary
|
|
||||||
run: |
|
|
||||||
teststat -markdown $(find /tmp/reports -type f -name '*.json' -print0 | xargs -0) >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
docker-py:
|
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
timeout-minutes: 120
|
|
||||||
needs:
|
|
||||||
- build-dev
|
|
||||||
steps:
|
|
||||||
-
|
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
-
|
|
||||||
name: Set up runner
|
|
||||||
uses: ./.github/actions/setup-runner
|
|
||||||
-
|
|
||||||
name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v2
|
|
||||||
-
|
|
||||||
name: Build dev image
|
|
||||||
uses: docker/bake-action@v2
|
|
||||||
with:
|
|
||||||
targets: dev
|
|
||||||
set: |
|
|
||||||
dev.cache-from=type=gha,scope=dev
|
|
||||||
-
|
|
||||||
name: Test
|
|
||||||
run: |
|
|
||||||
make -o build test-docker-py
|
|
||||||
-
|
|
||||||
name: Prepare reports
|
|
||||||
if: always()
|
|
||||||
run: |
|
|
||||||
mkdir -p bundles /tmp/reports
|
|
||||||
find bundles -path '*/root/*overlay2' -prune -o -type f \( -name '*-report.json' -o -name '*.log' -o -name '*.out' -o -name '*.prof' -o -name '*-report.xml' \) -print | xargs sudo tar -czf /tmp/reports.tar.gz
|
|
||||||
tar -xzf /tmp/reports.tar.gz -C /tmp/reports
|
|
||||||
sudo chown -R $(id -u):$(id -g) /tmp/reports
|
|
||||||
tree -nh /tmp/reports
|
|
||||||
-
|
|
||||||
name: Test daemon logs
|
|
||||||
if: always()
|
|
||||||
run: |
|
|
||||||
cat bundles/test-docker-py/docker.log
|
|
||||||
-
|
|
||||||
name: Upload reports
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: docker-py-reports
|
|
||||||
path: /tmp/reports/*
|
|
||||||
|
|
||||||
integration-flaky:
|
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
timeout-minutes: 120
|
|
||||||
needs:
|
|
||||||
- build-dev
|
|
||||||
steps:
|
|
||||||
-
|
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
-
|
|
||||||
name: Set up runner
|
|
||||||
uses: ./.github/actions/setup-runner
|
|
||||||
-
|
|
||||||
name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v2
|
|
||||||
-
|
|
||||||
name: Build dev image
|
|
||||||
uses: docker/bake-action@v2
|
|
||||||
with:
|
|
||||||
targets: dev
|
|
||||||
set: |
|
|
||||||
dev.cache-from=type=gha,scope=dev
|
|
||||||
-
|
|
||||||
name: Test
|
|
||||||
run: |
|
|
||||||
make -o build test-integration-flaky
|
|
||||||
env:
|
|
||||||
TEST_SKIP_INTEGRATION_CLI: 1
|
|
||||||
|
|
||||||
integration:
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
timeout-minutes: 120
|
|
||||||
needs:
|
|
||||||
- build-dev
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os:
|
|
||||||
- ubuntu-20.04
|
|
||||||
- ubuntu-22.04
|
|
||||||
mode:
|
|
||||||
- ""
|
|
||||||
- rootless
|
|
||||||
- systemd
|
|
||||||
#- rootless-systemd FIXME: https://github.com/moby/moby/issues/44084
|
|
||||||
steps:
|
|
||||||
-
|
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
-
|
|
||||||
name: Set up runner
|
|
||||||
uses: ./.github/actions/setup-runner
|
|
||||||
-
|
|
||||||
name: Prepare
|
|
||||||
run: |
|
|
||||||
CACHE_DEV_SCOPE=dev
|
|
||||||
if [[ "${{ matrix.mode }}" == *"rootless"* ]]; then
|
|
||||||
echo "DOCKER_ROOTLESS=1" >> $GITHUB_ENV
|
|
||||||
fi
|
|
||||||
if [[ "${{ matrix.mode }}" == *"systemd"* ]]; then
|
|
||||||
echo "SYSTEMD=true" >> $GITHUB_ENV
|
|
||||||
CACHE_DEV_SCOPE="${CACHE_DEV_SCOPE}systemd"
|
|
||||||
fi
|
|
||||||
echo "CACHE_DEV_SCOPE=${CACHE_DEV_SCOPE}" >> $GITHUB_ENV
|
|
||||||
-
|
|
||||||
name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v2
|
|
||||||
-
|
|
||||||
name: Build dev image
|
|
||||||
uses: docker/bake-action@v2
|
|
||||||
with:
|
|
||||||
targets: dev
|
|
||||||
set: |
|
|
||||||
dev.cache-from=type=gha,scope=${{ env.CACHE_DEV_SCOPE }}
|
|
||||||
-
|
|
||||||
name: Test
|
|
||||||
run: |
|
|
||||||
make -o build test-integration
|
|
||||||
env:
|
|
||||||
TEST_SKIP_INTEGRATION_CLI: 1
|
|
||||||
TESTCOVERAGE: 1
|
|
||||||
-
|
|
||||||
name: Prepare reports
|
|
||||||
if: always()
|
|
||||||
run: |
|
|
||||||
reportsPath="/tmp/reports/${{ matrix.os }}"
|
|
||||||
if [ -n "${{ matrix.mode }}" ]; then
|
|
||||||
reportsPath="$reportsPath-${{ matrix.mode }}"
|
|
||||||
fi
|
|
||||||
mkdir -p bundles $reportsPath
|
|
||||||
find bundles -path '*/root/*overlay2' -prune -o -type f \( -name '*-report.json' -o -name '*.log' -o -name '*.out' -o -name '*.prof' -o -name '*-report.xml' \) -print | xargs sudo tar -czf /tmp/reports.tar.gz
|
|
||||||
tar -xzf /tmp/reports.tar.gz -C $reportsPath
|
|
||||||
sudo chown -R $(id -u):$(id -g) $reportsPath
|
|
||||||
tree -nh $reportsPath
|
|
||||||
-
|
|
||||||
name: Send to Codecov
|
|
||||||
uses: codecov/codecov-action@v3
|
|
||||||
with:
|
|
||||||
directory: ./bundles/test-integration
|
|
||||||
env_vars: RUNNER_OS
|
|
||||||
flags: integration,${{ matrix.mode }}
|
|
||||||
-
|
|
||||||
name: Test daemon logs
|
|
||||||
if: always()
|
|
||||||
run: |
|
|
||||||
cat bundles/test-integration/docker.log
|
|
||||||
-
|
|
||||||
name: Upload reports
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: integration-reports
|
|
||||||
path: /tmp/reports/*
|
|
||||||
|
|
||||||
integration-report:
|
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
timeout-minutes: 10
|
|
||||||
if: always()
|
|
||||||
needs:
|
|
||||||
- integration
|
|
||||||
steps:
|
|
||||||
-
|
|
||||||
name: Set up Go
|
|
||||||
uses: actions/setup-go@v3
|
|
||||||
with:
|
|
||||||
go-version: ${{ env.GO_VERSION }}
|
|
||||||
-
|
|
||||||
name: Download reports
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: integration-reports
|
|
||||||
path: /tmp/reports
|
|
||||||
-
|
|
||||||
name: Install teststat
|
|
||||||
run: |
|
|
||||||
go install github.com/vearutop/teststat@${{ env.TESTSTAT_VERSION }}
|
|
||||||
-
|
|
||||||
name: Create summary
|
|
||||||
run: |
|
|
||||||
teststat -markdown $(find /tmp/reports -type f -name '*.json' -print0 | xargs -0) >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
integration-cli-prepare:
|
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
needs:
|
|
||||||
- validate-dco
|
|
||||||
outputs:
|
|
||||||
matrix: ${{ steps.tests.outputs.matrix }}
|
|
||||||
steps:
|
|
||||||
-
|
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
-
|
|
||||||
name: Set up Go
|
|
||||||
uses: actions/setup-go@v3
|
|
||||||
with:
|
|
||||||
go-version: ${{ env.GO_VERSION }}
|
|
||||||
-
|
|
||||||
name: Install gotestlist
|
|
||||||
run:
|
|
||||||
go install github.com/crazy-max/gotestlist/cmd/gotestlist@${{ env.GOTESTLIST_VERSION }}
|
|
||||||
-
|
|
||||||
name: Create matrix
|
|
||||||
id: tests
|
|
||||||
working-directory: ./integration-cli
|
|
||||||
run: |
|
|
||||||
# This step creates a matrix for integration-cli tests. Tests suites
|
|
||||||
# are distributed in integration-cli job through a matrix. There is
|
|
||||||
# also overrides being added to the matrix like "./..." to run
|
|
||||||
# "Test integration" step exclusively and specific tests suites that
|
|
||||||
# take a long time to run.
|
|
||||||
matrix="$(gotestlist -d ${{ env.ITG_CLI_MATRIX_SIZE }} -o "./..." -o "DockerSwarmSuite" -o "DockerNetworkSuite|DockerExternalVolumeSuite" ./...)"
|
|
||||||
echo "matrix=$matrix" >> $GITHUB_OUTPUT
|
|
||||||
-
|
|
||||||
name: Show matrix
|
|
||||||
run: |
|
|
||||||
echo ${{ steps.tests.outputs.matrix }}
|
|
||||||
|
|
||||||
integration-cli:
|
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
timeout-minutes: 120
|
|
||||||
needs:
|
|
||||||
- build-dev
|
|
||||||
- integration-cli-prepare
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
test: ${{ fromJson(needs.integration-cli-prepare.outputs.matrix) }}
|
|
||||||
steps:
|
|
||||||
-
|
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
-
|
|
||||||
name: Set up runner
|
|
||||||
uses: ./.github/actions/setup-runner
|
|
||||||
-
|
|
||||||
name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v2
|
|
||||||
-
|
|
||||||
name: Build dev image
|
|
||||||
uses: docker/bake-action@v2
|
|
||||||
with:
|
|
||||||
targets: dev
|
|
||||||
set: |
|
|
||||||
dev.cache-from=type=gha,scope=dev
|
|
||||||
-
|
|
||||||
name: Test
|
|
||||||
run: |
|
|
||||||
make -o build test-integration
|
|
||||||
env:
|
|
||||||
TEST_SKIP_INTEGRATION: 1
|
|
||||||
TESTCOVERAGE: 1
|
|
||||||
TESTFLAGS: "-test.run (${{ matrix.test }})/"
|
|
||||||
-
|
|
||||||
name: Prepare reports
|
|
||||||
if: always()
|
|
||||||
run: |
|
|
||||||
reportsPath=/tmp/reports/$(echo -n "${{ matrix.test }}" | sha256sum | cut -d " " -f 1)
|
|
||||||
mkdir -p bundles $reportsPath
|
|
||||||
echo "${{ matrix.test }}" | tr -s '|' '\n' | tee -a "$reportsPath/tests.txt"
|
|
||||||
find bundles -path '*/root/*overlay2' -prune -o -type f \( -name '*-report.json' -o -name '*.log' -o -name '*.out' -o -name '*.prof' -o -name '*-report.xml' \) -print | xargs sudo tar -czf /tmp/reports.tar.gz
|
|
||||||
tar -xzf /tmp/reports.tar.gz -C $reportsPath
|
|
||||||
sudo chown -R $(id -u):$(id -g) $reportsPath
|
|
||||||
tree -nh $reportsPath
|
|
||||||
-
|
|
||||||
name: Send to Codecov
|
|
||||||
uses: codecov/codecov-action@v3
|
|
||||||
with:
|
|
||||||
directory: ./bundles/test-integration
|
|
||||||
env_vars: RUNNER_OS
|
|
||||||
flags: integration-cli
|
|
||||||
-
|
|
||||||
name: Test daemon logs
|
|
||||||
if: always()
|
|
||||||
run: |
|
|
||||||
cat bundles/test-integration/docker.log
|
|
||||||
-
|
|
||||||
name: Upload reports
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: integration-cli-reports
|
|
||||||
path: /tmp/reports/*
|
|
||||||
|
|
||||||
integration-cli-report:
|
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
timeout-minutes: 10
|
|
||||||
if: always()
|
|
||||||
needs:
|
|
||||||
- integration-cli
|
|
||||||
steps:
|
|
||||||
-
|
|
||||||
name: Set up Go
|
|
||||||
uses: actions/setup-go@v3
|
|
||||||
with:
|
|
||||||
go-version: ${{ env.GO_VERSION }}
|
|
||||||
-
|
|
||||||
name: Download reports
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: integration-cli-reports
|
|
||||||
path: /tmp/reports
|
|
||||||
-
|
|
||||||
name: Install teststat
|
|
||||||
run: |
|
|
||||||
go install github.com/vearutop/teststat@${{ env.TESTSTAT_VERSION }}
|
|
||||||
-
|
|
||||||
name: Create summary
|
|
||||||
run: |
|
|
||||||
teststat -markdown $(find /tmp/reports -type f -name '*.json' -print0 | xargs -0) >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
prepare-smoke:
|
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
needs:
|
needs:
|
||||||
- validate-dco
|
- validate-dco
|
||||||
|
@ -518,7 +133,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
-
|
-
|
||||||
name: Create matrix
|
name: Create matrix
|
||||||
id: platforms
|
id: platforms
|
||||||
|
@ -533,15 +148,15 @@ jobs:
|
||||||
smoke:
|
smoke:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
needs:
|
needs:
|
||||||
- prepare-smoke
|
- smoke-prepare
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
platform: ${{ fromJson(needs.prepare-smoke.outputs.matrix) }}
|
platform: ${{ fromJson(needs.smoke-prepare.outputs.matrix) }}
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
-
|
-
|
||||||
name: Prepare
|
name: Prepare
|
||||||
run: |
|
run: |
|
||||||
|
@ -549,13 +164,13 @@ jobs:
|
||||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||||
-
|
-
|
||||||
name: Set up QEMU
|
name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v2
|
uses: docker/setup-qemu-action@v3
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v3
|
||||||
-
|
-
|
||||||
name: Test
|
name: Test
|
||||||
uses: docker/bake-action@v2
|
uses: docker/bake-action@v4
|
||||||
with:
|
with:
|
||||||
targets: binary-smoketest
|
targets: binary-smoketest
|
||||||
set: |
|
set: |
|
||||||
|
|
62
.github/workflows/validate-pr.yml
vendored
Normal file
62
.github/workflows/validate-pr.yml
vendored
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
name: validate-pr
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [opened, edited, labeled, unlabeled]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check-area-label:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
- name: Missing `area/` label
|
||||||
|
if: contains(join(github.event.pull_request.labels.*.name, ','), 'impact/') && !contains(join(github.event.pull_request.labels.*.name, ','), 'area/')
|
||||||
|
run: |
|
||||||
|
echo "::error::Every PR with an 'impact/*' label should also have an 'area/*' label"
|
||||||
|
exit 1
|
||||||
|
- name: OK
|
||||||
|
run: exit 0
|
||||||
|
|
||||||
|
check-changelog:
|
||||||
|
if: contains(join(github.event.pull_request.labels.*.name, ','), 'impact/')
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
env:
|
||||||
|
PR_BODY: |
|
||||||
|
${{ github.event.pull_request.body }}
|
||||||
|
steps:
|
||||||
|
- name: Check changelog description
|
||||||
|
run: |
|
||||||
|
# Extract the `markdown changelog` note code block
|
||||||
|
block=$(echo -n "$PR_BODY" | tr -d '\r' | awk '/^```markdown changelog$/{flag=1;next}/^```$/{flag=0}flag')
|
||||||
|
|
||||||
|
# Strip empty lines
|
||||||
|
desc=$(echo "$block" | awk NF)
|
||||||
|
|
||||||
|
if [ -z "$desc" ]; then
|
||||||
|
echo "::error::Changelog section is empty. Please provide a description for the changelog."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
len=$(echo -n "$desc" | wc -c)
|
||||||
|
if [[ $len -le 6 ]]; then
|
||||||
|
echo "::error::Description looks too short: $desc"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "This PR will be included in the release notes with the following note:"
|
||||||
|
echo "$desc"
|
||||||
|
|
||||||
|
check-pr-branch:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
env:
|
||||||
|
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||||
|
steps:
|
||||||
|
# Backports or PR that target a release branch directly should mention the target branch in the title, for example:
|
||||||
|
# [X.Y backport] Some change that needs backporting to X.Y
|
||||||
|
# [X.Y] Change directly targeting the X.Y branch
|
||||||
|
- name: Get branch from PR title
|
||||||
|
id: title_branch
|
||||||
|
run: echo "$PR_TITLE" | sed -n 's/^\[\([0-9]*\.[0-9]*\)[^]]*\].*/branch=\1/p' >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Check release branch
|
||||||
|
if: github.event.pull_request.base.ref != steps.title_branch.outputs.branch && !(github.event.pull_request.base.ref == 'master' && steps.title_branch.outputs.branch == '')
|
||||||
|
run: echo "::error::PR title suggests targetting the ${{ steps.title_branch.outputs.branch }} branch, but is opened against ${{ github.event.pull_request.base.ref }}" && exit 1
|
13
.github/workflows/windows-2019.yml
vendored
13
.github/workflows/windows-2019.yml
vendored
|
@ -13,10 +13,21 @@ jobs:
|
||||||
validate-dco:
|
validate-dco:
|
||||||
uses: ./.github/workflows/.dco.yml
|
uses: ./.github/workflows/.dco.yml
|
||||||
|
|
||||||
run:
|
test-prepare:
|
||||||
|
uses: ./.github/workflows/.test-prepare.yml
|
||||||
needs:
|
needs:
|
||||||
- validate-dco
|
- validate-dco
|
||||||
|
|
||||||
|
run:
|
||||||
|
needs:
|
||||||
|
- test-prepare
|
||||||
uses: ./.github/workflows/.windows.yml
|
uses: ./.github/workflows/.windows.yml
|
||||||
|
secrets: inherit
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
storage: ${{ fromJson(needs.test-prepare.outputs.matrix) }}
|
||||||
with:
|
with:
|
||||||
os: windows-2019
|
os: windows-2019
|
||||||
|
storage: ${{ matrix.storage }}
|
||||||
send_coverage: false
|
send_coverage: false
|
||||||
|
|
13
.github/workflows/windows-2022.yml
vendored
13
.github/workflows/windows-2022.yml
vendored
|
@ -16,10 +16,21 @@ jobs:
|
||||||
validate-dco:
|
validate-dco:
|
||||||
uses: ./.github/workflows/.dco.yml
|
uses: ./.github/workflows/.dco.yml
|
||||||
|
|
||||||
run:
|
test-prepare:
|
||||||
|
uses: ./.github/workflows/.test-prepare.yml
|
||||||
needs:
|
needs:
|
||||||
- validate-dco
|
- validate-dco
|
||||||
|
|
||||||
|
run:
|
||||||
|
needs:
|
||||||
|
- test-prepare
|
||||||
uses: ./.github/workflows/.windows.yml
|
uses: ./.github/workflows/.windows.yml
|
||||||
|
secrets: inherit
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
storage: ${{ fromJson(needs.test-prepare.outputs.matrix) }}
|
||||||
with:
|
with:
|
||||||
os: windows-2022
|
os: windows-2022
|
||||||
|
storage: ${{ matrix.storage }}
|
||||||
send_coverage: true
|
send_coverage: true
|
||||||
|
|
137
.golangci.yml
Normal file
137
.golangci.yml
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
linters:
|
||||||
|
enable:
|
||||||
|
- depguard
|
||||||
|
- dupword # Checks for duplicate words in the source code.
|
||||||
|
- goimports
|
||||||
|
- gosec
|
||||||
|
- gosimple
|
||||||
|
- govet
|
||||||
|
- importas
|
||||||
|
- ineffassign
|
||||||
|
- misspell
|
||||||
|
- revive
|
||||||
|
- staticcheck
|
||||||
|
- typecheck
|
||||||
|
- unconvert
|
||||||
|
- unused
|
||||||
|
|
||||||
|
disable:
|
||||||
|
- errcheck
|
||||||
|
|
||||||
|
run:
|
||||||
|
concurrency: 2
|
||||||
|
modules-download-mode: vendor
|
||||||
|
|
||||||
|
skip-dirs:
|
||||||
|
- docs
|
||||||
|
|
||||||
|
linters-settings:
|
||||||
|
dupword:
|
||||||
|
ignore:
|
||||||
|
- "true" # some tests use this as expected output
|
||||||
|
- "false" # some tests use this as expected output
|
||||||
|
- "root" # for tests using "ls" output with files owned by "root:root"
|
||||||
|
importas:
|
||||||
|
# Do not allow unaliased imports of aliased packages.
|
||||||
|
no-unaliased: true
|
||||||
|
|
||||||
|
alias:
|
||||||
|
# Enforce alias to prevent it accidentally being used instead of our
|
||||||
|
# own errdefs package (or vice-versa).
|
||||||
|
- pkg: github.com/containerd/containerd/errdefs
|
||||||
|
alias: cerrdefs
|
||||||
|
- pkg: github.com/opencontainers/image-spec/specs-go/v1
|
||||||
|
alias: ocispec
|
||||||
|
|
||||||
|
govet:
|
||||||
|
check-shadowing: false
|
||||||
|
depguard:
|
||||||
|
rules:
|
||||||
|
main:
|
||||||
|
deny:
|
||||||
|
- pkg: io/ioutil
|
||||||
|
desc: The io/ioutil package has been deprecated, see https://go.dev/doc/go1.16#ioutil
|
||||||
|
- pkg: "github.com/stretchr/testify/assert"
|
||||||
|
desc: Use "gotest.tools/v3/assert" instead
|
||||||
|
- pkg: "github.com/stretchr/testify/require"
|
||||||
|
desc: Use "gotest.tools/v3/assert" instead
|
||||||
|
- pkg: "github.com/stretchr/testify/suite"
|
||||||
|
desc: Do not use
|
||||||
|
revive:
|
||||||
|
rules:
|
||||||
|
# FIXME make sure all packages have a description. Currently, there's many packages without.
|
||||||
|
- name: package-comments
|
||||||
|
disabled: true
|
||||||
|
issues:
|
||||||
|
# The default exclusion rules are a bit too permissive, so copying the relevant ones below
|
||||||
|
exclude-use-default: false
|
||||||
|
|
||||||
|
exclude-rules:
|
||||||
|
# We prefer to use an "exclude-list" so that new "default" exclusions are not
|
||||||
|
# automatically inherited. We can decide whether or not to follow upstream
|
||||||
|
# defaults when updating golang-ci-lint versions.
|
||||||
|
# Unfortunately, this means we have to copy the whole exclusion pattern, as
|
||||||
|
# (unlike the "include" option), the "exclude" option does not take exclusion
|
||||||
|
# ID's.
|
||||||
|
#
|
||||||
|
# These exclusion patterns are copied from the default excluses at:
|
||||||
|
# https://github.com/golangci/golangci-lint/blob/v1.46.2/pkg/config/issues.go#L10-L104
|
||||||
|
|
||||||
|
# EXC0001
|
||||||
|
- text: "Error return value of .((os\\.)?std(out|err)\\..*|.*Close|.*Flush|os\\.Remove(All)?|.*print(f|ln)?|os\\.(Un)?Setenv). is not checked"
|
||||||
|
linters:
|
||||||
|
- errcheck
|
||||||
|
# EXC0006
|
||||||
|
- text: "Use of unsafe calls should be audited"
|
||||||
|
linters:
|
||||||
|
- gosec
|
||||||
|
# EXC0007
|
||||||
|
- text: "Subprocess launch(ed with variable|ing should be audited)"
|
||||||
|
linters:
|
||||||
|
- gosec
|
||||||
|
# EXC0008
|
||||||
|
# TODO: evaluate these and fix where needed: G307: Deferring unsafe method "*os.File" on type "Close" (gosec)
|
||||||
|
- text: "(G104|G307)"
|
||||||
|
linters:
|
||||||
|
- gosec
|
||||||
|
# EXC0009
|
||||||
|
- text: "(Expect directory permissions to be 0750 or less|Expect file permissions to be 0600 or less)"
|
||||||
|
linters:
|
||||||
|
- gosec
|
||||||
|
# EXC0010
|
||||||
|
- text: "Potential file inclusion via variable"
|
||||||
|
linters:
|
||||||
|
- gosec
|
||||||
|
|
||||||
|
# Looks like the match in "EXC0007" above doesn't catch this one
|
||||||
|
# TODO: consider upstreaming this to golangci-lint's default exclusion rules
|
||||||
|
- text: "G204: Subprocess launched with a potential tainted input or cmd arguments"
|
||||||
|
linters:
|
||||||
|
- gosec
|
||||||
|
# Looks like the match in "EXC0009" above doesn't catch this one
|
||||||
|
# TODO: consider upstreaming this to golangci-lint's default exclusion rules
|
||||||
|
- text: "G306: Expect WriteFile permissions to be 0600 or less"
|
||||||
|
linters:
|
||||||
|
- gosec
|
||||||
|
|
||||||
|
# Exclude some linters from running on tests files.
|
||||||
|
- path: _test\.go
|
||||||
|
linters:
|
||||||
|
- errcheck
|
||||||
|
- gosec
|
||||||
|
|
||||||
|
# Suppress golint complaining about generated types in api/types/
|
||||||
|
- text: "type name will be used as (container|volume)\\.(Container|Volume).* by other packages, and that stutters; consider calling this"
|
||||||
|
path: "api/types/(volume|container)/"
|
||||||
|
linters:
|
||||||
|
- revive
|
||||||
|
# FIXME temporarily suppress these (see https://github.com/gotestyourself/gotest.tools/issues/272)
|
||||||
|
- text: "SA1019: (assert|cmp|is)\\.ErrorType is deprecated"
|
||||||
|
linters:
|
||||||
|
- staticcheck
|
||||||
|
|
||||||
|
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
|
||||||
|
max-issues-per-linter: 0
|
||||||
|
|
||||||
|
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
|
||||||
|
max-same-issues: 0
|
24
.mailmap
24
.mailmap
|
@ -32,6 +32,7 @@ Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp> <suda.kyoto@gmail.com>
|
||||||
Akshay Moghe <akshay.moghe@gmail.com>
|
Akshay Moghe <akshay.moghe@gmail.com>
|
||||||
Albin Kerouanton <albinker@gmail.com>
|
Albin Kerouanton <albinker@gmail.com>
|
||||||
Albin Kerouanton <albinker@gmail.com> <albin@akerouanton.name>
|
Albin Kerouanton <albinker@gmail.com> <albin@akerouanton.name>
|
||||||
|
Albin Kerouanton <albinker@gmail.com> <557933+akerouanton@users.noreply.github.com>
|
||||||
Aleksa Sarai <asarai@suse.de>
|
Aleksa Sarai <asarai@suse.de>
|
||||||
Aleksa Sarai <asarai@suse.de> <asarai@suse.com>
|
Aleksa Sarai <asarai@suse.de> <asarai@suse.com>
|
||||||
Aleksa Sarai <asarai@suse.de> <cyphar@cyphar.com>
|
Aleksa Sarai <asarai@suse.de> <cyphar@cyphar.com>
|
||||||
|
@ -103,6 +104,9 @@ Bily Zhang <xcoder@tenxcloud.com>
|
||||||
Bin Liu <liubin0329@gmail.com>
|
Bin Liu <liubin0329@gmail.com>
|
||||||
Bin Liu <liubin0329@gmail.com> <liubin0329@users.noreply.github.com>
|
Bin Liu <liubin0329@gmail.com> <liubin0329@users.noreply.github.com>
|
||||||
Bingshen Wang <bingshen.wbs@alibaba-inc.com>
|
Bingshen Wang <bingshen.wbs@alibaba-inc.com>
|
||||||
|
Bjorn Neergaard <bjorn@neersighted.com>
|
||||||
|
Bjorn Neergaard <bjorn@neersighted.com> <bjorn.neergaard@docker.com>
|
||||||
|
Bjorn Neergaard <bjorn@neersighted.com> <bneergaard@mirantis.com>
|
||||||
Boaz Shuster <ripcurld.github@gmail.com>
|
Boaz Shuster <ripcurld.github@gmail.com>
|
||||||
Bojun Zhu <bojun.zhu@foxmail.com>
|
Bojun Zhu <bojun.zhu@foxmail.com>
|
||||||
Boqin Qin <bobbqqin@gmail.com>
|
Boqin Qin <bobbqqin@gmail.com>
|
||||||
|
@ -141,6 +145,8 @@ Cristian Ariza <dev@cristianrz.com>
|
||||||
Cristian Staretu <cristian.staretu@gmail.com>
|
Cristian Staretu <cristian.staretu@gmail.com>
|
||||||
Cristian Staretu <cristian.staretu@gmail.com> <unclejack@users.noreply.github.com>
|
Cristian Staretu <cristian.staretu@gmail.com> <unclejack@users.noreply.github.com>
|
||||||
Cristian Staretu <cristian.staretu@gmail.com> <unclejacksons@gmail.com>
|
Cristian Staretu <cristian.staretu@gmail.com> <unclejacksons@gmail.com>
|
||||||
|
cui fliter <imcusg@gmail.com>
|
||||||
|
cui fliter <imcusg@gmail.com> cuishuang <imcusg@gmail.com>
|
||||||
CUI Wei <ghostplant@qq.com> cuiwei13 <cuiwei13@pku.edu.cn>
|
CUI Wei <ghostplant@qq.com> cuiwei13 <cuiwei13@pku.edu.cn>
|
||||||
Daehyeok Mun <daehyeok@gmail.com>
|
Daehyeok Mun <daehyeok@gmail.com>
|
||||||
Daehyeok Mun <daehyeok@gmail.com> <daehyeok@daehyeok-ui-MacBook-Air.local>
|
Daehyeok Mun <daehyeok@gmail.com> <daehyeok@daehyeok-ui-MacBook-Air.local>
|
||||||
|
@ -167,6 +173,8 @@ Dattatraya Kumbhar <dattatraya.kumbhar@gslab.com>
|
||||||
Dave Goodchild <buddhamagnet@gmail.com>
|
Dave Goodchild <buddhamagnet@gmail.com>
|
||||||
Dave Henderson <dhenderson@gmail.com> <Dave.Henderson@ca.ibm.com>
|
Dave Henderson <dhenderson@gmail.com> <Dave.Henderson@ca.ibm.com>
|
||||||
Dave Tucker <dt@docker.com> <dave@dtucker.co.uk>
|
Dave Tucker <dt@docker.com> <dave@dtucker.co.uk>
|
||||||
|
David Dooling <dooling@gmail.com>
|
||||||
|
David Dooling <dooling@gmail.com> <david.dooling@docker.com>
|
||||||
David M. Karr <davidmichaelkarr@gmail.com>
|
David M. Karr <davidmichaelkarr@gmail.com>
|
||||||
David Sheets <dsheets@docker.com> <sheets@alum.mit.edu>
|
David Sheets <dsheets@docker.com> <sheets@alum.mit.edu>
|
||||||
David Sissitka <me@dsissitka.com>
|
David Sissitka <me@dsissitka.com>
|
||||||
|
@ -213,6 +221,8 @@ Felix Hupfeld <felix@quobyte.com> <quofelix@users.noreply.github.com>
|
||||||
Felix Ruess <felix.ruess@gmail.com> <felix.ruess@roboception.de>
|
Felix Ruess <felix.ruess@gmail.com> <felix.ruess@roboception.de>
|
||||||
Feng Yan <fy2462@gmail.com>
|
Feng Yan <fy2462@gmail.com>
|
||||||
Fengtu Wang <wangfengtu@huawei.com> <wangfengtu@huawei.com>
|
Fengtu Wang <wangfengtu@huawei.com> <wangfengtu@huawei.com>
|
||||||
|
Filipe Pina <hzlu1ot0@duck.com>
|
||||||
|
Filipe Pina <hzlu1ot0@duck.com> <636320+fopina@users.noreply.github.com>
|
||||||
Francisco Carriedo <fcarriedo@gmail.com>
|
Francisco Carriedo <fcarriedo@gmail.com>
|
||||||
Frank Rosquin <frank.rosquin+github@gmail.com> <frank.rosquin@gmail.com>
|
Frank Rosquin <frank.rosquin+github@gmail.com> <frank.rosquin@gmail.com>
|
||||||
Frank Yang <yyb196@gmail.com>
|
Frank Yang <yyb196@gmail.com>
|
||||||
|
@ -264,6 +274,7 @@ Hollie Teal <hollie@docker.com> <hollie.teal@docker.com>
|
||||||
Hollie Teal <hollie@docker.com> <hollietealok@users.noreply.github.com>
|
Hollie Teal <hollie@docker.com> <hollietealok@users.noreply.github.com>
|
||||||
hsinko <21551195@zju.edu.cn> <hsinko@users.noreply.github.com>
|
hsinko <21551195@zju.edu.cn> <hsinko@users.noreply.github.com>
|
||||||
Hu Keping <hukeping@huawei.com>
|
Hu Keping <hukeping@huawei.com>
|
||||||
|
Huajin Tong <fliterdashen@gmail.com>
|
||||||
Hui Kang <hkang.sunysb@gmail.com>
|
Hui Kang <hkang.sunysb@gmail.com>
|
||||||
Hui Kang <hkang.sunysb@gmail.com> <kangh@us.ibm.com>
|
Hui Kang <hkang.sunysb@gmail.com> <kangh@us.ibm.com>
|
||||||
Huu Nguyen <huu@prismskylabs.com> <whoshuu@gmail.com>
|
Huu Nguyen <huu@prismskylabs.com> <whoshuu@gmail.com>
|
||||||
|
@ -369,7 +380,9 @@ Ken Cochrane <kencochrane@gmail.com> <KenCochrane@gmail.com>
|
||||||
Ken Herner <kherner@progress.com> <chosenken@gmail.com>
|
Ken Herner <kherner@progress.com> <chosenken@gmail.com>
|
||||||
Ken Reese <krrgithub@gmail.com>
|
Ken Reese <krrgithub@gmail.com>
|
||||||
Kenfe-Mickaël Laventure <mickael.laventure@gmail.com>
|
Kenfe-Mickaël Laventure <mickael.laventure@gmail.com>
|
||||||
Kevin Alvarez <crazy-max@users.noreply.github.com>
|
Kevin Alvarez <github@crazymax.dev>
|
||||||
|
Kevin Alvarez <github@crazymax.dev> <1951866+crazy-max@users.noreply.github.com>
|
||||||
|
Kevin Alvarez <github@crazymax.dev> <crazy-max@users.noreply.github.com>
|
||||||
Kevin Feyrer <kevin.feyrer@btinternet.com> <kevinfeyrer@users.noreply.github.com>
|
Kevin Feyrer <kevin.feyrer@btinternet.com> <kevinfeyrer@users.noreply.github.com>
|
||||||
Kevin Kern <kaiwentan@harmonycloud.cn>
|
Kevin Kern <kaiwentan@harmonycloud.cn>
|
||||||
Kevin Meredith <kevin.m.meredith@gmail.com>
|
Kevin Meredith <kevin.m.meredith@gmail.com>
|
||||||
|
@ -469,10 +482,15 @@ Mikael Davranche <mikael.davranche@corp.ovh.com>
|
||||||
Mikael Davranche <mikael.davranche@corp.ovh.com> <mikael.davranche@corp.ovh.net>
|
Mikael Davranche <mikael.davranche@corp.ovh.com> <mikael.davranche@corp.ovh.net>
|
||||||
Mike Casas <mkcsas0@gmail.com> <mikecasas@users.noreply.github.com>
|
Mike Casas <mkcsas0@gmail.com> <mikecasas@users.noreply.github.com>
|
||||||
Mike Goelzer <mike.goelzer@docker.com> <mgoelzer@docker.com>
|
Mike Goelzer <mike.goelzer@docker.com> <mgoelzer@docker.com>
|
||||||
|
Milas Bowman <devnull@milas.dev>
|
||||||
|
Milas Bowman <devnull@milas.dev> <milasb@gmail.com>
|
||||||
|
Milas Bowman <devnull@milas.dev> <milas.bowman@docker.com>
|
||||||
Milind Chawre <milindchawre@gmail.com>
|
Milind Chawre <milindchawre@gmail.com>
|
||||||
Misty Stanley-Jones <misty@docker.com> <misty@apache.org>
|
Misty Stanley-Jones <misty@docker.com> <misty@apache.org>
|
||||||
Mohammad Banikazemi <MBanikazemi@gmail.com>
|
Mohammad Banikazemi <MBanikazemi@gmail.com>
|
||||||
Mohammad Banikazemi <MBanikazemi@gmail.com> <mb@us.ibm.com>
|
Mohammad Banikazemi <MBanikazemi@gmail.com> <mb@us.ibm.com>
|
||||||
|
Mohd Sadiq <mohdsadiq058@gmail.com> <mohdsadiq058@gmail.com>
|
||||||
|
Mohd Sadiq <mohdsadiq058@gmail.com> <42430865+msadiq058@users.noreply.github.com>
|
||||||
Mohit Soni <mosoni@ebay.com> <mohitsoni1989@gmail.com>
|
Mohit Soni <mosoni@ebay.com> <mohitsoni1989@gmail.com>
|
||||||
Moorthy RS <rsmoorthy@gmail.com> <rsmoorthy@users.noreply.github.com>
|
Moorthy RS <rsmoorthy@gmail.com> <rsmoorthy@users.noreply.github.com>
|
||||||
Moysés Borges <moysesb@gmail.com>
|
Moysés Borges <moysesb@gmail.com>
|
||||||
|
@ -548,7 +566,9 @@ Sebastiaan van Stijn <github@gone.nl>
|
||||||
Sebastiaan van Stijn <github@gone.nl> <moby@example.com>
|
Sebastiaan van Stijn <github@gone.nl> <moby@example.com>
|
||||||
Sebastiaan van Stijn <github@gone.nl> <sebastiaan@ws-key-sebas3.dpi1.dpi>
|
Sebastiaan van Stijn <github@gone.nl> <sebastiaan@ws-key-sebas3.dpi1.dpi>
|
||||||
Sebastiaan van Stijn <github@gone.nl> <thaJeztah@users.noreply.github.com>
|
Sebastiaan van Stijn <github@gone.nl> <thaJeztah@users.noreply.github.com>
|
||||||
|
Sebastian Thomschke <sebthom@users.noreply.github.com>
|
||||||
Seongyeol Lim <seongyeol37@gmail.com>
|
Seongyeol Lim <seongyeol37@gmail.com>
|
||||||
|
Serhii Nakon <serhii.n@thescimus.com>
|
||||||
Shaun Kaasten <shaunk@gmail.com>
|
Shaun Kaasten <shaunk@gmail.com>
|
||||||
Shawn Landden <shawn@churchofgit.com> <shawnlandden@gmail.com>
|
Shawn Landden <shawn@churchofgit.com> <shawnlandden@gmail.com>
|
||||||
Shengbo Song <thomassong@tencent.com>
|
Shengbo Song <thomassong@tencent.com>
|
||||||
|
@ -695,6 +715,8 @@ Xiaodong Liu <liuxiaodong@loongson.cn>
|
||||||
Xiaodong Zhang <a4012017@sina.com>
|
Xiaodong Zhang <a4012017@sina.com>
|
||||||
Xiaohua Ding <xiao_hua_ding@sina.cn>
|
Xiaohua Ding <xiao_hua_ding@sina.cn>
|
||||||
Xiaoyu Zhang <zhang.xiaoyu33@zte.com.cn>
|
Xiaoyu Zhang <zhang.xiaoyu33@zte.com.cn>
|
||||||
|
Xinfeng Liu <XinfengLiu@icloud.com>
|
||||||
|
Xinfeng Liu <XinfengLiu@icloud.com> <xinfeng.liu@gmail.com>
|
||||||
Xuecong Liao <satorulogic@gmail.com>
|
Xuecong Liao <satorulogic@gmail.com>
|
||||||
Yamasaki Masahide <masahide.y@gmail.com>
|
Yamasaki Masahide <masahide.y@gmail.com>
|
||||||
Yao Zaiyong <yaozaiyong@hotmail.com>
|
Yao Zaiyong <yaozaiyong@hotmail.com>
|
||||||
|
|
76
AUTHORS
76
AUTHORS
|
@ -27,8 +27,10 @@ Adam Miller <admiller@redhat.com>
|
||||||
Adam Mills <adam@armills.info>
|
Adam Mills <adam@armills.info>
|
||||||
Adam Pointer <adam.pointer@skybettingandgaming.com>
|
Adam Pointer <adam.pointer@skybettingandgaming.com>
|
||||||
Adam Singer <financeCoding@gmail.com>
|
Adam Singer <financeCoding@gmail.com>
|
||||||
|
Adam Thornton <adam.thornton@maryville.com>
|
||||||
Adam Walz <adam@adamwalz.net>
|
Adam Walz <adam@adamwalz.net>
|
||||||
Adam Williams <awilliams@mirantis.com>
|
Adam Williams <awilliams@mirantis.com>
|
||||||
|
AdamKorcz <adam@adalogics.com>
|
||||||
Addam Hardy <addam.hardy@gmail.com>
|
Addam Hardy <addam.hardy@gmail.com>
|
||||||
Aditi Rajagopal <arajagopal@us.ibm.com>
|
Aditi Rajagopal <arajagopal@us.ibm.com>
|
||||||
Aditya <aditya@netroy.in>
|
Aditya <aditya@netroy.in>
|
||||||
|
@ -81,6 +83,7 @@ Alex Goodman <wagoodman@gmail.com>
|
||||||
Alex Nordlund <alexander.nordlund@nasdaq.com>
|
Alex Nordlund <alexander.nordlund@nasdaq.com>
|
||||||
Alex Olshansky <i@creagenics.com>
|
Alex Olshansky <i@creagenics.com>
|
||||||
Alex Samorukov <samm@os2.kiev.ua>
|
Alex Samorukov <samm@os2.kiev.ua>
|
||||||
|
Alex Stockinger <alex@atomicjar.com>
|
||||||
Alex Warhawk <ax.warhawk@gmail.com>
|
Alex Warhawk <ax.warhawk@gmail.com>
|
||||||
Alexander Artemenko <svetlyak.40wt@gmail.com>
|
Alexander Artemenko <svetlyak.40wt@gmail.com>
|
||||||
Alexander Boyd <alex@opengroove.org>
|
Alexander Boyd <alex@opengroove.org>
|
||||||
|
@ -171,6 +174,7 @@ Andy Rothfusz <github@developersupport.net>
|
||||||
Andy Smith <github@anarkystic.com>
|
Andy Smith <github@anarkystic.com>
|
||||||
Andy Wilson <wilson.andrew.j+github@gmail.com>
|
Andy Wilson <wilson.andrew.j+github@gmail.com>
|
||||||
Andy Zhang <andy.zhangtao@hotmail.com>
|
Andy Zhang <andy.zhangtao@hotmail.com>
|
||||||
|
Aneesh Kulkarni <askthefactorcamera@gmail.com>
|
||||||
Anes Hasicic <anes.hasicic@gmail.com>
|
Anes Hasicic <anes.hasicic@gmail.com>
|
||||||
Angel Velazquez <angelcar@amazon.com>
|
Angel Velazquez <angelcar@amazon.com>
|
||||||
Anil Belur <askb23@gmail.com>
|
Anil Belur <askb23@gmail.com>
|
||||||
|
@ -198,6 +202,7 @@ Anusha Ragunathan <anusha.ragunathan@docker.com>
|
||||||
Anyu Wang <wanganyu@outlook.com>
|
Anyu Wang <wanganyu@outlook.com>
|
||||||
apocas <petermdias@gmail.com>
|
apocas <petermdias@gmail.com>
|
||||||
Arash Deshmeh <adeshmeh@ca.ibm.com>
|
Arash Deshmeh <adeshmeh@ca.ibm.com>
|
||||||
|
arcosx <arcosx@outlook.com>
|
||||||
ArikaChen <eaglesora@gmail.com>
|
ArikaChen <eaglesora@gmail.com>
|
||||||
Arko Dasgupta <arko@tetrate.io>
|
Arko Dasgupta <arko@tetrate.io>
|
||||||
Arnaud Lefebvre <a.lefebvre@outlook.fr>
|
Arnaud Lefebvre <a.lefebvre@outlook.fr>
|
||||||
|
@ -233,6 +238,7 @@ Ben Golub <ben.golub@dotcloud.com>
|
||||||
Ben Gould <ben@bengould.co.uk>
|
Ben Gould <ben@bengould.co.uk>
|
||||||
Ben Hall <ben@benhall.me.uk>
|
Ben Hall <ben@benhall.me.uk>
|
||||||
Ben Langfeld <ben@langfeld.me>
|
Ben Langfeld <ben@langfeld.me>
|
||||||
|
Ben Lovy <ben@deciduously.com>
|
||||||
Ben Sargent <ben@brokendigits.com>
|
Ben Sargent <ben@brokendigits.com>
|
||||||
Ben Severson <BenSeverson@users.noreply.github.com>
|
Ben Severson <BenSeverson@users.noreply.github.com>
|
||||||
Ben Toews <mastahyeti@gmail.com>
|
Ben Toews <mastahyeti@gmail.com>
|
||||||
|
@ -241,6 +247,7 @@ Benjamin Atkin <ben@benatkin.com>
|
||||||
Benjamin Baker <Benjamin.baker@utexas.edu>
|
Benjamin Baker <Benjamin.baker@utexas.edu>
|
||||||
Benjamin Boudreau <boudreau.benjamin@gmail.com>
|
Benjamin Boudreau <boudreau.benjamin@gmail.com>
|
||||||
Benjamin Böhmke <benjamin@boehmke.net>
|
Benjamin Böhmke <benjamin@boehmke.net>
|
||||||
|
Benjamin Wang <wachao@vmware.com>
|
||||||
Benjamin Yolken <yolken@stripe.com>
|
Benjamin Yolken <yolken@stripe.com>
|
||||||
Benny Ng <benny.tpng@gmail.com>
|
Benny Ng <benny.tpng@gmail.com>
|
||||||
Benoit Chesneau <bchesneau@gmail.com>
|
Benoit Chesneau <bchesneau@gmail.com>
|
||||||
|
@ -258,7 +265,7 @@ Billy Ridgway <wrridgwa@us.ibm.com>
|
||||||
Bily Zhang <xcoder@tenxcloud.com>
|
Bily Zhang <xcoder@tenxcloud.com>
|
||||||
Bin Liu <liubin0329@gmail.com>
|
Bin Liu <liubin0329@gmail.com>
|
||||||
Bingshen Wang <bingshen.wbs@alibaba-inc.com>
|
Bingshen Wang <bingshen.wbs@alibaba-inc.com>
|
||||||
Bjorn Neergaard <bneergaard@mirantis.com>
|
Bjorn Neergaard <bjorn@neersighted.com>
|
||||||
Blake Geno <blakegeno@gmail.com>
|
Blake Geno <blakegeno@gmail.com>
|
||||||
Boaz Shuster <ripcurld.github@gmail.com>
|
Boaz Shuster <ripcurld.github@gmail.com>
|
||||||
bobby abbott <ttobbaybbob@gmail.com>
|
bobby abbott <ttobbaybbob@gmail.com>
|
||||||
|
@ -275,6 +282,7 @@ Brandon Liu <bdon@bdon.org>
|
||||||
Brandon Philips <brandon.philips@coreos.com>
|
Brandon Philips <brandon.philips@coreos.com>
|
||||||
Brandon Rhodes <brandon@rhodesmill.org>
|
Brandon Rhodes <brandon@rhodesmill.org>
|
||||||
Brendan Dixon <brendand@microsoft.com>
|
Brendan Dixon <brendand@microsoft.com>
|
||||||
|
Brennan Kinney <5098581+polarathene@users.noreply.github.com>
|
||||||
Brent Salisbury <brent.salisbury@docker.com>
|
Brent Salisbury <brent.salisbury@docker.com>
|
||||||
Brett Higgins <brhiggins@arbor.net>
|
Brett Higgins <brhiggins@arbor.net>
|
||||||
Brett Kochendorfer <brett.kochendorfer@gmail.com>
|
Brett Kochendorfer <brett.kochendorfer@gmail.com>
|
||||||
|
@ -359,6 +367,7 @@ chenyuzhu <chenyuzhi@oschina.cn>
|
||||||
Chetan Birajdar <birajdar.chetan@gmail.com>
|
Chetan Birajdar <birajdar.chetan@gmail.com>
|
||||||
Chewey <prosto-chewey@users.noreply.github.com>
|
Chewey <prosto-chewey@users.noreply.github.com>
|
||||||
Chia-liang Kao <clkao@clkao.org>
|
Chia-liang Kao <clkao@clkao.org>
|
||||||
|
Chiranjeevi Tirunagari <vchiranjeeviak.tirunagari@gmail.com>
|
||||||
chli <chli@freewheel.tv>
|
chli <chli@freewheel.tv>
|
||||||
Cholerae Hu <choleraehyq@gmail.com>
|
Cholerae Hu <choleraehyq@gmail.com>
|
||||||
Chris Alfonso <calfonso@redhat.com>
|
Chris Alfonso <calfonso@redhat.com>
|
||||||
|
@ -429,8 +438,8 @@ Cristian Staretu <cristian.staretu@gmail.com>
|
||||||
cristiano balducci <cristiano.balducci@gmail.com>
|
cristiano balducci <cristiano.balducci@gmail.com>
|
||||||
Cristina Yenyxe Gonzalez Garcia <cristina.yenyxe@gmail.com>
|
Cristina Yenyxe Gonzalez Garcia <cristina.yenyxe@gmail.com>
|
||||||
Cruceru Calin-Cristian <crucerucalincristian@gmail.com>
|
Cruceru Calin-Cristian <crucerucalincristian@gmail.com>
|
||||||
|
cui fliter <imcusg@gmail.com>
|
||||||
CUI Wei <ghostplant@qq.com>
|
CUI Wei <ghostplant@qq.com>
|
||||||
cuishuang <imcusg@gmail.com>
|
|
||||||
Cuong Manh Le <cuong.manhle.vn@gmail.com>
|
Cuong Manh Le <cuong.manhle.vn@gmail.com>
|
||||||
Cyprian Gracz <cyprian.gracz@micro-jumbo.eu>
|
Cyprian Gracz <cyprian.gracz@micro-jumbo.eu>
|
||||||
Cyril F <cyrilf7x@gmail.com>
|
Cyril F <cyrilf7x@gmail.com>
|
||||||
|
@ -509,6 +518,7 @@ David Dooling <dooling@gmail.com>
|
||||||
David Gageot <david@gageot.net>
|
David Gageot <david@gageot.net>
|
||||||
David Gebler <davidgebler@gmail.com>
|
David Gebler <davidgebler@gmail.com>
|
||||||
David Glasser <glasser@davidglasser.net>
|
David Glasser <glasser@davidglasser.net>
|
||||||
|
David Karlsson <35727626+dvdksn@users.noreply.github.com>
|
||||||
David Lawrence <david.lawrence@docker.com>
|
David Lawrence <david.lawrence@docker.com>
|
||||||
David Lechner <david@lechnology.com>
|
David Lechner <david@lechnology.com>
|
||||||
David M. Karr <davidmichaelkarr@gmail.com>
|
David M. Karr <davidmichaelkarr@gmail.com>
|
||||||
|
@ -598,6 +608,7 @@ Donald Huang <don.hcd@gmail.com>
|
||||||
Dong Chen <dongluo.chen@docker.com>
|
Dong Chen <dongluo.chen@docker.com>
|
||||||
Donghwa Kim <shanytt@gmail.com>
|
Donghwa Kim <shanytt@gmail.com>
|
||||||
Donovan Jones <git@gamma.net.nz>
|
Donovan Jones <git@gamma.net.nz>
|
||||||
|
Dorin Geman <dorin.geman@docker.com>
|
||||||
Doron Podoleanu <doronp@il.ibm.com>
|
Doron Podoleanu <doronp@il.ibm.com>
|
||||||
Doug Davis <dug@us.ibm.com>
|
Doug Davis <dug@us.ibm.com>
|
||||||
Doug MacEachern <dougm@vmware.com>
|
Doug MacEachern <dougm@vmware.com>
|
||||||
|
@ -632,8 +643,10 @@ Emily Rose <emily@contactvibe.com>
|
||||||
Emir Ozer <emirozer@yandex.com>
|
Emir Ozer <emirozer@yandex.com>
|
||||||
Eng Zer Jun <engzerjun@gmail.com>
|
Eng Zer Jun <engzerjun@gmail.com>
|
||||||
Enguerran <engcolson@gmail.com>
|
Enguerran <engcolson@gmail.com>
|
||||||
|
Enrico Weigelt, metux IT consult <info@metux.net>
|
||||||
Eohyung Lee <liquidnuker@gmail.com>
|
Eohyung Lee <liquidnuker@gmail.com>
|
||||||
epeterso <epeterson@breakpoint-labs.com>
|
epeterso <epeterson@breakpoint-labs.com>
|
||||||
|
er0k <er0k@er0k.net>
|
||||||
Eric Barch <barch@tomesoftware.com>
|
Eric Barch <barch@tomesoftware.com>
|
||||||
Eric Curtin <ericcurtin17@gmail.com>
|
Eric Curtin <ericcurtin17@gmail.com>
|
||||||
Eric G. Noriega <enoriega@vizuri.com>
|
Eric G. Noriega <enoriega@vizuri.com>
|
||||||
|
@ -656,6 +669,7 @@ Erik Hollensbe <github@hollensbe.org>
|
||||||
Erik Inge Bolsø <knan@redpill-linpro.com>
|
Erik Inge Bolsø <knan@redpill-linpro.com>
|
||||||
Erik Kristensen <erik@erikkristensen.com>
|
Erik Kristensen <erik@erikkristensen.com>
|
||||||
Erik Sipsma <erik@sipsma.dev>
|
Erik Sipsma <erik@sipsma.dev>
|
||||||
|
Erik Sjölund <erik.sjolund@gmail.com>
|
||||||
Erik St. Martin <alakriti@gmail.com>
|
Erik St. Martin <alakriti@gmail.com>
|
||||||
Erik Weathers <erikdw@gmail.com>
|
Erik Weathers <erikdw@gmail.com>
|
||||||
Erno Hopearuoho <erno.hopearuoho@gmail.com>
|
Erno Hopearuoho <erno.hopearuoho@gmail.com>
|
||||||
|
@ -671,6 +685,7 @@ Evan Allrich <evan@unguku.com>
|
||||||
Evan Carmi <carmi@users.noreply.github.com>
|
Evan Carmi <carmi@users.noreply.github.com>
|
||||||
Evan Hazlett <ejhazlett@gmail.com>
|
Evan Hazlett <ejhazlett@gmail.com>
|
||||||
Evan Krall <krall@yelp.com>
|
Evan Krall <krall@yelp.com>
|
||||||
|
Evan Lezar <elezar@nvidia.com>
|
||||||
Evan Phoenix <evan@fallingsnow.net>
|
Evan Phoenix <evan@fallingsnow.net>
|
||||||
Evan Wies <evan@neomantra.net>
|
Evan Wies <evan@neomantra.net>
|
||||||
Evelyn Xu <evelynhsu21@gmail.com>
|
Evelyn Xu <evelynhsu21@gmail.com>
|
||||||
|
@ -717,6 +732,7 @@ Feroz Salam <feroz.salam@sourcegraph.com>
|
||||||
Ferran Rodenas <frodenas@gmail.com>
|
Ferran Rodenas <frodenas@gmail.com>
|
||||||
Filipe Brandenburger <filbranden@google.com>
|
Filipe Brandenburger <filbranden@google.com>
|
||||||
Filipe Oliveira <contato@fmoliveira.com.br>
|
Filipe Oliveira <contato@fmoliveira.com.br>
|
||||||
|
Filipe Pina <hzlu1ot0@duck.com>
|
||||||
Flavio Castelli <fcastelli@suse.com>
|
Flavio Castelli <fcastelli@suse.com>
|
||||||
Flavio Crisciani <flavio.crisciani@docker.com>
|
Flavio Crisciani <flavio.crisciani@docker.com>
|
||||||
Florian <FWirtz@users.noreply.github.com>
|
Florian <FWirtz@users.noreply.github.com>
|
||||||
|
@ -739,6 +755,7 @@ Frank Groeneveld <frank@ivaldi.nl>
|
||||||
Frank Herrmann <fgh@4gh.tv>
|
Frank Herrmann <fgh@4gh.tv>
|
||||||
Frank Macreery <frank@macreery.com>
|
Frank Macreery <frank@macreery.com>
|
||||||
Frank Rosquin <frank.rosquin+github@gmail.com>
|
Frank Rosquin <frank.rosquin+github@gmail.com>
|
||||||
|
Frank Villaro-Dixon <frank.villarodixon@merkle.com>
|
||||||
Frank Yang <yyb196@gmail.com>
|
Frank Yang <yyb196@gmail.com>
|
||||||
Fred Lifton <fred.lifton@docker.com>
|
Fred Lifton <fred.lifton@docker.com>
|
||||||
Frederick F. Kautz IV <fkautz@redhat.com>
|
Frederick F. Kautz IV <fkautz@redhat.com>
|
||||||
|
@ -754,6 +771,7 @@ Félix Baylac-Jacqué <baylac.felix@gmail.com>
|
||||||
Félix Cantournet <felix.cantournet@cloudwatt.com>
|
Félix Cantournet <felix.cantournet@cloudwatt.com>
|
||||||
Gabe Rosenhouse <gabe@missionst.com>
|
Gabe Rosenhouse <gabe@missionst.com>
|
||||||
Gabor Nagy <mail@aigeruth.hu>
|
Gabor Nagy <mail@aigeruth.hu>
|
||||||
|
Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
|
||||||
Gabriel Goller <gabrielgoller123@gmail.com>
|
Gabriel Goller <gabrielgoller123@gmail.com>
|
||||||
Gabriel L. Somlo <gsomlo@gmail.com>
|
Gabriel L. Somlo <gsomlo@gmail.com>
|
||||||
Gabriel Linder <linder.gabriel@gmail.com>
|
Gabriel Linder <linder.gabriel@gmail.com>
|
||||||
|
@ -855,9 +873,12 @@ Hongbin Lu <hongbin034@gmail.com>
|
||||||
Hongxu Jia <hongxu.jia@windriver.com>
|
Hongxu Jia <hongxu.jia@windriver.com>
|
||||||
Honza Pokorny <me@honza.ca>
|
Honza Pokorny <me@honza.ca>
|
||||||
Hsing-Hui Hsu <hsinghui@amazon.com>
|
Hsing-Hui Hsu <hsinghui@amazon.com>
|
||||||
|
Hsing-Yu (David) Chen <davidhsingyuchen@gmail.com>
|
||||||
hsinko <21551195@zju.edu.cn>
|
hsinko <21551195@zju.edu.cn>
|
||||||
Hu Keping <hukeping@huawei.com>
|
Hu Keping <hukeping@huawei.com>
|
||||||
Hu Tao <hutao@cn.fujitsu.com>
|
Hu Tao <hutao@cn.fujitsu.com>
|
||||||
|
Huajin Tong <fliterdashen@gmail.com>
|
||||||
|
huang-jl <1046678590@qq.com>
|
||||||
HuanHuan Ye <logindaveye@gmail.com>
|
HuanHuan Ye <logindaveye@gmail.com>
|
||||||
Huanzhong Zhang <zhanghuanzhong90@gmail.com>
|
Huanzhong Zhang <zhanghuanzhong90@gmail.com>
|
||||||
Huayi Zhang <irachex@gmail.com>
|
Huayi Zhang <irachex@gmail.com>
|
||||||
|
@ -887,6 +908,7 @@ Igor Dolzhikov <bluesriverz@gmail.com>
|
||||||
Igor Karpovich <i.karpovich@currencysolutions.com>
|
Igor Karpovich <i.karpovich@currencysolutions.com>
|
||||||
Iliana Weller <iweller@amazon.com>
|
Iliana Weller <iweller@amazon.com>
|
||||||
Ilkka Laukkanen <ilkka@ilkka.io>
|
Ilkka Laukkanen <ilkka@ilkka.io>
|
||||||
|
Illia Antypenko <ilya@antipenko.pp.ua>
|
||||||
Illo Abdulrahim <abdulrahim.illo@nokia.com>
|
Illo Abdulrahim <abdulrahim.illo@nokia.com>
|
||||||
Ilya Dmitrichenko <errordeveloper@gmail.com>
|
Ilya Dmitrichenko <errordeveloper@gmail.com>
|
||||||
Ilya Gusev <mail@igusev.ru>
|
Ilya Gusev <mail@igusev.ru>
|
||||||
|
@ -938,6 +960,7 @@ Jamie Hannaford <jamie@limetree.org>
|
||||||
Jamshid Afshar <jafshar@yahoo.com>
|
Jamshid Afshar <jafshar@yahoo.com>
|
||||||
Jan Breig <git@pygos.space>
|
Jan Breig <git@pygos.space>
|
||||||
Jan Chren <dev.rindeal@gmail.com>
|
Jan Chren <dev.rindeal@gmail.com>
|
||||||
|
Jan Garcia <github-public@n-garcia.com>
|
||||||
Jan Götte <jaseg@jaseg.net>
|
Jan Götte <jaseg@jaseg.net>
|
||||||
Jan Keromnes <janx@linux.com>
|
Jan Keromnes <janx@linux.com>
|
||||||
Jan Koprowski <jan.koprowski@gmail.com>
|
Jan Koprowski <jan.koprowski@gmail.com>
|
||||||
|
@ -950,6 +973,7 @@ Jannick Fahlbusch <git@jf-projects.de>
|
||||||
Januar Wayong <januar@gmail.com>
|
Januar Wayong <januar@gmail.com>
|
||||||
Jared Biel <jared.biel@bolderthinking.com>
|
Jared Biel <jared.biel@bolderthinking.com>
|
||||||
Jared Hocutt <jaredh@netapp.com>
|
Jared Hocutt <jaredh@netapp.com>
|
||||||
|
Jaroslav Jindrak <dzejrou@gmail.com>
|
||||||
Jaroslaw Zabiello <hipertracker@gmail.com>
|
Jaroslaw Zabiello <hipertracker@gmail.com>
|
||||||
Jasmine Hegman <jasmine@jhegman.com>
|
Jasmine Hegman <jasmine@jhegman.com>
|
||||||
Jason A. Donenfeld <Jason@zx2c4.com>
|
Jason A. Donenfeld <Jason@zx2c4.com>
|
||||||
|
@ -974,6 +998,7 @@ Jean Rouge <rougej+github@gmail.com>
|
||||||
Jean-Baptiste Barth <jeanbaptiste.barth@gmail.com>
|
Jean-Baptiste Barth <jeanbaptiste.barth@gmail.com>
|
||||||
Jean-Baptiste Dalido <jeanbaptiste@appgratis.com>
|
Jean-Baptiste Dalido <jeanbaptiste@appgratis.com>
|
||||||
Jean-Christophe Berthon <huygens@berthon.eu>
|
Jean-Christophe Berthon <huygens@berthon.eu>
|
||||||
|
Jean-Michel Rouet <jm.rouet@gmail.com>
|
||||||
Jean-Paul Calderone <exarkun@twistedmatrix.com>
|
Jean-Paul Calderone <exarkun@twistedmatrix.com>
|
||||||
Jean-Pierre Huynh <jean-pierre.huynh@ounet.fr>
|
Jean-Pierre Huynh <jean-pierre.huynh@ounet.fr>
|
||||||
Jean-Tiare Le Bigot <jt@yadutaf.fr>
|
Jean-Tiare Le Bigot <jt@yadutaf.fr>
|
||||||
|
@ -992,6 +1017,7 @@ Jeffrey Bolle <jeffreybolle@gmail.com>
|
||||||
Jeffrey Morgan <jmorganca@gmail.com>
|
Jeffrey Morgan <jmorganca@gmail.com>
|
||||||
Jeffrey van Gogh <jvg@google.com>
|
Jeffrey van Gogh <jvg@google.com>
|
||||||
Jenny Gebske <jennifer@gebske.de>
|
Jenny Gebske <jennifer@gebske.de>
|
||||||
|
Jeongseok Kang <piono623@naver.com>
|
||||||
Jeremy Chambers <jeremy@thehipbot.com>
|
Jeremy Chambers <jeremy@thehipbot.com>
|
||||||
Jeremy Grosser <jeremy@synack.me>
|
Jeremy Grosser <jeremy@synack.me>
|
||||||
Jeremy Huntwork <jhuntwork@lightcubesolutions.com>
|
Jeremy Huntwork <jhuntwork@lightcubesolutions.com>
|
||||||
|
@ -1004,10 +1030,12 @@ Jeroen Jacobs <github@jeroenj.be>
|
||||||
Jesse Dearing <jesse.dearing@gmail.com>
|
Jesse Dearing <jesse.dearing@gmail.com>
|
||||||
Jesse Dubay <jesse@thefortytwo.net>
|
Jesse Dubay <jesse@thefortytwo.net>
|
||||||
Jessica Frazelle <jess@oxide.computer>
|
Jessica Frazelle <jess@oxide.computer>
|
||||||
|
Jeyanthinath Muthuram <jeyanthinath10@gmail.com>
|
||||||
Jezeniel Zapanta <jpzapanta22@gmail.com>
|
Jezeniel Zapanta <jpzapanta22@gmail.com>
|
||||||
Jhon Honce <jhonce@redhat.com>
|
Jhon Honce <jhonce@redhat.com>
|
||||||
Ji.Zhilong <zhilongji@gmail.com>
|
Ji.Zhilong <zhilongji@gmail.com>
|
||||||
Jian Liao <jliao@alauda.io>
|
Jian Liao <jliao@alauda.io>
|
||||||
|
Jian Zeng <anonymousknight96@gmail.com>
|
||||||
Jian Zhang <zhangjian.fnst@cn.fujitsu.com>
|
Jian Zhang <zhangjian.fnst@cn.fujitsu.com>
|
||||||
Jiang Jinyang <jjyruby@gmail.com>
|
Jiang Jinyang <jjyruby@gmail.com>
|
||||||
Jianyong Wu <jianyong.wu@arm.com>
|
Jianyong Wu <jianyong.wu@arm.com>
|
||||||
|
@ -1132,6 +1160,7 @@ junxu <xujun@cmss.chinamobile.com>
|
||||||
Jussi Nummelin <jussi.nummelin@gmail.com>
|
Jussi Nummelin <jussi.nummelin@gmail.com>
|
||||||
Justas Brazauskas <brazauskasjustas@gmail.com>
|
Justas Brazauskas <brazauskasjustas@gmail.com>
|
||||||
Justen Martin <jmart@the-coder.com>
|
Justen Martin <jmart@the-coder.com>
|
||||||
|
Justin Chadwell <me@jedevc.com>
|
||||||
Justin Cormack <justin.cormack@docker.com>
|
Justin Cormack <justin.cormack@docker.com>
|
||||||
Justin Force <justin.force@gmail.com>
|
Justin Force <justin.force@gmail.com>
|
||||||
Justin Keller <85903732+jk-vb@users.noreply.github.com>
|
Justin Keller <85903732+jk-vb@users.noreply.github.com>
|
||||||
|
@ -1174,6 +1203,7 @@ Ke Xu <leonhartx.k@gmail.com>
|
||||||
Kei Ohmura <ohmura.kei@gmail.com>
|
Kei Ohmura <ohmura.kei@gmail.com>
|
||||||
Keith Hudgins <greenman@greenman.org>
|
Keith Hudgins <greenman@greenman.org>
|
||||||
Keli Hu <dev@keli.hu>
|
Keli Hu <dev@keli.hu>
|
||||||
|
Ken Bannister <kb2ma@runbox.com>
|
||||||
Ken Cochrane <kencochrane@gmail.com>
|
Ken Cochrane <kencochrane@gmail.com>
|
||||||
Ken Herner <kherner@progress.com>
|
Ken Herner <kherner@progress.com>
|
||||||
Ken ICHIKAWA <ichikawa.ken@jp.fujitsu.com>
|
Ken ICHIKAWA <ichikawa.ken@jp.fujitsu.com>
|
||||||
|
@ -1183,7 +1213,7 @@ Kenjiro Nakayama <nakayamakenjiro@gmail.com>
|
||||||
Kent Johnson <kentoj@gmail.com>
|
Kent Johnson <kentoj@gmail.com>
|
||||||
Kenta Tada <Kenta.Tada@sony.com>
|
Kenta Tada <Kenta.Tada@sony.com>
|
||||||
Kevin "qwazerty" Houdebert <kevin.houdebert@gmail.com>
|
Kevin "qwazerty" Houdebert <kevin.houdebert@gmail.com>
|
||||||
Kevin Alvarez <crazy-max@users.noreply.github.com>
|
Kevin Alvarez <github@crazymax.dev>
|
||||||
Kevin Burke <kev@inburke.com>
|
Kevin Burke <kev@inburke.com>
|
||||||
Kevin Clark <kevin.clark@gmail.com>
|
Kevin Clark <kevin.clark@gmail.com>
|
||||||
Kevin Feyrer <kevin.feyrer@btinternet.com>
|
Kevin Feyrer <kevin.feyrer@btinternet.com>
|
||||||
|
@ -1206,6 +1236,7 @@ Kimbro Staken <kstaken@kstaken.com>
|
||||||
Kir Kolyshkin <kolyshkin@gmail.com>
|
Kir Kolyshkin <kolyshkin@gmail.com>
|
||||||
Kiran Gangadharan <kiran.daredevil@gmail.com>
|
Kiran Gangadharan <kiran.daredevil@gmail.com>
|
||||||
Kirill SIbirev <l0kix2@gmail.com>
|
Kirill SIbirev <l0kix2@gmail.com>
|
||||||
|
Kirk Easterson <kirk.easterson@gmail.com>
|
||||||
knappe <tyler.knappe@gmail.com>
|
knappe <tyler.knappe@gmail.com>
|
||||||
Kohei Tsuruta <coheyxyz@gmail.com>
|
Kohei Tsuruta <coheyxyz@gmail.com>
|
||||||
Koichi Shiraishi <k@zchee.io>
|
Koichi Shiraishi <k@zchee.io>
|
||||||
|
@ -1215,6 +1246,7 @@ Konstantin Gribov <grossws@gmail.com>
|
||||||
Konstantin L <sw.double@gmail.com>
|
Konstantin L <sw.double@gmail.com>
|
||||||
Konstantin Pelykh <kpelykh@zettaset.com>
|
Konstantin Pelykh <kpelykh@zettaset.com>
|
||||||
Kostadin Plachkov <k.n.plachkov@gmail.com>
|
Kostadin Plachkov <k.n.plachkov@gmail.com>
|
||||||
|
kpcyrd <git@rxv.cc>
|
||||||
Krasi Georgiev <krasi@vip-consult.solutions>
|
Krasi Georgiev <krasi@vip-consult.solutions>
|
||||||
Krasimir Georgiev <support@vip-consult.co.uk>
|
Krasimir Georgiev <support@vip-consult.co.uk>
|
||||||
Kris-Mikael Krister <krismikael@protonmail.com>
|
Kris-Mikael Krister <krismikael@protonmail.com>
|
||||||
|
@ -1240,10 +1272,12 @@ Lars Kellogg-Stedman <lars@redhat.com>
|
||||||
Lars R. Damerow <lars@pixar.com>
|
Lars R. Damerow <lars@pixar.com>
|
||||||
Lars-Magnus Skog <ralphtheninja@riseup.net>
|
Lars-Magnus Skog <ralphtheninja@riseup.net>
|
||||||
Laszlo Meszaros <lacienator@gmail.com>
|
Laszlo Meszaros <lacienator@gmail.com>
|
||||||
|
Laura Brehm <laurabrehm@hey.com>
|
||||||
Laura Frank <ljfrank@gmail.com>
|
Laura Frank <ljfrank@gmail.com>
|
||||||
Laurent Bernaille <laurent.bernaille@datadoghq.com>
|
Laurent Bernaille <laurent.bernaille@datadoghq.com>
|
||||||
Laurent Erignoux <lerignoux@gmail.com>
|
Laurent Erignoux <lerignoux@gmail.com>
|
||||||
Laurie Voss <github@seldo.com>
|
Laurie Voss <github@seldo.com>
|
||||||
|
Leandro Motta Barros <lmb@stackedboxes.org>
|
||||||
Leandro Siqueira <leandro.siqueira@gmail.com>
|
Leandro Siqueira <leandro.siqueira@gmail.com>
|
||||||
Lee Calcote <leecalcote@gmail.com>
|
Lee Calcote <leecalcote@gmail.com>
|
||||||
Lee Chao <932819864@qq.com>
|
Lee Chao <932819864@qq.com>
|
||||||
|
@ -1294,6 +1328,7 @@ Lorenzo Fontana <fontanalorenz@gmail.com>
|
||||||
Lotus Fenn <fenn.lotus@gmail.com>
|
Lotus Fenn <fenn.lotus@gmail.com>
|
||||||
Louis Delossantos <ldelossa.ld@gmail.com>
|
Louis Delossantos <ldelossa.ld@gmail.com>
|
||||||
Louis Opter <kalessin@kalessin.fr>
|
Louis Opter <kalessin@kalessin.fr>
|
||||||
|
Luboslav Pivarc <lpivarc@redhat.com>
|
||||||
Luca Favatella <luca.favatella@erlang-solutions.com>
|
Luca Favatella <luca.favatella@erlang-solutions.com>
|
||||||
Luca Marturana <lucamarturana@gmail.com>
|
Luca Marturana <lucamarturana@gmail.com>
|
||||||
Luca Orlandi <luca.orlandi@gmail.com>
|
Luca Orlandi <luca.orlandi@gmail.com>
|
||||||
|
@ -1332,6 +1367,7 @@ Manuel Meurer <manuel@krautcomputing.com>
|
||||||
Manuel Rüger <manuel@rueg.eu>
|
Manuel Rüger <manuel@rueg.eu>
|
||||||
Manuel Woelker <github@manuel.woelker.org>
|
Manuel Woelker <github@manuel.woelker.org>
|
||||||
mapk0y <mapk0y@gmail.com>
|
mapk0y <mapk0y@gmail.com>
|
||||||
|
Marat Radchenko <marat@slonopotamus.org>
|
||||||
Marc Abramowitz <marc@marc-abramowitz.com>
|
Marc Abramowitz <marc@marc-abramowitz.com>
|
||||||
Marc Kuo <kuomarc2@gmail.com>
|
Marc Kuo <kuomarc2@gmail.com>
|
||||||
Marc Tamsky <mtamsky@gmail.com>
|
Marc Tamsky <mtamsky@gmail.com>
|
||||||
|
@ -1371,6 +1407,7 @@ Martijn van Oosterhout <kleptog@svana.org>
|
||||||
Martin Braun <braun@neuroforge.de>
|
Martin Braun <braun@neuroforge.de>
|
||||||
Martin Dojcak <martin.dojcak@lablabs.io>
|
Martin Dojcak <martin.dojcak@lablabs.io>
|
||||||
Martin Honermeyer <maze@strahlungsfrei.de>
|
Martin Honermeyer <maze@strahlungsfrei.de>
|
||||||
|
Martin Jirku <martin@jirku.sk>
|
||||||
Martin Kelly <martin@surround.io>
|
Martin Kelly <martin@surround.io>
|
||||||
Martin Mosegaard Amdisen <martin.amdisen@praqma.com>
|
Martin Mosegaard Amdisen <martin.amdisen@praqma.com>
|
||||||
Martin Muzatko <martin@happy-css.com>
|
Martin Muzatko <martin@happy-css.com>
|
||||||
|
@ -1449,6 +1486,7 @@ Michael Holzheu <holzheu@linux.vnet.ibm.com>
|
||||||
Michael Hudson-Doyle <michael.hudson@canonical.com>
|
Michael Hudson-Doyle <michael.hudson@canonical.com>
|
||||||
Michael Huettermann <michael@huettermann.net>
|
Michael Huettermann <michael@huettermann.net>
|
||||||
Michael Irwin <mikesir87@gmail.com>
|
Michael Irwin <mikesir87@gmail.com>
|
||||||
|
Michael Kebe <michael.kebe@hkm.de>
|
||||||
Michael Kuehn <micha@kuehn.io>
|
Michael Kuehn <micha@kuehn.io>
|
||||||
Michael Käufl <docker@c.michael-kaeufl.de>
|
Michael Käufl <docker@c.michael-kaeufl.de>
|
||||||
Michael Neale <michael.neale@gmail.com>
|
Michael Neale <michael.neale@gmail.com>
|
||||||
|
@ -1497,10 +1535,11 @@ Mike Lundy <mike@fluffypenguin.org>
|
||||||
Mike MacCana <mike.maccana@gmail.com>
|
Mike MacCana <mike.maccana@gmail.com>
|
||||||
Mike Naberezny <mike@naberezny.com>
|
Mike Naberezny <mike@naberezny.com>
|
||||||
Mike Snitzer <snitzer@redhat.com>
|
Mike Snitzer <snitzer@redhat.com>
|
||||||
|
Mike Sul <mike.sul@foundries.io>
|
||||||
mikelinjie <294893458@qq.com>
|
mikelinjie <294893458@qq.com>
|
||||||
Mikhail Sobolev <mss@mawhrin.net>
|
Mikhail Sobolev <mss@mawhrin.net>
|
||||||
Miklos Szegedi <miklos.szegedi@cloudera.com>
|
Miklos Szegedi <miklos.szegedi@cloudera.com>
|
||||||
Milas Bowman <milasb@gmail.com>
|
Milas Bowman <devnull@milas.dev>
|
||||||
Milind Chawre <milindchawre@gmail.com>
|
Milind Chawre <milindchawre@gmail.com>
|
||||||
Miloslav Trmač <mitr@redhat.com>
|
Miloslav Trmač <mitr@redhat.com>
|
||||||
mingqing <limingqing@cyou-inc.com>
|
mingqing <limingqing@cyou-inc.com>
|
||||||
|
@ -1512,6 +1551,7 @@ mlarcher <github@ringabell.org>
|
||||||
Mohammad Banikazemi <MBanikazemi@gmail.com>
|
Mohammad Banikazemi <MBanikazemi@gmail.com>
|
||||||
Mohammad Nasirifar <farnasirim@gmail.com>
|
Mohammad Nasirifar <farnasirim@gmail.com>
|
||||||
Mohammed Aaqib Ansari <maaquib@gmail.com>
|
Mohammed Aaqib Ansari <maaquib@gmail.com>
|
||||||
|
Mohd Sadiq <mohdsadiq058@gmail.com>
|
||||||
Mohit Soni <mosoni@ebay.com>
|
Mohit Soni <mosoni@ebay.com>
|
||||||
Moorthy RS <rsmoorthy@gmail.com>
|
Moorthy RS <rsmoorthy@gmail.com>
|
||||||
Morgan Bauer <mbauer@us.ibm.com>
|
Morgan Bauer <mbauer@us.ibm.com>
|
||||||
|
@ -1563,6 +1603,7 @@ Nick Neisen <nwneisen@gmail.com>
|
||||||
Nick Parker <nikaios@gmail.com>
|
Nick Parker <nikaios@gmail.com>
|
||||||
Nick Payne <nick@kurai.co.uk>
|
Nick Payne <nick@kurai.co.uk>
|
||||||
Nick Russo <nicholasjamesrusso@gmail.com>
|
Nick Russo <nicholasjamesrusso@gmail.com>
|
||||||
|
Nick Santos <nick.santos@docker.com>
|
||||||
Nick Stenning <nick.stenning@digital.cabinet-office.gov.uk>
|
Nick Stenning <nick.stenning@digital.cabinet-office.gov.uk>
|
||||||
Nick Stinemates <nick@stinemates.org>
|
Nick Stinemates <nick@stinemates.org>
|
||||||
Nick Wood <nwood@microsoft.com>
|
Nick Wood <nwood@microsoft.com>
|
||||||
|
@ -1584,6 +1625,7 @@ NikolaMandic <mn080202@gmail.com>
|
||||||
Nikolas Garofil <nikolas.garofil@uantwerpen.be>
|
Nikolas Garofil <nikolas.garofil@uantwerpen.be>
|
||||||
Nikolay Edigaryev <edigaryev@gmail.com>
|
Nikolay Edigaryev <edigaryev@gmail.com>
|
||||||
Nikolay Milovanov <nmil@itransformers.net>
|
Nikolay Milovanov <nmil@itransformers.net>
|
||||||
|
ningmingxiao <ning.mingxiao@zte.com.cn>
|
||||||
Nirmal Mehta <nirmalkmehta@gmail.com>
|
Nirmal Mehta <nirmalkmehta@gmail.com>
|
||||||
Nishant Totla <nishanttotla@gmail.com>
|
Nishant Totla <nishanttotla@gmail.com>
|
||||||
NIWA Hideyuki <niwa.niwa@nifty.ne.jp>
|
NIWA Hideyuki <niwa.niwa@nifty.ne.jp>
|
||||||
|
@ -1592,6 +1634,7 @@ Noah Treuhaft <noah.treuhaft@docker.com>
|
||||||
NobodyOnSE <ich@sektor.selfip.com>
|
NobodyOnSE <ich@sektor.selfip.com>
|
||||||
noducks <onemannoducks@gmail.com>
|
noducks <onemannoducks@gmail.com>
|
||||||
Nolan Darilek <nolan@thewordnerd.info>
|
Nolan Darilek <nolan@thewordnerd.info>
|
||||||
|
Nolan Miles <nolanpmiles@gmail.com>
|
||||||
Noriki Nakamura <noriki.nakamura@miraclelinux.com>
|
Noriki Nakamura <noriki.nakamura@miraclelinux.com>
|
||||||
nponeccop <andy.melnikov@gmail.com>
|
nponeccop <andy.melnikov@gmail.com>
|
||||||
Nurahmadie <nurahmadie@gmail.com>
|
Nurahmadie <nurahmadie@gmail.com>
|
||||||
|
@ -1615,6 +1658,7 @@ Omri Shiv <Omri.Shiv@teradata.com>
|
||||||
Onur Filiz <onur.filiz@microsoft.com>
|
Onur Filiz <onur.filiz@microsoft.com>
|
||||||
Oriol Francès <oriolfa@gmail.com>
|
Oriol Francès <oriolfa@gmail.com>
|
||||||
Oscar Bonilla <6f6231@gmail.com>
|
Oscar Bonilla <6f6231@gmail.com>
|
||||||
|
oscar.chen <2972789494@qq.com>
|
||||||
Oskar Niburski <oskarniburski@gmail.com>
|
Oskar Niburski <oskarniburski@gmail.com>
|
||||||
Otto Kekäläinen <otto@seravo.fi>
|
Otto Kekäläinen <otto@seravo.fi>
|
||||||
Ouyang Liduo <oyld0210@163.com>
|
Ouyang Liduo <oyld0210@163.com>
|
||||||
|
@ -1646,6 +1690,7 @@ Paul Lietar <paul@lietar.net>
|
||||||
Paul Liljenberg <liljenberg.paul@gmail.com>
|
Paul Liljenberg <liljenberg.paul@gmail.com>
|
||||||
Paul Morie <pmorie@gmail.com>
|
Paul Morie <pmorie@gmail.com>
|
||||||
Paul Nasrat <pnasrat@gmail.com>
|
Paul Nasrat <pnasrat@gmail.com>
|
||||||
|
Paul Seiffert <paul.seiffert@jimdo.com>
|
||||||
Paul Weaver <pauweave@cisco.com>
|
Paul Weaver <pauweave@cisco.com>
|
||||||
Paulo Gomes <pjbgf@linux.com>
|
Paulo Gomes <pjbgf@linux.com>
|
||||||
Paulo Ribeiro <paigr.io@gmail.com>
|
Paulo Ribeiro <paigr.io@gmail.com>
|
||||||
|
@ -1659,6 +1704,7 @@ Pavlos Ratis <dastergon@gentoo.org>
|
||||||
Pavol Vargovcik <pallly.vargovcik@gmail.com>
|
Pavol Vargovcik <pallly.vargovcik@gmail.com>
|
||||||
Pawel Konczalski <mail@konczalski.de>
|
Pawel Konczalski <mail@konczalski.de>
|
||||||
Paweł Gronowski <pawel.gronowski@docker.com>
|
Paweł Gronowski <pawel.gronowski@docker.com>
|
||||||
|
payall4u <payall4u@qq.com>
|
||||||
Peeyush Gupta <gpeeyush@linux.vnet.ibm.com>
|
Peeyush Gupta <gpeeyush@linux.vnet.ibm.com>
|
||||||
Peggy Li <peggyli.224@gmail.com>
|
Peggy Li <peggyli.224@gmail.com>
|
||||||
Pei Su <sillyousu@gmail.com>
|
Pei Su <sillyousu@gmail.com>
|
||||||
|
@ -1688,7 +1734,9 @@ Phil Estes <estesp@gmail.com>
|
||||||
Phil Sphicas <phil.sphicas@att.com>
|
Phil Sphicas <phil.sphicas@att.com>
|
||||||
Phil Spitler <pspitler@gmail.com>
|
Phil Spitler <pspitler@gmail.com>
|
||||||
Philip Alexander Etling <paetling@gmail.com>
|
Philip Alexander Etling <paetling@gmail.com>
|
||||||
|
Philip K. Warren <pkwarren@gmail.com>
|
||||||
Philip Monroe <phil@philmonroe.com>
|
Philip Monroe <phil@philmonroe.com>
|
||||||
|
Philipp Fruck <dev@p-fruck.de>
|
||||||
Philipp Gillé <philipp.gille@gmail.com>
|
Philipp Gillé <philipp.gille@gmail.com>
|
||||||
Philipp Wahala <philipp.wahala@gmail.com>
|
Philipp Wahala <philipp.wahala@gmail.com>
|
||||||
Philipp Weissensteiner <mail@philippweissensteiner.com>
|
Philipp Weissensteiner <mail@philippweissensteiner.com>
|
||||||
|
@ -1726,6 +1774,7 @@ Quentin Brossard <qbrossard@gmail.com>
|
||||||
Quentin Perez <qperez@ocs.online.net>
|
Quentin Perez <qperez@ocs.online.net>
|
||||||
Quentin Tayssier <qtayssier@gmail.com>
|
Quentin Tayssier <qtayssier@gmail.com>
|
||||||
r0n22 <cameron.regan@gmail.com>
|
r0n22 <cameron.regan@gmail.com>
|
||||||
|
Rachit Sharma <rachitsharma613@gmail.com>
|
||||||
Radostin Stoyanov <rstoyanov1@gmail.com>
|
Radostin Stoyanov <rstoyanov1@gmail.com>
|
||||||
Rafal Jeczalik <rjeczalik@gmail.com>
|
Rafal Jeczalik <rjeczalik@gmail.com>
|
||||||
Rafe Colton <rafael.colton@gmail.com>
|
Rafe Colton <rafael.colton@gmail.com>
|
||||||
|
@ -1758,6 +1807,7 @@ Rich Horwood <rjhorwood@apple.com>
|
||||||
Rich Moyse <rich@moyse.us>
|
Rich Moyse <rich@moyse.us>
|
||||||
Rich Seymour <rseymour@gmail.com>
|
Rich Seymour <rseymour@gmail.com>
|
||||||
Richard Burnison <rburnison@ebay.com>
|
Richard Burnison <rburnison@ebay.com>
|
||||||
|
Richard Hansen <rhansen@rhansen.org>
|
||||||
Richard Harvey <richard@squarecows.com>
|
Richard Harvey <richard@squarecows.com>
|
||||||
Richard Mathie <richard.mathie@amey.co.uk>
|
Richard Mathie <richard.mathie@amey.co.uk>
|
||||||
Richard Metzler <richard@paadee.com>
|
Richard Metzler <richard@paadee.com>
|
||||||
|
@ -1773,6 +1823,7 @@ Ritesh H Shukla <sritesh@vmware.com>
|
||||||
Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
|
Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
|
||||||
Rob Cowsill <42620235+rcowsill@users.noreply.github.com>
|
Rob Cowsill <42620235+rcowsill@users.noreply.github.com>
|
||||||
Rob Gulewich <rgulewich@netflix.com>
|
Rob Gulewich <rgulewich@netflix.com>
|
||||||
|
Rob Murray <rob.murray@docker.com>
|
||||||
Rob Vesse <rvesse@dotnetrdf.org>
|
Rob Vesse <rvesse@dotnetrdf.org>
|
||||||
Robert Bachmann <rb@robertbachmann.at>
|
Robert Bachmann <rb@robertbachmann.at>
|
||||||
Robert Bittle <guywithnose@gmail.com>
|
Robert Bittle <guywithnose@gmail.com>
|
||||||
|
@ -1822,6 +1873,7 @@ Rory Hunter <roryhunter2@gmail.com>
|
||||||
Rory McCune <raesene@gmail.com>
|
Rory McCune <raesene@gmail.com>
|
||||||
Ross Boucher <rboucher@gmail.com>
|
Ross Boucher <rboucher@gmail.com>
|
||||||
Rovanion Luckey <rovanion.luckey@gmail.com>
|
Rovanion Luckey <rovanion.luckey@gmail.com>
|
||||||
|
Roy Reznik <roy@wiz.io>
|
||||||
Royce Remer <royceremer@gmail.com>
|
Royce Remer <royceremer@gmail.com>
|
||||||
Rozhnov Alexandr <nox73@ya.ru>
|
Rozhnov Alexandr <nox73@ya.ru>
|
||||||
Rudolph Gottesheim <r.gottesheim@loot.at>
|
Rudolph Gottesheim <r.gottesheim@loot.at>
|
||||||
|
@ -1853,6 +1905,7 @@ ryancooper7 <ryan.cooper7@gmail.com>
|
||||||
RyanDeng <sheldon.d1018@gmail.com>
|
RyanDeng <sheldon.d1018@gmail.com>
|
||||||
Ryo Nakao <nakabonne@gmail.com>
|
Ryo Nakao <nakabonne@gmail.com>
|
||||||
Ryoga Saito <contact@proelbtn.com>
|
Ryoga Saito <contact@proelbtn.com>
|
||||||
|
Régis Behmo <regis@behmo.com>
|
||||||
Rémy Greinhofer <remy.greinhofer@livelovely.com>
|
Rémy Greinhofer <remy.greinhofer@livelovely.com>
|
||||||
s. rannou <mxs@sbrk.org>
|
s. rannou <mxs@sbrk.org>
|
||||||
Sabin Basyal <sabin.basyal@gmail.com>
|
Sabin Basyal <sabin.basyal@gmail.com>
|
||||||
|
@ -1869,6 +1922,7 @@ Sam J Sharpe <sam.sharpe@digital.cabinet-office.gov.uk>
|
||||||
Sam Neirinck <sam@samneirinck.com>
|
Sam Neirinck <sam@samneirinck.com>
|
||||||
Sam Reis <sreis@atlassian.com>
|
Sam Reis <sreis@atlassian.com>
|
||||||
Sam Rijs <srijs@airpost.net>
|
Sam Rijs <srijs@airpost.net>
|
||||||
|
Sam Thibault <sam.thibault@docker.com>
|
||||||
Sam Whited <sam@samwhited.com>
|
Sam Whited <sam@samwhited.com>
|
||||||
Sambuddha Basu <sambuddhabasu1@gmail.com>
|
Sambuddha Basu <sambuddhabasu1@gmail.com>
|
||||||
Sami Wagiaalla <swagiaal@redhat.com>
|
Sami Wagiaalla <swagiaal@redhat.com>
|
||||||
|
@ -1892,6 +1946,7 @@ Satoshi Tagomori <tagomoris@gmail.com>
|
||||||
Scott Bessler <scottbessler@gmail.com>
|
Scott Bessler <scottbessler@gmail.com>
|
||||||
Scott Collier <emailscottcollier@gmail.com>
|
Scott Collier <emailscottcollier@gmail.com>
|
||||||
Scott Johnston <scott@docker.com>
|
Scott Johnston <scott@docker.com>
|
||||||
|
Scott Moser <smoser@brickies.net>
|
||||||
Scott Percival <scottp@lastyard.com>
|
Scott Percival <scottp@lastyard.com>
|
||||||
Scott Stamp <scottstamp851@gmail.com>
|
Scott Stamp <scottstamp851@gmail.com>
|
||||||
Scott Walls <sawalls@umich.edu>
|
Scott Walls <sawalls@umich.edu>
|
||||||
|
@ -1907,6 +1962,7 @@ Sebastiaan van Steenis <mail@superseb.nl>
|
||||||
Sebastiaan van Stijn <github@gone.nl>
|
Sebastiaan van Stijn <github@gone.nl>
|
||||||
Sebastian Höffner <sebastian.hoeffner@mevis.fraunhofer.de>
|
Sebastian Höffner <sebastian.hoeffner@mevis.fraunhofer.de>
|
||||||
Sebastian Radloff <sradloff23@gmail.com>
|
Sebastian Radloff <sradloff23@gmail.com>
|
||||||
|
Sebastian Thomschke <sebthom@users.noreply.github.com>
|
||||||
Sebastien Goasguen <runseb@gmail.com>
|
Sebastien Goasguen <runseb@gmail.com>
|
||||||
Senthil Kumar Selvaraj <senthil.thecoder@gmail.com>
|
Senthil Kumar Selvaraj <senthil.thecoder@gmail.com>
|
||||||
Senthil Kumaran <senthil@uthcode.com>
|
Senthil Kumaran <senthil@uthcode.com>
|
||||||
|
@ -1918,6 +1974,7 @@ Sergey Evstifeev <sergey.evstifeev@gmail.com>
|
||||||
Sergii Kabashniuk <skabashnyuk@codenvy.com>
|
Sergii Kabashniuk <skabashnyuk@codenvy.com>
|
||||||
Sergio Lopez <slp@redhat.com>
|
Sergio Lopez <slp@redhat.com>
|
||||||
Serhat Gülçiçek <serhat25@gmail.com>
|
Serhat Gülçiçek <serhat25@gmail.com>
|
||||||
|
Serhii Nakon <serhii.n@thescimus.com>
|
||||||
SeungUkLee <lsy931106@gmail.com>
|
SeungUkLee <lsy931106@gmail.com>
|
||||||
Sevki Hasirci <s@sevki.org>
|
Sevki Hasirci <s@sevki.org>
|
||||||
Shane Canon <scanon@lbl.gov>
|
Shane Canon <scanon@lbl.gov>
|
||||||
|
@ -1980,6 +2037,7 @@ Stanislav Bondarenko <stanislav.bondarenko@gmail.com>
|
||||||
Stanislav Levin <slev@altlinux.org>
|
Stanislav Levin <slev@altlinux.org>
|
||||||
Steeve Morin <steeve.morin@gmail.com>
|
Steeve Morin <steeve.morin@gmail.com>
|
||||||
Stefan Berger <stefanb@linux.vnet.ibm.com>
|
Stefan Berger <stefanb@linux.vnet.ibm.com>
|
||||||
|
Stefan Gehrig <stefan.gehrig.hn@googlemail.com>
|
||||||
Stefan J. Wernli <swernli@microsoft.com>
|
Stefan J. Wernli <swernli@microsoft.com>
|
||||||
Stefan Praszalowicz <stefan@greplin.com>
|
Stefan Praszalowicz <stefan@greplin.com>
|
||||||
Stefan S. <tronicum@user.github.com>
|
Stefan S. <tronicum@user.github.com>
|
||||||
|
@ -1987,6 +2045,7 @@ Stefan Scherer <stefan.scherer@docker.com>
|
||||||
Stefan Staudenmeyer <doerte@instana.com>
|
Stefan Staudenmeyer <doerte@instana.com>
|
||||||
Stefan Weil <sw@weilnetz.de>
|
Stefan Weil <sw@weilnetz.de>
|
||||||
Steffen Butzer <steffen.butzer@outlook.com>
|
Steffen Butzer <steffen.butzer@outlook.com>
|
||||||
|
Stephan Henningsen <stephan-henningsen@users.noreply.github.com>
|
||||||
Stephan Spindler <shutefan@gmail.com>
|
Stephan Spindler <shutefan@gmail.com>
|
||||||
Stephen Benjamin <stephen@redhat.com>
|
Stephen Benjamin <stephen@redhat.com>
|
||||||
Stephen Crosby <stevecrozz@gmail.com>
|
Stephen Crosby <stevecrozz@gmail.com>
|
||||||
|
@ -2188,6 +2247,7 @@ Vinod Kulkarni <vinod.kulkarni@gmail.com>
|
||||||
Vishal Doshi <vishal.doshi@gmail.com>
|
Vishal Doshi <vishal.doshi@gmail.com>
|
||||||
Vishnu Kannan <vishnuk@google.com>
|
Vishnu Kannan <vishnuk@google.com>
|
||||||
Vitaly Ostrosablin <vostrosablin@virtuozzo.com>
|
Vitaly Ostrosablin <vostrosablin@virtuozzo.com>
|
||||||
|
Vitor Anjos <bartier@users.noreply.github.com>
|
||||||
Vitor Monteiro <vmrmonteiro@gmail.com>
|
Vitor Monteiro <vmrmonteiro@gmail.com>
|
||||||
Vivek Agarwal <me@vivek.im>
|
Vivek Agarwal <me@vivek.im>
|
||||||
Vivek Dasgupta <vdasgupt@redhat.com>
|
Vivek Dasgupta <vdasgupt@redhat.com>
|
||||||
|
@ -2201,6 +2261,7 @@ VladimirAus <v_roudakov@yahoo.com>
|
||||||
Vladislav Kolesnikov <vkolesnikov@beget.ru>
|
Vladislav Kolesnikov <vkolesnikov@beget.ru>
|
||||||
Vlastimil Zeman <vlastimil.zeman@diffblue.com>
|
Vlastimil Zeman <vlastimil.zeman@diffblue.com>
|
||||||
Vojtech Vitek (V-Teq) <vvitek@redhat.com>
|
Vojtech Vitek (V-Teq) <vvitek@redhat.com>
|
||||||
|
voloder <110066198+voloder@users.noreply.github.com>
|
||||||
Walter Leibbrandt <github@wrl.co.za>
|
Walter Leibbrandt <github@wrl.co.za>
|
||||||
Walter Stanish <walter@pratyeka.org>
|
Walter Stanish <walter@pratyeka.org>
|
||||||
Wang Chao <chao.wang@ucloud.cn>
|
Wang Chao <chao.wang@ucloud.cn>
|
||||||
|
@ -2234,6 +2295,7 @@ Wenxuan Zhao <viz@linux.com>
|
||||||
Wenyu You <21551128@zju.edu.cn>
|
Wenyu You <21551128@zju.edu.cn>
|
||||||
Wenzhi Liang <wenzhi.liang@gmail.com>
|
Wenzhi Liang <wenzhi.liang@gmail.com>
|
||||||
Wes Morgan <cap10morgan@gmail.com>
|
Wes Morgan <cap10morgan@gmail.com>
|
||||||
|
Wesley Pettit <wppttt@amazon.com>
|
||||||
Wewang Xiaorenfine <wang.xiaoren@zte.com.cn>
|
Wewang Xiaorenfine <wang.xiaoren@zte.com.cn>
|
||||||
Wiktor Kwapisiewicz <wiktor@metacode.biz>
|
Wiktor Kwapisiewicz <wiktor@metacode.biz>
|
||||||
Will Dietz <w@wdtz.org>
|
Will Dietz <w@wdtz.org>
|
||||||
|
@ -2271,8 +2333,9 @@ Xiaoyu Zhang <zhang.xiaoyu33@zte.com.cn>
|
||||||
xichengliudui <1693291525@qq.com>
|
xichengliudui <1693291525@qq.com>
|
||||||
xiekeyang <xiekeyang@huawei.com>
|
xiekeyang <xiekeyang@huawei.com>
|
||||||
Ximo Guanter Gonzálbez <joaquin.guantergonzalbez@telefonica.com>
|
Ximo Guanter Gonzálbez <joaquin.guantergonzalbez@telefonica.com>
|
||||||
|
xin.li <xin.li@daocloud.io>
|
||||||
Xinbo Weng <xihuanbo_0521@zju.edu.cn>
|
Xinbo Weng <xihuanbo_0521@zju.edu.cn>
|
||||||
Xinfeng Liu <xinfeng.liu@gmail.com>
|
Xinfeng Liu <XinfengLiu@icloud.com>
|
||||||
Xinzi Zhou <imdreamrunner@gmail.com>
|
Xinzi Zhou <imdreamrunner@gmail.com>
|
||||||
Xiuming Chen <cc@cxm.cc>
|
Xiuming Chen <cc@cxm.cc>
|
||||||
Xuecong Liao <satorulogic@gmail.com>
|
Xuecong Liao <satorulogic@gmail.com>
|
||||||
|
@ -2282,6 +2345,7 @@ Yahya <ya7yaz@gmail.com>
|
||||||
yalpul <yalpul@gmail.com>
|
yalpul <yalpul@gmail.com>
|
||||||
YAMADA Tsuyoshi <tyamada@minimum2scp.org>
|
YAMADA Tsuyoshi <tyamada@minimum2scp.org>
|
||||||
Yamasaki Masahide <masahide.y@gmail.com>
|
Yamasaki Masahide <masahide.y@gmail.com>
|
||||||
|
Yamazaki Masashi <masi19bw@gmail.com>
|
||||||
Yan Feng <yanfeng2@huawei.com>
|
Yan Feng <yanfeng2@huawei.com>
|
||||||
Yan Zhu <yanzhu@alauda.io>
|
Yan Zhu <yanzhu@alauda.io>
|
||||||
Yang Bai <hamo.by@gmail.com>
|
Yang Bai <hamo.by@gmail.com>
|
||||||
|
@ -2337,6 +2401,7 @@ Zen Lin(Zhinan Lin) <linzhinan@huawei.com>
|
||||||
Zhang Kun <zkazure@gmail.com>
|
Zhang Kun <zkazure@gmail.com>
|
||||||
Zhang Wei <zhangwei555@huawei.com>
|
Zhang Wei <zhangwei555@huawei.com>
|
||||||
Zhang Wentao <zhangwentao234@huawei.com>
|
Zhang Wentao <zhangwentao234@huawei.com>
|
||||||
|
zhangguanzhang <zhangguanzhang@qq.com>
|
||||||
ZhangHang <stevezhang2014@gmail.com>
|
ZhangHang <stevezhang2014@gmail.com>
|
||||||
zhangxianwei <xianwei.zw@alibaba-inc.com>
|
zhangxianwei <xianwei.zw@alibaba-inc.com>
|
||||||
Zhenan Ye <21551168@zju.edu.cn>
|
Zhenan Ye <21551168@zju.edu.cn>
|
||||||
|
@ -2363,6 +2428,7 @@ Zuhayr Elahi <zuhayr.elahi@docker.com>
|
||||||
Zunayed Ali <zunayed@gmail.com>
|
Zunayed Ali <zunayed@gmail.com>
|
||||||
Álvaro Lázaro <alvaro.lazaro.g@gmail.com>
|
Álvaro Lázaro <alvaro.lazaro.g@gmail.com>
|
||||||
Átila Camurça Alves <camurca.home@gmail.com>
|
Átila Camurça Alves <camurca.home@gmail.com>
|
||||||
|
吴小白 <296015668@qq.com>
|
||||||
尹吉峰 <jifeng.yin@gmail.com>
|
尹吉峰 <jifeng.yin@gmail.com>
|
||||||
屈骏 <qujun@tiduyun.com>
|
屈骏 <qujun@tiduyun.com>
|
||||||
徐俊杰 <paco.xu@daocloud.io>
|
徐俊杰 <paco.xu@daocloud.io>
|
||||||
|
|
|
@ -72,7 +72,7 @@ anybody starts working on it.
|
||||||
We are always thrilled to receive pull requests. We do our best to process them
|
We are always thrilled to receive pull requests. We do our best to process them
|
||||||
quickly. If your pull request is not accepted on the first try,
|
quickly. If your pull request is not accepted on the first try,
|
||||||
don't get discouraged! Our contributor's guide explains [the review process we
|
don't get discouraged! Our contributor's guide explains [the review process we
|
||||||
use for simple changes](https://docs.docker.com/opensource/workflow/make-a-contribution/).
|
use for simple changes](https://docs.docker.com/contribute/overview/).
|
||||||
|
|
||||||
### Design and cleanup proposals
|
### Design and cleanup proposals
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ the contributors guide.
|
||||||
<td>
|
<td>
|
||||||
<p>
|
<p>
|
||||||
Register for the Docker Community Slack at
|
Register for the Docker Community Slack at
|
||||||
<a href="https://dockr.ly/slack" target="_blank">https://dockr.ly/slack</a>.
|
<a href="https://dockr.ly/comm-slack" target="_blank">https://dockr.ly/comm-slack</a>.
|
||||||
We use the #moby-project channel for general discussion, and there are separate channels for other Moby projects such as #containerd.
|
We use the #moby-project channel for general discussion, and there are separate channels for other Moby projects such as #containerd.
|
||||||
</p>
|
</p>
|
||||||
</td>
|
</td>
|
||||||
|
@ -309,36 +309,6 @@ Don't forget: being a maintainer is a time investment. Make sure you
|
||||||
will have time to make yourself available. You don't have to be a
|
will have time to make yourself available. You don't have to be a
|
||||||
maintainer to make a difference on the project!
|
maintainer to make a difference on the project!
|
||||||
|
|
||||||
### Manage issues and pull requests using the Derek bot
|
|
||||||
|
|
||||||
If you want to help label, assign, close or reopen issues or pull requests
|
|
||||||
without commit rights, ask a maintainer to add your Github handle to the
|
|
||||||
`.DEREK.yml` file. [Derek](https://github.com/alexellis/derek) is a bot that extends
|
|
||||||
Github's user permissions to help non-committers to manage issues and pull requests simply by commenting.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
* Labels
|
|
||||||
|
|
||||||
```
|
|
||||||
Derek add label: kind/question
|
|
||||||
Derek remove label: status/claimed
|
|
||||||
```
|
|
||||||
|
|
||||||
* Assign work
|
|
||||||
|
|
||||||
```
|
|
||||||
Derek assign: username
|
|
||||||
Derek unassign: me
|
|
||||||
```
|
|
||||||
|
|
||||||
* Manage issues and PRs
|
|
||||||
|
|
||||||
```
|
|
||||||
Derek close
|
|
||||||
Derek reopen
|
|
||||||
```
|
|
||||||
|
|
||||||
## Moby community guidelines
|
## Moby community guidelines
|
||||||
|
|
||||||
We want to keep the Moby community awesome, growing and collaborative. We need
|
We want to keep the Moby community awesome, growing and collaborative. We need
|
||||||
|
@ -452,6 +422,6 @@ The rules:
|
||||||
guidelines. Since you've read all the rules, you now know that.
|
guidelines. Since you've read all the rules, you now know that.
|
||||||
|
|
||||||
If you are having trouble getting into the mood of idiomatic Go, we recommend
|
If you are having trouble getting into the mood of idiomatic Go, we recommend
|
||||||
reading through [Effective Go](https://golang.org/doc/effective_go.html). The
|
reading through [Effective Go](https://go.dev/doc/effective_go). The
|
||||||
[Go Blog](https://blog.golang.org) is also a great resource. Drinking the
|
[Go Blog](https://go.dev/blog/) is also a great resource. Drinking the
|
||||||
kool-aid is a lot easier than going thirsty.
|
kool-aid is a lot easier than going thirsty.
|
||||||
|
|
257
Dockerfile
257
Dockerfile
|
@ -1,17 +1,35 @@
|
||||||
# syntax=docker/dockerfile:1
|
# syntax=docker/dockerfile:1.7
|
||||||
|
|
||||||
ARG GO_VERSION=1.20.13
|
ARG GO_VERSION=1.21.9
|
||||||
ARG BASE_DEBIAN_DISTRO="bullseye"
|
ARG BASE_DEBIAN_DISTRO="bookworm"
|
||||||
ARG GOLANG_IMAGE="golang:${GO_VERSION}-${BASE_DEBIAN_DISTRO}"
|
ARG GOLANG_IMAGE="golang:${GO_VERSION}-${BASE_DEBIAN_DISTRO}"
|
||||||
ARG XX_VERSION=1.2.1
|
ARG XX_VERSION=1.4.0
|
||||||
|
|
||||||
ARG VPNKIT_VERSION=0.5.0
|
ARG VPNKIT_VERSION=0.5.0
|
||||||
ARG DOCKERCLI_VERSION=v17.06.2-ce
|
|
||||||
|
ARG DOCKERCLI_REPOSITORY="https://github.com/docker/cli.git"
|
||||||
|
ARG DOCKERCLI_VERSION=v26.0.0
|
||||||
|
# cli version used for integration-cli tests
|
||||||
|
ARG DOCKERCLI_INTEGRATION_REPOSITORY="https://github.com/docker/cli.git"
|
||||||
|
ARG DOCKERCLI_INTEGRATION_VERSION=v17.06.2-ce
|
||||||
|
ARG BUILDX_VERSION=0.13.1
|
||||||
|
ARG COMPOSE_VERSION=v2.25.0
|
||||||
|
|
||||||
ARG SYSTEMD="false"
|
ARG SYSTEMD="false"
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
|
||||||
ARG DOCKER_STATIC=1
|
ARG DOCKER_STATIC=1
|
||||||
|
|
||||||
|
# REGISTRY_VERSION specifies the version of the registry to download from
|
||||||
|
# https://hub.docker.com/r/distribution/distribution. This version of
|
||||||
|
# the registry is used to test schema 2 manifests. Generally, the version
|
||||||
|
# specified here should match a current release.
|
||||||
|
ARG REGISTRY_VERSION=2.8.3
|
||||||
|
|
||||||
|
# delve is currently only supported on linux/amd64 and linux/arm64;
|
||||||
|
# https://github.com/go-delve/delve/blob/v1.8.1/pkg/proc/native/support_sentinel.go#L1-L6
|
||||||
|
ARG DELVE_SUPPORTED=${TARGETPLATFORM#linux/amd64} DELVE_SUPPORTED=${DELVE_SUPPORTED#linux/arm64}
|
||||||
|
ARG DELVE_SUPPORTED=${DELVE_SUPPORTED:+"unsupported"}
|
||||||
|
ARG DELVE_SUPPORTED=${DELVE_SUPPORTED:-"supported"}
|
||||||
|
|
||||||
# cross compilation helper
|
# cross compilation helper
|
||||||
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
|
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
|
||||||
|
|
||||||
|
@ -26,21 +44,19 @@ COPY --from=build-dummy /build /build
|
||||||
FROM --platform=$BUILDPLATFORM ${GOLANG_IMAGE} AS base
|
FROM --platform=$BUILDPLATFORM ${GOLANG_IMAGE} AS base
|
||||||
COPY --from=xx / /
|
COPY --from=xx / /
|
||||||
RUN echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
|
RUN echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
|
||||||
ARG APT_MIRROR
|
|
||||||
RUN test -n "$APT_MIRROR" && sed -ri "s/(httpredir|deb|security).debian.org/${APT_MIRROR}/g" /etc/apt/sources.list || true
|
|
||||||
ARG DEBIAN_FRONTEND
|
|
||||||
RUN apt-get update && apt-get install --no-install-recommends -y file
|
RUN apt-get update && apt-get install --no-install-recommends -y file
|
||||||
ENV GO111MODULE=off
|
ENV GO111MODULE=off
|
||||||
|
ENV GOTOOLCHAIN=local
|
||||||
|
|
||||||
FROM base AS criu
|
FROM base AS criu
|
||||||
ARG DEBIAN_FRONTEND
|
|
||||||
ADD --chmod=0644 https://download.opensuse.org/repositories/devel:/tools:/criu/Debian_11/Release.key /etc/apt/trusted.gpg.d/criu.gpg.asc
|
ADD --chmod=0644 https://download.opensuse.org/repositories/devel:/tools:/criu/Debian_11/Release.key /etc/apt/trusted.gpg.d/criu.gpg.asc
|
||||||
RUN --mount=type=cache,sharing=locked,id=moby-criu-aptlib,target=/var/lib/apt \
|
RUN --mount=type=cache,sharing=locked,id=moby-criu-aptlib,target=/var/lib/apt \
|
||||||
--mount=type=cache,sharing=locked,id=moby-criu-aptcache,target=/var/cache/apt \
|
--mount=type=cache,sharing=locked,id=moby-criu-aptcache,target=/var/cache/apt \
|
||||||
echo 'deb https://download.opensuse.org/repositories/devel:/tools:/criu/Debian_11/ /' > /etc/apt/sources.list.d/criu.list \
|
echo 'deb https://download.opensuse.org/repositories/devel:/tools:/criu/Debian_12/ /' > /etc/apt/sources.list.d/criu.list \
|
||||||
&& apt-get update \
|
&& apt-get update \
|
||||||
&& apt-get install -y --no-install-recommends criu \
|
&& apt-get install -y --no-install-recommends criu \
|
||||||
&& install -D /usr/sbin/criu /build/criu
|
&& install -D /usr/sbin/criu /build/criu \
|
||||||
|
&& /build/criu --version
|
||||||
|
|
||||||
# registry
|
# registry
|
||||||
FROM base AS registry-src
|
FROM base AS registry-src
|
||||||
|
@ -49,11 +65,7 @@ RUN git init . && git remote add origin "https://github.com/distribution/distrib
|
||||||
|
|
||||||
FROM base AS registry
|
FROM base AS registry
|
||||||
WORKDIR /go/src/github.com/docker/distribution
|
WORKDIR /go/src/github.com/docker/distribution
|
||||||
# REGISTRY_VERSION specifies the version of the registry to build and install
|
|
||||||
# from the https://github.com/docker/distribution repository. This version of
|
|
||||||
# the registry is used to test both schema 1 and schema 2 manifests. Generally,
|
|
||||||
# the version specified here should match a current release.
|
|
||||||
ARG REGISTRY_VERSION=v2.3.0
|
|
||||||
# REGISTRY_VERSION_SCHEMA1 specifies the version of the registry to build and
|
# REGISTRY_VERSION_SCHEMA1 specifies the version of the registry to build and
|
||||||
# install from the https://github.com/docker/distribution repository. This is
|
# install from the https://github.com/docker/distribution repository. This is
|
||||||
# an older (pre v2.3.0) version of the registry that only supports schema1
|
# an older (pre v2.3.0) version of the registry that only supports schema1
|
||||||
|
@ -66,11 +78,10 @@ RUN --mount=from=registry-src,src=/usr/src/registry,rw \
|
||||||
--mount=type=cache,target=/go/pkg/mod \
|
--mount=type=cache,target=/go/pkg/mod \
|
||||||
--mount=type=tmpfs,target=/go/src <<EOT
|
--mount=type=tmpfs,target=/go/src <<EOT
|
||||||
set -ex
|
set -ex
|
||||||
git fetch -q --depth 1 origin "${REGISTRY_VERSION}" +refs/tags/*:refs/tags/*
|
|
||||||
git checkout -q FETCH_HEAD
|
|
||||||
export GOPATH="/go/src/github.com/docker/distribution/Godeps/_workspace:$GOPATH"
|
export GOPATH="/go/src/github.com/docker/distribution/Godeps/_workspace:$GOPATH"
|
||||||
CGO_ENABLED=0 xx-go build -o /build/registry-v2 -v ./cmd/registry
|
# Make the /build directory no matter what so that it doesn't fail on arm64 or
|
||||||
xx-verify /build/registry-v2
|
# any other platform where we don't build this registry
|
||||||
|
mkdir /build
|
||||||
case $TARGETPLATFORM in
|
case $TARGETPLATFORM in
|
||||||
linux/amd64|linux/arm/v7|linux/ppc64le|linux/s390x)
|
linux/amd64|linux/arm/v7|linux/ppc64le|linux/s390x)
|
||||||
git fetch -q --depth 1 origin "${REGISTRY_VERSION_SCHEMA1}" +refs/tags/*:refs/tags/*
|
git fetch -q --depth 1 origin "${REGISTRY_VERSION_SCHEMA1}" +refs/tags/*:refs/tags/*
|
||||||
|
@ -81,6 +92,9 @@ RUN --mount=from=registry-src,src=/usr/src/registry,rw \
|
||||||
esac
|
esac
|
||||||
EOT
|
EOT
|
||||||
|
|
||||||
|
FROM distribution/distribution:$REGISTRY_VERSION AS registry-v2
|
||||||
|
RUN mkdir /build && mv /bin/registry /build/registry-v2
|
||||||
|
|
||||||
# go-swagger
|
# go-swagger
|
||||||
FROM base AS swagger-src
|
FROM base AS swagger-src
|
||||||
WORKDIR /usr/src/swagger
|
WORKDIR /usr/src/swagger
|
||||||
|
@ -108,7 +122,6 @@ EOT
|
||||||
# See also frozenImages in "testutil/environment/protect.go" (which needs to
|
# See also frozenImages in "testutil/environment/protect.go" (which needs to
|
||||||
# be updated when adding images to this list)
|
# be updated when adding images to this list)
|
||||||
FROM debian:${BASE_DEBIAN_DISTRO} AS frozen-images
|
FROM debian:${BASE_DEBIAN_DISTRO} AS frozen-images
|
||||||
ARG DEBIAN_FRONTEND
|
|
||||||
RUN --mount=type=cache,sharing=locked,id=moby-frozen-images-aptlib,target=/var/lib/apt \
|
RUN --mount=type=cache,sharing=locked,id=moby-frozen-images-aptlib,target=/var/lib/apt \
|
||||||
--mount=type=cache,sharing=locked,id=moby-frozen-images-aptcache,target=/var/cache/apt \
|
--mount=type=cache,sharing=locked,id=moby-frozen-images-aptcache,target=/var/cache/apt \
|
||||||
apt-get update && apt-get install -y --no-install-recommends \
|
apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
@ -122,7 +135,7 @@ ARG TARGETVARIANT
|
||||||
RUN /download-frozen-image-v2.sh /build \
|
RUN /download-frozen-image-v2.sh /build \
|
||||||
busybox:latest@sha256:95cf004f559831017cdf4628aaf1bb30133677be8702a8c5f2994629f637a209 \
|
busybox:latest@sha256:95cf004f559831017cdf4628aaf1bb30133677be8702a8c5f2994629f637a209 \
|
||||||
busybox:glibc@sha256:1f81263701cddf6402afe9f33fca0266d9fff379e59b1748f33d3072da71ee85 \
|
busybox:glibc@sha256:1f81263701cddf6402afe9f33fca0266d9fff379e59b1748f33d3072da71ee85 \
|
||||||
debian:bullseye-slim@sha256:dacf278785a4daa9de07596ec739dbc07131e189942772210709c5c0777e8437 \
|
debian:bookworm-slim@sha256:2bc5c236e9b262645a323e9088dfa3bb1ecb16cc75811daf40a23a824d665be9 \
|
||||||
hello-world:latest@sha256:d58e752213a51785838f9eed2b7a498ffa1cb3aa7f946dda11af39286c3db9a9 \
|
hello-world:latest@sha256:d58e752213a51785838f9eed2b7a498ffa1cb3aa7f946dda11af39286c3db9a9 \
|
||||||
arm32v7/hello-world:latest@sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1
|
arm32v7/hello-world:latest@sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1
|
||||||
|
|
||||||
|
@ -134,10 +147,10 @@ RUN git init . && git remote add origin "https://github.com/go-delve/delve.git"
|
||||||
# from the https://github.com/go-delve/delve repository.
|
# from the https://github.com/go-delve/delve repository.
|
||||||
# It can be used to run Docker with a possibility of
|
# It can be used to run Docker with a possibility of
|
||||||
# attaching debugger to it.
|
# attaching debugger to it.
|
||||||
ARG DELVE_VERSION=v1.20.1
|
ARG DELVE_VERSION=v1.21.1
|
||||||
RUN git fetch -q --depth 1 origin "${DELVE_VERSION}" +refs/tags/*:refs/tags/* && git checkout -q FETCH_HEAD
|
RUN git fetch -q --depth 1 origin "${DELVE_VERSION}" +refs/tags/*:refs/tags/* && git checkout -q FETCH_HEAD
|
||||||
|
|
||||||
FROM base AS delve-build
|
FROM base AS delve-supported
|
||||||
WORKDIR /usr/src/delve
|
WORKDIR /usr/src/delve
|
||||||
ARG TARGETPLATFORM
|
ARG TARGETPLATFORM
|
||||||
RUN --mount=from=delve-src,src=/usr/src/delve,rw \
|
RUN --mount=from=delve-src,src=/usr/src/delve,rw \
|
||||||
|
@ -148,16 +161,8 @@ RUN --mount=from=delve-src,src=/usr/src/delve,rw \
|
||||||
xx-verify /build/dlv
|
xx-verify /build/dlv
|
||||||
EOT
|
EOT
|
||||||
|
|
||||||
# delve is currently only supported on linux/amd64 and linux/arm64;
|
FROM binary-dummy AS delve-unsupported
|
||||||
# https://github.com/go-delve/delve/blob/v1.8.1/pkg/proc/native/support_sentinel.go#L1-L6
|
FROM delve-${DELVE_SUPPORTED} AS delve
|
||||||
FROM binary-dummy AS delve-windows
|
|
||||||
FROM binary-dummy AS delve-linux-arm
|
|
||||||
FROM binary-dummy AS delve-linux-ppc64le
|
|
||||||
FROM binary-dummy AS delve-linux-s390x
|
|
||||||
FROM delve-build AS delve-linux-amd64
|
|
||||||
FROM delve-build AS delve-linux-arm64
|
|
||||||
FROM delve-linux-${TARGETARCH} AS delve-linux
|
|
||||||
FROM delve-${TARGETOS} AS delve
|
|
||||||
|
|
||||||
FROM base AS tomll
|
FROM base AS tomll
|
||||||
# GOTOML_VERSION specifies the version of the tomll binary to build and install
|
# GOTOML_VERSION specifies the version of the tomll binary to build and install
|
||||||
|
@ -174,7 +179,7 @@ RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||||
|
|
||||||
FROM base AS gowinres
|
FROM base AS gowinres
|
||||||
# GOWINRES_VERSION defines go-winres tool version
|
# GOWINRES_VERSION defines go-winres tool version
|
||||||
ARG GOWINRES_VERSION=v0.3.0
|
ARG GOWINRES_VERSION=v0.3.1
|
||||||
RUN --mount=type=cache,target=/root/.cache/go-build \
|
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||||
--mount=type=cache,target=/go/pkg/mod \
|
--mount=type=cache,target=/go/pkg/mod \
|
||||||
GOBIN=/build/ GO111MODULE=on go install "github.com/tc-hib/go-winres@${GOWINRES_VERSION}" \
|
GOBIN=/build/ GO111MODULE=on go install "github.com/tc-hib/go-winres@${GOWINRES_VERSION}" \
|
||||||
|
@ -191,17 +196,19 @@ RUN git init . && git remote add origin "https://github.com/containerd/container
|
||||||
# When updating the binary version you may also need to update the vendor
|
# When updating the binary version you may also need to update the vendor
|
||||||
# version to pick up bug fixes or new APIs, however, usually the Go packages
|
# version to pick up bug fixes or new APIs, however, usually the Go packages
|
||||||
# are built from a commit from the master branch.
|
# are built from a commit from the master branch.
|
||||||
ARG CONTAINERD_VERSION=v1.6.28
|
ARG CONTAINERD_VERSION=v1.7.15
|
||||||
RUN git fetch -q --depth 1 origin "${CONTAINERD_VERSION}" +refs/tags/*:refs/tags/* && git checkout -q FETCH_HEAD
|
RUN git fetch -q --depth 1 origin "${CONTAINERD_VERSION}" +refs/tags/*:refs/tags/* && git checkout -q FETCH_HEAD
|
||||||
|
|
||||||
FROM base AS containerd-build
|
FROM base AS containerd-build
|
||||||
WORKDIR /go/src/github.com/containerd/containerd
|
WORKDIR /go/src/github.com/containerd/containerd
|
||||||
ARG DEBIAN_FRONTEND
|
|
||||||
ARG TARGETPLATFORM
|
ARG TARGETPLATFORM
|
||||||
RUN --mount=type=cache,sharing=locked,id=moby-containerd-aptlib,target=/var/lib/apt \
|
RUN --mount=type=cache,sharing=locked,id=moby-containerd-aptlib,target=/var/lib/apt \
|
||||||
--mount=type=cache,sharing=locked,id=moby-containerd-aptcache,target=/var/cache/apt \
|
--mount=type=cache,sharing=locked,id=moby-containerd-aptcache,target=/var/cache/apt \
|
||||||
apt-get update && xx-apt-get install -y --no-install-recommends \
|
apt-get update && xx-apt-get install -y --no-install-recommends \
|
||||||
gcc libbtrfs-dev libsecret-1-dev
|
gcc \
|
||||||
|
libbtrfs-dev \
|
||||||
|
libsecret-1-dev \
|
||||||
|
pkg-config
|
||||||
ARG DOCKER_STATIC
|
ARG DOCKER_STATIC
|
||||||
RUN --mount=from=containerd-src,src=/usr/src/containerd,rw \
|
RUN --mount=from=containerd-src,src=/usr/src/containerd,rw \
|
||||||
--mount=type=cache,target=/root/.cache/go-build,id=containerd-build-$TARGETPLATFORM <<EOT
|
--mount=type=cache,target=/root/.cache/go-build,id=containerd-build-$TARGETPLATFORM <<EOT
|
||||||
|
@ -236,40 +243,41 @@ RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||||
&& /build/gotestsum --version
|
&& /build/gotestsum --version
|
||||||
|
|
||||||
FROM base AS shfmt
|
FROM base AS shfmt
|
||||||
ARG SHFMT_VERSION=v3.6.0
|
ARG SHFMT_VERSION=v3.8.0
|
||||||
RUN --mount=type=cache,target=/root/.cache/go-build \
|
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||||
--mount=type=cache,target=/go/pkg/mod \
|
--mount=type=cache,target=/go/pkg/mod \
|
||||||
GOBIN=/build/ GO111MODULE=on go install "mvdan.cc/sh/v3/cmd/shfmt@${SHFMT_VERSION}" \
|
GOBIN=/build/ GO111MODULE=on go install "mvdan.cc/sh/v3/cmd/shfmt@${SHFMT_VERSION}" \
|
||||||
&& /build/shfmt --version
|
&& /build/shfmt --version
|
||||||
|
|
||||||
# dockercli
|
FROM base AS gopls
|
||||||
FROM base AS dockercli-src
|
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||||
WORKDIR /tmp/dockercli
|
--mount=type=cache,target=/go/pkg/mod \
|
||||||
RUN git init . && git remote add origin "https://github.com/docker/cli.git"
|
GOBIN=/build/ GO111MODULE=on go install "golang.org/x/tools/gopls@latest" \
|
||||||
ARG DOCKERCLI_VERSION
|
&& /build/gopls version
|
||||||
RUN git fetch -q --depth 1 origin "${DOCKERCLI_VERSION}" +refs/tags/*:refs/tags/* && git checkout -q FETCH_HEAD
|
|
||||||
RUN [ -d ./components/cli ] && mv ./components/cli /usr/src/dockercli || mv /tmp/dockercli /usr/src/dockercli
|
|
||||||
WORKDIR /usr/src/dockercli
|
|
||||||
|
|
||||||
FROM base AS dockercli
|
FROM base AS dockercli
|
||||||
WORKDIR /go/src/github.com/docker/cli
|
WORKDIR /go/src/github.com/docker/cli
|
||||||
|
ARG DOCKERCLI_REPOSITORY
|
||||||
ARG DOCKERCLI_VERSION
|
ARG DOCKERCLI_VERSION
|
||||||
ARG DOCKERCLI_CHANNEL=stable
|
|
||||||
ARG TARGETPLATFORM
|
ARG TARGETPLATFORM
|
||||||
RUN xx-apt-get install -y --no-install-recommends gcc libc6-dev
|
RUN --mount=source=hack/dockerfile/cli.sh,target=/download-or-build-cli.sh \
|
||||||
RUN --mount=from=dockercli-src,src=/usr/src/dockercli,rw \
|
--mount=type=cache,id=dockercli-git-$TARGETPLATFORM,sharing=locked,target=./.git \
|
||||||
--mount=type=cache,target=/root/.cache/go-build,id=dockercli-build-$TARGETPLATFORM <<EOT
|
--mount=type=cache,target=/root/.cache/go-build,id=dockercli-build-$TARGETPLATFORM \
|
||||||
set -e
|
rm -f ./.git/*.lock \
|
||||||
DOWNLOAD_URL="https://download.docker.com/linux/static/${DOCKERCLI_CHANNEL}/$(xx-info march)/docker-${DOCKERCLI_VERSION#v}.tgz"
|
&& /download-or-build-cli.sh ${DOCKERCLI_VERSION} ${DOCKERCLI_REPOSITORY} /build \
|
||||||
if curl --head --silent --fail "${DOWNLOAD_URL}" 1>/dev/null 2>&1; then
|
&& /build/docker --version
|
||||||
mkdir /build
|
|
||||||
curl -Ls "${DOWNLOAD_URL}" | tar -xz docker/docker
|
FROM base AS dockercli-integration
|
||||||
mv docker/docker /build/docker
|
WORKDIR /go/src/github.com/docker/cli
|
||||||
else
|
ARG DOCKERCLI_INTEGRATION_REPOSITORY
|
||||||
CGO_ENABLED=0 xx-go build -o /build/docker ./cmd/docker
|
ARG DOCKERCLI_INTEGRATION_VERSION
|
||||||
fi
|
ARG TARGETPLATFORM
|
||||||
xx-verify /build/docker
|
RUN --mount=source=hack/dockerfile/cli.sh,target=/download-or-build-cli.sh \
|
||||||
EOT
|
--mount=type=cache,id=dockercli-git-$TARGETPLATFORM,sharing=locked,target=./.git \
|
||||||
|
--mount=type=cache,target=/root/.cache/go-build,id=dockercli-build-$TARGETPLATFORM \
|
||||||
|
rm -f ./.git/*.lock \
|
||||||
|
&& /download-or-build-cli.sh ${DOCKERCLI_INTEGRATION_VERSION} ${DOCKERCLI_INTEGRATION_REPOSITORY} /build \
|
||||||
|
&& /build/docker --version
|
||||||
|
|
||||||
# runc
|
# runc
|
||||||
FROM base AS runc-src
|
FROM base AS runc-src
|
||||||
|
@ -284,12 +292,15 @@ RUN git fetch -q --depth 1 origin "${RUNC_VERSION}" +refs/tags/*:refs/tags/* &&
|
||||||
|
|
||||||
FROM base AS runc-build
|
FROM base AS runc-build
|
||||||
WORKDIR /go/src/github.com/opencontainers/runc
|
WORKDIR /go/src/github.com/opencontainers/runc
|
||||||
ARG DEBIAN_FRONTEND
|
|
||||||
ARG TARGETPLATFORM
|
ARG TARGETPLATFORM
|
||||||
RUN --mount=type=cache,sharing=locked,id=moby-runc-aptlib,target=/var/lib/apt \
|
RUN --mount=type=cache,sharing=locked,id=moby-runc-aptlib,target=/var/lib/apt \
|
||||||
--mount=type=cache,sharing=locked,id=moby-runc-aptcache,target=/var/cache/apt \
|
--mount=type=cache,sharing=locked,id=moby-runc-aptcache,target=/var/cache/apt \
|
||||||
apt-get update && xx-apt-get install -y --no-install-recommends \
|
apt-get update && xx-apt-get install -y --no-install-recommends \
|
||||||
dpkg-dev gcc libc6-dev libseccomp-dev
|
dpkg-dev \
|
||||||
|
gcc \
|
||||||
|
libc6-dev \
|
||||||
|
libseccomp-dev \
|
||||||
|
pkg-config
|
||||||
ARG DOCKER_STATIC
|
ARG DOCKER_STATIC
|
||||||
RUN --mount=from=runc-src,src=/usr/src/runc,rw \
|
RUN --mount=from=runc-src,src=/usr/src/runc,rw \
|
||||||
--mount=type=cache,target=/root/.cache/go-build,id=runc-build-$TARGETPLATFORM <<EOT
|
--mount=type=cache,target=/root/.cache/go-build,id=runc-build-$TARGETPLATFORM <<EOT
|
||||||
|
@ -316,7 +327,6 @@ RUN git fetch -q --depth 1 origin "${TINI_VERSION}" +refs/tags/*:refs/tags/* &&
|
||||||
|
|
||||||
FROM base AS tini-build
|
FROM base AS tini-build
|
||||||
WORKDIR /go/src/github.com/krallin/tini
|
WORKDIR /go/src/github.com/krallin/tini
|
||||||
ARG DEBIAN_FRONTEND
|
|
||||||
RUN --mount=type=cache,sharing=locked,id=moby-tini-aptlib,target=/var/lib/apt \
|
RUN --mount=type=cache,sharing=locked,id=moby-tini-aptlib,target=/var/lib/apt \
|
||||||
--mount=type=cache,sharing=locked,id=moby-tini-aptcache,target=/var/cache/apt \
|
--mount=type=cache,sharing=locked,id=moby-tini-aptcache,target=/var/cache/apt \
|
||||||
apt-get update && apt-get install -y --no-install-recommends cmake
|
apt-get update && apt-get install -y --no-install-recommends cmake
|
||||||
|
@ -324,7 +334,9 @@ ARG TARGETPLATFORM
|
||||||
RUN --mount=type=cache,sharing=locked,id=moby-tini-aptlib,target=/var/lib/apt \
|
RUN --mount=type=cache,sharing=locked,id=moby-tini-aptlib,target=/var/lib/apt \
|
||||||
--mount=type=cache,sharing=locked,id=moby-tini-aptcache,target=/var/cache/apt \
|
--mount=type=cache,sharing=locked,id=moby-tini-aptcache,target=/var/cache/apt \
|
||||||
xx-apt-get install -y --no-install-recommends \
|
xx-apt-get install -y --no-install-recommends \
|
||||||
gcc libc6-dev
|
gcc \
|
||||||
|
libc6-dev \
|
||||||
|
pkg-config
|
||||||
RUN --mount=from=tini-src,src=/usr/src/tini,rw \
|
RUN --mount=from=tini-src,src=/usr/src/tini,rw \
|
||||||
--mount=type=cache,target=/root/.cache/go-build,id=tini-build-$TARGETPLATFORM <<EOT
|
--mount=type=cache,target=/root/.cache/go-build,id=tini-build-$TARGETPLATFORM <<EOT
|
||||||
set -e
|
set -e
|
||||||
|
@ -343,18 +355,19 @@ FROM tini-${TARGETOS} AS tini
|
||||||
FROM base AS rootlesskit-src
|
FROM base AS rootlesskit-src
|
||||||
WORKDIR /usr/src/rootlesskit
|
WORKDIR /usr/src/rootlesskit
|
||||||
RUN git init . && git remote add origin "https://github.com/rootless-containers/rootlesskit.git"
|
RUN git init . && git remote add origin "https://github.com/rootless-containers/rootlesskit.git"
|
||||||
# When updating, also update rootlesskit commit in vendor.mod accordingly.
|
# When updating, also update vendor.mod and hack/dockerfile/install/rootlesskit.installer accordingly.
|
||||||
ARG ROOTLESSKIT_VERSION=v1.1.0
|
ARG ROOTLESSKIT_VERSION=v2.0.2
|
||||||
RUN git fetch -q --depth 1 origin "${ROOTLESSKIT_VERSION}" +refs/tags/*:refs/tags/* && git checkout -q FETCH_HEAD
|
RUN git fetch -q --depth 1 origin "${ROOTLESSKIT_VERSION}" +refs/tags/*:refs/tags/* && git checkout -q FETCH_HEAD
|
||||||
|
|
||||||
FROM base AS rootlesskit-build
|
FROM base AS rootlesskit-build
|
||||||
WORKDIR /go/src/github.com/rootless-containers/rootlesskit
|
WORKDIR /go/src/github.com/rootless-containers/rootlesskit
|
||||||
ARG DEBIAN_FRONTEND
|
|
||||||
ARG TARGETPLATFORM
|
ARG TARGETPLATFORM
|
||||||
RUN --mount=type=cache,sharing=locked,id=moby-rootlesskit-aptlib,target=/var/lib/apt \
|
RUN --mount=type=cache,sharing=locked,id=moby-rootlesskit-aptlib,target=/var/lib/apt \
|
||||||
--mount=type=cache,sharing=locked,id=moby-rootlesskit-aptcache,target=/var/cache/apt \
|
--mount=type=cache,sharing=locked,id=moby-rootlesskit-aptcache,target=/var/cache/apt \
|
||||||
apt-get update && xx-apt-get install -y --no-install-recommends \
|
apt-get update && xx-apt-get install -y --no-install-recommends \
|
||||||
gcc libc6-dev
|
gcc \
|
||||||
|
libc6-dev \
|
||||||
|
pkg-config
|
||||||
ENV GO111MODULE=on
|
ENV GO111MODULE=on
|
||||||
ARG DOCKER_STATIC
|
ARG DOCKER_STATIC
|
||||||
RUN --mount=from=rootlesskit-src,src=/usr/src/rootlesskit,rw \
|
RUN --mount=from=rootlesskit-src,src=/usr/src/rootlesskit,rw \
|
||||||
|
@ -367,15 +380,15 @@ RUN --mount=from=rootlesskit-src,src=/usr/src/rootlesskit,rw \
|
||||||
xx-go build -o /build/rootlesskit-docker-proxy -ldflags="$([ "$DOCKER_STATIC" != "1" ] && echo "-linkmode=external")" ./cmd/rootlesskit-docker-proxy
|
xx-go build -o /build/rootlesskit-docker-proxy -ldflags="$([ "$DOCKER_STATIC" != "1" ] && echo "-linkmode=external")" ./cmd/rootlesskit-docker-proxy
|
||||||
xx-verify $([ "$DOCKER_STATIC" = "1" ] && echo "--static") /build/rootlesskit-docker-proxy
|
xx-verify $([ "$DOCKER_STATIC" = "1" ] && echo "--static") /build/rootlesskit-docker-proxy
|
||||||
EOT
|
EOT
|
||||||
COPY ./contrib/dockerd-rootless.sh /build/
|
COPY --link ./contrib/dockerd-rootless.sh /build/
|
||||||
COPY ./contrib/dockerd-rootless-setuptool.sh /build/
|
COPY --link ./contrib/dockerd-rootless-setuptool.sh /build/
|
||||||
|
|
||||||
FROM rootlesskit-build AS rootlesskit-linux
|
FROM rootlesskit-build AS rootlesskit-linux
|
||||||
FROM binary-dummy AS rootlesskit-windows
|
FROM binary-dummy AS rootlesskit-windows
|
||||||
FROM rootlesskit-${TARGETOS} AS rootlesskit
|
FROM rootlesskit-${TARGETOS} AS rootlesskit
|
||||||
|
|
||||||
FROM base AS crun
|
FROM base AS crun
|
||||||
ARG CRUN_VERSION=1.4.5
|
ARG CRUN_VERSION=1.12
|
||||||
RUN --mount=type=cache,sharing=locked,id=moby-crun-aptlib,target=/var/lib/apt \
|
RUN --mount=type=cache,sharing=locked,id=moby-crun-aptlib,target=/var/lib/apt \
|
||||||
--mount=type=cache,sharing=locked,id=moby-crun-aptcache,target=/var/cache/apt \
|
--mount=type=cache,sharing=locked,id=moby-crun-aptcache,target=/var/cache/apt \
|
||||||
apt-get update && apt-get install -y --no-install-recommends \
|
apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
@ -422,7 +435,11 @@ RUN git fetch -q --depth 1 origin "${CONTAINERUTILITY_VERSION}" +refs/tags/*:ref
|
||||||
FROM base AS containerutil-build
|
FROM base AS containerutil-build
|
||||||
WORKDIR /usr/src/containerutil
|
WORKDIR /usr/src/containerutil
|
||||||
ARG TARGETPLATFORM
|
ARG TARGETPLATFORM
|
||||||
RUN xx-apt-get install -y --no-install-recommends gcc g++ libc6-dev
|
RUN xx-apt-get install -y --no-install-recommends \
|
||||||
|
gcc \
|
||||||
|
g++ \
|
||||||
|
libc6-dev \
|
||||||
|
pkg-config
|
||||||
RUN --mount=from=containerutil-src,src=/usr/src/containerutil,rw \
|
RUN --mount=from=containerutil-src,src=/usr/src/containerutil,rw \
|
||||||
--mount=type=cache,target=/root/.cache/go-build,id=containerutil-build-$TARGETPLATFORM <<EOT
|
--mount=type=cache,target=/root/.cache/go-build,id=containerutil-build-$TARGETPLATFORM <<EOT
|
||||||
set -e
|
set -e
|
||||||
|
@ -436,33 +453,41 @@ FROM binary-dummy AS containerutil-linux
|
||||||
FROM containerutil-build AS containerutil-windows-amd64
|
FROM containerutil-build AS containerutil-windows-amd64
|
||||||
FROM containerutil-windows-${TARGETARCH} AS containerutil-windows
|
FROM containerutil-windows-${TARGETARCH} AS containerutil-windows
|
||||||
FROM containerutil-${TARGETOS} AS containerutil
|
FROM containerutil-${TARGETOS} AS containerutil
|
||||||
|
FROM docker/buildx-bin:${BUILDX_VERSION} as buildx
|
||||||
|
FROM docker/compose-bin:${COMPOSE_VERSION} as compose
|
||||||
|
|
||||||
FROM base AS dev-systemd-false
|
FROM base AS dev-systemd-false
|
||||||
COPY --from=dockercli /build/ /usr/local/cli
|
COPY --link --from=frozen-images /build/ /docker-frozen-images
|
||||||
COPY --from=frozen-images /build/ /docker-frozen-images
|
COPY --link --from=swagger /build/ /usr/local/bin/
|
||||||
COPY --from=swagger /build/ /usr/local/bin/
|
COPY --link --from=delve /build/ /usr/local/bin/
|
||||||
COPY --from=delve /build/ /usr/local/bin/
|
COPY --link --from=tomll /build/ /usr/local/bin/
|
||||||
COPY --from=tomll /build/ /usr/local/bin/
|
COPY --link --from=gowinres /build/ /usr/local/bin/
|
||||||
COPY --from=gowinres /build/ /usr/local/bin/
|
COPY --link --from=tini /build/ /usr/local/bin/
|
||||||
COPY --from=tini /build/ /usr/local/bin/
|
COPY --link --from=registry /build/ /usr/local/bin/
|
||||||
COPY --from=registry /build/ /usr/local/bin/
|
COPY --link --from=registry-v2 /build/ /usr/local/bin/
|
||||||
|
|
||||||
# Skip the CRIU stage for now, as the opensuse package repository is sometimes
|
# Skip the CRIU stage for now, as the opensuse package repository is sometimes
|
||||||
# unstable, and we're currently not using it in CI.
|
# unstable, and we're currently not using it in CI.
|
||||||
#
|
#
|
||||||
# FIXME(thaJeztah): re-enable this stage when https://github.com/moby/moby/issues/38963 is resolved (see https://github.com/moby/moby/pull/38984)
|
# FIXME(thaJeztah): re-enable this stage when https://github.com/moby/moby/issues/38963 is resolved (see https://github.com/moby/moby/pull/38984)
|
||||||
# COPY --from=criu /build/ /usr/local/bin/
|
# COPY --link --from=criu /build/ /usr/local/bin/
|
||||||
COPY --from=gotestsum /build/ /usr/local/bin/
|
COPY --link --from=gotestsum /build/ /usr/local/bin/
|
||||||
COPY --from=golangci_lint /build/ /usr/local/bin/
|
COPY --link --from=golangci_lint /build/ /usr/local/bin/
|
||||||
COPY --from=shfmt /build/ /usr/local/bin/
|
COPY --link --from=shfmt /build/ /usr/local/bin/
|
||||||
COPY --from=runc /build/ /usr/local/bin/
|
COPY --link --from=runc /build/ /usr/local/bin/
|
||||||
COPY --from=containerd /build/ /usr/local/bin/
|
COPY --link --from=containerd /build/ /usr/local/bin/
|
||||||
COPY --from=rootlesskit /build/ /usr/local/bin/
|
COPY --link --from=rootlesskit /build/ /usr/local/bin/
|
||||||
COPY --from=vpnkit / /usr/local/bin/
|
COPY --link --from=vpnkit / /usr/local/bin/
|
||||||
COPY --from=containerutil /build/ /usr/local/bin/
|
COPY --link --from=containerutil /build/ /usr/local/bin/
|
||||||
COPY --from=crun /build/ /usr/local/bin/
|
COPY --link --from=crun /build/ /usr/local/bin/
|
||||||
COPY hack/dockerfile/etc/docker/ /etc/docker/
|
COPY --link hack/dockerfile/etc/docker/ /etc/docker/
|
||||||
|
COPY --link --from=buildx /buildx /usr/local/libexec/docker/cli-plugins/docker-buildx
|
||||||
|
COPY --link --from=compose /docker-compose /usr/libexec/docker/cli-plugins/docker-compose
|
||||||
|
|
||||||
ENV PATH=/usr/local/cli:$PATH
|
ENV PATH=/usr/local/cli:$PATH
|
||||||
|
ENV TEST_CLIENT_BINARY=/usr/local/cli-integration/docker
|
||||||
|
ENV CONTAINERD_ADDRESS=/run/docker/containerd/containerd.sock
|
||||||
|
ENV CONTAINERD_NAMESPACE=moby
|
||||||
WORKDIR /go/src/github.com/docker/docker
|
WORKDIR /go/src/github.com/docker/docker
|
||||||
VOLUME /var/lib/docker
|
VOLUME /var/lib/docker
|
||||||
VOLUME /home/unprivilegeduser/.local/share/docker
|
VOLUME /home/unprivilegeduser/.local/share/docker
|
||||||
|
@ -477,13 +502,9 @@ RUN --mount=type=cache,sharing=locked,id=moby-dev-aptlib,target=/var/lib/apt \
|
||||||
dbus-user-session \
|
dbus-user-session \
|
||||||
systemd \
|
systemd \
|
||||||
systemd-sysv
|
systemd-sysv
|
||||||
RUN mkdir -p hack \
|
|
||||||
&& curl -o hack/dind-systemd https://raw.githubusercontent.com/AkihiroSuda/containerized-systemd/b70bac0daeea120456764248164c21684ade7d0d/docker-entrypoint.sh \
|
|
||||||
&& chmod +x hack/dind-systemd
|
|
||||||
ENTRYPOINT ["hack/dind-systemd"]
|
ENTRYPOINT ["hack/dind-systemd"]
|
||||||
|
|
||||||
FROM dev-systemd-${SYSTEMD} AS dev-base
|
FROM dev-systemd-${SYSTEMD} AS dev-base
|
||||||
ARG DEBIAN_FRONTEND
|
|
||||||
RUN groupadd -r docker
|
RUN groupadd -r docker
|
||||||
RUN useradd --create-home --gid docker unprivilegeduser \
|
RUN useradd --create-home --gid docker unprivilegeduser \
|
||||||
&& mkdir -p /home/unprivilegeduser/.local/share/docker \
|
&& mkdir -p /home/unprivilegeduser/.local/share/docker \
|
||||||
|
@ -517,10 +538,8 @@ RUN --mount=type=cache,sharing=locked,id=moby-dev-aptlib,target=/var/lib/apt \
|
||||||
net-tools \
|
net-tools \
|
||||||
patch \
|
patch \
|
||||||
pigz \
|
pigz \
|
||||||
python3-pip \
|
|
||||||
python3-setuptools \
|
|
||||||
python3-wheel \
|
|
||||||
sudo \
|
sudo \
|
||||||
|
systemd-journal-remote \
|
||||||
thin-provisioning-tools \
|
thin-provisioning-tools \
|
||||||
uidmap \
|
uidmap \
|
||||||
vim \
|
vim \
|
||||||
|
@ -534,8 +553,6 @@ RUN --mount=type=cache,sharing=locked,id=moby-dev-aptlib,target=/var/lib/apt \
|
||||||
RUN update-alternatives --set iptables /usr/sbin/iptables-legacy || true \
|
RUN update-alternatives --set iptables /usr/sbin/iptables-legacy || true \
|
||||||
&& update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy || true \
|
&& update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy || true \
|
||||||
&& update-alternatives --set arptables /usr/sbin/arptables-legacy || true
|
&& update-alternatives --set arptables /usr/sbin/arptables-legacy || true
|
||||||
ARG YAMLLINT_VERSION=1.27.1
|
|
||||||
RUN pip3 install yamllint==${YAMLLINT_VERSION}
|
|
||||||
RUN --mount=type=cache,sharing=locked,id=moby-dev-aptlib,target=/var/lib/apt \
|
RUN --mount=type=cache,sharing=locked,id=moby-dev-aptlib,target=/var/lib/apt \
|
||||||
--mount=type=cache,sharing=locked,id=moby-dev-aptcache,target=/var/cache/apt \
|
--mount=type=cache,sharing=locked,id=moby-dev-aptcache,target=/var/cache/apt \
|
||||||
apt-get update && apt-get install --no-install-recommends -y \
|
apt-get update && apt-get install --no-install-recommends -y \
|
||||||
|
@ -543,18 +560,19 @@ RUN --mount=type=cache,sharing=locked,id=moby-dev-aptlib,target=/var/lib/apt \
|
||||||
pkg-config \
|
pkg-config \
|
||||||
dpkg-dev \
|
dpkg-dev \
|
||||||
libapparmor-dev \
|
libapparmor-dev \
|
||||||
libdevmapper-dev \
|
|
||||||
libseccomp-dev \
|
libseccomp-dev \
|
||||||
libsecret-1-dev \
|
libsecret-1-dev \
|
||||||
libsystemd-dev \
|
libsystemd-dev \
|
||||||
libudev-dev
|
libudev-dev \
|
||||||
|
yamllint
|
||||||
|
COPY --link --from=dockercli /build/ /usr/local/cli
|
||||||
|
COPY --link --from=dockercli-integration /build/ /usr/local/cli-integration
|
||||||
|
|
||||||
FROM base AS build
|
FROM base AS build
|
||||||
COPY --from=gowinres /build/ /usr/local/bin/
|
COPY --from=gowinres /build/ /usr/local/bin/
|
||||||
WORKDIR /go/src/github.com/docker/docker
|
WORKDIR /go/src/github.com/docker/docker
|
||||||
ENV GO111MODULE=off
|
ENV GO111MODULE=off
|
||||||
ENV CGO_ENABLED=1
|
ENV CGO_ENABLED=1
|
||||||
ARG DEBIAN_FRONTEND
|
|
||||||
RUN --mount=type=cache,sharing=locked,id=moby-build-aptlib,target=/var/lib/apt \
|
RUN --mount=type=cache,sharing=locked,id=moby-build-aptlib,target=/var/lib/apt \
|
||||||
--mount=type=cache,sharing=locked,id=moby-build-aptcache,target=/var/cache/apt \
|
--mount=type=cache,sharing=locked,id=moby-build-aptcache,target=/var/cache/apt \
|
||||||
apt-get update && apt-get install --no-install-recommends -y \
|
apt-get update && apt-get install --no-install-recommends -y \
|
||||||
|
@ -569,11 +587,11 @@ RUN --mount=type=cache,sharing=locked,id=moby-build-aptlib,target=/var/lib/apt \
|
||||||
gcc \
|
gcc \
|
||||||
libapparmor-dev \
|
libapparmor-dev \
|
||||||
libc6-dev \
|
libc6-dev \
|
||||||
libdevmapper-dev \
|
|
||||||
libseccomp-dev \
|
libseccomp-dev \
|
||||||
libsecret-1-dev \
|
libsecret-1-dev \
|
||||||
libsystemd-dev \
|
libsystemd-dev \
|
||||||
libudev-dev
|
libudev-dev \
|
||||||
|
pkg-config
|
||||||
ARG DOCKER_BUILDTAGS
|
ARG DOCKER_BUILDTAGS
|
||||||
ARG DOCKER_DEBUG
|
ARG DOCKER_DEBUG
|
||||||
ARG DOCKER_GITCOMMIT=HEAD
|
ARG DOCKER_GITCOMMIT=HEAD
|
||||||
|
@ -593,7 +611,7 @@ RUN <<EOT
|
||||||
XX_CC_PREFER_LINKER=ld xx-clang --setup-target-triple
|
XX_CC_PREFER_LINKER=ld xx-clang --setup-target-triple
|
||||||
fi
|
fi
|
||||||
EOT
|
EOT
|
||||||
RUN --mount=type=bind,target=. \
|
RUN --mount=type=bind,target=.,rw \
|
||||||
--mount=type=tmpfs,target=cli/winresources/dockerd \
|
--mount=type=tmpfs,target=cli/winresources/dockerd \
|
||||||
--mount=type=tmpfs,target=cli/winresources/docker-proxy \
|
--mount=type=tmpfs,target=cli/winresources/docker-proxy \
|
||||||
--mount=type=cache,target=/root/.cache/go-build,id=moby-build-$TARGETPLATFORM <<EOT
|
--mount=type=cache,target=/root/.cache/go-build,id=moby-build-$TARGETPLATFORM <<EOT
|
||||||
|
@ -619,13 +637,13 @@ COPY --from=build /build/ /
|
||||||
# usage:
|
# usage:
|
||||||
# > docker buildx bake all
|
# > docker buildx bake all
|
||||||
FROM scratch AS all
|
FROM scratch AS all
|
||||||
COPY --from=tini /build/ /
|
COPY --link --from=tini /build/ /
|
||||||
COPY --from=runc /build/ /
|
COPY --link --from=runc /build/ /
|
||||||
COPY --from=containerd /build/ /
|
COPY --link --from=containerd /build/ /
|
||||||
COPY --from=rootlesskit /build/ /
|
COPY --link --from=rootlesskit /build/ /
|
||||||
COPY --from=containerutil /build/ /
|
COPY --link --from=containerutil /build/ /
|
||||||
COPY --from=vpnkit / /
|
COPY --link --from=vpnkit / /
|
||||||
COPY --from=build /build /
|
COPY --link --from=build /build /
|
||||||
|
|
||||||
# smoke tests
|
# smoke tests
|
||||||
# usage:
|
# usage:
|
||||||
|
@ -641,8 +659,13 @@ RUN <<EOT
|
||||||
docker-proxy --version
|
docker-proxy --version
|
||||||
EOT
|
EOT
|
||||||
|
|
||||||
|
# devcontainer is a stage used by .devcontainer/devcontainer.json
|
||||||
|
FROM dev-base AS devcontainer
|
||||||
|
COPY --link . .
|
||||||
|
COPY --link --from=gopls /build/ /usr/local/bin/
|
||||||
|
|
||||||
# usage:
|
# usage:
|
||||||
# > make shell
|
# > make shell
|
||||||
# > SYSTEMD=true make shell
|
# > SYSTEMD=true make shell
|
||||||
FROM dev-base AS dev
|
FROM dev-base AS dev
|
||||||
COPY . .
|
COPY --link . .
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
ARG GO_VERSION=1.20.5
|
|
||||||
|
|
||||||
FROM golang:${GO_VERSION}-alpine AS base
|
|
||||||
ENV GO111MODULE=off
|
|
||||||
RUN apk --no-cache add \
|
|
||||||
bash \
|
|
||||||
build-base \
|
|
||||||
curl \
|
|
||||||
lvm2-dev \
|
|
||||||
jq
|
|
||||||
|
|
||||||
RUN mkdir -p /build/
|
|
||||||
RUN mkdir -p /go/src/github.com/docker/docker/
|
|
||||||
WORKDIR /go/src/github.com/docker/docker/
|
|
||||||
|
|
||||||
FROM base AS frozen-images
|
|
||||||
# Get useful and necessary Hub images so we can "docker load" locally instead of pulling
|
|
||||||
COPY contrib/download-frozen-image-v2.sh /
|
|
||||||
RUN /download-frozen-image-v2.sh /build \
|
|
||||||
busybox:latest@sha256:95cf004f559831017cdf4628aaf1bb30133677be8702a8c5f2994629f637a209 \
|
|
||||||
busybox:latest@sha256:95cf004f559831017cdf4628aaf1bb30133677be8702a8c5f2994629f637a209 \
|
|
||||||
debian:bullseye-slim@sha256:dacf278785a4daa9de07596ec739dbc07131e189942772210709c5c0777e8437 \
|
|
||||||
hello-world:latest@sha256:d58e752213a51785838f9eed2b7a498ffa1cb3aa7f946dda11af39286c3db9a9 \
|
|
||||||
arm32v7/hello-world:latest@sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1
|
|
||||||
# See also frozenImages in "testutil/environment/protect.go" (which needs to be updated when adding images to this list)
|
|
||||||
|
|
||||||
FROM base AS dockercli
|
|
||||||
COPY hack/dockerfile/install/install.sh ./install.sh
|
|
||||||
COPY hack/dockerfile/install/dockercli.installer ./
|
|
||||||
RUN PREFIX=/build ./install.sh dockercli
|
|
||||||
|
|
||||||
# TestDockerCLIBuildSuite dependency
|
|
||||||
FROM base AS contrib
|
|
||||||
COPY contrib/syscall-test /build/syscall-test
|
|
||||||
COPY contrib/httpserver/Dockerfile /build/httpserver/Dockerfile
|
|
||||||
COPY contrib/httpserver contrib/httpserver
|
|
||||||
RUN CGO_ENABLED=0 go build -buildmode=pie -o /build/httpserver/httpserver github.com/docker/docker/contrib/httpserver
|
|
||||||
|
|
||||||
# Build the integration tests and copy the resulting binaries to /build/tests
|
|
||||||
FROM base AS builder
|
|
||||||
|
|
||||||
# Set tag and add sources
|
|
||||||
COPY . .
|
|
||||||
# Copy test sources tests that use assert can print errors
|
|
||||||
RUN mkdir -p /build${PWD} && find integration integration-cli -name \*_test.go -exec cp --parents '{}' /build${PWD} \;
|
|
||||||
# Build and install test binaries
|
|
||||||
ARG DOCKER_GITCOMMIT=undefined
|
|
||||||
RUN hack/make.sh build-integration-test-binary
|
|
||||||
RUN mkdir -p /build/tests && find . -name test.main -exec cp --parents '{}' /build/tests \;
|
|
||||||
|
|
||||||
## Generate testing image
|
|
||||||
FROM alpine:3.10 as runner
|
|
||||||
|
|
||||||
ENV DOCKER_REMOTE_DAEMON=1
|
|
||||||
ENV DOCKER_INTEGRATION_DAEMON_DEST=/
|
|
||||||
ENTRYPOINT ["/scripts/run.sh"]
|
|
||||||
|
|
||||||
# Add an unprivileged user to be used for tests which need it
|
|
||||||
RUN addgroup docker && adduser -D -G docker unprivilegeduser -s /bin/ash
|
|
||||||
|
|
||||||
# GNU tar is used for generating the emptyfs image
|
|
||||||
RUN apk --no-cache add \
|
|
||||||
bash \
|
|
||||||
ca-certificates \
|
|
||||||
g++ \
|
|
||||||
git \
|
|
||||||
inetutils-ping \
|
|
||||||
iptables \
|
|
||||||
libcap2-bin \
|
|
||||||
pigz \
|
|
||||||
tar \
|
|
||||||
xz
|
|
||||||
|
|
||||||
COPY hack/test/e2e-run.sh /scripts/run.sh
|
|
||||||
COPY hack/make/.ensure-emptyfs /scripts/ensure-emptyfs.sh
|
|
||||||
|
|
||||||
COPY integration/testdata /tests/integration/testdata
|
|
||||||
COPY integration/build/testdata /tests/integration/build/testdata
|
|
||||||
COPY integration-cli/fixtures /tests/integration-cli/fixtures
|
|
||||||
|
|
||||||
COPY --from=frozen-images /build/ /docker-frozen-images
|
|
||||||
COPY --from=dockercli /build/ /usr/bin/
|
|
||||||
COPY --from=contrib /build/ /tests/contrib/
|
|
||||||
COPY --from=builder /build/ /
|
|
|
@ -5,17 +5,14 @@
|
||||||
|
|
||||||
# This represents the bare minimum required to build and test Docker.
|
# This represents the bare minimum required to build and test Docker.
|
||||||
|
|
||||||
ARG GO_VERSION=1.20.13
|
ARG GO_VERSION=1.21.9
|
||||||
|
|
||||||
ARG BASE_DEBIAN_DISTRO="bullseye"
|
ARG BASE_DEBIAN_DISTRO="bookworm"
|
||||||
ARG GOLANG_IMAGE="golang:${GO_VERSION}-${BASE_DEBIAN_DISTRO}"
|
ARG GOLANG_IMAGE="golang:${GO_VERSION}-${BASE_DEBIAN_DISTRO}"
|
||||||
|
|
||||||
FROM ${GOLANG_IMAGE}
|
FROM ${GOLANG_IMAGE}
|
||||||
ENV GO111MODULE=off
|
ENV GO111MODULE=off
|
||||||
|
ENV GOTOOLCHAIN=local
|
||||||
# allow replacing httpredir or deb mirror
|
|
||||||
ARG APT_MIRROR=deb.debian.org
|
|
||||||
RUN sed -ri "s/(httpredir|deb).debian.org/$APT_MIRROR/g" /etc/apt/sources.list
|
|
||||||
|
|
||||||
# Compile and runtime deps
|
# Compile and runtime deps
|
||||||
# https://github.com/docker/docker/blob/master/project/PACKAGERS.md#build-dependencies
|
# https://github.com/docker/docker/blob/master/project/PACKAGERS.md#build-dependencies
|
||||||
|
@ -26,7 +23,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
cmake \
|
cmake \
|
||||||
git \
|
git \
|
||||||
libapparmor-dev \
|
libapparmor-dev \
|
||||||
libdevmapper-dev \
|
|
||||||
libseccomp-dev \
|
libseccomp-dev \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
e2fsprogs \
|
e2fsprogs \
|
||||||
|
|
|
@ -154,21 +154,17 @@
|
||||||
|
|
||||||
# The number of build steps below are explicitly minimised to improve performance.
|
# The number of build steps below are explicitly minimised to improve performance.
|
||||||
|
|
||||||
# Extremely important - do not change the following line to reference a "specific" image,
|
ARG WINDOWS_BASE_IMAGE=mcr.microsoft.com/windows/servercore
|
||||||
# such as `mcr.microsoft.com/windows/servercore:ltsc2022`. If using this Dockerfile in process
|
ARG WINDOWS_BASE_IMAGE_TAG=ltsc2022
|
||||||
# isolated containers, the kernel of the host must match the container image, and hence
|
FROM ${WINDOWS_BASE_IMAGE}:${WINDOWS_BASE_IMAGE_TAG}
|
||||||
# would fail between Windows Server 2016 (aka RS1) and Windows Server 2019 (aka RS5).
|
|
||||||
# It is expected that the image `microsoft/windowsservercore:latest` is present, and matches
|
|
||||||
# the hosts kernel version before doing a build.
|
|
||||||
FROM microsoft/windowsservercore
|
|
||||||
|
|
||||||
# Use PowerShell as the default shell
|
# Use PowerShell as the default shell
|
||||||
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
|
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
|
||||||
|
|
||||||
ARG GO_VERSION=1.20.13
|
ARG GO_VERSION=1.21.9
|
||||||
ARG GOTESTSUM_VERSION=v1.8.2
|
ARG GOTESTSUM_VERSION=v1.8.2
|
||||||
ARG GOWINRES_VERSION=v0.3.0
|
ARG GOWINRES_VERSION=v0.3.1
|
||||||
ARG CONTAINERD_VERSION=v1.6.28
|
ARG CONTAINERD_VERSION=v1.7.15
|
||||||
|
|
||||||
# Environment variable notes:
|
# Environment variable notes:
|
||||||
# - GO_VERSION must be consistent with 'Dockerfile' used by Linux.
|
# - GO_VERSION must be consistent with 'Dockerfile' used by Linux.
|
||||||
|
@ -179,6 +175,7 @@ ENV GO_VERSION=${GO_VERSION} `
|
||||||
GIT_VERSION=2.11.1 `
|
GIT_VERSION=2.11.1 `
|
||||||
GOPATH=C:\gopath `
|
GOPATH=C:\gopath `
|
||||||
GO111MODULE=off `
|
GO111MODULE=off `
|
||||||
|
GOTOOLCHAIN=local `
|
||||||
FROM_DOCKERFILE=1 `
|
FROM_DOCKERFILE=1 `
|
||||||
GOTESTSUM_VERSION=${GOTESTSUM_VERSION} `
|
GOTESTSUM_VERSION=${GOTESTSUM_VERSION} `
|
||||||
GOWINRES_VERSION=${GOWINRES_VERSION}
|
GOWINRES_VERSION=${GOWINRES_VERSION}
|
||||||
|
@ -223,7 +220,7 @@ RUN `
|
||||||
Download-File $location C:\gitsetup.zip; `
|
Download-File $location C:\gitsetup.zip; `
|
||||||
`
|
`
|
||||||
Write-Host INFO: Downloading go...; `
|
Write-Host INFO: Downloading go...; `
|
||||||
$dlGoVersion=$Env:GO_VERSION -replace '\.0$',''; `
|
$dlGoVersion=$Env:GO_VERSION; `
|
||||||
Download-File "https://go.dev/dl/go${dlGoVersion}.windows-amd64.zip" C:\go.zip; `
|
Download-File "https://go.dev/dl/go${dlGoVersion}.windows-amd64.zip" C:\go.zip; `
|
||||||
`
|
`
|
||||||
Write-Host INFO: Downloading compiler 1 of 3...; `
|
Write-Host INFO: Downloading compiler 1 of 3...; `
|
||||||
|
|
1
Jenkinsfile
vendored
1
Jenkinsfile
vendored
|
@ -111,6 +111,7 @@ pipeline {
|
||||||
-e DOCKER_GITCOMMIT=${GIT_COMMIT} \
|
-e DOCKER_GITCOMMIT=${GIT_COMMIT} \
|
||||||
-e DOCKER_GRAPHDRIVER \
|
-e DOCKER_GRAPHDRIVER \
|
||||||
-e TESTDEBUG \
|
-e TESTDEBUG \
|
||||||
|
-e TEST_INTEGRATION_USE_SNAPSHOTTER \
|
||||||
-e TEST_SKIP_INTEGRATION_CLI \
|
-e TEST_SKIP_INTEGRATION_CLI \
|
||||||
-e TIMEOUT \
|
-e TIMEOUT \
|
||||||
-e VALIDATE_REPO=${GIT_URL} \
|
-e VALIDATE_REPO=${GIT_URL} \
|
||||||
|
|
62
MAINTAINERS
62
MAINTAINERS
|
@ -24,15 +24,21 @@
|
||||||
# subsystem maintainers accountable. If ownership is unclear, they are the de facto owners.
|
# subsystem maintainers accountable. If ownership is unclear, they are the de facto owners.
|
||||||
|
|
||||||
people = [
|
people = [
|
||||||
|
"akerouanton",
|
||||||
"akihirosuda",
|
"akihirosuda",
|
||||||
"anusha",
|
"anusha",
|
||||||
"coolljt0725",
|
"coolljt0725",
|
||||||
|
"corhere",
|
||||||
"cpuguy83",
|
"cpuguy83",
|
||||||
|
"crazy-max",
|
||||||
"estesp",
|
"estesp",
|
||||||
"johnstep",
|
"johnstep",
|
||||||
"justincormack",
|
"justincormack",
|
||||||
"kolyshkin",
|
"kolyshkin",
|
||||||
|
"laurazard",
|
||||||
"mhbauer",
|
"mhbauer",
|
||||||
|
"neersighted",
|
||||||
|
"rumpl",
|
||||||
"runcom",
|
"runcom",
|
||||||
"samuelkarp",
|
"samuelkarp",
|
||||||
"stevvooe",
|
"stevvooe",
|
||||||
|
@ -43,6 +49,7 @@
|
||||||
"unclejack",
|
"unclejack",
|
||||||
"vdemeester",
|
"vdemeester",
|
||||||
"vieux",
|
"vieux",
|
||||||
|
"vvoland",
|
||||||
"yongtang"
|
"yongtang"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -61,15 +68,15 @@
|
||||||
people = [
|
people = [
|
||||||
"alexellis",
|
"alexellis",
|
||||||
"andrewhsu",
|
"andrewhsu",
|
||||||
"corhere",
|
"bsousaa",
|
||||||
|
"dmcgowan",
|
||||||
"fntlnz",
|
"fntlnz",
|
||||||
"gianarb",
|
"gianarb",
|
||||||
"ndeloof",
|
|
||||||
"neersighted",
|
|
||||||
"olljanat",
|
"olljanat",
|
||||||
"programmerq",
|
"programmerq",
|
||||||
"ripcurld",
|
"ripcurld",
|
||||||
"rumpl",
|
"robmry",
|
||||||
|
"sam-thibault",
|
||||||
"samwhited",
|
"samwhited",
|
||||||
"thajeztah"
|
"thajeztah"
|
||||||
]
|
]
|
||||||
|
@ -277,6 +284,11 @@
|
||||||
Email = "aaron.lehmann@docker.com"
|
Email = "aaron.lehmann@docker.com"
|
||||||
GitHub = "aaronlehmann"
|
GitHub = "aaronlehmann"
|
||||||
|
|
||||||
|
[people.akerouanton]
|
||||||
|
Name = "Albin Kerouanton"
|
||||||
|
Email = "albinker@gmail.com"
|
||||||
|
GitHub = "akerouanton"
|
||||||
|
|
||||||
[people.alexellis]
|
[people.alexellis]
|
||||||
Name = "Alex Ellis"
|
Name = "Alex Ellis"
|
||||||
Email = "alexellis2@gmail.com"
|
Email = "alexellis2@gmail.com"
|
||||||
|
@ -306,6 +318,11 @@
|
||||||
Name = "Anusha Ragunathan"
|
Name = "Anusha Ragunathan"
|
||||||
Email = "anusha@docker.com"
|
Email = "anusha@docker.com"
|
||||||
GitHub = "anusha-ragunathan"
|
GitHub = "anusha-ragunathan"
|
||||||
|
|
||||||
|
[people.bsousaa]
|
||||||
|
Name = "Bruno de Sousa"
|
||||||
|
Email = "bruno.sousa@docker.com"
|
||||||
|
GitHub = "bsousaa"
|
||||||
|
|
||||||
[people.calavera]
|
[people.calavera]
|
||||||
Name = "David Calavera"
|
Name = "David Calavera"
|
||||||
|
@ -327,6 +344,11 @@
|
||||||
Email = "cpuguy83@gmail.com"
|
Email = "cpuguy83@gmail.com"
|
||||||
GitHub = "cpuguy83"
|
GitHub = "cpuguy83"
|
||||||
|
|
||||||
|
[people.crazy-max]
|
||||||
|
Name = "Kevin Alvarez"
|
||||||
|
Email = "contact@crazymax.dev"
|
||||||
|
GitHub = "crazy-max"
|
||||||
|
|
||||||
[people.crosbymichael]
|
[people.crosbymichael]
|
||||||
Name = "Michael Crosby"
|
Name = "Michael Crosby"
|
||||||
Email = "crosbymichael@gmail.com"
|
Email = "crosbymichael@gmail.com"
|
||||||
|
@ -337,6 +359,11 @@
|
||||||
Email = "dnephin@gmail.com"
|
Email = "dnephin@gmail.com"
|
||||||
GitHub = "dnephin"
|
GitHub = "dnephin"
|
||||||
|
|
||||||
|
[people.dmcgowan]
|
||||||
|
Name = "Derek McGowan"
|
||||||
|
Email = "derek@mcgstyle.net"
|
||||||
|
GitHub = "dmcgowan"
|
||||||
|
|
||||||
[people.duglin]
|
[people.duglin]
|
||||||
Name = "Doug Davis"
|
Name = "Doug Davis"
|
||||||
Email = "dug@us.ibm.com"
|
Email = "dug@us.ibm.com"
|
||||||
|
@ -397,6 +424,11 @@
|
||||||
Email = "kolyshkin@gmail.com"
|
Email = "kolyshkin@gmail.com"
|
||||||
GitHub = "kolyshkin"
|
GitHub = "kolyshkin"
|
||||||
|
|
||||||
|
[people.laurazard]
|
||||||
|
Name = "Laura Brehm"
|
||||||
|
Email = "laura.brehm@docker.com"
|
||||||
|
GitHub = "laurazard"
|
||||||
|
|
||||||
[people.lk4d4]
|
[people.lk4d4]
|
||||||
Name = "Alexander Morozov"
|
Name = "Alexander Morozov"
|
||||||
Email = "lk4d4@docker.com"
|
Email = "lk4d4@docker.com"
|
||||||
|
@ -432,14 +464,9 @@
|
||||||
Email = "mrjana@docker.com"
|
Email = "mrjana@docker.com"
|
||||||
GitHub = "mrjana"
|
GitHub = "mrjana"
|
||||||
|
|
||||||
[people.ndeloof]
|
|
||||||
Name = "Nicolas De Loof"
|
|
||||||
Email = "nicolas.deloof@gmail.com"
|
|
||||||
GitHub = "ndeloof"
|
|
||||||
|
|
||||||
[people.neersighted]
|
[people.neersighted]
|
||||||
Name = "Bjorn Neergaard"
|
Name = "Bjorn Neergaard"
|
||||||
Email = "bneergaard@mirantis.com"
|
Email = "bjorn@neersighted.com"
|
||||||
GitHub = "neersighted"
|
GitHub = "neersighted"
|
||||||
|
|
||||||
[people.olljanat]
|
[people.olljanat]
|
||||||
|
@ -452,6 +479,11 @@
|
||||||
Email = "jeff@docker.com"
|
Email = "jeff@docker.com"
|
||||||
GitHub = "programmerq"
|
GitHub = "programmerq"
|
||||||
|
|
||||||
|
[people.robmry]
|
||||||
|
Name = "Rob Murray"
|
||||||
|
Email = "rob.murray@docker.com"
|
||||||
|
GitHub = "robmry"
|
||||||
|
|
||||||
[people.ripcurld]
|
[people.ripcurld]
|
||||||
Name = "Boaz Shuster"
|
Name = "Boaz Shuster"
|
||||||
Email = "ripcurld.github@gmail.com"
|
Email = "ripcurld.github@gmail.com"
|
||||||
|
@ -467,6 +499,11 @@
|
||||||
Email = "runcom@redhat.com"
|
Email = "runcom@redhat.com"
|
||||||
GitHub = "runcom"
|
GitHub = "runcom"
|
||||||
|
|
||||||
|
[people.sam-thibault]
|
||||||
|
Name = "Sam Thibault"
|
||||||
|
Email = "sam.thibault@docker.com"
|
||||||
|
GitHub = "sam-thibault"
|
||||||
|
|
||||||
[people.samuelkarp]
|
[people.samuelkarp]
|
||||||
Name = "Samuel Karp"
|
Name = "Samuel Karp"
|
||||||
Email = "me@samuelkarp.com"
|
Email = "me@samuelkarp.com"
|
||||||
|
@ -536,6 +573,11 @@
|
||||||
Name = "Vishnu Kannan"
|
Name = "Vishnu Kannan"
|
||||||
Email = "vishnuk@google.com"
|
Email = "vishnuk@google.com"
|
||||||
GitHub = "vishh"
|
GitHub = "vishh"
|
||||||
|
|
||||||
|
[people.vvoland]
|
||||||
|
Name = "Paweł Gronowski"
|
||||||
|
Email = "pawel.gronowski@docker.com"
|
||||||
|
GitHub = "vvoland"
|
||||||
|
|
||||||
[people.yongtang]
|
[people.yongtang]
|
||||||
Name = "Yong Tang"
|
Name = "Yong Tang"
|
||||||
|
|
50
Makefile
50
Makefile
|
@ -4,14 +4,10 @@ DOCKER ?= docker
|
||||||
BUILDX ?= $(DOCKER) buildx
|
BUILDX ?= $(DOCKER) buildx
|
||||||
|
|
||||||
# set the graph driver as the current graphdriver if not set
|
# set the graph driver as the current graphdriver if not set
|
||||||
DOCKER_GRAPHDRIVER := $(if $(DOCKER_GRAPHDRIVER),$(DOCKER_GRAPHDRIVER),$(shell docker info 2>&1 | grep "Storage Driver" | sed 's/.*: //'))
|
DOCKER_GRAPHDRIVER := $(if $(DOCKER_GRAPHDRIVER),$(DOCKER_GRAPHDRIVER),$(shell docker info -f '{{ .Driver }}' 2>&1))
|
||||||
export DOCKER_GRAPHDRIVER
|
export DOCKER_GRAPHDRIVER
|
||||||
|
|
||||||
# get OS/Arch of docker engine
|
DOCKER_GITCOMMIT := $(shell git rev-parse HEAD)
|
||||||
DOCKER_OSARCH := $(shell bash -c 'source hack/make/.detect-daemon-osarch && echo $${DOCKER_ENGINE_OSARCH}')
|
|
||||||
DOCKERFILE := $(shell bash -c 'source hack/make/.detect-daemon-osarch && echo $${DOCKERFILE}')
|
|
||||||
|
|
||||||
DOCKER_GITCOMMIT := $(shell git rev-parse --short HEAD || echo unsupported)
|
|
||||||
export DOCKER_GITCOMMIT
|
export DOCKER_GITCOMMIT
|
||||||
|
|
||||||
# allow overriding the repository and branch that validation scripts are running
|
# allow overriding the repository and branch that validation scripts are running
|
||||||
|
@ -20,6 +16,9 @@ export VALIDATE_REPO
|
||||||
export VALIDATE_BRANCH
|
export VALIDATE_BRANCH
|
||||||
export VALIDATE_ORIGIN_BRANCH
|
export VALIDATE_ORIGIN_BRANCH
|
||||||
|
|
||||||
|
export PAGER
|
||||||
|
export GIT_PAGER
|
||||||
|
|
||||||
# env vars passed through directly to Docker's build scripts
|
# env vars passed through directly to Docker's build scripts
|
||||||
# to allow things like `make KEEPBUNDLE=1 binary` easily
|
# to allow things like `make KEEPBUNDLE=1 binary` easily
|
||||||
# `project/PACKAGERS.md` have some limited documentation of some of these
|
# `project/PACKAGERS.md` have some limited documentation of some of these
|
||||||
|
@ -28,7 +27,7 @@ export VALIDATE_ORIGIN_BRANCH
|
||||||
# option of "go build". For example, a built-in graphdriver priority list
|
# option of "go build". For example, a built-in graphdriver priority list
|
||||||
# can be changed during build time like this:
|
# can be changed during build time like this:
|
||||||
#
|
#
|
||||||
# make DOCKER_LDFLAGS="-X github.com/docker/docker/daemon/graphdriver.priority=overlay2,devicemapper" dynbinary
|
# make DOCKER_LDFLAGS="-X github.com/docker/docker/daemon/graphdriver.priority=overlay2,zfs" dynbinary
|
||||||
#
|
#
|
||||||
DOCKER_ENVS := \
|
DOCKER_ENVS := \
|
||||||
-e BUILDFLAGS \
|
-e BUILDFLAGS \
|
||||||
|
@ -40,6 +39,10 @@ DOCKER_ENVS := \
|
||||||
-e DOCKER_BUILDKIT \
|
-e DOCKER_BUILDKIT \
|
||||||
-e DOCKER_BASH_COMPLETION_PATH \
|
-e DOCKER_BASH_COMPLETION_PATH \
|
||||||
-e DOCKER_CLI_PATH \
|
-e DOCKER_CLI_PATH \
|
||||||
|
-e DOCKERCLI_VERSION \
|
||||||
|
-e DOCKERCLI_REPOSITORY \
|
||||||
|
-e DOCKERCLI_INTEGRATION_VERSION \
|
||||||
|
-e DOCKERCLI_INTEGRATION_REPOSITORY \
|
||||||
-e DOCKER_DEBUG \
|
-e DOCKER_DEBUG \
|
||||||
-e DOCKER_EXPERIMENTAL \
|
-e DOCKER_EXPERIMENTAL \
|
||||||
-e DOCKER_GITCOMMIT \
|
-e DOCKER_GITCOMMIT \
|
||||||
|
@ -56,9 +59,11 @@ DOCKER_ENVS := \
|
||||||
-e GITHUB_ACTIONS \
|
-e GITHUB_ACTIONS \
|
||||||
-e TEST_FORCE_VALIDATE \
|
-e TEST_FORCE_VALIDATE \
|
||||||
-e TEST_INTEGRATION_DIR \
|
-e TEST_INTEGRATION_DIR \
|
||||||
|
-e TEST_INTEGRATION_USE_SNAPSHOTTER \
|
||||||
-e TEST_INTEGRATION_FAIL_FAST \
|
-e TEST_INTEGRATION_FAIL_FAST \
|
||||||
-e TEST_SKIP_INTEGRATION \
|
-e TEST_SKIP_INTEGRATION \
|
||||||
-e TEST_SKIP_INTEGRATION_CLI \
|
-e TEST_SKIP_INTEGRATION_CLI \
|
||||||
|
-e TEST_IGNORE_CGROUP_CHECK \
|
||||||
-e TESTCOVERAGE \
|
-e TESTCOVERAGE \
|
||||||
-e TESTDEBUG \
|
-e TESTDEBUG \
|
||||||
-e TESTDIRS \
|
-e TESTDIRS \
|
||||||
|
@ -74,7 +79,12 @@ DOCKER_ENVS := \
|
||||||
-e PLATFORM \
|
-e PLATFORM \
|
||||||
-e DEFAULT_PRODUCT_LICENSE \
|
-e DEFAULT_PRODUCT_LICENSE \
|
||||||
-e PRODUCT \
|
-e PRODUCT \
|
||||||
-e PACKAGER_NAME
|
-e PACKAGER_NAME \
|
||||||
|
-e PAGER \
|
||||||
|
-e GIT_PAGER \
|
||||||
|
-e OTEL_EXPORTER_OTLP_ENDPOINT \
|
||||||
|
-e OTEL_EXPORTER_OTLP_PROTOCOL \
|
||||||
|
-e OTEL_SERVICE_NAME
|
||||||
# note: we _cannot_ add "-e DOCKER_BUILDTAGS" here because even if it's unset in the shell, that would shadow the "ENV DOCKER_BUILDTAGS" set in our Dockerfile, which is very important for our official builds
|
# note: we _cannot_ add "-e DOCKER_BUILDTAGS" here because even if it's unset in the shell, that would shadow the "ENV DOCKER_BUILDTAGS" set in our Dockerfile, which is very important for our official builds
|
||||||
|
|
||||||
# to allow `make BIND_DIR=. shell` or `make BIND_DIR= test`
|
# to allow `make BIND_DIR=. shell` or `make BIND_DIR= test`
|
||||||
|
@ -133,11 +143,15 @@ endif
|
||||||
DOCKER_RUN_DOCKER := $(DOCKER_FLAGS) "$(DOCKER_IMAGE)"
|
DOCKER_RUN_DOCKER := $(DOCKER_FLAGS) "$(DOCKER_IMAGE)"
|
||||||
|
|
||||||
DOCKER_BUILD_ARGS += --build-arg=GO_VERSION
|
DOCKER_BUILD_ARGS += --build-arg=GO_VERSION
|
||||||
|
DOCKER_BUILD_ARGS += --build-arg=DOCKERCLI_VERSION
|
||||||
|
DOCKER_BUILD_ARGS += --build-arg=DOCKERCLI_REPOSITORY
|
||||||
|
DOCKER_BUILD_ARGS += --build-arg=DOCKERCLI_INTEGRATION_VERSION
|
||||||
|
DOCKER_BUILD_ARGS += --build-arg=DOCKERCLI_INTEGRATION_REPOSITORY
|
||||||
ifdef DOCKER_SYSTEMD
|
ifdef DOCKER_SYSTEMD
|
||||||
DOCKER_BUILD_ARGS += --build-arg=SYSTEMD=true
|
DOCKER_BUILD_ARGS += --build-arg=SYSTEMD=true
|
||||||
endif
|
endif
|
||||||
|
|
||||||
BUILD_OPTS := ${DOCKER_BUILD_ARGS} ${DOCKER_BUILD_OPTS} -f "$(DOCKERFILE)"
|
BUILD_OPTS := ${DOCKER_BUILD_ARGS} ${DOCKER_BUILD_OPTS}
|
||||||
BUILD_CMD := $(BUILDX) build
|
BUILD_CMD := $(BUILDX) build
|
||||||
BAKE_CMD := $(BUILDX) bake
|
BAKE_CMD := $(BUILDX) bake
|
||||||
|
|
||||||
|
@ -211,6 +225,11 @@ test-unit: build ## run the unit tests
|
||||||
validate: build ## validate DCO, Seccomp profile generation, gofmt,\n./pkg/ isolation, golint, tests, tomls, go vet and vendor
|
validate: build ## validate DCO, Seccomp profile generation, gofmt,\n./pkg/ isolation, golint, tests, tomls, go vet and vendor
|
||||||
$(DOCKER_RUN_DOCKER) hack/validate/all
|
$(DOCKER_RUN_DOCKER) hack/validate/all
|
||||||
|
|
||||||
|
validate-generate-files:
|
||||||
|
$(BUILD_CMD) --target "validate" \
|
||||||
|
--output "type=cacheonly" \
|
||||||
|
--file "./hack/dockerfiles/generate-files.Dockerfile" .
|
||||||
|
|
||||||
validate-%: build ## validate specific check
|
validate-%: build ## validate specific check
|
||||||
$(DOCKER_RUN_DOCKER) hack/validate/$*
|
$(DOCKER_RUN_DOCKER) hack/validate/$*
|
||||||
|
|
||||||
|
@ -232,3 +251,16 @@ swagger-docs: ## preview the API documentation
|
||||||
-e 'REDOC_OPTIONS=hide-hostname="true" lazy-rendering' \
|
-e 'REDOC_OPTIONS=hide-hostname="true" lazy-rendering' \
|
||||||
-p $(SWAGGER_DOCS_PORT):80 \
|
-p $(SWAGGER_DOCS_PORT):80 \
|
||||||
bfirsh/redoc:1.14.0
|
bfirsh/redoc:1.14.0
|
||||||
|
|
||||||
|
.PHONY: generate-files
|
||||||
|
generate-files:
|
||||||
|
$(eval $@_TMP_OUT := $(shell mktemp -d -t moby-output.XXXXXXXXXX))
|
||||||
|
@if [ -z "$($@_TMP_OUT)" ]; then \
|
||||||
|
echo "Temp dir is not set"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
$(BUILD_CMD) --target "update" \
|
||||||
|
--output "type=local,dest=$($@_TMP_OUT)" \
|
||||||
|
--file "./hack/dockerfiles/generate-files.Dockerfile" .
|
||||||
|
cp -R "$($@_TMP_OUT)"/. .
|
||||||
|
rm -rf "$($@_TMP_OUT)"/*
|
||||||
|
|
|
@ -14,7 +14,7 @@ Moby is an open project guided by strong principles, aiming to be modular, flexi
|
||||||
It is open to the community to help set its direction.
|
It is open to the community to help set its direction.
|
||||||
|
|
||||||
- Modular: the project includes lots of components that have well-defined functions and APIs that work together.
|
- Modular: the project includes lots of components that have well-defined functions and APIs that work together.
|
||||||
- Batteries included but swappable: Moby includes enough components to build fully featured container system, but its modular architecture ensures that most of the components can be swapped by different implementations.
|
- Batteries included but swappable: Moby includes enough components to build fully featured container systems, but its modular architecture ensures that most of the components can be swapped by different implementations.
|
||||||
- Usable security: Moby provides secure defaults without compromising usability.
|
- Usable security: Moby provides secure defaults without compromising usability.
|
||||||
- Developer focused: The APIs are intended to be functional and useful to build powerful tools.
|
- Developer focused: The APIs are intended to be functional and useful to build powerful tools.
|
||||||
They are not necessarily intended as end user tools but as components aimed at developers.
|
They are not necessarily intended as end user tools but as components aimed at developers.
|
||||||
|
|
|
@ -37,6 +37,6 @@ There is hopefully enough example material in the file for you to copy a similar
|
||||||
|
|
||||||
When you make edits to `swagger.yaml`, you may want to check the generated API documentation to ensure it renders correctly.
|
When you make edits to `swagger.yaml`, you may want to check the generated API documentation to ensure it renders correctly.
|
||||||
|
|
||||||
Run `make swagger-docs` and a preview will be running at `http://localhost`. Some of the styling may be incorrect, but you'll be able to ensure that it is generating the correct documentation.
|
Run `make swagger-docs` and a preview will be running at `http://localhost:9000`. Some of the styling may be incorrect, but you'll be able to ensure that it is generating the correct documentation.
|
||||||
|
|
||||||
The production documentation is generated by vendoring `swagger.yaml` into [docker/docker.github.io](https://github.com/docker/docker.github.io).
|
The production documentation is generated by vendoring `swagger.yaml` into [docker/docker.github.io](https://github.com/docker/docker.github.io).
|
||||||
|
|
|
@ -2,8 +2,17 @@ package api // import "github.com/docker/docker/api"
|
||||||
|
|
||||||
// Common constants for daemon and client.
|
// Common constants for daemon and client.
|
||||||
const (
|
const (
|
||||||
// DefaultVersion of Current REST API
|
// DefaultVersion of the current REST API.
|
||||||
DefaultVersion = "1.42"
|
DefaultVersion = "1.45"
|
||||||
|
|
||||||
|
// MinSupportedAPIVersion is the minimum API version that can be supported
|
||||||
|
// by the API server, specified as "major.minor". Note that the daemon
|
||||||
|
// may be configured with a different minimum API version, as returned
|
||||||
|
// in [github.com/docker/docker/api/types.Version.MinAPIVersion].
|
||||||
|
//
|
||||||
|
// API requests for API versions lower than the configured version produce
|
||||||
|
// an error.
|
||||||
|
MinSupportedAPIVersion = "1.24"
|
||||||
|
|
||||||
// NoBaseImageSpecifier is the symbol used by the FROM
|
// NoBaseImageSpecifier is the symbol used by the FROM
|
||||||
// command to specify that no base image is to be used.
|
// command to specify that no base image is to be used.
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
//go:build !windows
|
|
||||||
// +build !windows
|
|
||||||
|
|
||||||
package api // import "github.com/docker/docker/api"
|
|
||||||
|
|
||||||
// MinVersion represents Minimum REST API version supported
|
|
||||||
const MinVersion = "1.12"
|
|
|
@ -1,8 +0,0 @@
|
||||||
package api // import "github.com/docker/docker/api"
|
|
||||||
|
|
||||||
// MinVersion represents Minimum REST API version supported
|
|
||||||
// Technically the first daemon API version released on Windows is v1.25 in
|
|
||||||
// engine version 1.13. However, some clients are explicitly using downlevel
|
|
||||||
// APIs (e.g. docker-compose v2.1 file format) and that is just too restrictive.
|
|
||||||
// Hence also allowing 1.24 on Windows.
|
|
||||||
const MinVersion string = "1.24"
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/distribution/reference"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/backend"
|
"github.com/docker/docker/api/types/backend"
|
||||||
"github.com/docker/docker/api/types/events"
|
"github.com/docker/docker/api/types/events"
|
||||||
|
@ -21,7 +21,7 @@ import (
|
||||||
// ImageComponent provides an interface for working with images
|
// ImageComponent provides an interface for working with images
|
||||||
type ImageComponent interface {
|
type ImageComponent interface {
|
||||||
SquashImage(from string, to string) (string, error)
|
SquashImage(from string, to string) (string, error)
|
||||||
TagImageWithReference(image.ID, reference.Named) error
|
TagImage(context.Context, image.ID, reference.Named) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Builder defines interface for running a build
|
// Builder defines interface for running a build
|
||||||
|
@ -54,7 +54,7 @@ func (b *Backend) Build(ctx context.Context, config backend.BuildConfig) (string
|
||||||
options := config.Options
|
options := config.Options
|
||||||
useBuildKit := options.Version == types.BuilderBuildKit
|
useBuildKit := options.Version == types.BuilderBuildKit
|
||||||
|
|
||||||
tagger, err := NewTagger(b.imageComponent, config.ProgressWriter.StdoutFormatter, options.Tags)
|
tags, err := sanitizeRepoAndTags(options.Tags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ func (b *Backend) Build(ctx context.Context, config backend.BuildConfig) (string
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var imageID = build.ImageID
|
imageID := build.ImageID
|
||||||
if options.Squash {
|
if options.Squash {
|
||||||
if imageID, err = squashBuild(build, b.imageComponent); err != nil {
|
if imageID, err = squashBuild(build, b.imageComponent); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
@ -93,7 +93,7 @@ func (b *Backend) Build(ctx context.Context, config backend.BuildConfig) (string
|
||||||
fmt.Fprintf(stdout, "Successfully built %s\n", stringid.TruncateID(imageID))
|
fmt.Fprintf(stdout, "Successfully built %s\n", stringid.TruncateID(imageID))
|
||||||
}
|
}
|
||||||
if imageID != "" && !useBuildKit {
|
if imageID != "" && !useBuildKit {
|
||||||
err = tagger.TagImages(image.ID(imageID))
|
err = tagImages(ctx, b.imageComponent, config.ProgressWriter.StdoutFormatter, image.ID(imageID), tags)
|
||||||
}
|
}
|
||||||
return imageID, err
|
return imageID, err
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ func (b *Backend) PruneCache(ctx context.Context, opts types.BuildCachePruneOpti
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to prune build cache")
|
return nil, errors.Wrap(err, "failed to prune build cache")
|
||||||
}
|
}
|
||||||
b.eventsService.Log("prune", events.BuilderEventType, events.Actor{
|
b.eventsService.Log(events.ActionPrune, events.BuilderEventType, events.Actor{
|
||||||
Attributes: map[string]string{
|
Attributes: map[string]string{
|
||||||
"reclaimed": strconv.FormatInt(buildCacheSize, 10),
|
"reclaimed": strconv.FormatInt(buildCacheSize, 10),
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,55 +1,31 @@
|
||||||
package build // import "github.com/docker/docker/api/server/backend/build"
|
package build // import "github.com/docker/docker/api/server/backend/build"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/distribution/reference"
|
||||||
"github.com/docker/docker/image"
|
"github.com/docker/docker/image"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Tagger is responsible for tagging an image created by a builder
|
// tagImages creates image tags for the imageID.
|
||||||
type Tagger struct {
|
func tagImages(ctx context.Context, ic ImageComponent, stdout io.Writer, imageID image.ID, repoAndTags []reference.Named) error {
|
||||||
imageComponent ImageComponent
|
for _, rt := range repoAndTags {
|
||||||
stdout io.Writer
|
if err := ic.TagImage(ctx, imageID, rt); err != nil {
|
||||||
repoAndTags []reference.Named
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewTagger returns a new Tagger for tagging the images of a build.
|
|
||||||
// If any of the names are invalid tags an error is returned.
|
|
||||||
func NewTagger(backend ImageComponent, stdout io.Writer, names []string) (*Tagger, error) {
|
|
||||||
reposAndTags, err := sanitizeRepoAndTags(names)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &Tagger{
|
|
||||||
imageComponent: backend,
|
|
||||||
stdout: stdout,
|
|
||||||
repoAndTags: reposAndTags,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TagImages creates image tags for the imageID
|
|
||||||
func (bt *Tagger) TagImages(imageID image.ID) error {
|
|
||||||
for _, rt := range bt.repoAndTags {
|
|
||||||
if err := bt.imageComponent.TagImageWithReference(imageID, rt); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Fprintf(bt.stdout, "Successfully tagged %s\n", reference.FamiliarString(rt))
|
_, _ = fmt.Fprintln(stdout, "Successfully tagged", reference.FamiliarString(rt))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// sanitizeRepoAndTags parses the raw "t" parameter received from the client
|
// sanitizeRepoAndTags parses the raw "t" parameter received from the client
|
||||||
// to a slice of repoAndTag.
|
// to a slice of repoAndTag. It removes duplicates, and validates each name
|
||||||
// It also validates each repoName and tag.
|
// to not contain a digest.
|
||||||
func sanitizeRepoAndTags(names []string) ([]reference.Named, error) {
|
func sanitizeRepoAndTags(names []string) (repoAndTags []reference.Named, err error) {
|
||||||
var (
|
uniqNames := map[string]struct{}{}
|
||||||
repoAndTags []reference.Named
|
|
||||||
// This map is used for deduplicating the "-t" parameter.
|
|
||||||
uniqNames = make(map[string]struct{})
|
|
||||||
)
|
|
||||||
for _, repo := range names {
|
for _, repo := range names {
|
||||||
if repo == "" {
|
if repo == "" {
|
||||||
continue
|
continue
|
||||||
|
@ -60,14 +36,12 @@ func sanitizeRepoAndTags(names []string) ([]reference.Named, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, isCanonical := ref.(reference.Canonical); isCanonical {
|
if _, ok := ref.(reference.Digested); ok {
|
||||||
return nil, errors.New("build tag cannot contain a digest")
|
return nil, errors.New("build tag cannot contain a digest")
|
||||||
}
|
}
|
||||||
|
|
||||||
ref = reference.TagNameOnly(ref)
|
ref = reference.TagNameOnly(ref)
|
||||||
|
|
||||||
nameWithTag := ref.String()
|
nameWithTag := ref.String()
|
||||||
|
|
||||||
if _, exists := uniqNames[nameWithTag]; !exists {
|
if _, exists := uniqNames[nameWithTag]; !exists {
|
||||||
uniqNames[nameWithTag] = struct{}{}
|
uniqNames[nameWithTag] = struct{}{}
|
||||||
repoAndTags = append(repoAndTags, ref)
|
repoAndTags = append(repoAndTags, ref)
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
package server
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/docker/docker/api/server/httpstatus"
|
|
||||||
"github.com/docker/docker/api/server/httputils"
|
|
||||||
"github.com/docker/docker/api/types"
|
|
||||||
"github.com/docker/docker/api/types/versions"
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"google.golang.org/grpc/status"
|
|
||||||
)
|
|
||||||
|
|
||||||
// makeErrorHandler makes an HTTP handler that decodes a Docker error and
|
|
||||||
// returns it in the response.
|
|
||||||
func makeErrorHandler(err error) http.HandlerFunc {
|
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
statusCode := httpstatus.FromError(err)
|
|
||||||
vars := mux.Vars(r)
|
|
||||||
if apiVersionSupportsJSONErrors(vars["version"]) {
|
|
||||||
response := &types.ErrorResponse{
|
|
||||||
Message: err.Error(),
|
|
||||||
}
|
|
||||||
_ = httputils.WriteJSON(w, statusCode, response)
|
|
||||||
} else {
|
|
||||||
http.Error(w, status.Convert(err).Message(), statusCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func apiVersionSupportsJSONErrors(version string) bool {
|
|
||||||
const firstAPIVersionWithJSONErrors = "1.23"
|
|
||||||
return version == "" || versions.GreaterThan(version, firstAPIVersionWithJSONErrors)
|
|
||||||
}
|
|
|
@ -1,13 +1,14 @@
|
||||||
package httpstatus // import "github.com/docker/docker/api/server/httpstatus"
|
package httpstatus // import "github.com/docker/docker/api/server/httpstatus"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
containerderrors "github.com/containerd/containerd/errdefs"
|
cerrdefs "github.com/containerd/containerd/errdefs"
|
||||||
|
"github.com/containerd/log"
|
||||||
"github.com/docker/distribution/registry/api/errcode"
|
"github.com/docker/distribution/registry/api/errcode"
|
||||||
"github.com/docker/docker/errdefs"
|
"github.com/docker/docker/errdefs"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
@ -19,7 +20,7 @@ type causer interface {
|
||||||
// FromError retrieves status code from error message.
|
// FromError retrieves status code from error message.
|
||||||
func FromError(err error) int {
|
func FromError(err error) int {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
logrus.WithFields(logrus.Fields{"error": err}).Error("unexpected HTTP error handling")
|
log.G(context.TODO()).WithError(err).Error("unexpected HTTP error handling")
|
||||||
return http.StatusInternalServerError
|
return http.StatusInternalServerError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,10 +66,11 @@ func FromError(err error) int {
|
||||||
return FromError(e.Cause())
|
return FromError(e.Cause())
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.WithFields(logrus.Fields{
|
log.G(context.TODO()).WithFields(log.Fields{
|
||||||
"module": "api",
|
"module": "api",
|
||||||
|
"error": err,
|
||||||
"error_type": fmt.Sprintf("%T", err),
|
"error_type": fmt.Sprintf("%T", err),
|
||||||
}).Debugf("FIXME: Got an API for which error does not match any expected type!!!: %+v", err)
|
}).Debug("FIXME: Got an API for which error does not match any expected type!!!")
|
||||||
}
|
}
|
||||||
|
|
||||||
if statusCode == 0 {
|
if statusCode == 0 {
|
||||||
|
@ -132,17 +134,17 @@ func statusCodeFromDistributionError(err error) int {
|
||||||
// consumed directly (not through gRPC)
|
// consumed directly (not through gRPC)
|
||||||
func statusCodeFromContainerdError(err error) int {
|
func statusCodeFromContainerdError(err error) int {
|
||||||
switch {
|
switch {
|
||||||
case containerderrors.IsInvalidArgument(err):
|
case cerrdefs.IsInvalidArgument(err):
|
||||||
return http.StatusBadRequest
|
return http.StatusBadRequest
|
||||||
case containerderrors.IsNotFound(err):
|
case cerrdefs.IsNotFound(err):
|
||||||
return http.StatusNotFound
|
return http.StatusNotFound
|
||||||
case containerderrors.IsAlreadyExists(err):
|
case cerrdefs.IsAlreadyExists(err):
|
||||||
return http.StatusConflict
|
return http.StatusConflict
|
||||||
case containerderrors.IsFailedPrecondition(err):
|
case cerrdefs.IsFailedPrecondition(err):
|
||||||
return http.StatusPreconditionFailed
|
return http.StatusPreconditionFailed
|
||||||
case containerderrors.IsUnavailable(err):
|
case cerrdefs.IsUnavailable(err):
|
||||||
return http.StatusServiceUnavailable
|
return http.StatusServiceUnavailable
|
||||||
case containerderrors.IsNotImplemented(err):
|
case cerrdefs.IsNotImplemented(err):
|
||||||
return http.StatusNotImplemented
|
return http.StatusNotImplemented
|
||||||
default:
|
default:
|
||||||
return http.StatusInternalServerError
|
return http.StatusInternalServerError
|
||||||
|
|
|
@ -12,5 +12,4 @@ import (
|
||||||
// container configuration.
|
// container configuration.
|
||||||
type ContainerDecoder interface {
|
type ContainerDecoder interface {
|
||||||
DecodeConfig(src io.Reader) (*container.Config, *container.HostConfig, *network.NetworkingConfig, error)
|
DecodeConfig(src io.Reader) (*container.Config, *container.HostConfig, *network.NetworkingConfig, error)
|
||||||
DecodeHostConfig(src io.Reader) (*container.HostConfig, error)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
package httputils // import "github.com/docker/docker/api/server/httputils"
|
package httputils // import "github.com/docker/docker/api/server/httputils"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/distribution/reference"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BoolValue transforms a form value in different formats into a boolean type.
|
// BoolValue transforms a form value in different formats into a boolean type.
|
||||||
|
@ -41,6 +44,38 @@ func Int64ValueOrDefault(r *http.Request, field string, def int64) (int64, error
|
||||||
return def, nil
|
return def, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RepoTagReference parses form values "repo" and "tag" and returns a valid
|
||||||
|
// reference with repository and tag.
|
||||||
|
// If repo is empty, then a nil reference is returned.
|
||||||
|
// If no tag is given, then the default "latest" tag is set.
|
||||||
|
func RepoTagReference(repo, tag string) (reference.NamedTagged, error) {
|
||||||
|
if repo == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ref, err := reference.ParseNormalizedNamed(repo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, isDigested := ref.(reference.Digested); isDigested {
|
||||||
|
return nil, fmt.Errorf("cannot import digest reference")
|
||||||
|
}
|
||||||
|
|
||||||
|
if tag != "" {
|
||||||
|
return reference.WithTag(ref, tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
withDefaultTag := reference.TagNameOnly(ref)
|
||||||
|
|
||||||
|
namedTagged, ok := withDefaultTag.(reference.NamedTagged)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("unexpected reference: %q", ref.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
return namedTagged, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ArchiveOptions stores archive information for different operations.
|
// ArchiveOptions stores archive information for different operations.
|
||||||
type ArchiveOptions struct {
|
type ArchiveOptions struct {
|
||||||
Name string
|
Name string
|
||||||
|
|
|
@ -7,8 +7,8 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
|
||||||
"github.com/docker/docker/api/types/backend"
|
"github.com/docker/docker/api/types/backend"
|
||||||
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/pkg/ioutils"
|
"github.com/docker/docker/pkg/ioutils"
|
||||||
"github.com/docker/docker/pkg/jsonmessage"
|
"github.com/docker/docker/pkg/jsonmessage"
|
||||||
"github.com/docker/docker/pkg/stdcopy"
|
"github.com/docker/docker/pkg/stdcopy"
|
||||||
|
@ -16,7 +16,7 @@ import (
|
||||||
|
|
||||||
// WriteLogStream writes an encoded byte stream of log messages from the
|
// WriteLogStream writes an encoded byte stream of log messages from the
|
||||||
// messages channel, multiplexing them with a stdcopy.Writer if mux is true
|
// messages channel, multiplexing them with a stdcopy.Writer if mux is true
|
||||||
func WriteLogStream(_ context.Context, w io.Writer, msgs <-chan *backend.LogMessage, config *types.ContainerLogsOptions, mux bool) {
|
func WriteLogStream(_ context.Context, w io.Writer, msgs <-chan *backend.LogMessage, config *container.LogsOptions, mux bool) {
|
||||||
wf := ioutils.NewWriteFlusher(w)
|
wf := ioutils.NewWriteFlusher(w)
|
||||||
defer wf.Close()
|
defer wf.Close()
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package server // import "github.com/docker/docker/api/server"
|
package server // import "github.com/docker/docker/api/server"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/containerd/log"
|
||||||
"github.com/docker/docker/api/server/httputils"
|
"github.com/docker/docker/api/server/httputils"
|
||||||
"github.com/docker/docker/api/server/middleware"
|
"github.com/docker/docker/api/server/middleware"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// handlerWithGlobalMiddlewares wraps the handler function for a request with
|
// handlerWithGlobalMiddlewares wraps the handler function for a request with
|
||||||
|
@ -16,7 +16,7 @@ func (s *Server) handlerWithGlobalMiddlewares(handler httputils.APIFunc) httputi
|
||||||
next = m.WrapHandler(next)
|
next = m.WrapHandler(next)
|
||||||
}
|
}
|
||||||
|
|
||||||
if logrus.GetLevel() == logrus.DebugLevel {
|
if log.GetLevel() == log.DebugLevel {
|
||||||
next = middleware.DebugRequestMiddleware(next)
|
next = middleware.DebugRequestMiddleware(next)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/containerd/log"
|
||||||
|
"github.com/docker/docker/api/types/registry"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CORSMiddleware injects CORS headers to each request
|
// CORSMiddleware injects CORS headers to each request
|
||||||
|
@ -28,9 +29,9 @@ func (c CORSMiddleware) WrapHandler(handler func(ctx context.Context, w http.Res
|
||||||
corsHeaders = "*"
|
corsHeaders = "*"
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Debugf("CORS header is enabled and set to: %s", corsHeaders)
|
log.G(ctx).Debugf("CORS header is enabled and set to: %s", corsHeaders)
|
||||||
w.Header().Add("Access-Control-Allow-Origin", corsHeaders)
|
w.Header().Add("Access-Control-Allow-Origin", corsHeaders)
|
||||||
w.Header().Add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Registry-Auth")
|
w.Header().Add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, "+registry.AuthHeader)
|
||||||
w.Header().Add("Access-Control-Allow-Methods", "HEAD, GET, POST, DELETE, PUT, OPTIONS")
|
w.Header().Add("Access-Control-Allow-Methods", "HEAD, GET, POST, DELETE, PUT, OPTIONS")
|
||||||
return handler(ctx, w, r, vars)
|
return handler(ctx, w, r, vars)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,15 +8,15 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containerd/log"
|
||||||
"github.com/docker/docker/api/server/httputils"
|
"github.com/docker/docker/api/server/httputils"
|
||||||
"github.com/docker/docker/pkg/ioutils"
|
"github.com/docker/docker/pkg/ioutils"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// DebugRequestMiddleware dumps the request to logger
|
// DebugRequestMiddleware dumps the request to logger
|
||||||
func DebugRequestMiddleware(handler func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error) func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func DebugRequestMiddleware(handler func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error) func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
logrus.Debugf("Calling %s %s", r.Method, r.RequestURI)
|
log.G(ctx).Debugf("Calling %s %s", r.Method, r.RequestURI)
|
||||||
|
|
||||||
if r.Method != http.MethodPost {
|
if r.Method != http.MethodPost {
|
||||||
return handler(ctx, w, r, vars)
|
return handler(ctx, w, r, vars)
|
||||||
|
@ -44,9 +44,9 @@ func DebugRequestMiddleware(handler func(ctx context.Context, w http.ResponseWri
|
||||||
maskSecretKeys(postForm)
|
maskSecretKeys(postForm)
|
||||||
formStr, errMarshal := json.Marshal(postForm)
|
formStr, errMarshal := json.Marshal(postForm)
|
||||||
if errMarshal == nil {
|
if errMarshal == nil {
|
||||||
logrus.Debugf("form data: %s", string(formStr))
|
log.G(ctx).Debugf("form data: %s", string(formStr))
|
||||||
} else {
|
} else {
|
||||||
logrus.Debugf("form data: %q", postForm)
|
log.G(ctx).Debugf("form data: %q", postForm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/docker/docker/api"
|
||||||
"github.com/docker/docker/api/server/httputils"
|
"github.com/docker/docker/api/server/httputils"
|
||||||
"github.com/docker/docker/api/types/versions"
|
"github.com/docker/docker/api/types/versions"
|
||||||
)
|
)
|
||||||
|
@ -13,19 +14,40 @@ import (
|
||||||
// VersionMiddleware is a middleware that
|
// VersionMiddleware is a middleware that
|
||||||
// validates the client and server versions.
|
// validates the client and server versions.
|
||||||
type VersionMiddleware struct {
|
type VersionMiddleware struct {
|
||||||
serverVersion string
|
serverVersion string
|
||||||
defaultVersion string
|
|
||||||
minVersion string
|
// defaultAPIVersion is the default API version provided by the API server,
|
||||||
|
// specified as "major.minor". It is usually configured to the latest API
|
||||||
|
// version [github.com/docker/docker/api.DefaultVersion].
|
||||||
|
//
|
||||||
|
// API requests for API versions greater than this version are rejected by
|
||||||
|
// the server and produce a [versionUnsupportedError].
|
||||||
|
defaultAPIVersion string
|
||||||
|
|
||||||
|
// minAPIVersion is the minimum API version provided by the API server,
|
||||||
|
// specified as "major.minor".
|
||||||
|
//
|
||||||
|
// API requests for API versions lower than this version are rejected by
|
||||||
|
// the server and produce a [versionUnsupportedError].
|
||||||
|
minAPIVersion string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewVersionMiddleware creates a new VersionMiddleware
|
// NewVersionMiddleware creates a VersionMiddleware with the given versions.
|
||||||
// with the default versions.
|
func NewVersionMiddleware(serverVersion, defaultAPIVersion, minAPIVersion string) (*VersionMiddleware, error) {
|
||||||
func NewVersionMiddleware(s, d, m string) VersionMiddleware {
|
if versions.LessThan(defaultAPIVersion, api.MinSupportedAPIVersion) || versions.GreaterThan(defaultAPIVersion, api.DefaultVersion) {
|
||||||
return VersionMiddleware{
|
return nil, fmt.Errorf("invalid default API version (%s): must be between %s and %s", defaultAPIVersion, api.MinSupportedAPIVersion, api.DefaultVersion)
|
||||||
serverVersion: s,
|
|
||||||
defaultVersion: d,
|
|
||||||
minVersion: m,
|
|
||||||
}
|
}
|
||||||
|
if versions.LessThan(minAPIVersion, api.MinSupportedAPIVersion) || versions.GreaterThan(minAPIVersion, api.DefaultVersion) {
|
||||||
|
return nil, fmt.Errorf("invalid minimum API version (%s): must be between %s and %s", minAPIVersion, api.MinSupportedAPIVersion, api.DefaultVersion)
|
||||||
|
}
|
||||||
|
if versions.GreaterThan(minAPIVersion, defaultAPIVersion) {
|
||||||
|
return nil, fmt.Errorf("invalid API version: the minimum API version (%s) is higher than the default version (%s)", minAPIVersion, defaultAPIVersion)
|
||||||
|
}
|
||||||
|
return &VersionMiddleware{
|
||||||
|
serverVersion: serverVersion,
|
||||||
|
defaultAPIVersion: defaultAPIVersion,
|
||||||
|
minAPIVersion: minAPIVersion,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type versionUnsupportedError struct {
|
type versionUnsupportedError struct {
|
||||||
|
@ -45,18 +67,18 @@ func (e versionUnsupportedError) InvalidParameter() {}
|
||||||
func (v VersionMiddleware) WrapHandler(handler func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error) func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (v VersionMiddleware) WrapHandler(handler func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error) func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
w.Header().Set("Server", fmt.Sprintf("Docker/%s (%s)", v.serverVersion, runtime.GOOS))
|
w.Header().Set("Server", fmt.Sprintf("Docker/%s (%s)", v.serverVersion, runtime.GOOS))
|
||||||
w.Header().Set("API-Version", v.defaultVersion)
|
w.Header().Set("API-Version", v.defaultAPIVersion)
|
||||||
w.Header().Set("OSType", runtime.GOOS)
|
w.Header().Set("OSType", runtime.GOOS)
|
||||||
|
|
||||||
apiVersion := vars["version"]
|
apiVersion := vars["version"]
|
||||||
if apiVersion == "" {
|
if apiVersion == "" {
|
||||||
apiVersion = v.defaultVersion
|
apiVersion = v.defaultAPIVersion
|
||||||
}
|
}
|
||||||
if versions.LessThan(apiVersion, v.minVersion) {
|
if versions.LessThan(apiVersion, v.minAPIVersion) {
|
||||||
return versionUnsupportedError{version: apiVersion, minVersion: v.minVersion}
|
return versionUnsupportedError{version: apiVersion, minVersion: v.minAPIVersion}
|
||||||
}
|
}
|
||||||
if versions.GreaterThan(apiVersion, v.defaultVersion) {
|
if versions.GreaterThan(apiVersion, v.defaultAPIVersion) {
|
||||||
return versionUnsupportedError{version: apiVersion, maxVersion: v.defaultVersion}
|
return versionUnsupportedError{version: apiVersion, maxVersion: v.defaultAPIVersion}
|
||||||
}
|
}
|
||||||
ctx = context.WithValue(ctx, httputils.APIVersionKey{}, apiVersion)
|
ctx = context.WithValue(ctx, httputils.APIVersionKey{}, apiVersion)
|
||||||
return handler(ctx, w, r, vars)
|
return handler(ctx, w, r, vars)
|
||||||
|
|
|
@ -2,27 +2,82 @@ package middleware // import "github.com/docker/docker/api/server/middleware"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/docker/docker/api"
|
||||||
"github.com/docker/docker/api/server/httputils"
|
"github.com/docker/docker/api/server/httputils"
|
||||||
"gotest.tools/v3/assert"
|
"gotest.tools/v3/assert"
|
||||||
is "gotest.tools/v3/assert/cmp"
|
is "gotest.tools/v3/assert/cmp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestNewVersionMiddlewareValidation(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
doc, defaultVersion, minVersion, expectedErr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
doc: "defaults",
|
||||||
|
defaultVersion: api.DefaultVersion,
|
||||||
|
minVersion: api.MinSupportedAPIVersion,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "invalid default lower than min",
|
||||||
|
defaultVersion: api.MinSupportedAPIVersion,
|
||||||
|
minVersion: api.DefaultVersion,
|
||||||
|
expectedErr: fmt.Sprintf("invalid API version: the minimum API version (%s) is higher than the default version (%s)", api.DefaultVersion, api.MinSupportedAPIVersion),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "invalid default too low",
|
||||||
|
defaultVersion: "0.1",
|
||||||
|
minVersion: api.MinSupportedAPIVersion,
|
||||||
|
expectedErr: fmt.Sprintf("invalid default API version (0.1): must be between %s and %s", api.MinSupportedAPIVersion, api.DefaultVersion),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "invalid default too high",
|
||||||
|
defaultVersion: "9999.9999",
|
||||||
|
minVersion: api.DefaultVersion,
|
||||||
|
expectedErr: fmt.Sprintf("invalid default API version (9999.9999): must be between %s and %s", api.MinSupportedAPIVersion, api.DefaultVersion),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "invalid minimum too low",
|
||||||
|
defaultVersion: api.MinSupportedAPIVersion,
|
||||||
|
minVersion: "0.1",
|
||||||
|
expectedErr: fmt.Sprintf("invalid minimum API version (0.1): must be between %s and %s", api.MinSupportedAPIVersion, api.DefaultVersion),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "invalid minimum too high",
|
||||||
|
defaultVersion: api.DefaultVersion,
|
||||||
|
minVersion: "9999.9999",
|
||||||
|
expectedErr: fmt.Sprintf("invalid minimum API version (9999.9999): must be between %s and %s", api.MinSupportedAPIVersion, api.DefaultVersion),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
tc := tc
|
||||||
|
t.Run(tc.doc, func(t *testing.T) {
|
||||||
|
_, err := NewVersionMiddleware("1.2.3", tc.defaultVersion, tc.minVersion)
|
||||||
|
if tc.expectedErr == "" {
|
||||||
|
assert.Check(t, err)
|
||||||
|
} else {
|
||||||
|
assert.Check(t, is.Error(err, tc.expectedErr))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestVersionMiddlewareVersion(t *testing.T) {
|
func TestVersionMiddlewareVersion(t *testing.T) {
|
||||||
defaultVersion := "1.10.0"
|
expectedVersion := "<not set>"
|
||||||
minVersion := "1.2.0"
|
|
||||||
expectedVersion := defaultVersion
|
|
||||||
handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
v := httputils.VersionFromContext(ctx)
|
v := httputils.VersionFromContext(ctx)
|
||||||
assert.Check(t, is.Equal(expectedVersion, v))
|
assert.Check(t, is.Equal(expectedVersion, v))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
m := NewVersionMiddleware(defaultVersion, defaultVersion, minVersion)
|
m, err := NewVersionMiddleware("1.2.3", api.DefaultVersion, api.MinSupportedAPIVersion)
|
||||||
|
assert.NilError(t, err)
|
||||||
h := m.WrapHandler(handler)
|
h := m.WrapHandler(handler)
|
||||||
|
|
||||||
req, _ := http.NewRequest(http.MethodGet, "/containers/json", nil)
|
req, _ := http.NewRequest(http.MethodGet, "/containers/json", nil)
|
||||||
|
@ -35,19 +90,19 @@ func TestVersionMiddlewareVersion(t *testing.T) {
|
||||||
errString string
|
errString string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
expectedVersion: "1.10.0",
|
expectedVersion: api.DefaultVersion,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
reqVersion: "1.9.0",
|
reqVersion: api.MinSupportedAPIVersion,
|
||||||
expectedVersion: "1.9.0",
|
expectedVersion: api.MinSupportedAPIVersion,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
reqVersion: "0.1",
|
reqVersion: "0.1",
|
||||||
errString: "client version 0.1 is too old. Minimum supported API version is 1.2.0, please upgrade your client to a newer version",
|
errString: fmt.Sprintf("client version 0.1 is too old. Minimum supported API version is %s, please upgrade your client to a newer version", api.MinSupportedAPIVersion),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
reqVersion: "9999.9999",
|
reqVersion: "9999.9999",
|
||||||
errString: "client version 9999.9999 is too new. Maximum supported API version is 1.10.0",
|
errString: fmt.Sprintf("client version 9999.9999 is too new. Maximum supported API version is %s", api.DefaultVersion),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,9 +126,8 @@ func TestVersionMiddlewareWithErrorsReturnsHeaders(t *testing.T) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultVersion := "1.10.0"
|
m, err := NewVersionMiddleware("1.2.3", api.DefaultVersion, api.MinSupportedAPIVersion)
|
||||||
minVersion := "1.2.0"
|
assert.NilError(t, err)
|
||||||
m := NewVersionMiddleware(defaultVersion, defaultVersion, minVersion)
|
|
||||||
h := m.WrapHandler(handler)
|
h := m.WrapHandler(handler)
|
||||||
|
|
||||||
req, _ := http.NewRequest(http.MethodGet, "/containers/json", nil)
|
req, _ := http.NewRequest(http.MethodGet, "/containers/json", nil)
|
||||||
|
@ -81,12 +135,12 @@ func TestVersionMiddlewareWithErrorsReturnsHeaders(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
vars := map[string]string{"version": "0.1"}
|
vars := map[string]string{"version": "0.1"}
|
||||||
err := h(ctx, resp, req, vars)
|
err = h(ctx, resp, req, vars)
|
||||||
assert.Check(t, is.ErrorContains(err, ""))
|
assert.Check(t, is.ErrorContains(err, ""))
|
||||||
|
|
||||||
hdr := resp.Result().Header
|
hdr := resp.Result().Header
|
||||||
assert.Check(t, is.Contains(hdr.Get("Server"), "Docker/"+defaultVersion))
|
assert.Check(t, is.Contains(hdr.Get("Server"), "Docker/1.2.3"))
|
||||||
assert.Check(t, is.Contains(hdr.Get("Server"), runtime.GOOS))
|
assert.Check(t, is.Contains(hdr.Get("Server"), runtime.GOOS))
|
||||||
assert.Check(t, is.Equal(hdr.Get("API-Version"), defaultVersion))
|
assert.Check(t, is.Equal(hdr.Get("API-Version"), api.DefaultVersion))
|
||||||
assert.Check(t, is.Equal(hdr.Get("OSType"), runtime.GOOS))
|
assert.Check(t, is.Equal(hdr.Get("OSType"), runtime.GOOS))
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@ type Backend interface {
|
||||||
|
|
||||||
// Prune build cache
|
// Prune build cache
|
||||||
PruneCache(context.Context, types.BuildCachePruneOptions) (*types.BuildCachePruneReport, error)
|
PruneCache(context.Context, types.BuildCachePruneOptions) (*types.BuildCachePruneReport, error)
|
||||||
|
|
||||||
Cancel(context.Context, string) error
|
Cancel(context.Context, string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,18 +9,16 @@ import (
|
||||||
|
|
||||||
// buildRouter is a router to talk with the build controller
|
// buildRouter is a router to talk with the build controller
|
||||||
type buildRouter struct {
|
type buildRouter struct {
|
||||||
backend Backend
|
backend Backend
|
||||||
daemon experimentalProvider
|
daemon experimentalProvider
|
||||||
routes []router.Route
|
routes []router.Route
|
||||||
features *map[string]bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRouter initializes a new build router
|
// NewRouter initializes a new build router
|
||||||
func NewRouter(b Backend, d experimentalProvider, features *map[string]bool) router.Router {
|
func NewRouter(b Backend, d experimentalProvider) router.Router {
|
||||||
r := &buildRouter{
|
r := &buildRouter{
|
||||||
backend: b,
|
backend: b,
|
||||||
daemon: d,
|
daemon: d,
|
||||||
features: features,
|
|
||||||
}
|
}
|
||||||
r.initRoutes()
|
r.initRoutes()
|
||||||
return r
|
return r
|
||||||
|
|
|
@ -14,28 +14,26 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/containerd/log"
|
||||||
"github.com/docker/docker/api/server/httputils"
|
"github.com/docker/docker/api/server/httputils"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/backend"
|
"github.com/docker/docker/api/types/backend"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
|
"github.com/docker/docker/api/types/registry"
|
||||||
"github.com/docker/docker/api/types/versions"
|
"github.com/docker/docker/api/types/versions"
|
||||||
"github.com/docker/docker/errdefs"
|
|
||||||
"github.com/docker/docker/pkg/ioutils"
|
"github.com/docker/docker/pkg/ioutils"
|
||||||
"github.com/docker/docker/pkg/progress"
|
"github.com/docker/docker/pkg/progress"
|
||||||
"github.com/docker/docker/pkg/streamformatter"
|
"github.com/docker/docker/pkg/streamformatter"
|
||||||
units "github.com/docker/go-units"
|
units "github.com/docker/go-units"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type invalidIsolationError string
|
type invalidParam struct {
|
||||||
|
error
|
||||||
func (e invalidIsolationError) Error() string {
|
|
||||||
return fmt.Sprintf("Unsupported isolation: %q", string(e))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e invalidIsolationError) InvalidParameter() {}
|
func (e invalidParam) InvalidParameter() {}
|
||||||
|
|
||||||
func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBuildOptions, error) {
|
func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBuildOptions, error) {
|
||||||
options := &types.ImageBuildOptions{
|
options := &types.ImageBuildOptions{
|
||||||
|
@ -44,6 +42,7 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui
|
||||||
SuppressOutput: httputils.BoolValue(r, "q"),
|
SuppressOutput: httputils.BoolValue(r, "q"),
|
||||||
NoCache: httputils.BoolValue(r, "nocache"),
|
NoCache: httputils.BoolValue(r, "nocache"),
|
||||||
ForceRemove: httputils.BoolValue(r, "forcerm"),
|
ForceRemove: httputils.BoolValue(r, "forcerm"),
|
||||||
|
PullParent: httputils.BoolValue(r, "pull"),
|
||||||
MemorySwap: httputils.Int64ValueOrZero(r, "memswap"),
|
MemorySwap: httputils.Int64ValueOrZero(r, "memswap"),
|
||||||
Memory: httputils.Int64ValueOrZero(r, "memory"),
|
Memory: httputils.Int64ValueOrZero(r, "memory"),
|
||||||
CPUShares: httputils.Int64ValueOrZero(r, "cpushares"),
|
CPUShares: httputils.Int64ValueOrZero(r, "cpushares"),
|
||||||
|
@ -64,20 +63,18 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui
|
||||||
}
|
}
|
||||||
|
|
||||||
if runtime.GOOS != "windows" && options.SecurityOpt != nil {
|
if runtime.GOOS != "windows" && options.SecurityOpt != nil {
|
||||||
return nil, errdefs.InvalidParameter(errors.New("The daemon on this platform does not support setting security options on build"))
|
// SecurityOpt only supports "credentials-spec" on Windows, and not used on other platforms.
|
||||||
|
return nil, invalidParam{errors.New("security options are not supported on " + runtime.GOOS)}
|
||||||
}
|
}
|
||||||
|
|
||||||
version := httputils.VersionFromContext(ctx)
|
if httputils.BoolValue(r, "forcerm") {
|
||||||
if httputils.BoolValue(r, "forcerm") && versions.GreaterThanOrEqualTo(version, "1.12") {
|
|
||||||
options.Remove = true
|
options.Remove = true
|
||||||
} else if r.FormValue("rm") == "" && versions.GreaterThanOrEqualTo(version, "1.12") {
|
} else if r.FormValue("rm") == "" {
|
||||||
options.Remove = true
|
options.Remove = true
|
||||||
} else {
|
} else {
|
||||||
options.Remove = httputils.BoolValue(r, "rm")
|
options.Remove = httputils.BoolValue(r, "rm")
|
||||||
}
|
}
|
||||||
if httputils.BoolValue(r, "pull") && versions.GreaterThanOrEqualTo(version, "1.16") {
|
version := httputils.VersionFromContext(ctx)
|
||||||
options.PullParent = true
|
|
||||||
}
|
|
||||||
if versions.GreaterThanOrEqualTo(version, "1.32") {
|
if versions.GreaterThanOrEqualTo(version, "1.32") {
|
||||||
options.Platform = r.FormValue("platform")
|
options.Platform = r.FormValue("platform")
|
||||||
}
|
}
|
||||||
|
@ -86,7 +83,7 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui
|
||||||
if outputsJSON != "" {
|
if outputsJSON != "" {
|
||||||
var outputs []types.ImageBuildOutput
|
var outputs []types.ImageBuildOutput
|
||||||
if err := json.Unmarshal([]byte(outputsJSON), &outputs); err != nil {
|
if err := json.Unmarshal([]byte(outputsJSON), &outputs); err != nil {
|
||||||
return nil, err
|
return nil, invalidParam{errors.Wrap(err, "invalid outputs specified")}
|
||||||
}
|
}
|
||||||
options.Outputs = outputs
|
options.Outputs = outputs
|
||||||
}
|
}
|
||||||
|
@ -103,14 +100,14 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui
|
||||||
if i := r.FormValue("isolation"); i != "" {
|
if i := r.FormValue("isolation"); i != "" {
|
||||||
options.Isolation = container.Isolation(i)
|
options.Isolation = container.Isolation(i)
|
||||||
if !options.Isolation.IsValid() {
|
if !options.Isolation.IsValid() {
|
||||||
return nil, invalidIsolationError(options.Isolation)
|
return nil, invalidParam{errors.Errorf("unsupported isolation: %q", i)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ulimitsJSON := r.FormValue("ulimits"); ulimitsJSON != "" {
|
if ulimitsJSON := r.FormValue("ulimits"); ulimitsJSON != "" {
|
||||||
var buildUlimits = []*units.Ulimit{}
|
buildUlimits := []*units.Ulimit{}
|
||||||
if err := json.Unmarshal([]byte(ulimitsJSON), &buildUlimits); err != nil {
|
if err := json.Unmarshal([]byte(ulimitsJSON), &buildUlimits); err != nil {
|
||||||
return nil, errors.Wrap(errdefs.InvalidParameter(err), "error reading ulimit settings")
|
return nil, invalidParam{errors.Wrap(err, "error reading ulimit settings")}
|
||||||
}
|
}
|
||||||
options.Ulimits = buildUlimits
|
options.Ulimits = buildUlimits
|
||||||
}
|
}
|
||||||
|
@ -128,25 +125,25 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui
|
||||||
// so that it can print a warning about "foo" being unused if there is
|
// so that it can print a warning about "foo" being unused if there is
|
||||||
// no "ARG foo" in the Dockerfile.
|
// no "ARG foo" in the Dockerfile.
|
||||||
if buildArgsJSON := r.FormValue("buildargs"); buildArgsJSON != "" {
|
if buildArgsJSON := r.FormValue("buildargs"); buildArgsJSON != "" {
|
||||||
var buildArgs = map[string]*string{}
|
buildArgs := map[string]*string{}
|
||||||
if err := json.Unmarshal([]byte(buildArgsJSON), &buildArgs); err != nil {
|
if err := json.Unmarshal([]byte(buildArgsJSON), &buildArgs); err != nil {
|
||||||
return nil, errors.Wrap(errdefs.InvalidParameter(err), "error reading build args")
|
return nil, invalidParam{errors.Wrap(err, "error reading build args")}
|
||||||
}
|
}
|
||||||
options.BuildArgs = buildArgs
|
options.BuildArgs = buildArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
if labelsJSON := r.FormValue("labels"); labelsJSON != "" {
|
if labelsJSON := r.FormValue("labels"); labelsJSON != "" {
|
||||||
var labels = map[string]string{}
|
labels := map[string]string{}
|
||||||
if err := json.Unmarshal([]byte(labelsJSON), &labels); err != nil {
|
if err := json.Unmarshal([]byte(labelsJSON), &labels); err != nil {
|
||||||
return nil, errors.Wrap(errdefs.InvalidParameter(err), "error reading labels")
|
return nil, invalidParam{errors.Wrap(err, "error reading labels")}
|
||||||
}
|
}
|
||||||
options.Labels = labels
|
options.Labels = labels
|
||||||
}
|
}
|
||||||
|
|
||||||
if cacheFromJSON := r.FormValue("cachefrom"); cacheFromJSON != "" {
|
if cacheFromJSON := r.FormValue("cachefrom"); cacheFromJSON != "" {
|
||||||
var cacheFrom = []string{}
|
cacheFrom := []string{}
|
||||||
if err := json.Unmarshal([]byte(cacheFromJSON), &cacheFrom); err != nil {
|
if err := json.Unmarshal([]byte(cacheFromJSON), &cacheFrom); err != nil {
|
||||||
return nil, err
|
return nil, invalidParam{errors.Wrap(err, "error reading cache-from")}
|
||||||
}
|
}
|
||||||
options.CacheFrom = cacheFrom
|
options.CacheFrom = cacheFrom
|
||||||
}
|
}
|
||||||
|
@ -169,7 +166,7 @@ func parseVersion(s string) (types.BuilderVersion, error) {
|
||||||
case types.BuilderBuildKit:
|
case types.BuilderBuildKit:
|
||||||
return types.BuilderBuildKit, nil
|
return types.BuilderBuildKit, nil
|
||||||
default:
|
default:
|
||||||
return "", errors.Errorf("invalid version %q", s)
|
return "", invalidParam{errors.Errorf("invalid version %q", s)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +176,7 @@ func (br *buildRouter) postPrune(ctx context.Context, w http.ResponseWriter, r *
|
||||||
}
|
}
|
||||||
fltrs, err := filters.FromJSON(r.Form.Get("filters"))
|
fltrs, err := filters.FromJSON(r.Form.Get("filters"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "could not parse filters")
|
return err
|
||||||
}
|
}
|
||||||
ksfv := r.FormValue("keep-storage")
|
ksfv := r.FormValue("keep-storage")
|
||||||
if ksfv == "" {
|
if ksfv == "" {
|
||||||
|
@ -187,7 +184,7 @@ func (br *buildRouter) postPrune(ctx context.Context, w http.ResponseWriter, r *
|
||||||
}
|
}
|
||||||
ks, err := strconv.Atoi(ksfv)
|
ks, err := strconv.Atoi(ksfv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "keep-storage is in bytes and expects an integer, got %v", ksfv)
|
return invalidParam{errors.Wrapf(err, "keep-storage is in bytes and expects an integer, got %v", ksfv)}
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := types.BuildCachePruneOptions{
|
opts := types.BuildCachePruneOptions{
|
||||||
|
@ -208,7 +205,7 @@ func (br *buildRouter) postCancel(ctx context.Context, w http.ResponseWriter, r
|
||||||
|
|
||||||
id := r.FormValue("id")
|
id := r.FormValue("id")
|
||||||
if id == "" {
|
if id == "" {
|
||||||
return errors.Errorf("build ID not provided")
|
return invalidParam{errors.New("build ID not provided")}
|
||||||
}
|
}
|
||||||
|
|
||||||
return br.backend.Cancel(ctx, id)
|
return br.backend.Cancel(ctx, id)
|
||||||
|
@ -249,7 +246,7 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
|
||||||
}
|
}
|
||||||
_, err = output.Write(streamformatter.FormatError(err))
|
_, err = output.Write(streamformatter.FormatError(err))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Warnf("could not write error response: %v", err)
|
log.G(ctx).Warnf("could not write error response: %v", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -261,7 +258,7 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
|
||||||
buildOptions.AuthConfigs = getAuthConfigs(r.Header)
|
buildOptions.AuthConfigs = getAuthConfigs(r.Header)
|
||||||
|
|
||||||
if buildOptions.Squash && !br.daemon.HasExperimental() {
|
if buildOptions.Squash && !br.daemon.HasExperimental() {
|
||||||
return errdefs.InvalidParameter(errors.New("squash is only supported with experimental mode"))
|
return invalidParam{errors.New("squash is only supported with experimental mode")}
|
||||||
}
|
}
|
||||||
|
|
||||||
out := io.Writer(output)
|
out := io.Writer(output)
|
||||||
|
@ -295,8 +292,8 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAuthConfigs(header http.Header) map[string]types.AuthConfig {
|
func getAuthConfigs(header http.Header) map[string]registry.AuthConfig {
|
||||||
authConfigs := map[string]types.AuthConfig{}
|
authConfigs := map[string]registry.AuthConfig{}
|
||||||
authConfigsEncoded := header.Get("X-Registry-Config")
|
authConfigsEncoded := header.Get("X-Registry-Config")
|
||||||
|
|
||||||
if authConfigsEncoded == "" {
|
if authConfigsEncoded == "" {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package checkpoint // import "github.com/docker/docker/api/server/router/checkpoint"
|
package checkpoint // import "github.com/docker/docker/api/server/router/checkpoint"
|
||||||
|
|
||||||
import "github.com/docker/docker/api/types"
|
import "github.com/docker/docker/api/types/checkpoint"
|
||||||
|
|
||||||
// Backend for Checkpoint
|
// Backend for Checkpoint
|
||||||
type Backend interface {
|
type Backend interface {
|
||||||
CheckpointCreate(container string, config types.CheckpointCreateOptions) error
|
CheckpointCreate(container string, config checkpoint.CreateOptions) error
|
||||||
CheckpointDelete(container string, config types.CheckpointDeleteOptions) error
|
CheckpointDelete(container string, config checkpoint.DeleteOptions) error
|
||||||
CheckpointList(container string, config types.CheckpointListOptions) ([]types.Checkpoint, error)
|
CheckpointList(container string, config checkpoint.ListOptions) ([]checkpoint.Summary, error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/docker/docker/api/server/httputils"
|
"github.com/docker/docker/api/server/httputils"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types/checkpoint"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *checkpointRouter) postContainerCheckpoint(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (s *checkpointRouter) postContainerCheckpoint(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
|
@ -13,7 +13,7 @@ func (s *checkpointRouter) postContainerCheckpoint(ctx context.Context, w http.R
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var options types.CheckpointCreateOptions
|
var options checkpoint.CreateOptions
|
||||||
if err := httputils.ReadJSON(r, &options); err != nil {
|
if err := httputils.ReadJSON(r, &options); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -32,10 +32,9 @@ func (s *checkpointRouter) getContainerCheckpoints(ctx context.Context, w http.R
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
checkpoints, err := s.backend.CheckpointList(vars["name"], types.CheckpointListOptions{
|
checkpoints, err := s.backend.CheckpointList(vars["name"], checkpoint.ListOptions{
|
||||||
CheckpointDir: r.Form.Get("dir"),
|
CheckpointDir: r.Form.Get("dir"),
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -48,11 +47,10 @@ func (s *checkpointRouter) deleteContainerCheckpoint(ctx context.Context, w http
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err := s.backend.CheckpointDelete(vars["name"], types.CheckpointDeleteOptions{
|
err := s.backend.CheckpointDelete(vars["name"], checkpoint.DeleteOptions{
|
||||||
CheckpointDir: r.Form.Get("dir"),
|
CheckpointDir: r.Form.Get("dir"),
|
||||||
CheckpointID: vars["checkpoint"],
|
CheckpointID: vars["checkpoint"],
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,22 +24,21 @@ type execBackend interface {
|
||||||
// copyBackend includes functions to implement to provide container copy functionality.
|
// copyBackend includes functions to implement to provide container copy functionality.
|
||||||
type copyBackend interface {
|
type copyBackend interface {
|
||||||
ContainerArchivePath(name string, path string) (content io.ReadCloser, stat *types.ContainerPathStat, err error)
|
ContainerArchivePath(name string, path string) (content io.ReadCloser, stat *types.ContainerPathStat, err error)
|
||||||
ContainerCopy(name string, res string) (io.ReadCloser, error)
|
ContainerExport(ctx context.Context, name string, out io.Writer) error
|
||||||
ContainerExport(name string, out io.Writer) error
|
|
||||||
ContainerExtractToDir(name, path string, copyUIDGID, noOverwriteDirNonDir bool, content io.Reader) error
|
ContainerExtractToDir(name, path string, copyUIDGID, noOverwriteDirNonDir bool, content io.Reader) error
|
||||||
ContainerStatPath(name string, path string) (stat *types.ContainerPathStat, err error)
|
ContainerStatPath(name string, path string) (stat *types.ContainerPathStat, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// stateBackend includes functions to implement to provide container state lifecycle functionality.
|
// stateBackend includes functions to implement to provide container state lifecycle functionality.
|
||||||
type stateBackend interface {
|
type stateBackend interface {
|
||||||
ContainerCreate(config types.ContainerCreateConfig) (container.CreateResponse, error)
|
ContainerCreate(ctx context.Context, config backend.ContainerCreateConfig) (container.CreateResponse, error)
|
||||||
ContainerKill(name string, signal string) error
|
ContainerKill(name string, signal string) error
|
||||||
ContainerPause(name string) error
|
ContainerPause(name string) error
|
||||||
ContainerRename(oldName, newName string) error
|
ContainerRename(oldName, newName string) error
|
||||||
ContainerResize(name string, height, width int) error
|
ContainerResize(name string, height, width int) error
|
||||||
ContainerRestart(ctx context.Context, name string, options container.StopOptions) error
|
ContainerRestart(ctx context.Context, name string, options container.StopOptions) error
|
||||||
ContainerRm(name string, config *types.ContainerRmConfig) error
|
ContainerRm(name string, config *backend.ContainerRmConfig) error
|
||||||
ContainerStart(name string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
|
ContainerStart(ctx context.Context, name string, checkpoint string, checkpointDir string) error
|
||||||
ContainerStop(ctx context.Context, name string, options container.StopOptions) error
|
ContainerStop(ctx context.Context, name string, options container.StopOptions) error
|
||||||
ContainerUnpause(name string) error
|
ContainerUnpause(name string) error
|
||||||
ContainerUpdate(name string, hostConfig *container.HostConfig) (container.ContainerUpdateOKBody, error)
|
ContainerUpdate(name string, hostConfig *container.HostConfig) (container.ContainerUpdateOKBody, error)
|
||||||
|
@ -48,13 +47,12 @@ type stateBackend interface {
|
||||||
|
|
||||||
// monitorBackend includes functions to implement to provide containers monitoring functionality.
|
// monitorBackend includes functions to implement to provide containers monitoring functionality.
|
||||||
type monitorBackend interface {
|
type monitorBackend interface {
|
||||||
ContainerChanges(name string) ([]archive.Change, error)
|
ContainerChanges(ctx context.Context, name string) ([]archive.Change, error)
|
||||||
ContainerInspect(name string, size bool, version string) (interface{}, error)
|
ContainerInspect(ctx context.Context, name string, size bool, version string) (interface{}, error)
|
||||||
ContainerLogs(ctx context.Context, name string, config *types.ContainerLogsOptions) (msgs <-chan *backend.LogMessage, tty bool, err error)
|
ContainerLogs(ctx context.Context, name string, config *container.LogsOptions) (msgs <-chan *backend.LogMessage, tty bool, err error)
|
||||||
ContainerStats(ctx context.Context, name string, config *backend.ContainerStatsConfig) error
|
ContainerStats(ctx context.Context, name string, config *backend.ContainerStatsConfig) error
|
||||||
ContainerTop(name string, psArgs string) (*container.ContainerTopOKBody, error)
|
ContainerTop(name string, psArgs string) (*container.ContainerTopOKBody, error)
|
||||||
|
Containers(ctx context.Context, config *container.ListOptions) ([]*types.Container, error)
|
||||||
Containers(config *types.ContainerListOptions) ([]*types.Container, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// attachBackend includes function to implement to provide container attaching functionality.
|
// attachBackend includes function to implement to provide container attaching functionality.
|
||||||
|
@ -68,7 +66,7 @@ type systemBackend interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type commitBackend interface {
|
type commitBackend interface {
|
||||||
CreateImageFromContainer(name string, config *backend.CreateImageConfig) (imageID string, err error)
|
CreateImageFromContainer(ctx context.Context, name string, config *backend.CreateImageConfig) (imageID string, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Backend is all the methods that need to be implemented to provide container specific functionality.
|
// Backend is all the methods that need to be implemented to provide container specific functionality.
|
||||||
|
|
|
@ -56,7 +56,6 @@ func (r *containerRouter) initRoutes() {
|
||||||
router.NewPostRoute("/containers/{name:.*}/wait", r.postContainersWait),
|
router.NewPostRoute("/containers/{name:.*}/wait", r.postContainersWait),
|
||||||
router.NewPostRoute("/containers/{name:.*}/resize", r.postContainersResize),
|
router.NewPostRoute("/containers/{name:.*}/resize", r.postContainersResize),
|
||||||
router.NewPostRoute("/containers/{name:.*}/attach", r.postContainersAttach),
|
router.NewPostRoute("/containers/{name:.*}/attach", r.postContainersAttach),
|
||||||
router.NewPostRoute("/containers/{name:.*}/copy", r.postContainersCopy), // Deprecated since 1.8 (API v1.20), errors out since 1.12 (API v1.24)
|
|
||||||
router.NewPostRoute("/containers/{name:.*}/exec", r.postContainerExecCreate),
|
router.NewPostRoute("/containers/{name:.*}/exec", r.postContainerExecCreate),
|
||||||
router.NewPostRoute("/exec/{name:.*}/start", r.postContainerExecStart),
|
router.NewPostRoute("/exec/{name:.*}/start", r.postContainerExecStart),
|
||||||
router.NewPostRoute("/exec/{name:.*}/resize", r.postContainerExecResize),
|
router.NewPostRoute("/exec/{name:.*}/resize", r.postContainerExecResize),
|
||||||
|
|
|
@ -8,8 +8,10 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/containerd/containerd/platforms"
|
"github.com/containerd/containerd/platforms"
|
||||||
|
"github.com/containerd/log"
|
||||||
"github.com/docker/docker/api/server/httpstatus"
|
"github.com/docker/docker/api/server/httpstatus"
|
||||||
"github.com/docker/docker/api/server/httputils"
|
"github.com/docker/docker/api/server/httputils"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
|
@ -17,13 +19,14 @@ import (
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/api/types/mount"
|
"github.com/docker/docker/api/types/mount"
|
||||||
|
"github.com/docker/docker/api/types/network"
|
||||||
"github.com/docker/docker/api/types/versions"
|
"github.com/docker/docker/api/types/versions"
|
||||||
containerpkg "github.com/docker/docker/container"
|
containerpkg "github.com/docker/docker/container"
|
||||||
"github.com/docker/docker/errdefs"
|
"github.com/docker/docker/errdefs"
|
||||||
"github.com/docker/docker/pkg/ioutils"
|
"github.com/docker/docker/pkg/ioutils"
|
||||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
"github.com/docker/docker/runconfig"
|
||||||
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"golang.org/x/net/websocket"
|
"golang.org/x/net/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -36,29 +39,24 @@ func (s *containerRouter) postCommit(ctx context.Context, w http.ResponseWriter,
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove pause arg, and always pause in backend
|
|
||||||
pause := httputils.BoolValue(r, "pause")
|
|
||||||
version := httputils.VersionFromContext(ctx)
|
|
||||||
if r.FormValue("pause") == "" && versions.GreaterThanOrEqualTo(version, "1.13") {
|
|
||||||
pause = true
|
|
||||||
}
|
|
||||||
|
|
||||||
config, _, _, err := s.decoder.DecodeConfig(r.Body)
|
config, _, _, err := s.decoder.DecodeConfig(r.Body)
|
||||||
if err != nil && !errors.Is(err, io.EOF) { // Do not fail if body is empty.
|
if err != nil && !errors.Is(err, io.EOF) { // Do not fail if body is empty.
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
commitCfg := &backend.CreateImageConfig{
|
ref, err := httputils.RepoTagReference(r.Form.Get("repo"), r.Form.Get("tag"))
|
||||||
Pause: pause,
|
if err != nil {
|
||||||
Repo: r.Form.Get("repo"),
|
return errdefs.InvalidParameter(err)
|
||||||
Tag: r.Form.Get("tag"),
|
}
|
||||||
|
|
||||||
|
imgID, err := s.backend.CreateImageFromContainer(ctx, r.Form.Get("container"), &backend.CreateImageConfig{
|
||||||
|
Pause: httputils.BoolValueOrDefault(r, "pause", true), // TODO(dnephin): remove pause arg, and always pause in backend
|
||||||
|
Tag: ref,
|
||||||
Author: r.Form.Get("author"),
|
Author: r.Form.Get("author"),
|
||||||
Comment: r.Form.Get("comment"),
|
Comment: r.Form.Get("comment"),
|
||||||
Config: config,
|
Config: config,
|
||||||
Changes: r.Form["changes"],
|
Changes: r.Form["changes"],
|
||||||
}
|
})
|
||||||
|
|
||||||
imgID, err := s.backend.CreateImageFromContainer(r.Form.Get("container"), commitCfg)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -75,7 +73,7 @@ func (s *containerRouter) getContainersJSON(ctx context.Context, w http.Response
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &types.ContainerListOptions{
|
config := &container.ListOptions{
|
||||||
All: httputils.BoolValue(r, "all"),
|
All: httputils.BoolValue(r, "all"),
|
||||||
Size: httputils.BoolValue(r, "size"),
|
Size: httputils.BoolValue(r, "size"),
|
||||||
Since: r.Form.Get("since"),
|
Since: r.Form.Get("since"),
|
||||||
|
@ -91,7 +89,7 @@ func (s *containerRouter) getContainersJSON(ctx context.Context, w http.Response
|
||||||
config.Limit = limit
|
config.Limit = limit
|
||||||
}
|
}
|
||||||
|
|
||||||
containers, err := s.backend.Containers(config)
|
containers, err := s.backend.Containers(ctx, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -113,14 +111,11 @@ func (s *containerRouter) getContainersStats(ctx context.Context, w http.Respons
|
||||||
oneShot = httputils.BoolValueOrDefault(r, "one-shot", false)
|
oneShot = httputils.BoolValueOrDefault(r, "one-shot", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &backend.ContainerStatsConfig{
|
return s.backend.ContainerStats(ctx, vars["name"], &backend.ContainerStatsConfig{
|
||||||
Stream: stream,
|
Stream: stream,
|
||||||
OneShot: oneShot,
|
OneShot: oneShot,
|
||||||
OutStream: w,
|
OutStream: w,
|
||||||
Version: httputils.VersionFromContext(ctx),
|
})
|
||||||
}
|
|
||||||
|
|
||||||
return s.backend.ContainerStats(ctx, vars["name"], config)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *containerRouter) getContainersLogs(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (s *containerRouter) getContainersLogs(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
|
@ -139,7 +134,7 @@ func (s *containerRouter) getContainersLogs(ctx context.Context, w http.Response
|
||||||
}
|
}
|
||||||
|
|
||||||
containerName := vars["name"]
|
containerName := vars["name"]
|
||||||
logsConfig := &types.ContainerLogsOptions{
|
logsConfig := &container.LogsOptions{
|
||||||
Follow: httputils.BoolValue(r, "follow"),
|
Follow: httputils.BoolValue(r, "follow"),
|
||||||
Timestamps: httputils.BoolValue(r, "timestamps"),
|
Timestamps: httputils.BoolValue(r, "timestamps"),
|
||||||
Since: r.Form.Get("since"),
|
Since: r.Form.Get("since"),
|
||||||
|
@ -170,17 +165,9 @@ func (s *containerRouter) getContainersLogs(ctx context.Context, w http.Response
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *containerRouter) getContainersExport(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (s *containerRouter) getContainersExport(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
return s.backend.ContainerExport(vars["name"], w)
|
return s.backend.ContainerExport(ctx, vars["name"], w)
|
||||||
}
|
}
|
||||||
|
|
||||||
type bodyOnStartError struct{}
|
|
||||||
|
|
||||||
func (bodyOnStartError) Error() string {
|
|
||||||
return "starting container with non-empty request body was deprecated since API v1.22 and removed in v1.24"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bodyOnStartError) InvalidParameter() {}
|
|
||||||
|
|
||||||
func (s *containerRouter) postContainersStart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (s *containerRouter) postContainersStart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
// If contentLength is -1, we can assumed chunked encoding
|
// If contentLength is -1, we can assumed chunked encoding
|
||||||
// or more technically that the length is unknown
|
// or more technically that the length is unknown
|
||||||
|
@ -188,33 +175,17 @@ func (s *containerRouter) postContainersStart(ctx context.Context, w http.Respon
|
||||||
// net/http otherwise seems to swallow any headers related to chunked encoding
|
// net/http otherwise seems to swallow any headers related to chunked encoding
|
||||||
// including r.TransferEncoding
|
// including r.TransferEncoding
|
||||||
// allow a nil body for backwards compatibility
|
// allow a nil body for backwards compatibility
|
||||||
|
//
|
||||||
version := httputils.VersionFromContext(ctx)
|
|
||||||
var hostConfig *container.HostConfig
|
|
||||||
// A non-nil json object is at least 7 characters.
|
// A non-nil json object is at least 7 characters.
|
||||||
if r.ContentLength > 7 || r.ContentLength == -1 {
|
if r.ContentLength > 7 || r.ContentLength == -1 {
|
||||||
if versions.GreaterThanOrEqualTo(version, "1.24") {
|
return errdefs.InvalidParameter(errors.New("starting container with non-empty request body was deprecated since API v1.22 and removed in v1.24"))
|
||||||
return bodyOnStartError{}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := httputils.CheckForJSON(r); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
c, err := s.decoder.DecodeHostConfig(r.Body)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
hostConfig = c
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := httputils.ParseForm(r); err != nil {
|
if err := httputils.ParseForm(r); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
checkpoint := r.Form.Get("checkpoint")
|
if err := s.backend.ContainerStart(ctx, vars["name"], r.Form.Get("checkpoint"), r.Form.Get("checkpoint-dir")); err != nil {
|
||||||
checkpointDir := r.Form.Get("checkpoint-dir")
|
|
||||||
if err := s.backend.ContainerStart(vars["name"], hostConfig, checkpoint, checkpointDir); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,25 +221,14 @@ func (s *containerRouter) postContainersStop(ctx context.Context, w http.Respons
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *containerRouter) postContainersKill(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (s *containerRouter) postContainersKill(_ context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := httputils.ParseForm(r); err != nil {
|
if err := httputils.ParseForm(r); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
if err := s.backend.ContainerKill(name, r.Form.Get("signal")); err != nil {
|
if err := s.backend.ContainerKill(name, r.Form.Get("signal")); err != nil {
|
||||||
var isStopped bool
|
return errors.Wrapf(err, "cannot kill container: %s", name)
|
||||||
if errdefs.IsConflict(err) {
|
|
||||||
isStopped = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return error that's not caused because the container is stopped.
|
|
||||||
// Return error if the container is not running and the api is >= 1.20
|
|
||||||
// to keep backwards compatibility.
|
|
||||||
version := httputils.VersionFromContext(ctx)
|
|
||||||
if versions.GreaterThanOrEqualTo(version, "1.20") || !isStopped {
|
|
||||||
return errors.Wrapf(err, "Cannot kill container: %s", name)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
@ -397,7 +357,7 @@ func (s *containerRouter) postContainersWait(ctx context.Context, w http.Respons
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *containerRouter) getContainersChanges(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (s *containerRouter) getContainersChanges(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
changes, err := s.backend.ContainerChanges(vars["name"])
|
changes, err := s.backend.ContainerChanges(ctx, vars["name"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -489,21 +449,50 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config == nil {
|
||||||
|
return errdefs.InvalidParameter(runconfig.ErrEmptyConfig)
|
||||||
|
}
|
||||||
|
if hostConfig == nil {
|
||||||
|
hostConfig = &container.HostConfig{}
|
||||||
|
}
|
||||||
|
if networkingConfig == nil {
|
||||||
|
networkingConfig = &network.NetworkingConfig{}
|
||||||
|
}
|
||||||
|
if networkingConfig.EndpointsConfig == nil {
|
||||||
|
networkingConfig.EndpointsConfig = make(map[string]*network.EndpointSettings)
|
||||||
|
}
|
||||||
|
// The NetworkMode "default" is used as a way to express a container should
|
||||||
|
// be attached to the OS-dependant default network, in an OS-independent
|
||||||
|
// way. Doing this conversion as soon as possible ensures we have less
|
||||||
|
// NetworkMode to handle down the path (including in the
|
||||||
|
// backward-compatibility layer we have just below).
|
||||||
|
//
|
||||||
|
// Note that this is not the only place where this conversion has to be
|
||||||
|
// done (as there are various other places where containers get created).
|
||||||
|
if hostConfig.NetworkMode == "" || hostConfig.NetworkMode.IsDefault() {
|
||||||
|
hostConfig.NetworkMode = runconfig.DefaultDaemonNetworkMode()
|
||||||
|
if nw, ok := networkingConfig.EndpointsConfig[network.NetworkDefault]; ok {
|
||||||
|
networkingConfig.EndpointsConfig[hostConfig.NetworkMode.NetworkName()] = nw
|
||||||
|
delete(networkingConfig.EndpointsConfig, network.NetworkDefault)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
version := httputils.VersionFromContext(ctx)
|
version := httputils.VersionFromContext(ctx)
|
||||||
adjustCPUShares := versions.LessThan(version, "1.19")
|
|
||||||
|
|
||||||
// When using API 1.24 and under, the client is responsible for removing the container
|
// When using API 1.24 and under, the client is responsible for removing the container
|
||||||
if hostConfig != nil && versions.LessThan(version, "1.25") {
|
if versions.LessThan(version, "1.25") {
|
||||||
hostConfig.AutoRemove = false
|
hostConfig.AutoRemove = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if hostConfig != nil && versions.LessThan(version, "1.40") {
|
if versions.LessThan(version, "1.40") {
|
||||||
// Ignore BindOptions.NonRecursive because it was added in API 1.40.
|
// Ignore BindOptions.NonRecursive because it was added in API 1.40.
|
||||||
for _, m := range hostConfig.Mounts {
|
for _, m := range hostConfig.Mounts {
|
||||||
if bo := m.BindOptions; bo != nil {
|
if bo := m.BindOptions; bo != nil {
|
||||||
bo.NonRecursive = false
|
bo.NonRecursive = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore KernelMemoryTCP because it was added in API 1.40.
|
// Ignore KernelMemoryTCP because it was added in API 1.40.
|
||||||
hostConfig.KernelMemoryTCP = 0
|
hostConfig.KernelMemoryTCP = 0
|
||||||
|
|
||||||
|
@ -512,14 +501,26 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
|
||||||
hostConfig.IpcMode = container.IPCModeShareable
|
hostConfig.IpcMode = container.IPCModeShareable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if hostConfig != nil && versions.LessThan(version, "1.41") && !s.cgroup2 {
|
|
||||||
|
if versions.LessThan(version, "1.41") {
|
||||||
// Older clients expect the default to be "host" on cgroup v1 hosts
|
// Older clients expect the default to be "host" on cgroup v1 hosts
|
||||||
if hostConfig.CgroupnsMode.IsEmpty() {
|
if !s.cgroup2 && hostConfig.CgroupnsMode.IsEmpty() {
|
||||||
hostConfig.CgroupnsMode = container.CgroupnsModeHost
|
hostConfig.CgroupnsMode = container.CgroupnsModeHost
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if hostConfig != nil && versions.LessThan(version, "1.42") {
|
var platform *ocispec.Platform
|
||||||
|
if versions.GreaterThanOrEqualTo(version, "1.41") {
|
||||||
|
if v := r.Form.Get("platform"); v != "" {
|
||||||
|
p, err := platforms.Parse(v)
|
||||||
|
if err != nil {
|
||||||
|
return errdefs.InvalidParameter(err)
|
||||||
|
}
|
||||||
|
platform = &p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if versions.LessThan(version, "1.42") {
|
||||||
for _, m := range hostConfig.Mounts {
|
for _, m := range hostConfig.Mounts {
|
||||||
// Ignore BindOptions.CreateMountpoint because it was added in API 1.42.
|
// Ignore BindOptions.CreateMountpoint because it was added in API 1.42.
|
||||||
if bo := m.BindOptions; bo != nil {
|
if bo := m.BindOptions; bo != nil {
|
||||||
|
@ -539,9 +540,14 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
|
||||||
bo.CreateMountpoint = false
|
bo.CreateMountpoint = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if runtime.GOOS == "linux" {
|
||||||
|
// ConsoleSize is not respected by Linux daemon before API 1.42
|
||||||
|
hostConfig.ConsoleSize = [2]uint{0, 0}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if hostConfig != nil && versions.GreaterThanOrEqualTo(version, "1.42") {
|
if versions.GreaterThanOrEqualTo(version, "1.42") {
|
||||||
// Ignore KernelMemory removed in API 1.42.
|
// Ignore KernelMemory removed in API 1.42.
|
||||||
hostConfig.KernelMemory = 0
|
hostConfig.KernelMemory = 0
|
||||||
for _, m := range hostConfig.Mounts {
|
for _, m := range hostConfig.Mounts {
|
||||||
|
@ -557,23 +563,63 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if hostConfig != nil && runtime.GOOS == "linux" && versions.LessThan(version, "1.42") {
|
if versions.LessThan(version, "1.43") {
|
||||||
// ConsoleSize is not respected by Linux daemon before API 1.42
|
// Ignore Annotations because it was added in API v1.43.
|
||||||
hostConfig.ConsoleSize = [2]uint{0, 0}
|
hostConfig.Annotations = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var platform *specs.Platform
|
defaultReadOnlyNonRecursive := false
|
||||||
if versions.GreaterThanOrEqualTo(version, "1.41") {
|
if versions.LessThan(version, "1.44") {
|
||||||
if v := r.Form.Get("platform"); v != "" {
|
if config.Healthcheck != nil {
|
||||||
p, err := platforms.Parse(v)
|
// StartInterval was added in API 1.44
|
||||||
if err != nil {
|
config.Healthcheck.StartInterval = 0
|
||||||
return errdefs.InvalidParameter(err)
|
}
|
||||||
|
|
||||||
|
// Set ReadOnlyNonRecursive to true because it was added in API 1.44
|
||||||
|
// Before that all read-only mounts were non-recursive.
|
||||||
|
// Keep that behavior for clients on older APIs.
|
||||||
|
defaultReadOnlyNonRecursive = true
|
||||||
|
|
||||||
|
for _, m := range hostConfig.Mounts {
|
||||||
|
if m.Type == mount.TypeBind {
|
||||||
|
if m.BindOptions != nil && m.BindOptions.ReadOnlyForceRecursive {
|
||||||
|
// NOTE: that technically this is a breaking change for older
|
||||||
|
// API versions, and we should ignore the new field.
|
||||||
|
// However, this option may be incorrectly set by a client with
|
||||||
|
// the expectation that the failing to apply recursive read-only
|
||||||
|
// is enforced, so we decided to produce an error instead,
|
||||||
|
// instead of silently ignoring.
|
||||||
|
return errdefs.InvalidParameter(errors.New("BindOptions.ReadOnlyForceRecursive needs API v1.44 or newer"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
platform = &p
|
}
|
||||||
|
|
||||||
|
// Creating a container connected to several networks is not supported until v1.44.
|
||||||
|
if len(networkingConfig.EndpointsConfig) > 1 {
|
||||||
|
l := make([]string, 0, len(networkingConfig.EndpointsConfig))
|
||||||
|
for k := range networkingConfig.EndpointsConfig {
|
||||||
|
l = append(l, k)
|
||||||
|
}
|
||||||
|
return errdefs.InvalidParameter(errors.Errorf("Container cannot be created with multiple network endpoints: %s", strings.Join(l, ", ")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if hostConfig != nil && hostConfig.PidsLimit != nil && *hostConfig.PidsLimit <= 0 {
|
if versions.LessThan(version, "1.45") {
|
||||||
|
for _, m := range hostConfig.Mounts {
|
||||||
|
if m.VolumeOptions != nil && m.VolumeOptions.Subpath != "" {
|
||||||
|
return errdefs.InvalidParameter(errors.New("VolumeOptions.Subpath needs API v1.45 or newer"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var warnings []string
|
||||||
|
if warn, err := handleMACAddressBC(config, hostConfig, networkingConfig, version); err != nil {
|
||||||
|
return err
|
||||||
|
} else if warn != "" {
|
||||||
|
warnings = append(warnings, warn)
|
||||||
|
}
|
||||||
|
|
||||||
|
if hostConfig.PidsLimit != nil && *hostConfig.PidsLimit <= 0 {
|
||||||
// Don't set a limit if either no limit was specified, or "unlimited" was
|
// Don't set a limit if either no limit was specified, or "unlimited" was
|
||||||
// explicitly set.
|
// explicitly set.
|
||||||
// Both `0` and `-1` are accepted as "unlimited", and historically any
|
// Both `0` and `-1` are accepted as "unlimited", and historically any
|
||||||
|
@ -581,28 +627,107 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
|
||||||
hostConfig.PidsLimit = nil
|
hostConfig.PidsLimit = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ccr, err := s.backend.ContainerCreate(types.ContainerCreateConfig{
|
ccr, err := s.backend.ContainerCreate(ctx, backend.ContainerCreateConfig{
|
||||||
Name: name,
|
Name: name,
|
||||||
Config: config,
|
Config: config,
|
||||||
HostConfig: hostConfig,
|
HostConfig: hostConfig,
|
||||||
NetworkingConfig: networkingConfig,
|
NetworkingConfig: networkingConfig,
|
||||||
AdjustCPUShares: adjustCPUShares,
|
Platform: platform,
|
||||||
Platform: platform,
|
DefaultReadOnlyNonRecursive: defaultReadOnlyNonRecursive,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
ccr.Warnings = append(ccr.Warnings, warnings...)
|
||||||
return httputils.WriteJSON(w, http.StatusCreated, ccr)
|
return httputils.WriteJSON(w, http.StatusCreated, ccr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleMACAddressBC takes care of backward-compatibility for the container-wide MAC address by mutating the
|
||||||
|
// networkingConfig to set the endpoint-specific MACAddress field introduced in API v1.44. It returns a warning message
|
||||||
|
// or an error if the container-wide field was specified for API >= v1.44.
|
||||||
|
func handleMACAddressBC(config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, version string) (string, error) {
|
||||||
|
deprecatedMacAddress := config.MacAddress //nolint:staticcheck // ignore SA1019: field is deprecated, but still used on API < v1.44.
|
||||||
|
|
||||||
|
// For older versions of the API, migrate the container-wide MAC address to EndpointsConfig.
|
||||||
|
if versions.LessThan(version, "1.44") {
|
||||||
|
if deprecatedMacAddress == "" {
|
||||||
|
// If a MAC address is supplied in EndpointsConfig, discard it because the old API
|
||||||
|
// would have ignored it.
|
||||||
|
for _, ep := range networkingConfig.EndpointsConfig {
|
||||||
|
ep.MacAddress = ""
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
if !hostConfig.NetworkMode.IsBridge() && !hostConfig.NetworkMode.IsUserDefined() {
|
||||||
|
return "", runconfig.ErrConflictContainerNetworkAndMac
|
||||||
|
}
|
||||||
|
|
||||||
|
// There cannot be more than one entry in EndpointsConfig with API < 1.44.
|
||||||
|
|
||||||
|
// If there's no EndpointsConfig, create a place to store the configured address. It is
|
||||||
|
// safe to use NetworkMode as the network name, whether it's a name or id/short-id, as
|
||||||
|
// it will be normalised later and there is no other EndpointSettings object that might
|
||||||
|
// refer to this network/endpoint.
|
||||||
|
if len(networkingConfig.EndpointsConfig) == 0 {
|
||||||
|
nwName := hostConfig.NetworkMode.NetworkName()
|
||||||
|
networkingConfig.EndpointsConfig[nwName] = &network.EndpointSettings{}
|
||||||
|
}
|
||||||
|
// There's exactly one network in EndpointsConfig, either from the API or just-created.
|
||||||
|
// Migrate the container-wide setting to it.
|
||||||
|
// No need to check for a match between NetworkMode and the names/ids in EndpointsConfig,
|
||||||
|
// the old version of the API would have applied the address to this network anyway.
|
||||||
|
for _, ep := range networkingConfig.EndpointsConfig {
|
||||||
|
ep.MacAddress = deprecatedMacAddress
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// The container-wide MacAddress parameter is deprecated and should now be specified in EndpointsConfig.
|
||||||
|
if deprecatedMacAddress == "" {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
var warning string
|
||||||
|
if hostConfig.NetworkMode.IsBridge() || hostConfig.NetworkMode.IsUserDefined() {
|
||||||
|
nwName := hostConfig.NetworkMode.NetworkName()
|
||||||
|
// If there's no endpoint config, create a place to store the configured address.
|
||||||
|
if len(networkingConfig.EndpointsConfig) == 0 {
|
||||||
|
networkingConfig.EndpointsConfig[nwName] = &network.EndpointSettings{
|
||||||
|
MacAddress: deprecatedMacAddress,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// There is existing endpoint config - if it's not indexed by NetworkMode.Name(), we
|
||||||
|
// can't tell which network the container-wide settings was intended for. NetworkMode,
|
||||||
|
// the keys in EndpointsConfig and the NetworkID in EndpointsConfig may mix network
|
||||||
|
// name/id/short-id. It's not safe to create EndpointsConfig under the NetworkMode
|
||||||
|
// name to store the container-wide MAC address, because that may result in two sets
|
||||||
|
// of EndpointsConfig for the same network and one set will be discarded later. So,
|
||||||
|
// reject the request ...
|
||||||
|
ep, ok := networkingConfig.EndpointsConfig[nwName]
|
||||||
|
if !ok {
|
||||||
|
return "", errdefs.InvalidParameter(errors.New("if a container-wide MAC address is supplied, HostConfig.NetworkMode must match the identity of a network in NetworkSettings.Networks"))
|
||||||
|
}
|
||||||
|
// ep is the endpoint that needs the container-wide MAC address; migrate the address
|
||||||
|
// to it, or bail out if there's a mismatch.
|
||||||
|
if ep.MacAddress == "" {
|
||||||
|
ep.MacAddress = deprecatedMacAddress
|
||||||
|
} else if ep.MacAddress != deprecatedMacAddress {
|
||||||
|
return "", errdefs.InvalidParameter(errors.New("the container-wide MAC address must match the endpoint-specific MAC address for the main network, or be left empty"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
warning = "The container-wide MacAddress field is now deprecated. It should be specified in EndpointsConfig instead."
|
||||||
|
config.MacAddress = "" //nolint:staticcheck // ignore SA1019: field is deprecated, but still used on API < v1.44.
|
||||||
|
|
||||||
|
return warning, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *containerRouter) deleteContainers(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (s *containerRouter) deleteContainers(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := httputils.ParseForm(r); err != nil {
|
if err := httputils.ParseForm(r); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
config := &types.ContainerRmConfig{
|
config := &backend.ContainerRmConfig{
|
||||||
ForceRemove: httputils.BoolValue(r, "force"),
|
ForceRemove: httputils.BoolValue(r, "force"),
|
||||||
RemoveVolume: httputils.BoolValue(r, "v"),
|
RemoveVolume: httputils.BoolValue(r, "v"),
|
||||||
RemoveLink: httputils.BoolValue(r, "link"),
|
RemoveLink: httputils.BoolValue(r, "link"),
|
||||||
|
@ -687,11 +812,11 @@ func (s *containerRouter) postContainersAttach(ctx context.Context, w http.Respo
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = s.backend.ContainerAttach(containerName, attachConfig); err != nil {
|
if err = s.backend.ContainerAttach(containerName, attachConfig); err != nil {
|
||||||
logrus.WithError(err).Errorf("Handler for %s %s returned error", r.Method, r.URL.Path)
|
log.G(ctx).WithError(err).Errorf("Handler for %s %s returned error", r.Method, r.URL.Path)
|
||||||
// Remember to close stream if error happens
|
// Remember to close stream if error happens
|
||||||
conn, _, errHijack := hijacker.Hijack()
|
conn, _, errHijack := hijacker.Hijack()
|
||||||
if errHijack != nil {
|
if errHijack != nil {
|
||||||
logrus.WithError(err).Errorf("Handler for %s %s: unable to close stream; error when hijacking connection", r.Method, r.URL.Path)
|
log.G(ctx).WithError(err).Errorf("Handler for %s %s: unable to close stream; error when hijacking connection", r.Method, r.URL.Path)
|
||||||
} else {
|
} else {
|
||||||
statusCode := httpstatus.FromError(err)
|
statusCode := httpstatus.FromError(err)
|
||||||
statusText := http.StatusText(statusCode)
|
statusText := http.StatusText(statusCode)
|
||||||
|
@ -761,9 +886,9 @@ func (s *containerRouter) wsContainersAttach(ctx context.Context, w http.Respons
|
||||||
select {
|
select {
|
||||||
case <-started:
|
case <-started:
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("Error attaching websocket: %s", err)
|
log.G(ctx).Errorf("Error attaching websocket: %s", err)
|
||||||
} else {
|
} else {
|
||||||
logrus.Debug("websocket connection was closed by client")
|
log.G(ctx).Debug("websocket connection was closed by client")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
|
|
160
api/server/router/container/container_routes_test.go
Normal file
160
api/server/router/container/container_routes_test.go
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
package container
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/docker/docker/api/types/container"
|
||||||
|
"github.com/docker/docker/api/types/network"
|
||||||
|
"gotest.tools/v3/assert"
|
||||||
|
is "gotest.tools/v3/assert/cmp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestHandleMACAddressBC(t *testing.T) {
|
||||||
|
testcases := []struct {
|
||||||
|
name string
|
||||||
|
apiVersion string
|
||||||
|
ctrWideMAC string
|
||||||
|
networkMode container.NetworkMode
|
||||||
|
epConfig map[string]*network.EndpointSettings
|
||||||
|
expEpWithCtrWideMAC string
|
||||||
|
expEpWithNoMAC string
|
||||||
|
expCtrWideMAC string
|
||||||
|
expWarning string
|
||||||
|
expError string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "old api ctr-wide mac mix id and name",
|
||||||
|
apiVersion: "1.43",
|
||||||
|
ctrWideMAC: "11:22:33:44:55:66",
|
||||||
|
networkMode: "aNetId",
|
||||||
|
epConfig: map[string]*network.EndpointSettings{"aNetName": {}},
|
||||||
|
expEpWithCtrWideMAC: "aNetName",
|
||||||
|
expCtrWideMAC: "11:22:33:44:55:66",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "old api clear ep mac",
|
||||||
|
apiVersion: "1.43",
|
||||||
|
networkMode: "aNetId",
|
||||||
|
epConfig: map[string]*network.EndpointSettings{"aNetName": {MacAddress: "11:22:33:44:55:66"}},
|
||||||
|
expEpWithNoMAC: "aNetName",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "old api no-network ctr-wide mac",
|
||||||
|
apiVersion: "1.43",
|
||||||
|
networkMode: "none",
|
||||||
|
ctrWideMAC: "11:22:33:44:55:66",
|
||||||
|
expError: "conflicting options: mac-address and the network mode",
|
||||||
|
expCtrWideMAC: "11:22:33:44:55:66",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "old api create ep",
|
||||||
|
apiVersion: "1.43",
|
||||||
|
networkMode: "aNetId",
|
||||||
|
ctrWideMAC: "11:22:33:44:55:66",
|
||||||
|
epConfig: map[string]*network.EndpointSettings{},
|
||||||
|
expEpWithCtrWideMAC: "aNetId",
|
||||||
|
expCtrWideMAC: "11:22:33:44:55:66",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "old api migrate ctr-wide mac",
|
||||||
|
apiVersion: "1.43",
|
||||||
|
ctrWideMAC: "11:22:33:44:55:66",
|
||||||
|
networkMode: "aNetName",
|
||||||
|
epConfig: map[string]*network.EndpointSettings{"aNetName": {}},
|
||||||
|
expEpWithCtrWideMAC: "aNetName",
|
||||||
|
expCtrWideMAC: "11:22:33:44:55:66",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "new api no macs",
|
||||||
|
apiVersion: "1.44",
|
||||||
|
networkMode: "aNetId",
|
||||||
|
epConfig: map[string]*network.EndpointSettings{"aNetName": {}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "new api ep specific mac",
|
||||||
|
apiVersion: "1.44",
|
||||||
|
networkMode: "aNetName",
|
||||||
|
epConfig: map[string]*network.EndpointSettings{"aNetName": {MacAddress: "11:22:33:44:55:66"}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "new api migrate ctr-wide mac to new ep",
|
||||||
|
apiVersion: "1.44",
|
||||||
|
ctrWideMAC: "11:22:33:44:55:66",
|
||||||
|
networkMode: "aNetName",
|
||||||
|
epConfig: map[string]*network.EndpointSettings{},
|
||||||
|
expEpWithCtrWideMAC: "aNetName",
|
||||||
|
expWarning: "The container-wide MacAddress field is now deprecated",
|
||||||
|
expCtrWideMAC: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "new api migrate ctr-wide mac to existing ep",
|
||||||
|
apiVersion: "1.44",
|
||||||
|
ctrWideMAC: "11:22:33:44:55:66",
|
||||||
|
networkMode: "aNetName",
|
||||||
|
epConfig: map[string]*network.EndpointSettings{"aNetName": {}},
|
||||||
|
expEpWithCtrWideMAC: "aNetName",
|
||||||
|
expWarning: "The container-wide MacAddress field is now deprecated",
|
||||||
|
expCtrWideMAC: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "new api mode vs name mismatch",
|
||||||
|
apiVersion: "1.44",
|
||||||
|
ctrWideMAC: "11:22:33:44:55:66",
|
||||||
|
networkMode: "aNetId",
|
||||||
|
epConfig: map[string]*network.EndpointSettings{"aNetName": {}},
|
||||||
|
expError: "if a container-wide MAC address is supplied, HostConfig.NetworkMode must match the identity of a network in NetworkSettings.Networks",
|
||||||
|
expCtrWideMAC: "11:22:33:44:55:66",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "new api mac mismatch",
|
||||||
|
apiVersion: "1.44",
|
||||||
|
ctrWideMAC: "11:22:33:44:55:66",
|
||||||
|
networkMode: "aNetName",
|
||||||
|
epConfig: map[string]*network.EndpointSettings{"aNetName": {MacAddress: "00:11:22:33:44:55"}},
|
||||||
|
expError: "the container-wide MAC address must match the endpoint-specific MAC address",
|
||||||
|
expCtrWideMAC: "11:22:33:44:55:66",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testcases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
cfg := &container.Config{
|
||||||
|
MacAddress: tc.ctrWideMAC, //nolint:staticcheck // ignore SA1019: field is deprecated, but still used on API < v1.44.
|
||||||
|
}
|
||||||
|
hostCfg := &container.HostConfig{
|
||||||
|
NetworkMode: tc.networkMode,
|
||||||
|
}
|
||||||
|
epConfig := make(map[string]*network.EndpointSettings, len(tc.epConfig))
|
||||||
|
for k, v := range tc.epConfig {
|
||||||
|
v := v
|
||||||
|
epConfig[k] = v
|
||||||
|
}
|
||||||
|
netCfg := &network.NetworkingConfig{
|
||||||
|
EndpointsConfig: epConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
warning, err := handleMACAddressBC(cfg, hostCfg, netCfg, tc.apiVersion)
|
||||||
|
|
||||||
|
if tc.expError == "" {
|
||||||
|
assert.Check(t, err)
|
||||||
|
} else {
|
||||||
|
assert.Check(t, is.ErrorContains(err, tc.expError))
|
||||||
|
}
|
||||||
|
if tc.expWarning == "" {
|
||||||
|
assert.Check(t, is.Equal(warning, ""))
|
||||||
|
} else {
|
||||||
|
assert.Check(t, is.Contains(warning, tc.expWarning))
|
||||||
|
}
|
||||||
|
if tc.expEpWithCtrWideMAC != "" {
|
||||||
|
got := netCfg.EndpointsConfig[tc.expEpWithCtrWideMAC].MacAddress
|
||||||
|
assert.Check(t, is.Equal(got, tc.ctrWideMAC))
|
||||||
|
}
|
||||||
|
if tc.expEpWithNoMAC != "" {
|
||||||
|
got := netCfg.EndpointsConfig[tc.expEpWithNoMAC].MacAddress
|
||||||
|
assert.Check(t, is.Equal(got, ""))
|
||||||
|
}
|
||||||
|
gotCtrWideMAC := cfg.MacAddress //nolint:staticcheck // ignore SA1019: field is deprecated, but still used on API < v1.44.
|
||||||
|
assert.Check(t, is.Equal(gotCtrWideMAC, tc.expCtrWideMAC))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,49 +11,10 @@ import (
|
||||||
|
|
||||||
"github.com/docker/docker/api/server/httputils"
|
"github.com/docker/docker/api/server/httputils"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/versions"
|
|
||||||
gddohttputil "github.com/golang/gddo/httputil"
|
gddohttputil "github.com/golang/gddo/httputil"
|
||||||
)
|
)
|
||||||
|
|
||||||
type pathError struct{}
|
// setContainerPathStatHeader encodes the stat to JSON, base64 encode, and place in a header.
|
||||||
|
|
||||||
func (pathError) Error() string {
|
|
||||||
return "Path cannot be empty"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pathError) InvalidParameter() {}
|
|
||||||
|
|
||||||
// postContainersCopy is deprecated in favor of getContainersArchive.
|
|
||||||
//
|
|
||||||
// Deprecated since 1.8 (API v1.20), errors out since 1.12 (API v1.24)
|
|
||||||
func (s *containerRouter) postContainersCopy(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
|
||||||
version := httputils.VersionFromContext(ctx)
|
|
||||||
if versions.GreaterThanOrEqualTo(version, "1.24") {
|
|
||||||
w.WriteHeader(http.StatusNotFound)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg := types.CopyConfig{}
|
|
||||||
if err := httputils.ReadJSON(r, &cfg); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if cfg.Resource == "" {
|
|
||||||
return pathError{}
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := s.backend.ContainerCopy(vars["name"], cfg.Resource)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer data.Close()
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/x-tar")
|
|
||||||
_, err = io.Copy(w, data)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// // Encode the stat to JSON, base64 encode, and place in a header.
|
|
||||||
func setContainerPathStatHeader(stat *types.ContainerPathStat, header http.Header) error {
|
func setContainerPathStatHeader(stat *types.ContainerPathStat, header http.Header) error {
|
||||||
statJSON, err := json.Marshal(stat)
|
statJSON, err := json.Marshal(stat)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -7,13 +7,13 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/containerd/log"
|
||||||
"github.com/docker/docker/api/server/httputils"
|
"github.com/docker/docker/api/server/httputils"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/api/types/versions"
|
"github.com/docker/docker/api/types/versions"
|
||||||
"github.com/docker/docker/errdefs"
|
"github.com/docker/docker/errdefs"
|
||||||
"github.com/docker/docker/pkg/stdcopy"
|
"github.com/docker/docker/pkg/stdcopy"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *containerRouter) getExecByID(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (s *containerRouter) getExecByID(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
|
@ -56,7 +56,7 @@ func (s *containerRouter) postContainerExecCreate(ctx context.Context, w http.Re
|
||||||
// Register an instance of Exec in container.
|
// Register an instance of Exec in container.
|
||||||
id, err := s.backend.ContainerExecCreate(vars["name"], execConfig)
|
id, err := s.backend.ContainerExecCreate(vars["name"], execConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("Error setting up exec command in container %s: %v", vars["name"], err)
|
log.G(ctx).Errorf("Error setting up exec command in container %s: %v", vars["name"], err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,15 +71,6 @@ func (s *containerRouter) postContainerExecStart(ctx context.Context, w http.Res
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
version := httputils.VersionFromContext(ctx)
|
|
||||||
if versions.LessThan(version, "1.22") {
|
|
||||||
// API versions before 1.22 did not enforce application/json content-type.
|
|
||||||
// Allow older clients to work by patching the content-type.
|
|
||||||
if r.Header.Get("Content-Type") != "application/json" {
|
|
||||||
r.Header.Set("Content-Type", "application/json")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
execName = vars["name"]
|
execName = vars["name"]
|
||||||
stdin, inStream io.ReadCloser
|
stdin, inStream io.ReadCloser
|
||||||
|
@ -96,6 +87,8 @@ func (s *containerRouter) postContainerExecStart(ctx context.Context, w http.Res
|
||||||
}
|
}
|
||||||
|
|
||||||
if execStartCheck.ConsoleSize != nil {
|
if execStartCheck.ConsoleSize != nil {
|
||||||
|
version := httputils.VersionFromContext(ctx)
|
||||||
|
|
||||||
// Not supported before 1.42
|
// Not supported before 1.42
|
||||||
if versions.LessThan(version, "1.42") {
|
if versions.LessThan(version, "1.42") {
|
||||||
execStartCheck.ConsoleSize = nil
|
execStartCheck.ConsoleSize = nil
|
||||||
|
@ -154,7 +147,7 @@ func (s *containerRouter) postContainerExecStart(ctx context.Context, w http.Res
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
stdout.Write([]byte(err.Error() + "\r\n"))
|
stdout.Write([]byte(err.Error() + "\r\n"))
|
||||||
logrus.Errorf("Error running exec %s in container: %v", execName, err)
|
log.G(ctx).Errorf("Error running exec %s in container: %v", execName, err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ func (s *containerRouter) getContainersByName(ctx context.Context, w http.Respon
|
||||||
displaySize := httputils.BoolValue(r, "size")
|
displaySize := httputils.BoolValue(r, "size")
|
||||||
|
|
||||||
version := httputils.VersionFromContext(ctx)
|
version := httputils.VersionFromContext(ctx)
|
||||||
json, err := s.backend.ContainerInspect(vars["name"], displaySize, version)
|
json, err := s.backend.ContainerInspect(ctx, vars["name"], displaySize, version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,13 +3,13 @@ package distribution // import "github.com/docker/docker/api/server/router/distr
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/distribution/reference"
|
||||||
"github.com/docker/distribution"
|
"github.com/docker/distribution"
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/docker/docker/api/types/registry"
|
||||||
"github.com/docker/docker/api/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Backend is all the methods that need to be implemented
|
// Backend is all the methods that need to be implemented
|
||||||
// to provide image specific functionality.
|
// to provide image specific functionality.
|
||||||
type Backend interface {
|
type Backend interface {
|
||||||
GetRepository(context.Context, reference.Named, *types.AuthConfig) (distribution.Repository, error)
|
GetRepositories(context.Context, reference.Named, *registry.AuthConfig) ([]distribution.Repository, error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,20 +2,20 @@ package distribution // import "github.com/docker/docker/api/server/router/distr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"os"
|
||||||
|
|
||||||
|
"github.com/distribution/reference"
|
||||||
|
"github.com/docker/distribution"
|
||||||
"github.com/docker/distribution/manifest/manifestlist"
|
"github.com/docker/distribution/manifest/manifestlist"
|
||||||
"github.com/docker/distribution/manifest/schema1"
|
"github.com/docker/distribution/manifest/schema1"
|
||||||
"github.com/docker/distribution/manifest/schema2"
|
"github.com/docker/distribution/manifest/schema2"
|
||||||
"github.com/docker/distribution/reference"
|
|
||||||
"github.com/docker/docker/api/server/httputils"
|
"github.com/docker/docker/api/server/httputils"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types/registry"
|
||||||
registrytypes "github.com/docker/docker/api/types/registry"
|
distributionpkg "github.com/docker/docker/distribution"
|
||||||
"github.com/docker/docker/errdefs"
|
"github.com/docker/docker/errdefs"
|
||||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -26,25 +26,10 @@ func (s *distributionRouter) getDistributionInfo(ctx context.Context, w http.Res
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
var (
|
imgName := vars["name"]
|
||||||
config = &types.AuthConfig{}
|
|
||||||
authEncoded = r.Header.Get("X-Registry-Auth")
|
|
||||||
distributionInspect registrytypes.DistributionInspect
|
|
||||||
)
|
|
||||||
|
|
||||||
if authEncoded != "" {
|
|
||||||
authJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
|
|
||||||
if err := json.NewDecoder(authJSON).Decode(&config); err != nil {
|
|
||||||
// for a search it is not an error if no auth was given
|
|
||||||
// to increase compatibility with the existing api it is defaulting to be empty
|
|
||||||
config = &types.AuthConfig{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
image := vars["name"]
|
|
||||||
|
|
||||||
// TODO why is reference.ParseAnyReference() / reference.ParseNormalizedNamed() not using the reference.ErrTagInvalidFormat (and so on) errors?
|
// TODO why is reference.ParseAnyReference() / reference.ParseNormalizedNamed() not using the reference.ErrTagInvalidFormat (and so on) errors?
|
||||||
ref, err := reference.ParseAnyReference(image)
|
ref, err := reference.ParseAnyReference(imgName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errdefs.InvalidParameter(err)
|
return errdefs.InvalidParameter(err)
|
||||||
}
|
}
|
||||||
|
@ -54,28 +39,58 @@ func (s *distributionRouter) getDistributionInfo(ctx context.Context, w http.Res
|
||||||
// full image ID
|
// full image ID
|
||||||
return errors.Errorf("no manifest found for full image ID")
|
return errors.Errorf("no manifest found for full image ID")
|
||||||
}
|
}
|
||||||
return errdefs.InvalidParameter(errors.Errorf("unknown image reference format: %s", image))
|
return errdefs.InvalidParameter(errors.Errorf("unknown image reference format: %s", imgName))
|
||||||
}
|
}
|
||||||
|
|
||||||
distrepo, err := s.backend.GetRepository(ctx, namedRef, config)
|
// For a search it is not an error if no auth was given. Ignore invalid
|
||||||
|
// AuthConfig to increase compatibility with the existing API.
|
||||||
|
authConfig, _ := registry.DecodeAuthConfig(r.Header.Get(registry.AuthHeader))
|
||||||
|
repos, err := s.backend.GetRepositories(ctx, namedRef, authConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
blobsrvc := distrepo.Blobs(ctx)
|
|
||||||
|
|
||||||
|
// Fetch the manifest; if a mirror is configured, try the mirror first,
|
||||||
|
// but continue with upstream on failure.
|
||||||
|
//
|
||||||
|
// FIXME(thaJeztah): construct "repositories" on-demand;
|
||||||
|
// GetRepositories() will attempt to connect to all endpoints (registries),
|
||||||
|
// but we may only need the first one if it contains the manifest we're
|
||||||
|
// looking for, or if the configured mirror is a pull-through mirror.
|
||||||
|
//
|
||||||
|
// Logic for this could be implemented similar to "distribution.Pull()",
|
||||||
|
// which uses the "pullEndpoints" utility to iterate over the list
|
||||||
|
// of endpoints;
|
||||||
|
//
|
||||||
|
// - https://github.com/moby/moby/blob/12c7411b6b7314bef130cd59f1c7384a7db06d0b/distribution/pull.go#L17-L31
|
||||||
|
// - https://github.com/moby/moby/blob/12c7411b6b7314bef130cd59f1c7384a7db06d0b/distribution/pull.go#L76-L152
|
||||||
|
var lastErr error
|
||||||
|
for _, repo := range repos {
|
||||||
|
distributionInspect, err := s.fetchManifest(ctx, repo, namedRef)
|
||||||
|
if err != nil {
|
||||||
|
lastErr = err
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return httputils.WriteJSON(w, http.StatusOK, distributionInspect)
|
||||||
|
}
|
||||||
|
return lastErr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *distributionRouter) fetchManifest(ctx context.Context, distrepo distribution.Repository, namedRef reference.Named) (registry.DistributionInspect, error) {
|
||||||
|
var distributionInspect registry.DistributionInspect
|
||||||
if canonicalRef, ok := namedRef.(reference.Canonical); !ok {
|
if canonicalRef, ok := namedRef.(reference.Canonical); !ok {
|
||||||
namedRef = reference.TagNameOnly(namedRef)
|
namedRef = reference.TagNameOnly(namedRef)
|
||||||
|
|
||||||
taggedRef, ok := namedRef.(reference.NamedTagged)
|
taggedRef, ok := namedRef.(reference.NamedTagged)
|
||||||
if !ok {
|
if !ok {
|
||||||
return errdefs.InvalidParameter(errors.Errorf("image reference not tagged: %s", image))
|
return registry.DistributionInspect{}, errdefs.InvalidParameter(errors.Errorf("image reference not tagged: %s", namedRef))
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptor, err := distrepo.Tags(ctx).Get(ctx, taggedRef.Tag())
|
descriptor, err := distrepo.Tags(ctx).Get(ctx, taggedRef.Tag())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return registry.DistributionInspect{}, err
|
||||||
}
|
}
|
||||||
distributionInspect.Descriptor = v1.Descriptor{
|
distributionInspect.Descriptor = ocispec.Descriptor{
|
||||||
MediaType: descriptor.MediaType,
|
MediaType: descriptor.MediaType,
|
||||||
Digest: descriptor.Digest,
|
Digest: descriptor.Digest,
|
||||||
Size: descriptor.Size,
|
Size: descriptor.Size,
|
||||||
|
@ -90,7 +105,7 @@ func (s *distributionRouter) getDistributionInfo(ctx context.Context, w http.Res
|
||||||
// we have a digest, so we can retrieve the manifest
|
// we have a digest, so we can retrieve the manifest
|
||||||
mnfstsrvc, err := distrepo.Manifests(ctx)
|
mnfstsrvc, err := distrepo.Manifests(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return registry.DistributionInspect{}, err
|
||||||
}
|
}
|
||||||
mnfst, err := mnfstsrvc.Get(ctx, distributionInspect.Descriptor.Digest)
|
mnfst, err := mnfstsrvc.Get(ctx, distributionInspect.Descriptor.Digest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -102,14 +117,14 @@ func (s *distributionRouter) getDistributionInfo(ctx context.Context, w http.Res
|
||||||
reference.ErrNameEmpty,
|
reference.ErrNameEmpty,
|
||||||
reference.ErrNameTooLong,
|
reference.ErrNameTooLong,
|
||||||
reference.ErrNameNotCanonical:
|
reference.ErrNameNotCanonical:
|
||||||
return errdefs.InvalidParameter(err)
|
return registry.DistributionInspect{}, errdefs.InvalidParameter(err)
|
||||||
}
|
}
|
||||||
return err
|
return registry.DistributionInspect{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
mediaType, payload, err := mnfst.Payload()
|
mediaType, payload, err := mnfst.Payload()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return registry.DistributionInspect{}, err
|
||||||
}
|
}
|
||||||
// update MediaType because registry might return something incorrect
|
// update MediaType because registry might return something incorrect
|
||||||
distributionInspect.Descriptor.MediaType = mediaType
|
distributionInspect.Descriptor.MediaType = mediaType
|
||||||
|
@ -121,7 +136,7 @@ func (s *distributionRouter) getDistributionInfo(ctx context.Context, w http.Res
|
||||||
switch mnfstObj := mnfst.(type) {
|
switch mnfstObj := mnfst.(type) {
|
||||||
case *manifestlist.DeserializedManifestList:
|
case *manifestlist.DeserializedManifestList:
|
||||||
for _, m := range mnfstObj.Manifests {
|
for _, m := range mnfstObj.Manifests {
|
||||||
distributionInspect.Platforms = append(distributionInspect.Platforms, v1.Platform{
|
distributionInspect.Platforms = append(distributionInspect.Platforms, ocispec.Platform{
|
||||||
Architecture: m.Platform.Architecture,
|
Architecture: m.Platform.Architecture,
|
||||||
OS: m.Platform.OS,
|
OS: m.Platform.OS,
|
||||||
OSVersion: m.Platform.OSVersion,
|
OSVersion: m.Platform.OSVersion,
|
||||||
|
@ -130,8 +145,9 @@ func (s *distributionRouter) getDistributionInfo(ctx context.Context, w http.Res
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
case *schema2.DeserializedManifest:
|
case *schema2.DeserializedManifest:
|
||||||
configJSON, err := blobsrvc.Get(ctx, mnfstObj.Config.Digest)
|
blobStore := distrepo.Blobs(ctx)
|
||||||
var platform v1.Platform
|
configJSON, err := blobStore.Get(ctx, mnfstObj.Config.Digest)
|
||||||
|
var platform ocispec.Platform
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err := json.Unmarshal(configJSON, &platform)
|
err := json.Unmarshal(configJSON, &platform)
|
||||||
if err == nil && (platform.OS != "" || platform.Architecture != "") {
|
if err == nil && (platform.OS != "" || platform.Architecture != "") {
|
||||||
|
@ -139,12 +155,14 @@ func (s *distributionRouter) getDistributionInfo(ctx context.Context, w http.Res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *schema1.SignedManifest:
|
case *schema1.SignedManifest:
|
||||||
platform := v1.Platform{
|
if os.Getenv("DOCKER_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE") == "" {
|
||||||
|
return registry.DistributionInspect{}, distributionpkg.DeprecatedSchema1ImageError(namedRef)
|
||||||
|
}
|
||||||
|
platform := ocispec.Platform{
|
||||||
Architecture: mnfstObj.Architecture,
|
Architecture: mnfstObj.Architecture,
|
||||||
OS: "linux",
|
OS: "linux",
|
||||||
}
|
}
|
||||||
distributionInspect.Platforms = append(distributionInspect.Platforms, platform)
|
distributionInspect.Platforms = append(distributionInspect.Platforms, platform)
|
||||||
}
|
}
|
||||||
|
return distributionInspect, nil
|
||||||
return httputils.WriteJSON(w, http.StatusOK, distributionInspect)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
package grpc // import "github.com/docker/docker/api/server/router/grpc"
|
package grpc // import "github.com/docker/docker/api/server/router/grpc"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/docker/docker/api/server/router"
|
"github.com/docker/docker/api/server/router"
|
||||||
|
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
|
||||||
"github.com/moby/buildkit/util/grpcerrors"
|
"github.com/moby/buildkit/util/grpcerrors"
|
||||||
|
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
@ -15,12 +20,12 @@ type grpcRouter struct {
|
||||||
|
|
||||||
// NewRouter initializes a new grpc http router
|
// NewRouter initializes a new grpc http router
|
||||||
func NewRouter(backends ...Backend) router.Router {
|
func NewRouter(backends ...Backend) router.Router {
|
||||||
|
unary := grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(unaryInterceptor(), grpcerrors.UnaryServerInterceptor))
|
||||||
|
stream := grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(otelgrpc.StreamServerInterceptor(), grpcerrors.StreamServerInterceptor)) //nolint:staticcheck // TODO(thaJeztah): ignore SA1019 for deprecated options: see https://github.com/moby/moby/issues/47437
|
||||||
|
|
||||||
r := &grpcRouter{
|
r := &grpcRouter{
|
||||||
h2Server: &http2.Server{},
|
h2Server: &http2.Server{},
|
||||||
grpcServer: grpc.NewServer(
|
grpcServer: grpc.NewServer(unary, stream),
|
||||||
grpc.UnaryInterceptor(grpcerrors.UnaryServerInterceptor),
|
|
||||||
grpc.StreamInterceptor(grpcerrors.StreamServerInterceptor),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
for _, b := range backends {
|
for _, b := range backends {
|
||||||
b.RegisterGRPC(r.grpcServer)
|
b.RegisterGRPC(r.grpcServer)
|
||||||
|
@ -39,3 +44,17 @@ func (gr *grpcRouter) initRoutes() {
|
||||||
router.NewPostRoute("/grpc", gr.serveGRPC),
|
router.NewPostRoute("/grpc", gr.serveGRPC),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func unaryInterceptor() grpc.UnaryServerInterceptor {
|
||||||
|
withTrace := otelgrpc.UnaryServerInterceptor() //nolint:staticcheck // TODO(thaJeztah): ignore SA1019 for deprecated options: see https://github.com/moby/moby/issues/47437
|
||||||
|
|
||||||
|
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
|
||||||
|
// This method is used by the clients to send their traces to buildkit so they can be included
|
||||||
|
// in the daemon trace and stored in the build history record. This method can not be traced because
|
||||||
|
// it would cause an infinite loop.
|
||||||
|
if strings.HasSuffix(info.FullMethod, "opentelemetry.proto.collector.trace.v1.TraceService/Export") {
|
||||||
|
return handler(ctx, req)
|
||||||
|
}
|
||||||
|
return withTrace(ctx, req, info, handler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,12 +4,14 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/distribution/reference"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/backend"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/api/types/image"
|
"github.com/docker/docker/api/types/image"
|
||||||
"github.com/docker/docker/api/types/registry"
|
"github.com/docker/docker/api/types/registry"
|
||||||
dockerimage "github.com/docker/docker/image"
|
dockerimage "github.com/docker/docker/image"
|
||||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Backend is all the methods that need to be implemented
|
// Backend is all the methods that need to be implemented
|
||||||
|
@ -21,22 +23,25 @@ type Backend interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type imageBackend interface {
|
type imageBackend interface {
|
||||||
ImageDelete(imageRef string, force, prune bool) ([]types.ImageDeleteResponseItem, error)
|
ImageDelete(ctx context.Context, imageRef string, force, prune bool) ([]image.DeleteResponse, error)
|
||||||
ImageHistory(imageName string) ([]*image.HistoryResponseItem, error)
|
ImageHistory(ctx context.Context, imageName string) ([]*image.HistoryResponseItem, error)
|
||||||
Images(ctx context.Context, opts types.ImageListOptions) ([]*types.ImageSummary, error)
|
Images(ctx context.Context, opts image.ListOptions) ([]*image.Summary, error)
|
||||||
GetImage(refOrID string, platform *specs.Platform) (retImg *dockerimage.Image, retErr error)
|
GetImage(ctx context.Context, refOrID string, options backend.GetImageOpts) (*dockerimage.Image, error)
|
||||||
TagImage(imageName, repository, tag string) (string, error)
|
TagImage(ctx context.Context, id dockerimage.ID, newRef reference.Named) error
|
||||||
ImagesPrune(ctx context.Context, pruneFilters filters.Args) (*types.ImagesPruneReport, error)
|
ImagesPrune(ctx context.Context, pruneFilters filters.Args) (*types.ImagesPruneReport, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type importExportBackend interface {
|
type importExportBackend interface {
|
||||||
LoadImage(inTar io.ReadCloser, outStream io.Writer, quiet bool) error
|
LoadImage(ctx context.Context, inTar io.ReadCloser, outStream io.Writer, quiet bool) error
|
||||||
ImportImage(src string, repository string, platform *specs.Platform, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error
|
ImportImage(ctx context.Context, ref reference.Named, platform *ocispec.Platform, msg string, layerReader io.Reader, changes []string) (dockerimage.ID, error)
|
||||||
ExportImage(names []string, outStream io.Writer) error
|
ExportImage(ctx context.Context, names []string, outStream io.Writer) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type registryBackend interface {
|
type registryBackend interface {
|
||||||
PullImage(ctx context.Context, image, tag string, platform *specs.Platform, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
|
PullImage(ctx context.Context, ref reference.Named, platform *ocispec.Platform, metaHeaders map[string][]string, authConfig *registry.AuthConfig, outStream io.Writer) error
|
||||||
PushImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
|
PushImage(ctx context.Context, ref reference.Named, metaHeaders map[string][]string, authConfig *registry.AuthConfig, outStream io.Writer) error
|
||||||
SearchRegistryForImages(ctx context.Context, searchFilters filters.Args, term string, limit int, authConfig *types.AuthConfig, metaHeaders map[string][]string) (*registry.SearchResults, error)
|
}
|
||||||
|
|
||||||
|
type Searcher interface {
|
||||||
|
Search(ctx context.Context, searchFilters filters.Args, term string, limit int, authConfig *registry.AuthConfig, headers map[string][]string) ([]registry.SearchResult, error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
// imageRouter is a router to talk with the image controller
|
// imageRouter is a router to talk with the image controller
|
||||||
type imageRouter struct {
|
type imageRouter struct {
|
||||||
backend Backend
|
backend Backend
|
||||||
|
searcher Searcher
|
||||||
referenceBackend reference.Store
|
referenceBackend reference.Store
|
||||||
imageStore image.Store
|
imageStore image.Store
|
||||||
layerStore layer.Store
|
layerStore layer.Store
|
||||||
|
@ -17,39 +18,40 @@ type imageRouter struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRouter initializes a new image router
|
// NewRouter initializes a new image router
|
||||||
func NewRouter(backend Backend, referenceBackend reference.Store, imageStore image.Store, layerStore layer.Store) router.Router {
|
func NewRouter(backend Backend, searcher Searcher, referenceBackend reference.Store, imageStore image.Store, layerStore layer.Store) router.Router {
|
||||||
r := &imageRouter{
|
ir := &imageRouter{
|
||||||
backend: backend,
|
backend: backend,
|
||||||
|
searcher: searcher,
|
||||||
referenceBackend: referenceBackend,
|
referenceBackend: referenceBackend,
|
||||||
imageStore: imageStore,
|
imageStore: imageStore,
|
||||||
layerStore: layerStore,
|
layerStore: layerStore,
|
||||||
}
|
}
|
||||||
r.initRoutes()
|
ir.initRoutes()
|
||||||
return r
|
return ir
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routes returns the available routes to the image controller
|
// Routes returns the available routes to the image controller
|
||||||
func (r *imageRouter) Routes() []router.Route {
|
func (ir *imageRouter) Routes() []router.Route {
|
||||||
return r.routes
|
return ir.routes
|
||||||
}
|
}
|
||||||
|
|
||||||
// initRoutes initializes the routes in the image router
|
// initRoutes initializes the routes in the image router
|
||||||
func (r *imageRouter) initRoutes() {
|
func (ir *imageRouter) initRoutes() {
|
||||||
r.routes = []router.Route{
|
ir.routes = []router.Route{
|
||||||
// GET
|
// GET
|
||||||
router.NewGetRoute("/images/json", r.getImagesJSON),
|
router.NewGetRoute("/images/json", ir.getImagesJSON),
|
||||||
router.NewGetRoute("/images/search", r.getImagesSearch),
|
router.NewGetRoute("/images/search", ir.getImagesSearch),
|
||||||
router.NewGetRoute("/images/get", r.getImagesGet),
|
router.NewGetRoute("/images/get", ir.getImagesGet),
|
||||||
router.NewGetRoute("/images/{name:.*}/get", r.getImagesGet),
|
router.NewGetRoute("/images/{name:.*}/get", ir.getImagesGet),
|
||||||
router.NewGetRoute("/images/{name:.*}/history", r.getImagesHistory),
|
router.NewGetRoute("/images/{name:.*}/history", ir.getImagesHistory),
|
||||||
router.NewGetRoute("/images/{name:.*}/json", r.getImagesByName),
|
router.NewGetRoute("/images/{name:.*}/json", ir.getImagesByName),
|
||||||
// POST
|
// POST
|
||||||
router.NewPostRoute("/images/load", r.postImagesLoad),
|
router.NewPostRoute("/images/load", ir.postImagesLoad),
|
||||||
router.NewPostRoute("/images/create", r.postImagesCreate),
|
router.NewPostRoute("/images/create", ir.postImagesCreate),
|
||||||
router.NewPostRoute("/images/{name:.*}/push", r.postImagesPush),
|
router.NewPostRoute("/images/{name:.*}/push", ir.postImagesPush),
|
||||||
router.NewPostRoute("/images/{name:.*}/tag", r.postImagesTag),
|
router.NewPostRoute("/images/{name:.*}/tag", ir.postImagesTag),
|
||||||
router.NewPostRoute("/images/prune", r.postImagesPrune),
|
router.NewPostRoute("/images/prune", ir.postImagesPrune),
|
||||||
// DELETE
|
// DELETE
|
||||||
router.NewDeleteRoute("/images/{name:.*}", r.deleteImages),
|
router.NewDeleteRoute("/images/{name:.*}", ir.deleteImages),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,43 +2,50 @@ package image // import "github.com/docker/docker/api/server/router/image"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
"fmt"
|
||||||
"encoding/json"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd/platforms"
|
"github.com/containerd/containerd/platforms"
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/distribution/reference"
|
||||||
|
"github.com/docker/docker/api"
|
||||||
"github.com/docker/docker/api/server/httputils"
|
"github.com/docker/docker/api/server/httputils"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/backend"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
|
imagetypes "github.com/docker/docker/api/types/image"
|
||||||
|
"github.com/docker/docker/api/types/registry"
|
||||||
"github.com/docker/docker/api/types/versions"
|
"github.com/docker/docker/api/types/versions"
|
||||||
|
"github.com/docker/docker/builder/remotecontext"
|
||||||
|
"github.com/docker/docker/dockerversion"
|
||||||
"github.com/docker/docker/errdefs"
|
"github.com/docker/docker/errdefs"
|
||||||
"github.com/docker/docker/image"
|
"github.com/docker/docker/image"
|
||||||
"github.com/docker/docker/layer"
|
|
||||||
"github.com/docker/docker/pkg/ioutils"
|
"github.com/docker/docker/pkg/ioutils"
|
||||||
|
"github.com/docker/docker/pkg/progress"
|
||||||
"github.com/docker/docker/pkg/streamformatter"
|
"github.com/docker/docker/pkg/streamformatter"
|
||||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
"github.com/opencontainers/go-digest"
|
||||||
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Creates an image from Pull or from Import
|
// Creates an image from Pull or from Import
|
||||||
func (s *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (ir *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
|
|
||||||
if err := httputils.ParseForm(r); err != nil {
|
if err := httputils.ParseForm(r); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
image = r.Form.Get("fromImage")
|
img = r.Form.Get("fromImage")
|
||||||
repo = r.Form.Get("repo")
|
repo = r.Form.Get("repo")
|
||||||
tag = r.Form.Get("tag")
|
tag = r.Form.Get("tag")
|
||||||
message = r.Form.Get("message")
|
comment = r.Form.Get("message")
|
||||||
progressErr error
|
progressErr error
|
||||||
output = ioutils.NewWriteFlusher(w)
|
output = ioutils.NewWriteFlusher(w)
|
||||||
platform *specs.Platform
|
platform *ocispec.Platform
|
||||||
)
|
)
|
||||||
defer output.Close()
|
defer output.Close()
|
||||||
|
|
||||||
|
@ -55,7 +62,7 @@ func (s *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWrite
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if image != "" { // pull
|
if img != "" { // pull
|
||||||
metaHeaders := map[string][]string{}
|
metaHeaders := map[string][]string{}
|
||||||
for k, v := range r.Header {
|
for k, v := range r.Header {
|
||||||
if strings.HasPrefix(k, "X-Meta-") {
|
if strings.HasPrefix(k, "X-Meta-") {
|
||||||
|
@ -63,20 +70,80 @@ func (s *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWrite
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
authEncoded := r.Header.Get("X-Registry-Auth")
|
// Special case: "pull -a" may send an image name with a
|
||||||
authConfig := &types.AuthConfig{}
|
// trailing :. This is ugly, but let's not break API
|
||||||
if authEncoded != "" {
|
// compatibility.
|
||||||
authJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
|
imgName := strings.TrimSuffix(img, ":")
|
||||||
if err := json.NewDecoder(authJSON).Decode(authConfig); err != nil {
|
|
||||||
// for a pull it is not an error if no auth was given
|
ref, err := reference.ParseNormalizedNamed(imgName)
|
||||||
// to increase compatibility with the existing api it is defaulting to be empty
|
if err != nil {
|
||||||
authConfig = &types.AuthConfig{}
|
return errdefs.InvalidParameter(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(thaJeztah) this could use a WithTagOrDigest() utility
|
||||||
|
if tag != "" {
|
||||||
|
// The "tag" could actually be a digest.
|
||||||
|
var dgst digest.Digest
|
||||||
|
dgst, err = digest.Parse(tag)
|
||||||
|
if err == nil {
|
||||||
|
ref, err = reference.WithDigest(reference.TrimNamed(ref), dgst)
|
||||||
|
} else {
|
||||||
|
ref, err = reference.WithTag(ref, tag)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return errdefs.InvalidParameter(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
progressErr = s.backend.PullImage(ctx, image, tag, platform, metaHeaders, authConfig, output)
|
|
||||||
|
if err := validateRepoName(ref); err != nil {
|
||||||
|
return errdefs.Forbidden(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// For a pull it is not an error if no auth was given. Ignore invalid
|
||||||
|
// AuthConfig to increase compatibility with the existing API.
|
||||||
|
authConfig, _ := registry.DecodeAuthConfig(r.Header.Get(registry.AuthHeader))
|
||||||
|
progressErr = ir.backend.PullImage(ctx, ref, platform, metaHeaders, authConfig, output)
|
||||||
} else { // import
|
} else { // import
|
||||||
src := r.Form.Get("fromSrc")
|
src := r.Form.Get("fromSrc")
|
||||||
progressErr = s.backend.ImportImage(src, repo, platform, tag, message, r.Body, output, r.Form["changes"])
|
|
||||||
|
tagRef, err := httputils.RepoTagReference(repo, tag)
|
||||||
|
if err != nil {
|
||||||
|
return errdefs.InvalidParameter(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(comment) == 0 {
|
||||||
|
comment = "Imported from " + src
|
||||||
|
}
|
||||||
|
|
||||||
|
var layerReader io.ReadCloser
|
||||||
|
defer r.Body.Close()
|
||||||
|
if src == "-" {
|
||||||
|
layerReader = r.Body
|
||||||
|
} else {
|
||||||
|
if len(strings.Split(src, "://")) == 1 {
|
||||||
|
src = "http://" + src
|
||||||
|
}
|
||||||
|
u, err := url.Parse(src)
|
||||||
|
if err != nil {
|
||||||
|
return errdefs.InvalidParameter(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := remotecontext.GetWithStatusError(u.String())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
output.Write(streamformatter.FormatStatus("", "Downloading from %s", u))
|
||||||
|
progressOutput := streamformatter.NewJSONProgressOutput(output, true)
|
||||||
|
layerReader = progress.NewProgressReader(resp.Body, progressOutput, resp.ContentLength, "", "Importing")
|
||||||
|
defer layerReader.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
var id image.ID
|
||||||
|
id, progressErr = ir.backend.ImportImage(ctx, tagRef, platform, comment, layerReader, r.Form["changes"])
|
||||||
|
|
||||||
|
if progressErr == nil {
|
||||||
|
output.Write(streamformatter.FormatStatus("", id.String()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if progressErr != nil {
|
if progressErr != nil {
|
||||||
if !output.Flushed() {
|
if !output.Flushed() {
|
||||||
|
@ -88,7 +155,7 @@ func (s *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWrite
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *imageRouter) postImagesPush(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (ir *imageRouter) postImagesPush(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
metaHeaders := map[string][]string{}
|
metaHeaders := map[string][]string{}
|
||||||
for k, v := range r.Header {
|
for k, v := range r.Header {
|
||||||
if strings.HasPrefix(k, "X-Meta-") {
|
if strings.HasPrefix(k, "X-Meta-") {
|
||||||
|
@ -98,32 +165,47 @@ func (s *imageRouter) postImagesPush(ctx context.Context, w http.ResponseWriter,
|
||||||
if err := httputils.ParseForm(r); err != nil {
|
if err := httputils.ParseForm(r); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
authConfig := &types.AuthConfig{}
|
|
||||||
|
|
||||||
authEncoded := r.Header.Get("X-Registry-Auth")
|
var authConfig *registry.AuthConfig
|
||||||
if authEncoded != "" {
|
if authEncoded := r.Header.Get(registry.AuthHeader); authEncoded != "" {
|
||||||
// the new format is to handle the authConfig as a header
|
// the new format is to handle the authConfig as a header. Ignore invalid
|
||||||
authJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
|
// AuthConfig to increase compatibility with the existing API.
|
||||||
if err := json.NewDecoder(authJSON).Decode(authConfig); err != nil {
|
authConfig, _ = registry.DecodeAuthConfig(authEncoded)
|
||||||
// to increase compatibility to existing api it is defaulting to be empty
|
|
||||||
authConfig = &types.AuthConfig{}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// the old format is supported for compatibility if there was no authConfig header
|
// the old format is supported for compatibility if there was no authConfig header
|
||||||
if err := json.NewDecoder(r.Body).Decode(authConfig); err != nil {
|
var err error
|
||||||
return errors.Wrap(errdefs.InvalidParameter(err), "Bad parameters and missing X-Registry-Auth")
|
authConfig, err = registry.DecodeAuthConfigBody(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "bad parameters and missing X-Registry-Auth")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
image := vars["name"]
|
|
||||||
tag := r.Form.Get("tag")
|
|
||||||
|
|
||||||
output := ioutils.NewWriteFlusher(w)
|
output := ioutils.NewWriteFlusher(w)
|
||||||
defer output.Close()
|
defer output.Close()
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
if err := s.backend.PushImage(ctx, image, tag, metaHeaders, authConfig, output); err != nil {
|
img := vars["name"]
|
||||||
|
tag := r.Form.Get("tag")
|
||||||
|
|
||||||
|
var ref reference.Named
|
||||||
|
|
||||||
|
// Tag is empty only in case PushOptions.All is true.
|
||||||
|
if tag != "" {
|
||||||
|
r, err := httputils.RepoTagReference(img, tag)
|
||||||
|
if err != nil {
|
||||||
|
return errdefs.InvalidParameter(err)
|
||||||
|
}
|
||||||
|
ref = r
|
||||||
|
} else {
|
||||||
|
r, err := reference.ParseNormalizedNamed(img)
|
||||||
|
if err != nil {
|
||||||
|
return errdefs.InvalidParameter(err)
|
||||||
|
}
|
||||||
|
ref = r
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ir.backend.PushImage(ctx, ref, metaHeaders, authConfig, output); err != nil {
|
||||||
if !output.Flushed() {
|
if !output.Flushed() {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -132,7 +214,7 @@ func (s *imageRouter) postImagesPush(ctx context.Context, w http.ResponseWriter,
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *imageRouter) getImagesGet(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (ir *imageRouter) getImagesGet(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := httputils.ParseForm(r); err != nil {
|
if err := httputils.ParseForm(r); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -148,7 +230,7 @@ func (s *imageRouter) getImagesGet(ctx context.Context, w http.ResponseWriter, r
|
||||||
names = r.Form["names"]
|
names = r.Form["names"]
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.backend.ExportImage(names, output); err != nil {
|
if err := ir.backend.ExportImage(ctx, names, output); err != nil {
|
||||||
if !output.Flushed() {
|
if !output.Flushed() {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -157,7 +239,7 @@ func (s *imageRouter) getImagesGet(ctx context.Context, w http.ResponseWriter, r
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *imageRouter) postImagesLoad(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (ir *imageRouter) postImagesLoad(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := httputils.ParseForm(r); err != nil {
|
if err := httputils.ParseForm(r); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -167,7 +249,7 @@ func (s *imageRouter) postImagesLoad(ctx context.Context, w http.ResponseWriter,
|
||||||
|
|
||||||
output := ioutils.NewWriteFlusher(w)
|
output := ioutils.NewWriteFlusher(w)
|
||||||
defer output.Close()
|
defer output.Close()
|
||||||
if err := s.backend.LoadImage(r.Body, output, quiet); err != nil {
|
if err := ir.backend.LoadImage(ctx, r.Body, output, quiet); err != nil {
|
||||||
_, _ = output.Write(streamformatter.FormatError(err))
|
_, _ = output.Write(streamformatter.FormatError(err))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -181,7 +263,7 @@ func (missingImageError) Error() string {
|
||||||
|
|
||||||
func (missingImageError) InvalidParameter() {}
|
func (missingImageError) InvalidParameter() {}
|
||||||
|
|
||||||
func (s *imageRouter) deleteImages(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (ir *imageRouter) deleteImages(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := httputils.ParseForm(r); err != nil {
|
if err := httputils.ParseForm(r); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -195,7 +277,7 @@ func (s *imageRouter) deleteImages(ctx context.Context, w http.ResponseWriter, r
|
||||||
force := httputils.BoolValue(r, "force")
|
force := httputils.BoolValue(r, "force")
|
||||||
prune := !httputils.BoolValue(r, "noprune")
|
prune := !httputils.BoolValue(r, "noprune")
|
||||||
|
|
||||||
list, err := s.backend.ImageDelete(name, force, prune)
|
list, err := ir.backend.ImageDelete(ctx, name, force, prune)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -203,25 +285,37 @@ func (s *imageRouter) deleteImages(ctx context.Context, w http.ResponseWriter, r
|
||||||
return httputils.WriteJSON(w, http.StatusOK, list)
|
return httputils.WriteJSON(w, http.StatusOK, list)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *imageRouter) getImagesByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (ir *imageRouter) getImagesByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
image, err := s.backend.GetImage(vars["name"], nil)
|
img, err := ir.backend.GetImage(ctx, vars["name"], backend.GetImageOpts{Details: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
imageInspect, err := s.toImageInspect(image)
|
imageInspect, err := ir.toImageInspect(img)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version := httputils.VersionFromContext(ctx)
|
||||||
|
if versions.LessThan(version, "1.44") {
|
||||||
|
imageInspect.VirtualSize = imageInspect.Size //nolint:staticcheck // ignore SA1019: field is deprecated, but still set on API < v1.44.
|
||||||
|
|
||||||
|
if imageInspect.Created == "" {
|
||||||
|
// backwards compatibility for Created not existing returning "0001-01-01T00:00:00Z"
|
||||||
|
// https://github.com/moby/moby/issues/47368
|
||||||
|
imageInspect.Created = time.Time{}.Format(time.RFC3339Nano)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if versions.GreaterThanOrEqualTo(version, "1.45") {
|
||||||
|
imageInspect.Container = "" //nolint:staticcheck // ignore SA1019: field is deprecated, but still set on API < v1.45.
|
||||||
|
imageInspect.ContainerConfig = nil //nolint:staticcheck // ignore SA1019: field is deprecated, but still set on API < v1.45.
|
||||||
|
}
|
||||||
return httputils.WriteJSON(w, http.StatusOK, imageInspect)
|
return httputils.WriteJSON(w, http.StatusOK, imageInspect)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *imageRouter) toImageInspect(img *image.Image) (*types.ImageInspect, error) {
|
func (ir *imageRouter) toImageInspect(img *image.Image) (*types.ImageInspect, error) {
|
||||||
refs := s.referenceBackend.References(img.ID().Digest())
|
var repoTags, repoDigests []string
|
||||||
repoTags := []string{}
|
for _, ref := range img.Details.References {
|
||||||
repoDigests := []string{}
|
|
||||||
for _, ref := range refs {
|
|
||||||
switch ref.(type) {
|
switch ref.(type) {
|
||||||
case reference.NamedTagged:
|
case reference.NamedTagged:
|
||||||
repoTags = append(repoTags, reference.FamiliarString(ref))
|
repoTags = append(repoTags, reference.FamiliarString(ref))
|
||||||
|
@ -230,30 +324,22 @@ func (s *imageRouter) toImageInspect(img *image.Image) (*types.ImageInspect, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var size int64
|
|
||||||
var layerMetadata map[string]string
|
|
||||||
layerID := img.RootFS.ChainID()
|
|
||||||
if layerID != "" {
|
|
||||||
l, err := s.layerStore.Get(layerID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer layer.ReleaseAndLog(s.layerStore, l)
|
|
||||||
size = l.Size()
|
|
||||||
layerMetadata, err = l.Metadata()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
comment := img.Comment
|
comment := img.Comment
|
||||||
if len(comment) == 0 && len(img.History) > 0 {
|
if len(comment) == 0 && len(img.History) > 0 {
|
||||||
comment = img.History[len(img.History)-1].Comment
|
comment = img.History[len(img.History)-1].Comment
|
||||||
}
|
}
|
||||||
|
|
||||||
lastUpdated, err := s.imageStore.GetLastUpdated(img.ID())
|
// Make sure we output empty arrays instead of nil.
|
||||||
if err != nil {
|
if repoTags == nil {
|
||||||
return nil, err
|
repoTags = []string{}
|
||||||
|
}
|
||||||
|
if repoDigests == nil {
|
||||||
|
repoDigests = []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var created string
|
||||||
|
if img.Created != nil {
|
||||||
|
created = img.Created.Format(time.RFC3339Nano)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &types.ImageInspect{
|
return &types.ImageInspect{
|
||||||
|
@ -262,9 +348,9 @@ func (s *imageRouter) toImageInspect(img *image.Image) (*types.ImageInspect, err
|
||||||
RepoDigests: repoDigests,
|
RepoDigests: repoDigests,
|
||||||
Parent: img.Parent.String(),
|
Parent: img.Parent.String(),
|
||||||
Comment: comment,
|
Comment: comment,
|
||||||
Created: img.Created.Format(time.RFC3339Nano),
|
Created: created,
|
||||||
Container: img.Container,
|
Container: img.Container, //nolint:staticcheck // ignore SA1019: field is deprecated, but still set on API < v1.45.
|
||||||
ContainerConfig: &img.ContainerConfig,
|
ContainerConfig: &img.ContainerConfig, //nolint:staticcheck // ignore SA1019: field is deprecated, but still set on API < v1.45.
|
||||||
DockerVersion: img.DockerVersion,
|
DockerVersion: img.DockerVersion,
|
||||||
Author: img.Author,
|
Author: img.Author,
|
||||||
Config: img.Config,
|
Config: img.Config,
|
||||||
|
@ -272,15 +358,14 @@ func (s *imageRouter) toImageInspect(img *image.Image) (*types.ImageInspect, err
|
||||||
Variant: img.Variant,
|
Variant: img.Variant,
|
||||||
Os: img.OperatingSystem(),
|
Os: img.OperatingSystem(),
|
||||||
OsVersion: img.OSVersion,
|
OsVersion: img.OSVersion,
|
||||||
Size: size,
|
Size: img.Details.Size,
|
||||||
VirtualSize: size, // TODO: field unused, deprecate
|
|
||||||
GraphDriver: types.GraphDriverData{
|
GraphDriver: types.GraphDriverData{
|
||||||
Name: s.layerStore.DriverName(),
|
Name: img.Details.Driver,
|
||||||
Data: layerMetadata,
|
Data: img.Details.Metadata,
|
||||||
},
|
},
|
||||||
RootFS: rootFSToAPIType(img.RootFS),
|
RootFS: rootFSToAPIType(img.RootFS),
|
||||||
Metadata: types.ImageMetadata{
|
Metadata: imagetypes.Metadata{
|
||||||
LastTagTime: lastUpdated,
|
LastTagTime: img.Details.LastUpdated,
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -296,7 +381,7 @@ func rootFSToAPIType(rootfs *image.RootFS) types.RootFS {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *imageRouter) getImagesJSON(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (ir *imageRouter) getImagesJSON(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := httputils.ParseForm(r); err != nil {
|
if err := httputils.ParseForm(r); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -321,7 +406,7 @@ func (s *imageRouter) getImagesJSON(ctx context.Context, w http.ResponseWriter,
|
||||||
sharedSize = httputils.BoolValue(r, "shared-size")
|
sharedSize = httputils.BoolValue(r, "shared-size")
|
||||||
}
|
}
|
||||||
|
|
||||||
images, err := s.backend.Images(ctx, types.ImageListOptions{
|
images, err := ir.backend.Images(ctx, imagetypes.ListOptions{
|
||||||
All: httputils.BoolValue(r, "all"),
|
All: httputils.BoolValue(r, "all"),
|
||||||
Filters: imageFilters,
|
Filters: imageFilters,
|
||||||
SharedSize: sharedSize,
|
SharedSize: sharedSize,
|
||||||
|
@ -330,12 +415,32 @@ func (s *imageRouter) getImagesJSON(ctx context.Context, w http.ResponseWriter,
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useNone := versions.LessThan(version, "1.43")
|
||||||
|
withVirtualSize := versions.LessThan(version, "1.44")
|
||||||
|
for _, img := range images {
|
||||||
|
if useNone {
|
||||||
|
if len(img.RepoTags) == 0 && len(img.RepoDigests) == 0 {
|
||||||
|
img.RepoTags = append(img.RepoTags, "<none>:<none>")
|
||||||
|
img.RepoDigests = append(img.RepoDigests, "<none>@<none>")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if img.RepoTags == nil {
|
||||||
|
img.RepoTags = []string{}
|
||||||
|
}
|
||||||
|
if img.RepoDigests == nil {
|
||||||
|
img.RepoDigests = []string{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if withVirtualSize {
|
||||||
|
img.VirtualSize = img.Size //nolint:staticcheck // ignore SA1019: field is deprecated, but still set on API < v1.44.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return httputils.WriteJSON(w, http.StatusOK, images)
|
return httputils.WriteJSON(w, http.StatusOK, images)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *imageRouter) getImagesHistory(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (ir *imageRouter) getImagesHistory(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
name := vars["name"]
|
history, err := ir.backend.ImageHistory(ctx, vars["name"])
|
||||||
history, err := s.backend.ImageHistory(name)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -343,40 +448,37 @@ func (s *imageRouter) getImagesHistory(ctx context.Context, w http.ResponseWrite
|
||||||
return httputils.WriteJSON(w, http.StatusOK, history)
|
return httputils.WriteJSON(w, http.StatusOK, history)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *imageRouter) postImagesTag(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (ir *imageRouter) postImagesTag(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := httputils.ParseForm(r); err != nil {
|
if err := httputils.ParseForm(r); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := s.backend.TagImage(vars["name"], r.Form.Get("repo"), r.Form.Get("tag")); err != nil {
|
|
||||||
|
ref, err := httputils.RepoTagReference(r.Form.Get("repo"), r.Form.Get("tag"))
|
||||||
|
if ref == nil || err != nil {
|
||||||
|
return errdefs.InvalidParameter(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
refName := reference.FamiliarName(ref)
|
||||||
|
if refName == string(digest.Canonical) {
|
||||||
|
return errdefs.InvalidParameter(errors.New("refusing to create an ambiguous tag using digest algorithm as name"))
|
||||||
|
}
|
||||||
|
|
||||||
|
img, err := ir.backend.GetImage(ctx, vars["name"], backend.GetImageOpts{})
|
||||||
|
if err != nil {
|
||||||
|
return errdefs.NotFound(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ir.backend.TagImage(ctx, img.ID(), ref); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
w.WriteHeader(http.StatusCreated)
|
w.WriteHeader(http.StatusCreated)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *imageRouter) getImagesSearch(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (ir *imageRouter) getImagesSearch(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := httputils.ParseForm(r); err != nil {
|
if err := httputils.ParseForm(r); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var (
|
|
||||||
config *types.AuthConfig
|
|
||||||
authEncoded = r.Header.Get("X-Registry-Auth")
|
|
||||||
headers = map[string][]string{}
|
|
||||||
)
|
|
||||||
|
|
||||||
if authEncoded != "" {
|
|
||||||
authJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
|
|
||||||
if err := json.NewDecoder(authJSON).Decode(&config); err != nil {
|
|
||||||
// for a search it is not an error if no auth was given
|
|
||||||
// to increase compatibility with the existing api it is defaulting to be empty
|
|
||||||
config = &types.AuthConfig{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for k, v := range r.Header {
|
|
||||||
if strings.HasPrefix(k, "X-Meta-") {
|
|
||||||
headers[k] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var limit int
|
var limit int
|
||||||
if r.Form.Get("limit") != "" {
|
if r.Form.Get("limit") != "" {
|
||||||
|
@ -391,14 +493,26 @@ func (s *imageRouter) getImagesSearch(ctx context.Context, w http.ResponseWriter
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
query, err := s.backend.SearchRegistryForImages(ctx, searchFilters, r.Form.Get("term"), limit, config, headers)
|
// For a search it is not an error if no auth was given. Ignore invalid
|
||||||
|
// AuthConfig to increase compatibility with the existing API.
|
||||||
|
authConfig, _ := registry.DecodeAuthConfig(r.Header.Get(registry.AuthHeader))
|
||||||
|
|
||||||
|
headers := http.Header{}
|
||||||
|
for k, v := range r.Header {
|
||||||
|
k = http.CanonicalHeaderKey(k)
|
||||||
|
if strings.HasPrefix(k, "X-Meta-") {
|
||||||
|
headers[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
headers.Set("User-Agent", dockerversion.DockerUserAgent(ctx))
|
||||||
|
res, err := ir.searcher.Search(ctx, searchFilters, r.Form.Get("term"), limit, authConfig, headers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return httputils.WriteJSON(w, http.StatusOK, query.Results)
|
return httputils.WriteJSON(w, http.StatusOK, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *imageRouter) postImagesPrune(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (ir *imageRouter) postImagesPrune(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := httputils.ParseForm(r); err != nil {
|
if err := httputils.ParseForm(r); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -408,9 +522,18 @@ func (s *imageRouter) postImagesPrune(ctx context.Context, w http.ResponseWriter
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
pruneReport, err := s.backend.ImagesPrune(ctx, pruneFilters)
|
pruneReport, err := ir.backend.ImagesPrune(ctx, pruneFilters)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return httputils.WriteJSON(w, http.StatusOK, pruneReport)
|
return httputils.WriteJSON(w, http.StatusOK, pruneReport)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validateRepoName validates the name of a repository.
|
||||||
|
func validateRepoName(name reference.Named) error {
|
||||||
|
familiarName := reference.FamiliarName(name)
|
||||||
|
if familiarName == api.NoBaseImageSpecifier {
|
||||||
|
return fmt.Errorf("'%s' is a reserved name", familiarName)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -4,16 +4,15 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/backend"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/api/types/network"
|
"github.com/docker/docker/api/types/network"
|
||||||
"github.com/docker/docker/libnetwork"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Backend is all the methods that need to be implemented
|
// Backend is all the methods that need to be implemented
|
||||||
// to provide network specific functionality.
|
// to provide network specific functionality.
|
||||||
type Backend interface {
|
type Backend interface {
|
||||||
FindNetwork(idName string) (libnetwork.Network, error)
|
GetNetworks(filters.Args, backend.NetworkListConfig) ([]types.NetworkResource, error)
|
||||||
GetNetworks(filters.Args, types.NetworkListConfig) ([]types.NetworkResource, error)
|
|
||||||
CreateNetwork(nc types.NetworkCreateRequest) (*types.NetworkCreateResponse, error)
|
CreateNetwork(nc types.NetworkCreateRequest) (*types.NetworkCreateResponse, error)
|
||||||
ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error
|
ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error
|
||||||
DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error
|
DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
package network // import "github.com/docker/docker/api/server/router/network"
|
|
|
@ -8,12 +8,13 @@ import (
|
||||||
|
|
||||||
"github.com/docker/docker/api/server/httputils"
|
"github.com/docker/docker/api/server/httputils"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/backend"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/api/types/network"
|
"github.com/docker/docker/api/types/network"
|
||||||
"github.com/docker/docker/api/types/versions"
|
"github.com/docker/docker/api/types/versions"
|
||||||
"github.com/docker/docker/errdefs"
|
"github.com/docker/docker/errdefs"
|
||||||
"github.com/docker/docker/libnetwork"
|
"github.com/docker/docker/libnetwork"
|
||||||
netconst "github.com/docker/docker/libnetwork/datastore"
|
"github.com/docker/docker/libnetwork/scope"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -39,7 +40,7 @@ func (n *networkRouter) getNetworksList(ctx context.Context, w http.ResponseWrit
|
||||||
|
|
||||||
// Combine the network list returned by Docker daemon if it is not already
|
// Combine the network list returned by Docker daemon if it is not already
|
||||||
// returned by the cluster manager
|
// returned by the cluster manager
|
||||||
localNetworks, err := n.backend.GetNetworks(filter, types.NetworkListConfig{Detailed: versions.LessThan(httputils.VersionFromContext(ctx), "1.28")})
|
localNetworks, err := n.backend.GetNetworks(filter, backend.NetworkListConfig{Detailed: versions.LessThan(httputils.VersionFromContext(ctx), "1.28")})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -83,10 +84,6 @@ func (e ambigousResultsError) Error() string {
|
||||||
|
|
||||||
func (ambigousResultsError) InvalidParameter() {}
|
func (ambigousResultsError) InvalidParameter() {}
|
||||||
|
|
||||||
func nameConflict(name string) error {
|
|
||||||
return errdefs.Conflict(libnetwork.NetworkNameError(name))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *networkRouter) getNetwork(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (n *networkRouter) getNetwork(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := httputils.ParseForm(r); err != nil {
|
if err := httputils.ParseForm(r); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -102,7 +99,7 @@ func (n *networkRouter) getNetwork(ctx context.Context, w http.ResponseWriter, r
|
||||||
return errors.Wrapf(invalidRequestError{err}, "invalid value for verbose: %s", v)
|
return errors.Wrapf(invalidRequestError{err}, "invalid value for verbose: %s", v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope := r.URL.Query().Get("scope")
|
networkScope := r.URL.Query().Get("scope")
|
||||||
|
|
||||||
// In case multiple networks have duplicate names, return error.
|
// In case multiple networks have duplicate names, return error.
|
||||||
// TODO (yongtang): should we wrap with version here for backward compatibility?
|
// TODO (yongtang): should we wrap with version here for backward compatibility?
|
||||||
|
@ -118,23 +115,23 @@ func (n *networkRouter) getNetwork(ctx context.Context, w http.ResponseWriter, r
|
||||||
// TODO(@cpuguy83): All this logic for figuring out which network to return does not belong here
|
// TODO(@cpuguy83): All this logic for figuring out which network to return does not belong here
|
||||||
// Instead there should be a backend function to just get one network.
|
// Instead there should be a backend function to just get one network.
|
||||||
filter := filters.NewArgs(filters.Arg("idOrName", term))
|
filter := filters.NewArgs(filters.Arg("idOrName", term))
|
||||||
if scope != "" {
|
if networkScope != "" {
|
||||||
filter.Add("scope", scope)
|
filter.Add("scope", networkScope)
|
||||||
}
|
}
|
||||||
nw, _ := n.backend.GetNetworks(filter, types.NetworkListConfig{Detailed: true, Verbose: verbose})
|
networks, _ := n.backend.GetNetworks(filter, backend.NetworkListConfig{Detailed: true, Verbose: verbose})
|
||||||
for _, network := range nw {
|
for _, nw := range networks {
|
||||||
if network.ID == term {
|
if nw.ID == term {
|
||||||
return httputils.WriteJSON(w, http.StatusOK, network)
|
return httputils.WriteJSON(w, http.StatusOK, nw)
|
||||||
}
|
}
|
||||||
if network.Name == term {
|
if nw.Name == term {
|
||||||
// No need to check the ID collision here as we are still in
|
// No need to check the ID collision here as we are still in
|
||||||
// local scope and the network ID is unique in this scope.
|
// local scope and the network ID is unique in this scope.
|
||||||
listByFullName[network.ID] = network
|
listByFullName[nw.ID] = nw
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(network.ID, term) {
|
if strings.HasPrefix(nw.ID, term) {
|
||||||
// No need to check the ID collision here as we are still in
|
// No need to check the ID collision here as we are still in
|
||||||
// local scope and the network ID is unique in this scope.
|
// local scope and the network ID is unique in this scope.
|
||||||
listByPartialID[network.ID] = network
|
listByPartialID[nw.ID] = nw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +141,7 @@ func (n *networkRouter) getNetwork(ctx context.Context, w http.ResponseWriter, r
|
||||||
// or if the get network was passed with a network name and scope as swarm
|
// or if the get network was passed with a network name and scope as swarm
|
||||||
// return the network. Skipped using isMatchingScope because it is true if the scope
|
// return the network. Skipped using isMatchingScope because it is true if the scope
|
||||||
// is not set which would be case if the client API v1.30
|
// is not set which would be case if the client API v1.30
|
||||||
if strings.HasPrefix(nwk.ID, term) || (netconst.SwarmScope == scope) {
|
if strings.HasPrefix(nwk.ID, term) || networkScope == scope.Swarm {
|
||||||
// If we have a previous match "backend", return it, we need verbose when enabled
|
// If we have a previous match "backend", return it, we need verbose when enabled
|
||||||
// ex: overlay/partial_ID or name/swarm_scope
|
// ex: overlay/partial_ID or name/swarm_scope
|
||||||
if nwv, ok := listByPartialID[nwk.ID]; ok {
|
if nwv, ok := listByPartialID[nwk.ID]; ok {
|
||||||
|
@ -156,25 +153,25 @@ func (n *networkRouter) getNetwork(ctx context.Context, w http.ResponseWriter, r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nr, _ := n.cluster.GetNetworks(filter)
|
networks, _ = n.cluster.GetNetworks(filter)
|
||||||
for _, network := range nr {
|
for _, nw := range networks {
|
||||||
if network.ID == term {
|
if nw.ID == term {
|
||||||
return httputils.WriteJSON(w, http.StatusOK, network)
|
return httputils.WriteJSON(w, http.StatusOK, nw)
|
||||||
}
|
}
|
||||||
if network.Name == term {
|
if nw.Name == term {
|
||||||
// Check the ID collision as we are in swarm scope here, and
|
// Check the ID collision as we are in swarm scope here, and
|
||||||
// the map (of the listByFullName) may have already had a
|
// the map (of the listByFullName) may have already had a
|
||||||
// network with the same ID (from local scope previously)
|
// network with the same ID (from local scope previously)
|
||||||
if _, ok := listByFullName[network.ID]; !ok {
|
if _, ok := listByFullName[nw.ID]; !ok {
|
||||||
listByFullName[network.ID] = network
|
listByFullName[nw.ID] = nw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(network.ID, term) {
|
if strings.HasPrefix(nw.ID, term) {
|
||||||
// Check the ID collision as we are in swarm scope here, and
|
// Check the ID collision as we are in swarm scope here, and
|
||||||
// the map (of the listByPartialID) may have already had a
|
// the map (of the listByPartialID) may have already had a
|
||||||
// network with the same ID (from local scope previously)
|
// network with the same ID (from local scope previously)
|
||||||
if _, ok := listByPartialID[network.ID]; !ok {
|
if _, ok := listByPartialID[nw.ID]; !ok {
|
||||||
listByPartialID[network.ID] = network
|
listByPartialID[nw.ID] = nw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -213,21 +210,15 @@ func (n *networkRouter) postNetworkCreate(ctx context.Context, w http.ResponseWr
|
||||||
}
|
}
|
||||||
|
|
||||||
if nws, err := n.cluster.GetNetworksByName(create.Name); err == nil && len(nws) > 0 {
|
if nws, err := n.cluster.GetNetworksByName(create.Name); err == nil && len(nws) > 0 {
|
||||||
return nameConflict(create.Name)
|
return libnetwork.NetworkNameError(create.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For a Swarm-scoped network, this call to backend.CreateNetwork is used to
|
||||||
|
// validate the configuration. The network will not be created but, if the
|
||||||
|
// configuration is valid, ManagerRedirectError will be returned and handled
|
||||||
|
// below.
|
||||||
nw, err := n.backend.CreateNetwork(create)
|
nw, err := n.backend.CreateNetwork(create)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var warning string
|
|
||||||
if _, ok := err.(libnetwork.NetworkNameError); ok {
|
|
||||||
// check if user defined CheckDuplicate, if set true, return err
|
|
||||||
// otherwise prepare a warning message
|
|
||||||
if create.CheckDuplicate {
|
|
||||||
return nameConflict(create.Name)
|
|
||||||
}
|
|
||||||
warning = libnetwork.NetworkNameError(create.Name).Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := err.(libnetwork.ManagerRedirectError); !ok {
|
if _, ok := err.(libnetwork.ManagerRedirectError); !ok {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -236,8 +227,7 @@ func (n *networkRouter) postNetworkCreate(ctx context.Context, w http.ResponseWr
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
nw = &types.NetworkCreateResponse{
|
nw = &types.NetworkCreateResponse{
|
||||||
ID: id,
|
ID: id,
|
||||||
Warning: warning,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,42 +316,42 @@ func (n *networkRouter) findUniqueNetwork(term string) (types.NetworkResource, e
|
||||||
listByPartialID := map[string]types.NetworkResource{}
|
listByPartialID := map[string]types.NetworkResource{}
|
||||||
|
|
||||||
filter := filters.NewArgs(filters.Arg("idOrName", term))
|
filter := filters.NewArgs(filters.Arg("idOrName", term))
|
||||||
nw, _ := n.backend.GetNetworks(filter, types.NetworkListConfig{Detailed: true})
|
networks, _ := n.backend.GetNetworks(filter, backend.NetworkListConfig{Detailed: true})
|
||||||
for _, network := range nw {
|
for _, nw := range networks {
|
||||||
if network.ID == term {
|
if nw.ID == term {
|
||||||
return network, nil
|
return nw, nil
|
||||||
}
|
}
|
||||||
if network.Name == term && !network.Ingress {
|
if nw.Name == term && !nw.Ingress {
|
||||||
// No need to check the ID collision here as we are still in
|
// No need to check the ID collision here as we are still in
|
||||||
// local scope and the network ID is unique in this scope.
|
// local scope and the network ID is unique in this scope.
|
||||||
listByFullName[network.ID] = network
|
listByFullName[nw.ID] = nw
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(network.ID, term) {
|
if strings.HasPrefix(nw.ID, term) {
|
||||||
// No need to check the ID collision here as we are still in
|
// No need to check the ID collision here as we are still in
|
||||||
// local scope and the network ID is unique in this scope.
|
// local scope and the network ID is unique in this scope.
|
||||||
listByPartialID[network.ID] = network
|
listByPartialID[nw.ID] = nw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nr, _ := n.cluster.GetNetworks(filter)
|
networks, _ = n.cluster.GetNetworks(filter)
|
||||||
for _, network := range nr {
|
for _, nw := range networks {
|
||||||
if network.ID == term {
|
if nw.ID == term {
|
||||||
return network, nil
|
return nw, nil
|
||||||
}
|
}
|
||||||
if network.Name == term {
|
if nw.Name == term {
|
||||||
// Check the ID collision as we are in swarm scope here, and
|
// Check the ID collision as we are in swarm scope here, and
|
||||||
// the map (of the listByFullName) may have already had a
|
// the map (of the listByFullName) may have already had a
|
||||||
// network with the same ID (from local scope previously)
|
// network with the same ID (from local scope previously)
|
||||||
if _, ok := listByFullName[network.ID]; !ok {
|
if _, ok := listByFullName[nw.ID]; !ok {
|
||||||
listByFullName[network.ID] = network
|
listByFullName[nw.ID] = nw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(network.ID, term) {
|
if strings.HasPrefix(nw.ID, term) {
|
||||||
// Check the ID collision as we are in swarm scope here, and
|
// Check the ID collision as we are in swarm scope here, and
|
||||||
// the map (of the listByPartialID) may have already had a
|
// the map (of the listByPartialID) may have already had a
|
||||||
// network with the same ID (from local scope previously)
|
// network with the same ID (from local scope previously)
|
||||||
if _, ok := listByPartialID[network.ID]; !ok {
|
if _, ok := listByPartialID[nw.ID]; !ok {
|
||||||
listByPartialID[network.ID] = network
|
listByPartialID[nw.ID] = nw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,23 +5,25 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/distribution/reference"
|
||||||
enginetypes "github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/backend"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
|
"github.com/docker/docker/api/types/registry"
|
||||||
"github.com/docker/docker/plugin"
|
"github.com/docker/docker/plugin"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Backend for Plugin
|
// Backend for Plugin
|
||||||
type Backend interface {
|
type Backend interface {
|
||||||
Disable(name string, config *enginetypes.PluginDisableConfig) error
|
Disable(name string, config *backend.PluginDisableConfig) error
|
||||||
Enable(name string, config *enginetypes.PluginEnableConfig) error
|
Enable(name string, config *backend.PluginEnableConfig) error
|
||||||
List(filters.Args) ([]enginetypes.Plugin, error)
|
List(filters.Args) ([]types.Plugin, error)
|
||||||
Inspect(name string) (*enginetypes.Plugin, error)
|
Inspect(name string) (*types.Plugin, error)
|
||||||
Remove(name string, config *enginetypes.PluginRmConfig) error
|
Remove(name string, config *backend.PluginRmConfig) error
|
||||||
Set(name string, args []string) error
|
Set(name string, args []string) error
|
||||||
Privileges(ctx context.Context, ref reference.Named, metaHeaders http.Header, authConfig *enginetypes.AuthConfig) (enginetypes.PluginPrivileges, error)
|
Privileges(ctx context.Context, ref reference.Named, metaHeaders http.Header, authConfig *registry.AuthConfig) (types.PluginPrivileges, error)
|
||||||
Pull(ctx context.Context, ref reference.Named, name string, metaHeaders http.Header, authConfig *enginetypes.AuthConfig, privileges enginetypes.PluginPrivileges, outStream io.Writer, opts ...plugin.CreateOpt) error
|
Pull(ctx context.Context, ref reference.Named, name string, metaHeaders http.Header, authConfig *registry.AuthConfig, privileges types.PluginPrivileges, outStream io.Writer, opts ...plugin.CreateOpt) error
|
||||||
Push(ctx context.Context, name string, metaHeaders http.Header, authConfig *enginetypes.AuthConfig, outStream io.Writer) error
|
Push(ctx context.Context, name string, metaHeaders http.Header, authConfig *registry.AuthConfig, outStream io.Writer) error
|
||||||
Upgrade(ctx context.Context, ref reference.Named, name string, metaHeaders http.Header, authConfig *enginetypes.AuthConfig, privileges enginetypes.PluginPrivileges, outStream io.Writer) error
|
Upgrade(ctx context.Context, ref reference.Named, name string, metaHeaders http.Header, authConfig *registry.AuthConfig, privileges types.PluginPrivileges, outStream io.Writer) error
|
||||||
CreateFromContext(ctx context.Context, tarCtx io.ReadCloser, options *enginetypes.PluginCreateOptions) error
|
CreateFromContext(ctx context.Context, tarCtx io.ReadCloser, options *types.PluginCreateOptions) error
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,23 +2,22 @@ package plugin // import "github.com/docker/docker/api/server/router/plugin"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/distribution/reference"
|
||||||
"github.com/docker/docker/api/server/httputils"
|
"github.com/docker/docker/api/server/httputils"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/backend"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
|
"github.com/docker/docker/api/types/registry"
|
||||||
"github.com/docker/docker/pkg/ioutils"
|
"github.com/docker/docker/pkg/ioutils"
|
||||||
"github.com/docker/docker/pkg/streamformatter"
|
"github.com/docker/docker/pkg/streamformatter"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func parseHeaders(headers http.Header) (map[string][]string, *types.AuthConfig) {
|
func parseHeaders(headers http.Header) (map[string][]string, *registry.AuthConfig) {
|
||||||
|
|
||||||
metaHeaders := map[string][]string{}
|
metaHeaders := map[string][]string{}
|
||||||
for k, v := range headers {
|
for k, v := range headers {
|
||||||
if strings.HasPrefix(k, "X-Meta-") {
|
if strings.HasPrefix(k, "X-Meta-") {
|
||||||
|
@ -26,16 +25,8 @@ func parseHeaders(headers http.Header) (map[string][]string, *types.AuthConfig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get X-Registry-Auth
|
// Ignore invalid AuthConfig to increase compatibility with the existing API.
|
||||||
authEncoded := headers.Get("X-Registry-Auth")
|
authConfig, _ := registry.DecodeAuthConfig(headers.Get(registry.AuthHeader))
|
||||||
authConfig := &types.AuthConfig{}
|
|
||||||
if authEncoded != "" {
|
|
||||||
authJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
|
|
||||||
if err := json.NewDecoder(authJSON).Decode(authConfig); err != nil {
|
|
||||||
authConfig = &types.AuthConfig{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return metaHeaders, authConfig
|
return metaHeaders, authConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,7 +187,8 @@ func (pr *pluginRouter) createPlugin(ctx context.Context, w http.ResponseWriter,
|
||||||
}
|
}
|
||||||
|
|
||||||
options := &types.PluginCreateOptions{
|
options := &types.PluginCreateOptions{
|
||||||
RepoName: r.FormValue("name")}
|
RepoName: r.FormValue("name"),
|
||||||
|
}
|
||||||
|
|
||||||
if err := pr.backend.CreateFromContext(ctx, r.Body, options); err != nil {
|
if err := pr.backend.CreateFromContext(ctx, r.Body, options); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -216,7 +208,7 @@ func (pr *pluginRouter) enablePlugin(ctx context.Context, w http.ResponseWriter,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
config := &types.PluginEnableConfig{Timeout: timeout}
|
config := &backend.PluginEnableConfig{Timeout: timeout}
|
||||||
|
|
||||||
return pr.backend.Enable(name, config)
|
return pr.backend.Enable(name, config)
|
||||||
}
|
}
|
||||||
|
@ -227,7 +219,7 @@ func (pr *pluginRouter) disablePlugin(ctx context.Context, w http.ResponseWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
config := &types.PluginDisableConfig{
|
config := &backend.PluginDisableConfig{
|
||||||
ForceDisable: httputils.BoolValue(r, "force"),
|
ForceDisable: httputils.BoolValue(r, "force"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,7 +232,7 @@ func (pr *pluginRouter) removePlugin(ctx context.Context, w http.ResponseWriter,
|
||||||
}
|
}
|
||||||
|
|
||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
config := &types.PluginRmConfig{
|
config := &backend.PluginRmConfig{
|
||||||
ForceRemove: httputils.BoolValue(r, "force"),
|
ForceRemove: httputils.BoolValue(r, "force"),
|
||||||
}
|
}
|
||||||
return pr.backend.Remove(name, config)
|
return pr.backend.Remove(name, config)
|
||||||
|
|
|
@ -3,46 +3,41 @@ package swarm // import "github.com/docker/docker/api/server/router/swarm"
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
basictypes "github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/backend"
|
"github.com/docker/docker/api/types/backend"
|
||||||
types "github.com/docker/docker/api/types/swarm"
|
"github.com/docker/docker/api/types/container"
|
||||||
|
"github.com/docker/docker/api/types/swarm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Backend abstracts a swarm manager.
|
// Backend abstracts a swarm manager.
|
||||||
type Backend interface {
|
type Backend interface {
|
||||||
Init(req types.InitRequest) (string, error)
|
Init(req swarm.InitRequest) (string, error)
|
||||||
Join(req types.JoinRequest) error
|
Join(req swarm.JoinRequest) error
|
||||||
Leave(force bool) error
|
Leave(ctx context.Context, force bool) error
|
||||||
Inspect() (types.Swarm, error)
|
Inspect() (swarm.Swarm, error)
|
||||||
Update(uint64, types.Spec, types.UpdateFlags) error
|
Update(uint64, swarm.Spec, swarm.UpdateFlags) error
|
||||||
GetUnlockKey() (string, error)
|
GetUnlockKey() (string, error)
|
||||||
UnlockSwarm(req types.UnlockRequest) error
|
UnlockSwarm(req swarm.UnlockRequest) error
|
||||||
|
GetServices(types.ServiceListOptions) ([]swarm.Service, error)
|
||||||
GetServices(basictypes.ServiceListOptions) ([]types.Service, error)
|
GetService(idOrName string, insertDefaults bool) (swarm.Service, error)
|
||||||
GetService(idOrName string, insertDefaults bool) (types.Service, error)
|
CreateService(swarm.ServiceSpec, string, bool) (*swarm.ServiceCreateResponse, error)
|
||||||
CreateService(types.ServiceSpec, string, bool) (*basictypes.ServiceCreateResponse, error)
|
UpdateService(string, uint64, swarm.ServiceSpec, types.ServiceUpdateOptions, bool) (*swarm.ServiceUpdateResponse, error)
|
||||||
UpdateService(string, uint64, types.ServiceSpec, basictypes.ServiceUpdateOptions, bool) (*basictypes.ServiceUpdateResponse, error)
|
|
||||||
RemoveService(string) error
|
RemoveService(string) error
|
||||||
|
ServiceLogs(context.Context, *backend.LogSelector, *container.LogsOptions) (<-chan *backend.LogMessage, error)
|
||||||
ServiceLogs(context.Context, *backend.LogSelector, *basictypes.ContainerLogsOptions) (<-chan *backend.LogMessage, error)
|
GetNodes(types.NodeListOptions) ([]swarm.Node, error)
|
||||||
|
GetNode(string) (swarm.Node, error)
|
||||||
GetNodes(basictypes.NodeListOptions) ([]types.Node, error)
|
UpdateNode(string, uint64, swarm.NodeSpec) error
|
||||||
GetNode(string) (types.Node, error)
|
|
||||||
UpdateNode(string, uint64, types.NodeSpec) error
|
|
||||||
RemoveNode(string, bool) error
|
RemoveNode(string, bool) error
|
||||||
|
GetTasks(types.TaskListOptions) ([]swarm.Task, error)
|
||||||
GetTasks(basictypes.TaskListOptions) ([]types.Task, error)
|
GetTask(string) (swarm.Task, error)
|
||||||
GetTask(string) (types.Task, error)
|
GetSecrets(opts types.SecretListOptions) ([]swarm.Secret, error)
|
||||||
|
CreateSecret(s swarm.SecretSpec) (string, error)
|
||||||
GetSecrets(opts basictypes.SecretListOptions) ([]types.Secret, error)
|
|
||||||
CreateSecret(s types.SecretSpec) (string, error)
|
|
||||||
RemoveSecret(idOrName string) error
|
RemoveSecret(idOrName string) error
|
||||||
GetSecret(id string) (types.Secret, error)
|
GetSecret(id string) (swarm.Secret, error)
|
||||||
UpdateSecret(idOrName string, version uint64, spec types.SecretSpec) error
|
UpdateSecret(idOrName string, version uint64, spec swarm.SecretSpec) error
|
||||||
|
GetConfigs(opts types.ConfigListOptions) ([]swarm.Config, error)
|
||||||
GetConfigs(opts basictypes.ConfigListOptions) ([]types.Config, error)
|
CreateConfig(s swarm.ConfigSpec) (string, error)
|
||||||
CreateConfig(s types.ConfigSpec) (string, error)
|
|
||||||
RemoveConfig(id string) error
|
RemoveConfig(id string) error
|
||||||
GetConfig(id string) (types.Config, error)
|
GetConfig(id string) (swarm.Config, error)
|
||||||
UpdateConfig(idOrName string, version uint64, spec types.ConfigSpec) error
|
UpdateConfig(idOrName string, version uint64, spec swarm.ConfigSpec) error
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,15 +6,16 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/containerd/log"
|
||||||
"github.com/docker/docker/api/server/httputils"
|
"github.com/docker/docker/api/server/httputils"
|
||||||
basictypes "github.com/docker/docker/api/types"
|
basictypes "github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/backend"
|
"github.com/docker/docker/api/types/backend"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
|
"github.com/docker/docker/api/types/registry"
|
||||||
types "github.com/docker/docker/api/types/swarm"
|
types "github.com/docker/docker/api/types/swarm"
|
||||||
"github.com/docker/docker/api/types/versions"
|
"github.com/docker/docker/api/types/versions"
|
||||||
"github.com/docker/docker/errdefs"
|
"github.com/docker/docker/errdefs"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (sr *swarmRouter) initCluster(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (sr *swarmRouter) initCluster(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
|
@ -35,7 +36,7 @@ func (sr *swarmRouter) initCluster(ctx context.Context, w http.ResponseWriter, r
|
||||||
}
|
}
|
||||||
nodeID, err := sr.backend.Init(req)
|
nodeID, err := sr.backend.Init(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithContext(ctx).WithError(err).Debug("Error initializing swarm")
|
log.G(ctx).WithContext(ctx).WithError(err).Debug("Error initializing swarm")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return httputils.WriteJSON(w, http.StatusOK, nodeID)
|
return httputils.WriteJSON(w, http.StatusOK, nodeID)
|
||||||
|
@ -55,13 +56,13 @@ func (sr *swarmRouter) leaveCluster(ctx context.Context, w http.ResponseWriter,
|
||||||
}
|
}
|
||||||
|
|
||||||
force := httputils.BoolValue(r, "force")
|
force := httputils.BoolValue(r, "force")
|
||||||
return sr.backend.Leave(force)
|
return sr.backend.Leave(ctx, force)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sr *swarmRouter) inspectCluster(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (sr *swarmRouter) inspectCluster(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
swarm, err := sr.backend.Inspect()
|
swarm, err := sr.backend.Inspect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithContext(ctx).WithError(err).Debug("Error getting swarm")
|
log.G(ctx).WithContext(ctx).WithError(err).Debug("Error getting swarm")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +114,7 @@ func (sr *swarmRouter) updateCluster(ctx context.Context, w http.ResponseWriter,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := sr.backend.Update(version, swarm, flags); err != nil {
|
if err := sr.backend.Update(version, swarm, flags); err != nil {
|
||||||
logrus.WithContext(ctx).WithError(err).Debug("Error configuring swarm")
|
log.G(ctx).WithContext(ctx).WithError(err).Debug("Error configuring swarm")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -126,7 +127,7 @@ func (sr *swarmRouter) unlockCluster(ctx context.Context, w http.ResponseWriter,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := sr.backend.UnlockSwarm(req); err != nil {
|
if err := sr.backend.UnlockSwarm(req); err != nil {
|
||||||
logrus.WithContext(ctx).WithError(err).Debug("Error unlocking swarm")
|
log.G(ctx).WithContext(ctx).WithError(err).Debug("Error unlocking swarm")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -135,7 +136,7 @@ func (sr *swarmRouter) unlockCluster(ctx context.Context, w http.ResponseWriter,
|
||||||
func (sr *swarmRouter) getUnlockKey(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (sr *swarmRouter) getUnlockKey(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
unlockKey, err := sr.backend.GetUnlockKey()
|
unlockKey, err := sr.backend.GetUnlockKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithContext(ctx).WithError(err).Debug("Error retrieving swarm unlock key")
|
log.G(ctx).WithContext(ctx).WithError(err).Debug("Error retrieving swarm unlock key")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +168,7 @@ func (sr *swarmRouter) getServices(ctx context.Context, w http.ResponseWriter, r
|
||||||
|
|
||||||
services, err := sr.backend.GetServices(basictypes.ServiceListOptions{Filters: filter, Status: status})
|
services, err := sr.backend.GetServices(basictypes.ServiceListOptions{Filters: filter, Status: status})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithContext(ctx).WithError(err).Debug("Error getting services")
|
log.G(ctx).WithContext(ctx).WithError(err).Debug("Error getting services")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +194,7 @@ func (sr *swarmRouter) getService(ctx context.Context, w http.ResponseWriter, r
|
||||||
|
|
||||||
service, err := sr.backend.GetService(vars["id"], insertDefaults)
|
service, err := sr.backend.GetService(vars["id"], insertDefaults)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithContext(ctx).WithFields(logrus.Fields{
|
log.G(ctx).WithContext(ctx).WithFields(log.Fields{
|
||||||
"error": err,
|
"error": err,
|
||||||
"service-id": vars["id"],
|
"service-id": vars["id"],
|
||||||
}).Debug("Error getting service")
|
}).Debug("Error getting service")
|
||||||
|
@ -208,9 +209,13 @@ func (sr *swarmRouter) createService(ctx context.Context, w http.ResponseWriter,
|
||||||
if err := httputils.ReadJSON(r, &service); err != nil {
|
if err := httputils.ReadJSON(r, &service); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// TODO(thaJeztah): remove logentries check and migration code in release v26.0.0.
|
||||||
|
if service.TaskTemplate.LogDriver != nil && service.TaskTemplate.LogDriver.Name == "logentries" {
|
||||||
|
return errdefs.InvalidParameter(errors.New("the logentries logging driver has been deprecated and removed"))
|
||||||
|
}
|
||||||
|
|
||||||
// Get returns "" if the header does not exist
|
// Get returns "" if the header does not exist
|
||||||
encodedAuth := r.Header.Get("X-Registry-Auth")
|
encodedAuth := r.Header.Get(registry.AuthHeader)
|
||||||
queryRegistry := false
|
queryRegistry := false
|
||||||
if v := httputils.VersionFromContext(ctx); v != "" {
|
if v := httputils.VersionFromContext(ctx); v != "" {
|
||||||
if versions.LessThan(v, "1.30") {
|
if versions.LessThan(v, "1.30") {
|
||||||
|
@ -218,9 +223,18 @@ func (sr *swarmRouter) createService(ctx context.Context, w http.ResponseWriter,
|
||||||
}
|
}
|
||||||
adjustForAPIVersion(v, &service)
|
adjustForAPIVersion(v, &service)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version := httputils.VersionFromContext(ctx)
|
||||||
|
if versions.LessThan(version, "1.44") {
|
||||||
|
if service.TaskTemplate.ContainerSpec != nil && service.TaskTemplate.ContainerSpec.Healthcheck != nil {
|
||||||
|
// StartInterval was added in API 1.44
|
||||||
|
service.TaskTemplate.ContainerSpec.Healthcheck.StartInterval = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
resp, err := sr.backend.CreateService(service, encodedAuth, queryRegistry)
|
resp, err := sr.backend.CreateService(service, encodedAuth, queryRegistry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithContext(ctx).WithFields(logrus.Fields{
|
log.G(ctx).WithFields(log.Fields{
|
||||||
"error": err,
|
"error": err,
|
||||||
"service-name": service.Name,
|
"service-name": service.Name,
|
||||||
}).Debug("Error creating service")
|
}).Debug("Error creating service")
|
||||||
|
@ -235,6 +249,10 @@ func (sr *swarmRouter) updateService(ctx context.Context, w http.ResponseWriter,
|
||||||
if err := httputils.ReadJSON(r, &service); err != nil {
|
if err := httputils.ReadJSON(r, &service); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// TODO(thaJeztah): remove logentries check and migration code in release v26.0.0.
|
||||||
|
if service.TaskTemplate.LogDriver != nil && service.TaskTemplate.LogDriver.Name == "logentries" {
|
||||||
|
return errdefs.InvalidParameter(errors.New("the logentries logging driver has been deprecated and removed"))
|
||||||
|
}
|
||||||
|
|
||||||
rawVersion := r.URL.Query().Get("version")
|
rawVersion := r.URL.Query().Get("version")
|
||||||
version, err := strconv.ParseUint(rawVersion, 10, 64)
|
version, err := strconv.ParseUint(rawVersion, 10, 64)
|
||||||
|
@ -246,7 +264,7 @@ func (sr *swarmRouter) updateService(ctx context.Context, w http.ResponseWriter,
|
||||||
var flags basictypes.ServiceUpdateOptions
|
var flags basictypes.ServiceUpdateOptions
|
||||||
|
|
||||||
// Get returns "" if the header does not exist
|
// Get returns "" if the header does not exist
|
||||||
flags.EncodedRegistryAuth = r.Header.Get("X-Registry-Auth")
|
flags.EncodedRegistryAuth = r.Header.Get(registry.AuthHeader)
|
||||||
flags.RegistryAuthFrom = r.URL.Query().Get("registryAuthFrom")
|
flags.RegistryAuthFrom = r.URL.Query().Get("registryAuthFrom")
|
||||||
flags.Rollback = r.URL.Query().Get("rollback")
|
flags.Rollback = r.URL.Query().Get("rollback")
|
||||||
queryRegistry := false
|
queryRegistry := false
|
||||||
|
@ -259,7 +277,7 @@ func (sr *swarmRouter) updateService(ctx context.Context, w http.ResponseWriter,
|
||||||
|
|
||||||
resp, err := sr.backend.UpdateService(vars["id"], version, service, flags, queryRegistry)
|
resp, err := sr.backend.UpdateService(vars["id"], version, service, flags, queryRegistry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithContext(ctx).WithFields(logrus.Fields{
|
log.G(ctx).WithContext(ctx).WithFields(log.Fields{
|
||||||
"error": err,
|
"error": err,
|
||||||
"service-id": vars["id"],
|
"service-id": vars["id"],
|
||||||
}).Debug("Error updating service")
|
}).Debug("Error updating service")
|
||||||
|
@ -270,7 +288,7 @@ func (sr *swarmRouter) updateService(ctx context.Context, w http.ResponseWriter,
|
||||||
|
|
||||||
func (sr *swarmRouter) removeService(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (sr *swarmRouter) removeService(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := sr.backend.RemoveService(vars["id"]); err != nil {
|
if err := sr.backend.RemoveService(vars["id"]); err != nil {
|
||||||
logrus.WithContext(ctx).WithFields(logrus.Fields{
|
log.G(ctx).WithContext(ctx).WithFields(log.Fields{
|
||||||
"error": err,
|
"error": err,
|
||||||
"service-id": vars["id"],
|
"service-id": vars["id"],
|
||||||
}).Debug("Error removing service")
|
}).Debug("Error removing service")
|
||||||
|
@ -314,7 +332,7 @@ func (sr *swarmRouter) getNodes(ctx context.Context, w http.ResponseWriter, r *h
|
||||||
|
|
||||||
nodes, err := sr.backend.GetNodes(basictypes.NodeListOptions{Filters: filter})
|
nodes, err := sr.backend.GetNodes(basictypes.NodeListOptions{Filters: filter})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithContext(ctx).WithError(err).Debug("Error getting nodes")
|
log.G(ctx).WithContext(ctx).WithError(err).Debug("Error getting nodes")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,7 +342,7 @@ func (sr *swarmRouter) getNodes(ctx context.Context, w http.ResponseWriter, r *h
|
||||||
func (sr *swarmRouter) getNode(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (sr *swarmRouter) getNode(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
node, err := sr.backend.GetNode(vars["id"])
|
node, err := sr.backend.GetNode(vars["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithContext(ctx).WithFields(logrus.Fields{
|
log.G(ctx).WithContext(ctx).WithFields(log.Fields{
|
||||||
"error": err,
|
"error": err,
|
||||||
"node-id": vars["id"],
|
"node-id": vars["id"],
|
||||||
}).Debug("Error getting node")
|
}).Debug("Error getting node")
|
||||||
|
@ -348,7 +366,7 @@ func (sr *swarmRouter) updateNode(ctx context.Context, w http.ResponseWriter, r
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := sr.backend.UpdateNode(vars["id"], version, node); err != nil {
|
if err := sr.backend.UpdateNode(vars["id"], version, node); err != nil {
|
||||||
logrus.WithContext(ctx).WithFields(logrus.Fields{
|
log.G(ctx).WithContext(ctx).WithFields(log.Fields{
|
||||||
"error": err,
|
"error": err,
|
||||||
"node-id": vars["id"],
|
"node-id": vars["id"],
|
||||||
}).Debug("Error updating node")
|
}).Debug("Error updating node")
|
||||||
|
@ -365,7 +383,7 @@ func (sr *swarmRouter) removeNode(ctx context.Context, w http.ResponseWriter, r
|
||||||
force := httputils.BoolValue(r, "force")
|
force := httputils.BoolValue(r, "force")
|
||||||
|
|
||||||
if err := sr.backend.RemoveNode(vars["id"], force); err != nil {
|
if err := sr.backend.RemoveNode(vars["id"], force); err != nil {
|
||||||
logrus.WithContext(ctx).WithFields(logrus.Fields{
|
log.G(ctx).WithContext(ctx).WithFields(log.Fields{
|
||||||
"error": err,
|
"error": err,
|
||||||
"node-id": vars["id"],
|
"node-id": vars["id"],
|
||||||
}).Debug("Error removing node")
|
}).Debug("Error removing node")
|
||||||
|
@ -385,7 +403,7 @@ func (sr *swarmRouter) getTasks(ctx context.Context, w http.ResponseWriter, r *h
|
||||||
|
|
||||||
tasks, err := sr.backend.GetTasks(basictypes.TaskListOptions{Filters: filter})
|
tasks, err := sr.backend.GetTasks(basictypes.TaskListOptions{Filters: filter})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithContext(ctx).WithError(err).Debug("Error getting tasks")
|
log.G(ctx).WithContext(ctx).WithError(err).Debug("Error getting tasks")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,7 +413,7 @@ func (sr *swarmRouter) getTasks(ctx context.Context, w http.ResponseWriter, r *h
|
||||||
func (sr *swarmRouter) getTask(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (sr *swarmRouter) getTask(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
task, err := sr.backend.GetTask(vars["id"])
|
task, err := sr.backend.GetTask(vars["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithContext(ctx).WithFields(logrus.Fields{
|
log.G(ctx).WithContext(ctx).WithFields(log.Fields{
|
||||||
"error": err,
|
"error": err,
|
||||||
"task-id": vars["id"],
|
"task-id": vars["id"],
|
||||||
}).Debug("Error getting task")
|
}).Debug("Error getting task")
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/docker/docker/api/server/httputils"
|
"github.com/docker/docker/api/server/httputils"
|
||||||
basictypes "github.com/docker/docker/api/types"
|
basictypes "github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/backend"
|
"github.com/docker/docker/api/types/backend"
|
||||||
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/api/types/swarm"
|
"github.com/docker/docker/api/types/swarm"
|
||||||
"github.com/docker/docker/api/types/versions"
|
"github.com/docker/docker/api/types/versions"
|
||||||
)
|
)
|
||||||
|
@ -25,9 +26,9 @@ func (sr *swarmRouter) swarmLogs(ctx context.Context, w http.ResponseWriter, r *
|
||||||
return fmt.Errorf("Bad parameters: you must choose at least one stream")
|
return fmt.Errorf("Bad parameters: you must choose at least one stream")
|
||||||
}
|
}
|
||||||
|
|
||||||
// there is probably a neater way to manufacture the ContainerLogsOptions
|
// there is probably a neater way to manufacture the LogsOptions
|
||||||
// struct, probably in the caller, to eliminate the dependency on net/http
|
// struct, probably in the caller, to eliminate the dependency on net/http
|
||||||
logsConfig := &basictypes.ContainerLogsOptions{
|
logsConfig := &container.LogsOptions{
|
||||||
Follow: httputils.BoolValue(r, "follow"),
|
Follow: httputils.BoolValue(r, "follow"),
|
||||||
Timestamps: httputils.BoolValue(r, "timestamps"),
|
Timestamps: httputils.BoolValue(r, "timestamps"),
|
||||||
Since: r.Form.Get("since"),
|
Since: r.Form.Get("since"),
|
||||||
|
@ -118,4 +119,13 @@ func adjustForAPIVersion(cliVersion string, service *swarm.ServiceSpec) {
|
||||||
service.Mode.ReplicatedJob = nil
|
service.Mode.ReplicatedJob = nil
|
||||||
service.Mode.GlobalJob = nil
|
service.Mode.GlobalJob = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if versions.LessThan(cliVersion, "1.44") {
|
||||||
|
// seccomp, apparmor, and no_new_privs were added in 1.44.
|
||||||
|
if service.TaskTemplate.ContainerSpec != nil && service.TaskTemplate.ContainerSpec.Privileges != nil {
|
||||||
|
service.TaskTemplate.ContainerSpec.Privileges.Seccomp = nil
|
||||||
|
service.TaskTemplate.ContainerSpec.Privileges.AppArmor = nil
|
||||||
|
service.TaskTemplate.ContainerSpec.Privileges.NoNewPrivileges = false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAdjustForAPIVersion(t *testing.T) {
|
func TestAdjustForAPIVersion(t *testing.T) {
|
||||||
var (
|
expectedSysctls := map[string]string{"foo": "bar"}
|
||||||
expectedSysctls = map[string]string{"foo": "bar"}
|
|
||||||
)
|
|
||||||
// testing the negative -- does this leave everything else alone? -- is
|
// testing the negative -- does this leave everything else alone? -- is
|
||||||
// prohibitively time-consuming to write, because it would need an object
|
// prohibitively time-consuming to write, because it would need an object
|
||||||
// with literally every field filled in.
|
// with literally every field filled in.
|
||||||
|
|
|
@ -7,7 +7,9 @@ import (
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/events"
|
"github.com/docker/docker/api/types/events"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
|
"github.com/docker/docker/api/types/registry"
|
||||||
"github.com/docker/docker/api/types/swarm"
|
"github.com/docker/docker/api/types/swarm"
|
||||||
|
"github.com/docker/docker/api/types/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DiskUsageOptions holds parameters for system disk usage query.
|
// DiskUsageOptions holds parameters for system disk usage query.
|
||||||
|
@ -25,18 +27,18 @@ type DiskUsageOptions struct {
|
||||||
// Backend is the methods that need to be implemented to provide
|
// Backend is the methods that need to be implemented to provide
|
||||||
// system specific functionality.
|
// system specific functionality.
|
||||||
type Backend interface {
|
type Backend interface {
|
||||||
SystemInfo() *types.Info
|
SystemInfo(context.Context) (*system.Info, error)
|
||||||
SystemVersion() types.Version
|
SystemVersion(context.Context) (types.Version, error)
|
||||||
SystemDiskUsage(ctx context.Context, opts DiskUsageOptions) (*types.DiskUsage, error)
|
SystemDiskUsage(ctx context.Context, opts DiskUsageOptions) (*types.DiskUsage, error)
|
||||||
SubscribeToEvents(since, until time.Time, ef filters.Args) ([]events.Message, chan interface{})
|
SubscribeToEvents(since, until time.Time, ef filters.Args) ([]events.Message, chan interface{})
|
||||||
UnsubscribeFromEvents(chan interface{})
|
UnsubscribeFromEvents(chan interface{})
|
||||||
AuthenticateToRegistry(ctx context.Context, authConfig *types.AuthConfig) (string, string, error)
|
AuthenticateToRegistry(ctx context.Context, authConfig *registry.AuthConfig) (string, string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClusterBackend is all the methods that need to be implemented
|
// ClusterBackend is all the methods that need to be implemented
|
||||||
// to provide cluster system specific functionality.
|
// to provide cluster system specific functionality.
|
||||||
type ClusterBackend interface {
|
type ClusterBackend interface {
|
||||||
Info() swarm.Info
|
Info(context.Context) swarm.Info
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatusProvider provides methods to get the swarm status of the current node.
|
// StatusProvider provides methods to get the swarm status of the current node.
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
|
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||||
|
//go:build go1.19
|
||||||
|
|
||||||
package system // import "github.com/docker/docker/api/server/router/system"
|
package system // import "github.com/docker/docker/api/server/router/system"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/docker/docker/api/server/router"
|
"github.com/docker/docker/api/server/router"
|
||||||
|
"github.com/docker/docker/api/types/system"
|
||||||
buildkit "github.com/docker/docker/builder/builder-next"
|
buildkit "github.com/docker/docker/builder/builder-next"
|
||||||
|
"resenje.org/singleflight"
|
||||||
)
|
)
|
||||||
|
|
||||||
// systemRouter provides information about the Docker system overall.
|
// systemRouter provides information about the Docker system overall.
|
||||||
|
@ -12,11 +17,16 @@ type systemRouter struct {
|
||||||
cluster ClusterBackend
|
cluster ClusterBackend
|
||||||
routes []router.Route
|
routes []router.Route
|
||||||
builder *buildkit.Builder
|
builder *buildkit.Builder
|
||||||
features *map[string]bool
|
features func() map[string]bool
|
||||||
|
|
||||||
|
// collectSystemInfo is a single-flight for the /info endpoint,
|
||||||
|
// unique per API version (as different API versions may return
|
||||||
|
// a different API response).
|
||||||
|
collectSystemInfo singleflight.Group[string, *system.Info]
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRouter initializes a new system router
|
// NewRouter initializes a new system router
|
||||||
func NewRouter(b Backend, c ClusterBackend, builder *buildkit.Builder, features *map[string]bool) router.Router {
|
func NewRouter(b Backend, c ClusterBackend, builder *buildkit.Builder, features func() map[string]bool) router.Router {
|
||||||
r := &systemRouter{
|
r := &systemRouter{
|
||||||
backend: b,
|
backend: b,
|
||||||
cluster: c,
|
cluster: c,
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/containerd/log"
|
||||||
"github.com/docker/docker/api/server/httputils"
|
"github.com/docker/docker/api/server/httputils"
|
||||||
"github.com/docker/docker/api/server/router/build"
|
"github.com/docker/docker/api/server/router/build"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
|
@ -14,11 +15,11 @@ import (
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/api/types/registry"
|
"github.com/docker/docker/api/types/registry"
|
||||||
"github.com/docker/docker/api/types/swarm"
|
"github.com/docker/docker/api/types/swarm"
|
||||||
|
"github.com/docker/docker/api/types/system"
|
||||||
timetypes "github.com/docker/docker/api/types/time"
|
timetypes "github.com/docker/docker/api/types/time"
|
||||||
"github.com/docker/docker/api/types/versions"
|
"github.com/docker/docker/api/types/versions"
|
||||||
"github.com/docker/docker/pkg/ioutils"
|
"github.com/docker/docker/pkg/ioutils"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -31,7 +32,7 @@ func (s *systemRouter) pingHandler(ctx context.Context, w http.ResponseWriter, r
|
||||||
w.Header().Add("Cache-Control", "no-cache, no-store, must-revalidate")
|
w.Header().Add("Cache-Control", "no-cache, no-store, must-revalidate")
|
||||||
w.Header().Add("Pragma", "no-cache")
|
w.Header().Add("Pragma", "no-cache")
|
||||||
|
|
||||||
builderVersion := build.BuilderVersion(*s.features)
|
builderVersion := build.BuilderVersion(s.features())
|
||||||
if bv := builderVersion; bv != "" {
|
if bv := builderVersion; bv != "" {
|
||||||
w.Header().Set("Builder-Version", string(bv))
|
w.Header().Set("Builder-Version", string(bv))
|
||||||
}
|
}
|
||||||
|
@ -57,51 +58,58 @@ func (s *systemRouter) swarmStatus() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
info := s.backend.SystemInfo()
|
|
||||||
|
|
||||||
if s.cluster != nil {
|
|
||||||
info.Swarm = s.cluster.Info()
|
|
||||||
info.Warnings = append(info.Warnings, info.Swarm.Warnings...)
|
|
||||||
}
|
|
||||||
|
|
||||||
version := httputils.VersionFromContext(ctx)
|
version := httputils.VersionFromContext(ctx)
|
||||||
if versions.LessThan(version, "1.25") {
|
info, _, _ := s.collectSystemInfo.Do(ctx, version, func(ctx context.Context) (*system.Info, error) {
|
||||||
// TODO: handle this conversion in engine-api
|
info, err := s.backend.SystemInfo(ctx)
|
||||||
type oldInfo struct {
|
|
||||||
*types.Info
|
|
||||||
ExecutionDriver string
|
|
||||||
}
|
|
||||||
old := &oldInfo{
|
|
||||||
Info: info,
|
|
||||||
ExecutionDriver: "<not supported>",
|
|
||||||
}
|
|
||||||
nameOnlySecurityOptions := []string{}
|
|
||||||
kvSecOpts, err := types.DecodeSecurityOptions(old.SecurityOptions)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, s := range kvSecOpts {
|
|
||||||
nameOnlySecurityOptions = append(nameOnlySecurityOptions, s.Name)
|
if s.cluster != nil {
|
||||||
|
info.Swarm = s.cluster.Info(ctx)
|
||||||
|
info.Warnings = append(info.Warnings, info.Swarm.Warnings...)
|
||||||
}
|
}
|
||||||
old.SecurityOptions = nameOnlySecurityOptions
|
|
||||||
return httputils.WriteJSON(w, http.StatusOK, old)
|
if versions.LessThan(version, "1.25") {
|
||||||
}
|
// TODO: handle this conversion in engine-api
|
||||||
if versions.LessThan(version, "1.39") {
|
kvSecOpts, err := system.DecodeSecurityOptions(info.SecurityOptions)
|
||||||
if info.KernelVersion == "" {
|
if err != nil {
|
||||||
info.KernelVersion = "<unknown>"
|
info.Warnings = append(info.Warnings, err.Error())
|
||||||
|
}
|
||||||
|
var nameOnly []string
|
||||||
|
for _, so := range kvSecOpts {
|
||||||
|
nameOnly = append(nameOnly, so.Name)
|
||||||
|
}
|
||||||
|
info.SecurityOptions = nameOnly
|
||||||
|
info.ExecutionDriver = "<not supported>" //nolint:staticcheck // ignore SA1019 (ExecutionDriver is deprecated)
|
||||||
}
|
}
|
||||||
if info.OperatingSystem == "" {
|
if versions.LessThan(version, "1.39") {
|
||||||
info.OperatingSystem = "<unknown>"
|
if info.KernelVersion == "" {
|
||||||
|
info.KernelVersion = "<unknown>"
|
||||||
|
}
|
||||||
|
if info.OperatingSystem == "" {
|
||||||
|
info.OperatingSystem = "<unknown>"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if versions.LessThan(version, "1.44") {
|
||||||
if versions.GreaterThanOrEqualTo(version, "1.42") {
|
for k, rt := range info.Runtimes {
|
||||||
info.KernelMemory = false
|
// Status field introduced in API v1.44.
|
||||||
}
|
info.Runtimes[k] = system.RuntimeWithStatus{Runtime: rt.Runtime}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if versions.GreaterThanOrEqualTo(version, "1.42") {
|
||||||
|
info.KernelMemory = false
|
||||||
|
}
|
||||||
|
return info, nil
|
||||||
|
})
|
||||||
return httputils.WriteJSON(w, http.StatusOK, info)
|
return httputils.WriteJSON(w, http.StatusOK, info)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *systemRouter) getVersion(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (s *systemRouter) getVersion(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
info := s.backend.SystemVersion()
|
info, err := s.backend.SystemVersion(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return httputils.WriteJSON(w, http.StatusOK, info)
|
return httputils.WriteJSON(w, http.StatusOK, info)
|
||||||
}
|
}
|
||||||
|
@ -116,7 +124,7 @@ func (s *systemRouter) getDiskUsage(ctx context.Context, w http.ResponseWriter,
|
||||||
var getContainers, getImages, getVolumes, getBuildCache bool
|
var getContainers, getImages, getVolumes, getBuildCache bool
|
||||||
typeStrs, ok := r.Form["type"]
|
typeStrs, ok := r.Form["type"]
|
||||||
if versions.LessThan(version, "1.42") || !ok {
|
if versions.LessThan(version, "1.42") || !ok {
|
||||||
getContainers, getImages, getVolumes, getBuildCache = true, true, true, true
|
getContainers, getImages, getVolumes, getBuildCache = true, true, true, s.builder != nil
|
||||||
} else {
|
} else {
|
||||||
for _, typ := range typeStrs {
|
for _, typ := range typeStrs {
|
||||||
switch types.DiskUsageObject(typ) {
|
switch types.DiskUsageObject(typ) {
|
||||||
|
@ -185,6 +193,11 @@ func (s *systemRouter) getDiskUsage(ctx context.Context, w http.ResponseWriter,
|
||||||
b.Parent = "" //nolint:staticcheck // ignore SA1019 (Parent field is deprecated)
|
b.Parent = "" //nolint:staticcheck // ignore SA1019 (Parent field is deprecated)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if versions.LessThan(version, "1.44") {
|
||||||
|
for _, b := range systemDiskUsage.Images {
|
||||||
|
b.VirtualSize = b.Size //nolint:staticcheck // ignore SA1019: field is deprecated, but still set on API < v1.44.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
du := types.DiskUsage{
|
du := types.DiskUsage{
|
||||||
BuildCache: buildCache,
|
BuildCache: buildCache,
|
||||||
|
@ -274,7 +287,7 @@ func (s *systemRouter) getEvents(ctx context.Context, w http.ResponseWriter, r *
|
||||||
case ev := <-l:
|
case ev := <-l:
|
||||||
jev, ok := ev.(events.Message)
|
jev, ok := ev.(events.Message)
|
||||||
if !ok {
|
if !ok {
|
||||||
logrus.Warnf("unexpected event message: %q", ev)
|
log.G(ctx).Warnf("unexpected event message: %q", ev)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := enc.Encode(jev); err != nil {
|
if err := enc.Encode(jev); err != nil {
|
||||||
|
@ -283,14 +296,14 @@ func (s *systemRouter) getEvents(ctx context.Context, w http.ResponseWriter, r *
|
||||||
case <-timeout:
|
case <-timeout:
|
||||||
return nil
|
return nil
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
logrus.Debug("Client context cancelled, stop sending events")
|
log.G(ctx).Debug("Client context cancelled, stop sending events")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *systemRouter) postAuth(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (s *systemRouter) postAuth(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
var config *types.AuthConfig
|
var config *registry.AuthConfig
|
||||||
err := json.NewDecoder(r.Body).Decode(&config)
|
err := json.NewDecoder(r.Body).Decode(&config)
|
||||||
r.Body.Close()
|
r.Body.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/containerd/log"
|
||||||
"github.com/docker/docker/api/server/httputils"
|
"github.com/docker/docker/api/server/httputils"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/api/types/versions"
|
"github.com/docker/docker/api/types/versions"
|
||||||
|
@ -13,7 +14,6 @@ import (
|
||||||
"github.com/docker/docker/errdefs"
|
"github.com/docker/docker/errdefs"
|
||||||
"github.com/docker/docker/volume/service/opts"
|
"github.com/docker/docker/volume/service/opts"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -116,10 +116,10 @@ func (v *volumeRouter) postVolumesCreate(ctx context.Context, w http.ResponseWri
|
||||||
// Instead, we will allow creating a volume with a duplicate name, which
|
// Instead, we will allow creating a volume with a duplicate name, which
|
||||||
// should not break anything.
|
// should not break anything.
|
||||||
if req.ClusterVolumeSpec != nil && versions.GreaterThanOrEqualTo(version, clusterVolumesVersion) {
|
if req.ClusterVolumeSpec != nil && versions.GreaterThanOrEqualTo(version, clusterVolumesVersion) {
|
||||||
logrus.Debug("using cluster volume")
|
log.G(ctx).Debug("using cluster volume")
|
||||||
vol, err = v.cluster.CreateVolume(req)
|
vol, err = v.cluster.CreateVolume(req)
|
||||||
} else {
|
} else {
|
||||||
logrus.Debug("using regular volume")
|
log.G(ctx).Debug("using regular volume")
|
||||||
vol, err = v.backend.Create(ctx, req.Name, req.Driver, opts.WithCreateOptions(req.DriverOpts), opts.WithCreateLabels(req.Labels))
|
vol, err = v.backend.Create(ctx, req.Name, req.Driver, opts.WithCreateOptions(req.DriverOpts), opts.WithCreateLabels(req.Labels))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,6 @@ func TestGetVolumeByNameFoundRegular(t *testing.T) {
|
||||||
v := &volumeRouter{
|
v := &volumeRouter{
|
||||||
backend: &fakeVolumeBackend{
|
backend: &fakeVolumeBackend{
|
||||||
volumes: map[string]*volume.Volume{
|
volumes: map[string]*volume.Volume{
|
||||||
|
|
||||||
"volume1": {
|
"volume1": {
|
||||||
Name: "volume1",
|
Name: "volume1",
|
||||||
},
|
},
|
||||||
|
@ -108,6 +107,7 @@ func TestGetVolumeByNameFoundSwarm(t *testing.T) {
|
||||||
_, err := callGetVolume(v, "volume1")
|
_, err := callGetVolume(v, "volume1")
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestListVolumes(t *testing.T) {
|
func TestListVolumes(t *testing.T) {
|
||||||
v := &volumeRouter{
|
v := &volumeRouter{
|
||||||
backend: &fakeVolumeBackend{
|
backend: &fakeVolumeBackend{
|
||||||
|
|
|
@ -2,126 +2,37 @@ package server // import "github.com/docker/docker/api/server"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
|
"github.com/containerd/log"
|
||||||
"github.com/docker/docker/api/server/httpstatus"
|
"github.com/docker/docker/api/server/httpstatus"
|
||||||
"github.com/docker/docker/api/server/httputils"
|
"github.com/docker/docker/api/server/httputils"
|
||||||
"github.com/docker/docker/api/server/middleware"
|
"github.com/docker/docker/api/server/middleware"
|
||||||
"github.com/docker/docker/api/server/router"
|
"github.com/docker/docker/api/server/router"
|
||||||
"github.com/docker/docker/api/server/router/debug"
|
"github.com/docker/docker/api/server/router/debug"
|
||||||
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/dockerversion"
|
"github.com/docker/docker/dockerversion"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/sirupsen/logrus"
|
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
||||||
)
|
)
|
||||||
|
|
||||||
// versionMatcher defines a variable matcher to be parsed by the router
|
// versionMatcher defines a variable matcher to be parsed by the router
|
||||||
// when a request is about to be served.
|
// when a request is about to be served.
|
||||||
const versionMatcher = "/v{version:[0-9.]+}"
|
const versionMatcher = "/v{version:[0-9.]+}"
|
||||||
|
|
||||||
// Config provides the configuration for the API server
|
|
||||||
type Config struct {
|
|
||||||
CorsHeaders string
|
|
||||||
Version string
|
|
||||||
SocketGroup string
|
|
||||||
TLSConfig *tls.Config
|
|
||||||
// Hosts is a list of addresses for the API to listen on.
|
|
||||||
Hosts []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Server contains instance details for the server
|
// Server contains instance details for the server
|
||||||
type Server struct {
|
type Server struct {
|
||||||
cfg *Config
|
|
||||||
servers []*HTTPServer
|
|
||||||
routers []router.Router
|
|
||||||
middlewares []middleware.Middleware
|
middlewares []middleware.Middleware
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new instance of the server based on the specified configuration.
|
|
||||||
// It allocates resources which will be needed for ServeAPI(ports, unix-sockets).
|
|
||||||
func New(cfg *Config) *Server {
|
|
||||||
return &Server{
|
|
||||||
cfg: cfg,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UseMiddleware appends a new middleware to the request chain.
|
// UseMiddleware appends a new middleware to the request chain.
|
||||||
// This needs to be called before the API routes are configured.
|
// This needs to be called before the API routes are configured.
|
||||||
func (s *Server) UseMiddleware(m middleware.Middleware) {
|
func (s *Server) UseMiddleware(m middleware.Middleware) {
|
||||||
s.middlewares = append(s.middlewares, m)
|
s.middlewares = append(s.middlewares, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accept sets a listener the server accepts connections into.
|
func (s *Server) makeHTTPHandler(handler httputils.APIFunc, operation string) http.HandlerFunc {
|
||||||
func (s *Server) Accept(addr string, listeners ...net.Listener) {
|
return otelhttp.NewHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
for _, listener := range listeners {
|
|
||||||
httpServer := &HTTPServer{
|
|
||||||
srv: &http.Server{
|
|
||||||
Addr: addr,
|
|
||||||
ReadHeaderTimeout: 5 * time.Minute, // "G112: Potential Slowloris Attack (gosec)"; not a real concern for our use, so setting a long timeout.
|
|
||||||
},
|
|
||||||
l: listener,
|
|
||||||
}
|
|
||||||
s.servers = append(s.servers, httpServer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close closes servers and thus stop receiving requests
|
|
||||||
func (s *Server) Close() {
|
|
||||||
for _, srv := range s.servers {
|
|
||||||
if err := srv.Close(); err != nil {
|
|
||||||
logrus.Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// serveAPI loops through all initialized servers and spawns goroutine
|
|
||||||
// with Serve method for each. It sets createMux() as Handler also.
|
|
||||||
func (s *Server) serveAPI() error {
|
|
||||||
var chErrors = make(chan error, len(s.servers))
|
|
||||||
for _, srv := range s.servers {
|
|
||||||
srv.srv.Handler = s.createMux()
|
|
||||||
go func(srv *HTTPServer) {
|
|
||||||
var err error
|
|
||||||
logrus.Infof("API listen on %s", srv.l.Addr())
|
|
||||||
if err = srv.Serve(); err != nil && strings.Contains(err.Error(), "use of closed network connection") {
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
chErrors <- err
|
|
||||||
}(srv)
|
|
||||||
}
|
|
||||||
|
|
||||||
for range s.servers {
|
|
||||||
err := <-chErrors
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTPServer contains an instance of http server and the listener.
|
|
||||||
// srv *http.Server, contains configuration to create an http server and a mux router with all api end points.
|
|
||||||
// l net.Listener, is a TCP or Socket listener that dispatches incoming request to the router.
|
|
||||||
type HTTPServer struct {
|
|
||||||
srv *http.Server
|
|
||||||
l net.Listener
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serve starts listening for inbound requests.
|
|
||||||
func (s *HTTPServer) Serve() error {
|
|
||||||
return s.srv.Serve(s.l)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close closes the HTTPServer from listening for the inbound requests.
|
|
||||||
func (s *HTTPServer) Close() error {
|
|
||||||
return s.l.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) makeHTTPHandler(handler httputils.APIFunc) http.HandlerFunc {
|
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// Define the context that we'll pass around to share info
|
// Define the context that we'll pass around to share info
|
||||||
// like the docker-request-id.
|
// like the docker-request-id.
|
||||||
//
|
//
|
||||||
|
@ -133,6 +44,7 @@ func (s *Server) makeHTTPHandler(handler httputils.APIFunc) http.HandlerFunc {
|
||||||
// use intermediate variable to prevent "should not use basic type
|
// use intermediate variable to prevent "should not use basic type
|
||||||
// string as key in context.WithValue" golint errors
|
// string as key in context.WithValue" golint errors
|
||||||
ctx := context.WithValue(r.Context(), dockerversion.UAStringKey{}, r.Header.Get("User-Agent"))
|
ctx := context.WithValue(r.Context(), dockerversion.UAStringKey{}, r.Header.Get("User-Agent"))
|
||||||
|
|
||||||
r = r.WithContext(ctx)
|
r = r.WithContext(ctx)
|
||||||
handlerFunc := s.handlerWithGlobalMiddlewares(handler)
|
handlerFunc := s.handlerWithGlobalMiddlewares(handler)
|
||||||
|
|
||||||
|
@ -144,65 +56,45 @@ func (s *Server) makeHTTPHandler(handler httputils.APIFunc) http.HandlerFunc {
|
||||||
if err := handlerFunc(ctx, w, r, vars); err != nil {
|
if err := handlerFunc(ctx, w, r, vars); err != nil {
|
||||||
statusCode := httpstatus.FromError(err)
|
statusCode := httpstatus.FromError(err)
|
||||||
if statusCode >= 500 {
|
if statusCode >= 500 {
|
||||||
logrus.Errorf("Handler for %s %s returned error: %v", r.Method, r.URL.Path, err)
|
log.G(ctx).Errorf("Handler for %s %s returned error: %v", r.Method, r.URL.Path, err)
|
||||||
}
|
}
|
||||||
makeErrorHandler(err)(w, r)
|
_ = httputils.WriteJSON(w, statusCode, &types.ErrorResponse{
|
||||||
|
Message: err.Error(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}), operation).ServeHTTP
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitRouter initializes the list of routers for the server.
|
// CreateMux returns a new mux with all the routers registered.
|
||||||
// This method also enables the Go profiler.
|
func (s *Server) CreateMux(routers ...router.Router) *mux.Router {
|
||||||
func (s *Server) InitRouter(routers ...router.Router) {
|
|
||||||
s.routers = append(s.routers, routers...)
|
|
||||||
}
|
|
||||||
|
|
||||||
type pageNotFoundError struct{}
|
|
||||||
|
|
||||||
func (pageNotFoundError) Error() string {
|
|
||||||
return "page not found"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pageNotFoundError) NotFound() {}
|
|
||||||
|
|
||||||
// createMux initializes the main router the server uses.
|
|
||||||
func (s *Server) createMux() *mux.Router {
|
|
||||||
m := mux.NewRouter()
|
m := mux.NewRouter()
|
||||||
|
|
||||||
logrus.Debug("Registering routers")
|
log.G(context.TODO()).Debug("Registering routers")
|
||||||
for _, apiRouter := range s.routers {
|
for _, apiRouter := range routers {
|
||||||
for _, r := range apiRouter.Routes() {
|
for _, r := range apiRouter.Routes() {
|
||||||
f := s.makeHTTPHandler(r.Handler())
|
f := s.makeHTTPHandler(r.Handler(), r.Method()+" "+r.Path())
|
||||||
|
|
||||||
logrus.Debugf("Registering %s, %s", r.Method(), r.Path())
|
log.G(context.TODO()).Debugf("Registering %s, %s", r.Method(), r.Path())
|
||||||
m.Path(versionMatcher + r.Path()).Methods(r.Method()).Handler(f)
|
m.Path(versionMatcher + r.Path()).Methods(r.Method()).Handler(f)
|
||||||
m.Path(r.Path()).Methods(r.Method()).Handler(f)
|
m.Path(r.Path()).Methods(r.Method()).Handler(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debugRouter := debug.NewRouter()
|
debugRouter := debug.NewRouter()
|
||||||
s.routers = append(s.routers, debugRouter)
|
|
||||||
for _, r := range debugRouter.Routes() {
|
for _, r := range debugRouter.Routes() {
|
||||||
f := s.makeHTTPHandler(r.Handler())
|
f := s.makeHTTPHandler(r.Handler(), r.Method()+" "+r.Path())
|
||||||
m.Path("/debug" + r.Path()).Handler(f)
|
m.Path("/debug" + r.Path()).Handler(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
notFoundHandler := makeErrorHandler(pageNotFoundError{})
|
notFoundHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
_ = httputils.WriteJSON(w, http.StatusNotFound, &types.ErrorResponse{
|
||||||
|
Message: "page not found",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
m.HandleFunc(versionMatcher+"/{path:.*}", notFoundHandler)
|
m.HandleFunc(versionMatcher+"/{path:.*}", notFoundHandler)
|
||||||
m.NotFoundHandler = notFoundHandler
|
m.NotFoundHandler = notFoundHandler
|
||||||
m.MethodNotAllowedHandler = notFoundHandler
|
m.MethodNotAllowedHandler = notFoundHandler
|
||||||
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait blocks the server goroutine until it exits.
|
|
||||||
// It sends an error message if there is any error during
|
|
||||||
// the API execution.
|
|
||||||
func (s *Server) Wait(waitChan chan error) {
|
|
||||||
if err := s.serveAPI(); err != nil {
|
|
||||||
logrus.Errorf("ServeAPI error: %v", err)
|
|
||||||
waitChan <- err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
waitChan <- nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -13,14 +13,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMiddlewares(t *testing.T) {
|
func TestMiddlewares(t *testing.T) {
|
||||||
cfg := &Config{
|
srv := &Server{}
|
||||||
Version: "0.1omega2",
|
|
||||||
}
|
|
||||||
srv := &Server{
|
|
||||||
cfg: cfg,
|
|
||||||
}
|
|
||||||
|
|
||||||
srv.UseMiddleware(middleware.NewVersionMiddleware("0.1omega2", api.DefaultVersion, api.MinVersion))
|
m, err := middleware.NewVersionMiddleware("0.1omega2", api.DefaultVersion, api.MinSupportedAPIVersion)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
srv.UseMiddleware(*m)
|
||||||
|
|
||||||
req, _ := http.NewRequest(http.MethodGet, "/containers/json", nil)
|
req, _ := http.NewRequest(http.MethodGet, "/containers/json", nil)
|
||||||
resp := httptest.NewRecorder()
|
resp := httptest.NewRecorder()
|
||||||
|
|
496
api/swagger.yaml
496
api/swagger.yaml
|
@ -19,10 +19,10 @@ produces:
|
||||||
consumes:
|
consumes:
|
||||||
- "application/json"
|
- "application/json"
|
||||||
- "text/plain"
|
- "text/plain"
|
||||||
basePath: "/v1.42"
|
basePath: "/v1.45"
|
||||||
info:
|
info:
|
||||||
title: "Docker Engine API"
|
title: "Docker Engine API"
|
||||||
version: "1.42"
|
version: "1.45"
|
||||||
x-logo:
|
x-logo:
|
||||||
url: "https://docs.docker.com/assets/images/logo-docker-main.png"
|
url: "https://docs.docker.com/assets/images/logo-docker-main.png"
|
||||||
description: |
|
description: |
|
||||||
|
@ -55,8 +55,8 @@ info:
|
||||||
the URL is not supported by the daemon, a HTTP `400 Bad Request` error message
|
the URL is not supported by the daemon, a HTTP `400 Bad Request` error message
|
||||||
is returned.
|
is returned.
|
||||||
|
|
||||||
If you omit the version-prefix, the current version of the API (v1.42) is used.
|
If you omit the version-prefix, the current version of the API (v1.45) is used.
|
||||||
For example, calling `/info` is the same as calling `/v1.42/info`. Using the
|
For example, calling `/info` is the same as calling `/v1.45/info`. Using the
|
||||||
API without a version-prefix is deprecated and will be removed in a future release.
|
API without a version-prefix is deprecated and will be removed in a future release.
|
||||||
|
|
||||||
Engine releases in the near future should support this version of the API,
|
Engine releases in the near future should support this version of the API,
|
||||||
|
@ -388,6 +388,20 @@ definitions:
|
||||||
description: "Create mount point on host if missing"
|
description: "Create mount point on host if missing"
|
||||||
type: "boolean"
|
type: "boolean"
|
||||||
default: false
|
default: false
|
||||||
|
ReadOnlyNonRecursive:
|
||||||
|
description: |
|
||||||
|
Make the mount non-recursively read-only, but still leave the mount recursive
|
||||||
|
(unless NonRecursive is set to `true` in conjunction).
|
||||||
|
|
||||||
|
Addded in v1.44, before that version all read-only mounts were
|
||||||
|
non-recursive by default. To match the previous behaviour this
|
||||||
|
will default to `true` for clients on versions prior to v1.44.
|
||||||
|
type: "boolean"
|
||||||
|
default: false
|
||||||
|
ReadOnlyForceRecursive:
|
||||||
|
description: "Raise an error if the mount cannot be made recursively read-only."
|
||||||
|
type: "boolean"
|
||||||
|
default: false
|
||||||
VolumeOptions:
|
VolumeOptions:
|
||||||
description: "Optional configuration for the `volume` type."
|
description: "Optional configuration for the `volume` type."
|
||||||
type: "object"
|
type: "object"
|
||||||
|
@ -413,6 +427,10 @@ definitions:
|
||||||
type: "object"
|
type: "object"
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: "string"
|
type: "string"
|
||||||
|
Subpath:
|
||||||
|
description: "Source path inside the volume. Must be relative without any back traversals."
|
||||||
|
type: "string"
|
||||||
|
example: "dir-inside-volume/subdirectory"
|
||||||
TmpfsOptions:
|
TmpfsOptions:
|
||||||
description: "Optional configuration for the `tmpfs` type."
|
description: "Optional configuration for the `tmpfs` type."
|
||||||
type: "object"
|
type: "object"
|
||||||
|
@ -794,6 +812,12 @@ definitions:
|
||||||
1000000 (1 ms). 0 means inherit.
|
1000000 (1 ms). 0 means inherit.
|
||||||
type: "integer"
|
type: "integer"
|
||||||
format: "int64"
|
format: "int64"
|
||||||
|
StartInterval:
|
||||||
|
description: |
|
||||||
|
The time to wait between checks in nanoseconds during the start period.
|
||||||
|
It should be 0 or at least 1000000 (1 ms). 0 means inherit.
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
|
||||||
Health:
|
Health:
|
||||||
description: |
|
description: |
|
||||||
|
@ -976,6 +1000,13 @@ definitions:
|
||||||
items:
|
items:
|
||||||
type: "integer"
|
type: "integer"
|
||||||
minimum: 0
|
minimum: 0
|
||||||
|
Annotations:
|
||||||
|
type: "object"
|
||||||
|
description: |
|
||||||
|
Arbitrary non-identifying metadata attached to container and
|
||||||
|
provided to the runtime when the container is started.
|
||||||
|
additionalProperties:
|
||||||
|
type: "string"
|
||||||
|
|
||||||
# Applicable to UNIX platforms
|
# Applicable to UNIX platforms
|
||||||
CapAdd:
|
CapAdd:
|
||||||
|
@ -1122,6 +1153,7 @@ definitions:
|
||||||
remapping option is enabled.
|
remapping option is enabled.
|
||||||
ShmSize:
|
ShmSize:
|
||||||
type: "integer"
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
description: |
|
description: |
|
||||||
Size of `/dev/shm` in bytes. If omitted, the system uses 64MB.
|
Size of `/dev/shm` in bytes. If omitted, the system uses 64MB.
|
||||||
minimum: 0
|
minimum: 0
|
||||||
|
@ -1289,7 +1321,10 @@ definitions:
|
||||||
type: "boolean"
|
type: "boolean"
|
||||||
x-nullable: true
|
x-nullable: true
|
||||||
MacAddress:
|
MacAddress:
|
||||||
description: "MAC address of the container."
|
description: |
|
||||||
|
MAC address of the container.
|
||||||
|
|
||||||
|
Deprecated: this field is deprecated in API v1.44 and up. Use EndpointSettings.MacAddress instead.
|
||||||
type: "string"
|
type: "string"
|
||||||
x-nullable: true
|
x-nullable: true
|
||||||
OnBuild:
|
OnBuild:
|
||||||
|
@ -1339,16 +1374,16 @@ definitions:
|
||||||
EndpointsConfig:
|
EndpointsConfig:
|
||||||
description: |
|
description: |
|
||||||
A mapping of network name to endpoint configuration for that network.
|
A mapping of network name to endpoint configuration for that network.
|
||||||
|
The endpoint configuration can be left empty to connect to that
|
||||||
|
network with no particular endpoint configuration.
|
||||||
type: "object"
|
type: "object"
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
$ref: "#/definitions/EndpointSettings"
|
$ref: "#/definitions/EndpointSettings"
|
||||||
example:
|
example:
|
||||||
# putting an example here, instead of using the example values from
|
# putting an example here, instead of using the example values from
|
||||||
# /definitions/EndpointSettings, because containers/create currently
|
# /definitions/EndpointSettings, because EndpointSettings contains
|
||||||
# does not support attaching to multiple networks, so the example request
|
# operational data returned when inspecting a container that we don't
|
||||||
# would be confusing if it showed that multiple networks can be contained
|
# accept here.
|
||||||
# in the EndpointsConfig.
|
|
||||||
# TODO remove once we support multiple networks on container create (see https://github.com/moby/moby/blob/07e6b843594e061f82baa5fa23c2ff7d536c2a05/daemon/create.go#L323)
|
|
||||||
EndpointsConfig:
|
EndpointsConfig:
|
||||||
isolated_nw:
|
isolated_nw:
|
||||||
IPAMConfig:
|
IPAMConfig:
|
||||||
|
@ -1357,19 +1392,22 @@ definitions:
|
||||||
LinkLocalIPs:
|
LinkLocalIPs:
|
||||||
- "169.254.34.68"
|
- "169.254.34.68"
|
||||||
- "fe80::3468"
|
- "fe80::3468"
|
||||||
|
MacAddress: "02:42:ac:12:05:02"
|
||||||
Links:
|
Links:
|
||||||
- "container_1"
|
- "container_1"
|
||||||
- "container_2"
|
- "container_2"
|
||||||
Aliases:
|
Aliases:
|
||||||
- "server_x"
|
- "server_x"
|
||||||
- "server_y"
|
- "server_y"
|
||||||
|
database_nw: {}
|
||||||
|
|
||||||
NetworkSettings:
|
NetworkSettings:
|
||||||
description: "NetworkSettings exposes the network settings in the API"
|
description: "NetworkSettings exposes the network settings in the API"
|
||||||
type: "object"
|
type: "object"
|
||||||
properties:
|
properties:
|
||||||
Bridge:
|
Bridge:
|
||||||
description: Name of the network's bridge (for example, `docker0`).
|
description: |
|
||||||
|
Name of the default bridge interface when dockerd's --bridge flag is set.
|
||||||
type: "string"
|
type: "string"
|
||||||
example: "docker0"
|
example: "docker0"
|
||||||
SandboxID:
|
SandboxID:
|
||||||
|
@ -1379,34 +1417,40 @@ definitions:
|
||||||
HairpinMode:
|
HairpinMode:
|
||||||
description: |
|
description: |
|
||||||
Indicates if hairpin NAT should be enabled on the virtual interface.
|
Indicates if hairpin NAT should be enabled on the virtual interface.
|
||||||
|
|
||||||
|
Deprecated: This field is never set and will be removed in a future release.
|
||||||
type: "boolean"
|
type: "boolean"
|
||||||
example: false
|
example: false
|
||||||
LinkLocalIPv6Address:
|
LinkLocalIPv6Address:
|
||||||
description: IPv6 unicast address using the link-local prefix.
|
description: |
|
||||||
|
IPv6 unicast address using the link-local prefix.
|
||||||
|
|
||||||
|
Deprecated: This field is never set and will be removed in a future release.
|
||||||
type: "string"
|
type: "string"
|
||||||
example: "fe80::42:acff:fe11:1"
|
example: ""
|
||||||
LinkLocalIPv6PrefixLen:
|
LinkLocalIPv6PrefixLen:
|
||||||
description: Prefix length of the IPv6 unicast address.
|
description: |
|
||||||
|
Prefix length of the IPv6 unicast address.
|
||||||
|
|
||||||
|
Deprecated: This field is never set and will be removed in a future release.
|
||||||
type: "integer"
|
type: "integer"
|
||||||
example: "64"
|
example: ""
|
||||||
Ports:
|
Ports:
|
||||||
$ref: "#/definitions/PortMap"
|
$ref: "#/definitions/PortMap"
|
||||||
SandboxKey:
|
SandboxKey:
|
||||||
description: SandboxKey identifies the sandbox
|
description: SandboxKey is the full path of the netns handle
|
||||||
type: "string"
|
type: "string"
|
||||||
example: "/var/run/docker/netns/8ab54b426c38"
|
example: "/var/run/docker/netns/8ab54b426c38"
|
||||||
|
|
||||||
# TODO is SecondaryIPAddresses actually used?
|
|
||||||
SecondaryIPAddresses:
|
SecondaryIPAddresses:
|
||||||
description: ""
|
description: "Deprecated: This field is never set and will be removed in a future release."
|
||||||
type: "array"
|
type: "array"
|
||||||
items:
|
items:
|
||||||
$ref: "#/definitions/Address"
|
$ref: "#/definitions/Address"
|
||||||
x-nullable: true
|
x-nullable: true
|
||||||
|
|
||||||
# TODO is SecondaryIPv6Addresses actually used?
|
|
||||||
SecondaryIPv6Addresses:
|
SecondaryIPv6Addresses:
|
||||||
description: ""
|
description: "Deprecated: This field is never set and will be removed in a future release."
|
||||||
type: "array"
|
type: "array"
|
||||||
items:
|
items:
|
||||||
$ref: "#/definitions/Address"
|
$ref: "#/definitions/Address"
|
||||||
|
@ -1610,6 +1654,34 @@ definitions:
|
||||||
"WorkDir": "/var/lib/docker/overlay2/ef749362d13333e65fc95c572eb525abbe0052e16e086cb64bc3b98ae9aa6d74/work"
|
"WorkDir": "/var/lib/docker/overlay2/ef749362d13333e65fc95c572eb525abbe0052e16e086cb64bc3b98ae9aa6d74/work"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FilesystemChange:
|
||||||
|
description: |
|
||||||
|
Change in the container's filesystem.
|
||||||
|
type: "object"
|
||||||
|
required: [Path, Kind]
|
||||||
|
properties:
|
||||||
|
Path:
|
||||||
|
description: |
|
||||||
|
Path to file or directory that has changed.
|
||||||
|
type: "string"
|
||||||
|
x-nullable: false
|
||||||
|
Kind:
|
||||||
|
$ref: "#/definitions/ChangeType"
|
||||||
|
|
||||||
|
ChangeType:
|
||||||
|
description: |
|
||||||
|
Kind of change
|
||||||
|
|
||||||
|
Can be one of:
|
||||||
|
|
||||||
|
- `0`: Modified ("C")
|
||||||
|
- `1`: Added ("A")
|
||||||
|
- `2`: Deleted ("D")
|
||||||
|
type: "integer"
|
||||||
|
format: "uint8"
|
||||||
|
enum: [0, 1, 2]
|
||||||
|
x-nullable: false
|
||||||
|
|
||||||
ImageInspect:
|
ImageInspect:
|
||||||
description: |
|
description: |
|
||||||
Information about an image in the local image cache.
|
Information about an image in the local image cache.
|
||||||
|
@ -1679,18 +1751,27 @@ definitions:
|
||||||
description: |
|
description: |
|
||||||
Date and time at which the image was created, formatted in
|
Date and time at which the image was created, formatted in
|
||||||
[RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds.
|
[RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds.
|
||||||
|
|
||||||
|
This information is only available if present in the image,
|
||||||
|
and omitted otherwise.
|
||||||
type: "string"
|
type: "string"
|
||||||
x-nullable: false
|
format: "dateTime"
|
||||||
|
x-nullable: true
|
||||||
example: "2022-02-04T21:20:12.497794809Z"
|
example: "2022-02-04T21:20:12.497794809Z"
|
||||||
Container:
|
Container:
|
||||||
description: |
|
description: |
|
||||||
The ID of the container that was used to create the image.
|
The ID of the container that was used to create the image.
|
||||||
|
|
||||||
Depending on how the image was created, this field may be empty.
|
Depending on how the image was created, this field may be empty.
|
||||||
|
|
||||||
|
**Deprecated**: this field is kept for backward compatibility, but
|
||||||
|
will be removed in API v1.45.
|
||||||
type: "string"
|
type: "string"
|
||||||
x-nullable: false
|
|
||||||
example: "65974bc86f1770ae4bff79f651ebdbce166ae9aada632ee3fa9af3a264911735"
|
example: "65974bc86f1770ae4bff79f651ebdbce166ae9aada632ee3fa9af3a264911735"
|
||||||
ContainerConfig:
|
ContainerConfig:
|
||||||
|
description: |
|
||||||
|
**Deprecated**: this field is kept for backward compatibility, but
|
||||||
|
will be removed in API v1.45.
|
||||||
$ref: "#/definitions/ContainerConfig"
|
$ref: "#/definitions/ContainerConfig"
|
||||||
DockerVersion:
|
DockerVersion:
|
||||||
description: |
|
description: |
|
||||||
|
@ -1745,16 +1826,9 @@ definitions:
|
||||||
description: |
|
description: |
|
||||||
Total size of the image including all layers it is composed of.
|
Total size of the image including all layers it is composed of.
|
||||||
|
|
||||||
In versions of Docker before v1.10, this field was calculated from
|
Deprecated: this field is omitted in API v1.44, but kept for backward compatibility. Use Size instead.
|
||||||
the image itself and all of its parent images. Docker v1.10 and up
|
|
||||||
store images self-contained, and no longer use a parent-chain, making
|
|
||||||
this field an equivalent of the Size field.
|
|
||||||
|
|
||||||
This field is kept for backward compatibility, but may be removed in
|
|
||||||
a future version of the API.
|
|
||||||
type: "integer"
|
type: "integer"
|
||||||
format: "int64"
|
format: "int64"
|
||||||
x-nullable: false
|
|
||||||
example: 1239828
|
example: 1239828
|
||||||
GraphDriver:
|
GraphDriver:
|
||||||
$ref: "#/definitions/GraphDriverData"
|
$ref: "#/definitions/GraphDriverData"
|
||||||
|
@ -1794,6 +1868,7 @@ definitions:
|
||||||
x-nullable: true
|
x-nullable: true
|
||||||
ImageSummary:
|
ImageSummary:
|
||||||
type: "object"
|
type: "object"
|
||||||
|
x-go-name: "Summary"
|
||||||
required:
|
required:
|
||||||
- Id
|
- Id
|
||||||
- ParentId
|
- ParentId
|
||||||
|
@ -1802,7 +1877,6 @@ definitions:
|
||||||
- Created
|
- Created
|
||||||
- Size
|
- Size
|
||||||
- SharedSize
|
- SharedSize
|
||||||
- VirtualSize
|
|
||||||
- Labels
|
- Labels
|
||||||
- Containers
|
- Containers
|
||||||
properties:
|
properties:
|
||||||
|
@ -1888,19 +1962,12 @@ definitions:
|
||||||
x-nullable: false
|
x-nullable: false
|
||||||
example: 1239828
|
example: 1239828
|
||||||
VirtualSize:
|
VirtualSize:
|
||||||
description: |
|
description: |-
|
||||||
Total size of the image including all layers it is composed of.
|
Total size of the image including all layers it is composed of.
|
||||||
|
|
||||||
In versions of Docker before v1.10, this field was calculated from
|
Deprecated: this field is omitted in API v1.44, but kept for backward compatibility. Use Size instead.
|
||||||
the image itself and all of its parent images. Docker v1.10 and up
|
|
||||||
store images self-contained, and no longer use a parent-chain, making
|
|
||||||
this field an equivalent of the Size field.
|
|
||||||
|
|
||||||
This field is kept for backward compatibility, but may be removed in
|
|
||||||
a future version of the API.
|
|
||||||
type: "integer"
|
type: "integer"
|
||||||
format: "int64"
|
format: "int64"
|
||||||
x-nullable: false
|
|
||||||
example: 172064416
|
example: 172064416
|
||||||
Labels:
|
Labels:
|
||||||
description: "User-defined key/value metadata."
|
description: "User-defined key/value metadata."
|
||||||
|
@ -2416,6 +2483,11 @@ definitions:
|
||||||
example:
|
example:
|
||||||
- "container_1"
|
- "container_1"
|
||||||
- "container_2"
|
- "container_2"
|
||||||
|
MacAddress:
|
||||||
|
description: |
|
||||||
|
MAC address for the endpoint on this network. The network driver might ignore this parameter.
|
||||||
|
type: "string"
|
||||||
|
example: "02:42:ac:11:00:04"
|
||||||
Aliases:
|
Aliases:
|
||||||
type: "array"
|
type: "array"
|
||||||
items:
|
items:
|
||||||
|
@ -2466,11 +2538,6 @@ definitions:
|
||||||
type: "integer"
|
type: "integer"
|
||||||
format: "int64"
|
format: "int64"
|
||||||
example: 64
|
example: 64
|
||||||
MacAddress:
|
|
||||||
description: |
|
|
||||||
MAC address for the endpoint on this network.
|
|
||||||
type: "string"
|
|
||||||
example: "02:42:ac:11:00:04"
|
|
||||||
DriverOpts:
|
DriverOpts:
|
||||||
description: |
|
description: |
|
||||||
DriverOpts is a mapping of driver options and values. These options
|
DriverOpts is a mapping of driver options and values. These options
|
||||||
|
@ -2482,6 +2549,21 @@ definitions:
|
||||||
example:
|
example:
|
||||||
com.example.some-label: "some-value"
|
com.example.some-label: "some-value"
|
||||||
com.example.some-other-label: "some-other-value"
|
com.example.some-other-label: "some-other-value"
|
||||||
|
DNSNames:
|
||||||
|
description: |
|
||||||
|
List of all DNS names an endpoint has on a specific network. This
|
||||||
|
list is based on the container name, network aliases, container short
|
||||||
|
ID, and hostname.
|
||||||
|
|
||||||
|
These DNS names are non-fully qualified but can contain several dots.
|
||||||
|
You can get fully qualified DNS names by appending `.<network-name>`.
|
||||||
|
For instance, if container name is `my.ctr` and the network is named
|
||||||
|
`testnet`, `DNSNames` will contain `my.ctr` and the FQDN will be
|
||||||
|
`my.ctr.testnet`.
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
example: ["foobar", "server_x", "server_y", "my.ctr"]
|
||||||
|
|
||||||
EndpointIPAMConfig:
|
EndpointIPAMConfig:
|
||||||
description: |
|
description: |
|
||||||
|
@ -2979,8 +3061,6 @@ definitions:
|
||||||
Name: "journald"
|
Name: "journald"
|
||||||
- Type: "Log"
|
- Type: "Log"
|
||||||
Name: "json-file"
|
Name: "json-file"
|
||||||
- Type: "Log"
|
|
||||||
Name: "logentries"
|
|
||||||
- Type: "Log"
|
- Type: "Log"
|
||||||
Name: "splunk"
|
Name: "splunk"
|
||||||
- Type: "Log"
|
- Type: "Log"
|
||||||
|
@ -3515,6 +3595,32 @@ definitions:
|
||||||
Level:
|
Level:
|
||||||
type: "string"
|
type: "string"
|
||||||
description: "SELinux level label"
|
description: "SELinux level label"
|
||||||
|
Seccomp:
|
||||||
|
type: "object"
|
||||||
|
description: "Options for configuring seccomp on the container"
|
||||||
|
properties:
|
||||||
|
Mode:
|
||||||
|
type: "string"
|
||||||
|
enum:
|
||||||
|
- "default"
|
||||||
|
- "unconfined"
|
||||||
|
- "custom"
|
||||||
|
Profile:
|
||||||
|
description: "The custom seccomp profile as a json object"
|
||||||
|
type: "string"
|
||||||
|
AppArmor:
|
||||||
|
type: "object"
|
||||||
|
description: "Options for configuring AppArmor on the container"
|
||||||
|
properties:
|
||||||
|
Mode:
|
||||||
|
type: "string"
|
||||||
|
enum:
|
||||||
|
- "default"
|
||||||
|
- "disabled"
|
||||||
|
NoNewPrivileges:
|
||||||
|
type: "boolean"
|
||||||
|
description: "Configuration of the no_new_privs bit in the container"
|
||||||
|
|
||||||
TTY:
|
TTY:
|
||||||
description: "Whether a pseudo-TTY should be allocated."
|
description: "Whether a pseudo-TTY should be allocated."
|
||||||
type: "boolean"
|
type: "boolean"
|
||||||
|
@ -3909,6 +4015,44 @@ definitions:
|
||||||
- "remove"
|
- "remove"
|
||||||
- "orphaned"
|
- "orphaned"
|
||||||
|
|
||||||
|
ContainerStatus:
|
||||||
|
type: "object"
|
||||||
|
description: "represents the status of a container."
|
||||||
|
properties:
|
||||||
|
ContainerID:
|
||||||
|
type: "string"
|
||||||
|
PID:
|
||||||
|
type: "integer"
|
||||||
|
ExitCode:
|
||||||
|
type: "integer"
|
||||||
|
|
||||||
|
PortStatus:
|
||||||
|
type: "object"
|
||||||
|
description: "represents the port status of a task's host ports whose service has published host ports"
|
||||||
|
properties:
|
||||||
|
Ports:
|
||||||
|
type: "array"
|
||||||
|
items:
|
||||||
|
$ref: "#/definitions/EndpointPortConfig"
|
||||||
|
|
||||||
|
TaskStatus:
|
||||||
|
type: "object"
|
||||||
|
description: "represents the status of a task."
|
||||||
|
properties:
|
||||||
|
Timestamp:
|
||||||
|
type: "string"
|
||||||
|
format: "dateTime"
|
||||||
|
State:
|
||||||
|
$ref: "#/definitions/TaskState"
|
||||||
|
Message:
|
||||||
|
type: "string"
|
||||||
|
Err:
|
||||||
|
type: "string"
|
||||||
|
ContainerStatus:
|
||||||
|
$ref: "#/definitions/ContainerStatus"
|
||||||
|
PortStatus:
|
||||||
|
$ref: "#/definitions/PortStatus"
|
||||||
|
|
||||||
Task:
|
Task:
|
||||||
type: "object"
|
type: "object"
|
||||||
properties:
|
properties:
|
||||||
|
@ -3944,26 +4088,7 @@ definitions:
|
||||||
AssignedGenericResources:
|
AssignedGenericResources:
|
||||||
$ref: "#/definitions/GenericResources"
|
$ref: "#/definitions/GenericResources"
|
||||||
Status:
|
Status:
|
||||||
type: "object"
|
$ref: "#/definitions/TaskStatus"
|
||||||
properties:
|
|
||||||
Timestamp:
|
|
||||||
type: "string"
|
|
||||||
format: "dateTime"
|
|
||||||
State:
|
|
||||||
$ref: "#/definitions/TaskState"
|
|
||||||
Message:
|
|
||||||
type: "string"
|
|
||||||
Err:
|
|
||||||
type: "string"
|
|
||||||
ContainerStatus:
|
|
||||||
type: "object"
|
|
||||||
properties:
|
|
||||||
ContainerID:
|
|
||||||
type: "string"
|
|
||||||
PID:
|
|
||||||
type: "integer"
|
|
||||||
ExitCode:
|
|
||||||
type: "integer"
|
|
||||||
DesiredState:
|
DesiredState:
|
||||||
$ref: "#/definitions/TaskState"
|
$ref: "#/definitions/TaskState"
|
||||||
JobIteration:
|
JobIteration:
|
||||||
|
@ -4179,7 +4304,10 @@ definitions:
|
||||||
- "stop-first"
|
- "stop-first"
|
||||||
- "start-first"
|
- "start-first"
|
||||||
Networks:
|
Networks:
|
||||||
description: "Specifies which networks the service should attach to."
|
description: |
|
||||||
|
Specifies which networks the service should attach to.
|
||||||
|
|
||||||
|
Deprecated: This field is deprecated since v1.44. The Networks field in TaskSpec should be used instead.
|
||||||
type: "array"
|
type: "array"
|
||||||
items:
|
items:
|
||||||
$ref: "#/definitions/NetworkAttachmentConfig"
|
$ref: "#/definitions/NetworkAttachmentConfig"
|
||||||
|
@ -4413,6 +4541,7 @@ definitions:
|
||||||
|
|
||||||
ImageDeleteResponseItem:
|
ImageDeleteResponseItem:
|
||||||
type: "object"
|
type: "object"
|
||||||
|
x-go-name: "DeleteResponse"
|
||||||
properties:
|
properties:
|
||||||
Untagged:
|
Untagged:
|
||||||
description: "The image ID of an image that was untagged"
|
description: "The image ID of an image that was untagged"
|
||||||
|
@ -4421,6 +4550,29 @@ definitions:
|
||||||
description: "The image ID of an image that was deleted"
|
description: "The image ID of an image that was deleted"
|
||||||
type: "string"
|
type: "string"
|
||||||
|
|
||||||
|
ServiceCreateResponse:
|
||||||
|
type: "object"
|
||||||
|
description: |
|
||||||
|
contains the information returned to a client on the
|
||||||
|
creation of a new service.
|
||||||
|
properties:
|
||||||
|
ID:
|
||||||
|
description: "The ID of the created service."
|
||||||
|
type: "string"
|
||||||
|
x-nullable: false
|
||||||
|
example: "ak7w3gjqoa3kuz8xcpnyy0pvl"
|
||||||
|
Warnings:
|
||||||
|
description: |
|
||||||
|
Optional warning message.
|
||||||
|
|
||||||
|
FIXME(thaJeztah): this should have "omitempty" in the generated type.
|
||||||
|
type: "array"
|
||||||
|
x-nullable: true
|
||||||
|
items:
|
||||||
|
type: "string"
|
||||||
|
example:
|
||||||
|
- "unable to pin image doesnotexist:latest to digest: image library/doesnotexist:latest not found"
|
||||||
|
|
||||||
ServiceUpdateResponse:
|
ServiceUpdateResponse:
|
||||||
type: "object"
|
type: "object"
|
||||||
properties:
|
properties:
|
||||||
|
@ -4430,7 +4582,8 @@ definitions:
|
||||||
items:
|
items:
|
||||||
type: "string"
|
type: "string"
|
||||||
example:
|
example:
|
||||||
Warning: "unable to pin image doesnotexist:latest to digest: image library/doesnotexist:latest not found"
|
Warnings:
|
||||||
|
- "unable to pin image doesnotexist:latest to digest: image library/doesnotexist:latest not found"
|
||||||
|
|
||||||
ContainerSummary:
|
ContainerSummary:
|
||||||
type: "object"
|
type: "object"
|
||||||
|
@ -4652,7 +4805,8 @@ definitions:
|
||||||
example: false
|
example: false
|
||||||
OOMKilled:
|
OOMKilled:
|
||||||
description: |
|
description: |
|
||||||
Whether this container has been killed because it ran out of memory.
|
Whether a process within this container has been killed because it ran
|
||||||
|
out of memory since the container was last started.
|
||||||
type: "boolean"
|
type: "boolean"
|
||||||
example: false
|
example: false
|
||||||
Dead:
|
Dead:
|
||||||
|
@ -5035,7 +5189,7 @@ definitions:
|
||||||
Go runtime (`GOOS`).
|
Go runtime (`GOOS`).
|
||||||
|
|
||||||
Currently returned values are "linux" and "windows". A full list of
|
Currently returned values are "linux" and "windows". A full list of
|
||||||
possible values can be found in the [Go documentation](https://golang.org/doc/install/source#environment).
|
possible values can be found in the [Go documentation](https://go.dev/doc/install/source#environment).
|
||||||
type: "string"
|
type: "string"
|
||||||
example: "linux"
|
example: "linux"
|
||||||
Architecture:
|
Architecture:
|
||||||
|
@ -5043,7 +5197,7 @@ definitions:
|
||||||
Hardware architecture of the host, as returned by the Go runtime
|
Hardware architecture of the host, as returned by the Go runtime
|
||||||
(`GOARCH`).
|
(`GOARCH`).
|
||||||
|
|
||||||
A full list of possible values can be found in the [Go documentation](https://golang.org/doc/install/source#environment).
|
A full list of possible values can be found in the [Go documentation](https://go.dev/doc/install/source#environment).
|
||||||
type: "string"
|
type: "string"
|
||||||
example: "x86_64"
|
example: "x86_64"
|
||||||
NCPU:
|
NCPU:
|
||||||
|
@ -5129,42 +5283,8 @@ definitions:
|
||||||
ServerVersion:
|
ServerVersion:
|
||||||
description: |
|
description: |
|
||||||
Version string of the daemon.
|
Version string of the daemon.
|
||||||
|
|
||||||
> **Note**: the [standalone Swarm API](https://docs.docker.com/swarm/swarm-api/)
|
|
||||||
> returns the Swarm version instead of the daemon version, for example
|
|
||||||
> `swarm/1.2.8`.
|
|
||||||
type: "string"
|
type: "string"
|
||||||
example: "17.06.0-ce"
|
example: "24.0.2"
|
||||||
ClusterStore:
|
|
||||||
description: |
|
|
||||||
URL of the distributed storage backend.
|
|
||||||
|
|
||||||
|
|
||||||
The storage backend is used for multihost networking (to store
|
|
||||||
network and endpoint information) and by the node discovery mechanism.
|
|
||||||
|
|
||||||
<p><br /></p>
|
|
||||||
|
|
||||||
> **Deprecated**: This field is only propagated when using standalone Swarm
|
|
||||||
> mode, and overlay networking using an external k/v store. Overlay
|
|
||||||
> networks with Swarm mode enabled use the built-in raft store, and
|
|
||||||
> this field will be empty.
|
|
||||||
type: "string"
|
|
||||||
example: "consul://consul.corp.example.com:8600/some/path"
|
|
||||||
ClusterAdvertise:
|
|
||||||
description: |
|
|
||||||
The network endpoint that the Engine advertises for the purpose of
|
|
||||||
node discovery. ClusterAdvertise is a `host:port` combination on which
|
|
||||||
the daemon is reachable by other hosts.
|
|
||||||
|
|
||||||
<p><br /></p>
|
|
||||||
|
|
||||||
> **Deprecated**: This field is only propagated when using standalone Swarm
|
|
||||||
> mode, and overlay networking using an external k/v store. Overlay
|
|
||||||
> networks with Swarm mode enabled use the built-in raft store, and
|
|
||||||
> this field will be empty.
|
|
||||||
type: "string"
|
|
||||||
example: "node5.corp.example.com:8000"
|
|
||||||
Runtimes:
|
Runtimes:
|
||||||
description: |
|
description: |
|
||||||
List of [OCI compliant](https://github.com/opencontainers/runtime-spec)
|
List of [OCI compliant](https://github.com/opencontainers/runtime-spec)
|
||||||
|
@ -5242,7 +5362,8 @@ definitions:
|
||||||
SecurityOptions:
|
SecurityOptions:
|
||||||
description: |
|
description: |
|
||||||
List of security features that are enabled on the daemon, such as
|
List of security features that are enabled on the daemon, such as
|
||||||
apparmor, seccomp, SELinux, user-namespaces (userns), and rootless.
|
apparmor, seccomp, SELinux, user-namespaces (userns), rootless and
|
||||||
|
no-new-privileges.
|
||||||
|
|
||||||
Additional configuration options for each security feature may
|
Additional configuration options for each security feature may
|
||||||
be present, and are included as a comma-separated list of key/value
|
be present, and are included as a comma-separated list of key/value
|
||||||
|
@ -5296,7 +5417,25 @@ definitions:
|
||||||
- "WARNING: No memory limit support"
|
- "WARNING: No memory limit support"
|
||||||
- "WARNING: bridge-nf-call-iptables is disabled"
|
- "WARNING: bridge-nf-call-iptables is disabled"
|
||||||
- "WARNING: bridge-nf-call-ip6tables is disabled"
|
- "WARNING: bridge-nf-call-ip6tables is disabled"
|
||||||
|
CDISpecDirs:
|
||||||
|
description: |
|
||||||
|
List of directories where (Container Device Interface) CDI
|
||||||
|
specifications are located.
|
||||||
|
|
||||||
|
These specifications define vendor-specific modifications to an OCI
|
||||||
|
runtime specification for a container being created.
|
||||||
|
|
||||||
|
An empty list indicates that CDI device injection is disabled.
|
||||||
|
|
||||||
|
Note that since using CDI device injection requires the daemon to have
|
||||||
|
experimental enabled. For non-experimental daemons an empty list will
|
||||||
|
always be returned.
|
||||||
|
type: "array"
|
||||||
|
items:
|
||||||
|
type: "string"
|
||||||
|
example:
|
||||||
|
- "/etc/cdi"
|
||||||
|
- "/var/run/cdi"
|
||||||
|
|
||||||
# PluginsInfo is a temp struct holding Plugins name
|
# PluginsInfo is a temp struct holding Plugins name
|
||||||
# registered with docker daemon. It is used by Info struct
|
# registered with docker daemon. It is used by Info struct
|
||||||
|
@ -5334,7 +5473,7 @@ definitions:
|
||||||
type: "array"
|
type: "array"
|
||||||
items:
|
items:
|
||||||
type: "string"
|
type: "string"
|
||||||
example: ["awslogs", "fluentd", "gcplogs", "gelf", "journald", "json-file", "logentries", "splunk", "syslog"]
|
example: ["awslogs", "fluentd", "gcplogs", "gelf", "journald", "json-file", "splunk", "syslog"]
|
||||||
|
|
||||||
|
|
||||||
RegistryServiceConfig:
|
RegistryServiceConfig:
|
||||||
|
@ -5532,6 +5671,28 @@ definitions:
|
||||||
items:
|
items:
|
||||||
type: "string"
|
type: "string"
|
||||||
example: ["--debug", "--systemd-cgroup=false"]
|
example: ["--debug", "--systemd-cgroup=false"]
|
||||||
|
status:
|
||||||
|
description: |
|
||||||
|
Information specific to the runtime.
|
||||||
|
|
||||||
|
While this API specification does not define data provided by runtimes,
|
||||||
|
the following well-known properties may be provided by runtimes:
|
||||||
|
|
||||||
|
`org.opencontainers.runtime-spec.features`: features structure as defined
|
||||||
|
in the [OCI Runtime Specification](https://github.com/opencontainers/runtime-spec/blob/main/features.md),
|
||||||
|
in a JSON string representation.
|
||||||
|
|
||||||
|
<p><br /></p>
|
||||||
|
|
||||||
|
> **Note**: The information returned in this field, including the
|
||||||
|
> formatting of values and labels, should not be considered stable,
|
||||||
|
> and may change without notice.
|
||||||
|
type: "object"
|
||||||
|
x-nullable: true
|
||||||
|
additionalProperties:
|
||||||
|
type: "string"
|
||||||
|
example:
|
||||||
|
"org.opencontainers.runtime-spec.features": "{\"ociVersionMin\":\"1.0.0\",\"ociVersionMax\":\"1.1.0\",\"...\":\"...\"}"
|
||||||
|
|
||||||
Commit:
|
Commit:
|
||||||
description: |
|
description: |
|
||||||
|
@ -6416,6 +6577,7 @@ paths:
|
||||||
Aliases:
|
Aliases:
|
||||||
- "server_x"
|
- "server_x"
|
||||||
- "server_y"
|
- "server_y"
|
||||||
|
database_nw: {}
|
||||||
|
|
||||||
required: true
|
required: true
|
||||||
responses:
|
responses:
|
||||||
|
@ -6563,7 +6725,7 @@ paths:
|
||||||
StopSignal: "SIGTERM"
|
StopSignal: "SIGTERM"
|
||||||
StopTimeout: 10
|
StopTimeout: 10
|
||||||
Created: "2015-01-06T15:47:31.485331387Z"
|
Created: "2015-01-06T15:47:31.485331387Z"
|
||||||
Driver: "devicemapper"
|
Driver: "overlay2"
|
||||||
ExecIDs:
|
ExecIDs:
|
||||||
- "b35395de42bc8abd327f9dd65d913b9ba28c74d2f0734eeeae84fa1c616a0fca"
|
- "b35395de42bc8abd327f9dd65d913b9ba28c74d2f0734eeeae84fa1c616a0fca"
|
||||||
- "3fc1232e5cd20c8de182ed81178503dc6437f4e7ef12b52cc5e8de020652f1c4"
|
- "3fc1232e5cd20c8de182ed81178503dc6437f4e7ef12b52cc5e8de020652f1c4"
|
||||||
|
@ -6875,9 +7037,9 @@ paths:
|
||||||
Returns which files in a container's filesystem have been added, deleted,
|
Returns which files in a container's filesystem have been added, deleted,
|
||||||
or modified. The `Kind` of modification can be one of:
|
or modified. The `Kind` of modification can be one of:
|
||||||
|
|
||||||
- `0`: Modified
|
- `0`: Modified ("C")
|
||||||
- `1`: Added
|
- `1`: Added ("A")
|
||||||
- `2`: Deleted
|
- `2`: Deleted ("D")
|
||||||
operationId: "ContainerChanges"
|
operationId: "ContainerChanges"
|
||||||
produces: ["application/json"]
|
produces: ["application/json"]
|
||||||
responses:
|
responses:
|
||||||
|
@ -6886,22 +7048,7 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
type: "array"
|
type: "array"
|
||||||
items:
|
items:
|
||||||
type: "object"
|
$ref: "#/definitions/FilesystemChange"
|
||||||
x-go-name: "ContainerChangeResponseItem"
|
|
||||||
title: "ContainerChangeResponseItem"
|
|
||||||
description: "change item in response to ContainerChanges operation"
|
|
||||||
required: [Path, Kind]
|
|
||||||
properties:
|
|
||||||
Path:
|
|
||||||
description: "Path to file that has changed"
|
|
||||||
type: "string"
|
|
||||||
x-nullable: false
|
|
||||||
Kind:
|
|
||||||
description: "Kind of change"
|
|
||||||
type: "integer"
|
|
||||||
format: "uint8"
|
|
||||||
enum: [0, 1, 2]
|
|
||||||
x-nullable: false
|
|
||||||
examples:
|
examples:
|
||||||
application/json:
|
application/json:
|
||||||
- Path: "/dev"
|
- Path: "/dev"
|
||||||
|
@ -8009,6 +8156,7 @@ paths:
|
||||||
- `label=key` or `label="key=value"` of an image label
|
- `label=key` or `label="key=value"` of an image label
|
||||||
- `reference`=(`<image-name>[:<tag>]`)
|
- `reference`=(`<image-name>[:<tag>]`)
|
||||||
- `since`=(`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`)
|
- `since`=(`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`)
|
||||||
|
- `until=<timestamp>`
|
||||||
type: "string"
|
type: "string"
|
||||||
- name: "shared-size"
|
- name: "shared-size"
|
||||||
in: "query"
|
in: "query"
|
||||||
|
@ -8191,6 +8339,16 @@ paths:
|
||||||
description: "BuildKit output configuration"
|
description: "BuildKit output configuration"
|
||||||
type: "string"
|
type: "string"
|
||||||
default: ""
|
default: ""
|
||||||
|
- name: "version"
|
||||||
|
in: "query"
|
||||||
|
type: "string"
|
||||||
|
default: "1"
|
||||||
|
enum: ["1", "2"]
|
||||||
|
description: |
|
||||||
|
Version of the builder backend to use.
|
||||||
|
|
||||||
|
- `1` is the first generation classic (deprecated) builder in the Docker daemon (default)
|
||||||
|
- `2` is [BuildKit](https://github.com/moby/buildkit)
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: "no error"
|
description: "no error"
|
||||||
|
@ -8228,7 +8386,7 @@ paths:
|
||||||
|
|
||||||
Available filters:
|
Available filters:
|
||||||
|
|
||||||
- `until=<duration>`: duration relative to daemon's time, during which build cache was not used, in Go's duration format (e.g., '24h')
|
- `until=<timestamp>` remove cache older than `<timestamp>`. The `<timestamp>` can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. `10m`, `1h30m`) computed relative to the daemon's local time.
|
||||||
- `id=<id>`
|
- `id=<id>`
|
||||||
- `parent=<id>`
|
- `parent=<id>`
|
||||||
- `type=<string>`
|
- `type=<string>`
|
||||||
|
@ -8260,7 +8418,7 @@ paths:
|
||||||
/images/create:
|
/images/create:
|
||||||
post:
|
post:
|
||||||
summary: "Create an image"
|
summary: "Create an image"
|
||||||
description: "Create an image by either pulling it from a registry or importing it."
|
description: "Pull or import an image."
|
||||||
operationId: "ImageCreate"
|
operationId: "ImageCreate"
|
||||||
consumes:
|
consumes:
|
||||||
- "text/plain"
|
- "text/plain"
|
||||||
|
@ -8611,28 +8769,35 @@ paths:
|
||||||
is_official:
|
is_official:
|
||||||
type: "boolean"
|
type: "boolean"
|
||||||
is_automated:
|
is_automated:
|
||||||
|
description: |
|
||||||
|
Whether this repository has automated builds enabled.
|
||||||
|
|
||||||
|
<p><br /></p>
|
||||||
|
|
||||||
|
> **Deprecated**: This field is deprecated and will always be "false".
|
||||||
type: "boolean"
|
type: "boolean"
|
||||||
|
example: false
|
||||||
name:
|
name:
|
||||||
type: "string"
|
type: "string"
|
||||||
star_count:
|
star_count:
|
||||||
type: "integer"
|
type: "integer"
|
||||||
examples:
|
examples:
|
||||||
application/json:
|
application/json:
|
||||||
- description: ""
|
- description: "A minimal Docker image based on Alpine Linux with a complete package index and only 5 MB in size!"
|
||||||
is_official: false
|
is_official: true
|
||||||
is_automated: false
|
is_automated: false
|
||||||
name: "wma55/u1210sshd"
|
name: "alpine"
|
||||||
star_count: 0
|
star_count: 10093
|
||||||
- description: ""
|
- description: "Busybox base image."
|
||||||
is_official: false
|
is_official: true
|
||||||
is_automated: false
|
is_automated: false
|
||||||
name: "jdswinbank/sshd"
|
name: "Busybox base image."
|
||||||
star_count: 0
|
star_count: 3037
|
||||||
- description: ""
|
- description: "The PostgreSQL object-relational database system provides reliability and data integrity."
|
||||||
is_official: false
|
is_official: true
|
||||||
is_automated: false
|
is_automated: false
|
||||||
name: "vgauthier/sshd"
|
name: "postgres"
|
||||||
star_count: 0
|
star_count: 12408
|
||||||
500:
|
500:
|
||||||
description: "Server error"
|
description: "Server error"
|
||||||
schema:
|
schema:
|
||||||
|
@ -8652,7 +8817,6 @@ paths:
|
||||||
description: |
|
description: |
|
||||||
A JSON encoded value of the filters (a `map[string][]string`) to process on the images list. Available filters:
|
A JSON encoded value of the filters (a `map[string][]string`) to process on the images list. Available filters:
|
||||||
|
|
||||||
- `is-automated=(true|false)`
|
|
||||||
- `is-official=(true|false)`
|
- `is-official=(true|false)`
|
||||||
- `stars=<number>` Matches images that has at least 'number' stars.
|
- `stars=<number>` Matches images that has at least 'number' stars.
|
||||||
type: "string"
|
type: "string"
|
||||||
|
@ -9047,7 +9211,6 @@ paths:
|
||||||
Created: 1466724217
|
Created: 1466724217
|
||||||
Size: 1092588
|
Size: 1092588
|
||||||
SharedSize: 0
|
SharedSize: 0
|
||||||
VirtualSize: 1092588
|
|
||||||
Labels: {}
|
Labels: {}
|
||||||
Containers: 1
|
Containers: 1
|
||||||
Containers:
|
Containers:
|
||||||
|
@ -9910,8 +10073,14 @@ paths:
|
||||||
example:
|
example:
|
||||||
Id: "22be93d5babb089c5aab8dbc369042fad48ff791584ca2da2100db837a1c7c30"
|
Id: "22be93d5babb089c5aab8dbc369042fad48ff791584ca2da2100db837a1c7c30"
|
||||||
Warning: ""
|
Warning: ""
|
||||||
|
400:
|
||||||
|
description: "bad parameter"
|
||||||
|
schema:
|
||||||
|
$ref: "#/definitions/ErrorResponse"
|
||||||
403:
|
403:
|
||||||
description: "operation not supported for pre-defined networks"
|
description: |
|
||||||
|
Forbidden operation. This happens when trying to create a network named after a pre-defined network,
|
||||||
|
or when trying to create an overlay network on a daemon which is not part of a Swarm cluster.
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/definitions/ErrorResponse"
|
$ref: "#/definitions/ErrorResponse"
|
||||||
404:
|
404:
|
||||||
|
@ -9937,13 +10106,7 @@ paths:
|
||||||
type: "string"
|
type: "string"
|
||||||
CheckDuplicate:
|
CheckDuplicate:
|
||||||
description: |
|
description: |
|
||||||
Check for networks with duplicate names. Since Network is
|
Deprecated: CheckDuplicate is now always enabled.
|
||||||
primarily keyed based on a random ID and not on the name, and
|
|
||||||
network name is strictly a user-friendly alias to the network
|
|
||||||
which is uniquely identified using ID, there is no guaranteed
|
|
||||||
way to check for duplicates. CheckDuplicate is there to provide
|
|
||||||
a best effort checking of any networks which has the same name
|
|
||||||
but it is not guaranteed to catch all name collisions.
|
|
||||||
type: "boolean"
|
type: "boolean"
|
||||||
Driver:
|
Driver:
|
||||||
description: "Name of the network driver plugin to use."
|
description: "Name of the network driver plugin to use."
|
||||||
|
@ -10011,14 +10174,19 @@ paths:
|
||||||
/networks/{id}/connect:
|
/networks/{id}/connect:
|
||||||
post:
|
post:
|
||||||
summary: "Connect a container to a network"
|
summary: "Connect a container to a network"
|
||||||
|
description: "The network must be either a local-scoped network or a swarm-scoped network with the `attachable` option set. A network cannot be re-attached to a running container"
|
||||||
operationId: "NetworkConnect"
|
operationId: "NetworkConnect"
|
||||||
consumes:
|
consumes:
|
||||||
- "application/json"
|
- "application/json"
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: "No error"
|
description: "No error"
|
||||||
|
400:
|
||||||
|
description: "bad parameter"
|
||||||
|
schema:
|
||||||
|
$ref: "#/definitions/ErrorResponse"
|
||||||
403:
|
403:
|
||||||
description: "Operation not supported for swarm scoped networks"
|
description: "Operation forbidden"
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/definitions/ErrorResponse"
|
$ref: "#/definitions/ErrorResponse"
|
||||||
404:
|
404:
|
||||||
|
@ -10053,6 +10221,7 @@ paths:
|
||||||
IPAMConfig:
|
IPAMConfig:
|
||||||
IPv4Address: "172.24.56.89"
|
IPv4Address: "172.24.56.89"
|
||||||
IPv6Address: "2001:db8::5689"
|
IPv6Address: "2001:db8::5689"
|
||||||
|
MacAddress: "02:42:ac:12:05:02"
|
||||||
tags: ["Network"]
|
tags: ["Network"]
|
||||||
|
|
||||||
/networks/{id}/disconnect:
|
/networks/{id}/disconnect:
|
||||||
|
@ -10374,6 +10543,12 @@ paths:
|
||||||
default if omitted.
|
default if omitted.
|
||||||
required: true
|
required: true
|
||||||
type: "string"
|
type: "string"
|
||||||
|
- name: "force"
|
||||||
|
in: "query"
|
||||||
|
description: |
|
||||||
|
Force disable a plugin even if still in use.
|
||||||
|
required: false
|
||||||
|
type: "boolean"
|
||||||
tags: ["Plugin"]
|
tags: ["Plugin"]
|
||||||
/plugins/{name}/upgrade:
|
/plugins/{name}/upgrade:
|
||||||
post:
|
post:
|
||||||
|
@ -11040,18 +11215,7 @@ paths:
|
||||||
201:
|
201:
|
||||||
description: "no error"
|
description: "no error"
|
||||||
schema:
|
schema:
|
||||||
type: "object"
|
$ref: "#/definitions/ServiceCreateResponse"
|
||||||
title: "ServiceCreateResponse"
|
|
||||||
properties:
|
|
||||||
ID:
|
|
||||||
description: "The ID of the created service."
|
|
||||||
type: "string"
|
|
||||||
Warning:
|
|
||||||
description: "Optional warning message"
|
|
||||||
type: "string"
|
|
||||||
example:
|
|
||||||
ID: "ak7w3gjqoa3kuz8xcpnyy0pvl"
|
|
||||||
Warning: "unable to pin image doesnotexist:latest to digest: image library/doesnotexist:latest not found"
|
|
||||||
400:
|
400:
|
||||||
description: "bad parameter"
|
description: "bad parameter"
|
||||||
schema:
|
schema:
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
package types // import "github.com/docker/docker/api/types"
|
|
||||||
|
|
||||||
// AuthConfig contains authorization information for connecting to a Registry
|
|
||||||
type AuthConfig struct {
|
|
||||||
Username string `json:"username,omitempty"`
|
|
||||||
Password string `json:"password,omitempty"`
|
|
||||||
Auth string `json:"auth,omitempty"`
|
|
||||||
|
|
||||||
// Email is an optional value associated with the username.
|
|
||||||
// This field is deprecated and will be removed in a later
|
|
||||||
// version of docker.
|
|
||||||
Email string `json:"email,omitempty"`
|
|
||||||
|
|
||||||
ServerAddress string `json:"serveraddress,omitempty"`
|
|
||||||
|
|
||||||
// IdentityToken is used to authenticate the user and get
|
|
||||||
// an access token for the registry.
|
|
||||||
IdentityToken string `json:"identitytoken,omitempty"`
|
|
||||||
|
|
||||||
// RegistryToken is a bearer token to be sent to a registry
|
|
||||||
RegistryToken string `json:"registrytoken,omitempty"`
|
|
||||||
}
|
|
|
@ -5,9 +5,29 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/distribution/reference"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
|
"github.com/docker/docker/api/types/network"
|
||||||
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ContainerCreateConfig is the parameter set to ContainerCreate()
|
||||||
|
type ContainerCreateConfig struct {
|
||||||
|
Name string
|
||||||
|
Config *container.Config
|
||||||
|
HostConfig *container.HostConfig
|
||||||
|
NetworkingConfig *network.NetworkingConfig
|
||||||
|
Platform *ocispec.Platform
|
||||||
|
DefaultReadOnlyNonRecursive bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContainerRmConfig holds arguments for the container remove
|
||||||
|
// operation. This struct is used to tell the backend what operations
|
||||||
|
// to perform.
|
||||||
|
type ContainerRmConfig struct {
|
||||||
|
ForceRemove, RemoveVolume, RemoveLink bool
|
||||||
|
}
|
||||||
|
|
||||||
// ContainerAttachConfig holds the streams to use when connecting to a container to view logs.
|
// ContainerAttachConfig holds the streams to use when connecting to a container to view logs.
|
||||||
type ContainerAttachConfig struct {
|
type ContainerAttachConfig struct {
|
||||||
GetStreams func(multiplexed bool) (io.ReadCloser, io.Writer, io.Writer, error)
|
GetStreams func(multiplexed bool) (io.ReadCloser, io.Writer, io.Writer, error)
|
||||||
|
@ -70,7 +90,6 @@ type ContainerStatsConfig struct {
|
||||||
Stream bool
|
Stream bool
|
||||||
OneShot bool
|
OneShot bool
|
||||||
OutStream io.Writer
|
OutStream io.Writer
|
||||||
Version string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecInspect holds information about a running process started
|
// ExecInspect holds information about a running process started
|
||||||
|
@ -102,8 +121,7 @@ type ExecProcessConfig struct {
|
||||||
// CreateImageConfig is the configuration for creating an image from a
|
// CreateImageConfig is the configuration for creating an image from a
|
||||||
// container.
|
// container.
|
||||||
type CreateImageConfig struct {
|
type CreateImageConfig struct {
|
||||||
Repo string
|
Tag reference.NamedTagged
|
||||||
Tag string
|
|
||||||
Pause bool
|
Pause bool
|
||||||
Author string
|
Author string
|
||||||
Comment string
|
Comment string
|
||||||
|
@ -111,6 +129,13 @@ type CreateImageConfig struct {
|
||||||
Changes []string
|
Changes []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetImageOpts holds parameters to retrieve image information
|
||||||
|
// from the backend.
|
||||||
|
type GetImageOpts struct {
|
||||||
|
Platform *ocispec.Platform
|
||||||
|
Details bool
|
||||||
|
}
|
||||||
|
|
||||||
// CommitConfig is the configuration for creating an image as part of a build.
|
// CommitConfig is the configuration for creating an image as part of a build.
|
||||||
type CommitConfig struct {
|
type CommitConfig struct {
|
||||||
Author string
|
Author string
|
||||||
|
@ -122,3 +147,25 @@ type CommitConfig struct {
|
||||||
ContainerOS string
|
ContainerOS string
|
||||||
ParentImageID string
|
ParentImageID string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PluginRmConfig holds arguments for plugin remove.
|
||||||
|
type PluginRmConfig struct {
|
||||||
|
ForceRemove bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// PluginEnableConfig holds arguments for plugin enable
|
||||||
|
type PluginEnableConfig struct {
|
||||||
|
Timeout int
|
||||||
|
}
|
||||||
|
|
||||||
|
// PluginDisableConfig holds arguments for plugin disable.
|
||||||
|
type PluginDisableConfig struct {
|
||||||
|
ForceDisable bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkListConfig stores the options available for listing networks
|
||||||
|
type NetworkListConfig struct {
|
||||||
|
// TODO(@cpuguy83): naming is hard, this is pulled from what was being used in the router before moving here
|
||||||
|
Detailed bool
|
||||||
|
Verbose bool
|
||||||
|
}
|
||||||
|
|
|
@ -4,8 +4,9 @@ import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/registry"
|
||||||
"github.com/docker/docker/pkg/streamformatter"
|
"github.com/docker/docker/pkg/streamformatter"
|
||||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PullOption defines different modes for accessing images
|
// PullOption defines different modes for accessing images
|
||||||
|
@ -39,7 +40,7 @@ type BuildConfig struct {
|
||||||
// GetImageAndLayerOptions are the options supported by GetImageAndReleasableLayer
|
// GetImageAndLayerOptions are the options supported by GetImageAndReleasableLayer
|
||||||
type GetImageAndLayerOptions struct {
|
type GetImageAndLayerOptions struct {
|
||||||
PullOption PullOption
|
PullOption PullOption
|
||||||
AuthConfig map[string]types.AuthConfig
|
AuthConfig map[string]registry.AuthConfig
|
||||||
Output io.Writer
|
Output io.Writer
|
||||||
Platform *specs.Platform
|
Platform *ocispec.Platform
|
||||||
}
|
}
|
||||||
|
|
7
api/types/checkpoint/list.go
Normal file
7
api/types/checkpoint/list.go
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package checkpoint
|
||||||
|
|
||||||
|
// Summary represents the details of a checkpoint when listing endpoints.
|
||||||
|
type Summary struct {
|
||||||
|
// Name is the name of the checkpoint.
|
||||||
|
Name string
|
||||||
|
}
|
19
api/types/checkpoint/options.go
Normal file
19
api/types/checkpoint/options.go
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
package checkpoint
|
||||||
|
|
||||||
|
// CreateOptions holds parameters to create a checkpoint from a container.
|
||||||
|
type CreateOptions struct {
|
||||||
|
CheckpointID string
|
||||||
|
CheckpointDir string
|
||||||
|
Exit bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOptions holds parameters to list checkpoints for a container.
|
||||||
|
type ListOptions struct {
|
||||||
|
CheckpointDir string
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteOptions holds parameters to delete a checkpoint from a container.
|
||||||
|
type DeleteOptions struct {
|
||||||
|
CheckpointID string
|
||||||
|
CheckpointDir string
|
||||||
|
}
|
|
@ -7,47 +7,10 @@ import (
|
||||||
|
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
|
"github.com/docker/docker/api/types/registry"
|
||||||
units "github.com/docker/go-units"
|
units "github.com/docker/go-units"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CheckpointCreateOptions holds parameters to create a checkpoint from a container
|
|
||||||
type CheckpointCreateOptions struct {
|
|
||||||
CheckpointID string
|
|
||||||
CheckpointDir string
|
|
||||||
Exit bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckpointListOptions holds parameters to list checkpoints for a container
|
|
||||||
type CheckpointListOptions struct {
|
|
||||||
CheckpointDir string
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckpointDeleteOptions holds parameters to delete a checkpoint from a container
|
|
||||||
type CheckpointDeleteOptions struct {
|
|
||||||
CheckpointID string
|
|
||||||
CheckpointDir string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContainerAttachOptions holds parameters to attach to a container.
|
|
||||||
type ContainerAttachOptions struct {
|
|
||||||
Stream bool
|
|
||||||
Stdin bool
|
|
||||||
Stdout bool
|
|
||||||
Stderr bool
|
|
||||||
DetachKeys string
|
|
||||||
Logs bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContainerCommitOptions holds parameters to commit changes into a container.
|
|
||||||
type ContainerCommitOptions struct {
|
|
||||||
Reference string
|
|
||||||
Comment string
|
|
||||||
Author string
|
|
||||||
Changes []string
|
|
||||||
Pause bool
|
|
||||||
Config *container.Config
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContainerExecInspect holds information returned by exec inspect.
|
// ContainerExecInspect holds information returned by exec inspect.
|
||||||
type ContainerExecInspect struct {
|
type ContainerExecInspect struct {
|
||||||
ExecID string `json:"ID"`
|
ExecID string `json:"ID"`
|
||||||
|
@ -57,42 +20,6 @@ type ContainerExecInspect struct {
|
||||||
Pid int
|
Pid int
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerListOptions holds parameters to list containers with.
|
|
||||||
type ContainerListOptions struct {
|
|
||||||
Size bool
|
|
||||||
All bool
|
|
||||||
Latest bool
|
|
||||||
Since string
|
|
||||||
Before string
|
|
||||||
Limit int
|
|
||||||
Filters filters.Args
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContainerLogsOptions holds parameters to filter logs with.
|
|
||||||
type ContainerLogsOptions struct {
|
|
||||||
ShowStdout bool
|
|
||||||
ShowStderr bool
|
|
||||||
Since string
|
|
||||||
Until string
|
|
||||||
Timestamps bool
|
|
||||||
Follow bool
|
|
||||||
Tail string
|
|
||||||
Details bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContainerRemoveOptions holds parameters to remove containers.
|
|
||||||
type ContainerRemoveOptions struct {
|
|
||||||
RemoveVolumes bool
|
|
||||||
RemoveLinks bool
|
|
||||||
Force bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContainerStartOptions holds parameters to start containers.
|
|
||||||
type ContainerStartOptions struct {
|
|
||||||
CheckpointID string
|
|
||||||
CheckpointDir string
|
|
||||||
}
|
|
||||||
|
|
||||||
// CopyToContainerOptions holds information
|
// CopyToContainerOptions holds information
|
||||||
// about files to copy into a container
|
// about files to copy into a container
|
||||||
type CopyToContainerOptions struct {
|
type CopyToContainerOptions struct {
|
||||||
|
@ -180,7 +107,7 @@ type ImageBuildOptions struct {
|
||||||
// at all (nil). See the parsing of buildArgs in
|
// at all (nil). See the parsing of buildArgs in
|
||||||
// api/server/router/build/build_routes.go for even more info.
|
// api/server/router/build/build_routes.go for even more info.
|
||||||
BuildArgs map[string]*string
|
BuildArgs map[string]*string
|
||||||
AuthConfigs map[string]AuthConfig
|
AuthConfigs map[string]registry.AuthConfig
|
||||||
Context io.Reader
|
Context io.Reader
|
||||||
Labels map[string]string
|
Labels map[string]string
|
||||||
// squash the resulting image's layers to the parent
|
// squash the resulting image's layers to the parent
|
||||||
|
@ -230,42 +157,12 @@ type ImageBuildResponse struct {
|
||||||
OSType string
|
OSType string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImageCreateOptions holds information to create images.
|
|
||||||
type ImageCreateOptions struct {
|
|
||||||
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry.
|
|
||||||
Platform string // Platform is the target platform of the image if it needs to be pulled from the registry.
|
|
||||||
}
|
|
||||||
|
|
||||||
// ImageImportSource holds source information for ImageImport
|
// ImageImportSource holds source information for ImageImport
|
||||||
type ImageImportSource struct {
|
type ImageImportSource struct {
|
||||||
Source io.Reader // Source is the data to send to the server to create this image from. You must set SourceName to "-" to leverage this.
|
Source io.Reader // Source is the data to send to the server to create this image from. You must set SourceName to "-" to leverage this.
|
||||||
SourceName string // SourceName is the name of the image to pull. Set to "-" to leverage the Source attribute.
|
SourceName string // SourceName is the name of the image to pull. Set to "-" to leverage the Source attribute.
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImageImportOptions holds information to import images from the client host.
|
|
||||||
type ImageImportOptions struct {
|
|
||||||
Tag string // Tag is the name to tag this image with. This attribute is deprecated.
|
|
||||||
Message string // Message is the message to tag the image with
|
|
||||||
Changes []string // Changes are the raw changes to apply to this image
|
|
||||||
Platform string // Platform is the target platform of the image
|
|
||||||
}
|
|
||||||
|
|
||||||
// ImageListOptions holds parameters to list images with.
|
|
||||||
type ImageListOptions struct {
|
|
||||||
// All controls whether all images in the graph are filtered, or just
|
|
||||||
// the heads.
|
|
||||||
All bool
|
|
||||||
|
|
||||||
// Filters is a JSON-encoded set of filter arguments.
|
|
||||||
Filters filters.Args
|
|
||||||
|
|
||||||
// SharedSize indicates whether the shared size of images should be computed.
|
|
||||||
SharedSize bool
|
|
||||||
|
|
||||||
// ContainerCount indicates whether container count should be computed.
|
|
||||||
ContainerCount bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// ImageLoadResponse returns information to the client about a load process.
|
// ImageLoadResponse returns information to the client about a load process.
|
||||||
type ImageLoadResponse struct {
|
type ImageLoadResponse struct {
|
||||||
// Body must be closed to avoid a resource leak
|
// Body must be closed to avoid a resource leak
|
||||||
|
@ -273,14 +170,6 @@ type ImageLoadResponse struct {
|
||||||
JSON bool
|
JSON bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImagePullOptions holds information to pull images.
|
|
||||||
type ImagePullOptions struct {
|
|
||||||
All bool
|
|
||||||
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry
|
|
||||||
PrivilegeFunc RequestPrivilegeFunc
|
|
||||||
Platform string
|
|
||||||
}
|
|
||||||
|
|
||||||
// RequestPrivilegeFunc is a function interface that
|
// RequestPrivilegeFunc is a function interface that
|
||||||
// clients can supply to retry operations after
|
// clients can supply to retry operations after
|
||||||
// getting an authorization error.
|
// getting an authorization error.
|
||||||
|
@ -289,15 +178,6 @@ type ImagePullOptions struct {
|
||||||
// if the privilege request fails.
|
// if the privilege request fails.
|
||||||
type RequestPrivilegeFunc func() (string, error)
|
type RequestPrivilegeFunc func() (string, error)
|
||||||
|
|
||||||
// ImagePushOptions holds information to push images.
|
|
||||||
type ImagePushOptions ImagePullOptions
|
|
||||||
|
|
||||||
// ImageRemoveOptions holds parameters to remove images.
|
|
||||||
type ImageRemoveOptions struct {
|
|
||||||
Force bool
|
|
||||||
PruneChildren bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// ImageSearchOptions holds parameters to search images with.
|
// ImageSearchOptions holds parameters to search images with.
|
||||||
type ImageSearchOptions struct {
|
type ImageSearchOptions struct {
|
||||||
RegistryAuth string
|
RegistryAuth string
|
||||||
|
@ -306,14 +186,6 @@ type ImageSearchOptions struct {
|
||||||
Limit int
|
Limit int
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResizeOptions holds parameters to resize a tty.
|
|
||||||
// It can be used to resize container ttys and
|
|
||||||
// exec process ttys too.
|
|
||||||
type ResizeOptions struct {
|
|
||||||
Height uint
|
|
||||||
Width uint
|
|
||||||
}
|
|
||||||
|
|
||||||
// NodeListOptions holds parameters to list nodes with.
|
// NodeListOptions holds parameters to list nodes with.
|
||||||
type NodeListOptions struct {
|
type NodeListOptions struct {
|
||||||
Filters filters.Args
|
Filters filters.Args
|
||||||
|
@ -339,15 +211,6 @@ type ServiceCreateOptions struct {
|
||||||
QueryRegistry bool
|
QueryRegistry bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServiceCreateResponse contains the information returned to a client
|
|
||||||
// on the creation of a new service.
|
|
||||||
type ServiceCreateResponse struct {
|
|
||||||
// ID is the ID of the created service.
|
|
||||||
ID string
|
|
||||||
// Warnings is a set of non-fatal warning messages to pass on to the user.
|
|
||||||
Warnings []string `json:",omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Values for RegistryAuthFrom in ServiceUpdateOptions
|
// Values for RegistryAuthFrom in ServiceUpdateOptions
|
||||||
const (
|
const (
|
||||||
RegistryAuthFromSpec = "spec"
|
RegistryAuthFromSpec = "spec"
|
||||||
|
|
|
@ -1,32 +1,5 @@
|
||||||
package types // import "github.com/docker/docker/api/types"
|
package types // import "github.com/docker/docker/api/types"
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/docker/docker/api/types/container"
|
|
||||||
"github.com/docker/docker/api/types/network"
|
|
||||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
// configs holds structs used for internal communication between the
|
|
||||||
// frontend (such as an http server) and the backend (such as the
|
|
||||||
// docker daemon).
|
|
||||||
|
|
||||||
// ContainerCreateConfig is the parameter set to ContainerCreate()
|
|
||||||
type ContainerCreateConfig struct {
|
|
||||||
Name string
|
|
||||||
Config *container.Config
|
|
||||||
HostConfig *container.HostConfig
|
|
||||||
NetworkingConfig *network.NetworkingConfig
|
|
||||||
Platform *specs.Platform
|
|
||||||
AdjustCPUShares bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContainerRmConfig holds arguments for the container remove
|
|
||||||
// operation. This struct is used to tell the backend what operations
|
|
||||||
// to perform.
|
|
||||||
type ContainerRmConfig struct {
|
|
||||||
ForceRemove, RemoveVolume, RemoveLink bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExecConfig is a small subset of the Config struct that holds the configuration
|
// ExecConfig is a small subset of the Config struct that holds the configuration
|
||||||
// for the exec feature of docker.
|
// for the exec feature of docker.
|
||||||
type ExecConfig struct {
|
type ExecConfig struct {
|
||||||
|
@ -43,25 +16,3 @@ type ExecConfig struct {
|
||||||
WorkingDir string // Working directory
|
WorkingDir string // Working directory
|
||||||
Cmd []string // Execution commands and args
|
Cmd []string // Execution commands and args
|
||||||
}
|
}
|
||||||
|
|
||||||
// PluginRmConfig holds arguments for plugin remove.
|
|
||||||
type PluginRmConfig struct {
|
|
||||||
ForceRemove bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// PluginEnableConfig holds arguments for plugin enable
|
|
||||||
type PluginEnableConfig struct {
|
|
||||||
Timeout int
|
|
||||||
}
|
|
||||||
|
|
||||||
// PluginDisableConfig holds arguments for plugin disable.
|
|
||||||
type PluginDisableConfig struct {
|
|
||||||
ForceDisable bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// NetworkListConfig stores the options available for listing networks
|
|
||||||
type NetworkListConfig struct {
|
|
||||||
// TODO(@cpuguy83): naming is hard, this is pulled from what was being used in the router before moving here
|
|
||||||
Detailed bool
|
|
||||||
Verbose bool
|
|
||||||
}
|
|
||||||
|
|
15
api/types/container/change_type.go
Normal file
15
api/types/container/change_type.go
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package container
|
||||||
|
|
||||||
|
// This file was generated by the swagger tool.
|
||||||
|
// Editing this file might prove futile when you re-run the swagger generate command
|
||||||
|
|
||||||
|
// ChangeType Kind of change
|
||||||
|
//
|
||||||
|
// Can be one of:
|
||||||
|
//
|
||||||
|
// - `0`: Modified ("C")
|
||||||
|
// - `1`: Added ("A")
|
||||||
|
// - `2`: Deleted ("D")
|
||||||
|
//
|
||||||
|
// swagger:model ChangeType
|
||||||
|
type ChangeType uint8
|
23
api/types/container/change_types.go
Normal file
23
api/types/container/change_types.go
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
package container
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ChangeModify represents the modify operation.
|
||||||
|
ChangeModify ChangeType = 0
|
||||||
|
// ChangeAdd represents the add operation.
|
||||||
|
ChangeAdd ChangeType = 1
|
||||||
|
// ChangeDelete represents the delete operation.
|
||||||
|
ChangeDelete ChangeType = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
func (ct ChangeType) String() string {
|
||||||
|
switch ct {
|
||||||
|
case ChangeModify:
|
||||||
|
return "C"
|
||||||
|
case ChangeAdd:
|
||||||
|
return "A"
|
||||||
|
case ChangeDelete:
|
||||||
|
return "D"
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ import (
|
||||||
|
|
||||||
"github.com/docker/docker/api/types/strslice"
|
"github.com/docker/docker/api/types/strslice"
|
||||||
"github.com/docker/go-connections/nat"
|
"github.com/docker/go-connections/nat"
|
||||||
|
dockerspec "github.com/moby/docker-image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MinimumDuration puts a minimum on user configured duration.
|
// MinimumDuration puts a minimum on user configured duration.
|
||||||
|
@ -33,25 +34,7 @@ type StopOptions struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// HealthConfig holds configuration settings for the HEALTHCHECK feature.
|
// HealthConfig holds configuration settings for the HEALTHCHECK feature.
|
||||||
type HealthConfig struct {
|
type HealthConfig = dockerspec.HealthcheckConfig
|
||||||
// Test is the test to perform to check that the container is healthy.
|
|
||||||
// An empty slice means to inherit the default.
|
|
||||||
// The options are:
|
|
||||||
// {} : inherit healthcheck
|
|
||||||
// {"NONE"} : disable healthcheck
|
|
||||||
// {"CMD", args...} : exec arguments directly
|
|
||||||
// {"CMD-SHELL", command} : run command with system's default shell
|
|
||||||
Test []string `json:",omitempty"`
|
|
||||||
|
|
||||||
// Zero means to inherit. Durations are expressed as integer nanoseconds.
|
|
||||||
Interval time.Duration `json:",omitempty"` // Interval is the time to wait between checks.
|
|
||||||
Timeout time.Duration `json:",omitempty"` // Timeout is the time to wait before considering the check to have hung.
|
|
||||||
StartPeriod time.Duration `json:",omitempty"` // The start period for the container to initialize before the retries starts to count down.
|
|
||||||
|
|
||||||
// Retries is the number of consecutive failures needed to consider a container as unhealthy.
|
|
||||||
// Zero means inherit.
|
|
||||||
Retries int `json:",omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExecStartOptions holds the options to start container's exec.
|
// ExecStartOptions holds the options to start container's exec.
|
||||||
type ExecStartOptions struct {
|
type ExecStartOptions struct {
|
||||||
|
@ -87,10 +70,13 @@ type Config struct {
|
||||||
WorkingDir string // Current directory (PWD) in the command will be launched
|
WorkingDir string // Current directory (PWD) in the command will be launched
|
||||||
Entrypoint strslice.StrSlice // Entrypoint to run when starting the container
|
Entrypoint strslice.StrSlice // Entrypoint to run when starting the container
|
||||||
NetworkDisabled bool `json:",omitempty"` // Is network disabled
|
NetworkDisabled bool `json:",omitempty"` // Is network disabled
|
||||||
MacAddress string `json:",omitempty"` // Mac Address of the container
|
// Mac Address of the container.
|
||||||
OnBuild []string // ONBUILD metadata that were defined on the image Dockerfile
|
//
|
||||||
Labels map[string]string // List of labels set to this container
|
// Deprecated: this field is deprecated since API v1.44. Use EndpointSettings.MacAddress instead.
|
||||||
StopSignal string `json:",omitempty"` // Signal to stop a container
|
MacAddress string `json:",omitempty"`
|
||||||
StopTimeout *int `json:",omitempty"` // Timeout (in seconds) to stop a container
|
OnBuild []string // ONBUILD metadata that were defined on the image Dockerfile
|
||||||
Shell strslice.StrSlice `json:",omitempty"` // Shell for shell-form of RUN, CMD, ENTRYPOINT
|
Labels map[string]string // List of labels set to this container
|
||||||
|
StopSignal string `json:",omitempty"` // Signal to stop a container
|
||||||
|
StopTimeout *int `json:",omitempty"` // Timeout (in seconds) to stop a container
|
||||||
|
Shell strslice.StrSlice `json:",omitempty"` // Shell for shell-form of RUN, CMD, ENTRYPOINT
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
package container // import "github.com/docker/docker/api/types/container"
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// Code generated by `swagger generate operation`. DO NOT EDIT.
|
|
||||||
//
|
|
||||||
// See hack/generate-swagger-api.sh
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// ContainerChangeResponseItem change item in response to ContainerChanges operation
|
|
||||||
// swagger:model ContainerChangeResponseItem
|
|
||||||
type ContainerChangeResponseItem struct {
|
|
||||||
|
|
||||||
// Kind of change
|
|
||||||
// Required: true
|
|
||||||
Kind uint8 `json:"Kind"`
|
|
||||||
|
|
||||||
// Path to file that has changed
|
|
||||||
// Required: true
|
|
||||||
Path string `json:"Path"`
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
package container // import "github.com/docker/docker/api/types/container"
|
|
||||||
|
|
||||||
// ContainerCreateCreatedBody OK response to ContainerCreate operation
|
|
||||||
//
|
|
||||||
// Deprecated: use CreateResponse
|
|
||||||
type ContainerCreateCreatedBody = CreateResponse
|
|
||||||
|
|
||||||
// ContainerWaitOKBody OK response to ContainerWait operation
|
|
||||||
//
|
|
||||||
// Deprecated: use WaitResponse
|
|
||||||
type ContainerWaitOKBody = WaitResponse
|
|
||||||
|
|
||||||
// ContainerWaitOKBodyError container waiting error, if any
|
|
||||||
//
|
|
||||||
// Deprecated: use WaitExitError
|
|
||||||
type ContainerWaitOKBodyError = WaitExitError
|
|
9
api/types/container/errors.go
Normal file
9
api/types/container/errors.go
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
package container
|
||||||
|
|
||||||
|
type errInvalidParameter struct{ error }
|
||||||
|
|
||||||
|
func (e *errInvalidParameter) InvalidParameter() {}
|
||||||
|
|
||||||
|
func (e *errInvalidParameter) Unwrap() error {
|
||||||
|
return e.error
|
||||||
|
}
|
19
api/types/container/filesystem_change.go
Normal file
19
api/types/container/filesystem_change.go
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
package container
|
||||||
|
|
||||||
|
// This file was generated by the swagger tool.
|
||||||
|
// Editing this file might prove futile when you re-run the swagger generate command
|
||||||
|
|
||||||
|
// FilesystemChange Change in the container's filesystem.
|
||||||
|
//
|
||||||
|
// swagger:model FilesystemChange
|
||||||
|
type FilesystemChange struct {
|
||||||
|
|
||||||
|
// kind
|
||||||
|
// Required: true
|
||||||
|
Kind ChangeType `json:"Kind"`
|
||||||
|
|
||||||
|
// Path to file or directory that has changed.
|
||||||
|
//
|
||||||
|
// Required: true
|
||||||
|
Path string `json:"Path"`
|
||||||
|
}
|
|
@ -1,465 +0,0 @@
|
||||||
package container // import "github.com/docker/docker/api/types/container"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/docker/docker/api/types/blkiodev"
|
|
||||||
"github.com/docker/docker/api/types/mount"
|
|
||||||
"github.com/docker/docker/api/types/strslice"
|
|
||||||
"github.com/docker/go-connections/nat"
|
|
||||||
units "github.com/docker/go-units"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CgroupnsMode represents the cgroup namespace mode of the container
|
|
||||||
type CgroupnsMode string
|
|
||||||
|
|
||||||
// cgroup namespace modes for containers
|
|
||||||
const (
|
|
||||||
CgroupnsModeEmpty CgroupnsMode = ""
|
|
||||||
CgroupnsModePrivate CgroupnsMode = "private"
|
|
||||||
CgroupnsModeHost CgroupnsMode = "host"
|
|
||||||
)
|
|
||||||
|
|
||||||
// IsPrivate indicates whether the container uses its own private cgroup namespace
|
|
||||||
func (c CgroupnsMode) IsPrivate() bool {
|
|
||||||
return c == CgroupnsModePrivate
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsHost indicates whether the container shares the host's cgroup namespace
|
|
||||||
func (c CgroupnsMode) IsHost() bool {
|
|
||||||
return c == CgroupnsModeHost
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty indicates whether the container cgroup namespace mode is unset
|
|
||||||
func (c CgroupnsMode) IsEmpty() bool {
|
|
||||||
return c == CgroupnsModeEmpty
|
|
||||||
}
|
|
||||||
|
|
||||||
// Valid indicates whether the cgroup namespace mode is valid
|
|
||||||
func (c CgroupnsMode) Valid() bool {
|
|
||||||
return c.IsEmpty() || c.IsPrivate() || c.IsHost()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Isolation represents the isolation technology of a container. The supported
|
|
||||||
// values are platform specific
|
|
||||||
type Isolation string
|
|
||||||
|
|
||||||
// Isolation modes for containers
|
|
||||||
const (
|
|
||||||
IsolationEmpty Isolation = "" // IsolationEmpty is unspecified (same behavior as default)
|
|
||||||
IsolationDefault Isolation = "default" // IsolationDefault is the default isolation mode on current daemon
|
|
||||||
IsolationProcess Isolation = "process" // IsolationProcess is process isolation mode
|
|
||||||
IsolationHyperV Isolation = "hyperv" // IsolationHyperV is HyperV isolation mode
|
|
||||||
)
|
|
||||||
|
|
||||||
// IsDefault indicates the default isolation technology of a container. On Linux this
|
|
||||||
// is the native driver. On Windows, this is a Windows Server Container.
|
|
||||||
func (i Isolation) IsDefault() bool {
|
|
||||||
// TODO consider making isolation-mode strict (case-sensitive)
|
|
||||||
v := Isolation(strings.ToLower(string(i)))
|
|
||||||
return v == IsolationDefault || v == IsolationEmpty
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsHyperV indicates the use of a Hyper-V partition for isolation
|
|
||||||
func (i Isolation) IsHyperV() bool {
|
|
||||||
// TODO consider making isolation-mode strict (case-sensitive)
|
|
||||||
return Isolation(strings.ToLower(string(i))) == IsolationHyperV
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsProcess indicates the use of process isolation
|
|
||||||
func (i Isolation) IsProcess() bool {
|
|
||||||
// TODO consider making isolation-mode strict (case-sensitive)
|
|
||||||
return Isolation(strings.ToLower(string(i))) == IsolationProcess
|
|
||||||
}
|
|
||||||
|
|
||||||
// IpcMode represents the container ipc stack.
|
|
||||||
type IpcMode string
|
|
||||||
|
|
||||||
// IpcMode constants
|
|
||||||
const (
|
|
||||||
IPCModeNone IpcMode = "none"
|
|
||||||
IPCModeHost IpcMode = "host"
|
|
||||||
IPCModeContainer IpcMode = "container"
|
|
||||||
IPCModePrivate IpcMode = "private"
|
|
||||||
IPCModeShareable IpcMode = "shareable"
|
|
||||||
)
|
|
||||||
|
|
||||||
// IsPrivate indicates whether the container uses its own private ipc namespace which can not be shared.
|
|
||||||
func (n IpcMode) IsPrivate() bool {
|
|
||||||
return n == IPCModePrivate
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsHost indicates whether the container shares the host's ipc namespace.
|
|
||||||
func (n IpcMode) IsHost() bool {
|
|
||||||
return n == IPCModeHost
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsShareable indicates whether the container's ipc namespace can be shared with another container.
|
|
||||||
func (n IpcMode) IsShareable() bool {
|
|
||||||
return n == IPCModeShareable
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsContainer indicates whether the container uses another container's ipc namespace.
|
|
||||||
func (n IpcMode) IsContainer() bool {
|
|
||||||
return strings.HasPrefix(string(n), string(IPCModeContainer)+":")
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNone indicates whether container IpcMode is set to "none".
|
|
||||||
func (n IpcMode) IsNone() bool {
|
|
||||||
return n == IPCModeNone
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty indicates whether container IpcMode is empty
|
|
||||||
func (n IpcMode) IsEmpty() bool {
|
|
||||||
return n == ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// Valid indicates whether the ipc mode is valid.
|
|
||||||
func (n IpcMode) Valid() bool {
|
|
||||||
return n.IsEmpty() || n.IsNone() || n.IsPrivate() || n.IsHost() || n.IsShareable() || n.IsContainer()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Container returns the name of the container ipc stack is going to be used.
|
|
||||||
func (n IpcMode) Container() string {
|
|
||||||
if n.IsContainer() {
|
|
||||||
return strings.TrimPrefix(string(n), string(IPCModeContainer)+":")
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// NetworkMode represents the container network stack.
|
|
||||||
type NetworkMode string
|
|
||||||
|
|
||||||
// IsNone indicates whether container isn't using a network stack.
|
|
||||||
func (n NetworkMode) IsNone() bool {
|
|
||||||
return n == "none"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsDefault indicates whether container uses the default network stack.
|
|
||||||
func (n NetworkMode) IsDefault() bool {
|
|
||||||
return n == "default"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsPrivate indicates whether container uses its private network stack.
|
|
||||||
func (n NetworkMode) IsPrivate() bool {
|
|
||||||
return !(n.IsHost() || n.IsContainer())
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsContainer indicates whether container uses a container network stack.
|
|
||||||
func (n NetworkMode) IsContainer() bool {
|
|
||||||
parts := strings.SplitN(string(n), ":", 2)
|
|
||||||
return len(parts) > 1 && parts[0] == "container"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConnectedContainer is the id of the container which network this container is connected to.
|
|
||||||
func (n NetworkMode) ConnectedContainer() string {
|
|
||||||
parts := strings.SplitN(string(n), ":", 2)
|
|
||||||
if len(parts) > 1 {
|
|
||||||
return parts[1]
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserDefined indicates user-created network
|
|
||||||
func (n NetworkMode) UserDefined() string {
|
|
||||||
if n.IsUserDefined() {
|
|
||||||
return string(n)
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// UsernsMode represents userns mode in the container.
|
|
||||||
type UsernsMode string
|
|
||||||
|
|
||||||
// IsHost indicates whether the container uses the host's userns.
|
|
||||||
func (n UsernsMode) IsHost() bool {
|
|
||||||
return n == "host"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsPrivate indicates whether the container uses the a private userns.
|
|
||||||
func (n UsernsMode) IsPrivate() bool {
|
|
||||||
return !(n.IsHost())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Valid indicates whether the userns is valid.
|
|
||||||
func (n UsernsMode) Valid() bool {
|
|
||||||
parts := strings.Split(string(n), ":")
|
|
||||||
switch mode := parts[0]; mode {
|
|
||||||
case "", "host":
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// CgroupSpec represents the cgroup to use for the container.
|
|
||||||
type CgroupSpec string
|
|
||||||
|
|
||||||
// IsContainer indicates whether the container is using another container cgroup
|
|
||||||
func (c CgroupSpec) IsContainer() bool {
|
|
||||||
parts := strings.SplitN(string(c), ":", 2)
|
|
||||||
return len(parts) > 1 && parts[0] == "container"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Valid indicates whether the cgroup spec is valid.
|
|
||||||
func (c CgroupSpec) Valid() bool {
|
|
||||||
return c.IsContainer() || c == ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// Container returns the name of the container whose cgroup will be used.
|
|
||||||
func (c CgroupSpec) Container() string {
|
|
||||||
parts := strings.SplitN(string(c), ":", 2)
|
|
||||||
if len(parts) > 1 {
|
|
||||||
return parts[1]
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// UTSMode represents the UTS namespace of the container.
|
|
||||||
type UTSMode string
|
|
||||||
|
|
||||||
// IsPrivate indicates whether the container uses its private UTS namespace.
|
|
||||||
func (n UTSMode) IsPrivate() bool {
|
|
||||||
return !(n.IsHost())
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsHost indicates whether the container uses the host's UTS namespace.
|
|
||||||
func (n UTSMode) IsHost() bool {
|
|
||||||
return n == "host"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Valid indicates whether the UTS namespace is valid.
|
|
||||||
func (n UTSMode) Valid() bool {
|
|
||||||
parts := strings.Split(string(n), ":")
|
|
||||||
switch mode := parts[0]; mode {
|
|
||||||
case "", "host":
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// PidMode represents the pid namespace of the container.
|
|
||||||
type PidMode string
|
|
||||||
|
|
||||||
// IsPrivate indicates whether the container uses its own new pid namespace.
|
|
||||||
func (n PidMode) IsPrivate() bool {
|
|
||||||
return !(n.IsHost() || n.IsContainer())
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsHost indicates whether the container uses the host's pid namespace.
|
|
||||||
func (n PidMode) IsHost() bool {
|
|
||||||
return n == "host"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsContainer indicates whether the container uses a container's pid namespace.
|
|
||||||
func (n PidMode) IsContainer() bool {
|
|
||||||
parts := strings.SplitN(string(n), ":", 2)
|
|
||||||
return len(parts) > 1 && parts[0] == "container"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Valid indicates whether the pid namespace is valid.
|
|
||||||
func (n PidMode) Valid() bool {
|
|
||||||
parts := strings.Split(string(n), ":")
|
|
||||||
switch mode := parts[0]; mode {
|
|
||||||
case "", "host":
|
|
||||||
case "container":
|
|
||||||
if len(parts) != 2 || parts[1] == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Container returns the name of the container whose pid namespace is going to be used.
|
|
||||||
func (n PidMode) Container() string {
|
|
||||||
parts := strings.SplitN(string(n), ":", 2)
|
|
||||||
if len(parts) > 1 {
|
|
||||||
return parts[1]
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeviceRequest represents a request for devices from a device driver.
|
|
||||||
// Used by GPU device drivers.
|
|
||||||
type DeviceRequest struct {
|
|
||||||
Driver string // Name of device driver
|
|
||||||
Count int // Number of devices to request (-1 = All)
|
|
||||||
DeviceIDs []string // List of device IDs as recognizable by the device driver
|
|
||||||
Capabilities [][]string // An OR list of AND lists of device capabilities (e.g. "gpu")
|
|
||||||
Options map[string]string // Options to pass onto the device driver
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeviceMapping represents the device mapping between the host and the container.
|
|
||||||
type DeviceMapping struct {
|
|
||||||
PathOnHost string
|
|
||||||
PathInContainer string
|
|
||||||
CgroupPermissions string
|
|
||||||
}
|
|
||||||
|
|
||||||
// RestartPolicy represents the restart policies of the container.
|
|
||||||
type RestartPolicy struct {
|
|
||||||
Name string
|
|
||||||
MaximumRetryCount int
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNone indicates whether the container has the "no" restart policy.
|
|
||||||
// This means the container will not automatically restart when exiting.
|
|
||||||
func (rp *RestartPolicy) IsNone() bool {
|
|
||||||
return rp.Name == "no" || rp.Name == ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsAlways indicates whether the container has the "always" restart policy.
|
|
||||||
// This means the container will automatically restart regardless of the exit status.
|
|
||||||
func (rp *RestartPolicy) IsAlways() bool {
|
|
||||||
return rp.Name == "always"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsOnFailure indicates whether the container has the "on-failure" restart policy.
|
|
||||||
// This means the container will automatically restart of exiting with a non-zero exit status.
|
|
||||||
func (rp *RestartPolicy) IsOnFailure() bool {
|
|
||||||
return rp.Name == "on-failure"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsUnlessStopped indicates whether the container has the
|
|
||||||
// "unless-stopped" restart policy. This means the container will
|
|
||||||
// automatically restart unless user has put it to stopped state.
|
|
||||||
func (rp *RestartPolicy) IsUnlessStopped() bool {
|
|
||||||
return rp.Name == "unless-stopped"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsSame compares two RestartPolicy to see if they are the same
|
|
||||||
func (rp *RestartPolicy) IsSame(tp *RestartPolicy) bool {
|
|
||||||
return rp.Name == tp.Name && rp.MaximumRetryCount == tp.MaximumRetryCount
|
|
||||||
}
|
|
||||||
|
|
||||||
// LogMode is a type to define the available modes for logging
|
|
||||||
// These modes affect how logs are handled when log messages start piling up.
|
|
||||||
type LogMode string
|
|
||||||
|
|
||||||
// Available logging modes
|
|
||||||
const (
|
|
||||||
LogModeUnset LogMode = ""
|
|
||||||
LogModeBlocking LogMode = "blocking"
|
|
||||||
LogModeNonBlock LogMode = "non-blocking"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LogConfig represents the logging configuration of the container.
|
|
||||||
type LogConfig struct {
|
|
||||||
Type string
|
|
||||||
Config map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resources contains container's resources (cgroups config, ulimits...)
|
|
||||||
type Resources struct {
|
|
||||||
// Applicable to all platforms
|
|
||||||
CPUShares int64 `json:"CpuShares"` // CPU shares (relative weight vs. other containers)
|
|
||||||
Memory int64 // Memory limit (in bytes)
|
|
||||||
NanoCPUs int64 `json:"NanoCpus"` // CPU quota in units of 10<sup>-9</sup> CPUs.
|
|
||||||
|
|
||||||
// Applicable to UNIX platforms
|
|
||||||
CgroupParent string // Parent cgroup.
|
|
||||||
BlkioWeight uint16 // Block IO weight (relative weight vs. other containers)
|
|
||||||
BlkioWeightDevice []*blkiodev.WeightDevice
|
|
||||||
BlkioDeviceReadBps []*blkiodev.ThrottleDevice
|
|
||||||
BlkioDeviceWriteBps []*blkiodev.ThrottleDevice
|
|
||||||
BlkioDeviceReadIOps []*blkiodev.ThrottleDevice
|
|
||||||
BlkioDeviceWriteIOps []*blkiodev.ThrottleDevice
|
|
||||||
CPUPeriod int64 `json:"CpuPeriod"` // CPU CFS (Completely Fair Scheduler) period
|
|
||||||
CPUQuota int64 `json:"CpuQuota"` // CPU CFS (Completely Fair Scheduler) quota
|
|
||||||
CPURealtimePeriod int64 `json:"CpuRealtimePeriod"` // CPU real-time period
|
|
||||||
CPURealtimeRuntime int64 `json:"CpuRealtimeRuntime"` // CPU real-time runtime
|
|
||||||
CpusetCpus string // CpusetCpus 0-2, 0,1
|
|
||||||
CpusetMems string // CpusetMems 0-2, 0,1
|
|
||||||
Devices []DeviceMapping // List of devices to map inside the container
|
|
||||||
DeviceCgroupRules []string // List of rule to be added to the device cgroup
|
|
||||||
DeviceRequests []DeviceRequest // List of device requests for device drivers
|
|
||||||
|
|
||||||
// KernelMemory specifies the kernel memory limit (in bytes) for the container.
|
|
||||||
// Deprecated: kernel 5.4 deprecated kmem.limit_in_bytes.
|
|
||||||
KernelMemory int64 `json:",omitempty"`
|
|
||||||
KernelMemoryTCP int64 `json:",omitempty"` // Hard limit for kernel TCP buffer memory (in bytes)
|
|
||||||
MemoryReservation int64 // Memory soft limit (in bytes)
|
|
||||||
MemorySwap int64 // Total memory usage (memory + swap); set `-1` to enable unlimited swap
|
|
||||||
MemorySwappiness *int64 // Tuning container memory swappiness behaviour
|
|
||||||
OomKillDisable *bool // Whether to disable OOM Killer or not
|
|
||||||
PidsLimit *int64 // Setting PIDs limit for a container; Set `0` or `-1` for unlimited, or `null` to not change.
|
|
||||||
Ulimits []*units.Ulimit // List of ulimits to be set in the container
|
|
||||||
|
|
||||||
// Applicable to Windows
|
|
||||||
CPUCount int64 `json:"CpuCount"` // CPU count
|
|
||||||
CPUPercent int64 `json:"CpuPercent"` // CPU percent
|
|
||||||
IOMaximumIOps uint64 // Maximum IOps for the container system drive
|
|
||||||
IOMaximumBandwidth uint64 // Maximum IO in bytes per second for the container system drive
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateConfig holds the mutable attributes of a Container.
|
|
||||||
// Those attributes can be updated at runtime.
|
|
||||||
type UpdateConfig struct {
|
|
||||||
// Contains container's resources (cgroups, ulimits)
|
|
||||||
Resources
|
|
||||||
RestartPolicy RestartPolicy
|
|
||||||
}
|
|
||||||
|
|
||||||
// HostConfig the non-portable Config structure of a container.
|
|
||||||
// Here, "non-portable" means "dependent of the host we are running on".
|
|
||||||
// Portable information *should* appear in Config.
|
|
||||||
type HostConfig struct {
|
|
||||||
// Applicable to all platforms
|
|
||||||
Binds []string // List of volume bindings for this container
|
|
||||||
ContainerIDFile string // File (path) where the containerId is written
|
|
||||||
LogConfig LogConfig // Configuration of the logs for this container
|
|
||||||
NetworkMode NetworkMode // Network mode to use for the container
|
|
||||||
PortBindings nat.PortMap // Port mapping between the exposed port (container) and the host
|
|
||||||
RestartPolicy RestartPolicy // Restart policy to be used for the container
|
|
||||||
AutoRemove bool // Automatically remove container when it exits
|
|
||||||
VolumeDriver string // Name of the volume driver used to mount volumes
|
|
||||||
VolumesFrom []string // List of volumes to take from other container
|
|
||||||
ConsoleSize [2]uint // Initial console size (height,width)
|
|
||||||
|
|
||||||
// Applicable to UNIX platforms
|
|
||||||
CapAdd strslice.StrSlice // List of kernel capabilities to add to the container
|
|
||||||
CapDrop strslice.StrSlice // List of kernel capabilities to remove from the container
|
|
||||||
CgroupnsMode CgroupnsMode // Cgroup namespace mode to use for the container
|
|
||||||
DNS []string `json:"Dns"` // List of DNS server to lookup
|
|
||||||
DNSOptions []string `json:"DnsOptions"` // List of DNSOption to look for
|
|
||||||
DNSSearch []string `json:"DnsSearch"` // List of DNSSearch to look for
|
|
||||||
ExtraHosts []string // List of extra hosts
|
|
||||||
GroupAdd []string // List of additional groups that the container process will run as
|
|
||||||
IpcMode IpcMode // IPC namespace to use for the container
|
|
||||||
Cgroup CgroupSpec // Cgroup to use for the container
|
|
||||||
Links []string // List of links (in the name:alias form)
|
|
||||||
OomScoreAdj int // Container preference for OOM-killing
|
|
||||||
PidMode PidMode // PID namespace to use for the container
|
|
||||||
Privileged bool // Is the container in privileged mode
|
|
||||||
PublishAllPorts bool // Should docker publish all exposed port for the container
|
|
||||||
ReadonlyRootfs bool // Is the container root filesystem in read-only
|
|
||||||
SecurityOpt []string // List of string values to customize labels for MLS systems, such as SELinux.
|
|
||||||
StorageOpt map[string]string `json:",omitempty"` // Storage driver options per container.
|
|
||||||
Tmpfs map[string]string `json:",omitempty"` // List of tmpfs (mounts) used for the container
|
|
||||||
UTSMode UTSMode // UTS namespace to use for the container
|
|
||||||
UsernsMode UsernsMode // The user namespace to use for the container
|
|
||||||
ShmSize int64 // Total shm memory usage
|
|
||||||
Sysctls map[string]string `json:",omitempty"` // List of Namespaced sysctls used for the container
|
|
||||||
Runtime string `json:",omitempty"` // Runtime to use with this container
|
|
||||||
|
|
||||||
// Applicable to Windows
|
|
||||||
Isolation Isolation // Isolation technology of the container (e.g. default, hyperv)
|
|
||||||
|
|
||||||
// Contains container's resources (cgroups, ulimits)
|
|
||||||
Resources
|
|
||||||
|
|
||||||
// Mounts specs used by the container
|
|
||||||
Mounts []mount.Mount `json:",omitempty"`
|
|
||||||
|
|
||||||
// MaskedPaths is the list of paths to be masked inside the container (this overrides the default set of paths)
|
|
||||||
MaskedPaths []string
|
|
||||||
|
|
||||||
// ReadonlyPaths is the list of paths to be set as read-only inside the container (this overrides the default set of paths)
|
|
||||||
ReadonlyPaths []string
|
|
||||||
|
|
||||||
// Run a custom init inside the container, if null, use the daemon's configured settings
|
|
||||||
Init *bool `json:",omitempty"`
|
|
||||||
}
|
|
494
api/types/container/hostconfig.go
Normal file
494
api/types/container/hostconfig.go
Normal file
|
@ -0,0 +1,494 @@
|
||||||
|
package container // import "github.com/docker/docker/api/types/container"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/docker/docker/api/types/blkiodev"
|
||||||
|
"github.com/docker/docker/api/types/mount"
|
||||||
|
"github.com/docker/docker/api/types/network"
|
||||||
|
"github.com/docker/docker/api/types/strslice"
|
||||||
|
"github.com/docker/go-connections/nat"
|
||||||
|
units "github.com/docker/go-units"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CgroupnsMode represents the cgroup namespace mode of the container
|
||||||
|
type CgroupnsMode string
|
||||||
|
|
||||||
|
// cgroup namespace modes for containers
|
||||||
|
const (
|
||||||
|
CgroupnsModeEmpty CgroupnsMode = ""
|
||||||
|
CgroupnsModePrivate CgroupnsMode = "private"
|
||||||
|
CgroupnsModeHost CgroupnsMode = "host"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IsPrivate indicates whether the container uses its own private cgroup namespace
|
||||||
|
func (c CgroupnsMode) IsPrivate() bool {
|
||||||
|
return c == CgroupnsModePrivate
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsHost indicates whether the container shares the host's cgroup namespace
|
||||||
|
func (c CgroupnsMode) IsHost() bool {
|
||||||
|
return c == CgroupnsModeHost
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty indicates whether the container cgroup namespace mode is unset
|
||||||
|
func (c CgroupnsMode) IsEmpty() bool {
|
||||||
|
return c == CgroupnsModeEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid indicates whether the cgroup namespace mode is valid
|
||||||
|
func (c CgroupnsMode) Valid() bool {
|
||||||
|
return c.IsEmpty() || c.IsPrivate() || c.IsHost()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Isolation represents the isolation technology of a container. The supported
|
||||||
|
// values are platform specific
|
||||||
|
type Isolation string
|
||||||
|
|
||||||
|
// Isolation modes for containers
|
||||||
|
const (
|
||||||
|
IsolationEmpty Isolation = "" // IsolationEmpty is unspecified (same behavior as default)
|
||||||
|
IsolationDefault Isolation = "default" // IsolationDefault is the default isolation mode on current daemon
|
||||||
|
IsolationProcess Isolation = "process" // IsolationProcess is process isolation mode
|
||||||
|
IsolationHyperV Isolation = "hyperv" // IsolationHyperV is HyperV isolation mode
|
||||||
|
)
|
||||||
|
|
||||||
|
// IsDefault indicates the default isolation technology of a container. On Linux this
|
||||||
|
// is the native driver. On Windows, this is a Windows Server Container.
|
||||||
|
func (i Isolation) IsDefault() bool {
|
||||||
|
// TODO consider making isolation-mode strict (case-sensitive)
|
||||||
|
v := Isolation(strings.ToLower(string(i)))
|
||||||
|
return v == IsolationDefault || v == IsolationEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsHyperV indicates the use of a Hyper-V partition for isolation
|
||||||
|
func (i Isolation) IsHyperV() bool {
|
||||||
|
// TODO consider making isolation-mode strict (case-sensitive)
|
||||||
|
return Isolation(strings.ToLower(string(i))) == IsolationHyperV
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsProcess indicates the use of process isolation
|
||||||
|
func (i Isolation) IsProcess() bool {
|
||||||
|
// TODO consider making isolation-mode strict (case-sensitive)
|
||||||
|
return Isolation(strings.ToLower(string(i))) == IsolationProcess
|
||||||
|
}
|
||||||
|
|
||||||
|
// IpcMode represents the container ipc stack.
|
||||||
|
type IpcMode string
|
||||||
|
|
||||||
|
// IpcMode constants
|
||||||
|
const (
|
||||||
|
IPCModeNone IpcMode = "none"
|
||||||
|
IPCModeHost IpcMode = "host"
|
||||||
|
IPCModeContainer IpcMode = "container"
|
||||||
|
IPCModePrivate IpcMode = "private"
|
||||||
|
IPCModeShareable IpcMode = "shareable"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IsPrivate indicates whether the container uses its own private ipc namespace which can not be shared.
|
||||||
|
func (n IpcMode) IsPrivate() bool {
|
||||||
|
return n == IPCModePrivate
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsHost indicates whether the container shares the host's ipc namespace.
|
||||||
|
func (n IpcMode) IsHost() bool {
|
||||||
|
return n == IPCModeHost
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsShareable indicates whether the container's ipc namespace can be shared with another container.
|
||||||
|
func (n IpcMode) IsShareable() bool {
|
||||||
|
return n == IPCModeShareable
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsContainer indicates whether the container uses another container's ipc namespace.
|
||||||
|
func (n IpcMode) IsContainer() bool {
|
||||||
|
_, ok := containerID(string(n))
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNone indicates whether container IpcMode is set to "none".
|
||||||
|
func (n IpcMode) IsNone() bool {
|
||||||
|
return n == IPCModeNone
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty indicates whether container IpcMode is empty
|
||||||
|
func (n IpcMode) IsEmpty() bool {
|
||||||
|
return n == ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid indicates whether the ipc mode is valid.
|
||||||
|
func (n IpcMode) Valid() bool {
|
||||||
|
// TODO(thaJeztah): align with PidMode, and consider container-mode without a container name/ID to be invalid.
|
||||||
|
return n.IsEmpty() || n.IsNone() || n.IsPrivate() || n.IsHost() || n.IsShareable() || n.IsContainer()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Container returns the name of the container ipc stack is going to be used.
|
||||||
|
func (n IpcMode) Container() (idOrName string) {
|
||||||
|
idOrName, _ = containerID(string(n))
|
||||||
|
return idOrName
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkMode represents the container network stack.
|
||||||
|
type NetworkMode string
|
||||||
|
|
||||||
|
// IsNone indicates whether container isn't using a network stack.
|
||||||
|
func (n NetworkMode) IsNone() bool {
|
||||||
|
return n == network.NetworkNone
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsDefault indicates whether container uses the default network stack.
|
||||||
|
func (n NetworkMode) IsDefault() bool {
|
||||||
|
return n == network.NetworkDefault
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPrivate indicates whether container uses its private network stack.
|
||||||
|
func (n NetworkMode) IsPrivate() bool {
|
||||||
|
return !(n.IsHost() || n.IsContainer())
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsContainer indicates whether container uses a container network stack.
|
||||||
|
func (n NetworkMode) IsContainer() bool {
|
||||||
|
_, ok := containerID(string(n))
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConnectedContainer is the id of the container which network this container is connected to.
|
||||||
|
func (n NetworkMode) ConnectedContainer() (idOrName string) {
|
||||||
|
idOrName, _ = containerID(string(n))
|
||||||
|
return idOrName
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserDefined indicates user-created network
|
||||||
|
func (n NetworkMode) UserDefined() string {
|
||||||
|
if n.IsUserDefined() {
|
||||||
|
return string(n)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// UsernsMode represents userns mode in the container.
|
||||||
|
type UsernsMode string
|
||||||
|
|
||||||
|
// IsHost indicates whether the container uses the host's userns.
|
||||||
|
func (n UsernsMode) IsHost() bool {
|
||||||
|
return n == "host"
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPrivate indicates whether the container uses the a private userns.
|
||||||
|
func (n UsernsMode) IsPrivate() bool {
|
||||||
|
return !n.IsHost()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid indicates whether the userns is valid.
|
||||||
|
func (n UsernsMode) Valid() bool {
|
||||||
|
return n == "" || n.IsHost()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CgroupSpec represents the cgroup to use for the container.
|
||||||
|
type CgroupSpec string
|
||||||
|
|
||||||
|
// IsContainer indicates whether the container is using another container cgroup
|
||||||
|
func (c CgroupSpec) IsContainer() bool {
|
||||||
|
_, ok := containerID(string(c))
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid indicates whether the cgroup spec is valid.
|
||||||
|
func (c CgroupSpec) Valid() bool {
|
||||||
|
// TODO(thaJeztah): align with PidMode, and consider container-mode without a container name/ID to be invalid.
|
||||||
|
return c == "" || c.IsContainer()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Container returns the ID or name of the container whose cgroup will be used.
|
||||||
|
func (c CgroupSpec) Container() (idOrName string) {
|
||||||
|
idOrName, _ = containerID(string(c))
|
||||||
|
return idOrName
|
||||||
|
}
|
||||||
|
|
||||||
|
// UTSMode represents the UTS namespace of the container.
|
||||||
|
type UTSMode string
|
||||||
|
|
||||||
|
// IsPrivate indicates whether the container uses its private UTS namespace.
|
||||||
|
func (n UTSMode) IsPrivate() bool {
|
||||||
|
return !n.IsHost()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsHost indicates whether the container uses the host's UTS namespace.
|
||||||
|
func (n UTSMode) IsHost() bool {
|
||||||
|
return n == "host"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid indicates whether the UTS namespace is valid.
|
||||||
|
func (n UTSMode) Valid() bool {
|
||||||
|
return n == "" || n.IsHost()
|
||||||
|
}
|
||||||
|
|
||||||
|
// PidMode represents the pid namespace of the container.
|
||||||
|
type PidMode string
|
||||||
|
|
||||||
|
// IsPrivate indicates whether the container uses its own new pid namespace.
|
||||||
|
func (n PidMode) IsPrivate() bool {
|
||||||
|
return !(n.IsHost() || n.IsContainer())
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsHost indicates whether the container uses the host's pid namespace.
|
||||||
|
func (n PidMode) IsHost() bool {
|
||||||
|
return n == "host"
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsContainer indicates whether the container uses a container's pid namespace.
|
||||||
|
func (n PidMode) IsContainer() bool {
|
||||||
|
_, ok := containerID(string(n))
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid indicates whether the pid namespace is valid.
|
||||||
|
func (n PidMode) Valid() bool {
|
||||||
|
return n == "" || n.IsHost() || validContainer(string(n))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Container returns the name of the container whose pid namespace is going to be used.
|
||||||
|
func (n PidMode) Container() (idOrName string) {
|
||||||
|
idOrName, _ = containerID(string(n))
|
||||||
|
return idOrName
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeviceRequest represents a request for devices from a device driver.
|
||||||
|
// Used by GPU device drivers.
|
||||||
|
type DeviceRequest struct {
|
||||||
|
Driver string // Name of device driver
|
||||||
|
Count int // Number of devices to request (-1 = All)
|
||||||
|
DeviceIDs []string // List of device IDs as recognizable by the device driver
|
||||||
|
Capabilities [][]string // An OR list of AND lists of device capabilities (e.g. "gpu")
|
||||||
|
Options map[string]string // Options to pass onto the device driver
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeviceMapping represents the device mapping between the host and the container.
|
||||||
|
type DeviceMapping struct {
|
||||||
|
PathOnHost string
|
||||||
|
PathInContainer string
|
||||||
|
CgroupPermissions string
|
||||||
|
}
|
||||||
|
|
||||||
|
// RestartPolicy represents the restart policies of the container.
|
||||||
|
type RestartPolicy struct {
|
||||||
|
Name RestartPolicyMode
|
||||||
|
MaximumRetryCount int
|
||||||
|
}
|
||||||
|
|
||||||
|
type RestartPolicyMode string
|
||||||
|
|
||||||
|
const (
|
||||||
|
RestartPolicyDisabled RestartPolicyMode = "no"
|
||||||
|
RestartPolicyAlways RestartPolicyMode = "always"
|
||||||
|
RestartPolicyOnFailure RestartPolicyMode = "on-failure"
|
||||||
|
RestartPolicyUnlessStopped RestartPolicyMode = "unless-stopped"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IsNone indicates whether the container has the "no" restart policy.
|
||||||
|
// This means the container will not automatically restart when exiting.
|
||||||
|
func (rp *RestartPolicy) IsNone() bool {
|
||||||
|
return rp.Name == RestartPolicyDisabled || rp.Name == ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsAlways indicates whether the container has the "always" restart policy.
|
||||||
|
// This means the container will automatically restart regardless of the exit status.
|
||||||
|
func (rp *RestartPolicy) IsAlways() bool {
|
||||||
|
return rp.Name == RestartPolicyAlways
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsOnFailure indicates whether the container has the "on-failure" restart policy.
|
||||||
|
// This means the container will automatically restart of exiting with a non-zero exit status.
|
||||||
|
func (rp *RestartPolicy) IsOnFailure() bool {
|
||||||
|
return rp.Name == RestartPolicyOnFailure
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsUnlessStopped indicates whether the container has the
|
||||||
|
// "unless-stopped" restart policy. This means the container will
|
||||||
|
// automatically restart unless user has put it to stopped state.
|
||||||
|
func (rp *RestartPolicy) IsUnlessStopped() bool {
|
||||||
|
return rp.Name == RestartPolicyUnlessStopped
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSame compares two RestartPolicy to see if they are the same
|
||||||
|
func (rp *RestartPolicy) IsSame(tp *RestartPolicy) bool {
|
||||||
|
return rp.Name == tp.Name && rp.MaximumRetryCount == tp.MaximumRetryCount
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateRestartPolicy validates the given RestartPolicy.
|
||||||
|
func ValidateRestartPolicy(policy RestartPolicy) error {
|
||||||
|
switch policy.Name {
|
||||||
|
case RestartPolicyAlways, RestartPolicyUnlessStopped, RestartPolicyDisabled:
|
||||||
|
if policy.MaximumRetryCount != 0 {
|
||||||
|
msg := "invalid restart policy: maximum retry count can only be used with 'on-failure'"
|
||||||
|
if policy.MaximumRetryCount < 0 {
|
||||||
|
msg += " and cannot be negative"
|
||||||
|
}
|
||||||
|
return &errInvalidParameter{fmt.Errorf(msg)}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
case RestartPolicyOnFailure:
|
||||||
|
if policy.MaximumRetryCount < 0 {
|
||||||
|
return &errInvalidParameter{fmt.Errorf("invalid restart policy: maximum retry count cannot be negative")}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
case "":
|
||||||
|
// Versions before v25.0.0 created an empty restart-policy "name" as
|
||||||
|
// default. Allow an empty name with "any" MaximumRetryCount for
|
||||||
|
// backward-compatibility.
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return &errInvalidParameter{fmt.Errorf("invalid restart policy: unknown policy '%s'; use one of '%s', '%s', '%s', or '%s'", policy.Name, RestartPolicyDisabled, RestartPolicyAlways, RestartPolicyOnFailure, RestartPolicyUnlessStopped)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LogMode is a type to define the available modes for logging
|
||||||
|
// These modes affect how logs are handled when log messages start piling up.
|
||||||
|
type LogMode string
|
||||||
|
|
||||||
|
// Available logging modes
|
||||||
|
const (
|
||||||
|
LogModeUnset LogMode = ""
|
||||||
|
LogModeBlocking LogMode = "blocking"
|
||||||
|
LogModeNonBlock LogMode = "non-blocking"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LogConfig represents the logging configuration of the container.
|
||||||
|
type LogConfig struct {
|
||||||
|
Type string
|
||||||
|
Config map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resources contains container's resources (cgroups config, ulimits...)
|
||||||
|
type Resources struct {
|
||||||
|
// Applicable to all platforms
|
||||||
|
CPUShares int64 `json:"CpuShares"` // CPU shares (relative weight vs. other containers)
|
||||||
|
Memory int64 // Memory limit (in bytes)
|
||||||
|
NanoCPUs int64 `json:"NanoCpus"` // CPU quota in units of 10<sup>-9</sup> CPUs.
|
||||||
|
|
||||||
|
// Applicable to UNIX platforms
|
||||||
|
CgroupParent string // Parent cgroup.
|
||||||
|
BlkioWeight uint16 // Block IO weight (relative weight vs. other containers)
|
||||||
|
BlkioWeightDevice []*blkiodev.WeightDevice
|
||||||
|
BlkioDeviceReadBps []*blkiodev.ThrottleDevice
|
||||||
|
BlkioDeviceWriteBps []*blkiodev.ThrottleDevice
|
||||||
|
BlkioDeviceReadIOps []*blkiodev.ThrottleDevice
|
||||||
|
BlkioDeviceWriteIOps []*blkiodev.ThrottleDevice
|
||||||
|
CPUPeriod int64 `json:"CpuPeriod"` // CPU CFS (Completely Fair Scheduler) period
|
||||||
|
CPUQuota int64 `json:"CpuQuota"` // CPU CFS (Completely Fair Scheduler) quota
|
||||||
|
CPURealtimePeriod int64 `json:"CpuRealtimePeriod"` // CPU real-time period
|
||||||
|
CPURealtimeRuntime int64 `json:"CpuRealtimeRuntime"` // CPU real-time runtime
|
||||||
|
CpusetCpus string // CpusetCpus 0-2, 0,1
|
||||||
|
CpusetMems string // CpusetMems 0-2, 0,1
|
||||||
|
Devices []DeviceMapping // List of devices to map inside the container
|
||||||
|
DeviceCgroupRules []string // List of rule to be added to the device cgroup
|
||||||
|
DeviceRequests []DeviceRequest // List of device requests for device drivers
|
||||||
|
|
||||||
|
// KernelMemory specifies the kernel memory limit (in bytes) for the container.
|
||||||
|
// Deprecated: kernel 5.4 deprecated kmem.limit_in_bytes.
|
||||||
|
KernelMemory int64 `json:",omitempty"`
|
||||||
|
KernelMemoryTCP int64 `json:",omitempty"` // Hard limit for kernel TCP buffer memory (in bytes)
|
||||||
|
MemoryReservation int64 // Memory soft limit (in bytes)
|
||||||
|
MemorySwap int64 // Total memory usage (memory + swap); set `-1` to enable unlimited swap
|
||||||
|
MemorySwappiness *int64 // Tuning container memory swappiness behaviour
|
||||||
|
OomKillDisable *bool // Whether to disable OOM Killer or not
|
||||||
|
PidsLimit *int64 // Setting PIDs limit for a container; Set `0` or `-1` for unlimited, or `null` to not change.
|
||||||
|
Ulimits []*units.Ulimit // List of ulimits to be set in the container
|
||||||
|
|
||||||
|
// Applicable to Windows
|
||||||
|
CPUCount int64 `json:"CpuCount"` // CPU count
|
||||||
|
CPUPercent int64 `json:"CpuPercent"` // CPU percent
|
||||||
|
IOMaximumIOps uint64 // Maximum IOps for the container system drive
|
||||||
|
IOMaximumBandwidth uint64 // Maximum IO in bytes per second for the container system drive
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateConfig holds the mutable attributes of a Container.
|
||||||
|
// Those attributes can be updated at runtime.
|
||||||
|
type UpdateConfig struct {
|
||||||
|
// Contains container's resources (cgroups, ulimits)
|
||||||
|
Resources
|
||||||
|
RestartPolicy RestartPolicy
|
||||||
|
}
|
||||||
|
|
||||||
|
// HostConfig the non-portable Config structure of a container.
|
||||||
|
// Here, "non-portable" means "dependent of the host we are running on".
|
||||||
|
// Portable information *should* appear in Config.
|
||||||
|
type HostConfig struct {
|
||||||
|
// Applicable to all platforms
|
||||||
|
Binds []string // List of volume bindings for this container
|
||||||
|
ContainerIDFile string // File (path) where the containerId is written
|
||||||
|
LogConfig LogConfig // Configuration of the logs for this container
|
||||||
|
NetworkMode NetworkMode // Network mode to use for the container
|
||||||
|
PortBindings nat.PortMap // Port mapping between the exposed port (container) and the host
|
||||||
|
RestartPolicy RestartPolicy // Restart policy to be used for the container
|
||||||
|
AutoRemove bool // Automatically remove container when it exits
|
||||||
|
VolumeDriver string // Name of the volume driver used to mount volumes
|
||||||
|
VolumesFrom []string // List of volumes to take from other container
|
||||||
|
ConsoleSize [2]uint // Initial console size (height,width)
|
||||||
|
Annotations map[string]string `json:",omitempty"` // Arbitrary non-identifying metadata attached to container and provided to the runtime
|
||||||
|
|
||||||
|
// Applicable to UNIX platforms
|
||||||
|
CapAdd strslice.StrSlice // List of kernel capabilities to add to the container
|
||||||
|
CapDrop strslice.StrSlice // List of kernel capabilities to remove from the container
|
||||||
|
CgroupnsMode CgroupnsMode // Cgroup namespace mode to use for the container
|
||||||
|
DNS []string `json:"Dns"` // List of DNS server to lookup
|
||||||
|
DNSOptions []string `json:"DnsOptions"` // List of DNSOption to look for
|
||||||
|
DNSSearch []string `json:"DnsSearch"` // List of DNSSearch to look for
|
||||||
|
ExtraHosts []string // List of extra hosts
|
||||||
|
GroupAdd []string // List of additional groups that the container process will run as
|
||||||
|
IpcMode IpcMode // IPC namespace to use for the container
|
||||||
|
Cgroup CgroupSpec // Cgroup to use for the container
|
||||||
|
Links []string // List of links (in the name:alias form)
|
||||||
|
OomScoreAdj int // Container preference for OOM-killing
|
||||||
|
PidMode PidMode // PID namespace to use for the container
|
||||||
|
Privileged bool // Is the container in privileged mode
|
||||||
|
PublishAllPorts bool // Should docker publish all exposed port for the container
|
||||||
|
ReadonlyRootfs bool // Is the container root filesystem in read-only
|
||||||
|
SecurityOpt []string // List of string values to customize labels for MLS systems, such as SELinux.
|
||||||
|
StorageOpt map[string]string `json:",omitempty"` // Storage driver options per container.
|
||||||
|
Tmpfs map[string]string `json:",omitempty"` // List of tmpfs (mounts) used for the container
|
||||||
|
UTSMode UTSMode // UTS namespace to use for the container
|
||||||
|
UsernsMode UsernsMode // The user namespace to use for the container
|
||||||
|
ShmSize int64 // Total shm memory usage
|
||||||
|
Sysctls map[string]string `json:",omitempty"` // List of Namespaced sysctls used for the container
|
||||||
|
Runtime string `json:",omitempty"` // Runtime to use with this container
|
||||||
|
|
||||||
|
// Applicable to Windows
|
||||||
|
Isolation Isolation // Isolation technology of the container (e.g. default, hyperv)
|
||||||
|
|
||||||
|
// Contains container's resources (cgroups, ulimits)
|
||||||
|
Resources
|
||||||
|
|
||||||
|
// Mounts specs used by the container
|
||||||
|
Mounts []mount.Mount `json:",omitempty"`
|
||||||
|
|
||||||
|
// MaskedPaths is the list of paths to be masked inside the container (this overrides the default set of paths)
|
||||||
|
MaskedPaths []string
|
||||||
|
|
||||||
|
// ReadonlyPaths is the list of paths to be set as read-only inside the container (this overrides the default set of paths)
|
||||||
|
ReadonlyPaths []string
|
||||||
|
|
||||||
|
// Run a custom init inside the container, if null, use the daemon's configured settings
|
||||||
|
Init *bool `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// containerID splits "container:<ID|name>" values. It returns the container
|
||||||
|
// ID or name, and whether an ID/name was found. It returns an empty string and
|
||||||
|
// a "false" if the value does not have a "container:" prefix. Further validation
|
||||||
|
// of the returned, including checking if the value is empty, should be handled
|
||||||
|
// by the caller.
|
||||||
|
func containerID(val string) (idOrName string, ok bool) {
|
||||||
|
k, v, hasSep := strings.Cut(val, ":")
|
||||||
|
if !hasSep || k != "container" {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
return v, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// validContainer checks if the given value is a "container:" mode with
|
||||||
|
// a non-empty name/ID.
|
||||||
|
func validContainer(val string) bool {
|
||||||
|
id, ok := containerID(val)
|
||||||
|
return ok && id != ""
|
||||||
|
}
|
105
api/types/container/hostconfig_test.go
Normal file
105
api/types/container/hostconfig_test.go
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
package container
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/docker/docker/errdefs"
|
||||||
|
"gotest.tools/v3/assert"
|
||||||
|
is "gotest.tools/v3/assert/cmp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestValidateRestartPolicy(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
input RestartPolicy
|
||||||
|
expectedErr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "empty",
|
||||||
|
input: RestartPolicy{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty with invalid MaxRestartCount (for backward compatibility)",
|
||||||
|
input: RestartPolicy{MaximumRetryCount: 123},
|
||||||
|
expectedErr: "", // Allowed for backward compatibility
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty with negative MaxRestartCount)",
|
||||||
|
input: RestartPolicy{MaximumRetryCount: -123},
|
||||||
|
expectedErr: "", // Allowed for backward compatibility
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "always",
|
||||||
|
input: RestartPolicy{Name: RestartPolicyAlways},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "always with MaxRestartCount",
|
||||||
|
input: RestartPolicy{Name: RestartPolicyAlways, MaximumRetryCount: 123},
|
||||||
|
expectedErr: "invalid restart policy: maximum retry count can only be used with 'on-failure'",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "always with negative MaxRestartCount",
|
||||||
|
input: RestartPolicy{Name: RestartPolicyAlways, MaximumRetryCount: -123},
|
||||||
|
expectedErr: "invalid restart policy: maximum retry count can only be used with 'on-failure' and cannot be negative",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unless-stopped",
|
||||||
|
input: RestartPolicy{Name: RestartPolicyUnlessStopped},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unless-stopped with MaxRestartCount",
|
||||||
|
input: RestartPolicy{Name: RestartPolicyUnlessStopped, MaximumRetryCount: 123},
|
||||||
|
expectedErr: "invalid restart policy: maximum retry count can only be used with 'on-failure'",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unless-stopped with negative MaxRestartCount",
|
||||||
|
input: RestartPolicy{Name: RestartPolicyUnlessStopped, MaximumRetryCount: -123},
|
||||||
|
expectedErr: "invalid restart policy: maximum retry count can only be used with 'on-failure' and cannot be negative",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "disabled",
|
||||||
|
input: RestartPolicy{Name: RestartPolicyDisabled},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "disabled with MaxRestartCount",
|
||||||
|
input: RestartPolicy{Name: RestartPolicyDisabled, MaximumRetryCount: 123},
|
||||||
|
expectedErr: "invalid restart policy: maximum retry count can only be used with 'on-failure'",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "disabled with negative MaxRestartCount",
|
||||||
|
input: RestartPolicy{Name: RestartPolicyDisabled, MaximumRetryCount: -123},
|
||||||
|
expectedErr: "invalid restart policy: maximum retry count can only be used with 'on-failure' and cannot be negative",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "on-failure",
|
||||||
|
input: RestartPolicy{Name: RestartPolicyOnFailure},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "on-failure with MaxRestartCount",
|
||||||
|
input: RestartPolicy{Name: RestartPolicyOnFailure, MaximumRetryCount: 123},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "on-failure with negative MaxRestartCount",
|
||||||
|
input: RestartPolicy{Name: RestartPolicyOnFailure, MaximumRetryCount: -123},
|
||||||
|
expectedErr: "invalid restart policy: maximum retry count cannot be negative",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unknown policy",
|
||||||
|
input: RestartPolicy{Name: "unknown"},
|
||||||
|
expectedErr: "invalid restart policy: unknown policy 'unknown'; use one of 'no', 'always', 'on-failure', or 'unless-stopped'",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
tc := tc
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
err := ValidateRestartPolicy(tc.input)
|
||||||
|
if tc.expectedErr == "" {
|
||||||
|
assert.Check(t, err)
|
||||||
|
} else {
|
||||||
|
assert.Check(t, is.ErrorType(err, errdefs.IsInvalidParameter))
|
||||||
|
assert.Check(t, is.Error(err, tc.expectedErr))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,9 @@
|
||||||
//go:build !windows
|
//go:build !windows
|
||||||
// +build !windows
|
|
||||||
|
|
||||||
package container // import "github.com/docker/docker/api/types/container"
|
package container // import "github.com/docker/docker/api/types/container"
|
||||||
|
|
||||||
|
import "github.com/docker/docker/api/types/network"
|
||||||
|
|
||||||
// IsValid indicates if an isolation technology is valid
|
// IsValid indicates if an isolation technology is valid
|
||||||
func (i Isolation) IsValid() bool {
|
func (i Isolation) IsValid() bool {
|
||||||
return i.IsDefault()
|
return i.IsDefault()
|
||||||
|
@ -11,15 +12,15 @@ func (i Isolation) IsValid() bool {
|
||||||
// NetworkName returns the name of the network stack.
|
// NetworkName returns the name of the network stack.
|
||||||
func (n NetworkMode) NetworkName() string {
|
func (n NetworkMode) NetworkName() string {
|
||||||
if n.IsBridge() {
|
if n.IsBridge() {
|
||||||
return "bridge"
|
return network.NetworkBridge
|
||||||
} else if n.IsHost() {
|
} else if n.IsHost() {
|
||||||
return "host"
|
return network.NetworkHost
|
||||||
} else if n.IsContainer() {
|
} else if n.IsContainer() {
|
||||||
return "container"
|
return "container"
|
||||||
} else if n.IsNone() {
|
} else if n.IsNone() {
|
||||||
return "none"
|
return network.NetworkNone
|
||||||
} else if n.IsDefault() {
|
} else if n.IsDefault() {
|
||||||
return "default"
|
return network.NetworkDefault
|
||||||
} else if n.IsUserDefined() {
|
} else if n.IsUserDefined() {
|
||||||
return n.UserDefined()
|
return n.UserDefined()
|
||||||
}
|
}
|
||||||
|
@ -28,12 +29,12 @@ func (n NetworkMode) NetworkName() string {
|
||||||
|
|
||||||
// IsBridge indicates whether container uses the bridge network stack
|
// IsBridge indicates whether container uses the bridge network stack
|
||||||
func (n NetworkMode) IsBridge() bool {
|
func (n NetworkMode) IsBridge() bool {
|
||||||
return n == "bridge"
|
return n == network.NetworkBridge
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsHost indicates whether container uses the host network stack.
|
// IsHost indicates whether container uses the host network stack.
|
||||||
func (n NetworkMode) IsHost() bool {
|
func (n NetworkMode) IsHost() bool {
|
||||||
return n == "host"
|
return n == network.NetworkHost
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsUserDefined indicates user-created network
|
// IsUserDefined indicates user-created network
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue