Compare commits

..

84 Commits

Author SHA1 Message Date
Tõnis Tiigi
1fc5647dc2 Merge pull request #2846 from tonistiigi/v0.19.2-picks
[v0.19] v0.19.2 cherry-picks
2024-12-06 14:45:47 -08:00
Tonis Tiigi
b2c0c26c26 bake: allow entitlements from overrides automatically
If override specifies a path, mark it automatically allowed
so there is no need to use duplicate flags for defining the
same feature.

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
(cherry picked from commit dd596d6542)
2024-12-06 14:15:46 -08:00
Tonis Tiigi
c30db6a955 bake: fix entitlements path checks for local outputs
Previous check based on dest attributes was not correct
as the attributes already get converted before validation happens.

Because the local path is not preserved for single-file
outputs and gets replaced by io.Writer, a temporary array variable
was needed. This value should instead be added to ExportEntry
struct in BuildKit in future revision.

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
(cherry picked from commit c6e403ad7f)
2024-12-06 14:02:04 -08:00
Tõnis Tiigi
5113f9ea89 Merge pull request #2824 from jsternberg/bake-revert-composable-attributes
[v0.19] revert: "bake: initial set of composable bake attributes"
2024-11-27 09:37:55 -08:00
CrazyMax
8b029626f3 bake: additional test for empty variable
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-27 18:28:43 +01:00
Jonathan A. Sternberg
cd017e98ed revert: "bake: initial set of composable bake attributes"
This reverts commit 3ccbb88e6a.

Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
2024-11-27 09:39:57 -06:00
Tõnis Tiigi
71c7889719 Merge pull request #2821 from tonistiigi/update-buildkit-v0.18.0
vendor: update buildkit to v0.18.0
2024-11-26 14:49:31 -08:00
Tonis Tiigi
a3418e0178 vendor: update buildkit to v0.18.0
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2024-11-26 13:57:25 -08:00
Tõnis Tiigi
6a1cf78879 Merge pull request #2818 from tonistiigi/vendor-buildkit-v0.18.0-rc2
vendor: update buildkit to v0.18.0-rc2
2024-11-25 17:52:46 -08:00
Tonis Tiigi
ec1f712328 vendor: update buildkit to v0.18.0-rc2
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2024-11-25 17:42:30 -08:00
CrazyMax
5ce6597c07 Merge pull request #2812 from crazy-max/bake-win-fs-ent
bake: add wildcard to fs entitlements to allow any paths
2024-11-25 20:29:14 +01:00
CrazyMax
9c75071793 bake: add wildcard to fs entitlements to allow any paths
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-25 20:13:27 +01:00
Tõnis Tiigi
d612139b19 Merge pull request #2811 from crazy-max/update-buildkit
dockerfile: update buildkit to v0.17.2
2024-11-25 10:11:09 -08:00
Tõnis Tiigi
42f7898c53 Merge pull request #2815 from tonistiigi/entitlements-symlink-tests
bake: fix entitlement test when running from symlink temp
2024-11-25 10:08:19 -08:00
Tonis Tiigi
3148c098a2 bake: remove unnecessary GetLongPathName calls
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2024-11-25 08:26:02 -08:00
Tonis Tiigi
f95d574f94 bake: fix entitlement test when running from symlink temp
As the paths returned by validator have the symlinks resolved,
the test needs to resolve the symlinks also in the expected
values. Previously this would fail if t.TempDir() or os.GetWd()
returned a path that contained a symlink.

The issue was purely in the test and not in the entitlements
validation logic.

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2024-11-25 00:03:54 -08:00
CrazyMax
60822781be ci: update buildkit to v0.17.2
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-22 13:00:07 +01:00
CrazyMax
4c83475703 dockerfile: update buildkit to v0.17.2
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-22 11:27:33 +01:00
Tõnis Tiigi
17eff25fe5 Merge pull request #2807 from tonistiigi/buildkit-v0.18.0-rc1
vendor: update buildkit to v0.18.0-rc1
2024-11-21 14:29:29 -08:00
Tõnis Tiigi
9c8ffb77d6 Merge pull request #2806 from tonistiigi/vendor-compose-v2.4.4
vendor: update compose to v2.4.4
2024-11-21 14:29:18 -08:00
Tonis Tiigi
13a426fca6 vendor: update buildkit to v0.18.0-rc1
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2024-11-21 12:57:27 -08:00
Tõnis Tiigi
1a039115bc Merge pull request #2758 from jsternberg/bake-composable-attributes
bake: initial set of composable bake attributes
2024-11-21 12:54:54 -08:00
Tonis Tiigi
07d58782b8 vendor: update compose to v2.4.4
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2024-11-21 10:32:02 -08:00
Jonathan A. Sternberg
3ccbb88e6a bake: initial set of composable bake attributes
This allows using either the csv syntax or object syntax to specify
certain attributes.

This applies to the following fields:
- output
- cache-from
- cache-to
- secret
- ssh

There are still some remaining fields to translate. Specifically
ulimits, annotations, and attest.

Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
2024-11-21 12:31:11 -06:00
Tõnis Tiigi
a34c641bc4 Merge pull request #2796 from tonistiigi/fs-entitlements
bake: add filesystem entitlements support
2024-11-21 09:51:49 -08:00
CrazyMax
f10be074b4 bake: handle root evaluation with available drives for windows entitlement
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-21 14:05:13 +01:00
CrazyMax
9f429965c0 bake: windows entitlement path fixes take 2
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-21 14:05:12 +01:00
CrazyMax
f3929447d7 fix lint issues
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-21 14:05:12 +01:00
Tonis Tiigi
615f4f6759 bake: windows entitlement path fixes
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2024-11-21 14:05:12 +01:00
Tonis Tiigi
9a7b028bab bake: add fs entitlements for context paths
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2024-11-21 14:05:11 +01:00
Tonis Tiigi
1af4f05ba4 bake: add filesystem entitlements support
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2024-11-21 14:05:11 +01:00
CrazyMax
4b5d78db9b Merge pull request #2801 from tonistiigi/enable-testifylint
lint: enable testifylint
2024-11-21 13:57:54 +01:00
Tonis Tiigi
d2c512a95b lint: enable testifylint
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2024-11-20 10:53:11 -08:00
Tõnis Tiigi
5937ba0e00 Merge pull request #2307 from crazy-max/test-docker-multi-ver
tests: handle multiple docker versions
2024-11-20 09:53:57 -08:00
Tõnis Tiigi
21fb026aa3 Merge pull request #2775 from crazy-max/openbsd
build openbsd
2024-11-20 09:49:49 -08:00
CrazyMax
bc45641086 build openbsd
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-20 11:42:10 +01:00
CrazyMax
96689e5d05 Merge pull request #2782 from crazy-max/go-1.23
update to go 1.23
2024-11-20 11:40:54 +01:00
CrazyMax
50a8f11f0f dockerfile: missing xx update to 1.5.0
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-20 11:20:18 +01:00
CrazyMax
11cf38bd97 update to go 1.23
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-20 11:20:18 +01:00
CrazyMax
300d56b3ff update gopls and golangci-lint
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-20 11:20:18 +01:00
CrazyMax
e04da86aca fix golangci-lint issues
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-20 11:20:17 +01:00
Akihiro Suda
9f1fc99018 Merge pull request #2797 from crazy-max/ci-macos-14
ci: update runner to macos-14
2024-11-20 18:16:59 +09:00
CrazyMax
26bbddb5d6 Merge pull request #2798 from tonistiigi/linter-updates
Improve linter checks
2024-11-20 10:05:37 +01:00
Tonis Tiigi
58fd190c31 lint: enable importas rules from buildkit
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2024-11-19 18:29:04 -08:00
Tonis Tiigi
e7a53fb829 lint: enable forbidigo context rules
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2024-11-19 18:27:25 -08:00
Tonis Tiigi
c0fd64f4f8 lint: enable linters from buildkit
Skipping errname and testifylint

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2024-11-19 17:51:24 -08:00
Tonis Tiigi
0c629335ac lint: sort linters
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2024-11-19 17:40:42 -08:00
Tonis Tiigi
f216b71ad2 lint: enable gosimple
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2024-11-19 17:39:22 -08:00
CrazyMax
debe8c0187 ci: update runner to macos-14
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-20 01:02:43 +01:00
CrazyMax
a69d857b8a tests: handle multiple docker versions
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-20 00:59:09 +01:00
Tõnis Tiigi
a6ef9db84d Merge pull request #2794 from crazy-max/bake-var-req
bake: basic variable validation
2024-11-19 12:23:44 -08:00
CrazyMax
9c27be752c Merge pull request #2791 from docker/dependabot/github_actions/codecov/codecov-action-5
build(deps): bump codecov/codecov-action from 4 to 5
2024-11-19 19:06:56 +01:00
CrazyMax
82a65d4f9b Merge pull request #2792 from thaJeztah/test_engine_27.4
Dockerfile: update to docker v27.4.0-rc.2
2024-11-19 18:36:00 +01:00
Sebastiaan van Stijn
8647f408ac Dockerfile: update to docker v27.4.0-rc.2
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-11-19 17:31:21 +01:00
CrazyMax
e51cdcac50 bake: basic variable validation
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-19 12:41:06 +01:00
CrazyMax
55a544d976 Merge pull request #2795 from dvdksn/bake-docs-call-check
docs: add "call" attribute for target
2024-11-18 16:12:57 +01:00
Tõnis Tiigi
3b943bd4ba Merge pull request #2790 from crazy-max/fix-network-attr-yaml
bake: check for empty build network with compose
2024-11-14 18:55:33 -08:00
dependabot[bot]
502bb51a3b build(deps): bump codecov/codecov-action from 4 to 5
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4 to 5.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-14 18:33:10 +00:00
CrazyMax
48977780ad bake: check for empty build network with compose
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-14 19:27:54 +01:00
Tõnis Tiigi
e540bb03a4 Merge pull request #2773 from crazy-max/dockerfile-bump-versions
dockerfile: update testing tools
2024-11-13 15:54:31 -08:00
CrazyMax
919c52395d dockerfile: update gotestsum to 1.12.0
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-13 22:47:31 +01:00
CrazyMax
7f01c63be7 dockerfile: update registry to 2.8.3
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-13 22:47:31 +01:00
CrazyMax
076d2f19d5 dockerfile: update undock to 0.8.0
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-13 22:47:30 +01:00
CrazyMax
3c3150b8d3 dockerfile: update docker to 27.3.1
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-13 22:47:30 +01:00
CrazyMax
b03d8c52e1 dockerfile: update buildkit to v0.17.1
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-13 22:47:30 +01:00
CrazyMax
e67ccb080b Merge pull request #2787 from docker/dependabot/github_actions/softprops/action-gh-release-2.1.0
build(deps): bump softprops/action-gh-release from 2.0.9 to 2.1.0
2024-11-13 12:14:53 +01:00
dependabot[bot]
dab02c347e build(deps): bump softprops/action-gh-release from 2.0.9 to 2.1.0
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.0.9 to 2.1.0.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](e7a8f85e1c...01570a1f39)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-12 18:14:26 +00:00
Tõnis Tiigi
6caa151e98 Merge pull request #2777 from LaurentGoderre/metadata-list-support
Add ability to output json lists in metadata build file
2024-11-11 13:52:09 -08:00
Laurent Goderre
be6d8326a8 Add ability to output json lists in metadata build file
Signed-off-by: Laurent Goderre <laurent.goderre@docker.com>
2024-11-11 16:36:45 -05:00
Tõnis Tiigi
7855f8324b Merge pull request #2781 from crazy-max/update-fsutil
vendor: github.com/tonistiigi/fsutil 8d32dbdd27d3
2024-11-10 20:21:13 -08:00
CrazyMax
850e5330ad Merge pull request #2778 from jsternberg/improve-missing-name-set-error
bake: improve error when using incorrect format for setting labels
2024-11-06 12:07:26 +01:00
CrazyMax
b7ea25eb59 vendor: github.com/tonistiigi/fsutil 8d32dbdd27d3
full diff: 397af5306b...8d32dbdd27

Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-06 12:02:13 +01:00
Tõnis Tiigi
8cdeac54ab Merge pull request #2780 from glours/bump-compose-go-v2.4.3
bump compose-go to version v2.4.3
2024-11-05 09:48:20 -08:00
Guillaume Lours
752c70a06c bump compose-go to version v2.4.3
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2024-11-05 18:29:03 +01:00
Tõnis Tiigi
83dd969dc1 Merge pull request #2774 from crazy-max/freebsd
build freebsd
2024-11-05 08:30:26 -08:00
Jonathan A. Sternberg
a5bb117ff0 bake: improve error when using incorrect format for setting labels
Improves the error message when using an incorrect format for setting
labels. This includes the intended format directly in the error message
instead of assuming the user knows what the format is.

Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
2024-11-04 14:38:23 -06:00
CrazyMax
735b7f68fe build freebsd
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-11-03 10:39:28 +01:00
Tõnis Tiigi
bcac44f658 Merge pull request #2771 from docker/dependabot/github_actions/softprops/action-gh-release-2.0.9
build(deps): bump softprops/action-gh-release from 2.0.8 to 2.0.9
2024-10-31 16:59:55 -07:00
dependabot[bot]
d46595eed8 build(deps): bump softprops/action-gh-release from 2.0.8 to 2.0.9
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.0.8 to 2.0.9.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](c062e08bd5...e7a8f85e1c)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-31 18:34:55 +00:00
Tõnis Tiigi
62407927fa Merge pull request #2757 from dvdksn/pprof-dev-docs
docs: add dev instructions on generating/analyzing pprof samples
2024-10-30 15:09:19 -07:00
Tõnis Tiigi
c7b0a84c6a Merge pull request #2767 from tonistiigi/buildkit-v0.17.0
vendor: update buildkit to v0.17.0
2024-10-30 14:41:33 -07:00
Tonis Tiigi
1aac809c63 vendor: update buildkit to v0.17.0
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2024-10-30 12:04:42 -07:00
David Karlsson
ca502cc9a5 docs: add dev instructions on generating/analyzing pprof samples
Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
2024-10-28 17:15:27 +01:00
David Karlsson
8056a3dc7c docs: add "call" attribute for target
Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
2024-10-17 14:09:19 +02:00
529 changed files with 37364 additions and 6207 deletions

View File

@@ -188,6 +188,89 @@ To generate new vendored files with go modules run:
$ make vendor $ make vendor
``` ```
### Generate profiling data
You can configure Buildx to generate [`pprof`](https://github.com/google/pprof)
memory and CPU profiles to analyze and optimize your builds. These profiles are
useful for identifying performance bottlenecks, detecting memory
inefficiencies, and ensuring the program (Buildx) runs efficiently.
The following environment variables control whether Buildx generates profiling
data for builds:
```console
$ export BUILDX_CPU_PROFILE=buildx_cpu.prof
$ export BUILDX_MEM_PROFILE=buildx_mem.prof
```
When set, Buildx emits profiling samples for the builds to the location
specified by the environment variable.
To analyze and visualize profiling samples, you need `pprof` from the Go
toolchain, and (optionally) GraphViz for visualization in a graphical format.
To inspect profiling data with `pprof`:
1. Build a local binary of Buildx from source.
```console
$ docker buildx bake
```
The binary gets exported to `./bin/build/buildx`.
2. Run a build and with the environment variables set to generate profiling data.
```console
$ export BUILDX_CPU_PROFILE=buildx_cpu.prof
$ export BUILDX_MEM_PROFILE=buildx_mem.prof
$ ./bin/build/buildx bake
```
This creates `buildx_cpu.prof` and `buildx_mem.prof` for the build.
3. Start `pprof` and specify the filename of the profile that you want to
analyze.
```console
$ go tool pprof buildx_cpu.prof
```
This opens the `pprof` interactive console. From here, you can inspect the
profiling sample using various commands. For example, use `top 10` command
to view the top 10 most time-consuming entries.
```plaintext
(pprof) top 10
Showing nodes accounting for 3.04s, 91.02% of 3.34s total
Dropped 123 nodes (cum <= 0.02s)
Showing top 10 nodes out of 159
flat flat% sum% cum cum%
1.14s 34.13% 34.13% 1.14s 34.13% syscall.syscall
0.91s 27.25% 61.38% 0.91s 27.25% runtime.kevent
0.35s 10.48% 71.86% 0.35s 10.48% runtime.pthread_cond_wait
0.22s 6.59% 78.44% 0.22s 6.59% runtime.pthread_cond_signal
0.15s 4.49% 82.93% 0.15s 4.49% runtime.usleep
0.10s 2.99% 85.93% 0.10s 2.99% runtime.memclrNoHeapPointers
0.10s 2.99% 88.92% 0.10s 2.99% runtime.memmove
0.03s 0.9% 89.82% 0.03s 0.9% runtime.madvise
0.02s 0.6% 90.42% 0.02s 0.6% runtime.(*mspan).typePointersOfUnchecked
0.02s 0.6% 91.02% 0.02s 0.6% runtime.pcvalue
```
To view the call graph in a GUI, run `go tool pprof -http=:8081 <sample>`.
> [!NOTE]
> Requires [GraphViz](https://www.graphviz.org/) to be installed.
```console
$ go tool pprof -http=:8081 buildx_cpu.prof
Serving web UI on http://127.0.0.1:8081
http://127.0.0.1:8081
```
For more information about using `pprof` and how to interpret the call graph,
refer to the [`pprof` README](https://github.com/google/pprof/blob/main/doc/README.md).
### Conventions ### Conventions

View File

@@ -36,7 +36,7 @@ env:
TEST_CACHE_SCOPE: "test" TEST_CACHE_SCOPE: "test"
TESTFLAGS: "-v --parallel=6 --timeout=30m" TESTFLAGS: "-v --parallel=6 --timeout=30m"
GOTESTSUM_FORMAT: "standard-verbose" GOTESTSUM_FORMAT: "standard-verbose"
GO_VERSION: "1.22" GO_VERSION: "1.23"
GOTESTSUM_VERSION: "v1.9.0" # same as one in Dockerfile GOTESTSUM_VERSION: "v1.9.0" # same as one in Dockerfile
jobs: jobs:
@@ -54,9 +54,9 @@ jobs:
- master - master
- latest - latest
- buildx-stable-1 - buildx-stable-1
- v0.17.2
- v0.16.0
- v0.15.2 - v0.15.2
- v0.14.1
- v0.13.2
worker: worker:
- docker-container - docker-container
- remote - remote
@@ -76,6 +76,16 @@ jobs:
- worker: docker+containerd # same as docker, but with containerd snapshotter - worker: docker+containerd # same as docker, but with containerd snapshotter
pkg: ./tests pkg: ./tests
mode: experimental mode: experimental
- worker: "docker@26.1"
pkg: ./tests
- worker: "docker+containerd@26.1" # same as docker, but with containerd snapshotter
pkg: ./tests
- worker: "docker@26.1"
pkg: ./tests
mode: experimental
- worker: "docker+containerd@26.1" # same as docker, but with containerd snapshotter
pkg: ./tests
mode: experimental
steps: steps:
- -
name: Prepare name: Prepare
@@ -86,7 +96,7 @@ jobs:
fi fi
testFlags="--run=//worker=$(echo "${{ matrix.worker }}" | sed 's/\+/\\+/g')$" testFlags="--run=//worker=$(echo "${{ matrix.worker }}" | sed 's/\+/\\+/g')$"
case "${{ matrix.worker }}" in case "${{ matrix.worker }}" in
docker | docker+containerd) docker | docker+containerd | docker@* | docker+containerd@*)
echo "TESTFLAGS=${{ env.TESTFLAGS_DOCKER }} $testFlags" >> $GITHUB_ENV echo "TESTFLAGS=${{ env.TESTFLAGS_DOCKER }} $testFlags" >> $GITHUB_ENV
;; ;;
*) *)
@@ -131,7 +141,7 @@ jobs:
- -
name: Send to Codecov name: Send to Codecov
if: always() if: always()
uses: codecov/codecov-action@v4 uses: codecov/codecov-action@v5
with: with:
directory: ./bin/testreports directory: ./bin/testreports
flags: integration flags: integration
@@ -158,7 +168,7 @@ jobs:
matrix: matrix:
os: os:
- ubuntu-24.04 - ubuntu-24.04
- macos-12 - macos-14
- windows-2022 - windows-2022
env: env:
SKIP_INTEGRATION_TESTS: 1 SKIP_INTEGRATION_TESTS: 1
@@ -203,7 +213,7 @@ jobs:
- -
name: Send to Codecov name: Send to Codecov
if: always() if: always()
uses: codecov/codecov-action@v4 uses: codecov/codecov-action@v5
with: with:
directory: ${{ env.TESTREPORTS_DIR }} directory: ${{ env.TESTREPORTS_DIR }}
env_vars: RUNNER_OS env_vars: RUNNER_OS
@@ -438,7 +448,7 @@ jobs:
- -
name: GitHub Release name: GitHub Release
if: startsWith(github.ref, 'refs/tags/v') if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 # v2.0.8 uses: softprops/action-gh-release@01570a1f39cb168c169c802c3bceb9e93fb10974 # v2.1.0
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:

View File

@@ -17,7 +17,7 @@ on:
pull_request: pull_request:
env: env:
GO_VERSION: "1.22" GO_VERSION: "1.23"
jobs: jobs:
codeql: codeql:

View File

@@ -1,26 +1,52 @@
run: run:
timeout: 30m timeout: 30m
modules-download-mode: vendor modules-download-mode: vendor
# default uses Go version from the go.mod file, fallback on the env var
# `GOVERSION`, fallback on 1.17: https://golangci-lint.run/usage/configuration/#run-configuration
go: "1.23"
linters: linters:
enable: enable:
- gofmt - bodyclose
- govet
- depguard - depguard
- forbidigo
- gocritic
- gofmt
- goimports - goimports
- gosec
- gosimple
- govet
- ineffassign - ineffassign
- makezero
- misspell - misspell
- unused - noctx
- nolintlint
- revive - revive
- staticcheck - staticcheck
- testifylint
- typecheck - typecheck
- nolintlint - unused
- gosec - whitespace
- forbidigo
disable-all: true disable-all: true
linters-settings: linters-settings:
gocritic:
disabled-checks:
- "ifElseChain"
- "assignOp"
- "appendAssign"
- "singleCaseSwitch"
- "exitAfterDefer" # FIXME
importas:
alias:
# Enforce alias to prevent it accidentally being used instead of
# buildkit errdefs package (or vice-versa).
- pkg: "github.com/containerd/errdefs"
alias: "cerrdefs"
- pkg: "github.com/opencontainers/image-spec/specs-go/v1"
alias: "ocispecs"
- pkg: "github.com/opencontainers/go-digest"
alias: "digest"
govet: govet:
enable: enable:
- nilness - nilness
@@ -43,14 +69,27 @@ linters-settings:
desc: The io/ioutil package has been deprecated. desc: The io/ioutil package has been deprecated.
forbidigo: forbidigo:
forbid: forbid:
- '^context\.WithCancel(# use context\.WithCancelCause instead)?$'
- '^context\.WithDeadline(# use context\.WithDeadline instead)?$'
- '^context\.WithTimeout(# use context\.WithTimeoutCause instead)?$'
- '^ctx\.Err(# use context\.Cause instead)?$'
- '^fmt\.Errorf(# use errors\.Errorf instead)?$' - '^fmt\.Errorf(# use errors\.Errorf instead)?$'
- '^platforms\.DefaultString(# use platforms\.Format(platforms\.DefaultSpec()) instead\.)?$' - '^platforms\.DefaultString(# use platforms\.Format(platforms\.DefaultSpec()) instead\.)?$'
gosec: gosec:
excludes: excludes:
- G204 # Audit use of command execution - G204 # Audit use of command execution
- G402 # TLS MinVersion too low - G402 # TLS MinVersion too low
- G115 # integer overflow conversion (TODO: verify these)
config: config:
G306: "0644" G306: "0644"
testifylint:
disable:
# disable rules that reduce the test condition
- "empty"
- "bool-compare"
- "len"
- "negative-positive"
issues: issues:
exclude-files: exclude-files:

View File

@@ -1,20 +1,23 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
ARG GO_VERSION=1.22 ARG GO_VERSION=1.23
ARG XX_VERSION=1.5.0 ARG XX_VERSION=1.5.0
# for testing # for testing
ARG DOCKER_VERSION=27.2.1 ARG DOCKER_VERSION=27.4.0-rc.2
ARG DOCKER_VERSION_ALT_26=26.1.3
ARG DOCKER_CLI_VERSION=${DOCKER_VERSION} ARG DOCKER_CLI_VERSION=${DOCKER_VERSION}
ARG GOTESTSUM_VERSION=v1.9.0 ARG GOTESTSUM_VERSION=v1.12.0
ARG REGISTRY_VERSION=2.8.0 ARG REGISTRY_VERSION=2.8.3
ARG BUILDKIT_VERSION=v0.16.0 ARG BUILDKIT_VERSION=v0.17.2
ARG UNDOCK_VERSION=0.7.0 ARG UNDOCK_VERSION=0.8.0
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine AS golatest FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine AS golatest
FROM moby/moby-bin:$DOCKER_VERSION AS docker-engine FROM moby/moby-bin:$DOCKER_VERSION AS docker-engine
FROM dockereng/cli-bin:$DOCKER_CLI_VERSION AS docker-cli FROM dockereng/cli-bin:$DOCKER_CLI_VERSION AS docker-cli
FROM moby/moby-bin:$DOCKER_VERSION_ALT_26 AS docker-engine-alt
FROM dockereng/cli-bin:$DOCKER_VERSION_ALT_26 AS docker-cli-alt
FROM registry:$REGISTRY_VERSION AS registry FROM registry:$REGISTRY_VERSION AS registry
FROM moby/buildkit:$BUILDKIT_VERSION AS buildkit FROM moby/buildkit:$BUILDKIT_VERSION AS buildkit
FROM crazymax/undock:$UNDOCK_VERSION AS undock FROM crazymax/undock:$UNDOCK_VERSION AS undock
@@ -77,6 +80,7 @@ RUN --mount=type=bind,target=. \
set -e set -e
xx-go --wrap xx-go --wrap
DESTDIR=/usr/bin VERSION=$(cat /buildx-version/version) REVISION=$(cat /buildx-version/revision) GO_EXTRA_LDFLAGS="-s -w" ./hack/build DESTDIR=/usr/bin VERSION=$(cat /buildx-version/version) REVISION=$(cat /buildx-version/revision) GO_EXTRA_LDFLAGS="-s -w" ./hack/build
file /usr/bin/docker-buildx
xx-verify --static /usr/bin/docker-buildx xx-verify --static /usr/bin/docker-buildx
EOT EOT
@@ -95,7 +99,9 @@ FROM scratch AS binaries-unix
COPY --link --from=buildx-build /usr/bin/docker-buildx /buildx COPY --link --from=buildx-build /usr/bin/docker-buildx /buildx
FROM binaries-unix AS binaries-darwin FROM binaries-unix AS binaries-darwin
FROM binaries-unix AS binaries-freebsd
FROM binaries-unix AS binaries-linux FROM binaries-unix AS binaries-linux
FROM binaries-unix AS binaries-openbsd
FROM scratch AS binaries-windows FROM scratch AS binaries-windows
COPY --link --from=buildx-build /usr/bin/docker-buildx /buildx.exe COPY --link --from=buildx-build /usr/bin/docker-buildx /buildx.exe
@@ -120,10 +126,13 @@ COPY --link --from=gotestsum /out /usr/bin/
COPY --link --from=registry /bin/registry /usr/bin/ COPY --link --from=registry /bin/registry /usr/bin/
COPY --link --from=docker-engine / /usr/bin/ COPY --link --from=docker-engine / /usr/bin/
COPY --link --from=docker-cli / /usr/bin/ COPY --link --from=docker-cli / /usr/bin/
COPY --link --from=docker-engine-alt / /opt/docker-alt-26/
COPY --link --from=docker-cli-alt / /opt/docker-alt-26/
COPY --link --from=buildkit /usr/bin/buildkitd /usr/bin/ COPY --link --from=buildkit /usr/bin/buildkitd /usr/bin/
COPY --link --from=buildkit /usr/bin/buildctl /usr/bin/ COPY --link --from=buildkit /usr/bin/buildctl /usr/bin/
COPY --link --from=undock /usr/local/bin/undock /usr/bin/ COPY --link --from=undock /usr/local/bin/undock /usr/bin/
COPY --link --from=binaries /buildx /usr/bin/ COPY --link --from=binaries /buildx /usr/bin/
ENV TEST_DOCKER_EXTRA="docker@26.1=/opt/docker-alt-26"
FROM integration-test-base AS integration-test FROM integration-test-base AS integration-test
COPY . . COPY . .

View File

