Compare commits
268 Commits
v24.0.0-be
...
v24.0.9
| Author | SHA1 | Date | |
|---|---|---|---|
| 2936816130 | |||
| 50a008a288 | |||
| 07d335afb2 | |||
| 3e7d90796c | |||
| 979eeaa248 | |||
| e0dfb46e22 | |||
| ca4e8ebdbd | |||
| d44992a3de | |||
| 41e3a4ce1f | |||
| 6bce8001c0 | |||
| 02d2f482da | |||
| 27f03ce8e1 | |||
| bda52bd5c2 | |||
| bb3e6c03e4 | |||
| 6bb590f0b9 | |||
| b0c5946ba5 | |||
| bff22cbacf | |||
| 0f82fd8861 | |||
| f8b1e75618 | |||
| 7ba6984ec6 | |||
| fb2f337bc1 | |||
| a976e5084a | |||
| 3ab117e7cd | |||
| f9cdb6f96a | |||
| 13a7d571a1 | |||
| 55cec698b7 | |||
| 9df8eb2b9c | |||
| f5a9aabe74 | |||
| cda067a175 | |||
| 998d2e8d78 | |||
| 65bc42b4af | |||
| 00dbc19cab | |||
| 207d9edaa7 | |||
| e799792d8a | |||
| 327b84fcbf | |||
| 48ec4f339e | |||
| 88a745999d | |||
| afdd53b4e3 | |||
| 12c309fe91 | |||
| f42719820d | |||
| 17770189de | |||
| cde0441dc8 | |||
| d9f94d5719 | |||
| 54d83fbbf4 | |||
| 30a185e936 | |||
| d43c48d5ab | |||
| 1919679638 | |||
| 6c5bc490d4 | |||
| 66558a4e64 | |||
| 0d554b549b | |||
| 8c4dc6c603 | |||
| aef1157742 | |||
| 54894f0224 | |||
| 0f109aafa8 | |||
| 89ce230bd8 | |||
| db6e494b40 | |||
| 5b3e376f86 | |||
| a47889a70f | |||
| 3c10203b39 | |||
| 9662d73735 | |||
| 35453d6c4f | |||
| 2a76b0c4e7 | |||
| 1ebaef3663 | |||
| 8a7833ab62 | |||
| 2e86812d7a | |||
| e7ca37861b | |||
| 1f8118b1cc | |||
| f2a3d50b30 | |||
| edae25f8af | |||
| d848d49be9 | |||
| 4feeefbd68 | |||
| ed223bc820 | |||
| fab55e13ce | |||
| 989b340a6c | |||
| 2fcff17544 | |||
| b74d8e1a53 | |||
| 3789f8a39e | |||
| d3485b9e9f | |||
| 613380299f | |||
| b83959e001 | |||
| 28a08a22b9 | |||
| 8e0393932b | |||
| efd052eb85 | |||
| cdd81d6559 | |||
| d9770a962e | |||
| 6efe73abe0 | |||
| d977531018 | |||
| e9f843bf04 | |||
| cfbaee4689 | |||
| daeee46977 | |||
| 08ad72160f | |||
| 3c4fe7b3e6 | |||
| 98ffe42d84 | |||
| 0d5df48121 | |||
| bf081eec36 | |||
| dc45bcc993 | |||
| 710dd00e95 | |||
| bf632329d2 | |||
| 724548bc7d | |||
| 3c6c0bce1c | |||
| 65655cc262 | |||
| 580730fce9 | |||
| 11606268f8 | |||
| 27a19966fb | |||
| a8987063b3 | |||
| b74562d917 | |||
| c0e376854b | |||
| 3bc4543f83 | |||
| 1481c8ce9a | |||
| b17b6b562d | |||
| e97c765575 | |||
| ced0996600 | |||
| 1ee40e2c74 | |||
| 40cc1d8eae | |||
| 3c2278afae | |||
| 3bd6d6902e | |||
| 05bf7fbcc8 | |||
| c6d7c0bb21 | |||
| dd08d44044 | |||
| 809975d8bd | |||
| 8b5023dd2e | |||
| 9edd9a1f2f | |||
| e93cdb6ca5 | |||
| 2a6348d1b2 | |||
| f4782b3250 | |||
| a5024666e7 | |||
| 39b2a6cc6a | |||
| 7d06f6b2f7 | |||
| 1447974b83 | |||
| 46293e97f7 | |||
| bfe2ff8208 | |||
| 380eb72940 | |||
| b407429628 | |||
| 79c42c0b97 | |||
| a96d0a526c | |||
| 5c5c50d717 | |||
| 4bf11b7562 | |||
| 224c7dbec4 | |||
| e25d5c64c5 | |||
| 419e94df4a | |||
| 3713ee1eea | |||
| 2d5f041bde | |||
| 520e3600ee | |||
| fad718c7ea | |||
| cd68c8f003 | |||
| 05fabe63ba | |||
| 0a2dcdb446 | |||
| a78fd6ca69 | |||
| ddb9220abf | |||
| 9cd335d44b | |||
| bcc889f6cf | |||
| d61e4fe879 | |||
| ee62dcd8dc | |||
| b3750a8461 | |||
| 8e3a2942a5 | |||
| c3ef1ceadf | |||
| 44eebb8bc1 | |||
| 7ecfa2e7fd | |||
| 751bb353fe | |||
| f11f309090 | |||
| 3a6c11773d | |||
| 0823df7daa | |||
| 11af1189d7 | |||
| f118c05e87 | |||
| be0e76bf84 | |||
| f66f7ed7ff | |||
| ec621aae2d | |||
| 2814c01b09 | |||
| 4dc5ea0e80 | |||
| 32f66cbe51 | |||
| cb74dfcd85 | |||
| dc4707edb0 | |||
| 680212238b | |||
| 298e67926e | |||
| aa40216965 | |||
| 9175ffa9b2 | |||
| beb0330a72 | |||
| 405be90634 | |||
| 7a269817b5 | |||
| 41ef7c45cc | |||
| 199b872c98 | |||
| 661f70b52d | |||
| c184a61dab | |||
| e7a60449f7 | |||
| 77541afeab | |||
| f4b354f688 | |||
| e67a7acd06 | |||
| 98fdcd769b | |||
| fb6ae356c7 | |||
| 1d7dd91593 | |||
| de93c9b260 | |||
| 75f2669d56 | |||
| 46615e8724 | |||
| cafdcf283e | |||
| 3768143c2e | |||
| 59e9fbd497 | |||
| 52ac1a974c | |||
| f25ae85b8e | |||
| 58f37f630c | |||
| 8fc956ce77 | |||
| f4201b9302 | |||
| 9f15ba0d13 | |||
| 4f97f55999 | |||
| 0428418d6b | |||
| 05bf6fff2e | |||
| b403a49207 | |||
| 44fce07069 | |||
| f7600fb539 | |||
| fd0621d0fe | |||
| 054343be38 | |||
| 7d72214202 | |||
| 155f7d9e2b | |||
| 1e89037d72 | |||
| 8cfefc6ea2 | |||
| ba7a200f0a | |||
| 73938cd618 | |||
| 2d0ea86b0a | |||
| be6f4cd56c | |||
| 1d70f7cdb4 | |||
| 416e55bedb | |||
| f233becf91 | |||
| afd320c5ab | |||
| bd2c26328f | |||
| 69181952e1 | |||
| f02301ab5d | |||
| 59b07b7253 | |||
| eeaaf5d016 | |||
| 4569378ca6 | |||
| ec5504a83f | |||
| 41b6ec07ce | |||
| b9e84d6817 | |||
| 962e22c311 | |||
| 72192c75c2 | |||
| c177e2060d | |||
| eabb927811 | |||
| e693e7f3b4 | |||
| 6d58b07ac6 | |||
| 019657a986 | |||
| 04bf047a2c | |||
| 1c1fca4ebe | |||
| 73e12985f2 | |||
| 591320db4a | |||
| c180202cea | |||
| 4e19b8128f | |||
| 26a73575f1 | |||
| 0dec5d20a2 | |||
| d4f2609ce8 | |||
| 1277e8f8dc | |||
| d70b539fa8 | |||
| ff7f76af7a | |||
| 3bc814ed3d | |||
| 271b9667ee | |||
| e2bfd21991 | |||
| bad7a04ad3 | |||
| 6c4c3c23c7 | |||
| 8ef8f41311 | |||
| e3cb324ed9 | |||
| a4bcabc7d2 | |||
| 0286e36bbe | |||
| 1f1a6c5a82 | |||
| 6e2163a712 | |||
| 551d519b57 | |||
| c97c3211bd | |||
| 88be16cb5b | |||
| da3871fd8e | |||
| be307c5792 | |||
| 71fde20e17 | |||
| 25ebf0ec9c |
12
.github/workflows/build.yml
vendored
12
.github/workflows/build.yml
vendored
@ -22,7 +22,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Create matrix
|
||||
id: platforms
|
||||
@ -50,7 +50,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
-
|
||||
@ -58,7 +58,7 @@ jobs:
|
||||
uses: docker/setup-buildx-action@v2
|
||||
-
|
||||
name: Build
|
||||
uses: docker/bake-action@v2
|
||||
uses: docker/bake-action@v3
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
set: |
|
||||
@ -93,7 +93,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Create matrix
|
||||
id: platforms
|
||||
@ -115,13 +115,13 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
-
|
||||
name: Build
|
||||
uses: docker/bake-action@v2
|
||||
uses: docker/bake-action@v3
|
||||
with:
|
||||
targets: plugins-cross
|
||||
set: |
|
||||
|
||||
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@ -19,7 +19,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
-
|
||||
|
||||
2
.github/workflows/e2e.yml
vendored
2
.github/workflows/e2e.yml
vendored
@ -36,7 +36,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Update daemon.json
|
||||
run: |
|
||||
|
||||
8
.github/workflows/test.yml
vendored
8
.github/workflows/test.yml
vendored
@ -20,13 +20,13 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
-
|
||||
name: Test
|
||||
uses: docker/bake-action@v2
|
||||
uses: docker/bake-action@v3
|
||||
with:
|
||||
targets: test-coverage
|
||||
-
|
||||
@ -56,14 +56,14 @@ jobs:
|
||||
git config --system core.eol lf
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: ${{ env.GOPATH }}/src/github.com/docker/cli
|
||||
-
|
||||
name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.20.3
|
||||
go-version: 1.20.13
|
||||
-
|
||||
name: Test
|
||||
run: |
|
||||
|
||||
8
.github/workflows/validate.yml
vendored
8
.github/workflows/validate.yml
vendored
@ -28,10 +28,10 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Run
|
||||
uses: docker/bake-action@v2
|
||||
uses: docker/bake-action@v3
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
@ -41,7 +41,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Generate
|
||||
shell: 'script --return --quiet --command "bash {0}"'
|
||||
@ -67,7 +67,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Run
|
||||
shell: 'script --return --quiet --command "bash {0}"'
|
||||
|
||||
@ -32,12 +32,11 @@ run:
|
||||
|
||||
linters-settings:
|
||||
depguard:
|
||||
list-type: blacklist
|
||||
include-go-root: true
|
||||
packages:
|
||||
# The io/ioutil package has been deprecated.
|
||||
# https://go.dev/doc/go1.16#ioutil
|
||||
- io/ioutil
|
||||
rules:
|
||||
main:
|
||||
deny:
|
||||
- pkg: io/ioutil
|
||||
desc: The io/ioutil package has been deprecated, see https://go.dev/doc/go1.16#ioutil
|
||||
gocyclo:
|
||||
min-complexity: 16
|
||||
govet:
|
||||
@ -117,7 +116,10 @@ issues:
|
||||
- text: "package-comments: should have a package comment"
|
||||
linters:
|
||||
- revive
|
||||
|
||||
# FIXME temporarily suppress these (see https://github.com/gotestyourself/gotest.tools/issues/272)
|
||||
- text: "SA1019: (assert|cmp|is)\\.ErrorType is deprecated"
|
||||
linters:
|
||||
- staticcheck
|
||||
# Exclude some linters from running on tests files.
|
||||
- path: _test\.go
|
||||
linters:
|
||||
|
||||
@ -192,7 +192,7 @@ For more details, see the [MAINTAINERS](MAINTAINERS) page.
|
||||
The sign-off is a simple line at the end of the explanation for the patch. Your
|
||||
signature certifies that you wrote the patch or otherwise have the right to pass
|
||||
it on as an open-source patch. The rules are pretty simple: if you can certify
|
||||
the below (from [developercertificate.org](http://developercertificate.org/)):
|
||||
the below (from [developercertificate.org](https://developercertificate.org):
|
||||
|
||||
```
|
||||
Developer Certificate of Origin
|
||||
@ -336,9 +336,8 @@ The rules:
|
||||
1. All code should be formatted with `gofumpt` (preferred) or `gofmt -s`.
|
||||
2. All code should pass the default levels of
|
||||
[`golint`](https://github.com/golang/lint).
|
||||
3. All code should follow the guidelines covered in [Effective
|
||||
Go](http://golang.org/doc/effective_go.html) and [Go Code Review
|
||||
Comments](https://github.com/golang/go/wiki/CodeReviewComments).
|
||||
3. All code should follow the guidelines covered in [Effective Go](https://go.dev/doc/effective_go)
|
||||
and [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments).
|
||||
4. Comment the code. Tell us the why, the history and the context.
|
||||
5. Document _all_ declarations and methods, even private ones. Declare
|
||||
expectations, caveats and anything else that may be important. If a type
|
||||
@ -360,6 +359,6 @@ The rules:
|
||||
guidelines. Since you've read all the rules, you now know that.
|
||||
|
||||
If you are having trouble getting into the mood of idiomatic Go, we recommend
|
||||
reading through [Effective Go](https://golang.org/doc/effective_go.html). The
|
||||
[Go Blog](https://blog.golang.org) is also a great resource. Drinking the
|
||||
reading through [Effective Go](https://go.dev/doc/effective_go). The
|
||||
[Go Blog](https://go.dev/blog/) is also a great resource. Drinking the
|
||||
kool-aid is a lot easier than going thirsty.
|
||||
|
||||
48
Dockerfile
48
Dockerfile
@ -1,17 +1,19 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG BASE_VARIANT=alpine
|
||||
ARG GO_VERSION=1.20.3
|
||||
ARG ALPINE_VERSION=3.16
|
||||
ARG XX_VERSION=1.1.1
|
||||
ARG GO_VERSION=1.20.13
|
||||
ARG ALPINE_VERSION=3.18
|
||||
ARG XX_VERSION=1.2.1
|
||||
ARG GOVERSIONINFO_VERSION=v1.3.0
|
||||
ARG GOTESTSUM_VERSION=v1.8.2
|
||||
ARG BUILDX_VERSION=0.10.4
|
||||
ARG GOTESTSUM_VERSION=v1.10.0
|
||||
ARG BUILDX_VERSION=0.11.2
|
||||
ARG COMPOSE_VERSION=v2.22.0
|
||||
|
||||
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
|
||||
|
||||
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS build-base-alpine
|
||||
COPY --from=xx / /
|
||||
ENV GOTOOLCHAIN=local
|
||||
COPY --link --from=xx / /
|
||||
RUN apk add --no-cache bash clang lld llvm file git
|
||||
WORKDIR /go/src/github.com/docker/cli
|
||||
|
||||
@ -21,7 +23,8 @@ ARG TARGETPLATFORM
|
||||
RUN xx-apk add --no-cache musl-dev gcc
|
||||
|
||||
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-bullseye AS build-base-bullseye
|
||||
COPY --from=xx / /
|
||||
ENV GOTOOLCHAIN=local
|
||||
COPY --link --from=xx / /
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y bash clang lld llvm file
|
||||
WORKDIR /go/src/github.com/docker/cli
|
||||
|
||||
@ -40,13 +43,13 @@ FROM build-base-${BASE_VARIANT} AS goversioninfo
|
||||
ARG GOVERSIONINFO_VERSION
|
||||
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
GOBIN=/out GO111MODULE=on go install "github.com/josephspurrier/goversioninfo/cmd/goversioninfo@${GOVERSIONINFO_VERSION}"
|
||||
GOBIN=/out GO111MODULE=on CGO_ENABLED=0 go install "github.com/josephspurrier/goversioninfo/cmd/goversioninfo@${GOVERSIONINFO_VERSION}"
|
||||
|
||||
FROM build-base-${BASE_VARIANT} AS gotestsum
|
||||
ARG GOTESTSUM_VERSION
|
||||
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
GOBIN=/out GO111MODULE=on go install "gotest.tools/gotestsum@${GOTESTSUM_VERSION}" \
|
||||
GOBIN=/out GO111MODULE=on CGO_ENABLED=0 go install "gotest.tools/gotestsum@${GOTESTSUM_VERSION}" \
|
||||
&& /out/gotestsum --version
|
||||
|
||||
FROM build-${BASE_VARIANT} AS build
|
||||
@ -62,7 +65,7 @@ ARG CGO_ENABLED
|
||||
ARG VERSION
|
||||
# PACKAGER_NAME sets the company that produced the windows binary
|
||||
ARG PACKAGER_NAME
|
||||
COPY --from=goversioninfo /out/goversioninfo /usr/bin/goversioninfo
|
||||
COPY --link --from=goversioninfo /out/goversioninfo /usr/bin/goversioninfo
|
||||
# in bullseye arm64 target does not link with lld so configure it to use ld instead
|
||||
RUN [ ! -f /etc/alpine-release ] && xx-info is-cross && [ "$(xx-info arch)" = "arm64" ] && XX_CC_PREFER_LINKER=ld xx-clang --setup-target-triple || true
|
||||
RUN --mount=type=bind,target=.,ro \
|
||||
@ -76,7 +79,7 @@ RUN --mount=type=bind,target=.,ro \
|
||||
xx-verify $([ "$GO_LINKMODE" = "static" ] && echo "--static") /out/docker
|
||||
|
||||
FROM build-${BASE_VARIANT} AS test
|
||||
COPY --from=gotestsum /out/gotestsum /usr/bin/gotestsum
|
||||
COPY --link --from=gotestsum /out/gotestsum /usr/bin/gotestsum
|
||||
ENV GO111MODULE=auto
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/root/.cache \
|
||||
@ -98,32 +101,31 @@ RUN --mount=ro --mount=type=cache,target=/root/.cache \
|
||||
TARGET=/out ./scripts/build/plugins e2e/cli-plugins/plugins/*
|
||||
|
||||
FROM build-base-alpine AS e2e-base-alpine
|
||||
RUN apk add --no-cache build-base curl docker-compose openssl openssh-client
|
||||
RUN apk add --no-cache build-base curl openssl openssh-client
|
||||
|
||||
FROM build-base-bullseye AS e2e-base-bullseye
|
||||
RUN apt-get update && apt-get install -y build-essential curl openssl openssh-client
|
||||
ARG COMPOSE_VERSION=1.29.2
|
||||
RUN curl -fsSL https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose && \
|
||||
chmod +x /usr/local/bin/docker-compose
|
||||
|
||||
FROM docker/buildx-bin:${BUILDX_VERSION} AS buildx
|
||||
FROM docker/buildx-bin:${BUILDX_VERSION} AS buildx
|
||||
FROM docker/compose-bin:${COMPOSE_VERSION} AS compose
|
||||
|
||||
FROM e2e-base-${BASE_VARIANT} AS e2e
|
||||
ARG NOTARY_VERSION=v0.6.1
|
||||
ADD --chmod=0755 https://github.com/theupdateframework/notary/releases/download/${NOTARY_VERSION}/notary-Linux-amd64 /usr/local/bin/notary
|
||||
COPY e2e/testdata/notary/root-ca.cert /usr/share/ca-certificates/notary.cert
|
||||
COPY --link e2e/testdata/notary/root-ca.cert /usr/share/ca-certificates/notary.cert
|
||||
RUN echo 'notary.cert' >> /etc/ca-certificates.conf && update-ca-certificates
|
||||
COPY --from=gotestsum /out/gotestsum /usr/bin/gotestsum
|
||||
COPY --from=build /out ./build/
|
||||
COPY --from=build-plugins /out ./build/
|
||||
COPY --from=buildx /buildx /usr/libexec/docker/cli-plugins/docker-buildx
|
||||
COPY . .
|
||||
COPY --link --from=gotestsum /out/gotestsum /usr/bin/gotestsum
|
||||
COPY --link --from=build /out ./build/
|
||||
COPY --link --from=build-plugins /out ./build/
|
||||
COPY --link --from=buildx /buildx /usr/libexec/docker/cli-plugins/docker-buildx
|
||||
COPY --link --from=compose /docker-compose /usr/libexec/docker/cli-plugins/docker-compose
|
||||
COPY --link . .
|
||||
ENV DOCKER_BUILDKIT=1
|
||||
ENV PATH=/go/src/github.com/docker/cli/build:$PATH
|
||||
CMD ./scripts/test/e2e/entry
|
||||
|
||||
FROM build-base-${BASE_VARIANT} AS dev
|
||||
COPY . .
|
||||
COPY --link . .
|
||||
|
||||
FROM scratch AS plugins
|
||||
COPY --from=build-plugins /out .
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package manager
|
||||
|
||||
import (
|
||||
|
||||
@ -23,6 +23,7 @@ type Metadata struct {
|
||||
// URL is a pointer to the plugin's homepage.
|
||||
URL string `json:",omitempty"`
|
||||
// Experimental specifies whether the plugin is experimental.
|
||||
//
|
||||
// Deprecated: experimental features are now always enabled in the CLI
|
||||
Experimental bool `json:",omitempty"`
|
||||
}
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package command
|
||||
|
||||
import (
|
||||
@ -8,7 +11,6 @@ import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -162,8 +164,8 @@ func (cli *DockerCli) ContentTrustEnabled() bool {
|
||||
|
||||
// BuildKitEnabled returns buildkit is enabled or not.
|
||||
func (cli *DockerCli) BuildKitEnabled() (bool, error) {
|
||||
// use DOCKER_BUILDKIT env var value if set
|
||||
if v, ok := os.LookupEnv("DOCKER_BUILDKIT"); ok {
|
||||
// use DOCKER_BUILDKIT env var value if set and not empty
|
||||
if v := os.Getenv("DOCKER_BUILDKIT"); v != "" {
|
||||
enabled, err := strconv.ParseBool(v)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "DOCKER_BUILDKIT environment variable expects boolean value")
|
||||
@ -327,13 +329,8 @@ func (cli *DockerCli) getInitTimeout() time.Duration {
|
||||
|
||||
func (cli *DockerCli) initializeFromClient() {
|
||||
ctx := context.Background()
|
||||
if !strings.HasPrefix(cli.dockerEndpoint.Host, "ssh://") {
|
||||
// @FIXME context.WithTimeout doesn't work with connhelper / ssh connections
|
||||
// time="2020-04-10T10:16:26Z" level=warning msg="commandConn.CloseWrite: commandconn: failed to wait: signal: killed"
|
||||
var cancel func()
|
||||
ctx, cancel = context.WithTimeout(ctx, cli.getInitTimeout())
|
||||
defer cancel()
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(ctx, cli.getInitTimeout())
|
||||
defer cancel()
|
||||
|
||||
ping, err := cli.client.Ping(ctx)
|
||||
if err != nil {
|
||||
@ -381,7 +378,7 @@ func (cli *DockerCli) ContextStore() store.Store {
|
||||
// the "default" context is used if:
|
||||
//
|
||||
// - The "--host" option is set
|
||||
// - The "DOCKER_HOST" ([DefaultContextName]) environment variable is set
|
||||
// - The "DOCKER_HOST" ([client.EnvOverrideHost]) environment variable is set
|
||||
// to a non-empty value.
|
||||
//
|
||||
// In these cases, the default context is used, which uses the host as
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
|
||||
@ -3,7 +3,6 @@ package container
|
||||
import (
|
||||
"github.com/docker/cli/cli/command/formatter"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -23,7 +22,7 @@ func NewDiffFormat(source string) formatter.Format {
|
||||
}
|
||||
|
||||
// DiffFormatWrite writes formatted diff using the Context
|
||||
func DiffFormatWrite(ctx formatter.Context, changes []container.ContainerChangeResponseItem) error {
|
||||
func DiffFormatWrite(ctx formatter.Context, changes []container.FilesystemChange) error {
|
||||
render := func(format func(subContext formatter.SubContext) error) error {
|
||||
for _, change := range changes {
|
||||
if err := format(&diffContext{c: change}); err != nil {
|
||||
@ -37,7 +36,7 @@ func DiffFormatWrite(ctx formatter.Context, changes []container.ContainerChangeR
|
||||
|
||||
type diffContext struct {
|
||||
formatter.HeaderContext
|
||||
c container.ContainerChangeResponseItem
|
||||
c container.FilesystemChange
|
||||
}
|
||||
|
||||
func newDiffContext() *diffContext {
|
||||
@ -54,16 +53,7 @@ func (d *diffContext) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (d *diffContext) Type() string {
|
||||
var kind string
|
||||
switch d.c.Kind {
|
||||
case archive.ChangeModify:
|
||||
kind = "C"
|
||||
case archive.ChangeAdd:
|
||||
kind = "A"
|
||||
case archive.ChangeDelete:
|
||||
kind = "D"
|
||||
}
|
||||
return kind
|
||||
return d.c.Kind.String()
|
||||
}
|
||||
|
||||
func (d *diffContext) Path() string {
|
||||
|
||||
@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/docker/cli/cli/command/formatter"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
@ -41,10 +40,10 @@ D: /usr/app/old_app.js
|
||||
},
|
||||
}
|
||||
|
||||
diffs := []container.ContainerChangeResponseItem{
|
||||
{Kind: archive.ChangeModify, Path: "/var/log/app.log"},
|
||||
{Kind: archive.ChangeAdd, Path: "/usr/app/app.js"},
|
||||
{Kind: archive.ChangeDelete, Path: "/usr/app/old_app.js"},
|
||||
diffs := []container.FilesystemChange{
|
||||
{Kind: container.ChangeModify, Path: "/var/log/app.log"},
|
||||
{Kind: container.ChangeAdd, Path: "/usr/app/app.js"},
|
||||
{Kind: container.ChangeDelete, Path: "/usr/app/old_app.js"},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package container
|
||||
|
||||
import (
|
||||
|
||||
@ -123,6 +123,7 @@ type containerOptions struct {
|
||||
runtime string
|
||||
autoRemove bool
|
||||
init bool
|
||||
annotations *opts.MapOpts
|
||||
|
||||
Image string
|
||||
Args []string
|
||||
@ -163,6 +164,7 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
|
||||
ulimits: opts.NewUlimitOpt(nil),
|
||||
volumes: opts.NewListOpts(nil),
|
||||
volumesFrom: opts.NewListOpts(nil),
|
||||
annotations: opts.NewMapOpts(nil, nil),
|
||||
}
|
||||
|
||||
// General purpose flags
|
||||
@ -297,6 +299,10 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
|
||||
|
||||
flags.BoolVar(&copts.init, "init", false, "Run an init inside the container that forwards signals and reaps processes")
|
||||
flags.SetAnnotation("init", "version", []string{"1.25"})
|
||||
|
||||
flags.Var(copts.annotations, "annotation", "Add an annotation to the container (passed through to the OCI runtime)")
|
||||
flags.SetAnnotation("annotation", "version", []string{"1.43"})
|
||||
|
||||
return copts
|
||||
}
|
||||
|
||||
@ -348,7 +354,10 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
|
||||
volumes := copts.volumes.GetMap()
|
||||
// add any bind targets to the list of container volumes
|
||||
for bind := range copts.volumes.GetMap() {
|
||||
parsed, _ := loader.ParseVolume(bind)
|
||||
parsed, err := loader.ParseVolume(bind)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if parsed.Source != "" {
|
||||
toBind := bind
|
||||
@ -654,6 +663,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
|
||||
Mounts: mounts,
|
||||
MaskedPaths: maskedPaths,
|
||||
ReadonlyPaths: readonlyPaths,
|
||||
Annotations: copts.annotations.GetAll(),
|
||||
}
|
||||
|
||||
if copts.autoRemove && !hostConfig.RestartPolicy.IsNone() {
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package command
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package context
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package context
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package context
|
||||
|
||||
import (
|
||||
|
||||
@ -6,6 +6,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/cli/command"
|
||||
@ -13,7 +14,6 @@ import (
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
"github.com/docker/cli/cli/flags"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/pkg/homedir"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
@ -57,7 +57,11 @@ func TestUseDefaultWithoutConfigFile(t *testing.T) {
|
||||
// the _default_ configuration file. If we specify a custom configuration
|
||||
// file, the CLI produces an error if the file doesn't exist.
|
||||
tmpHomeDir := t.TempDir()
|
||||
t.Setenv(homedir.Key(), tmpHomeDir)
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Setenv("USERPROFILE", tmpHomeDir)
|
||||
} else {
|
||||
t.Setenv("HOME", tmpHomeDir)
|
||||
}
|
||||
configDir := filepath.Join(tmpHomeDir, ".docker")
|
||||
configFilePath := filepath.Join(configDir, "config.json")
|
||||
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package command
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package command
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package command
|
||||
|
||||
import (
|
||||
|
||||
@ -3,28 +3,28 @@ package command
|
||||
import (
|
||||
"sync"
|
||||
|
||||
eventtypes "github.com/docker/docker/api/types/events"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// EventHandler is abstract interface for user to customize
|
||||
// own handle functions of each type of events
|
||||
type EventHandler interface {
|
||||
Handle(action string, h func(eventtypes.Message))
|
||||
Watch(c <-chan eventtypes.Message)
|
||||
Handle(action string, h func(events.Message))
|
||||
Watch(c <-chan events.Message)
|
||||
}
|
||||
|
||||
// InitEventHandler initializes and returns an EventHandler
|
||||
func InitEventHandler() EventHandler {
|
||||
return &eventHandler{handlers: make(map[string]func(eventtypes.Message))}
|
||||
return &eventHandler{handlers: make(map[string]func(events.Message))}
|
||||
}
|
||||
|
||||
type eventHandler struct {
|
||||
handlers map[string]func(eventtypes.Message)
|
||||
handlers map[string]func(events.Message)
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func (w *eventHandler) Handle(action string, h func(eventtypes.Message)) {
|
||||
func (w *eventHandler) Handle(action string, h func(events.Message)) {
|
||||
w.mu.Lock()
|
||||
w.handlers[action] = h
|
||||
w.mu.Unlock()
|
||||
@ -33,7 +33,7 @@ func (w *eventHandler) Handle(action string, h func(eventtypes.Message)) {
|
||||
// Watch ranges over the passed in event chan and processes the events based on the
|
||||
// handlers created for a given action.
|
||||
// To stop watching, close the event chan.
|
||||
func (w *eventHandler) Watch(c <-chan eventtypes.Message) {
|
||||
func (w *eventHandler) Watch(c <-chan events.Message) {
|
||||
for e := range c {
|
||||
w.mu.Lock()
|
||||
h, exists := w.handlers[e.Action]
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package formatter
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package formatter
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package formatter
|
||||
|
||||
import "strings"
|
||||
|
||||
@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
defaultDiskUsageImageTableFormat = "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedSince}}\t{{.VirtualSize}}\t{{.SharedSize}}\t{{.UniqueSize}}\t{{.Containers}}"
|
||||
defaultDiskUsageImageTableFormat = "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedSince}}\t{{.Size}}\t{{.SharedSize}}\t{{.UniqueSize}}\t{{.Containers}}"
|
||||
defaultDiskUsageContainerTableFormat = "table {{.ID}}\t{{.Image}}\t{{.Command}}\t{{.LocalVolumes}}\t{{.Size}}\t{{.RunningFor}}\t{{.Status}}\t{{.Names}}"
|
||||
defaultDiskUsageVolumeTableFormat = "table {{.Name}}\t{{.Links}}\t{{.Size}}"
|
||||
defaultDiskUsageBuildCacheTableFormat = "table {{.ID}}\t{{.CacheType}}\t{{.Size}}\t{{.CreatedSince}}\t{{.LastUsedSince}}\t{{.UsageCount}}\t{{.Shared}}"
|
||||
@ -296,10 +296,10 @@ func (c *diskUsageImagesContext) Reclaimable() string {
|
||||
|
||||
for _, i := range c.images {
|
||||
if i.Containers != 0 {
|
||||
if i.VirtualSize == -1 || i.SharedSize == -1 {
|
||||
if i.Size == -1 || i.SharedSize == -1 {
|
||||
continue
|
||||
}
|
||||
used += i.VirtualSize - i.SharedSize
|
||||
used += i.Size - i.SharedSize
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package formatter
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package formatter
|
||||
|
||||
import (
|
||||
|
||||
@ -205,7 +205,7 @@ func newImageContext() *imageContext {
|
||||
"CreatedAt": CreatedAtHeader,
|
||||
"Size": SizeHeader,
|
||||
"Containers": containersHeader,
|
||||
"VirtualSize": SizeHeader,
|
||||
"VirtualSize": SizeHeader, // Deprecated: VirtualSize is deprecated, and equivalent to Size.
|
||||
"SharedSize": sharedSizeHeader,
|
||||
"UniqueSize": uniqueSizeHeader,
|
||||
}
|
||||
@ -260,8 +260,13 @@ func (c *imageContext) Containers() string {
|
||||
return fmt.Sprintf("%d", c.i.Containers)
|
||||
}
|
||||
|
||||
// VirtualSize shows the virtual size of the image and all of its parent
|
||||
// images. Starting with docker 1.10, images are self-contained, and
|
||||
// the VirtualSize is identical to Size.
|
||||
//
|
||||
// Deprecated: VirtualSize is deprecated, and equivalent to [imageContext.Size].
|
||||
func (c *imageContext) VirtualSize() string {
|
||||
return units.HumanSize(float64(c.i.VirtualSize))
|
||||
return units.HumanSize(float64(c.i.Size))
|
||||
}
|
||||
|
||||
func (c *imageContext) SharedSize() string {
|
||||
@ -272,8 +277,8 @@ func (c *imageContext) SharedSize() string {
|
||||
}
|
||||
|
||||
func (c *imageContext) UniqueSize() string {
|
||||
if c.i.VirtualSize == -1 || c.i.SharedSize == -1 {
|
||||
if c.i.Size == -1 || c.i.SharedSize == -1 {
|
||||
return "N/A"
|
||||
}
|
||||
return units.HumanSize(float64(c.i.VirtualSize - c.i.SharedSize))
|
||||
return units.HumanSize(float64(c.i.Size - c.i.SharedSize))
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ func TestImageContext(t *testing.T) {
|
||||
call: ctx.ID,
|
||||
},
|
||||
{
|
||||
imageCtx: imageContext{i: types.ImageSummary{Size: 10, VirtualSize: 10}, trunc: true},
|
||||
imageCtx: imageContext{i: types.ImageSummary{Size: 10}, trunc: true},
|
||||
expValue: "10B",
|
||||
call: ctx.Size,
|
||||
},
|
||||
@ -70,9 +70,9 @@ func TestImageContext(t *testing.T) {
|
||||
call: ctx.Containers,
|
||||
},
|
||||
{
|
||||
imageCtx: imageContext{i: types.ImageSummary{VirtualSize: 10000}},
|
||||
imageCtx: imageContext{i: types.ImageSummary{Size: 10000}},
|
||||
expValue: "10kB",
|
||||
call: ctx.VirtualSize,
|
||||
call: ctx.VirtualSize, //nolint:staticcheck // ignore SA1019: field is deprecated, but still set on API < v1.44.
|
||||
},
|
||||
{
|
||||
imageCtx: imageContext{i: types.ImageSummary{SharedSize: 10000}},
|
||||
@ -80,7 +80,7 @@ func TestImageContext(t *testing.T) {
|
||||
call: ctx.SharedSize,
|
||||
},
|
||||
{
|
||||
imageCtx: imageContext{i: types.ImageSummary{SharedSize: 5000, VirtualSize: 20000}},
|
||||
imageCtx: imageContext{i: types.ImageSummary{SharedSize: 5000, Size: 20000}},
|
||||
expValue: "15kB",
|
||||
call: ctx.UniqueSize,
|
||||
},
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package formatter
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package formatter
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package formatter
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package idresolver
|
||||
|
||||
import (
|
||||
|
||||
@ -128,7 +128,7 @@ func NewBuildCommand(dockerCli command.Cli) *cobra.Command {
|
||||
flags.Int64Var(&options.cpuQuota, "cpu-quota", 0, "Limit the CPU CFS (Completely Fair Scheduler) quota")
|
||||
flags.StringVar(&options.cpuSetCpus, "cpuset-cpus", "", "CPUs in which to allow execution (0-3, 0,1)")
|
||||
flags.StringVar(&options.cpuSetMems, "cpuset-mems", "", "MEMs in which to allow execution (0-3, 0,1)")
|
||||
flags.StringVar(&options.cgroupParent, "cgroup-parent", "", "Optional parent cgroup for the container")
|
||||
flags.StringVar(&options.cgroupParent, "cgroup-parent", "", `Set the parent cgroup for the "RUN" instructions during build`)
|
||||
flags.StringVar(&options.isolation, "isolation", "", "Container isolation technology")
|
||||
flags.Var(&options.labels, "label", "Set metadata for an image")
|
||||
flags.BoolVar(&options.noCache, "no-cache", false, "Do not use cache when building the image")
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
package build
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/moby/buildkit/frontend/dockerfile/dockerignore"
|
||||
"github.com/moby/patternmatcher"
|
||||
"github.com/moby/patternmatcher/ignorefile"
|
||||
)
|
||||
|
||||
// ReadDockerignore reads the .dockerignore file in the context directory and
|
||||
@ -22,7 +23,11 @@ func ReadDockerignore(contextDir string) ([]string, error) {
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
return dockerignore.ReadAll(f)
|
||||
patterns, err := ignorefile.ReadAll(f)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading .dockerignore: %w", err)
|
||||
}
|
||||
return patterns, nil
|
||||
}
|
||||
|
||||
// TrimBuildFilesFromExcludes removes the named Dockerfile and .dockerignore from
|
||||
|
||||
@ -34,7 +34,7 @@ func TestRunBuildDockerfileFromStdinWithCompress(t *testing.T) {
|
||||
|
||||
cli := test.NewFakeCli(&fakeClient{imageBuildFunc: fakeImageBuild})
|
||||
dockerfile := bytes.NewBufferString(`
|
||||
FROM alpine:3.6
|
||||
FROM alpine:frozen
|
||||
COPY foo /
|
||||
`)
|
||||
cli.SetIn(streams.NewIn(io.NopCloser(dockerfile)))
|
||||
@ -66,7 +66,7 @@ func TestRunBuildResetsUidAndGidInContext(t *testing.T) {
|
||||
dir := fs.NewDir(t, "test-build-context",
|
||||
fs.WithFile("foo", "some content", fs.AsUser(65534, 65534)),
|
||||
fs.WithFile("Dockerfile", `
|
||||
FROM alpine:3.6
|
||||
FROM alpine:frozen
|
||||
COPY foo bar /
|
||||
`),
|
||||
)
|
||||
@ -155,7 +155,7 @@ func TestRunBuildFromLocalGitHubDir(t *testing.T) {
|
||||
func TestRunBuildWithSymlinkedContext(t *testing.T) {
|
||||
t.Setenv("DOCKER_BUILDKIT", "0")
|
||||
dockerfile := `
|
||||
FROM alpine:3.6
|
||||
FROM alpine:frozen
|
||||
RUN echo hello world
|
||||
`
|
||||
|
||||
|
||||
@ -11,7 +11,6 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"gotest.tools/v3/assert"
|
||||
"gotest.tools/v3/golden"
|
||||
"gotest.tools/v3/skip"
|
||||
)
|
||||
|
||||
func TestNewHistoryCommandErrors(t *testing.T) {
|
||||
@ -43,13 +42,7 @@ func TestNewHistoryCommandErrors(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func notUTCTimezone() bool {
|
||||
now := time.Now()
|
||||
return now != now.UTC()
|
||||
}
|
||||
|
||||
func TestNewHistoryCommandSuccess(t *testing.T) {
|
||||
skip.If(t, notUTCTimezone, "expected output requires UTC timezone")
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
@ -62,6 +55,7 @@ func TestNewHistoryCommandSuccess(t *testing.T) {
|
||||
return []image.HistoryResponseItem{{
|
||||
ID: "1234567890123456789",
|
||||
Created: time.Now().Unix(),
|
||||
Comment: "none",
|
||||
}}, nil
|
||||
},
|
||||
},
|
||||
@ -93,13 +87,19 @@ func TestNewHistoryCommandSuccess(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
cli := test.NewFakeCli(&fakeClient{imageHistoryFunc: tc.imageHistoryFunc})
|
||||
cmd := NewHistoryCommand(cli)
|
||||
cmd.SetOut(io.Discard)
|
||||
cmd.SetArgs(tc.args)
|
||||
err := cmd.Execute()
|
||||
assert.NilError(t, err)
|
||||
actual := cli.OutBuffer().String()
|
||||
golden.Assert(t, actual, fmt.Sprintf("history-command-success.%s.golden", tc.name))
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// Set to UTC timezone as timestamps in output are
|
||||
// printed in the current timezone
|
||||
t.Setenv("TZ", "UTC")
|
||||
cli := test.NewFakeCli(&fakeClient{imageHistoryFunc: tc.imageHistoryFunc})
|
||||
cmd := NewHistoryCommand(cli)
|
||||
cmd.SetOut(io.Discard)
|
||||
cmd.SetArgs(tc.args)
|
||||
err := cmd.Execute()
|
||||
assert.NilError(t, err)
|
||||
actual := cli.OutBuffer().String()
|
||||
golden.Assert(t, actual, fmt.Sprintf("history-command-success.%s.golden", tc.name))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package image
|
||||
|
||||
import (
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
IMAGE CREATED AT CREATED BY SIZE COMMENT
|
||||
abcdef 2017-01-01T12:00:03Z rose 0 new history item!
|
||||
IMAGE CREATED AT CREATED BY SIZE COMMENT
|
||||
abcdef 2017-01-01T12:00:03Z rose 0 new history item!
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
IMAGE CREATED CREATED BY SIZE COMMENT
|
||||
123456789012 Less than a second ago 0B
|
||||
IMAGE CREATED CREATED BY SIZE COMMENT
|
||||
123456789012 Less than a second ago 0B none
|
||||
|
||||
@ -14,7 +14,6 @@
|
||||
"Architecture": "",
|
||||
"Os": "",
|
||||
"Size": 0,
|
||||
"VirtualSize": 0,
|
||||
"GraphDriver": {
|
||||
"Data": null,
|
||||
"Name": ""
|
||||
@ -39,7 +38,6 @@
|
||||
"Architecture": "",
|
||||
"Os": "",
|
||||
"Size": 0,
|
||||
"VirtualSize": 0,
|
||||
"GraphDriver": {
|
||||
"Data": null,
|
||||
"Name": ""
|
||||
|
||||
@ -14,7 +14,6 @@
|
||||
"Architecture": "",
|
||||
"Os": "",
|
||||
"Size": 0,
|
||||
"VirtualSize": 0,
|
||||
"GraphDriver": {
|
||||
"Data": null,
|
||||
"Name": ""
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package inspect
|
||||
|
||||
import (
|
||||
|
||||
@ -16,7 +16,7 @@ type osArch struct {
|
||||
|
||||
// Remove any unsupported os/arch combo
|
||||
// list of valid os/arch values (see "Optional Environment Variables" section
|
||||
// of https://golang.org/doc/install/source
|
||||
// of https://go.dev/doc/install/source
|
||||
// Added linux/s390x as we know System z support already exists
|
||||
// Keep in sync with _docker_manifest_annotate in contrib/completion/bash/docker
|
||||
var validOSArches = map[osArch]bool{
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package network
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package network
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package node
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package node
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
"strings"
|
||||
|
||||
configtypes "github.com/docker/cli/cli/config/types"
|
||||
"github.com/docker/cli/cli/hints"
|
||||
"github.com/docker/cli/cli/streams"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/docker/api/types"
|
||||
@ -19,6 +20,10 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const patSuggest = "You can log in with your password or a Personal Access " +
|
||||
"Token (PAT). Using a limited-scope PAT grants better security and is required " +
|
||||
"for organizations using SSO. Learn more at https://docs.docker.com/go/access-tokens/"
|
||||
|
||||
// EncodeAuthToBase64 serializes the auth configuration as JSON base64 payload.
|
||||
//
|
||||
// Deprecated: use [registrytypes.EncodeAuthConfig] instead.
|
||||
@ -113,7 +118,11 @@ func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *registrytypes
|
||||
if flUser = strings.TrimSpace(flUser); flUser == "" {
|
||||
if isDefaultRegistry {
|
||||
// if this is a default registry (docker hub), then display the following message.
|
||||
fmt.Fprintln(cli.Out(), "Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.")
|
||||
fmt.Fprintln(cli.Out(), "Log in with your Docker ID or email address to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com/ to create one.")
|
||||
if hints.Enabled() {
|
||||
fmt.Fprintln(cli.Out(), patSuggest)
|
||||
fmt.Fprintln(cli.Out())
|
||||
}
|
||||
}
|
||||
promptWithDefault(cli.Out(), "Username", authconfig.Username)
|
||||
var err error
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package secret
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
@ -1001,7 +1004,7 @@ const (
|
||||
flagTTY = "tty"
|
||||
flagUpdateDelay = "update-delay"
|
||||
flagUpdateFailureAction = "update-failure-action"
|
||||
flagUpdateMaxFailureRatio = "update-max-failure-ratio"
|
||||
flagUpdateMaxFailureRatio = "update-max-failure-ratio" // #nosec G101 -- ignoring: Potential hardcoded credentials (gosec)
|
||||
flagUpdateMonitor = "update-monitor"
|
||||
flagUpdateOrder = "update-order"
|
||||
flagUpdateParallelism = "update-parallelism"
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package loader
|
||||
|
||||
import (
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/docker/cli/cli/streams"
|
||||
)
|
||||
|
||||
// InStream is an input stream used by the DockerCli to read user input
|
||||
//
|
||||
// Deprecated: Use [streams.In] instead.
|
||||
type InStream = streams.In
|
||||
|
||||
// OutStream is an output stream used by the DockerCli to write normal program
|
||||
// output.
|
||||
//
|
||||
// Deprecated: Use [streams.Out] instead.
|
||||
type OutStream = streams.Out
|
||||
|
||||
// NewInStream returns a new [streams.In] from an [io.ReadCloser].
|
||||
//
|
||||
// Deprecated: Use [streams.NewIn] instead.
|
||||
func NewInStream(in io.ReadCloser) *streams.In {
|
||||
return streams.NewIn(in)
|
||||
}
|
||||
|
||||
// NewOutStream returns a new [streams.Out] from an [io.Writer].
|
||||
//
|
||||
// Deprecated: Use [streams.NewOut] instead.
|
||||
func NewOutStream(out io.Writer) *streams.Out {
|
||||
return streams.NewOut(out)
|
||||
}
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
"github.com/docker/docker/client"
|
||||
)
|
||||
|
||||
@ -12,6 +13,7 @@ type fakeClient struct {
|
||||
|
||||
version string
|
||||
serverVersion func(ctx context.Context) (types.Version, error)
|
||||
eventsFn func(context.Context, types.EventsOptions) (<-chan events.Message, <-chan error)
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ServerVersion(ctx context.Context) (types.Version, error) {
|
||||
@ -21,3 +23,7 @@ func (cli *fakeClient) ServerVersion(ctx context.Context) (types.Version, error)
|
||||
func (cli *fakeClient) ClientVersion() string {
|
||||
return cli.version
|
||||
}
|
||||
|
||||
func (cli *fakeClient) Events(ctx context.Context, opts types.EventsOptions) (<-chan events.Message, <-chan error) {
|
||||
return cli.eventsFn(ctx, opts)
|
||||
}
|
||||
|
||||
@ -12,10 +12,12 @@ import (
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/completion"
|
||||
"github.com/docker/cli/cli/command/formatter"
|
||||
flagsHelper "github.com/docker/cli/cli/flags"
|
||||
"github.com/docker/cli/opts"
|
||||
"github.com/docker/cli/templates"
|
||||
"github.com/docker/docker/api/types"
|
||||
eventtypes "github.com/docker/docker/api/types/events"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -47,7 +49,7 @@ func NewEventsCommand(dockerCli command.Cli) *cobra.Command {
|
||||
flags.StringVar(&options.since, "since", "", "Show all events created since timestamp")
|
||||
flags.StringVar(&options.until, "until", "", "Stream events until this timestamp")
|
||||
flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided")
|
||||
flags.StringVar(&options.format, "format", "", "Format the output using the given Go template")
|
||||
flags.StringVar(&options.format, "format", "", flagsHelper.InspectFormatHelp) // using the same flag description as "inspect" commands for now.
|
||||
|
||||
return cmd
|
||||
}
|
||||
@ -60,21 +62,19 @@ func runEvents(dockerCli command.Cli, options *eventsOptions) error {
|
||||
Status: "Error parsing format: " + err.Error(),
|
||||
}
|
||||
}
|
||||
eventOptions := types.EventsOptions{
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
evts, errs := dockerCli.Client().Events(ctx, types.EventsOptions{
|
||||
Since: options.since,
|
||||
Until: options.until,
|
||||
Filters: options.filter.Value(),
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
events, errs := dockerCli.Client().Events(ctx, eventOptions)
|
||||
})
|
||||
defer cancel()
|
||||
|
||||
out := dockerCli.Out()
|
||||
|
||||
for {
|
||||
select {
|
||||
case event := <-events:
|
||||
case event := <-evts:
|
||||
if err := handleEvent(out, event, tmpl); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -87,7 +87,7 @@ func runEvents(dockerCli command.Cli, options *eventsOptions) error {
|
||||
}
|
||||
}
|
||||
|
||||
func handleEvent(out io.Writer, event eventtypes.Message, tmpl *template.Template) error {
|
||||
func handleEvent(out io.Writer, event events.Message, tmpl *template.Template) error {
|
||||
if tmpl == nil {
|
||||
return prettyPrintEvent(out, event)
|
||||
}
|
||||
@ -96,16 +96,19 @@ func handleEvent(out io.Writer, event eventtypes.Message, tmpl *template.Templat
|
||||
}
|
||||
|
||||
func makeTemplate(format string) (*template.Template, error) {
|
||||
if format == "" {
|
||||
switch format {
|
||||
case "":
|
||||
return nil, nil
|
||||
case formatter.JSONFormatKey:
|
||||
format = formatter.JSONFormat
|
||||
}
|
||||
tmpl, err := templates.Parse(format)
|
||||
if err != nil {
|
||||
return tmpl, err
|
||||
}
|
||||
// we execute the template for an empty message, so as to validate
|
||||
// a bad template like "{{.badFieldString}}"
|
||||
return tmpl, tmpl.Execute(io.Discard, &eventtypes.Message{})
|
||||
// execute the template on an empty message to validate a bad
|
||||
// template like "{{.badFieldString}}"
|
||||
return tmpl, tmpl.Execute(io.Discard, &events.Message{})
|
||||
}
|
||||
|
||||
// rfc3339NanoFixed is similar to time.RFC3339Nano, except it pads nanoseconds
|
||||
@ -115,7 +118,7 @@ const rfc3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00"
|
||||
// prettyPrintEvent prints all types of event information.
|
||||
// Each output includes the event type, actor id, name and action.
|
||||
// Actor attributes are printed at the end if the actor has any.
|
||||
func prettyPrintEvent(out io.Writer, event eventtypes.Message) error {
|
||||
func prettyPrintEvent(out io.Writer, event events.Message) error {
|
||||
if event.TimeNano != 0 {
|
||||
fmt.Fprintf(out, "%s ", time.Unix(0, event.TimeNano).Format(rfc3339NanoFixed))
|
||||
} else if event.Time != 0 {
|
||||
@ -141,7 +144,7 @@ func prettyPrintEvent(out io.Writer, event eventtypes.Message) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func formatEvent(out io.Writer, event eventtypes.Message, tmpl *template.Template) error {
|
||||
func formatEvent(out io.Writer, event events.Message, tmpl *template.Template) error {
|
||||
defer out.Write([]byte{'\n'})
|
||||
return tmpl.Execute(out, event)
|
||||
}
|
||||
|
||||
83
cli/command/system/events_test.go
Normal file
83
cli/command/system/events_test.go
Normal file
@ -0,0 +1,83 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
"gotest.tools/v3/assert"
|
||||
"gotest.tools/v3/golden"
|
||||
)
|
||||
|
||||
func TestEventsFormat(t *testing.T) {
|
||||
var evts []events.Message
|
||||
for i, action := range []string{"create", "start", "attach", "die"} {
|
||||
evts = append(evts, events.Message{
|
||||
Status: action,
|
||||
ID: "abc123",
|
||||
From: "ubuntu:latest",
|
||||
Type: events.ContainerEventType,
|
||||
Action: action,
|
||||
Actor: events.Actor{
|
||||
ID: "abc123",
|
||||
Attributes: map[string]string{"image": "ubuntu:latest"},
|
||||
},
|
||||
Scope: "local",
|
||||
Time: int64(time.Second) * int64(i+1),
|
||||
TimeNano: int64(time.Second) * int64(i+1),
|
||||
})
|
||||
}
|
||||
tests := []struct {
|
||||
name, format string
|
||||
}{
|
||||
{
|
||||
name: "default",
|
||||
},
|
||||
{
|
||||
name: "json",
|
||||
format: "json",
|
||||
},
|
||||
{
|
||||
name: "json template",
|
||||
format: "{{ json . }}",
|
||||
},
|
||||
{
|
||||
name: "json action",
|
||||
format: "{{ json .Action }}",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// Set to UTC timezone as timestamps in output are
|
||||
// printed in the current timezone
|
||||
t.Setenv("TZ", "UTC")
|
||||
cli := test.NewFakeCli(&fakeClient{eventsFn: func(context.Context, types.EventsOptions) (<-chan events.Message, <-chan error) {
|
||||
messages := make(chan events.Message)
|
||||
errs := make(chan error, 1)
|
||||
go func() {
|
||||
for _, msg := range evts {
|
||||
messages <- msg
|
||||
}
|
||||
errs <- io.EOF
|
||||
}()
|
||||
return messages, errs
|
||||
}})
|
||||
cmd := NewEventsCommand(cli)
|
||||
if tc.format != "" {
|
||||
cmd.Flags().Set("format", tc.format)
|
||||
}
|
||||
assert.Check(t, cmd.Execute())
|
||||
out := cli.OutBuffer().String()
|
||||
assert.Check(t, golden.String(out, fmt.Sprintf("docker-events-%s.golden", strings.ReplaceAll(tc.name, " ", "-"))))
|
||||
cli.OutBuffer().Reset()
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package system
|
||||
|
||||
import (
|
||||
@ -19,6 +22,7 @@ import (
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"github.com/docker/docker/registry"
|
||||
"github.com/docker/go-units"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -41,6 +45,7 @@ type info struct {
|
||||
// object.
|
||||
*types.Info `json:",omitempty"`
|
||||
ServerErrors []string `json:",omitempty"`
|
||||
UserName string `json:"-"`
|
||||
|
||||
ClientInfo *clientInfo `json:",omitempty"`
|
||||
ClientErrors []string `json:",omitempty"`
|
||||
@ -106,15 +111,17 @@ func runInfo(cmd *cobra.Command, dockerCli command.Cli, opts *infoOptions) error
|
||||
} else {
|
||||
// if a format is provided, print the error, as it may be hidden
|
||||
// otherwise if the template doesn't include the ServerErrors field.
|
||||
fmt.Fprintln(dockerCli.Err(), err)
|
||||
fprintln(dockerCli.Err(), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if opts.format == "" {
|
||||
info.UserName = dockerCli.ConfigFile().AuthConfigs[registry.IndexServer].Username
|
||||
info.ClientInfo.APIVersion = dockerCli.CurrentVersion()
|
||||
return prettyPrintInfo(dockerCli, info)
|
||||
}
|
||||
return formatInfo(dockerCli, info, opts.format)
|
||||
return formatInfo(dockerCli.Out(), info, opts.format)
|
||||
}
|
||||
|
||||
// placeHolders does a rudimentary match for possible placeholders in a
|
||||
@ -156,29 +163,29 @@ func needsServerInfo(template string, info info) bool {
|
||||
return err != nil
|
||||
}
|
||||
|
||||
func prettyPrintInfo(dockerCli command.Cli, info info) error {
|
||||
func prettyPrintInfo(streams command.Streams, info info) error {
|
||||
// Only append the platform info if it's not empty, to prevent printing a trailing space.
|
||||
if p := info.clientPlatform(); p != "" {
|
||||
_, _ = fmt.Fprintln(dockerCli.Out(), "Client:", p)
|
||||
fprintln(streams.Out(), "Client:", p)
|
||||
} else {
|
||||
_, _ = fmt.Fprintln(dockerCli.Out(), "Client:")
|
||||
fprintln(streams.Out(), "Client:")
|
||||
}
|
||||
if info.ClientInfo != nil {
|
||||
prettyPrintClientInfo(dockerCli, *info.ClientInfo)
|
||||
prettyPrintClientInfo(streams, *info.ClientInfo)
|
||||
}
|
||||
for _, err := range info.ClientErrors {
|
||||
fmt.Fprintln(dockerCli.Err(), "ERROR:", err)
|
||||
fprintln(streams.Err(), "ERROR:", err)
|
||||
}
|
||||
|
||||
fmt.Fprintln(dockerCli.Out())
|
||||
fmt.Fprintln(dockerCli.Out(), "Server:")
|
||||
fprintln(streams.Out())
|
||||
fprintln(streams.Out(), "Server:")
|
||||
if info.Info != nil {
|
||||
for _, err := range prettyPrintServerInfo(dockerCli, *info.Info) {
|
||||
for _, err := range prettyPrintServerInfo(streams, &info) {
|
||||
info.ServerErrors = append(info.ServerErrors, err.Error())
|
||||
}
|
||||
}
|
||||
for _, err := range info.ServerErrors {
|
||||
fmt.Fprintln(dockerCli.Err(), "ERROR:", err)
|
||||
fprintln(streams.Err(), "ERROR:", err)
|
||||
}
|
||||
|
||||
if len(info.ServerErrors) > 0 || len(info.ClientErrors) > 0 {
|
||||
@ -187,18 +194,18 @@ func prettyPrintInfo(dockerCli command.Cli, info info) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func prettyPrintClientInfo(dockerCli command.Cli, info clientInfo) {
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Version: ", info.Version)
|
||||
fmt.Fprintln(dockerCli.Out(), " Context: ", info.Context)
|
||||
fmt.Fprintln(dockerCli.Out(), " Debug Mode:", info.Debug)
|
||||
func prettyPrintClientInfo(streams command.Streams, info clientInfo) {
|
||||
fprintlnNonEmpty(streams.Out(), " Version: ", info.Version)
|
||||
fprintln(streams.Out(), " Context: ", info.Context)
|
||||
fprintln(streams.Out(), " Debug Mode:", info.Debug)
|
||||
|
||||
if len(info.Plugins) > 0 {
|
||||
fmt.Fprintln(dockerCli.Out(), " Plugins:")
|
||||
fprintln(streams.Out(), " Plugins:")
|
||||
for _, p := range info.Plugins {
|
||||
if p.Err == nil {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s: %s (%s)\n", p.Name, p.ShortDescription, p.Vendor)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Version: ", p.Version)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Path: ", p.Path)
|
||||
fprintf(streams.Out(), " %s: %s (%s)\n", p.Name, p.ShortDescription, p.Vendor)
|
||||
fprintlnNonEmpty(streams.Out(), " Version: ", p.Version)
|
||||
fprintlnNonEmpty(streams.Out(), " Path: ", p.Path)
|
||||
} else {
|
||||
info.Warnings = append(info.Warnings, fmt.Sprintf("WARNING: Plugin %q is not valid: %s", p.Path, p.Err))
|
||||
}
|
||||
@ -206,59 +213,60 @@ func prettyPrintClientInfo(dockerCli command.Cli, info clientInfo) {
|
||||
}
|
||||
|
||||
if len(info.Warnings) > 0 {
|
||||
fmt.Fprintln(dockerCli.Err(), strings.Join(info.Warnings, "\n"))
|
||||
fprintln(streams.Err(), strings.Join(info.Warnings, "\n"))
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func prettyPrintServerInfo(dockerCli command.Cli, info types.Info) []error {
|
||||
func prettyPrintServerInfo(streams command.Streams, info *info) []error {
|
||||
var errs []error
|
||||
output := streams.Out()
|
||||
|
||||
fmt.Fprintln(dockerCli.Out(), " Containers:", info.Containers)
|
||||
fmt.Fprintln(dockerCli.Out(), " Running:", info.ContainersRunning)
|
||||
fmt.Fprintln(dockerCli.Out(), " Paused:", info.ContainersPaused)
|
||||
fmt.Fprintln(dockerCli.Out(), " Stopped:", info.ContainersStopped)
|
||||
fmt.Fprintln(dockerCli.Out(), " Images:", info.Images)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Server Version:", info.ServerVersion)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Storage Driver:", info.Driver)
|
||||
fprintln(output, " Containers:", info.Containers)
|
||||
fprintln(output, " Running:", info.ContainersRunning)
|
||||
fprintln(output, " Paused:", info.ContainersPaused)
|
||||
fprintln(output, " Stopped:", info.ContainersStopped)
|
||||
fprintln(output, " Images:", info.Images)
|
||||
fprintlnNonEmpty(output, " Server Version:", info.ServerVersion)
|
||||
fprintlnNonEmpty(output, " Storage Driver:", info.Driver)
|
||||
if info.DriverStatus != nil {
|
||||
for _, pair := range info.DriverStatus {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s: %s\n", pair[0], pair[1])
|
||||
fprintf(output, " %s: %s\n", pair[0], pair[1])
|
||||
}
|
||||
}
|
||||
if info.SystemStatus != nil {
|
||||
for _, pair := range info.SystemStatus {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s: %s\n", pair[0], pair[1])
|
||||
fprintf(output, " %s: %s\n", pair[0], pair[1])
|
||||
}
|
||||
}
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Logging Driver:", info.LoggingDriver)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Cgroup Driver:", info.CgroupDriver)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Cgroup Version:", info.CgroupVersion)
|
||||
fprintlnNonEmpty(output, " Logging Driver:", info.LoggingDriver)
|
||||
fprintlnNonEmpty(output, " Cgroup Driver:", info.CgroupDriver)
|
||||
fprintlnNonEmpty(output, " Cgroup Version:", info.CgroupVersion)
|
||||
|
||||
fmt.Fprintln(dockerCli.Out(), " Plugins:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Volume:", strings.Join(info.Plugins.Volume, " "))
|
||||
fmt.Fprintln(dockerCli.Out(), " Network:", strings.Join(info.Plugins.Network, " "))
|
||||
fprintln(output, " Plugins:")
|
||||
fprintln(output, " Volume:", strings.Join(info.Plugins.Volume, " "))
|
||||
fprintln(output, " Network:", strings.Join(info.Plugins.Network, " "))
|
||||
|
||||
if len(info.Plugins.Authorization) != 0 {
|
||||
fmt.Fprintln(dockerCli.Out(), " Authorization:", strings.Join(info.Plugins.Authorization, " "))
|
||||
fprintln(output, " Authorization:", strings.Join(info.Plugins.Authorization, " "))
|
||||
}
|
||||
|
||||
fmt.Fprintln(dockerCli.Out(), " Log:", strings.Join(info.Plugins.Log, " "))
|
||||
fprintln(output, " Log:", strings.Join(info.Plugins.Log, " "))
|
||||
|
||||
fmt.Fprintln(dockerCli.Out(), " Swarm:", info.Swarm.LocalNodeState)
|
||||
printSwarmInfo(dockerCli, info)
|
||||
fprintln(output, " Swarm:", info.Swarm.LocalNodeState)
|
||||
printSwarmInfo(output, *info.Info)
|
||||
|
||||
if len(info.Runtimes) > 0 {
|
||||
fmt.Fprint(dockerCli.Out(), " Runtimes:")
|
||||
names := make([]string, 0, len(info.Runtimes))
|
||||
for name := range info.Runtimes {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s", name)
|
||||
names = append(names, name)
|
||||
}
|
||||
fmt.Fprint(dockerCli.Out(), "\n")
|
||||
fmt.Fprintln(dockerCli.Out(), " Default Runtime:", info.DefaultRuntime)
|
||||
fprintln(output, " Runtimes:", strings.Join(names, " "))
|
||||
fprintln(output, " Default Runtime:", info.DefaultRuntime)
|
||||
}
|
||||
|
||||
if info.OSType == "linux" {
|
||||
fmt.Fprintln(dockerCli.Out(), " Init Binary:", info.InitBinary)
|
||||
fprintln(output, " Init Binary:", info.InitBinary)
|
||||
|
||||
for _, ci := range []struct {
|
||||
Name string
|
||||
@ -268,23 +276,23 @@ func prettyPrintServerInfo(dockerCli command.Cli, info types.Info) []error {
|
||||
{"runc", info.RuncCommit},
|
||||
{"init", info.InitCommit},
|
||||
} {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s version: %s", ci.Name, ci.Commit.ID)
|
||||
fprintf(output, " %s version: %s", ci.Name, ci.Commit.ID)
|
||||
if ci.Commit.ID != ci.Commit.Expected {
|
||||
fmt.Fprintf(dockerCli.Out(), " (expected: %s)", ci.Commit.Expected)
|
||||
fprintf(output, " (expected: %s)", ci.Commit.Expected)
|
||||
}
|
||||
fmt.Fprint(dockerCli.Out(), "\n")
|
||||
fprintln(output)
|
||||
}
|
||||
if len(info.SecurityOptions) != 0 {
|
||||
if kvs, err := types.DecodeSecurityOptions(info.SecurityOptions); err != nil {
|
||||
errs = append(errs, err)
|
||||
} else {
|
||||
fmt.Fprintln(dockerCli.Out(), " Security Options:")
|
||||
fprintln(output, " Security Options:")
|
||||
for _, so := range kvs {
|
||||
fmt.Fprintln(dockerCli.Out(), " "+so.Name)
|
||||
fprintln(output, " "+so.Name)
|
||||
for _, o := range so.Options {
|
||||
switch o.Key {
|
||||
case "profile":
|
||||
fmt.Fprintln(dockerCli.Out(), " Profile:", o.Value)
|
||||
fprintln(output, " Profile:", o.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -294,166 +302,163 @@ func prettyPrintServerInfo(dockerCli command.Cli, info types.Info) []error {
|
||||
|
||||
// Isolation only has meaning on a Windows daemon.
|
||||
if info.OSType == "windows" {
|
||||
fmt.Fprintln(dockerCli.Out(), " Default Isolation:", info.Isolation)
|
||||
fprintln(output, " Default Isolation:", info.Isolation)
|
||||
}
|
||||
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Kernel Version:", info.KernelVersion)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Operating System:", info.OperatingSystem)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " OSType:", info.OSType)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Architecture:", info.Architecture)
|
||||
fmt.Fprintln(dockerCli.Out(), " CPUs:", info.NCPU)
|
||||
fmt.Fprintln(dockerCli.Out(), " Total Memory:", units.BytesSize(float64(info.MemTotal)))
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Name:", info.Name)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " ID:", info.ID)
|
||||
fmt.Fprintln(dockerCli.Out(), " Docker Root Dir:", info.DockerRootDir)
|
||||
fmt.Fprintln(dockerCli.Out(), " Debug Mode:", info.Debug)
|
||||
fprintlnNonEmpty(output, " Kernel Version:", info.KernelVersion)
|
||||
fprintlnNonEmpty(output, " Operating System:", info.OperatingSystem)
|
||||
fprintlnNonEmpty(output, " OSType:", info.OSType)
|
||||
fprintlnNonEmpty(output, " Architecture:", info.Architecture)
|
||||
fprintln(output, " CPUs:", info.NCPU)
|
||||
fprintln(output, " Total Memory:", units.BytesSize(float64(info.MemTotal)))
|
||||
fprintlnNonEmpty(output, " Name:", info.Name)
|
||||
fprintlnNonEmpty(output, " ID:", info.ID)
|
||||
fprintln(output, " Docker Root Dir:", info.DockerRootDir)
|
||||
fprintln(output, " Debug Mode:", info.Debug)
|
||||
|
||||
if info.Debug {
|
||||
fmt.Fprintln(dockerCli.Out(), " File Descriptors:", info.NFd)
|
||||
fmt.Fprintln(dockerCli.Out(), " Goroutines:", info.NGoroutines)
|
||||
fmt.Fprintln(dockerCli.Out(), " System Time:", info.SystemTime)
|
||||
fmt.Fprintln(dockerCli.Out(), " EventsListeners:", info.NEventsListener)
|
||||
}
|
||||
|
||||
fprintlnNonEmpty(dockerCli.Out(), " HTTP Proxy:", info.HTTPProxy)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " HTTPS Proxy:", info.HTTPSProxy)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " No Proxy:", info.NoProxy)
|
||||
|
||||
if info.IndexServerAddress != "" {
|
||||
u := dockerCli.ConfigFile().AuthConfigs[info.IndexServerAddress].Username
|
||||
if len(u) > 0 {
|
||||
fmt.Fprintln(dockerCli.Out(), " Username:", u)
|
||||
}
|
||||
// The daemon collects this information regardless if "debug" is
|
||||
// enabled. Print the debugging information if either the daemon,
|
||||
// or the client has debug enabled. We should probably improve this
|
||||
// logic and print any of these if set (but some special rules are
|
||||
// needed for file-descriptors, which may use "-1".
|
||||
if info.Debug || debug.IsEnabled() {
|
||||
fprintln(output, " File Descriptors:", info.NFd)
|
||||
fprintln(output, " Goroutines:", info.NGoroutines)
|
||||
fprintln(output, " System Time:", info.SystemTime)
|
||||
fprintln(output, " EventsListeners:", info.NEventsListener)
|
||||
}
|
||||
|
||||
fprintlnNonEmpty(output, " HTTP Proxy:", info.HTTPProxy)
|
||||
fprintlnNonEmpty(output, " HTTPS Proxy:", info.HTTPSProxy)
|
||||
fprintlnNonEmpty(output, " No Proxy:", info.NoProxy)
|
||||
fprintlnNonEmpty(output, " Username:", info.UserName)
|
||||
if len(info.Labels) > 0 {
|
||||
fmt.Fprintln(dockerCli.Out(), " Labels:")
|
||||
fprintln(output, " Labels:")
|
||||
for _, lbl := range info.Labels {
|
||||
fmt.Fprintln(dockerCli.Out(), " "+lbl)
|
||||
fprintln(output, " "+lbl)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintln(dockerCli.Out(), " Experimental:", info.ExperimentalBuild)
|
||||
fprintln(output, " Experimental:", info.ExperimentalBuild)
|
||||
|
||||
if info.RegistryConfig != nil && (len(info.RegistryConfig.InsecureRegistryCIDRs) > 0 || len(info.RegistryConfig.IndexConfigs) > 0) {
|
||||
fmt.Fprintln(dockerCli.Out(), " Insecure Registries:")
|
||||
for _, registry := range info.RegistryConfig.IndexConfigs {
|
||||
if !registry.Secure {
|
||||
fmt.Fprintln(dockerCli.Out(), " "+registry.Name)
|
||||
fprintln(output, " Insecure Registries:")
|
||||
for _, registryConfig := range info.RegistryConfig.IndexConfigs {
|
||||
if !registryConfig.Secure {
|
||||
fprintln(output, " "+registryConfig.Name)
|
||||
}
|
||||
}
|
||||
|
||||
for _, registry := range info.RegistryConfig.InsecureRegistryCIDRs {
|
||||
mask, _ := registry.Mask.Size()
|
||||
fmt.Fprintf(dockerCli.Out(), " %s/%d\n", registry.IP.String(), mask)
|
||||
for _, registryConfig := range info.RegistryConfig.InsecureRegistryCIDRs {
|
||||
mask, _ := registryConfig.Mask.Size()
|
||||
fprintf(output, " %s/%d\n", registryConfig.IP.String(), mask)
|
||||
}
|
||||
}
|
||||
|
||||
if info.RegistryConfig != nil && len(info.RegistryConfig.Mirrors) > 0 {
|
||||
fmt.Fprintln(dockerCli.Out(), " Registry Mirrors:")
|
||||
fprintln(output, " Registry Mirrors:")
|
||||
for _, mirror := range info.RegistryConfig.Mirrors {
|
||||
fmt.Fprintln(dockerCli.Out(), " "+mirror)
|
||||
fprintln(output, " "+mirror)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintln(dockerCli.Out(), " Live Restore Enabled:", info.LiveRestoreEnabled)
|
||||
fprintln(output, " Live Restore Enabled:", info.LiveRestoreEnabled)
|
||||
if info.ProductLicense != "" {
|
||||
fmt.Fprintln(dockerCli.Out(), " Product License:", info.ProductLicense)
|
||||
fprintln(output, " Product License:", info.ProductLicense)
|
||||
}
|
||||
|
||||
if info.DefaultAddressPools != nil && len(info.DefaultAddressPools) > 0 {
|
||||
fmt.Fprintln(dockerCli.Out(), " Default Address Pools:")
|
||||
fprintln(output, " Default Address Pools:")
|
||||
for _, pool := range info.DefaultAddressPools {
|
||||
fmt.Fprintf(dockerCli.Out(), " Base: %s, Size: %d\n", pool.Base, pool.Size)
|
||||
fprintf(output, " Base: %s, Size: %d\n", pool.Base, pool.Size)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprint(dockerCli.Out(), "\n")
|
||||
|
||||
printServerWarnings(dockerCli, info)
|
||||
fprintln(output)
|
||||
printServerWarnings(streams.Err(), info)
|
||||
return errs
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func printSwarmInfo(dockerCli command.Cli, info types.Info) {
|
||||
func printSwarmInfo(output io.Writer, info types.Info) {
|
||||
if info.Swarm.LocalNodeState == swarm.LocalNodeStateInactive || info.Swarm.LocalNodeState == swarm.LocalNodeStateLocked {
|
||||
return
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " NodeID:", info.Swarm.NodeID)
|
||||
fprintln(output, " NodeID:", info.Swarm.NodeID)
|
||||
if info.Swarm.Error != "" {
|
||||
fmt.Fprintln(dockerCli.Out(), " Error:", info.Swarm.Error)
|
||||
fprintln(output, " Error:", info.Swarm.Error)
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " Is Manager:", info.Swarm.ControlAvailable)
|
||||
fprintln(output, " Is Manager:", info.Swarm.ControlAvailable)
|
||||
if info.Swarm.Cluster != nil && info.Swarm.ControlAvailable && info.Swarm.Error == "" && info.Swarm.LocalNodeState != swarm.LocalNodeStateError {
|
||||
fmt.Fprintln(dockerCli.Out(), " ClusterID:", info.Swarm.Cluster.ID)
|
||||
fmt.Fprintln(dockerCli.Out(), " Managers:", info.Swarm.Managers)
|
||||
fmt.Fprintln(dockerCli.Out(), " Nodes:", info.Swarm.Nodes)
|
||||
fprintln(output, " ClusterID:", info.Swarm.Cluster.ID)
|
||||
fprintln(output, " Managers:", info.Swarm.Managers)
|
||||
fprintln(output, " Nodes:", info.Swarm.Nodes)
|
||||
var strAddrPool strings.Builder
|
||||
if info.Swarm.Cluster.DefaultAddrPool != nil {
|
||||
for _, p := range info.Swarm.Cluster.DefaultAddrPool {
|
||||
strAddrPool.WriteString(p + " ")
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " Default Address Pool:", strAddrPool.String())
|
||||
fmt.Fprintln(dockerCli.Out(), " SubnetSize:", info.Swarm.Cluster.SubnetSize)
|
||||
fprintln(output, " Default Address Pool:", strAddrPool.String())
|
||||
fprintln(output, " SubnetSize:", info.Swarm.Cluster.SubnetSize)
|
||||
}
|
||||
if info.Swarm.Cluster.DataPathPort > 0 {
|
||||
fmt.Fprintln(dockerCli.Out(), " Data Path Port:", info.Swarm.Cluster.DataPathPort)
|
||||
fprintln(output, " Data Path Port:", info.Swarm.Cluster.DataPathPort)
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " Orchestration:")
|
||||
fprintln(output, " Orchestration:")
|
||||
|
||||
taskHistoryRetentionLimit := int64(0)
|
||||
if info.Swarm.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit != nil {
|
||||
taskHistoryRetentionLimit = *info.Swarm.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " Task History Retention Limit:", taskHistoryRetentionLimit)
|
||||
fmt.Fprintln(dockerCli.Out(), " Raft:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Snapshot Interval:", info.Swarm.Cluster.Spec.Raft.SnapshotInterval)
|
||||
fprintln(output, " Task History Retention Limit:", taskHistoryRetentionLimit)
|
||||
fprintln(output, " Raft:")
|
||||
fprintln(output, " Snapshot Interval:", info.Swarm.Cluster.Spec.Raft.SnapshotInterval)
|
||||
if info.Swarm.Cluster.Spec.Raft.KeepOldSnapshots != nil {
|
||||
fmt.Fprintf(dockerCli.Out(), " Number of Old Snapshots to Retain: %d\n", *info.Swarm.Cluster.Spec.Raft.KeepOldSnapshots)
|
||||
fprintf(output, " Number of Old Snapshots to Retain: %d\n", *info.Swarm.Cluster.Spec.Raft.KeepOldSnapshots)
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " Heartbeat Tick:", info.Swarm.Cluster.Spec.Raft.HeartbeatTick)
|
||||
fmt.Fprintln(dockerCli.Out(), " Election Tick:", info.Swarm.Cluster.Spec.Raft.ElectionTick)
|
||||
fmt.Fprintln(dockerCli.Out(), " Dispatcher:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Heartbeat Period:", units.HumanDuration(info.Swarm.Cluster.Spec.Dispatcher.HeartbeatPeriod))
|
||||
fmt.Fprintln(dockerCli.Out(), " CA Configuration:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Expiry Duration:", units.HumanDuration(info.Swarm.Cluster.Spec.CAConfig.NodeCertExpiry))
|
||||
fmt.Fprintln(dockerCli.Out(), " Force Rotate:", info.Swarm.Cluster.Spec.CAConfig.ForceRotate)
|
||||
fprintln(output, " Heartbeat Tick:", info.Swarm.Cluster.Spec.Raft.HeartbeatTick)
|
||||
fprintln(output, " Election Tick:", info.Swarm.Cluster.Spec.Raft.ElectionTick)
|
||||
fprintln(output, " Dispatcher:")
|
||||
fprintln(output, " Heartbeat Period:", units.HumanDuration(info.Swarm.Cluster.Spec.Dispatcher.HeartbeatPeriod))
|
||||
fprintln(output, " CA Configuration:")
|
||||
fprintln(output, " Expiry Duration:", units.HumanDuration(info.Swarm.Cluster.Spec.CAConfig.NodeCertExpiry))
|
||||
fprintln(output, " Force Rotate:", info.Swarm.Cluster.Spec.CAConfig.ForceRotate)
|
||||
if caCert := strings.TrimSpace(info.Swarm.Cluster.Spec.CAConfig.SigningCACert); caCert != "" {
|
||||
fmt.Fprintf(dockerCli.Out(), " Signing CA Certificate: \n%s\n\n", caCert)
|
||||
fprintf(output, " Signing CA Certificate: \n%s\n\n", caCert)
|
||||
}
|
||||
if len(info.Swarm.Cluster.Spec.CAConfig.ExternalCAs) > 0 {
|
||||
fmt.Fprintln(dockerCli.Out(), " External CAs:")
|
||||
fprintln(output, " External CAs:")
|
||||
for _, entry := range info.Swarm.Cluster.Spec.CAConfig.ExternalCAs {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s: %s\n", entry.Protocol, entry.URL)
|
||||
fprintf(output, " %s: %s\n", entry.Protocol, entry.URL)
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " Autolock Managers:", info.Swarm.Cluster.Spec.EncryptionConfig.AutoLockManagers)
|
||||
fmt.Fprintln(dockerCli.Out(), " Root Rotation In Progress:", info.Swarm.Cluster.RootRotationInProgress)
|
||||
fprintln(output, " Autolock Managers:", info.Swarm.Cluster.Spec.EncryptionConfig.AutoLockManagers)
|
||||
fprintln(output, " Root Rotation In Progress:", info.Swarm.Cluster.RootRotationInProgress)
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " Node Address:", info.Swarm.NodeAddr)
|
||||
fprintln(output, " Node Address:", info.Swarm.NodeAddr)
|
||||
if len(info.Swarm.RemoteManagers) > 0 {
|
||||
managers := []string{}
|
||||
for _, entry := range info.Swarm.RemoteManagers {
|
||||
managers = append(managers, entry.Addr)
|
||||
}
|
||||
sort.Strings(managers)
|
||||
fmt.Fprintln(dockerCli.Out(), " Manager Addresses:")
|
||||
fprintln(output, " Manager Addresses:")
|
||||
for _, entry := range managers {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s\n", entry)
|
||||
fprintf(output, " %s\n", entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func printServerWarnings(dockerCli command.Cli, info types.Info) {
|
||||
if versions.LessThan(dockerCli.Client().ClientVersion(), "1.42") {
|
||||
printSecurityOptionsWarnings(dockerCli, info)
|
||||
func printServerWarnings(stdErr io.Writer, info *info) {
|
||||
if versions.LessThan(info.ClientInfo.APIVersion, "1.42") {
|
||||
printSecurityOptionsWarnings(stdErr, *info.Info)
|
||||
}
|
||||
if len(info.Warnings) > 0 {
|
||||
fmt.Fprintln(dockerCli.Err(), strings.Join(info.Warnings, "\n"))
|
||||
fprintln(stdErr, strings.Join(info.Warnings, "\n"))
|
||||
return
|
||||
}
|
||||
// daemon didn't return warnings. Fallback to old behavior
|
||||
printServerWarningsLegacy(dockerCli, info)
|
||||
printServerWarningsLegacy(stdErr, *info.Info)
|
||||
}
|
||||
|
||||
// printSecurityOptionsWarnings prints warnings based on the security options
|
||||
@ -462,7 +467,7 @@ func printServerWarnings(dockerCli command.Cli, info types.Info) {
|
||||
// info.Warnings. This function is used to provide backward compatibility with
|
||||
// daemons that do not provide these warnings. No new warnings should be added
|
||||
// here.
|
||||
func printSecurityOptionsWarnings(dockerCli command.Cli, info types.Info) {
|
||||
func printSecurityOptionsWarnings(stdErr io.Writer, info types.Info) {
|
||||
if info.OSType == "windows" {
|
||||
return
|
||||
}
|
||||
@ -473,7 +478,7 @@ func printSecurityOptionsWarnings(dockerCli command.Cli, info types.Info) {
|
||||
}
|
||||
for _, o := range so.Options {
|
||||
if o.Key == "profile" && o.Value != "default" && o.Value != "builtin" {
|
||||
_, _ = fmt.Fprintln(dockerCli.Err(), "WARNING: You're not using the default seccomp profile")
|
||||
_, _ = fmt.Fprintln(stdErr, "WARNING: You're not using the default seccomp profile")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -484,43 +489,43 @@ func printSecurityOptionsWarnings(dockerCli command.Cli, info types.Info) {
|
||||
// info.Warnings. This function is used to provide backward compatibility with
|
||||
// daemons that do not provide these warnings. No new warnings should be added
|
||||
// here.
|
||||
func printServerWarningsLegacy(dockerCli command.Cli, info types.Info) {
|
||||
func printServerWarningsLegacy(stdErr io.Writer, info types.Info) {
|
||||
if info.OSType == "windows" {
|
||||
return
|
||||
}
|
||||
if !info.MemoryLimit {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No memory limit support")
|
||||
fprintln(stdErr, "WARNING: No memory limit support")
|
||||
}
|
||||
if !info.SwapLimit {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No swap limit support")
|
||||
fprintln(stdErr, "WARNING: No swap limit support")
|
||||
}
|
||||
if !info.OomKillDisable && info.CgroupVersion != "2" {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No oom kill disable support")
|
||||
fprintln(stdErr, "WARNING: No oom kill disable support")
|
||||
}
|
||||
if !info.CPUCfsQuota {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs quota support")
|
||||
fprintln(stdErr, "WARNING: No cpu cfs quota support")
|
||||
}
|
||||
if !info.CPUCfsPeriod {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs period support")
|
||||
fprintln(stdErr, "WARNING: No cpu cfs period support")
|
||||
}
|
||||
if !info.CPUShares {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu shares support")
|
||||
fprintln(stdErr, "WARNING: No cpu shares support")
|
||||
}
|
||||
if !info.CPUSet {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No cpuset support")
|
||||
fprintln(stdErr, "WARNING: No cpuset support")
|
||||
}
|
||||
if !info.IPv4Forwarding {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: IPv4 forwarding is disabled")
|
||||
fprintln(stdErr, "WARNING: IPv4 forwarding is disabled")
|
||||
}
|
||||
if !info.BridgeNfIptables {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-iptables is disabled")
|
||||
fprintln(stdErr, "WARNING: bridge-nf-call-iptables is disabled")
|
||||
}
|
||||
if !info.BridgeNfIP6tables {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-ip6tables is disabled")
|
||||
fprintln(stdErr, "WARNING: bridge-nf-call-ip6tables is disabled")
|
||||
}
|
||||
}
|
||||
|
||||
func formatInfo(dockerCli command.Cli, info info, format string) error {
|
||||
func formatInfo(output io.Writer, info info, format string) error {
|
||||
if format == formatter.JSONFormatKey {
|
||||
format = formatter.JSONFormat
|
||||
}
|
||||
@ -537,13 +542,21 @@ func formatInfo(dockerCli command.Cli, info info, format string) error {
|
||||
Status: "template parsing error: " + err.Error(),
|
||||
}
|
||||
}
|
||||
err = tmpl.Execute(dockerCli.Out(), info)
|
||||
dockerCli.Out().Write([]byte{'\n'})
|
||||
err = tmpl.Execute(output, info)
|
||||
fprintln(output)
|
||||
return err
|
||||
}
|
||||
|
||||
func fprintf(w io.Writer, format string, a ...any) {
|
||||
_, _ = fmt.Fprintf(w, format, a...)
|
||||
}
|
||||
|
||||
func fprintln(w io.Writer, a ...any) {
|
||||
_, _ = fmt.Fprintln(w, a...)
|
||||
}
|
||||
|
||||
func fprintlnNonEmpty(w io.Writer, label, value string) {
|
||||
if value != "" {
|
||||
fmt.Fprintln(w, label, value)
|
||||
_, _ = fmt.Fprintln(w, label, value)
|
||||
}
|
||||
}
|
||||
|
||||
@ -406,12 +406,12 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
|
||||
if tc.jsonGolden != "" {
|
||||
cli = test.NewFakeCli(&fakeClient{})
|
||||
assert.NilError(t, formatInfo(cli, tc.dockerInfo, "{{json .}}"))
|
||||
assert.NilError(t, formatInfo(cli.Out(), tc.dockerInfo, "{{json .}}"))
|
||||
golden.Assert(t, cli.OutBuffer().String(), tc.jsonGolden+".json.golden")
|
||||
assert.Check(t, is.Equal("", cli.ErrBuffer().String()))
|
||||
|
||||
cli = test.NewFakeCli(&fakeClient{})
|
||||
assert.NilError(t, formatInfo(cli, tc.dockerInfo, "json"))
|
||||
assert.NilError(t, formatInfo(cli.Out(), tc.dockerInfo, "json"))
|
||||
golden.Assert(t, cli.OutBuffer().String(), tc.jsonGolden+".json.golden")
|
||||
assert.Check(t, is.Equal("", cli.ErrBuffer().String()))
|
||||
}
|
||||
@ -419,6 +419,30 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkPrettyPrintInfo(b *testing.B) {
|
||||
infoWithSwarm := sampleInfoNoSwarm
|
||||
infoWithSwarm.Swarm = sampleSwarmInfo
|
||||
|
||||
dockerInfo := info{
|
||||
Info: &infoWithSwarm,
|
||||
ClientInfo: &clientInfo{
|
||||
clientVersion: clientVersion{
|
||||
Platform: &platformInfo{Name: "Docker Engine - Community"},
|
||||
Version: "24.0.0",
|
||||
Context: "default",
|
||||
},
|
||||
Debug: true,
|
||||
},
|
||||
}
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = prettyPrintInfo(cli, dockerInfo)
|
||||
cli.ResetOutputBuffers()
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatInfo(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
doc string
|
||||
@ -449,7 +473,7 @@ func TestFormatInfo(t *testing.T) {
|
||||
Info: &sampleInfoNoSwarm,
|
||||
ClientInfo: &clientInfo{Debug: true},
|
||||
}
|
||||
err := formatInfo(cli, info, tc.template)
|
||||
err := formatInfo(cli.Out(), info, tc.template)
|
||||
if tc.expectedOut != "" {
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, cli.OutBuffer().String(), tc.expectedOut)
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package system
|
||||
|
||||
import (
|
||||
|
||||
@ -48,7 +48,7 @@ func newPruneCommand(dockerCli command.Cli) *cobra.Command {
|
||||
flags := cmd.Flags()
|
||||
flags.BoolVarP(&options.force, "force", "f", false, "Do not prompt for confirmation")
|
||||
flags.BoolVarP(&options.all, "all", "a", false, "Remove all unused images not just dangling ones")
|
||||
flags.BoolVar(&options.pruneVolumes, "volumes", false, "Prune volumes")
|
||||
flags.BoolVar(&options.pruneVolumes, "volumes", false, "Prune anonymous volumes")
|
||||
flags.Var(&options.filter, "filter", `Provide filter values (e.g. "label=<key>=<value>")`)
|
||||
// "filter" flag is available in 1.28 (docker 17.04) and up
|
||||
flags.SetAnnotation("filter", "version", []string{"1.28"})
|
||||
@ -114,7 +114,7 @@ func confirmationMessage(dockerCli command.Cli, options pruneOptions) string {
|
||||
"all networks not used by at least one container",
|
||||
}
|
||||
if options.pruneVolumes {
|
||||
warnings = append(warnings, "all volumes not used by at least one container")
|
||||
warnings = append(warnings, "all anonymous volumes not used by at least one container")
|
||||
}
|
||||
if options.all {
|
||||
warnings = append(warnings, "all images without at least one container associated to them")
|
||||
|
||||
4
cli/command/system/testdata/docker-events-default.golden
vendored
Normal file
4
cli/command/system/testdata/docker-events-default.golden
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
1970-01-01T00:00:01.000000000Z container create abc123 (image=ubuntu:latest)
|
||||
1970-01-01T00:00:02.000000000Z container start abc123 (image=ubuntu:latest)
|
||||
1970-01-01T00:00:03.000000000Z container attach abc123 (image=ubuntu:latest)
|
||||
1970-01-01T00:00:04.000000000Z container die abc123 (image=ubuntu:latest)
|
||||
4
cli/command/system/testdata/docker-events-json-action.golden
vendored
Normal file
4
cli/command/system/testdata/docker-events-json-action.golden
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
"create"
|
||||
"start"
|
||||
"attach"
|
||||
"die"
|
||||
4
cli/command/system/testdata/docker-events-json-template.golden
vendored
Normal file
4
cli/command/system/testdata/docker-events-json-template.golden
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{"status":"create","id":"abc123","from":"ubuntu:latest","Type":"container","Action":"create","Actor":{"ID":"abc123","Attributes":{"image":"ubuntu:latest"}},"scope":"local","time":1000000000,"timeNano":1000000000}
|
||||
{"status":"start","id":"abc123","from":"ubuntu:latest","Type":"container","Action":"start","Actor":{"ID":"abc123","Attributes":{"image":"ubuntu:latest"}},"scope":"local","time":2000000000,"timeNano":2000000000}
|
||||
{"status":"attach","id":"abc123","from":"ubuntu:latest","Type":"container","Action":"attach","Actor":{"ID":"abc123","Attributes":{"image":"ubuntu:latest"}},"scope":"local","time":3000000000,"timeNano":3000000000}
|
||||
{"status":"die","id":"abc123","from":"ubuntu:latest","Type":"container","Action":"die","Actor":{"ID":"abc123","Attributes":{"image":"ubuntu:latest"}},"scope":"local","time":4000000000,"timeNano":4000000000}
|
||||
4
cli/command/system/testdata/docker-events-json.golden
vendored
Normal file
4
cli/command/system/testdata/docker-events-json.golden
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{"status":"create","id":"abc123","from":"ubuntu:latest","Type":"container","Action":"create","Actor":{"ID":"abc123","Attributes":{"image":"ubuntu:latest"}},"scope":"local","time":1000000000,"timeNano":1000000000}
|
||||
{"status":"start","id":"abc123","from":"ubuntu:latest","Type":"container","Action":"start","Actor":{"ID":"abc123","Attributes":{"image":"ubuntu:latest"}},"scope":"local","time":2000000000,"timeNano":2000000000}
|
||||
{"status":"attach","id":"abc123","from":"ubuntu:latest","Type":"container","Action":"attach","Actor":{"ID":"abc123","Attributes":{"image":"ubuntu:latest"}},"scope":"local","time":3000000000,"timeNano":3000000000}
|
||||
{"status":"die","id":"abc123","from":"ubuntu:latest","Type":"container","Action":"die","Actor":{"ID":"abc123","Attributes":{"image":"ubuntu:latest"}},"scope":"local","time":4000000000,"timeNano":4000000000}
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package trust
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package command
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package volume
|
||||
|
||||
import (
|
||||
|
||||
@ -8,11 +8,15 @@ import (
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/completion"
|
||||
"github.com/docker/cli/opts"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"github.com/docker/docker/errdefs"
|
||||
units "github.com/docker/go-units"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type pruneOptions struct {
|
||||
all bool
|
||||
force bool
|
||||
filter opts.FilterOpt
|
||||
}
|
||||
@ -23,7 +27,7 @@ func NewPruneCommand(dockerCli command.Cli) *cobra.Command {
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "prune [OPTIONS]",
|
||||
Short: "Remove all unused local volumes",
|
||||
Short: "Remove unused local volumes",
|
||||
Args: cli.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
spaceReclaimed, output, err := runPrune(dockerCli, options)
|
||||
@ -41,18 +45,37 @@ func NewPruneCommand(dockerCli command.Cli) *cobra.Command {
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
flags.BoolVarP(&options.all, "all", "a", false, "Remove all unused volumes, not just anonymous ones")
|
||||
flags.SetAnnotation("all", "version", []string{"1.42"})
|
||||
flags.BoolVarP(&options.force, "force", "f", false, "Do not prompt for confirmation")
|
||||
flags.Var(&options.filter, "filter", `Provide filter values (e.g. "label=<label>")`)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
const warning = `WARNING! This will remove all local volumes not used by at least one container.
|
||||
const (
|
||||
unusedVolumesWarning = `WARNING! This will remove anonymous local volumes not used by at least one container.
|
||||
Are you sure you want to continue?`
|
||||
allVolumesWarning = `WARNING! This will remove all local volumes not used by at least one container.
|
||||
Are you sure you want to continue?`
|
||||
)
|
||||
|
||||
func runPrune(dockerCli command.Cli, options pruneOptions) (spaceReclaimed uint64, output string, err error) {
|
||||
pruneFilters := command.PruneFilters(dockerCli, options.filter.Value())
|
||||
|
||||
warning := unusedVolumesWarning
|
||||
if versions.GreaterThanOrEqualTo(dockerCli.CurrentVersion(), "1.42") {
|
||||
if options.all {
|
||||
if pruneFilters.Contains("all") {
|
||||
return 0, "", errdefs.InvalidParameter(errors.New("conflicting options: cannot specify both --all and --filter all=1"))
|
||||
}
|
||||
pruneFilters.Add("all", "true")
|
||||
warning = allVolumesWarning
|
||||
}
|
||||
} else {
|
||||
// API < v1.42 removes all volumes (anonymous and named) by default.
|
||||
warning = allVolumesWarning
|
||||
}
|
||||
if !options.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), warning) {
|
||||
return 0, "", nil
|
||||
}
|
||||
|
||||
@ -13,22 +13,26 @@ import (
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/pkg/errors"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
"gotest.tools/v3/golden"
|
||||
"gotest.tools/v3/skip"
|
||||
)
|
||||
|
||||
func TestVolumePruneErrors(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
flags map[string]string
|
||||
volumePruneFunc func(args filters.Args) (types.VolumesPruneReport, error)
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
name: "accepts no arguments",
|
||||
args: []string{"foo"},
|
||||
expectedError: "accepts no argument",
|
||||
},
|
||||
{
|
||||
name: "forced but other error",
|
||||
flags: map[string]string{
|
||||
"force": "true",
|
||||
},
|
||||
@ -37,20 +41,75 @@ func TestVolumePruneErrors(t *testing.T) {
|
||||
},
|
||||
expectedError: "error pruning volumes",
|
||||
},
|
||||
{
|
||||
name: "conflicting options",
|
||||
flags: map[string]string{
|
||||
"all": "true",
|
||||
"filter": "all=1",
|
||||
},
|
||||
expectedError: "conflicting options: cannot specify both --all and --filter all=1",
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
cmd := NewPruneCommand(
|
||||
test.NewFakeCli(&fakeClient{
|
||||
volumePruneFunc: tc.volumePruneFunc,
|
||||
}),
|
||||
)
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
cmd.SetOut(io.Discard)
|
||||
cmd.SetErr(io.Discard)
|
||||
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := NewPruneCommand(
|
||||
test.NewFakeCli(&fakeClient{
|
||||
volumePruneFunc: tc.volumePruneFunc,
|
||||
}),
|
||||
)
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
cmd.SetOut(io.Discard)
|
||||
cmd.SetErr(io.Discard)
|
||||
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVolumePruneSuccess(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
volumePruneFunc func(args filters.Args) (types.VolumesPruneReport, error)
|
||||
}{
|
||||
{
|
||||
name: "all",
|
||||
args: []string{"--all"},
|
||||
volumePruneFunc: func(pruneFilter filters.Args) (types.VolumesPruneReport, error) {
|
||||
assert.Check(t, is.Equal([]string{"true"}, pruneFilter.Get("all")))
|
||||
return types.VolumesPruneReport{}, nil
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "all-forced",
|
||||
args: []string{"--all", "--force"},
|
||||
volumePruneFunc: func(pruneFilter filters.Args) (types.VolumesPruneReport, error) {
|
||||
return types.VolumesPruneReport{}, nil
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "label-filter",
|
||||
args: []string{"--filter", "label=foobar"},
|
||||
volumePruneFunc: func(pruneFilter filters.Args) (types.VolumesPruneReport, error) {
|
||||
assert.Check(t, is.Equal([]string{"foobar"}, pruneFilter.Get("label")))
|
||||
return types.VolumesPruneReport{}, nil
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{volumePruneFunc: tc.volumePruneFunc})
|
||||
cmd := NewPruneCommand(cli)
|
||||
cmd.SetOut(io.Discard)
|
||||
cmd.SetArgs(tc.args)
|
||||
err := cmd.Execute()
|
||||
assert.NilError(t, err)
|
||||
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("volume-prune-success.%s.golden", tc.name))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
WARNING! This will remove all local volumes not used by at least one container.
|
||||
WARNING! This will remove anonymous local volumes not used by at least one container.
|
||||
Are you sure you want to continue? [y/N] Total reclaimed space: 0B
|
||||
|
||||
1
cli/command/volume/testdata/volume-prune-success.all-forced.golden
vendored
Normal file
1
cli/command/volume/testdata/volume-prune-success.all-forced.golden
vendored
Normal file
@ -0,0 +1 @@
|
||||
Total reclaimed space: 0B
|
||||
2
cli/command/volume/testdata/volume-prune-success.all.golden
vendored
Normal file
2
cli/command/volume/testdata/volume-prune-success.all.golden
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
WARNING! This will remove all local volumes not used by at least one container.
|
||||
Are you sure you want to continue? [y/N] Total reclaimed space: 0B
|
||||
2
cli/command/volume/testdata/volume-prune-success.label-filter.golden
vendored
Normal file
2
cli/command/volume/testdata/volume-prune-success.label-filter.golden
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
WARNING! This will remove anonymous local volumes not used by at least one container.
|
||||
Are you sure you want to continue? [y/N] Total reclaimed space: 0B
|
||||
@ -1,4 +1,4 @@
|
||||
WARNING! This will remove all local volumes not used by at least one container.
|
||||
WARNING! This will remove anonymous local volumes not used by at least one container.
|
||||
Are you sure you want to continue? [y/N] Deleted Volumes:
|
||||
foo
|
||||
bar
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package interpolation
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package interpolation
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package loader
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package loader
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package loader
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package loader
|
||||
|
||||
import (
|
||||
@ -179,7 +182,7 @@ func strPtr(val string) *string {
|
||||
}
|
||||
|
||||
var sampleConfig = types.Config{
|
||||
Version: "3.10",
|
||||
Version: "3.11",
|
||||
Services: []types.ServiceConfig{
|
||||
{
|
||||
Name: "foo",
|
||||
@ -488,6 +491,17 @@ services:
|
||||
assert.Check(t, is.ErrorContains(err, "services.foo.image must be a string"))
|
||||
}
|
||||
|
||||
func TestIgnoreBuildProperties(t *testing.T) {
|
||||
_, err := loadYAML(`
|
||||
services:
|
||||
foo:
|
||||
image: busybox
|
||||
build:
|
||||
unsupported_prop: foo
|
||||
`)
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func TestLoadWithEnvironment(t *testing.T) {
|
||||
config, err := loadYAMLWithEnv(`
|
||||
version: "3"
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package loader
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package loader
|
||||
|
||||
import (
|
||||
|
||||
@ -223,3 +223,8 @@ func TestParseVolumeInvalidSections(t *testing.T) {
|
||||
_, err := ParseVolume("/foo::rw")
|
||||
assert.ErrorContains(t, err, "invalid spec")
|
||||
}
|
||||
|
||||
func TestParseVolumeWithEmptySource(t *testing.T) {
|
||||
_, err := ParseVolume(":/vol")
|
||||
assert.ErrorContains(t, err, "empty section between colons")
|
||||
}
|
||||
|
||||
672
cli/compose/schema/data/config_schema_v3.11.json
Normal file
672
cli/compose/schema/data/config_schema_v3.11.json
Normal file
@ -0,0 +1,672 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"id": "config_schema_v3.11.json",
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string",
|
||||
"default": "3.11"
|
||||
},
|
||||
|
||||
"services": {
|
||||
"id": "#/properties/services",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/service"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"networks": {
|
||||
"id": "#/properties/networks",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/network"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"volumes": {
|
||||
"id": "#/properties/volumes",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/volume"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"secrets": {
|
||||
"id": "#/properties/secrets",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/secret"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"configs": {
|
||||
"id": "#/properties/configs",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/config"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false,
|
||||
|
||||
"definitions": {
|
||||
|
||||
"service": {
|
||||
"id": "#/definitions/service",
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"deploy": {"$ref": "#/definitions/deployment"},
|
||||
"build": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {"type": "string"},
|
||||
"dockerfile": {"type": "string"},
|
||||
"args": {"$ref": "#/definitions/list_or_dict"},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"},
|
||||
"cache_from": {"$ref": "#/definitions/list_of_strings"},
|
||||
"network": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"shm_size": {"type": ["integer", "string"]},
|
||||
"extra_hosts": {"$ref": "#/definitions/list_or_dict"}
|
||||
},
|
||||
"additionalProperties": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"cap_add": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cap_drop": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cgroupns_mode": {"type": "string"},
|
||||
"cgroup_parent": {"type": "string"},
|
||||
"command": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"configs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"source": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"uid": {"type": "string"},
|
||||
"gid": {"type": "string"},
|
||||
"mode": {"type": "number"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"container_name": {"type": "string"},
|
||||
"credential_spec": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"config": {"type": "string"},
|
||||
"file": {"type": "string"},
|
||||
"registry": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"depends_on": {"$ref": "#/definitions/list_of_strings"},
|
||||
"devices": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"dns": {"$ref": "#/definitions/string_or_list"},
|
||||
"dns_search": {"$ref": "#/definitions/string_or_list"},
|
||||
"domainname": {"type": "string"},
|
||||
"entrypoint": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"env_file": {"$ref": "#/definitions/string_or_list"},
|
||||
"environment": {"$ref": "#/definitions/list_or_dict"},
|
||||
|
||||
"expose": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"],
|
||||
"format": "expose"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
||||
"healthcheck": {"$ref": "#/definitions/healthcheck"},
|
||||
"hostname": {"type": "string"},
|
||||
"image": {"type": "string"},
|
||||
"init": {"type": "boolean"},
|
||||
"ipc": {"type": "string"},
|
||||
"isolation": {"type": "string"},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"},
|
||||
"links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
|
||||
"logging": {
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"options": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number", "null"]}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"mac_address": {"type": "string"},
|
||||
"network_mode": {"type": "string"},
|
||||
|
||||
"networks": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/definitions/list_of_strings"},
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"aliases": {"$ref": "#/definitions/list_of_strings"},
|
||||
"ipv4_address": {"type": "string"},
|
||||
"ipv6_address": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "null"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"pid": {"type": ["string", "null"]},
|
||||
|
||||
"ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "number", "format": "ports"},
|
||||
{"type": "string", "format": "ports"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mode": {"type": "string"},
|
||||
"target": {"type": "integer"},
|
||||
"published": {"type": "integer"},
|
||||
"protocol": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"privileged": {"type": "boolean"},
|
||||
"read_only": {"type": "boolean"},
|
||||
"restart": {"type": "string"},
|
||||
"security_opt": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"shm_size": {"type": ["number", "string"]},
|
||||
"secrets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"source": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"uid": {"type": "string"},
|
||||
"gid": {"type": "string"},
|
||||
"mode": {"type": "number"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"sysctls": {"$ref": "#/definitions/list_or_dict"},
|
||||
"stdin_open": {"type": "boolean"},
|
||||
"stop_grace_period": {"type": "string", "format": "duration"},
|
||||
"stop_signal": {"type": "string"},
|
||||
"tmpfs": {"$ref": "#/definitions/string_or_list"},
|
||||
"tty": {"type": "boolean"},
|
||||
"ulimits": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-z]+$": {
|
||||
"oneOf": [
|
||||
{"type": "integer"},
|
||||
{
|
||||
"type":"object",
|
||||
"properties": {
|
||||
"hard": {"type": "integer"},
|
||||
"soft": {"type": "integer"}
|
||||
},
|
||||
"required": ["soft", "hard"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"user": {"type": "string"},
|
||||
"userns_mode": {"type": "string"},
|
||||
"volumes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["type"],
|
||||
"properties": {
|
||||
"type": {"type": "string"},
|
||||
"source": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"read_only": {"type": "boolean"},
|
||||
"consistency": {"type": "string"},
|
||||
"bind": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"propagation": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"volume": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"nocopy": {"type": "boolean"}
|
||||
}
|
||||
},
|
||||
"tmpfs": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"size": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
],
|
||||
"uniqueItems": true
|
||||
}
|
||||
},
|
||||
"working_dir": {"type": "string"}
|
||||
},
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"healthcheck": {
|
||||
"id": "#/definitions/healthcheck",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"disable": {"type": "boolean"},
|
||||
"interval": {"type": "string", "format": "duration"},
|
||||
"retries": {"type": "number"},
|
||||
"test": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"timeout": {"type": "string", "format": "duration"},
|
||||
"start_period": {"type": "string", "format": "duration"}
|
||||
}
|
||||
},
|
||||
"deployment": {
|
||||
"id": "#/definitions/deployment",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"mode": {"type": "string"},
|
||||
"endpoint_mode": {"type": "string"},
|
||||
"replicas": {"type": "integer"},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"},
|
||||
"rollback_config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"parallelism": {"type": "integer"},
|
||||
"delay": {"type": "string", "format": "duration"},
|
||||
"failure_action": {"type": "string"},
|
||||
"monitor": {"type": "string", "format": "duration"},
|
||||
"max_failure_ratio": {"type": "number"},
|
||||
"order": {"type": "string", "enum": [
|
||||
"start-first", "stop-first"
|
||||
]}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"update_config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"parallelism": {"type": "integer"},
|
||||
"delay": {"type": "string", "format": "duration"},
|
||||
"failure_action": {"type": "string"},
|
||||
"monitor": {"type": "string", "format": "duration"},
|
||||
"max_failure_ratio": {"type": "number"},
|
||||
"order": {"type": "string", "enum": [
|
||||
"start-first", "stop-first"
|
||||
]}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"resources": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"limits": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cpus": {"type": "string"},
|
||||
"memory": {"type": "string"},
|
||||
"pids": {"type": "integer"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"reservations": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cpus": {"type": "string"},
|
||||
"memory": {"type": "string"},
|
||||
"generic_resources": {"$ref": "#/definitions/generic_resources"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"restart_policy": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"condition": {"type": "string"},
|
||||
"delay": {"type": "string", "format": "duration"},
|
||||
"max_attempts": {"type": "integer"},
|
||||
"window": {"type": "string", "format": "duration"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"placement": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"constraints": {"type": "array", "items": {"type": "string"}},
|
||||
"preferences": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"spread": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"max_replicas_per_node": {"type": "integer"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"generic_resources": {
|
||||
"id": "#/definitions/generic_resources",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"discrete_resource_spec": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"kind": {"type": "string"},
|
||||
"value": {"type": "number"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
|
||||
"network": {
|
||||
"id": "#/definitions/network",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"ipam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"config": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"subnet": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"internal": {"type": "boolean"},
|
||||
"attachable": {"type": "boolean"},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"}
|
||||
},
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"volume": {
|
||||
"id": "#/definitions/volume",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"},
|
||||
"x-cluster-spec": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"group": {"type": "string"},
|
||||
"access_mode": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"scope": {"type": "string"},
|
||||
"sharing": {"type": "string"},
|
||||
"block_volume": {"type": "object"},
|
||||
"mount_volume": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"fs_type": {"type": "string"},
|
||||
"mount_flags": {"type": "array", "items": {"type": "string"}}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"accessibility_requirements": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"requisite": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"segments": {"$ref": "#/definitions/list_or_dict"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferred": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"segments": {"$ref": "#/definitions/list_or_dict"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"capacity_range": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"required_bytes": {"type": "string"},
|
||||
"limit_bytes": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"availability": {"type": "string"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"secret": {
|
||||
"id": "#/definitions/secret",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"file": {"type": "string"},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"},
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"template_driver": {"type": "string"}
|
||||
},
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"config": {
|
||||
"id": "#/definitions/config",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"file": {"type": "string"},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"},
|
||||
"template_driver": {"type": "string"}
|
||||
},
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"string_or_list": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"$ref": "#/definitions/list_of_strings"}
|
||||
]
|
||||
},
|
||||
|
||||
"list_of_strings": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"list_or_dict": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": ["string", "number", "null"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"constraints": {
|
||||
"service": {
|
||||
"id": "#/definitions/constraints/service",
|
||||
"anyOf": [
|
||||
{"required": ["build"]},
|
||||
{"required": ["image"]}
|
||||
],
|
||||
"properties": {
|
||||
"build": {
|
||||
"required": ["context"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package schema
|
||||
|
||||
import (
|
||||
@ -11,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
defaultVersion = "3.10"
|
||||
defaultVersion = "3.11"
|
||||
versionField = "version"
|
||||
)
|
||||
|
||||
@ -40,7 +43,7 @@ func init() {
|
||||
}
|
||||
|
||||
// Version returns the version of the config, defaulting to the latest "3.x"
|
||||
// version (3.10). If only the major version "3" is specified, it is used as
|
||||
// version (3.11). If only the major version "3" is specified, it is used as
|
||||
// version "3.x" and returns the default version (latest 3.x).
|
||||
func Version(config map[string]interface{}) string {
|
||||
version, ok := config[versionField]
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package schema
|
||||
|
||||
import (
|
||||
@ -99,6 +102,7 @@ func TestValidateCredentialSpecs(t *testing.T) {
|
||||
{version: "3.8"},
|
||||
{version: "3.9"},
|
||||
{version: "3.10"},
|
||||
{version: "3.11"},
|
||||
{version: "3"},
|
||||
{version: ""},
|
||||
}
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package template
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package template
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.19
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
|
||||
@ -94,6 +94,9 @@ func (configFile *ConfigFile) ContainsAuth() bool {
|
||||
|
||||
// GetAuthConfigs returns the mapping of repo to auth configuration
|
||||
func (configFile *ConfigFile) GetAuthConfigs() map[string]types.AuthConfig {
|
||||
if configFile.AuthConfigs == nil {
|
||||
configFile.AuthConfigs = make(map[string]types.AuthConfig)
|
||||
}
|
||||
return configFile.AuthConfigs
|
||||
}
|
||||
|
||||
|
||||
@ -52,7 +52,8 @@ func (c *fileStore) GetAll() (map[string]types.AuthConfig, error) {
|
||||
|
||||
// Store saves the given credentials in the file store.
|
||||
func (c *fileStore) Store(authConfig types.AuthConfig) error {
|
||||
c.file.GetAuthConfigs()[authConfig.ServerAddress] = authConfig
|
||||
authConfigs := c.file.GetAuthConfigs()
|
||||
authConfigs[authConfig.ServerAddress] = authConfig
|
||||
return c.file.Save()
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user