mirror of
https://github.com/docker/compose.git
synced 2026-02-14 12:39:23 +08:00
Compare commits
94 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
69651136cf | ||
|
|
f3e0c386d2 | ||
|
|
88406491c9 | ||
|
|
63b126622d | ||
|
|
23deefd20c | ||
|
|
e5eb00f618 | ||
|
|
2f2460b40e | ||
|
|
3aceaa1694 | ||
|
|
c07de59a98 | ||
|
|
235734823e | ||
|
|
d23c261c7d | ||
|
|
157d38aa69 | ||
|
|
5723dee316 | ||
|
|
6eb34031f6 | ||
|
|
9e7ae6cb30 | ||
|
|
f880b4129c | ||
|
|
832eee0e8f | ||
|
|
a1d19119d2 | ||
|
|
b96b5449e5 | ||
|
|
a226fe9daf | ||
|
|
fcfcc1524e | ||
|
|
6fe34c45ca | ||
|
|
10cfd551e3 | ||
|
|
0b4cb85c84 | ||
|
|
3f4f4e5975 | ||
|
|
86c925fbd3 | ||
|
|
a64a5a61a7 | ||
|
|
09e6b0292a | ||
|
|
3c561e7017 | ||
|
|
8ad63f7150 | ||
|
|
10532201a2 | ||
|
|
3022b6479f | ||
|
|
abc73ed3d6 | ||
|
|
0ec04058cd | ||
|
|
293cf21c58 | ||
|
|
25f4cb2ee6 | ||
|
|
817e875cbf | ||
|
|
8d12042f39 | ||
|
|
f5a1bb875d | ||
|
|
3e5b8659eb | ||
|
|
79ed1290a6 | ||
|
|
51ef754387 | ||
|
|
58c477f916 | ||
|
|
4853ace155 | ||
|
|
de49bea774 | ||
|
|
5ec20296e4 | ||
|
|
e8389306ae | ||
|
|
3fc020c20a | ||
|
|
0db6dfee03 | ||
|
|
27227a8824 | ||
|
|
12ad0fddab | ||
|
|
e623b5ca1e | ||
|
|
359133b800 | ||
|
|
c47079e795 | ||
|
|
bf4ca6219a | ||
|
|
ae08f57928 | ||
|
|
ca990146e9 | ||
|
|
143a40a618 | ||
|
|
7c405706b4 | ||
|
|
e65ada3984 | ||
|
|
bb04677b0f | ||
|
|
7572bec674 | ||
|
|
1ee44a0acb | ||
|
|
8d4846f210 | ||
|
|
92f32b5c79 | ||
|
|
ca05ffe36e | ||
|
|
c586ca4d0e | ||
|
|
be495ab8e6 | ||
|
|
d2a6c2c200 | ||
|
|
f6e96dd783 | ||
|
|
765c071c89 | ||
|
|
3dfdad61df | ||
|
|
bbaaa6a9de | ||
|
|
ddd9d4b6e4 | ||
|
|
d0d06d414d | ||
|
|
b1e4cde2da | ||
|
|
9e48afb830 | ||
|
|
9db79856be | ||
|
|
5ead5d1cd6 | ||
|
|
7289e87a38 | ||
|
|
052469104f | ||
|
|
bff44ff466 | ||
|
|
57f98eff03 | ||
|
|
1eeb12fe1e | ||
|
|
c9876f4c66 | ||
|
|
4bd12e1aa3 | ||
|
|
d789b2e426 | ||
|
|
8d84a12333 | ||
|
|
ce740b1ff6 | ||
|
|
630c600929 | ||
|
|
960453fa22 | ||
|
|
e24d274bbc | ||
|
|
89dfb9140e | ||
|
|
d62c9fe842 |
@@ -1,2 +1 @@
|
||||
bin/
|
||||
dist/
|
||||
|
||||
60
.github/workflows/artifacts.yml
vendored
60
.github/workflows/artifacts.yml
vendored
@@ -1,60 +0,0 @@
|
||||
name: Publish Artifacts
|
||||
env:
|
||||
GO_VERSION: 1.18.4
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
jobs:
|
||||
publish-artifacts:
|
||||
if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/generate-artifacts')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code into the Go module directory
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache: true
|
||||
|
||||
- name: Build cross platform compose-plugin binaries
|
||||
run: make -f builder.Makefile cross
|
||||
|
||||
- name: Upload macos-amd64 binary
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: docker-compose-darwin-amd64
|
||||
path: ${{ github.workspace }}/bin/docker-compose-darwin-amd64
|
||||
|
||||
- name: Upload macos-arm64 binary
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: docker-compose-darwin-arm64
|
||||
path: ${{ github.workspace }}/bin/docker-compose-darwin-arm64
|
||||
|
||||
- name: Upload linux-amd64 binary
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: docker-compose-linux-amd64
|
||||
path: ${{ github.workspace }}/bin/docker-compose-linux-amd64
|
||||
|
||||
- name: Upload linux-ppc64le binary
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: docker-compose-linux-ppc64le
|
||||
path: ${{ github.workspace }}/bin/docker-compose-linux-ppc64le
|
||||
|
||||
- name: Upload windows-amd64 binary
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: docker-compose-windows-amd64.exe
|
||||
path: ${{ github.workspace }}/bin/docker-compose-windows-amd64.exe
|
||||
|
||||
- name: Update comment
|
||||
uses: peter-evans/create-or-update-comment@v1
|
||||
with:
|
||||
comment-id: ${{ github.event.comment.id }}
|
||||
body: |
|
||||
This PR can be tested using [binaries](https://github.com/docker/compose-cli/actions/runs/${{ github.run_id }}).
|
||||
reactions: eyes
|
||||
272
.github/workflows/ci.yml
vendored
272
.github/workflows/ci.yml
vendored
@@ -1,9 +1,15 @@
|
||||
name: Continuous integration
|
||||
name: ci
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- v2
|
||||
- 'v2'
|
||||
tags:
|
||||
- 'v*'
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
@@ -11,113 +17,209 @@ on:
|
||||
description: 'To run with tmate enter "debug_enabled"'
|
||||
required: false
|
||||
default: "false"
|
||||
|
||||
env:
|
||||
GO_VERSION: 1.18.4
|
||||
GO_VERSION: "1.18.5" # for non sandboxed e2e tests
|
||||
DESTDIR: "./bin"
|
||||
DOCKER_CLI_VERSION: "20.10.17"
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: Lint
|
||||
prepare:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.platforms.outputs.matrix }}
|
||||
steps:
|
||||
- name: Checkout code into the Go module directory
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache: true
|
||||
|
||||
- name: Validate go-mod, license headers and docs are up-to-date
|
||||
run: make validate
|
||||
|
||||
- name: Run golangci-lint
|
||||
env:
|
||||
BUILD_TAGS: e2e
|
||||
uses: golangci/golangci-lint-action@v2
|
||||
with:
|
||||
args: --timeout=180s
|
||||
|
||||
# only on main branch, costs too much for the gain on every PR
|
||||
validate-cross-build:
|
||||
name: Validate cross build
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/main'
|
||||
steps:
|
||||
- name: Checkout code into the Go module directory
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache: true
|
||||
|
||||
# Ensure we don't discover cross platform build issues at release time.
|
||||
# Time used to build linux here is gained back in the build for local E2E step
|
||||
- name: Build packages
|
||||
run: make -f builder.Makefile cross
|
||||
|
||||
build-plugin:
|
||||
name: Build and tests in plugin mode
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code into the Go module directory
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache: true
|
||||
|
||||
- name: Setup docker CLI
|
||||
-
|
||||
name: Create matrix
|
||||
id: platforms
|
||||
run: |
|
||||
curl https://download.docker.com/linux/static/stable/x86_64/docker-20.10.3.tgz | tar xz
|
||||
sudo cp ./docker/docker /usr/bin/ && rm -rf docker && docker version
|
||||
echo ::set-output name=matrix::$(docker buildx bake binary-cross --print | jq -cr '.target."binary-cross".platforms')
|
||||
-
|
||||
name: Show matrix
|
||||
run: |
|
||||
echo ${{ steps.platforms.outputs.matrix }}
|
||||
|
||||
- name: Test
|
||||
run: make -f builder.Makefile test
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target:
|
||||
- lint
|
||||
- validate-go-mod
|
||||
- validate-headers
|
||||
- validate-docs
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
-
|
||||
name: Run
|
||||
run: |
|
||||
make ${{ matrix.target }}
|
||||
|
||||
- name: Build for local E2E
|
||||
env:
|
||||
BUILD_TAGS: e2e
|
||||
run: make GIT_TAG=e2e-PR-${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }} -f builder.Makefile compose-plugin
|
||||
binary:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- prepare
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: ${{ fromJson(needs.prepare.outputs.matrix) }}
|
||||
steps:
|
||||
-
|
||||
name: Prepare
|
||||
run: |
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
-
|
||||
name: Build
|
||||
uses: docker/bake-action@v2
|
||||
with:
|
||||
targets: release
|
||||
set: |
|
||||
*.platform=${{ matrix.platform }}
|
||||
*.cache-from=type=gha,scope=binary-${{ env.PLATFORM_PAIR }}
|
||||
*.cache-to=type=gha,scope=binary-${{ env.PLATFORM_PAIR }},mode=max
|
||||
-
|
||||
name: Upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: compose
|
||||
path: ${{ env.DESTDIR }}/*
|
||||
if-no-files-found: error
|
||||
|
||||
- name: E2E Test in plugin mode
|
||||
run: make e2e-compose
|
||||
|
||||
build-standalone:
|
||||
name: Build and tests in standalone mode
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code into the Go module directory
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
-
|
||||
name: Test
|
||||
uses: docker/bake-action@v2
|
||||
with:
|
||||
targets: test
|
||||
set: |
|
||||
*.cache-from=type=gha,scope=test
|
||||
*.cache-to=type=gha,scope=test
|
||||
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
e2e:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DESTDIR: "./bin/build"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
mode:
|
||||
- plugin
|
||||
- standalone
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
-
|
||||
name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache: true
|
||||
|
||||
- name: Setup docker CLI
|
||||
-
|
||||
name: Setup docker CLI
|
||||
run: |
|
||||
curl https://download.docker.com/linux/static/stable/x86_64/docker-20.10.3.tgz | tar xz
|
||||
curl https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_CLI_VERSION}.tgz | tar xz
|
||||
sudo cp ./docker/docker /usr/bin/ && rm -rf docker && docker version
|
||||
|
||||
- name: Build for local E2E
|
||||
-
|
||||
name: Build
|
||||
uses: docker/bake-action@v2
|
||||
with:
|
||||
targets: binary
|
||||
set: |
|
||||
*.cache-from=type=gha,scope=binary-linux-amd64
|
||||
*.cache-from=type=gha,scope=binary-e2e-${{ matrix.mode }}
|
||||
*.cache-to=type=gha,scope=binary-e2e-${{ matrix.mode }},mode=max
|
||||
env:
|
||||
BUILD_TAGS: e2e
|
||||
run: make GIT_TAG=e2e-PR-${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }} -f builder.Makefile compose-plugin
|
||||
|
||||
- name: Setup tmate session
|
||||
uses: mxschmitt/action-tmate@v3
|
||||
-
|
||||
name: Setup tmate session
|
||||
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled }}
|
||||
uses: mxschmitt/action-tmate@8b4e4ac71822ed7e0ad5fb3d1c33483e9e8fb270 # v3.11
|
||||
with:
|
||||
limit-access-to-actor: true
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled }}
|
||||
|
||||
- name: E2E Test in standalone mode
|
||||
-
|
||||
name: Test plugin mode
|
||||
if: ${{ matrix.mode == 'plugin' }}
|
||||
run: |
|
||||
make e2e-compose
|
||||
-
|
||||
name: Test standalone mode
|
||||
if: ${{ matrix.mode == 'standalone' }}
|
||||
run: |
|
||||
rm -f /usr/local/bin/docker-compose
|
||||
cp bin/docker-compose /usr/local/bin
|
||||
cp bin/build/docker-compose /usr/local/bin
|
||||
make e2e-compose-standalone
|
||||
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- binary
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Download artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: compose
|
||||
path: ${{ env.DESTDIR }}
|
||||
-
|
||||
name: Create checksums
|
||||
working-directory: ${{ env.DESTDIR }}
|
||||
run: |
|
||||
find . -type f -print0 | sort -z | xargs -r0 shasum -a 256 -b | sed 's# \*\./# *#' > $RUNNER_TEMP/checksums.txt
|
||||
shasum -a 256 -U -c $RUNNER_TEMP/checksums.txt
|
||||
mv $RUNNER_TEMP/checksums.txt .
|
||||
cat checksums.txt | while read sum file; do echo "$sum $file" > ${file#\*}.sha256; done
|
||||
-
|
||||
name: License
|
||||
run: cp packaging/* ${{ env.DESTDIR }}/
|
||||
-
|
||||
name: List artifacts
|
||||
run: |
|
||||
tree -nh ${{ env.DESTDIR }}
|
||||
-
|
||||
name: Check artifacts
|
||||
run: |
|
||||
find ${{ env.DESTDIR }} -type f -exec file -e ascii -- {} +
|
||||
-
|
||||
name: GitHub Release
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
uses: ncipollo/release-action@58ae73b360456532aafd58ee170c045abbeaee37 # v1.10.0
|
||||
with:
|
||||
artifacts: ${{ env.DESTDIR }}/*
|
||||
generateReleaseNotes: true
|
||||
draft: true
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
11
.github/workflows/pr-closed.yml
vendored
11
.github/workflows/pr-closed.yml
vendored
@@ -1,11 +0,0 @@
|
||||
name: PR cleanup
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
jobs:
|
||||
delete_pr_artifacts:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: stefanluptak/delete-old-pr-artifacts@v1
|
||||
with:
|
||||
workflow_filename: ci.yaml
|
||||
45
.github/workflows/release.yaml
vendored
45
.github/workflows/release.yaml
vendored
@@ -1,45 +0,0 @@
|
||||
name: Releaser
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: "Release Tag"
|
||||
required: true
|
||||
env:
|
||||
GO_VERSION: 1.18.4
|
||||
jobs:
|
||||
upload-release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code into the Go module directory
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache: true
|
||||
|
||||
- name: Setup docker CLI
|
||||
run: |
|
||||
curl https://download.docker.com/linux/static/stable/x86_64/docker-20.10.3.tgz | tar xz
|
||||
sudo cp ./docker/docker /usr/bin/ && rm -rf docker && docker version
|
||||
|
||||
- name: Build
|
||||
run: make GIT_TAG=${{ github.event.inputs.tag }} -f builder.Makefile cross
|
||||
|
||||
- name: Compute checksums
|
||||
run: cd bin; for f in *; do shasum --binary --algorithm 256 $f | tee -a checksums.txt > $f.sha256; done
|
||||
|
||||
- name: License
|
||||
run: cp packaging/* bin/
|
||||
|
||||
- uses: ncipollo/release-action@v1
|
||||
with:
|
||||
artifacts: "bin/*"
|
||||
generateReleaseNotes: true
|
||||
draft: true
|
||||
commit: "v2"
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
tag: ${{ github.event.inputs.tag }}
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,2 @@
|
||||
bin/
|
||||
dist/
|
||||
/.vscode/
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
run:
|
||||
concurrency: 2
|
||||
timeout: 10m
|
||||
linters:
|
||||
enable-all: false
|
||||
disable-all: true
|
||||
@@ -18,6 +19,7 @@ linters:
|
||||
- lll
|
||||
- misspell
|
||||
- nakedret
|
||||
- nolintlint
|
||||
- staticcheck
|
||||
- structcheck
|
||||
- typecheck
|
||||
@@ -27,7 +29,7 @@ linters:
|
||||
- varcheck
|
||||
linters-settings:
|
||||
depguard:
|
||||
list-type: blacklist
|
||||
list-type: denylist
|
||||
include-go-root: true
|
||||
packages:
|
||||
# The io/ioutil package has been deprecated.
|
||||
|
||||
@@ -19,7 +19,8 @@ Once you have the prerequisites installed, you can build the CLI using:
|
||||
make
|
||||
```
|
||||
|
||||
This will output a `docker-compose` CLI plugin for your host machine in `./bin`.
|
||||
This will output a `docker-compose` CLI plugin for your host machine in
|
||||
`./bin/build`.
|
||||
|
||||
You can statically cross compile the CLI for Windows, macOS, and Linux using the
|
||||
`cross` target.
|
||||
@@ -38,7 +39,6 @@ If you need to update a golden file simply do `go test ./... -test.update-golden
|
||||
To run e2e tests, the Compose CLI binary need to be build. All the commands to run e2e tests propose a version
|
||||
with the prefix `build-and-e2e` to first build the CLI before executing tests.
|
||||
|
||||
|
||||
Note that this requires a local Docker Engine to be running.
|
||||
|
||||
#### Whole end-to-end tests suite
|
||||
@@ -76,6 +76,7 @@ make e2e-compose-standalone
|
||||
```
|
||||
|
||||
Or if you need to build the CLI, run:
|
||||
|
||||
```console
|
||||
make build-and-e2e-compose-standalone
|
||||
```
|
||||
|
||||
@@ -124,9 +124,10 @@ Fork the repository and make changes on your fork in a feature branch:
|
||||
issue.
|
||||
|
||||
Submit unit tests for your changes. Go has a great test framework built in; use
|
||||
it! Take a look at existing tests for inspiration. [Run the full test
|
||||
suite](README.md) on your branch before
|
||||
submitting a pull request.
|
||||
it! Take a look at existing tests for inspiration. Also end-to-end tests are
|
||||
available. Run the full test suite, both unit tests and e2e tests on your
|
||||
branch before submitting a pull request. See [BUILDING.md](BUILDING.md) for
|
||||
instructions to build and run tests.
|
||||
|
||||
Write clean code. Universally formatted code promotes ease of writing, reading,
|
||||
and maintenance. Always run `gofmt -s -w file.go` on each changed file before
|
||||
|
||||
230
Dockerfile
230
Dockerfile
@@ -1,4 +1,4 @@
|
||||
# syntax=docker/dockerfile:1.2
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
|
||||
# Copyright 2020 Docker Compose CLI authors
|
||||
@@ -15,98 +15,166 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
ARG GO_VERSION=1.18.4-alpine
|
||||
ARG GOLANGCI_LINT_VERSION=v1.46.2-alpine
|
||||
ARG PROTOC_GEN_GO_VERSION=v1.4.3
|
||||
ARG GO_VERSION=1.18.5
|
||||
ARG XX_VERSION=1.1.2
|
||||
ARG GOLANGCI_LINT_VERSION=v1.47.3
|
||||
ARG ADDLICENSE_VERSION=v1.0.0
|
||||
|
||||
FROM --platform=${BUILDPLATFORM} golangci/golangci-lint:${GOLANGCI_LINT_VERSION} AS local-golangci-lint
|
||||
ARG BUILD_TAGS="e2e,kube"
|
||||
ARG DOCS_FORMATS="md,yaml"
|
||||
ARG LICENSE_FILES=".*\(Dockerfile\|Makefile\|\.go\|\.hcl\|\.sh\)"
|
||||
|
||||
FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS base
|
||||
WORKDIR /compose-cli
|
||||
RUN apk add --no-cache -vv \
|
||||
git \
|
||||
docker \
|
||||
make \
|
||||
protoc \
|
||||
protobuf-dev
|
||||
# xx is a helper for cross-compilation
|
||||
FROM --platform=${BUILDPLATFORM} tonistiigi/xx:${XX_VERSION} AS xx
|
||||
|
||||
FROM golangci/golangci-lint:${GOLANGCI_LINT_VERSION}-alpine AS golangci-lint
|
||||
FROM ghcr.io/google/addlicense:${ADDLICENSE_VERSION} AS addlicense
|
||||
|
||||
FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION}-alpine AS base
|
||||
COPY --from=xx / /
|
||||
RUN apk add --no-cache \
|
||||
docker \
|
||||
file \
|
||||
git \
|
||||
make \
|
||||
protoc \
|
||||
protobuf-dev
|
||||
WORKDIR /src
|
||||
ENV CGO_ENABLED=0
|
||||
|
||||
FROM base AS build-base
|
||||
COPY go.* .
|
||||
RUN --mount=type=cache,target=/go/pkg/mod \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
go mod download
|
||||
|
||||
FROM base AS lint
|
||||
ENV CGO_ENABLED=0
|
||||
COPY --from=local-golangci-lint /usr/bin/golangci-lint /usr/bin/golangci-lint
|
||||
ARG BUILD_TAGS
|
||||
ARG GIT_TAG
|
||||
RUN --mount=target=. \
|
||||
FROM build-base AS vendored
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
--mount=type=cache,target=/root/.cache/golangci-lint \
|
||||
BUILD_TAGS=${BUILD_TAGS} \
|
||||
GIT_TAG=${GIT_TAG} \
|
||||
make -f builder.Makefile lint
|
||||
go mod tidy && mkdir /out && cp go.mod go.sum /out
|
||||
|
||||
FROM base AS make-compose-plugin
|
||||
ENV CGO_ENABLED=0
|
||||
FROM scratch AS vendor-update
|
||||
COPY --from=vendored /out /
|
||||
|
||||
FROM vendored AS vendor-validate
|
||||
RUN --mount=type=bind,target=.,rw <<EOT
|
||||
set -e
|
||||
git add -A
|
||||
cp -rf /out/* .
|
||||
diff=$(git status --porcelain -- go.mod go.sum)
|
||||
if [ -n "$diff" ]; then
|
||||
echo >&2 'ERROR: Vendor result differs. Please vendor your package with "make go-mod-tidy"'
|
||||
echo "$diff"
|
||||
exit 1
|
||||
fi
|
||||
EOT
|
||||
|
||||
FROM build-base AS build
|
||||
ARG BUILD_TAGS
|
||||
ARG TARGETPLATFORM
|
||||
RUN xx-go --wrap
|
||||
RUN --mount=type=bind,target=. \
|
||||
--mount=type=cache,target=/root/.cache \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
make build GO_BUILDTAGS="$BUILD_TAGS" DESTDIR=/usr/bin && \
|
||||
xx-verify --static /usr/bin/docker-compose
|
||||
|
||||
FROM build-base AS lint
|
||||
ARG BUILD_TAGS
|
||||
RUN --mount=type=bind,target=. \
|
||||
--mount=type=cache,target=/root/.cache \
|
||||
--mount=from=golangci-lint,source=/usr/bin/golangci-lint,target=/usr/bin/golangci-lint \
|
||||
golangci-lint run --build-tags "$BUILD_TAGS" ./...
|
||||
|
||||
FROM build-base AS test
|
||||
ARG CGO_ENABLED=0
|
||||
ARG BUILD_TAGS
|
||||
RUN --mount=type=bind,target=. \
|
||||
--mount=type=cache,target=/root/.cache \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
go test -tags "$BUILD_TAGS" -v -coverprofile=/tmp/coverage.txt -covermode=atomic $(go list $(TAGS) ./... | grep -vE 'e2e') && \
|
||||
go tool cover -func=/tmp/coverage.txt
|
||||
|
||||
FROM scratch AS test-coverage
|
||||
COPY --from=test /tmp/coverage.txt /coverage.txt
|
||||
|
||||
FROM base AS license-set
|
||||
ARG LICENSE_FILES
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=from=addlicense,source=/app/addlicense,target=/usr/bin/addlicense \
|
||||
find . -regex "${LICENSE_FILES}" | xargs addlicense -c 'Docker Compose CLI' -l apache && \
|
||||
mkdir /out && \
|
||||
find . -regex "${LICENSE_FILES}" | cpio -pdm /out
|
||||
|
||||
FROM scratch AS license-update
|
||||
COPY --from=set /out /
|
||||
|
||||
FROM base AS license-validate
|
||||
ARG LICENSE_FILES
|
||||
RUN --mount=type=bind,target=. \
|
||||
--mount=from=addlicense,source=/app/addlicense,target=/usr/bin/addlicense \
|
||||
find . -regex "${LICENSE_FILES}" | xargs addlicense -check -c 'Docker Compose CLI' -l apache -ignore validate -ignore testdata -ignore resolvepath -v
|
||||
|
||||
FROM base AS docsgen
|
||||
WORKDIR /src
|
||||
RUN --mount=target=. \
|
||||
--mount=target=/root/.cache,type=cache \
|
||||
go build -o /out/docsgen ./docs/yaml/main/generate.go
|
||||
|
||||
FROM --platform=${BUILDPLATFORM} alpine AS docs-build
|
||||
RUN apk add --no-cache rsync git
|
||||
WORKDIR /src
|
||||
COPY --from=docsgen /out/docsgen /usr/bin
|
||||
ARG DOCS_FORMATS
|
||||
RUN --mount=target=/context \
|
||||
--mount=target=.,type=tmpfs <<EOT
|
||||
set -e
|
||||
rsync -a /context/. .
|
||||
docsgen --formats "$DOCS_FORMATS" --source "docs/reference"
|
||||
mkdir /out
|
||||
cp -r docs/reference /out
|
||||
EOT
|
||||
|
||||
FROM scratch AS docs-update
|
||||
COPY --from=docs-build /out /out
|
||||
|
||||
FROM docs-build AS docs-validate
|
||||
RUN --mount=target=/context \
|
||||
--mount=target=.,type=tmpfs <<EOT
|
||||
set -e
|
||||
rsync -a /context/. .
|
||||
git add -A
|
||||
rm -rf docs/reference/*
|
||||
cp -rf /out/* ./docs/
|
||||
if [ -n "$(git status --porcelain -- docs/reference)" ]; then
|
||||
echo >&2 'ERROR: Docs result differs. Please update with "make docs"'
|
||||
git status --porcelain -- docs/reference
|
||||
exit 1
|
||||
fi
|
||||
EOT
|
||||
|
||||
FROM scratch AS binary-unix
|
||||
COPY --link --from=build /usr/bin/docker-compose /
|
||||
FROM binary-unix AS binary-darwin
|
||||
FROM binary-unix AS binary-linux
|
||||
FROM scratch AS binary-windows
|
||||
COPY --link --from=build /usr/bin/docker-compose /docker-compose.exe
|
||||
FROM binary-$TARGETOS AS binary
|
||||
|
||||
FROM --platform=$BUILDPLATFORM alpine AS releaser
|
||||
WORKDIR /work
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
ARG BUILD_TAGS
|
||||
ARG GIT_TAG
|
||||
RUN --mount=target=. \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
GOOS=${TARGETOS} \
|
||||
GOARCH=${TARGETARCH} \
|
||||
BUILD_TAGS=${BUILD_TAGS} \
|
||||
GIT_TAG=${GIT_TAG} \
|
||||
make COMPOSE_BINARY=/out/docker-compose -f builder.Makefile compose-plugin
|
||||
ARG TARGETVARIANT
|
||||
RUN --mount=from=binary \
|
||||
mkdir -p /out && \
|
||||
# TODO: should just use standard arch
|
||||
TARGETARCH=$([ "$TARGETARCH" = "amd64" ] && echo "x86_64" || echo "$TARGETARCH"); \
|
||||
TARGETARCH=$([ "$TARGETARCH" = "arm64" ] && echo "aarch64" || echo "$TARGETARCH"); \
|
||||
cp docker-compose* "/out/docker-compose-${TARGETOS}-${TARGETARCH}${TARGETVARIANT}$(ls docker-compose* | sed -e 's/^docker-compose//')"
|
||||
|
||||
FROM base AS make-cross
|
||||
ARG BUILD_TAGS
|
||||
ARG GIT_TAG
|
||||
RUN --mount=target=. \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
BUILD_TAGS=${BUILD_TAGS} \
|
||||
GIT_TAG=${GIT_TAG} \
|
||||
make COMPOSE_BINARY=/out/docker-compose -f builder.Makefile cross
|
||||
|
||||
FROM scratch AS compose-plugin
|
||||
COPY --from=make-compose-plugin /out/* .
|
||||
|
||||
FROM scratch AS cross
|
||||
COPY --from=make-cross /out/* .
|
||||
|
||||
FROM base AS test
|
||||
ENV CGO_ENABLED=0
|
||||
ARG BUILD_TAGS
|
||||
ARG GIT_TAG
|
||||
RUN --mount=target=. \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
BUILD_TAGS=${BUILD_TAGS} \
|
||||
GIT_TAG=${GIT_TAG} \
|
||||
make -f builder.Makefile test
|
||||
|
||||
FROM base AS check-license-headers
|
||||
RUN go install github.com/google/addlicense@latest
|
||||
RUN --mount=target=. \
|
||||
make -f builder.Makefile check-license-headers
|
||||
|
||||
FROM base AS make-go-mod-tidy
|
||||
COPY . .
|
||||
RUN --mount=type=cache,target=/go/pkg/mod \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
go mod tidy
|
||||
|
||||
FROM scratch AS go-mod-tidy
|
||||
COPY --from=make-go-mod-tidy /compose-cli/go.mod .
|
||||
COPY --from=make-go-mod-tidy /compose-cli/go.sum .
|
||||
|
||||
FROM base AS check-go-mod
|
||||
COPY . .
|
||||
RUN make -f builder.Makefile check-go-mod
|
||||
FROM scratch AS release
|
||||
COPY --from=releaser /out/ /
|
||||
|
||||
# docs-reference is a target used as remote context to update docs on release
|
||||
# with latest changes on docker.github.io.
|
||||
|
||||
74
Makefile
74
Makefile
@@ -12,7 +12,11 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
export DOCKER_BUILDKIT=1
|
||||
PKG := github.com/docker/compose/v2
|
||||
VERSION ?= $(shell git describe --match 'v[0-9]*' --dirty='.m' --always --tags)
|
||||
|
||||
GO_LDFLAGS ?= -s -w -X ${PKG}/internal.Version=${VERSION}
|
||||
GO_BUILDTAGS ?= e2e,kube
|
||||
|
||||
UNAME_S := $(shell uname -s)
|
||||
ifeq ($(UNAME_S),Linux)
|
||||
@@ -22,8 +26,6 @@ ifeq ($(UNAME_S),Darwin)
|
||||
MOBY_DOCKER=/Applications/Docker.app/Contents/Resources/bin/docker
|
||||
endif
|
||||
|
||||
BINARY_FOLDER=$(shell pwd)/bin
|
||||
GIT_TAG?=$(shell git describe --tags --match "v[0-9]*")
|
||||
TEST_FLAGS?=
|
||||
E2E_TEST?=
|
||||
ifeq ($(E2E_TEST),)
|
||||
@@ -31,15 +33,23 @@ else
|
||||
TEST_FLAGS=-run $(E2E_TEST)
|
||||
endif
|
||||
|
||||
all: compose-plugin
|
||||
BUILDX_CMD ?= docker buildx
|
||||
DESTDIR ?= ./bin/build
|
||||
|
||||
.PHONY: compose-plugin
|
||||
compose-plugin: ## Compile the compose cli-plugin
|
||||
@docker build . --target compose-plugin \
|
||||
--platform local \
|
||||
--build-arg BUILD_TAGS=e2e,kube \
|
||||
--build-arg GIT_TAG=$(GIT_TAG) \
|
||||
--output ./bin
|
||||
all: build
|
||||
|
||||
.PHONY: build ## Build the compose cli-plugin
|
||||
build:
|
||||
CGO_ENABLED=0 GO111MODULE=on go build -trimpath -tags "$(GO_BUILDTAGS)" -ldflags "$(GO_LDFLAGS)" -o "$(DESTDIR)/docker-compose" ./cmd
|
||||
|
||||
.PHONY: binary
|
||||
binary:
|
||||
$(BUILDX_CMD) bake binary
|
||||
|
||||
.PHONY: install
|
||||
install: binary
|
||||
mkdir -p ~/.docker/cli-plugins
|
||||
install bin/build/docker-compose ~/.docker/cli-plugins/docker-compose
|
||||
|
||||
.PHONY: e2e-compose
|
||||
e2e-compose: ## Run end to end local tests in plugin mode. Set E2E_TEST=TestName to run a single test
|
||||
@@ -52,10 +62,10 @@ e2e-compose-standalone: ## Run End to end local tests in standalone mode. Set E2
|
||||
go test $(TEST_FLAGS) -v -count=1 -parallel=1 --tags=standalone ./pkg/e2e
|
||||
|
||||
.PHONY: build-and-e2e-compose
|
||||
build-and-e2e-compose: compose-plugin e2e-compose ## Compile the compose cli-plugin and run end to end local tests in plugin mode. Set E2E_TEST=TestName to run a single test
|
||||
build-and-e2e-compose: build e2e-compose ## Compile the compose cli-plugin and run end to end local tests in plugin mode. Set E2E_TEST=TestName to run a single test
|
||||
|
||||
.PHONY: build-and-e2e-compose-standalone
|
||||
build-and-e2e-compose-standalone: compose-plugin e2e-compose-standalone ## Compile the compose cli-plugin and run End to end local tests in standalone mode. Set E2E_TEST=TestName to run a single test
|
||||
build-and-e2e-compose-standalone: build e2e-compose-standalone ## Compile the compose cli-plugin and run End to end local tests in standalone mode. Set E2E_TEST=TestName to run a single test
|
||||
|
||||
.PHONY: mocks
|
||||
mocks:
|
||||
@@ -67,49 +77,35 @@ mocks:
|
||||
e2e: e2e-compose e2e-compose-standalone ## Run end to end local tests in both modes. Set E2E_TEST=TestName to run a single test
|
||||
|
||||
.PHONY: build-and-e2e
|
||||
build-and-e2e: compose-plugin e2e-compose e2e-compose-standalone ## Compile the compose cli-plugin and run end to end local tests in both modes. Set E2E_TEST=TestName to run a single test
|
||||
build-and-e2e: build e2e-compose e2e-compose-standalone ## Compile the compose cli-plugin and run end to end local tests in both modes. Set E2E_TEST=TestName to run a single test
|
||||
|
||||
.PHONY: cross
|
||||
cross: ## Compile the CLI for linux, darwin and windows
|
||||
@docker build . --target cross \
|
||||
--build-arg BUILD_TAGS \
|
||||
--build-arg GIT_TAG=$(GIT_TAG) \
|
||||
--output ./bin \
|
||||
$(BUILDX_CMD) bake binary-cross
|
||||
|
||||
.PHONY: test
|
||||
test: ## Run unit tests
|
||||
@docker build --progress=plain . \
|
||||
--build-arg BUILD_TAGS=kube \
|
||||
--build-arg GIT_TAG=$(GIT_TAG) \
|
||||
--target test
|
||||
$(BUILDX_CMD) bake test
|
||||
|
||||
.PHONY: cache-clear
|
||||
cache-clear: ## Clear the builder cache
|
||||
@docker builder prune --force --filter type=exec.cachemount --filter=unused-for=24h
|
||||
$(BUILDX_CMD) prune --force --filter type=exec.cachemount --filter=unused-for=24h
|
||||
|
||||
.PHONY: lint
|
||||
lint: ## run linter(s)
|
||||
@docker build . \
|
||||
--build-arg BUILD_TAGS=kube,e2e \
|
||||
--build-arg GIT_TAG=$(GIT_TAG) \
|
||||
--target lint
|
||||
$(BUILDX_CMD) bake lint
|
||||
|
||||
.PHONY: docs
|
||||
docs: ## generate documentation
|
||||
$(eval $@_TMP_OUT := $(shell mktemp -d -t dockercli-output.XXXXXXXXXX))
|
||||
docker build . \
|
||||
--output type=local,dest=$($@_TMP_OUT) \
|
||||
-f ./docs/docs.Dockerfile \
|
||||
--target update
|
||||
$(eval $@_TMP_OUT := $(shell mktemp -d -t compose-output.XXXXXXXXXX))
|
||||
$(BUILDX_CMD) bake --set "*.output=type=local,dest=$($@_TMP_OUT)" docs-update
|
||||
rm -rf ./docs/internal
|
||||
cp -R "$($@_TMP_OUT)"/out/* ./docs/
|
||||
rm -rf "$($@_TMP_OUT)"/*
|
||||
|
||||
.PHONY: validate-docs
|
||||
validate-docs: ## validate the doc does not change
|
||||
@docker build . \
|
||||
-f ./docs/docs.Dockerfile \
|
||||
--target validate
|
||||
$(BUILDX_CMD) bake docs-validate
|
||||
|
||||
.PHONY: check-dependencies
|
||||
check-dependencies: ## check dependency updates
|
||||
@@ -117,19 +113,19 @@ check-dependencies: ## check dependency updates
|
||||
|
||||
.PHONY: validate-headers
|
||||
validate-headers: ## Check license header for all files
|
||||
@docker build . --target check-license-headers
|
||||
$(BUILDX_CMD) bake license-validate
|
||||
|
||||
.PHONY: go-mod-tidy
|
||||
go-mod-tidy: ## Run go mod tidy in a container and output resulting go.mod and go.sum
|
||||
@docker build . --target go-mod-tidy --output .
|
||||
$(BUILDX_CMD) bake vendor-update
|
||||
|
||||
.PHONY: validate-go-mod
|
||||
validate-go-mod: ## Validate go.mod and go.sum are up-to-date
|
||||
@docker build . --target check-go-mod
|
||||
$(BUILDX_CMD) bake vendor-validate
|
||||
|
||||
validate: validate-go-mod validate-headers validate-docs ## Validate sources
|
||||
|
||||
pre-commit: validate check-dependencies lint compose-plugin test e2e-compose
|
||||
pre-commit: validate check-dependencies lint build test e2e-compose
|
||||
|
||||
help: ## Show help
|
||||
@echo Please specify a build target. The choices are:
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# Docker Compose v2
|
||||
|
||||
[](https://github.com/docker/compose/actions)
|
||||
[](https://github.com/docker/compose/releases/latest)
|
||||
[](https://pkg.go.dev/github.com/docker/compose/v2)
|
||||
[](https://github.com/docker/compose/actions?query=workflow%3Aci)
|
||||
[](https://goreportcard.com/report/github.com/docker/compose/v2)
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
# Copyright 2020 Docker Compose CLI authors
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
GOOS?=$(shell go env GOOS)
|
||||
GOARCH?=$(shell go env GOARCH)
|
||||
|
||||
PKG_NAME := github.com/docker/compose/v2
|
||||
|
||||
EXTENSION:=
|
||||
ifeq ($(GOOS),windows)
|
||||
EXTENSION:=.exe
|
||||
endif
|
||||
|
||||
STATIC_FLAGS=CGO_ENABLED=0
|
||||
|
||||
GIT_TAG?=$(shell git describe --tags --match "v[0-9]*")
|
||||
|
||||
LDFLAGS="-s -w -X $(PKG_NAME)/internal.Version=${GIT_TAG}"
|
||||
GO_BUILD=$(STATIC_FLAGS) go build -trimpath -ldflags=$(LDFLAGS)
|
||||
|
||||
COMPOSE_BINARY?=bin/docker-compose
|
||||
COMPOSE_BINARY_WITH_EXTENSION=$(COMPOSE_BINARY)$(EXTENSION)
|
||||
|
||||
WORK_DIR:=$(shell mktemp -d)
|
||||
|
||||
TAGS:=
|
||||
ifdef BUILD_TAGS
|
||||
TAGS=-tags $(BUILD_TAGS)
|
||||
LINT_TAGS=--build-tags $(BUILD_TAGS)
|
||||
endif
|
||||
|
||||
.PHONY: compose-plugin
|
||||
compose-plugin:
|
||||
GOOS=${GOOS} GOARCH=${GOARCH} $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY_WITH_EXTENSION) ./cmd
|
||||
|
||||
.PHONY: cross
|
||||
cross:
|
||||
GOOS=linux GOARCH=amd64 $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-linux-x86_64 ./cmd
|
||||
GOOS=linux GOARCH=ppc64le $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-linux-ppc64le ./cmd
|
||||
GOOS=linux GOARCH=arm64 $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-linux-aarch64 ./cmd
|
||||
GOOS=linux GOARM=6 GOARCH=arm $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-linux-armv6 ./cmd
|
||||
GOOS=linux GOARM=7 GOARCH=arm $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-linux-armv7 ./cmd
|
||||
GOOS=linux GOARCH=s390x $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-linux-s390x ./cmd
|
||||
GOOS=darwin GOARCH=amd64 $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-darwin-x86_64 ./cmd
|
||||
GOOS=darwin GOARCH=arm64 $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-darwin-aarch64 ./cmd
|
||||
GOOS=windows GOARCH=amd64 $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-windows-x86_64.exe ./cmd
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
go test $(TAGS) -cover $(shell go list $(TAGS) ./... | grep -vE 'e2e')
|
||||
|
||||
.PHONY: lint
|
||||
lint:
|
||||
golangci-lint run $(LINT_TAGS) --timeout 10m0s ./...
|
||||
|
||||
.PHONY: check-license-headers
|
||||
check-license-headers:
|
||||
./scripts/validate/fileheader
|
||||
|
||||
.PHONY: check-go-mod
|
||||
check-go-mod:
|
||||
./scripts/validate/check-go-mod
|
||||
@@ -77,7 +77,7 @@ func buildCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
projectOptions: p,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "build [SERVICE...]",
|
||||
Use: "build [OPTIONS] [SERVICE...]",
|
||||
Short: "Build or rebuild services",
|
||||
PreRunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
if opts.memory != "" {
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
"github.com/compose-spec/compose-go/cli"
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
composegoutils "github.com/compose-spec/compose-go/utils"
|
||||
"github.com/docker/buildx/util/logutil"
|
||||
dockercli "github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli-plugins/manager"
|
||||
"github.com/docker/cli/cli/command"
|
||||
@@ -136,6 +137,24 @@ func (o *projectOptions) addProjectFlags(f *pflag.FlagSet) {
|
||||
_ = f.MarkHidden("workdir")
|
||||
}
|
||||
|
||||
func (o *projectOptions) projectOrName() (*types.Project, string, error) {
|
||||
name := o.ProjectName
|
||||
var project *types.Project
|
||||
if o.ProjectName == "" {
|
||||
p, err := o.toProject(nil)
|
||||
if err != nil {
|
||||
envProjectName := os.Getenv("COMPOSE_PROJECT_NAME")
|
||||
if envProjectName != "" {
|
||||
return nil, envProjectName, nil
|
||||
}
|
||||
return nil, "", err
|
||||
}
|
||||
project = p
|
||||
name = p.Name
|
||||
}
|
||||
return project, name, nil
|
||||
}
|
||||
|
||||
func (o *projectOptions) toProjectName() (string, error) {
|
||||
if o.ProjectName != "" {
|
||||
return o.ProjectName, nil
|
||||
@@ -232,6 +251,16 @@ func RunningAsStandalone() bool {
|
||||
|
||||
// RootCommand returns the compose command with its child commands
|
||||
func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command {
|
||||
// filter out useless commandConn.CloseWrite warning message that can occur
|
||||
// when using a remote context that is unreachable: "commandConn.CloseWrite: commandconn: failed to wait: signal: killed"
|
||||
// https://github.com/docker/cli/blob/e1f24d3c93df6752d3c27c8d61d18260f141310c/cli/connhelper/commandconn/commandconn.go#L203-L215
|
||||
logrus.AddHook(logutil.NewFilter([]logrus.Level{
|
||||
logrus.WarnLevel,
|
||||
},
|
||||
"commandConn.CloseWrite:",
|
||||
"commandConn.CloseRead:",
|
||||
))
|
||||
|
||||
opts := projectOptions{}
|
||||
var (
|
||||
ansi string
|
||||
@@ -354,8 +383,10 @@ func setEnvWithDotEnv(prjOpts *projectOptions) error {
|
||||
return err
|
||||
}
|
||||
for k, v := range envFromFile {
|
||||
if err := os.Setenv(k, v); err != nil { // overwrite the process env with merged OS + env file results
|
||||
return err
|
||||
if _, ok := os.LookupEnv(k); !ok { // Precedence to OS Env
|
||||
if err := os.Setenv(k, v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -58,7 +58,7 @@ func convertCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Aliases: []string{"config"},
|
||||
Use: "convert SERVICES",
|
||||
Use: "convert [OPTIONS] [SERVICE...]",
|
||||
Short: "Converts the compose file to platform's canonical format",
|
||||
PreRunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
if opts.quiet {
|
||||
|
||||
@@ -31,6 +31,7 @@ type createOptions struct {
|
||||
Build bool
|
||||
noBuild bool
|
||||
Pull string
|
||||
pullChanged bool
|
||||
removeOrphans bool
|
||||
ignoreOrphans bool
|
||||
forceRecreate bool
|
||||
@@ -45,9 +46,10 @@ type createOptions struct {
|
||||
func createCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
opts := createOptions{}
|
||||
cmd := &cobra.Command{
|
||||
Use: "create [SERVICE...]",
|
||||
Use: "create [OPTIONS] [SERVICE...]",
|
||||
Short: "Creates containers for a service.",
|
||||
PreRunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
|
||||
opts.pullChanged = cmd.Flags().Changed("pull")
|
||||
if opts.Build && opts.noBuild {
|
||||
return fmt.Errorf("--build and --no-build are incompatible")
|
||||
}
|
||||
@@ -108,7 +110,7 @@ func (opts createOptions) GetTimeout() *time.Duration {
|
||||
}
|
||||
|
||||
func (opts createOptions) Apply(project *types.Project) {
|
||||
if opts.Pull != "" {
|
||||
if opts.pullChanged {
|
||||
for i, service := range project.Services {
|
||||
service.PullPolicy = opts.Pull
|
||||
project.Services[i] = service
|
||||
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/docker/compose/v2/pkg/utils"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -45,7 +44,7 @@ func downCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
projectOptions: p,
|
||||
}
|
||||
downCmd := &cobra.Command{
|
||||
Use: "down",
|
||||
Use: "down [OPTIONS]",
|
||||
Short: "Stop and remove containers, networks",
|
||||
PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
|
||||
opts.timeChanged = cmd.Flags().Changed("timeout")
|
||||
@@ -66,7 +65,7 @@ func downCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
removeOrphans := utils.StringToBool(os.Getenv("COMPOSE_REMOVE_ORPHANS"))
|
||||
flags.BoolVar(&opts.removeOrphans, "remove-orphans", removeOrphans, "Remove containers for services not defined in the Compose file.")
|
||||
flags.IntVarP(&opts.timeout, "timeout", "t", 10, "Specify a shutdown timeout in seconds")
|
||||
flags.BoolVarP(&opts.volumes, "volumes", "v", false, " Remove named volumes declared in the `volumes` section of the Compose file and anonymous volumes attached to containers.")
|
||||
flags.BoolVarP(&opts.volumes, "volumes", "v", false, "Remove named volumes declared in the `volumes` section of the Compose file and anonymous volumes attached to containers.")
|
||||
flags.StringVar(&opts.images, "rmi", "", `Remove images used by services. "local" remove only images that don't have a custom tag ("local"|"all")`)
|
||||
flags.SetNormalizeFunc(func(f *pflag.FlagSet, name string) pflag.NormalizedName {
|
||||
if name == "volume" {
|
||||
@@ -79,15 +78,9 @@ func downCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
}
|
||||
|
||||
func runDown(ctx context.Context, backend api.Service, opts downOptions) error {
|
||||
name := opts.ProjectName
|
||||
var project *types.Project
|
||||
if opts.ProjectName == "" {
|
||||
p, err := opts.toProject(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
project = p
|
||||
name = p.Name
|
||||
project, name, err := opts.projectOrName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var timeout *time.Duration
|
||||
|
||||
@@ -38,7 +38,7 @@ func eventsCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
},
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "events [options] [--] [SERVICE...]",
|
||||
Use: "events [OPTIONS] [SERVICE...]",
|
||||
Short: "Receive real time events from containers.",
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runEvents(ctx, backend, opts, args)
|
||||
@@ -51,12 +51,12 @@ func eventsCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
}
|
||||
|
||||
func runEvents(ctx context.Context, backend api.Service, opts eventsOpts, services []string) error {
|
||||
project, err := opts.toProjectName()
|
||||
name, err := opts.toProjectName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return backend.Events(ctx, project, api.EventsOptions{
|
||||
return backend.Events(ctx, name, api.EventsOptions{
|
||||
Services: services,
|
||||
Consumer: func(event api.Event) error {
|
||||
if opts.json {
|
||||
|
||||
@@ -50,7 +50,7 @@ func execCommand(p *projectOptions, dockerCli command.Cli, backend api.Service)
|
||||
},
|
||||
}
|
||||
runCmd := &cobra.Command{
|
||||
Use: "exec [options] [-e KEY=VAL...] [--] SERVICE COMMAND [ARGS...]",
|
||||
Use: "exec [OPTIONS] SERVICE COMMAND [ARGS...]",
|
||||
Short: "Execute a command in a running container.",
|
||||
Args: cobra.MinimumNArgs(2),
|
||||
PreRunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
|
||||
@@ -43,7 +43,7 @@ func imagesCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
projectOptions: p,
|
||||
}
|
||||
imgCmd := &cobra.Command{
|
||||
Use: "images [SERVICE...]",
|
||||
Use: "images [OPTIONS] [SERVICE...]",
|
||||
Short: "List images used by the created containers",
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runImages(ctx, backend, opts, args)
|
||||
|
||||
@@ -18,15 +18,18 @@ package compose
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/docker/compose/v2/pkg/utils"
|
||||
)
|
||||
|
||||
type killOptions struct {
|
||||
*projectOptions
|
||||
signal string
|
||||
removeOrphans bool
|
||||
signal string
|
||||
}
|
||||
|
||||
func killCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
@@ -34,7 +37,7 @@ func killCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
projectOptions: p,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "kill [options] [SERVICE...]",
|
||||
Use: "kill [OPTIONS] [SERVICE...]",
|
||||
Short: "Force stop service containers.",
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runKill(ctx, backend, opts, args)
|
||||
@@ -43,20 +46,24 @@ func killCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
removeOrphans := utils.StringToBool(os.Getenv("COMPOSE_REMOVE_ORPHANS"))
|
||||
flags.BoolVar(&opts.removeOrphans, "remove-orphans", removeOrphans, "Remove containers for services not defined in the Compose file.")
|
||||
flags.StringVarP(&opts.signal, "signal", "s", "SIGKILL", "SIGNAL to send to the container.")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runKill(ctx context.Context, backend api.Service, opts killOptions, services []string) error {
|
||||
projectName, err := opts.toProjectName()
|
||||
project, name, err := opts.projectOrName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return backend.Kill(ctx, projectName, api.KillOptions{
|
||||
Services: services,
|
||||
Signal: opts.signal,
|
||||
return backend.Kill(ctx, name, api.KillOptions{
|
||||
RemoveOrphans: opts.removeOrphans,
|
||||
Project: project,
|
||||
Services: services,
|
||||
Signal: opts.signal,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ type lsOptions struct {
|
||||
func listCommand(backend api.Service) *cobra.Command {
|
||||
lsOpts := lsOptions{Filter: opts.NewFilterOpt()}
|
||||
lsCmd := &cobra.Command{
|
||||
Use: "ls",
|
||||
Use: "ls [OPTIONS]",
|
||||
Short: "List running compose projects",
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runList(ctx, backend, lsOpts)
|
||||
|
||||
@@ -44,7 +44,7 @@ func logsCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
projectOptions: p,
|
||||
}
|
||||
logsCmd := &cobra.Command{
|
||||
Use: "logs [SERVICE...]",
|
||||
Use: "logs [OPTIONS] [SERVICE...]",
|
||||
Short: "View output from containers",
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runLogs(ctx, backend, opts, args)
|
||||
|
||||
@@ -44,13 +44,14 @@ func pauseCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
}
|
||||
|
||||
func runPause(ctx context.Context, backend api.Service, opts pauseOptions, services []string) error {
|
||||
project, err := opts.toProjectName()
|
||||
project, name, err := opts.projectOrName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return backend.Pause(ctx, project, api.PauseOptions{
|
||||
return backend.Pause(ctx, name, api.PauseOptions{
|
||||
Services: services,
|
||||
Project: project,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -74,12 +75,13 @@ func unpauseCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
}
|
||||
|
||||
func runUnPause(ctx context.Context, backend api.Service, opts unpauseOptions, services []string) error {
|
||||
project, err := opts.toProjectName()
|
||||
project, name, err := opts.projectOrName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return backend.UnPause(ctx, project, api.PauseOptions{
|
||||
return backend.UnPause(ctx, name, api.PauseOptions{
|
||||
Services: services,
|
||||
Project: project,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ func portCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
projectOptions: p,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "port [options] [--] SERVICE PRIVATE_PORT",
|
||||
Use: "port [OPTIONS] SERVICE PRIVATE_PORT",
|
||||
Short: "Print the public port for a port binding.",
|
||||
Args: cobra.MinimumNArgs(2),
|
||||
PreRunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
|
||||
@@ -70,7 +70,7 @@ func psCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
projectOptions: p,
|
||||
}
|
||||
psCmd := &cobra.Command{
|
||||
Use: "ps [SERVICE...]",
|
||||
Use: "ps [OPTIONS] [SERVICE...]",
|
||||
Short: "List containers",
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
return opts.parseFilter()
|
||||
@@ -91,11 +91,12 @@ func psCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
}
|
||||
|
||||
func runPs(ctx context.Context, backend api.Service, services []string, opts psOptions) error {
|
||||
projectName, err := opts.toProjectName()
|
||||
project, name, err := opts.projectOrName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
containers, err := backend.Ps(ctx, projectName, api.PsOptions{
|
||||
containers, err := backend.Ps(ctx, name, api.PsOptions{
|
||||
Project: project,
|
||||
All: opts.All,
|
||||
Services: services,
|
||||
})
|
||||
|
||||
@@ -43,7 +43,7 @@ func pullCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
projectOptions: p,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "pull [SERVICE...]",
|
||||
Use: "pull [OPTIONS] [SERVICE...]",
|
||||
Short: "Pull service images",
|
||||
PreRunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
if opts.noParallel {
|
||||
|
||||
@@ -36,7 +36,7 @@ func pushCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
projectOptions: p,
|
||||
}
|
||||
pushCmd := &cobra.Command{
|
||||
Use: "push [SERVICE...]",
|
||||
Use: "push [OPTIONS] [SERVICE...]",
|
||||
Short: "Push service images",
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runPush(ctx, backend, opts, args)
|
||||
|
||||
@@ -35,7 +35,7 @@ func removeCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
projectOptions: p,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "rm [SERVICE...]",
|
||||
Use: "rm [OPTIONS] [SERVICE...]",
|
||||
Short: "Removes stopped service containers",
|
||||
Long: `Removes stopped service containers
|
||||
|
||||
@@ -59,23 +59,25 @@ Any data which is not in a volume will be lost.`,
|
||||
}
|
||||
|
||||
func runRemove(ctx context.Context, backend api.Service, opts removeOptions, services []string) error {
|
||||
project, err := opts.toProjectName()
|
||||
project, name, err := opts.projectOrName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if opts.stop {
|
||||
err := backend.Stop(ctx, project, api.StopOptions{
|
||||
err := backend.Stop(ctx, name, api.StopOptions{
|
||||
Services: services,
|
||||
Project: project,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return backend.Remove(ctx, project, api.RemoveOptions{
|
||||
return backend.Remove(ctx, name, api.RemoveOptions{
|
||||
Services: services,
|
||||
Force: opts.force,
|
||||
Volumes: opts.volumes,
|
||||
Project: project,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ func restartCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
projectOptions: p,
|
||||
}
|
||||
restartCmd := &cobra.Command{
|
||||
Use: "restart [SERVICE...]",
|
||||
Use: "restart [OPTIONS] [SERVICE...]",
|
||||
Short: "Restart service containers",
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runRestart(ctx, backend, opts, args)
|
||||
@@ -49,14 +49,15 @@ func restartCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
}
|
||||
|
||||
func runRestart(ctx context.Context, backend api.Service, opts restartOptions, services []string) error {
|
||||
projectName, err := opts.toProjectName()
|
||||
project, name, err := opts.projectOrName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
timeout := time.Duration(opts.timeout) * time.Second
|
||||
return backend.Restart(ctx, projectName, api.RestartOptions{
|
||||
return backend.Restart(ctx, name, api.RestartOptions{
|
||||
Timeout: &timeout,
|
||||
Services: services,
|
||||
Project: project,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ func runCommand(p *projectOptions, dockerCli command.Cli, backend api.Service) *
|
||||
},
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "run [options] [-v VOLUME...] [-p PORT...] [-e KEY=VAL...] [-l KEY=VALUE...] SERVICE [COMMAND] [ARGS...]",
|
||||
Use: "run [OPTIONS] SERVICE [COMMAND] [ARGS...]",
|
||||
Short: "Run a one-off command on a service.",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
|
||||
@@ -151,7 +151,7 @@ func runCommand(p *projectOptions, dockerCli command.Cli, backend api.Service) *
|
||||
flags.StringArrayVarP(&opts.labels, "label", "l", []string{}, "Add or override a label")
|
||||
flags.BoolVar(&opts.Remove, "rm", false, "Automatically remove the container when it exits")
|
||||
flags.BoolVarP(&opts.noTty, "no-TTY", "T", !dockerCli.Out().IsTerminal(), "Disable pseudo-TTY allocation (default: auto-detected).")
|
||||
flags.StringVar(&opts.name, "name", "", " Assign a name to the container")
|
||||
flags.StringVar(&opts.name, "name", "", "Assign a name to the container")
|
||||
flags.StringVarP(&opts.user, "user", "u", "", "Run as specified username or uid")
|
||||
flags.StringVarP(&opts.workdir, "workdir", "w", "", "Working directory inside the container")
|
||||
flags.StringVar(&opts.entrypoint, "entrypoint", "", "Override the entrypoint of the image")
|
||||
|
||||
@@ -43,12 +43,13 @@ func startCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
}
|
||||
|
||||
func runStart(ctx context.Context, backend api.Service, opts startOptions, services []string) error {
|
||||
projectName, err := opts.toProjectName()
|
||||
project, name, err := opts.projectOrName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return backend.Start(ctx, projectName, api.StartOptions{
|
||||
return backend.Start(ctx, name, api.StartOptions{
|
||||
AttachTo: services,
|
||||
Project: project,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ func stopCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
projectOptions: p,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "stop [SERVICE...]",
|
||||
Use: "stop [OPTIONS] [SERVICE...]",
|
||||
Short: "Stop services",
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
opts.timeChanged = cmd.Flags().Changed("timeout")
|
||||
@@ -53,7 +53,7 @@ func stopCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
}
|
||||
|
||||
func runStop(ctx context.Context, backend api.Service, opts stopOptions, services []string) error {
|
||||
projectName, err := opts.toProjectName()
|
||||
project, name, err := opts.projectOrName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -63,8 +63,9 @@ func runStop(ctx context.Context, backend api.Service, opts stopOptions, service
|
||||
timeoutValue := time.Duration(opts.timeout) * time.Second
|
||||
timeout = &timeoutValue
|
||||
}
|
||||
return backend.Stop(ctx, projectName, api.StopOptions{
|
||||
return backend.Stop(ctx, name, api.StopOptions{
|
||||
Timeout: timeout,
|
||||
Services: services,
|
||||
Project: project,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ func upCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
up := upOptions{}
|
||||
create := createOptions{}
|
||||
upCmd := &cobra.Command{
|
||||
Use: "up [SERVICE...]",
|
||||
Use: "up [OPTIONS] [SERVICE...]",
|
||||
Short: "Create and start containers",
|
||||
PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
|
||||
create.timeChanged = cmd.Flags().Changed("timeout")
|
||||
|
||||
@@ -35,13 +35,18 @@ type versionOptions struct {
|
||||
func versionCommand() *cobra.Command {
|
||||
opts := versionOptions{}
|
||||
cmd := &cobra.Command{
|
||||
Use: "version",
|
||||
Use: "version [OPTIONS]",
|
||||
Short: "Show the Docker Compose version information",
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
runVersion(opts)
|
||||
return nil
|
||||
},
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
// overwrite parent PersistentPreRunE to avoid trying to load
|
||||
// compose file on version command if COMPOSE_FILE is set
|
||||
return nil
|
||||
},
|
||||
}
|
||||
// define flags for backward compatibility with com.docker.cli
|
||||
flags := cmd.Flags()
|
||||
|
||||
@@ -89,7 +89,7 @@ func (l *logConsumer) Log(container, service, message string) {
|
||||
}
|
||||
p := l.getPresenter(container)
|
||||
for _, line := range strings.Split(message, "\n") {
|
||||
fmt.Fprintf(l.writer, "%s%s\n", p.prefix, line) //nolint:errcheck
|
||||
fmt.Fprintf(l.writer, "%s%s\n", p.prefix, line)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
126
docker-bake.hcl
Normal file
126
docker-bake.hcl
Normal file
@@ -0,0 +1,126 @@
|
||||
// Copyright 2022 Docker Compose CLI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
variable "GO_VERSION" {
|
||||
default = "1.18.5"
|
||||
}
|
||||
|
||||
variable "BUILD_TAGS" {
|
||||
default = "e2e,kube"
|
||||
}
|
||||
|
||||
variable "DOCS_FORMATS" {
|
||||
default = "md,yaml"
|
||||
}
|
||||
|
||||
# Defines the output folder
|
||||
variable "DESTDIR" {
|
||||
default = ""
|
||||
}
|
||||
function "bindir" {
|
||||
params = [defaultdir]
|
||||
result = DESTDIR != "" ? DESTDIR : "./bin/${defaultdir}"
|
||||
}
|
||||
|
||||
target "_common" {
|
||||
args = {
|
||||
GO_VERSION = GO_VERSION
|
||||
BUILD_TAGS = BUILD_TAGS
|
||||
BUILDKIT_CONTEXT_KEEP_GIT_DIR = 1
|
||||
}
|
||||
}
|
||||
|
||||
group "default" {
|
||||
targets = ["binary"]
|
||||
}
|
||||
|
||||
group "validate" {
|
||||
targets = ["lint", "vendor-validate", "license-validate"]
|
||||
}
|
||||
|
||||
target "lint" {
|
||||
inherits = ["_common"]
|
||||
target = "lint"
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "license-validate" {
|
||||
target = "license-validate"
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "license-update" {
|
||||
target = "license-update"
|
||||
output = ["."]
|
||||
}
|
||||
|
||||
target "vendor-validate" {
|
||||
inherits = ["_common"]
|
||||
target = "vendor-validate"
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "vendor" {
|
||||
inherits = ["_common"]
|
||||
target = "vendor-update"
|
||||
output = ["."]
|
||||
}
|
||||
|
||||
target "test" {
|
||||
inherits = ["_common"]
|
||||
target = "test-coverage"
|
||||
output = [bindir("coverage")]
|
||||
}
|
||||
|
||||
target "binary" {
|
||||
inherits = ["_common"]
|
||||
target = "binary"
|
||||
output = [bindir("build")]
|
||||
platforms = ["local"]
|
||||
}
|
||||
|
||||
target "binary-cross" {
|
||||
inherits = ["binary"]
|
||||
platforms = [
|
||||
"darwin/amd64",
|
||||
"darwin/arm64",
|
||||
"linux/amd64",
|
||||
"linux/arm/v6",
|
||||
"linux/arm/v7",
|
||||
"linux/arm64",
|
||||
"linux/ppc64le",
|
||||
"linux/riscv64",
|
||||
"linux/s390x",
|
||||
"windows/amd64",
|
||||
"windows/arm64"
|
||||
]
|
||||
}
|
||||
|
||||
target "release" {
|
||||
inherits = ["binary-cross"]
|
||||
target = "release"
|
||||
output = [bindir("release")]
|
||||
}
|
||||
|
||||
target "docs-validate" {
|
||||
inherits = ["_common"]
|
||||
target = "docs-validate"
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "docs-update" {
|
||||
inherits = ["_common"]
|
||||
target = "docs-update"
|
||||
output = ["./docs"]
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
# syntax=docker/dockerfile:1.3-labs
|
||||
|
||||
|
||||
# Copyright 2020 Docker Compose CLI authors
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
ARG GO_VERSION=1.18.4
|
||||
ARG FORMATS=md,yaml
|
||||
|
||||
FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION}-alpine AS docsgen
|
||||
WORKDIR /src
|
||||
RUN --mount=target=. \
|
||||
--mount=target=/root/.cache,type=cache \
|
||||
go build -o /out/docsgen ./docs/yaml/main/generate.go
|
||||
|
||||
FROM --platform=${BUILDPLATFORM} alpine AS gen
|
||||
RUN apk add --no-cache rsync git
|
||||
WORKDIR /src
|
||||
COPY --from=docsgen /out/docsgen /usr/bin
|
||||
ARG FORMATS
|
||||
RUN --mount=target=/context \
|
||||
--mount=target=.,type=tmpfs <<EOT
|
||||
set -e
|
||||
rsync -a /context/. .
|
||||
docsgen --formats "$FORMATS" --source "docs/reference"
|
||||
mkdir /out
|
||||
cp -r docs/reference /out
|
||||
EOT
|
||||
|
||||
FROM scratch AS update
|
||||
COPY --from=gen /out /out
|
||||
|
||||
FROM gen AS validate
|
||||
RUN --mount=target=/context \
|
||||
--mount=target=.,type=tmpfs <<EOT
|
||||
set -e
|
||||
rsync -a /context/. .
|
||||
git add -A
|
||||
rm -rf docs/reference/*
|
||||
cp -rf /out/* ./docs/
|
||||
if [ -n "$(git status --porcelain -- docs/reference)" ]; then
|
||||
echo >&2 'ERROR: Docs result differs. Please update with "make docs"'
|
||||
git status --porcelain -- docs/reference
|
||||
exit 1
|
||||
fi
|
||||
EOT
|
||||
@@ -10,7 +10,7 @@ Stop and remove containers, networks
|
||||
| `--remove-orphans` | | | Remove containers for services not defined in the Compose file. |
|
||||
| `--rmi` | `string` | | Remove images used by services. "local" remove only images that don't have a custom tag ("local"\|"all") |
|
||||
| `-t`, `--timeout` | `int` | `10` | Specify a shutdown timeout in seconds |
|
||||
| `-v`, `--volumes` | | | Remove named volumes declared in the `volumes` section of the Compose file and anonymous volumes attached to containers. |
|
||||
| `-v`, `--volumes` | | | Remove named volumes declared in the `volumes` section of the Compose file and anonymous volumes attached to containers. |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
@@ -7,6 +7,7 @@ Force stop service containers.
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--remove-orphans` | | | Remove containers for services not defined in the Compose file. |
|
||||
| `-s`, `--signal` | `string` | `SIGKILL` | SIGNAL to send to the container. |
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ Run a one-off command on a service.
|
||||
| `-e`, `--env` | `stringArray` | | Set environment variables |
|
||||
| `-i`, `--interactive` | | | Keep STDIN open even if not attached. |
|
||||
| `-l`, `--label` | `stringArray` | | Add or override a label |
|
||||
| `--name` | `string` | | Assign a name to the container |
|
||||
| `--name` | `string` | | Assign a name to the container |
|
||||
| `-T`, `--no-TTY` | | | Disable pseudo-TTY allocation (default: auto-detected). |
|
||||
| `--no-deps` | | | Don't start linked services. |
|
||||
| `-p`, `--publish` | `stringArray` | | Publish a container's port(s) to the host. |
|
||||
|
||||
@@ -10,7 +10,7 @@ long: |-
|
||||
|
||||
If you change a service's `Dockerfile` or the contents of its build directory,
|
||||
run `docker compose build` to rebuild it.
|
||||
usage: docker compose build [SERVICE...]
|
||||
usage: docker compose build [OPTIONS] [SERVICE...]
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
options:
|
||||
|
||||
@@ -7,7 +7,7 @@ long: |-
|
||||
fully defined Compose model.
|
||||
|
||||
To allow smooth migration from docker-compose, this subcommand declares alias `docker compose config`
|
||||
usage: docker compose convert SERVICES
|
||||
usage: docker compose convert [OPTIONS] [SERVICE...]
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
options:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
command: docker compose create
|
||||
short: Creates containers for a service.
|
||||
long: Creates containers for a service.
|
||||
usage: docker compose create [SERVICE...]
|
||||
usage: docker compose create [OPTIONS] [SERVICE...]
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
options:
|
||||
|
||||
@@ -14,7 +14,7 @@ long: |-
|
||||
Anonymous volumes are not removed by default. However, as they don’t have a stable name, they will not be automatically
|
||||
mounted by a subsequent `up`. For data that needs to persist between updates, use explicit paths as bind mounts or
|
||||
named volumes.
|
||||
usage: docker compose down
|
||||
usage: docker compose down [OPTIONS]
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
options:
|
||||
|
||||
@@ -20,7 +20,7 @@ long: |-
|
||||
```
|
||||
|
||||
The events that can be received using this can be seen [here](/engine/reference/commandline/events/#object-types).
|
||||
usage: docker compose events [options] [--] [SERVICE...]
|
||||
usage: docker compose events [OPTIONS] [SERVICE...]
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
options:
|
||||
|
||||
@@ -5,7 +5,7 @@ long: |-
|
||||
|
||||
With this subcommand you can run arbitrary commands in your services. Commands are by default allocating a TTY, so
|
||||
you can use a command such as `docker compose exec web sh` to get an interactive prompt.
|
||||
usage: docker compose exec [options] [-e KEY=VAL...] [--] SERVICE COMMAND [ARGS...]
|
||||
usage: docker compose exec [OPTIONS] SERVICE COMMAND [ARGS...]
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
options:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
command: docker compose images
|
||||
short: List images used by the created containers
|
||||
long: List images used by the created containers
|
||||
usage: docker compose images [SERVICE...]
|
||||
usage: docker compose images [OPTIONS] [SERVICE...]
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
options:
|
||||
|
||||
@@ -6,10 +6,20 @@ long: |-
|
||||
```console
|
||||
$ docker-compose kill -s SIGINT
|
||||
```
|
||||
usage: docker compose kill [options] [SERVICE...]
|
||||
usage: docker compose kill [OPTIONS] [SERVICE...]
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
options:
|
||||
- option: remove-orphans
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Remove containers for services not defined in the Compose file.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: signal
|
||||
shorthand: s
|
||||
value_type: string
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
command: docker compose logs
|
||||
short: View output from containers
|
||||
long: Displays log output from services.
|
||||
usage: docker compose logs [SERVICE...]
|
||||
usage: docker compose logs [OPTIONS] [SERVICE...]
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
options:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
command: docker compose ls
|
||||
short: List running compose projects
|
||||
long: List Compose projects running on platform.
|
||||
usage: docker compose ls
|
||||
usage: docker compose ls [OPTIONS]
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
options:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
command: docker compose port
|
||||
short: Print the public port for a port binding.
|
||||
long: Prints the public port for a port binding.
|
||||
usage: docker compose port [options] [--] SERVICE PRIVATE_PORT
|
||||
usage: docker compose port [OPTIONS] SERVICE PRIVATE_PORT
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
options:
|
||||
|
||||
@@ -10,7 +10,7 @@ long: |-
|
||||
example-bar-1 "/docker-entrypoint.…" bar exited (0)
|
||||
example-foo-1 "/docker-entrypoint.…" foo running 0.0.0.0:8080->80/tcp
|
||||
```
|
||||
usage: docker compose ps [SERVICE...]
|
||||
usage: docker compose ps [OPTIONS] [SERVICE...]
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
options:
|
||||
|
||||
@@ -3,7 +3,7 @@ short: Pull service images
|
||||
long: |-
|
||||
Pulls an image associated with a service defined in a `compose.yaml` file, but does not start containers based on
|
||||
those images.
|
||||
usage: docker compose pull [SERVICE...]
|
||||
usage: docker compose pull [OPTIONS] [SERVICE...]
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
options:
|
||||
|
||||
@@ -19,7 +19,7 @@ long: |-
|
||||
build: .
|
||||
image: your-dockerid/yourimage ## goes to your repository on Docker Hub
|
||||
```
|
||||
usage: docker compose push [SERVICE...]
|
||||
usage: docker compose push [OPTIONS] [SERVICE...]
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
options:
|
||||
|
||||
@@ -11,7 +11,7 @@ long: |-
|
||||
If you are looking to configure a service's restart policy, please refer to
|
||||
[restart](https://github.com/compose-spec/compose-spec/blob/master/spec.md#restart)
|
||||
or [restart_policy](https://github.com/compose-spec/compose-spec/blob/master/deploy.md#restart_policy).
|
||||
usage: docker compose restart [SERVICE...]
|
||||
usage: docker compose restart [OPTIONS] [SERVICE...]
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
options:
|
||||
|
||||
@@ -16,7 +16,7 @@ long: |-
|
||||
Are you sure? [yN] y
|
||||
Removing djangoquickstart_web_run_1 ... done
|
||||
```
|
||||
usage: docker compose rm [SERVICE...]
|
||||
usage: docker compose rm [OPTIONS] [SERVICE...]
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
options:
|
||||
|
||||
@@ -54,7 +54,7 @@ long: |-
|
||||
|
||||
This runs a database upgrade script, and removes the container when finished running, even if a restart policy is
|
||||
specified in the service configuration.
|
||||
usage: docker compose run [options] [-v VOLUME...] [-p PORT...] [-e KEY=VAL...] [-l KEY=VALUE...] SERVICE [COMMAND] [ARGS...]
|
||||
usage: docker compose run [OPTIONS] SERVICE [COMMAND] [ARGS...]
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
options:
|
||||
|
||||
@@ -2,7 +2,7 @@ command: docker compose stop
|
||||
short: Stop services
|
||||
long: |
|
||||
Stops running containers without removing them. They can be started again with `docker compose start`.
|
||||
usage: docker compose stop [SERVICE...]
|
||||
usage: docker compose stop [OPTIONS] [SERVICE...]
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
options:
|
||||
|
||||
@@ -17,7 +17,7 @@ long: |-
|
||||
|
||||
If the process encounters an error, the exit code for this command is `1`.
|
||||
If the process is interrupted using `SIGINT` (ctrl + C) or `SIGTERM`, the containers are stopped, and the exit code is `0`.
|
||||
usage: docker compose up [SERVICE...]
|
||||
usage: docker compose up [OPTIONS] [SERVICE...]
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
options:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
command: docker compose version
|
||||
short: Show the Docker Compose version information
|
||||
long: Show the Docker Compose version information
|
||||
usage: docker compose version
|
||||
usage: docker compose version [OPTIONS]
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
options:
|
||||
|
||||
19
go.mod
19
go.mod
@@ -5,11 +5,11 @@ go 1.18
|
||||
require (
|
||||
github.com/AlecAivazis/survey/v2 v2.3.5
|
||||
github.com/buger/goterm v1.0.4
|
||||
github.com/cnabio/cnab-to-oci v0.3.5
|
||||
github.com/compose-spec/compose-go v1.3.0
|
||||
github.com/cnabio/cnab-to-oci v0.3.6
|
||||
github.com/compose-spec/compose-go v1.5.0
|
||||
github.com/containerd/console v1.0.3
|
||||
github.com/containerd/containerd v1.6.6
|
||||
github.com/distribution/distribution/v3 v3.0.0-20220725133111-4bf3547399eb
|
||||
github.com/containerd/containerd v1.6.8
|
||||
github.com/distribution/distribution/v3 v3.0.0-20220729163034-26163d82560f
|
||||
github.com/docker/buildx v0.8.2 // when updating, also update the replace rules accordingly
|
||||
github.com/docker/cli v20.10.17+incompatible
|
||||
github.com/docker/cli-docs-tool v0.5.0
|
||||
@@ -19,21 +19,21 @@ require (
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/hashicorp/go-version v1.6.0
|
||||
github.com/mattn/go-isatty v0.0.14
|
||||
github.com/mattn/go-isatty v0.0.16
|
||||
github.com/mattn/go-shellwords v1.0.12
|
||||
github.com/moby/buildkit v0.10.1-0.20220403220257-10e6f94bf90d
|
||||
github.com/moby/buildkit v0.10.4
|
||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6
|
||||
github.com/morikuni/aec v1.0.0
|
||||
github.com/opencontainers/go-digest v1.0.0
|
||||
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/sanathkr/go-yaml v0.0.0-20170819195128-ed9d249f429b
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/spf13/cobra v1.5.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.8.0
|
||||
github.com/theupdateframework/notary v0.7.0
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
gotest.tools v2.2.0+incompatible
|
||||
gotest.tools/v3 v3.3.0
|
||||
)
|
||||
@@ -45,7 +45,7 @@ require (
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/cnabio/cnab-go v0.23.4 // indirect
|
||||
github.com/containerd/continuity v0.2.2 // indirect
|
||||
github.com/containerd/continuity v0.2.3-0.20220330195504-d132b287edc8 // indirect
|
||||
github.com/containerd/ttrpc v1.1.0 // indirect
|
||||
github.com/containerd/typeurl v1.0.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
@@ -111,7 +111,7 @@ require (
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
|
||||
@@ -120,7 +120,6 @@ require (
|
||||
google.golang.org/grpc v1.45.0 // indirect
|
||||
google.golang.org/protobuf v1.27.1 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/apimachinery v0.24.1 // indirect; see replace for the actual version used
|
||||
k8s.io/client-go v0.24.1 // indirect; see replace for the actual version used
|
||||
|
||||
33
go.sum
33
go.sum
@@ -141,7 +141,7 @@ github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwT
|
||||
github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
|
||||
github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg=
|
||||
github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
|
||||
github.com/Microsoft/hcsshim v0.9.3 h1:k371PzBuRrz2b+ebGuI2nVgVhgsVX60jMfSw80NECxo=
|
||||
github.com/Microsoft/hcsshim v0.9.4 h1:mnUj0ivWy6UzbB1uLFqKR6F+ZyiDc7j4iGgHTpO+5+I=
|
||||
github.com/Microsoft/hcsshim/test v0.0.0-20200826032352-301c83a30e7c/go.mod h1:30A5igQ91GEmhYJF8TaRP79pMBOYynRsyOByfVV0dU4=
|
||||
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
|
||||
github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
|
||||
@@ -270,8 +270,8 @@ github.com/cloudflare/cfssl v0.0.0-20181213083726-b94e044bb51e/go.mod h1:yMWuSON
|
||||
github.com/cloudflare/cfssl v1.4.1 h1:vScfU2DrIUI9VPHBVeeAQ0q5A+9yshO1Gz+3QoUQiKw=
|
||||
github.com/cnabio/cnab-go v0.23.4 h1:jplQcSnvFyQlD6swiqL3BmqRnhbnS+lc/EKdBLH9E80=
|
||||
github.com/cnabio/cnab-go v0.23.4/go.mod h1:9EmgHR51LFqQStzaC+xHPJlkD4OPsF6Ev5Y8e/YHEns=
|
||||
github.com/cnabio/cnab-to-oci v0.3.5 h1:X/8WVW1LjwGH4qD8rhovkmibW95CbItZdE39Velvg0k=
|
||||
github.com/cnabio/cnab-to-oci v0.3.5/go.mod h1:7f86Z39HUg67wg8dZvxvFpW2pGDjK3RwbJAMJGxTXHQ=
|
||||
github.com/cnabio/cnab-to-oci v0.3.6 h1:QVvy4WjQpGyf20xbbeYtRObX+pB8cWNuvvT/e4w1DoQ=
|
||||
github.com/cnabio/cnab-to-oci v0.3.6/go.mod h1:AvVNl0Hh3VBk1zqeLdyE5S3bTQ5EsZPPF4mUUJYyy1Y=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
@@ -286,8 +286,8 @@ github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoC
|
||||
github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
github.com/compose-spec/compose-go v1.2.1/go.mod h1:pAy7Mikpeft4pxkFU565/DRHEbDfR84G6AQuiL+Hdg8=
|
||||
github.com/compose-spec/compose-go v1.3.0 h1:n5fSOUXQsfnCpn/lZBgNM3qEu1PDhvcbWrWXVBlUNmA=
|
||||
github.com/compose-spec/compose-go v1.3.0/go.mod h1:l7RUULbFFLzlQHuxtJr7SVLyWdqEpbJEGTWCgcu6Eqw=
|
||||
github.com/compose-spec/compose-go v1.5.0 h1:yOmYpIm13pYt2o+oKVe/JAD6o2Tv+eUyOcRhf0qF4fA=
|
||||
github.com/compose-spec/compose-go v1.5.0/go.mod h1:l7RUULbFFLzlQHuxtJr7SVLyWdqEpbJEGTWCgcu6Eqw=
|
||||
github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE=
|
||||
github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU=
|
||||
github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU=
|
||||
@@ -330,8 +330,8 @@ github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTV
|
||||
github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c=
|
||||
github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s=
|
||||
github.com/containerd/containerd v1.6.1/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE=
|
||||
github.com/containerd/containerd v1.6.6 h1:xJNPhbrmz8xAMDNoVjHy9YHtWwEQNS+CDkcIRh7t8Y0=
|
||||
github.com/containerd/containerd v1.6.6/go.mod h1:ZoP1geJldzCVY3Tonoz7b1IXk8rIX0Nltt5QE4OMNk0=
|
||||
github.com/containerd/containerd v1.6.8 h1:h4dOFDwzHmqFEP754PgfgTeVXFnLiRc6kiqC7tplDJs=
|
||||
github.com/containerd/containerd v1.6.8/go.mod h1:By6p5KqPK0/7/CgO/A6t/Gz+CUYUu2zf1hUaaymVXB0=
|
||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
@@ -339,8 +339,9 @@ github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cE
|
||||
github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y=
|
||||
github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ=
|
||||
github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM=
|
||||
github.com/containerd/continuity v0.2.2 h1:QSqfxcn8c+12slxwu00AtzXrsami0MJb/MQs9lOLHLA=
|
||||
github.com/containerd/continuity v0.2.2/go.mod h1:pWygW9u7LtS1o4N/Tn0FoCFDIXZ7rxcMX7HX1Dmibvk=
|
||||
github.com/containerd/continuity v0.2.3-0.20220330195504-d132b287edc8 h1:yGFEcFNMhze29DxAAB33v/1OMRYF/cM9iwwgV2P0ZrE=
|
||||
github.com/containerd/continuity v0.2.3-0.20220330195504-d132b287edc8/go.mod h1:pWygW9u7LtS1o4N/Tn0FoCFDIXZ7rxcMX7HX1Dmibvk=
|
||||
github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
||||
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
||||
github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
|
||||
@@ -448,8 +449,8 @@ github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8
|
||||
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
|
||||
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
|
||||
github.com/distribution/distribution/v3 v3.0.0-20210316161203-a01c71e2477e/go.mod h1:xpWTC2KnJMiDLkoawhsPQcXjvwATEBcbq0xevG2YR9M=
|
||||
github.com/distribution/distribution/v3 v3.0.0-20220725133111-4bf3547399eb h1:oCCuuU3kMO3sjZH/p7LamvQNW9SWoT4yQuMGcdSxGAE=
|
||||
github.com/distribution/distribution/v3 v3.0.0-20220725133111-4bf3547399eb/go.mod h1:28YO/VJk9/64+sTGNuYaBjWxrXTPrj0C0XmgTIOjxX4=
|
||||
github.com/distribution/distribution/v3 v3.0.0-20220729163034-26163d82560f h1:3NCYdjXycNd/Xn/iICZzmxkiDX1e1cjTHjbMAz+wRVk=
|
||||
github.com/distribution/distribution/v3 v3.0.0-20220729163034-26163d82560f/go.mod h1:28YO/VJk9/64+sTGNuYaBjWxrXTPrj0C0XmgTIOjxX4=
|
||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||
github.com/docker/buildx v0.8.2 h1:dsd3F0hhmUydFX/KFrvbK81JvlTA4T3Iy0lwDJt4PsU=
|
||||
github.com/docker/buildx v0.8.2/go.mod h1:5sMOfNwOmO2jy/MxBL4ySk2LoLIG1tQFu2EU8wbKa34=
|
||||
@@ -970,8 +971,9 @@ github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
|
||||
github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
|
||||
@@ -1014,14 +1016,14 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
||||
github.com/moby/buildkit v0.8.1/go.mod h1:/kyU1hKy/aYCuP39GZA9MaKioovHku57N6cqlKZIaiQ=
|
||||
github.com/moby/buildkit v0.10.1-0.20220403220257-10e6f94bf90d h1:6pLVBJO3V/lMegbVD5kh2QrpZwqS4ZrxEm/MyifCPaY=
|
||||
github.com/moby/buildkit v0.10.1-0.20220403220257-10e6f94bf90d/go.mod h1:WvwAZv8aRScHkqc/+X46cRC2CKMKpqcaX+pRvUTtPes=
|
||||
github.com/moby/buildkit v0.10.4 h1:FvC+buO8isGpUFZ1abdSLdGHZVqg9sqI4BbFL8tlzP4=
|
||||
github.com/moby/buildkit v0.10.4/go.mod h1:Yajz9vt1Zw5q9Pp4pdb3TCSUXJBIroIQGQ3TTs/sLug=
|
||||
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
||||
github.com/moby/sys/mount v0.1.0/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74=
|
||||
github.com/moby/sys/mount v0.1.1/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74=
|
||||
github.com/moby/sys/mount v0.3.0 h1:bXZYMmq7DBQPwHRxH/MG+u9+XF90ZOwoXpHTOznMGp0=
|
||||
github.com/moby/sys/mount v0.3.0/go.mod h1:U2Z3ur2rXPFrFmy4q6WMwWrBOAQGYtYTRVM8BIvzbwk=
|
||||
github.com/moby/sys/mountinfo v0.1.0/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+Syr3h52Tw4o=
|
||||
github.com/moby/sys/mountinfo v0.1.3/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+Syr3h52Tw4o=
|
||||
@@ -1221,8 +1223,6 @@ github.com/ryancurrah/gomodguard v1.1.0/go.mod h1:4O8tr7hBODaGE6VIhfJDHcwzh5GUcc
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
||||
github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
||||
github.com/sanathkr/go-yaml v0.0.0-20170819195128-ed9d249f429b h1:jUK33OXuZP/l6babJtnLo1qsGvq6G9so9KMflGAm4YA=
|
||||
github.com/sanathkr/go-yaml v0.0.0-20170819195128-ed9d249f429b/go.mod h1:8458kAagoME2+LN5//WxE71ysZ3B7r22fdgb7qVmXSY=
|
||||
github.com/sassoftware/go-rpmutils v0.0.0-20190420191620-a8f1baeba37b/go.mod h1:am+Fp8Bt506lA3Rk3QCmSqmYmLMnPDhdDUcosQCAx+I=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
|
||||
@@ -1796,8 +1796,9 @@ golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
|
||||
@@ -117,7 +117,7 @@ type CreateOptions struct {
|
||||
|
||||
// StartOptions group options of the Start API
|
||||
type StartOptions struct {
|
||||
// Project is the compose project used to define this app. Might be nil if user ran `start` just with project name
|
||||
// Project is the compose project used to define this app. Might be nil if user ran command just with project name
|
||||
Project *types.Project
|
||||
// Attach to container and forward logs if not nil
|
||||
Attach LogConsumer
|
||||
@@ -133,6 +133,8 @@ type StartOptions struct {
|
||||
|
||||
// RestartOptions group options of the Restart API
|
||||
type RestartOptions struct {
|
||||
// Project is the compose project used to define this app. Might be nil if user ran command just with project name
|
||||
Project *types.Project
|
||||
// Timeout override container restart timeout
|
||||
Timeout *time.Duration
|
||||
// Services passed in the command line to be restarted
|
||||
@@ -141,6 +143,8 @@ type RestartOptions struct {
|
||||
|
||||
// StopOptions group options of the Stop API
|
||||
type StopOptions struct {
|
||||
// Project is the compose project used to define this app. Might be nil if user ran command just with project name
|
||||
Project *types.Project
|
||||
// Timeout override container stop timeout
|
||||
Timeout *time.Duration
|
||||
// Services passed in the command line to be stopped
|
||||
@@ -193,6 +197,10 @@ type ImagesOptions struct {
|
||||
|
||||
// KillOptions group options of the Kill API
|
||||
type KillOptions struct {
|
||||
// RemoveOrphans will cleanup containers that are not declared on the compose model but own the same labels
|
||||
RemoveOrphans bool
|
||||
// Project is the compose project used to define this app. Might be nil if user ran command just with project name
|
||||
Project *types.Project
|
||||
// Services passed in the command line to be killed
|
||||
Services []string
|
||||
// Signal to send to containers
|
||||
@@ -201,6 +209,8 @@ type KillOptions struct {
|
||||
|
||||
// RemoveOptions group options of the Remove API
|
||||
type RemoveOptions struct {
|
||||
// Project is the compose project used to define this app. Might be nil if user ran command just with project name
|
||||
Project *types.Project
|
||||
// DryRun just list removable resources
|
||||
DryRun bool
|
||||
// Volumes remove anonymous volumes
|
||||
@@ -213,6 +223,8 @@ type RemoveOptions struct {
|
||||
|
||||
// RunOptions group options of the Run API
|
||||
type RunOptions struct {
|
||||
// Project is the compose project used to define this app. Might be nil if user ran command just with project name
|
||||
Project *types.Project
|
||||
Name string
|
||||
Service string
|
||||
Command []string
|
||||
@@ -272,6 +284,7 @@ type ListOptions struct {
|
||||
|
||||
// PsOptions group options of the Ps API
|
||||
type PsOptions struct {
|
||||
Project *types.Project
|
||||
All bool
|
||||
Services []string
|
||||
}
|
||||
@@ -377,6 +390,8 @@ type LogOptions struct {
|
||||
type PauseOptions struct {
|
||||
// Services passed in the command line to be started
|
||||
Services []string
|
||||
// Project is the compose project used to define this app. Might be nil if user ran command just with project name
|
||||
Project *types.Project
|
||||
}
|
||||
|
||||
const (
|
||||
|
||||
@@ -22,6 +22,8 @@ import (
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
)
|
||||
|
||||
var _ Service = &ServiceProxy{}
|
||||
|
||||
// ServiceProxy implements Service by delegating to implementation functions. This allows lazy init and per-method overrides
|
||||
type ServiceProxy struct {
|
||||
BuildFn func(ctx context.Context, project *types.Project, options BuildOptions) error
|
||||
@@ -59,8 +61,6 @@ func NewServiceProxy() *ServiceProxy {
|
||||
// Interceptor allow to customize the compose types.Project before the actual Service method is executed
|
||||
type Interceptor func(ctx context.Context, project *types.Project)
|
||||
|
||||
var _ Service = &ServiceProxy{}
|
||||
|
||||
// WithService configure proxy to use specified Service as delegate
|
||||
func (s *ServiceProxy) WithService(service Service) *ServiceProxy {
|
||||
s.BuildFn = service.Build
|
||||
|
||||
@@ -50,10 +50,7 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
|
||||
opts := map[string]build.Options{}
|
||||
var imagesToBuild []string
|
||||
|
||||
args := flatten(options.Args.Resolve(func(s string) (string, bool) {
|
||||
s, ok := project.Environment[s]
|
||||
return s, ok
|
||||
}))
|
||||
args := flatten(options.Args.Resolve(envResolver(project.Environment)))
|
||||
|
||||
services, err := project.GetServices(options.Services...)
|
||||
if err != nil {
|
||||
@@ -214,10 +211,7 @@ func (s *composeService) toBuildOptions(project *types.Project, service types.Se
|
||||
var tags []string
|
||||
tags = append(tags, imageTag)
|
||||
|
||||
buildArgs := flatten(service.Build.Args.Resolve(func(s string) (string, bool) {
|
||||
s, ok := project.Environment[s]
|
||||
return s, ok
|
||||
}))
|
||||
buildArgs := flatten(service.Build.Args.Resolve(envResolver(project.Environment)))
|
||||
|
||||
var plats []specs.Platform
|
||||
if platform, ok := project.Environment["DOCKER_DEFAULT_PLATFORM"]; ok {
|
||||
|
||||
@@ -29,7 +29,6 @@ import (
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
buildx "github.com/docker/buildx/build"
|
||||
"github.com/docker/cli/cli/command/image/build"
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
dockertypes "github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/cli"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
@@ -40,6 +39,8 @@ import (
|
||||
"github.com/docker/docker/pkg/urlutil"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
)
|
||||
|
||||
func (s *composeService) doBuildClassic(ctx context.Context, project *types.Project, opts map[string]buildx.Options) (map[string]string, error) {
|
||||
@@ -65,7 +66,7 @@ func (s *composeService) doBuildClassic(ctx context.Context, project *types.Proj
|
||||
return nameDigests, errs
|
||||
}
|
||||
|
||||
//nolint: gocyclo
|
||||
//nolint:gocyclo
|
||||
func (s *composeService) doBuildClassicSimpleImage(ctx context.Context, options buildx.Options) (string, error) {
|
||||
var (
|
||||
buildCtx io.ReadCloser
|
||||
|
||||
@@ -24,6 +24,8 @@ import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
@@ -33,7 +35,6 @@ import (
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sanathkr/go-yaml"
|
||||
)
|
||||
|
||||
// NewComposeService create a local implementation of the compose.Service API
|
||||
@@ -172,26 +173,6 @@ SERVICES:
|
||||
return project, nil
|
||||
}
|
||||
|
||||
// actualState list resources labelled by projectName to rebuild compose project model
|
||||
func (s *composeService) actualState(ctx context.Context, projectName string, services []string) (Containers, *types.Project, error) {
|
||||
var containers Containers
|
||||
// don't filter containers by options.Services so projectFromName can rebuild project with all existing resources
|
||||
containers, err := s.getContainers(ctx, projectName, oneOffInclude, true)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
project, err := s.projectFromName(containers, projectName, services...)
|
||||
if err != nil && !api.IsNotFoundError(err) {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if len(services) > 0 {
|
||||
containers = containers.filter(isService(services...))
|
||||
}
|
||||
return containers, project, nil
|
||||
}
|
||||
|
||||
func (s *composeService) actualVolumes(ctx context.Context, projectName string) (types.Volumes, error) {
|
||||
volumes, err := s.apiClient().VolumeList(ctx, filters.NewArgs(projectFilter(projectName)))
|
||||
if err != nil {
|
||||
|
||||
@@ -30,13 +30,13 @@ const (
|
||||
// ContainerRunning running status
|
||||
ContainerRunning = "running"
|
||||
// ContainerRemoving removing status
|
||||
ContainerRemoving = "removing" //nolint
|
||||
ContainerRemoving = "removing"
|
||||
// ContainerPaused paused status
|
||||
ContainerPaused = "paused" //nolint
|
||||
ContainerPaused = "paused"
|
||||
// ContainerExited exited status
|
||||
ContainerExited = "exited" //nolint
|
||||
ContainerExited = "exited"
|
||||
// ContainerDead dead status
|
||||
ContainerDead = "dead" //nolint
|
||||
ContainerDead = "dead"
|
||||
)
|
||||
|
||||
var _ io.ReadCloser = ContainerStdout{}
|
||||
|
||||
@@ -352,6 +352,12 @@ func shouldWaitForDependency(serviceName string, dependencyConfig types.ServiceD
|
||||
return false, nil
|
||||
}
|
||||
if service, err := project.GetService(serviceName); err != nil {
|
||||
for _, ds := range project.DisabledServices {
|
||||
if ds.Name == serviceName {
|
||||
// don't wait for disabled service (--no-deps)
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
return false, err
|
||||
} else if service.Scale == 0 {
|
||||
// don't wait for the dependency which configured to have 0 containers running
|
||||
@@ -605,8 +611,9 @@ func (s *composeService) connectContainerToNetwork(ctx context.Context, id strin
|
||||
ipv4Address = cfg.Ipv4Address
|
||||
ipv6Address = cfg.Ipv6Address
|
||||
ipam = &network.EndpointIPAMConfig{
|
||||
IPv4Address: ipv4Address,
|
||||
IPv6Address: ipv6Address,
|
||||
IPv4Address: ipv4Address,
|
||||
IPv6Address: ipv6Address,
|
||||
LinkLocalIPs: cfg.LinkLocalIPs,
|
||||
}
|
||||
}
|
||||
err := s.apiClient().NetworkConnect(ctx, netwrk, id, &network.EndpointSettings{
|
||||
|
||||
@@ -146,6 +146,9 @@ func prepareNetworks(project *types.Project) {
|
||||
}
|
||||
|
||||
func prepareServicesDependsOn(p *types.Project) error {
|
||||
allServices := types.Project{}
|
||||
allServices.Services = p.AllServices()
|
||||
|
||||
for i, service := range p.Services {
|
||||
var dependencies []string
|
||||
networkDependency := getDependentServiceFromMode(service.NetworkMode)
|
||||
@@ -178,20 +181,24 @@ func prepareServicesDependsOn(p *types.Project) error {
|
||||
dependencies = append(dependencies, strings.Split(link, ":")[0])
|
||||
}
|
||||
|
||||
for d := range service.DependsOn {
|
||||
dependencies = append(dependencies, d)
|
||||
}
|
||||
|
||||
if len(dependencies) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// Verify dependencies exist in the project, whether disabled or not
|
||||
deps, err := allServices.GetServices(dependencies...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if service.DependsOn == nil {
|
||||
service.DependsOn = make(types.DependsOnConfig)
|
||||
}
|
||||
|
||||
// Verify dependencies exist in the project, whether disabled or not
|
||||
projAllServices := types.Project{}
|
||||
projAllServices.Services = p.AllServices()
|
||||
deps, err := projAllServices.GetServices(dependencies...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, d := range deps {
|
||||
if _, ok := service.DependsOn[d.Name]; !ok {
|
||||
service.DependsOn[d.Name] = types.ServiceDependency{
|
||||
@@ -306,8 +313,9 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
|
||||
ipv4Address = config.Ipv4Address
|
||||
ipv6Address = config.Ipv6Address
|
||||
ipam = &network.EndpointIPAMConfig{
|
||||
IPv4Address: ipv4Address,
|
||||
IPv6Address: ipv6Address,
|
||||
IPv4Address: ipv4Address,
|
||||
IPv6Address: ipv6Address,
|
||||
LinkLocalIPs: config.LinkLocalIPs,
|
||||
}
|
||||
}
|
||||
networkConfig = &network.NetworkingConfig{
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"gotest.tools/v3/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var project = types.Project{
|
||||
@@ -45,25 +45,27 @@ var project = types.Project{
|
||||
}
|
||||
|
||||
func TestInDependencyUpCommandOrder(t *testing.T) {
|
||||
order := make(chan string)
|
||||
//nolint:errcheck, unparam
|
||||
go InDependencyOrder(context.TODO(), &project, func(ctx context.Context, config string) error {
|
||||
order <- config
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
t.Cleanup(cancel)
|
||||
|
||||
var order []string
|
||||
err := InDependencyOrder(ctx, &project, func(ctx context.Context, service string) error {
|
||||
order = append(order, service)
|
||||
return nil
|
||||
})
|
||||
assert.Equal(t, <-order, "test3")
|
||||
assert.Equal(t, <-order, "test2")
|
||||
assert.Equal(t, <-order, "test1")
|
||||
require.NoError(t, err, "Error during iteration")
|
||||
require.Equal(t, []string{"test3", "test2", "test1"}, order)
|
||||
}
|
||||
|
||||
func TestInDependencyReverseDownCommandOrder(t *testing.T) {
|
||||
order := make(chan string)
|
||||
//nolint:errcheck, unparam
|
||||
go InReverseDependencyOrder(context.TODO(), &project, func(ctx context.Context, config string) error {
|
||||
order <- config
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
t.Cleanup(cancel)
|
||||
|
||||
var order []string
|
||||
err := InReverseDependencyOrder(ctx, &project, func(ctx context.Context, service string) error {
|
||||
order = append(order, service)
|
||||
return nil
|
||||
})
|
||||
assert.Equal(t, <-order, "test1")
|
||||
assert.Equal(t, <-order, "test2")
|
||||
assert.Equal(t, <-order, "test3")
|
||||
require.NoError(t, err, "Error during iteration")
|
||||
require.Equal(t, []string{"test1", "test2", "test3"}, order)
|
||||
}
|
||||
|
||||
@@ -45,8 +45,11 @@ func (s *composeService) down(ctx context.Context, projectName string, options a
|
||||
w := progress.ContextWriter(ctx)
|
||||
resourceToRemove := false
|
||||
|
||||
var containers Containers
|
||||
containers, err := s.getContainers(ctx, projectName, oneOffInclude, true)
|
||||
include := oneOffExclude
|
||||
if options.RemoveOrphans {
|
||||
include = oneOffInclude
|
||||
}
|
||||
containers, err := s.getContainers(ctx, projectName, include, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ func TestDown(t *testing.T) {
|
||||
tested.dockerCli = cli
|
||||
cli.EXPECT().Client().Return(api).AnyTimes()
|
||||
|
||||
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return(
|
||||
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(false)).Return(
|
||||
[]moby.Container{
|
||||
testContainer("service1", "123", false),
|
||||
testContainer("service2", "456", false),
|
||||
@@ -88,7 +88,7 @@ func TestDownRemoveOrphans(t *testing.T) {
|
||||
tested.dockerCli = cli
|
||||
cli.EXPECT().Client().Return(api).AnyTimes()
|
||||
|
||||
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return(
|
||||
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(true)).Return(
|
||||
[]moby.Container{
|
||||
testContainer("service1", "123", false),
|
||||
testContainer("service2", "789", false),
|
||||
@@ -125,7 +125,7 @@ func TestDownRemoveVolumes(t *testing.T) {
|
||||
tested.dockerCli = cli
|
||||
cli.EXPECT().Client().Return(api).AnyTimes()
|
||||
|
||||
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return(
|
||||
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(false)).Return(
|
||||
[]moby.Container{testContainer("service1", "123", false)}, nil)
|
||||
api.EXPECT().VolumeList(gomock.Any(), filters.NewArgs(projectFilter(strings.ToLower(testProject)))).
|
||||
Return(volume.VolumeListOKBody{
|
||||
|
||||
68
pkg/compose/envresolver.go
Normal file
68
pkg/compose/envresolver.go
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
Copyright 2020 Docker Compose CLI authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package compose
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
// isCaseInsensitiveEnvVars is true on platforms where environment variable names are treated case-insensitively.
|
||||
isCaseInsensitiveEnvVars = (runtime.GOOS == "windows")
|
||||
)
|
||||
|
||||
// envResolver returns resolver for environment variables suitable for the current platform.
|
||||
// Expected to be used with `MappingWithEquals.Resolve`.
|
||||
// Updates in `environment` may not be reflected.
|
||||
func envResolver(environment map[string]string) func(string) (string, bool) {
|
||||
return envResolverWithCase(environment, isCaseInsensitiveEnvVars)
|
||||
}
|
||||
|
||||
// envResolverWithCase returns resolver for environment variables with the specified case-sensitive condition.
|
||||
// Expected to be used with `MappingWithEquals.Resolve`.
|
||||
// Updates in `environment` may not be reflected.
|
||||
func envResolverWithCase(environment map[string]string, caseInsensitive bool) func(string) (string, bool) {
|
||||
if environment == nil {
|
||||
return func(s string) (string, bool) {
|
||||
return "", false
|
||||
}
|
||||
}
|
||||
if !caseInsensitive {
|
||||
return func(s string) (string, bool) {
|
||||
v, ok := environment[s]
|
||||
return v, ok
|
||||
}
|
||||
}
|
||||
// variable names must be treated case-insensitively.
|
||||
// Resolves in this way:
|
||||
// * Return the value if its name matches with the passed name case-sensitively.
|
||||
// * Otherwise, return the value if its lower-cased name matches lower-cased passed name.
|
||||
// * The value is indefinite if multiple variable matches.
|
||||
loweredEnvironment := make(map[string]string, len(environment))
|
||||
for k, v := range environment {
|
||||
loweredEnvironment[strings.ToLower(k)] = v
|
||||
}
|
||||
return func(s string) (string, bool) {
|
||||
v, ok := environment[s]
|
||||
if ok {
|
||||
return v, ok
|
||||
}
|
||||
v, ok = loweredEnvironment[strings.ToLower(s)]
|
||||
return v, ok
|
||||
}
|
||||
}
|
||||
115
pkg/compose/envresolver_test.go
Normal file
115
pkg/compose/envresolver_test.go
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
Copyright 2020 Docker Compose CLI authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package compose
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
)
|
||||
|
||||
func Test_EnvResolverWithCase(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
environment map[string]string
|
||||
caseInsensitive bool
|
||||
search string
|
||||
expectedValue string
|
||||
expectedOk bool
|
||||
}{
|
||||
{
|
||||
name: "case sensitive/case match",
|
||||
environment: map[string]string{
|
||||
"Env1": "Value1",
|
||||
"Env2": "Value2",
|
||||
},
|
||||
caseInsensitive: false,
|
||||
search: "Env1",
|
||||
expectedValue: "Value1",
|
||||
expectedOk: true,
|
||||
},
|
||||
{
|
||||
name: "case sensitive/case unmatch",
|
||||
environment: map[string]string{
|
||||
"Env1": "Value1",
|
||||
"Env2": "Value2",
|
||||
},
|
||||
caseInsensitive: false,
|
||||
search: "ENV1",
|
||||
expectedValue: "",
|
||||
expectedOk: false,
|
||||
},
|
||||
{
|
||||
name: "case sensitive/nil environment",
|
||||
environment: nil,
|
||||
caseInsensitive: false,
|
||||
search: "Env1",
|
||||
expectedValue: "",
|
||||
expectedOk: false,
|
||||
},
|
||||
{
|
||||
name: "case insensitive/case match",
|
||||
environment: map[string]string{
|
||||
"Env1": "Value1",
|
||||
"Env2": "Value2",
|
||||
},
|
||||
caseInsensitive: true,
|
||||
search: "Env1",
|
||||
expectedValue: "Value1",
|
||||
expectedOk: true,
|
||||
},
|
||||
{
|
||||
name: "case insensitive/case unmatch",
|
||||
environment: map[string]string{
|
||||
"Env1": "Value1",
|
||||
"Env2": "Value2",
|
||||
},
|
||||
caseInsensitive: true,
|
||||
search: "ENV1",
|
||||
expectedValue: "Value1",
|
||||
expectedOk: true,
|
||||
},
|
||||
{
|
||||
name: "case insensitive/unmatch",
|
||||
environment: map[string]string{
|
||||
"Env1": "Value1",
|
||||
"Env2": "Value2",
|
||||
},
|
||||
caseInsensitive: true,
|
||||
search: "Env3",
|
||||
expectedValue: "",
|
||||
expectedOk: false,
|
||||
},
|
||||
{
|
||||
name: "case insensitive/nil environment",
|
||||
environment: nil,
|
||||
caseInsensitive: true,
|
||||
search: "Env1",
|
||||
expectedValue: "",
|
||||
expectedOk: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
f := envResolverWithCase(test.environment, test.caseInsensitive)
|
||||
v, ok := f(test.search)
|
||||
assert.Equal(t, v, test.expectedValue)
|
||||
assert.Equal(t, ok, test.expectedOk)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
"github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
// ServiceHash compute configuration has for a service
|
||||
// ServiceHash computes the configuration hash for a service.
|
||||
func ServiceHash(o types.ServiceConfig) (string, error) {
|
||||
// remove the Build config when generating the service hash
|
||||
o.Build = nil
|
||||
|
||||
@@ -45,6 +45,17 @@ func (s *composeService) kill(ctx context.Context, projectName string, options a
|
||||
return err
|
||||
}
|
||||
|
||||
project := options.Project
|
||||
if project == nil {
|
||||
project, err = s.getProjectWithResources(ctx, containers, projectName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if !options.RemoveOrphans {
|
||||
containers = containers.filter(isService(project.ServiceNames()...))
|
||||
}
|
||||
if len(containers) == 0 {
|
||||
fmt.Fprintf(s.stderr(), "no container to kill")
|
||||
}
|
||||
|
||||
@@ -18,12 +18,14 @@ package compose
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
moby "github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/volume"
|
||||
"github.com/golang/mock/gomock"
|
||||
"gotest.tools/v3/assert"
|
||||
|
||||
@@ -51,6 +53,12 @@ func TestKillAll(t *testing.T) {
|
||||
Filters: filters.NewArgs(projectFilter(name)),
|
||||
}).Return(
|
||||
[]moby.Container{testContainer("service1", "123", false), testContainer("service1", "456", false), testContainer("service2", "789", false)}, nil)
|
||||
api.EXPECT().VolumeList(gomock.Any(), filters.NewArgs(projectFilter(strings.ToLower(testProject)))).
|
||||
Return(volume.VolumeListOKBody{}, nil)
|
||||
api.EXPECT().NetworkList(gomock.Any(), moby.NetworkListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
|
||||
Return([]moby.NetworkResource{
|
||||
{ID: "abc123", Name: "testProject_default"},
|
||||
}, nil)
|
||||
api.EXPECT().ContainerKill(anyCancellableContext(), "123", "").Return(nil)
|
||||
api.EXPECT().ContainerKill(anyCancellableContext(), "456", "").Return(nil)
|
||||
api.EXPECT().ContainerKill(anyCancellableContext(), "789", "").Return(nil)
|
||||
@@ -76,6 +84,12 @@ func TestKillSignal(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
api.EXPECT().ContainerList(ctx, listOptions).Return([]moby.Container{testContainer(serviceName, "123", false)}, nil)
|
||||
api.EXPECT().VolumeList(gomock.Any(), filters.NewArgs(projectFilter(strings.ToLower(testProject)))).
|
||||
Return(volume.VolumeListOKBody{}, nil)
|
||||
api.EXPECT().NetworkList(gomock.Any(), moby.NetworkListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
|
||||
Return([]moby.NetworkResource{
|
||||
{ID: "abc123", Name: "testProject_default"},
|
||||
}, nil)
|
||||
api.EXPECT().ContainerKill(anyCancellableContext(), "123", "SIGTERM").Return(nil)
|
||||
|
||||
err := tested.kill(ctx, name, compose.KillOptions{Services: []string{serviceName}, Signal: "SIGTERM"})
|
||||
@@ -110,9 +124,15 @@ func anyCancellableContext() gomock.Matcher {
|
||||
return gomock.AssignableToTypeOf(ctxWithCancel)
|
||||
}
|
||||
|
||||
func projectFilterListOpt() moby.ContainerListOptions {
|
||||
func projectFilterListOpt(withOneOff bool) moby.ContainerListOptions {
|
||||
filter := filters.NewArgs(
|
||||
projectFilter(strings.ToLower(testProject)),
|
||||
)
|
||||
if !withOneOff {
|
||||
filter.Add("label", fmt.Sprintf("%s=False", compose.OneoffLabel))
|
||||
}
|
||||
return moby.ContainerListOptions{
|
||||
Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))),
|
||||
Filters: filter,
|
||||
All: true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,11 +21,12 @@ import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/docker/compose/v2/pkg/utils"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/docker/compose/v2/pkg/utils"
|
||||
)
|
||||
|
||||
func (s *composeService) Logs(ctx context.Context, projectName string, consumer api.LogConsumer, options api.LogOptions) error {
|
||||
@@ -95,7 +96,7 @@ func (s *composeService) logContainers(ctx context.Context, consumer api.LogCons
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer r.Close() //nolint errcheck
|
||||
defer r.Close() //nolint:errcheck
|
||||
|
||||
name := getContainerNameWithoutProject(c)
|
||||
w := utils.GetWriter(func(line string) {
|
||||
|
||||
@@ -33,12 +33,16 @@ func (s *composeService) Pause(ctx context.Context, projectName string, options
|
||||
})
|
||||
}
|
||||
|
||||
func (s *composeService) pause(ctx context.Context, project string, options api.PauseOptions) error {
|
||||
containers, err := s.getContainers(ctx, project, oneOffExclude, false, options.Services...)
|
||||
func (s *composeService) pause(ctx context.Context, projectName string, options api.PauseOptions) error {
|
||||
containers, err := s.getContainers(ctx, projectName, oneOffExclude, false, options.Services...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if options.Project != nil {
|
||||
containers = containers.filter(isService(options.Project.ServiceNames()...))
|
||||
}
|
||||
|
||||
w := progress.ContextWriter(ctx)
|
||||
eg, ctx := errgroup.WithContext(ctx)
|
||||
containers.forEach(func(container moby.Container) {
|
||||
@@ -67,6 +71,10 @@ func (s *composeService) unPause(ctx context.Context, projectName string, option
|
||||
return err
|
||||
}
|
||||
|
||||
if options.Project != nil {
|
||||
containers = containers.filter(isService(options.Project.ServiceNames()...))
|
||||
}
|
||||
|
||||
w := progress.ContextWriter(ctx)
|
||||
eg, ctx := errgroup.WithContext(ctx)
|
||||
containers.forEach(func(container moby.Container) {
|
||||
|
||||
@@ -21,8 +21,6 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// logPrinter watch application containers an collect their logs
|
||||
@@ -99,7 +97,6 @@ func (p *printer) Run(ctx context.Context, cascadeStop bool, exitCodeFrom string
|
||||
exitCodeFrom = event.Service
|
||||
}
|
||||
if exitCodeFrom == event.Service {
|
||||
logrus.Error(event.ExitCode)
|
||||
exitCode = event.ExitCode
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,19 @@ func (s *composeService) Ps(ctx context.Context, projectName string, options api
|
||||
return nil, err
|
||||
}
|
||||
|
||||
project := options.Project
|
||||
if project == nil {
|
||||
project, err = s.getProjectWithResources(ctx, containers, projectName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(options.Services) == 0 {
|
||||
options.Services = project.ServiceNames()
|
||||
}
|
||||
|
||||
containers = containers.filter(isService(options.Services...))
|
||||
summary := make([]api.ContainerSummary, len(containers))
|
||||
eg, ctx := errgroup.WithContext(ctx)
|
||||
for i, container := range containers {
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
|
||||
moby "github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/volume"
|
||||
|
||||
compose "github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/docker/compose/v2/pkg/mocks"
|
||||
@@ -48,6 +49,8 @@ func TestPs(t *testing.T) {
|
||||
c2, inspect2 := containerDetails("service1", "456", "running", "", 0)
|
||||
c2.Ports = []moby.Port{{PublicPort: 80, PrivatePort: 90, IP: "localhost"}}
|
||||
c3, inspect3 := containerDetails("service2", "789", "exited", "", 130)
|
||||
api.EXPECT().VolumeList(ctx, gomock.Any()).Return(volume.VolumeListOKBody{}, nil)
|
||||
api.EXPECT().NetworkList(ctx, gomock.Any()).Return([]moby.NetworkResource{}, nil)
|
||||
api.EXPECT().ContainerList(ctx, listOpts).Return([]moby.Container{c1, c2, c3}, nil)
|
||||
api.EXPECT().ContainerInspect(anyCancellableContext(), "123").Return(inspect1, nil)
|
||||
api.EXPECT().ContainerInspect(anyCancellableContext(), "456").Return(inspect2, nil)
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
@@ -64,13 +65,16 @@ func (s *composeService) pull(ctx context.Context, project *types.Project, opts
|
||||
eg, ctx := errgroup.WithContext(ctx)
|
||||
|
||||
var mustBuild []string
|
||||
|
||||
imagesBeingPulled := map[string]string{}
|
||||
|
||||
for _, service := range project.Services {
|
||||
service := service
|
||||
if service.Image == "" {
|
||||
w.Event(progress.Event{
|
||||
ID: service.Name,
|
||||
Status: progress.Done,
|
||||
Text: "Skipped",
|
||||
Text: "Skipped - No image to be pulled",
|
||||
})
|
||||
continue
|
||||
}
|
||||
@@ -84,16 +88,27 @@ func (s *composeService) pull(ctx context.Context, project *types.Project, opts
|
||||
})
|
||||
continue
|
||||
case types.PullPolicyMissing, types.PullPolicyIfNotPresent:
|
||||
if _, ok := images[service.Image]; ok {
|
||||
if imageAlreadyPresent(service.Image, images) {
|
||||
w.Event(progress.Event{
|
||||
ID: service.Name,
|
||||
Status: progress.Done,
|
||||
Text: "Exists",
|
||||
Text: "Skipped - Image is already present locally",
|
||||
})
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if s, ok := imagesBeingPulled[service.Image]; ok {
|
||||
w.Event(progress.Event{
|
||||
ID: service.Name,
|
||||
Status: progress.Done,
|
||||
Text: fmt.Sprintf("Skipped - Image is already being pulled by %v", s),
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
imagesBeingPulled[service.Image] = service.Name
|
||||
|
||||
eg.Go(func() error {
|
||||
_, err := s.pullServiceImage(ctx, service, info, s.configFile(), w, false)
|
||||
if err != nil {
|
||||
@@ -118,6 +133,19 @@ func (s *composeService) pull(ctx context.Context, project *types.Project, opts
|
||||
return err
|
||||
}
|
||||
|
||||
func imageAlreadyPresent(serviceImage string, localImages map[string]string) bool {
|
||||
normalizedImage, err := reference.ParseDockerRef(serviceImage)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
tagged, ok := normalizedImage.(reference.NamedTagged)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
_, ok = localImages[serviceImage]
|
||||
return ok && tagged.Tag() != "latest"
|
||||
}
|
||||
|
||||
func (s *composeService) pullServiceImage(ctx context.Context, service types.ServiceConfig, info moby.Info, configFile driver.Auth, w progress.Writer, quietPull bool) (string, error) {
|
||||
w.Event(progress.Event{
|
||||
ID: service.Name,
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
|
||||
func (s *composeService) Remove(ctx context.Context, projectName string, options api.RemoveOptions) error {
|
||||
projectName = strings.ToLower(projectName)
|
||||
containers, _, err := s.actualState(ctx, projectName, options.Services)
|
||||
containers, err := s.getContainers(ctx, projectName, oneOffExclude, true, options.Services...)
|
||||
if err != nil {
|
||||
if api.IsNotFoundError(err) {
|
||||
fmt.Fprintln(s.stderr(), "No stopped containers")
|
||||
@@ -40,6 +40,10 @@ func (s *composeService) Remove(ctx context.Context, projectName string, options
|
||||
return err
|
||||
}
|
||||
|
||||
if options.Project != nil {
|
||||
containers = containers.filter(isService(options.Project.ServiceNames()...))
|
||||
}
|
||||
|
||||
stoppedContainers := containers.filter(func(c moby.Container) bool {
|
||||
return c.State != ContainerRunning
|
||||
})
|
||||
|
||||
@@ -34,15 +34,17 @@ func (s *composeService) Restart(ctx context.Context, projectName string, option
|
||||
}
|
||||
|
||||
func (s *composeService) restart(ctx context.Context, projectName string, options api.RestartOptions) error {
|
||||
|
||||
observedState, err := s.getContainers(ctx, projectName, oneOffExclude, true)
|
||||
containers, err := s.getContainers(ctx, projectName, oneOffExclude, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
project, err := s.projectFromName(observedState, projectName, options.Services...)
|
||||
if err != nil {
|
||||
return err
|
||||
project := options.Project
|
||||
if project == nil {
|
||||
project, err = s.getProjectWithResources(ctx, containers, projectName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(options.Services) == 0 {
|
||||
@@ -50,12 +52,12 @@ func (s *composeService) restart(ctx context.Context, projectName string, option
|
||||
}
|
||||
|
||||
w := progress.ContextWriter(ctx)
|
||||
err = InDependencyOrder(ctx, project, func(c context.Context, service string) error {
|
||||
return InDependencyOrder(ctx, project, func(c context.Context, service string) error {
|
||||
if !utils.StringContains(options.Services, service) {
|
||||
return nil
|
||||
}
|
||||
eg, ctx := errgroup.WithContext(ctx)
|
||||
for _, container := range observedState.filter(isService(service)) {
|
||||
for _, container := range containers.filter(isService(service)) {
|
||||
container := container
|
||||
eg.Go(func() error {
|
||||
eventName := getContainerProgressName(container)
|
||||
@@ -69,8 +71,4 @@ func (s *composeService) restart(ctx context.Context, projectName string, option
|
||||
}
|
||||
return eg.Wait()
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ func applyRunOptions(project *types.Project, service *types.ServiceConfig, opts
|
||||
if len(opts.Environment) > 0 {
|
||||
cmdEnv := types.NewMappingWithEquals(opts.Environment)
|
||||
serviceOverrideEnv := cmdEnv.Resolve(func(s string) (string, bool) {
|
||||
v, ok := project.Environment[s]
|
||||
v, ok := envResolver(project.Environment)(s)
|
||||
return v, ok
|
||||
}).RemoveEmpty()
|
||||
service.Environment.OverrideBy(serviceOverrideEnv)
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/docker/compose/v2/pkg/progress"
|
||||
"github.com/docker/compose/v2/pkg/utils"
|
||||
)
|
||||
|
||||
func (s *composeService) Stop(ctx context.Context, projectName string, options api.StopOptions) error {
|
||||
@@ -31,15 +32,28 @@ func (s *composeService) Stop(ctx context.Context, projectName string, options a
|
||||
}
|
||||
|
||||
func (s *composeService) stop(ctx context.Context, projectName string, options api.StopOptions) error {
|
||||
w := progress.ContextWriter(ctx)
|
||||
|
||||
containers, project, err := s.actualState(ctx, projectName, options.Services)
|
||||
containers, err := s.getContainers(ctx, projectName, oneOffExclude, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
project := options.Project
|
||||
if project == nil {
|
||||
project, err = s.getProjectWithResources(ctx, containers, projectName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(options.Services) == 0 {
|
||||
options.Services = project.ServiceNames()
|
||||
}
|
||||
|
||||
w := progress.ContextWriter(ctx)
|
||||
return InReverseDependencyOrder(ctx, project, func(c context.Context, service string) error {
|
||||
containersToStop := containers.filter(isService(service)).filter(isNotOneOff)
|
||||
return s.stopContainers(ctx, w, containersToStop, options.Timeout)
|
||||
if !utils.StringContains(options.Services, service) {
|
||||
return nil
|
||||
}
|
||||
return s.stopContainers(ctx, w, containers.filter(isService(service)).filter(isNotOneOff), options.Timeout)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ import (
|
||||
"github.com/docker/compose/v2/pkg/mocks"
|
||||
|
||||
moby "github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/volume"
|
||||
"github.com/golang/mock/gomock"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
@@ -40,12 +42,16 @@ func TestStopTimeout(t *testing.T) {
|
||||
cli.EXPECT().Client().Return(api).AnyTimes()
|
||||
|
||||
ctx := context.Background()
|
||||
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return(
|
||||
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(false)).Return(
|
||||
[]moby.Container{
|
||||
testContainer("service1", "123", false),
|
||||
testContainer("service1", "456", false),
|
||||
testContainer("service2", "789", false),
|
||||
}, nil)
|
||||
api.EXPECT().VolumeList(gomock.Any(), filters.NewArgs(projectFilter(strings.ToLower(testProject)))).
|
||||
Return(volume.VolumeListOKBody{}, nil)
|
||||
api.EXPECT().NetworkList(gomock.Any(), moby.NetworkListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
|
||||
Return([]moby.NetworkResource{}, nil)
|
||||
|
||||
timeout := time.Duration(2) * time.Second
|
||||
api.EXPECT().ContainerStop(gomock.Any(), "123", &timeout).Return(nil)
|
||||
|
||||
@@ -61,12 +61,12 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
|
||||
go func() {
|
||||
<-signalChan
|
||||
s.Kill(ctx, project.Name, api.KillOptions{ //nolint:errcheck
|
||||
Services: project.ServiceNames(),
|
||||
Services: options.Create.Services,
|
||||
})
|
||||
}()
|
||||
|
||||
return s.Stop(ctx, project.Name, api.StopOptions{
|
||||
Services: project.ServiceNames(),
|
||||
Services: options.Create.Services,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
46
pkg/e2e/assert.go
Normal file
46
pkg/e2e/assert.go
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright 2022 Docker Compose CLI authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// RequireServiceState ensures that the container is in the expected state
|
||||
// (running or exited).
|
||||
func RequireServiceState(t testing.TB, cli *CLI, service string, state string) {
|
||||
t.Helper()
|
||||
psRes := cli.RunDockerComposeCmd(t, "ps", "--format=json", service)
|
||||
var psOut []map[string]interface{}
|
||||
require.NoError(t, json.Unmarshal([]byte(psRes.Stdout()), &psOut),
|
||||
"Invalid `compose ps` JSON output")
|
||||
|
||||
for _, svc := range psOut {
|
||||
require.Equal(t, service, svc["Service"],
|
||||
"Found ps output for unexpected service")
|
||||
require.Equalf(t,
|
||||
strings.ToLower(state),
|
||||
strings.ToLower(svc["State"].(string)),
|
||||
"Service %q (%s) not in expected state",
|
||||
service, svc["Name"],
|
||||
)
|
||||
}
|
||||
}
|
||||
66
pkg/e2e/buffer.go
Normal file
66
pkg/e2e/buffer.go
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright 2022 Docker Compose CLI authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type lockedBuffer struct {
|
||||
mu sync.Mutex
|
||||
buf bytes.Buffer
|
||||
}
|
||||
|
||||
func (l *lockedBuffer) Read(p []byte) (n int, err error) {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
return l.buf.Read(p)
|
||||
}
|
||||
|
||||
func (l *lockedBuffer) Write(p []byte) (n int, err error) {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
return l.buf.Write(p)
|
||||
}
|
||||
|
||||
func (l *lockedBuffer) String() string {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
return l.buf.String()
|
||||
}
|
||||
|
||||
func (l *lockedBuffer) RequireEventuallyContains(t testing.TB, v string) {
|
||||
t.Helper()
|
||||
var bufContents strings.Builder
|
||||
require.Eventuallyf(t, func() bool {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
if _, err := l.buf.WriteTo(&bufContents); err != nil {
|
||||
require.FailNowf(t, "Failed to copy from buffer",
|
||||
"Error: %v", err)
|
||||
}
|
||||
return strings.Contains(bufContents.String(), v)
|
||||
}, 2*time.Second, 20*time.Millisecond,
|
||||
"Buffer did not contain %q\n============\n%s\n============",
|
||||
v, &bufContents)
|
||||
}
|
||||
@@ -34,7 +34,7 @@ func TestEnvPriority(t *testing.T) {
|
||||
})
|
||||
|
||||
// Full options activated
|
||||
// 1. Command Line (docker compose run --env <KEY[=VAL]>) <-- Result expected (From environment patched by --env-file)
|
||||
// 1. Command Line (docker compose run --env <KEY[=VAL]>) <-- Result expected (From OS Environment)
|
||||
// 2. Compose File (service::environment section)
|
||||
// 3. Compose File (service::env_file section file)
|
||||
// 4. Container Image ENV directive
|
||||
@@ -45,7 +45,7 @@ func TestEnvPriority(t *testing.T) {
|
||||
"run", "--rm", "-e", "WHEREAMI", "env-compose-priority")
|
||||
cmd.Env = append(cmd.Env, "WHEREAMI=shell")
|
||||
res := icmd.RunCmd(cmd)
|
||||
assert.Equal(t, strings.TrimSpace(res.Stdout()), "override")
|
||||
assert.Equal(t, strings.TrimSpace(res.Stdout()), "shell")
|
||||
})
|
||||
|
||||
// Full options activated
|
||||
@@ -63,7 +63,7 @@ func TestEnvPriority(t *testing.T) {
|
||||
})
|
||||
|
||||
// No Compose file, all other options
|
||||
// 1. Command Line (docker compose run --env <KEY[=VAL]>) <-- Result expected (From environment patched by --env-file)
|
||||
// 1. Command Line (docker compose run --env <KEY[=VAL]>) <-- Result expected (From OS Environment)
|
||||
// 2. Compose File (service::environment section)
|
||||
// 3. Compose File (service::env_file section file)
|
||||
// 4. Container Image ENV directive
|
||||
@@ -74,7 +74,7 @@ func TestEnvPriority(t *testing.T) {
|
||||
"run", "--rm", "-e", "WHEREAMI", "env-compose-priority")
|
||||
cmd.Env = append(cmd.Env, "WHEREAMI=shell")
|
||||
res := icmd.RunCmd(cmd)
|
||||
assert.Equal(t, strings.TrimSpace(res.Stdout()), "override")
|
||||
assert.Equal(t, strings.TrimSpace(res.Stdout()), "shell")
|
||||
})
|
||||
|
||||
// No Compose file, all other options with env variable from OS environment
|
||||
|
||||
@@ -79,7 +79,7 @@ func TestLocalComposeRun(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("down", func(t *testing.T) {
|
||||
c.RunDockerComposeCmd(t, "-f", "./fixtures/run-test/compose.yaml", "down")
|
||||
c.RunDockerComposeCmd(t, "-f", "./fixtures/run-test/compose.yaml", "down", "--remove-orphans")
|
||||
res := c.RunDockerCmd(t, "ps", "--all")
|
||||
assert.Assert(t, !strings.Contains(res.Stdout(), "run-test"), res.Stdout())
|
||||
})
|
||||
@@ -121,6 +121,7 @@ func TestLocalComposeRun(t *testing.T) {
|
||||
c.Env = append(c.Env, "COMPOSE_REMOVE_ORPHANS=True")
|
||||
})
|
||||
res := c.RunDockerCmd(t, "ps", "--all")
|
||||
|
||||
assert.Assert(t, !strings.Contains(res.Stdout(), "run-test"), res.Stdout())
|
||||
})
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ func TestLocalComposeUp(t *testing.T) {
|
||||
assert.Assert(t, strings.Contains(output, `"word":`))
|
||||
|
||||
res = c.RunDockerCmd(t, "network", "ls")
|
||||
res.Assert(t, icmd.Expected{Out: projectName + "-default"})
|
||||
res.Assert(t, icmd.Expected{Out: projectName + "_default"})
|
||||
})
|
||||
|
||||
t.Run("top", func(t *testing.T) {
|
||||
@@ -74,7 +74,7 @@ func TestLocalComposeUp(t *testing.T) {
|
||||
res.Assert(t, icmd.Expected{Out: `"com.docker.compose.service": "web"`})
|
||||
res.Assert(t, icmd.Expected{Out: `"com.docker.compose.version":`})
|
||||
|
||||
res = c.RunDockerCmd(t, "network", "inspect", projectName+"-default")
|
||||
res = c.RunDockerCmd(t, "network", "inspect", projectName+"_default")
|
||||
res.Assert(t, icmd.Expected{Out: `"com.docker.compose.network": "default"`})
|
||||
res.Assert(t, icmd.Expected{Out: `"com.docker.compose.project": `})
|
||||
res.Assert(t, icmd.Expected{Out: `"com.docker.compose.version": `})
|
||||
@@ -119,22 +119,12 @@ func TestLocalComposeUp(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestComposePull(t *testing.T) {
|
||||
c := NewParallelCLI(t)
|
||||
|
||||
res := c.RunDockerComposeCmd(t, "--project-directory", "fixtures/simple-composefile", "pull")
|
||||
output := res.Combined()
|
||||
|
||||
assert.Assert(t, strings.Contains(output, "simple Pulled"))
|
||||
assert.Assert(t, strings.Contains(output, "another Pulled"))
|
||||
}
|
||||
|
||||
func TestDownComposefileInParentFolder(t *testing.T) {
|
||||
c := NewParallelCLI(t)
|
||||
|
||||
tmpFolder, err := os.MkdirTemp("fixtures/simple-composefile", "test-tmp")
|
||||
assert.NilError(t, err)
|
||||
defer os.Remove(tmpFolder) // nolint: errcheck
|
||||
defer os.Remove(tmpFolder) //nolint:errcheck
|
||||
projectName := filepath.Base(tmpFolder)
|
||||
|
||||
res := c.RunDockerComposeCmd(t, "--project-directory", tmpFolder, "up", "-d")
|
||||
@@ -241,6 +231,6 @@ func TestConvert(t *testing.T) {
|
||||
default: null
|
||||
networks:
|
||||
default:
|
||||
name: compose-e2e-convert-default`, filepath.Join(wd, "fixtures", "simple-build-test", "nginx-build")), ExitCode: 0})
|
||||
name: compose-e2e-convert_default`, filepath.Join(wd, "fixtures", "simple-build-test", "nginx-build")), ExitCode: 0})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# syntax=docker/dockerfile:1.2
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
|
||||
# Copyright 2020 Docker Compose CLI authors
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# syntax=docker/dockerfile:1.2
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
|
||||
# Copyright 2020 Docker Compose CLI authors
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
services:
|
||||
simple:
|
||||
image: alpine:3.13
|
||||
command: top
|
||||
another:
|
||||
image: alpine:3.13
|
||||
command: top
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user