@@ -193,7 +193,7 @@ func ListTargets(files []File) ([]string, error) {
return dedupSlice(targets), nil return dedupSlice(targets), nil
} }
func ReadTargets(ctx context.Context, files []File, targets, overrides []string, defaults map[string]string) (map[string]*Target, map[string]*Group, error) { func ReadTargets(ctx context.Context, files []File, targets, overrides []string, defaults map[string]string, ent *EntitlementConf) (map[string]*Target, map[string]*Group, error) {
c, _, err := ParseFiles(files, defaults) c, _, err := ParseFiles(files, defaults)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@@ -212,7 +212,7 @@ func ReadTargets(ctx context.Context, files []File, targets, overrides []string,
for _, target := range targets { for _, target := range targets {
ts, gs := c.ResolveGroup(target) ts, gs := c.ResolveGroup(target)
for _, tname := range ts { for _, tname := range ts {
t, err := c.ResolveTarget(tname, o) t, err := c.ResolveTarget(tname, o, ent)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@@ -244,7 +244,7 @@ func ReadTargets(ctx context.Context, files []File, targets, overrides []string,
} }
for name, t := range m { for name, t := range m {
if err := c.loadLinks(name, t, m, o, nil); err != nil { if err := c.loadLinks(name, t, m, o, nil, ent); err != nil {
return nil, nil, err return nil, nil, err
} }
} }
@@ -476,7 +476,7 @@ func (c Config) expandTargets(pattern string) ([]string, error) {
return names, nil return names, nil
} }
func (c Config) loadLinks(name string, t *Target, m map[string]*Target, o map[string]map[string]Override, visited []string) error { func (c Config) loadLinks(name string, t *Target, m map[string]*Target, o map[string]map[string]Override, visited []string, ent *EntitlementConf) error {
visited = append(visited, name) visited = append(visited, name)
for _, v := range t.Contexts { for _, v := range t.Contexts {
if strings.HasPrefix(v, "target:") { if strings.HasPrefix(v, "target:") {
@@ -492,7 +492,7 @@ func (c Config) loadLinks(name string, t *Target, m map[string]*Target, o map[st
t2, ok := m[target] t2, ok := m[target]
if !ok { if !ok {
var err error var err error
t2, err = c.ResolveTarget(target, o) t2, err = c.ResolveTarget(target, o, ent)
if err != nil { if err != nil {
return err return err
} }
@@ -500,7 +500,7 @@ func (c Config) loadLinks(name string, t *Target, m map[string]*Target, o map[st
t2.linked = true t2.linked = true
m[target] = t2 m[target] = t2
} }
if err := c.loadLinks(target, t2, m, o, visited); err != nil { if err := c.loadLinks(target, t2, m, o, visited, ent); err != nil {
return err return err
} }
@@ -627,8 +627,8 @@ func (c Config) group(name string, visited map[string]visit) ([]string, []string
return targets, groups return targets, groups
} }
func (c Config) ResolveTarget(name string, overrides map[string]map[string]Override) (*Target, error) { func (c Config) ResolveTarget(name string, overrides map[string]map[string]Override, ent *EntitlementConf) (*Target, error) {
t, err := c.target(name, map[string]*Target{}, overrides) t, err := c.target(name, map[string]*Target{}, overrides, ent)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -644,7 +644,7 @@ func (c Config) ResolveTarget(name string, overrides map[string]map[string]Overr
return t, nil return t, nil
} }
func (c Config) target(name string, visited map[string]*Target, overrides map[string]map[string]Override) (*Target, error) { func (c Config) target(name string, visited map[string]*Target, overrides map[string]map[string]Override, ent *EntitlementConf) (*Target, error) {
if t, ok := visited[name]; ok { if t, ok := visited[name]; ok {
return t, nil return t, nil
} }
@@ -661,7 +661,7 @@ func (c Config) target(name string, visited map[string]*Target, overrides map[st
} }
tt := &Target{} tt := &Target{}
for _, name := range t.Inherits { for _, name := range t.Inherits {
t, err := c.target(name, visited, overrides) t, err := c.target(name, visited, overrides, ent)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -673,7 +673,7 @@ func (c Config) target(name string, visited map[string]*Target, overrides map[st
m.Merge(tt) m.Merge(tt)
m.Merge(t) m.Merge(t)
tt = m tt = m
if err := tt.AddOverrides(overrides[name]); err != nil { if err := tt.AddOverrides(overrides[name], ent); err != nil {
return nil, err return nil, err
} }
tt.normalize() tt.normalize()
@@ -725,10 +725,12 @@ type Target struct {
linked bool linked bool
} }
var _ hclparser.WithEvalContexts = &Target{} var (
var _ hclparser.WithGetName = &Target{} _ hclparser.WithEvalContexts = &Target{}
var _ hclparser.WithEvalContexts = &Group{} _ hclparser.WithGetName = &Target{}
var _ hclparser.WithGetName = &Group{} _ hclparser.WithEvalContexts = &Group{}
_ hclparser.WithGetName = &Group{}
)
func (t *Target) normalize() { func (t *Target) normalize() {
t.Annotations = removeDupes(t.Annotations) t.Annotations = removeDupes(t.Annotations)
@@ -854,7 +856,7 @@ func (t *Target) Merge(t2 *Target) {
t.Inherits = append(t.Inherits, t2.Inherits...) t.Inherits = append(t.Inherits, t2.Inherits...)
} }
func (t *Target) AddOverrides(overrides map[string]Override) error { func (t *Target) AddOverrides(overrides map[string]Override, ent *EntitlementConf) error {
for key, o := range overrides { for key, o := range overrides {
value := o.Value value := o.Value
keys := strings.SplitN(key, ".", 2) keys := strings.SplitN(key, ".", 2)
@@ -865,7 +867,7 @@ func (t *Target) AddOverrides(overrides map[string]Override) error {
t.Dockerfile = &value t.Dockerfile = &value
case "args": case "args":
if len(keys) != 2 { if len(keys) != 2 {
return errors.Errorf("args require name") return errors.Errorf("invalid format for args, expecting args.<name>=<value>")
} }
if t.Args == nil { if t.Args == nil {
t.Args = map[string]*string{} t.Args = map[string]*string{}
@@ -873,7 +875,7 @@ func (t *Target) AddOverrides(overrides map[string]Override) error {
t.Args[keys[1]] = &value t.Args[keys[1]] = &value
case "contexts": case "contexts":
if len(keys) != 2 { if len(keys) != 2 {
return errors.Errorf("contexts require name") return errors.Errorf("invalid format for contexts, expecting contexts.<name>=<value>")
} }
if t.Contexts == nil { if t.Contexts == nil {
t.Contexts = map[string]string{} t.Contexts = map[string]string{}
@@ -881,7 +883,7 @@ func (t *Target) AddOverrides(overrides map[string]Override) error {
t.Contexts[keys[1]] = value t.Contexts[keys[1]] = value
case "labels": case "labels":
if len(keys) != 2 { if len(keys) != 2 {
return errors.Errorf("labels require name") return errors.Errorf("invalid format for labels, expecting labels.<name>=<value>")
} }
if t.Labels == nil { if t.Labels == nil {
t.Labels = map[string]*string{} t.Labels = map[string]*string{}
@@ -891,22 +893,76 @@ func (t *Target) AddOverrides(overrides map[string]Override) error {
t.Tags = o.ArrValue t.Tags = o.ArrValue
case "cache-from": case "cache-from":
t.CacheFrom = o.ArrValue t.CacheFrom = o.ArrValue
cacheFrom, err := buildflags.ParseCacheEntry(o.ArrValue)
if err != nil {
return err
}
for _, c := range cacheFrom {
if c.Type == "local" {
if v, ok := c.Attrs["src"]; ok {
ent.FSRead = append(ent.FSRead, v)
}
}
}
case "cache-to": case "cache-to":
t.CacheTo = o.ArrValue t.CacheTo = o.ArrValue
cacheTo, err := buildflags.ParseCacheEntry(o.ArrValue)
if err != nil {
return err
}
for _, c := range cacheTo {
if c.Type == "local" {
if v, ok := c.Attrs["dest"]; ok {
ent.FSWrite = append(ent.FSWrite, v)
}
}
}
case "target": case "target":
t.Target = &value t.Target = &value
case "call": case "call":
t.Call = &value t.Call = &value
case "secrets": case "secrets":
t.Secrets = o.ArrValue t.Secrets = o.ArrValue
secrets, err := buildflags.ParseSecretSpecs(o.ArrValue)
if err != nil {
return errors.Wrap(err, "invalid value for outputs")
}
for _, s := range secrets {
if s.FilePath != "" {
ent.FSRead = append(ent.FSRead, s.FilePath)
}
}
case "ssh": case "ssh":
t.SSH = o.ArrValue t.SSH = o.ArrValue
ssh, err := buildflags.ParseSSHSpecs(o.ArrValue)
if err != nil {
return errors.Wrap(err, "invalid value for outputs")
}
for _, s := range ssh {
ent.FSRead = append(ent.FSRead, s.Paths...)
}
case "platform": case "platform":
t.Platforms = o.ArrValue t.Platforms = o.ArrValue
case "output": case "output":
t.Outputs = o.ArrValue t.Outputs = o.ArrValue
outputs, err := buildflags.ParseExports(o.ArrValue)
if err != nil {
return errors.Wrap(err, "invalid value for outputs")
}
for _, o := range outputs {
if o.Destination != "" {
ent.FSWrite = append(ent.FSWrite, o.Destination)
}
}
case "entitlements": case "entitlements":
t.Entitlements = append(t.Entitlements, o.ArrValue...) t.Entitlements = append(t.Entitlements, o.ArrValue...)
for _, v := range o.ArrValue {
if v == string(EntitlementKeyNetworkHost) {
ent.NetworkHost = true
} else if v == string(EntitlementKeySecurityInsecure) {
ent.SecurityInsecure = true
}
}
case "annotations": case "annotations":
t.Annotations = append(t.Annotations, o.ArrValue...) t.Annotations = append(t.Annotations, o.ArrValue...)
case "attest": case "attest":
@@ -1115,62 +1171,34 @@ func updateContext(t *build.Inputs, inp *Input) {
t.ContextState = &st t.ContextState = &st
} }
// validateContextsEntitlements is a basic check to ensure contexts do not func collectLocalPaths(t build.Inputs) []string {
// escape local directories when loaded from remote sources. This is to be var out []string
// replaced with proper entitlements support in the future.
func validateContextsEntitlements(t build.Inputs, inp *Input) error {
if inp == nil || inp.State == nil {
return nil
}
if v, ok := os.LookupEnv("BAKE_ALLOW_REMOTE_FS_ACCESS"); ok {
if vv, _ := strconv.ParseBool(v); vv {
return nil
}
}
if t.ContextState == nil { if t.ContextState == nil {
if err := checkPath(t.ContextPath); err != nil { if v, ok := isLocalPath(t.ContextPath); ok {
return err out = append(out, v)
} }
if v, ok := isLocalPath(t.DockerfilePath); ok {
out = append(out, v)
}
} else if strings.HasPrefix(t.ContextPath, "cwd://") {
out = append(out, strings.TrimPrefix(t.ContextPath, "cwd://"))
} }
for _, v := range t.NamedContexts { for _, v := range t.NamedContexts {
if v.State != nil { if v.State != nil {
continue continue
} }
if err := checkPath(v.Path); err != nil { if v, ok := isLocalPath(v.Path); ok {
return err out = append(out, v)
} }
} }
return nil return out
} }
func checkPath(p string) error { func isLocalPath(p string) (string, bool) {
if build.IsRemoteURL(p) || strings.HasPrefix(p, "target:") || strings.HasPrefix(p, "docker-image:") { if build.IsRemoteURL(p) || strings.HasPrefix(p, "target:") || strings.HasPrefix(p, "docker-image:") {
return nil return "", false
} }
p, err := filepath.EvalSymlinks(p) return strings.TrimPrefix(p, "cwd://"), true
if err != nil {
if os.IsNotExist(err) {
return nil
}
return err
}
p, err = filepath.Abs(p)
if err != nil {
return err
}
wd, err := os.Getwd()
if err != nil {
return err
}
rel, err := filepath.Rel(wd, p)
if err != nil {
return err
}
parts := strings.Split(rel, string(os.PathSeparator))
if parts[0] == ".." {
return errors.Errorf("path %s is outside of the working directory, please set BAKE_ALLOW_REMOTE_FS_ACCESS=1", p)
}
return nil
} }
func toBuildOpt(t *Target, inp *Input) (*build.Options, error) { func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
@@ -1210,9 +1238,6 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
// it's not outside the working directory and then resolve it to an // it's not outside the working directory and then resolve it to an
// absolute path. // absolute path.
bi.DockerfilePath = path.Clean(strings.TrimPrefix(bi.DockerfilePath, "cwd://")) bi.DockerfilePath = path.Clean(strings.TrimPrefix(bi.DockerfilePath, "cwd://"))
if err := checkPath(bi.DockerfilePath); err != nil {
return nil, err
}
var err error var err error
bi.DockerfilePath, err = filepath.Abs(bi.DockerfilePath) bi.DockerfilePath, err = filepath.Abs(bi.DockerfilePath)
if err != nil { if err != nil {
@@ -1249,10 +1274,6 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
} }
} }
if err := validateContextsEntitlements(bi, inp); err != nil {
return nil, err
}
t.Context = &bi.ContextPath t.Context = &bi.ContextPath
args := map[string]string{} args := map[string]string{}
@@ -1313,6 +1334,8 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
bo.SecretSpecs = secrets
secretAttachment, err := controllerapi.CreateSecrets(secrets) secretAttachment, err := controllerapi.CreateSecrets(secrets)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -1326,6 +1349,8 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
if len(sshSpecs) == 0 && (buildflags.IsGitSSH(bi.ContextPath) || (inp != nil && buildflags.IsGitSSH(inp.URL))) { if len(sshSpecs) == 0 && (buildflags.IsGitSSH(bi.ContextPath) || (inp != nil && buildflags.IsGitSSH(inp.URL))) {
sshSpecs = append(sshSpecs, &controllerapi.SSH{ID: "default"}) sshSpecs = append(sshSpecs, &controllerapi.SSH{ID: "default"})
} }
bo.SSHSpecs = sshSpecs
sshAttachment, err := controllerapi.CreateSSH(sshSpecs) sshAttachment, err := controllerapi.CreateSSH(sshSpecs)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -1358,7 +1383,8 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
bo.Exports, err = controllerapi.CreateExports(outputs)
bo.Exports, bo.ExportsLocalPathsTemporary, err = controllerapi.CreateExports(outputs)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -40,7 +40,7 @@ target "webapp" {
t.Run("NoOverrides", func(t *testing.T) { t.Run("NoOverrides", func(t *testing.T) {
t.Parallel() t.Parallel()
m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, nil, nil) m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(m)) require.Equal(t, 1, len(m))
@@ -58,9 +58,9 @@ target "webapp" {
t.Run("InvalidTargetOverrides", func(t *testing.T) { t.Run("InvalidTargetOverrides", func(t *testing.T) {
t.Parallel() t.Parallel()
_, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"nosuchtarget.context=foo"}, nil) _, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"nosuchtarget.context=foo"}, nil, &EntitlementConf{})
require.NotNil(t, err) require.Error(t, err)
require.Equal(t, err.Error(), "could not find any target matching 'nosuchtarget'") require.Equal(t, "could not find any target matching 'nosuchtarget'", err.Error())
}) })
t.Run("ArgsOverrides", func(t *testing.T) { t.Run("ArgsOverrides", func(t *testing.T) {
@@ -74,7 +74,7 @@ target "webapp" {
"webapp.args.VAR_FROMENV" + t.Name(), "webapp.args.VAR_FROMENV" + t.Name(),
"webapp.args.VAR_INHERITED=override", "webapp.args.VAR_INHERITED=override",
// not overriding VAR_BOTH on purpose // not overriding VAR_BOTH on purpose
}, nil) }, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, "Dockerfile.webapp", *m["webapp"].Dockerfile) require.Equal(t, "Dockerfile.webapp", *m["webapp"].Dockerfile)
@@ -103,7 +103,7 @@ target "webapp" {
m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{ m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{
"webDEP.args.VAR_INHERITED=override", "webDEP.args.VAR_INHERITED=override",
"webDEP.args.VAR_BOTH=override", "webDEP.args.VAR_BOTH=override",
}, nil) }, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, ptrstr("override"), m["webapp"].Args["VAR_INHERITED"]) require.Equal(t, ptrstr("override"), m["webapp"].Args["VAR_INHERITED"])
@@ -115,10 +115,10 @@ target "webapp" {
t.Run("ContextOverride", func(t *testing.T) { t.Run("ContextOverride", func(t *testing.T) {
t.Parallel() t.Parallel()
_, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.context"}, nil) _, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.context"}, nil, &EntitlementConf{})
require.NotNil(t, err) require.Error(t, err)
m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.context=foo"}, nil) m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.context=foo"}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, "foo", *m["webapp"].Context) require.Equal(t, "foo", *m["webapp"].Context)
require.Equal(t, 1, len(g)) require.Equal(t, 1, len(g))
@@ -127,7 +127,7 @@ target "webapp" {
t.Run("NoCacheOverride", func(t *testing.T) { t.Run("NoCacheOverride", func(t *testing.T) {
t.Parallel() t.Parallel()
m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.no-cache=false"}, nil) m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.no-cache=false"}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, false, *m["webapp"].NoCache) require.Equal(t, false, *m["webapp"].NoCache)
require.Equal(t, 1, len(g)) require.Equal(t, 1, len(g))
@@ -135,14 +135,14 @@ target "webapp" {
}) })
t.Run("ShmSizeOverride", func(t *testing.T) { t.Run("ShmSizeOverride", func(t *testing.T) {
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.shm-size=256m"}, nil) m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.shm-size=256m"}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, "256m", *m["webapp"].ShmSize) require.Equal(t, "256m", *m["webapp"].ShmSize)
}) })
t.Run("PullOverride", func(t *testing.T) { t.Run("PullOverride", func(t *testing.T) {
t.Parallel() t.Parallel()
m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.pull=false"}, nil) m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.pull=false"}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, false, *m["webapp"].Pull) require.Equal(t, false, *m["webapp"].Pull)
require.Equal(t, 1, len(g)) require.Equal(t, 1, len(g))
@@ -203,14 +203,14 @@ target "webapp" {
// NOTE: I am unsure whether failing to match should always error out // NOTE: I am unsure whether failing to match should always error out
// instead of simply skipping that override. // instead of simply skipping that override.
// Let's enforce the error and we can relax it later if users complain. // Let's enforce the error and we can relax it later if users complain.
require.NotNil(t, err) require.Error(t, err)
require.Equal(t, err.Error(), "could not find any target matching 'nomatch*'") require.Equal(t, "could not find any target matching 'nomatch*'", err.Error())
}, },
}, },
} }
for _, test := range cases { for _, test := range cases {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
m, g, err := ReadTargets(ctx, []File{fp}, test.targets, test.overrides, nil) m, g, err := ReadTargets(ctx, []File{fp}, test.targets, test.overrides, nil, &EntitlementConf{})
test.check(t, m, g, err) test.check(t, m, g, err)
}) })
} }
@@ -225,7 +225,7 @@ func TestPushOverride(t *testing.T) {
`target "app" { `target "app" {
}`), }`),
} }
m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.push=true"}, nil) m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.push=true"}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(m["app"].Outputs)) require.Equal(t, 1, len(m["app"].Outputs))
require.Equal(t, "type=image,push=true", m["app"].Outputs[0]) require.Equal(t, "type=image,push=true", m["app"].Outputs[0])
@@ -239,7 +239,7 @@ func TestPushOverride(t *testing.T) {
output = ["type=image,compression=zstd"] output = ["type=image,compression=zstd"]
}`), }`),
} }
m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.push=true"}, nil) m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.push=true"}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(m["app"].Outputs)) require.Equal(t, 1, len(m["app"].Outputs))
require.Equal(t, "type=image,compression=zstd,push=true", m["app"].Outputs[0]) require.Equal(t, "type=image,compression=zstd,push=true", m["app"].Outputs[0])
@@ -253,7 +253,7 @@ func TestPushOverride(t *testing.T) {
output = ["type=image,compression=zstd"] output = ["type=image,compression=zstd"]
}`), }`),
} }
m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.push=false"}, nil) m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.push=false"}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(m["app"].Outputs)) require.Equal(t, 1, len(m["app"].Outputs))
require.Equal(t, "type=image,compression=zstd,push=false", m["app"].Outputs[0]) require.Equal(t, "type=image,compression=zstd,push=false", m["app"].Outputs[0])
@@ -267,7 +267,7 @@ func TestPushOverride(t *testing.T) {
output = ["type=registry"] output = ["type=registry"]
}`), }`),
} }
m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.push=true"}, nil) m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.push=true"}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(m["app"].Outputs)) require.Equal(t, 1, len(m["app"].Outputs))
require.Equal(t, "type=registry", m["app"].Outputs[0]) require.Equal(t, "type=registry", m["app"].Outputs[0])
@@ -281,7 +281,7 @@ func TestPushOverride(t *testing.T) {
output = ["type=registry"] output = ["type=registry"]
}`), }`),
} }
m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.push=false"}, nil) m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.push=false"}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 0, len(m["app"].Outputs)) require.Equal(t, 0, len(m["app"].Outputs))
}) })
@@ -296,7 +296,7 @@ func TestPushOverride(t *testing.T) {
target "bar" { target "bar" {
}`), }`),
} }
m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"foo", "bar"}, []string{"*.push=true"}, nil) m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"foo", "bar"}, []string{"*.push=true"}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(m)) require.Equal(t, 2, len(m))
require.Equal(t, 1, len(m["foo"].Outputs)) require.Equal(t, 1, len(m["foo"].Outputs))
@@ -314,7 +314,7 @@ func TestLoadOverride(t *testing.T) {
`target "app" { `target "app" {
}`), }`),
} }
m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil) m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(m["app"].Outputs)) require.Equal(t, 1, len(m["app"].Outputs))
require.Equal(t, "type=docker", m["app"].Outputs[0]) require.Equal(t, "type=docker", m["app"].Outputs[0])
@@ -328,7 +328,7 @@ func TestLoadOverride(t *testing.T) {
output = ["type=docker"] output = ["type=docker"]
}`), }`),
} }
m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil) m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(m["app"].Outputs)) require.Equal(t, 1, len(m["app"].Outputs))
require.Equal(t, []string{"type=docker"}, m["app"].Outputs) require.Equal(t, []string{"type=docker"}, m["app"].Outputs)
@@ -342,7 +342,7 @@ func TestLoadOverride(t *testing.T) {
output = ["type=image"] output = ["type=image"]
}`), }`),
} }
m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil) m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(m["app"].Outputs)) require.Equal(t, 2, len(m["app"].Outputs))
require.Equal(t, []string{"type=image", "type=docker"}, m["app"].Outputs) require.Equal(t, []string{"type=image", "type=docker"}, m["app"].Outputs)
@@ -356,7 +356,7 @@ func TestLoadOverride(t *testing.T) {
output = ["type=image"] output = ["type=image"]
}`), }`),
} }
m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=false"}, nil) m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=false"}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(m["app"].Outputs)) require.Equal(t, 1, len(m["app"].Outputs))
require.Equal(t, []string{"type=image"}, m["app"].Outputs) require.Equal(t, []string{"type=image"}, m["app"].Outputs)
@@ -370,7 +370,7 @@ func TestLoadOverride(t *testing.T) {
output = ["type=registry"] output = ["type=registry"]
}`), }`),
} }
m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil) m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(m["app"].Outputs)) require.Equal(t, 2, len(m["app"].Outputs))
require.Equal(t, []string{"type=registry", "type=docker"}, m["app"].Outputs) require.Equal(t, []string{"type=registry", "type=docker"}, m["app"].Outputs)
@@ -384,7 +384,7 @@ func TestLoadOverride(t *testing.T) {
output = ["type=oci,dest=out"] output = ["type=oci,dest=out"]
}`), }`),
} }
m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil) m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(m["app"].Outputs)) require.Equal(t, 2, len(m["app"].Outputs))
require.Equal(t, []string{"type=oci,dest=out", "type=docker"}, m["app"].Outputs) require.Equal(t, []string{"type=oci,dest=out", "type=docker"}, m["app"].Outputs)
@@ -398,7 +398,7 @@ func TestLoadOverride(t *testing.T) {
output = ["type=docker,dest=out"] output = ["type=docker,dest=out"]
}`), }`),
} }
m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil) m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(m["app"].Outputs)) require.Equal(t, 2, len(m["app"].Outputs))
require.Equal(t, []string{"type=docker,dest=out", "type=docker"}, m["app"].Outputs) require.Equal(t, []string{"type=docker,dest=out", "type=docker"}, m["app"].Outputs)
@@ -414,7 +414,7 @@ func TestLoadOverride(t *testing.T) {
target "bar" { target "bar" {
}`), }`),
} }
m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"foo", "bar"}, []string{"*.load=true"}, nil) m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"foo", "bar"}, []string{"*.load=true"}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(m)) require.Equal(t, 2, len(m))
require.Equal(t, 1, len(m["foo"].Outputs)) require.Equal(t, 1, len(m["foo"].Outputs))
@@ -435,7 +435,7 @@ func TestLoadAndPushOverride(t *testing.T) {
target "bar" { target "bar" {
}`), }`),
} }
m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"foo", "bar"}, []string{"*.load=true", "*.push=true"}, nil) m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"foo", "bar"}, []string{"*.load=true", "*.push=true"}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(m)) require.Equal(t, 2, len(m))
@@ -456,7 +456,7 @@ func TestLoadAndPushOverride(t *testing.T) {
output = [ "type=registry" ] output = [ "type=registry" ]
}`), }`),
} }
m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"foo"}, []string{"*.load=true", "*.push=true"}, nil) m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"foo"}, []string{"*.load=true", "*.push=true"}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(m)) require.Equal(t, 1, len(m))
@@ -512,7 +512,7 @@ services:
ctx := context.TODO() ctx := context.TODO()
m, g, err := ReadTargets(ctx, []File{fp, fp2, fp3}, []string{"default"}, nil, nil) m, g, err := ReadTargets(ctx, []File{fp, fp2, fp3}, []string{"default"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 3, len(m)) require.Equal(t, 3, len(m))
@@ -559,7 +559,7 @@ services:
ctx := context.TODO() ctx := context.TODO()
m, _, err := ReadTargets(ctx, []File{fp}, []string{"web.app"}, nil, nil) m, _, err := ReadTargets(ctx, []File{fp}, []string{"web.app"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(m)) require.Equal(t, 1, len(m))
_, ok := m["web_app"] _, ok := m["web_app"]
@@ -567,7 +567,7 @@ services:
require.Equal(t, "Dockerfile.webapp", *m["web_app"].Dockerfile) require.Equal(t, "Dockerfile.webapp", *m["web_app"].Dockerfile)
require.Equal(t, ptrstr("1"), m["web_app"].Args["buildno"]) require.Equal(t, ptrstr("1"), m["web_app"].Args["buildno"])
m, _, err = ReadTargets(ctx, []File{fp2}, []string{"web_app"}, nil, nil) m, _, err = ReadTargets(ctx, []File{fp2}, []string{"web_app"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(m)) require.Equal(t, 1, len(m))
_, ok = m["web_app"] _, ok = m["web_app"]
@@ -575,7 +575,7 @@ services:
require.Equal(t, "Dockerfile", *m["web_app"].Dockerfile) require.Equal(t, "Dockerfile", *m["web_app"].Dockerfile)
require.Equal(t, ptrstr("12"), m["web_app"].Args["buildno2"]) require.Equal(t, ptrstr("12"), m["web_app"].Args["buildno2"])
m, g, err := ReadTargets(ctx, []File{fp, fp2}, []string{"default"}, nil, nil) m, g, err := ReadTargets(ctx, []File{fp, fp2}, []string{"default"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(m)) require.Equal(t, 1, len(m))
_, ok = m["web_app"] _, ok = m["web_app"]
@@ -600,7 +600,7 @@ func TestHCLContextCwdPrefix(t *testing.T) {
}`), }`),
} }
ctx := context.TODO() ctx := context.TODO()
m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
bo, err := TargetsToBuildOpt(m, &Input{}) bo, err := TargetsToBuildOpt(m, &Input{})
@@ -631,7 +631,7 @@ func TestHCLDockerfileCwdPrefix(t *testing.T) {
cwd, err := os.Getwd() cwd, err := os.Getwd()
require.NoError(t, err) require.NoError(t, err)
m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
bo, err := TargetsToBuildOpt(m, &Input{}) bo, err := TargetsToBuildOpt(m, &Input{})
@@ -662,7 +662,7 @@ func TestOverrideMerge(t *testing.T) {
"app.platform=linux/arm", "app.platform=linux/arm",
"app.platform=linux/ppc64le", "app.platform=linux/ppc64le",
"app.output=type=registry", "app.output=type=registry",
}, nil) }, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(m)) require.Equal(t, 1, len(m))
@@ -697,7 +697,7 @@ func TestReadContexts(t *testing.T) {
} }
ctx := context.TODO() ctx := context.TODO()
m, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, []string{}, nil) m, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, []string{}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(m)) require.Equal(t, 1, len(m))
@@ -713,7 +713,7 @@ func TestReadContexts(t *testing.T) {
require.Equal(t, "baz", ctxs["foo"].Path) require.Equal(t, "baz", ctxs["foo"].Path)
require.Equal(t, "def", ctxs["abc"].Path) require.Equal(t, "def", ctxs["abc"].Path)
m, _, err = ReadTargets(ctx, []File{fp}, []string{"app"}, []string{"app.contexts.foo=bay", "base.contexts.ghi=jkl"}, nil) m, _, err = ReadTargets(ctx, []File{fp}, []string{"app"}, []string{"app.contexts.foo=bay", "base.contexts.ghi=jkl"}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(m)) require.Equal(t, 1, len(m))
@@ -731,7 +731,7 @@ func TestReadContexts(t *testing.T) {
require.Equal(t, "jkl", ctxs["ghi"].Path) require.Equal(t, "jkl", ctxs["ghi"].Path)
// test resetting base values // test resetting base values
m, _, err = ReadTargets(ctx, []File{fp}, []string{"app"}, []string{"app.contexts.foo="}, nil) m, _, err = ReadTargets(ctx, []File{fp}, []string{"app"}, []string{"app.contexts.foo="}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(m)) require.Equal(t, 1, len(m))
@@ -766,7 +766,7 @@ func TestReadContextFromTargetUnknown(t *testing.T) {
} }
ctx := context.TODO() ctx := context.TODO()
_, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, []string{}, nil) _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, []string{}, nil, &EntitlementConf{})
require.Error(t, err) require.Error(t, err)
require.Contains(t, err.Error(), "failed to find target bar") require.Contains(t, err.Error(), "failed to find target bar")
} }
@@ -790,7 +790,7 @@ services:
ctx := context.TODO() ctx := context.TODO()
m, _, err := ReadTargets(ctx, []File{fp, fp2}, []string{"app1", "app2"}, nil, nil) m, _, err := ReadTargets(ctx, []File{fp, fp2}, []string{"app1", "app2"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(m)) require.Equal(t, 2, len(m))
@@ -828,7 +828,7 @@ func TestReadContextFromTargetChain(t *testing.T) {
`), `),
} }
m, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, []string{}, nil) m, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, []string{}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 3, len(m)) require.Equal(t, 3, len(m))
@@ -867,7 +867,7 @@ func TestReadContextFromTargetInfiniteLoop(t *testing.T) {
} }
`), `),
} }
_, _, err := ReadTargets(ctx, []File{fp}, []string{"app", "mid"}, []string{}, nil) _, _, err := ReadTargets(ctx, []File{fp}, []string{"app", "mid"}, []string{}, nil, &EntitlementConf{})
require.Error(t, err) require.Error(t, err)
require.Contains(t, err.Error(), "infinite loop from") require.Contains(t, err.Error(), "infinite loop from")
} }
@@ -889,7 +889,7 @@ func TestReadContextFromTargetMultiPlatform(t *testing.T) {
} }
`), `),
} }
_, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, []string{}, nil) _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, []string{}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
} }
@@ -910,7 +910,7 @@ func TestReadContextFromTargetInvalidPlatforms(t *testing.T) {
} }
`), `),
} }
_, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, []string{}, nil) _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, []string{}, nil, &EntitlementConf{})
require.Error(t, err) require.Error(t, err)
require.Contains(t, err.Error(), "defined for different platforms") require.Contains(t, err.Error(), "defined for different platforms")
} }
@@ -926,7 +926,7 @@ target "default" {
dockerfile = "test" dockerfile = "test"
}`)} }`)}
m, g, err := ReadTargets(ctx, []File{f}, []string{"default"}, nil, nil) m, g, err := ReadTargets(ctx, []File{f}, []string{"default"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 0, len(g)) require.Equal(t, 0, len(g))
require.Equal(t, 1, len(m)) require.Equal(t, 1, len(m))
@@ -944,10 +944,10 @@ target "image" {
dockerfile = "test" dockerfile = "test"
}`)} }`)}
_, _, err := ReadTargets(ctx, []File{f}, []string{"default"}, nil, nil) _, _, err := ReadTargets(ctx, []File{f}, []string{"default"}, nil, nil, &EntitlementConf{})
require.Error(t, err) require.Error(t, err)
m, g, err := ReadTargets(ctx, []File{f}, []string{"image"}, nil, nil) m, g, err := ReadTargets(ctx, []File{f}, []string{"image"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(g)) require.Equal(t, 1, len(g))
require.Equal(t, []string{"image"}, g["default"].Targets) require.Equal(t, []string{"image"}, g["default"].Targets)
@@ -969,7 +969,7 @@ target "image" {
dockerfile = "test" dockerfile = "test"
}`)} }`)}
m, g, err := ReadTargets(ctx, []File{f}, []string{"foo"}, nil, nil) m, g, err := ReadTargets(ctx, []File{f}, []string{"foo"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(g)) require.Equal(t, 2, len(g))
require.Equal(t, []string{"foo"}, g["default"].Targets) require.Equal(t, []string{"foo"}, g["default"].Targets)
@@ -995,7 +995,7 @@ target "image" {
dockerfile = "test" dockerfile = "test"
}`)} }`)}
m, g, err := ReadTargets(ctx, []File{f}, []string{"foo"}, nil, nil) m, g, err := ReadTargets(ctx, []File{f}, []string{"foo"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(g)) require.Equal(t, 2, len(g))
require.Equal(t, []string{"foo"}, g["default"].Targets) require.Equal(t, []string{"foo"}, g["default"].Targets)
@@ -1003,7 +1003,7 @@ target "image" {
require.Equal(t, 1, len(m)) require.Equal(t, 1, len(m))
require.Equal(t, "test", *m["image"].Dockerfile) require.Equal(t, "test", *m["image"].Dockerfile)
m, g, err = ReadTargets(ctx, []File{f}, []string{"foo", "foo"}, nil, nil) m, g, err = ReadTargets(ctx, []File{f}, []string{"foo", "foo"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(g)) require.Equal(t, 2, len(g))
require.Equal(t, []string{"foo"}, g["default"].Targets) require.Equal(t, []string{"foo"}, g["default"].Targets)
@@ -1083,7 +1083,7 @@ services:
} }
}`)} }`)}
m, g, err := ReadTargets(ctx, []File{fhcl}, []string{"default"}, nil, nil) m, g, err := ReadTargets(ctx, []File{fhcl}, []string{"default"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(g)) require.Equal(t, 1, len(g))
require.Equal(t, []string{"image"}, g["default"].Targets) require.Equal(t, []string{"image"}, g["default"].Targets)
@@ -1091,7 +1091,7 @@ services:
require.Equal(t, 1, len(m["image"].Outputs)) require.Equal(t, 1, len(m["image"].Outputs))
require.Equal(t, "type=docker", m["image"].Outputs[0]) require.Equal(t, "type=docker", m["image"].Outputs[0])
m, g, err = ReadTargets(ctx, []File{fhcl}, []string{"image-release"}, nil, nil) m, g, err = ReadTargets(ctx, []File{fhcl}, []string{"image-release"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(g)) require.Equal(t, 1, len(g))
require.Equal(t, []string{"image-release"}, g["default"].Targets) require.Equal(t, []string{"image-release"}, g["default"].Targets)
@@ -1099,7 +1099,7 @@ services:
require.Equal(t, 1, len(m["image-release"].Outputs)) require.Equal(t, 1, len(m["image-release"].Outputs))
require.Equal(t, "type=image,push=true", m["image-release"].Outputs[0]) require.Equal(t, "type=image,push=true", m["image-release"].Outputs[0])
m, g, err = ReadTargets(ctx, []File{fhcl}, []string{"image", "image-release"}, nil, nil) m, g, err = ReadTargets(ctx, []File{fhcl}, []string{"image", "image-release"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(g)) require.Equal(t, 1, len(g))
require.Equal(t, []string{"image", "image-release"}, g["default"].Targets) require.Equal(t, []string{"image", "image-release"}, g["default"].Targets)
@@ -1108,21 +1108,21 @@ services:
require.Equal(t, 1, len(m["image-release"].Outputs)) require.Equal(t, 1, len(m["image-release"].Outputs))
require.Equal(t, "type=image,push=true", m["image-release"].Outputs[0]) require.Equal(t, "type=image,push=true", m["image-release"].Outputs[0])
m, g, err = ReadTargets(ctx, []File{fyml, fhcl}, []string{"default"}, nil, nil) m, g, err = ReadTargets(ctx, []File{fyml, fhcl}, []string{"default"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(g)) require.Equal(t, 1, len(g))
require.Equal(t, []string{"image"}, g["default"].Targets) require.Equal(t, []string{"image"}, g["default"].Targets)
require.Equal(t, 1, len(m)) require.Equal(t, 1, len(m))
require.Equal(t, ".", *m["image"].Context) require.Equal(t, ".", *m["image"].Context)
m, g, err = ReadTargets(ctx, []File{fjson}, []string{"default"}, nil, nil) m, g, err = ReadTargets(ctx, []File{fjson}, []string{"default"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(g)) require.Equal(t, 1, len(g))
require.Equal(t, []string{"image"}, g["default"].Targets) require.Equal(t, []string{"image"}, g["default"].Targets)
require.Equal(t, 1, len(m)) require.Equal(t, 1, len(m))
require.Equal(t, ".", *m["image"].Context) require.Equal(t, ".", *m["image"].Context)
m, g, err = ReadTargets(ctx, []File{fyml}, []string{"default"}, nil, nil) m, g, err = ReadTargets(ctx, []File{fyml}, []string{"default"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(g)) require.Equal(t, 1, len(g))
sort.Strings(g["default"].Targets) sort.Strings(g["default"].Targets)
@@ -1131,7 +1131,7 @@ services:
require.Equal(t, "./Dockerfile", *m["addon"].Dockerfile) require.Equal(t, "./Dockerfile", *m["addon"].Dockerfile)
require.Equal(t, "./aws.Dockerfile", *m["aws"].Dockerfile) require.Equal(t, "./aws.Dockerfile", *m["aws"].Dockerfile)
m, g, err = ReadTargets(ctx, []File{fyml, fhcl}, []string{"addon", "aws"}, nil, nil) m, g, err = ReadTargets(ctx, []File{fyml, fhcl}, []string{"addon", "aws"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(g)) require.Equal(t, 1, len(g))
sort.Strings(g["default"].Targets) sort.Strings(g["default"].Targets)
@@ -1140,7 +1140,7 @@ services:
require.Equal(t, "./Dockerfile", *m["addon"].Dockerfile) require.Equal(t, "./Dockerfile", *m["addon"].Dockerfile)
require.Equal(t, "./aws.Dockerfile", *m["aws"].Dockerfile) require.Equal(t, "./aws.Dockerfile", *m["aws"].Dockerfile)
m, g, err = ReadTargets(ctx, []File{fyml, fhcl}, []string{"addon", "aws", "image"}, nil, nil) m, g, err = ReadTargets(ctx, []File{fyml, fhcl}, []string{"addon", "aws", "image"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(g)) require.Equal(t, 1, len(g))
sort.Strings(g["default"].Targets) sort.Strings(g["default"].Targets)
@@ -1168,7 +1168,7 @@ target "image" {
output = ["type=docker"] output = ["type=docker"]
}`)} }`)}
m, g, err := ReadTargets(ctx, []File{f}, []string{"foo"}, nil, nil) m, g, err := ReadTargets(ctx, []File{f}, []string{"foo"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(g)) require.Equal(t, 2, len(g))
require.Equal(t, []string{"foo"}, g["default"].Targets) require.Equal(t, []string{"foo"}, g["default"].Targets)
@@ -1176,7 +1176,7 @@ target "image" {
require.Equal(t, 1, len(m)) require.Equal(t, 1, len(m))
require.Equal(t, "bar", *m["foo"].Dockerfile) require.Equal(t, "bar", *m["foo"].Dockerfile)
m, g, err = ReadTargets(ctx, []File{f}, []string{"foo", "foo"}, nil, nil) m, g, err = ReadTargets(ctx, []File{f}, []string{"foo", "foo"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(g)) require.Equal(t, 2, len(g))
require.Equal(t, []string{"foo"}, g["default"].Targets) require.Equal(t, []string{"foo"}, g["default"].Targets)
@@ -1202,7 +1202,7 @@ target "image" {
output = ["type=docker"] output = ["type=docker"]
}`)} }`)}
m, g, err := ReadTargets(ctx, []File{f}, []string{"foo"}, nil, nil) m, g, err := ReadTargets(ctx, []File{f}, []string{"foo"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(g)) require.Equal(t, 2, len(g))
require.Equal(t, []string{"foo"}, g["default"].Targets) require.Equal(t, []string{"foo"}, g["default"].Targets)
@@ -1211,7 +1211,7 @@ target "image" {
require.Equal(t, "bar", *m["foo"].Dockerfile) require.Equal(t, "bar", *m["foo"].Dockerfile)
require.Equal(t, "type=docker", m["image"].Outputs[0]) require.Equal(t, "type=docker", m["image"].Outputs[0])
m, g, err = ReadTargets(ctx, []File{f}, []string{"foo", "image"}, nil, nil) m, g, err = ReadTargets(ctx, []File{f}, []string{"foo", "image"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(g)) require.Equal(t, 2, len(g))
require.Equal(t, []string{"foo", "image"}, g["default"].Targets) require.Equal(t, []string{"foo", "image"}, g["default"].Targets)
@@ -1273,7 +1273,7 @@ target "d" {
for _, tt := range cases { for _, tt := range cases {
tt := tt tt := tt
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
m, g, err := ReadTargets(ctx, []File{f}, []string{"d"}, tt.overrides, nil) m, g, err := ReadTargets(ctx, []File{f}, []string{"d"}, tt.overrides, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(g)) require.Equal(t, 1, len(g))
require.Equal(t, []string{"d"}, g["default"].Targets) require.Equal(t, []string{"d"}, g["default"].Targets)
@@ -1345,7 +1345,7 @@ group "default" {
for _, tt := range cases { for _, tt := range cases {
tt := tt tt := tt
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
m, g, err := ReadTargets(ctx, []File{f}, []string{"default"}, tt.overrides, nil) m, g, err := ReadTargets(ctx, []File{f}, []string{"default"}, tt.overrides, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(g)) require.Equal(t, 1, len(g))
require.Equal(t, []string{"child1", "child2"}, g["default"].Targets) require.Equal(t, []string{"child1", "child2"}, g["default"].Targets)
@@ -1403,7 +1403,7 @@ func TestTargetName(t *testing.T) {
_, _, err := ReadTargets(ctx, []File{{ _, _, err := ReadTargets(ctx, []File{{
Name: "docker-bake.hcl", Name: "docker-bake.hcl",
Data: []byte(`target "` + tt.target + `" {}`), Data: []byte(`target "` + tt.target + `" {}`),
}}, []string{tt.target}, nil, nil) }}, []string{tt.target}, nil, nil, &EntitlementConf{})
if tt.wantErr { if tt.wantErr {
require.Error(t, err) require.Error(t, err)
} else { } else {
@@ -1490,7 +1490,7 @@ target "f" {
for _, tt := range cases { for _, tt := range cases {
tt := tt tt := tt
t.Run(strings.Join(tt.names, "+"), func(t *testing.T) { t.Run(strings.Join(tt.names, "+"), func(t *testing.T) {
m, g, err := ReadTargets(ctx, []File{f}, tt.names, nil, nil) m, g, err := ReadTargets(ctx, []File{f}, tt.names, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
var gnames []string var gnames []string
@@ -1567,7 +1567,7 @@ func TestHCLNullVars(t *testing.T) {
} }
ctx := context.TODO() ctx := context.TODO()
m, _, err := ReadTargets(ctx, []File{fp}, []string{"default"}, nil, nil) m, _, err := ReadTargets(ctx, []File{fp}, []string{"default"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(m)) require.Equal(t, 1, len(m))
@@ -1602,7 +1602,7 @@ func TestJSONNullVars(t *testing.T) {
} }
ctx := context.TODO() ctx := context.TODO()
m, _, err := ReadTargets(ctx, []File{fp}, []string{"default"}, nil, nil) m, _, err := ReadTargets(ctx, []File{fp}, []string{"default"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(m)) require.Equal(t, 1, len(m))
@@ -1677,7 +1677,7 @@ func TestAttestDuplicates(t *testing.T) {
} }
ctx := context.TODO() ctx := context.TODO()
m, _, err := ReadTargets(ctx, []File{fp}, []string{"default"}, nil, nil) m, _, err := ReadTargets(ctx, []File{fp}, []string{"default"}, nil, nil, &EntitlementConf{})
require.Equal(t, []string{"type=sbom,foo=bar", "type=provenance,mode=max"}, m["default"].Attest) require.Equal(t, []string{"type=sbom,foo=bar", "type=provenance,mode=max"}, m["default"].Attest)
require.NoError(t, err) require.NoError(t, err)
@@ -1688,7 +1688,7 @@ func TestAttestDuplicates(t *testing.T) {
"provenance": ptrstr("type=provenance,mode=max"), "provenance": ptrstr("type=provenance,mode=max"),
}, opts["default"].Attests) }, opts["default"].Attests)
m, _, err = ReadTargets(ctx, []File{fp}, []string{"default"}, []string{"*.attest=type=sbom,disabled=true"}, nil) m, _, err = ReadTargets(ctx, []File{fp}, []string{"default"}, []string{"*.attest=type=sbom,disabled=true"}, nil, &EntitlementConf{})
require.Equal(t, []string{"type=sbom,disabled=true", "type=provenance,mode=max"}, m["default"].Attest) require.Equal(t, []string{"type=sbom,disabled=true", "type=provenance,mode=max"}, m["default"].Attest)
require.NoError(t, err) require.NoError(t, err)
@@ -1710,7 +1710,7 @@ func TestAnnotations(t *testing.T) {
}`), }`),
} }
ctx := context.TODO() ctx := context.TODO()
m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
bo, err := TargetsToBuildOpt(m, &Input{}) bo, err := TargetsToBuildOpt(m, &Input{})
@@ -1737,7 +1737,7 @@ func TestHCLEntitlements(t *testing.T) {
}`), }`),
} }
ctx := context.TODO() ctx := context.TODO()
m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
bo, err := TargetsToBuildOpt(m, &Input{}) bo, err := TargetsToBuildOpt(m, &Input{})
@@ -1777,7 +1777,7 @@ func TestEntitlementsForNetHostCompose(t *testing.T) {
} }
ctx := context.TODO() ctx := context.TODO()
m, g, err := ReadTargets(ctx, []File{fp, fp2}, []string{"app"}, nil, nil) m, g, err := ReadTargets(ctx, []File{fp, fp2}, []string{"app"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
bo, err := TargetsToBuildOpt(m, &Input{}) bo, err := TargetsToBuildOpt(m, &Input{})
@@ -1808,7 +1808,7 @@ func TestEntitlementsForNetHost(t *testing.T) {
} }
ctx := context.TODO() ctx := context.TODO()
m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
bo, err := TargetsToBuildOpt(m, &Input{}) bo, err := TargetsToBuildOpt(m, &Input{})
@@ -1839,7 +1839,7 @@ func TestNetNone(t *testing.T) {
} }
ctx := context.TODO() ctx := context.TODO()
m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)
bo, err := TargetsToBuildOpt(m, &Input{}) bo, err := TargetsToBuildOpt(m, &Input{})
@@ -1856,3 +1856,175 @@ func TestNetNone(t *testing.T) {
require.Len(t, bo["app"].Allow, 0) require.Len(t, bo["app"].Allow, 0)
require.Equal(t, "none", bo["app"].NetworkMode) require.Equal(t, "none", bo["app"].NetworkMode)
} }
func TestVariableValidation(t *testing.T) {
fp := File{
Name: "docker-bake.hcl",
Data: []byte(`
variable "FOO" {
validation {
condition = FOO != ""
error_message = "FOO is required."
}
}
target "app" {
args = {
FOO = FOO
}
}
`),
}
ctx := context.TODO()
t.Run("Valid", func(t *testing.T) {
t.Setenv("FOO", "bar")
_, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{})
require.NoError(t, err)
})
t.Run("Invalid", func(t *testing.T) {
_, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{})
require.Error(t, err)
require.Contains(t, err.Error(), "FOO is required.")
})
}
func TestVariableValidationMulti(t *testing.T) {
fp := File{
Name: "docker-bake.hcl",
Data: []byte(`
variable "FOO" {
validation {
condition = FOO != ""
error_message = "FOO is required."
}
validation {
condition = strlen(FOO) > 4
error_message = "FOO must be longer than 4 characters."
}
}
target "app" {
args = {
FOO = FOO
}
}
`),
}
ctx := context.TODO()
t.Run("Valid", func(t *testing.T) {
t.Setenv("FOO", "barbar")
_, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{})
require.NoError(t, err)
})
t.Run("InvalidLength", func(t *testing.T) {
t.Setenv("FOO", "bar")
_, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{})
require.Error(t, err)
require.Contains(t, err.Error(), "FOO must be longer than 4 characters.")
})
t.Run("InvalidEmpty", func(t *testing.T) {
_, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{})
require.Error(t, err)
require.Contains(t, err.Error(), "FOO is required.")
})
}
func TestVariableValidationWithDeps(t *testing.T) {
fp := File{
Name: "docker-bake.hcl",
Data: []byte(`
variable "FOO" {}
variable "BAR" {
validation {
condition = FOO != ""
error_message = "BAR requires FOO to be set."
}
}
target "app" {
args = {
BAR = BAR
}
}
`),
}
ctx := context.TODO()
t.Run("Valid", func(t *testing.T) {
t.Setenv("FOO", "bar")
_, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{})
require.NoError(t, err)
})
t.Run("SetBar", func(t *testing.T) {
t.Setenv("FOO", "bar")
t.Setenv("BAR", "baz")
_, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{})
require.NoError(t, err)
})
t.Run("Invalid", func(t *testing.T) {
_, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{})
require.Error(t, err)
require.Contains(t, err.Error(), "BAR requires FOO to be set.")
})
}
func TestVariableValidationTyped(t *testing.T) {
fp := File{
Name: "docker-bake.hcl",
Data: []byte(`
variable "FOO" {
default = 0
validation {
condition = FOO > 5
error_message = "FOO must be greater than 5."
}
}
target "app" {
args = {
FOO = FOO
}
}
`),
}
ctx := context.TODO()
t.Run("Valid", func(t *testing.T) {
t.Setenv("FOO", "10")
_, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{})
require.NoError(t, err)
})
t.Run("Invalid", func(t *testing.T) {
_, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{})
require.Error(t, err)
require.Contains(t, err.Error(), "FOO must be greater than 5.")
})
}
// https://github.com/docker/buildx/issues/2822
func TestVariableEmpty(t *testing.T) {
fp := File{
Name: "docker-bake.hcl",
Data: []byte(`
variable "FOO" {
default = ""
}
target "app" {
output = [FOO]
}
`),
}
ctx := context.TODO()
_, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{})
require.NoError(t, err)
}

View File

@@ -102,6 +102,12 @@ func ParseCompose(cfgs []composetypes.ConfigFile, envs map[string]string) (*Conf
shmSize = &shmSizeStr shmSize = &shmSizeStr
} }
var networkModeP *string
if s.Build.Network != "" {
networkMode := s.Build.Network
networkModeP = &networkMode
}
var ulimits []string var ulimits []string
if s.Build.Ulimits != nil { if s.Build.Ulimits != nil {
for n, u := range s.Build.Ulimits { for n, u := range s.Build.Ulimits {
@@ -154,7 +160,7 @@ func ParseCompose(cfgs []composetypes.ConfigFile, envs map[string]string) (*Conf
})), })),
CacheFrom: s.Build.CacheFrom, CacheFrom: s.Build.CacheFrom,
CacheTo: s.Build.CacheTo, CacheTo: s.Build.CacheTo,
NetworkMode: &s.Build.Network, NetworkMode: networkModeP,
SSH: ssh, SSH: ssh,
Secrets: secrets, Secrets: secrets,
ShmSize: shmSize, ShmSize: shmSize,
@@ -173,7 +179,6 @@ func ParseCompose(cfgs []composetypes.ConfigFile, envs map[string]string) (*Conf
c.Targets = append(c.Targets, t) c.Targets = append(c.Targets, t)
} }
c.Groups = append(c.Groups, g) c.Groups = append(c.Groups, g)
} }
return &c, nil return &c, nil

