Compare commits

...

91 Commits

Author SHA1 Message Date
Guillaume Lours
a1aceba655 Merge pull request #11215 from docker/dependabot/go_modules/github.com/compose-spec/compose-go-1.20.2
build(deps): bump github.com/compose-spec/compose-go from 1.20.1 to 1.20.2
2023-11-22 14:29:48 +01:00
dependabot[bot]
a39cf75e86 build(deps): bump github.com/compose-spec/compose-go
Bumps [github.com/compose-spec/compose-go](https://github.com/compose-spec/compose-go) from 1.20.1 to 1.20.2.
- [Release notes](https://github.com/compose-spec/compose-go/releases)
- [Commits](https://github.com/compose-spec/compose-go/compare/v1.20.1...v1.20.2)

---
updated-dependencies:
- dependency-name: github.com/compose-spec/compose-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-22 14:19:50 +01:00
Guillaume Lours
5b0dcc5a44 Merge pull request #11214 from docker/dependabot/go_modules/github.com/spf13/cobra-1.8.0
build(deps): bump github.com/spf13/cobra from 1.7.0 to 1.8.0
2023-11-22 14:19:27 +01:00
dependabot[bot]
46ba9c99ce build(deps): bump github.com/spf13/cobra from 1.7.0 to 1.8.0
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.7.0 to 1.8.0.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.7.0...v1.8.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-22 09:43:55 +00:00
Guillaume Lours
1148b6765a Merge pull request #11142 from docker/dependabot/go_modules/github.com/docker/cli-24.0.7incompatible
build(deps): bump github.com/docker/cli from 24.0.6+incompatible to 24.0.7+incompatible
2023-11-22 10:15:33 +01:00
dependabot[bot]
5c5d30c674 build(deps): bump github.com/docker/cli
Bumps [github.com/docker/cli](https://github.com/docker/cli) from 24.0.6+incompatible to 24.0.7+incompatible.
- [Commits](https://github.com/docker/cli/compare/v24.0.6...v24.0.7)

---
updated-dependencies:
- dependency-name: github.com/docker/cli
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-22 09:55:15 +01:00
Guillaume Lours
2068eceee4 Merge pull request #11143 from docker/dependabot/go_modules/github.com/docker/docker-24.0.7incompatible
build(deps): bump github.com/docker/docker from 24.0.6+incompatible to 24.0.7+incompatible
2023-11-22 09:54:14 +01:00
dependabot[bot]
36fa8d4e71 build(deps): bump github.com/docker/docker
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 24.0.6+incompatible to 24.0.7+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v24.0.6...v24.0.7)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-22 09:43:45 +01:00
Guillaume Lours
69985b8b89 Merge pull request #11112 from docker/dependabot/go_modules/github.com/moby/buildkit-0.12.3
build(deps): bump github.com/moby/buildkit from 0.12.2 to 0.12.3
2023-11-22 09:43:06 +01:00
dependabot[bot]
2384635ee1 build(deps): bump github.com/moby/buildkit from 0.12.2 to 0.12.3
Bumps [github.com/moby/buildkit](https://github.com/moby/buildkit) from 0.12.2 to 0.12.3.
- [Release notes](https://github.com/moby/buildkit/releases)
- [Commits](https://github.com/moby/buildkit/compare/v0.12.2...v0.12.3)

---
updated-dependencies:
- dependency-name: github.com/moby/buildkit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-22 09:33:44 +01:00
Guillaume Lours
587dba1167 Merge pull request #11213 from glours/watch-force-build-at-startup
in watch mode force pull policy to build for services with both build and develop attributes
2023-11-22 09:32:15 +01:00
Guillaume Lours
2ba5e4c1d0 in watch mode force pull policy to build for services with both build and develop attributes
This default behaviour will force a rebuild of the service images at watch process startup and be sure containers will be in sync with the local source code

Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2023-11-21 16:42:43 +01:00
Nicolas De Loof
b1a26dac1d Assume /src/pkg/compose/testdata absolute workingdir to make tests reproducible
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-21 16:11:42 +01:00
Guillaume Lours
0ab21a2080 Merge pull request #11211 from ndeloof/Services
avoir use of []types.ServiceConfig
2023-11-21 12:17:09 +01:00
Nicolas De Loof
5e77ae9247 avoir use of []types.ServiceConfig
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-21 12:08:12 +01:00
Guillaume Lours
f557220140 identify services to build and don't display 'building' if none
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2023-11-21 11:35:11 +01:00
Nicolas De Loof
8e1b32365e fix --remove-orphans not to consider disabled services as orphaned
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-20 21:35:13 +01:00
Guillaume Lours
a1b7bee094 Merge pull request #11206 from ndeloof/check_runtime
introduce RuntimeVersion for code to check container runtime support
2023-11-20 11:59:43 +01:00
Nicolas De Loof
7cb1f8baf2 introduce RuntimeVersion for code to check container runtime supports required features
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-20 11:45:16 +01:00
Nicolas De Loof
cb01186c2b push also consider build.tags
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-17 16:31:52 +01:00
Ulysses Souza
efea084df6 Merge pull request #11192 from ulyssessouza/exclude-tests-context 2023-11-16 12:25:13 +01:00
Nicolas De Loof
9c4efbdd92 Strip project prefix from docker-compose up output
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-15 21:39:16 +01:00
Ulysses Souza
8ea7c9e0d2 Make it context aware and add test skipping options
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2023-11-15 21:09:50 +01:00
Nicolas De Loof
c16943609c render quiet after filtering applied
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-15 20:25:40 +01:00
Guillaume Lours
254a94b07d bump golang to version 1.21.4
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2023-11-13 22:16:33 +01:00
Nicolas De Loof
cf608fa954 bump compose-go to v1.20.1
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-13 22:07:02 +01:00
Nicolas De Loof
426377a4c9 reject compose file using secrets|configs.driver or template_driver
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-13 17:26:00 +01:00
Guillaume Lours
43c3f54598 Merge pull request #11180 from ulyssessouza/skip-flaky-tests
skips flaky e2e tests on watch and attach
2023-11-10 19:51:00 +01:00
Ulysses Souza
493f6c8055 skips flaky e2e tests on watch and attach
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2023-11-10 18:31:25 +01:00
Guillaume Lours
c1a9ffa07e Merge pull request #11171 from szampardi/main
fix docker/compose#11170 add newline in cmd/compose/build.go fmt.Fprint
2023-11-08 23:23:16 +01:00
szampardi
646a8fc0e8 fix docker/compose#11170 add newline in cmd/compose/build.go fmt.Fprint
Signed-off-by: szampardi <szampardi@deepnull.com>
2023-11-08 16:17:23 +01:00
Nicolas De Loof
2945532f97 fix --pull documentation
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-07 09:03:49 +01:00
Guillaume Lours
e5cd265abb improve watch configuration logging
Add action associated to each managed path

Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2023-11-06 13:48:15 +01:00
Nicolas De Loof
d646d757a2 lint
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-02 11:16:35 +01:00
Nicolas De Loof
71237ef62b do not resolve cache dir until remote resource is in use
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-02 11:16:35 +01:00
Nicolas De Loof
0d905a896d add a copyright notice with original author
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-02 11:16:35 +01:00
Nicolas De Loof
b847c7f5a4 implement runtime file selection
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-02 11:16:35 +01:00
Nicolas De Loof
5e3d8f671d re-implement cache folder detection
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-02 11:16:35 +01:00
Nicolas De Loof
6727908803 introduce --resolve-image-digests for publish to seal service images by digest
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-02 10:43:45 +01:00
Guillaume Lours
5661fd1bfe Merge pull request #11149 from aevesdocker/ENGDOCS-1764
ENGDOCS-1764: Trivial fixes
2023-11-02 10:30:10 +01:00
aevesdocker
4cd61957ed fix build
Signed-off-by: aevesdocker <allie.sadler@docker.com>
2023-10-31 10:50:42 +00:00
aevesdocker
0d4cbbdbc9 fix
Signed-off-by: aevesdocker <allie.sadler@docker.com>
2023-10-31 10:44:59 +00:00
aevesdocker
9631a49daa ENGDOCS-1764
Signed-off-by: aevesdocker <allie.sadler@docker.com>
2023-10-31 10:40:48 +00:00
David Karlsson
328ca3f239 add docs upstream validation workflow
verifies that the reference docs don't contain broken links etc

Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
2023-10-30 18:36:30 +01:00
dependabot[bot]
e1bbfc6376 build(deps): bump go.uber.org/goleak from 1.2.1 to 1.3.0
Bumps [go.uber.org/goleak](https://github.com/uber-go/goleak) from 1.2.1 to 1.3.0.
- [Release notes](https://github.com/uber-go/goleak/releases)
- [Changelog](https://github.com/uber-go/goleak/blob/master/CHANGELOG.md)
- [Commits](https://github.com/uber-go/goleak/compare/v1.2.1...v1.3.0)

---
updated-dependencies:
- dependency-name: go.uber.org/goleak
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-30 08:18:38 +01:00
kimdcottrell
616bba0afd linter errors fixed
Signed-off-by: kimdcottrell <me@kimdcottrell.com>
2023-10-29 22:08:00 +01:00
kimdcottrell
ee6e3c2a44 NetworkList to NetworkInspect for ID search
Signed-off-by: kimdcottrell <me@kimdcottrell.com>
2023-10-29 22:08:00 +01:00
kimdcottrell
c7e31a3c15 Squashing feature branch commits in order to add signoff message.
- added clarity with error handling. added test to show issue.

- in manual testing, this fixes the issue and allows watch to run after rebuild

- added cleanup back in

- fixed issue where watch extnet rebuild test would start all containers listed in the fixture

Signed-off-by: kimdcottrell <me@kimdcottrell.com>
2023-10-29 22:08:00 +01:00
Matthew Walowski
704a9fd337 Use project.ServiceNames() if no service specified in hash
Signed-off-by: Matthew Walowski <mattwalowski@gmail.com>
2023-10-27 21:16:15 +02:00
temenuzhka-thede
d9e0e42d95 Add branch configuration for pull_request trigger
Signed-off-by: temenuzhka-thede <temenuzhka.thede@docker.com>

Add check-latest option to set up go step

Signed-off-by: temenuzhka-thede <temenuzhka.thede@docker.com>
2023-10-27 09:17:32 +02:00
temenuzhka-thede
c48e3c4a4f Initial codeql.yml commit
Signed-off-by: temenuzhka-thede <temenuzhka.thede@docker.com>

add new line

Signed-off-by: temenuzhka-thede <temenuzhka.thede@docker.com>

remove new line

Signed-off-by: temenuzhka-thede <temenuzhka.thede@docker.com>

remove new line

Signed-off-by: temenuzhka-thede <temenuzhka.thede@docker.com>

remove new line

Signed-off-by: temenuzhka-thede <temenuzhka.thede@docker.com>

remove new line

Signed-off-by: temenuzhka-thede <temenuzhka.thede@docker.com>

remove new line

Signed-off-by: temenuzhka-thede <temenuzhka.thede@docker.com>

remove os customization

Signed-off-by: temenuzhka-thede <temenuzhka.thede@docker.com>

remove os customization

Signed-off-by: temenuzhka-thede <temenuzhka.thede@docker.com>
2023-10-27 09:17:32 +02:00
Nicolas De Loof
dd0803dba1 fix SIGTERM support to stop/kill stack
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-10-26 12:19:50 +02:00
Nicolas De Loof
39008c539c align with OCI artifact best practices
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-10-23 20:26:13 +02:00
Guillaume Lours
6ab41d629f Merge pull request #11060 from Juneezee/refactor/redundant-len-check
refactor(cmd/compose/run): remove redundant `len` check
2023-10-23 10:32:46 +02:00
Eng Zer Jun
6c345b3755 refactor(cmd/compose/run): remove redundant len check
From the Go specification [1]:

  "1. For a nil slice, the number of iterations is 0."

`len` returns 0 if the slice is nil [2]. Therefore, checking
`len(v) > 0` before a loop is unnecessary.

[1]: https://go.dev/ref/spec#For_range
[2]: https://pkg.go.dev/builtin#len

Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
2023-10-23 16:06:52 +08:00
Guillaume Lours
b8773ad1c5 Merge pull request #11110 from ndeloof/wait_missing
fail start if depependency is missing
2023-10-19 10:04:32 +02:00
Nicolas De Loof
1ffa194e12 fail start if depependency is missing
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-10-19 09:50:37 +02:00
Guillaume Lours
b92981015e check that the pull policy provided is a valid one
or is not missing when --pull is used

Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2023-10-18 15:44:37 +02:00
Guillaume Lours
af87f10650 Merge pull request #11108 from ndeloof/down-services
enable profile when down is ran with explicit service names
2023-10-18 13:49:11 +02:00
Guillaume Lours
5e1d3f2b41 Merge pull request #11051 from ndeloof/warn_remote_disabled
warn user remote resource is disabled
2023-10-18 12:54:40 +02:00
Guillaume Lours
3d0207ebc8 remove uncessary return value of pullComposeFiles function
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2023-10-18 12:42:11 +02:00
Nicolas De Loof
16a7c20960 enable profile when down is ran with explicit service names
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-10-18 12:19:45 +02:00
Guillaume Lours
818bc3c34a add sync+restart action to watch attribute
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2023-10-18 12:11:02 +02:00
Guillaume Lours
cf3e686d8c Merge pull request #11078 from docker/dependabot/go_modules/github.com/containerd/containerd-1.7.7
build(deps): bump github.com/containerd/containerd from 1.7.6 to 1.7.7
2023-10-18 11:35:04 +02:00
dependabot[bot]
38bc6d5dbc build(deps): bump github.com/containerd/containerd from 1.7.6 to 1.7.7
Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.6 to 1.7.7.
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v1.7.6...v1.7.7)

---
updated-dependencies:
- dependency-name: github.com/containerd/containerd
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-18 11:20:06 +02:00
Guillaume Lours
4a2d4c44b2 Merge pull request #11083 from docker/dependabot/go_modules/github.com/google/go-cmp-0.6.0
build(deps): bump github.com/google/go-cmp from 0.5.9 to 0.6.0
2023-10-18 11:18:06 +02:00
dependabot[bot]
0b6ce6ee42 build(deps): bump github.com/google/go-cmp from 0.5.9 to 0.6.0
Bumps [github.com/google/go-cmp](https://github.com/google/go-cmp) from 0.5.9 to 0.6.0.
- [Release notes](https://github.com/google/go-cmp/releases)
- [Commits](https://github.com/google/go-cmp/compare/v0.5.9...v0.6.0)

---
updated-dependencies:
- dependency-name: github.com/google/go-cmp
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-18 11:03:14 +02:00
Guillaume Lours
034458dac7 Merge pull request #11105 from docker/dependabot/go_modules/google.golang.org/grpc-1.59.0
build(deps): bump google.golang.org/grpc from 1.58.2 to 1.59.0
2023-10-18 11:00:43 +02:00
dependabot[bot]
ae16bbbf05 build(deps): bump google.golang.org/grpc from 1.58.2 to 1.59.0
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.58.2 to 1.59.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.58.2...v1.59.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-18 08:45:06 +00:00
Guillaume Lours
eb5f01baf4 Merge pull request #11068 from docker/dependabot/go_modules/golang.org/x/sync-0.4.0
build(deps): bump golang.org/x/sync from 0.3.0 to 0.4.0
2023-10-18 10:44:00 +02:00
dependabot[bot]
d13ad1f997 build(deps): bump golang.org/x/sync from 0.3.0 to 0.4.0
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.3.0 to 0.4.0.
- [Commits](https://github.com/golang/sync/compare/v0.3.0...v0.4.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-18 10:27:48 +02:00
Guillaume Lours
9b4d577c65 remove refrecence docs generation
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2023-10-11 14:19:56 +02:00
Guillaume Lours
b30978fb40 Merge pull request #11076 from glours/remove-cucumber
remove cucumber tests as we haven't added new ones for a while
2023-10-10 23:16:33 +02:00
Guillaume Lours
14b43c1a93 remove cucumber tests as we haven't added new ones for a while
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2023-10-10 09:57:25 +02:00
Guillaume Lours
9dd081b92e add support of COMPOSE_ENV_FILES env variable to pass a list of env files
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2023-10-05 21:55:43 +02:00
Guillaume Lours
2c0b023273 add dry-run support for publish command
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2023-10-05 21:55:00 +02:00
Nicolas De Loof
599e4b242a extract method to reduce cyclomatic complexity
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-09-29 10:18:11 +02:00
Nicolas De Loof
fe8c2780c8 warn user remote resource is disabled
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-09-29 09:30:38 +02:00
Matthew Walowski
a345515f91 Don't delete dependent services
Signed-off-by: Matthew Walowski <mattwalowski@gmail.com>
2023-09-29 06:43:16 +02:00
Matthew Walowski
8967df7a91 Apply platform before hashing
Signed-off-by: Matthew Walowski <mattwalowski@gmail.com>
2023-09-29 06:43:16 +02:00
Matthieu MOREL
4f694919ff deps: remove deprecated github.com/pkg/errors
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2023-09-29 06:28:58 +02:00
Matthew Walowski
6ecab95775 Include image name in error message
Signed-off-by: Matthew Walowski <mattwalowski@gmail.com>
2023-09-29 06:25:10 +02:00
Bjorn Neergaard
12e0ac898a pkg/compose/publish: use empty config descriptor mediaType
Signed-off-by: Bjorn Neergaard <bjorn.neergaard@docker.com>
2023-09-29 05:27:14 +02:00
Bjorn Neergaard
a6b7d78575 pkg/remote/oci: check artifactType instead of config.mediaType
Signed-off-by: Bjorn Neergaard <bjorn.neergaard@docker.com>
2023-09-29 05:27:14 +02:00
Bjorn Neergaard
991901f2ef pkg/remote/oci: refer to the manifest as manifest
Signed-off-by: Bjorn Neergaard <bjorn.neergaard@docker.com>
2023-09-29 05:27:14 +02:00
Guillaume Lours
bd74a9260d Merge pull request #11047 from glours/update-watch-warning-section
update the watch warning message when no services with a develop section
2023-09-27 23:41:53 +02:00
Guillaume Lours
2d971fc97d update the watch warning message when no services with a develop section
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2023-09-27 23:28:45 +02:00
Djordje Lukic
78f3361921 ci: enable verbose output for e2e tests (#11045)
It's easier to see that something is happening.

Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
2023-09-27 16:29:54 +00:00
Nicolas De Loof
44d21280e7 truncate command by default, introduce --no-trunc flag to get the full command
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-09-23 06:34:26 +02:00
Guillaume Lours
cd743d17ba Merge pull request #11036 from docker/dependabot/go_modules/google.golang.org/grpc-1.58.2
build(deps): bump google.golang.org/grpc from 1.58.1 to 1.58.2
2023-09-22 11:23:05 +02:00
dependabot[bot]
ff2ff18cdc build(deps): bump google.golang.org/grpc from 1.58.1 to 1.58.2
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.58.1 to 1.58.2.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.58.1...v1.58.2)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-22 09:10:26 +00:00
123 changed files with 1602 additions and 1059 deletions

View File

@@ -138,7 +138,6 @@ jobs:
mode:
- plugin
- standalone
- cucumber
steps:
-
name: Checkout
@@ -198,11 +197,6 @@ jobs:
rm -f /usr/local/bin/docker-compose
cp bin/build/docker-compose /usr/local/bin
make e2e-compose-standalone
-
name: Run cucumber tests
if: ${{ matrix.mode == 'cucumber'}}
run: |
make test-cucumber
coverage:
runs-on: ubuntu-22.04

58
.github/workflows/codeql.yml vendored Normal file
View File

@@ -0,0 +1,58 @@
name: codeql
on:
push:
branches:
- 'main'
paths-ignore:
- '**/*.md'
- '**/*.txt'
- '**/*.yaml'
- '**/*_test.go'
pull_request:
branches:
- 'main'
paths-ignore:
- '**/*.md'
- '**/*.txt'
- '**/*.yaml'
- '**/*_test.go'
jobs:
analyze:
name: Analyze
runs-on: 'ubuntu-latest'
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language:
- go
steps:
-
name: Checkout
uses: actions/checkout@v4
-
name: Set up Go
uses: actions/setup-go@v4
with:
go-version-file: go.mod
check-latest: true
-
name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
-
name: Autobuild
uses: github/codeql-action/autobuild@v2
-
name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"

42
.github/workflows/docs-upstream.yml vendored Normal file
View File

@@ -0,0 +1,42 @@
# this workflow runs the remote validate bake target from docker/docs
# to check if yaml reference docs used in this repo are valid
name: docs-upstream
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
push:
branches:
- 'main'
- 'v[0-9]*'
paths:
- '.github/workflows/docs-upstream.yml'
- 'docs/**'
pull_request:
paths:
- '.github/workflows/docs-upstream.yml'
- 'docs/**'
jobs:
docs-yaml:
runs-on: ubuntu-22.04
steps:
-
name: Checkout
uses: actions/checkout@v4
-
name: Upload reference YAML docs
uses: actions/upload-artifact@v3
with:
name: docs-yaml
path: docs/reference
retention-days: 1
validate:
uses: docker/docs/.github/workflows/validate-upstream.yml@main
needs:
- docs-yaml
with:
module-name: docker/compose

View File

@@ -1,56 +0,0 @@
name: Docs
on:
release:
types: [published]
permissions: {}
jobs:
open-pr:
permissions:
contents: write # to create branch (peter-evans/create-pull-request)
pull-requests: write # to create a PR (peter-evans/create-pull-request)
runs-on: ubuntu-latest
steps:
-
name: Checkout docs repo
uses: actions/checkout@v3
with:
token: ${{ secrets.GHPAT_DOCS_DISPATCH }}
repository: docker/docs
ref: main
-
name: Prepare
run: |
rm -rf ./_data/compose-cli/*
-
name: Build
uses: docker/build-push-action@v3
with:
context: ${{ github.server_url }}/${{ github.repository }}.git#${{ github.event.release.name }}
target: docs-reference
outputs: ./_data/compose-cli
-
name: Update compose_version in _config.yml
run: |
sed -i "s|^compose_version\:.*|compose_version\: \"${{ github.event.release.name }}\"|g" _config.yml
cat _config.yml | yq .compose_version
-
name: Commit changes
run: |
git add -A .
-
name: Create PR on docs repo
uses: peter-evans/create-pull-request@923ad837f191474af6b1721408744feb989a4c27 # v4.0.4
with:
token: ${{ secrets.GHPAT_DOCS_DISPATCH }}
push-to-fork: docker-tools-robot/docker.github.io
commit-message: Update Compose reference API to ${{ github.event.release.name }}
signoff: true
branch: dispatch/compose-api-reference-${{ github.event.release.name }}
delete-branch: true
title: Update Compose reference API to ${{ github.event.release.name }}
body: |
Update the Compose reference API documentation to keep in sync with the latest release `${{ github.event.release.name }}`
draft: false

View File

@@ -7,6 +7,7 @@ linters:
enable:
- depguard
- errcheck
- errorlint
- gocritic
- gocyclo
- gofmt
@@ -40,6 +41,11 @@ linters-settings:
desc: 'compose-go uses yaml.v3'
gomodguard:
blocked:
modules:
- github.com/pkg/errors:
recommendations:
- errors
- fmt
versions:
- github.com/distribution/distribution:
reason: "use distribution/reference"

View File

@@ -15,7 +15,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
ARG GO_VERSION=1.21.1
ARG GO_VERSION=1.21.4
ARG XX_VERSION=1.2.1
ARG GOLANGCI_LINT_VERSION=v1.54.2
ARG ADDLICENSE_VERSION=v1.0.0
@@ -192,9 +192,3 @@ RUN --mount=from=binary \
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 docs.docker.com.
# see open-pr job in .github/workflows/docs.yml for more details
FROM scratch AS docs-reference
COPY docs/reference/*.yaml .

View File

@@ -32,9 +32,13 @@ endif
BUILD_FLAGS?=
TEST_FLAGS?=
E2E_TEST?=
ifeq ($(E2E_TEST),)
else
TEST_FLAGS=-run $(E2E_TEST)
ifneq ($(E2E_TEST),)
TEST_FLAGS:=$(TEST_FLAGS) -run '$(E2E_TEST)'
endif
EXCLUDE_E2E_TESTS?=
ifneq ($(EXCLUDE_E2E_TESTS),)
TEST_FLAGS:=$(TEST_FLAGS) -skip '$(EXCLUDE_E2E_TESTS)'
endif
BUILDX_CMD ?= docker buildx
@@ -71,16 +75,12 @@ install: binary
.PHONY: e2e-compose
e2e-compose: ## Run end to end local tests in plugin mode. Set E2E_TEST=TestName to run a single test
go test $(TEST_FLAGS) -count=1 ./pkg/e2e
go test -v $(TEST_FLAGS) -count=1 ./pkg/e2e
.PHONY: e2e-compose-standalone
e2e-compose-standalone: ## Run End to end local tests in standalone mode. Set E2E_TEST=TestName to run a single test
go test $(TEST_FLAGS) -v -count=1 -parallel=1 --tags=standalone ./pkg/e2e
.PHONY: test-cucumber
test-cucumber:
go test $(TEST_FLAGS) -v -count=1 -parallel=1 ./e2e
.PHONY: build-and-e2e-compose
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

View File

@@ -96,7 +96,7 @@ func buildCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
opts.ssh = "default"
}
if cmd.Flags().Changed("progress") && opts.ssh == "" {
fmt.Fprint(os.Stderr, "--progress is a global compose flag, better use `docker compose --progress xx build ...")
fmt.Fprint(os.Stderr, "--progress is a global compose flag, better use `docker compose --progress xx build ...\n")
}
return runBuild(ctx, dockerCli, backend, opts, args)
}),

View File

@@ -18,6 +18,7 @@ package compose
import (
"context"
"errors"
"fmt"
"os"
"os/signal"
@@ -37,7 +38,6 @@ import (
"github.com/docker/cli/cli/command"
"github.com/docker/compose/v2/pkg/remote"
"github.com/morikuni/aec"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
@@ -60,6 +60,8 @@ const (
ComposeRemoveOrphans = "COMPOSE_REMOVE_ORPHANS"
// ComposeIgnoreOrphans ignore "orphaned" containers
ComposeIgnoreOrphans = "COMPOSE_IGNORE_ORPHANS"
// ComposeEnvFiles defines the env files to use if --env-file isn't used
ComposeEnvFiles = "COMPOSE_ENV_FILES"
)
// Command defines a compose CLI command as a func with args
@@ -81,6 +83,8 @@ func AdaptCmd(fn CobraCommand) func(cmd *cobra.Command, args []string) error {
go func() {
<-s
cancel()
signal.Stop(s)
close(s)
}()
}
err := fn(ctx, cmd, args)
@@ -200,11 +204,7 @@ func (o *ProjectOptions) toProjectName(dockerCli command.Cli) (string, error) {
func (o *ProjectOptions) ToProject(dockerCli command.Cli, services []string, po ...cli.ProjectOptionsFn) (*types.Project, error) {
if !o.Offline {
var err error
po, err = o.configureRemoteLoaders(dockerCli, po)
if err != nil {
return nil, err
}
po = o.configureRemoteLoaders(dockerCli, po)
}
options, err := o.toProjectOptions(po...)
@@ -251,31 +251,12 @@ func (o *ProjectOptions) ToProject(dockerCli command.Cli, services []string, po
return project, err
}
func (o *ProjectOptions) configureRemoteLoaders(dockerCli command.Cli, po []cli.ProjectOptionsFn) ([]cli.ProjectOptionsFn, error) {
enabled, err := remote.GitRemoteLoaderEnabled()
if err != nil {
return nil, err
}
if enabled {
git, err := remote.NewGitRemoteLoader(o.Offline)
if err != nil {
return nil, err
}
po = append(po, cli.WithResourceLoader(git))
}
func (o *ProjectOptions) configureRemoteLoaders(dockerCli command.Cli, po []cli.ProjectOptionsFn) []cli.ProjectOptionsFn {
git := remote.NewGitRemoteLoader(o.Offline)
oci := remote.NewOCIRemoteLoader(dockerCli, o.Offline)
enabled, err = remote.OCIRemoteLoaderEnabled()
if err != nil {
return nil, err
}
if enabled {
git, err := remote.NewOCIRemoteLoader(dockerCli, o.Offline)
if err != nil {
return nil, err
}
po = append(po, cli.WithResourceLoader(git))
}
return po, nil
po = append(po, cli.WithResourceLoader(git), cli.WithResourceLoader(oci))
return po
}
func (o *ProjectOptions) toProjectOptions(po ...cli.ProjectOptionsFn) (*cli.ProjectOptions, error) {
@@ -517,6 +498,11 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command { //
}
func setEnvWithDotEnv(prjOpts *ProjectOptions) error {
if len(prjOpts.EnvFiles) == 0 {
if envFiles := os.Getenv(ComposeEnvFiles); envFiles != "" {
prjOpts.EnvFiles = strings.Split(envFiles, ",")
}
}
options, err := prjOpts.toProjectOptions()
if err != nil {
return compose.WrapComposeError(err)

View File

@@ -25,7 +25,7 @@ import (
func TestFilterServices(t *testing.T) {
p := &types.Project{
Services: []types.ServiceConfig{
Services: types.Services{
{
Name: "foo",
Links: []string{"bar"},

View File

@@ -186,20 +186,27 @@ func runHash(ctx context.Context, dockerCli command.Cli, opts configOptions) err
return err
}
if len(services) > 0 {
err = project.ForServices(services, types.IgnoreDependencies)
if err := applyPlatforms(project, true); err != nil {
return err
}
if len(services) == 0 {
services = project.ServiceNames()
}
sorted := services
sort.Slice(sorted, func(i, j int) bool {
return sorted[i] < sorted[j]
})
for _, name := range sorted {
s, err := project.GetService(name)
if err != nil {
return err
}
}
sorted := project.Services
sort.Slice(sorted, func(i, j int) bool {
return sorted[i].Name < sorted[j].Name
})
for _, s := range sorted {
hash, err := compose.ServiceHash(s)
if err != nil {
return err
}

View File

@@ -19,6 +19,7 @@ package compose
import (
"context"
"fmt"
"slices"
"strconv"
"strings"
"time"
@@ -73,7 +74,7 @@ func createCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service
flags := cmd.Flags()
flags.BoolVar(&opts.Build, "build", false, "Build images before starting containers.")
flags.BoolVar(&opts.noBuild, "no-build", false, "Don't build an image, even if it's policy.")
flags.StringVar(&opts.Pull, "pull", "policy", `Pull image before running ("always"|"policy"|"never")`)
flags.StringVar(&opts.Pull, "pull", "policy", `Pull image before running ("always"|"missing"|"never"|"build")`)
flags.BoolVar(&opts.forceRecreate, "force-recreate", false, "Recreate containers even if their configuration and image haven't changed.")
flags.BoolVar(&opts.noRecreate, "no-recreate", false, "If containers already exist, don't recreate them. Incompatible with --force-recreate.")
flags.BoolVar(&opts.removeOrphans, "remove-orphans", false, "Remove containers for services not defined in the Compose file.")
@@ -138,6 +139,9 @@ func (opts createOptions) GetTimeout() *time.Duration {
func (opts createOptions) Apply(project *types.Project) error {
if opts.pullChanged {
if !opts.isPullPolicyValid() {
return fmt.Errorf("invalid --pull option %q", opts.Pull)
}
for i, service := range project.Services {
service.PullPolicy = opts.Pull
project.Services[i] = service
@@ -187,3 +191,9 @@ func (opts createOptions) Apply(project *types.Project) error {
}
return nil
}
func (opts createOptions) isPullPolicyValid() bool {
pullPolicies := []string{types.PullPolicyAlways, types.PullPolicyNever, types.PullPolicyBuild,
types.PullPolicyMissing, types.PullPolicyIfNotPresent}
return slices.Contains(pullPolicies, opts.Pull)
}

View File

@@ -78,7 +78,7 @@ func downCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
}
func runDown(ctx context.Context, dockerCli command.Cli, backend api.Service, opts downOptions, services []string) error {
project, name, err := opts.projectOrName(dockerCli)
project, name, err := opts.projectOrName(dockerCli, services...)
if err != nil {
return err
}

View File

@@ -72,12 +72,6 @@ func runList(ctx context.Context, dockerCli command.Cli, backend api.Service, ls
if err != nil {
return err
}
if lsOpts.Quiet {
for _, s := range stackList {
fmt.Fprintln(dockerCli.Out(), s.Name)
}
return nil
}
if filters.Len() > 0 {
var filtered []api.Stack
@@ -90,6 +84,13 @@ func runList(ctx context.Context, dockerCli command.Cli, backend api.Service, ls
stackList = filtered
}
if lsOpts.Quiet {
for _, s := range stackList {
fmt.Fprintln(dockerCli.Out(), s.Name)
}
return nil
}
view := viewFromStackList(stackList)
return formatter.Print(view, lsOpts.Format, dockerCli.Out(), func(w io.Writer) {
for _, stack := range view {

View File

@@ -26,7 +26,7 @@ import (
func TestApplyPlatforms_InferFromRuntime(t *testing.T) {
makeProject := func() *types.Project {
return &types.Project{
Services: []types.ServiceConfig{
Services: types.Services{
{
Name: "test",
Image: "foo",
@@ -64,7 +64,7 @@ func TestApplyPlatforms_DockerDefaultPlatform(t *testing.T) {
Environment: map[string]string{
"DOCKER_DEFAULT_PLATFORM": "linux/amd64",
},
Services: []types.ServiceConfig{
Services: types.Services{
{
Name: "test",
Image: "foo",
@@ -100,7 +100,7 @@ func TestApplyPlatforms_UnsupportedPlatform(t *testing.T) {
Environment: map[string]string{
"DOCKER_DEFAULT_PLATFORM": "commodore/64",
},
Services: []types.ServiceConfig{
Services: types.Services{
{
Name: "test",
Image: "foo",

View File

@@ -18,6 +18,7 @@ package compose
import (
"context"
"errors"
"fmt"
"sort"
"strings"
@@ -29,7 +30,6 @@ import (
"github.com/docker/cli/cli/command"
cliformatter "github.com/docker/cli/cli/command/formatter"
cliflags "github.com/docker/cli/cli/flags"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -41,6 +41,7 @@ type psOptions struct {
Services bool
Filter string
Status []string
noTrunc bool
}
func (p *psOptions) parseFilter() error {
@@ -84,6 +85,7 @@ func psCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *c
flags.BoolVarP(&opts.Quiet, "quiet", "q", false, "Only display IDs")
flags.BoolVar(&opts.Services, "services", false, "Display services")
flags.BoolVarP(&opts.All, "all", "a", false, "Show all stopped containers (including those created by the run command)")
flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Don't truncate output")
return psCmd
}
@@ -145,6 +147,7 @@ func runPs(ctx context.Context, dockerCli command.Cli, backend api.Service, serv
containerCtx := cliformatter.Context{
Output: dockerCli.Out(),
Format: formatter.NewContainerFormat(opts.Format, opts.Quiet, false),
Trunc: !opts.noTrunc,
}
return formatter.ContainerWrite(containerCtx, containers)
}

View File

@@ -25,11 +25,16 @@ import (
"github.com/docker/compose/v2/pkg/api"
)
type publishOptions struct {
*ProjectOptions
resolveImageDigests bool
}
func publishCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *cobra.Command {
opts := pushOptions{
opts := publishOptions{
ProjectOptions: p,
}
publishCmd := &cobra.Command{
cmd := &cobra.Command{
Use: "publish [OPTIONS] [REPOSITORY]",
Short: "Publish compose application",
RunE: Adapt(func(ctx context.Context, args []string) error {
@@ -37,14 +42,18 @@ func publishCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Servic
}),
Args: cobra.ExactArgs(1),
}
return publishCmd
flags := cmd.Flags()
flags.BoolVar(&opts.resolveImageDigests, "resolve-image-digests", false, "Pin image tags to digests.")
return cmd
}
func runPublish(ctx context.Context, dockerCli command.Cli, backend api.Service, opts pushOptions, repository string) error {
func runPublish(ctx context.Context, dockerCli command.Cli, backend api.Service, opts publishOptions, repository string) error {
project, err := opts.ToProject(dockerCli, nil)
if err != nil {
return err
}
return backend.Publish(ctx, project, repository, api.PublishOptions{})
return backend.Publish(ctx, project, repository, api.PublishOptions{
ResolveImageDigests: opts.resolveImageDigests,
})
}

View File

@@ -25,7 +25,7 @@ import (
func TestApplyPullOptions(t *testing.T) {
project := &types.Project{
Services: []types.ServiceConfig{
Services: types.Services{
{
Name: "must-build",
// No image, local build only

View File

@@ -80,11 +80,10 @@ func (options runOptions) apply(project *types.Project) error {
target.Tty = !options.noTty
target.StdinOpen = options.interactive
// --service-ports and --publish are incompatible
if !options.servicePorts {
target.Ports = []types.ServicePortConfig{}
}
if len(options.publish) > 0 {
target.Ports = []types.ServicePortConfig{}
for _, p := range options.publish {
config, err := types.ParsePortConfig(p)
if err != nil {
@@ -93,14 +92,13 @@ func (options runOptions) apply(project *types.Project) error {
target.Ports = append(target.Ports, config...)
}
}
if len(options.volumes) > 0 {
for _, v := range options.volumes {
volume, err := loader.ParseVolume(v)
if err != nil {
return err
}
target.Volumes = append(target.Volumes, volume)
for _, v := range options.volumes {
volume, err := loader.ParseVolume(v)
if err != nil {
return err
}
target.Volumes = append(target.Volumes, volume)
}
for i, s := range project.Services {

View File

@@ -18,13 +18,13 @@ package compose
import (
"context"
"fmt"
"strconv"
"strings"
"github.com/docker/cli/cli/command"
"github.com/compose-spec/compose-go/types"
"github.com/pkg/errors"
"golang.org/x/exp/maps"
"github.com/docker/compose/v2/pkg/api"
@@ -95,12 +95,12 @@ func parseServicesReplicasArgs(args []string) (map[string]int, error) {
for _, arg := range args {
key, val, ok := strings.Cut(arg, "=")
if !ok || key == "" || val == "" {
return nil, errors.Errorf("invalid scale specifier: %s", arg)
return nil, fmt.Errorf("invalid scale specifier: %s", arg)
}
intValue, err := strconv.Atoi(val)
if err != nil {
return nil, errors.Errorf("invalid scale specifier: can't parse replica value as int: %v", arg)
return nil, fmt.Errorf("invalid scale specifier: can't parse replica value as int: %v", arg)
}
serviceReplicaTuples[key] = intValue
}

View File

@@ -102,7 +102,7 @@ func upCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *c
flags.BoolVarP(&up.Detach, "detach", "d", false, "Detached mode: Run containers in the background")
flags.BoolVar(&create.Build, "build", false, "Build images before starting containers.")
flags.BoolVar(&create.noBuild, "no-build", false, "Don't build an image, even if it's policy.")
flags.StringVar(&create.Pull, "pull", "policy", `Pull image before running ("always"|"policy"|"never")`)
flags.StringVar(&create.Pull, "pull", "policy", `Pull image before running ("always"|"missing"|"never")`)
flags.BoolVar(&create.removeOrphans, "remove-orphans", false, "Remove containers for services not defined in the Compose file.")
flags.StringArrayVar(&create.scale, "scale", []string{}, "Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present.")
flags.BoolVar(&up.noColor, "no-color", false, "Produce monochrome output.")

View File

@@ -25,7 +25,7 @@ import (
func TestApplyScaleOpt(t *testing.T) {
p := types.Project{
Services: []types.ServiceConfig{
Services: types.Services{
{
Name: "foo",
},

View File

@@ -20,6 +20,8 @@ import (
"context"
"fmt"
"github.com/compose-spec/compose-go/types"
"github.com/docker/cli/cli/command"
"github.com/docker/compose/v2/internal/locker"
"github.com/docker/compose/v2/pkg/api"
@@ -78,13 +80,19 @@ func runWatch(ctx context.Context, dockerCli command.Cli, backend api.Service, w
// validation done -- ensure we have the lockfile for this project before doing work
l, err := locker.NewPidfile(project.Name)
if err != nil {
return fmt.Errorf("cannot take exclusive lock for project %q: %v", project.Name, err)
return fmt.Errorf("cannot take exclusive lock for project %q: %w", project.Name, err)
}
if err := l.Lock(); err != nil {
return fmt.Errorf("cannot take exclusive lock for project %q: %v", project.Name, err)
return fmt.Errorf("cannot take exclusive lock for project %q: %w", project.Name, err)
}
if !watchOpts.noUp {
for index, service := range project.Services {
if service.Build != nil && service.Develop != nil {
service.PullPolicy = types.PullPolicyBuild
}
project.Services[index] = service
}
upOpts := api.UpOptions{
Create: api.CreateOptions{
Build: &build,

View File

@@ -23,8 +23,6 @@ import (
"strings"
"github.com/docker/compose/v2/pkg/api"
"github.com/pkg/errors"
)
// Print prints formatted lists in different formats
@@ -67,7 +65,7 @@ func Print(toJSON interface{}, format string, outWriter io.Writer, writerFn func
_, _ = fmt.Fprintln(outWriter, outJSON)
}
default:
return errors.Wrapf(api.ErrParsingFailed, "format value %q could not be parsed", format)
return fmt.Errorf("format value %q could not be parsed: %w", format, api.ErrParsingFailed)
}
return nil
}

View File

@@ -57,7 +57,7 @@ Define and run multi-container applications with Docker.
## Description
You can use compose subcommand, `docker compose [-f <arg>...] [options] [COMMAND] [ARGS...]`, to build and manage
You can use the compose subcommand, `docker compose [-f <arg>...] [options] [COMMAND] [ARGS...]`, to build and manage
multiple services in Docker containers.
### Use `-f` to specify the name and path of one or more Compose files
@@ -146,16 +146,16 @@ demo_1 | 64 bytes from 127.0.0.1: seq=0 ttl=64 time=0.095 ms
### Use profiles to enable optional services
Use `--profile` to specify one or more active profiles
Calling `docker compose --profile frontend up` will start the services with the profile `frontend` and services
Calling `docker compose --profile frontend up` starts the services with the profile `frontend` and services
without any specified profiles.
You can also enable multiple profiles, e.g. with `docker compose --profile frontend --profile debug up` the profiles `frontend` and `debug` will be enabled.
You can also enable multiple profiles, e.g. with `docker compose --profile frontend --profile debug up` the profiles `frontend` and `debug` is enabled.
Profiles can also be set by `COMPOSE_PROFILES` environment variable.
### Configuring parallelism
Use `--parallel` to specify the maximum level of parallelism for concurrent engine calls.
Calling `docker compose --parallel 1 pull` will pull the pullable images defined in the Compose file
Calling `docker compose --parallel 1 pull` pulls the pullable images defined in the Compose file
one at a time. This can also be used to control build concurrency.
Parallelism can also be set by the `COMPOSE_PARALLEL_LIMIT` environment variable.
@@ -171,7 +171,7 @@ and `COMPOSE_PARALLEL_LIMIT` does the same as the `--parallel` flag.
If flags are explicitly set on the command line, the associated environment variable is ignored.
Setting the `COMPOSE_IGNORE_ORPHANS` environment variable to `true` will stop docker compose from detecting orphaned
Setting the `COMPOSE_IGNORE_ORPHANS` environment variable to `true` stops docker compose from detecting orphaned
containers for the project.
### Use Dry Run mode to test your command

View File

@@ -1,7 +1,7 @@
# docker compose alpha dry-run
<!---MARKER_GEN_START-->
EXPERIMENTAL - Dry run command allow you to test a command without applying changes
Dry run command allows you to test a command without applying changes.
<!---MARKER_GEN_END-->

View File

@@ -5,9 +5,10 @@ Publish compose application
### Options
| Name | Type | Default | Description |
|:------------|:-----|:--------|:--------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| Name | Type | Default | Description |
|:--------------------------|:-----|:--------|:--------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `--resolve-image-digests` | | | Pin image tags to digests. |
<!---MARKER_GEN_END-->

View File

@@ -1,14 +1,14 @@
# docker compose alpha scale
<!---MARKER_GEN_START-->
Scale services
Scale services.
### Options
| Name | Type | Default | Description |
|:------------|:-----|:--------|:--------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `--no-deps` | | | Don't start linked services. |
| `--no-deps` | | | Don't start linked services |
<!---MARKER_GEN_END-->

View File

@@ -31,6 +31,6 @@ Parse, resolve and render compose file in canonical format
## Description
`docker compose config` renders the actual data model to be applied on the Docker engine.
it merges the Compose files set by `-f` flags, resolves variables in the Compose file, and expands short-notation into
`docker compose config` renders the actual data model to be applied on the Docker Engine.
It merges the Compose files set by `-f` flags, resolves variables in the Compose file, and expands short-notation into
the canonical format.

View File

@@ -12,7 +12,7 @@ Creates containers for a service.
| `--force-recreate` | | | Recreate containers even if their configuration and image haven't changed. |
| `--no-build` | | | Don't build an image, even if it's policy. |
| `--no-recreate` | | | If containers already exist, don't recreate them. Incompatible with --force-recreate. |
| `--pull` | `string` | `policy` | Pull image before running ("always"\|"policy"\|"never") |
| `--pull` | `string` | `policy` | Pull image before running ("always"\|"missing"\|"never"\|"build") |
| `--remove-orphans` | | | Remove containers for services not defined in the Compose file. |
| `--scale` | `stringArray` | | Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present. |

View File

@@ -22,12 +22,12 @@ Stops containers and removes containers, networks, volumes, and images created b
By default, the only things removed are:
- Containers for services defined in the Compose file
- Networks defined in the networks section of the Compose file
- The default network, if one is used
- Containers for services defined in the Compose file.
- Networks defined in the networks section of the Compose file.
- The default network, if one is used.
Networks and volumes defined as external are never removed.
Anonymous volumes are not removed by default. However, as they dont have a stable name, they will not be automatically
Anonymous volumes are not removed by default. However, as they dont have a stable name, they are not automatically
mounted by a subsequent `up`. For data that needs to persist between updates, use explicit paths as bind mounts or
named volumes.

View File

@@ -11,6 +11,7 @@ List containers
| `--dry-run` | | | Execute command in dry run mode |
| [`--filter`](#filter) | `string` | | Filter services by a property (supported filters: status). |
| [`--format`](#format) | `string` | `table` | Format output using a custom template:<br>'table': Print output in table format with column headers (default)<br>'table TEMPLATE': Print output in table format using the given Go template<br>'json': Print in JSON format<br>'TEMPLATE': Print output using the given Go template.<br>Refer to https://docs.docker.com/go/formatting/ for more information about formatting output with templates |
| `--no-trunc` | | | Don't truncate output |
| `-q`, `--quiet` | | | Only display IDs |
| `--services` | | | Display services |
| [`--status`](#status) | `stringArray` | | Filter services by status. Values: [paused \| restarting \| removing \| running \| dead \| created \| exited] |
@@ -28,7 +29,7 @@ NAME IMAGE COMMAND SERVICE CREATED STATUS
example-foo-1 alpine "/entrypoint.…" foo 4 seconds ago Up 2 seconds 0.0.0.0:8080->80/tcp
```
By default, only running containers are shown. `--all` flag can be used to include stopped containers
By default, only running containers are shown. `--all` flag can be used to include stopped containers.
```console
$ docker compose ps --all
@@ -52,7 +53,7 @@ $ docker compose ps --format json
```
The JSON output allows you to use the information in other tools for further
processing, for example, using the [`jq` utility](https://stedolan.github.io/jq/){:target="_blank" rel="noopener" class="_"}
processing, for example, using the [`jq` utility](https://stedolan.github.io/jq/)
to pretty-print the JSON:
```console

View File

@@ -25,7 +25,7 @@ those images.
## Examples
suppose you have this `compose.yaml`:
Consider the following `compose.yaml`:
```yaml
services:
@@ -66,5 +66,4 @@ $ docker compose pull db
⠹ c8752d5b785c Waiting 9.3s
```
`docker compose pull` will try to pull image for services with a build section. If pull fails, it will let
user know this service image MUST be built. You can skip this by setting `--ignore-buildable` flag
`docker compose pull` tries to pull image for services with a build section. If pull fails, it lets you know this service image must be built. You can skip this by setting `--ignore-buildable` flag.

View File

@@ -23,6 +23,6 @@ after running this command. For example, changes to environment variables (which
after a container is built, but before the container's command is executed) are not updated
after restarting.
If you are looking to configure a service's restart policy, please refer to
If you are looking to configure a service's restart policy, 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).

View File

@@ -23,7 +23,7 @@ Create and start containers
| `--no-log-prefix` | | | Don't print prefix in logs. |
| `--no-recreate` | | | If containers already exist, don't recreate them. Incompatible with --force-recreate. |
| `--no-start` | | | Don't start the services after creating them. |
| `--pull` | `string` | `policy` | Pull image before running ("always"\|"policy"\|"never") |
| `--pull` | `string` | `policy` | Pull image before running ("always"\|"missing"\|"never") |
| `--quiet-pull` | | | Pull without printing progress information. |
| `--remove-orphans` | | | Remove containers for services not defined in the Compose file. |
| `-V`, `--renew-anon-volumes` | | | Recreate anonymous volumes instead of retrieving data from the previous containers. |

View File

@@ -1,7 +1,7 @@
command: docker compose
short: Docker Compose
long: |-
You can use compose subcommand, `docker compose [-f <arg>...] [options] [COMMAND] [ARGS...]`, to build and manage
You can use the compose subcommand, `docker compose [-f <arg>...] [options] [COMMAND] [ARGS...]`, to build and manage
multiple services in Docker containers.
### Use `-f` to specify the name and path of one or more Compose files
@@ -90,16 +90,16 @@ long: |-
### Use profiles to enable optional services
Use `--profile` to specify one or more active profiles
Calling `docker compose --profile frontend up` will start the services with the profile `frontend` and services
Calling `docker compose --profile frontend up` starts the services with the profile `frontend` and services
without any specified profiles.
You can also enable multiple profiles, e.g. with `docker compose --profile frontend --profile debug up` the profiles `frontend` and `debug` will be enabled.
You can also enable multiple profiles, e.g. with `docker compose --profile frontend --profile debug up` the profiles `frontend` and `debug` is enabled.
Profiles can also be set by `COMPOSE_PROFILES` environment variable.
### Configuring parallelism
Use `--parallel` to specify the maximum level of parallelism for concurrent engine calls.
Calling `docker compose --parallel 1 pull` will pull the pullable images defined in the Compose file
Calling `docker compose --parallel 1 pull` pulls the pullable images defined in the Compose file
one at a time. This can also be used to control build concurrency.
Parallelism can also be set by the `COMPOSE_PARALLEL_LIMIT` environment variable.
@@ -115,7 +115,7 @@ long: |-
If flags are explicitly set on the command line, the associated environment variable is ignored.
Setting the `COMPOSE_IGNORE_ORPHANS` environment variable to `true` will stop docker compose from detecting orphaned
Setting the `COMPOSE_IGNORE_ORPHANS` environment variable to `true` stops docker compose from detecting orphaned
containers for the project.
### Use Dry Run mode to test your command

View File

@@ -4,6 +4,17 @@ long: Publish compose application
usage: docker compose alpha publish [OPTIONS] [REPOSITORY]
pname: docker compose alpha
plink: docker_compose_alpha.yaml
options:
- option: resolve-image-digests
value_type: bool
default_value: "false"
description: Pin image tags to digests.
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
inherited_options:
- option: dry-run
value_type: bool

View File

@@ -2,8 +2,8 @@ command: docker compose config
aliases: docker compose config, docker compose convert
short: Parse, resolve and render compose file in canonical format
long: |-
`docker compose config` renders the actual data model to be applied on the Docker engine.
it merges the Compose files set by `-f` flags, resolves variables in the Compose file, and expands short-notation into
`docker compose config` renders the actual data model to be applied on the Docker Engine.
It merges the Compose files set by `-f` flags, resolves variables in the Compose file, and expands short-notation into
the canonical format.
usage: docker compose config [OPTIONS] [SERVICE...]
pname: docker compose

View File

@@ -50,7 +50,7 @@ options:
- option: pull
value_type: string
default_value: policy
description: Pull image before running ("always"|"policy"|"never")
description: Pull image before running ("always"|"missing"|"never"|"build")
deprecated: false
hidden: false
experimental: false

View File

@@ -5,13 +5,13 @@ long: |-
By default, the only things removed are:
- Containers for services defined in the Compose file
- Networks defined in the networks section of the Compose file
- The default network, if one is used
- Containers for services defined in the Compose file.
- Networks defined in the networks section of the Compose file.
- The default network, if one is used.
Networks and volumes defined as external are never removed.
Anonymous volumes are not removed by default. However, as they dont have a stable name, they will not be automatically
Anonymous volumes are not removed by default. However, as they dont have a stable name, they are not 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 [OPTIONS] [SERVICES]

View File

@@ -9,7 +9,7 @@ long: |-
example-foo-1 alpine "/entrypoint.…" foo 4 seconds ago Up 2 seconds 0.0.0.0:8080->80/tcp
```
By default, only running containers are shown. `--all` flag can be used to include stopped containers
By default, only running containers are shown. `--all` flag can be used to include stopped containers.
```console
$ docker compose ps --all
@@ -60,6 +60,16 @@ options:
experimentalcli: false
kubernetes: false
swarm: false
- option: no-trunc
value_type: bool
default_value: "false"
description: Don't truncate output
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: quiet
shorthand: q
value_type: bool
@@ -118,7 +128,7 @@ examples: |-
```
The JSON output allows you to use the information in other tools for further
processing, for example, using the [`jq` utility](https://stedolan.github.io/jq/){:target="_blank" rel="noopener" class="_"}
processing, for example, using the [`jq` utility](https://stedolan.github.io/jq/)
to pretty-print the JSON:
```console

View File

@@ -89,7 +89,7 @@ inherited_options:
kubernetes: false
swarm: false
examples: |-
suppose you have this `compose.yaml`:
Consider the following `compose.yaml`:
```yaml
services:
@@ -130,8 +130,7 @@ examples: |-
⠹ c8752d5b785c Waiting 9.3s
```
`docker compose pull` will try to pull image for services with a build section. If pull fails, it will let
user know this service image MUST be built. You can skip this by setting `--ignore-buildable` flag
`docker compose pull` tries to pull image for services with a build section. If pull fails, it lets you know this service image must be built. You can skip this by setting `--ignore-buildable` flag.
deprecated: false
hidden: false
experimental: false

View File

@@ -8,7 +8,7 @@ long: |-
after a container is built, but before the container's command is executed) are not updated
after restarting.
If you are looking to configure a service's restart policy, please refer to
If you are looking to configure a service's restart policy, 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 [OPTIONS] [SERVICE...]

View File

@@ -182,7 +182,7 @@ options:
- option: pull
value_type: string
default_value: policy
description: Pull image before running ("always"|"policy"|"never")
description: Pull image before running ("always"|"missing"|"never")
deprecated: false
hidden: false
experimental: false

View File

@@ -1,21 +0,0 @@
Feature: Build Contexts
Background:
Given a compose file
"""
services:
a:
build:
context: .
dockerfile_inline: |
# syntax=docker/dockerfile:1
FROM alpine:latest
COPY --from=dep /etc/hostname /
additional_contexts:
- dep=docker-image://ubuntu:latest
"""
Scenario: Build w/ build context
When I run "compose build"
Then the exit code is 0

View File

@@ -1,5 +0,0 @@
Feature: Down
Scenario: No resources to remove
When I run "compose down"
Then the output contains "Warning: No resource found to remove for project "no_resources_to_remove""

View File

@@ -1,28 +0,0 @@
Feature: Report port conflicts
Background:
Given a compose file
"""
services:
web:
image: nginx
ports:
- 31415:80
"""
And I run "docker rm -f nginx-pi-31415"
Scenario: Reports a port allocation conflict with another container
Given I run "docker run -d -p 31415:80 --name nginx-pi-31415 nginx"
When I run "compose up -d"
Then the output contains "port is already allocated"
And the exit code is 1
Scenario: Reports a port conflict with some other process
Given a process listening on port 31415
When I run "compose up -d"
Then the output contains "address already in use"
And the exit code is 1
Scenario: Cleanup
Given I run "docker rm -f nginx-pi-31415"

View File

@@ -1,29 +0,0 @@
Feature: PS
Background:
Given a compose file
"""
services:
build:
image: test:latest
build:
context: ./
pull:
image: alpine
command: top
"""
And a dockerfile
"""
FROM golang:1.19-alpine
"""
And I run "docker rm -f external-test"
Scenario: external container from compose image exists
When I run "compose build"
Then the exit code is 0
And I run "docker run --name external-test test:latest ls"
Then the exit code is 0
And I run "compose ps -a"
Then the output does not contain "external-test"
And I run "docker rm -f external-test"

View File

@@ -1,15 +0,0 @@
Feature: Simple service up
Background:
Given a compose file
"""
services:
simple:
image: alpine
command: top
"""
Scenario: compose up
When I run "compose up -d"
Then the output contains "simple-1 Started"
And service "simple" is "Up"

View File

@@ -1,21 +0,0 @@
Feature: Start
Background:
Given a compose file
"""
services:
simple:
image: alpine
command: top
another:
image: alpine
command: top
"""
Scenario: Start single service
When I run "compose create"
Then the output contains "simple-1 Created"
And the output contains "another-1 Created"
Then I run "compose start another"
And service "another" is "Up"
And service "simple" is "Created"

View File

@@ -1,38 +0,0 @@
Feature: Stop
Background:
Given a compose file
"""
services:
should_fail:
image: alpine
command: ['sh', '-c', 'exit 123']
sleep: # will be killed
image: alpine
command: ping localhost
init: true
"""
Scenario: Cascade stop
When I run "compose up --abort-on-container-exit"
Then the output contains "should_fail-1 exited with code 123"
And the output contains "Aborting on container exit..."
And the exit code is 123
Scenario: Exit code from
When I run "compose up --exit-code-from should_fail"
Then the output contains "should_fail-1 exited with code 123"
And the output contains "Aborting on container exit..."
And the exit code is 123
# TODO: this is currently not working propagating the exit code properly
#Scenario: Exit code from (cascade stop)
# When I run "compose up --exit-code-from sleep"
# Then the output contains "should_fail-1 exited with code 123"
# And the output contains "Aborting on container exit..."
# And the exit code is 143
Scenario: Exit code from unknown service
When I run "compose up --exit-code-from unknown"
Then the output contains "no such service: unknown"
And the exit code is 1

View File

@@ -1,17 +0,0 @@
Feature: Up
Background:
Given a compose file
"""
services:
simple:
image: alpine
command: top
"""
Scenario: --pull always
When I run "compose up --pull=always -d"
And the output contains "simple Pulled"
Then I run "compose up --pull=always -d"
And the output contains "simple Pulled"

View File

@@ -1,23 +0,0 @@
Feature: Volume: tmpfs
Background:
Given a compose file
"""
services:
svc:
image: busybox
volumes:
- type: tmpfs
target: /volumes/tmpfs
tmpfs:
size: 2M
mode: 0o647
"""
Scenario: tmpfs Permissions Set
When I run "compose run --rm svc stat -c "%a" /volumes/tmpfs"
Then the output contains "647"
Scenario: tmpfs Size Set
When I run "compose run --rm svc sh -c 'df /volumes/tmpfs | tail -n1 | awk '"'"'{print $4}'"'"'' "
Then the output contains "2048"

View File

@@ -1,191 +0,0 @@
/*
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 cucumber
import (
"context"
"fmt"
"net"
"os"
"path/filepath"
"regexp"
"strings"
"testing"
"github.com/compose-spec/compose-go/loader"
"github.com/cucumber/godog"
"github.com/cucumber/godog/colors"
"github.com/mattn/go-shellwords"
"gotest.tools/v3/icmd"
"github.com/docker/compose/v2/pkg/e2e"
)
func TestCucumber(t *testing.T) {
testingOptions := godog.Options{
TestingT: t,
Paths: []string{"./cucumber-features"},
Output: colors.Colored(os.Stdout),
Format: "pretty",
}
status := godog.TestSuite{
Name: "godogs",
Options: &testingOptions,
ScenarioInitializer: setup,
}.Run()
if status == 2 {
t.SkipNow()
}
if status != 0 {
t.Fatalf("zero status code expected, %d received", status)
}
}
func setup(s *godog.ScenarioContext) {
t := s.TestingT()
projectName := loader.NormalizeProjectName(strings.Split(t.Name(), "/")[1])
cli := e2e.NewCLI(t, e2e.WithEnv(
fmt.Sprintf("COMPOSE_PROJECT_NAME=%s", projectName),
))
th := testHelper{
T: t,
CLI: cli,
ProjectName: projectName,
}
s.Before(func(ctx context.Context, sc *godog.Scenario) (context.Context, error) {
cli.RunDockerComposeCmd(t, "down", "--remove-orphans", "-v", "-t", "0")
return ctx, nil
})
s.After(func(ctx context.Context, sc *godog.Scenario, err error) (context.Context, error) {
cli.RunDockerComposeCmd(t, "down", "--remove-orphans", "-v", "-t", "0")
return ctx, nil
})
s.Step(`^a compose file$`, th.setComposeFile)
s.Step(`^a dockerfile$`, th.setDockerfile)
s.Step(`^I run "compose (.*)"$`, th.runComposeCommand)
s.Step(`^I run "docker (.*)"$`, th.runDockerCommand)
s.Step(`service "(.*)" is "(.*)"$`, th.serviceIsStatus)
s.Step(`output contains "(.*)"$`, th.outputContains(true))
s.Step(`output does not contain "(.*)"$`, th.outputContains(false))
s.Step(`exit code is (\d+)$`, th.exitCodeIs)
s.Step(`a process listening on port (\d+)$`, th.listenerOnPort)
}
type testHelper struct {
T *testing.T
ProjectName string
ComposeFile string
TestDir string
CommandOutput string
CommandExitCode int
CLI *e2e.CLI
}
func (th *testHelper) serviceIsStatus(service, status string) error {
serviceContainerName := fmt.Sprintf("%s-%s-1", strings.ToLower(th.ProjectName), service)
statusRegex := fmt.Sprintf("%s.*%s", serviceContainerName, status)
res := th.CLI.RunDockerComposeCmd(th.T, "ps", "-a")
r, _ := regexp.Compile(statusRegex)
if !r.MatchString(res.Combined()) {
return fmt.Errorf("Missing/incorrect ps output:\n%s\nregex:\n%s", res.Combined(), statusRegex)
}
return nil
}
func (th *testHelper) outputContains(expected bool) func(string) error {
return func(substring string) error {
contains := strings.Contains(th.CommandOutput, substring)
if contains && !expected {
return fmt.Errorf("Unexpected substring in output: %s\noutput: %s", substring, th.CommandOutput)
} else if !contains && expected {
return fmt.Errorf("Missing substring in output: %s\noutput: %s", substring, th.CommandOutput)
}
return nil
}
}
func (th *testHelper) exitCodeIs(exitCode int) error {
if exitCode != th.CommandExitCode {
return fmt.Errorf("Wrong exit code: %d expected: %d || command output: %s", th.CommandExitCode, exitCode, th.CommandOutput)
}
return nil
}
func (th *testHelper) runComposeCommand(command string) error {
commandArgs, err := shellwords.Parse(command)
if err != nil {
return err
}
commandArgs = append([]string{"-f", "-"}, commandArgs...)
cmd := th.CLI.NewDockerComposeCmd(th.T, commandArgs...)
cmd.Stdin = strings.NewReader(th.ComposeFile)
cmd.Dir = th.TestDir
res := icmd.RunCmd(cmd)
th.CommandOutput = res.Combined()
th.CommandExitCode = res.ExitCode
return nil
}
func (th *testHelper) runDockerCommand(command string) error {
commandArgs, err := shellwords.Parse(command)
if err != nil {
return err
}
cmd := th.CLI.NewDockerCmd(th.T, commandArgs...)
cmd.Dir = th.TestDir
res := icmd.RunCmd(cmd)
th.CommandOutput = res.Combined()
th.CommandExitCode = res.ExitCode
return nil
}
func (th *testHelper) setComposeFile(composeString string) error {
th.ComposeFile = composeString
return nil
}
func (th *testHelper) setDockerfile(dockerfileString string) error {
tempDir := th.T.TempDir()
th.TestDir = tempDir
err := os.WriteFile(filepath.Join(tempDir, "Dockerfile"), []byte(dockerfileString), 0o644)
if err != nil {
return err
}
return nil
}
func (th *testHelper) listenerOnPort(port int) error {
l, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
return err
}
th.T.Cleanup(func() {
_ = l.Close()
})
return nil
}

57
go.mod
View File

@@ -5,37 +5,35 @@ go 1.21
require (
github.com/AlecAivazis/survey/v2 v2.3.7
github.com/Microsoft/go-winio v0.6.1
github.com/adrg/xdg v0.4.0
github.com/buger/goterm v1.0.4
github.com/compose-spec/compose-go v1.19.0
github.com/compose-spec/compose-go v1.20.2
github.com/containerd/console v1.0.3
github.com/containerd/containerd v1.7.6
github.com/cucumber/godog v0.0.0-00010101000000-000000000000 // replaced; see replace for the actual version used
github.com/containerd/containerd v1.7.7
github.com/davecgh/go-spew v1.1.1
github.com/distribution/reference v0.5.0
github.com/docker/buildx v0.11.2
github.com/docker/cli v24.0.6+incompatible
github.com/docker/cli v24.0.7+incompatible
github.com/docker/cli-docs-tool v0.6.0
github.com/docker/docker v24.0.6+incompatible
github.com/docker/docker v24.0.7+incompatible
github.com/docker/go-connections v0.4.0
github.com/docker/go-units v0.5.0
github.com/fsnotify/fsevents v0.1.1
github.com/golang/mock v1.6.0
github.com/google/go-cmp v0.5.9
github.com/google/go-cmp v0.6.0
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/go-version v1.6.0
github.com/jonboulle/clockwork v0.4.0
github.com/mattn/go-shellwords v1.0.12
github.com/mitchellh/mapstructure v1.5.0
github.com/moby/buildkit v0.12.2
github.com/moby/buildkit v0.12.3
github.com/moby/patternmatcher v0.6.0
github.com/moby/term v0.5.0
github.com/morikuni/aec v1.0.0
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.1.0-rc5
github.com/pkg/errors v0.9.1
github.com/otiai10/copy v1.14.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.7.0
github.com/spf13/cobra v1.8.0
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.4
github.com/theupdateframework/notary v0.7.0
@@ -45,19 +43,19 @@ require (
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.14.0
go.opentelemetry.io/otel/sdk v1.14.0
go.opentelemetry.io/otel/trace v1.14.0
go.uber.org/goleak v1.2.1
golang.org/x/sync v0.3.0
google.golang.org/grpc v1.58.1
go.uber.org/goleak v1.3.0
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1
golang.org/x/sync v0.5.0
golang.org/x/sys v0.14.0
google.golang.org/grpc v1.59.0
gotest.tools/v3 v3.5.1
)
require golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1
require (
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/Microsoft/hcsshim v0.11.0 // indirect
github.com/Microsoft/hcsshim v0.11.1 // indirect
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d // indirect
github.com/aws/aws-sdk-go-v2 v1.17.6 // indirect
github.com/aws/aws-sdk-go-v2/config v1.18.16 // indirect
@@ -75,9 +73,8 @@ require (
github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/containerd/continuity v0.4.2 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/typeurl/v2 v2.1.1 // indirect
github.com/cucumber/gherkin-go/v19 v19.0.3 // indirect
github.com/cucumber/messages-go/v16 v16.0.1 // indirect
github.com/docker/distribution v2.8.2+incompatible // indirect
github.com/docker/docker-credential-helpers v0.7.0 // indirect
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect
@@ -102,9 +99,6 @@ require (
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/go-memdb v1.3.2 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/in-toto/in-toto-golang v0.5.0 // indirect
@@ -132,6 +126,7 @@ require (
github.com/opencontainers/runc v1.1.7 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.14.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
@@ -156,19 +151,18 @@ require (
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.14.0 // indirect
go.opentelemetry.io/otel/metric v0.37.0 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
golang.org/x/crypto v0.11.0 // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/mod v0.11.0 // indirect
golang.org/x/net v0.12.0 // indirect
golang.org/x/oauth2 v0.10.0 // indirect
golang.org/x/sys v0.10.0 // indirect
golang.org/x/term v0.10.0 // indirect
golang.org/x/text v0.11.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/oauth2 v0.11.0 // indirect
golang.org/x/term v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.7.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
@@ -184,6 +178,3 @@ require (
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)
// Override for e2e tests
replace github.com/cucumber/godog => github.com/laurazard/godog v0.0.0-20220922095256-4c4b17abdae7

133
go.sum
View File

@@ -17,15 +17,15 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
cloud.google.com/go v0.110.4 h1:1JYyxKMN9hd5dR2MYTPWkGUgcoxVVhg0LKNKEo0qvmk=
cloud.google.com/go v0.110.7 h1:rJyC7nWRg2jWGZ4wSJ5nY65GTdYJkg0cd/uXb+ACI6o=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk=
cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY=
cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
@@ -55,16 +55,14 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/Microsoft/hcsshim v0.11.0 h1:7EFNIY4igHEXUdj1zXgAyU3fLc7QfOKHbkldRVTBdiM=
github.com/Microsoft/hcsshim v0.11.0/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM=
github.com/Microsoft/hcsshim v0.11.1 h1:hJ3s7GbWlGK4YVV92sO88BQSyF4ZLVy7/awqOlPxFbA=
github.com/Microsoft/hcsshim v0.11.1/go.mod h1:nFJmaO4Zr5Y7eADdFOpYswDDlNVbvcIJJNJLECr5JQg=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs=
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls=
github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc=
@@ -139,18 +137,20 @@ github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+g
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4=
github.com/compose-spec/compose-go v1.19.0 h1:t68gAcwStDg0hy2kFvqHJIksf6xkqRnlSKfL45/ETqo=
github.com/compose-spec/compose-go v1.19.0/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM=
github.com/compose-spec/compose-go v1.20.2 h1:u/yfZHn4EaHGdidrZycWpxXgFffjYULlTbRfJ51ykjQ=
github.com/compose-spec/compose-go v1.20.2/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM=
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
github.com/containerd/containerd v1.7.6 h1:oNAVsnhPoy4BTPQivLgTzI9Oleml9l/+eYIDYXRCYo8=
github.com/containerd/containerd v1.7.6/go.mod h1:SY6lrkkuJT40BVNO37tlYTSnKJnP5AXBc0fhx0q+TJ4=
github.com/containerd/containerd v1.7.7 h1:QOC2K4A42RQpcrZyptP6z9EJZnlHfHJUfZrAAHe15q4=
github.com/containerd/containerd v1.7.7/go.mod h1:3c4XZv6VeT9qgf9GMTxNTMFxGJrGpI2vz1yk4ye+YY8=
github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM=
github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ=
github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY=
github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/containerd/nydus-snapshotter v0.8.2 h1:7SOrMU2YmLzfbsr5J7liMZJlNi5WT6vtIOxLGv+iz7E=
github.com/containerd/nydus-snapshotter v0.8.2/go.mod h1:UJILTN5LVBRY+dt8BGJbp72Xy729hUZsOugObEI3/O8=
github.com/containerd/stargz-snapshotter v0.14.3 h1:OTUVZoPSPs8mGgmQUE1dqw3WX/3nrsmsurW7UPLWl1U=
@@ -160,17 +160,11 @@ github.com/containerd/ttrpc v1.2.2 h1:9vqZr0pxwOF5koz6N0N3kJ0zDHokrcPxIR/ZR2YFtO
github.com/containerd/ttrpc v1.2.2/go.mod h1:sIT6l32Ph/H9cvnJsfXM5drIVzTr5A2flTf1G5tYZak=
github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9FqcttATPO/4=
github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/cucumber/gherkin-go/v19 v19.0.3 h1:mMSKu1077ffLbTJULUfM5HPokgeBcIGboyeNUof1MdE=
github.com/cucumber/gherkin-go/v19 v19.0.3/go.mod h1:jY/NP6jUtRSArQQJ5h1FXOUgk5fZK24qtE7vKi776Vw=
github.com/cucumber/messages-go/v16 v16.0.0/go.mod h1:EJcyR5Mm5ZuDsKJnT2N9KRnBK30BGjtYotDKpwQ0v6g=
github.com/cucumber/messages-go/v16 v16.0.1 h1:fvkpwsLgnIm0qugftrw2YwNlio+ABe2Iu94Ap8GMYIY=
github.com/cucumber/messages-go/v16 v16.0.1/go.mod h1:EJcyR5Mm5ZuDsKJnT2N9KRnBK30BGjtYotDKpwQ0v6g=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -179,15 +173,15 @@ github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/buildx v0.11.2 h1:R3p9F0gnI4FwvQ0p40UwdX1T4ugap4UWxY3TFHoP4Ws=
github.com/docker/buildx v0.11.2/go.mod h1:CWAABt10iIuGpleypA3103mplDfcGu0A2AvT03xfpTc=
github.com/docker/cli v24.0.6+incompatible h1:fF+XCQCgJjjQNIMjzaSmiKJSCcfcXb3TWTcc7GAneOY=
github.com/docker/cli v24.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v24.0.7+incompatible h1:wa/nIwYFW7BVTGa7SWPVyyXU9lgORqUb1xfI36MSkFg=
github.com/docker/cli v24.0.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli-docs-tool v0.6.0 h1:Z9x10SaZgFaB6jHgz3OWooynhSa40CsWkpe5hEnG/qA=
github.com/docker/cli-docs-tool v0.6.0/go.mod h1:zMjqTFCU361PRh8apiXzeAZ1Q/xupbIwTusYpzCXS/o=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE=
github.com/docker/docker v24.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM=
github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
@@ -257,7 +251,6 @@ github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0=
github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0=
@@ -269,8 +262,8 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=
github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ=
github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo=
github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -322,8 +315,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -344,13 +337,11 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
@@ -366,22 +357,12 @@ github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMW
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-memdb v1.3.2 h1:RBKHOsnSszpU6vxq80LzC2BaQjuuvoyaQbkLTf7V7g8=
github.com/hashicorp/go-memdb v1.3.2/go.mod h1:Mluclgwib3R93Hk5fxEfiRhB+6Dar64wWh71LpNSe3g=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE=
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
@@ -415,8 +396,6 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA=
@@ -439,8 +418,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/laurazard/godog v0.0.0-20220922095256-4c4b17abdae7 h1:R/J7xECY9oHrAg+4QjC38EoXaYysNLzhvXhH/SXcsVc=
github.com/laurazard/godog v0.0.0-20220922095256-4c4b17abdae7/go.mod h1:Y02TTpimPXDb70PnG6M3zpODXm1+bjCsuZzcW76xAww=
github.com/lib/pq v0.0.0-20150723085316-0dad96c0b94f/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/magiconair/properties v1.5.3 h1:C8fxWnhYyME3n0klPOhVM7PtYUB3eV1W3DeFmN3j53Y=
github.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
@@ -471,8 +448,8 @@ github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WT
github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/moby/buildkit v0.12.2 h1:B7guBgY6sfk4dBlv/ORUxyYlp0UojYaYyATgtNwSCXc=
github.com/moby/buildkit v0.12.2/go.mod h1:adB4y0SxxX8trnrY+oEulb48ODLqPO6pKMF0ppGcCoI=
github.com/moby/buildkit v0.12.3 h1:cFaPVnyC0PwAP5xHHfzdU5v9rgQrCi6HnGSg3WuFKp4=
github.com/moby/buildkit v0.12.3/go.mod h1:adB4y0SxxX8trnrY+oEulb48ODLqPO6pKMF0ppGcCoI=
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/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
@@ -525,6 +502,10 @@ github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaL
github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU=
github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w=
github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks=
github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg=
@@ -576,10 +557,6 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spdx/tools-golang v0.5.1 h1:fJg3SVOGG+eIva9ZUBm/hvyA7PIPVFjRxUKe6fdAgwE=
github.com/spdx/tools-golang v0.5.1/go.mod h1:/DRDQuBfB37HctM29YtrX1v+bXiVmT2OpQDalRmX9aU=
@@ -588,9 +565,8 @@ github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcD
github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94 h1:JmfC365KywYwHB946TTiQWEb8kqPY+pybPLoGE9GgVk=
github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431 h1:XTHrT015sxHyJ5FnQ0AeemSspZWaDq7DoTRW0EVsDCE=
github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
@@ -675,8 +651,8 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe
go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw=
go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -691,8 +667,8 @@ golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWP
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -768,8 +744,8 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -780,8 +756,8 @@ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU=
golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -794,8 +770,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -849,13 +825,13 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c=
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -865,8 +841,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -878,7 +854,6 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
@@ -997,12 +972,12 @@ google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 h1:Z0hjGZePRE0ZBWotvtrwxFNrNE9CUAGtplaDK5NNI/g=
google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98/go.mod h1:S7mY02OqCJTD0E1OiQy1F72PWFB4bZJ87cAtLPYgDR0=
google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw=
google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY=
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4=
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q=
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
@@ -1024,8 +999,8 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58=
google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=

View File

@@ -19,8 +19,8 @@ package locker
import (
"fmt"
"os"
"path/filepath"
"github.com/adrg/xdg"
"github.com/docker/docker/pkg/pidfile"
)
@@ -29,10 +29,11 @@ type Pidfile struct {
}
func NewPidfile(projectName string) (*Pidfile, error) {
path, err := xdg.RuntimeFile(fmt.Sprintf("docker-compose.%s.pid", projectName))
run, err := runDir()
if err != nil {
return nil, err
}
path := filepath.Join(run, fmt.Sprintf("%s.pid", projectName))
return &Pidfile{path: path}, nil
}

View File

@@ -0,0 +1,35 @@
/*
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 locker
import (
"os"
)
func runDir() (string, error) {
run, ok := os.LookupEnv("XDG_RUNTIME_DIR")
if ok {
return run, nil
}
path, err := osDependentRunDir()
if err != nil {
return "", err
}
err = os.MkdirAll(path, 0o700)
return path, err
}

View File

@@ -0,0 +1,34 @@
/*
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 locker
import (
"os"
"path/filepath"
)
// Based on https://github.com/adrg/xdg
// Licensed under MIT License (MIT)
// Copyright (c) 2014 Adrian-George Bostan <adrg@epistack.com>
func osDependentRunDir() (string, error) {
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
return filepath.Join(home, "Library", "Application Support", "com.docker.compose"), nil
}

View File

@@ -0,0 +1,43 @@
//go:build linux
/*
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 locker
import (
"os"
"path/filepath"
"strconv"
)
// Based on https://github.com/adrg/xdg
// Licensed under MIT License (MIT)
// Copyright (c) 2014 Adrian-George Bostan <adrg@epistack.com>
func osDependentRunDir() (string, error) {
run := filepath.Join("run", "user", strconv.Itoa(os.Getuid()))
if _, err := os.Stat(run); err == nil {
return run, nil
}
// /run/user/$uid is set by pam_systemd, but might not be present, especially in containerized environments
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
return filepath.Join(home, ".docker", "docker-compose"), nil
}

View File

@@ -0,0 +1,49 @@
/*
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 locker
import (
"os"
"path/filepath"
"golang.org/x/sys/windows"
)
// Based on https://github.com/adrg/xdg
// Licensed under MIT License (MIT)
// Copyright (c) 2014 Adrian-George Bostan <adrg@epistack.com>
func osDependentRunDir() (string, error) {
flags := []uint32{windows.KF_FLAG_DEFAULT, windows.KF_FLAG_DEFAULT_PATH}
for _, flag := range flags {
p, _ := windows.KnownFolderPath(windows.FOLDERID_LocalAppData, flag|windows.KF_FLAG_DONT_VERIFY)
if p != "" {
return filepath.Join(p, "docker-compose"), nil
}
}
appData, ok := os.LookupEnv("LOCALAPPDATA")
if ok {
return filepath.Join(appData, "docker-compose"), nil
}
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
return filepath.Join(home, "AppData", "Local", "docker-compose"), nil
}

View File

@@ -21,6 +21,7 @@ import (
"archive/tar"
"bytes"
"context"
"errors"
"fmt"
"io"
"io/fs"
@@ -30,7 +31,6 @@ import (
"strings"
"github.com/hashicorp/go-multierror"
"github.com/pkg/errors"
"github.com/compose-spec/compose-go/types"
moby "github.com/docker/docker/api/types"
@@ -212,7 +212,7 @@ func (a *ArchiveBuilder) writeEntry(entry archiveEntry) error {
if useBuf {
a.copyBuf.Reset()
_, err = io.Copy(a.copyBuf, file)
if err != nil && err != io.EOF {
if err != nil && !errors.Is(err, io.EOF) {
return fmt.Errorf("copying %q: %w", pathInTar, err)
}
header.Size = int64(len(a.copyBuf.Bytes()))
@@ -232,7 +232,7 @@ func (a *ArchiveBuilder) writeEntry(entry archiveEntry) error {
_, err = io.Copy(a.tw, file)
}
if err != nil && err != io.EOF {
if err != nil && !errors.Is(err, io.EOF) {
return fmt.Errorf("copying %q: %w", pathInTar, err)
}

View File

@@ -18,12 +18,12 @@ package sync
import (
"context"
"errors"
"io"
"sync"
"testing"
"time"
"github.com/pkg/errors"
"github.com/stretchr/testify/require"
)
@@ -115,7 +115,7 @@ func (b *bufReader) consume() {
b.data = append(b.data, buf[:n]...)
b.mu.Unlock()
}
if err == io.EOF {
if errors.Is(err, io.EOF) {
return
}
if err != nil {

View File

@@ -39,7 +39,7 @@ func traceClientFromDockerContext(dockerCli command.Cli, otelEnv envMap) (otlptr
// automatic integration with Docker Desktop;
cfg, err := ConfigFromDockerContext(dockerCli.ContextStore(), dockerCli.CurrentContext())
if err != nil {
return nil, fmt.Errorf("loading otel config from docker context metadata: %v", err)
return nil, fmt.Errorf("loading otel config from docker context metadata: %w", err)
}
if cfg.Endpoint == "" {
@@ -52,13 +52,13 @@ func traceClientFromDockerContext(dockerCli command.Cli, otelEnv envMap) (otlptr
defer func() {
for k, v := range otelEnv {
if err := os.Setenv(k, v); err != nil {
panic(fmt.Errorf("restoring env for %q: %v", k, err))
panic(fmt.Errorf("restoring env for %q: %w", k, err))
}
}
}()
for k := range otelEnv {
if err := os.Unsetenv(k); err != nil {
return nil, fmt.Errorf("stashing env for %q: %v", k, err)
return nil, fmt.Errorf("stashing env for %q: %w", k, err)
}
}
@@ -71,7 +71,7 @@ func traceClientFromDockerContext(dockerCli command.Cli, otelEnv envMap) (otlptr
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
if err != nil {
return nil, fmt.Errorf("initializing otel connection from docker context metadata: %v", err)
return nil, fmt.Errorf("initializing otel connection from docker context metadata: %w", err)
}
client := otlptracegrpc.NewClient(otlptracegrpc.WithGRPCConn(conn))

View File

@@ -111,7 +111,7 @@ func InitProvider(dockerCli command.Cli) (ShutdownFunc, error) {
),
)
if err != nil {
return nil, fmt.Errorf("failed to create resource: %v", err)
return nil, fmt.Errorf("failed to create resource: %w", err)
}
muxExporter := MuxExporter{exporters: exporters}

View File

@@ -363,6 +363,7 @@ type PortOptions struct {
// PublishOptions group options of the Publish API
type PublishOptions struct {
ResolveImageDigests bool
}
func (e Event) String() string {

View File

@@ -21,6 +21,7 @@ import (
"context"
"crypto/rand"
"encoding/json"
"errors"
"fmt"
"io"
"net"
@@ -44,7 +45,6 @@ import (
"github.com/docker/docker/client"
"github.com/docker/docker/pkg/jsonmessage"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)
const (

View File

@@ -17,7 +17,7 @@
package api
import (
"github.com/pkg/errors"
"errors"
)
const (

View File

@@ -17,35 +17,36 @@
package api
import (
"errors"
"fmt"
"testing"
"github.com/pkg/errors"
"gotest.tools/v3/assert"
)
func TestIsNotFound(t *testing.T) {
err := errors.Wrap(ErrNotFound, `object "name"`)
err := fmt.Errorf(`object "name": %w`, ErrNotFound)
assert.Assert(t, IsNotFoundError(err))
assert.Assert(t, !IsNotFoundError(errors.New("another error")))
}
func TestIsAlreadyExists(t *testing.T) {
err := errors.Wrap(ErrAlreadyExists, `object "name"`)
err := fmt.Errorf(`object "name": %w`, ErrAlreadyExists)
assert.Assert(t, IsAlreadyExistsError(err))
assert.Assert(t, !IsAlreadyExistsError(errors.New("another error")))
}
func TestIsForbidden(t *testing.T) {
err := errors.Wrap(ErrForbidden, `object "name"`)
err := fmt.Errorf(`object "name": %w`, ErrForbidden)
assert.Assert(t, IsForbiddenError(err))
assert.Assert(t, !IsForbiddenError(errors.New("another error")))
}
func TestIsUnknown(t *testing.T) {
err := errors.Wrap(ErrUnknown, `object "name"`)
err := fmt.Errorf(`object "name": %w`, ErrUnknown)
assert.Assert(t, IsUnknownError(err))
assert.Assert(t, !IsUnknownError(errors.New("another error")))

View File

@@ -18,6 +18,7 @@ package compose
import (
"context"
"errors"
"fmt"
"io"
"strings"
@@ -132,7 +133,8 @@ func (s *composeService) attachContainerStreams(ctx context.Context, container s
if streamIn != nil && stdin != nil {
go func() {
_, err := io.Copy(streamIn, stdin)
if _, ok := err.(term.EscapeError); ok {
var escapeErr term.EscapeError
if errors.As(err, &escapeErr) {
close(detached)
}
}()

View File

@@ -22,6 +22,7 @@ import (
"fmt"
"os"
"path/filepath"
"sync"
"github.com/compose-spec/compose-go/types"
"github.com/containerd/containerd/platforms"
@@ -32,11 +33,13 @@ import (
"github.com/docker/buildx/util/buildflags"
xprogress "github.com/docker/buildx/util/progress"
"github.com/docker/cli/cli/command"
cliopts "github.com/docker/cli/opts"
"github.com/docker/compose/v2/internal/tracing"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/progress"
"github.com/docker/compose/v2/pkg/utils"
"github.com/docker/docker/builder/remotecontext/urlutil"
"github.com/docker/go-units"
bclient "github.com/moby/buildkit/client"
"github.com/moby/buildkit/session"
"github.com/moby/buildkit/session/auth/authprovider"
@@ -61,6 +64,11 @@ func (s *composeService) Build(ctx context.Context, project *types.Project, opti
}, s.stdinfo(), "Building")
}
type serviceToBuild struct {
idx int
service types.ServiceConfig
}
//nolint:gocyclo
func (s *composeService) build(ctx context.Context, project *types.Project, options api.BuildOptions, localImages map[string]string) (map[string]string, error) {
buildkitEnabled, err := s.dockerCli.BuildKitEnabled()
@@ -68,6 +76,36 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
return nil, err
}
imageIDs := map[string]string{}
serviceToBeBuild := map[string]serviceToBuild{}
mapServiceMutx := sync.Mutex{}
err = InDependencyOrder(ctx, project, func(ctx context.Context, name string) error {
if len(options.Services) > 0 && !utils.Contains(options.Services, name) {
return nil
}
service, idx := getServiceIndex(project, name)
if service.Build == nil {
return nil
}
image := api.GetImageNameOrDefault(service, project.Name)
_, localImagePresent := localImages[image]
if localImagePresent && service.PullPolicy != types.PullPolicyBuild {
return nil
}
mapServiceMutx.Lock()
serviceToBeBuild[name] = serviceToBuild{idx: idx, service: service}
mapServiceMutx.Unlock()
return nil
}, func(traversal *graphTraversal) {
traversal.maxConcurrency = s.maxConcurrency
})
if err != nil || len(serviceToBeBuild) == 0 {
return imageIDs, err
}
// Initialize buildkit nodes
var (
b *builder.Builder
@@ -111,17 +149,12 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
if len(options.Services) > 0 && !utils.Contains(options.Services, name) {
return nil
}
service, idx := getServiceIndex(project, name)
if service.Build == nil {
return nil
}
image := api.GetImageNameOrDefault(service, project.Name)
_, localImagePresent := localImages[image]
if localImagePresent && service.PullPolicy != types.PullPolicyBuild {
serviceToBuild, ok := serviceToBeBuild[name]
if !ok {
return nil
}
service := serviceToBuild.service
idx := serviceToBuild.idx
if !buildkitEnabled {
id, err := s.doBuildClassic(ctx, project, service, options)
@@ -167,7 +200,6 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
return nil, err
}
imageIDs := map[string]string{}
for i, imageDigest := range builtDigests {
if imageDigest != "" {
imageRef := api.GetImageNameOrDefault(project.Services[i], project.Name)
@@ -407,11 +439,24 @@ func (s *composeService) toBuildOptions(project *types.Project, service types.Se
Labels: imageLabels,
NetworkMode: service.Build.Network,
ExtraHosts: service.Build.ExtraHosts.AsList(),
Ulimits: toUlimitOpt(service.Build.Ulimits),
Session: sessionConfig,
Allow: allow,
}, nil
}
func toUlimitOpt(ulimits map[string]*types.UlimitsConfig) *cliopts.UlimitOpt {
ref := map[string]*units.Ulimit{}
for _, limit := range toUlimits(ulimits) {
ref[limit.Name] = &units.Ulimit{
Name: limit.Name,
Hard: limit.Hard,
Soft: limit.Soft,
}
}
return cliopts.NewUlimitOpt(&ref)
}
func flatten(in types.MappingWithEquals) types.Mapping {
out := types.Mapping{}
if len(in) == 0 {

View File

@@ -19,6 +19,7 @@ package compose
import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"os"
@@ -41,7 +42,6 @@ import (
"github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/pkg/progress"
"github.com/docker/docker/pkg/streamformatter"
"github.com/pkg/errors"
"github.com/docker/compose/v2/pkg/api"
)
@@ -64,19 +64,19 @@ func (s *composeService) doBuildClassic(ctx context.Context, project *types.Proj
buildBuff := s.stdout()
if len(service.Build.Platforms) > 1 {
return "", errors.Errorf("the classic builder doesn't support multi-arch build, set DOCKER_BUILDKIT=1 to use BuildKit")
return "", fmt.Errorf("the classic builder doesn't support multi-arch build, set DOCKER_BUILDKIT=1 to use BuildKit")
}
if service.Build.Privileged {
return "", errors.Errorf("the classic builder doesn't support privileged mode, set DOCKER_BUILDKIT=1 to use BuildKit")
return "", fmt.Errorf("the classic builder doesn't support privileged mode, set DOCKER_BUILDKIT=1 to use BuildKit")
}
if len(service.Build.AdditionalContexts) > 0 {
return "", errors.Errorf("the classic builder doesn't support additional contexts, set DOCKER_BUILDKIT=1 to use BuildKit")
return "", fmt.Errorf("the classic builder doesn't support additional contexts, set DOCKER_BUILDKIT=1 to use BuildKit")
}
if len(service.Build.SSH) > 0 {
return "", errors.Errorf("the classic builder doesn't support SSH keys, set DOCKER_BUILDKIT=1 to use BuildKit")
return "", fmt.Errorf("the classic builder doesn't support SSH keys, set DOCKER_BUILDKIT=1 to use BuildKit")
}
if len(service.Build.Secrets) > 0 {
return "", errors.Errorf("the classic builder doesn't support secrets, set DOCKER_BUILDKIT=1 to use BuildKit")
return "", fmt.Errorf("the classic builder doesn't support secrets, set DOCKER_BUILDKIT=1 to use BuildKit")
}
if service.Build.Labels == nil {
@@ -91,7 +91,7 @@ func (s *composeService) doBuildClassic(ctx context.Context, project *types.Proj
// Dockerfile is outside of build-context; read the Dockerfile and pass it as dockerfileCtx
dockerfileCtx, err = os.Open(dockerfileName)
if err != nil {
return "", errors.Errorf("unable to open Dockerfile: %v", err)
return "", fmt.Errorf("unable to open Dockerfile: %w", err)
}
defer dockerfileCtx.Close() //nolint:errcheck
}
@@ -100,11 +100,11 @@ func (s *composeService) doBuildClassic(ctx context.Context, project *types.Proj
case urlutil.IsURL(specifiedContext):
buildCtx, relDockerfile, err = build.GetContextFromURL(progBuff, specifiedContext, dockerfileName)
default:
return "", errors.Errorf("unable to prepare context: path %q not found", specifiedContext)
return "", fmt.Errorf("unable to prepare context: path %q not found", specifiedContext)
}
if err != nil {
return "", errors.Errorf("unable to prepare context: %s", err)
return "", fmt.Errorf("unable to prepare context: %w", err)
}
if tempDir != "" {
@@ -120,7 +120,7 @@ func (s *composeService) doBuildClassic(ctx context.Context, project *types.Proj
}
if err := build.ValidateContextDirectory(contextDir, excludes); err != nil {
return "", errors.Wrap(err, "checking context")
return "", fmt.Errorf("checking context: %w", err)
}
// And canonicalize dockerfile name to a platform-independent one
@@ -188,7 +188,8 @@ func (s *composeService) doBuildClassic(ctx context.Context, project *types.Proj
err = jsonmessage.DisplayJSONMessagesStream(response.Body, buildBuff, progBuff.FD(), true, aux)
if err != nil {
if jerr, ok := err.(*jsonmessage.JSONError); ok {
var jerr *jsonmessage.JSONError
if errors.As(err, &jerr) {
// If no error code is set, default to 1
if jerr.Code == 0 {
jerr.Code = 1

View File

@@ -41,7 +41,6 @@ import (
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/client"
"github.com/opencontainers/go-digest"
"github.com/pkg/errors"
)
var stdioToStdout bool
@@ -137,13 +136,14 @@ func getCanonicalContainerName(c moby.Container) string {
}
func getContainerNameWithoutProject(c moby.Container) string {
name := getCanonicalContainerName(c)
project := c.Labels[api.ProjectLabel]
prefix := fmt.Sprintf("%s_%s_", project, c.Labels[api.ServiceLabel])
if strings.HasPrefix(name, prefix) {
return name[len(project)+1:]
defaultName := getDefaultContainerName(project, c.Labels[api.ServiceLabel], c.Labels[api.ContainerNumberLabel])
name := getCanonicalContainerName(c)
if name != defaultName {
// service declares a custom container_name
return name
}
return name
return name[len(project)+1:]
}
func (s *composeService) Config(ctx context.Context, project *types.Project, options api.ConfigOptions) ([]byte, error) {
@@ -180,7 +180,7 @@ func (s *composeService) projectFromName(containers Containers, projectName stri
Name: projectName,
}
if len(containers) == 0 {
return project, errors.Wrap(api.ErrNotFound, fmt.Sprintf("no container found for project %q", projectName))
return project, fmt.Errorf("no container found for project %q: %w", projectName, api.ErrNotFound)
}
set := map[string]*types.ServiceConfig{}
for _, c := range containers {
@@ -226,7 +226,7 @@ SERVICES:
continue SERVICES
}
}
return project, errors.Wrapf(api.ErrNotFound, "no such service: %q", qs)
return project, fmt.Errorf("no such service: %q: %w", qs, api.ErrNotFound)
}
err := project.ForServices(services)
if err != nil {
@@ -295,5 +295,22 @@ func (s *composeService) isSWarmEnabled(ctx context.Context) (bool, error) {
}
})
return swarmEnabled.val, swarmEnabled.err
}
var runtimeVersion = struct {
once sync.Once
val string
err error
}{}
func (s *composeService) RuntimeVersion(ctx context.Context) (string, error) {
runtimeVersion.once.Do(func() {
version, err := s.dockerCli.Client().ServerVersion(ctx)
if err != nil {
runtimeVersion.err = err
}
runtimeVersion.val = version.APIVersion
})
return runtimeVersion.val, runtimeVersion.err
}

View File

@@ -22,6 +22,7 @@ import (
"sort"
"strconv"
"github.com/compose-spec/compose-go/types"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/utils"
moby "github.com/docker/docker/api/types"
@@ -123,6 +124,21 @@ func isNotService(services ...string) containerPredicate {
}
}
// isOrphaned is a predicate to select containers without a matching service definition in compose project
func isOrphaned(project *types.Project) containerPredicate {
var services []string
for _, s := range project.Services {
services = append(services, s.Name)
}
for _, s := range project.DisabledServices {
services = append(services, s.Name)
}
return func(c moby.Container) bool {
service := c.Labels[api.ServiceLabel]
return !utils.StringContains(services, service)
}
}
func isNotOneOff(c moby.Container) bool {
v, ok := c.Labels[api.OneoffLabel]
return !ok || v == "False"

View File

@@ -18,6 +18,7 @@ package compose
import (
"context"
"errors"
"fmt"
"sort"
"strconv"
@@ -34,7 +35,6 @@ import (
moby "github.com/docker/docker/api/types"
containerType "github.com/docker/docker/api/types/container"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"
@@ -287,13 +287,17 @@ func mustRecreate(expected types.ServiceConfig, actual moby.Container, policy st
}
func getContainerName(projectName string, service types.ServiceConfig, number int) string {
name := strings.Join([]string{projectName, service.Name, strconv.Itoa(number)}, api.Separator)
name := getDefaultContainerName(projectName, service.Name, strconv.Itoa(number))
if service.ContainerName != "" {
name = service.ContainerName
}
return name
}
func getDefaultContainerName(projectName, serviceName, index string) string {
return strings.Join([]string{projectName, serviceName, index}, api.Separator)
}
func getContainerProgressName(container moby.Container) string {
return "Container " + getCanonicalContainerName(container)
}
@@ -318,7 +322,7 @@ func containerReasonEvents(containers Containers, eventFunc func(string, string)
const ServiceConditionRunningOrHealthy = "running_or_healthy"
//nolint:gocyclo
func (s *composeService) waitDependencies(ctx context.Context, project *types.Project, dependencies types.DependsOnConfig, containers Containers) error {
func (s *composeService) waitDependencies(ctx context.Context, project *types.Project, dependant string, dependencies types.DependsOnConfig, containers Containers) error {
eg, _ := errgroup.WithContext(ctx)
w := progress.ContextWriter(ctx)
for dep, config := range dependencies {
@@ -330,6 +334,13 @@ func (s *composeService) waitDependencies(ctx context.Context, project *types.Pr
waitingFor := containers.filter(isService(dep))
w.Events(containerEvents(waitingFor, progress.Waiting))
if len(waitingFor) == 0 {
if config.Required {
return fmt.Errorf("%s is missing dependency %s", dependant, dep)
}
logrus.Warnf("%s is missing dependency %s", dependant, dep)
continue
}
dep, config := dep, config
eg.Go(func() error {
@@ -365,7 +376,7 @@ func (s *composeService) waitDependencies(ctx context.Context, project *types.Pr
return nil
}
w.Events(containerEvents(waitingFor, progress.ErrorEvent))
return errors.Wrap(err, "dependency failed to start")
return fmt.Errorf("dependency failed to start: %w", err)
}
if healthy {
w.Events(containerEvents(waitingFor, progress.Healthy))
@@ -616,6 +627,11 @@ func (s *composeService) createMobyContainer(ctx context.Context,
}
err = s.injectSecrets(ctx, project, service, created.ID)
if err != nil {
return created, err
}
err = s.injectConfigs(ctx, project, service, created.ID)
return created, err
}
@@ -729,7 +745,7 @@ func (s *composeService) startService(ctx context.Context, project *types.Projec
return nil
}
err := s.waitDependencies(ctx, project, service.DependsOn, containers)
err := s.waitDependencies(ctx, project, service.Name, service.DependsOn, containers)
if err != nil {
return err
}

View File

@@ -224,21 +224,21 @@ func TestWaitDependencies(t *testing.T) {
t.Run("should skip dependencies with scale 0", func(t *testing.T) {
dbService := types.ServiceConfig{Name: "db", Scale: 0}
redisService := types.ServiceConfig{Name: "redis", Scale: 0}
project := types.Project{Name: strings.ToLower(testProject), Services: []types.ServiceConfig{dbService, redisService}}
project := types.Project{Name: strings.ToLower(testProject), Services: types.Services{dbService, redisService}}
dependencies := types.DependsOnConfig{
"db": {Condition: ServiceConditionRunningOrHealthy},
"redis": {Condition: ServiceConditionRunningOrHealthy},
}
assert.NilError(t, tested.waitDependencies(context.Background(), &project, dependencies, nil))
assert.NilError(t, tested.waitDependencies(context.Background(), &project, "", dependencies, nil))
})
t.Run("should skip dependencies with condition service_started", func(t *testing.T) {
dbService := types.ServiceConfig{Name: "db", Scale: 1}
redisService := types.ServiceConfig{Name: "redis", Scale: 1}
project := types.Project{Name: strings.ToLower(testProject), Services: []types.ServiceConfig{dbService, redisService}}
project := types.Project{Name: strings.ToLower(testProject), Services: types.Services{dbService, redisService}}
dependencies := types.DependsOnConfig{
"db": {Condition: types.ServiceConditionStarted, Required: true},
"redis": {Condition: types.ServiceConditionStarted, Required: true},
}
assert.NilError(t, tested.waitDependencies(context.Background(), &project, dependencies, nil))
assert.NilError(t, tested.waitDependencies(context.Background(), &project, "", dependencies, nil))
})
}

View File

@@ -18,6 +18,7 @@ package compose
import (
"context"
"errors"
"fmt"
"io"
"os"
@@ -32,7 +33,6 @@ import (
moby "github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/system"
"github.com/pkg/errors"
)
type copyDirection int
@@ -175,7 +175,7 @@ func (s *composeService) copyToContainer(ctx context.Context, containerID string
// Validate the destination path
if err := command.ValidateOutputPathFileMode(dstStat.Mode); err != nil {
return errors.Wrapf(err, `destination "%s:%s" must be a directory or a regular file`, containerID, dstPath)
return fmt.Errorf(`destination "%s:%s" must be a directory or a regular file: %w`, containerID, dstPath, err)
}
// Ignore any error and assume that the parent directory of the destination
@@ -197,7 +197,7 @@ func (s *composeService) copyToContainer(ctx context.Context, containerID string
content = s.stdin()
resolvedDstPath = dstInfo.Path
if !dstInfo.IsDir {
return errors.Errorf("destination \"%s:%s\" must be a directory", containerID, dstPath)
return fmt.Errorf("destination \"%s:%s\" must be a directory", containerID, dstPath)
}
} else {
// Prepare source copy info.

View File

@@ -20,6 +20,7 @@ import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"os"
"path"
@@ -38,7 +39,6 @@ import (
"github.com/docker/docker/errdefs"
"github.com/docker/go-connections/nat"
"github.com/docker/go-units"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/compose-spec/compose-go/types"
@@ -345,17 +345,17 @@ func parseSecurityOpts(p *types.Project, securityOpts []string) ([]string, bool,
if strings.Contains(opt, ":") {
con = strings.SplitN(opt, ":", 2)
} else {
return securityOpts, false, errors.Errorf("Invalid security-opt: %q", opt)
return securityOpts, false, fmt.Errorf("Invalid security-opt: %q", opt)
}
}
if con[0] == "seccomp" && con[1] != "unconfined" {
f, err := os.ReadFile(p.RelativePath(con[1]))
if err != nil {
return securityOpts, false, errors.Errorf("opening seccomp profile (%s) failed: %v", con[1], err)
return securityOpts, false, fmt.Errorf("opening seccomp profile (%s) failed: %w", con[1], err)
}
b := bytes.NewBuffer(nil)
if err := json.Compact(b, f); err != nil {
return securityOpts, false, errors.Errorf("compacting json for seccomp profile (%s) failed: %v", con[1], err)
return securityOpts, false, fmt.Errorf("compacting json for seccomp profile (%s) failed: %w", con[1], err)
}
parsed = append(parsed, fmt.Sprintf("seccomp=%s", b.Bytes()))
} else {
@@ -521,7 +521,14 @@ func getDeployResources(s types.ServiceConfig) container.Resources {
})
}
for name, u := range s.Ulimits {
ulimits := toUlimits(s.Ulimits)
resources.Ulimits = ulimits
return resources
}
func toUlimits(m map[string]*types.UlimitsConfig) []*units.Ulimit {
var ulimits []*units.Ulimit
for name, u := range m {
soft := u.Single
if u.Soft != 0 {
soft = u.Soft
@@ -530,13 +537,13 @@ func getDeployResources(s types.ServiceConfig) container.Resources {
if u.Hard != 0 {
hard = u.Hard
}
resources.Ulimits = append(resources.Ulimits, &units.Ulimit{
ulimits = append(ulimits, &units.Ulimit{
Name: name,
Hard: int64(hard),
Soft: int64(soft),
})
}
return resources
return ulimits
}
func setReservations(reservations *types.Resource, resources *container.Resources) {
@@ -805,6 +812,17 @@ func buildContainerConfigMounts(p types.Project, s types.ServiceConfig) ([]mount
return nil, fmt.Errorf("unsupported external config %s", definedConfig.Name)
}
if definedConfig.Driver != "" {
return nil, errors.New("Docker Compose does not support configs.*.driver")
}
if definedConfig.TemplateDriver != "" {
return nil, errors.New("Docker Compose does not support configs.*.template_driver")
}
if definedConfig.Environment != "" || definedConfig.Content != "" {
continue
}
bindMount, err := buildMount(p, types.ServiceVolumeConfig{
Type: types.VolumeTypeBind,
Source: definedConfig.File,
@@ -844,6 +862,13 @@ func buildContainerSecretMounts(p types.Project, s types.ServiceConfig) ([]mount
return nil, fmt.Errorf("unsupported external secret %s", definedSecret.Name)
}
if definedSecret.Driver != "" {
return nil, errors.New("Docker Compose does not support secrets.*.driver")
}
if definedSecret.TemplateDriver != "" {
return nil, errors.New("Docker Compose does not support secrets.*.template_driver")
}
if definedSecret.Environment != "" {
continue
}
@@ -1111,7 +1136,7 @@ func (s *composeService) resolveOrCreateNetwork(ctx context.Context, n *types.Ne
_, err = s.apiClient().NetworkCreate(ctx, n.Name, createOpts)
if err != nil {
w.Event(progress.ErrorEvent(networkEventName))
return errors.Wrapf(err, "failed to create network %s", n.Name)
return fmt.Errorf("failed to create network %s: %w", n.Name, err)
}
w.Event(progress.CreatedEvent(networkEventName))
return nil
@@ -1125,13 +1150,27 @@ func (s *composeService) resolveExternalNetwork(ctx context.Context, n *types.Ne
networks, err := s.apiClient().NetworkList(ctx, moby.NetworkListOptions{
Filters: filters.NewArgs(filters.Arg("name", n.Name)),
})
if err != nil {
return err
}
if len(networks) == 0 {
// in this instance, n.Name is really an ID
sn, err := s.apiClient().NetworkInspect(ctx, n.Name, moby.NetworkInspectOptions{})
if err != nil {
return err
}
networks = append(networks, sn)
}
// NetworkList API doesn't return the exact name match, so we can retrieve more than one network with a request
networks = utils.Filter(networks, func(net moby.NetworkResource) bool {
return net.Name == n.Name
// later in this function, the name is changed the to ID.
// this function is called during the rebuild stage of `compose watch`.
// we still require just one network back, but we need to run the search on the ID
return net.Name == n.Name || net.ID == n.Name
})
switch len(networks) {

View File

@@ -24,7 +24,6 @@ import (
"github.com/compose-spec/compose-go/types"
"github.com/docker/compose/v2/pkg/api"
"github.com/pkg/errors"
"golang.org/x/sync/errgroup"
"github.com/docker/compose/v2/pkg/utils"
@@ -324,10 +323,10 @@ func (g *Graph) AddEdge(source string, destination string) error {
destinationVertex := g.Vertices[destination]
if sourceVertex == nil {
return errors.Wrapf(api.ErrNotFound, "could not find %s", source)
return fmt.Errorf("could not find %s: %w", source, api.ErrNotFound)
}
if destinationVertex == nil {
return errors.Wrapf(api.ErrNotFound, "could not find %s", destination)
return fmt.Errorf("could not find %s: %w", destination, api.ErrNotFound)
}
// If they are already connected

View File

@@ -32,7 +32,7 @@ import (
func createTestProject() *types.Project {
return &types.Project{
Services: []types.ServiceConfig{
Services: types.Services{
{
Name: "test1",
DependsOn: map[string]types.ServiceDependency{
@@ -59,7 +59,7 @@ func TestTraversalWithMultipleParents(t *testing.T) {
}
project := types.Project{
Services: []types.ServiceConfig{dependent},
Services: types.Services{dependent},
}
for i := 1; i <= 100; i++ {

View File

@@ -29,7 +29,6 @@ import (
containerType "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/errdefs"
"github.com/pkg/errors"
"golang.org/x/sync/errgroup"
"github.com/docker/compose/v2/pkg/api"
@@ -84,7 +83,7 @@ func (s *composeService) down(ctx context.Context, projectName string, options a
return err
}
orphans := containers.filter(isNotService(project.ServiceNames()...))
orphans := containers.filter(isOrphaned(project))
if options.RemoveOrphans && len(orphans) > 0 {
err := s.removeContainers(ctx, w, orphans, options.Timeout, false)
if err != nil {
@@ -192,7 +191,7 @@ func (s *composeService) removeNetwork(ctx context.Context, composeNetworkName s
networkFilter(composeNetworkName)),
})
if err != nil {
return errors.Wrapf(err, "failed to list networks")
return fmt.Errorf("failed to list networks: %w", err)
}
if len(networks) == 0 {
@@ -226,7 +225,7 @@ func (s *composeService) removeNetwork(ctx context.Context, composeNetworkName s
continue
}
w.Event(progress.ErrorEvent(eventName))
return errors.Wrapf(err, fmt.Sprintf("failed to remove network %s", name))
return fmt.Errorf("failed to remove network %s: %w", name, err)
}
w.Event(progress.RemovedEvent(eventName))
found++

View File

@@ -17,10 +17,9 @@
package compose
import (
"errors"
"io/fs"
"github.com/pkg/errors"
"github.com/compose-spec/compose-go/errdefs"
)

View File

@@ -18,6 +18,7 @@ package compose
import (
"context"
"errors"
"strings"
"github.com/docker/cli/cli"
@@ -50,7 +51,8 @@ func (s *composeService) Exec(ctx context.Context, projectName string, options a
}
err = container.RunExec(s.dockerCli, exec)
if sterr, ok := err.(cli.StatusError); ok {
var sterr cli.StatusError
if errors.As(err, &sterr) {
return sterr.StatusCode, nil
}
return 0, err

View File

@@ -90,7 +90,7 @@ func (s *composeService) getImages(ctx context.Context, images []string) (map[st
if errdefs.IsNotFound(err) {
return nil
}
return err
return fmt.Errorf("unable to get image '%s': %w", img, err)
}
tag := ""
repository := ""

View File

@@ -114,7 +114,7 @@ func testContainer(service string, id string, oneOff bool) moby.Container {
}
func containerLabels(service string, oneOff bool) map[string]string {
workingdir, _ := filepath.Abs("testdata")
workingdir := "/src/pkg/compose/testdata"
composefile := filepath.Join(workingdir, "compose.yaml")
labels := map[string]string{
compose.ServiceLabel: service,

View File

@@ -18,6 +18,7 @@ package compose
import (
"context"
"errors"
"io"
"strings"
"time"
@@ -56,7 +57,8 @@ func (s *composeService) Logs(
c := c
eg.Go(func() error {
err := s.logContainers(ctx, consumer, c, options)
if _, ok := err.(errdefs.ErrNotImplemented); ok {
var notImplErr errdefs.ErrNotImplemented
if errors.As(err, &notImplErr) {
logrus.Warnf("Can't retrieve logs for %q: %s", getCanonicalContainerName(c), err.Error())
return nil
}
@@ -97,7 +99,8 @@ func (s *composeService) Logs(
Tail: options.Tail,
Timestamps: options.Timestamps,
})
if _, ok := err.(errdefs.ErrNotImplemented); ok {
var notImplErr errdefs.ErrNotImplemented
if errors.As(err, &notImplErr) {
// ignore
return nil
}

View File

@@ -20,6 +20,8 @@ import (
"context"
"encoding/json"
"os"
"path/filepath"
"time"
"github.com/compose-spec/compose-go/types"
"github.com/distribution/reference"
@@ -61,36 +63,24 @@ func (s *composeService) publish(ctx context.Context, project *types.Project, re
return err
}
w.Event(progress.Event{
ID: file,
Text: "publishing",
Status: progress.Working,
})
layer := v1.Descriptor{
MediaType: "application/vnd.docker.compose.file+yaml",
Digest: digest.FromString(string(f)),
Size: int64(len(f)),
Annotations: map[string]string{
"com.docker.compose": api.ComposeVersion,
},
layer, err := s.pushComposeFile(ctx, file, f, resolver, named)
if err != nil {
return err
}
layers = append(layers, layer)
err = resolver.Push(ctx, named, layer, f)
if err != nil {
w.Event(progress.Event{
ID: file,
Text: "publishing",
Status: progress.Error,
})
}
if options.ResolveImageDigests {
yaml, err := s.generateImageDigestsOverride(ctx, project)
if err != nil {
return err
}
w.Event(progress.Event{
ID: file,
Text: "published",
Status: progress.Done,
})
layer, err := s.pushComposeFile(ctx, "image-digests.yaml", yaml, resolver, named)
if err != nil {
return err
}
layers = append(layers, layer)
}
emptyConfig, err := json.Marshal(v1.ImageConfig{})
@@ -98,27 +88,29 @@ func (s *composeService) publish(ctx context.Context, project *types.Project, re
return err
}
configDescriptor := v1.Descriptor{
MediaType: "application/vnd.docker.compose.project",
MediaType: "application/vnd.oci.empty.v1+json",
Digest: digest.FromBytes(emptyConfig),
Size: int64(len(emptyConfig)),
Annotations: map[string]string{
"com.docker.compose.version": api.ComposeVersion,
},
}
err = resolver.Push(ctx, named, configDescriptor, emptyConfig)
if err != nil {
return err
}
imageManifest, err := json.Marshal(v1.Manifest{
Versioned: specs.Versioned{SchemaVersion: 2},
MediaType: v1.MediaTypeImageManifest,
ArtifactType: "application/vnd.docker.compose.project",
Config: configDescriptor,
Layers: layers,
})
if err != nil {
return err
var imageManifest []byte
if !s.dryRun {
err = resolver.Push(ctx, named, configDescriptor, emptyConfig)
if err != nil {
return err
}
imageManifest, err = json.Marshal(v1.Manifest{
Versioned: specs.Versioned{SchemaVersion: 2},
MediaType: v1.MediaTypeImageManifest,
ArtifactType: "application/vnd.docker.compose.project",
Config: configDescriptor,
Layers: layers,
Annotations: map[string]string{
"org.opencontainers.image.created": time.Now().Format(time.RFC3339),
},
})
if err != nil {
return err
}
}
w.Event(progress.Event{
@@ -126,23 +118,24 @@ func (s *composeService) publish(ctx context.Context, project *types.Project, re
Text: "publishing",
Status: progress.Working,
})
err = resolver.Push(ctx, named, v1.Descriptor{
MediaType: v1.MediaTypeImageManifest,
Digest: digest.FromString(string(imageManifest)),
Size: int64(len(imageManifest)),
Annotations: map[string]string{
"com.docker.compose.version": api.ComposeVersion,
},
ArtifactType: "application/vnd.docker.compose.project",
}, imageManifest)
if err != nil {
w.Event(progress.Event{
ID: repository,
Text: "publishing",
Status: progress.Error,
})
return err
if !s.dryRun {
err = resolver.Push(ctx, named, v1.Descriptor{
MediaType: v1.MediaTypeImageManifest,
Digest: digest.FromString(string(imageManifest)),
Size: int64(len(imageManifest)),
Annotations: map[string]string{
"com.docker.compose.version": api.ComposeVersion,
},
ArtifactType: "application/vnd.docker.compose.project",
}, imageManifest)
if err != nil {
w.Event(progress.Event{
ID: repository,
Text: "publishing",
Status: progress.Error,
})
return err
}
}
w.Event(progress.Event{
ID: repository,
@@ -151,3 +144,61 @@ func (s *composeService) publish(ctx context.Context, project *types.Project, re
})
return nil
}
func (s *composeService) generateImageDigestsOverride(ctx context.Context, project *types.Project) ([]byte, error) {
project.ApplyProfiles([]string{"*"})
err := project.ResolveImages(func(named reference.Named) (digest.Digest, error) {
auth, err := encodedAuth(named, s.configFile())
if err != nil {
return "", err
}
inspect, err := s.apiClient().DistributionInspect(ctx, named.String(), auth)
if err != nil {
return "", err
}
return inspect.Descriptor.Digest, nil
})
if err != nil {
return nil, err
}
override := types.Project{}
for _, service := range project.Services {
override.Services = append(override.Services, types.ServiceConfig{
Name: service.Name,
Image: service.Image,
})
}
return override.MarshalYAML()
}
func (s *composeService) pushComposeFile(ctx context.Context, file string, content []byte, resolver *imagetools.Resolver, named reference.Named) (v1.Descriptor, error) {
w := progress.ContextWriter(ctx)
w.Event(progress.Event{
ID: file,
Text: "publishing",
Status: progress.Working,
})
layer := v1.Descriptor{
MediaType: "application/vnd.docker.compose.file+yaml",
Digest: digest.FromString(string(content)),
Size: int64(len(content)),
Annotations: map[string]string{
"com.docker.compose.version": api.ComposeVersion,
"com.docker.compose.file": filepath.Base(file),
},
}
err := resolver.Push(ctx, named, layer, content)
w.Event(progress.Event{
ID: file,
Text: "published",
Status: statusFor(err),
})
return layer, err
}
func statusFor(err error) progress.EventStatus {
if err != nil {
return progress.Error
}
return progress.Done
}

View File

@@ -215,7 +215,7 @@ func (s *composeService) pullServiceImage(ctx context.Context, service types.Ser
for {
var jm jsonmessage.JSONMessage
if err := dec.Decode(&jm); err != nil {
if err == io.EOF {
if errors.Is(err, io.EOF) {
break
}
return "", WrapCategorisedComposeError(err, PullFailure)
@@ -260,7 +260,7 @@ func encodedAuth(ref reference.Named, configFile driver.Auth) (string, error) {
}
func (s *composeService) pullRequiredImages(ctx context.Context, project *types.Project, images map[string]string, quietPull bool) error {
var needPull []types.ServiceConfig
var needPull types.Services
for _, service := range project.Services {
if service.Image == "" {
continue
@@ -308,7 +308,7 @@ func (s *composeService) pullRequiredImages(ctx context.Context, project *types.
}, s.stdinfo())
}
func isServiceImageToBuild(service types.ServiceConfig, services []types.ServiceConfig) bool {
func isServiceImageToBuild(service types.ServiceConfig, services types.Services) bool {
if service.Build != nil {
return true
}

View File

@@ -20,8 +20,10 @@ import (
"context"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io"
"strings"
"github.com/compose-spec/compose-go/types"
"github.com/distribution/reference"
@@ -29,7 +31,6 @@ import (
moby "github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/registry"
"github.com/pkg/errors"
"golang.org/x/sync/errgroup"
"github.com/docker/compose/v2/pkg/api"
@@ -68,22 +69,30 @@ func (s *composeService) push(ctx context.Context, project *types.Project, optio
continue
}
service := service
eg.Go(func() error {
err := s.pushServiceImage(ctx, service, info, s.configFile(), w, options.Quiet)
if err != nil {
if !options.IgnoreFailures {
return err
tags := []string{service.Image}
if service.Build != nil {
tags = append(tags, service.Build.Tags...)
}
for _, tag := range tags {
tag := tag
eg.Go(func() error {
err := s.pushServiceImage(ctx, tag, info, s.configFile(), w, options.Quiet)
if err != nil {
if !options.IgnoreFailures {
return err
}
w.TailMsgf("Pushing %s: %s", service.Name, err.Error())
}
w.TailMsgf("Pushing %s: %s", service.Name, err.Error())
}
return nil
})
return nil
})
}
}
return eg.Wait()
}
func (s *composeService) pushServiceImage(ctx context.Context, service types.ServiceConfig, info moby.Info, configFile driver.Auth, w progress.Writer, quietPush bool) error {
ref, err := reference.ParseNormalizedNamed(service.Image)
func (s *composeService) pushServiceImage(ctx context.Context, tag string, info moby.Info, configFile driver.Auth, w progress.Writer, quietPush bool) error {
ref, err := reference.ParseNormalizedNamed(tag)
if err != nil {
return err
}
@@ -107,7 +116,7 @@ func (s *composeService) pushServiceImage(ctx context.Context, service types.Ser
return err
}
stream, err := s.apiClient().ImagePush(ctx, service.Image, moby.ImagePushOptions{
stream, err := s.apiClient().ImagePush(ctx, tag, moby.ImagePushOptions{
RegistryAuth: base64.URLEncoding.EncodeToString(buf),
})
if err != nil {
@@ -117,7 +126,7 @@ func (s *composeService) pushServiceImage(ctx context.Context, service types.Ser
for {
var jm jsonmessage.JSONMessage
if err := dec.Decode(&jm); err != nil {
if err == io.EOF {
if errors.Is(err, io.EOF) {
break
}
return err
@@ -127,9 +136,10 @@ func (s *composeService) pushServiceImage(ctx context.Context, service types.Ser
}
if !quietPush {
toPushProgressEvent(service.Name, jm, w)
toPushProgressEvent(tag, jm, w)
}
}
return nil
}
@@ -145,7 +155,7 @@ func toPushProgressEvent(prefix string, jm jsonmessage.JSONMessage, w progress.W
current int64
percent int
)
if jm.Status == "Pushed" || jm.Status == "Already exists" {
if isDone(jm) {
status = progress.Done
percent = 100
}
@@ -174,3 +184,13 @@ func toPushProgressEvent(prefix string, jm jsonmessage.JSONMessage, w progress.W
StatusText: text,
})
}
func isDone(msg jsonmessage.JSONMessage) bool {
// TODO there should be a better way to detect push is done than such a status message check
switch strings.ToLower(msg.Status) {
case "pushed", "layer already exists":
return true
default:
return false
}
}

View File

@@ -92,7 +92,7 @@ func (s *composeService) prepareRun(ctx context.Context, project *types.Project,
}
if !opts.NoDeps {
if err := s.waitDependencies(ctx, project, service.DependsOn, observedState); err != nil {
if err := s.waitDependencies(ctx, project, service.Name, service.DependsOn, observedState); err != nil {
return "", err
}
}

View File

@@ -39,7 +39,7 @@ func (s *composeService) injectSecrets(ctx context.Context, project *types.Proje
if !ok {
return fmt.Errorf("environment variable %q required by secret %q is not set", secret.Environment, secret.Name)
}
b, err := createTar(env, config)
b, err := createTar(env, types.FileReferenceConfig(config))
if err != nil {
return err
}
@@ -54,7 +54,37 @@ func (s *composeService) injectSecrets(ctx context.Context, project *types.Proje
return nil
}
func createTar(env string, config types.ServiceSecretConfig) (bytes.Buffer, error) {
func (s *composeService) injectConfigs(ctx context.Context, project *types.Project, service types.ServiceConfig, id string) error {
for _, config := range service.Configs {
secret := project.Configs[config.Source]
content := secret.Content
if secret.Environment != "" {
env, ok := project.Environment[secret.Environment]
if !ok {
return fmt.Errorf("environment variable %q required by secret %q is not set", secret.Environment, secret.Name)
}
content = env
}
if content == "" {
continue
}
b, err := createTar(content, types.FileReferenceConfig(config))
if err != nil {
return err
}
err = s.apiClient().CopyToContainer(ctx, id, "/", &b, moby.CopyToContainerOptions{
CopyUIDGID: config.UID != "" || config.GID != "",
})
if err != nil {
return err
}
}
return nil
}
func createTar(env string, config types.FileReferenceConfig) (bytes.Buffer, error) {
value := []byte(env)
b := bytes.Buffer{}
tarWriter := tar.NewWriter(&b)

View File

@@ -18,6 +18,7 @@ package compose
import (
"context"
"errors"
"fmt"
"strings"
"time"
@@ -31,7 +32,6 @@ import (
"github.com/compose-spec/compose-go/types"
moby "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/pkg/errors"
"golang.org/x/sync/errgroup"
)
@@ -148,9 +148,9 @@ func (s *composeService) start(ctx context.Context, projectName string, options
defer cancel()
}
err = s.waitDependencies(ctx, project, depends, containers)
err = s.waitDependencies(ctx, project, project.Name, depends, containers)
if err != nil {
if ctx.Err() == context.DeadlineExceeded {
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
return fmt.Errorf("application not healthy after %s", options.WaitTimeout)
}
return err

View File

@@ -21,7 +21,6 @@ import (
"fmt"
"os"
"os/signal"
"sync"
"syscall"
"github.com/compose-spec/compose-go/types"
@@ -55,76 +54,79 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
return err
}
var eg multierror.Group
// if we get a second signal during shutdown, we kill the services
// immediately, so the channel needs to have sufficient capacity or
// we might miss a signal while setting up the second channel read
// (this is also why signal.Notify is used vs signal.NotifyContext)
signalChan := make(chan os.Signal, 2)
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
signalCancel := sync.OnceFunc(func() {
signal.Stop(signalChan)
close(signalChan)
defer close(signalChan)
var isTerminated bool
doneCh := make(chan bool)
eg.Go(func() error {
first := true
for {
select {
case <-doneCh:
return nil
case <-signalChan:
if first {
fmt.Fprintln(s.stdinfo(), "Gracefully stopping... (press Ctrl+C again to force)")
eg.Go(func() error {
err := s.Stop(context.Background(), project.Name, api.StopOptions{
Services: options.Create.Services,
Project: project,
})
isTerminated = true
close(doneCh)
return err
})
first = false
} else {
eg.Go(func() error {
return s.Kill(context.Background(), project.Name, api.KillOptions{
Services: options.Create.Services,
Project: project,
})
})
return nil
}
}
}
})
defer signalCancel()
printer := newLogPrinter(options.Start.Attach)
stopFunc := func() error {
fmt.Fprintln(s.stdinfo(), "Aborting on container exit...")
ctx := context.Background()
return progress.Run(ctx, func(ctx context.Context) error {
// race two goroutines - one that blocks until another signal is received
// and then does a Kill() and one that immediately starts a friendly Stop()
errCh := make(chan error, 1)
go func() {
if _, ok := <-signalChan; !ok {
// channel closed, so the outer function is done, which
// means the other goroutine (calling Stop()) finished
return
}
errCh <- s.Kill(ctx, project.Name, api.KillOptions{
Services: options.Create.Services,
Project: project,
})
}()
go func() {
errCh <- s.Stop(ctx, project.Name, api.StopOptions{
Services: options.Create.Services,
Project: project,
})
}()
return <-errCh
}, s.stdinfo())
}
var isTerminated bool
var eg multierror.Group
eg.Go(func() error {
if _, ok := <-signalChan; !ok {
// function finished without receiving a signal
return nil
}
isTerminated = true
printer.Cancel()
fmt.Fprintln(s.stdinfo(), "Gracefully stopping... (press Ctrl+C again to force)")
return stopFunc()
})
var exitCode int
eg.Go(func() error {
code, err := printer.Run(options.Start.CascadeStop, options.Start.ExitCodeFrom, stopFunc)
code, err := printer.Run(options.Start.CascadeStop, options.Start.ExitCodeFrom, func() error {
fmt.Fprintln(s.stdinfo(), "Aborting on container exit...")
return progress.Run(ctx, func(ctx context.Context) error {
return s.Stop(ctx, project.Name, api.StopOptions{
Services: options.Create.Services,
Project: project,
})
}, s.stdinfo())
})
exitCode = code
return err
})
err = s.start(ctx, project.Name, options.Start, printer.HandleEvent)
// We don't use parent (cancelable) context as we manage sigterm to stop the stack
err = s.start(context.Background(), project.Name, options.Start, printer.HandleEvent)
if err != nil && !isTerminated { // Ignore error if the process is terminated
return err
}
// signal for the goroutines to stop & wait for them to finish any remaining work
signalCancel()
printer.Stop()
if !isTerminated {
// signal for the signal-handler goroutines to stop
close(doneCh)
}
err = eg.Wait().ErrorOrNil()
if exitCode != 0 {
errMsg := ""

View File

@@ -33,7 +33,7 @@ func TestViz(t *testing.T) {
project := types.Project{
Name: "viz-test",
WorkingDir: "/home",
Services: []types.ServiceConfig{
Services: types.Services{
{
Name: "service1",
Image: "image-for-service1",

View File

@@ -16,6 +16,7 @@ package compose
import (
"context"
"errors"
"fmt"
"io"
"os"
@@ -33,7 +34,6 @@ import (
moby "github.com/docker/docker/api/types"
"github.com/jonboulle/clockwork"
"github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"
)
@@ -121,13 +121,14 @@ func (s *composeService) Watch(ctx context.Context, project *types.Project, serv
dotGitIgnore,
)
var paths []string
var paths, pathLogs []string
for _, trigger := range config.Watch {
if checkIfPathAlreadyBindMounted(trigger.Path, service.Volumes) {
logrus.Warnf("path '%s' also declared by a bind mount volume, this path won't be monitored!\n", trigger.Path)
continue
}
paths = append(paths, trigger.Path)
pathLogs = append(pathLogs, fmt.Sprintf("Action %s for path %q", trigger.Action, trigger.Path))
}
watcher, err := watch.NewWatcher(paths, ignore)
@@ -135,7 +136,12 @@ func (s *composeService) Watch(ctx context.Context, project *types.Project, serv
return err
}
fmt.Fprintf(s.stdinfo(), "watching %s\n", paths)
fmt.Fprintf(
s.stdinfo(),
"Watch configuration for service %q:%s\n",
service.Name,
strings.Join(append([]string{""}, pathLogs...), "\n - "),
)
err = watcher.Start()
if err != nil {
return err
@@ -149,7 +155,7 @@ func (s *composeService) Watch(ctx context.Context, project *types.Project, serv
}
if !watching {
return fmt.Errorf("none of the selected services is configured for watch, consider setting an 'x-develop' section")
return fmt.Errorf("none of the selected services is configured for watch, consider setting an 'develop' section")
}
return eg.Wait()
@@ -415,11 +421,12 @@ func (t tarDockerClient) Exec(ctx context.Context, containerID string, cmd []str
func (s *composeService) handleWatchBatch(ctx context.Context, project *types.Project, serviceName string, build api.BuildOptions, batch []fileEvent, syncer sync.Syncer) error {
pathMappings := make([]sync.PathMapping, len(batch))
restartService := false
for i := range batch {
if batch[i].Action == types.WatchActionRebuild {
fmt.Fprintf(
s.stdinfo(),
"Rebuilding %s after changes were detected:%s\n",
"Rebuilding service %q after changes were detected:%s\n",
serviceName,
strings.Join(append([]string{""}, batch[i].HostPath), "\n - "),
)
@@ -437,10 +444,13 @@ func (s *composeService) handleWatchBatch(ctx context.Context, project *types.Pr
},
})
if err != nil {
fmt.Fprintf(s.stderr(), "Application failed to start after update\n")
fmt.Fprintf(s.stderr(), "Application failed to start after update. Error: %v\n", err)
}
return nil
}
if batch[i].Action == types.WatchActionSyncRestart {
restartService = true
}
pathMappings[i] = batch[i].PathMapping
}
@@ -453,6 +463,13 @@ func (s *composeService) handleWatchBatch(ctx context.Context, project *types.Pr
if err := syncer.Sync(ctx, service, pathMappings); err != nil {
return err
}
if restartService {
return s.Restart(ctx, project.Name, api.RestartOptions{
Services: []string{serviceName},
Project: project,
NoDeps: false,
})
}
return nil
}
@@ -466,7 +483,7 @@ func writeWatchSyncMessage(w io.Writer, serviceName string, pathMappings []sync.
}
fmt.Fprintf(
w,
"Syncing %s after changes were detected:%s\n",
"Syncing %q after changes were detected:%s\n",
serviceName,
strings.Join(append([]string{""}, hostPathsToSync...), "\n - "),
)
@@ -477,7 +494,7 @@ func writeWatchSyncMessage(w io.Writer, serviceName string, pathMappings []sync.
}
fmt.Fprintf(
w,
"Syncing %s after %d changes were detected\n",
"Syncing service %q after %d changes were detected\n",
serviceName,
len(pathMappings),
)

View File

@@ -105,7 +105,7 @@ func TestWatch_Sync(t *testing.T) {
t.Cleanup(cancelFunc)
proj := types.Project{
Services: []types.ServiceConfig{
Services: types.Services{
{
Name: "test",
},

View File

@@ -333,7 +333,7 @@ func TestBuildPlatformsWithCorrectBuildxConfig(t *testing.T) {
t.Run("multi-arch up --build", func(t *testing.T) {
res := c.RunDockerComposeCmdNoCheck(t, "--project-directory", "fixtures/build-test/platforms", "up", "--build")
assert.NilError(t, res.Error, res.Stderr())
res.Assert(t, icmd.Expected{Out: "platforms-platforms-1 exited with code 0"})
res.Assert(t, icmd.Expected{Out: "platforms-1 exited with code 0"})
})
t.Run("use DOCKER_DEFAULT_PLATFORM value when up --build", func(t *testing.T) {

View File

@@ -106,6 +106,20 @@ func TestEnvPriority(t *testing.T) {
assert.Equal(t, strings.TrimSpace(res.Stdout()), "EnvFileDefaultValue")
})
// No Compose file, all other options with env variable from OS environment
// 1. Command Line (docker compose run --env <KEY[=VAL]>) <-- Result expected (From environment default value from file in COMPOSE_ENV_FILES)
// 2. Compose File (service::environment section)
// 3. Compose File (service::env_file section file)
// 4. Container Image ENV directive
// 5. Variable is not defined
t.Run("shell priority from COMPOSE_ENV_FILES variable", func(t *testing.T) {
cmd := c.NewDockerComposeCmd(t, "-f", "./fixtures/environment/env-priority/compose.yaml",
"run", "--rm", "-e", "WHEREAMI", "env-compose-priority")
cmd.Env = append(cmd.Env, "COMPOSE_ENV_FILES=./fixtures/environment/env-priority/.env.override.with.default")
res := icmd.RunCmd(cmd)
assert.Equal(t, strings.TrimSpace(res.Stdout()), "EnvFileDefaultValue")
})
// No Compose file and env variable pass to the run command
// 1. Command Line (docker compose run --env <KEY[=VAL]>) <-- Result expected
// 2. Compose File (service::environment section)

View File

@@ -96,10 +96,18 @@ func TestLocalComposeRun(t *testing.T) {
})
t.Run("compose run --publish", func(t *testing.T) {
c.RunDockerComposeCmd(t, "-f", "./fixtures/run-test/compose.yaml", "run", "--publish", "8081:80", "-d", "back",
c.RunDockerComposeCmd(t, "-f", "./fixtures/run-test/ports.yaml", "run", "--publish", "8081:80", "-d", "back",
"/bin/sh", "-c", "sleep 1")
res := c.RunDockerCmd(t, "ps")
assert.Assert(t, strings.Contains(res.Stdout(), "8081->80/tcp"), res.Stdout())
assert.Assert(t, !strings.Contains(res.Stdout(), "8082->80/tcp"), res.Stdout())
})
t.Run("compose run --service-ports", func(t *testing.T) {
c.RunDockerComposeCmd(t, "-f", "./fixtures/run-test/ports.yaml", "run", "--service-ports", "-d", "back",
"/bin/sh", "-c", "sleep 1")
res := c.RunDockerCmd(t, "ps")
assert.Assert(t, strings.Contains(res.Stdout(), "8082->80/tcp"), res.Stdout())
})
t.Run("compose run orphan", func(t *testing.T) {

View File

@@ -141,6 +141,8 @@ func TestDownComposefileInParentFolder(t *testing.T) {
}
func TestAttachRestart(t *testing.T) {
t.Skip("Skipping test until we can fix it")
if _, ok := os.LookupEnv("CI"); ok {
t.Skip("Skipping test on CI... flaky")
}
@@ -290,3 +292,24 @@ func TestStopWithDependenciesAttached(t *testing.T) {
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/dependencies/compose.yaml", "-p", projectName, "up", "--attach-dependencies", "foo")
res.Assert(t, icmd.Expected{Out: "exited with code 0"})
}
func TestRemoveOrphaned(t *testing.T) {
const projectName = "compose-e2e-remove-orphaned"
c := NewParallelCLI(t)
cleanup := func() {
c.RunDockerComposeCmd(t, "-p", projectName, "down", "--remove-orphans", "--timeout=0")
}
cleanup()
t.Cleanup(cleanup)
// run stack
c.RunDockerComposeCmd(t, "-f", "./fixtures/sentences/compose.yaml", "-p", projectName, "up", "-d")
// down "web" service with orphaned removed
c.RunDockerComposeCmd(t, "-f", "./fixtures/sentences/compose.yaml", "-p", projectName, "down", "--remove-orphans", "web")
// check "words" service has not been considered orphaned
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/sentences/compose.yaml", "-p", projectName, "ps", "--format", "{{.Name}}")
res.Assert(t, icmd.Expected{Out: fmt.Sprintf("%s-words-1", projectName)})
}

Some files were not shown because too many files have changed in this diff Show More