mirror of
https://github.com/moby/moby.git
synced 2026-01-14 03:08:07 +00:00
Compare commits
479 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45873be4ae | ||
|
|
7994426e61 | ||
|
|
f144264bae | ||
|
|
768cfaeb62 | ||
|
|
d3289dda4b | ||
|
|
7a0bf747f5 | ||
|
|
b43afbf898 | ||
|
|
c299ba3b38 | ||
|
|
0e2cc22d36 | ||
|
|
e37efd4c2d | ||
|
|
1d6b471ce2 | ||
|
|
5cc94a552d | ||
|
|
8330a083d5 | ||
|
|
dc519a0f18 | ||
|
|
148a19b6d6 | ||
|
|
0ab8108b57 | ||
|
|
21a165de23 | ||
|
|
637e8142ce | ||
|
|
37caf3881a | ||
|
|
08768e4d9d | ||
|
|
416dc8c1bf | ||
|
|
8803b58259 | ||
|
|
dcf253ffe2 | ||
|
|
8561016335 | ||
|
|
f06c450a8e | ||
|
|
528f2284ee | ||
|
|
14852fcd82 | ||
|
|
a1a789dbd0 | ||
|
|
6ee53a6831 | ||
|
|
083ccfa486 | ||
|
|
55da8ea276 | ||
|
|
364d8d8b31 | ||
|
|
415fc7b41e | ||
|
|
f0eaf228c1 | ||
|
|
f98b7005d2 | ||
|
|
048199f191 | ||
|
|
5d7550e9ef | ||
|
|
d188df0039 | ||
|
|
0317f773a6 | ||
|
|
7ea613d780 | ||
|
|
e48ea1c6e0 | ||
|
|
f9f0db0789 | ||
|
|
7ea0e60dde | ||
|
|
0d6e7cd983 | ||
|
|
9866738736 | ||
|
|
b6d76eb572 | ||
|
|
3bdf99d127 | ||
|
|
458e69fc2e | ||
|
|
67535a4454 | ||
|
|
034298520b | ||
|
|
4da3b4bf2d | ||
|
|
f5f3be4f9a | ||
|
|
da92a28a53 | ||
|
|
339be4e2ae | ||
|
|
26db31fdab | ||
|
|
588a05a1ce | ||
|
|
94daa36f03 | ||
|
|
a9649e7a5d | ||
|
|
cd2702e04e | ||
|
|
01fec904e4 | ||
|
|
d0ad1357a1 | ||
|
|
072483f9d7 | ||
|
|
30da69d694 | ||
|
|
acf6b6542e | ||
|
|
871675be9b | ||
|
|
153b16ad27 | ||
|
|
536b35299b | ||
|
|
d15f59243a | ||
|
|
d7cca3f997 | ||
|
|
4dc961d0e9 | ||
|
|
0ec3278d48 | ||
|
|
6aa8288cfb | ||
|
|
b1c0bfa225 | ||
|
|
e03ac1fad9 | ||
|
|
a5a3a74a79 | ||
|
|
7263ae74cd | ||
|
|
158c04fac8 | ||
|
|
6021139a9f | ||
|
|
888cbfddf2 | ||
|
|
42970fc461 | ||
|
|
926a4dd23c | ||
|
|
979f18691a | ||
|
|
32c5774524 | ||
|
|
56d5a46c0f | ||
|
|
c6b9bb00f9 | ||
|
|
f4ffeb8c38 | ||
|
|
dddc943a6a | ||
|
|
560299a16f | ||
|
|
b3160e88bf | ||
|
|
7148c6a5f5 | ||
|
|
b590eff717 | ||
|
|
e354e42e14 | ||
|
|
0facb0cd63 | ||
|
|
61a1a297c0 | ||
|
|
94b5e85c10 | ||
|
|
a2ada6b258 | ||
|
|
894244cc37 | ||
|
|
2c57455339 | ||
|
|
a3ce441ae0 | ||
|
|
86187b2606 | ||
|
|
a3bee4156f | ||
|
|
e8c269843c | ||
|
|
a9ec07a005 | ||
|
|
8601b22f5d | ||
|
|
dfcf95540f | ||
|
|
e655763837 | ||
|
|
6bde39b729 | ||
|
|
144363fea2 | ||
|
|
6cd9eaf5ab | ||
|
|
68a8a8f3c8 | ||
|
|
0b4495463f | ||
|
|
ad4a3d32c6 | ||
|
|
df96159df0 | ||
|
|
7e8b26ecb9 | ||
|
|
2356f435a6 | ||
|
|
4a830df491 | ||
|
|
8f2bf4aef5 | ||
|
|
a1035ec59b | ||
|
|
370b7e65fc | ||
|
|
27e64d3bdb | ||
|
|
f030c7bf10 | ||
|
|
c75ca8ef10 | ||
|
|
eafa2266f6 | ||
|
|
685fa0bb91 | ||
|
|
bb41e5a32e | ||
|
|
cbeec12d12 | ||
|
|
9319fefe35 | ||
|
|
cf11cd1aac | ||
|
|
0b1c7a8306 | ||
|
|
31d62930f7 | ||
|
|
5ad0867236 | ||
|
|
7e8f630bec | ||
|
|
f008d85edc | ||
|
|
b13528522a | ||
|
|
7937f0846c | ||
|
|
7f4bf1229a | ||
|
|
02fe3a8dd1 | ||
|
|
5e8fd897e1 | ||
|
|
9432eff6bc | ||
|
|
adf7ecc366 | ||
|
|
b781699ee2 | ||
|
|
d8ee5caf9a | ||
|
|
a6cd40de6b | ||
|
|
3658dae265 | ||
|
|
2e65796c86 | ||
|
|
44f30261da | ||
|
|
832efcd672 | ||
|
|
88453254af | ||
|
|
047343d070 | ||
|
|
6402a106e7 | ||
|
|
043c7fa539 | ||
|
|
a8ed3bd734 | ||
|
|
c88f921331 | ||
|
|
051dae4fdc | ||
|
|
cae3ccd34b | ||
|
|
bfc684d3f7 | ||
|
|
19f3259093 | ||
|
|
a411a39be0 | ||
|
|
23117afca8 | ||
|
|
3d1e4d9002 | ||
|
|
94e84169ec | ||
|
|
bb7dbaafcd | ||
|
|
4b9f0707a0 | ||
|
|
71862f3303 | ||
|
|
6505d3877c | ||
|
|
b45aa469ca | ||
|
|
ede73684c4 | ||
|
|
2ff42e192f | ||
|
|
48733b0751 | ||
|
|
81116f75de | ||
|
|
e190fdf286 | ||
|
|
114b8a4fa9 | ||
|
|
7130cd4f16 | ||
|
|
7c09fa25fd | ||
|
|
a891e4e3e1 | ||
|
|
2a96d2eb8d | ||
|
|
c1b2be0399 | ||
|
|
9095698a5c | ||
|
|
f95a7c47e8 | ||
|
|
b70b496505 | ||
|
|
23bbfea718 | ||
|
|
6d7a370fe5 | ||
|
|
eefe68a37c | ||
|
|
7aa7369f1f | ||
|
|
c04dec1143 | ||
|
|
bcc7954343 | ||
|
|
242985bcfc | ||
|
|
a022e916c8 | ||
|
|
fd1a78e0a3 | ||
|
|
994d2800c1 | ||
|
|
63bcfab0ed | ||
|
|
66dab7ac65 | ||
|
|
4cecce03f6 | ||
|
|
07466d2e9b | ||
|
|
5919ab26f0 | ||
|
|
e7ccfae846 | ||
|
|
702d19e2c2 | ||
|
|
d5c370dee6 | ||
|
|
9d1b069a4b | ||
|
|
270a4d41dc | ||
|
|
205ba05feb | ||
|
|
49e43afb47 | ||
|
|
23fa0ae74a | ||
|
|
fadb571106 | ||
|
|
5c16f2d091 | ||
|
|
a90a9d899b | ||
|
|
f1bb44aeee | ||
|
|
ba2ddd75e4 | ||
|
|
f07242f6d7 | ||
|
|
2c5f8c51c5 | ||
|
|
2438415cb8 | ||
|
|
3ded7b97d0 | ||
|
|
68e025a11b | ||
|
|
493662ddd3 | ||
|
|
7bc6fd09da | ||
|
|
a6ad2f2157 | ||
|
|
8cb41620fd | ||
|
|
76b24759f0 | ||
|
|
7a7d72e874 | ||
|
|
8e57a019dc | ||
|
|
b87aecc50a | ||
|
|
c4dc09eac1 | ||
|
|
c2348c9fc3 | ||
|
|
b3ed54db81 | ||
|
|
7b5d2b4ec3 | ||
|
|
3d1cfb4de0 | ||
|
|
c9b01e0c4c | ||
|
|
2e25c2b14f | ||
|
|
61646c8bfc | ||
|
|
2154b9c646 | ||
|
|
350bb5197a | ||
|
|
06afbe9618 | ||
|
|
976f855f68 | ||
|
|
c3f484dada | ||
|
|
eeba428939 | ||
|
|
9f1e3ae306 | ||
|
|
1028b123e8 | ||
|
|
a3aea15257 | ||
|
|
ada8bc3695 | ||
|
|
c68671d908 | ||
|
|
ba0ad9e80f | ||
|
|
a7ef4a208d | ||
|
|
854f3f62db | ||
|
|
44b653ef99 | ||
|
|
e477df3b31 | ||
|
|
3bbdda696d | ||
|
|
b811829595 | ||
|
|
294f0c36e4 | ||
|
|
d42d79dceb | ||
|
|
10ac996d64 | ||
|
|
0d6d4456ea | ||
|
|
7828a65aeb | ||
|
|
3af89f31f6 | ||
|
|
8b6d6b9ad5 | ||
|
|
d89cd570f0 | ||
|
|
17702d9dcb | ||
|
|
37259540e9 | ||
|
|
daeb080ff1 | ||
|
|
ea2e147c4c | ||
|
|
cb38cc0fdd | ||
|
|
e824fed281 | ||
|
|
99368eeba2 | ||
|
|
02e800dcbb | ||
|
|
57b27f2e9e | ||
|
|
08c5ebe040 | ||
|
|
239bf178b8 | ||
|
|
f84694ebdc | ||
|
|
24f305b666 | ||
|
|
23825bc1fd | ||
|
|
4b6a9d23af | ||
|
|
4c189b8fe8 | ||
|
|
ea37a1f040 | ||
|
|
900bd88848 | ||
|
|
46baf7deb0 | ||
|
|
1b4ba20708 | ||
|
|
735ccfbc6f | ||
|
|
72a11b84d4 | ||
|
|
b38f73afe3 | ||
|
|
d44b2e4bd7 | ||
|
|
4a00ce10fa | ||
|
|
1cf7d7ea4b | ||
|
|
e991c7185d | ||
|
|
89ee292709 | ||
|
|
7979b3d46b | ||
|
|
7dae7c54dd | ||
|
|
c8db8ca6b2 | ||
|
|
31e992cccd | ||
|
|
97be6333e6 | ||
|
|
56ad941564 | ||
|
|
dc1d23c646 | ||
|
|
4b9092aa27 | ||
|
|
62694ab30c | ||
|
|
9b19172c7f | ||
|
|
f848191e40 | ||
|
|
6f477852a1 | ||
|
|
7957a28859 | ||
|
|
fe403362b4 | ||
|
|
0bd82bfac2 | ||
|
|
df662ebc59 | ||
|
|
f9c4601760 | ||
|
|
6ac3afe483 | ||
|
|
986988a394 | ||
|
|
3606712e2d | ||
|
|
fe2d323c82 | ||
|
|
79b1b561a3 | ||
|
|
e67b6bfc69 | ||
|
|
943dfa985d | ||
|
|
0b169d34e4 | ||
|
|
154230cdd7 | ||
|
|
962fd8bc41 | ||
|
|
cfdfbfab9b | ||
|
|
152db74d96 | ||
|
|
f87dcbe350 | ||
|
|
6981aad790 | ||
|
|
d1c58bdbbe | ||
|
|
1b317b0323 | ||
|
|
e205701266 | ||
|
|
49a0770c7a | ||
|
|
69ee71225e | ||
|
|
1244685329 | ||
|
|
1b1a5a6878 | ||
|
|
84ef7e4899 | ||
|
|
4c4810e5d2 | ||
|
|
dacf445614 | ||
|
|
697c17ca95 | ||
|
|
90ec2c209b | ||
|
|
e3f9edd348 | ||
|
|
ec65f2d21b | ||
|
|
d71afd73bf | ||
|
|
d0af7c3c08 | ||
|
|
b0777be89e | ||
|
|
3cbb1ae736 | ||
|
|
44843d9917 | ||
|
|
a9bf151260 | ||
|
|
92e497b9dc | ||
|
|
aef409dfb2 | ||
|
|
453c165be7 | ||
|
|
9eec936eb0 | ||
|
|
d3579b9582 | ||
|
|
9315b15dc6 | ||
|
|
70139978d3 | ||
|
|
9e9b6cc42e | ||
|
|
27bf320a72 | ||
|
|
98fa4bcfeb | ||
|
|
95af77d038 | ||
|
|
f770f6c5ec | ||
|
|
a88c49f38e | ||
|
|
4f9214c156 | ||
|
|
be54c79d9c | ||
|
|
2cce9a51ca | ||
|
|
e2e7f9964f | ||
|
|
b0711d5fe9 | ||
|
|
7d8df25d16 | ||
|
|
fef139ccc1 | ||
|
|
e547b63e1a | ||
|
|
4ae3705d06 | ||
|
|
ef15c13611 | ||
|
|
6f3ccaf311 | ||
|
|
5e1171a508 | ||
|
|
76adb8f5c3 | ||
|
|
fa23123741 | ||
|
|
44a3453d73 | ||
|
|
c16caabe36 | ||
|
|
a94643a1b3 | ||
|
|
fb4e0bcd2a | ||
|
|
33f5b9e963 | ||
|
|
c129c0fa9f | ||
|
|
5d8192fcce | ||
|
|
9aa66be7ec | ||
|
|
a79d081aa5 | ||
|
|
b0e8932009 | ||
|
|
19ccb75c62 | ||
|
|
9ed975a247 | ||
|
|
3e586094fc | ||
|
|
2145cf6309 | ||
|
|
6da1ff6bf9 | ||
|
|
692610414a | ||
|
|
0fcd23ec13 | ||
|
|
4c57ffaca7 | ||
|
|
eef5c75276 | ||
|
|
7edd83a1b3 | ||
|
|
7dbe2f1fb6 | ||
|
|
357b136ee9 | ||
|
|
f831618e5b | ||
|
|
f633e8f03f | ||
|
|
190ad0610d | ||
|
|
ba15bbc422 | ||
|
|
48220008d8 | ||
|
|
088c180a9e | ||
|
|
dc79403f7b | ||
|
|
8d5177b229 | ||
|
|
533f0a0f75 | ||
|
|
9b62592bfe | ||
|
|
9ee1716c41 | ||
|
|
bf8673db87 | ||
|
|
1437cf558e | ||
|
|
d6b2aec809 | ||
|
|
029f267d9b | ||
|
|
fdbf246889 | ||
|
|
b0f93d5283 | ||
|
|
ab8e3da82c | ||
|
|
d17a62592f | ||
|
|
f193ff1317 | ||
|
|
e4bf3995d7 | ||
|
|
91f6e00ffa | ||
|
|
fac076ccf9 | ||
|
|
7868d3ee3e | ||
|
|
100102108b | ||
|
|
878de14c8d | ||
|
|
11f65b566d | ||
|
|
ea7152e493 | ||
|
|
4b41198e3c | ||
|
|
2b869baea3 | ||
|
|
88f6dd72e5 | ||
|
|
3b4e21081f | ||
|
|
35167dc616 | ||
|
|
bb57656932 | ||
|
|
5416f2d57c | ||
|
|
f38b1fa30d | ||
|
|
c025dd74f0 | ||
|
|
49d5b2cc8e | ||
|
|
3f2296cfc1 | ||
|
|
1e4bb14bcd | ||
|
|
c690e0076a | ||
|
|
91473ce253 | ||
|
|
c5031c8632 | ||
|
|
890d48de19 | ||
|
|
19e79906cb | ||
|
|
50a856157c | ||
|
|
eee14cff72 | ||
|
|
5749bc242a | ||
|
|
b54a038bec | ||
|
|
82fc83ec41 | ||
|
|
37725b5eae | ||
|
|
5ccaf18e8c | ||
|
|
8d0c272e4a | ||
|
|
b466483877 | ||
|
|
e7599dad7e | ||
|
|
dfd59c0a95 | ||
|
|
af0232d52b | ||
|
|
a0ff0a361e | ||
|
|
c333c0df17 | ||
|
|
59920a733f | ||
|
|
0451e4fa18 | ||
|
|
31c7a10822 | ||
|
|
dea236e0ce | ||
|
|
282b3f7b97 | ||
|
|
8c36a22e79 | ||
|
|
aa4abaf820 | ||
|
|
75c60598b7 | ||
|
|
6997452eb5 | ||
|
|
42d149e45d | ||
|
|
972c3918c5 | ||
|
|
c3a7df35e7 | ||
|
|
784da88b15 | ||
|
|
7305bf47b8 | ||
|
|
eede75c9d4 | ||
|
|
e3a0f2e690 | ||
|
|
bcc720abde | ||
|
|
54a556a5ef | ||
|
|
2808e59f4c | ||
|
|
a75be33ba0 | ||
|
|
dd36139b1a | ||
|
|
f1e3ed0c48 | ||
|
|
01f442b84d | ||
|
|
e03c0f03e7 | ||
|
|
8dde918e77 | ||
|
|
e70ce7a35b | ||
|
|
fc8361c078 | ||
|
|
62f51e4367 | ||
|
|
bbbb0036df | ||
|
|
ead379a464 | ||
|
|
7c52c4d92e | ||
|
|
6573a13e4a | ||
|
|
619f1ddd05 | ||
|
|
6083fad7df | ||
|
|
c2b7abacf8 | ||
|
|
d4e0d6f2a1 | ||
|
|
fd5e772aec |
@@ -1,4 +1,6 @@
|
||||
.git
|
||||
bundles/
|
||||
cli/winresources/**/winres.json
|
||||
cli/winresources/**/*.syso
|
||||
/.git
|
||||
|
||||
# build artifacts
|
||||
/bundles/
|
||||
/cli/winresources/dockerd/winres.json
|
||||
/cli/winresources/dockerd/*.syso
|
||||
|
||||
123
.github/workflows/.test-unit.yml
vendored
Normal file
123
.github/workflows/.test-unit.yml
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
# reusable workflow
|
||||
name: .test-unit
|
||||
|
||||
# TODO: hide reusable workflow from the UI. Tracked in https://github.com/community/community/discussions/12025
|
||||
|
||||
# Default to 'contents: read', which grants actions to read commits.
|
||||
#
|
||||
# If any permission is set, any permission not included in the list is
|
||||
# implicitly set to "none".
|
||||
#
|
||||
# see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
GO_VERSION: "1.24.3"
|
||||
GOTESTLIST_VERSION: v0.3.1
|
||||
TESTSTAT_VERSION: v0.1.25
|
||||
SETUP_BUILDX_VERSION: edge
|
||||
SETUP_BUILDKIT_IMAGE: moby/buildkit:latest
|
||||
|
||||
jobs:
|
||||
unit:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 120 # guardrails timeout for the whole job
|
||||
continue-on-error: ${{ github.event_name != 'pull_request' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
mode:
|
||||
- ""
|
||||
- firewalld
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Set up runner
|
||||
uses: ./.github/actions/setup-runner
|
||||
-
|
||||
name: Prepare
|
||||
run: |
|
||||
CACHE_DEV_SCOPE=dev
|
||||
if [[ "${{ matrix.mode }}" == *"firewalld"* ]]; then
|
||||
echo "FIREWALLD=true" >> $GITHUB_ENV
|
||||
CACHE_DEV_SCOPE="${CACHE_DEV_SCOPE}firewalld"
|
||||
fi
|
||||
echo "CACHE_DEV_SCOPE=${CACHE_DEV_SCOPE}" >> $GITHUB_ENV
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ env.SETUP_BUILDX_VERSION }}
|
||||
driver-opts: image=${{ env.SETUP_BUILDKIT_IMAGE }}
|
||||
buildkitd-flags: --debug
|
||||
-
|
||||
name: Build dev image
|
||||
uses: docker/bake-action@v6
|
||||
with:
|
||||
targets: dev
|
||||
set: |
|
||||
dev.cache-from=type=gha,scope=${{ env.CACHE_DEV_SCOPE }}
|
||||
-
|
||||
name: Test
|
||||
run: |
|
||||
make -o build test-unit
|
||||
-
|
||||
name: Prepare reports
|
||||
if: always()
|
||||
run: |
|
||||
mkdir -p bundles /tmp/reports
|
||||
find bundles -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--${{ matrix.mode }}
|
||||
path: /tmp/reports/*
|
||||
retention-days: 1
|
||||
|
||||
unit-report:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 10
|
||||
continue-on-error: ${{ github.event_name != 'pull_request' }}
|
||||
if: always()
|
||||
needs:
|
||||
- unit
|
||||
steps:
|
||||
-
|
||||
name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache-dependency-path: vendor.sum
|
||||
-
|
||||
name: Download reports
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: test-reports-unit-*
|
||||
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
|
||||
134
.github/workflows/.test.yml
vendored
134
.github/workflows/.test.yml
vendored
@@ -21,7 +21,7 @@ on:
|
||||
default: "graphdriver"
|
||||
|
||||
env:
|
||||
GO_VERSION: "1.23.8"
|
||||
GO_VERSION: "1.24.3"
|
||||
GOTESTLIST_VERSION: v0.3.1
|
||||
TESTSTAT_VERSION: v0.1.25
|
||||
ITG_CLI_MATRIX_SIZE: 6
|
||||
@@ -32,138 +32,6 @@ env:
|
||||
SETUP_BUILDKIT_IMAGE: moby/buildkit:latest
|
||||
|
||||
jobs:
|
||||
unit-prepare:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 10 # guardrails timeout for the whole job
|
||||
continue-on-error: ${{ github.event_name != 'pull_request' }}
|
||||
outputs:
|
||||
includes: ${{ steps.set.outputs.includes }}
|
||||
steps:
|
||||
-
|
||||
name: Create matrix includes
|
||||
id: set
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
let includes = [
|
||||
{ mode: '' },
|
||||
{ mode: 'systemd' },
|
||||
];
|
||||
if ("${{ inputs.storage }}" == "snapshotter") {
|
||||
includes.push({ mode: 'firewalld' });
|
||||
}
|
||||
await core.group(`Set matrix`, async () => {
|
||||
core.info(`matrix: ${JSON.stringify(includes)}`);
|
||||
core.setOutput('includes', JSON.stringify(includes));
|
||||
});
|
||||
-
|
||||
name: Show matrix
|
||||
run: |
|
||||
echo ${{ steps.set.outputs.includes }}
|
||||
|
||||
unit:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 120 # guardrails timeout for the whole job
|
||||
continue-on-error: ${{ github.event_name != 'pull_request' }}
|
||||
needs:
|
||||
- unit-prepare
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include: ${{ fromJson(needs.unit-prepare.outputs.includes) }}
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Set up runner
|
||||
uses: ./.github/actions/setup-runner
|
||||
-
|
||||
name: Prepare
|
||||
run: |
|
||||
CACHE_DEV_SCOPE=dev
|
||||
if [[ "${{ matrix.mode }}" == *"firewalld"* ]]; then
|
||||
echo "FIREWALLD=true" >> $GITHUB_ENV
|
||||
CACHE_DEV_SCOPE="${CACHE_DEV_SCOPE}firewalld"
|
||||
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
|
||||
with:
|
||||
version: ${{ env.SETUP_BUILDX_VERSION }}
|
||||
driver-opts: image=${{ env.SETUP_BUILDKIT_IMAGE }}
|
||||
buildkitd-flags: --debug
|
||||
-
|
||||
name: Build dev image
|
||||
uses: docker/bake-action@v6
|
||||
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 }}-${{ matrix.mode }}
|
||||
path: /tmp/reports/*
|
||||
retention-days: 1
|
||||
|
||||
unit-report:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 10
|
||||
continue-on-error: ${{ github.event_name != 'pull_request' }}
|
||||
if: always()
|
||||
needs:
|
||||
- unit
|
||||
steps:
|
||||
-
|
||||
name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache-dependency-path: vendor.sum
|
||||
-
|
||||
name: Download reports
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: 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-24.04
|
||||
timeout-minutes: 120 # guardrails timeout for the whole job
|
||||
|
||||
2
.github/workflows/.windows.yml
vendored
2
.github/workflows/.windows.yml
vendored
@@ -28,7 +28,7 @@ on:
|
||||
default: false
|
||||
|
||||
env:
|
||||
GO_VERSION: "1.23.8"
|
||||
GO_VERSION: "1.24.3"
|
||||
GOTESTLIST_VERSION: v0.3.1
|
||||
TESTSTAT_VERSION: v0.1.25
|
||||
WINDOWS_BASE_IMAGE: mcr.microsoft.com/windows/servercore
|
||||
|
||||
2
.github/workflows/arm64.yml
vendored
2
.github/workflows/arm64.yml
vendored
@@ -23,7 +23,7 @@ on:
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
GO_VERSION: "1.23.8"
|
||||
GO_VERSION: "1.24.3"
|
||||
TESTSTAT_VERSION: v0.1.25
|
||||
DESTDIR: ./build
|
||||
SETUP_BUILDX_VERSION: edge
|
||||
|
||||
218
.github/workflows/buildkit.yml
vendored
218
.github/workflows/buildkit.yml
vendored
@@ -23,7 +23,7 @@ on:
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
GO_VERSION: "1.23.8"
|
||||
GO_VERSION: "1.24.3"
|
||||
DESTDIR: ./build
|
||||
SETUP_BUILDX_VERSION: edge
|
||||
SETUP_BUILDKIT_IMAGE: moby/buildkit:latest
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
validate-dco:
|
||||
uses: ./.github/workflows/.dco.yml
|
||||
|
||||
build:
|
||||
build-linux:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 120 # guardrails timeout for the whole job
|
||||
needs:
|
||||
@@ -59,11 +59,11 @@ jobs:
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
test:
|
||||
test-linux:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 120 # guardrails timeout for the whole job
|
||||
needs:
|
||||
- build
|
||||
- build-linux
|
||||
env:
|
||||
TEST_IMAGE_BUILD: "0"
|
||||
TEST_IMAGE_ID: "buildkit-tests"
|
||||
@@ -162,3 +162,213 @@ jobs:
|
||||
TESTPKGS: "./${{ matrix.pkg }}"
|
||||
TESTFLAGS: "-v --parallel=1 --timeout=30m --run=//worker=${{ matrix.worker }}$"
|
||||
working-directory: buildkit
|
||||
|
||||
build-windows:
|
||||
runs-on: windows-2022
|
||||
timeout-minutes: 120
|
||||
needs:
|
||||
- validate-dco
|
||||
env:
|
||||
GOPATH: ${{ github.workspace }}\go
|
||||
GOBIN: ${{ github.workspace }}\go\bin
|
||||
BIN_OUT: ${{ github.workspace }}\out
|
||||
WINDOWS_BASE_IMAGE: mcr.microsoft.com/windows/servercore
|
||||
WINDOWS_BASE_TAG_2022: ltsc2022
|
||||
TEST_IMAGE_NAME: moby:test
|
||||
TEST_CTN_NAME: moby
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ env.GOPATH }}/src/github.com/docker/docker
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: ${{ env.GOPATH }}/src/github.com/docker/docker
|
||||
|
||||
- name: Env
|
||||
run: |
|
||||
Get-ChildItem Env: | Out-String
|
||||
- name: Moby - Init
|
||||
run: |
|
||||
New-Item -ItemType "directory" -Path "${{ github.workspace }}\go-build"
|
||||
New-Item -ItemType "directory" -Path "${{ github.workspace }}\go\pkg\mod"
|
||||
echo "WINDOWS_BASE_IMAGE_TAG=${{ env.WINDOWS_BASE_TAG_2022 }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache-dependency-path: vendor.sum
|
||||
- name: Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~\AppData\Local\go-build
|
||||
~\go\pkg\mod
|
||||
${{ github.workspace }}\go-build
|
||||
${{ env.GOPATH }}\pkg\mod
|
||||
key: ${{ inputs.os }}-${{ github.job }}-${{ hashFiles('**/vendor.sum') }}
|
||||
restore-keys: |
|
||||
${{ inputs.os }}-${{ github.job }}-
|
||||
|
||||
- name: Docker info
|
||||
run: |
|
||||
docker info
|
||||
|
||||
- name: Build base image
|
||||
run: |
|
||||
& docker build `
|
||||
--build-arg WINDOWS_BASE_IMAGE `
|
||||
--build-arg WINDOWS_BASE_IMAGE_TAG `
|
||||
--build-arg GO_VERSION `
|
||||
-t ${{ env.TEST_IMAGE_NAME }} `
|
||||
-f Dockerfile.windows .
|
||||
|
||||
- name: Build binaries
|
||||
run: |
|
||||
& docker run --name ${{ env.TEST_CTN_NAME }} -e "DOCKER_GITCOMMIT=${{ github.sha }}" `
|
||||
-v "${{ github.workspace }}\go-build:C:\Users\ContainerAdministrator\AppData\Local\go-build" `
|
||||
-v "${{ github.workspace }}\go\pkg\mod:C:\gopath\pkg\mod" `
|
||||
${{ env.TEST_IMAGE_NAME }} hack\make.ps1 -Daemon -Client
|
||||
go install github.com/distribution/distribution/v3/cmd/registry@latest
|
||||
|
||||
- name: Checkout BuildKit
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: moby/buildkit
|
||||
ref: master
|
||||
path: buildkit
|
||||
|
||||
- name: Add buildctl to binaries
|
||||
run: |
|
||||
go install ./cmd/buildctl
|
||||
working-directory: buildkit
|
||||
|
||||
- name: Copy artifacts
|
||||
run: |
|
||||
New-Item -ItemType "directory" -Path "${{ env.BIN_OUT }}"
|
||||
docker cp "${{ env.TEST_CTN_NAME }}`:c`:\gopath\src\github.com\docker\docker\bundles\docker.exe" ${{ env.BIN_OUT }}\
|
||||
docker cp "${{ env.TEST_CTN_NAME }}`:c`:\gopath\src\github.com\docker\docker\bundles\dockerd.exe" ${{ env.BIN_OUT }}\
|
||||
docker cp "${{ env.TEST_CTN_NAME }}`:c`:\gopath\bin\gotestsum.exe" ${{ env.BIN_OUT }}\
|
||||
docker cp "${{ env.TEST_CTN_NAME }}`:c`:\containerd\bin\containerd.exe" ${{ env.BIN_OUT }}\
|
||||
docker cp "${{ env.TEST_CTN_NAME }}`:c`:\containerd\bin\containerd-shim-runhcs-v1.exe" ${{ env.BIN_OUT }}\
|
||||
cp ${{ env.GOPATH }}\bin\registry.exe ${{ env.BIN_OUT }}
|
||||
cp ${{ env.GOPATH }}\bin\buildctl.exe ${{ env.BIN_OUT }}
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-windows
|
||||
path: ${{ env.BIN_OUT }}/*
|
||||
if-no-files-found: error
|
||||
retention-days: 2
|
||||
|
||||
test-windows:
|
||||
runs-on: windows-2022
|
||||
timeout-minutes: 120 # guardrails timeout for the whole job
|
||||
needs:
|
||||
- build-windows
|
||||
env:
|
||||
TEST_IMAGE_BUILD: "0"
|
||||
TEST_IMAGE_ID: "buildkit-tests"
|
||||
GOPATH: ${{ github.workspace }}\go
|
||||
GOBIN: ${{ github.workspace }}\go\bin
|
||||
BIN_OUT: ${{ github.workspace }}\out
|
||||
TESTFLAGS: "-v --timeout=90m"
|
||||
TEST_DOCKERD: "1"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
worker:
|
||||
- dockerd-containerd
|
||||
pkg:
|
||||
- ./client#1-4
|
||||
- ./client#2-4
|
||||
- ./client#3-4
|
||||
- ./client#4-4
|
||||
- ./cmd/buildctl
|
||||
- ./frontend
|
||||
- ./frontend/dockerfile#1-12
|
||||
- ./frontend/dockerfile#2-12
|
||||
- ./frontend/dockerfile#3-12
|
||||
- ./frontend/dockerfile#4-12
|
||||
- ./frontend/dockerfile#5-12
|
||||
- ./frontend/dockerfile#6-12
|
||||
- ./frontend/dockerfile#7-12
|
||||
- ./frontend/dockerfile#8-12
|
||||
- ./frontend/dockerfile#9-12
|
||||
- ./frontend/dockerfile#10-12
|
||||
- ./frontend/dockerfile#11-12
|
||||
- ./frontend/dockerfile#12-12
|
||||
steps:
|
||||
- name: Prepare
|
||||
shell: bash
|
||||
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
|
||||
- name: Expose GitHub Runtime
|
||||
uses: crazy-max/ghaction-github-runtime@v3
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: moby
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache-dependency-path: vendor.sum
|
||||
- name: BuildKit ref
|
||||
shell: bash
|
||||
run: |
|
||||
echo "$(./hack/buildkit-ref)" >> $GITHUB_ENV
|
||||
working-directory: moby
|
||||
- name: Checkout BuildKit ${{ env.BUILDKIT_REF }}
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: ${{ env.BUILDKIT_REPO }}
|
||||
ref: ${{ env.BUILDKIT_REF }}
|
||||
path: buildkit
|
||||
|
||||
- name: Download Moby artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: build-windows
|
||||
path: ${{ env.BIN_OUT }}
|
||||
|
||||
- name: Add binaries to PATH
|
||||
run: |
|
||||
ls ${{ env.BIN_OUT }}
|
||||
Write-Output "${{ env.BIN_OUT }}" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||
|
||||
- name: Test Prep
|
||||
shell: bash
|
||||
run: |
|
||||
TESTPKG=$(echo "${{ matrix.pkg }}" | awk '-F#' '{print $1}')
|
||||
echo "TESTPKG=$TESTPKG" >> $GITHUB_ENV
|
||||
echo "TEST_REPORT_NAME=${{ github.job }}-$(echo "${{ matrix.pkg }}-${{ matrix.worker }}" | tr -dc '[:alnum:]-\n\r' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
|
||||
testFlags="${{ env.TESTFLAGS }}"
|
||||
testSlice=$(echo "${{ matrix.pkg }}" | awk '-F#' '{print $2}')
|
||||
testSliceOffset=""
|
||||
if [ -n "$testSlice" ]; then
|
||||
testSliceOffset="slice=$testSlice/"
|
||||
fi
|
||||
if [ -n "${{ matrix.worker }}" ]; then
|
||||
testFlags="${testFlags} --run=TestIntegration/$testSliceOffset.*/worker=${{ matrix.worker }}"
|
||||
fi
|
||||
echo "TESTFLAGS=${testFlags}" >> $GITHUB_ENV
|
||||
- name: Test
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p ./bin/testreports
|
||||
gotestsum \
|
||||
--jsonfile="./bin/testreports/go-test-report-${{ env.TEST_REPORT_NAME }}.json" \
|
||||
--junitfile="./bin/testreports/junit-report-${{ env.TEST_REPORT_NAME }}.xml" \
|
||||
--packages="${{ env.TESTPKG }}" \
|
||||
-- \
|
||||
"-mod=vendor" \
|
||||
"-coverprofile" "./bin/testreports/coverage-${{ env.TEST_REPORT_NAME }}.txt" \
|
||||
"-covermode" "atomic" ${{ env.TESTFLAGS }}
|
||||
working-directory: buildkit
|
||||
|
||||
2
.github/workflows/codeql.yml
vendored
2
.github/workflows/codeql.yml
vendored
@@ -58,7 +58,7 @@ jobs:
|
||||
- name: Update Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.23.8"
|
||||
go-version: "1.24.3"
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
|
||||
9
.github/workflows/test.yml
vendored
9
.github/workflows/test.yml
vendored
@@ -23,7 +23,7 @@ on:
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
GO_VERSION: "1.23.8"
|
||||
GO_VERSION: "1.24.3"
|
||||
GIT_PAGER: "cat"
|
||||
PAGER: "cat"
|
||||
SETUP_BUILDX_VERSION: edge
|
||||
@@ -83,6 +83,13 @@ jobs:
|
||||
with:
|
||||
storage: ${{ matrix.storage }}
|
||||
|
||||
test-unit:
|
||||
needs:
|
||||
- build-dev
|
||||
- validate-dco
|
||||
uses: ./.github/workflows/.test-unit.yml
|
||||
secrets: inherit
|
||||
|
||||
validate-prepare:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 10 # guardrails timeout for the whole job
|
||||
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -14,10 +14,9 @@ thumbs.db
|
||||
.editorconfig
|
||||
|
||||
# build artifacts
|
||||
bundles/
|
||||
cli/winresources/*/*.syso
|
||||
cli/winresources/*/winres.json
|
||||
contrib/builder/rpm/*/changelog
|
||||
/bundles/
|
||||
/cli/winresources/dockerd/*.syso
|
||||
/cli/winresources/dockerd/winres.json
|
||||
|
||||
# ci artifacts
|
||||
*.exe
|
||||
|
||||
476
.golangci.yml
476
.golangci.yml
@@ -1,249 +1,261 @@
|
||||
linters:
|
||||
enable:
|
||||
- asasalint # Detects "[]any" used as argument for variadic "func(...any)".
|
||||
- copyloopvar # Detects places where loop variables are copied.
|
||||
- depguard
|
||||
- dogsled # Detects assignments with too many blank identifiers.
|
||||
- dupword # Detects duplicate words.
|
||||
- durationcheck # Detect cases where two time.Duration values are being multiplied in possibly erroneous ways.
|
||||
- errchkjson # Detects unsupported types passed to json encoding functions and reports if checks for the returned error can be omitted.
|
||||
- exhaustive # Detects missing options in enum switch statements.
|
||||
- exptostd # Detects functions from golang.org/x/exp/ that can be replaced by std functions.
|
||||
- fatcontext # Detects nested contexts in loops and function literals.
|
||||
- gocheckcompilerdirectives # Detects invalid go compiler directive comments (//go:).
|
||||
- goimports
|
||||
- gosec # Detects security problems.
|
||||
- gosimple
|
||||
- govet
|
||||
- forbidigo
|
||||
- iface # Detects incorrect use of interfaces. Currently only used for "identical" interfaces in the same package.
|
||||
- importas
|
||||
- ineffassign
|
||||
- makezero # Finds slice declarations with non-zero initial length.
|
||||
- mirror # Detects wrong mirror patterns of bytes/strings usage.
|
||||
- misspell # Detects commonly misspelled English words in comments.
|
||||
- nakedret # Detects uses of naked returns.
|
||||
- nilnesserr # Detects returning nil errors. It combines the features of nilness and nilerr,
|
||||
- nosprintfhostport # Detects misuse of Sprintf to construct a host with port in a URL.
|
||||
- reassign # Detects reassigning a top-level variable in another package.
|
||||
- revive # Metalinter; drop-in replacement for golint.
|
||||
- spancheck # Detects mistakes with OpenTelemetry/Census spans.
|
||||
- staticcheck
|
||||
- typecheck
|
||||
- unconvert # Detects unnecessary type conversions.
|
||||
- unused
|
||||
- wastedassign # Detects wasted assignment statements.
|
||||
|
||||
disable:
|
||||
- errcheck
|
||||
version: "2"
|
||||
|
||||
run:
|
||||
# prevent golangci-lint from deducting the go version to lint for through go.mod,
|
||||
# which causes it to fallback to go1.17 semantics.
|
||||
go: "1.23.8"
|
||||
go: "1.24.3"
|
||||
concurrency: 2
|
||||
# Only supported with go modules enabled (build flag -mod=vendor only valid when using modules)
|
||||
# modules-download-mode: vendor
|
||||
|
||||
linters-settings:
|
||||
depguard:
|
||||
formatters:
|
||||
enable:
|
||||
- gofmt
|
||||
- goimports
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- asasalint # Detects "[]any" used as argument for variadic "func(...any)".
|
||||
- copyloopvar # Detects places where loop variables are copied.
|
||||
- depguard
|
||||
- dogsled # Detects assignments with too many blank identifiers.
|
||||
- dupword # Detects duplicate words.
|
||||
- durationcheck # Detect cases where two time.Duration values are being multiplied in possibly erroneous ways.
|
||||
- errchkjson # Detects unsupported types passed to json encoding functions and reports if checks for the returned error can be omitted.
|
||||
- exhaustive # Detects missing options in enum switch statements.
|
||||
- exptostd # Detects functions from golang.org/x/exp/ that can be replaced by std functions.
|
||||
- fatcontext # Detects nested contexts in loops and function literals.
|
||||
- forbidigo
|
||||
- gocheckcompilerdirectives # Detects invalid go compiler directive comments (//go:).
|
||||
- gosec # Detects security problems.
|
||||
- govet
|
||||
- iface # Detects incorrect use of interfaces. Currently only used for "identical" interfaces in the same package.
|
||||
- importas
|
||||
- ineffassign
|
||||
- makezero # Finds slice declarations with non-zero initial length.
|
||||
- mirror # Detects wrong mirror patterns of bytes/strings usage.
|
||||
- misspell # Detects commonly misspelled English words in comments.
|
||||
- nakedret # Detects uses of naked returns.
|
||||
- nilnesserr # Detects returning nil errors. It combines the features of nilness and nilerr,
|
||||
- nosprintfhostport # Detects misuse of Sprintf to construct a host with port in a URL.
|
||||
- reassign # Detects reassigning a top-level variable in another package.
|
||||
- revive # Metalinter; drop-in replacement for golint.
|
||||
- spancheck # Detects mistakes with OpenTelemetry/Census spans.
|
||||
- staticcheck
|
||||
- unconvert # Detects unnecessary type conversions.
|
||||
- unused
|
||||
- usestdlibvars # Detects the possibility to use variables/constants from the Go standard library.
|
||||
- wastedassign # Detects wasted assignment statements.
|
||||
|
||||
disable:
|
||||
- errcheck
|
||||
- spancheck # FIXME
|
||||
|
||||
settings:
|
||||
depguard:
|
||||
rules:
|
||||
main:
|
||||
deny:
|
||||
- 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
|
||||
- pkg: "github.com/containerd/containerd/pkg/userns"
|
||||
desc: Use github.com/moby/sys/userns instead.
|
||||
- pkg: "github.com/tonistiigi/fsutil"
|
||||
desc: The fsutil module does not have a stable API, so we should not have a direct dependency unless necessary.
|
||||
|
||||
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"
|
||||
|
||||
exhaustive:
|
||||
# Program elements to check for exhaustiveness.
|
||||
# Default: [ switch ]
|
||||
check:
|
||||
- switch
|
||||
# - map # TODO(thaJeztah): also enable for maps
|
||||
# Presence of "default" case in switch statements satisfies exhaustiveness,
|
||||
# even if all enum members are not listed.
|
||||
# Default: false
|
||||
#
|
||||
# TODO(thaJeztah): consider not allowing this to catch new values being added (and falling through to "default")
|
||||
default-signifies-exhaustive: true
|
||||
|
||||
forbidigo:
|
||||
forbid:
|
||||
- pkg: ^sync/atomic$
|
||||
pattern: ^atomic\.(Add|CompareAndSwap|Load|Store|Swap).
|
||||
msg: Go 1.19 atomic types should be used instead.
|
||||
- pkg: ^regexp$
|
||||
pattern: ^regexp\.MustCompile
|
||||
msg: Use internal/lazyregexp.New instead.
|
||||
- pkg: github.com/vishvananda/netlink$
|
||||
pattern: ^netlink\.(Handle\.)?(AddrList|BridgeVlanList|ChainList|ClassList|ConntrackTableList|ConntrackDeleteFilter$|ConntrackDeleteFilters|DevLinkGetDeviceList|DevLinkGetAllPortList|DevlinkGetDeviceParams|FilterList|FouList|GenlFamilyList|GTPPDPList|LinkByName|LinkByAlias|LinkList|LinkSubscribeWithOptions|NeighList$|NeighProxyList|NeighListExecute|NeighSubscribeWithOptions|LinkGetProtinfo|QdiscList|RdmaLinkList|RdmaLinkByName|RdmaLinkDel|RouteList|RouteListFilteredIter|RuleListFiltered$|RouteSubscribeWithOptions|RuleList$|RuleListFiltered|SocketGet|SocketDiagTCPInfo|SocketDiagTCP|SocketDiagUDPInfo|SocketDiagUDP|UnixSocketDiagInfo|UnixSocketDiag|VDPAGetDevConfigList|VDPAGetDevList|VDPAGetMGMTDevList|XfrmPolicyList|XfrmStateList)
|
||||
msg: Use internal nlwrap package for EINTR handling.
|
||||
- pkg: github.com/docker/docker/internal/nlwrap$
|
||||
pattern: ^nlwrap.Handle.(BridgeVlanList|ChainList|ClassList|ConntrackDeleteFilter$|DevLinkGetDeviceList|DevLinkGetAllPortList|DevlinkGetDeviceParams|FilterList|FouList|GenlFamilyList|GTPPDPList|LinkByAlias|LinkSubscribeWithOptions|NeighList$|NeighProxyList|NeighListExecute|NeighSubscribeWithOptions|LinkGetProtinfo|QdiscList|RdmaLinkList|RdmaLinkByName|RdmaLinkDel|RouteListFilteredIter|RuleListFiltered$|RouteSubscribeWithOptions|RuleList$|RuleListFiltered|SocketGet|SocketDiagTCPInfo|SocketDiagTCP|SocketDiagUDPInfo|SocketDiagUDP|UnixSocketDiagInfo|UnixSocketDiag|VDPAGetDevConfigList|VDPAGetDevList|VDPAGetMGMTDevList)
|
||||
msg: Add a wrapper to nlwrap.Handle for EINTR handling and update the list in .golangci.yml.
|
||||
analyze-types: true
|
||||
|
||||
gosec:
|
||||
excludes:
|
||||
- G104 # G104: Errors unhandled; (TODO: reduce unhandled errors, or explicitly ignore)
|
||||
- G115 # G115: integer overflow conversion; (TODO: verify these: https://github.com/moby/moby/issues/48358)
|
||||
- G204 # G204: Subprocess launched with variable; too many false positives.
|
||||
- G301 # G301: Expect directory permissions to be 0750 or less (also EXC0009); too restrictive
|
||||
- G302 # G302: Expect file permissions to be 0600 or less (also EXC0009); too restrictive
|
||||
- G304 # G304: Potential file inclusion via variable.
|
||||
- G306 # G306: Expect WriteFile permissions to be 0600 or less (too restrictive; also flags "0o644" permissions)
|
||||
- G307 # G307: Deferring unsafe method "*os.File" on type "Close" (also EXC0008); (TODO: evaluate these and fix where needed: G307: Deferring unsafe method "*os.File" on type "Close")
|
||||
- G504 # G504: Blocklisted import net/http/cgi: Go versions < 1.6.3 are vulnerable to Httpoxy attack: (CVE-2016-5386); (only affects go < 1.6.3)
|
||||
|
||||
govet:
|
||||
enable-all: true
|
||||
disable:
|
||||
- fieldalignment # TODO: evaluate which ones should be updated.
|
||||
|
||||
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/errdefs
|
||||
alias: cerrdefs
|
||||
- pkg: github.com/containerd/containerd/images
|
||||
alias: c8dimages
|
||||
- pkg: github.com/opencontainers/image-spec/specs-go/v1
|
||||
alias: ocispec
|
||||
- pkg: go.etcd.io/bbolt
|
||||
alias: bolt
|
||||
# Enforce that gotest.tools/v3/assert/cmp is always aliased as "is"
|
||||
- pkg: gotest.tools/v3/assert/cmp
|
||||
alias: is
|
||||
|
||||
nakedret:
|
||||
# Disallow naked returns if func has more lines of code than this setting.
|
||||
# Default: 30
|
||||
max-func-lines: 0
|
||||
|
||||
revive:
|
||||
rules:
|
||||
# FIXME make sure all packages have a description. Currently, there's many packages without.
|
||||
- name: package-comments
|
||||
disabled: true
|
||||
|
||||
staticcheck:
|
||||
checks:
|
||||
- all
|
||||
- -QF1008 # Omit embedded fields from selector expression; https://staticcheck.dev/docs/checks/#QF1008
|
||||
- -ST1000 # Incorrect or missing package comment; https://staticcheck.dev/docs/checks/#ST1000
|
||||
- -ST1003 # Poorly chosen identifier; https://staticcheck.dev/docs/checks/#ST1003
|
||||
- -ST1005 # Incorrectly formatted error string; https://staticcheck.dev/docs/checks/#ST1005
|
||||
|
||||
spancheck:
|
||||
# Default: ["end"]
|
||||
checks:
|
||||
- end # check that `span.End()` is called
|
||||
- record-error # check that `span.RecordError(err)` is called when an error is returned
|
||||
- set-status # check that `span.SetStatus(codes.Error, msg)` is called when an error is returned
|
||||
|
||||
usestdlibvars:
|
||||
# Suggest the use of http.MethodXX.
|
||||
http-method: true
|
||||
# Suggest the use of http.StatusXX.
|
||||
http-status-code: true
|
||||
|
||||
exclusions:
|
||||
paths:
|
||||
- volume/drivers/proxy.go # TODO: this is a generated file but with an invalid header, see https://github.com/moby/moby/pull/46274
|
||||
|
||||
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
|
||||
- pkg: "github.com/containerd/containerd/errdefs"
|
||||
desc: The errdefs package has moved to a separate module, https://github.com/containerd/errdefs
|
||||
- pkg: "github.com/containerd/containerd/log"
|
||||
desc: The logs package has moved to a separate module, https://github.com/containerd/log
|
||||
- pkg: "github.com/containerd/containerd/pkg/userns"
|
||||
desc: Use github.com/moby/sys/userns instead.
|
||||
- pkg: "github.com/tonistiigi/fsutil"
|
||||
desc: The fsutil module does not have a stable API, so we should not have a direct dependency unless necessary.
|
||||
# We prefer to use an "linters.exclusions.rules" 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 excludes at:
|
||||
# https://github.com/golangci/golangci-lint/blob/v1.61.0/pkg/config/issues.go#L11-L104
|
||||
#
|
||||
# The default list of exclusions can be found at:
|
||||
# https://golangci-lint.run/usage/false-positives/#default-exclusions
|
||||
|
||||
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"
|
||||
# Exclude some linters from running on tests files.
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- errcheck
|
||||
|
||||
exhaustive:
|
||||
# Program elements to check for exhaustiveness.
|
||||
# Default: [ switch ]
|
||||
check:
|
||||
- switch
|
||||
# - map # TODO(thaJeztah): also enable for maps
|
||||
# Presence of "default" case in switch statements satisfies exhaustiveness,
|
||||
# even if all enum members are not listed.
|
||||
- text: "G404: Use of weak random number generator"
|
||||
path: _test\.go
|
||||
linters:
|
||||
- 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: ignoring unused assigns to ctx for now; too many hits in libnetwork/xxx functions that setup traces
|
||||
- text: "assigned to ctx, but never used afterwards"
|
||||
linters:
|
||||
- wastedassign
|
||||
|
||||
- text: "ineffectual assignment to ctx"
|
||||
source: "ctx[, ].*=.*\\(ctx[,)]"
|
||||
linters:
|
||||
- ineffassign
|
||||
|
||||
- text: "SA4006: this value of ctx is never used"
|
||||
source: "ctx[, ].*=.*\\(ctx[,)]"
|
||||
linters:
|
||||
- staticcheck
|
||||
|
||||
# FIXME(thaJeztah): ignoring these transitional utilities until BuildKit is vendored with https://github.com/moby/moby/pull/49743
|
||||
- text: "SA1019: idtools\\.(ToUserIdentityMapping|FromUserIdentityMapping) is deprecated"
|
||||
linters:
|
||||
- staticcheck
|
||||
|
||||
# Ignore "nested context in function literal (fatcontext)" as we intentionally set up tracing on a base-context for tests.
|
||||
# FIXME(thaJeztah): see if there's a more iodiomatic way to do this.
|
||||
- text: 'nested context in function literal'
|
||||
path: '((main|check)_(linux_|)test\.go)|testutil/helpers\.go'
|
||||
linters:
|
||||
- fatcontext
|
||||
|
||||
- text: '^shadow: declaration of "(ctx|err|ok)" shadows declaration'
|
||||
linters:
|
||||
- govet
|
||||
- text: '^shadow: declaration of "(out)" shadows declaration'
|
||||
path: _test\.go
|
||||
linters:
|
||||
- govet
|
||||
- text: 'use of `regexp.MustCompile` forbidden'
|
||||
path: _test\.go
|
||||
linters:
|
||||
- forbidigo
|
||||
- text: 'use of `regexp.MustCompile` forbidden'
|
||||
path: "internal/lazyregexp"
|
||||
linters:
|
||||
- forbidigo
|
||||
- text: 'use of `regexp.MustCompile` forbidden'
|
||||
path: "libnetwork/cmd/networkdb-test/dbclient"
|
||||
linters:
|
||||
- forbidigo
|
||||
|
||||
# Log a warning if an exclusion rule is unused.
|
||||
# Default: false
|
||||
#
|
||||
# TODO(thaJeztah): consider not allowing this to catch new values being added (and falling through to "default")
|
||||
default-signifies-exhaustive: true
|
||||
|
||||
forbidigo:
|
||||
forbid:
|
||||
- pkg: ^sync/atomic$
|
||||
p: ^atomic\.(Add|CompareAndSwap|Load|Store|Swap).
|
||||
msg: Go 1.19 atomic types should be used instead.
|
||||
- pkg: ^regexp$
|
||||
p: ^regexp\.MustCompile
|
||||
msg: Use internal/lazyregexp.New instead.
|
||||
- pkg: github.com/vishvananda/netlink$
|
||||
p: ^netlink\.(Handle\.)?(AddrList|BridgeVlanList|ChainList|ClassList|ConntrackTableList|ConntrackDeleteFilter$|ConntrackDeleteFilters|DevLinkGetDeviceList|DevLinkGetAllPortList|DevlinkGetDeviceParams|FilterList|FouList|GenlFamilyList|GTPPDPList|LinkByName|LinkByAlias|LinkList|LinkSubscribeWithOptions|NeighList$|NeighProxyList|NeighListExecute|NeighSubscribeWithOptions|LinkGetProtinfo|QdiscList|RdmaLinkList|RdmaLinkByName|RdmaLinkDel|RouteList|RouteListFilteredIter|RuleListFiltered$|RouteSubscribeWithOptions|RuleList$|RuleListFiltered|SocketGet|SocketDiagTCPInfo|SocketDiagTCP|SocketDiagUDPInfo|SocketDiagUDP|UnixSocketDiagInfo|UnixSocketDiag|VDPAGetDevConfigList|VDPAGetDevList|VDPAGetMGMTDevList|XfrmPolicyList|XfrmStateList)
|
||||
msg: Use internal nlwrap package for EINTR handling.
|
||||
- pkg: github.com/docker/docker/internal/nlwrap$
|
||||
p: ^nlwrap.Handle.(BridgeVlanList|ChainList|ClassList|ConntrackDeleteFilter$|DevLinkGetDeviceList|DevLinkGetAllPortList|DevlinkGetDeviceParams|FilterList|FouList|GenlFamilyList|GTPPDPList|LinkByAlias|LinkSubscribeWithOptions|NeighList$|NeighProxyList|NeighListExecute|NeighSubscribeWithOptions|LinkGetProtinfo|QdiscList|RdmaLinkList|RdmaLinkByName|RdmaLinkDel|RouteListFilteredIter|RuleListFiltered$|RouteSubscribeWithOptions|RuleList$|RuleListFiltered|SocketGet|SocketDiagTCPInfo|SocketDiagTCP|SocketDiagUDPInfo|SocketDiagUDP|UnixSocketDiagInfo|UnixSocketDiag|VDPAGetDevConfigList|VDPAGetDevList|VDPAGetMGMTDevList)
|
||||
msg: Add a wrapper to nlwrap.Handle for EINTR handling and update the list in .golangci.yml.
|
||||
analyze-types: true
|
||||
|
||||
gosec:
|
||||
excludes:
|
||||
- G104 # G104: Errors unhandled; (TODO: reduce unhandled errors, or explicitly ignore)
|
||||
- G113 # G113: Potential uncontrolled memory consumption in Rat.SetString (CVE-2022-23772); (only affects go < 1.16.14. and go < 1.17.7)
|
||||
- G115 # G115: integer overflow conversion; (TODO: verify these: https://github.com/moby/moby/issues/48358)
|
||||
- G204 # G204: Subprocess launched with variable; too many false positives.
|
||||
- G301 # G301: Expect directory permissions to be 0750 or less (also EXC0009); too restrictive
|
||||
- G302 # G302: Expect file permissions to be 0600 or less (also EXC0009); too restrictive
|
||||
- G304 # G304: Potential file inclusion via variable.
|
||||
- G306 # G306: Expect WriteFile permissions to be 0600 or less (too restrictive; also flags "0o644" permissions)
|
||||
- G307 # G307: Deferring unsafe method "*os.File" on type "Close" (also EXC0008); (TODO: evaluate these and fix where needed: G307: Deferring unsafe method "*os.File" on type "Close")
|
||||
- G504 # G504: Blocklisted import net/http/cgi: Go versions < 1.6.3 are vulnerable to Httpoxy attack: (CVE-2016-5386); (only affects go < 1.6.3)
|
||||
|
||||
govet:
|
||||
enable-all: true
|
||||
disable:
|
||||
- fieldalignment # TODO: evaluate which ones should be updated.
|
||||
|
||||
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/errdefs
|
||||
alias: cerrdefs
|
||||
- pkg: github.com/containerd/containerd/images
|
||||
alias: c8dimages
|
||||
- pkg: github.com/opencontainers/image-spec/specs-go/v1
|
||||
alias: ocispec
|
||||
# Enforce that gotest.tools/v3/assert/cmp is always aliased as "is"
|
||||
- pkg: gotest.tools/v3/assert/cmp
|
||||
alias: is
|
||||
|
||||
nakedret:
|
||||
# Disallow naked returns if func has more lines of code than this setting.
|
||||
# Default: 30
|
||||
max-func-lines: 0
|
||||
|
||||
revive:
|
||||
rules:
|
||||
# FIXME make sure all packages have a description. Currently, there's many packages without.
|
||||
- name: package-comments
|
||||
disabled: true
|
||||
|
||||
spancheck:
|
||||
# Default: ["end"]
|
||||
checks:
|
||||
- end # check that `span.End()` is called
|
||||
- record-error # check that `span.RecordError(err)` is called when an error is returned
|
||||
- set-status # check that `span.SetStatus(codes.Error, msg)` is called when an error is returned
|
||||
warn-unused: true
|
||||
|
||||
issues:
|
||||
# The default exclusion rules are a bit too permissive, so copying the relevant ones below
|
||||
exclude-use-default: false
|
||||
|
||||
exclude-dirs:
|
||||
- docs
|
||||
|
||||
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 excludes at:
|
||||
# https://github.com/golangci/golangci-lint/blob/v1.61.0/pkg/config/issues.go#L11-L104
|
||||
#
|
||||
# The default list of exclusions can be found at:
|
||||
# https://golangci-lint.run/usage/false-positives/#default-exclusions
|
||||
|
||||
# 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
|
||||
|
||||
# Exclude some linters from running on tests files.
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- errcheck
|
||||
|
||||
- text: "G404: Use of weak random number generator"
|
||||
path: _test\.go
|
||||
linters:
|
||||
- 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: ignoring unused assigns to ctx for now; too many hits in libnetwork/xxx functions that setup traces
|
||||
- text: "assigned to ctx, but never used afterwards"
|
||||
linters:
|
||||
- wastedassign
|
||||
|
||||
- text: "ineffectual assignment to ctx"
|
||||
source: "ctx[, ].*=.*\\(ctx[,)]"
|
||||
linters:
|
||||
- ineffassign
|
||||
|
||||
- text: "SA4006: this value of `ctx` is never used"
|
||||
source: "ctx[, ].*=.*\\(ctx[,)]"
|
||||
linters:
|
||||
- staticcheck
|
||||
|
||||
# FIXME(thaJeztah): ignoring these transitional utilities until BuildKit is vendored with https://github.com/moby/moby/pull/49743
|
||||
- text: "SA1019: idtools\\.(ToUserIdentityMapping|FromUserIdentityMapping) is deprecated"
|
||||
linters:
|
||||
- staticcheck
|
||||
|
||||
# Ignore "nested context in function literal (fatcontext)" as we intentionally set up tracing on a base-context for tests.
|
||||
# FIXME(thaJeztah): see if there's a more iodiomatic way to do this.
|
||||
- text: 'nested context in function literal'
|
||||
path: '((main|check)_(linux_|)test\.go)|testutil/helpers\.go'
|
||||
linters:
|
||||
- fatcontext
|
||||
|
||||
- text: '^shadow: declaration of "(ctx|err|ok)" shadows declaration'
|
||||
linters:
|
||||
- govet
|
||||
- text: '^shadow: declaration of "(out)" shadows declaration'
|
||||
path: _test\.go
|
||||
linters:
|
||||
- govet
|
||||
- text: 'use of `regexp.MustCompile` forbidden'
|
||||
path: _test\.go
|
||||
linters:
|
||||
- forbidigo
|
||||
- text: 'use of `regexp.MustCompile` forbidden'
|
||||
path: "internal/lazyregexp"
|
||||
linters:
|
||||
- forbidigo
|
||||
- text: 'use of `regexp.MustCompile` forbidden'
|
||||
path: "libnetwork/cmd/networkdb-test/dbclient"
|
||||
linters:
|
||||
- forbidigo
|
||||
|
||||
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
|
||||
max-issues-per-linter: 0
|
||||
|
||||
|
||||
6
.mailmap
6
.mailmap
@@ -94,8 +94,9 @@ Arnaud Rebillout <arnaud.rebillout@collabora.com>
|
||||
Arnaud Rebillout <arnaud.rebillout@collabora.com> <elboulangero@gmail.com>
|
||||
Arthur Gautier <baloo@gandi.net> <superbaloo+registrations.github@superbaloo.net>
|
||||
Artur Meyster <arthurfbi@yahoo.com>
|
||||
Austin Vazquez <macedonv@amazon.com>
|
||||
Austin Vazquez <macedonv@amazon.com> <55906459+austinvazquez@users.noreply.github.com>
|
||||
Austin Vazquez <austin.vazquez.dev@gmail.com>
|
||||
Austin Vazquez <austin.vazquez.dev@gmail.com> <55906459+austinvazquez@users.noreply.github.com>
|
||||
Austin Vazquez <austin.vazquez.dev@gmail.com> <macedonv@amazon.com>
|
||||
Avi Miller <avi.miller@oracle.com> <avi.miller@gmail.com>
|
||||
Ben Bonnefoy <frenchben@docker.com>
|
||||
Ben Golub <ben.golub@dotcloud.com>
|
||||
@@ -138,6 +139,7 @@ Chen Mingjie <chenmingjie0828@163.com>
|
||||
Chen Qiu <cheney-90@hotmail.com>
|
||||
Chen Qiu <cheney-90@hotmail.com> <21321229@zju.edu.cn>
|
||||
Chengfei Shang <cfshang@alauda.io>
|
||||
Chengyu Zhu <hudson@cyzhu.com>
|
||||
Chentianze <cmoman@126.com>
|
||||
Chris Dias <cdias@microsoft.com>
|
||||
Chris McKinnel <chris.mckinnel@tangentlabs.co.uk>
|
||||
|
||||
8
AUTHORS
8
AUTHORS
@@ -2,6 +2,7 @@
|
||||
# This file lists all contributors to the repository.
|
||||
# See hack/generate-authors.sh to make modifications.
|
||||
|
||||
17neverends <ionianrise@gmail.com>
|
||||
7sunarni <710720732@qq.com>
|
||||
Aanand Prasad <aanand.prasad@gmail.com>
|
||||
Aarni Koskela <akx@iki.fi>
|
||||
@@ -189,6 +190,7 @@ Anes Hasicic <anes.hasicic@gmail.com>
|
||||
Angel Velazquez <angelcar@amazon.com>
|
||||
Anil Belur <askb23@gmail.com>
|
||||
Anil Madhavapeddy <anil@recoil.org>
|
||||
Anirudh Aithal <aithal@amazon.com>
|
||||
Ankit Jain <ajatkj@yahoo.co.in>
|
||||
Ankush Agarwal <ankushagarwal11@gmail.com>
|
||||
Anonmily <michelle@michelleliu.io>
|
||||
@@ -227,7 +229,7 @@ Arun Gupta <arun.gupta@gmail.com>
|
||||
Asad Saeeduddin <masaeedu@gmail.com>
|
||||
Asbjørn Enge <asbjorn@hanafjedle.net>
|
||||
Ashly Mathew <ashly.mathew@sap.com>
|
||||
Austin Vazquez <macedonv@amazon.com>
|
||||
Austin Vazquez <austin.vazquez.dev@gmail.com>
|
||||
averagehuman <averagehuman@users.noreply.github.com>
|
||||
Avi Das <andas222@gmail.com>
|
||||
Avi Kivity <avi@scylladb.com>
|
||||
@@ -377,6 +379,7 @@ Chen Qiu <cheney-90@hotmail.com>
|
||||
Cheng-mean Liu <soccerl@microsoft.com>
|
||||
Chengfei Shang <cfshang@alauda.io>
|
||||
Chengguang Xu <cgxu519@gmx.com>
|
||||
Chengyu Zhu <hudson@cyzhu.com>
|
||||
Chentianze <cmoman@126.com>
|
||||
Chenyang Yan <memory.yancy@gmail.com>
|
||||
chenyuzhu <chenyuzhi@oschina.cn>
|
||||
@@ -1209,6 +1212,7 @@ K. Heller <pestophagous@gmail.com>
|
||||
Kai Blin <kai@samba.org>
|
||||
Kai Qiang Wu (Kennan) <wkq5325@gmail.com>
|
||||
Kaijie Chen <chen@kaijie.org>
|
||||
Kaita Nakamura <kaita.nakamura0830@gmail.com>
|
||||
Kamil Domański <kamil@domanski.co>
|
||||
Kamjar Gerami <kami.gerami@gmail.com>
|
||||
Kanstantsin Shautsou <kanstantsin.sha@gmail.com>
|
||||
@@ -1485,6 +1489,7 @@ Matthias Kühnle <git.nivoc@neverbox.com>
|
||||
Matthias Rampke <mr@soundcloud.com>
|
||||
Matthieu Fronton <m@tthieu.fr>
|
||||
Matthieu Hauglustaine <matt.hauglustaine@gmail.com>
|
||||
Matthieu MOREL <matthieu.morel35@gmail.com>
|
||||
Mattias Jernberg <nostrad@gmail.com>
|
||||
Mauricio Garavaglia <mauricio@medallia.com>
|
||||
mauriyouth <mauriyouth@gmail.com>
|
||||
@@ -1874,6 +1879,7 @@ Robert Obryk <robryk@gmail.com>
|
||||
Robert Schneider <mail@shakeme.info>
|
||||
Robert Shade <robert.shade@gmail.com>
|
||||
Robert Stern <lexandro2000@gmail.com>
|
||||
Robert Sturla <robertsturla@outlook.com>
|
||||
Robert Terhaar <rterhaar@atlanticdynamic.com>
|
||||
Robert Wallis <smilingrob@gmail.com>
|
||||
Robert Wang <robert@arctic.tw>
|
||||
|
||||
67
Dockerfile
67
Dockerfile
@@ -1,22 +1,27 @@
|
||||
# syntax=docker/dockerfile:1.7
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_VERSION=1.23.8
|
||||
ARG GO_VERSION=1.24.3
|
||||
ARG BASE_DEBIAN_DISTRO="bookworm"
|
||||
ARG GOLANG_IMAGE="golang:${GO_VERSION}-${BASE_DEBIAN_DISTRO}"
|
||||
ARG XX_VERSION=1.6.1
|
||||
|
||||
ARG VPNKIT_VERSION=0.5.0
|
||||
# VPNKIT_VERSION is the version of the vpnkit binary which is used as a fallback
|
||||
# network driver for rootless.
|
||||
ARG VPNKIT_VERSION=0.6.0
|
||||
|
||||
# DOCKERCLI_VERSION is the version of the CLI to install in the dev-container.
|
||||
ARG DOCKERCLI_VERSION=v28.0.1
|
||||
ARG DOCKERCLI_VERSION=v28.2.0-rc.2
|
||||
ARG DOCKERCLI_REPOSITORY="https://github.com/docker/cli.git"
|
||||
|
||||
# cli version used for integration-cli tests
|
||||
ARG DOCKERCLI_INTEGRATION_REPOSITORY="https://github.com/docker/cli.git"
|
||||
ARG DOCKERCLI_INTEGRATION_VERSION=v18.06.3-ce
|
||||
|
||||
# BUILDX_VERSION is the version of buildx to install in the dev container.
|
||||
ARG BUILDX_VERSION=0.20.1
|
||||
ARG COMPOSE_VERSION=v2.33.1
|
||||
ARG BUILDX_VERSION=0.24.0
|
||||
|
||||
# COMPOSE_VERSION is the version of compose to install in the dev container.
|
||||
ARG COMPOSE_VERSION=v2.36.2
|
||||
|
||||
ARG SYSTEMD="false"
|
||||
ARG FIREWALLD="false"
|
||||
@@ -73,41 +78,8 @@ RUN --mount=type=cache,sharing=locked,id=moby-criu-aptlib,target=/var/lib/apt \
|
||||
&& /build/criu --version
|
||||
|
||||
# registry
|
||||
FROM base AS registry-src
|
||||
WORKDIR /usr/src/registry
|
||||
RUN git init . && git remote add origin "https://github.com/distribution/distribution.git"
|
||||
|
||||
FROM base AS registry
|
||||
WORKDIR /go/src/github.com/docker/distribution
|
||||
|
||||
# REGISTRY_VERSION_SCHEMA1 specifies the version of the registry to build and
|
||||
# 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
|
||||
# manifests. This version of the registry is not working on arm64, so installation
|
||||
# is skipped on that architecture.
|
||||
ARG REGISTRY_VERSION_SCHEMA1=v2.1.0
|
||||
ARG TARGETPLATFORM
|
||||
RUN --mount=from=registry-src,src=/usr/src/registry,rw \
|
||||
--mount=type=cache,target=/root/.cache/go-build,id=registry-build-$TARGETPLATFORM \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
--mount=type=tmpfs,target=/go/src <<EOT
|
||||
set -ex
|
||||
export GOPATH="/go/src/github.com/docker/distribution/Godeps/_workspace:$GOPATH"
|
||||
# Make the /build directory no matter what so that it doesn't fail on arm64 or
|
||||
# any other platform where we don't build this registry
|
||||
mkdir /build
|
||||
case $TARGETPLATFORM in
|
||||
linux/amd64|linux/arm/v7|linux/ppc64le|linux/s390x)
|
||||
git fetch -q --depth 1 origin "${REGISTRY_VERSION_SCHEMA1}" +refs/tags/*:refs/tags/*
|
||||
git checkout -q FETCH_HEAD
|
||||
CGO_ENABLED=0 xx-go build -o /build/registry-v2-schema1 -v ./cmd/registry
|
||||
xx-verify /build/registry-v2-schema1
|
||||
;;
|
||||
esac
|
||||
EOT
|
||||
|
||||
FROM distribution/distribution:$REGISTRY_VERSION AS registry-v2
|
||||
RUN mkdir /build && mv /bin/registry /build/registry-v2
|
||||
FROM distribution/distribution:$REGISTRY_VERSION AS registry
|
||||
RUN mkdir /build && mv /bin/registry /build/registry
|
||||
|
||||
# go-swagger
|
||||
FROM base AS swagger-src
|
||||
@@ -230,10 +202,10 @@ FROM binary-dummy AS containerd-windows
|
||||
FROM containerd-${TARGETOS} AS containerd
|
||||
|
||||
FROM base AS golangci_lint
|
||||
ARG GOLANGCI_LINT_VERSION=v1.64.5
|
||||
ARG GOLANGCI_LINT_VERSION=v2.1.5
|
||||
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
GOBIN=/build/ GO111MODULE=on go install "github.com/golangci/golangci-lint/cmd/golangci-lint@${GOLANGCI_LINT_VERSION}" \
|
||||
GOBIN=/build/ GO111MODULE=on go install "github.com/golangci/golangci-lint/v2/cmd/golangci-lint@${GOLANGCI_LINT_VERSION}" \
|
||||
&& /build/golangci-lint --version
|
||||
|
||||
FROM base AS gotestsum
|
||||
@@ -387,7 +359,8 @@ FROM binary-dummy AS rootlesskit-windows
|
||||
FROM rootlesskit-${TARGETOS} AS rootlesskit
|
||||
|
||||
FROM base AS crun
|
||||
ARG CRUN_VERSION=1.12
|
||||
# CRUN_VERSION is the version of crun to install in the dev-container.
|
||||
ARG CRUN_VERSION=1.21
|
||||
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 \
|
||||
apt-get update && apt-get install -y --no-install-recommends \
|
||||
@@ -418,8 +391,8 @@ FROM scratch AS vpnkit-linux-arm
|
||||
FROM scratch AS vpnkit-linux-ppc64le
|
||||
FROM scratch AS vpnkit-linux-riscv64
|
||||
FROM scratch AS vpnkit-linux-s390x
|
||||
FROM djs55/vpnkit:${VPNKIT_VERSION} AS vpnkit-linux-amd64
|
||||
FROM djs55/vpnkit:${VPNKIT_VERSION} AS vpnkit-linux-arm64
|
||||
FROM moby/vpnkit-bin:${VPNKIT_VERSION} AS vpnkit-linux-amd64
|
||||
FROM moby/vpnkit-bin:${VPNKIT_VERSION} AS vpnkit-linux-arm64
|
||||
FROM vpnkit-linux-${TARGETARCH} AS vpnkit-linux
|
||||
FROM vpnkit-${TARGETOS} AS vpnkit
|
||||
|
||||
@@ -461,7 +434,6 @@ COPY --link --from=delve /build/ /usr/local/bin/
|
||||
COPY --link --from=gowinres /build/ /usr/local/bin/
|
||||
COPY --link --from=tini /build/ /usr/local/bin/
|
||||
COPY --link --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
|
||||
# unstable, and we're currently not using it in CI.
|
||||
@@ -540,6 +512,7 @@ RUN --mount=type=cache,sharing=locked,id=moby-dev-aptlib,target=/var/lib/apt \
|
||||
libnl-3-200 \
|
||||
libprotobuf-c1 \
|
||||
libyajl2 \
|
||||
nano \
|
||||
net-tools \
|
||||
netcat-openbsd \
|
||||
patch \
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
# This represents the bare minimum required to build and test Docker.
|
||||
|
||||
ARG GO_VERSION=1.23.8
|
||||
ARG GO_VERSION=1.24.3
|
||||
|
||||
ARG BASE_DEBIAN_DISTRO="bookworm"
|
||||
ARG GOLANG_IMAGE="golang:${GO_VERSION}-${BASE_DEBIAN_DISTRO}"
|
||||
|
||||
@@ -161,9 +161,11 @@ FROM ${WINDOWS_BASE_IMAGE}:${WINDOWS_BASE_IMAGE_TAG}
|
||||
# Use PowerShell as the default shell
|
||||
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
|
||||
|
||||
ARG GO_VERSION=1.23.8
|
||||
ARG GO_VERSION=1.24.3
|
||||
ARG GOTESTSUM_VERSION=v1.12.0
|
||||
ARG GOWINRES_VERSION=v0.3.1
|
||||
|
||||
# GOWINRES_VERSION is the version of go-winres to install.
|
||||
ARG GOWINRES_VERSION=v0.3.3
|
||||
ARG CONTAINERD_VERSION=v1.7.27
|
||||
|
||||
# Environment variable notes:
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"akerouanton","Albin Kerouanton","albinker@gmail.com"
|
||||
"AkihiroSuda","Akihiro Suda","akihiro.suda.cz@hco.ntt.co.jp"
|
||||
"austinvazquez","Austin Vazquez","macedonv@amazon.com"
|
||||
"corhere","Cory Snider","csnider@mirantis.com"
|
||||
"cpuguy83","Brian Goff","cpuguy83@gmail.com"
|
||||
"robmry","Rob Murray","rob.murray@docker.com"
|
||||
"thaJeztah","Sebastiaan van Stijn","github@gone.nl"
|
||||
@@ -17,7 +18,6 @@
|
||||
# REVIEWERS
|
||||
# GitHub ID, Name, Email address, GPG fingerprint
|
||||
"coolljt0725","Lei Jitang","leijitang@huawei.com"
|
||||
"corhere","Cory Snider","csnider@mirantis.com"
|
||||
"crazy-max","Kevin Alvarez","contact@crazymax.dev"
|
||||
"dmcgowan","Derek McGowan","derek@mcgstyle.net"
|
||||
"estesp","Phil Estes","estesp@linux.vnet.ibm.com"
|
||||
|
||||
4
Makefile
4
Makefile
@@ -83,11 +83,11 @@ DOCKER_ENVS := \
|
||||
# to allow `make BIND_DIR=. shell` or `make BIND_DIR= test`
|
||||
# (default to no bind mount if DOCKER_HOST is set)
|
||||
# note: BINDDIR is supported for backwards-compatibility here
|
||||
BIND_DIR := $(if $(BINDDIR),$(BINDDIR),$(if $(DOCKER_HOST),,bundles))
|
||||
BIND_DIR := $(if $(BINDDIR),$(BINDDIR),$(if $(DOCKER_HOST),,.))
|
||||
|
||||
# DOCKER_MOUNT can be overridden, but use at your own risk!
|
||||
ifndef DOCKER_MOUNT
|
||||
DOCKER_MOUNT := $(if $(BIND_DIR),-v "$(CURDIR)/$(BIND_DIR):/go/src/github.com/docker/docker/$(BIND_DIR)")
|
||||
DOCKER_MOUNT := $(if $(BIND_DIR),-v "$(BIND_DIR):/go/src/github.com/docker/docker/$(BIND_DIR)")
|
||||
DOCKER_MOUNT := $(if $(DOCKER_BINDDIR_MOUNT_OPTS),$(DOCKER_MOUNT):$(DOCKER_BINDDIR_MOUNT_OPTS),$(DOCKER_MOUNT))
|
||||
|
||||
# This allows the test suite to be able to run without worrying about the underlying fs used by the container running the daemon (e.g. aufs-on-aufs), so long as the host running the container is running a supported fs.
|
||||
|
||||
@@ -3,7 +3,7 @@ package api // import "github.com/docker/docker/api"
|
||||
// Common constants for daemon and client.
|
||||
const (
|
||||
// DefaultVersion of the current REST API.
|
||||
DefaultVersion = "1.49"
|
||||
DefaultVersion = "1.50"
|
||||
|
||||
// MinSupportedAPIVersion is the minimum API version that can be supported
|
||||
// by the API server, specified as "major.minor". Note that the daemon
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"strconv"
|
||||
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
"github.com/docker/docker/api/types/build"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
"github.com/docker/docker/builder"
|
||||
buildkit "github.com/docker/docker/builder/builder-next"
|
||||
@@ -52,37 +52,37 @@ func (b *Backend) RegisterGRPC(s *grpc.Server) {
|
||||
// Build builds an image from a Source
|
||||
func (b *Backend) Build(ctx context.Context, config backend.BuildConfig) (string, error) {
|
||||
options := config.Options
|
||||
useBuildKit := options.Version == types.BuilderBuildKit
|
||||
useBuildKit := options.Version == build.BuilderBuildKit
|
||||
|
||||
tags, err := sanitizeRepoAndTags(options.Tags)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var build *builder.Result
|
||||
var buildResult *builder.Result
|
||||
if useBuildKit {
|
||||
build, err = b.buildkit.Build(ctx, config)
|
||||
buildResult, err = b.buildkit.Build(ctx, config)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
build, err = b.builder.Build(ctx, config)
|
||||
buildResult, err = b.builder.Build(ctx, config)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
if build == nil {
|
||||
if buildResult == nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
imageID := build.ImageID
|
||||
imageID := buildResult.ImageID
|
||||
if options.Squash {
|
||||
if imageID, err = squashBuild(build, b.imageComponent); err != nil {
|
||||
if imageID, err = squashBuild(buildResult, b.imageComponent); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if config.ProgressWriter.AuxFormatter != nil {
|
||||
if err = config.ProgressWriter.AuxFormatter.Emit("moby.image.id", types.BuildResult{ID: imageID}); err != nil {
|
||||
if err = config.ProgressWriter.AuxFormatter.Emit("moby.image.id", build.Result{ID: imageID}); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
@@ -97,7 +97,7 @@ func (b *Backend) Build(ctx context.Context, config backend.BuildConfig) (string
|
||||
}
|
||||
|
||||
// PruneCache removes all cached build sources
|
||||
func (b *Backend) PruneCache(ctx context.Context, opts types.BuildCachePruneOptions) (*types.BuildCachePruneReport, error) {
|
||||
func (b *Backend) PruneCache(ctx context.Context, opts build.CachePruneOptions) (*build.CachePruneReport, error) {
|
||||
buildCacheSize, cacheIDs, err := b.buildkit.Prune(ctx, opts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to prune build cache")
|
||||
@@ -107,7 +107,7 @@ func (b *Backend) PruneCache(ctx context.Context, opts types.BuildCachePruneOpti
|
||||
"reclaimed": strconv.FormatInt(buildCacheSize, 10),
|
||||
},
|
||||
})
|
||||
return &types.BuildCachePruneReport{SpaceReclaimed: uint64(buildCacheSize), CachesDeleted: cacheIDs}, nil
|
||||
return &build.CachePruneReport{SpaceReclaimed: uint64(buildCacheSize), CachesDeleted: cacheIDs}, nil
|
||||
}
|
||||
|
||||
// Cancel cancels the build by ID
|
||||
|
||||
@@ -24,7 +24,7 @@ func tagImages(ctx context.Context, ic ImageComponent, stdout io.Writer, imageID
|
||||
// sanitizeRepoAndTags parses the raw "t" parameter received from the client
|
||||
// to a slice of repoAndTag. It removes duplicates, and validates each name
|
||||
// to not contain a digest.
|
||||
func sanitizeRepoAndTags(names []string) (repoAndTags []reference.Named, err error) {
|
||||
func sanitizeRepoAndTags(names []string) (repoAndTags []reference.Named, _ error) {
|
||||
uniqNames := map[string]struct{}{}
|
||||
for _, repo := range names {
|
||||
if repo == "" {
|
||||
|
||||
@@ -8,15 +8,10 @@ import (
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/containerd/log"
|
||||
"github.com/docker/distribution/registry/api/errcode"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
type causer interface {
|
||||
Cause() error
|
||||
}
|
||||
|
||||
// FromError retrieves status code from error message.
|
||||
func FromError(err error) int {
|
||||
if err == nil {
|
||||
@@ -24,48 +19,55 @@ func FromError(err error) int {
|
||||
return http.StatusInternalServerError
|
||||
}
|
||||
|
||||
// Stop right there
|
||||
// Are you sure you should be adding a new error class here? Do one of the existing ones work?
|
||||
// Resolve the error to ensure status is chosen from the first outermost error
|
||||
rerr := cerrdefs.Resolve(err)
|
||||
|
||||
// Note that the below functions are already checking the error causal chain for matches.
|
||||
// Only check errors from the errdefs package, no new error type checking may be added
|
||||
switch {
|
||||
case errdefs.IsNotFound(err):
|
||||
case cerrdefs.IsNotFound(rerr):
|
||||
return http.StatusNotFound
|
||||
case errdefs.IsInvalidParameter(err):
|
||||
case cerrdefs.IsInvalidArgument(rerr):
|
||||
return http.StatusBadRequest
|
||||
case errdefs.IsConflict(err):
|
||||
case cerrdefs.IsConflict(rerr):
|
||||
return http.StatusConflict
|
||||
case errdefs.IsUnauthorized(err):
|
||||
case cerrdefs.IsUnauthorized(rerr):
|
||||
return http.StatusUnauthorized
|
||||
case errdefs.IsUnavailable(err):
|
||||
case cerrdefs.IsUnavailable(rerr):
|
||||
return http.StatusServiceUnavailable
|
||||
case errdefs.IsForbidden(err):
|
||||
case cerrdefs.IsPermissionDenied(rerr):
|
||||
return http.StatusForbidden
|
||||
case errdefs.IsNotModified(err):
|
||||
case cerrdefs.IsNotModified(rerr):
|
||||
return http.StatusNotModified
|
||||
case errdefs.IsNotImplemented(err):
|
||||
case cerrdefs.IsNotImplemented(rerr):
|
||||
return http.StatusNotImplemented
|
||||
case errdefs.IsSystem(err) || errdefs.IsUnknown(err) || errdefs.IsDataLoss(err) || errdefs.IsDeadline(err) || errdefs.IsCancelled(err):
|
||||
case cerrdefs.IsInternal(rerr) || cerrdefs.IsDataLoss(rerr) || cerrdefs.IsDeadlineExceeded(rerr) || cerrdefs.IsCanceled(rerr):
|
||||
return http.StatusInternalServerError
|
||||
default:
|
||||
if statusCode := statusCodeFromGRPCError(err); statusCode != http.StatusInternalServerError {
|
||||
return statusCode
|
||||
}
|
||||
if statusCode := statusCodeFromContainerdError(err); statusCode != http.StatusInternalServerError {
|
||||
return statusCode
|
||||
}
|
||||
if statusCode := statusCodeFromDistributionError(err); statusCode != http.StatusInternalServerError {
|
||||
return statusCode
|
||||
}
|
||||
if e, ok := err.(causer); ok {
|
||||
return FromError(e.Cause())
|
||||
switch e := err.(type) {
|
||||
case interface{ Unwrap() error }:
|
||||
return FromError(e.Unwrap())
|
||||
case interface{ Unwrap() []error }:
|
||||
for _, ue := range e.Unwrap() {
|
||||
if statusCode := FromError(ue); statusCode != http.StatusInternalServerError {
|
||||
return statusCode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.G(context.TODO()).WithFields(log.Fields{
|
||||
"module": "api",
|
||||
"error": err,
|
||||
"error_type": fmt.Sprintf("%T", err),
|
||||
}).Debug("FIXME: Got an API for which error does not match any expected type!!!")
|
||||
if !cerrdefs.IsUnknown(err) {
|
||||
log.G(context.TODO()).WithFields(log.Fields{
|
||||
"module": "api",
|
||||
"error": err,
|
||||
"error_type": fmt.Sprintf("%T", err),
|
||||
}).Debug("FIXME: Got an API for which error does not match any expected type!!!")
|
||||
}
|
||||
|
||||
return http.StatusInternalServerError
|
||||
}
|
||||
@@ -120,24 +122,3 @@ func statusCodeFromDistributionError(err error) int {
|
||||
}
|
||||
return http.StatusInternalServerError
|
||||
}
|
||||
|
||||
// statusCodeFromContainerdError returns status code for containerd errors when
|
||||
// consumed directly (not through gRPC)
|
||||
func statusCodeFromContainerdError(err error) int {
|
||||
switch {
|
||||
case cerrdefs.IsInvalidArgument(err):
|
||||
return http.StatusBadRequest
|
||||
case cerrdefs.IsNotFound(err):
|
||||
return http.StatusNotFound
|
||||
case cerrdefs.IsAlreadyExists(err):
|
||||
return http.StatusConflict
|
||||
case cerrdefs.IsFailedPrecondition(err):
|
||||
return http.StatusPreconditionFailed
|
||||
case cerrdefs.IsUnavailable(err):
|
||||
return http.StatusServiceUnavailable
|
||||
case cerrdefs.IsNotImplemented(err):
|
||||
return http.StatusNotImplemented
|
||||
default:
|
||||
return http.StatusInternalServerError
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,12 @@ import (
|
||||
|
||||
// BoolValue transforms a form value in different formats into a boolean type.
|
||||
func BoolValue(r *http.Request, k string) bool {
|
||||
s := strings.ToLower(strings.TrimSpace(r.FormValue(k)))
|
||||
return !(s == "" || s == "0" || s == "no" || s == "false" || s == "none")
|
||||
switch strings.ToLower(strings.TrimSpace(r.FormValue(k))) {
|
||||
case "", "0", "no", "false", "none":
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// BoolValueOrDefault returns the default bool passed if the query param is
|
||||
@@ -158,3 +162,22 @@ func DecodePlatform(platformJSON string) (*ocispec.Platform, error) {
|
||||
|
||||
return &p, nil
|
||||
}
|
||||
|
||||
// DecodePlatforms decodes the OCI platform JSON string into a Platform struct.
|
||||
//
|
||||
// Typically, the argument is a value of: r.Form["platform"]
|
||||
func DecodePlatforms(platformJSONs []string) ([]ocispec.Platform, error) {
|
||||
if len(platformJSONs) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var output []ocispec.Platform
|
||||
for _, platform := range platformJSONs {
|
||||
p, err := DecodePlatform(platform)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
output = append(output, *p)
|
||||
}
|
||||
return output, nil
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/errdefs"
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
@@ -225,7 +225,7 @@ func TestDecodePlatform(t *testing.T) {
|
||||
p, err := DecodePlatform(tc.platformJSON)
|
||||
assert.Check(t, is.DeepEqual(p, tc.expected))
|
||||
if tc.expectedErr != "" {
|
||||
assert.Check(t, errdefs.IsInvalidParameter(err))
|
||||
assert.Check(t, cerrdefs.IsInvalidArgument(err))
|
||||
assert.Check(t, is.Error(err, tc.expectedErr))
|
||||
} else {
|
||||
assert.Check(t, err)
|
||||
|
||||
@@ -3,8 +3,8 @@ package build // import "github.com/docker/docker/api/server/router/build"
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
"github.com/docker/docker/api/types/build"
|
||||
)
|
||||
|
||||
// Backend abstracts an image builder whose only purpose is to build an image referenced by an imageID.
|
||||
@@ -13,8 +13,8 @@ type Backend interface {
|
||||
// TODO: make this return a reference instead of string
|
||||
Build(context.Context, backend.BuildConfig) (string, error)
|
||||
|
||||
// Prune build cache
|
||||
PruneCache(context.Context, types.BuildCachePruneOptions) (*types.BuildCachePruneReport, error)
|
||||
// PruneCache prunes the build cache.
|
||||
PruneCache(context.Context, build.CachePruneOptions) (*build.CachePruneReport, error)
|
||||
Cancel(context.Context, string) error
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"runtime"
|
||||
|
||||
"github.com/docker/docker/api/server/router"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/build"
|
||||
)
|
||||
|
||||
// buildRouter is a router to talk with the build controller
|
||||
@@ -25,15 +25,15 @@ func NewRouter(b Backend, d experimentalProvider) router.Router {
|
||||
}
|
||||
|
||||
// Routes returns the available routers to the build controller
|
||||
func (r *buildRouter) Routes() []router.Route {
|
||||
return r.routes
|
||||
func (br *buildRouter) Routes() []router.Route {
|
||||
return br.routes
|
||||
}
|
||||
|
||||
func (r *buildRouter) initRoutes() {
|
||||
r.routes = []router.Route{
|
||||
router.NewPostRoute("/build", r.postBuild),
|
||||
router.NewPostRoute("/build/prune", r.postPrune),
|
||||
router.NewPostRoute("/build/cancel", r.postCancel),
|
||||
func (br *buildRouter) initRoutes() {
|
||||
br.routes = []router.Route{
|
||||
router.NewPostRoute("/build", br.postBuild),
|
||||
router.NewPostRoute("/build/prune", br.postPrune),
|
||||
router.NewPostRoute("/build/cancel", br.postCancel),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,15 +46,22 @@ func (r *buildRouter) initRoutes() {
|
||||
//
|
||||
// This value is only a recommendation as advertised by the daemon, and it is
|
||||
// up to the client to choose which builder to use.
|
||||
func BuilderVersion(features map[string]bool) types.BuilderVersion {
|
||||
func BuilderVersion(features map[string]bool) build.BuilderVersion {
|
||||
// TODO(thaJeztah) move the default to daemon/config
|
||||
bv := build.BuilderBuildKit
|
||||
if runtime.GOOS == "windows" {
|
||||
return types.BuilderV1
|
||||
// BuildKit is not yet the default on Windows.
|
||||
bv = build.BuilderV1
|
||||
}
|
||||
|
||||
bv := types.BuilderBuildKit
|
||||
if v, ok := features["buildkit"]; ok && !v {
|
||||
bv = types.BuilderV1
|
||||
// Allow the features field in the daemon config to override the
|
||||
// default builder to advertise.
|
||||
if enable, ok := features["buildkit"]; ok {
|
||||
if enable {
|
||||
bv = build.BuilderBuildKit
|
||||
} else {
|
||||
bv = build.BuilderV1
|
||||
}
|
||||
}
|
||||
return bv
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ import (
|
||||
|
||||
"github.com/containerd/log"
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
"github.com/docker/docker/api/types/build"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
@@ -35,9 +35,9 @@ type invalidParam struct {
|
||||
|
||||
func (e invalidParam) InvalidParameter() {}
|
||||
|
||||
func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBuildOptions, error) {
|
||||
options := &types.ImageBuildOptions{
|
||||
Version: types.BuilderV1, // Builder V1 is the default, but can be overridden
|
||||
func newImageBuildOptions(ctx context.Context, r *http.Request) (*build.ImageBuildOptions, error) {
|
||||
options := &build.ImageBuildOptions{
|
||||
Version: build.BuilderV1, // Builder V1 is the default, but can be overridden
|
||||
Dockerfile: r.FormValue("dockerfile"),
|
||||
SuppressOutput: httputils.BoolValue(r, "q"),
|
||||
NoCache: httputils.BoolValue(r, "nocache"),
|
||||
@@ -81,7 +81,7 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui
|
||||
if versions.GreaterThanOrEqualTo(version, "1.40") {
|
||||
outputsJSON := r.FormValue("outputs")
|
||||
if outputsJSON != "" {
|
||||
var outputs []types.ImageBuildOutput
|
||||
var outputs []build.ImageBuildOutput
|
||||
if err := json.Unmarshal([]byte(outputsJSON), &outputs); err != nil {
|
||||
return nil, invalidParam{errors.Wrap(err, "invalid outputs specified")}
|
||||
}
|
||||
@@ -159,12 +159,12 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui
|
||||
return options, nil
|
||||
}
|
||||
|
||||
func parseVersion(s string) (types.BuilderVersion, error) {
|
||||
switch types.BuilderVersion(s) {
|
||||
case types.BuilderV1:
|
||||
return types.BuilderV1, nil
|
||||
case types.BuilderBuildKit:
|
||||
return types.BuilderBuildKit, nil
|
||||
func parseVersion(s string) (build.BuilderVersion, error) {
|
||||
switch build.BuilderVersion(s) {
|
||||
case build.BuilderV1:
|
||||
return build.BuilderV1, nil
|
||||
case build.BuilderBuildKit:
|
||||
return build.BuilderBuildKit, nil
|
||||
default:
|
||||
return "", invalidParam{errors.Errorf("invalid version %q", s)}
|
||||
}
|
||||
@@ -179,7 +179,7 @@ func (br *buildRouter) postPrune(ctx context.Context, w http.ResponseWriter, r *
|
||||
return err
|
||||
}
|
||||
|
||||
opts := types.BuildCachePruneOptions{
|
||||
opts := build.CachePruneOptions{
|
||||
All: httputils.BoolValue(r, "all"),
|
||||
Filters: fltrs,
|
||||
}
|
||||
@@ -197,17 +197,18 @@ func (br *buildRouter) postPrune(ctx context.Context, w http.ResponseWriter, r *
|
||||
|
||||
version := httputils.VersionFromContext(ctx)
|
||||
if versions.GreaterThanOrEqualTo(version, "1.48") {
|
||||
bs, err := parseBytesFromFormValue("reserved-space")
|
||||
if err != nil {
|
||||
if bs, err := parseBytesFromFormValue("reserved-space"); err != nil {
|
||||
return err
|
||||
} else if bs == 0 {
|
||||
// Deprecated parameter. Only checked if reserved-space is not used.
|
||||
bs, err = parseBytesFromFormValue("keep-storage")
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
if bs == 0 {
|
||||
// Deprecated parameter. Only checked if reserved-space is not used.
|
||||
bs, err = parseBytesFromFormValue("keep-storage")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
opts.ReservedSpace = bs
|
||||
}
|
||||
opts.ReservedSpace = bs
|
||||
|
||||
if bs, err := parseBytesFromFormValue("max-used-space"); err != nil {
|
||||
return err
|
||||
@@ -222,11 +223,11 @@ func (br *buildRouter) postPrune(ctx context.Context, w http.ResponseWriter, r *
|
||||
}
|
||||
} else {
|
||||
// Only keep-storage was valid in pre-1.48 versions.
|
||||
bs, err := parseBytesFromFormValue("keep-storage")
|
||||
if err != nil {
|
||||
if bs, err := parseBytesFromFormValue("keep-storage"); err != nil {
|
||||
return err
|
||||
} else {
|
||||
opts.ReservedSpace = bs
|
||||
}
|
||||
opts.ReservedSpace = bs
|
||||
}
|
||||
|
||||
report, err := br.backend.PruneCache(ctx, opts)
|
||||
|
||||
@@ -23,14 +23,14 @@ func NewRouter(b Backend, decoder httputils.ContainerDecoder) router.Router {
|
||||
}
|
||||
|
||||
// Routes returns the available routers to the checkpoint controller
|
||||
func (r *checkpointRouter) Routes() []router.Route {
|
||||
return r.routes
|
||||
func (cr *checkpointRouter) Routes() []router.Route {
|
||||
return cr.routes
|
||||
}
|
||||
|
||||
func (r *checkpointRouter) initRoutes() {
|
||||
r.routes = []router.Route{
|
||||
router.NewGetRoute("/containers/{name:.*}/checkpoints", r.getContainerCheckpoints, router.Experimental),
|
||||
router.NewPostRoute("/containers/{name:.*}/checkpoints", r.postContainerCheckpoint, router.Experimental),
|
||||
router.NewDeleteRoute("/containers/{name}/checkpoints/{checkpoint}", r.deleteContainerCheckpoint, router.Experimental),
|
||||
func (cr *checkpointRouter) initRoutes() {
|
||||
cr.routes = []router.Route{
|
||||
router.NewGetRoute("/containers/{name:.*}/checkpoints", cr.getContainerCheckpoints, router.Experimental),
|
||||
router.NewPostRoute("/containers/{name:.*}/checkpoints", cr.postContainerCheckpoint, router.Experimental),
|
||||
router.NewDeleteRoute("/containers/{name}/checkpoints/{checkpoint}", cr.deleteContainerCheckpoint, router.Experimental),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"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 (cr *checkpointRouter) postContainerCheckpoint(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -18,7 +18,7 @@ func (s *checkpointRouter) postContainerCheckpoint(ctx context.Context, w http.R
|
||||
return err
|
||||
}
|
||||
|
||||
err := s.backend.CheckpointCreate(vars["name"], options)
|
||||
err := cr.backend.CheckpointCreate(vars["name"], options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -27,12 +27,12 @@ func (s *checkpointRouter) postContainerCheckpoint(ctx context.Context, w http.R
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *checkpointRouter) getContainerCheckpoints(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
func (cr *checkpointRouter) getContainerCheckpoints(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
checkpoints, err := s.backend.CheckpointList(vars["name"], checkpoint.ListOptions{
|
||||
checkpoints, err := cr.backend.CheckpointList(vars["name"], checkpoint.ListOptions{
|
||||
CheckpointDir: r.Form.Get("dir"),
|
||||
})
|
||||
if err != nil {
|
||||
@@ -42,12 +42,12 @@ func (s *checkpointRouter) getContainerCheckpoints(ctx context.Context, w http.R
|
||||
return httputils.WriteJSON(w, http.StatusOK, checkpoints)
|
||||
}
|
||||
|
||||
func (s *checkpointRouter) deleteContainerCheckpoint(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
func (cr *checkpointRouter) deleteContainerCheckpoint(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err := s.backend.CheckpointDelete(vars["name"], checkpoint.DeleteOptions{
|
||||
err := cr.backend.CheckpointDelete(vars["name"], checkpoint.DeleteOptions{
|
||||
CheckpointDir: r.Form.Get("dir"),
|
||||
CheckpointID: vars["checkpoint"],
|
||||
})
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
containerpkg "github.com/docker/docker/container"
|
||||
"github.com/moby/go-archive"
|
||||
)
|
||||
|
||||
@@ -41,7 +40,7 @@ type stateBackend interface {
|
||||
ContainerStop(ctx context.Context, name string, options container.StopOptions) error
|
||||
ContainerUnpause(name string) error
|
||||
ContainerUpdate(name string, hostConfig *container.HostConfig) (container.UpdateResponse, error)
|
||||
ContainerWait(ctx context.Context, name string, condition containerpkg.WaitCondition) (<-chan containerpkg.StateStatus, error)
|
||||
ContainerWait(ctx context.Context, name string, condition container.WaitCondition) (<-chan container.StateStatus, error)
|
||||
}
|
||||
|
||||
// monitorBackend includes functions to implement to provide containers monitoring functionality.
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
"github.com/docker/docker/api/types/mount"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
containerpkg "github.com/docker/docker/container"
|
||||
networkSettings "github.com/docker/docker/daemon/network"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/libnetwork/netlabel"
|
||||
@@ -164,7 +163,7 @@ func (c *containerRouter) getContainersLogs(ctx context.Context, w http.Response
|
||||
// any error after the stream starts (i.e. container not found, wrong parameters)
|
||||
// with the appropriate status code.
|
||||
stdout, stderr := httputils.BoolValue(r, "stdout"), httputils.BoolValue(r, "stderr")
|
||||
if !(stdout || stderr) {
|
||||
if !stdout && !stderr {
|
||||
return errdefs.InvalidParameter(errors.New("Bad parameters: you must choose at least one stream"))
|
||||
}
|
||||
|
||||
@@ -337,7 +336,7 @@ func (c *containerRouter) postContainersWait(ctx context.Context, w http.Respons
|
||||
legacyRemovalWaitPre134 := false
|
||||
|
||||
// The wait condition defaults to "not-running".
|
||||
waitCondition := containerpkg.WaitConditionNotRunning
|
||||
waitCondition := container.WaitConditionNotRunning
|
||||
if !legacyBehaviorPre130 {
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
@@ -345,11 +344,11 @@ func (c *containerRouter) postContainersWait(ctx context.Context, w http.Respons
|
||||
if v := r.Form.Get("condition"); v != "" {
|
||||
switch container.WaitCondition(v) {
|
||||
case container.WaitConditionNotRunning:
|
||||
waitCondition = containerpkg.WaitConditionNotRunning
|
||||
waitCondition = container.WaitConditionNotRunning
|
||||
case container.WaitConditionNextExit:
|
||||
waitCondition = containerpkg.WaitConditionNextExit
|
||||
waitCondition = container.WaitConditionNextExit
|
||||
case container.WaitConditionRemoved:
|
||||
waitCondition = containerpkg.WaitConditionRemoved
|
||||
waitCondition = container.WaitConditionRemoved
|
||||
legacyRemovalWaitPre134 = versions.LessThan(version, "1.34")
|
||||
default:
|
||||
return errdefs.InvalidParameter(errors.Errorf("invalid condition: %q", v))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.22
|
||||
//go:build go1.23
|
||||
|
||||
package container // import "github.com/docker/docker/api/server/router/container"
|
||||
|
||||
|
||||
@@ -18,14 +18,14 @@ func NewRouter(backend Backend) router.Router {
|
||||
}
|
||||
|
||||
// Routes returns the available routes
|
||||
func (r *distributionRouter) Routes() []router.Route {
|
||||
return r.routes
|
||||
func (dr *distributionRouter) Routes() []router.Route {
|
||||
return dr.routes
|
||||
}
|
||||
|
||||
// initRoutes initializes the routes in the distribution router
|
||||
func (r *distributionRouter) initRoutes() {
|
||||
r.routes = []router.Route{
|
||||
func (dr *distributionRouter) initRoutes() {
|
||||
dr.routes = []router.Route{
|
||||
// GET
|
||||
router.NewGetRoute("/distribution/{name:.*}/json", r.getDistributionInfo),
|
||||
router.NewGetRoute("/distribution/{name:.*}/json", dr.getDistributionInfo),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/distribution"
|
||||
@@ -19,7 +18,7 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (s *distributionRouter) getDistributionInfo(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
func (dr *distributionRouter) getDistributionInfo(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -45,7 +44,7 @@ func (s *distributionRouter) getDistributionInfo(ctx context.Context, w http.Res
|
||||
// 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)
|
||||
repos, err := dr.backend.GetRepositories(ctx, namedRef, authConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -66,7 +65,7 @@ func (s *distributionRouter) getDistributionInfo(ctx context.Context, w http.Res
|
||||
// - 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)
|
||||
distributionInspect, err := dr.fetchManifest(ctx, repo, namedRef)
|
||||
if err != nil {
|
||||
lastErr = err
|
||||
continue
|
||||
@@ -76,7 +75,7 @@ func (s *distributionRouter) getDistributionInfo(ctx context.Context, w http.Res
|
||||
return lastErr
|
||||
}
|
||||
|
||||
func (s *distributionRouter) fetchManifest(ctx context.Context, distrepo distribution.Repository, namedRef reference.Named) (registry.DistributionInspect, error) {
|
||||
func (dr *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 {
|
||||
namedRef = reference.TagNameOnly(namedRef)
|
||||
@@ -154,15 +153,10 @@ func (s *distributionRouter) fetchManifest(ctx context.Context, distrepo distrib
|
||||
distributionInspect.Platforms = append(distributionInspect.Platforms, platform)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(thaJeztah); we only use this to produce a nice error, but as a result, we can't remove libtrust as dependency - see if we can reduce the dependencies, but still able to detect it's a deprecated manifest
|
||||
case *schema1.SignedManifest:
|
||||
if os.Getenv("DOCKER_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE") == "" {
|
||||
return registry.DistributionInspect{}, distributionpkg.DeprecatedSchema1ImageError(namedRef)
|
||||
}
|
||||
platform := ocispec.Platform{
|
||||
Architecture: mnfstObj.Architecture,
|
||||
OS: "linux",
|
||||
}
|
||||
distributionInspect.Platforms = append(distributionInspect.Platforms, platform)
|
||||
return registry.DistributionInspect{}, distributionpkg.DeprecatedSchema1ImageError(namedRef)
|
||||
}
|
||||
return distributionInspect, nil
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.22
|
||||
//go:build go1.23
|
||||
|
||||
package grpc // import "github.com/docker/docker/api/server/router/grpc"
|
||||
|
||||
@@ -60,7 +60,7 @@ func (gr *grpcRouter) initRoutes() {
|
||||
}
|
||||
}
|
||||
|
||||
func unaryInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) {
|
||||
func unaryInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, _ 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.
|
||||
@@ -68,11 +68,11 @@ func unaryInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo,
|
||||
return handler(ctx, req)
|
||||
}
|
||||
|
||||
resp, err = handler(ctx, req)
|
||||
resp, err := handler(ctx, req)
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).Error(info.FullMethod)
|
||||
if log.GetLevel() >= log.DebugLevel {
|
||||
fmt.Fprintf(os.Stderr, "%+v", stack.Formatter(grpcerrors.FromGRPC(err)))
|
||||
_, _ = fmt.Fprintf(os.Stderr, "%+v", stack.Formatter(grpcerrors.FromGRPC(err)))
|
||||
}
|
||||
}
|
||||
return resp, err
|
||||
|
||||
@@ -22,7 +22,7 @@ type Backend interface {
|
||||
}
|
||||
|
||||
type imageBackend interface {
|
||||
ImageDelete(ctx context.Context, imageRef string, force, prune bool) ([]image.DeleteResponse, error)
|
||||
ImageDelete(ctx context.Context, imageRef string, options image.RemoveOptions) ([]image.DeleteResponse, error)
|
||||
ImageHistory(ctx context.Context, imageName string, platform *ocispec.Platform) ([]*image.HistoryResponseItem, error)
|
||||
Images(ctx context.Context, opts image.ListOptions) ([]*image.Summary, error)
|
||||
GetImage(ctx context.Context, refOrID string, options backend.GetImageOpts) (*dockerimage.Image, error)
|
||||
|
||||
@@ -2,23 +2,20 @@ package image // import "github.com/docker/docker/api/server/router/image"
|
||||
|
||||
import (
|
||||
"github.com/docker/docker/api/server/router"
|
||||
"github.com/docker/docker/reference"
|
||||
)
|
||||
|
||||
// imageRouter is a router to talk with the image controller
|
||||
type imageRouter struct {
|
||||
backend Backend
|
||||
searcher Searcher
|
||||
referenceBackend reference.Store
|
||||
routes []router.Route
|
||||
backend Backend
|
||||
searcher Searcher
|
||||
routes []router.Route
|
||||
}
|
||||
|
||||
// NewRouter initializes a new image router
|
||||
func NewRouter(backend Backend, searcher Searcher, referenceBackend reference.Store) router.Router {
|
||||
func NewRouter(backend Backend, searcher Searcher) router.Router {
|
||||
ir := &imageRouter{
|
||||
backend: backend,
|
||||
searcher: searcher,
|
||||
referenceBackend: referenceBackend,
|
||||
backend: backend,
|
||||
searcher: searcher,
|
||||
}
|
||||
ir.initRoutes()
|
||||
return ir
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/docker/docker/api"
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
imagetypes "github.com/docker/docker/api/types/image"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
@@ -26,6 +27,8 @@ import (
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/docker/docker/pkg/progress"
|
||||
"github.com/docker/docker/pkg/streamformatter"
|
||||
"github.com/docker/go-connections/nat"
|
||||
dockerspec "github.com/moby/docker-image-spec/specs-go/v1"
|
||||
"github.com/opencontainers/go-digest"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
@@ -323,7 +326,20 @@ func (ir *imageRouter) deleteImages(ctx context.Context, w http.ResponseWriter,
|
||||
force := httputils.BoolValue(r, "force")
|
||||
prune := !httputils.BoolValue(r, "noprune")
|
||||
|
||||
list, err := ir.backend.ImageDelete(ctx, name, force, prune)
|
||||
var platforms []ocispec.Platform
|
||||
if versions.GreaterThanOrEqualTo(httputils.VersionFromContext(ctx), "1.50") {
|
||||
p, err := httputils.DecodePlatforms(r.Form["platforms"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
platforms = p
|
||||
}
|
||||
|
||||
list, err := ir.backend.ImageDelete(ctx, name, imagetypes.RemoveOptions{
|
||||
Force: force,
|
||||
PruneChildren: prune,
|
||||
Platforms: platforms,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -388,6 +404,17 @@ func (ir *imageRouter) getImagesByName(ctx context.Context, w http.ResponseWrite
|
||||
if versions.LessThan(version, "1.48") {
|
||||
imageInspect.Descriptor = nil
|
||||
}
|
||||
if versions.LessThan(version, "1.50") {
|
||||
type imageInspectLegacy struct {
|
||||
imagetypes.InspectResponse
|
||||
LegacyConfig *container.Config `json:"Config"`
|
||||
}
|
||||
return httputils.WriteJSON(w, http.StatusOK, imageInspectLegacy{
|
||||
InspectResponse: *imageInspect,
|
||||
LegacyConfig: dockerOCIImageConfigToContainerConfig(*imageInspect.Config),
|
||||
})
|
||||
}
|
||||
|
||||
return httputils.WriteJSON(w, http.StatusOK, imageInspect)
|
||||
}
|
||||
|
||||
@@ -571,3 +598,27 @@ func validateRepoName(name reference.Named) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FIXME(thaJeztah): this is a copy of dockerOCIImageConfigToContainerConfig in daemon/containerd: https://github.com/moby/moby/blob/6b617699c500522aa6526cfcae4558333911b11f/daemon/containerd/imagespec.go#L107-L128
|
||||
func dockerOCIImageConfigToContainerConfig(cfg dockerspec.DockerOCIImageConfig) *container.Config {
|
||||
exposedPorts := make(nat.PortSet, len(cfg.ExposedPorts))
|
||||
for k, v := range cfg.ExposedPorts {
|
||||
exposedPorts[nat.Port(k)] = v
|
||||
}
|
||||
|
||||
return &container.Config{
|
||||
Entrypoint: cfg.Entrypoint,
|
||||
Env: cfg.Env,
|
||||
Cmd: cfg.Cmd,
|
||||
User: cfg.User,
|
||||
WorkingDir: cfg.WorkingDir,
|
||||
ExposedPorts: exposedPorts,
|
||||
Volumes: cfg.Volumes,
|
||||
Labels: cfg.Labels,
|
||||
ArgsEscaped: cfg.ArgsEscaped, //nolint:staticcheck // Ignore SA1019. Need to keep it in image.
|
||||
StopSignal: cfg.StopSignal,
|
||||
Healthcheck: cfg.Healthcheck,
|
||||
OnBuild: cfg.OnBuild,
|
||||
Shell: cfg.Shell,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,22 +22,22 @@ func NewRouter(b Backend, c ClusterBackend) router.Router {
|
||||
}
|
||||
|
||||
// Routes returns the available routes to the network controller
|
||||
func (r *networkRouter) Routes() []router.Route {
|
||||
return r.routes
|
||||
func (n *networkRouter) Routes() []router.Route {
|
||||
return n.routes
|
||||
}
|
||||
|
||||
func (r *networkRouter) initRoutes() {
|
||||
r.routes = []router.Route{
|
||||
func (n *networkRouter) initRoutes() {
|
||||
n.routes = []router.Route{
|
||||
// GET
|
||||
router.NewGetRoute("/networks", r.getNetworksList),
|
||||
router.NewGetRoute("/networks/", r.getNetworksList),
|
||||
router.NewGetRoute("/networks/{id:.+}", r.getNetwork),
|
||||
router.NewGetRoute("/networks", n.getNetworksList),
|
||||
router.NewGetRoute("/networks/", n.getNetworksList),
|
||||
router.NewGetRoute("/networks/{id:.+}", n.getNetwork),
|
||||
// POST
|
||||
router.NewPostRoute("/networks/create", r.postNetworkCreate),
|
||||
router.NewPostRoute("/networks/{id:.*}/connect", r.postNetworkConnect),
|
||||
router.NewPostRoute("/networks/{id:.*}/disconnect", r.postNetworkDisconnect),
|
||||
router.NewPostRoute("/networks/prune", r.postNetworksPrune),
|
||||
router.NewPostRoute("/networks/create", n.postNetworkCreate),
|
||||
router.NewPostRoute("/networks/{id:.*}/connect", n.postNetworkConnect),
|
||||
router.NewPostRoute("/networks/{id:.*}/disconnect", n.postNetworkDisconnect),
|
||||
router.NewPostRoute("/networks/prune", n.postNetworksPrune),
|
||||
// DELETE
|
||||
router.NewDeleteRoute("/networks/{id:.*}", r.deleteNetwork),
|
||||
router.NewDeleteRoute("/networks/{id:.*}", n.deleteNetwork),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ func (n *networkRouter) getNetwork(ctx context.Context, w http.ResponseWriter, r
|
||||
// ex: overlay/partial_ID or name/swarm_scope
|
||||
if nwv, ok := listByPartialID[nwk.ID]; ok {
|
||||
nwk = nwv
|
||||
} else if nwv, ok := listByFullName[nwk.ID]; ok {
|
||||
} else if nwv, ok = listByFullName[nwk.ID]; ok {
|
||||
nwk = nwv
|
||||
}
|
||||
return httputils.WriteJSON(w, http.StatusOK, nwk)
|
||||
|
||||
@@ -18,22 +18,22 @@ func NewRouter(b Backend) router.Router {
|
||||
}
|
||||
|
||||
// Routes returns the available routers to the plugin controller
|
||||
func (r *pluginRouter) Routes() []router.Route {
|
||||
return r.routes
|
||||
func (pr *pluginRouter) Routes() []router.Route {
|
||||
return pr.routes
|
||||
}
|
||||
|
||||
func (r *pluginRouter) initRoutes() {
|
||||
r.routes = []router.Route{
|
||||
router.NewGetRoute("/plugins", r.listPlugins),
|
||||
router.NewGetRoute("/plugins/{name:.*}/json", r.inspectPlugin),
|
||||
router.NewGetRoute("/plugins/privileges", r.getPrivileges),
|
||||
router.NewDeleteRoute("/plugins/{name:.*}", r.removePlugin),
|
||||
router.NewPostRoute("/plugins/{name:.*}/enable", r.enablePlugin),
|
||||
router.NewPostRoute("/plugins/{name:.*}/disable", r.disablePlugin),
|
||||
router.NewPostRoute("/plugins/pull", r.pullPlugin),
|
||||
router.NewPostRoute("/plugins/{name:.*}/push", r.pushPlugin),
|
||||
router.NewPostRoute("/plugins/{name:.*}/upgrade", r.upgradePlugin),
|
||||
router.NewPostRoute("/plugins/{name:.*}/set", r.setPlugin),
|
||||
router.NewPostRoute("/plugins/create", r.createPlugin),
|
||||
func (pr *pluginRouter) initRoutes() {
|
||||
pr.routes = []router.Route{
|
||||
router.NewGetRoute("/plugins", pr.listPlugins),
|
||||
router.NewGetRoute("/plugins/{name:.*}/json", pr.inspectPlugin),
|
||||
router.NewGetRoute("/plugins/privileges", pr.getPrivileges),
|
||||
router.NewDeleteRoute("/plugins/{name:.*}", pr.removePlugin),
|
||||
router.NewPostRoute("/plugins/{name:.*}/enable", pr.enablePlugin),
|
||||
router.NewPostRoute("/plugins/{name:.*}/disable", pr.disablePlugin),
|
||||
router.NewPostRoute("/plugins/pull", pr.pullPlugin),
|
||||
router.NewPostRoute("/plugins/{name:.*}/push", pr.pushPlugin),
|
||||
router.NewPostRoute("/plugins/{name:.*}/upgrade", pr.upgradePlugin),
|
||||
router.NewPostRoute("/plugins/{name:.*}/set", pr.setPlugin),
|
||||
router.NewPostRoute("/plugins/create", pr.createPlugin),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,12 +18,12 @@ func NewRouter(b Backend) router.Router {
|
||||
}
|
||||
|
||||
// Routes returns the available routers to the session controller
|
||||
func (r *sessionRouter) Routes() []router.Route {
|
||||
return r.routes
|
||||
func (sr *sessionRouter) Routes() []router.Route {
|
||||
return sr.routes
|
||||
}
|
||||
|
||||
func (r *sessionRouter) initRoutes() {
|
||||
r.routes = []router.Route{
|
||||
router.NewPostRoute("/session", r.startSession),
|
||||
func (sr *sessionRouter) initRoutes() {
|
||||
sr.routes = []router.Route{
|
||||
router.NewPostRoute("/session", sr.startSession),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package swarm // import "github.com/docker/docker/api/server/router/swarm"
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
@@ -18,24 +17,24 @@ type Backend interface {
|
||||
Update(uint64, swarm.Spec, swarm.UpdateFlags) error
|
||||
GetUnlockKey() (string, error)
|
||||
UnlockSwarm(req swarm.UnlockRequest) error
|
||||
GetServices(types.ServiceListOptions) ([]swarm.Service, error)
|
||||
GetServices(swarm.ServiceListOptions) ([]swarm.Service, error)
|
||||
GetService(idOrName string, insertDefaults bool) (swarm.Service, error)
|
||||
CreateService(swarm.ServiceSpec, string, bool) (*swarm.ServiceCreateResponse, error)
|
||||
UpdateService(string, uint64, swarm.ServiceSpec, types.ServiceUpdateOptions, bool) (*swarm.ServiceUpdateResponse, error)
|
||||
UpdateService(string, uint64, swarm.ServiceSpec, swarm.ServiceUpdateOptions, bool) (*swarm.ServiceUpdateResponse, error)
|
||||
RemoveService(string) error
|
||||
ServiceLogs(context.Context, *backend.LogSelector, *container.LogsOptions) (<-chan *backend.LogMessage, error)
|
||||
GetNodes(types.NodeListOptions) ([]swarm.Node, error)
|
||||
GetNodes(swarm.NodeListOptions) ([]swarm.Node, error)
|
||||
GetNode(string) (swarm.Node, error)
|
||||
UpdateNode(string, uint64, swarm.NodeSpec) error
|
||||
RemoveNode(string, bool) error
|
||||
GetTasks(types.TaskListOptions) ([]swarm.Task, error)
|
||||
GetTasks(swarm.TaskListOptions) ([]swarm.Task, error)
|
||||
GetTask(string) (swarm.Task, error)
|
||||
GetSecrets(opts types.SecretListOptions) ([]swarm.Secret, error)
|
||||
GetSecrets(opts swarm.SecretListOptions) ([]swarm.Secret, error)
|
||||
CreateSecret(s swarm.SecretSpec) (string, error)
|
||||
RemoveSecret(idOrName string) error
|
||||
GetSecret(id string) (swarm.Secret, error)
|
||||
UpdateSecret(idOrName string, version uint64, spec swarm.SecretSpec) error
|
||||
GetConfigs(opts types.ConfigListOptions) ([]swarm.Config, error)
|
||||
GetConfigs(opts swarm.ConfigListOptions) ([]swarm.Config, error)
|
||||
CreateConfig(s swarm.ConfigSpec) (string, error)
|
||||
RemoveConfig(id string) error
|
||||
GetConfig(id string) (swarm.Config, error)
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
|
||||
"github.com/containerd/log"
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
basictypes "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/registry"
|
||||
@@ -140,7 +139,7 @@ func (sr *swarmRouter) getUnlockKey(ctx context.Context, w http.ResponseWriter,
|
||||
return err
|
||||
}
|
||||
|
||||
return httputils.WriteJSON(w, http.StatusOK, &basictypes.SwarmUnlockKeyResponse{
|
||||
return httputils.WriteJSON(w, http.StatusOK, &types.UnlockKeyResponse{
|
||||
UnlockKey: unlockKey,
|
||||
})
|
||||
}
|
||||
@@ -166,7 +165,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(types.ServiceListOptions{Filters: filter, Status: status})
|
||||
if err != nil {
|
||||
log.G(ctx).WithContext(ctx).WithError(err).Debug("Error getting services")
|
||||
return err
|
||||
@@ -245,7 +244,7 @@ func (sr *swarmRouter) updateService(ctx context.Context, w http.ResponseWriter,
|
||||
return errdefs.InvalidParameter(err)
|
||||
}
|
||||
|
||||
var flags basictypes.ServiceUpdateOptions
|
||||
var flags types.ServiceUpdateOptions
|
||||
|
||||
// Get returns "" if the header does not exist
|
||||
flags.EncodedRegistryAuth = r.Header.Get(registry.AuthHeader)
|
||||
@@ -314,7 +313,7 @@ func (sr *swarmRouter) getNodes(ctx context.Context, w http.ResponseWriter, r *h
|
||||
return err
|
||||
}
|
||||
|
||||
nodes, err := sr.backend.GetNodes(basictypes.NodeListOptions{Filters: filter})
|
||||
nodes, err := sr.backend.GetNodes(types.NodeListOptions{Filters: filter})
|
||||
if err != nil {
|
||||
log.G(ctx).WithContext(ctx).WithError(err).Debug("Error getting nodes")
|
||||
return err
|
||||
@@ -385,7 +384,7 @@ func (sr *swarmRouter) getTasks(ctx context.Context, w http.ResponseWriter, r *h
|
||||
return err
|
||||
}
|
||||
|
||||
tasks, err := sr.backend.GetTasks(basictypes.TaskListOptions{Filters: filter})
|
||||
tasks, err := sr.backend.GetTasks(types.TaskListOptions{Filters: filter})
|
||||
if err != nil {
|
||||
log.G(ctx).WithContext(ctx).WithError(err).Debug("Error getting tasks")
|
||||
return err
|
||||
@@ -416,7 +415,7 @@ func (sr *swarmRouter) getSecrets(ctx context.Context, w http.ResponseWriter, r
|
||||
return err
|
||||
}
|
||||
|
||||
secrets, err := sr.backend.GetSecrets(basictypes.SecretListOptions{Filters: filters})
|
||||
secrets, err := sr.backend.GetSecrets(types.SecretListOptions{Filters: filters})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -439,7 +438,7 @@ func (sr *swarmRouter) createSecret(ctx context.Context, w http.ResponseWriter,
|
||||
return err
|
||||
}
|
||||
|
||||
return httputils.WriteJSON(w, http.StatusCreated, &basictypes.SecretCreateResponse{
|
||||
return httputils.WriteJSON(w, http.StatusCreated, &types.SecretCreateResponse{
|
||||
ID: id,
|
||||
})
|
||||
}
|
||||
@@ -487,7 +486,7 @@ func (sr *swarmRouter) getConfigs(ctx context.Context, w http.ResponseWriter, r
|
||||
return err
|
||||
}
|
||||
|
||||
configs, err := sr.backend.GetConfigs(basictypes.ConfigListOptions{Filters: filters})
|
||||
configs, err := sr.backend.GetConfigs(types.ConfigListOptions{Filters: filters})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -511,7 +510,7 @@ func (sr *swarmRouter) createConfig(ctx context.Context, w http.ResponseWriter,
|
||||
return err
|
||||
}
|
||||
|
||||
return httputils.WriteJSON(w, http.StatusCreated, &basictypes.ConfigCreateResponse{
|
||||
return httputils.WriteJSON(w, http.StatusCreated, &types.ConfigCreateResponse{
|
||||
ID: id,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ func (sr *swarmRouter) swarmLogs(ctx context.Context, w http.ResponseWriter, r *
|
||||
// any error after the stream starts (i.e. container not found, wrong parameters)
|
||||
// with the appropriate status code.
|
||||
stdout, stderr := httputils.BoolValue(r, "stdout"), httputils.BoolValue(r, "stderr")
|
||||
if !(stdout || stderr) {
|
||||
if !stdout && !stderr {
|
||||
return fmt.Errorf("Bad parameters: you must choose at least one stream")
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/build"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
@@ -29,7 +30,7 @@ type DiskUsageOptions struct {
|
||||
type Backend interface {
|
||||
SystemInfo(context.Context) (*system.Info, error)
|
||||
SystemVersion(context.Context) (types.Version, error)
|
||||
SystemDiskUsage(ctx context.Context, opts DiskUsageOptions) (*types.DiskUsage, error)
|
||||
SystemDiskUsage(ctx context.Context, opts DiskUsageOptions) (*system.DiskUsage, error)
|
||||
SubscribeToEvents(since, until time.Time, ef filters.Args) ([]events.Message, chan interface{})
|
||||
UnsubscribeFromEvents(chan interface{})
|
||||
AuthenticateToRegistry(ctx context.Context, authConfig *registry.AuthConfig) (string, string, error)
|
||||
@@ -41,6 +42,11 @@ type ClusterBackend interface {
|
||||
Info(context.Context) swarm.Info
|
||||
}
|
||||
|
||||
// BuildBackend provides build specific system information.
|
||||
type BuildBackend interface {
|
||||
DiskUsage(context.Context) ([]*build.CacheRecord, error)
|
||||
}
|
||||
|
||||
// StatusProvider provides methods to get the swarm status of the current node.
|
||||
type StatusProvider interface {
|
||||
Status() string
|
||||
|
||||
39
api/server/router/system/info_response.go
Normal file
39
api/server/router/system/info_response.go
Normal file
@@ -0,0 +1,39 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.23
|
||||
|
||||
package system
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/docker/docker/api/types/system"
|
||||
)
|
||||
|
||||
// infoResponse is a wrapper around [system.Info] with a custom
|
||||
// marshal function for legacy fields.
|
||||
type infoResponse struct {
|
||||
*system.Info
|
||||
|
||||
// extraFields is for internal use to include deprecated fields on older API versions.
|
||||
extraFields map[string]any
|
||||
}
|
||||
|
||||
// MarshalJSON implements a custom marshaler to include legacy fields
|
||||
// in API responses.
|
||||
func (sc *infoResponse) MarshalJSON() ([]byte, error) {
|
||||
type tmp *system.Info
|
||||
base, err := json.Marshal((tmp)(sc.Info))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(sc.extraFields) == 0 {
|
||||
return base, nil
|
||||
}
|
||||
var merged map[string]any
|
||||
_ = json.Unmarshal(base, &merged)
|
||||
|
||||
for k, v := range sc.extraFields {
|
||||
merged[k] = v
|
||||
}
|
||||
return json.Marshal(merged)
|
||||
}
|
||||
33
api/server/router/system/info_response_test.go
Normal file
33
api/server/router/system/info_response_test.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types/system"
|
||||
)
|
||||
|
||||
func TestLegacyFields(t *testing.T) {
|
||||
infoResp := &infoResponse{
|
||||
Info: &system.Info{
|
||||
Containers: 10,
|
||||
},
|
||||
extraFields: map[string]any{
|
||||
"LegacyFoo": false,
|
||||
"LegacyBar": true,
|
||||
},
|
||||
}
|
||||
|
||||
data, err := json.MarshalIndent(infoResp, "", " ")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if expected := `"LegacyFoo": false`; !strings.Contains(string(data), expected) {
|
||||
t.Errorf("legacy fields should contain %s: %s", expected, string(data))
|
||||
}
|
||||
if expected := `"LegacyBar": true`; !strings.Contains(string(data), expected) {
|
||||
t.Errorf("legacy fields should contain %s: %s", expected, string(data))
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,10 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.22
|
||||
//go:build go1.23
|
||||
|
||||
package system // import "github.com/docker/docker/api/server/router/system"
|
||||
|
||||
import (
|
||||
"github.com/docker/docker/api/server/router"
|
||||
"github.com/docker/docker/api/types/system"
|
||||
buildkit "github.com/docker/docker/builder/builder-next"
|
||||
"resenje.org/singleflight"
|
||||
)
|
||||
|
||||
@@ -16,17 +14,17 @@ type systemRouter struct {
|
||||
backend Backend
|
||||
cluster ClusterBackend
|
||||
routes []router.Route
|
||||
builder *buildkit.Builder
|
||||
builder BuildBackend
|
||||
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]
|
||||
collectSystemInfo singleflight.Group[string, *infoResponse]
|
||||
}
|
||||
|
||||
// NewRouter initializes a new system router
|
||||
func NewRouter(b Backend, c ClusterBackend, builder *buildkit.Builder, features func() map[string]bool) router.Router {
|
||||
func NewRouter(b Backend, c ClusterBackend, builder BuildBackend, features func() map[string]bool) router.Router {
|
||||
r := &systemRouter{
|
||||
backend: b,
|
||||
cluster: c,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.22
|
||||
//go:build go1.23
|
||||
|
||||
package system // import "github.com/docker/docker/api/server/router/system"
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
"github.com/docker/docker/api/server/router/build"
|
||||
"github.com/docker/docker/api/types"
|
||||
buildtypes "github.com/docker/docker/api/types/build"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
@@ -62,7 +63,7 @@ func (s *systemRouter) swarmStatus() string {
|
||||
|
||||
func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
version := httputils.VersionFromContext(ctx)
|
||||
info, _, _ := s.collectSystemInfo.Do(ctx, version, func(ctx context.Context) (*system.Info, error) {
|
||||
info, _, _ := s.collectSystemInfo.Do(ctx, version, func(ctx context.Context) (*infoResponse, error) {
|
||||
info, err := s.backend.SystemInfo(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -116,6 +117,7 @@ func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *ht
|
||||
info.FirewallBackend = nil
|
||||
}
|
||||
|
||||
extraFields := map[string]any{}
|
||||
if versions.LessThan(version, "1.49") {
|
||||
// Expected commits are omitted in API 1.49, but should still be
|
||||
// included in older versions.
|
||||
@@ -126,8 +128,19 @@ func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *ht
|
||||
if versions.GreaterThanOrEqualTo(version, "1.42") {
|
||||
info.KernelMemory = false
|
||||
}
|
||||
return info, nil
|
||||
if versions.LessThan(version, "1.50") {
|
||||
info.DiscoveredDevices = nil
|
||||
|
||||
// These fields are omitted in > API 1.49, and always false
|
||||
// older API versions.
|
||||
extraFields = map[string]any{
|
||||
"BridgeNfIptables": json.RawMessage("false"),
|
||||
"BridgeNfIp6tables": json.RawMessage("false"),
|
||||
}
|
||||
}
|
||||
return &infoResponse{Info: info, extraFields: extraFields}, nil
|
||||
})
|
||||
|
||||
return httputils.WriteJSON(w, http.StatusOK, info)
|
||||
}
|
||||
|
||||
@@ -170,7 +183,7 @@ func (s *systemRouter) getDiskUsage(ctx context.Context, w http.ResponseWriter,
|
||||
|
||||
eg, ctx := errgroup.WithContext(ctx)
|
||||
|
||||
var systemDiskUsage *types.DiskUsage
|
||||
var systemDiskUsage *system.DiskUsage
|
||||
if getContainers || getImages || getVolumes {
|
||||
eg.Go(func() error {
|
||||
var err error
|
||||
@@ -183,7 +196,7 @@ func (s *systemRouter) getDiskUsage(ctx context.Context, w http.ResponseWriter,
|
||||
})
|
||||
}
|
||||
|
||||
var buildCache []*types.BuildCache
|
||||
var buildCache []*buildtypes.CacheRecord
|
||||
if getBuildCache {
|
||||
eg.Go(func() error {
|
||||
var err error
|
||||
@@ -194,7 +207,7 @@ func (s *systemRouter) getDiskUsage(ctx context.Context, w http.ResponseWriter,
|
||||
if buildCache == nil {
|
||||
// Ensure empty `BuildCache` field is represented as empty JSON array(`[]`)
|
||||
// instead of `null` to be consistent with `Images`, `Containers` etc.
|
||||
buildCache = []*types.BuildCache{}
|
||||
buildCache = []*buildtypes.CacheRecord{}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@@ -219,23 +232,42 @@ func (s *systemRouter) getDiskUsage(ctx context.Context, w http.ResponseWriter,
|
||||
b.Parent = "" //nolint:staticcheck // ignore SA1019 (Parent field is deprecated)
|
||||
}
|
||||
}
|
||||
if versions.LessThan(version, "1.44") {
|
||||
for _, b := range systemDiskUsage.Images {
|
||||
if versions.LessThan(version, "1.44") && systemDiskUsage != nil && systemDiskUsage.Images != nil {
|
||||
for _, b := range systemDiskUsage.Images.Items {
|
||||
b.VirtualSize = b.Size //nolint:staticcheck // ignore SA1019: field is deprecated, but still set on API < v1.44.
|
||||
}
|
||||
}
|
||||
|
||||
du := types.DiskUsage{
|
||||
BuildCache: buildCache,
|
||||
BuilderSize: builderSize,
|
||||
du := system.DiskUsage{}
|
||||
if getBuildCache {
|
||||
du.BuildCache = &buildtypes.CacheDiskUsage{
|
||||
TotalSize: builderSize,
|
||||
Items: buildCache,
|
||||
}
|
||||
}
|
||||
if systemDiskUsage != nil {
|
||||
du.LayersSize = systemDiskUsage.LayersSize
|
||||
du.Images = systemDiskUsage.Images
|
||||
du.Containers = systemDiskUsage.Containers
|
||||
du.Volumes = systemDiskUsage.Volumes
|
||||
}
|
||||
return httputils.WriteJSON(w, http.StatusOK, du)
|
||||
|
||||
// Use the old struct for the API return value.
|
||||
var v types.DiskUsage
|
||||
if du.Images != nil {
|
||||
v.LayersSize = du.Images.TotalSize
|
||||
v.Images = du.Images.Items
|
||||
}
|
||||
if du.Containers != nil {
|
||||
v.Containers = du.Containers.Items
|
||||
}
|
||||
if du.Volumes != nil {
|
||||
v.Volumes = du.Volumes.Items
|
||||
}
|
||||
if du.BuildCache != nil {
|
||||
v.BuildCache = du.BuildCache.Items
|
||||
}
|
||||
v.BuilderSize = builderSize
|
||||
return httputils.WriteJSON(w, http.StatusOK, v)
|
||||
}
|
||||
|
||||
type invalidRequestError struct {
|
||||
|
||||
@@ -20,21 +20,21 @@ func NewRouter(b Backend, cb ClusterBackend) router.Router {
|
||||
}
|
||||
|
||||
// Routes returns the available routes to the volumes controller
|
||||
func (r *volumeRouter) Routes() []router.Route {
|
||||
return r.routes
|
||||
func (v *volumeRouter) Routes() []router.Route {
|
||||
return v.routes
|
||||
}
|
||||
|
||||
func (r *volumeRouter) initRoutes() {
|
||||
r.routes = []router.Route{
|
||||
func (v *volumeRouter) initRoutes() {
|
||||
v.routes = []router.Route{
|
||||
// GET
|
||||
router.NewGetRoute("/volumes", r.getVolumesList),
|
||||
router.NewGetRoute("/volumes/{name:.*}", r.getVolumeByName),
|
||||
router.NewGetRoute("/volumes", v.getVolumesList),
|
||||
router.NewGetRoute("/volumes/{name:.*}", v.getVolumeByName),
|
||||
// POST
|
||||
router.NewPostRoute("/volumes/create", r.postVolumesCreate),
|
||||
router.NewPostRoute("/volumes/prune", r.postVolumesPrune),
|
||||
router.NewPostRoute("/volumes/create", v.postVolumesCreate),
|
||||
router.NewPostRoute("/volumes/prune", v.postVolumesPrune),
|
||||
// PUT
|
||||
router.NewPutRoute("/volumes/{name:.*}", r.putVolumesUpdate),
|
||||
router.NewPutRoute("/volumes/{name:.*}", v.putVolumesUpdate),
|
||||
// DELETE
|
||||
router.NewDeleteRoute("/volumes/{name:.*}", r.deleteVolumes),
|
||||
router.NewDeleteRoute("/volumes/{name:.*}", v.deleteVolumes),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/containerd/log"
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
@@ -69,7 +70,7 @@ func (v *volumeRouter) getVolumeByName(ctx context.Context, w http.ResponseWrite
|
||||
// if the volume is not found in the regular volume backend, and the client
|
||||
// is using an API version greater than 1.42 (when cluster volumes were
|
||||
// introduced), then check if Swarm has the volume.
|
||||
if errdefs.IsNotFound(err) && versions.GreaterThanOrEqualTo(version, clusterVolumesVersion) && v.cluster.IsManager() {
|
||||
if cerrdefs.IsNotFound(err) && versions.GreaterThanOrEqualTo(version, clusterVolumesVersion) && v.cluster.IsManager() {
|
||||
swarmVol, err := v.cluster.GetVolume(vars["name"])
|
||||
// if swarm returns an error and that error indicates that swarm is not
|
||||
// initialized, return original NotFound error. Otherwise, we'd return
|
||||
@@ -164,7 +165,7 @@ func (v *volumeRouter) deleteVolumes(ctx context.Context, w http.ResponseWriter,
|
||||
// errors at this stage. Note that no "not found" error is produced if
|
||||
// "force" is enabled.
|
||||
err := v.backend.Remove(ctx, vars["name"], opts.WithPurgeOnError(force))
|
||||
if err != nil && !errdefs.IsNotFound(err) {
|
||||
if err != nil && !cerrdefs.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -172,7 +173,7 @@ func (v *volumeRouter) deleteVolumes(ctx context.Context, w http.ResponseWriter,
|
||||
// is enabled, the volume backend won't return an error for non-existing
|
||||
// volumes, so we don't know if removal succeeded (or not volume existed).
|
||||
// In that case we always try to delete cluster volumes as well.
|
||||
if errdefs.IsNotFound(err) || force {
|
||||
if cerrdefs.IsNotFound(err) || force {
|
||||
version := httputils.VersionFromContext(ctx)
|
||||
if versions.GreaterThanOrEqualTo(version, clusterVolumesVersion) && v.cluster.IsManager() {
|
||||
err = v.cluster.RemoveVolume(vars["name"], force)
|
||||
|
||||
@@ -5,11 +5,13 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/volume"
|
||||
@@ -20,7 +22,7 @@ import (
|
||||
func callGetVolume(v *volumeRouter, name string) (*httptest.ResponseRecorder, error) {
|
||||
ctx := context.WithValue(context.Background(), httputils.APIVersionKey{}, clusterVolumesVersion)
|
||||
vars := map[string]string{"name": name}
|
||||
req := httptest.NewRequest("GET", fmt.Sprintf("/volumes/%s", name), nil)
|
||||
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/volumes/%s", name), nil)
|
||||
resp := httptest.NewRecorder()
|
||||
|
||||
err := v.getVolumeByName(ctx, resp, req, vars)
|
||||
@@ -30,7 +32,7 @@ func callGetVolume(v *volumeRouter, name string) (*httptest.ResponseRecorder, er
|
||||
func callListVolumes(v *volumeRouter) (*httptest.ResponseRecorder, error) {
|
||||
ctx := context.WithValue(context.Background(), httputils.APIVersionKey{}, clusterVolumesVersion)
|
||||
vars := map[string]string{}
|
||||
req := httptest.NewRequest("GET", "/volumes", nil)
|
||||
req := httptest.NewRequest(http.MethodGet, "/volumes", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
|
||||
err := v.getVolumesList(ctx, resp, req, vars)
|
||||
@@ -46,7 +48,7 @@ func TestGetVolumeByNameNotFoundNoSwarm(t *testing.T) {
|
||||
_, err := callGetVolume(v, "notReal")
|
||||
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Assert(t, errdefs.IsNotFound(err))
|
||||
assert.Assert(t, cerrdefs.IsNotFound(err))
|
||||
}
|
||||
|
||||
func TestGetVolumeByNameNotFoundNotManager(t *testing.T) {
|
||||
@@ -58,7 +60,7 @@ func TestGetVolumeByNameNotFoundNotManager(t *testing.T) {
|
||||
_, err := callGetVolume(v, "notReal")
|
||||
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Assert(t, errdefs.IsNotFound(err))
|
||||
assert.Assert(t, cerrdefs.IsNotFound(err))
|
||||
}
|
||||
|
||||
func TestGetVolumeByNameNotFound(t *testing.T) {
|
||||
@@ -70,7 +72,7 @@ func TestGetVolumeByNameNotFound(t *testing.T) {
|
||||
_, err := callGetVolume(v, "notReal")
|
||||
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Assert(t, errdefs.IsNotFound(err))
|
||||
assert.Assert(t, cerrdefs.IsNotFound(err))
|
||||
}
|
||||
|
||||
func TestGetVolumeByNameFoundRegular(t *testing.T) {
|
||||
@@ -193,7 +195,7 @@ func TestCreateRegularVolume(t *testing.T) {
|
||||
assert.NilError(t, err)
|
||||
|
||||
ctx := context.WithValue(context.Background(), httputils.APIVersionKey{}, clusterVolumesVersion)
|
||||
req := httptest.NewRequest("POST", "/volumes/create", &buf)
|
||||
req := httptest.NewRequest(http.MethodPost, "/volumes/create", &buf)
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
|
||||
resp := httptest.NewRecorder()
|
||||
@@ -231,13 +233,13 @@ func TestCreateSwarmVolumeNoSwarm(t *testing.T) {
|
||||
assert.NilError(t, err)
|
||||
|
||||
ctx := context.WithValue(context.Background(), httputils.APIVersionKey{}, clusterVolumesVersion)
|
||||
req := httptest.NewRequest("POST", "/volumes/create", &buf)
|
||||
req := httptest.NewRequest(http.MethodPost, "/volumes/create", &buf)
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
|
||||
resp := httptest.NewRecorder()
|
||||
err = v.postVolumesCreate(ctx, resp, req, nil)
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Assert(t, errdefs.IsUnavailable(err))
|
||||
assert.Assert(t, cerrdefs.IsUnavailable(err))
|
||||
}
|
||||
|
||||
func TestCreateSwarmVolumeNotManager(t *testing.T) {
|
||||
@@ -260,13 +262,13 @@ func TestCreateSwarmVolumeNotManager(t *testing.T) {
|
||||
assert.NilError(t, err)
|
||||
|
||||
ctx := context.WithValue(context.Background(), httputils.APIVersionKey{}, clusterVolumesVersion)
|
||||
req := httptest.NewRequest("POST", "/volumes/create", &buf)
|
||||
req := httptest.NewRequest(http.MethodPost, "/volumes/create", &buf)
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
|
||||
resp := httptest.NewRecorder()
|
||||
err = v.postVolumesCreate(ctx, resp, req, nil)
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Assert(t, errdefs.IsUnavailable(err))
|
||||
assert.Assert(t, cerrdefs.IsUnavailable(err))
|
||||
}
|
||||
|
||||
func TestCreateVolumeCluster(t *testing.T) {
|
||||
@@ -292,7 +294,7 @@ func TestCreateVolumeCluster(t *testing.T) {
|
||||
assert.NilError(t, err)
|
||||
|
||||
ctx := context.WithValue(context.Background(), httputils.APIVersionKey{}, clusterVolumesVersion)
|
||||
req := httptest.NewRequest("POST", "/volumes/create", &buf)
|
||||
req := httptest.NewRequest(http.MethodPost, "/volumes/create", &buf)
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
|
||||
resp := httptest.NewRecorder()
|
||||
@@ -339,7 +341,7 @@ func TestUpdateVolume(t *testing.T) {
|
||||
assert.NilError(t, err)
|
||||
|
||||
ctx := context.WithValue(context.Background(), httputils.APIVersionKey{}, clusterVolumesVersion)
|
||||
req := httptest.NewRequest("POST", "/volumes/vol1/update?version=0", &buf)
|
||||
req := httptest.NewRequest(http.MethodPost, "/volumes/vol1/update?version=0", &buf)
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
|
||||
resp := httptest.NewRecorder()
|
||||
@@ -368,14 +370,14 @@ func TestUpdateVolumeNoSwarm(t *testing.T) {
|
||||
assert.NilError(t, err)
|
||||
|
||||
ctx := context.WithValue(context.Background(), httputils.APIVersionKey{}, clusterVolumesVersion)
|
||||
req := httptest.NewRequest("POST", "/volumes/vol1/update?version=0", &buf)
|
||||
req := httptest.NewRequest(http.MethodPost, "/volumes/vol1/update?version=0", &buf)
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
|
||||
resp := httptest.NewRecorder()
|
||||
|
||||
err = v.putVolumesUpdate(ctx, resp, req, map[string]string{"name": "vol1"})
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Assert(t, errdefs.IsUnavailable(err))
|
||||
assert.Assert(t, cerrdefs.IsUnavailable(err))
|
||||
}
|
||||
|
||||
func TestUpdateVolumeNotFound(t *testing.T) {
|
||||
@@ -400,14 +402,14 @@ func TestUpdateVolumeNotFound(t *testing.T) {
|
||||
assert.NilError(t, err)
|
||||
|
||||
ctx := context.WithValue(context.Background(), httputils.APIVersionKey{}, clusterVolumesVersion)
|
||||
req := httptest.NewRequest("POST", "/volumes/vol1/update?version=0", &buf)
|
||||
req := httptest.NewRequest(http.MethodPost, "/volumes/vol1/update?version=0", &buf)
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
|
||||
resp := httptest.NewRecorder()
|
||||
|
||||
err = v.putVolumesUpdate(ctx, resp, req, map[string]string{"name": "vol1"})
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Assert(t, errdefs.IsNotFound(err))
|
||||
assert.Assert(t, cerrdefs.IsNotFound(err))
|
||||
}
|
||||
|
||||
func TestVolumeRemove(t *testing.T) {
|
||||
@@ -426,7 +428,7 @@ func TestVolumeRemove(t *testing.T) {
|
||||
}
|
||||
|
||||
ctx := context.WithValue(context.Background(), httputils.APIVersionKey{}, clusterVolumesVersion)
|
||||
req := httptest.NewRequest("DELETE", "/volumes/vol1", nil)
|
||||
req := httptest.NewRequest(http.MethodDelete, "/volumes/vol1", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
|
||||
err := v.deleteVolumes(ctx, resp, req, map[string]string{"name": "vol1"})
|
||||
@@ -453,7 +455,7 @@ func TestVolumeRemoveSwarm(t *testing.T) {
|
||||
}
|
||||
|
||||
ctx := context.WithValue(context.Background(), httputils.APIVersionKey{}, clusterVolumesVersion)
|
||||
req := httptest.NewRequest("DELETE", "/volumes/vol1", nil)
|
||||
req := httptest.NewRequest(http.MethodDelete, "/volumes/vol1", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
|
||||
err := v.deleteVolumes(ctx, resp, req, map[string]string{"name": "vol1"})
|
||||
@@ -470,12 +472,12 @@ func TestVolumeRemoveNotFoundNoSwarm(t *testing.T) {
|
||||
}
|
||||
|
||||
ctx := context.WithValue(context.Background(), httputils.APIVersionKey{}, clusterVolumesVersion)
|
||||
req := httptest.NewRequest("DELETE", "/volumes/vol1", nil)
|
||||
req := httptest.NewRequest(http.MethodDelete, "/volumes/vol1", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
|
||||
err := v.deleteVolumes(ctx, resp, req, map[string]string{"name": "vol1"})
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Assert(t, errdefs.IsNotFound(err), err.Error())
|
||||
assert.Assert(t, cerrdefs.IsNotFound(err), err.Error())
|
||||
}
|
||||
|
||||
func TestVolumeRemoveNotFoundNoManager(t *testing.T) {
|
||||
@@ -487,12 +489,12 @@ func TestVolumeRemoveNotFoundNoManager(t *testing.T) {
|
||||
}
|
||||
|
||||
ctx := context.WithValue(context.Background(), httputils.APIVersionKey{}, clusterVolumesVersion)
|
||||
req := httptest.NewRequest("DELETE", "/volumes/vol1", nil)
|
||||
req := httptest.NewRequest(http.MethodDelete, "/volumes/vol1", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
|
||||
err := v.deleteVolumes(ctx, resp, req, map[string]string{"name": "vol1"})
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Assert(t, errdefs.IsNotFound(err))
|
||||
assert.Assert(t, cerrdefs.IsNotFound(err))
|
||||
}
|
||||
|
||||
func TestVolumeRemoveFoundNoSwarm(t *testing.T) {
|
||||
@@ -511,7 +513,7 @@ func TestVolumeRemoveFoundNoSwarm(t *testing.T) {
|
||||
}
|
||||
|
||||
ctx := context.WithValue(context.Background(), httputils.APIVersionKey{}, clusterVolumesVersion)
|
||||
req := httptest.NewRequest("DELETE", "/volumes/vol1", nil)
|
||||
req := httptest.NewRequest(http.MethodDelete, "/volumes/vol1", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
|
||||
err := v.deleteVolumes(ctx, resp, req, map[string]string{"name": "vol1"})
|
||||
@@ -534,12 +536,12 @@ func TestVolumeRemoveNoSwarmInUse(t *testing.T) {
|
||||
}
|
||||
|
||||
ctx := context.WithValue(context.Background(), httputils.APIVersionKey{}, clusterVolumesVersion)
|
||||
req := httptest.NewRequest("DELETE", "/volumes/inuse", nil)
|
||||
req := httptest.NewRequest(http.MethodDelete, "/volumes/inuse", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
|
||||
err := v.deleteVolumes(ctx, resp, req, map[string]string{"name": "inuse"})
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Assert(t, errdefs.IsConflict(err))
|
||||
assert.Assert(t, cerrdefs.IsConflict(err))
|
||||
}
|
||||
|
||||
func TestVolumeRemoveSwarmForce(t *testing.T) {
|
||||
@@ -562,16 +564,16 @@ func TestVolumeRemoveSwarmForce(t *testing.T) {
|
||||
}
|
||||
|
||||
ctx := context.WithValue(context.Background(), httputils.APIVersionKey{}, clusterVolumesVersion)
|
||||
req := httptest.NewRequest("DELETE", "/volumes/vol1", nil)
|
||||
req := httptest.NewRequest(http.MethodDelete, "/volumes/vol1", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
|
||||
err := v.deleteVolumes(ctx, resp, req, map[string]string{"name": "vol1"})
|
||||
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Assert(t, errdefs.IsConflict(err))
|
||||
assert.Assert(t, cerrdefs.IsConflict(err))
|
||||
|
||||
ctx = context.WithValue(context.Background(), httputils.APIVersionKey{}, clusterVolumesVersion)
|
||||
req = httptest.NewRequest("DELETE", "/volumes/vol1?force=1", nil)
|
||||
req = httptest.NewRequest(http.MethodDelete, "/volumes/vol1?force=1", nil)
|
||||
resp = httptest.NewRecorder()
|
||||
|
||||
err = v.deleteVolumes(ctx, resp, req, map[string]string{"name": "vol1"})
|
||||
|
||||
@@ -60,7 +60,7 @@ func (s *Server) makeHTTPHandler(handler httputils.APIFunc, operation string) ht
|
||||
|
||||
if err := handlerFunc(ctx, w, r, vars); err != nil {
|
||||
statusCode := httpstatus.FromError(err)
|
||||
if statusCode >= 500 {
|
||||
if statusCode >= http.StatusInternalServerError {
|
||||
log.G(ctx).Errorf("Handler for %s %s returned error: %v", r.Method, r.URL.Path, err)
|
||||
}
|
||||
// While we no longer support API versions older 1.24 [api.MinSupportedAPIVersion],
|
||||
|
||||
188
api/swagger.yaml
188
api/swagger.yaml
@@ -19,10 +19,10 @@ produces:
|
||||
consumes:
|
||||
- "application/json"
|
||||
- "text/plain"
|
||||
basePath: "/v1.49"
|
||||
basePath: "/v1.50"
|
||||
info:
|
||||
title: "Docker Engine API"
|
||||
version: "1.49"
|
||||
version: "1.50"
|
||||
x-logo:
|
||||
url: "https://docs.docker.com/assets/images/logo-docker-main.png"
|
||||
description: |
|
||||
@@ -55,8 +55,8 @@ info:
|
||||
the URL is not supported by the daemon, a HTTP `400 Bad Request` error message
|
||||
is returned.
|
||||
|
||||
If you omit the version-prefix, the current version of the API (v1.49) is used.
|
||||
For example, calling `/info` is the same as calling `/v1.49/info`. Using the
|
||||
If you omit the version-prefix, the current version of the API (v1.50) is used.
|
||||
For example, calling `/info` is the same as calling `/v1.50/info`. Using the
|
||||
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,
|
||||
@@ -1428,63 +1428,10 @@ definitions:
|
||||
when starting a container from the image.
|
||||
type: "object"
|
||||
properties:
|
||||
Hostname:
|
||||
description: |
|
||||
The hostname to use for the container, as a valid RFC 1123 hostname.
|
||||
|
||||
<p><br /></p>
|
||||
|
||||
> **Deprecated**: this field is not part of the image specification and is
|
||||
> always empty. It must not be used, and will be removed in API v1.48.
|
||||
type: "string"
|
||||
example: ""
|
||||
Domainname:
|
||||
description: |
|
||||
The domain name to use for the container.
|
||||
|
||||
<p><br /></p>
|
||||
|
||||
> **Deprecated**: this field is not part of the image specification and is
|
||||
> always empty. It must not be used, and will be removed in API v1.48.
|
||||
type: "string"
|
||||
example: ""
|
||||
User:
|
||||
description: "The user that commands are run as inside the container."
|
||||
type: "string"
|
||||
example: "web:web"
|
||||
AttachStdin:
|
||||
description: |
|
||||
Whether to attach to `stdin`.
|
||||
|
||||
<p><br /></p>
|
||||
|
||||
> **Deprecated**: this field is not part of the image specification and is
|
||||
> always false. It must not be used, and will be removed in API v1.48.
|
||||
type: "boolean"
|
||||
default: false
|
||||
example: false
|
||||
AttachStdout:
|
||||
description: |
|
||||
Whether to attach to `stdout`.
|
||||
|
||||
<p><br /></p>
|
||||
|
||||
> **Deprecated**: this field is not part of the image specification and is
|
||||
> always false. It must not be used, and will be removed in API v1.48.
|
||||
type: "boolean"
|
||||
default: false
|
||||
example: false
|
||||
AttachStderr:
|
||||
description: |
|
||||
Whether to attach to `stderr`.
|
||||
|
||||
<p><br /></p>
|
||||
|
||||
> **Deprecated**: this field is not part of the image specification and is
|
||||
> always false. It must not be used, and will be removed in API v1.48.
|
||||
type: "boolean"
|
||||
default: false
|
||||
example: false
|
||||
ExposedPorts:
|
||||
description: |
|
||||
An object mapping ports to an empty object in the form:
|
||||
@@ -1501,39 +1448,6 @@ definitions:
|
||||
"80/tcp": {},
|
||||
"443/tcp": {}
|
||||
}
|
||||
Tty:
|
||||
description: |
|
||||
Attach standard streams to a TTY, including `stdin` if it is not closed.
|
||||
|
||||
<p><br /></p>
|
||||
|
||||
> **Deprecated**: this field is not part of the image specification and is
|
||||
> always false. It must not be used, and will be removed in API v1.48.
|
||||
type: "boolean"
|
||||
default: false
|
||||
example: false
|
||||
OpenStdin:
|
||||
description: |
|
||||
Open `stdin`
|
||||
|
||||
<p><br /></p>
|
||||
|
||||
> **Deprecated**: this field is not part of the image specification and is
|
||||
> always false. It must not be used, and will be removed in API v1.48.
|
||||
type: "boolean"
|
||||
default: false
|
||||
example: false
|
||||
StdinOnce:
|
||||
description: |
|
||||
Close `stdin` after one attached client disconnects.
|
||||
|
||||
<p><br /></p>
|
||||
|
||||
> **Deprecated**: this field is not part of the image specification and is
|
||||
> always false. It must not be used, and will be removed in API v1.48.
|
||||
type: "boolean"
|
||||
default: false
|
||||
example: false
|
||||
Env:
|
||||
description: |
|
||||
A list of environment variables to set inside the container in the
|
||||
@@ -1559,18 +1473,6 @@ definitions:
|
||||
default: false
|
||||
example: false
|
||||
x-nullable: true
|
||||
Image:
|
||||
description: |
|
||||
The name (or reference) of the image to use when creating the container,
|
||||
or which was used when the container was created.
|
||||
|
||||
<p><br /></p>
|
||||
|
||||
> **Deprecated**: this field is not part of the image specification and is
|
||||
> always empty. It must not be used, and will be removed in API v1.48.
|
||||
type: "string"
|
||||
default: ""
|
||||
example: ""
|
||||
Volumes:
|
||||
description: |
|
||||
An object mapping mount point paths inside the container to empty
|
||||
@@ -1599,30 +1501,6 @@ definitions:
|
||||
items:
|
||||
type: "string"
|
||||
example: []
|
||||
NetworkDisabled:
|
||||
description: |
|
||||
Disable networking for the container.
|
||||
|
||||
<p><br /></p>
|
||||
|
||||
> **Deprecated**: this field is not part of the image specification and is
|
||||
> always omitted. It must not be used, and will be removed in API v1.48.
|
||||
type: "boolean"
|
||||
default: false
|
||||
example: false
|
||||
x-nullable: true
|
||||
MacAddress:
|
||||
description: |
|
||||
MAC address of the container.
|
||||
|
||||
<p><br /></p>
|
||||
|
||||
> **Deprecated**: this field is not part of the image specification and is
|
||||
> always omitted. It must not be used, and will be removed in API v1.48.
|
||||
type: "string"
|
||||
default: ""
|
||||
example: ""
|
||||
x-nullable: true
|
||||
OnBuild:
|
||||
description: |
|
||||
`ONBUILD` metadata that were defined in the image's `Dockerfile`.
|
||||
@@ -1645,17 +1523,6 @@ definitions:
|
||||
type: "string"
|
||||
example: "SIGTERM"
|
||||
x-nullable: true
|
||||
StopTimeout:
|
||||
description: |
|
||||
Timeout to stop a container in seconds.
|
||||
|
||||
<p><br /></p>
|
||||
|
||||
> **Deprecated**: this field is not part of the image specification and is
|
||||
> always omitted. It must not be used, and will be removed in API v1.48.
|
||||
type: "integer"
|
||||
default: 10
|
||||
x-nullable: true
|
||||
Shell:
|
||||
description: |
|
||||
Shell for when `RUN`, `CMD`, and `ENTRYPOINT` uses a shell.
|
||||
@@ -1666,19 +1533,11 @@ definitions:
|
||||
example: ["/bin/sh", "-c"]
|
||||
# FIXME(thaJeztah): temporarily using a full example to remove some "omitempty" fields. Remove once the fields are removed.
|
||||
example:
|
||||
"Hostname": ""
|
||||
"Domainname": ""
|
||||
"User": "web:web"
|
||||
"AttachStdin": false
|
||||
"AttachStdout": false
|
||||
"AttachStderr": false
|
||||
"ExposedPorts": {
|
||||
"80/tcp": {},
|
||||
"443/tcp": {}
|
||||
}
|
||||
"Tty": false
|
||||
"OpenStdin": false
|
||||
"StdinOnce": false
|
||||
"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"]
|
||||
"Cmd": ["/bin/sh"]
|
||||
"Healthcheck": {
|
||||
@@ -1690,7 +1549,6 @@ definitions:
|
||||
"StartInterval": 0
|
||||
}
|
||||
"ArgsEscaped": true
|
||||
"Image": ""
|
||||
"Volumes": {
|
||||
"/app/data": {},
|
||||
"/app/config": {}
|
||||
@@ -2956,6 +2814,23 @@ definitions:
|
||||
progressDetail:
|
||||
$ref: "#/definitions/ProgressDetail"
|
||||
|
||||
DeviceInfo:
|
||||
type: "object"
|
||||
description: |
|
||||
DeviceInfo represents a device that can be used by a container.
|
||||
properties:
|
||||
Source:
|
||||
type: "string"
|
||||
example: "cdi"
|
||||
description: |
|
||||
The origin device driver.
|
||||
ID:
|
||||
type: "string"
|
||||
example: "vendor.com/gpu=0"
|
||||
description: |
|
||||
The unique identifier for the device within its source driver.
|
||||
For CDI devices, this would be an FQDN like "vendor.com/gpu=0".
|
||||
|
||||
ErrorDetail:
|
||||
type: "object"
|
||||
properties:
|
||||
@@ -6858,6 +6733,15 @@ definitions:
|
||||
example: "24"
|
||||
FirewallBackend:
|
||||
$ref: "#/definitions/FirewallInfo"
|
||||
DiscoveredDevices:
|
||||
description: |
|
||||
List of devices discovered by device drivers.
|
||||
|
||||
Each device includes information about its source driver, kind, name,
|
||||
and additional driver-specific attributes.
|
||||
type: "array"
|
||||
items:
|
||||
$ref: "#/definitions/DeviceInfo"
|
||||
Warnings:
|
||||
description: |
|
||||
List of warnings / informational messages about missing features, or
|
||||
@@ -9934,6 +9818,18 @@ paths:
|
||||
description: "Do not delete untagged parent images"
|
||||
type: "boolean"
|
||||
default: false
|
||||
- name: "platforms"
|
||||
in: "query"
|
||||
description: |
|
||||
Select platform-specific content to delete.
|
||||
Multiple values are accepted.
|
||||
Each platform is a OCI platform encoded as a JSON string.
|
||||
type: "array"
|
||||
items:
|
||||
# This should be OCIPlatform
|
||||
# but $ref is not supported for array in query in Swagger 2.0
|
||||
# $ref: "#/definitions/OCIPlatform"
|
||||
type: "string"
|
||||
tags: ["Image"]
|
||||
/images/search:
|
||||
get:
|
||||
|
||||
@@ -160,7 +160,7 @@ type ImageInspectOpts struct {
|
||||
type CommitConfig struct {
|
||||
Author string
|
||||
Comment string
|
||||
Config *container.Config
|
||||
Config *container.Config // TODO(thaJeztah); change this to [dockerspec.DockerOCIImageConfig]
|
||||
ContainerConfig *container.Config
|
||||
ContainerID string
|
||||
ContainerMountLabel string
|
||||
|
||||
@@ -3,7 +3,7 @@ package backend // import "github.com/docker/docker/api/types/backend"
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/build"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/pkg/streamformatter"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
@@ -34,7 +34,7 @@ type ProgressWriter struct {
|
||||
type BuildConfig struct {
|
||||
Source io.ReadCloser
|
||||
ProgressWriter ProgressWriter
|
||||
Options *types.ImageBuildOptions
|
||||
Options *build.ImageBuildOptions
|
||||
}
|
||||
|
||||
// GetImageAndLayerOptions are the options supported by GetImageAndReleasableLayer
|
||||
|
||||
91
api/types/build/build.go
Normal file
91
api/types/build/build.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package build
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
)
|
||||
|
||||
// BuilderVersion sets the version of underlying builder to use
|
||||
type BuilderVersion string
|
||||
|
||||
const (
|
||||
// BuilderV1 is the first generation builder in docker daemon
|
||||
BuilderV1 BuilderVersion = "1"
|
||||
// BuilderBuildKit is builder based on moby/buildkit project
|
||||
BuilderBuildKit BuilderVersion = "2"
|
||||
)
|
||||
|
||||
// Result contains the image id of a successful build.
|
||||
type Result struct {
|
||||
ID string
|
||||
}
|
||||
|
||||
// ImageBuildOptions holds the information
|
||||
// necessary to build images.
|
||||
type ImageBuildOptions struct {
|
||||
Tags []string
|
||||
SuppressOutput bool
|
||||
RemoteContext string
|
||||
NoCache bool
|
||||
Remove bool
|
||||
ForceRemove bool
|
||||
PullParent bool
|
||||
Isolation container.Isolation
|
||||
CPUSetCPUs string
|
||||
CPUSetMems string
|
||||
CPUShares int64
|
||||
CPUQuota int64
|
||||
CPUPeriod int64
|
||||
Memory int64
|
||||
MemorySwap int64
|
||||
CgroupParent string
|
||||
NetworkMode string
|
||||
ShmSize int64
|
||||
Dockerfile string
|
||||
Ulimits []*container.Ulimit
|
||||
// BuildArgs needs to be a *string instead of just a string so that
|
||||
// we can tell the difference between "" (empty string) and no value
|
||||
// at all (nil). See the parsing of buildArgs in
|
||||
// api/server/router/build/build_routes.go for even more info.
|
||||
BuildArgs map[string]*string
|
||||
AuthConfigs map[string]registry.AuthConfig
|
||||
Context io.Reader
|
||||
Labels map[string]string
|
||||
// squash the resulting image's layers to the parent
|
||||
// preserves the original image and creates a new one from the parent with all
|
||||
// the changes applied to a single layer
|
||||
Squash bool
|
||||
// CacheFrom specifies images that are used for matching cache. Images
|
||||
// specified here do not need to have a valid parent chain to match cache.
|
||||
CacheFrom []string
|
||||
SecurityOpt []string
|
||||
ExtraHosts []string // List of extra hosts
|
||||
Target string
|
||||
SessionID string
|
||||
Platform string
|
||||
// Version specifies the version of the underlying builder to use
|
||||
Version BuilderVersion
|
||||
// BuildID is an optional identifier that can be passed together with the
|
||||
// build request. The same identifier can be used to gracefully cancel the
|
||||
// build with the cancel request.
|
||||
BuildID string
|
||||
// Outputs defines configurations for exporting build results. Only supported
|
||||
// in BuildKit mode
|
||||
Outputs []ImageBuildOutput
|
||||
}
|
||||
|
||||
// ImageBuildOutput defines configuration for exporting a build result
|
||||
type ImageBuildOutput struct {
|
||||
Type string
|
||||
Attrs map[string]string
|
||||
}
|
||||
|
||||
// ImageBuildResponse holds information
|
||||
// returned by a server after building
|
||||
// an image.
|
||||
type ImageBuildResponse struct {
|
||||
Body io.ReadCloser
|
||||
OSType string
|
||||
}
|
||||
52
api/types/build/cache.go
Normal file
52
api/types/build/cache.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package build
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
)
|
||||
|
||||
// CacheRecord contains information about a build cache record.
|
||||
type CacheRecord struct {
|
||||
// ID is the unique ID of the build cache record.
|
||||
ID string
|
||||
// Parent is the ID of the parent build cache record.
|
||||
//
|
||||
// Deprecated: deprecated in API v1.42 and up, as it was deprecated in BuildKit; use Parents instead.
|
||||
Parent string `json:"Parent,omitempty"`
|
||||
// Parents is the list of parent build cache record IDs.
|
||||
Parents []string `json:" Parents,omitempty"`
|
||||
// Type is the cache record type.
|
||||
Type string
|
||||
// Description is a description of the build-step that produced the build cache.
|
||||
Description string
|
||||
// InUse indicates if the build cache is in use.
|
||||
InUse bool
|
||||
// Shared indicates if the build cache is shared.
|
||||
Shared bool
|
||||
// Size is the amount of disk space used by the build cache (in bytes).
|
||||
Size int64
|
||||
// CreatedAt is the date and time at which the build cache was created.
|
||||
CreatedAt time.Time
|
||||
// LastUsedAt is the date and time at which the build cache was last used.
|
||||
LastUsedAt *time.Time
|
||||
UsageCount int
|
||||
}
|
||||
|
||||
// CachePruneOptions hold parameters to prune the build cache.
|
||||
type CachePruneOptions struct {
|
||||
All bool
|
||||
ReservedSpace int64
|
||||
MaxUsedSpace int64
|
||||
MinFreeSpace int64
|
||||
Filters filters.Args
|
||||
|
||||
KeepStorage int64 // Deprecated: deprecated in API 1.48.
|
||||
}
|
||||
|
||||
// CachePruneReport contains the response for Engine API:
|
||||
// POST "/build/prune"
|
||||
type CachePruneReport struct {
|
||||
CachesDeleted []string
|
||||
SpaceReclaimed uint64
|
||||
}
|
||||
8
api/types/build/disk_usage.go
Normal file
8
api/types/build/disk_usage.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package build
|
||||
|
||||
// CacheDiskUsage contains disk usage for the build cache.
|
||||
type CacheDiskUsage struct {
|
||||
TotalSize int64
|
||||
Reclaimable int64
|
||||
Items []*CacheRecord
|
||||
}
|
||||
@@ -3,12 +3,7 @@ package types // import "github.com/docker/docker/api/types"
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"io"
|
||||
"net"
|
||||
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
)
|
||||
|
||||
// NewHijackedResponse initializes a [HijackedResponse] type.
|
||||
@@ -51,165 +46,6 @@ func (h *HijackedResponse) CloseWrite() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ImageBuildOptions holds the information
|
||||
// necessary to build images.
|
||||
type ImageBuildOptions struct {
|
||||
Tags []string
|
||||
SuppressOutput bool
|
||||
RemoteContext string
|
||||
NoCache bool
|
||||
Remove bool
|
||||
ForceRemove bool
|
||||
PullParent bool
|
||||
Isolation container.Isolation
|
||||
CPUSetCPUs string
|
||||
CPUSetMems string
|
||||
CPUShares int64
|
||||
CPUQuota int64
|
||||
CPUPeriod int64
|
||||
Memory int64
|
||||
MemorySwap int64
|
||||
CgroupParent string
|
||||
NetworkMode string
|
||||
ShmSize int64
|
||||
Dockerfile string
|
||||
Ulimits []*container.Ulimit
|
||||
// BuildArgs needs to be a *string instead of just a string so that
|
||||
// we can tell the difference between "" (empty string) and no value
|
||||
// at all (nil). See the parsing of buildArgs in
|
||||
// api/server/router/build/build_routes.go for even more info.
|
||||
BuildArgs map[string]*string
|
||||
AuthConfigs map[string]registry.AuthConfig
|
||||
Context io.Reader
|
||||
Labels map[string]string
|
||||
// squash the resulting image's layers to the parent
|
||||
// preserves the original image and creates a new one from the parent with all
|
||||
// the changes applied to a single layer
|
||||
Squash bool
|
||||
// CacheFrom specifies images that are used for matching cache. Images
|
||||
// specified here do not need to have a valid parent chain to match cache.
|
||||
CacheFrom []string
|
||||
SecurityOpt []string
|
||||
ExtraHosts []string // List of extra hosts
|
||||
Target string
|
||||
SessionID string
|
||||
Platform string
|
||||
// Version specifies the version of the underlying builder to use
|
||||
Version BuilderVersion
|
||||
// BuildID is an optional identifier that can be passed together with the
|
||||
// build request. The same identifier can be used to gracefully cancel the
|
||||
// build with the cancel request.
|
||||
BuildID string
|
||||
// Outputs defines configurations for exporting build results. Only supported
|
||||
// in BuildKit mode
|
||||
Outputs []ImageBuildOutput
|
||||
}
|
||||
|
||||
// ImageBuildOutput defines configuration for exporting a build result
|
||||
type ImageBuildOutput struct {
|
||||
Type string
|
||||
Attrs map[string]string
|
||||
}
|
||||
|
||||
// BuilderVersion sets the version of underlying builder to use
|
||||
type BuilderVersion string
|
||||
|
||||
const (
|
||||
// BuilderV1 is the first generation builder in docker daemon
|
||||
BuilderV1 BuilderVersion = "1"
|
||||
// BuilderBuildKit is builder based on moby/buildkit project
|
||||
BuilderBuildKit BuilderVersion = "2"
|
||||
)
|
||||
|
||||
// ImageBuildResponse holds information
|
||||
// returned by a server after building
|
||||
// an image.
|
||||
type ImageBuildResponse struct {
|
||||
Body io.ReadCloser
|
||||
OSType string
|
||||
}
|
||||
|
||||
// NodeListOptions holds parameters to list nodes with.
|
||||
type NodeListOptions struct {
|
||||
Filters filters.Args
|
||||
}
|
||||
|
||||
// NodeRemoveOptions holds parameters to remove nodes with.
|
||||
type NodeRemoveOptions struct {
|
||||
Force bool
|
||||
}
|
||||
|
||||
// ServiceCreateOptions contains the options to use when creating a service.
|
||||
type ServiceCreateOptions struct {
|
||||
// EncodedRegistryAuth is the encoded registry authorization credentials to
|
||||
// use when updating the service.
|
||||
//
|
||||
// This field follows the format of the X-Registry-Auth header.
|
||||
EncodedRegistryAuth string
|
||||
|
||||
// QueryRegistry indicates whether the service update requires
|
||||
// contacting a registry. A registry may be contacted to retrieve
|
||||
// the image digest and manifest, which in turn can be used to update
|
||||
// platform or other information about the service.
|
||||
QueryRegistry bool
|
||||
}
|
||||
|
||||
// Values for RegistryAuthFrom in ServiceUpdateOptions
|
||||
const (
|
||||
RegistryAuthFromSpec = "spec"
|
||||
RegistryAuthFromPreviousSpec = "previous-spec"
|
||||
)
|
||||
|
||||
// ServiceUpdateOptions contains the options to be used for updating services.
|
||||
type ServiceUpdateOptions struct {
|
||||
// EncodedRegistryAuth is the encoded registry authorization credentials to
|
||||
// use when updating the service.
|
||||
//
|
||||
// This field follows the format of the X-Registry-Auth header.
|
||||
EncodedRegistryAuth string
|
||||
|
||||
// TODO(stevvooe): Consider moving the version parameter of ServiceUpdate
|
||||
// into this field. While it does open API users up to racy writes, most
|
||||
// users may not need that level of consistency in practice.
|
||||
|
||||
// RegistryAuthFrom specifies where to find the registry authorization
|
||||
// credentials if they are not given in EncodedRegistryAuth. Valid
|
||||
// values are "spec" and "previous-spec".
|
||||
RegistryAuthFrom string
|
||||
|
||||
// Rollback indicates whether a server-side rollback should be
|
||||
// performed. When this is set, the provided spec will be ignored.
|
||||
// The valid values are "previous" and "none". An empty value is the
|
||||
// same as "none".
|
||||
Rollback string
|
||||
|
||||
// QueryRegistry indicates whether the service update requires
|
||||
// contacting a registry. A registry may be contacted to retrieve
|
||||
// the image digest and manifest, which in turn can be used to update
|
||||
// platform or other information about the service.
|
||||
QueryRegistry bool
|
||||
}
|
||||
|
||||
// ServiceListOptions holds parameters to list services with.
|
||||
type ServiceListOptions struct {
|
||||
Filters filters.Args
|
||||
|
||||
// Status indicates whether the server should include the service task
|
||||
// count of running and desired tasks.
|
||||
Status bool
|
||||
}
|
||||
|
||||
// ServiceInspectOptions holds parameters related to the "service inspect"
|
||||
// operation.
|
||||
type ServiceInspectOptions struct {
|
||||
InsertDefaults bool
|
||||
}
|
||||
|
||||
// TaskListOptions holds parameters to list tasks with.
|
||||
type TaskListOptions struct {
|
||||
Filters filters.Args
|
||||
}
|
||||
|
||||
// PluginRemoveOptions holds parameters to remove plugins.
|
||||
type PluginRemoveOptions struct {
|
||||
Force bool
|
||||
@@ -243,13 +79,6 @@ type PluginInstallOptions struct {
|
||||
Args []string
|
||||
}
|
||||
|
||||
// SwarmUnlockKeyResponse contains the response for Engine API:
|
||||
// GET /swarm/unlockkey
|
||||
type SwarmUnlockKeyResponse struct {
|
||||
// UnlockKey is the unlock key in ASCII-armored format.
|
||||
UnlockKey string
|
||||
}
|
||||
|
||||
// PluginCreateOptions hold all options to plugin create.
|
||||
type PluginCreateOptions struct {
|
||||
RepoName string
|
||||
|
||||
@@ -104,7 +104,7 @@ type MountPoint struct {
|
||||
// State stores container's running state
|
||||
// it's part of ContainerJSONBase and returned by "inspect" command
|
||||
type State struct {
|
||||
Status string // String representation of the container state. Can be one of "created", "running", "paused", "restarting", "removing", "exited", or "dead"
|
||||
Status ContainerState // String representation of the container state. Can be one of "created", "running", "paused", "restarting", "removing", "exited", or "dead"
|
||||
Running bool
|
||||
Paused bool
|
||||
Restarting bool
|
||||
@@ -132,7 +132,7 @@ type Summary struct {
|
||||
SizeRw int64 `json:",omitempty"`
|
||||
SizeRootFs int64 `json:",omitempty"`
|
||||
Labels map[string]string
|
||||
State string
|
||||
State ContainerState
|
||||
Status string
|
||||
HostConfig struct {
|
||||
NetworkMode string `json:",omitempty"`
|
||||
|
||||
8
api/types/container/disk_usage.go
Normal file
8
api/types/container/disk_usage.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package container
|
||||
|
||||
// DiskUsage contains disk usage for containers.
|
||||
type DiskUsage struct {
|
||||
TotalSize int64
|
||||
Reclaimable int64
|
||||
Items []*Summary
|
||||
}
|
||||
@@ -1,18 +1,27 @@
|
||||
package container
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// HealthStatus is a string representation of the container's health.
|
||||
//
|
||||
// It currently is an alias for string, but may become a distinct type in future.
|
||||
type HealthStatus = string
|
||||
|
||||
// Health states
|
||||
const (
|
||||
NoHealthcheck = "none" // Indicates there is no healthcheck
|
||||
Starting = "starting" // Starting indicates that the container is not yet ready
|
||||
Healthy = "healthy" // Healthy indicates that the container is running correctly
|
||||
Unhealthy = "unhealthy" // Unhealthy indicates that the container has a problem
|
||||
NoHealthcheck HealthStatus = "none" // Indicates there is no healthcheck
|
||||
Starting HealthStatus = "starting" // Starting indicates that the container is not yet ready
|
||||
Healthy HealthStatus = "healthy" // Healthy indicates that the container is running correctly
|
||||
Unhealthy HealthStatus = "unhealthy" // Unhealthy indicates that the container has a problem
|
||||
)
|
||||
|
||||
// Health stores information about the container's healthcheck results
|
||||
type Health struct {
|
||||
Status string // Status is one of [Starting], [Healthy] or [Unhealthy].
|
||||
Status HealthStatus // Status is one of [Starting], [Healthy] or [Unhealthy].
|
||||
FailingStreak int // FailingStreak is the number of consecutive failures
|
||||
Log []*HealthcheckResult // Log contains the last few results (oldest first)
|
||||
}
|
||||
@@ -24,3 +33,18 @@ type HealthcheckResult struct {
|
||||
ExitCode int // ExitCode meanings: 0=healthy, 1=unhealthy, 2=reserved (considered unhealthy), else=error running probe
|
||||
Output string // Output from last check
|
||||
}
|
||||
|
||||
var validHealths = []string{
|
||||
NoHealthcheck, Starting, Healthy, Unhealthy,
|
||||
}
|
||||
|
||||
// ValidateHealthStatus checks if the provided string is a valid
|
||||
// container [HealthStatus].
|
||||
func ValidateHealthStatus(s HealthStatus) error {
|
||||
switch s {
|
||||
case NoHealthcheck, Starting, Healthy, Unhealthy:
|
||||
return nil
|
||||
default:
|
||||
return errInvalidParameter{error: fmt.Errorf("invalid value for health (%s): must be one of %s", s, strings.Join(validHealths, ", "))}
|
||||
}
|
||||
}
|
||||
|
||||
31
api/types/container/health_test.go
Normal file
31
api/types/container/health_test.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
func TestValidateHealthStatus(t *testing.T) {
|
||||
tests := []struct {
|
||||
health HealthStatus
|
||||
expectedErr string
|
||||
}{
|
||||
{health: Healthy},
|
||||
{health: Unhealthy},
|
||||
{health: Starting},
|
||||
{health: NoHealthcheck},
|
||||
{health: "invalid-health-string", expectedErr: `invalid value for health (invalid-health-string): must be one of none, starting, healthy, unhealthy`},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.health, func(t *testing.T) {
|
||||
err := ValidateHealthStatus(tc.health)
|
||||
if tc.expectedErr == "" {
|
||||
assert.NilError(t, err)
|
||||
} else {
|
||||
assert.Error(t, err, tc.expectedErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -145,7 +145,7 @@ func (n NetworkMode) IsDefault() bool {
|
||||
|
||||
// IsPrivate indicates whether container uses its private network stack.
|
||||
func (n NetworkMode) IsPrivate() bool {
|
||||
return !(n.IsHost() || n.IsContainer())
|
||||
return !n.IsHost() && !n.IsContainer()
|
||||
}
|
||||
|
||||
// IsContainer indicates whether container uses a container network stack.
|
||||
@@ -230,7 +230,7 @@ type PidMode string
|
||||
|
||||
// IsPrivate indicates whether the container uses its own new pid namespace.
|
||||
func (n PidMode) IsPrivate() bool {
|
||||
return !(n.IsHost() || n.IsContainer())
|
||||
return !n.IsHost() && !n.IsContainer()
|
||||
}
|
||||
|
||||
// IsHost indicates whether the container uses the host's pid namespace.
|
||||
|
||||
@@ -102,7 +102,7 @@ func TestValidateRestartPolicy(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// isInvalidParameter is a minimal implementation of [github.com/docker/docker/errdefs.IsInvalidParameter],
|
||||
// isInvalidParameter is a minimal implementation of [github.com/containerd/errdefs.IsInvalidArgument],
|
||||
// because this was the only import of that package in api/types, which is the
|
||||
// package imported by external users.
|
||||
func isInvalidParameter(err error) bool {
|
||||
|
||||
64
api/types/container/state.go
Normal file
64
api/types/container/state.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ContainerState is a string representation of the container's current state.
|
||||
//
|
||||
// It currently is an alias for string, but may become a distinct type in the future.
|
||||
type ContainerState = string
|
||||
|
||||
const (
|
||||
StateCreated ContainerState = "created" // StateCreated indicates the container is created, but not (yet) started.
|
||||
StateRunning ContainerState = "running" // StateRunning indicates that the container is running.
|
||||
StatePaused ContainerState = "paused" // StatePaused indicates that the container's current state is paused.
|
||||
StateRestarting ContainerState = "restarting" // StateRestarting indicates that the container is currently restarting.
|
||||
StateRemoving ContainerState = "removing" // StateRemoving indicates that the container is being removed.
|
||||
StateExited ContainerState = "exited" // StateExited indicates that the container exited.
|
||||
StateDead ContainerState = "dead" // StateDead indicates that the container failed to be deleted. Containers in this state are attempted to be cleaned up when the daemon restarts.
|
||||
)
|
||||
|
||||
var validStates = []ContainerState{
|
||||
StateCreated, StateRunning, StatePaused, StateRestarting, StateRemoving, StateExited, StateDead,
|
||||
}
|
||||
|
||||
// ValidateContainerState checks if the provided string is a valid
|
||||
// container [ContainerState].
|
||||
func ValidateContainerState(s ContainerState) error {
|
||||
switch s {
|
||||
case StateCreated, StateRunning, StatePaused, StateRestarting, StateRemoving, StateExited, StateDead:
|
||||
return nil
|
||||
default:
|
||||
return errInvalidParameter{error: fmt.Errorf("invalid value for state (%s): must be one of %s", s, strings.Join(validStates, ", "))}
|
||||
}
|
||||
}
|
||||
|
||||
// StateStatus is used to return container wait results.
|
||||
// Implements exec.ExitCode interface.
|
||||
// This type is needed as State include a sync.Mutex field which make
|
||||
// copying it unsafe.
|
||||
type StateStatus struct {
|
||||
exitCode int
|
||||
err error
|
||||
}
|
||||
|
||||
// ExitCode returns current exitcode for the state.
|
||||
func (s StateStatus) ExitCode() int {
|
||||
return s.exitCode
|
||||
}
|
||||
|
||||
// Err returns current error for the state. Returns nil if the container had
|
||||
// exited on its own.
|
||||
func (s StateStatus) Err() error {
|
||||
return s.err
|
||||
}
|
||||
|
||||
// NewStateStatus returns a new StateStatus with the given exit code and error.
|
||||
func NewStateStatus(exitCode int, err error) StateStatus {
|
||||
return StateStatus{
|
||||
exitCode: exitCode,
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
33
api/types/container/state_test.go
Normal file
33
api/types/container/state_test.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
func TestValidateContainerState(t *testing.T) {
|
||||
tests := []struct {
|
||||
state ContainerState
|
||||
expectedErr string
|
||||
}{
|
||||
{state: StatePaused},
|
||||
{state: StateRestarting},
|
||||
{state: StateRunning},
|
||||
{state: StateDead},
|
||||
{state: StateCreated},
|
||||
{state: StateExited},
|
||||
{state: StateRemoving},
|
||||
{state: "invalid-state-string", expectedErr: `invalid value for state (invalid-state-string): must be one of created, running, paused, restarting, removing, exited, dead`},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.state, func(t *testing.T) {
|
||||
err := ValidateContainerState(tc.state)
|
||||
if tc.expectedErr == "" {
|
||||
assert.NilError(t, err)
|
||||
} else {
|
||||
assert.Error(t, err, tc.expectedErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
8
api/types/image/disk_usage.go
Normal file
8
api/types/image/disk_usage.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package image
|
||||
|
||||
// DiskUsage contains disk usage for images.
|
||||
type DiskUsage struct {
|
||||
TotalSize int64
|
||||
Reclaimable int64
|
||||
Items []*Summary
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package image
|
||||
import (
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/storage"
|
||||
dockerspec "github.com/moby/docker-image-spec/specs-go/v1"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
@@ -84,7 +85,7 @@ type InspectResponse struct {
|
||||
// Author is the name of the author that was specified when committing the
|
||||
// image, or as specified through MAINTAINER (deprecated) in the Dockerfile.
|
||||
Author string
|
||||
Config *container.Config
|
||||
Config *dockerspec.DockerOCIImageConfig
|
||||
|
||||
// Architecture is the hardware CPU architecture that the image runs on.
|
||||
Architecture string
|
||||
|
||||
@@ -83,6 +83,7 @@ type ListOptions struct {
|
||||
|
||||
// RemoveOptions holds parameters to remove images.
|
||||
type RemoveOptions struct {
|
||||
Platforms []ocispec.Platform
|
||||
Force bool
|
||||
PruneChildren bool
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.22
|
||||
//go:build go1.23
|
||||
|
||||
package registry // import "github.com/docker/docker/api/types/registry"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.22
|
||||
//go:build go1.23
|
||||
|
||||
package registry
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package swarm // import "github.com/docker/docker/api/types/swarm"
|
||||
|
||||
import "os"
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
)
|
||||
|
||||
// Config represents a config.
|
||||
type Config struct {
|
||||
@@ -44,3 +48,15 @@ type ConfigReference struct {
|
||||
ConfigID string
|
||||
ConfigName string
|
||||
}
|
||||
|
||||
// ConfigCreateResponse contains the information returned to a client
|
||||
// on the creation of a new config.
|
||||
type ConfigCreateResponse struct {
|
||||
// ID is the id of the created config.
|
||||
ID string
|
||||
}
|
||||
|
||||
// ConfigListOptions holds parameters to list configs
|
||||
type ConfigListOptions struct {
|
||||
Filters filters.Args
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package swarm // import "github.com/docker/docker/api/types/swarm"
|
||||
import "github.com/docker/docker/api/types/filters"
|
||||
|
||||
// Node represents a node.
|
||||
type Node struct {
|
||||
@@ -137,3 +138,13 @@ const (
|
||||
type Topology struct {
|
||||
Segments map[string]string `json:",omitempty"`
|
||||
}
|
||||
|
||||
// NodeListOptions holds parameters to list nodes with.
|
||||
type NodeListOptions struct {
|
||||
Filters filters.Args
|
||||
}
|
||||
|
||||
// NodeRemoveOptions holds parameters to remove nodes with.
|
||||
type NodeRemoveOptions struct {
|
||||
Force bool
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package swarm // import "github.com/docker/docker/api/types/swarm"
|
||||
|
||||
import "os"
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
)
|
||||
|
||||
// Secret represents a secret.
|
||||
type Secret struct {
|
||||
@@ -48,3 +52,15 @@ type SecretReference struct {
|
||||
SecretID string
|
||||
SecretName string
|
||||
}
|
||||
|
||||
// SecretCreateResponse contains the information returned to a client
|
||||
// on the creation of a new secret.
|
||||
type SecretCreateResponse struct {
|
||||
// ID is the id of the created secret.
|
||||
ID string
|
||||
}
|
||||
|
||||
// SecretListOptions holds parameters to list secrets
|
||||
type SecretListOptions struct {
|
||||
Filters filters.Args
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package swarm // import "github.com/docker/docker/api/types/swarm"
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
)
|
||||
|
||||
// Service represents a service.
|
||||
type Service struct {
|
||||
@@ -200,3 +204,69 @@ type JobStatus struct {
|
||||
// Swarm manager.
|
||||
LastExecution time.Time `json:",omitempty"`
|
||||
}
|
||||
|
||||
// ServiceCreateOptions contains the options to use when creating a service.
|
||||
type ServiceCreateOptions struct {
|
||||
// EncodedRegistryAuth is the encoded registry authorization credentials to
|
||||
// use when updating the service.
|
||||
//
|
||||
// This field follows the format of the X-Registry-Auth header.
|
||||
EncodedRegistryAuth string
|
||||
|
||||
// QueryRegistry indicates whether the service update requires
|
||||
// contacting a registry. A registry may be contacted to retrieve
|
||||
// the image digest and manifest, which in turn can be used to update
|
||||
// platform or other information about the service.
|
||||
QueryRegistry bool
|
||||
}
|
||||
|
||||
// Values for RegistryAuthFrom in ServiceUpdateOptions
|
||||
const (
|
||||
RegistryAuthFromSpec = "spec"
|
||||
RegistryAuthFromPreviousSpec = "previous-spec"
|
||||
)
|
||||
|
||||
// ServiceUpdateOptions contains the options to be used for updating services.
|
||||
type ServiceUpdateOptions struct {
|
||||
// EncodedRegistryAuth is the encoded registry authorization credentials to
|
||||
// use when updating the service.
|
||||
//
|
||||
// This field follows the format of the X-Registry-Auth header.
|
||||
EncodedRegistryAuth string
|
||||
|
||||
// TODO(stevvooe): Consider moving the version parameter of ServiceUpdate
|
||||
// into this field. While it does open API users up to racy writes, most
|
||||
// users may not need that level of consistency in practice.
|
||||
|
||||
// RegistryAuthFrom specifies where to find the registry authorization
|
||||
// credentials if they are not given in EncodedRegistryAuth. Valid
|
||||
// values are "spec" and "previous-spec".
|
||||
RegistryAuthFrom string
|
||||
|
||||
// Rollback indicates whether a server-side rollback should be
|
||||
// performed. When this is set, the provided spec will be ignored.
|
||||
// The valid values are "previous" and "none". An empty value is the
|
||||
// same as "none".
|
||||
Rollback string
|
||||
|
||||
// QueryRegistry indicates whether the service update requires
|
||||
// contacting a registry. A registry may be contacted to retrieve
|
||||
// the image digest and manifest, which in turn can be used to update
|
||||
// platform or other information about the service.
|
||||
QueryRegistry bool
|
||||
}
|
||||
|
||||
// ServiceListOptions holds parameters to list services with.
|
||||
type ServiceListOptions struct {
|
||||
Filters filters.Args
|
||||
|
||||
// Status indicates whether the server should include the service task
|
||||
// count of running and desired tasks.
|
||||
Status bool
|
||||
}
|
||||
|
||||
// ServiceInspectOptions holds parameters related to the "service inspect"
|
||||
// operation.
|
||||
type ServiceInspectOptions struct {
|
||||
InsertDefaults bool
|
||||
}
|
||||
|
||||
@@ -235,3 +235,10 @@ type UpdateFlags struct {
|
||||
RotateManagerToken bool
|
||||
RotateManagerUnlockKey bool
|
||||
}
|
||||
|
||||
// UnlockKeyResponse contains the response for Engine API:
|
||||
// GET /swarm/unlockkey
|
||||
type UnlockKeyResponse struct {
|
||||
// UnlockKey is the unlock key in ASCII-armored format.
|
||||
UnlockKey string
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package swarm // import "github.com/docker/docker/api/types/swarm"
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/swarm/runtime"
|
||||
)
|
||||
|
||||
@@ -223,3 +224,8 @@ type VolumeAttachment struct {
|
||||
// in the ContainerSpec, that this volume fulfills.
|
||||
Target string `json:",omitempty"`
|
||||
}
|
||||
|
||||
// TaskListOptions holds parameters to list tasks with.
|
||||
type TaskListOptions struct {
|
||||
Filters filters.Args
|
||||
}
|
||||
|
||||
17
api/types/system/disk_usage.go
Normal file
17
api/types/system/disk_usage.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/docker/docker/api/types/build"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/image"
|
||||
"github.com/docker/docker/api/types/volume"
|
||||
)
|
||||
|
||||
// DiskUsage contains response of Engine API for API 1.49 and greater:
|
||||
// GET "/system/df"
|
||||
type DiskUsage struct {
|
||||
Images *image.DiskUsage
|
||||
Containers *container.DiskUsage
|
||||
Volumes *volume.DiskUsage
|
||||
BuildCache *build.CacheDiskUsage
|
||||
}
|
||||
@@ -29,8 +29,6 @@ type Info struct {
|
||||
CPUSet bool
|
||||
PidsLimit bool
|
||||
IPv4Forwarding bool
|
||||
BridgeNfIptables bool `json:"BridgeNfIptables"` // Deprecated: netfilter module is now loaded on-demand and no longer during daemon startup, making this field obsolete. This field is always false and will be removed in the next release.
|
||||
BridgeNfIP6tables bool `json:"BridgeNfIp6tables"` // Deprecated: netfilter module is now loaded on-demand and no longer during daemon startup, making this field obsolete. This field is always false and will be removed in the next release.
|
||||
Debug bool
|
||||
NFd int
|
||||
OomKillDisable bool
|
||||
@@ -75,6 +73,7 @@ type Info struct {
|
||||
DefaultAddressPools []NetworkAddressPool `json:",omitempty"`
|
||||
FirewallBackend *FirewallInfo `json:"FirewallBackend,omitempty"`
|
||||
CDISpecDirs []string
|
||||
DiscoveredDevices []DeviceInfo `json:",omitempty"`
|
||||
|
||||
Containerd *ContainerdInfo `json:",omitempty"`
|
||||
|
||||
@@ -160,3 +159,12 @@ type FirewallInfo struct {
|
||||
// Info is a list of label/value pairs, containing information related to the firewall.
|
||||
Info [][2]string `json:"Info,omitempty"`
|
||||
}
|
||||
|
||||
// DeviceInfo represents a discoverable device from a device driver.
|
||||
type DeviceInfo struct {
|
||||
// Source indicates the origin device driver.
|
||||
Source string `json:"Source"`
|
||||
// ID is the unique identifier for the device.
|
||||
// Example: CDI FQDN like "vendor.com/gpu=0", or other driver-specific device ID
|
||||
ID string `json:"ID"`
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ func GetTimestamp(value string, reference time.Time) (string, error) {
|
||||
|
||||
var format string
|
||||
// if the string has a Z or a + or three dashes use parse otherwise use parseinlocation
|
||||
parseInLocation := !(strings.ContainsAny(value, "zZ+") || strings.Count(value, "-") == 3)
|
||||
parseInLocation := !strings.ContainsAny(value, "zZ+") && strings.Count(value, "-") != 3
|
||||
|
||||
if strings.Contains(value, ".") {
|
||||
if parseInLocation {
|
||||
@@ -105,23 +105,23 @@ func GetTimestamp(value string, reference time.Time) (string, error) {
|
||||
// since := time.Unix(seconds, nanoseconds)
|
||||
//
|
||||
// returns seconds as defaultSeconds if value == ""
|
||||
func ParseTimestamps(value string, defaultSeconds int64) (seconds int64, nanoseconds int64, err error) {
|
||||
func ParseTimestamps(value string, defaultSeconds int64) (seconds int64, nanoseconds int64, _ error) {
|
||||
if value == "" {
|
||||
return defaultSeconds, 0, nil
|
||||
}
|
||||
return parseTimestamp(value)
|
||||
}
|
||||
|
||||
func parseTimestamp(value string) (sec int64, nsec int64, err error) {
|
||||
func parseTimestamp(value string) (seconds int64, nanoseconds int64, _ error) {
|
||||
s, n, ok := strings.Cut(value, ".")
|
||||
sec, err = strconv.ParseInt(s, 10, 64)
|
||||
sec, err := strconv.ParseInt(s, 10, 64)
|
||||
if err != nil {
|
||||
return sec, 0, err
|
||||
}
|
||||
if !ok {
|
||||
return sec, 0, nil
|
||||
}
|
||||
nsec, err = strconv.ParseInt(n, 10, 64)
|
||||
nsec, err := strconv.ParseInt(n, 10, 64)
|
||||
if err != nil {
|
||||
return sec, nsec, err
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package types // import "github.com/docker/docker/api/types"
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types/build"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/image"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/api/types/volume"
|
||||
@@ -24,7 +22,7 @@ type Ping struct {
|
||||
APIVersion string
|
||||
OSType string
|
||||
Experimental bool
|
||||
BuilderVersion BuilderVersion
|
||||
BuilderVersion build.BuilderVersion
|
||||
|
||||
// SwarmStatus provides information about the current swarm status of the
|
||||
// engine, obtained from the "Swarm" header in the API response.
|
||||
@@ -91,41 +89,10 @@ type DiskUsage struct {
|
||||
Images []*image.Summary
|
||||
Containers []*container.Summary
|
||||
Volumes []*volume.Volume
|
||||
BuildCache []*BuildCache
|
||||
BuildCache []*build.CacheRecord
|
||||
BuilderSize int64 `json:",omitempty"` // Deprecated: deprecated in API 1.38, and no longer used since API 1.40.
|
||||
}
|
||||
|
||||
// BuildCachePruneReport contains the response for Engine API:
|
||||
// POST "/build/prune"
|
||||
type BuildCachePruneReport struct {
|
||||
CachesDeleted []string
|
||||
SpaceReclaimed uint64
|
||||
}
|
||||
|
||||
// SecretCreateResponse contains the information returned to a client
|
||||
// on the creation of a new secret.
|
||||
type SecretCreateResponse struct {
|
||||
// ID is the id of the created secret.
|
||||
ID string
|
||||
}
|
||||
|
||||
// SecretListOptions holds parameters to list secrets
|
||||
type SecretListOptions struct {
|
||||
Filters filters.Args
|
||||
}
|
||||
|
||||
// ConfigCreateResponse contains the information returned to a client
|
||||
// on the creation of a new config.
|
||||
type ConfigCreateResponse struct {
|
||||
// ID is the id of the created config.
|
||||
ID string
|
||||
}
|
||||
|
||||
// ConfigListOptions holds parameters to list configs
|
||||
type ConfigListOptions struct {
|
||||
Filters filters.Args
|
||||
}
|
||||
|
||||
// PushResult contains the tag, manifest digest, and manifest size from the
|
||||
// push. It's used to signal this information to the trust code in the client
|
||||
// so it can sign the manifest if necessary.
|
||||
@@ -134,46 +101,3 @@ type PushResult struct {
|
||||
Digest string
|
||||
Size int
|
||||
}
|
||||
|
||||
// BuildResult contains the image id of a successful build
|
||||
type BuildResult struct {
|
||||
ID string
|
||||
}
|
||||
|
||||
// BuildCache contains information about a build cache record.
|
||||
type BuildCache struct {
|
||||
// ID is the unique ID of the build cache record.
|
||||
ID string
|
||||
// Parent is the ID of the parent build cache record.
|
||||
//
|
||||
// Deprecated: deprecated in API v1.42 and up, as it was deprecated in BuildKit; use Parents instead.
|
||||
Parent string `json:"Parent,omitempty"`
|
||||
// Parents is the list of parent build cache record IDs.
|
||||
Parents []string `json:" Parents,omitempty"`
|
||||
// Type is the cache record type.
|
||||
Type string
|
||||
// Description is a description of the build-step that produced the build cache.
|
||||
Description string
|
||||
// InUse indicates if the build cache is in use.
|
||||
InUse bool
|
||||
// Shared indicates if the build cache is shared.
|
||||
Shared bool
|
||||
// Size is the amount of disk space used by the build cache (in bytes).
|
||||
Size int64
|
||||
// CreatedAt is the date and time at which the build cache was created.
|
||||
CreatedAt time.Time
|
||||
// LastUsedAt is the date and time at which the build cache was last used.
|
||||
LastUsedAt *time.Time
|
||||
UsageCount int
|
||||
}
|
||||
|
||||
// BuildCachePruneOptions hold parameters to prune the build cache
|
||||
type BuildCachePruneOptions struct {
|
||||
All bool
|
||||
ReservedSpace int64
|
||||
MaxUsedSpace int64
|
||||
MinFreeSpace int64
|
||||
Filters filters.Args
|
||||
|
||||
KeepStorage int64 // Deprecated: deprecated in API 1.48.
|
||||
}
|
||||
|
||||
@@ -3,10 +3,12 @@ package types
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/docker/api/types/build"
|
||||
"github.com/docker/docker/api/types/common"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/image"
|
||||
"github.com/docker/docker/api/types/storage"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
)
|
||||
|
||||
// IDResponse Response to an API call that returns just an Id.
|
||||
@@ -113,3 +115,127 @@ type ImageInspect = image.InspectResponse
|
||||
//
|
||||
// Deprecated: moved to [github.com/docker/docker/api/types/registry.RequestAuthConfig].
|
||||
type RequestPrivilegeFunc func(context.Context) (string, error)
|
||||
|
||||
// SecretCreateResponse contains the information returned to a client
|
||||
// on the creation of a new secret.
|
||||
//
|
||||
// Deprecated: use [swarm.SecretCreateResponse].
|
||||
type SecretCreateResponse = swarm.SecretCreateResponse
|
||||
|
||||
// SecretListOptions holds parameters to list secrets
|
||||
//
|
||||
// Deprecated: use [swarm.SecretListOptions].
|
||||
type SecretListOptions = swarm.SecretListOptions
|
||||
|
||||
// ConfigCreateResponse contains the information returned to a client
|
||||
// on the creation of a new config.
|
||||
//
|
||||
// Deprecated: use [swarm.ConfigCreateResponse].
|
||||
type ConfigCreateResponse = swarm.ConfigCreateResponse
|
||||
|
||||
// ConfigListOptions holds parameters to list configs
|
||||
//
|
||||
// Deprecated: use [swarm.ConfigListOptions].
|
||||
type ConfigListOptions = swarm.ConfigListOptions
|
||||
|
||||
// NodeListOptions holds parameters to list nodes with.
|
||||
//
|
||||
// Deprecated: use [swarm.NodeListOptions].
|
||||
type NodeListOptions = swarm.NodeListOptions
|
||||
|
||||
// NodeRemoveOptions holds parameters to remove nodes with.
|
||||
//
|
||||
// Deprecated: use [swarm.NodeRemoveOptions].
|
||||
type NodeRemoveOptions = swarm.NodeRemoveOptions
|
||||
|
||||
// TaskListOptions holds parameters to list tasks with.
|
||||
//
|
||||
// Deprecated: use [swarm.TaskListOptions].
|
||||
type TaskListOptions = swarm.TaskListOptions
|
||||
|
||||
// ServiceCreateOptions contains the options to use when creating a service.
|
||||
//
|
||||
// Deprecated: use [swarm.ServiceCreateOptions].
|
||||
type ServiceCreateOptions = swarm.ServiceCreateOptions
|
||||
|
||||
// ServiceUpdateOptions contains the options to be used for updating services.
|
||||
//
|
||||
// Deprecated: use [swarm.ServiceCreateOptions].
|
||||
type ServiceUpdateOptions = swarm.ServiceUpdateOptions
|
||||
|
||||
const (
|
||||
RegistryAuthFromSpec = swarm.RegistryAuthFromSpec // Deprecated: use [swarm.RegistryAuthFromSpec].
|
||||
RegistryAuthFromPreviousSpec = swarm.RegistryAuthFromPreviousSpec // Deprecated: use [swarm.RegistryAuthFromPreviousSpec].
|
||||
)
|
||||
|
||||
// ServiceListOptions holds parameters to list services with.
|
||||
//
|
||||
// Deprecated: use [swarm.ServiceListOptions].
|
||||
type ServiceListOptions = swarm.ServiceListOptions
|
||||
|
||||
// ServiceInspectOptions holds parameters related to the "service inspect"
|
||||
// operation.
|
||||
//
|
||||
// Deprecated: use [swarm.ServiceInspectOptions].
|
||||
type ServiceInspectOptions = swarm.ServiceInspectOptions
|
||||
|
||||
// SwarmUnlockKeyResponse contains the response for Engine API:
|
||||
// GET /swarm/unlockkey
|
||||
//
|
||||
// Deprecated: use [swarm.UnlockKeyResponse].
|
||||
type SwarmUnlockKeyResponse = swarm.UnlockKeyResponse
|
||||
|
||||
// BuildCache contains information about a build cache record.
|
||||
//
|
||||
// Deprecated: deprecated in API 1.49. Use [build.CacheRecord] instead.
|
||||
type BuildCache = build.CacheRecord
|
||||
|
||||
// BuildCachePruneOptions hold parameters to prune the build cache
|
||||
//
|
||||
// Deprecated: use [build.CachePruneOptions].
|
||||
type BuildCachePruneOptions = build.CachePruneOptions
|
||||
|
||||
// BuildCachePruneReport contains the response for Engine API:
|
||||
// POST "/build/prune"
|
||||
//
|
||||
// Deprecated: use [build.CachePruneReport].
|
||||
type BuildCachePruneReport = build.CachePruneReport
|
||||
|
||||
// BuildResult contains the image id of a successful build/
|
||||
//
|
||||
// Deprecated: use [build.Result].
|
||||
type BuildResult = build.Result
|
||||
|
||||
// ImageBuildOptions holds the information
|
||||
// necessary to build images.
|
||||
//
|
||||
// Deprecated: use [build.ImageBuildOptions].
|
||||
type ImageBuildOptions = build.ImageBuildOptions
|
||||
|
||||
// ImageBuildOutput defines configuration for exporting a build result
|
||||
//
|
||||
// Deprecated: use [build.ImageBuildOutput].
|
||||
type ImageBuildOutput = build.ImageBuildOutput
|
||||
|
||||
// ImageBuildResponse holds information
|
||||
// returned by a server after building
|
||||
// an image.
|
||||
//
|
||||
// Deprecated: use [build.ImageBuildResponse].
|
||||
type ImageBuildResponse = build.ImageBuildResponse
|
||||
|
||||
// BuilderVersion sets the version of underlying builder to use
|
||||
//
|
||||
// Deprecated: use [build.BuilderVersion].
|
||||
type BuilderVersion = build.BuilderVersion
|
||||
|
||||
const (
|
||||
// BuilderV1 is the first generation builder in docker daemon
|
||||
//
|
||||
// Deprecated: use [build.BuilderV1].
|
||||
BuilderV1 = build.BuilderV1
|
||||
// BuilderBuildKit is builder based on moby/buildkit project
|
||||
//
|
||||
// Deprecated: use [build.BuilderBuildKit].
|
||||
BuilderBuildKit = build.BuilderBuildKit
|
||||
)
|
||||
|
||||
8
api/types/volume/disk_usage.go
Normal file
8
api/types/volume/disk_usage.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package volume
|
||||
|
||||
// DiskUsage contains disk usage for volumes.
|
||||
type DiskUsage struct {
|
||||
TotalSize int64
|
||||
Reclaimable int64
|
||||
Items []*Volume
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.22
|
||||
//go:build go1.23
|
||||
|
||||
package containerimage
|
||||
|
||||
@@ -19,10 +19,8 @@ import (
|
||||
"github.com/containerd/containerd/v2/core/leases"
|
||||
"github.com/containerd/containerd/v2/core/remotes"
|
||||
"github.com/containerd/containerd/v2/core/remotes/docker"
|
||||
"github.com/containerd/containerd/v2/core/remotes/docker/schema1" //nolint:staticcheck // Ignore SA1019: "github.com/containerd/containerd/remotes/docker/schema1" is deprecated: use images formatted in Docker Image Manifest v2, Schema 2, or OCI Image Spec v1.
|
||||
"github.com/containerd/containerd/v2/pkg/gc"
|
||||
cdreference "github.com/containerd/containerd/v2/pkg/reference"
|
||||
ctdreference "github.com/containerd/containerd/v2/pkg/reference"
|
||||
c8dreference "github.com/containerd/containerd/v2/pkg/reference"
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
@@ -183,7 +181,7 @@ func (is *Source) resolveRemote(ctx context.Context, ref string, platform *ocisp
|
||||
p = *platform
|
||||
}
|
||||
// key is used to synchronize resolutions that can happen in parallel when doing multi-stage.
|
||||
key := "getconfig::" + ref + "::" + platforms.Format(p)
|
||||
key := "getconfig::" + ref + "::" + platforms.FormatAll(p)
|
||||
res, err := is.g.Do(ctx, key, func(ctx context.Context) (*resolveRemoteResult, error) {
|
||||
res := resolver.DefaultPool.GetResolver(is.RegistryHosts, ref, "pull", sm, g)
|
||||
dgst, dt, err := imageutil.Config(ctx, ref, res, is.ContentStore, is.LeaseManager, platform)
|
||||
@@ -343,10 +341,10 @@ func (p *puller) resolveLocal() {
|
||||
}
|
||||
|
||||
func (p *puller) resolve(ctx context.Context, g session.Group) error {
|
||||
_, err := p.g.Do(ctx, "", func(ctx context.Context) (_ struct{}, err error) {
|
||||
_, err := p.g.Do(ctx, "", func(ctx context.Context) (_ struct{}, retErr error) {
|
||||
resolveProgressDone := oneOffProgress(ctx, "resolve "+p.src.Reference.String())
|
||||
defer func() {
|
||||
resolveProgressDone(err)
|
||||
_ = resolveProgressDone(retErr)
|
||||
}()
|
||||
|
||||
ref, err := distreference.ParseNormalizedNamed(p.src.Reference.String())
|
||||
@@ -370,11 +368,11 @@ func (p *puller) resolve(ctx context.Context, g session.Group) error {
|
||||
// It may be possible to have a mapping between schema 1 manifests
|
||||
// and the schema 2 manifests they are converted to.
|
||||
if p.config == nil && p.desc.MediaType != c8dimages.MediaTypeDockerSchema1Manifest {
|
||||
ref, err := distreference.WithDigest(ref, p.desc.Digest)
|
||||
refWithDigest, err := distreference.WithDigest(ref, p.desc.Digest)
|
||||
if err != nil {
|
||||
return struct{}{}, err
|
||||
}
|
||||
_, dt, err := p.is.ResolveImageConfig(ctx, ref.String(), sourceresolver.Opt{
|
||||
_, dt, err := p.is.ResolveImageConfig(ctx, refWithDigest.String(), sourceresolver.Opt{
|
||||
Platform: &p.platform,
|
||||
ImageOpt: &sourceresolver.ResolveImageOpt{
|
||||
ResolveMode: p.src.ResolveMode.String(),
|
||||
@@ -384,7 +382,7 @@ func (p *puller) resolve(ctx context.Context, g session.Group) error {
|
||||
return struct{}{}, err
|
||||
}
|
||||
|
||||
p.ref = ref.String()
|
||||
p.ref = refWithDigest.String()
|
||||
p.config = dt
|
||||
}
|
||||
return struct{}{}, nil
|
||||
@@ -519,18 +517,13 @@ func (p *puller) Snapshot(ctx context.Context, g session.Group) (cache.Immutable
|
||||
|
||||
var nonLayers []digest.Digest
|
||||
|
||||
var (
|
||||
schema1Converter *schema1.Converter
|
||||
handlers []c8dimages.Handler
|
||||
)
|
||||
var handlers []c8dimages.Handler
|
||||
if p.desc.MediaType == c8dimages.MediaTypeDockerSchema1Manifest {
|
||||
schema1Converter, err = schema1.NewConverter(p.is.ContentStore, fetcher)
|
||||
if err != nil {
|
||||
stopProgress()
|
||||
return nil, err
|
||||
}
|
||||
handlers = append(handlers, schema1Converter)
|
||||
|
||||
stopProgress()
|
||||
// similar to [github.com/docker/docker/distribution/DeprecatedSchema1ImageError]
|
||||
errMsg := "support for Docker Image Format v1 and Docker Image manifest version 2, schema 1 has been removed in Docker Engine v28.2. " +
|
||||
"More information at https://docs.docker.com/go/deprecated-image-specs/"
|
||||
return nil, cerrdefs.ErrInvalidArgument.WithMessage(errMsg)
|
||||
// TODO: Optimize to do dispatch and integrate pulling with download manager,
|
||||
// leverage existing blob mapping and layer storage
|
||||
} else {
|
||||
@@ -569,13 +562,6 @@ func (p *puller) Snapshot(ctx context.Context, g session.Group) (cache.Immutable
|
||||
}
|
||||
defer stopProgress()
|
||||
|
||||
if schema1Converter != nil {
|
||||
p.desc, err = schema1Converter.Convert(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
mfst, err := c8dimages.Manifest(ctx, p.is.ContentStore, p.desc, platform)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -697,7 +683,7 @@ type layerDescriptor struct {
|
||||
fetcher remotes.Fetcher
|
||||
desc ocispec.Descriptor
|
||||
diffID layer.DiffID
|
||||
ref ctdreference.Spec
|
||||
ref c8dreference.Spec
|
||||
}
|
||||
|
||||
func (ld *layerDescriptor) Key() string {
|
||||
@@ -902,15 +888,15 @@ type statusInfo struct {
|
||||
|
||||
func oneOffProgress(ctx context.Context, id string) func(err error) error {
|
||||
pw, _, _ := progress.NewFromContext(ctx)
|
||||
now := time.Now()
|
||||
s := time.Now()
|
||||
st := progress.Status{
|
||||
Started: &now,
|
||||
Started: &s,
|
||||
}
|
||||
_ = pw.Write(id, st)
|
||||
return func(err error) error {
|
||||
// TODO: set error on status
|
||||
now := time.Now()
|
||||
st.Completed = &now
|
||||
c := time.Now()
|
||||
st.Completed = &c
|
||||
_ = pw.Write(id, st)
|
||||
_ = pw.Close()
|
||||
return err
|
||||
@@ -943,7 +929,7 @@ func platformMatches(img *image.Image, p *ocispec.Platform) bool {
|
||||
}
|
||||
|
||||
func applySourcePolicies(ctx context.Context, str string, spls []*spb.Policy) (string, error) {
|
||||
ref, err := cdreference.Parse(str)
|
||||
ref, err := c8dreference.Parse(str)
|
||||
if err != nil {
|
||||
return "", errors.WithStack(err)
|
||||
}
|
||||
@@ -964,7 +950,7 @@ func applySourcePolicies(ctx context.Context, str string, spls []*spb.Policy) (s
|
||||
if t != srctypes.DockerImageScheme {
|
||||
return "", &imageutil.ResolveToNonImageError{Ref: str, Updated: newRef}
|
||||
}
|
||||
ref, err = cdreference.Parse(newRef)
|
||||
ref, err = c8dreference.Parse(newRef)
|
||||
if err != nil {
|
||||
return "", errors.WithStack(err)
|
||||
}
|
||||
|
||||
@@ -25,8 +25,7 @@ func (s *snapshotter) EnsureLayer(ctx context.Context, key string) ([]layer.Diff
|
||||
s.layerCreateLocker.Lock(key)
|
||||
defer s.layerCreateLocker.Unlock(key)
|
||||
|
||||
diffIDs, err := s.GetDiffIDs(ctx, key)
|
||||
if err != nil {
|
||||
if diffIDs, err := s.GetDiffIDs(ctx, key); err != nil {
|
||||
return nil, err
|
||||
} else if diffIDs != nil {
|
||||
return diffIDs, nil
|
||||
|
||||
@@ -12,8 +12,8 @@ import (
|
||||
|
||||
"github.com/containerd/containerd/v2/core/remotes/docker"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
"github.com/docker/docker/api/types/build"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
timetypes "github.com/docker/docker/api/types/time"
|
||||
@@ -149,15 +149,15 @@ func (b *Builder) Cancel(ctx context.Context, id string) error {
|
||||
}
|
||||
|
||||
// DiskUsage returns a report about space used by build cache
|
||||
func (b *Builder) DiskUsage(ctx context.Context) ([]*types.BuildCache, error) {
|
||||
func (b *Builder) DiskUsage(ctx context.Context) ([]*build.CacheRecord, error) {
|
||||
duResp, err := b.controller.DiskUsage(ctx, &controlapi.DiskUsageRequest{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var items []*types.BuildCache
|
||||
var items []*build.CacheRecord
|
||||
for _, r := range duResp.Record {
|
||||
items = append(items, &types.BuildCache{
|
||||
items = append(items, &build.CacheRecord{
|
||||
ID: r.ID,
|
||||
Parent: r.Parent, //nolint:staticcheck // ignore SA1019 (Parent field is deprecated)
|
||||
Parents: r.Parents,
|
||||
@@ -186,7 +186,7 @@ func (b *Builder) DiskUsage(ctx context.Context) ([]*types.BuildCache, error) {
|
||||
}
|
||||
|
||||
// Prune clears all reclaimable build cache.
|
||||
func (b *Builder) Prune(ctx context.Context, opts types.BuildCachePruneOptions) (int64, []string, error) {
|
||||
func (b *Builder) Prune(ctx context.Context, opts build.CachePruneOptions) (int64, []string, error) {
|
||||
ch := make(chan *controlapi.UsageRecord)
|
||||
|
||||
eg, ctx := errgroup.WithContext(ctx)
|
||||
@@ -437,7 +437,7 @@ func (b *Builder) Build(ctx context.Context, opt backend.BuildConfig) (*builder.
|
||||
return errors.Errorf("missing image id")
|
||||
}
|
||||
out.ImageID = imgID
|
||||
return aux.Emit("moby.image.id", types.BuildResult{ID: imgID})
|
||||
return aux.Emit("moby.image.id", build.Result{ID: imgID})
|
||||
})
|
||||
|
||||
ch := make(chan *controlapi.StatusResponse)
|
||||
@@ -535,11 +535,12 @@ type wrapRC struct {
|
||||
func (w *wrapRC) Read(b []byte) (int, error) {
|
||||
n, err := w.ReadCloser.Read(b)
|
||||
if err != nil {
|
||||
e := err
|
||||
if e == io.EOF {
|
||||
e = nil
|
||||
switch err {
|
||||
case io.EOF:
|
||||
w.close(nil)
|
||||
default:
|
||||
w.close(err)
|
||||
}
|
||||
w.close(e)
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
@@ -639,7 +640,7 @@ func toBuildkitUlimits(inp []*container.Ulimit) (string, error) {
|
||||
return strings.Join(ulimits, ","), nil
|
||||
}
|
||||
|
||||
func toBuildkitPruneInfo(opts types.BuildCachePruneOptions) (client.PruneInfo, error) {
|
||||
func toBuildkitPruneInfo(opts build.CachePruneOptions) (client.PruneInfo, error) {
|
||||
var until time.Duration
|
||||
untilValues := opts.Filters.Get("until") // canonical
|
||||
unusedForValues := opts.Filters.Get("unused-for") // deprecated synonym for "until" filter
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
"github.com/containerd/containerd/v2/plugins/content/local"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/build"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/builder/builder-next/adapters/containerimage"
|
||||
"github.com/docker/docker/builder/builder-next/adapters/localinlinecache"
|
||||
@@ -57,7 +57,6 @@ import (
|
||||
"github.com/moby/buildkit/worker/containerd"
|
||||
"github.com/moby/buildkit/worker/label"
|
||||
"github.com/pkg/errors"
|
||||
"go.etcd.io/bbolt"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
"go.opentelemetry.io/otel/sdk/trace"
|
||||
"tags.cncf.io/container-device-interface/pkg/cdi"
|
||||
@@ -152,7 +151,18 @@ func newSnapshotterController(ctx context.Context, rt http.RoundTripper, opt Opt
|
||||
wo.RegistryHosts = opt.RegistryHosts
|
||||
wo.Labels = getLabels(opt, wo.Labels)
|
||||
|
||||
exec, err := newExecutor(opt.Root, opt.DefaultCgroupParent, opt.NetworkController, dns, opt.Rootless, opt.IdentityMapping, opt.ApparmorProfile, cdiManager)
|
||||
exec, err := newExecutor(
|
||||
opt.Root,
|
||||
opt.DefaultCgroupParent,
|
||||
opt.NetworkController,
|
||||
dns,
|
||||
opt.Rootless,
|
||||
opt.IdentityMapping,
|
||||
opt.ApparmorProfile,
|
||||
cdiManager,
|
||||
opt.ContainerdAddress,
|
||||
opt.ContainerdNamespace,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -208,7 +218,7 @@ func newSnapshotterController(ctx context.Context, rt http.RoundTripper, opt Opt
|
||||
}
|
||||
|
||||
func openHistoryDB(root string, fn string, cfg *config.BuilderHistoryConfig) (*bolt.DB, *bkconfig.HistoryConfig, error) {
|
||||
db, err := bbolt.Open(filepath.Join(root, fn), 0o600, nil)
|
||||
db, err := bolt.Open(filepath.Join(root, fn), 0o600, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -332,7 +342,18 @@ func newGraphDriverController(ctx context.Context, rt http.RoundTripper, opt Opt
|
||||
return nil, err
|
||||
}
|
||||
|
||||
exec, err := newExecutor(root, opt.DefaultCgroupParent, opt.NetworkController, dns, opt.Rootless, opt.IdentityMapping, opt.ApparmorProfile, cdiManager)
|
||||
exec, err := newExecutorGD(
|
||||
root,
|
||||
opt.DefaultCgroupParent,
|
||||
opt.NetworkController,
|
||||
dns,
|
||||
opt.Rootless,
|
||||
opt.IdentityMapping,
|
||||
opt.ApparmorProfile,
|
||||
cdiManager,
|
||||
opt.ContainerdAddress,
|
||||
opt.ContainerdNamespace,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -445,7 +466,7 @@ func newGraphDriverController(ctx context.Context, rt http.RoundTripper, opt Opt
|
||||
|
||||
func getGCPolicy(conf config.BuilderConfig, root string) ([]client.PruneInfo, error) {
|
||||
var gcPolicy []client.PruneInfo
|
||||
if conf.GC.Enabled {
|
||||
if conf.GC.IsEnabled() {
|
||||
if conf.GC.Policy == nil {
|
||||
reservedSpace, maxUsedSpace, minFreeSpace, err := parseGCPolicy(config.BuilderGCRule{
|
||||
ReservedSpace: conf.GC.DefaultReservedSpace,
|
||||
@@ -464,7 +485,7 @@ func getGCPolicy(conf config.BuilderConfig, root string) ([]client.PruneInfo, er
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gcPolicy[i], err = toBuildkitPruneInfo(types.BuildCachePruneOptions{
|
||||
gcPolicy[i], err = toBuildkitPruneInfo(build.CachePruneOptions{
|
||||
All: p.All,
|
||||
ReservedSpace: reservedSpace,
|
||||
MaxUsedSpace: maxUsedSpace,
|
||||
|
||||
119
builder/builder-next/executor.go
Normal file
119
builder/builder-next/executor.go
Normal file
@@ -0,0 +1,119 @@
|
||||
package buildkit
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/containerd/log"
|
||||
"github.com/docker/docker/daemon/config"
|
||||
"github.com/docker/docker/libnetwork"
|
||||
"github.com/moby/buildkit/executor/oci"
|
||||
resourcestypes "github.com/moby/buildkit/executor/resources/types"
|
||||
"github.com/moby/buildkit/identity"
|
||||
"github.com/moby/buildkit/util/network"
|
||||
)
|
||||
|
||||
type bridgeProvider struct {
|
||||
*libnetwork.Controller
|
||||
Root string
|
||||
}
|
||||
|
||||
type lnInterface struct {
|
||||
ep *libnetwork.Endpoint
|
||||
sbx *libnetwork.Sandbox
|
||||
sync.Once
|
||||
err error
|
||||
ready chan struct{}
|
||||
provider *bridgeProvider
|
||||
}
|
||||
|
||||
func (p *bridgeProvider) New(_ context.Context, _ string) (network.Namespace, error) {
|
||||
n, err := p.NetworkByName(networkName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
iface := &lnInterface{ready: make(chan struct{}), provider: p}
|
||||
iface.Once.Do(func() {
|
||||
go iface.init(p.Controller, n)
|
||||
})
|
||||
|
||||
return iface, nil
|
||||
}
|
||||
|
||||
func (p *bridgeProvider) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (iface *lnInterface) init(c *libnetwork.Controller, n *libnetwork.Network) {
|
||||
defer close(iface.ready)
|
||||
id := identity.NewID()
|
||||
|
||||
ep, err := n.CreateEndpoint(context.TODO(), id, libnetwork.CreateOptionDisableResolution())
|
||||
if err != nil {
|
||||
iface.err = err
|
||||
return
|
||||
}
|
||||
|
||||
sbx, err := c.NewSandbox(
|
||||
context.TODO(),
|
||||
id,
|
||||
libnetwork.OptionUseExternalKey(),
|
||||
libnetwork.OptionHostsPath(filepath.Join(iface.provider.Root, id, "hosts")),
|
||||
libnetwork.OptionResolvConfPath(filepath.Join(iface.provider.Root, id, "resolv.conf")),
|
||||
)
|
||||
if err != nil {
|
||||
iface.err = err
|
||||
return
|
||||
}
|
||||
|
||||
if err := ep.Join(context.TODO(), sbx); err != nil {
|
||||
iface.err = err
|
||||
return
|
||||
}
|
||||
|
||||
iface.sbx = sbx
|
||||
iface.ep = ep
|
||||
}
|
||||
|
||||
// TODO(neersighted): Unstub Sample(), and collect data from the libnetwork Endpoint.
|
||||
func (iface *lnInterface) Sample() (*resourcestypes.NetworkSample, error) {
|
||||
return &resourcestypes.NetworkSample{}, nil
|
||||
}
|
||||
|
||||
func (iface *lnInterface) Close() error {
|
||||
<-iface.ready
|
||||
if iface.sbx != nil {
|
||||
go func() {
|
||||
if err := iface.sbx.Delete(context.TODO()); err != nil {
|
||||
log.G(context.TODO()).WithError(err).Errorf("failed to delete builder network sandbox")
|
||||
}
|
||||
if err := os.RemoveAll(filepath.Join(iface.provider.Root, iface.sbx.ContainerID())); err != nil {
|
||||
log.G(context.TODO()).WithError(err).Errorf("failed to delete builder sandbox directory")
|
||||
}
|
||||
}()
|
||||
}
|
||||
return iface.err
|
||||
}
|
||||
|
||||
func getDNSConfig(cfg config.DNSConfig) *oci.DNSConfig {
|
||||
if cfg.DNS != nil || cfg.DNSSearch != nil || cfg.DNSOptions != nil {
|
||||
return &oci.DNSConfig{
|
||||
Nameservers: ipAddresses(cfg.DNS),
|
||||
SearchDomains: cfg.DNSSearch,
|
||||
Options: cfg.DNSOptions,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ipAddresses(ips []net.IP) []string {
|
||||
var addrs []string
|
||||
for _, ip := range ips {
|
||||
addrs = append(addrs, ip.String())
|
||||
}
|
||||
return addrs
|
||||
}
|
||||
@@ -2,22 +2,17 @@ package buildkit
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/containerd/log"
|
||||
"github.com/docker/docker/daemon/config"
|
||||
"github.com/docker/docker/libnetwork"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/moby/buildkit/executor"
|
||||
"github.com/moby/buildkit/executor/oci"
|
||||
"github.com/moby/buildkit/executor/resources"
|
||||
resourcestypes "github.com/moby/buildkit/executor/resources/types"
|
||||
"github.com/moby/buildkit/executor/runcexecutor"
|
||||
"github.com/moby/buildkit/identity"
|
||||
"github.com/moby/buildkit/solver/llbsolver/cdidevices"
|
||||
"github.com/moby/buildkit/solver/pb"
|
||||
"github.com/moby/buildkit/util/network"
|
||||
@@ -27,7 +22,7 @@ import (
|
||||
|
||||
const networkName = "bridge"
|
||||
|
||||
func newExecutor(root, cgroupParent string, net *libnetwork.Controller, dnsConfig *oci.DNSConfig, rootless bool, idmap user.IdentityMapping, apparmorProfile string, cdiManager *cdidevices.Manager) (executor.Executor, error) {
|
||||
func newExecutor(root, cgroupParent string, net *libnetwork.Controller, dnsConfig *oci.DNSConfig, rootless bool, idmap user.IdentityMapping, apparmorProfile string, cdiManager *cdidevices.Manager, _, _ string) (executor.Executor, error) {
|
||||
netRoot := filepath.Join(root, "net")
|
||||
networkProviders := map[pb.NetMode]network.Provider{
|
||||
pb.NetMode_UNSET: &bridgeProvider{Controller: net, Root: netRoot},
|
||||
@@ -79,67 +74,21 @@ func newExecutor(root, cgroupParent string, net *libnetwork.Controller, dnsConfi
|
||||
}, networkProviders)
|
||||
}
|
||||
|
||||
type bridgeProvider struct {
|
||||
*libnetwork.Controller
|
||||
Root string
|
||||
}
|
||||
|
||||
func (p *bridgeProvider) New(ctx context.Context, hostname string) (network.Namespace, error) {
|
||||
n, err := p.NetworkByName(networkName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
iface := &lnInterface{ready: make(chan struct{}), provider: p}
|
||||
iface.Once.Do(func() {
|
||||
go iface.init(p.Controller, n)
|
||||
})
|
||||
|
||||
return iface, nil
|
||||
}
|
||||
|
||||
func (p *bridgeProvider) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type lnInterface struct {
|
||||
ep *libnetwork.Endpoint
|
||||
sbx *libnetwork.Sandbox
|
||||
sync.Once
|
||||
err error
|
||||
ready chan struct{}
|
||||
provider *bridgeProvider
|
||||
}
|
||||
|
||||
func (iface *lnInterface) init(c *libnetwork.Controller, n *libnetwork.Network) {
|
||||
defer close(iface.ready)
|
||||
id := identity.NewID()
|
||||
|
||||
ep, err := n.CreateEndpoint(context.TODO(), id, libnetwork.CreateOptionDisableResolution())
|
||||
if err != nil {
|
||||
iface.err = err
|
||||
return
|
||||
}
|
||||
|
||||
sbx, err := c.NewSandbox(context.TODO(), id, libnetwork.OptionUseExternalKey(), libnetwork.OptionHostsPath(filepath.Join(iface.provider.Root, id, "hosts")),
|
||||
libnetwork.OptionResolvConfPath(filepath.Join(iface.provider.Root, id, "resolv.conf")))
|
||||
if err != nil {
|
||||
iface.err = err
|
||||
return
|
||||
}
|
||||
|
||||
if err := ep.Join(context.TODO(), sbx); err != nil {
|
||||
iface.err = err
|
||||
return
|
||||
}
|
||||
|
||||
iface.sbx = sbx
|
||||
iface.ep = ep
|
||||
}
|
||||
|
||||
// TODO(neersighted): Unstub Sample(), and collect data from the libnetwork Endpoint.
|
||||
func (iface *lnInterface) Sample() (*resourcestypes.NetworkSample, error) {
|
||||
return &resourcestypes.NetworkSample{}, nil
|
||||
// newExecutorGD calls newExecutor() on Linux.
|
||||
// Created for symmetry with the non-linux platforms, esp. Windows.
|
||||
func newExecutorGD(root, cgroupParent string, net *libnetwork.Controller, dnsConfig *oci.DNSConfig, rootless bool, idmap user.IdentityMapping, apparmorProfile string, cdiManager *cdidevices.Manager, _, _ string) (executor.Executor, error) {
|
||||
return newExecutor(
|
||||
root,
|
||||
cgroupParent,
|
||||
net,
|
||||
dnsConfig,
|
||||
rootless,
|
||||
idmap,
|
||||
apparmorProfile,
|
||||
cdiManager,
|
||||
"",
|
||||
"",
|
||||
)
|
||||
}
|
||||
|
||||
func (iface *lnInterface) Set(s *specs.Spec) error {
|
||||
@@ -158,37 +107,3 @@ func (iface *lnInterface) Set(s *specs.Spec) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (iface *lnInterface) Close() error {
|
||||
<-iface.ready
|
||||
if iface.sbx != nil {
|
||||
go func() {
|
||||
if err := iface.sbx.Delete(context.TODO()); err != nil {
|
||||
log.G(context.TODO()).WithError(err).Errorf("failed to delete builder network sandbox")
|
||||
}
|
||||
if err := os.RemoveAll(filepath.Join(iface.provider.Root, iface.sbx.ContainerID())); err != nil {
|
||||
log.G(context.TODO()).WithError(err).Errorf("failed to delete builder sandbox directory")
|
||||
}
|
||||
}()
|
||||
}
|
||||
return iface.err
|
||||
}
|
||||
|
||||
func getDNSConfig(cfg config.DNSConfig) *oci.DNSConfig {
|
||||
if cfg.DNS != nil || cfg.DNSSearch != nil || cfg.DNSOptions != nil {
|
||||
return &oci.DNSConfig{
|
||||
Nameservers: ipAddresses(cfg.DNS),
|
||||
SearchDomains: cfg.DNSSearch,
|
||||
Options: cfg.DNSOptions,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ipAddresses(ips []net.IP) []string {
|
||||
var addrs []string
|
||||
for _, ip := range ips {
|
||||
addrs = append(addrs, ip.String())
|
||||
}
|
||||
return addrs
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"errors"
|
||||
"runtime"
|
||||
|
||||
"github.com/docker/docker/daemon/config"
|
||||
"github.com/docker/docker/libnetwork"
|
||||
"github.com/moby/buildkit/executor"
|
||||
"github.com/moby/buildkit/executor/oci"
|
||||
@@ -16,10 +15,6 @@ import (
|
||||
"github.com/moby/sys/user"
|
||||
)
|
||||
|
||||
func newExecutor(_, _ string, _ *libnetwork.Controller, _ *oci.DNSConfig, _ bool, _ user.IdentityMapping, _ string, _ *cdidevices.Manager) (executor.Executor, error) {
|
||||
return &stubExecutor{}, nil
|
||||
}
|
||||
|
||||
type stubExecutor struct{}
|
||||
|
||||
func (w *stubExecutor) Run(ctx context.Context, id string, root executor.Mount, mounts []executor.Mount, process executor.ProcessInfo, started chan<- struct{}) (resourcetypes.Recorder, error) {
|
||||
@@ -30,6 +25,7 @@ func (w *stubExecutor) Exec(ctx context.Context, id string, process executor.Pro
|
||||
return errors.New("buildkit executor not implemented for " + runtime.GOOS)
|
||||
}
|
||||
|
||||
func getDNSConfig(config.DNSConfig) *oci.DNSConfig {
|
||||
return nil
|
||||
// function stub created for GraphDriver
|
||||
func newExecutorGD(_, _ string, _ *libnetwork.Controller, _ *oci.DNSConfig, _ bool, _ user.IdentityMapping, _ string, _ *cdidevices.Manager, _, _ string) (executor.Executor, error) {
|
||||
return &stubExecutor{}, nil
|
||||
}
|
||||
|
||||
7
builder/builder-next/executor_others.go
Normal file
7
builder/builder-next/executor_others.go
Normal file
@@ -0,0 +1,7 @@
|
||||
//go:build !linux && !windows
|
||||
|
||||
package buildkit
|
||||
|
||||
func newExecutor(_, _ string, _ *libnetwork.Controller, _ *oci.DNSConfig, _ bool, _ user.IdentityMapping, _ string, _ *cdidevices.Manager, _, _ string) (executor.Executor, error) {
|
||||
return &stubExecutor{}, nil
|
||||
}
|
||||
94
builder/builder-next/executor_windows.go
Normal file
94
builder/builder-next/executor_windows.go
Normal file
@@ -0,0 +1,94 @@
|
||||
package buildkit
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"path/filepath"
|
||||
|
||||
ctd "github.com/containerd/containerd/v2/client"
|
||||
"github.com/containerd/log"
|
||||
"github.com/docker/docker/libnetwork"
|
||||
"github.com/moby/buildkit/executor"
|
||||
"github.com/moby/buildkit/executor/containerdexecutor"
|
||||
"github.com/moby/buildkit/executor/oci"
|
||||
"github.com/moby/buildkit/solver/llbsolver/cdidevices"
|
||||
"github.com/moby/buildkit/solver/pb"
|
||||
"github.com/moby/buildkit/util/network"
|
||||
"github.com/moby/sys/user"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
)
|
||||
|
||||
const networkName = "nat"
|
||||
|
||||
func newExecutor(
|
||||
root string,
|
||||
_ string,
|
||||
net *libnetwork.Controller,
|
||||
dns *oci.DNSConfig,
|
||||
_ bool,
|
||||
_ user.IdentityMapping,
|
||||
_ string,
|
||||
cdiManager *cdidevices.Manager,
|
||||
containerdAddr string,
|
||||
containerdNamespace string,
|
||||
) (executor.Executor, error) {
|
||||
netRoot := filepath.Join(root, "net")
|
||||
np := map[pb.NetMode]network.Provider{
|
||||
pb.NetMode_UNSET: &bridgeProvider{Controller: net, Root: netRoot},
|
||||
pb.NetMode_NONE: network.NewNoneProvider(),
|
||||
}
|
||||
|
||||
opt := ctd.WithDefaultNamespace(containerdNamespace)
|
||||
client, err := ctd.New(containerdAddr, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
executorOpts := containerdexecutor.ExecutorOptions{
|
||||
Client: client,
|
||||
Root: root,
|
||||
DNSConfig: dns,
|
||||
CDIManager: cdiManager,
|
||||
NetworkProviders: np,
|
||||
}
|
||||
return containerdexecutor.New(executorOpts), nil
|
||||
}
|
||||
|
||||
func (iface *lnInterface) Set(s *specs.Spec) error {
|
||||
<-iface.ready
|
||||
if iface.err != nil {
|
||||
log.G(context.TODO()).WithError(iface.err).Error("failed to set networking spec")
|
||||
return iface.err
|
||||
}
|
||||
|
||||
allowUnqualifiedDNSQuery := false
|
||||
var epList []string
|
||||
for _, ep := range iface.sbx.Endpoints() {
|
||||
data, err := ep.DriverInfo()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if data["hnsid"] != nil {
|
||||
epList = append(epList, data["hnsid"].(string))
|
||||
}
|
||||
|
||||
if data["AllowUnqualifiedDNSQuery"] != nil {
|
||||
allowUnqualifiedDNSQuery = true
|
||||
}
|
||||
}
|
||||
if s.Windows == nil {
|
||||
s.Windows = &specs.Windows{}
|
||||
}
|
||||
if s.Windows.Network == nil {
|
||||
s.Windows.Network = &specs.WindowsNetwork{}
|
||||
}
|
||||
s.Windows.Network.EndpointList = epList
|
||||
s.Windows.Network.AllowUnqualifiedDNSQuery = allowUnqualifiedDNSQuery
|
||||
|
||||
if b, err := json.Marshal(s); err == nil {
|
||||
log.G(context.TODO()).Debugf("Generated spec: %s", string(b))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
// SanitizeRepoAndTags parses the raw names to a slice of repoAndTag.
|
||||
// It removes duplicates and validates each repoName and tag to not contain a digest.
|
||||
func SanitizeRepoAndTags(names []string) (repoAndTags []string, err error) {
|
||||
func SanitizeRepoAndTags(names []string) (repoAndTags []string, _ error) {
|
||||
uniqNames := map[string]struct{}{}
|
||||
for _, repo := range names {
|
||||
if repo == "" {
|
||||
|
||||
@@ -158,15 +158,7 @@ func (w *Worker) Labels() map[string]string {
|
||||
// Platforms returns one or more platforms supported by the image.
|
||||
func (w *Worker) Platforms(noCache bool) []ocispec.Platform {
|
||||
if noCache {
|
||||
pm := make(map[string]struct{}, len(w.Opt.Platforms))
|
||||
for _, p := range w.Opt.Platforms {
|
||||
pm[platforms.Format(p)] = struct{}{}
|
||||
}
|
||||
for _, p := range archutil.SupportedPlatforms(noCache) {
|
||||
if _, ok := pm[platforms.Format(p)]; !ok {
|
||||
w.Opt.Platforms = append(w.Opt.Platforms, p)
|
||||
}
|
||||
}
|
||||
w.Opt.Platforms = mergePlatforms(w.Opt.Platforms, archutil.SupportedPlatforms(noCache))
|
||||
}
|
||||
if len(w.Opt.Platforms) == 0 {
|
||||
return []ocispec.Platform{platforms.DefaultSpec()}
|
||||
@@ -174,6 +166,30 @@ func (w *Worker) Platforms(noCache bool) []ocispec.Platform {
|
||||
return w.Opt.Platforms
|
||||
}
|
||||
|
||||
// mergePlatforms merges the defined platforms with the supported platforms
|
||||
// and returns a new slice of platforms. It ensures no duplicates.
|
||||
func mergePlatforms(defined, supported []ocispec.Platform) []ocispec.Platform {
|
||||
result := []ocispec.Platform{}
|
||||
matchers := make([]platforms.MatchComparer, len(defined))
|
||||
for i, p := range defined {
|
||||
result = append(result, p)
|
||||
matchers[i] = platforms.Only(p)
|
||||
}
|
||||
for _, p := range supported {
|
||||
exists := false
|
||||
for _, m := range matchers {
|
||||
if m.Match(p) {
|
||||
exists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !exists {
|
||||
result = append(result, p)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// GCPolicy returns automatic GC Policy
|
||||
func (w *Worker) GCPolicy() []client.PruneInfo {
|
||||
return w.Opt.GCPolicy
|
||||
@@ -567,15 +583,15 @@ func getLayers(ctx context.Context, descs []ocispec.Descriptor) ([]rootfs.Layer,
|
||||
|
||||
func oneOffProgress(ctx context.Context, id string) func(err error) error {
|
||||
pw, _, _ := progress.NewFromContext(ctx)
|
||||
now := time.Now()
|
||||
s := time.Now()
|
||||
st := progress.Status{
|
||||
Started: &now,
|
||||
Started: &s,
|
||||
}
|
||||
_ = pw.Write(id, st)
|
||||
return func(err error) error {
|
||||
// TODO: set error on status
|
||||
now := time.Now()
|
||||
st.Completed = &now
|
||||
c := time.Now()
|
||||
st.Completed = &c
|
||||
_ = pw.Write(id, st)
|
||||
_ = pw.Close()
|
||||
return err
|
||||
|
||||
76
builder/builder-next/worker/worker_test.go
Normal file
76
builder/builder-next/worker/worker_test.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package worker
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
|
||||
func TestMergePlatforms(t *testing.T) {
|
||||
defaultPlatform := ocispec.Platform{OS: "linux", Architecture: "amd64"}
|
||||
otherPlatform := ocispec.Platform{OS: "windows", Architecture: "amd64"}
|
||||
thirdPlatform := ocispec.Platform{OS: "darwin", Architecture: "arm64"}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
defined []ocispec.Platform
|
||||
supported []ocispec.Platform
|
||||
contains []ocispec.Platform
|
||||
wantLen int
|
||||
}{
|
||||
{
|
||||
name: "AllUnique",
|
||||
defined: []ocispec.Platform{defaultPlatform},
|
||||
supported: []ocispec.Platform{otherPlatform, thirdPlatform},
|
||||
contains: []ocispec.Platform{defaultPlatform, otherPlatform, thirdPlatform},
|
||||
wantLen: 3,
|
||||
},
|
||||
{
|
||||
name: "SomeOverlap",
|
||||
defined: []ocispec.Platform{defaultPlatform, otherPlatform},
|
||||
supported: []ocispec.Platform{otherPlatform, thirdPlatform},
|
||||
contains: []ocispec.Platform{defaultPlatform, otherPlatform, thirdPlatform},
|
||||
wantLen: 3,
|
||||
},
|
||||
{
|
||||
name: "AllOverlap",
|
||||
defined: []ocispec.Platform{defaultPlatform, otherPlatform},
|
||||
supported: []ocispec.Platform{defaultPlatform, otherPlatform},
|
||||
contains: []ocispec.Platform{defaultPlatform, otherPlatform},
|
||||
wantLen: 2,
|
||||
},
|
||||
{
|
||||
name: "EmptySupported",
|
||||
defined: []ocispec.Platform{defaultPlatform},
|
||||
supported: []ocispec.Platform{},
|
||||
contains: []ocispec.Platform{defaultPlatform},
|
||||
wantLen: 1,
|
||||
},
|
||||
{
|
||||
name: "EmptyDefined",
|
||||
defined: []ocispec.Platform{},
|
||||
supported: []ocispec.Platform{defaultPlatform, otherPlatform},
|
||||
contains: []ocispec.Platform{defaultPlatform, otherPlatform},
|
||||
wantLen: 2,
|
||||
},
|
||||
{
|
||||
name: "BothEmpty",
|
||||
defined: []ocispec.Platform{},
|
||||
supported: []ocispec.Platform{},
|
||||
contains: []ocispec.Platform{},
|
||||
wantLen: 0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
got := mergePlatforms(tc.defined, tc.supported)
|
||||
assert.Equal(t, len(got), tc.wantLen)
|
||||
for _, p := range tc.contains {
|
||||
assert.Assert(t, is.Contains(got, p))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
containerpkg "github.com/docker/docker/container"
|
||||
"github.com/docker/docker/image"
|
||||
"github.com/docker/docker/layer"
|
||||
"github.com/opencontainers/go-digest"
|
||||
@@ -66,7 +65,7 @@ type ExecBackend interface {
|
||||
// ContainerStart starts a new container
|
||||
ContainerStart(ctx context.Context, containerID string, checkpoint string, checkpointDir string) error
|
||||
// ContainerWait stops processing until the given container is stopped.
|
||||
ContainerWait(ctx context.Context, name string, condition containerpkg.WaitCondition) (<-chan containerpkg.StateStatus, error)
|
||||
ContainerWait(ctx context.Context, name string, condition container.WaitCondition) (<-chan container.StateStatus, error)
|
||||
}
|
||||
|
||||
// Result is the output produced by a Builder
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
"github.com/docker/docker/api/types/build"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/builder"
|
||||
"github.com/docker/docker/builder/remotecontext"
|
||||
@@ -99,7 +99,7 @@ func (bm *BuildManager) Build(ctx context.Context, config backend.BuildConfig) (
|
||||
|
||||
// builderOptions are the dependencies required by the builder
|
||||
type builderOptions struct {
|
||||
Options *types.ImageBuildOptions
|
||||
Options *build.ImageBuildOptions
|
||||
Backend builder.Backend
|
||||
ProgressWriter backend.ProgressWriter
|
||||
PathCache pathCache
|
||||
@@ -109,7 +109,7 @@ type builderOptions struct {
|
||||
// Builder is a Dockerfile builder
|
||||
// It implements the builder.Backend interface.
|
||||
type Builder struct {
|
||||
options *types.ImageBuildOptions
|
||||
options *build.ImageBuildOptions
|
||||
|
||||
Stdout io.Writer
|
||||
Stderr io.Writer
|
||||
@@ -131,7 +131,7 @@ type Builder struct {
|
||||
func newBuilder(ctx context.Context, options builderOptions) (*Builder, error) {
|
||||
config := options.Options
|
||||
if config == nil {
|
||||
config = new(types.ImageBuildOptions)
|
||||
config = new(build.ImageBuildOptions)
|
||||
}
|
||||
|
||||
imgProber, err := newImageProber(ctx, options.Backend, config.CacheFrom, config.NoCache)
|
||||
@@ -222,7 +222,7 @@ func emitImageID(aux *streamformatter.AuxFormatter, state *dispatchState) error
|
||||
if aux == nil || state.imageID == "" {
|
||||
return nil
|
||||
}
|
||||
return aux.Emit("", types.BuildResult{ID: state.imageID})
|
||||
return aux.Emit("", build.Result{ID: state.imageID})
|
||||
}
|
||||
|
||||
func processMetaArg(meta instructions.ArgCommand, shlex *shell.Lex, args *BuildArgs) error {
|
||||
@@ -331,7 +331,7 @@ func BuildFromConfig(ctx context.Context, config *container.Config, changes []st
|
||||
}
|
||||
|
||||
b, err := newBuilder(ctx, builderOptions{
|
||||
Options: &types.ImageBuildOptions{NoCache: true},
|
||||
Options: &build.ImageBuildOptions{NoCache: true},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -5,12 +5,11 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/containerd/log"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/builder"
|
||||
containerpkg "github.com/docker/docker/container"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@@ -44,7 +43,7 @@ func (c *containerManager) Create(ctx context.Context, runConfig *container.Conf
|
||||
var errCancelled = errors.New("build cancelled")
|
||||
|
||||
// Run a container by ID
|
||||
func (c *containerManager) Run(ctx context.Context, cID string, stdout, stderr io.Writer) (err error) {
|
||||
func (c *containerManager) Run(ctx context.Context, cID string, stdout, stderr io.Writer) error {
|
||||
attached := make(chan struct{})
|
||||
errCh := make(chan error, 1)
|
||||
go func() {
|
||||
@@ -62,7 +61,7 @@ func (c *containerManager) Run(ctx context.Context, cID string, stdout, stderr i
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
log.G(ctx).Debugln("Build cancelled, removing container:", cID)
|
||||
err = c.backend.ContainerRm(cID, &backend.ContainerRmConfig{ForceRemove: true, RemoveVolume: true})
|
||||
err := c.backend.ContainerRm(cID, &backend.ContainerRmConfig{ForceRemove: true, RemoveVolume: true})
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(stdout, "Removing container %s: %v\n", stringid.TruncateID(cID), err)
|
||||
}
|
||||
@@ -85,7 +84,7 @@ func (c *containerManager) Run(ctx context.Context, cID string, stdout, stderr i
|
||||
return err
|
||||
}
|
||||
|
||||
waitC, err := c.backend.ContainerWait(ctx, cID, containerpkg.WaitConditionNotRunning)
|
||||
waitC, err := c.backend.ContainerWait(ctx, cID, container.WaitConditionNotRunning)
|
||||
if err != nil {
|
||||
close(finished)
|
||||
logCancellationError(cancelErrCh, fmt.Sprintf("unable to begin ContainerWait: %s", err))
|
||||
@@ -94,8 +93,7 @@ func (c *containerManager) Run(ctx context.Context, cID string, stdout, stderr i
|
||||
|
||||
if status := <-waitC; status.ExitCode() != 0 {
|
||||
close(finished)
|
||||
logCancellationError(cancelErrCh,
|
||||
fmt.Sprintf("a non-zero code from ContainerWait: %d", status.ExitCode()))
|
||||
logCancellationError(cancelErrCh, fmt.Sprintf("a non-zero code from ContainerWait: %d", status.ExitCode()))
|
||||
return &statusCodeError{code: status.ExitCode(), err: status.Err()}
|
||||
}
|
||||
|
||||
@@ -128,7 +126,7 @@ func (e *statusCodeError) StatusCode() int {
|
||||
// RemoveAll containers managed by this container manager
|
||||
func (c *containerManager) RemoveAll(stdout io.Writer) {
|
||||
for containerID := range c.tmpContainers {
|
||||
if err := c.backend.ContainerRm(containerID, &backend.ContainerRmConfig{ForceRemove: true, RemoveVolume: true}); err != nil && !errdefs.IsNotFound(err) {
|
||||
if err := c.backend.ContainerRm(containerID, &backend.ContainerRmConfig{ForceRemove: true, RemoveVolume: true}); err != nil && !cerrdefs.IsNotFound(err) {
|
||||
_, _ = fmt.Fprintf(stdout, "Removing intermediate container %s: %v\n", stringid.TruncateID(containerID), err)
|
||||
continue
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user