View File

@@ -2,15 +2,21 @@ package bake
import ( import (
"bufio" "bufio"
"cmp"
"context" "context"
"fmt" "fmt"
"io" "io"
"io/fs"
"os" "os"
"path/filepath"
"slices" "slices"
"strconv"
"strings" "strings"
"syscall"
"github.com/containerd/console" "github.com/containerd/console"
"github.com/docker/buildx/build" "github.com/docker/buildx/build"
"github.com/docker/buildx/util/osutil"
"github.com/moby/buildkit/util/entitlements" "github.com/moby/buildkit/util/entitlements"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@@ -67,10 +73,8 @@ func ParseEntitlements(in []string) (EntitlementConf, error) {
conf.ImagePush = append(conf.ImagePush, v) conf.ImagePush = append(conf.ImagePush, v)
conf.ImageLoad = append(conf.ImageLoad, v) conf.ImageLoad = append(conf.ImageLoad, v)
default: default:
return conf, errors.Errorf("uknown entitlement key %q", k) return conf, errors.Errorf("unknown entitlement key %q", k)
} }
// TODO: dedupe slices and parent paths
} }
} }
return conf, nil return conf, nil
@@ -101,10 +105,64 @@ func (c EntitlementConf) check(bo build.Options, expected *EntitlementConf) erro
} }
} }
} }
rwPaths := map[string]struct{}{}
roPaths := map[string]struct{}{}
for _, p := range collectLocalPaths(bo.Inputs) {
roPaths[p] = struct{}{}
}
for _, p := range bo.ExportsLocalPathsTemporary {
rwPaths[p] = struct{}{}
}
for _, ce := range bo.CacheTo {
if ce.Type == "local" {
if dest, ok := ce.Attrs["dest"]; ok {
rwPaths[dest] = struct{}{}
}
}
}
for _, ci := range bo.CacheFrom {
if ci.Type == "local" {
if src, ok := ci.Attrs["src"]; ok {
roPaths[src] = struct{}{}
}
}
}
for _, secret := range bo.SecretSpecs {
if secret.FilePath != "" {
roPaths[secret.FilePath] = struct{}{}
}
}
for _, ssh := range bo.SSHSpecs {
for _, p := range ssh.Paths {
roPaths[p] = struct{}{}
}
if len(ssh.Paths) == 0 {
expected.SSH = true
}
}
var err error
expected.FSRead, err = findMissingPaths(c.FSRead, roPaths)
if err != nil {
return err
}
expected.FSWrite, err = findMissingPaths(c.FSWrite, rwPaths)
if err != nil {
return err
}
return nil return nil
} }
func (c EntitlementConf) Prompt(ctx context.Context, out io.Writer) error { func (c EntitlementConf) Prompt(ctx context.Context, isRemote bool, out io.Writer) error {
var term bool var term bool
if _, err := console.ConsoleFromFile(os.Stdin); err == nil { if _, err := console.ConsoleFromFile(os.Stdin); err == nil {
term = true term = true
@@ -113,32 +171,78 @@ func (c EntitlementConf) Prompt(ctx context.Context, out io.Writer) error {
var msgs []string var msgs []string
var flags []string var flags []string
// these warnings are currently disabled to give users time to update
var msgsFS []string
var flagsFS []string
if c.NetworkHost { if c.NetworkHost {
msgs = append(msgs, " - Running build containers that can access host network") msgs = append(msgs, " - Running build containers that can access host network")
flags = append(flags, "network.host") flags = append(flags, string(EntitlementKeyNetworkHost))
} }
if c.SecurityInsecure { if c.SecurityInsecure {
msgs = append(msgs, " - Running privileged containers that can make system changes") msgs = append(msgs, " - Running privileged containers that can make system changes")
flags = append(flags, "security.insecure") flags = append(flags, string(EntitlementKeySecurityInsecure))
} }
if len(msgs) == 0 { if c.SSH {
msgsFS = append(msgsFS, " - Forwarding default SSH agent socket")
flagsFS = append(flagsFS, string(EntitlementKeySSH))
}
roPaths, rwPaths, commonPaths := groupSamePaths(c.FSRead, c.FSWrite)
wd, err := os.Getwd()
if err != nil {
return errors.Wrap(err, "failed to get current working directory")
}
wd, err = filepath.EvalSymlinks(wd)
if err != nil {
return errors.Wrap(err, "failed to evaluate working directory")
}
roPaths = toRelativePaths(roPaths, wd)
rwPaths = toRelativePaths(rwPaths, wd)
commonPaths = toRelativePaths(commonPaths, wd)
if len(commonPaths) > 0 {
for _, p := range commonPaths {
msgsFS = append(msgsFS, fmt.Sprintf(" - Read and write access to path %s", p))
flagsFS = append(flagsFS, string(EntitlementKeyFS)+"="+p)
}
}
if len(roPaths) > 0 {
for _, p := range roPaths {
msgsFS = append(msgsFS, fmt.Sprintf(" - Read access to path %s", p))
flagsFS = append(flagsFS, string(EntitlementKeyFSRead)+"="+p)
}
}
if len(rwPaths) > 0 {
for _, p := range rwPaths {
msgsFS = append(msgsFS, fmt.Sprintf(" - Write access to path %s", p))
flagsFS = append(flagsFS, string(EntitlementKeyFSWrite)+"="+p)
}
}
if len(msgs) == 0 && len(msgsFS) == 0 {
return nil return nil
} }
fmt.Fprintf(out, "Your build is requesting privileges for following possibly insecure capabilities:\n\n") fmt.Fprintf(out, "Your build is requesting privileges for following possibly insecure capabilities:\n\n")
for _, m := range msgs { for _, m := range slices.Concat(msgs, msgsFS) {
fmt.Fprintf(out, "%s\n", m) fmt.Fprintf(out, "%s\n", m)
} }
for i, f := range flags { for i, f := range flags {
flags[i] = "--allow=" + f flags[i] = "--allow=" + f
} }
for i, f := range flagsFS {
flagsFS[i] = "--allow=" + f
}
if term { if term {
fmt.Fprintf(out, "\nIn order to not see this message in the future pass %q to grant requested privileges.\n", strings.Join(flags, " ")) fmt.Fprintf(out, "\nIn order to not see this message in the future pass %q to grant requested privileges.\n", strings.Join(slices.Concat(flags, flagsFS), " "))
} else { } else {
fmt.Fprintf(out, "\nPass %q to grant requested privileges.\n", strings.Join(flags, " ")) fmt.Fprintf(out, "\nPass %q to grant requested privileges.\n", strings.Join(slices.Concat(flags, flagsFS), " "))
} }
args := append([]string(nil), os.Args...) args := append([]string(nil), os.Args...)
@@ -149,7 +253,35 @@ func (c EntitlementConf) Prompt(ctx context.Context, out io.Writer) error {
if idx != -1 { if idx != -1 {
fmt.Fprintf(out, "\nYour full command with requested privileges:\n\n") fmt.Fprintf(out, "\nYour full command with requested privileges:\n\n")
fmt.Fprintf(out, "%s %s %s\n\n", strings.Join(args[:idx+1], " "), strings.Join(flags, " "), strings.Join(args[idx+1:], " ")) fmt.Fprintf(out, "%s %s %s\n\n", strings.Join(args[:idx+1], " "), strings.Join(slices.Concat(flags, flagsFS), " "), strings.Join(args[idx+1:], " "))
}
fsEntitlementsEnabled := false
if isRemote {
if v, ok := os.LookupEnv("BAKE_ALLOW_REMOTE_FS_ACCESS"); ok {
vv, err := strconv.ParseBool(v)
if err != nil {
return errors.Wrapf(err, "failed to parse BAKE_ALLOW_REMOTE_FS_ACCESS value %q", v)
}
fsEntitlementsEnabled = !vv
} else {
fsEntitlementsEnabled = true
}
}
v, fsEntitlementsSet := os.LookupEnv("BUILDX_BAKE_ENTITLEMENTS_FS")
if fsEntitlementsSet {
vv, err := strconv.ParseBool(v)
if err != nil {
return errors.Wrapf(err, "failed to parse BUILDX_BAKE_ENTITLEMENTS_FS value %q", v)
}
fsEntitlementsEnabled = vv
}
if !fsEntitlementsEnabled && len(msgs) == 0 {
if !fsEntitlementsSet {
fmt.Fprintf(out, "This warning will become an error in a future release. To enable filesystem entitlements checks at the moment, set BUILDX_BAKE_ENTITLEMENTS_FS=1 .\n\n")
}
return nil
} }
if term { if term {
@@ -173,3 +305,288 @@ func (c EntitlementConf) Prompt(ctx context.Context, out io.Writer) error {
return errors.Errorf("additional privileges requested") return errors.Errorf("additional privileges requested")
} }
func isParentOrEqualPath(p, parent string) bool {
if p == parent || parent == "/" {
return true
}
if strings.HasPrefix(p, filepath.Clean(parent+string(filepath.Separator))) {
return true
}
return false
}
func findMissingPaths(set []string, paths map[string]struct{}) ([]string, error) {
set, allowAny, err := evaluatePaths(set)
if err != nil {
return nil, err
} else if allowAny {
return nil, nil
}
paths, err = evaluateToExistingPaths(paths)
if err != nil {
return nil, err
}
paths, err = dedupPaths(paths)
if err != nil {
return nil, err
}
out := make([]string, 0, len(paths))
loop0:
for p := range paths {
for _, c := range set {
if isParentOrEqualPath(p, c) {
continue loop0
}
}
out = append(out, p)
}
if len(out) == 0 {
return nil, nil
}
slices.Sort(out)
return out, nil
}
func dedupPaths(in map[string]struct{}) (map[string]struct{}, error) {
arr := make([]string, 0, len(in))
for p := range in {
arr = append(arr, filepath.Clean(p))
}
slices.SortFunc(arr, func(a, b string) int {
return cmp.Compare(len(a), len(b))
})
m := make(map[string]struct{}, len(arr))
loop0:
for _, p := range arr {
for parent := range m {
if strings.HasPrefix(p, parent+string(filepath.Separator)) {
continue loop0
}
}
m[p] = struct{}{}
}
return m, nil
}
func toRelativePaths(in []string, wd string) []string {
out := make([]string, 0, len(in))
for _, p := range in {
rel, err := filepath.Rel(wd, p)
if err == nil {
// allow up to one level of ".." in the path
if !strings.HasPrefix(rel, ".."+string(filepath.Separator)+"..") {
out = append(out, rel)
continue
}
}
out = append(out, p)
}
return out
}
func groupSamePaths(in1, in2 []string) ([]string, []string, []string) {
if in1 == nil || in2 == nil {
return in1, in2, nil
}
slices.Sort(in1)
slices.Sort(in2)
common := []string{}
i, j := 0, 0
for i < len(in1) && j < len(in2) {
switch {
case in1[i] == in2[j]:
common = append(common, in1[i])
i++
j++
case in1[i] < in2[j]:
i++
default:
j++
}
}
in1 = removeCommonPaths(in1, common)
in2 = removeCommonPaths(in2, common)
return in1, in2, common
}
func removeCommonPaths(in, common []string) []string {
filtered := make([]string, 0, len(in))
commonIndex := 0
for _, path := range in {
if commonIndex < len(common) && path == common[commonIndex] {
commonIndex++
continue
}
filtered = append(filtered, path)
}
return filtered
}
func evaluatePaths(in []string) ([]string, bool, error) {
out := make([]string, 0, len(in))
allowAny := false
for _, p := range in {
if p == "*" {
allowAny = true
continue
}
v, err := filepath.Abs(p)
if err != nil {
return nil, false, errors.Wrapf(err, "failed to evaluate path %q", p)
}
v, err = filepath.EvalSymlinks(v)
if err != nil {
return nil, false, errors.Wrapf(err, "failed to evaluate path %q", p)
}
out = append(out, v)
}
return out, allowAny, nil
}
func evaluateToExistingPaths(in map[string]struct{}) (map[string]struct{}, error) {
m := make(map[string]struct{}, len(in))
for p := range in {
v, err := evaluateToExistingPath(p)
if err != nil {
return nil, errors.Wrapf(err, "failed to evaluate path %q", p)
}
v, err = osutil.GetLongPathName(v)
if err != nil {
return nil, errors.Wrapf(err, "failed to evaluate path %q", p)
}
m[v] = struct{}{}
}
return m, nil
}
func evaluateToExistingPath(in string) (string, error) {
in, err := filepath.Abs(in)
if err != nil {
return "", err
}
volLen := volumeNameLen(in)
pathSeparator := string(os.PathSeparator)
if volLen < len(in) && os.IsPathSeparator(in[volLen]) {
volLen++
}
vol := in[:volLen]
dest := vol
linksWalked := 0
var end int
for start := volLen; start < len(in); start = end {
for start < len(in) && os.IsPathSeparator(in[start]) {
start++
}
end = start
for end < len(in) && !os.IsPathSeparator(in[end]) {
end++
}
if end == start {
break
} else if in[start:end] == "." {
continue
} else if in[start:end] == ".." {
var r int
for r = len(dest) - 1; r >= volLen; r-- {
if os.IsPathSeparator(dest[r]) {
break
}
}
if r < volLen || dest[r+1:] == ".." {
if len(dest) > volLen {
dest += pathSeparator
}
dest += ".."
} else {
dest = dest[:r]
}
continue
}
if len(dest) > volumeNameLen(dest) && !os.IsPathSeparator(dest[len(dest)-1]) {
dest += pathSeparator
}
dest += in[start:end]
fi, err := os.Lstat(dest)
if err != nil {
// If the component doesn't exist, return the last valid path
if os.IsNotExist(err) {
for r := len(dest) - 1; r >= volLen; r-- {
if os.IsPathSeparator(dest[r]) {
return dest[:r], nil
}
}
return vol, nil
}
return "", err
}
if fi.Mode()&fs.ModeSymlink == 0 {
if !fi.Mode().IsDir() && end < len(in) {
return "", syscall.ENOTDIR
}
continue
}
linksWalked++
if linksWalked > 255 {
return "", errors.New("too many symlinks")
}
link, err := os.Readlink(dest)
if err != nil {
return "", err
}
in = link + in[end:]
v := volumeNameLen(link)
if v > 0 {
if v < len(link) && os.IsPathSeparator(link[v]) {
v++
}
vol = link[:v]
dest = vol
end = len(vol)
} else if len(link) > 0 && os.IsPathSeparator(link[0]) {
dest = link[:1]
end = 1
vol = link[:1]
volLen = 1
} else {
var r int
for r = len(dest) - 1; r >= volLen; r-- {
if os.IsPathSeparator(dest[r]) {
break
}
}
if r < volLen {
dest = vol
} else {
dest = dest[:r]
}
end = 0
}
}
return filepath.Clean(dest), nil
}
func volumeNameLen(s string) int {
return len(filepath.VolumeName(s))
}

444
bake/entitlements_test.go Normal file
View File

@@ -0,0 +1,444 @@
package bake
import (
"fmt"
"os"
"path/filepath"
"slices"
"testing"
"github.com/docker/buildx/build"
"github.com/docker/buildx/controller/pb"
"github.com/docker/buildx/util/osutil"
"github.com/moby/buildkit/client/llb"
"github.com/moby/buildkit/util/entitlements"
"github.com/stretchr/testify/require"
)
func TestEvaluateToExistingPath(t *testing.T) {
tempDir, err := osutil.GetLongPathName(t.TempDir())
require.NoError(t, err)
// Setup temporary directory structure for testing
existingFile := filepath.Join(tempDir, "existing_file")
require.NoError(t, os.WriteFile(existingFile, []byte("test"), 0644))
existingDir := filepath.Join(tempDir, "existing_dir")
require.NoError(t, os.Mkdir(existingDir, 0755))
symlinkToFile := filepath.Join(tempDir, "symlink_to_file")
require.NoError(t, os.Symlink(existingFile, symlinkToFile))
symlinkToDir := filepath.Join(tempDir, "symlink_to_dir")
require.NoError(t, os.Symlink(existingDir, symlinkToDir))
nonexistentPath := filepath.Join(tempDir, "nonexistent", "path", "file.txt")
tests := []struct {
name string
input string
expected string
expectErr bool
}{
{
name: "Existing file",
input: existingFile,
expected: existingFile,
expectErr: false,
},
{
name: "Existing directory",
input: existingDir,
expected: existingDir,
expectErr: false,
},
{
name: "Symlink to file",
input: symlinkToFile,
expected: existingFile,
expectErr: false,
},
{
name: "Symlink to directory",
input: symlinkToDir,
expected: existingDir,
expectErr: false,
},
{
name: "Non-existent path",
input: nonexistentPath,
expected: tempDir,
expectErr: false,
},
{
name: "Non-existent intermediate path",
input: filepath.Join(tempDir, "nonexistent", "file.txt"),
expected: tempDir,
expectErr: false,
},
{
name: "Root path",
input: "/",
expected: func() string {
root, _ := filepath.Abs("/")
return root
}(),
expectErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := evaluateToExistingPath(tt.input)
if tt.expectErr {
require.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, tt.expected, result)
}
})
}
}
func TestDedupePaths(t *testing.T) {
wd := osutil.GetWd()
tcases := []struct {
in map[string]struct{}
out map[string]struct{}
}{
{
in: map[string]struct{}{
"/a/b/c": {},
"/a/b/d": {},
"/a/b/e": {},
},
out: map[string]struct{}{
"/a/b/c": {},
"/a/b/d": {},
"/a/b/e": {},
},
},
{
in: map[string]struct{}{
"/a/b/c": {},
"/a/b/c/d": {},
"/a/b/c/d/e": {},
"/a/b/../b/c": {},
},
out: map[string]struct{}{
"/a/b/c": {},
},
},
{
in: map[string]struct{}{
filepath.Join(wd, "a/b/c"): {},
filepath.Join(wd, "../aa"): {},
filepath.Join(wd, "a/b"): {},
filepath.Join(wd, "a/b/d"): {},
filepath.Join(wd, "../aa/b"): {},
filepath.Join(wd, "../../bb"): {},
},
out: map[string]struct{}{
"a/b": {},
"../aa": {},
filepath.Join(wd, "../../bb"): {},
},
},
}
for i, tc := range tcases {
t.Run(fmt.Sprintf("case%d", i), func(t *testing.T) {
out, err := dedupPaths(tc.in)
if err != nil {
require.NoError(t, err)
}
// convert to relative paths as that is shown to user
arr := make([]string, 0, len(out))
for k := range out {
arr = append(arr, k)
}
require.NoError(t, err)
arr = toRelativePaths(arr, wd)
m := make(map[string]struct{})
for _, v := range arr {
m[filepath.ToSlash(v)] = struct{}{}
}
o := make(map[string]struct{}, len(tc.out))
for k := range tc.out {
o[filepath.ToSlash(k)] = struct{}{}
}
require.Equal(t, o, m)
})
}
}
func TestValidateEntitlements(t *testing.T) {
dir1 := t.TempDir()
dir2 := t.TempDir()
// the paths returned by entitlements validation will have symlinks resolved
expDir1, err := filepath.EvalSymlinks(dir1)
require.NoError(t, err)
expDir2, err := filepath.EvalSymlinks(dir2)
require.NoError(t, err)
escapeLink := filepath.Join(dir1, "escape_link")
require.NoError(t, os.Symlink("../../aa", escapeLink))
wd, err := os.Getwd()
require.NoError(t, err)
expWd, err := filepath.EvalSymlinks(wd)
require.NoError(t, err)
tcases := []struct {
name string
conf EntitlementConf
opt build.Options
expected EntitlementConf
}{
{
name: "No entitlements",
opt: build.Options{
Inputs: build.Inputs{
ContextState: &llb.State{},
},
},
},
{
name: "NetworkHostMissing",
opt: build.Options{
Allow: []entitlements.Entitlement{
entitlements.EntitlementNetworkHost,
},
},
expected: EntitlementConf{
NetworkHost: true,
FSRead: []string{expWd},
},
},
{
name: "NetworkHostSet",
conf: EntitlementConf{
NetworkHost: true,
},
opt: build.Options{
Allow: []entitlements.Entitlement{
entitlements.EntitlementNetworkHost,
},
},
expected: EntitlementConf{
FSRead: []string{expWd},
},
},
{
name: "SecurityAndNetworkHostMissing",
opt: build.Options{
Allow: []entitlements.Entitlement{
entitlements.EntitlementNetworkHost,
entitlements.EntitlementSecurityInsecure,
},
},
expected: EntitlementConf{
NetworkHost: true,
SecurityInsecure: true,
FSRead: []string{expWd},
},
},
{
name: "SecurityMissingAndNetworkHostSet",
conf: EntitlementConf{
NetworkHost: true,
},
opt: build.Options{
Allow: []entitlements.Entitlement{
entitlements.EntitlementNetworkHost,
entitlements.EntitlementSecurityInsecure,
},
},
expected: EntitlementConf{
SecurityInsecure: true,
FSRead: []string{expWd},
},
},
{
name: "SSHMissing",
opt: build.Options{
SSHSpecs: []*pb.SSH{
{
ID: "test",
},
},
},
expected: EntitlementConf{
SSH: true,
FSRead: []string{expWd},
},
},
{
name: "ExportLocal",
opt: build.Options{
ExportsLocalPathsTemporary: []string{
dir1,
filepath.Join(dir1, "subdir"),
dir2,
},
},
expected: EntitlementConf{
FSWrite: func() []string {
exp := []string{expDir1, expDir2}
slices.Sort(exp)
return exp
}(),
FSRead: []string{expWd},
},
},
{
name: "SecretFromSubFile",
opt: build.Options{
SecretSpecs: []*pb.Secret{
{
FilePath: filepath.Join(dir1, "subfile"),
},
},
},
conf: EntitlementConf{
FSRead: []string{wd, dir1},
},
},
{
name: "SecretFromEscapeLink",
opt: build.Options{
SecretSpecs: []*pb.Secret{
{
FilePath: escapeLink,
},
},
},
conf: EntitlementConf{
FSRead: []string{wd, dir1},
},
expected: EntitlementConf{
FSRead: []string{filepath.Join(expDir1, "../..")},
},
},
{
name: "SecretFromEscapeLinkAllowRoot",
opt: build.Options{
SecretSpecs: []*pb.Secret{
{
FilePath: escapeLink,
},
},
},
conf: EntitlementConf{
FSRead: []string{"/"},
},
expected: EntitlementConf{
FSRead: func() []string {
// on windows root (/) is only allowed if it is the same volume as wd
if filepath.VolumeName(wd) == filepath.VolumeName(escapeLink) {
return nil
}
// if not, then escapeLink is not allowed
exp, err := evaluateToExistingPath(escapeLink)
require.NoError(t, err)
exp, err = filepath.EvalSymlinks(exp)
require.NoError(t, err)
return []string{exp}
}(),
},
},
{
name: "SecretFromEscapeLinkAllowAny",
opt: build.Options{
SecretSpecs: []*pb.Secret{
{
FilePath: escapeLink,
},
},
},
conf: EntitlementConf{
FSRead: []string{"*"},
},
expected: EntitlementConf{},
},
}
for _, tc := range tcases {
t.Run(tc.name, func(t *testing.T) {
expected, err := tc.conf.Validate(map[string]build.Options{"test": tc.opt})
require.NoError(t, err)
require.Equal(t, tc.expected, expected)
})
}
}
func TestGroupSamePaths(t *testing.T) {
tests := []struct {
name string
in1 []string
in2 []string
expected1 []string
expected2 []string
expectedC []string
}{
{
name: "All common paths",
in1: []string{"/path/a", "/path/b", "/path/c"},
in2: []string{"/path/a", "/path/b", "/path/c"},
expected1: []string{},
expected2: []string{},
expectedC: []string{"/path/a", "/path/b", "/path/c"},
},
{
name: "No common paths",
in1: []string{"/path/a", "/path/b"},
in2: []string{"/path/c", "/path/d"},
expected1: []string{"/path/a", "/path/b"},
expected2: []string{"/path/c", "/path/d"},
expectedC: []string{},
},
{
name: "Some common paths",
in1: []string{"/path/a", "/path/b", "/path/c"},
in2: []string{"/path/b", "/path/c", "/path/d"},
expected1: []string{"/path/a"},
expected2: []string{"/path/d"},
expectedC: []string{"/path/b", "/path/c"},
},
{
name: "Empty inputs",
in1: []string{},
in2: []string{},
expected1: []string{},
expected2: []string{},
expectedC: []string{},
},
{
name: "One empty input",
in1: []string{"/path/a", "/path/b"},
in2: []string{},
expected1: []string{"/path/a", "/path/b"},
expected2: []string{},
expectedC: []string{},
},
{
name: "Unsorted inputs with common paths",
in1: []string{"/path/c", "/path/a", "/path/b"},
in2: []string{"/path/b", "/path/c", "/path/a"},
expected1: []string{},
expected2: []string{},
expectedC: []string{"/path/a", "/path/b", "/path/c"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
out1, out2, common := groupSamePaths(tt.in1, tt.in2)
require.Equal(t, tt.expected1, out1, "in1 should match expected1")
require.Equal(t, tt.expected2, out2, "in2 should match expected2")
require.Equal(t, tt.expectedC, common, "common should match expectedC")
})
}
}

View File

@@ -49,18 +49,18 @@ func TestHCLBasic(t *testing.T) {
require.Equal(t, []string{"db", "webapp"}, c.Groups[0].Targets) require.Equal(t, []string{"db", "webapp"}, c.Groups[0].Targets)
require.Equal(t, 4, len(c.Targets)) require.Equal(t, 4, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "db") require.Equal(t, "db", c.Targets[0].Name)
require.Equal(t, "./db", *c.Targets[0].Context) require.Equal(t, "./db", *c.Targets[0].Context)
require.Equal(t, c.Targets[1].Name, "webapp") require.Equal(t, "webapp", c.Targets[1].Name)
require.Equal(t, 1, len(c.Targets[1].Args)) require.Equal(t, 1, len(c.Targets[1].Args))
require.Equal(t, ptrstr("123"), c.Targets[1].Args["buildno"]) require.Equal(t, ptrstr("123"), c.Targets[1].Args["buildno"])
require.Equal(t, c.Targets[2].Name, "cross") require.Equal(t, "cross", c.Targets[2].Name)
require.Equal(t, 2, len(c.Targets[2].Platforms)) require.Equal(t, 2, len(c.Targets[2].Platforms))
require.Equal(t, []string{"linux/amd64", "linux/arm64"}, c.Targets[2].Platforms) require.Equal(t, []string{"linux/amd64", "linux/arm64"}, c.Targets[2].Platforms)
require.Equal(t, c.Targets[3].Name, "webapp-plus") require.Equal(t, "webapp-plus", c.Targets[3].Name)
require.Equal(t, 1, len(c.Targets[3].Args)) require.Equal(t, 1, len(c.Targets[3].Args))
require.Equal(t, map[string]*string{"IAMCROSS": ptrstr("true")}, c.Targets[3].Args) require.Equal(t, map[string]*string{"IAMCROSS": ptrstr("true")}, c.Targets[3].Args)
} }
@@ -109,18 +109,18 @@ func TestHCLBasicInJSON(t *testing.T) {
require.Equal(t, []string{"db", "webapp"}, c.Groups[0].Targets) require.Equal(t, []string{"db", "webapp"}, c.Groups[0].Targets)
require.Equal(t, 4, len(c.Targets)) require.Equal(t, 4, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "db") require.Equal(t, "db", c.Targets[0].Name)
require.Equal(t, "./db", *c.Targets[0].Context) require.Equal(t, "./db", *c.Targets[0].Context)
require.Equal(t, c.Targets[1].Name, "webapp") require.Equal(t, "webapp", c.Targets[1].Name)
require.Equal(t, 1, len(c.Targets[1].Args)) require.Equal(t, 1, len(c.Targets[1].Args))
require.Equal(t, ptrstr("123"), c.Targets[1].Args["buildno"]) require.Equal(t, ptrstr("123"), c.Targets[1].Args["buildno"])
require.Equal(t, c.Targets[2].Name, "cross") require.Equal(t, "cross", c.Targets[2].Name)
require.Equal(t, 2, len(c.Targets[2].Platforms)) require.Equal(t, 2, len(c.Targets[2].Platforms))
require.Equal(t, []string{"linux/amd64", "linux/arm64"}, c.Targets[2].Platforms) require.Equal(t, []string{"linux/amd64", "linux/arm64"}, c.Targets[2].Platforms)
require.Equal(t, c.Targets[3].Name, "webapp-plus") require.Equal(t, "webapp-plus", c.Targets[3].Name)
require.Equal(t, 1, len(c.Targets[3].Args)) require.Equal(t, 1, len(c.Targets[3].Args))
require.Equal(t, map[string]*string{"IAMCROSS": ptrstr("true")}, c.Targets[3].Args) require.Equal(t, map[string]*string{"IAMCROSS": ptrstr("true")}, c.Targets[3].Args)
} }
@@ -146,7 +146,7 @@ func TestHCLWithFunctions(t *testing.T) {
require.Equal(t, []string{"webapp"}, c.Groups[0].Targets) require.Equal(t, []string{"webapp"}, c.Groups[0].Targets)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "webapp") require.Equal(t, "webapp", c.Targets[0].Name)
require.Equal(t, ptrstr("124"), c.Targets[0].Args["buildno"]) require.Equal(t, ptrstr("124"), c.Targets[0].Args["buildno"])
} }
@@ -176,7 +176,7 @@ func TestHCLWithUserDefinedFunctions(t *testing.T) {
require.Equal(t, []string{"webapp"}, c.Groups[0].Targets) require.Equal(t, []string{"webapp"}, c.Groups[0].Targets)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "webapp") require.Equal(t, "webapp", c.Targets[0].Name)
require.Equal(t, ptrstr("124"), c.Targets[0].Args["buildno"]) require.Equal(t, ptrstr("124"), c.Targets[0].Args["buildno"])
} }
@@ -205,7 +205,7 @@ func TestHCLWithVariables(t *testing.T) {
require.Equal(t, []string{"webapp"}, c.Groups[0].Targets) require.Equal(t, []string{"webapp"}, c.Groups[0].Targets)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "webapp") require.Equal(t, "webapp", c.Targets[0].Name)
require.Equal(t, ptrstr("123"), c.Targets[0].Args["buildno"]) require.Equal(t, ptrstr("123"), c.Targets[0].Args["buildno"])
t.Setenv("BUILD_NUMBER", "456") t.Setenv("BUILD_NUMBER", "456")
@@ -218,7 +218,7 @@ func TestHCLWithVariables(t *testing.T) {
require.Equal(t, []string{"webapp"}, c.Groups[0].Targets) require.Equal(t, []string{"webapp"}, c.Groups[0].Targets)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "webapp") require.Equal(t, "webapp", c.Targets[0].Name)
require.Equal(t, ptrstr("456"), c.Targets[0].Args["buildno"]) require.Equal(t, ptrstr("456"), c.Targets[0].Args["buildno"])
} }
@@ -241,7 +241,7 @@ func TestHCLWithVariablesInFunctions(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "webapp") require.Equal(t, "webapp", c.Targets[0].Name)
require.Equal(t, []string{"user/repo:v1"}, c.Targets[0].Tags) require.Equal(t, []string{"user/repo:v1"}, c.Targets[0].Tags)
t.Setenv("REPO", "docker/buildx") t.Setenv("REPO", "docker/buildx")
@@ -250,7 +250,7 @@ func TestHCLWithVariablesInFunctions(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "webapp") require.Equal(t, "webapp", c.Targets[0].Name)
require.Equal(t, []string{"docker/buildx:v1"}, c.Targets[0].Tags) require.Equal(t, []string{"docker/buildx:v1"}, c.Targets[0].Tags)
} }
@@ -279,7 +279,7 @@ func TestHCLMultiFileSharedVariables(t *testing.T) {
}, nil) }, nil)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, "app", c.Targets[0].Name)
require.Equal(t, ptrstr("pre-abc"), c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("pre-abc"), c.Targets[0].Args["v1"])
require.Equal(t, ptrstr("abc-post"), c.Targets[0].Args["v2"]) require.Equal(t, ptrstr("abc-post"), c.Targets[0].Args["v2"])
@@ -292,7 +292,7 @@ func TestHCLMultiFileSharedVariables(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, "app", c.Targets[0].Name)
require.Equal(t, ptrstr("pre-def"), c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("pre-def"), c.Targets[0].Args["v1"])
require.Equal(t, ptrstr("def-post"), c.Targets[0].Args["v2"]) require.Equal(t, ptrstr("def-post"), c.Targets[0].Args["v2"])
} }
@@ -328,7 +328,7 @@ func TestHCLVarsWithVars(t *testing.T) {
}, nil) }, nil)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, "app", c.Targets[0].Name)
require.Equal(t, ptrstr("pre--ABCDEF-"), c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("pre--ABCDEF-"), c.Targets[0].Args["v1"])
require.Equal(t, ptrstr("ABCDEF-post"), c.Targets[0].Args["v2"]) require.Equal(t, ptrstr("ABCDEF-post"), c.Targets[0].Args["v2"])
@@ -341,7 +341,7 @@ func TestHCLVarsWithVars(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, "app", c.Targets[0].Name)
require.Equal(t, ptrstr("pre--NEWDEF-"), c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("pre--NEWDEF-"), c.Targets[0].Args["v1"])
require.Equal(t, ptrstr("NEWDEF-post"), c.Targets[0].Args["v2"]) require.Equal(t, ptrstr("NEWDEF-post"), c.Targets[0].Args["v2"])
} }
@@ -366,7 +366,7 @@ func TestHCLTypedVariables(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, "app", c.Targets[0].Name)
require.Equal(t, ptrstr("lower"), c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("lower"), c.Targets[0].Args["v1"])
require.Equal(t, ptrstr("yes"), c.Targets[0].Args["v2"]) require.Equal(t, ptrstr("yes"), c.Targets[0].Args["v2"])
@@ -377,7 +377,7 @@ func TestHCLTypedVariables(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, "app", c.Targets[0].Name)
require.Equal(t, ptrstr("higher"), c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("higher"), c.Targets[0].Args["v1"])
require.Equal(t, ptrstr("no"), c.Targets[0].Args["v2"]) require.Equal(t, ptrstr("no"), c.Targets[0].Args["v2"])
@@ -475,7 +475,7 @@ func TestHCLAttrs(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, "app", c.Targets[0].Name)
require.Equal(t, ptrstr("attr-abcdef"), c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("attr-abcdef"), c.Targets[0].Args["v1"])
// env does not apply if no variable // env does not apply if no variable
@@ -484,7 +484,7 @@ func TestHCLAttrs(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, "app", c.Targets[0].Name)
require.Equal(t, ptrstr("attr-abcdef"), c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("attr-abcdef"), c.Targets[0].Args["v1"])
// attr-multifile // attr-multifile
} }
@@ -592,7 +592,7 @@ func TestHCLAttrsCustomType(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, "app", c.Targets[0].Name)
require.Equal(t, []string{"linux/arm64", "linux/amd64"}, c.Targets[0].Platforms) require.Equal(t, []string{"linux/arm64", "linux/amd64"}, c.Targets[0].Platforms)
require.Equal(t, ptrstr("linux/arm64"), c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("linux/arm64"), c.Targets[0].Args["v1"])
} }
@@ -618,7 +618,7 @@ func TestHCLMultiFileAttrs(t *testing.T) {
}, nil) }, nil)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, "app", c.Targets[0].Name)
require.Equal(t, ptrstr("pre-def"), c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("pre-def"), c.Targets[0].Args["v1"])
t.Setenv("FOO", "ghi") t.Setenv("FOO", "ghi")
@@ -630,7 +630,7 @@ func TestHCLMultiFileAttrs(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, "app", c.Targets[0].Name)
require.Equal(t, ptrstr("pre-ghi"), c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("pre-ghi"), c.Targets[0].Args["v1"])
} }
@@ -653,7 +653,7 @@ func TestHCLMultiFileGlobalAttrs(t *testing.T) {
}, nil) }, nil)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, "app", c.Targets[0].Name)
require.Equal(t, "pre-def", *c.Targets[0].Args["v1"]) require.Equal(t, "pre-def", *c.Targets[0].Args["v1"])
} }
@@ -839,12 +839,12 @@ func TestHCLRenameMultiFile(t *testing.T) {
require.Equal(t, 2, len(c.Targets)) require.Equal(t, 2, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "bar") require.Equal(t, "bar", c.Targets[0].Name)
require.Equal(t, *c.Targets[0].Dockerfile, "x") require.Equal(t, "x", *c.Targets[0].Dockerfile)
require.Equal(t, *c.Targets[0].Target, "z") require.Equal(t, "z", *c.Targets[0].Target)
require.Equal(t, c.Targets[1].Name, "foo") require.Equal(t, "foo", c.Targets[1].Name)
require.Equal(t, *c.Targets[1].Context, "y") require.Equal(t, "y", *c.Targets[1].Context)
} }
func TestHCLMatrixBasic(t *testing.T) { func TestHCLMatrixBasic(t *testing.T) {
@@ -862,10 +862,10 @@ func TestHCLMatrixBasic(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(c.Targets)) require.Equal(t, 2, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "x") require.Equal(t, "x", c.Targets[0].Name)
require.Equal(t, c.Targets[1].Name, "y") require.Equal(t, "y", c.Targets[1].Name)
require.Equal(t, *c.Targets[0].Dockerfile, "x.Dockerfile") require.Equal(t, "x.Dockerfile", *c.Targets[0].Dockerfile)
require.Equal(t, *c.Targets[1].Dockerfile, "y.Dockerfile") require.Equal(t, "y.Dockerfile", *c.Targets[1].Dockerfile)
require.Equal(t, 1, len(c.Groups)) require.Equal(t, 1, len(c.Groups))
require.Equal(t, "default", c.Groups[0].Name) require.Equal(t, "default", c.Groups[0].Name)
@@ -948,9 +948,9 @@ func TestHCLMatrixMaps(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(c.Targets)) require.Equal(t, 2, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "aa") require.Equal(t, "aa", c.Targets[0].Name)
require.Equal(t, c.Targets[0].Args["target"], ptrstr("valbb")) require.Equal(t, c.Targets[0].Args["target"], ptrstr("valbb"))
require.Equal(t, c.Targets[1].Name, "cc") require.Equal(t, "cc", c.Targets[1].Name)
require.Equal(t, c.Targets[1].Args["target"], ptrstr("valdd")) require.Equal(t, c.Targets[1].Args["target"], ptrstr("valdd"))
} }
@@ -1141,7 +1141,7 @@ func TestJSONAttributes(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, "app", c.Targets[0].Name)
require.Equal(t, ptrstr("pre-abc-def"), c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("pre-abc-def"), c.Targets[0].Args["v1"])
} }
@@ -1166,7 +1166,7 @@ func TestJSONFunctions(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, "app", c.Targets[0].Name)
require.Equal(t, ptrstr("pre-<FOO-abc>"), c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("pre-<FOO-abc>"), c.Targets[0].Args["v1"])
} }
@@ -1184,7 +1184,7 @@ func TestJSONInvalidFunctions(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, "app", c.Targets[0].Name)
require.Equal(t, ptrstr(`myfunc("foo")`), c.Targets[0].Args["v1"]) require.Equal(t, ptrstr(`myfunc("foo")`), c.Targets[0].Args["v1"])
} }
@@ -1212,7 +1212,7 @@ func TestHCLFunctionInAttr(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, "app", c.Targets[0].Name)
require.Equal(t, ptrstr("FOO <> [baz]"), c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("FOO <> [baz]"), c.Targets[0].Args["v1"])
} }
@@ -1243,7 +1243,7 @@ services:
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, "app", c.Targets[0].Name)
require.Equal(t, ptrstr("foo"), c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("foo"), c.Targets[0].Args["v1"])
require.Equal(t, ptrstr("bar"), c.Targets[0].Args["v2"]) require.Equal(t, ptrstr("bar"), c.Targets[0].Args["v2"])
require.Equal(t, "dir", *c.Targets[0].Context) require.Equal(t, "dir", *c.Targets[0].Context)
@@ -1266,7 +1266,7 @@ func TestHCLBuiltinVars(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, "app", c.Targets[0].Name)
require.Equal(t, "foo", *c.Targets[0].Context) require.Equal(t, "foo", *c.Targets[0].Context)
require.Equal(t, "test", *c.Targets[0].Dockerfile) require.Equal(t, "test", *c.Targets[0].Dockerfile)
} }
@@ -1332,17 +1332,17 @@ target "b" {
require.Equal(t, 4, len(c.Targets)) require.Equal(t, 4, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "metadata-a") require.Equal(t, "metadata-a", c.Targets[0].Name)
require.Equal(t, []string{"app/a:1.0.0", "app/a:latest"}, c.Targets[0].Tags) require.Equal(t, []string{"app/a:1.0.0", "app/a:latest"}, c.Targets[0].Tags)
require.Equal(t, c.Targets[1].Name, "metadata-b") require.Equal(t, "metadata-b", c.Targets[1].Name)
require.Equal(t, []string{"app/b:1.0.0", "app/b:latest"}, c.Targets[1].Tags) require.Equal(t, []string{"app/b:1.0.0", "app/b:latest"}, c.Targets[1].Tags)
require.Equal(t, c.Targets[2].Name, "a") require.Equal(t, "a", c.Targets[2].Name)
require.Equal(t, ".", *c.Targets[2].Context) require.Equal(t, ".", *c.Targets[2].Context)
require.Equal(t, "a", *c.Targets[2].Target) require.Equal(t, "a", *c.Targets[2].Target)
require.Equal(t, c.Targets[3].Name, "b") require.Equal(t, "b", c.Targets[3].Name)
require.Equal(t, ".", *c.Targets[3].Context) require.Equal(t, ".", *c.Targets[3].Context)
require.Equal(t, "b", *c.Targets[3].Target) require.Equal(t, "b", *c.Targets[3].Target)
} }
@@ -1389,10 +1389,10 @@ target "two" {
require.Equal(t, 2, len(c.Targets)) require.Equal(t, 2, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "one") require.Equal(t, "one", c.Targets[0].Name)
require.Equal(t, map[string]*string{"a": ptrstr("pre-ghi-jkl")}, c.Targets[0].Args) require.Equal(t, map[string]*string{"a": ptrstr("pre-ghi-jkl")}, c.Targets[0].Args)
require.Equal(t, c.Targets[1].Name, "two") require.Equal(t, "two", c.Targets[1].Name)
require.Equal(t, map[string]*string{"b": ptrstr("pre-jkl")}, c.Targets[1].Args) require.Equal(t, map[string]*string{"b": ptrstr("pre-jkl")}, c.Targets[1].Args)
} }

View File

@@ -28,10 +28,16 @@ type variable struct {
Name string `json:"-" hcl:"name,label"` Name string `json:"-" hcl:"name,label"`
Default *hcl.Attribute `json:"default,omitempty" hcl:"default,optional"` Default *hcl.Attribute `json:"default,omitempty" hcl:"default,optional"`
Description string `json:"description,omitempty" hcl:"description,optional"` Description string `json:"description,omitempty" hcl:"description,optional"`
Validations []*variableValidation `json:"validation,omitempty" hcl:"validation,block"`
Body hcl.Body `json:"-" hcl:",body"` Body hcl.Body `json:"-" hcl:",body"`
Remain hcl.Body `json:"-" hcl:",remain"` Remain hcl.Body `json:"-" hcl:",remain"`
} }
type variableValidation struct {
Condition hcl.Expression `json:"condition" hcl:"condition"`
ErrorMessage hcl.Expression `json:"error_message" hcl:"error_message"`
}
type functionDef struct { type functionDef struct {
Name string `json:"-" hcl:"name,label"` Name string `json:"-" hcl:"name,label"`
Params *hcl.Attribute `json:"params,omitempty" hcl:"params"` Params *hcl.Attribute `json:"params,omitempty" hcl:"params"`
@@ -541,6 +547,33 @@ func (p *parser) resolveBlockNames(block *hcl.Block) ([]string, error) {
return names, nil return names, nil
} }
func (p *parser) validateVariables(vars map[string]*variable, ectx *hcl.EvalContext) hcl.Diagnostics {
var diags hcl.Diagnostics
for _, v := range vars {
for _, validation := range v.Validations {
condition, condDiags := validation.Condition.Value(ectx)
if condDiags.HasErrors() {
diags = append(diags, condDiags...)
continue
}
if !condition.True() {
message, msgDiags := validation.ErrorMessage.Value(ectx)
if msgDiags.HasErrors() {
diags = append(diags, msgDiags...)
continue
}
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Validation failed",
Detail: message.AsString(),
Subject: validation.Condition.Range().Ptr(),
})
}
}
}
return diags
}
type Variable struct { type Variable struct {
Name string Name string
Description string Description string
@@ -686,6 +719,9 @@ func Parse(b hcl.Body, opt Opt, val interface{}) (*ParseMeta, hcl.Diagnostics) {
} }
vars = append(vars, v) vars = append(vars, v)
} }
if diags := p.validateVariables(p.vars, p.ectx); diags.HasErrors() {
return nil, diags
}
for k := range p.funcs { for k := range p.funcs {
if err := p.resolveFunction(p.ectx, k); err != nil { if err := p.resolveFunction(p.ectx, k); err != nil {

View File

@@ -170,7 +170,6 @@ func indexOfFunc() function.Function {
} }
} }
return cty.NilVal, errors.New("item not found") return cty.NilVal, errors.New("item not found")
}, },
}) })
} }

View File

@@ -18,6 +18,7 @@ import (
"github.com/containerd/containerd/images" "github.com/containerd/containerd/images"
"github.com/distribution/reference" "github.com/distribution/reference"
"github.com/docker/buildx/builder" "github.com/docker/buildx/builder"
controllerapi "github.com/docker/buildx/controller/pb"
"github.com/docker/buildx/driver" "github.com/docker/buildx/driver"
"github.com/docker/buildx/util/confutil" "github.com/docker/buildx/util/confutil"
"github.com/docker/buildx/util/desktop" "github.com/docker/buildx/util/desktop"
@@ -69,6 +70,7 @@ type Options struct {
CacheTo []client.CacheOptionsEntry CacheTo []client.CacheOptionsEntry
CgroupParent string CgroupParent string
Exports []client.ExportEntry Exports []client.ExportEntry
ExportsLocalPathsTemporary []string // should be removed after client.ExportEntry update in buildkit v0.19.0
ExtraHosts []string ExtraHosts []string
Labels map[string]string Labels map[string]string
NetworkMode string NetworkMode string
@@ -76,6 +78,8 @@ type Options struct {
NoCacheFilter []string NoCacheFilter []string
Platforms []specs.Platform Platforms []specs.Platform
Pull bool Pull bool
SecretSpecs []*controllerapi.Secret
SSHSpecs []*controllerapi.SSH
ShmSize opts.MemBytes ShmSize opts.MemBytes
Tags []string Tags []string
Target string Target string

View File

@@ -23,7 +23,7 @@ func setupTest(tb testing.TB) {
gitutil.GitInit(c, tb) gitutil.GitInit(c, tb)
df := []byte("FROM alpine:latest\n") df := []byte("FROM alpine:latest\n")
assert.NoError(tb, os.WriteFile("Dockerfile", df, 0644)) require.NoError(tb, os.WriteFile("Dockerfile", df, 0644))
gitutil.GitAdd(c, tb, "Dockerfile") gitutil.GitAdd(c, tb, "Dockerfile")
gitutil.GitCommit(c, tb, "initial commit") gitutil.GitCommit(c, tb, "initial commit")
@@ -32,7 +32,7 @@ func setupTest(tb testing.TB) {
func TestGetGitAttributesNotGitRepo(t *testing.T) { func TestGetGitAttributesNotGitRepo(t *testing.T) {
_, err := getGitAttributes(context.Background(), t.TempDir(), "Dockerfile") _, err := getGitAttributes(context.Background(), t.TempDir(), "Dockerfile")
assert.NoError(t, err) require.NoError(t, err)
} }
func TestGetGitAttributesBadGitRepo(t *testing.T) { func TestGetGitAttributesBadGitRepo(t *testing.T) {
@@ -47,7 +47,7 @@ func TestGetGitAttributesNoContext(t *testing.T) {
setupTest(t) setupTest(t)
addGitAttrs, err := getGitAttributes(context.Background(), "", "Dockerfile") addGitAttrs, err := getGitAttributes(context.Background(), "", "Dockerfile")
assert.NoError(t, err) require.NoError(t, err)
var so client.SolveOpt var so client.SolveOpt
addGitAttrs(&so) addGitAttrs(&so)
assert.Empty(t, so.FrontendAttrs) assert.Empty(t, so.FrontendAttrs)
@@ -195,8 +195,8 @@ func TestLocalDirsSub(t *testing.T) {
gitutil.GitInit(c, t) gitutil.GitInit(c, t)
df := []byte("FROM alpine:latest\n") df := []byte("FROM alpine:latest\n")
assert.NoError(t, os.MkdirAll("app", 0755)) require.NoError(t, os.MkdirAll("app", 0755))
assert.NoError(t, os.WriteFile("app/Dockerfile", df, 0644)) require.NoError(t, os.WriteFile("app/Dockerfile", df, 0644))
gitutil.GitAdd(c, t, "app/Dockerfile") gitutil.GitAdd(c, t, "app/Dockerfile")
gitutil.GitCommit(c, t, "initial commit") gitutil.GitCommit(c, t, "initial commit")

View File

@@ -16,7 +16,7 @@ import (
type Container struct { type Container struct {
cancelOnce sync.Once cancelOnce sync.Once
containerCancel func() containerCancel func(error)
isUnavailable atomic.Bool isUnavailable atomic.Bool
initStarted atomic.Bool initStarted atomic.Bool
container gateway.Container container gateway.Container
@@ -31,18 +31,18 @@ func NewContainer(ctx context.Context, resultCtx *ResultHandle, cfg *controllera
errCh := make(chan error) errCh := make(chan error)
go func() { go func() {
err := resultCtx.build(func(ctx context.Context, c gateway.Client) (*gateway.Result, error) { err := resultCtx.build(func(ctx context.Context, c gateway.Client) (*gateway.Result, error) {
ctx, cancel := context.WithCancel(ctx) ctx, cancel := context.WithCancelCause(ctx)
go func() { go func() {
<-mainCtx.Done() <-mainCtx.Done()
cancel() cancel(errors.WithStack(context.Canceled))
}() }()
containerCfg, err := resultCtx.getContainerConfig(cfg) containerCfg, err := resultCtx.getContainerConfig(cfg)
if err != nil { if err != nil {
return nil, err return nil, err
} }
containerCtx, containerCancel := context.WithCancel(ctx) containerCtx, containerCancel := context.WithCancelCause(ctx)
defer containerCancel() defer containerCancel(errors.WithStack(context.Canceled))
bkContainer, err := c.NewContainer(containerCtx, containerCfg) bkContainer, err := c.NewContainer(containerCtx, containerCfg)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -83,7 +83,7 @@ func (c *Container) Cancel() {
c.markUnavailable() c.markUnavailable()
c.cancelOnce.Do(func() { c.cancelOnce.Do(func() {
if c.containerCancel != nil { if c.containerCancel != nil {
c.containerCancel() c.containerCancel(errors.WithStack(context.Canceled))
} }
close(c.releaseCh) close(c.releaseCh)
}) })

View File

@@ -10,7 +10,6 @@ import (
"time" "time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func generateRandomData(size int) []byte { func generateRandomData(size int) []byte {
@@ -57,7 +56,7 @@ func TestSyncMultiReaderParallel(t *testing.T) {
return return
} }
require.NoError(t, err, "Reader %d error", readerId) assert.NoError(t, err, "Reader %d error", readerId)
if mathrand.Intn(1000) == 0 { //nolint:gosec if mathrand.Intn(1000) == 0 { //nolint:gosec
t.Logf("Reader %d closing", readerId) t.Logf("Reader %d closing", readerId)

View File

@@ -82,7 +82,7 @@ func NewResultHandle(ctx context.Context, cc *client.Client, opt client.SolveOpt
var respHandle *ResultHandle var respHandle *ResultHandle
go func() { go func() {
defer cancel(context.Canceled) // ensure no dangling processes defer func() { cancel(errors.WithStack(context.Canceled)) }() // ensure no dangling processes
var res *gateway.Result var res *gateway.Result
var err error var err error
@@ -181,7 +181,7 @@ func NewResultHandle(ctx context.Context, cc *client.Client, opt client.SolveOpt
case <-respHandle.done: case <-respHandle.done:
case <-ctx.Done(): case <-ctx.Done():
} }
return nil, ctx.Err() return nil, context.Cause(ctx)
}, nil) }, nil)
if respHandle != nil { if respHandle != nil {
return return

View File

@@ -138,7 +138,7 @@ func TestToBuildkitExtraHosts(t *testing.T) {
actualOut, actualErr := toBuildkitExtraHosts(context.TODO(), tc.input, nil) actualOut, actualErr := toBuildkitExtraHosts(context.TODO(), tc.input, nil)
if tc.expectedErr == "" { if tc.expectedErr == "" {
require.Equal(t, tc.expectedOut, actualOut) require.Equal(t, tc.expectedOut, actualOut)
require.Nil(t, actualErr) require.NoError(t, actualErr)
} else { } else {
require.Zero(t, actualOut) require.Zero(t, actualOut)
require.Error(t, actualErr, tc.expectedErr) require.Error(t, actualErr, tc.expectedErr)

View File

@@ -288,7 +288,15 @@ func GetBuilders(dockerCli command.Cli, txn *store.Txn) ([]*Builder, error) {
return nil, err return nil, err
} }
builders := make([]*Builder, len(storeng)) contexts, err := dockerCli.ContextStore().List()
if err != nil {
return nil, err
}
sort.Slice(contexts, func(i, j int) bool {
return contexts[i].Name < contexts[j].Name
})
builders := make([]*Builder, len(storeng), len(storeng)+len(contexts))
seen := make(map[string]struct{}) seen := make(map[string]struct{})
for i, ng := range storeng { for i, ng := range storeng {
b, err := New(dockerCli, b, err := New(dockerCli,
@@ -303,14 +311,6 @@ func GetBuilders(dockerCli command.Cli, txn *store.Txn) ([]*Builder, error) {
seen[b.NodeGroup.Name] = struct{}{} seen[b.NodeGroup.Name] = struct{}{}
} }
contexts, err := dockerCli.ContextStore().List()
if err != nil {
return nil, err
}
sort.Slice(contexts, func(i, j int) bool {
return contexts[i].Name < contexts[j].Name
})
for _, c := range contexts { for _, c := range contexts {
// if a context has the same name as an instance from the store, do not // if a context has the same name as an instance from the store, do not
// add it to the builders list. An instance from the store takes // add it to the builders list. An instance from the store takes
@@ -522,8 +522,9 @@ func Create(ctx context.Context, txn *store.Txn, dockerCli command.Cli, opts Cre
return nil, err return nil, err
} }
timeoutCtx, cancel := context.WithTimeout(ctx, 20*time.Second) cancelCtx, cancel := context.WithCancelCause(ctx)
defer cancel() timeoutCtx, _ := context.WithTimeoutCause(cancelCtx, 20*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet,lostcancel // no need to manually cancel this context as we already rely on parent
defer func() { cancel(errors.WithStack(context.Canceled)) }()
nodes, err := b.LoadNodes(timeoutCtx, WithData()) nodes, err := b.LoadNodes(timeoutCtx, WithData())
if err != nil { if err != nil {

View File

@@ -19,13 +19,13 @@ func TestCsvToMap(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Contains(t, r, "tolerations") require.Contains(t, r, "tolerations")
require.Equal(t, r["tolerations"], "key=foo,value=bar;key=foo2,value=bar2") require.Equal(t, "key=foo,value=bar;key=foo2,value=bar2", r["tolerations"])
require.Contains(t, r, "replicas") require.Contains(t, r, "replicas")
require.Equal(t, r["replicas"], "1") require.Equal(t, "1", r["replicas"])
require.Contains(t, r, "namespace") require.Contains(t, r, "namespace")
require.Equal(t, r["namespace"], "default") require.Equal(t, "default", r["namespace"])
} }
func TestParseBuildkitdFlags(t *testing.T) { func TestParseBuildkitdFlags(t *testing.T) {

View File

@@ -107,9 +107,16 @@ func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in ba
if err != nil { if err != nil {
return err return err
} }
wd, err := os.Getwd()
if err != nil {
return errors.Wrapf(err, "failed to get current working directory")
}
// filesystem access under the current working directory is allowed by default
ent.FSRead = append(ent.FSRead, wd)
ent.FSWrite = append(ent.FSWrite, wd)
ctx2, cancel := context.WithCancel(context.TODO()) ctx2, cancel := context.WithCancelCause(context.TODO())
defer cancel() defer cancel(errors.WithStack(context.Canceled))
var nodes []builder.Node var nodes []builder.Node
var progressConsoleDesc, progressTextDesc string var progressConsoleDesc, progressTextDesc string
@@ -192,7 +199,7 @@ func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in ba
} }
} }
tgts, grps, err := bake.ReadTargets(ctx, files, targets, overrides, defaults) tgts, grps, err := bake.ReadTargets(ctx, files, targets, overrides, defaults, &ent)
if err != nil { if err != nil {
return err return err
} }
@@ -250,7 +257,7 @@ func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in ba
if err != nil { if err != nil {
return err return err
} }
if err := exp.Prompt(ctx, &syncWriter{w: dockerCli.Err(), wait: printer.Wait}); err != nil { if err := exp.Prompt(ctx, url != "", &syncWriter{w: dockerCli.Err(), wait: printer.Wait}); err != nil {
return err return err
} }
if printer.IsDone() { if printer.IsDone() {

View File

@@ -325,8 +325,8 @@ func runBuild(ctx context.Context, dockerCli command.Cli, options buildOptions)
} }
attributes := buildMetricAttributes(dockerCli, driverType, &options) attributes := buildMetricAttributes(dockerCli, driverType, &options)
ctx2, cancel := context.WithCancel(context.TODO()) ctx2, cancel := context.WithCancelCause(context.TODO())
defer cancel() defer func() { cancel(errors.WithStack(context.Canceled)) }()
progressMode, err := options.toDisplayMode() progressMode, err := options.toDisplayMode()
if err != nil { if err != nil {
return err return err
@@ -763,9 +763,12 @@ func decodeExporterResponse(exporterResponse map[string]string) map[string]inter
} }
var raw map[string]interface{} var raw map[string]interface{}
if err = json.Unmarshal(dt, &raw); err != nil || len(raw) == 0 { if err = json.Unmarshal(dt, &raw); err != nil || len(raw) == 0 {
var rawList []map[string]interface{}
if err = json.Unmarshal(dt, &rawList); err != nil || len(rawList) == 0 {
out[k] = v out[k] = v
continue continue
} }
}
out[k] = json.RawMessage(dt) out[k] = json.RawMessage(dt)
} }
return out return out
@@ -882,7 +885,6 @@ func printWarnings(w io.Writer, warnings []client.VertexWarning, mode progressui
src.Print(w) src.Print(w)
} }
fmt.Fprintf(w, "\n") fmt.Fprintf(w, "\n")
} }
} }

View File

@@ -42,7 +42,7 @@ func runCreate(ctx context.Context, dockerCli command.Cli, in createOptions, arg
return errors.Errorf("can't push with no tags specified, please set --tag or --dry-run") return errors.Errorf("can't push with no tags specified, please set --tag or --dry-run")
} }
fileArgs := make([]string, len(in.files)) fileArgs := make([]string, len(in.files), len(in.files)+len(args))
for i, f := range in.files { for i, f := range in.files {
dt, err := os.ReadFile(f) dt, err := os.ReadFile(f)
if err != nil { if err != nil {
@@ -173,8 +173,8 @@ func runCreate(ctx context.Context, dockerCli command.Cli, in createOptions, arg
// new resolver cause need new auth // new resolver cause need new auth
r = imagetools.New(imageopt) r = imagetools.New(imageopt)
ctx2, cancel := context.WithCancel(context.TODO()) ctx2, cancel := context.WithCancelCause(context.TODO())
defer cancel() defer func() { cancel(errors.WithStack(context.Canceled)) }()
printer, err := progress.NewPrinter(ctx2, os.Stderr, progressui.DisplayMode(in.progress)) printer, err := progress.NewPrinter(ctx2, os.Stderr, progressui.DisplayMode(in.progress))
if err != nil { if err != nil {
return err return err

View File

@@ -17,6 +17,7 @@ import (
"github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/debug" "github.com/docker/cli/cli/debug"
"github.com/docker/go-units" "github.com/docker/go-units"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@@ -34,8 +35,9 @@ func runInspect(ctx context.Context, dockerCli command.Cli, in inspectOptions) e
return err return err
} }
timeoutCtx, cancel := context.WithTimeout(ctx, 20*time.Second) timeoutCtx, cancel := context.WithCancelCause(ctx)
defer cancel() timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 20*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet,lostcancel // no need to manually cancel this context as we already rely on parent
defer func() { cancel(errors.WithStack(context.Canceled)) }()
nodes, err := b.LoadNodes(timeoutCtx, builder.WithData()) nodes, err := b.LoadNodes(timeoutCtx, builder.WithData())
if in.bootstrap { if in.bootstrap {

View File

@@ -18,6 +18,7 @@ import (
"github.com/docker/cli/cli" "github.com/docker/cli/cli"
"github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/formatter" "github.com/docker/cli/cli/command/formatter"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
) )
@@ -57,8 +58,9 @@ func runLs(ctx context.Context, dockerCli command.Cli, in lsOptions) error {
return err return err
} }
timeoutCtx, cancel := context.WithTimeout(ctx, 20*time.Second) timeoutCtx, cancel := context.WithCancelCause(ctx)
defer cancel() timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 20*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet,lostcancel // no need to manually cancel this context as we already rely on parent
defer func() { cancel(errors.WithStack(context.Canceled)) }()
eg, _ := errgroup.WithContext(timeoutCtx) eg, _ := errgroup.WithContext(timeoutCtx)
for _, b := range builders { for _, b := range builders {
@@ -319,7 +321,7 @@ func (tp truncatedPlatforms) String() string {
if tpf, ok := tp.res[mpf]; ok { if tpf, ok := tp.res[mpf]; ok {
seen[mpf] = struct{}{} seen[mpf] = struct{}{}
if len(tpf) == 1 { if len(tpf) == 1 {
out = append(out, fmt.Sprintf("%s", tpf[0])) out = append(out, tpf[0])
count++ count++
} else { } else {
hasPreferredPlatform := false hasPreferredPlatform := false
@@ -347,7 +349,7 @@ func (tp truncatedPlatforms) String() string {
continue continue
} }
if len(tp.res[mpf]) == 1 { if len(tp.res[mpf]) == 1 {
out = append(out, fmt.Sprintf("%s", tp.res[mpf][0])) out = append(out, tp.res[mpf][0])
count++ count++
} else { } else {
hasPreferredPlatform := false hasPreferredPlatform := false

View File

@@ -150,8 +150,9 @@ func rmAllInactive(ctx context.Context, txn *store.Txn, dockerCli command.Cli, i
return err return err
} }
timeoutCtx, cancel := context.WithTimeout(ctx, 20*time.Second) timeoutCtx, cancel := context.WithCancelCause(ctx)
defer cancel() timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 20*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet,lostcancel // no need to manually cancel this context as we already rely on parent
defer func() { cancel(errors.WithStack(context.Canceled)) }()
eg, _ := errgroup.WithContext(timeoutCtx) eg, _ := errgroup.WithContext(timeoutCtx)
for _, b := range builders { for _, b := range builders {

View File

@@ -46,7 +46,6 @@ func runUse(dockerCli command.Cli, in useOptions) error {
return errors.Errorf("run `docker context use %s` to switch to context %s", in.builder, in.builder) return errors.Errorf("run `docker context use %s` to switch to context %s", in.builder, in.builder)
} }
} }
} }
return errors.Wrapf(err, "failed to find instance %q", in.builder) return errors.Wrapf(err, "failed to find instance %q", in.builder)
} }

View File

@@ -93,7 +93,7 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in *controllerapi.Buil
} }
opts.Session = append(opts.Session, ssh) opts.Session = append(opts.Session, ssh)
outputs, err := controllerapi.CreateExports(in.Exports) outputs, _, err := controllerapi.CreateExports(in.Exports)
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }

View File

@@ -109,7 +109,7 @@ func (b *localController) Invoke(ctx context.Context, sessionID string, pid stri
// Attach containerIn to this process // Attach containerIn to this process
ioCancelledCh := make(chan struct{}) ioCancelledCh := make(chan struct{})
proc.ForwardIO(&ioset.In{Stdin: ioIn, Stdout: ioOut, Stderr: ioErr}, func() { close(ioCancelledCh) }) proc.ForwardIO(&ioset.In{Stdin: ioIn, Stdout: ioOut, Stderr: ioErr}, func(error) { close(ioCancelledCh) })
select { select {
case <-ioCancelledCh: case <-ioCancelledCh:
@@ -117,7 +117,7 @@ func (b *localController) Invoke(ctx context.Context, sessionID string, pid stri
case err := <-proc.Done(): case err := <-proc.Done():
return err return err
case <-ctx.Done(): case <-ctx.Done():
return ctx.Err() return context.Cause(ctx)
} }
} }

View File

@@ -10,15 +10,16 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
func CreateExports(entries []*ExportEntry) ([]client.ExportEntry, error) { func CreateExports(entries []*ExportEntry) ([]client.ExportEntry, []string, error) {
var outs []client.ExportEntry var outs []client.ExportEntry
var localPaths []string
if len(entries) == 0 { if len(entries) == 0 {
return nil, nil return nil, nil, nil
} }
var stdoutUsed bool var stdoutUsed bool
for _, entry := range entries { for _, entry := range entries {
if entry.Type == "" { if entry.Type == "" {
return nil, errors.Errorf("type is required for output") return nil, nil, errors.Errorf("type is required for output")
} }
out := client.ExportEntry{ out := client.ExportEntry{
@@ -49,20 +50,21 @@ func CreateExports(entries []*ExportEntry) ([]client.ExportEntry, error) {
if supportDir { if supportDir {
if entry.Destination == "" { if entry.Destination == "" {
return nil, errors.Errorf("dest is required for %s exporter", out.Type) return nil, nil, errors.Errorf("dest is required for %s exporter", out.Type)
} }
if entry.Destination == "-" { if entry.Destination == "-" {
return nil, errors.Errorf("dest cannot be stdout for %s exporter", out.Type) return nil, nil, errors.Errorf("dest cannot be stdout for %s exporter", out.Type)
} }
fi, err := os.Stat(entry.Destination) fi, err := os.Stat(entry.Destination)
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {
return nil, errors.Wrapf(err, "invalid destination directory: %s", entry.Destination) return nil, nil, errors.Wrapf(err, "invalid destination directory: %s", entry.Destination)
} }
if err == nil && !fi.IsDir() { if err == nil && !fi.IsDir() {
return nil, errors.Errorf("destination directory %s is a file", entry.Destination) return nil, nil, errors.Errorf("destination directory %s is a file", entry.Destination)
} }
out.OutputDir = entry.Destination out.OutputDir = entry.Destination
localPaths = append(localPaths, entry.Destination)
} }
if supportFile { if supportFile {
if entry.Destination == "" && out.Type != client.ExporterDocker { if entry.Destination == "" && out.Type != client.ExporterDocker {
@@ -70,32 +72,33 @@ func CreateExports(entries []*ExportEntry) ([]client.ExportEntry, error) {
} }
if entry.Destination == "-" { if entry.Destination == "-" {
if stdoutUsed { if stdoutUsed {
return nil, errors.Errorf("multiple outputs configured to write to stdout") return nil, nil, errors.Errorf("multiple outputs configured to write to stdout")
} }
if _, err := console.ConsoleFromFile(os.Stdout); err == nil { if _, err := console.ConsoleFromFile(os.Stdout); err == nil {
return nil, errors.Errorf("dest file is required for %s exporter. refusing to write to console", out.Type) return nil, nil, errors.Errorf("dest file is required for %s exporter. refusing to write to console", out.Type)
} }
out.Output = wrapWriteCloser(os.Stdout) out.Output = wrapWriteCloser(os.Stdout)
stdoutUsed = true stdoutUsed = true
} else if entry.Destination != "" { } else if entry.Destination != "" {
fi, err := os.Stat(entry.Destination) fi, err := os.Stat(entry.Destination)
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {
return nil, errors.Wrapf(err, "invalid destination file: %s", entry.Destination) return nil, nil, errors.Wrapf(err, "invalid destination file: %s", entry.Destination)
} }
if err == nil && fi.IsDir() { if err == nil && fi.IsDir() {
return nil, errors.Errorf("destination file %s is a directory", entry.Destination) return nil, nil, errors.Errorf("destination file %s is a directory", entry.Destination)
} }
f, err := os.Create(entry.Destination) f, err := os.Create(entry.Destination)
if err != nil { if err != nil {
return nil, errors.Errorf("failed to open %s", err) return nil, nil, errors.Errorf("failed to open %s", err)
} }
out.Output = wrapWriteCloser(f) out.Output = wrapWriteCloser(f)
localPaths = append(localPaths, entry.Destination)
} }
} }
outs = append(outs, out) outs = append(outs, out)
} }
return outs, nil return outs, localPaths, nil
} }
func wrapWriteCloser(wc io.WriteCloser) func(map[string]string) (io.WriteCloser, error) { func wrapWriteCloser(wc io.WriteCloser) func(map[string]string) (io.WriteCloser, error) {

View File

@@ -153,7 +153,6 @@ func ResolveOptionPaths(options *BuildOptions) (_ *BuildOptions, err error) {
} }
} }
ps = append(ps, p) ps = append(ps, p)
} }
s.Paths = ps s.Paths = ps
ssh = append(ssh, s) ssh = append(ssh, s)

View File

@@ -22,9 +22,7 @@ func (w *writer) Write(status *client.SolveStatus) {
w.ch <- ToControlStatus(status) w.ch <- ToControlStatus(status)
} }
func (w *writer) WriteBuildRef(target string, ref string) { func (w *writer) WriteBuildRef(target string, ref string) {}
return
}
func (w *writer) ValidateLogSource(digest.Digest, interface{}) bool { func (w *writer) ValidateLogSource(digest.Digest, interface{}) bool {
return true return true

View File

@@ -18,16 +18,16 @@ type Process struct {
invokeConfig *pb.InvokeConfig invokeConfig *pb.InvokeConfig
errCh chan error errCh chan error
processCancel func() processCancel func()
serveIOCancel func() serveIOCancel func(error)
} }
// ForwardIO forwards process's io to the specified reader/writer. // ForwardIO forwards process's io to the specified reader/writer.
// Optionally specify ioCancelCallback which will be called when // Optionally specify ioCancelCallback which will be called when
// the process closes the specified IO. This will be useful for additional cleanup. // the process closes the specified IO. This will be useful for additional cleanup.
func (p *Process) ForwardIO(in *ioset.In, ioCancelCallback func()) { func (p *Process) ForwardIO(in *ioset.In, ioCancelCallback func(error)) {
p.inEnd.SetIn(in) p.inEnd.SetIn(in)
if f := p.serveIOCancel; f != nil { if f := p.serveIOCancel; f != nil {
f() f(errors.WithStack(context.Canceled))
} }
p.serveIOCancel = ioCancelCallback p.serveIOCancel = ioCancelCallback
} }
@@ -124,9 +124,16 @@ func (m *Manager) StartProcess(pid string, resultCtx *build.ResultHandle, cfg *p
f.SetOut(&out) f.SetOut(&out)
// Register process // Register process
ctx, cancel := context.WithCancel(context.TODO()) ctx, cancel := context.WithCancelCause(context.TODO())
var cancelOnce sync.Once var cancelOnce sync.Once
processCancelFunc := func() { cancelOnce.Do(func() { cancel(); f.Close(); in.Close(); out.Close() }) } processCancelFunc := func() {
cancelOnce.Do(func() {
cancel(errors.WithStack(context.Canceled))
f.Close()
in.Close()
out.Close()
})
}
p := &Process{ p := &Process{
inEnd: f, inEnd: f,
invokeConfig: cfg, invokeConfig: cfg,

View File

@@ -62,9 +62,10 @@ func NewRemoteBuildxController(ctx context.Context, dockerCli command.Cli, opts
serverRoot := filepath.Join(rootDir, "shared") serverRoot := filepath.Join(rootDir, "shared")
// connect to buildx server if it is already running // connect to buildx server if it is already running
ctx2, cancel := context.WithTimeout(ctx, 1*time.Second) ctx2, cancel := context.WithCancelCause(ctx)
ctx2, _ = context.WithTimeoutCause(ctx2, 1*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet,lostcancel // no need to manually cancel this context as we already rely on parent
c, err := newBuildxClientAndCheck(ctx2, filepath.Join(serverRoot, defaultSocketFilename)) c, err := newBuildxClientAndCheck(ctx2, filepath.Join(serverRoot, defaultSocketFilename))
cancel() cancel(errors.WithStack(context.Canceled))
if err != nil { if err != nil {
if !errors.Is(err, context.DeadlineExceeded) { if !errors.Is(err, context.DeadlineExceeded) {
return nil, errors.Wrap(err, "cannot connect to the buildx server") return nil, errors.Wrap(err, "cannot connect to the buildx server")
@@ -90,9 +91,10 @@ func NewRemoteBuildxController(ctx context.Context, dockerCli command.Cli, opts
go wait() go wait()
// wait for buildx server to be ready // wait for buildx server to be ready
ctx2, cancel = context.WithTimeout(ctx, 10*time.Second) ctx2, cancel = context.WithCancelCause(ctx)
ctx2, _ = context.WithTimeoutCause(ctx2, 10*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet,lostcancel // no need to manually cancel this context as we already rely on parent
c, err = newBuildxClientAndCheck(ctx2, filepath.Join(serverRoot, defaultSocketFilename)) c, err = newBuildxClientAndCheck(ctx2, filepath.Join(serverRoot, defaultSocketFilename))
cancel() cancel(errors.WithStack(context.Canceled))
if err != nil { if err != nil {
return errors.Wrap(err, "cannot connect to the buildx server") return errors.Wrap(err, "cannot connect to the buildx server")
} }

View File

@@ -302,7 +302,6 @@ func attachIO(ctx context.Context, stream msgStream, initMessage *pb.InitMessage
out = cfg.stderr out = cfg.stderr
default: default:
return errors.Errorf("unsupported fd %d", file.Fd) return errors.Errorf("unsupported fd %d", file.Fd)
} }
if out == nil { if out == nil {
logrus.Warnf("attachIO: no writer for fd %d", file.Fd) logrus.Warnf("attachIO: no writer for fd %d", file.Fd)
@@ -345,7 +344,7 @@ func receive(ctx context.Context, stream msgStream) (*pb.Message, error) {
case err := <-errCh: case err := <-errCh:
return nil, err return nil, err
case <-ctx.Done(): case <-ctx.Done():
return nil, ctx.Err() return nil, context.Cause(ctx)
} }
} }

View File

@@ -37,7 +37,7 @@ type Server struct {
type session struct { type session struct {
buildOnGoing atomic.Bool buildOnGoing atomic.Bool
statusChan chan *pb.StatusResponse statusChan chan *pb.StatusResponse
cancelBuild func() cancelBuild func(error)
buildOptions *pb.BuildOptions buildOptions *pb.BuildOptions
inputPipe *io.PipeWriter inputPipe *io.PipeWriter
@@ -109,7 +109,7 @@ func (m *Server) Disconnect(ctx context.Context, req *pb.DisconnectRequest) (res
m.sessionMu.Lock() m.sessionMu.Lock()
if s, ok := m.session[sessionID]; ok { if s, ok := m.session[sessionID]; ok {
if s.cancelBuild != nil { if s.cancelBuild != nil {
s.cancelBuild() s.cancelBuild(errors.WithStack(context.Canceled))
} }
s.cancelRunningProcesses() s.cancelRunningProcesses()
if s.result != nil { if s.result != nil {
@@ -127,7 +127,7 @@ func (m *Server) Close() error {
for k := range m.session { for k := range m.session {
if s, ok := m.session[k]; ok { if s, ok := m.session[k]; ok {
if s.cancelBuild != nil { if s.cancelBuild != nil {
s.cancelBuild() s.cancelBuild(errors.WithStack(context.Canceled))
} }
s.cancelRunningProcesses() s.cancelRunningProcesses()
} }
@@ -199,8 +199,8 @@ func (m *Server) Build(ctx context.Context, req *pb.BuildRequest) (*pb.BuildResp
pw := pb.NewProgressWriter(statusChan) pw := pb.NewProgressWriter(statusChan)
// Build the specified request // Build the specified request
ctx, cancel := context.WithCancel(ctx) ctx, cancel := context.WithCancelCause(ctx)
defer cancel() defer func() { cancel(errors.WithStack(context.Canceled)) }()
resp, res, _, buildErr := m.buildFunc(ctx, req.Options, inR, pw) resp, res, _, buildErr := m.buildFunc(ctx, req.Options, inR, pw)
m.sessionMu.Lock() m.sessionMu.Lock()
if s, ok := m.session[sessionID]; ok { if s, ok := m.session[sessionID]; ok {
@@ -341,7 +341,7 @@ func (m *Server) Input(stream pb.Controller_InputServer) (err error) {
select { select {
case msg = <-msgCh: case msg = <-msgCh:
case <-ctx.Done(): case <-ctx.Done():
return errors.Wrap(ctx.Err(), "canceled") return context.Cause(ctx)
} }
if msg == nil { if msg == nil {
return nil return nil
@@ -370,9 +370,9 @@ func (m *Server) Invoke(srv pb.Controller_InvokeServer) error {
initDoneCh := make(chan *processes.Process) initDoneCh := make(chan *processes.Process)
initErrCh := make(chan error) initErrCh := make(chan error)
eg, egCtx := errgroup.WithContext(context.TODO()) eg, egCtx := errgroup.WithContext(context.TODO())
srvIOCtx, srvIOCancel := context.WithCancel(egCtx) srvIOCtx, srvIOCancel := context.WithCancelCause(egCtx)
eg.Go(func() error { eg.Go(func() error {
defer srvIOCancel() defer srvIOCancel(errors.WithStack(context.Canceled))
return serveIO(srvIOCtx, srv, func(initMessage *pb.InitMessage) (retErr error) { return serveIO(srvIOCtx, srv, func(initMessage *pb.InitMessage) (retErr error) {
defer func() { defer func() {
if retErr != nil { if retErr != nil {
@@ -418,7 +418,7 @@ func (m *Server) Invoke(srv pb.Controller_InvokeServer) error {
}) })
}) })
eg.Go(func() (rErr error) { eg.Go(func() (rErr error) {
defer srvIOCancel() defer srvIOCancel(errors.WithStack(context.Canceled))
// Wait for init done // Wait for init done
var proc *processes.Process var proc *processes.Process
select { select {

View File

@@ -41,11 +41,15 @@ target "lint" {
platforms = GOLANGCI_LINT_MULTIPLATFORM != "" ? [ platforms = GOLANGCI_LINT_MULTIPLATFORM != "" ? [
"darwin/amd64", "darwin/amd64",
"darwin/arm64", "darwin/arm64",
"freebsd/amd64",
"freebsd/arm64",
"linux/amd64", "linux/amd64",
"linux/arm64", "linux/arm64",
"linux/s390x", "linux/s390x",
"linux/ppc64le", "linux/ppc64le",
"linux/riscv64", "linux/riscv64",
"openbsd/amd64",
"openbsd/arm64",
"windows/amd64", "windows/amd64",
"windows/arm64" "windows/arm64"
] : [] ] : []
@@ -154,6 +158,8 @@ target "binaries-cross" {
platforms = [ platforms = [
"darwin/amd64", "darwin/amd64",
"darwin/arm64", "darwin/arm64",
"freebsd/amd64",
"freebsd/arm64",
"linux/amd64", "linux/amd64",
"linux/arm/v6", "linux/arm/v6",
"linux/arm/v7", "linux/arm/v7",
@@ -161,6 +167,8 @@ target "binaries-cross" {
"linux/ppc64le", "linux/ppc64le",
"linux/riscv64", "linux/riscv64",
"linux/s390x", "linux/s390x",
"openbsd/amd64",
"openbsd/arm64",
"windows/amd64", "windows/amd64",
"windows/arm64" "windows/arm64"
] ]

View File

@@ -359,6 +359,21 @@ target "app" {
} }
``` ```
### `target.call`
Specifies the frontend method to use. Frontend methods let you, for example,
execute build checks only, instead of running a build. This is the same as the
`--call` flag.
```hcl
target "app" {
call = "check"
}
```
For more information about frontend methods, refer to the CLI reference for
[`docker buildx build --call`](https://docs.docker.com/reference/cli/docker/buildx/build/#call).
### `target.context` ### `target.context`
Specifies the location of the build context to use for this target. Specifies the location of the build context to use for this target.

View File

@@ -177,7 +177,6 @@ func (d *Driver) create(ctx context.Context, l progress.SubLogger) error {
break break
} }
} }
} }
_, err := d.DockerAPI.ContainerCreate(ctx, cfg, hc, &network.NetworkingConfig{}, nil, d.Name) _, err := d.DockerAPI.ContainerCreate(ctx, cfg, hc, &network.NetworkingConfig{}, nil, d.Name)
if err != nil && !errdefs.IsConflict(err) { if err != nil && !errdefs.IsConflict(err) {
@@ -213,7 +212,7 @@ func (d *Driver) wait(ctx context.Context, l progress.SubLogger) error {
} }
select { select {
case <-ctx.Done(): case <-ctx.Done():
return ctx.Err() return context.Cause(ctx)
case <-time.After(time.Duration(try*120) * time.Millisecond): case <-time.After(time.Duration(try*120) * time.Millisecond):
try++ try++
continue continue

View File

@@ -29,7 +29,7 @@ func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error {
func (d *Driver) Info(ctx context.Context) (*driver.Info, error) { func (d *Driver) Info(ctx context.Context) (*driver.Info, error) {
_, err := d.DockerAPI.ServerVersion(ctx) _, err := d.DockerAPI.ServerVersion(ctx)
if err != nil { if err != nil {
return nil, errors.Wrapf(driver.ErrNotConnecting{}, err.Error()) return nil, errors.Wrap(driver.ErrNotConnecting{}, err.Error())
} }
return &driver.Info{ return &driver.Info{
Status: driver.Running, Status: driver.Running,
@@ -39,7 +39,7 @@ func (d *Driver) Info(ctx context.Context) (*driver.Info, error) {
func (d *Driver) Version(ctx context.Context) (string, error) { func (d *Driver) Version(ctx context.Context) (string, error) {
v, err := d.DockerAPI.ServerVersion(ctx) v, err := d.DockerAPI.ServerVersion(ctx)
if err != nil { if err != nil {
return "", errors.Wrapf(driver.ErrNotConnecting{}, err.Error()) return "", errors.Wrap(driver.ErrNotConnecting{}, err.Error())
} }
if bkversion, _ := resolveBuildKitVersion(v.Version); bkversion != "" { if bkversion, _ := resolveBuildKitVersion(v.Version); bkversion != "" {
return bkversion, nil return bkversion, nil

View File

@@ -176,11 +176,6 @@ func resolveBuildKitVersion(ver string) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
//if _, errs := c.Validate(mobyVersion); len(errs) > 0 {
// for _, err := range errs {
// fmt.Printf("%s: %v\n", m.MobyVersionConstraint, err)
// }
//}
if !c.Check(mobyVersion) { if !c.Check(mobyVersion) {
continue continue
} }

View File

@@ -191,7 +191,7 @@ func checkClientConfig(t *testing.T, ep Endpoint, server, namespace string, ca,
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, proxyURLString, proxyURL.String()) assert.Equal(t, proxyURLString, proxyURL.String())
} else { } else {
assert.True(t, cfg.Proxy == nil, "expected proxy to be nil, but is not nil instead") assert.Nil(t, cfg.Proxy, "expected proxy to be nil, but is not nil instead")
} }
} }
@@ -224,7 +224,7 @@ func TestSaveLoadGKEConfig(t *testing.T) {
persistedMetadata, err := store.GetMetadata("gke-context") persistedMetadata, err := store.GetMetadata("gke-context")
require.NoError(t, err) require.NoError(t, err)
persistedEPMeta := EndpointFromContext(persistedMetadata) persistedEPMeta := EndpointFromContext(persistedMetadata)
assert.True(t, persistedEPMeta != nil) assert.NotNil(t, persistedEPMeta)
persistedEP, err := persistedEPMeta.WithTLSData(store, "gke-context") persistedEP, err := persistedEPMeta.WithTLSData(store, "gke-context")
require.NoError(t, err) require.NoError(t, err)
persistedCfg := persistedEP.KubernetesConfig() persistedCfg := persistedEP.KubernetesConfig()
@@ -249,7 +249,7 @@ func TestSaveLoadEKSConfig(t *testing.T) {
persistedMetadata, err := store.GetMetadata("eks-context") persistedMetadata, err := store.GetMetadata("eks-context")
require.NoError(t, err) require.NoError(t, err)
persistedEPMeta := EndpointFromContext(persistedMetadata) persistedEPMeta := EndpointFromContext(persistedMetadata)
assert.True(t, persistedEPMeta != nil) assert.NotNil(t, persistedEPMeta)
persistedEP, err := persistedEPMeta.WithTLSData(store, "eks-context") persistedEP, err := persistedEPMeta.WithTLSData(store, "eks-context")
require.NoError(t, err) require.NoError(t, err)
persistedCfg := persistedEP.KubernetesConfig() persistedCfg := persistedEP.KubernetesConfig()
@@ -274,14 +274,14 @@ func TestSaveLoadK3SConfig(t *testing.T) {
persistedMetadata, err := store.GetMetadata("k3s-context") persistedMetadata, err := store.GetMetadata("k3s-context")
require.NoError(t, err) require.NoError(t, err)
persistedEPMeta := EndpointFromContext(persistedMetadata) persistedEPMeta := EndpointFromContext(persistedMetadata)
assert.True(t, persistedEPMeta != nil) assert.NotNil(t, persistedEPMeta)
persistedEP, err := persistedEPMeta.WithTLSData(store, "k3s-context") persistedEP, err := persistedEPMeta.WithTLSData(store, "k3s-context")
require.NoError(t, err) require.NoError(t, err)
persistedCfg := persistedEP.KubernetesConfig() persistedCfg := persistedEP.KubernetesConfig()
actualCfg, err := persistedCfg.ClientConfig() actualCfg, err := persistedCfg.ClientConfig()
require.NoError(t, err) require.NoError(t, err)
assert.True(t, len(actualCfg.Username) > 0) assert.Greater(t, len(actualCfg.Username), 0)
assert.True(t, len(actualCfg.Password) > 0) assert.Greater(t, len(actualCfg.Password), 0)
assert.Equal(t, expectedCfg.Username, actualCfg.Username) assert.Equal(t, expectedCfg.Username, actualCfg.Username)
assert.Equal(t, expectedCfg.Password, actualCfg.Password) assert.Equal(t, expectedCfg.Password, actualCfg.Password)
} }

View File

@@ -112,7 +112,7 @@ func (d *Driver) wait(ctx context.Context) error {
for { for {
select { select {
case <-ctx.Done(): case <-ctx.Done():
return ctx.Err() return context.Cause(ctx)
case <-timeoutChan: case <-timeoutChan:
return err return err
case <-ticker.C: case <-ticker.C:

View File

@@ -47,8 +47,9 @@ func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error {
return err return err
} }
return progress.Wrap("[internal] waiting for connection", l, func(_ progress.SubLogger) error { return progress.Wrap("[internal] waiting for connection", l, func(_ progress.SubLogger) error {
ctx, cancel := context.WithTimeout(ctx, 20*time.Second) cancelCtx, cancel := context.WithCancelCause(ctx)
defer cancel() ctx, _ := context.WithTimeoutCause(cancelCtx, 20*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet,lostcancel // no need to manually cancel this context as we already rely on parent
defer func() { cancel(errors.WithStack(context.Canceled)) }()
return c.Wait(ctx) return c.Wait(ctx)
}) })
} }

57
go.mod
View File

@@ -6,19 +6,19 @@ require (
github.com/Masterminds/semver/v3 v3.2.1 github.com/Masterminds/semver/v3 v3.2.1
github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/go-winio v0.6.2
github.com/aws/aws-sdk-go-v2/config v1.26.6 github.com/aws/aws-sdk-go-v2/config v1.26.6
github.com/compose-spec/compose-go/v2 v2.4.1 github.com/compose-spec/compose-go/v2 v2.4.4
github.com/containerd/console v1.0.4 github.com/containerd/console v1.0.4
github.com/containerd/containerd v1.7.22 github.com/containerd/containerd v1.7.24
github.com/containerd/continuity v0.4.4 github.com/containerd/continuity v0.4.5
github.com/containerd/errdefs v0.1.0 github.com/containerd/errdefs v0.3.0
github.com/containerd/log v0.1.0 github.com/containerd/log v0.1.0
github.com/containerd/platforms v0.2.1 github.com/containerd/platforms v0.2.1
github.com/containerd/typeurl/v2 v2.2.0 github.com/containerd/typeurl/v2 v2.2.3
github.com/creack/pty v1.1.21 github.com/creack/pty v1.1.21
github.com/distribution/reference v0.6.0 github.com/distribution/reference v0.6.0
github.com/docker/cli v27.3.1+incompatible github.com/docker/cli v27.4.0-rc.2+incompatible
github.com/docker/cli-docs-tool v0.8.0 github.com/docker/cli-docs-tool v0.8.0
github.com/docker/docker v27.3.1+incompatible github.com/docker/docker v27.4.0-rc.2+incompatible
github.com/docker/go-units v0.5.0 github.com/docker/go-units v0.5.0
github.com/gofrs/flock v0.12.1 github.com/gofrs/flock v0.12.1
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
@@ -27,7 +27,7 @@ require (
github.com/hashicorp/hcl/v2 v2.20.1 github.com/hashicorp/hcl/v2 v2.20.1
github.com/in-toto/in-toto-golang v0.5.0 github.com/in-toto/in-toto-golang v0.5.0
github.com/mitchellh/hashstructure/v2 v2.0.2 github.com/mitchellh/hashstructure/v2 v2.0.2
github.com/moby/buildkit v0.17.0 github.com/moby/buildkit v0.18.0
github.com/moby/sys/mountinfo v0.7.2 github.com/moby/sys/mountinfo v0.7.2
github.com/moby/sys/signal v0.7.1 github.com/moby/sys/signal v0.7.1
github.com/morikuni/aec v1.0.0 github.com/morikuni/aec v1.0.0
@@ -41,19 +41,19 @@ require (
github.com/spf13/cobra v1.8.1 github.com/spf13/cobra v1.8.1
github.com/spf13/pflag v1.0.5 github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.9.0 github.com/stretchr/testify v1.9.0
github.com/tonistiigi/fsutil v0.0.0-20241028165955-397af5306b5c github.com/tonistiigi/fsutil v0.0.0-20241121093142-31cf1f437184
github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4 github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4
github.com/zclconf/go-cty v1.14.4 github.com/zclconf/go-cty v1.14.4
go.opentelemetry.io/otel v1.21.0 go.opentelemetry.io/otel v1.28.0
go.opentelemetry.io/otel/metric v1.21.0 go.opentelemetry.io/otel/metric v1.28.0
go.opentelemetry.io/otel/sdk v1.21.0 go.opentelemetry.io/otel/sdk v1.28.0
go.opentelemetry.io/otel/trace v1.21.0 go.opentelemetry.io/otel/trace v1.28.0
golang.org/x/mod v0.21.0 golang.org/x/mod v0.21.0
golang.org/x/sync v0.8.0 golang.org/x/sync v0.8.0
golang.org/x/sys v0.26.0 golang.org/x/sys v0.26.0
golang.org/x/term v0.24.0 golang.org/x/term v0.24.0
golang.org/x/text v0.18.0 golang.org/x/text v0.18.0
google.golang.org/grpc v1.66.2 google.golang.org/grpc v1.66.3
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1
google.golang.org/protobuf v1.35.1 google.golang.org/protobuf v1.35.1
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
@@ -82,7 +82,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 // indirect
github.com/aws/smithy-go v1.19.0 // indirect github.com/aws/smithy-go v1.19.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/containerd/containerd/api v1.7.19 // indirect github.com/containerd/containerd/api v1.7.19 // indirect
github.com/containerd/ttrpc v1.2.5 // indirect github.com/containerd/ttrpc v1.2.5 // indirect
@@ -96,7 +96,7 @@ require (
github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fvbommel/sortorder v1.0.1 // indirect github.com/fvbommel/sortorder v1.0.1 // indirect
github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect
@@ -109,7 +109,7 @@ require (
github.com/google/gofuzz v1.2.0 // indirect github.com/google/gofuzz v1.2.0 // indirect
github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/mux v1.8.1 // indirect
github.com/gorilla/websocket v1.5.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect
@@ -121,7 +121,6 @@ require (
github.com/mailru/easyjson v0.7.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mattn/go-shellwords v1.0.12 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/miekg/pkcs11 v1.1.1 // indirect github.com/miekg/pkcs11 v1.1.1 // indirect
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect
@@ -138,9 +137,9 @@ require (
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.17.0 // indirect github.com/prometheus/client_golang v1.20.2 // indirect
github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect
github.com/rivo/uniseg v0.2.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect
@@ -155,14 +154,14 @@ require (
github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.46.1 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.46.1 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.44.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.44.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.21.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.28.0 // indirect
go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect
golang.org/x/crypto v0.27.0 // indirect golang.org/x/crypto v0.27.0 // indirect
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
golang.org/x/net v0.29.0 // indirect golang.org/x/net v0.29.0 // indirect
@@ -170,8 +169,8 @@ require (
golang.org/x/time v0.6.0 // indirect golang.org/x/time v0.6.0 // indirect
golang.org/x/tools v0.25.0 // indirect golang.org/x/tools v0.25.0 // indirect
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/klog/v2 v2.110.1 // indirect k8s.io/klog/v2 v2.110.1 // indirect

130
go.sum
View File

@@ -14,8 +14,8 @@ 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/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.12.5 h1:bpTInLlDy/nDRWFVcefDZZ1+U8tS+rz3MxjKgu9boo0= github.com/Microsoft/hcsshim v0.12.8 h1:BtDWYlFMcWhorrvSSo2M7z0csPdw6t7no/C3FsSvqiI=
github.com/Microsoft/hcsshim v0.12.5/go.mod h1:tIUGego4G1EN5Hb6KC90aDYiUI2dqLSTTOCjVNpOgZ8= github.com/Microsoft/hcsshim v0.12.8/go.mod h1:cibQ4BqhJ32FXDwPdQhKhwrwophnh3FuT4nwQZF907w=
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-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 h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs=
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
@@ -73,8 +73,8 @@ github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembj
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o=
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004 h1:lkAMpLVBDaj17e85keuznYcH5rqI438v41pKcBl4ZxQ= github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004 h1:lkAMpLVBDaj17e85keuznYcH5rqI438v41pKcBl4ZxQ=
@@ -83,21 +83,21 @@ github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnTh
github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE= 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/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4=
github.com/compose-spec/compose-go/v2 v2.4.1 h1:tEg6Qn/9LZnKg42fZlFmxN4lxSqnCvsiG5TXnxzvI4c= github.com/compose-spec/compose-go/v2 v2.4.4 h1:cvHBl5Jf1iNBmRrZCICmHvaoskYc1etTPEMLKVwokAY=
github.com/compose-spec/compose-go/v2 v2.4.1/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/compose-spec/compose-go/v2 v2.4.4/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc=
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0=
github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE= github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0=
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
github.com/containerd/containerd v1.7.22 h1:nZuNnNRA6T6jB975rx2RRNqqH2k6ELYKDZfqTHqwyy0= github.com/containerd/containerd v1.7.24 h1:zxszGrGjrra1yYJW/6rhm9cJ1ZQ8rkKBR48brqsa7nA=
github.com/containerd/containerd v1.7.22/go.mod h1:e3Jz1rYRUZ2Lt51YrH9Rz0zPyJBOlSvB3ghr2jbVD8g= github.com/containerd/containerd v1.7.24/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw=
github.com/containerd/containerd/api v1.7.19 h1:VWbJL+8Ap4Ju2mx9c9qS1uFSB1OVYr5JJrW2yT5vFoA= github.com/containerd/containerd/api v1.7.19 h1:VWbJL+8Ap4Ju2mx9c9qS1uFSB1OVYr5JJrW2yT5vFoA=
github.com/containerd/containerd/api v1.7.19/go.mod h1:fwGavl3LNwAV5ilJ0sbrABL44AQxmNjDRcwheXDb6Ig= github.com/containerd/containerd/api v1.7.19/go.mod h1:fwGavl3LNwAV5ilJ0sbrABL44AQxmNjDRcwheXDb6Ig=
github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII= github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
github.com/containerd/continuity v0.4.4/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM= github.com/containerd/errdefs v0.3.0 h1:FSZgGOeK4yuT/+DnF07/Olde/q4KBoMsaamhXxIMDp4=
github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0= github.com/containerd/errdefs v0.3.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY= github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY=
github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o= 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 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
@@ -111,8 +111,8 @@ github.com/containerd/stargz-snapshotter/estargz v0.15.1 h1:eXJjw9RbkLFgioVaTG+G
github.com/containerd/stargz-snapshotter/estargz v0.15.1/go.mod h1:gr2RNwukQ/S9Nv33Lt6UC7xEx58C+LHRdoqbEKjz1Kk= github.com/containerd/stargz-snapshotter/estargz v0.15.1/go.mod h1:gr2RNwukQ/S9Nv33Lt6UC7xEx58C+LHRdoqbEKjz1Kk=
github.com/containerd/ttrpc v1.2.5 h1:IFckT1EFQoFBMG4c3sMdT8EP3/aKfumK1msY+Ze4oLU= github.com/containerd/ttrpc v1.2.5 h1:IFckT1EFQoFBMG4c3sMdT8EP3/aKfumK1msY+Ze4oLU=
github.com/containerd/ttrpc v1.2.5/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= github.com/containerd/ttrpc v1.2.5/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso= github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40=
github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g= github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
@@ -125,15 +125,15 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/cli v27.3.1+incompatible h1:qEGdFBF3Xu6SCvCYhc7CzaQTlBmqDuzxPDpigSyeKQQ= github.com/docker/cli v27.4.0-rc.2+incompatible h1:A0GZwegDlt2wdt3tpmrUzkVOZmbhvd7i05wPSf7Oo74=
github.com/docker/cli v27.3.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v27.4.0-rc.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli-docs-tool v0.8.0 h1:YcDWl7rQJC3lJ7WVZRwSs3bc9nka97QLWfyJQli8yJU= github.com/docker/cli-docs-tool v0.8.0 h1:YcDWl7rQJC3lJ7WVZRwSs3bc9nka97QLWfyJQli8yJU=
github.com/docker/cli-docs-tool v0.8.0/go.mod h1:8TQQ3E7mOXoYUs811LiPdUnAhXrcVsBIrW21a5pUbdk= github.com/docker/cli-docs-tool v0.8.0/go.mod h1:8TQQ3E7mOXoYUs811LiPdUnAhXrcVsBIrW21a5pUbdk=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI= github.com/docker/docker v27.4.0-rc.2+incompatible h1:9OJjVGtelk/zGC3TyKweJ29b9Axzh0s/0vtU4mneumE=
github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v27.4.0-rc.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo=
github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0= github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
@@ -166,8 +166,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
@@ -192,8 +192,6 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4=
github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -228,8 +226,8 @@ github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWS
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@@ -279,6 +277,8 @@ 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.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 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/lib/pq v0.0.0-20150723085316-0dad96c0b94f/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= 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 h1:C8fxWnhYyME3n0klPOhVM7PtYUB3eV1W3DeFmN3j53Y=
github.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
@@ -290,8 +290,6 @@ github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebG
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mattn/go-sqlite3 v1.6.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.6.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
@@ -303,8 +301,8 @@ github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/z
github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 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 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/moby/buildkit v0.17.0 h1:ZA/4AxwBbve1f3ZaNNJQiCBtTV62R6YweWNwq4A+sTc= github.com/moby/buildkit v0.18.0 h1:KSelhNINJcNA3FCWBbGCytvicjP+kjU5kZlZhkTUkVo=
github.com/moby/buildkit v0.17.0/go.mod h1:ru8NFyDHD8HbuKaLXJIjK9nr3x6FZR+IWjtF07S+wdM= github.com/moby/buildkit v0.18.0/go.mod h1:vCR5CX8NGsPTthTg681+9kdmfvkvqJBXEv71GZe5msU=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
@@ -375,18 +373,18 @@ github.com/prometheus/client_golang v0.9.0-pre1.0.20180209125602-c332b6f63c06/go
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= github.com/prometheus/client_golang v1.20.2 h1:5ctymQzZlyOON1666svgwn3s6IKWgfbjsejTMiXIyjg=
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_golang v1.20.2/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
@@ -395,8 +393,8 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/secure-systems-lab/go-securesystemslib v0.4.0 h1:b23VGrQhTA8cN2CbBw7/FulN9fTtqYUdS5+Oxzt+DUE= github.com/secure-systems-lab/go-securesystemslib v0.4.0 h1:b23VGrQhTA8cN2CbBw7/FulN9fTtqYUdS5+Oxzt+DUE=
@@ -443,8 +441,8 @@ github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4D
github.com/theupdateframework/notary v0.7.0/go.mod h1:c9DRxcmhHmVLDay4/2fUYdISnHqbFDGRSlXPO0AhYWw= github.com/theupdateframework/notary v0.7.0/go.mod h1:c9DRxcmhHmVLDay4/2fUYdISnHqbFDGRSlXPO0AhYWw=
github.com/tonistiigi/dchapes-mode v0.0.0-20241001053921-ca0759fec205 h1:eUk79E1w8yMtXeHSzjKorxuC8qJOnyXQnLaJehxpJaI= github.com/tonistiigi/dchapes-mode v0.0.0-20241001053921-ca0759fec205 h1:eUk79E1w8yMtXeHSzjKorxuC8qJOnyXQnLaJehxpJaI=
github.com/tonistiigi/dchapes-mode v0.0.0-20241001053921-ca0759fec205/go.mod h1:3Iuxbr0P7D3zUzBMAZB+ois3h/et0shEz0qApgHYGpY= github.com/tonistiigi/dchapes-mode v0.0.0-20241001053921-ca0759fec205/go.mod h1:3Iuxbr0P7D3zUzBMAZB+ois3h/et0shEz0qApgHYGpY=
github.com/tonistiigi/fsutil v0.0.0-20241028165955-397af5306b5c h1:bQLsfX+uEPZUjyR2qmoJs5F8Z57bPVmF3IsUf22Xo9Y= github.com/tonistiigi/fsutil v0.0.0-20241121093142-31cf1f437184 h1:RgyoSI38Y36zjQaszel/0RAcIehAnjA1B0RiUV9SDO4=
github.com/tonistiigi/fsutil v0.0.0-20241028165955-397af5306b5c/go.mod h1:Dl/9oEjK7IqnjAm21Okx/XIxUCFJzvh+XdVHUlBwXTw= github.com/tonistiigi/fsutil v0.0.0-20241121093142-31cf1f437184/go.mod h1:Dl/9oEjK7IqnjAm21Okx/XIxUCFJzvh+XdVHUlBwXTw=
github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4 h1:7I5c2Ig/5FgqkYOh/N87NzoyI9U15qUPXhDD8uCupv8= github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4 h1:7I5c2Ig/5FgqkYOh/N87NzoyI9U15qUPXhDD8uCupv8=
github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4/go.mod h1:278M4p8WsNh3n4a1eqiFcV2FGk7wE5fwUpUom9mK9lE= github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4/go.mod h1:278M4p8WsNh3n4a1eqiFcV2FGk7wE5fwUpUom9mK9lE=
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/v/cCndK0AMpt1wiVFb/YYmqB3/QG0= github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/v/cCndK0AMpt1wiVFb/YYmqB3/QG0=
@@ -474,30 +472,30 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.4
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE=
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.46.1 h1:gbhw/u49SS3gkPWiYweQNJGm/uJN5GkI/FrosxSHT7A= go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.46.1 h1:gbhw/u49SS3gkPWiYweQNJGm/uJN5GkI/FrosxSHT7A=
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.46.1/go.mod h1:GnOaBaFQ2we3b9AGWJpsBa7v1S5RlQzlC3O7dRMxZhM= go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.46.1/go.mod h1:GnOaBaFQ2we3b9AGWJpsBa7v1S5RlQzlC3O7dRMxZhM=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg=
go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0 h1:jd0+5t/YynESZqsSyPz+7PAFdEop0dlN0+PkyHYo8oI= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0 h1:jd0+5t/YynESZqsSyPz+7PAFdEop0dlN0+PkyHYo8oI=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0/go.mod h1:U707O40ee1FpQGyhvqnzmCJm1Wh6OX6GGBVn0E6Uyyk= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0/go.mod h1:U707O40ee1FpQGyhvqnzmCJm1Wh6OX6GGBVn0E6Uyyk=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.44.0 h1:bflGWrfYyuulcdxf14V6n9+CoQcu5SAAdHmDPAJnlps= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.44.0 h1:bflGWrfYyuulcdxf14V6n9+CoQcu5SAAdHmDPAJnlps=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.44.0/go.mod h1:qcTO4xHAxZLaLxPd60TdE88rxtItPHgHWqOhOGRr0as= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.44.0/go.mod h1:qcTO4xHAxZLaLxPd60TdE88rxtItPHgHWqOhOGRr0as=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqheXEFWAZ7O8A7m+J0aPTmpJN3YQ7qetUAdkkkKpk= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 h1:digkEZCJWobwBqMwC0cwCq8/wkkRy/OowZg5OArWZrM= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 h1:j9+03ymgYhPKmeXGk5Zu+cIZOlVzd9Zv7QIiyItjFBU=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0/go.mod h1:/OpE/y70qVkndM0TrxT4KBoN3RsFZP0QaofcfYrj76I= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0/go.mod h1:Y5+XiUG4Emn1hTfciPzGPJaSI+RpDts6BnCIir0SLqk=
go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE=
go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg=
go.opentelemetry.io/otel/sdk/metric v1.21.0 h1:smhI5oD714d6jHE6Tie36fPx4WDFIg+Y6RfAY4ICcR0= go.opentelemetry.io/otel/sdk/metric v1.28.0 h1:OkuaKgKrgAbYrrY0t92c+cC+2F6hsFNnCQArXCKlg08=
go.opentelemetry.io/otel/sdk/metric v1.21.0/go.mod h1:FJ8RAsoPGv/wYMgBdUJXOm+6pzFY3YdljnXtv1SBE8Q= go.opentelemetry.io/otel/sdk/metric v1.28.0/go.mod h1:cWPjykihLAPvXKi4iZc1dpER3Jdq2Z0YLse3moQUCpg=
go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= 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/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -572,13 +570,13 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ=
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro=
google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0=
google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= google.golang.org/grpc v1.66.3 h1:TWlsh8Mv0QI/1sIbs1W36lqRclxrmF+eFJ4DbI0fuhA=
google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/grpc v1.66.3/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zteSqZV6fqFOWBl4Yde8En8MryZA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zteSqZV6fqFOWBl4Yde8En8MryZA=
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=

View File

@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
ARG GO_VERSION=1.22 ARG GO_VERSION=1.23
ARG FORMATS=md,yaml ARG FORMATS=md,yaml
FROM golang:${GO_VERSION}-alpine AS docsgen FROM golang:${GO_VERSION}-alpine AS docsgen

View File

@@ -5,8 +5,8 @@
# Copyright The Buildx Authors. # Copyright The Buildx Authors.
# Licensed under the Apache License, Version 2.0 # Licensed under the Apache License, Version 2.0
ARG GO_VERSION="1.22" ARG GO_VERSION=1.23
ARG PROTOC_VERSION="3.11.4" ARG PROTOC_VERSION=3.11.4
ARG PROTOC_GOOGLEAPIS_VERSION=2af421884dd468d565137215c946ebe4e245ae26 ARG PROTOC_GOOGLEAPIS_VERSION=2af421884dd468d565137215c946ebe4e245ae26
# protoc is dynamically linked to glibc so can't use alpine base # protoc is dynamically linked to glibc so can't use alpine base

View File

@@ -1,7 +1,7 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
ARG GO_VERSION="1.22" ARG GO_VERSION=1.23
ARG GOVULNCHECK_VERSION="v1.1.3" ARG GOVULNCHECK_VERSION=v1.1.3
ARG FORMAT="text" ARG FORMAT="text"
FROM golang:${GO_VERSION}-alpine AS base FROM golang:${GO_VERSION}-alpine AS base

View File

@@ -1,12 +1,11 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
ARG GO_VERSION=1.22 ARG GO_VERSION=1.23
ARG XX_VERSION=1.3.0 ARG XX_VERSION=1.5.0
ARG GOLANGCI_LINT_VERSION=1.57.2 ARG GOLANGCI_LINT_VERSION=1.62.0
ARG GOPLS_VERSION=v0.20.0 ARG GOPLS_VERSION=v0.26.0
# disabled: deprecated unusedvariable simplifyrange # disabled: deprecated unusedvariable simplifyrange
ARG GOPLS_ANALYZERS="embeddirective fillreturns infertypeargs nonewvars noresultvalues simplifycompositelit simplifyslice stubmethods undeclaredname unusedparams useany" ARG GOPLS_ANALYZERS="embeddirective fillreturns infertypeargs nonewvars norangeoverfunc noresultvalues simplifycompositelit simplifyslice undeclaredname unusedparams useany"
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx

View File

@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
ARG GO_VERSION=1.22 ARG GO_VERSION=1.23
ARG MODOUTDATED_VERSION=v0.9.0 ARG MODOUTDATED_VERSION=v0.9.0
FROM golang:${GO_VERSION}-alpine AS base FROM golang:${GO_VERSION}-alpine AS base

View File

@@ -326,7 +326,7 @@ func (m *monitor) invoke(ctx context.Context, pid string, cfg *controllerapi.Inv
if m.AttachedSessionID() == "" { if m.AttachedSessionID() == "" {
return nil return nil
} }
invokeCtx, invokeCancel := context.WithCancel(ctx) invokeCtx, invokeCancel := context.WithCancelCause(ctx)
containerIn, containerOut := ioset.Pipe() containerIn, containerOut := ioset.Pipe()
m.invokeIO.SetOut(&containerOut) m.invokeIO.SetOut(&containerOut)
@@ -336,7 +336,7 @@ func (m *monitor) invoke(ctx context.Context, pid string, cfg *controllerapi.Inv
cancelOnce.Do(func() { cancelOnce.Do(func() {
containerIn.Close() containerIn.Close()
m.invokeIO.SetOut(nil) m.invokeIO.SetOut(nil)
invokeCancel() invokeCancel(errors.WithStack(context.Canceled))
}) })
<-waitInvokeDoneCh <-waitInvokeDoneCh
} }

View File

@@ -17,13 +17,13 @@ func TestNodeGroupUpdate(t *testing.T) {
err = ng.Update("foo1", "foo1", []string{"linux/arm64", "linux/arm/v7"}, true, true, nil, "", nil) err = ng.Update("foo1", "foo1", []string{"linux/arm64", "linux/arm/v7"}, true, true, nil, "", nil)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, len(ng.Nodes), 2) require.Equal(t, 2, len(ng.Nodes))
// update // update
err = ng.Update("foo", "foo2", []string{"linux/amd64", "linux/arm"}, true, false, nil, "", nil) err = ng.Update("foo", "foo2", []string{"linux/amd64", "linux/arm"}, true, false, nil, "", nil)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, len(ng.Nodes), 2) require.Equal(t, 2, len(ng.Nodes))
require.Equal(t, []string{"linux/amd64", "linux/arm/v7"}, platformutil.Format(ng.Nodes[0].Platforms)) require.Equal(t, []string{"linux/amd64", "linux/arm/v7"}, platformutil.Format(ng.Nodes[0].Platforms))
require.Equal(t, []string{"linux/arm64"}, platformutil.Format(ng.Nodes[1].Platforms)) require.Equal(t, []string{"linux/arm64"}, platformutil.Format(ng.Nodes[1].Platforms))
@@ -39,6 +39,6 @@ func TestNodeGroupUpdate(t *testing.T) {
err = ng.Leave("foo") err = ng.Leave("foo")
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, len(ng.Nodes), 1) require.Equal(t, 1, len(ng.Nodes))
require.Equal(t, []string{"linux/arm64"}, platformutil.Format(ng.Nodes[0].Platforms)) require.Equal(t, []string{"linux/arm64"}, platformutil.Format(ng.Nodes[0].Platforms))
} }

View File

@@ -7,6 +7,7 @@ import (
"github.com/docker/buildx/util/confutil" "github.com/docker/buildx/util/confutil"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@@ -44,7 +45,7 @@ func TestNodeLocking(t *testing.T) {
go func() { go func() {
_, release, err := s.Txn() _, release, err := s.Txn()
require.NoError(t, err) assert.NoError(t, err)
release() release()
close(ready) close(ready)
}() }()

View File

@@ -63,22 +63,44 @@ var bakeTests = []func(t *testing.T, sb integration.Sandbox){
} }
func testBakePrint(t *testing.T, sb integration.Sandbox) { func testBakePrint(t *testing.T, sb integration.Sandbox) {
dockerfile := []byte(` testCases := []struct {
FROM busybox name string
ARG HELLO f string
RUN echo "Hello ${HELLO}" dt []byte
`) }{
bakefile := []byte(` {
"HCL",
"docker-bake.hcl",
[]byte(`
target "build" { target "build" {
args = { args = {
HELLO = "foo" HELLO = "foo"
} }
} }
`) `)},
{
"Compose",
"compose.yml",
[]byte(`
services:
build:
build:
context: .
args:
HELLO: foo
`)},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("docker-bake.hcl", bakefile, 0600), fstest.CreateFile(tc.f, tc.dt, 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("Dockerfile", []byte(`
FROM busybox
ARG HELLO
RUN echo "Hello ${HELLO}"
`), 0600),
) )
cmd := buildxCmd(sb, withDir(dir), withArgs("bake", "--print", "build")) cmd := buildxCmd(sb, withDir(dir), withArgs("bake", "--print", "build"))
@@ -104,7 +126,7 @@ target "build" {
require.Equal(t, "Dockerfile", *def.Target["build"].Dockerfile) require.Equal(t, "Dockerfile", *def.Target["build"].Dockerfile)
require.Equal(t, map[string]*string{"HELLO": ptrstr("foo")}, def.Target["build"].Args) require.Equal(t, map[string]*string{"HELLO": ptrstr("foo")}, def.Target["build"].Args)
require.Equal(t, `{ require.JSONEq(t, `{
"group": { "group": {
"default": { "default": {
"targets": [ "targets": [
@@ -123,6 +145,8 @@ target "build" {
} }
} }
`, stdout.String()) `, stdout.String())
})
}
} }
func testBakeLocal(t *testing.T, sb integration.Sandbox) { func testBakeLocal(t *testing.T, sb integration.Sandbox) {
@@ -484,7 +508,8 @@ EOT
withArgs(addr, "--set", "*.output=type=local,dest="+dirDest), withArgs(addr, "--set", "*.output=type=local,dest="+dirDest),
) )
require.Error(t, err, out) require.Error(t, err, out)
require.Contains(t, out, "outside of the working directory, please set BAKE_ALLOW_REMOTE_FS_ACCESS") require.Contains(t, out, "Your build is requesting privileges for following possibly insecure capabilities")
require.Contains(t, out, "Read access to path ../")
out, err = bakeCmd( out, err = bakeCmd(
sb, sb,
@@ -531,7 +556,8 @@ EOT
withArgs(addr, "--set", "*.output=type=local,dest="+dirDest), withArgs(addr, "--set", "*.output=type=local,dest="+dirDest),
) )
require.Error(t, err, out) require.Error(t, err, out)
require.Contains(t, out, "outside of the working directory, please set BAKE_ALLOW_REMOTE_FS_ACCESS") require.Contains(t, out, "Your build is requesting privileges for following possibly insecure capabilities")
require.Contains(t, out, "Read access to path ..")
out, err = bakeCmd( out, err = bakeCmd(
sb, sb,
@@ -954,7 +980,6 @@ func testBakeMultiPlatform(t *testing.T, sb integration.Sandbox) {
require.NotNil(t, img) require.NotNil(t, img)
img = imgs.Find("linux/arm64") img = imgs.Find("linux/arm64")
require.NotNil(t, img) require.NotNil(t, img)
} else { } else {
require.Error(t, err, string(out)) require.Error(t, err, string(out))
require.Contains(t, string(out), "Multi-platform build is not supported") require.Contains(t, string(out), "Multi-platform build is not supported")
@@ -1444,7 +1469,7 @@ target "third" {
fstest.CreateFile("docker-bake.hcl", bakefile, 0600), fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
) )
dockerfilePathFirst := filepath.Join("Dockerfile") dockerfilePathFirst := "Dockerfile"
dockerfilePathSecond := filepath.Join("subdir", "Dockerfile") dockerfilePathSecond := filepath.Join("subdir", "Dockerfile")
dockerfilePathThird := filepath.Join("subdir", "subsubdir", "Dockerfile") dockerfilePathThird := filepath.Join("subdir", "subsubdir", "Dockerfile")

View File

@@ -471,7 +471,7 @@ RUN echo foo > /bar`)
cmd := buildxCmd(sb, withArgs("build", "--output=type=cacheonly", dir)) cmd := buildxCmd(sb, withArgs("build", "--output=type=cacheonly", dir))
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
require.NoError(t, err, string(out)) require.NoError(t, err, string(out))
require.False(t, buildDetailsPattern.MatchString(string(out)), fmt.Sprintf("build details link not expected in output, got %q", out)) require.False(t, buildDetailsPattern.MatchString(string(out)), "build details link not expected in output, got %q", out)
// create desktop-build .lastaccess file // create desktop-build .lastaccess file
home, err := os.UserHomeDir() // TODO: sandbox should create a temp home dir and expose it through its interface home, err := os.UserHomeDir() // TODO: sandbox should create a temp home dir and expose it through its interface
@@ -491,7 +491,7 @@ RUN echo foo > /bar`)
cmd = buildxCmd(sb, withArgs("build", "--output=type=cacheonly", dir)) cmd = buildxCmd(sb, withArgs("build", "--output=type=cacheonly", dir))
out, err = cmd.CombinedOutput() out, err = cmd.CombinedOutput()
require.NoError(t, err, string(out)) require.NoError(t, err, string(out))
require.True(t, buildDetailsPattern.MatchString(string(out)), fmt.Sprintf("expected build details link in output, got %q", out)) require.True(t, buildDetailsPattern.MatchString(string(out)), "expected build details link in output, got %q", out)
// build erroneous dockerfile // build erroneous dockerfile
dockerfile = []byte(`FROM busybox:latest dockerfile = []byte(`FROM busybox:latest
@@ -500,12 +500,12 @@ RUN exit 1`)
cmd = buildxCmd(sb, withArgs("build", "--output=type=cacheonly", dir)) cmd = buildxCmd(sb, withArgs("build", "--output=type=cacheonly", dir))
out, err = cmd.CombinedOutput() out, err = cmd.CombinedOutput()
require.Error(t, err, string(out)) require.Error(t, err, string(out))
require.True(t, buildDetailsPattern.MatchString(string(out)), fmt.Sprintf("expected build details link in output, got %q", out)) require.True(t, buildDetailsPattern.MatchString(string(out)), "expected build details link in output, got %q", out)
} }
func testBuildProgress(t *testing.T, sb integration.Sandbox) { func testBuildProgress(t *testing.T, sb integration.Sandbox) {
dir := createTestProject(t) dir := createTestProject(t)
sbDriver, _ := driverName(sb.Name()) sbDriver, _, _ := driverName(sb.Name())
name := sb.Address() name := sb.Address()
// progress=tty // progress=tty
@@ -578,7 +578,7 @@ func testBuildBuildArgNoKey(t *testing.T, sb integration.Sandbox) {
cmd := buildxCmd(sb, withArgs("build", "--build-arg", "=TEST_STRING", dir)) cmd := buildxCmd(sb, withArgs("build", "--build-arg", "=TEST_STRING", dir))
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
require.Error(t, err, string(out)) require.Error(t, err, string(out))
require.Equal(t, strings.TrimSpace(string(out)), `ERROR: invalid key-value pair "=TEST_STRING": empty key`) require.Equal(t, `ERROR: invalid key-value pair "=TEST_STRING": empty key`, strings.TrimSpace(string(out)))
} }
func testBuildLabelNoKey(t *testing.T, sb integration.Sandbox) { func testBuildLabelNoKey(t *testing.T, sb integration.Sandbox) {
@@ -586,7 +586,7 @@ func testBuildLabelNoKey(t *testing.T, sb integration.Sandbox) {
cmd := buildxCmd(sb, withArgs("build", "--label", "=TEST_STRING", dir)) cmd := buildxCmd(sb, withArgs("build", "--label", "=TEST_STRING", dir))
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
require.Error(t, err, string(out)) require.Error(t, err, string(out))
require.Equal(t, strings.TrimSpace(string(out)), `ERROR: invalid key-value pair "=TEST_STRING": empty key`) require.Equal(t, `ERROR: invalid key-value pair "=TEST_STRING": empty key`, strings.TrimSpace(string(out)))
} }
func testBuildCacheExportNotSupported(t *testing.T, sb integration.Sandbox) { func testBuildCacheExportNotSupported(t *testing.T, sb integration.Sandbox) {
@@ -649,7 +649,6 @@ func testBuildMultiPlatform(t *testing.T, sb integration.Sandbox) {
require.NotNil(t, img) require.NotNil(t, img)
img = imgs.Find("linux/arm64") img = imgs.Find("linux/arm64")
require.NotNil(t, img) require.NotNil(t, img)
} else { } else {
require.Error(t, err, string(out)) require.Error(t, err, string(out))
require.Contains(t, string(out), "Multi-platform build is not supported") require.Contains(t, string(out), "Multi-platform build is not supported")

View File

@@ -102,7 +102,7 @@ func testCreateRemoteContainer(t *testing.T, sb integration.Sandbox) {
for _, line := range strings.Split(out, "\n") { for _, line := range strings.Split(out, "\n") {
if v, ok := strings.CutPrefix(line, "Status:"); ok { if v, ok := strings.CutPrefix(line, "Status:"); ok {
require.Equal(t, strings.TrimSpace(v), "running") require.Equal(t, "running", strings.TrimSpace(v))
return return
} }
} }

View File

@@ -17,7 +17,6 @@ import (
"github.com/moby/buildkit/util/progress/progressui" "github.com/moby/buildkit/util/progress/progressui"
"github.com/moby/buildkit/util/testutil/integration" "github.com/moby/buildkit/util/testutil/integration"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@@ -57,7 +56,7 @@ func testDialStdio(t *testing.T, sb integration.Sandbox) {
case <-time.After(10 * time.Second): case <-time.After(10 * time.Second):
t.Error("timeout waiting for buildx command to exit") t.Error("timeout waiting for buildx command to exit")
case <-chErr: case <-chErr:
assert.NoError(t, err) require.NoError(t, err)
} }
}() }()

View File

@@ -45,7 +45,7 @@ func testInspect(t *testing.T, sb integration.Sandbox) {
} }
require.Equal(t, sb.Address(), name) require.Equal(t, sb.Address(), name)
sbDriver, _ := driverName(sb.Name()) sbDriver, _, _ := driverName(sb.Name())
require.Equal(t, sbDriver, driver) require.Equal(t, sbDriver, driver)
if isDockerWorker(sb) { if isDockerWorker(sb) {
require.NotEmpty(t, hostGatewayIP, "host-gateway-ip worker label should be set with docker driver") require.NotEmpty(t, hostGatewayIP, "host-gateway-ip worker label should be set with docker driver")

View File

@@ -95,33 +95,37 @@ func buildxConfig(sb integration.Sandbox) string {
} }
func isMobyWorker(sb integration.Sandbox) bool { func isMobyWorker(sb integration.Sandbox) bool {
name, hasFeature := driverName(sb.Name()) name, _, hasFeature := driverName(sb.Name())
return name == "docker" && !hasFeature return name == "docker" && !hasFeature
} }
func isMobyContainerdSnapWorker(sb integration.Sandbox) bool { func isMobyContainerdSnapWorker(sb integration.Sandbox) bool {
name, hasFeature := driverName(sb.Name()) name, _, hasFeature := driverName(sb.Name())
return name == "docker" && hasFeature return name == "docker" && hasFeature
} }
func isDockerWorker(sb integration.Sandbox) bool { func isDockerWorker(sb integration.Sandbox) bool {
name, _ := driverName(sb.Name()) name, _, _ := driverName(sb.Name())
return name == "docker" return name == "docker"
} }
func isDockerContainerWorker(sb integration.Sandbox) bool { func isDockerContainerWorker(sb integration.Sandbox) bool {
name, _ := driverName(sb.Name()) name, _, _ := driverName(sb.Name())
return name == "docker-container" return name == "docker-container"
} }
func driverName(sbName string) (string, bool) { func driverName(sbName string) (string, bool, bool) {
name := sbName name := sbName
var hasFeature bool var hasVersion, hasFeature bool
if b, _, ok := strings.Cut(sbName, "@"); ok {
name = b
hasVersion = true
}
if b, _, ok := strings.Cut(name, "+"); ok { if b, _, ok := strings.Cut(name, "+"); ok {
name = b name = b
hasFeature = true hasFeature = true
} }
return name, hasFeature return name, hasVersion, hasFeature
} }
func isExperimental() bool { func isExperimental() bool {

View File

@@ -34,7 +34,7 @@ func testLs(t *testing.T, sb integration.Sandbox) {
}, },
} }
sbDriver, _ := driverName(sb.Name()) sbDriver, _, _ := driverName(sb.Name())
for _, tt := range tests { for _, tt := range tests {
tt := tt tt := tt
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {

View File

@@ -2,10 +2,14 @@ package workers
import ( import (
"context" "context"
"fmt"
"os" "os"
"os/exec" "os/exec"
"path/filepath"
"strings"
"github.com/moby/buildkit/identity" "github.com/moby/buildkit/identity"
"github.com/moby/buildkit/util/testutil/dockerd"
"github.com/moby/buildkit/util/testutil/integration" "github.com/moby/buildkit/util/testutil/integration"
bkworkers "github.com/moby/buildkit/util/testutil/workers" bkworkers "github.com/moby/buildkit/util/testutil/workers"
"github.com/pkg/errors" "github.com/pkg/errors"
@@ -14,17 +18,60 @@ import (
func InitDockerWorker() { func InitDockerWorker() {
integration.Register(&dockerWorker{ integration.Register(&dockerWorker{
id: "docker", id: "docker",
binary: dockerd.DefaultDockerdBinary,
}) })
integration.Register(&dockerWorker{ integration.Register(&dockerWorker{
id: "docker+containerd", id: "docker+containerd",
binary: dockerd.DefaultDockerdBinary,
containerdSnapshotter: true, containerdSnapshotter: true,
}) })
// e.g. `docker@26.0=/opt/docker-26.0,docker@25.0=/opt/docker-25.0`
if s := os.Getenv("TEST_DOCKER_EXTRA"); s != "" {
entries := strings.Split(s, ",")
for _, entry := range entries {
ver, bin, err := func(entry string) (string, string, error) {
p1 := strings.Split(strings.TrimSpace(entry), "=")
if len(p1) != 2 {
return "", "", errors.Errorf("invalid entry: %q", entry)
}
name, bin := p1[0], p1[1]
if _, err := os.Stat(bin); err != nil {
return "", "", errors.Wrapf(err, "bin not found: %q", bin)
}
p2 := strings.Split(strings.TrimSpace(name), "@")
if len(p2) != 2 {
return "", "", errors.Errorf("invalid name: %q", name)
}
_, ver := p2[0], p2[1]
if ver == "" {
return "", "", errors.New("empty version")
}
return ver, bin, nil
}(entry)
if err != nil {
panic(errors.Wrapf(err, "unexpected TEST_DOCKER_EXTRA: %q", s))
}
integration.Register(&dockerWorker{
id: fmt.Sprintf("docker@%s", ver),
binary: filepath.Join(bin, "dockerd"),
extraEnv: []string{fmt.Sprintf("PATH=%s:%s", bin, os.Getenv("PATH"))},
})
integration.Register(&dockerWorker{
id: fmt.Sprintf("docker+containerd@%s", ver),
binary: filepath.Join(bin, "dockerd"),
containerdSnapshotter: true,
extraEnv: []string{fmt.Sprintf("PATH=%s:%s", bin, os.Getenv("PATH"))},
})
}
}
} }
type dockerWorker struct { type dockerWorker struct {
id string id string
binary string
containerdSnapshotter bool containerdSnapshotter bool
unsupported []string unsupported []string
extraEnv []string
} }
func (c dockerWorker) Name() string { func (c dockerWorker) Name() string {
@@ -42,7 +89,9 @@ func (c *dockerWorker) NetNSDetached() bool {
func (c dockerWorker) New(ctx context.Context, cfg *integration.BackendConfig) (b integration.Backend, cl func() error, err error) { func (c dockerWorker) New(ctx context.Context, cfg *integration.BackendConfig) (b integration.Backend, cl func() error, err error) {
moby := bkworkers.Moby{ moby := bkworkers.Moby{
ID: c.id, ID: c.id,
Binary: c.binary,
ContainerdSnapshotter: c.containerdSnapshotter, ContainerdSnapshotter: c.containerdSnapshotter,
ExtraEnv: c.extraEnv,
} }
bk, bkclose, err := moby.New(ctx, cfg) bk, bkclose, err := moby.New(ctx, cfg)
if err != nil { if err != nil {

View File

@@ -138,7 +138,6 @@ func ParseAnnotations(inp []string) (map[exptypes.AnnotationKey]string, error) {
} }
annotations[ak] = v annotations[ak] = v
} }
} }
return annotations, nil return annotations, nil
} }

View File

@@ -7,6 +7,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func TestIsSubPath(t *testing.T) { func TestIsSubPath(t *testing.T) {
@@ -51,7 +52,7 @@ func TestIsSubPath(t *testing.T) {
tt := tt tt := tt
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
ok, err := isSubPath(tt.basePath, tt.subPath) ok, err := isSubPath(tt.basePath, tt.subPath)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, tt.expected, ok) assert.Equal(t, tt.expected, ok)
}) })
} }

View File

@@ -41,7 +41,6 @@ func (c *Client) LoadImage(ctx context.Context, name string, status progress.Wri
pr, pw := io.Pipe() pr, pw := io.Pipe()
done := make(chan struct{}) done := make(chan struct{})
ctx, cancel := context.WithCancel(ctx)
var w *waitingWriter var w *waitingWriter
w = &waitingWriter{ w = &waitingWriter{
PipeWriter: pw, PipeWriter: pw,
@@ -68,7 +67,6 @@ func (c *Client) LoadImage(ctx context.Context, name string, status progress.Wri
} }
}, },
done: done, done: done,
cancel: cancel,
} }
return w, func() { return w, func() {
pr.Close() pr.Close()
@@ -106,7 +104,6 @@ type waitingWriter struct {
mu sync.Mutex mu sync.Mutex
err error err error
done chan struct{} done chan struct{}
cancel func()
} }
func (w *waitingWriter) Write(dt []byte) (int, error) { func (w *waitingWriter) Write(dt []byte) (int, error) {

View File

@@ -55,7 +55,7 @@ func fromReader(l progress.SubLogger, rc io.ReadCloser) error {
Started: &now, Started: &now,
} }
} }
timeDelta := time.Now().Sub(st.Timestamp) timeDelta := time.Since(st.Timestamp)
if timeDelta < minTimeDelta { if timeDelta < minTimeDelta {
continue continue
} }

View File

@@ -7,6 +7,7 @@ import (
"net/http" "net/http"
"testing" "testing"
"github.com/pkg/errors"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@@ -25,7 +26,7 @@ func WithAccessToken(token string) GitServeOpt {
func GitServeHTTP(c *Git, t testing.TB, opts ...GitServeOpt) (url string) { func GitServeHTTP(c *Git, t testing.TB, opts ...GitServeOpt) (url string) {
t.Helper() t.Helper()
gitUpdateServerInfo(c, t) gitUpdateServerInfo(c, t)
ctx, cancel := context.WithCancel(context.TODO()) ctx, cancel := context.WithCancelCause(context.TODO())
gs := &gitServe{} gs := &gitServe{}
for _, opt := range opts { for _, opt := range opts {
@@ -38,7 +39,7 @@ func GitServeHTTP(c *Git, t testing.TB, opts ...GitServeOpt) (url string) {
name := "test.git" name := "test.git"
dir, err := c.GitDir() dir, err := c.GitDir()
if err != nil { if err != nil {
cancel() cancel(err)
} }
var addr string var addr string
@@ -84,7 +85,7 @@ func GitServeHTTP(c *Git, t testing.TB, opts ...GitServeOpt) (url string) {
<-ready <-ready
t.Cleanup(func() { t.Cleanup(func() {
cancel() cancel(errors.Errorf("cleanup"))
<-done <-done
}) })
return fmt.Sprintf("http://%s/%s", addr, name) return fmt.Sprintf("http://%s/%s", addr, name)

View File

@@ -47,7 +47,6 @@ func (f mockFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.Rea
reader := io.NopCloser(strings.NewReader(desc.Annotations["test_content"])) reader := io.NopCloser(strings.NewReader(desc.Annotations["test_content"]))
return reader, nil return reader, nil
} }
} }
func (r mockResolver) Resolve(ctx context.Context, ref string) (name string, desc ocispec.Descriptor, err error) { func (r mockResolver) Resolve(ctx context.Context, ref string) (name string, desc ocispec.Descriptor, err error) {

View File

@@ -10,6 +10,7 @@ import (
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func TestLoad(t *testing.T) { func TestLoad(t *testing.T) {
@@ -19,7 +20,7 @@ func TestLoad(t *testing.T) {
r := getImageNoAttestation() r := getImageNoAttestation()
indexDigest := reflect.ValueOf(r.indexes).MapKeys()[0].String() indexDigest := reflect.ValueOf(r.indexes).MapKeys()[0].String()
result, err := loader.Load(ctx, fmt.Sprintf("test@%s", indexDigest)) result, err := loader.Load(ctx, fmt.Sprintf("test@%s", indexDigest))
assert.NoError(t, err) require.NoError(t, err)
if err == nil { if err == nil {
assert.Equal(t, 1, len(result.indexes)) assert.Equal(t, 1, len(result.indexes))
assert.Equal(t, 2, len(result.images)) assert.Equal(t, 2, len(result.images))
@@ -32,7 +33,7 @@ func TestLoad(t *testing.T) {
r = getImageWithAttestation(plainSpdx) r = getImageWithAttestation(plainSpdx)
indexDigest = reflect.ValueOf(r.indexes).MapKeys()[0].String() indexDigest = reflect.ValueOf(r.indexes).MapKeys()[0].String()
result, err = loader.Load(ctx, fmt.Sprintf("test@%s", indexDigest)) result, err = loader.Load(ctx, fmt.Sprintf("test@%s", indexDigest))
assert.NoError(t, err) require.NoError(t, err)
if err == nil { if err == nil {
assert.Equal(t, 1, len(result.indexes)) assert.Equal(t, 1, len(result.indexes))
assert.Equal(t, 2, len(result.images)) assert.Equal(t, 2, len(result.images))
@@ -92,7 +93,7 @@ func TestSBOM(t *testing.T) {
r.assets["linux/amd64"] = a r.assets["linux/amd64"] = a
actual, err := r.SBOM() actual, err := r.SBOM()
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, 1, len(actual)) assert.Equal(t, 1, len(actual))
}) })
} }
@@ -140,7 +141,7 @@ func TestProvenance(t *testing.T) {
r.assets["linux/amd64"] = a r.assets["linux/amd64"] = a
actual, err := r.Provenance() actual, err := r.Provenance()
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, 1, len(actual)) assert.Equal(t, 1, len(actual))
}) })
} }
@@ -167,7 +168,7 @@ func Test_isInTotoDSSE(t *testing.T) {
for _, test := range tests { for _, test := range tests {
t.Run(test.mime, func(t *testing.T) { t.Run(test.mime, func(t *testing.T) {
assert.Equal(t, isInTotoDSSE(test.mime), test.expected) assert.Equal(t, test.expected, isInTotoDSSE(test.mime))
}) })
} }
} }
@@ -175,19 +176,19 @@ func Test_isInTotoDSSE(t *testing.T) {
func Test_decodeDSSE(t *testing.T) { func Test_decodeDSSE(t *testing.T) {
// Returns input when mime isn't a DSSE type // Returns input when mime isn't a DSSE type
actual, err := decodeDSSE([]byte("foobar"), "application/vnd.in-toto+json") actual, err := decodeDSSE([]byte("foobar"), "application/vnd.in-toto+json")
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, []byte("foobar"), actual) assert.Equal(t, []byte("foobar"), actual)
// Returns the base64 decoded payload if is a DSSE // Returns the base64 decoded payload if is a DSSE
payload := base64.StdEncoding.EncodeToString([]byte("hello world")) payload := base64.StdEncoding.EncodeToString([]byte("hello world"))
envelope := fmt.Sprintf("{\"payload\":\"%s\"}", payload) envelope := fmt.Sprintf("{\"payload\":\"%s\"}", payload)
actual, err = decodeDSSE([]byte(envelope), "application/vnd.in-toto.spdx+dsse") actual, err = decodeDSSE([]byte(envelope), "application/vnd.in-toto.spdx+dsse")
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "hello world", string(actual)) assert.Equal(t, "hello world", string(actual))
_, err = decodeDSSE([]byte("not a json"), "application/vnd.in-toto.spdx+dsse") _, err = decodeDSSE([]byte("not a json"), "application/vnd.in-toto.spdx+dsse")
assert.Error(t, err) require.Error(t, err)
_, err = decodeDSSE([]byte("{\"payload\": \"not base64\"}"), "application/vnd.in-toto.spdx+dsse") _, err = decodeDSSE([]byte("{\"payload\": \"not base64\"}"), "application/vnd.in-toto.spdx+dsse")
assert.Error(t, err) require.Error(t, err)
} }

View File

@@ -61,7 +61,7 @@ func (m *Map) Get(ctx context.Context, keys ...string) (map[string]interface{},
m.mu.Unlock() m.mu.Unlock()
select { select {
case <-ctx.Done(): case <-ctx.Done():
return nil, ctx.Err() return nil, context.Cause(ctx)
case <-ch: case <-ch:
m.mu.Lock() m.mu.Lock()
} }

View File

@@ -2,7 +2,6 @@ package waitmap
import ( import (
"context" "context"
"errors"
"testing" "testing"
"time" "time"
@@ -34,12 +33,12 @@ func TestTimeout(t *testing.T) {
m.Set("foo", "bar") m.Set("foo", "bar")
ctx, cancel := context.WithTimeout(context.TODO(), 100*time.Millisecond) ctx, cancel := context.WithTimeoutCause(context.TODO(), 100*time.Millisecond, nil)
defer cancel() defer cancel()
_, err := m.Get(ctx, "bar") _, err := m.Get(ctx, "bar")
require.Error(t, err) require.Error(t, err)
require.True(t, errors.Is(err, context.DeadlineExceeded)) require.ErrorIs(t, err, context.DeadlineExceeded)
} }
func TestBlocking(t *testing.T) { func TestBlocking(t *testing.T) {

View File

@@ -1,4 +1,4 @@
# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Build Status][travis image]][travis] [![Coverage Status][coveralls image]][coveralls] # Exponential Backoff [![GoDoc][godoc image]][godoc] [![Coverage Status][coveralls image]][coveralls]
This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client]. This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client].
@@ -21,8 +21,6 @@ Use https://pkg.go.dev/github.com/cenkalti/backoff/v4 to view the documentation.
[godoc]: https://pkg.go.dev/github.com/cenkalti/backoff/v4 [godoc]: https://pkg.go.dev/github.com/cenkalti/backoff/v4
[godoc image]: https://godoc.org/github.com/cenkalti/backoff?status.png [godoc image]: https://godoc.org/github.com/cenkalti/backoff?status.png
[travis]: https://travis-ci.org/cenkalti/backoff
[travis image]: https://travis-ci.org/cenkalti/backoff.png?branch=master
[coveralls]: https://coveralls.io/github/cenkalti/backoff?branch=master [coveralls]: https://coveralls.io/github/cenkalti/backoff?branch=master
[coveralls image]: https://coveralls.io/repos/github/cenkalti/backoff/badge.svg?branch=master [coveralls image]: https://coveralls.io/repos/github/cenkalti/backoff/badge.svg?branch=master

View File

@@ -71,6 +71,9 @@ type Clock interface {
Now() time.Time Now() time.Time
} }
// ExponentialBackOffOpts is a function type used to configure ExponentialBackOff options.
type ExponentialBackOffOpts func(*ExponentialBackOff)
// Default values for ExponentialBackOff. // Default values for ExponentialBackOff.
const ( const (
DefaultInitialInterval = 500 * time.Millisecond DefaultInitialInterval = 500 * time.Millisecond
@@ -81,7 +84,7 @@ const (
) )
// NewExponentialBackOff creates an instance of ExponentialBackOff using default values. // NewExponentialBackOff creates an instance of ExponentialBackOff using default values.
func NewExponentialBackOff() *ExponentialBackOff { func NewExponentialBackOff(opts ...ExponentialBackOffOpts) *ExponentialBackOff {
b := &ExponentialBackOff{ b := &ExponentialBackOff{
InitialInterval: DefaultInitialInterval, InitialInterval: DefaultInitialInterval,
RandomizationFactor: DefaultRandomizationFactor, RandomizationFactor: DefaultRandomizationFactor,
@@ -91,10 +94,62 @@ func NewExponentialBackOff() *ExponentialBackOff {
Stop: Stop, Stop: Stop,
Clock: SystemClock, Clock: SystemClock,
} }
for _, fn := range opts {
fn(b)
}
b.Reset() b.Reset()
return b return b
} }
// WithInitialInterval sets the initial interval between retries.
func WithInitialInterval(duration time.Duration) ExponentialBackOffOpts {
return func(ebo *ExponentialBackOff) {
ebo.InitialInterval = duration
}
}
// WithRandomizationFactor sets the randomization factor to add jitter to intervals.
func WithRandomizationFactor(randomizationFactor float64) ExponentialBackOffOpts {
return func(ebo *ExponentialBackOff) {
ebo.RandomizationFactor = randomizationFactor
}
}
// WithMultiplier sets the multiplier for increasing the interval after each retry.
func WithMultiplier(multiplier float64) ExponentialBackOffOpts {
return func(ebo *ExponentialBackOff) {
ebo.Multiplier = multiplier
}
}
// WithMaxInterval sets the maximum interval between retries.
func WithMaxInterval(duration time.Duration) ExponentialBackOffOpts {
return func(ebo *ExponentialBackOff) {
ebo.MaxInterval = duration
}
}
// WithMaxElapsedTime sets the maximum total time for retries.
func WithMaxElapsedTime(duration time.Duration) ExponentialBackOffOpts {
return func(ebo *ExponentialBackOff) {
ebo.MaxElapsedTime = duration
}
}
// WithRetryStopDuration sets the duration after which retries should stop.
func WithRetryStopDuration(duration time.Duration) ExponentialBackOffOpts {
return func(ebo *ExponentialBackOff) {
ebo.Stop = duration
}
}
// WithClockProvider sets the clock used to measure time.
func WithClockProvider(clock Clock) ExponentialBackOffOpts {
return func(ebo *ExponentialBackOff) {
ebo.Clock = clock
}
}
type systemClock struct{} type systemClock struct{}
func (t systemClock) Now() time.Time { func (t systemClock) Now() time.Time {

View File

@@ -414,7 +414,7 @@ func (o *ProjectOptions) ReadConfigFiles(ctx context.Context, workingDir string,
for i, c := range config.ConfigFiles { for i, c := range config.ConfigFiles {
var err error var err error
var b []byte var b []byte
if c.Filename == "-" { if c.IsStdin() {
b, err = io.ReadAll(os.Stdin) b, err = io.ReadAll(os.Stdin)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -318,6 +318,13 @@ func LoadConfigFiles(ctx context.Context, configFiles []string, workingDir strin
opts.ResourceLoaders = append(opts.ResourceLoaders, localResourceLoader{}) opts.ResourceLoaders = append(opts.ResourceLoaders, localResourceLoader{})
for i, p := range configFiles { for i, p := range configFiles {
if p == "-" {
config.ConfigFiles[i] = types.ConfigFile{
Filename: p,
}
continue
}
for _, loader := range opts.ResourceLoaders { for _, loader := range opts.ResourceLoaders {
_, isLocalResourceLoader := loader.(localResourceLoader) _, isLocalResourceLoader := loader.(localResourceLoader)
if !loader.Accept(p) { if !loader.Accept(p) {

View File

@@ -28,11 +28,12 @@ import (
type ResetProcessor struct { type ResetProcessor struct {
target interface{} target interface{}
paths []tree.Path paths []tree.Path
visitedNodes map[*yaml.Node]string visitedNodes map[*yaml.Node][]string
} }
// UnmarshalYAML implement yaml.Unmarshaler // UnmarshalYAML implement yaml.Unmarshaler
func (p *ResetProcessor) UnmarshalYAML(value *yaml.Node) error { func (p *ResetProcessor) UnmarshalYAML(value *yaml.Node) error {
p.visitedNodes = make(map[*yaml.Node][]string)
resolved, err := p.resolveReset(value, tree.NewPath()) resolved, err := p.resolveReset(value, tree.NewPath())
p.visitedNodes = nil p.visitedNodes = nil
if err != nil { if err != nil {
@@ -49,24 +50,12 @@ func (p *ResetProcessor) resolveReset(node *yaml.Node, path tree.Path) (*yaml.No
path = tree.NewPath(strings.Replace(pathStr, ".<<", "", 1)) path = tree.NewPath(strings.Replace(pathStr, ".<<", "", 1))
} }
// Check for cycle
if p.visitedNodes == nil {
p.visitedNodes = make(map[*yaml.Node]string)
}
// Check for cycle by seeing if the node has already been visited at this path
if previousPath, found := p.visitedNodes[node]; found {
// If the current node has been visited, we have a cycle if the previous path is a prefix
if strings.HasPrefix(pathStr, previousPath) {
return nil, fmt.Errorf("cycle detected at path: %s", pathStr)
}
}
// Mark the current node as visited
p.visitedNodes[node] = pathStr
// If the node is an alias, We need to process the alias field in order to consider the !override and !reset tags // If the node is an alias, We need to process the alias field in order to consider the !override and !reset tags
if node.Kind == yaml.AliasNode { if node.Kind == yaml.AliasNode {
if err := p.checkForCycle(node.Alias, path); err != nil {
return nil, err
}
return p.resolveReset(node.Alias, path) return p.resolveReset(node.Alias, path)
} }
@@ -154,3 +143,48 @@ func (p *ResetProcessor) applyNullOverrides(target any, path tree.Path) error {
} }
return nil return nil
} }
func (p *ResetProcessor) checkForCycle(node *yaml.Node, path tree.Path) error {
paths := p.visitedNodes[node]
pathStr := path.String()
for _, prevPath := range paths {
// If we're visiting the exact same path, it's not a cycle
if pathStr == prevPath {
continue
}
// If either path is using a merge key, it's legitimate YAML merging
if strings.Contains(prevPath, "<<") || strings.Contains(pathStr, "<<") {
continue
}
// Only consider it a cycle if one path is contained within the other
// and they're not in different service definitions
if (strings.HasPrefix(pathStr, prevPath+".") ||
strings.HasPrefix(prevPath, pathStr+".")) &&
!areInDifferentServices(pathStr, prevPath) {
return fmt.Errorf("cycle detected: node at path %s references node at path %s", pathStr, prevPath)
}
}
p.visitedNodes[node] = append(paths, pathStr)
return nil
}
// areInDifferentServices checks if two paths are in different service definitions
func areInDifferentServices(path1, path2 string) bool {
// Split paths into components
parts1 := strings.Split(path1, ".")
parts2 := strings.Split(path2, ".")
// Look for the services component and compare the service names
for i := 0; i < len(parts1) && i < len(parts2); i++ {
if parts1[i] == "services" && i+1 < len(parts1) &&
parts2[i] == "services" && i+1 < len(parts2) {
// If they're different services, it's not a cycle
return parts1[i+1] != parts2[i+1]
}
}
return false
}

View File

@@ -67,6 +67,10 @@ type ConfigFile struct {
Config map[string]interface{} Config map[string]interface{}
} }
func (cf ConfigFile) IsStdin() bool {
return cf.Filename == "-"
}
func ToConfigFiles(path []string) (f []ConfigFile) { func ToConfigFiles(path []string) (f []ConfigFile) {
for _, p := range path { for _, p := range path {
f = append(f, ConfigFile{Filename: p}) f = append(f, ConfigFile{Filename: p})

View File

@@ -24,11 +24,12 @@ import (
"sync" "sync"
"time" "time"
"github.com/containerd/containerd/pkg/randutil"
"github.com/containerd/errdefs"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/pkg/randutil"
) )
var ErrReset = errors.New("writer has been reset") var ErrReset = errors.New("writer has been reset")

View File

@@ -21,7 +21,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/containerd/errdefs" "github.com/containerd/containerd/errdefs"
) )
// Handles locking references // Handles locking references

View File

@@ -22,7 +22,7 @@ import (
"os" "os"
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
"github.com/containerd/errdefs" "github.com/containerd/containerd/errdefs"
) )
// readerat implements io.ReaderAt in a completely stateless manner by opening // readerat implements io.ReaderAt in a completely stateless manner by opening

View File

@@ -27,13 +27,14 @@ import (
"sync" "sync"
"time" "time"
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/filters"
"github.com/containerd/containerd/pkg/randutil"
"github.com/containerd/errdefs"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/filters"
"github.com/containerd/containerd/pkg/randutil"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
) )
@@ -66,6 +67,8 @@ type LabelStore interface {
type store struct { type store struct {
root string root string
ls LabelStore ls LabelStore
ensureIngestRootOnce func() error
} }
// NewStore returns a local content store // NewStore returns a local content store
@@ -79,14 +82,13 @@ func NewStore(root string) (content.Store, error) {
// require labels and should use `NewStore`. `NewLabeledStore` is primarily // require labels and should use `NewStore`. `NewLabeledStore` is primarily
// useful for tests or standalone implementations. // useful for tests or standalone implementations.
func NewLabeledStore(root string, ls LabelStore) (content.Store, error) { func NewLabeledStore(root string, ls LabelStore) (content.Store, error) {
if err := os.MkdirAll(filepath.Join(root, "ingest"), 0777); err != nil { s := &store{
return nil, err
}
return &store{
root: root, root: root,
ls: ls, ls: ls,
}, nil }
s.ensureIngestRootOnce = sync.OnceValue(s.ensureIngestRoot)
return s, nil
} }
func (s *store) Info(ctx context.Context, dgst digest.Digest) (content.Info, error) { func (s *store) Info(ctx context.Context, dgst digest.Digest) (content.Info, error) {
@@ -293,6 +295,9 @@ func (s *store) Status(ctx context.Context, ref string) (content.Status, error)
func (s *store) ListStatuses(ctx context.Context, fs ...string) ([]content.Status, error) { func (s *store) ListStatuses(ctx context.Context, fs ...string) ([]content.Status, error) {
fp, err := os.Open(filepath.Join(s.root, "ingest")) fp, err := os.Open(filepath.Join(s.root, "ingest"))
if err != nil { if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err return nil, err
} }
@@ -343,6 +348,9 @@ func (s *store) ListStatuses(ctx context.Context, fs ...string) ([]content.Statu
func (s *store) WalkStatusRefs(ctx context.Context, fn func(string) error) error { func (s *store) WalkStatusRefs(ctx context.Context, fn func(string) error) error {
fp, err := os.Open(filepath.Join(s.root, "ingest")) fp, err := os.Open(filepath.Join(s.root, "ingest"))
if err != nil { if err != nil {
if os.IsNotExist(err) {
return nil
}
return err return err
} }
@@ -544,6 +552,11 @@ func (s *store) writer(ctx context.Context, ref string, total int64, expected di
) )
foundValidIngest := false foundValidIngest := false
if err := s.ensureIngestRootOnce(); err != nil {
return nil, err
}
// ensure that the ingest path has been created. // ensure that the ingest path has been created.
if err := os.Mkdir(path, 0755); err != nil { if err := os.Mkdir(path, 0755); err != nil {
if !os.IsExist(err) { if !os.IsExist(err) {
@@ -654,6 +667,10 @@ func (s *store) ingestPaths(ref string) (string, string, string) {
return fp, rp, dp return fp, rp, dp
} }
func (s *store) ensureIngestRoot() error {
return os.MkdirAll(filepath.Join(s.root, "ingest"), 0777)
}
func readFileString(path string) (string, error) { func readFileString(path string) (string, error) {
p, err := os.ReadFile(path) p, err := os.ReadFile(path)
return string(p), err return string(p), err

View File

@@ -26,10 +26,11 @@ import (
"runtime" "runtime"
"time" "time"
"github.com/containerd/containerd/content"
"github.com/containerd/errdefs"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/errdefs"
) )
// writer represents a write transaction against the blob store. // writer represents a write transaction against the blob store.

View File

@@ -22,9 +22,9 @@ import (
contentapi "github.com/containerd/containerd/api/services/content/v1" contentapi "github.com/containerd/containerd/api/services/content/v1"
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/protobuf" "github.com/containerd/containerd/protobuf"
protobuftypes "github.com/containerd/containerd/protobuf/types" protobuftypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/errdefs"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
) )

View File

@@ -23,8 +23,8 @@ import (
contentapi "github.com/containerd/containerd/api/services/content/v1" contentapi "github.com/containerd/containerd/api/services/content/v1"
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/protobuf" "github.com/containerd/containerd/protobuf"
"github.com/containerd/errdefs"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
) )

View File

@@ -0,0 +1,72 @@
/*
Copyright The containerd 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 errdefs defines the common errors used throughout containerd
// packages.
//
// Use with fmt.Errorf to add context to an error.
//
// To detect an error class, use the IsXXX functions to tell whether an error
// is of a certain type.
package errdefs
import (
"github.com/containerd/errdefs"
)
// Definitions of common error types used throughout containerd. All containerd
// errors returned by most packages will map into one of these errors classes.
// Packages should return errors of these types when they want to instruct a
// client to take a particular action.
//
// These errors map closely to grpc errors.
var (
ErrUnknown = errdefs.ErrUnknown
ErrInvalidArgument = errdefs.ErrInvalidArgument
ErrNotFound = errdefs.ErrNotFound
ErrAlreadyExists = errdefs.ErrAlreadyExists
ErrPermissionDenied = errdefs.ErrPermissionDenied
ErrResourceExhausted = errdefs.ErrResourceExhausted
ErrFailedPrecondition = errdefs.ErrFailedPrecondition
ErrConflict = errdefs.ErrConflict
ErrNotModified = errdefs.ErrNotModified
ErrAborted = errdefs.ErrAborted
ErrOutOfRange = errdefs.ErrOutOfRange
ErrNotImplemented = errdefs.ErrNotImplemented
ErrInternal = errdefs.ErrInternal
ErrUnavailable = errdefs.ErrUnavailable
ErrDataLoss = errdefs.ErrDataLoss
ErrUnauthenticated = errdefs.ErrUnauthenticated
IsCanceled = errdefs.IsCanceled
IsUnknown = errdefs.IsUnknown
IsInvalidArgument = errdefs.IsInvalidArgument
IsDeadlineExceeded = errdefs.IsDeadlineExceeded
IsNotFound = errdefs.IsNotFound
IsAlreadyExists = errdefs.IsAlreadyExists
IsPermissionDenied = errdefs.IsPermissionDenied
IsResourceExhausted = errdefs.IsResourceExhausted
IsFailedPrecondition = errdefs.IsFailedPrecondition
IsConflict = errdefs.IsConflict
IsNotModified = errdefs.IsNotModified
IsAborted = errdefs.IsAborted
IsOutOfRange = errdefs.IsOutOfRange
IsNotImplemented = errdefs.IsNotImplemented
IsInternal = errdefs.IsInternal
IsUnavailable = errdefs.IsUnavailable
IsDataLoss = errdefs.IsDataLoss
IsUnauthorized = errdefs.IsUnauthorized
)

View File

@@ -20,7 +20,7 @@ import (
"fmt" "fmt"
"io" "io"
"github.com/containerd/errdefs" "github.com/containerd/containerd/errdefs"
) )
/* /*

View File

@@ -28,7 +28,7 @@ import (
"fmt" "fmt"
"regexp" "regexp"
"github.com/containerd/errdefs" "github.com/containerd/containerd/errdefs"
) )
const ( const (

View File

@@ -26,15 +26,16 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/images"
"github.com/containerd/containerd/labels"
"github.com/containerd/errdefs"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/containerd/platforms" "github.com/containerd/platforms"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
ocispecs "github.com/opencontainers/image-spec/specs-go" ocispecs "github.com/opencontainers/image-spec/specs-go"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/images"
"github.com/containerd/containerd/labels"
) )
type exportOptions struct { type exportOptions struct {

View File

@@ -29,9 +29,9 @@ import (
"github.com/containerd/containerd/archive/compression" "github.com/containerd/containerd/archive/compression"
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/images" "github.com/containerd/containerd/images"
"github.com/containerd/containerd/labels" "github.com/containerd/containerd/labels"
"github.com/containerd/errdefs"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/containerd/platforms" "github.com/containerd/platforms"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"

View File

@@ -22,12 +22,13 @@ import (
"fmt" "fmt"
"sort" "sort"
"github.com/containerd/containerd/content"
"github.com/containerd/errdefs"
"github.com/containerd/platforms" "github.com/containerd/platforms"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
"golang.org/x/sync/semaphore" "golang.org/x/sync/semaphore"
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/errdefs"
) )
var ( var (

View File

@@ -23,12 +23,13 @@ import (
"sort" "sort"
"time" "time"
"github.com/containerd/containerd/content"
"github.com/containerd/errdefs"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/containerd/platforms" "github.com/containerd/platforms"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/errdefs"
) )
// Image provides the model for how containerd views container images. // Image provides the model for how containerd views container images.

View File

@@ -22,7 +22,7 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/containerd/errdefs" "github.com/containerd/containerd/errdefs"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
) )

View File

@@ -19,7 +19,7 @@ package labels
import ( import (
"fmt" "fmt"
"github.com/containerd/errdefs" "github.com/containerd/containerd/errdefs"
) )
const ( const (

View File

@@ -21,8 +21,8 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/identifiers" "github.com/containerd/containerd/identifiers"
"github.com/containerd/errdefs"
) )
const ( const (

View File

@@ -25,10 +25,11 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/containerd/log"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/remotes/docker/auth" "github.com/containerd/containerd/remotes/docker/auth"
remoteerrors "github.com/containerd/containerd/remotes/errors" remoteerrors "github.com/containerd/containerd/remotes/errors"
"github.com/containerd/errdefs"
"github.com/containerd/log"
) )
type dockerAuthorizer struct { type dockerAuthorizer struct {

View File

@@ -26,11 +26,12 @@ import (
"net/url" "net/url"
"strings" "strings"
"github.com/containerd/containerd/images"
"github.com/containerd/errdefs"
"github.com/containerd/log" "github.com/containerd/log"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/images"
) )
type dockerFetcher struct { type dockerFetcher struct {

View File

@@ -21,8 +21,9 @@ import (
"fmt" "fmt"
"io" "io"
"github.com/containerd/errdefs"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/containerd/containerd/errdefs"
) )
const maxRetry = 3 const maxRetry = 3

View File

@@ -28,14 +28,15 @@ import (
"sync" "sync"
"time" "time"
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/images"
"github.com/containerd/containerd/remotes"
remoteserrors "github.com/containerd/containerd/remotes/errors"
"github.com/containerd/errdefs"
"github.com/containerd/log" "github.com/containerd/log"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/images"
"github.com/containerd/containerd/remotes"
remoteserrors "github.com/containerd/containerd/remotes/errors"
) )
type dockerPusher struct { type dockerPusher struct {

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