Compare commits

..

19 Commits

Author SHA1 Message Date
CrazyMax
1360a9e8d2 Merge pull request #3037 from crazy-max/0.21_picks_0.21.2
[v0.21] cherry-picks for v0.21.2
2025-03-03 17:10:32 +01:00
Jonathan A. Sternberg
6019a2b32f buildflags: skip empty cache entries when parsing
Broken in 11c84973ef. The section to skip
an empty input was accidentally removed when some code was refactored to
fix a separate issue.

This skips empty cache entries which allows disabling the `cache-from` and
`cache-to` entries from the command line overrides.

Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
2025-03-03 16:30:03 +01:00
Laurent Goderre
6da88e1555 Fix handling of attest extra arguments
Signed-off-by: Laurent Goderre <laurent.goderre@docker.com>
2025-03-03 16:29:20 +01:00
Laurent Goderre
41f8e5c85c Add attest extra args tests
Signed-off-by: Laurent Goderre <laurent.goderre@docker.com>
2025-03-03 16:29:20 +01:00
CrazyMax
7c2359c6bf Merge pull request #3018 from crazy-max/0.21_picks_0.21.1
[v0.21] cherry-picks for v0.21.1
2025-02-21 13:22:55 +01:00
Tonis Tiigi
65a52b5272 remove accidental debug
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2025-02-21 09:43:43 +01:00
Jonathan A. Sternberg
34ed52e4ae Merge pull request #3011 from jsternberg/v0.21.0-picks
[v0.21] cherry-picks for v0.21.0
2025-02-19 13:54:05 -06:00
Jonathan A. Sternberg
a05bbb9e3d vendor: github.com/moby/buildkit v0.20.0
Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
(cherry picked from commit 80c3832c94)
2025-02-19 13:53:30 -06:00
CrazyMax
d9f8c73375 Merge pull request #3004 from crazy-max/0.21_picks_0.21.0-rc3
[v0.21] cherry-picks 0.21.0-rc3
2025-02-18 22:55:57 +01:00
CrazyMax
af5d0d4ab5 vendor: update buildkit to v0.20.0-rc3
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2025-02-18 22:29:44 +01:00
Tõnis Tiigi
20256b6999 support for device entitlement in build and bake
Allow access to CDI Devices in Buildkit v0.20.0+ for
devices that are not automatically allowed to be used by
everyone in BuildKit configuration.

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2025-02-18 22:29:43 +01:00
CrazyMax
c09d38af8a cache: fix gha cache url handling
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2025-02-18 21:25:21 +01:00
CrazyMax
9430ed6752 cache: enable gha cache backend if cache service v2 detected
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2025-02-18 21:25:20 +01:00
Tonis Tiigi
3b31a33d59 progress: fix race on pausing progress on debug shell
Current progress writer has a logic of pausing/unpausing
the printer and internally recreating internal channels.

This conflicts with a change that added sync.Once to Wait
to allow it being called multiple times without erroring.

In debug shell this could mean that new progress printer
showed up in debug shell because it was not closed.

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2025-02-18 11:01:09 +01:00
CrazyMax
5e5568f3cd Merge pull request #2996 from crazy-max/0.21_backport_docker-28
[v0.21 backport] vendor: docker, docker/cli v28.0.0-rc.2
2025-02-17 17:53:00 +01:00
Sebastiaan van Stijn
9ac9a4170b vendor: github.com/docker/cli v28.0.0-rc.2
full diff: https://github.com/docker/cli/compare/v28.0.0-rc.1...v28.0.0-rc.2

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-02-17 17:09:23 +01:00
Sebastiaan van Stijn
8d1ba91dcb vendor: github.com/docker/docker v28.0.0-rc.2
full diff: https://github.com/docker/docker/compare/v28.0.0-rc.1...v28.0.0-rc.2

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-02-17 17:09:23 +01:00
Sebastiaan van Stijn
0df7a75961 vendor: github.com/docker/cli/v28.0.0-rc.1
full diff: https://github.com/docker/cli/compare/v27.5.1..v28.0.0-rc.1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-02-14 14:07:46 +01:00
Sebastiaan van Stijn
de5fbc38b8 vendor: github.com/docker/docker/v28.0.0-rc.1
full diff: https://github.com/docker/docker/compare/v27.5.1..v28.0.0-rc.1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-02-14 14:07:46 +01:00
129 changed files with 982 additions and 1437 deletions

View File

@@ -54,9 +54,9 @@ jobs:
- master - master
- latest - latest
- buildx-stable-1 - buildx-stable-1
- v0.20.1
- v0.19.0 - v0.19.0
- v0.18.2 - v0.18.2
- v0.17.2
worker: worker:
- docker-container - docker-container
- remote - remote
@@ -76,16 +76,6 @@ 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@27.5"
pkg: ./tests
- worker: "docker+containerd@27.5" # same as docker, but with containerd snapshotter
pkg: ./tests
- worker: "docker@27.5"
pkg: ./tests
mode: experimental
- worker: "docker+containerd@27.5" # same as docker, but with containerd snapshotter
pkg: ./tests
mode: experimental
- worker: "docker@26.1" - worker: "docker@26.1"
pkg: ./tests pkg: ./tests
- worker: "docker+containerd@26.1" # same as docker, but with containerd snapshotter - worker: "docker+containerd@26.1" # same as docker, but with containerd snapshotter
@@ -258,17 +248,12 @@ jobs:
matrix: matrix:
os: os:
- freebsd - freebsd
- netbsd
- openbsd - openbsd
steps: steps:
- -
name: Prepare name: Prepare
run: | run: |
echo "VAGRANT_FILE=hack/Vagrantfile.${{ matrix.os }}" >> $GITHUB_ENV echo "VAGRANT_FILE=hack/Vagrantfile.${{ matrix.os }}" >> $GITHUB_ENV
# Sets semver Go version to be able to download tarball during vagrant setup
goVersion=$(curl --silent "https://go.dev/dl/?mode=json&include=all" | jq -r '.[].files[].version' | uniq | sed -e 's/go//' | sort -V | grep $GO_VERSION | tail -1)
echo "GO_VERSION=$goVersion" >> $GITHUB_ENV
- -
name: Checkout name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -411,15 +396,6 @@ jobs:
- test-unit - test-unit
if: ${{ github.event_name != 'pull_request' && github.repository == 'docker/buildx' }} if: ${{ github.event_name != 'pull_request' && github.repository == 'docker/buildx' }}
steps: steps:
-
name: Free disk space
uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1
with:
android: true
dotnet: true
haskell: true
large-packages: true
swap-storage: true
- -
name: Set up QEMU name: Set up QEMU
uses: docker/setup-qemu-action@v3 uses: docker/setup-qemu-action@v3

View File

@@ -77,7 +77,7 @@ jobs:
VENDOR_MODULE: github.com/docker/buildx@${{ env.RELEASE_NAME }} VENDOR_MODULE: github.com/docker/buildx@${{ env.RELEASE_NAME }}
- -
name: Create PR on docs repo name: Create PR on docs repo
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6
with: with:
token: ${{ secrets.GHPAT_DOCS_DISPATCH }} token: ${{ secrets.GHPAT_DOCS_DISPATCH }}
push-to-fork: docker-tools-robot/docker.github.io push-to-fork: docker-tools-robot/docker.github.io

View File

@@ -29,7 +29,7 @@ env:
SETUP_BUILDX_VERSION: "edge" SETUP_BUILDX_VERSION: "edge"
SETUP_BUILDKIT_IMAGE: "moby/buildkit:latest" SETUP_BUILDKIT_IMAGE: "moby/buildkit:latest"
DESTDIR: "./bin" DESTDIR: "./bin"
K3S_VERSION: "v1.32.2+k3s1" K3S_VERSION: "v1.21.2-k3s1"
jobs: jobs:
build: build:
@@ -65,7 +65,7 @@ jobs:
retention-days: 7 retention-days: 7
driver: driver:
runs-on: ubuntu-24.04 runs-on: ubuntu-20.04
needs: needs:
- build - build
strategy: strategy:
@@ -153,7 +153,7 @@ jobs:
- -
name: Install k3s name: Install k3s
if: matrix.driver == 'kubernetes' if: matrix.driver == 'kubernetes'
uses: crazy-max/.github/.github/actions/install-k3s@7730d1434364d4b9aded32735b078a7ace5ea79a uses: crazy-max/.github/.github/actions/install-k3s@fa6141aedf23596fb8bdcceab9cce8dadaa31bd9
with: with:
version: ${{ env.K3S_VERSION }} version: ${{ env.K3S_VERSION }}
- -

View File

@@ -5,23 +5,20 @@ ARG ALPINE_VERSION=3.21
ARG XX_VERSION=1.6.1 ARG XX_VERSION=1.6.1
# for testing # for testing
ARG DOCKER_VERSION=28.0.0 ARG DOCKER_VERSION=28.0.0-rc.1
ARG DOCKER_VERSION_ALT_27=27.5.1
ARG DOCKER_VERSION_ALT_26=26.1.3 ARG DOCKER_VERSION_ALT_26=26.1.3
ARG DOCKER_CLI_VERSION=${DOCKER_VERSION} ARG DOCKER_CLI_VERSION=${DOCKER_VERSION}
ARG GOTESTSUM_VERSION=v1.12.0 ARG GOTESTSUM_VERSION=v1.12.0
ARG REGISTRY_VERSION=2.8.3 ARG REGISTRY_VERSION=2.8.3
ARG BUILDKIT_VERSION=v0.20.1 ARG BUILDKIT_VERSION=v0.19.0
ARG UNDOCK_VERSION=0.9.0 ARG UNDOCK_VERSION=0.9.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${ALPINE_VERSION} AS golatest FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine${ALPINE_VERSION} 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_27 AS docker-engine-alt27 FROM moby/moby-bin:$DOCKER_VERSION_ALT_26 AS docker-engine-alt
FROM moby/moby-bin:$DOCKER_VERSION_ALT_26 AS docker-engine-alt26 FROM dockereng/cli-bin:$DOCKER_VERSION_ALT_26 AS docker-cli-alt
FROM dockereng/cli-bin:$DOCKER_VERSION_ALT_27 AS docker-cli-alt27
FROM dockereng/cli-bin:$DOCKER_VERSION_ALT_26 AS docker-cli-alt26
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
@@ -105,7 +102,6 @@ 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-freebsd
FROM binaries-unix AS binaries-linux FROM binaries-unix AS binaries-linux
FROM binaries-unix AS binaries-netbsd
FROM binaries-unix AS binaries-openbsd FROM binaries-unix AS binaries-openbsd
FROM scratch AS binaries-windows FROM scratch AS binaries-windows
@@ -131,15 +127,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-alt27 / /opt/docker-alt-27/ COPY --link --from=docker-engine-alt / /opt/docker-alt-26/
COPY --link --from=docker-engine-alt26 / /opt/docker-alt-26/ COPY --link --from=docker-cli-alt / /opt/docker-alt-26/
COPY --link --from=docker-cli-alt27 / /opt/docker-alt-27/
COPY --link --from=docker-cli-alt26 / /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@27.5=/opt/docker-alt-27,docker@26.1=/opt/docker-alt-26" 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

@@ -45,7 +45,6 @@ type File struct {
type Override struct { type Override struct {
Value string Value string
ArrValue []string ArrValue []string
Append bool
} }
func defaultFilenames() []string { func defaultFilenames() []string {
@@ -486,8 +485,10 @@ func (c Config) loadLinks(name string, t *Target, m map[string]*Target, o map[st
if target == name { if target == name {
return errors.Errorf("target %s cannot link to itself", target) return errors.Errorf("target %s cannot link to itself", target)
} }
if slices.Contains(visited, target) { for _, v := range visited {
return errors.Errorf("infinite loop from %s to %s", name, target) if v == target {
return errors.Errorf("infinite loop from %s to %s", name, target)
}
} }
t2, ok := m[target] t2, ok := m[target]
if !ok { if !ok {
@@ -527,12 +528,9 @@ func (c Config) newOverrides(v []string) (map[string]map[string]Override, error)
m := map[string]map[string]Override{} m := map[string]map[string]Override{}
for _, v := range v { for _, v := range v {
parts := strings.SplitN(v, "=", 2) parts := strings.SplitN(v, "=", 2)
keys := strings.SplitN(parts[0], ".", 3)
skey := strings.TrimSuffix(parts[0], "+")
appendTo := strings.HasSuffix(parts[0], "+")
keys := strings.SplitN(skey, ".", 3)
if len(keys) < 2 { if len(keys) < 2 {
return nil, errors.Errorf("invalid override key %s, expected target.name", skey) return nil, errors.Errorf("invalid override key %s, expected target.name", parts[0])
} }
pattern := keys[0] pattern := keys[0]
@@ -545,7 +543,8 @@ func (c Config) newOverrides(v []string) (map[string]map[string]Override, error)
return nil, err return nil, err
} }
okey := strings.Join(keys[1:], ".") kk := strings.SplitN(parts[0], ".", 2)
for _, name := range names { for _, name := range names {
t, ok := m[name] t, ok := m[name]
if !ok { if !ok {
@@ -553,15 +552,14 @@ func (c Config) newOverrides(v []string) (map[string]map[string]Override, error)
m[name] = t m[name] = t
} }
override := t[okey] o := t[kk[1]]
// IMPORTANT: if you add more fields here, do not forget to update // IMPORTANT: if you add more fields here, do not forget to update
// docs/reference/buildx_bake.md (--set) and https://docs.docker.com/build/bake/overrides/ // docs/bake-reference.md and https://docs.docker.com/build/bake/overrides/
switch keys[1] { switch keys[1] {
case "output", "cache-to", "cache-from", "tags", "platform", "secrets", "ssh", "attest", "entitlements", "network", "annotations": case "output", "cache-to", "cache-from", "tags", "platform", "secrets", "ssh", "attest", "entitlements", "network":
if len(parts) == 2 { if len(parts) == 2 {
override.Append = appendTo o.ArrValue = append(o.ArrValue, parts[1])
override.ArrValue = append(override.ArrValue, parts[1])
} }
case "args": case "args":
if len(keys) != 3 { if len(keys) != 3 {
@@ -572,7 +570,7 @@ func (c Config) newOverrides(v []string) (map[string]map[string]Override, error)
if !ok { if !ok {
continue continue
} }
override.Value = v o.Value = v
} }
fallthrough fallthrough
case "contexts": case "contexts":
@@ -582,11 +580,11 @@ func (c Config) newOverrides(v []string) (map[string]map[string]Override, error)
fallthrough fallthrough
default: default:
if len(parts) == 2 { if len(parts) == 2 {
override.Value = parts[1] o.Value = parts[1]
} }
} }
t[okey] = override t[kk[1]] = o
} }
} }
return m, nil return m, nil
@@ -898,21 +896,13 @@ func (t *Target) AddOverrides(overrides map[string]Override, ent *EntitlementCon
} }
t.Labels[keys[1]] = &value t.Labels[keys[1]] = &value
case "tags": case "tags":
if o.Append { t.Tags = o.ArrValue
t.Tags = append(t.Tags, o.ArrValue...)
} else {
t.Tags = o.ArrValue
}
case "cache-from": case "cache-from":
cacheFrom, err := buildflags.ParseCacheEntry(o.ArrValue) cacheFrom, err := buildflags.ParseCacheEntry(o.ArrValue)
if err != nil { if err != nil {
return err return err
} }
if o.Append { t.CacheFrom = cacheFrom
t.CacheFrom = t.CacheFrom.Merge(cacheFrom)
} else {
t.CacheFrom = cacheFrom
}
for _, c := range t.CacheFrom { for _, c := range t.CacheFrom {
if c.Type == "local" { if c.Type == "local" {
if v, ok := c.Attrs["src"]; ok { if v, ok := c.Attrs["src"]; ok {
@@ -925,11 +915,7 @@ func (t *Target) AddOverrides(overrides map[string]Override, ent *EntitlementCon
if err != nil { if err != nil {
return err return err
} }
if o.Append { t.CacheTo = cacheTo
t.CacheTo = t.CacheTo.Merge(cacheTo)
} else {
t.CacheTo = cacheTo
}
for _, c := range t.CacheTo { for _, c := range t.CacheTo {
if c.Type == "local" { if c.Type == "local" {
if v, ok := c.Attrs["dest"]; ok { if v, ok := c.Attrs["dest"]; ok {
@@ -946,11 +932,7 @@ func (t *Target) AddOverrides(overrides map[string]Override, ent *EntitlementCon
if err != nil { if err != nil {
return errors.Wrap(err, "invalid value for outputs") return errors.Wrap(err, "invalid value for outputs")
} }
if o.Append { t.Secrets = secrets
t.Secrets = t.Secrets.Merge(secrets)
} else {
t.Secrets = secrets
}
for _, s := range t.Secrets { for _, s := range t.Secrets {
if s.FilePath != "" { if s.FilePath != "" {
ent.FSRead = append(ent.FSRead, s.FilePath) ent.FSRead = append(ent.FSRead, s.FilePath)
@@ -961,30 +943,18 @@ func (t *Target) AddOverrides(overrides map[string]Override, ent *EntitlementCon
if err != nil { if err != nil {
return errors.Wrap(err, "invalid value for outputs") return errors.Wrap(err, "invalid value for outputs")
} }
if o.Append { t.SSH = ssh
t.SSH = t.SSH.Merge(ssh)
} else {
t.SSH = ssh
}
for _, s := range t.SSH { for _, s := range t.SSH {
ent.FSRead = append(ent.FSRead, s.Paths...) ent.FSRead = append(ent.FSRead, s.Paths...)
} }
case "platform": case "platform":
if o.Append { t.Platforms = o.ArrValue
t.Platforms = append(t.Platforms, o.ArrValue...)
} else {
t.Platforms = o.ArrValue
}
case "output": case "output":
outputs, err := parseArrValue[buildflags.ExportEntry](o.ArrValue) outputs, err := parseArrValue[buildflags.ExportEntry](o.ArrValue)
if err != nil { if err != nil {
return errors.Wrap(err, "invalid value for outputs") return errors.Wrap(err, "invalid value for outputs")
} }
if o.Append { t.Outputs = outputs
t.Outputs = t.Outputs.Merge(outputs)
} else {
t.Outputs = outputs
}
for _, o := range t.Outputs { for _, o := range t.Outputs {
if o.Destination != "" { if o.Destination != "" {
ent.FSWrite = append(ent.FSWrite, o.Destination) ent.FSWrite = append(ent.FSWrite, o.Destination)
@@ -1014,19 +984,11 @@ func (t *Target) AddOverrides(overrides map[string]Override, ent *EntitlementCon
} }
t.NoCache = &noCache t.NoCache = &noCache
case "no-cache-filter": case "no-cache-filter":
if o.Append { t.NoCacheFilter = o.ArrValue
t.NoCacheFilter = append(t.NoCacheFilter, o.ArrValue...)
} else {
t.NoCacheFilter = o.ArrValue
}
case "shm-size": case "shm-size":
t.ShmSize = &value t.ShmSize = &value
case "ulimits": case "ulimits":
if o.Append { t.Ulimits = o.ArrValue
t.Ulimits = append(t.Ulimits, o.ArrValue...)
} else {
t.Ulimits = o.ArrValue
}
case "network": case "network":
t.NetworkMode = &value t.NetworkMode = &value
case "pull": case "pull":

View File

@@ -34,18 +34,6 @@ target "webapp" {
args = { args = {
VAR_BOTH = "webapp" VAR_BOTH = "webapp"
} }
annotations = [
"index,manifest:org.opencontainers.image.authors=dvdksn"
]
attest = [
"type=provenance,mode=max"
]
platforms = [
"linux/amd64"
]
secret = [
"id=FOO,env=FOO"
]
inherits = ["webDEP"] inherits = ["webDEP"]
}`), }`),
} }
@@ -127,31 +115,6 @@ target "webapp" {
}) })
}) })
t.Run("AnnotationsOverrides", func(t *testing.T) {
t.Parallel()
m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.annotations=index,manifest:org.opencontainers.image.vendor=docker"}, nil, &EntitlementConf{})
require.NoError(t, err)
require.Equal(t, []string{"index,manifest:org.opencontainers.image.authors=dvdksn", "index,manifest:org.opencontainers.image.vendor=docker"}, m["webapp"].Annotations)
require.Equal(t, 1, len(g))
require.Equal(t, []string{"webapp"}, g["default"].Targets)
})
t.Run("AttestOverride", func(t *testing.T) {
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.attest=type=sbom"}, nil, &EntitlementConf{})
require.NoError(t, err)
require.Len(t, m["webapp"].Attest, 2)
require.Equal(t, "provenance", m["webapp"].Attest[0].Type)
require.Equal(t, "sbom", m["webapp"].Attest[1].Type)
})
t.Run("AttestAppend", func(t *testing.T) {
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.attest+=type=sbom"}, nil, &EntitlementConf{})
require.NoError(t, err)
require.Len(t, m["webapp"].Attest, 2)
require.Equal(t, "provenance", m["webapp"].Attest[0].Type)
require.Equal(t, "sbom", m["webapp"].Attest[1].Type)
})
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, &EntitlementConf{}) _, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.context"}, nil, &EntitlementConf{})
@@ -173,49 +136,6 @@ target "webapp" {
require.Equal(t, []string{"webapp"}, g["default"].Targets) require.Equal(t, []string{"webapp"}, g["default"].Targets)
}) })
t.Run("PlatformOverride", func(t *testing.T) {
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.platform=linux/arm64"}, nil, &EntitlementConf{})
require.NoError(t, err)
require.Equal(t, []string{"linux/arm64"}, m["webapp"].Platforms)
})
t.Run("PlatformAppend", func(t *testing.T) {
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.platform+=linux/arm64"}, nil, &EntitlementConf{})
require.NoError(t, err)
require.Equal(t, []string{"linux/amd64", "linux/arm64"}, m["webapp"].Platforms)
})
t.Run("PlatformAppendMulti", func(t *testing.T) {
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.platform+=linux/arm64", "webapp.platform+=linux/riscv64"}, nil, &EntitlementConf{})
require.NoError(t, err)
require.Equal(t, []string{"linux/amd64", "linux/arm64", "linux/riscv64"}, m["webapp"].Platforms)
})
t.Run("PlatformAppendMultiLastOverride", func(t *testing.T) {
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.platform+=linux/arm64", "webapp.platform=linux/riscv64"}, nil, &EntitlementConf{})
require.NoError(t, err)
require.Equal(t, []string{"linux/arm64", "linux/riscv64"}, m["webapp"].Platforms)
})
t.Run("SecretsOverride", func(t *testing.T) {
t.Setenv("FOO", "foo")
t.Setenv("BAR", "bar")
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.secrets=id=BAR,env=BAR"}, nil, &EntitlementConf{})
require.NoError(t, err)
require.Len(t, m["webapp"].Secrets, 1)
require.Equal(t, "BAR", m["webapp"].Secrets[0].ID)
})
t.Run("SecretsAppend", func(t *testing.T) {
t.Setenv("FOO", "foo")
t.Setenv("BAR", "bar")
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.secrets+=id=BAR,env=BAR"}, nil, &EntitlementConf{})
require.NoError(t, err)
require.Len(t, m["webapp"].Secrets, 2)
require.Equal(t, "FOO", m["webapp"].Secrets[0].ID)
require.Equal(t, "BAR", m["webapp"].Secrets[1].ID)
})
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, &EntitlementConf{}) m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.shm-size=256m"}, nil, &EntitlementConf{})
require.NoError(t, err) require.NoError(t, err)

View File

@@ -315,7 +315,7 @@ type (
stringArray []string stringArray []string
) )
func (sa *stringArray) UnmarshalYAML(unmarshal func(any) error) error { func (sa *stringArray) UnmarshalYAML(unmarshal func(interface{}) error) error {
var multi []string var multi []string
err := unmarshal(&multi) err := unmarshal(&multi)
if err != nil { if err != nil {
@@ -332,7 +332,7 @@ func (sa *stringArray) UnmarshalYAML(unmarshal func(any) error) error {
// composeExtTarget converts Compose build extension x-bake to bake Target // composeExtTarget converts Compose build extension x-bake to bake Target
// https://github.com/compose-spec/compose-spec/blob/master/spec.md#extension // https://github.com/compose-spec/compose-spec/blob/master/spec.md#extension
func (t *Target) composeExtTarget(exts map[string]any) error { func (t *Target) composeExtTarget(exts map[string]interface{}) error {
var xb xbake var xb xbake
ext, ok := exts["x-bake"] ext, ok := exts["x-bake"]

View File

@@ -306,7 +306,7 @@ func (c EntitlementConf) Prompt(ctx context.Context, isRemote bool, out io.Write
fmt.Fprintf(out, "\nPass %q to grant requested privileges.\n", strings.Join(slices.Concat(flags, flagsFS), " ")) fmt.Fprintf(out, "\nPass %q to grant requested privileges.\n", strings.Join(slices.Concat(flags, flagsFS), " "))
} }
args := slices.Clone(os.Args) args := append([]string(nil), os.Args...)
if v, ok := os.LookupEnv("DOCKER_CLI_PLUGIN_ORIGINAL_CLI_COMMAND"); ok && v != "" { if v, ok := os.LookupEnv("DOCKER_CLI_PLUGIN_ORIGINAL_CLI_COMMAND"); ok && v != "" {
args[0] = v args[0] = v
} }

View File

@@ -1645,7 +1645,7 @@ func TestHCLIndexOfFunc(t *testing.T) {
require.Empty(t, c.Targets[1].Tags[1]) require.Empty(t, c.Targets[1].Tags[1])
} }
func ptrstr(s any) *string { func ptrstr(s interface{}) *string {
var n *string var n *string
if reflect.ValueOf(s).Kind() == reflect.String { if reflect.ValueOf(s).Kind() == reflect.String {
ss := s.(string) ss := s.(string)

View File

@@ -15,11 +15,11 @@ import (
// DecodeOptions allows customizing sections of the decoding process. // DecodeOptions allows customizing sections of the decoding process.
type DecodeOptions struct { type DecodeOptions struct {
ImpliedType func(gv any) (cty.Type, error) ImpliedType func(gv interface{}) (cty.Type, error)
Convert func(in cty.Value, want cty.Type) (cty.Value, error) Convert func(in cty.Value, want cty.Type) (cty.Value, error)
} }
func (o DecodeOptions) DecodeBody(body hcl.Body, ctx *hcl.EvalContext, val any) hcl.Diagnostics { func (o DecodeOptions) DecodeBody(body hcl.Body, ctx *hcl.EvalContext, val interface{}) hcl.Diagnostics {
o = o.withDefaults() o = o.withDefaults()
rv := reflect.ValueOf(val) rv := reflect.ValueOf(val)
@@ -46,7 +46,7 @@ func (o DecodeOptions) DecodeBody(body hcl.Body, ctx *hcl.EvalContext, val any)
// are returned then the given value may have been partially-populated but // are returned then the given value may have been partially-populated but
// may still be accessed by a careful caller for static analysis and editor // may still be accessed by a careful caller for static analysis and editor
// integration use-cases. // integration use-cases.
func DecodeBody(body hcl.Body, ctx *hcl.EvalContext, val any) hcl.Diagnostics { func DecodeBody(body hcl.Body, ctx *hcl.EvalContext, val interface{}) hcl.Diagnostics {
return DecodeOptions{}.DecodeBody(body, ctx, val) return DecodeOptions{}.DecodeBody(body, ctx, val)
} }
@@ -282,7 +282,7 @@ func (o DecodeOptions) decodeBlockToValue(block *hcl.Block, ctx *hcl.EvalContext
return diags return diags
} }
func (o DecodeOptions) DecodeExpression(expr hcl.Expression, ctx *hcl.EvalContext, val any) hcl.Diagnostics { func (o DecodeOptions) DecodeExpression(expr hcl.Expression, ctx *hcl.EvalContext, val interface{}) hcl.Diagnostics {
o = o.withDefaults() o = o.withDefaults()
srcVal, diags := expr.Value(ctx) srcVal, diags := expr.Value(ctx)
@@ -332,7 +332,7 @@ func (o DecodeOptions) DecodeExpression(expr hcl.Expression, ctx *hcl.EvalContex
// are returned then the given value may have been partially-populated but // are returned then the given value may have been partially-populated but
// may still be accessed by a careful caller for static analysis and editor // may still be accessed by a careful caller for static analysis and editor
// integration use-cases. // integration use-cases.
func DecodeExpression(expr hcl.Expression, ctx *hcl.EvalContext, val any) hcl.Diagnostics { func DecodeExpression(expr hcl.Expression, ctx *hcl.EvalContext, val interface{}) hcl.Diagnostics {
return DecodeOptions{}.DecodeExpression(expr, ctx, val) return DecodeOptions{}.DecodeExpression(expr, ctx, val)
} }

View File

@@ -16,8 +16,8 @@ import (
) )
func TestDecodeBody(t *testing.T) { func TestDecodeBody(t *testing.T) {
deepEquals := func(other any) func(v any) bool { deepEquals := func(other interface{}) func(v interface{}) bool {
return func(v any) bool { return func(v interface{}) bool {
return reflect.DeepEqual(v, other) return reflect.DeepEqual(v, other)
} }
} }
@@ -45,19 +45,19 @@ func TestDecodeBody(t *testing.T) {
} }
tests := []struct { tests := []struct {
Body map[string]any Body map[string]interface{}
Target func() any Target func() interface{}
Check func(v any) bool Check func(v interface{}) bool
DiagCount int DiagCount int
}{ }{
{ {
map[string]any{}, map[string]interface{}{},
makeInstantiateType(struct{}{}), makeInstantiateType(struct{}{}),
deepEquals(struct{}{}), deepEquals(struct{}{}),
0, 0,
}, },
{ {
map[string]any{}, map[string]interface{}{},
makeInstantiateType(struct { makeInstantiateType(struct {
Name string `hcl:"name"` Name string `hcl:"name"`
}{}), }{}),
@@ -67,7 +67,7 @@ func TestDecodeBody(t *testing.T) {
1, // name is required 1, // name is required
}, },
{ {
map[string]any{}, map[string]interface{}{},
makeInstantiateType(struct { makeInstantiateType(struct {
Name *string `hcl:"name"` Name *string `hcl:"name"`
}{}), }{}),
@@ -77,7 +77,7 @@ func TestDecodeBody(t *testing.T) {
0, 0,
}, // name nil }, // name nil
{ {
map[string]any{}, map[string]interface{}{},
makeInstantiateType(struct { makeInstantiateType(struct {
Name string `hcl:"name,optional"` Name string `hcl:"name,optional"`
}{}), }{}),
@@ -87,9 +87,9 @@ func TestDecodeBody(t *testing.T) {
0, 0,
}, // name optional }, // name optional
{ {
map[string]any{}, map[string]interface{}{},
makeInstantiateType(withNameExpression{}), makeInstantiateType(withNameExpression{}),
func(v any) bool { func(v interface{}) bool {
if v == nil { if v == nil {
return false return false
} }
@@ -109,11 +109,11 @@ func TestDecodeBody(t *testing.T) {
0, 0,
}, },
{ {
map[string]any{ map[string]interface{}{
"name": "Ermintrude", "name": "Ermintrude",
}, },
makeInstantiateType(withNameExpression{}), makeInstantiateType(withNameExpression{}),
func(v any) bool { func(v interface{}) bool {
if v == nil { if v == nil {
return false return false
} }
@@ -133,7 +133,7 @@ func TestDecodeBody(t *testing.T) {
0, 0,
}, },
{ {
map[string]any{ map[string]interface{}{
"name": "Ermintrude", "name": "Ermintrude",
}, },
makeInstantiateType(struct { makeInstantiateType(struct {
@@ -145,7 +145,7 @@ func TestDecodeBody(t *testing.T) {
0, 0,
}, },
{ {
map[string]any{ map[string]interface{}{
"name": "Ermintrude", "name": "Ermintrude",
"age": 23, "age": 23,
}, },
@@ -158,7 +158,7 @@ func TestDecodeBody(t *testing.T) {
1, // Extraneous "age" property 1, // Extraneous "age" property
}, },
{ {
map[string]any{ map[string]interface{}{
"name": "Ermintrude", "name": "Ermintrude",
"age": 50, "age": 50,
}, },
@@ -166,7 +166,7 @@ func TestDecodeBody(t *testing.T) {
Name string `hcl:"name"` Name string `hcl:"name"`
Attrs hcl.Attributes `hcl:",remain"` Attrs hcl.Attributes `hcl:",remain"`
}{}), }{}),
func(gotI any) bool { func(gotI interface{}) bool {
got := gotI.(struct { got := gotI.(struct {
Name string `hcl:"name"` Name string `hcl:"name"`
Attrs hcl.Attributes `hcl:",remain"` Attrs hcl.Attributes `hcl:",remain"`
@@ -176,7 +176,7 @@ func TestDecodeBody(t *testing.T) {
0, 0,
}, },
{ {
map[string]any{ map[string]interface{}{
"name": "Ermintrude", "name": "Ermintrude",
"age": 50, "age": 50,
}, },
@@ -184,7 +184,7 @@ func TestDecodeBody(t *testing.T) {
Name string `hcl:"name"` Name string `hcl:"name"`
Remain hcl.Body `hcl:",remain"` Remain hcl.Body `hcl:",remain"`
}{}), }{}),
func(gotI any) bool { func(gotI interface{}) bool {
got := gotI.(struct { got := gotI.(struct {
Name string `hcl:"name"` Name string `hcl:"name"`
Remain hcl.Body `hcl:",remain"` Remain hcl.Body `hcl:",remain"`
@@ -197,7 +197,7 @@ func TestDecodeBody(t *testing.T) {
0, 0,
}, },
{ {
map[string]any{ map[string]interface{}{
"name": "Ermintrude", "name": "Ermintrude",
"living": true, "living": true,
}, },
@@ -217,7 +217,7 @@ func TestDecodeBody(t *testing.T) {
0, 0,
}, },
{ {
map[string]any{ map[string]interface{}{
"name": "Ermintrude", "name": "Ermintrude",
"age": 50, "age": 50,
}, },
@@ -226,7 +226,7 @@ func TestDecodeBody(t *testing.T) {
Body hcl.Body `hcl:",body"` Body hcl.Body `hcl:",body"`
Remain hcl.Body `hcl:",remain"` Remain hcl.Body `hcl:",remain"`
}{}), }{}),
func(gotI any) bool { func(gotI interface{}) bool {
got := gotI.(struct { got := gotI.(struct {
Name string `hcl:"name"` Name string `hcl:"name"`
Body hcl.Body `hcl:",body"` Body hcl.Body `hcl:",body"`
@@ -241,76 +241,76 @@ func TestDecodeBody(t *testing.T) {
0, 0,
}, },
{ {
map[string]any{ map[string]interface{}{
"noodle": map[string]any{}, "noodle": map[string]interface{}{},
}, },
makeInstantiateType(struct { makeInstantiateType(struct {
Noodle struct{} `hcl:"noodle,block"` Noodle struct{} `hcl:"noodle,block"`
}{}), }{}),
func(gotI any) bool { func(gotI interface{}) bool {
// Generating no diagnostics is good enough for this one. // Generating no diagnostics is good enough for this one.
return true return true
}, },
0, 0,
}, },
{ {
map[string]any{ map[string]interface{}{
"noodle": []map[string]any{{}}, "noodle": []map[string]interface{}{{}},
}, },
makeInstantiateType(struct { makeInstantiateType(struct {
Noodle struct{} `hcl:"noodle,block"` Noodle struct{} `hcl:"noodle,block"`
}{}), }{}),
func(gotI any) bool { func(gotI interface{}) bool {
// Generating no diagnostics is good enough for this one. // Generating no diagnostics is good enough for this one.
return true return true
}, },
0, 0,
}, },
{ {
map[string]any{ map[string]interface{}{
"noodle": []map[string]any{{}, {}}, "noodle": []map[string]interface{}{{}, {}},
}, },
makeInstantiateType(struct { makeInstantiateType(struct {
Noodle struct{} `hcl:"noodle,block"` Noodle struct{} `hcl:"noodle,block"`
}{}), }{}),
func(gotI any) bool { func(gotI interface{}) bool {
// Generating one diagnostic is good enough for this one. // Generating one diagnostic is good enough for this one.
return true return true
}, },
1, 1,
}, },
{ {
map[string]any{}, map[string]interface{}{},
makeInstantiateType(struct { makeInstantiateType(struct {
Noodle struct{} `hcl:"noodle,block"` Noodle struct{} `hcl:"noodle,block"`
}{}), }{}),
func(gotI any) bool { func(gotI interface{}) bool {
// Generating one diagnostic is good enough for this one. // Generating one diagnostic is good enough for this one.
return true return true
}, },
1, 1,
}, },
{ {
map[string]any{ map[string]interface{}{
"noodle": []map[string]any{}, "noodle": []map[string]interface{}{},
}, },
makeInstantiateType(struct { makeInstantiateType(struct {
Noodle struct{} `hcl:"noodle,block"` Noodle struct{} `hcl:"noodle,block"`
}{}), }{}),
func(gotI any) bool { func(gotI interface{}) bool {
// Generating one diagnostic is good enough for this one. // Generating one diagnostic is good enough for this one.
return true return true
}, },
1, 1,
}, },
{ {
map[string]any{ map[string]interface{}{
"noodle": map[string]any{}, "noodle": map[string]interface{}{},
}, },
makeInstantiateType(struct { makeInstantiateType(struct {
Noodle *struct{} `hcl:"noodle,block"` Noodle *struct{} `hcl:"noodle,block"`
}{}), }{}),
func(gotI any) bool { func(gotI interface{}) bool {
return gotI.(struct { return gotI.(struct {
Noodle *struct{} `hcl:"noodle,block"` Noodle *struct{} `hcl:"noodle,block"`
}).Noodle != nil }).Noodle != nil
@@ -318,13 +318,13 @@ func TestDecodeBody(t *testing.T) {
0, 0,
}, },
{ {
map[string]any{ map[string]interface{}{
"noodle": []map[string]any{{}}, "noodle": []map[string]interface{}{{}},
}, },
makeInstantiateType(struct { makeInstantiateType(struct {
Noodle *struct{} `hcl:"noodle,block"` Noodle *struct{} `hcl:"noodle,block"`
}{}), }{}),
func(gotI any) bool { func(gotI interface{}) bool {
return gotI.(struct { return gotI.(struct {
Noodle *struct{} `hcl:"noodle,block"` Noodle *struct{} `hcl:"noodle,block"`
}).Noodle != nil }).Noodle != nil
@@ -332,13 +332,13 @@ func TestDecodeBody(t *testing.T) {
0, 0,
}, },
{ {
map[string]any{ map[string]interface{}{
"noodle": []map[string]any{}, "noodle": []map[string]interface{}{},
}, },
makeInstantiateType(struct { makeInstantiateType(struct {
Noodle *struct{} `hcl:"noodle,block"` Noodle *struct{} `hcl:"noodle,block"`
}{}), }{}),
func(gotI any) bool { func(gotI interface{}) bool {
return gotI.(struct { return gotI.(struct {
Noodle *struct{} `hcl:"noodle,block"` Noodle *struct{} `hcl:"noodle,block"`
}).Noodle == nil }).Noodle == nil
@@ -346,26 +346,26 @@ func TestDecodeBody(t *testing.T) {
0, 0,
}, },
{ {
map[string]any{ map[string]interface{}{
"noodle": []map[string]any{{}, {}}, "noodle": []map[string]interface{}{{}, {}},
}, },
makeInstantiateType(struct { makeInstantiateType(struct {
Noodle *struct{} `hcl:"noodle,block"` Noodle *struct{} `hcl:"noodle,block"`
}{}), }{}),
func(gotI any) bool { func(gotI interface{}) bool {
// Generating one diagnostic is good enough for this one. // Generating one diagnostic is good enough for this one.
return true return true
}, },
1, 1,
}, },
{ {
map[string]any{ map[string]interface{}{
"noodle": []map[string]any{}, "noodle": []map[string]interface{}{},
}, },
makeInstantiateType(struct { makeInstantiateType(struct {
Noodle []struct{} `hcl:"noodle,block"` Noodle []struct{} `hcl:"noodle,block"`
}{}), }{}),
func(gotI any) bool { func(gotI interface{}) bool {
noodle := gotI.(struct { noodle := gotI.(struct {
Noodle []struct{} `hcl:"noodle,block"` Noodle []struct{} `hcl:"noodle,block"`
}).Noodle }).Noodle
@@ -374,13 +374,13 @@ func TestDecodeBody(t *testing.T) {
0, 0,
}, },
{ {
map[string]any{ map[string]interface{}{
"noodle": []map[string]any{{}}, "noodle": []map[string]interface{}{{}},
}, },
makeInstantiateType(struct { makeInstantiateType(struct {
Noodle []struct{} `hcl:"noodle,block"` Noodle []struct{} `hcl:"noodle,block"`
}{}), }{}),
func(gotI any) bool { func(gotI interface{}) bool {
noodle := gotI.(struct { noodle := gotI.(struct {
Noodle []struct{} `hcl:"noodle,block"` Noodle []struct{} `hcl:"noodle,block"`
}).Noodle }).Noodle
@@ -389,13 +389,13 @@ func TestDecodeBody(t *testing.T) {
0, 0,
}, },
{ {
map[string]any{ map[string]interface{}{
"noodle": []map[string]any{{}, {}}, "noodle": []map[string]interface{}{{}, {}},
}, },
makeInstantiateType(struct { makeInstantiateType(struct {
Noodle []struct{} `hcl:"noodle,block"` Noodle []struct{} `hcl:"noodle,block"`
}{}), }{}),
func(gotI any) bool { func(gotI interface{}) bool {
noodle := gotI.(struct { noodle := gotI.(struct {
Noodle []struct{} `hcl:"noodle,block"` Noodle []struct{} `hcl:"noodle,block"`
}).Noodle }).Noodle
@@ -404,15 +404,15 @@ func TestDecodeBody(t *testing.T) {
0, 0,
}, },
{ {
map[string]any{ map[string]interface{}{
"noodle": map[string]any{}, "noodle": map[string]interface{}{},
}, },
makeInstantiateType(struct { makeInstantiateType(struct {
Noodle struct { Noodle struct {
Name string `hcl:"name,label"` Name string `hcl:"name,label"`
} `hcl:"noodle,block"` } `hcl:"noodle,block"`
}{}), }{}),
func(gotI any) bool { func(gotI interface{}) bool {
//nolint:misspell //nolint:misspell
// Generating two diagnostics is good enough for this one. // Generating two diagnostics is good enough for this one.
// (one for the missing noodle block and the other for // (one for the missing noodle block and the other for
@@ -423,9 +423,9 @@ func TestDecodeBody(t *testing.T) {
2, 2,
}, },
{ {
map[string]any{ map[string]interface{}{
"noodle": map[string]any{ "noodle": map[string]interface{}{
"foo_foo": map[string]any{}, "foo_foo": map[string]interface{}{},
}, },
}, },
makeInstantiateType(struct { makeInstantiateType(struct {
@@ -433,7 +433,7 @@ func TestDecodeBody(t *testing.T) {
Name string `hcl:"name,label"` Name string `hcl:"name,label"`
} `hcl:"noodle,block"` } `hcl:"noodle,block"`
}{}), }{}),
func(gotI any) bool { func(gotI interface{}) bool {
noodle := gotI.(struct { noodle := gotI.(struct {
Noodle struct { Noodle struct {
Name string `hcl:"name,label"` Name string `hcl:"name,label"`
@@ -444,10 +444,10 @@ func TestDecodeBody(t *testing.T) {
0, 0,
}, },
{ {
map[string]any{ map[string]interface{}{
"noodle": map[string]any{ "noodle": map[string]interface{}{
"foo_foo": map[string]any{}, "foo_foo": map[string]interface{}{},
"bar_baz": map[string]any{}, "bar_baz": map[string]interface{}{},
}, },
}, },
makeInstantiateType(struct { makeInstantiateType(struct {
@@ -455,17 +455,17 @@ func TestDecodeBody(t *testing.T) {
Name string `hcl:"name,label"` Name string `hcl:"name,label"`
} `hcl:"noodle,block"` } `hcl:"noodle,block"`
}{}), }{}),
func(gotI any) bool { func(gotI interface{}) bool {
// One diagnostic is enough for this one. // One diagnostic is enough for this one.
return true return true
}, },
1, 1,
}, },
{ {
map[string]any{ map[string]interface{}{
"noodle": map[string]any{ "noodle": map[string]interface{}{
"foo_foo": map[string]any{}, "foo_foo": map[string]interface{}{},
"bar_baz": map[string]any{}, "bar_baz": map[string]interface{}{},
}, },
}, },
makeInstantiateType(struct { makeInstantiateType(struct {
@@ -473,7 +473,7 @@ func TestDecodeBody(t *testing.T) {
Name string `hcl:"name,label"` Name string `hcl:"name,label"`
} `hcl:"noodle,block"` } `hcl:"noodle,block"`
}{}), }{}),
func(gotI any) bool { func(gotI interface{}) bool {
noodles := gotI.(struct { noodles := gotI.(struct {
Noodles []struct { Noodles []struct {
Name string `hcl:"name,label"` Name string `hcl:"name,label"`
@@ -484,9 +484,9 @@ func TestDecodeBody(t *testing.T) {
0, 0,
}, },
{ {
map[string]any{ map[string]interface{}{
"noodle": map[string]any{ "noodle": map[string]interface{}{
"foo_foo": map[string]any{ "foo_foo": map[string]interface{}{
"type": "rice", "type": "rice",
}, },
}, },
@@ -497,7 +497,7 @@ func TestDecodeBody(t *testing.T) {
Type string `hcl:"type"` Type string `hcl:"type"`
} `hcl:"noodle,block"` } `hcl:"noodle,block"`
}{}), }{}),
func(gotI any) bool { func(gotI interface{}) bool {
noodle := gotI.(struct { noodle := gotI.(struct {
Noodle struct { Noodle struct {
Name string `hcl:"name,label"` Name string `hcl:"name,label"`
@@ -510,7 +510,7 @@ func TestDecodeBody(t *testing.T) {
}, },
{ {
map[string]any{ map[string]interface{}{
"name": "Ermintrude", "name": "Ermintrude",
"age": 34, "age": 34,
}, },
@@ -522,31 +522,31 @@ func TestDecodeBody(t *testing.T) {
0, 0,
}, },
{ {
map[string]any{ map[string]interface{}{
"name": "Ermintrude", "name": "Ermintrude",
"age": 89, "age": 89,
}, },
makeInstantiateType(map[string]*hcl.Attribute(nil)), makeInstantiateType(map[string]*hcl.Attribute(nil)),
func(gotI any) bool { func(gotI interface{}) bool {
got := gotI.(map[string]*hcl.Attribute) got := gotI.(map[string]*hcl.Attribute)
return len(got) == 2 && got["name"] != nil && got["age"] != nil return len(got) == 2 && got["name"] != nil && got["age"] != nil
}, },
0, 0,
}, },
{ {
map[string]any{ map[string]interface{}{
"name": "Ermintrude", "name": "Ermintrude",
"age": 13, "age": 13,
}, },
makeInstantiateType(map[string]hcl.Expression(nil)), makeInstantiateType(map[string]hcl.Expression(nil)),
func(gotI any) bool { func(gotI interface{}) bool {
got := gotI.(map[string]hcl.Expression) got := gotI.(map[string]hcl.Expression)
return len(got) == 2 && got["name"] != nil && got["age"] != nil return len(got) == 2 && got["name"] != nil && got["age"] != nil
}, },
0, 0,
}, },
{ {
map[string]any{ map[string]interface{}{
"name": "Ermintrude", "name": "Ermintrude",
"living": true, "living": true,
}, },
@@ -559,10 +559,10 @@ func TestDecodeBody(t *testing.T) {
}, },
{ {
// Retain "nested" block while decoding // Retain "nested" block while decoding
map[string]any{ map[string]interface{}{
"plain": "foo", "plain": "foo",
}, },
func() any { func() interface{} {
return &withNestedBlock{ return &withNestedBlock{
Plain: "bar", Plain: "bar",
Nested: &withTwoAttributes{ Nested: &withTwoAttributes{
@@ -570,7 +570,7 @@ func TestDecodeBody(t *testing.T) {
}, },
} }
}, },
func(gotI any) bool { func(gotI interface{}) bool {
foo := gotI.(withNestedBlock) foo := gotI.(withNestedBlock)
return foo.Plain == "foo" && foo.Nested != nil && foo.Nested.A == "bar" return foo.Plain == "foo" && foo.Nested != nil && foo.Nested.A == "bar"
}, },
@@ -578,19 +578,19 @@ func TestDecodeBody(t *testing.T) {
}, },
{ {
// Retain values in "nested" block while decoding // Retain values in "nested" block while decoding
map[string]any{ map[string]interface{}{
"nested": map[string]any{ "nested": map[string]interface{}{
"a": "foo", "a": "foo",
}, },
}, },
func() any { func() interface{} {
return &withNestedBlock{ return &withNestedBlock{
Nested: &withTwoAttributes{ Nested: &withTwoAttributes{
B: "bar", B: "bar",
}, },
} }
}, },
func(gotI any) bool { func(gotI interface{}) bool {
foo := gotI.(withNestedBlock) foo := gotI.(withNestedBlock)
return foo.Nested.A == "foo" && foo.Nested.B == "bar" return foo.Nested.A == "foo" && foo.Nested.B == "bar"
}, },
@@ -598,14 +598,14 @@ func TestDecodeBody(t *testing.T) {
}, },
{ {
// Retain values in "nested" block list while decoding // Retain values in "nested" block list while decoding
map[string]any{ map[string]interface{}{
"nested": []map[string]any{ "nested": []map[string]interface{}{
{ {
"a": "foo", "a": "foo",
}, },
}, },
}, },
func() any { func() interface{} {
return &withListofNestedBlocks{ return &withListofNestedBlocks{
Nested: []*withTwoAttributes{ Nested: []*withTwoAttributes{
{ {
@@ -614,7 +614,7 @@ func TestDecodeBody(t *testing.T) {
}, },
} }
}, },
func(gotI any) bool { func(gotI interface{}) bool {
n := gotI.(withListofNestedBlocks) n := gotI.(withListofNestedBlocks)
return n.Nested[0].A == "foo" && n.Nested[0].B == "bar" return n.Nested[0].A == "foo" && n.Nested[0].B == "bar"
}, },
@@ -622,14 +622,14 @@ func TestDecodeBody(t *testing.T) {
}, },
{ {
// Remove additional elements from the list while decoding nested blocks // Remove additional elements from the list while decoding nested blocks
map[string]any{ map[string]interface{}{
"nested": []map[string]any{ "nested": []map[string]interface{}{
{ {
"a": "foo", "a": "foo",
}, },
}, },
}, },
func() any { func() interface{} {
return &withListofNestedBlocks{ return &withListofNestedBlocks{
Nested: []*withTwoAttributes{ Nested: []*withTwoAttributes{
{ {
@@ -641,7 +641,7 @@ func TestDecodeBody(t *testing.T) {
}, },
} }
}, },
func(gotI any) bool { func(gotI interface{}) bool {
n := gotI.(withListofNestedBlocks) n := gotI.(withListofNestedBlocks)
return len(n.Nested) == 1 return len(n.Nested) == 1
}, },
@@ -649,8 +649,8 @@ func TestDecodeBody(t *testing.T) {
}, },
{ {
// Make sure decoding value slices works the same as pointer slices. // Make sure decoding value slices works the same as pointer slices.
map[string]any{ map[string]interface{}{
"nested": []map[string]any{ "nested": []map[string]interface{}{
{ {
"b": "bar", "b": "bar",
}, },
@@ -659,7 +659,7 @@ func TestDecodeBody(t *testing.T) {
}, },
}, },
}, },
func() any { func() interface{} {
return &withListofNestedBlocksNoPointers{ return &withListofNestedBlocksNoPointers{
Nested: []withTwoAttributes{ Nested: []withTwoAttributes{
{ {
@@ -668,7 +668,7 @@ func TestDecodeBody(t *testing.T) {
}, },
} }
}, },
func(gotI any) bool { func(gotI interface{}) bool {
n := gotI.(withListofNestedBlocksNoPointers) n := gotI.(withListofNestedBlocksNoPointers)
return n.Nested[0].B == "bar" && len(n.Nested) == 2 return n.Nested[0].B == "bar" && len(n.Nested) == 2
}, },
@@ -710,8 +710,8 @@ func TestDecodeBody(t *testing.T) {
func TestDecodeExpression(t *testing.T) { func TestDecodeExpression(t *testing.T) {
tests := []struct { tests := []struct {
Value cty.Value Value cty.Value
Target any Target interface{}
Want any Want interface{}
DiagCount int DiagCount int
}{ }{
{ {
@@ -799,8 +799,8 @@ func (e *fixedExpression) Variables() []hcl.Traversal {
return nil return nil
} }
func makeInstantiateType(target any) func() any { func makeInstantiateType(target interface{}) func() interface{} {
return func() any { return func() interface{} {
return reflect.New(reflect.TypeOf(target)).Interface() return reflect.New(reflect.TypeOf(target)).Interface()
} }
} }

View File

@@ -34,9 +34,9 @@ import (
// The layout of the resulting HCL source is derived from the ordering of // The layout of the resulting HCL source is derived from the ordering of
// the struct fields, with blank lines around nested blocks of different types. // the struct fields, with blank lines around nested blocks of different types.
// Fields representing attributes should usually precede those representing // Fields representing attributes should usually precede those representing
// blocks so that the attributes can group together in the result. For more // blocks so that the attributes can group togather in the result. For more
// control, use the hclwrite API directly. // control, use the hclwrite API directly.
func EncodeIntoBody(val any, dst *hclwrite.Body) { func EncodeIntoBody(val interface{}, dst *hclwrite.Body) {
rv := reflect.ValueOf(val) rv := reflect.ValueOf(val)
ty := rv.Type() ty := rv.Type()
if ty.Kind() == reflect.Ptr { if ty.Kind() == reflect.Ptr {
@@ -60,7 +60,7 @@ func EncodeIntoBody(val any, dst *hclwrite.Body) {
// //
// This function has the same constraints as EncodeIntoBody and will panic // This function has the same constraints as EncodeIntoBody and will panic
// if they are violated. // if they are violated.
func EncodeAsBlock(val any, blockType string) *hclwrite.Block { func EncodeAsBlock(val interface{}, blockType string) *hclwrite.Block {
rv := reflect.ValueOf(val) rv := reflect.ValueOf(val)
ty := rv.Type() ty := rv.Type()
if ty.Kind() == reflect.Ptr { if ty.Kind() == reflect.Ptr {
@@ -158,7 +158,7 @@ func populateBody(rv reflect.Value, ty reflect.Type, tags *fieldTags, dst *hclwr
if isSeq { if isSeq {
l := fieldVal.Len() l := fieldVal.Len()
for i := range l { for i := 0; i < l; i++ {
elemVal := fieldVal.Index(i) elemVal := fieldVal.Index(i)
if !elemVal.IsValid() { if !elemVal.IsValid() {
continue // ignore (elem value is nil pointer) continue // ignore (elem value is nil pointer)

View File

@@ -22,7 +22,7 @@ import (
// This uses the tags on the fields of the struct to discover how each // This uses the tags on the fields of the struct to discover how each
// field's value should be expressed within configuration. If an invalid // field's value should be expressed within configuration. If an invalid
// mapping is attempted, this function will panic. // mapping is attempted, this function will panic.
func ImpliedBodySchema(val any) (schema *hcl.BodySchema, partial bool) { func ImpliedBodySchema(val interface{}) (schema *hcl.BodySchema, partial bool) {
ty := reflect.TypeOf(val) ty := reflect.TypeOf(val)
if ty.Kind() == reflect.Ptr { if ty.Kind() == reflect.Ptr {
@@ -134,7 +134,7 @@ func getFieldTags(ty reflect.Type) *fieldTags {
} }
ct := ty.NumField() ct := ty.NumField()
for i := range ct { for i := 0; i < ct; i++ {
field := ty.Field(i) field := ty.Field(i)
tag := field.Tag.Get("hcl") tag := field.Tag.Get("hcl")
if tag == "" { if tag == "" {

View File

@@ -14,7 +14,7 @@ import (
func TestImpliedBodySchema(t *testing.T) { func TestImpliedBodySchema(t *testing.T) {
tests := []struct { tests := []struct {
val any val interface{}
wantSchema *hcl.BodySchema wantSchema *hcl.BodySchema
wantPartial bool wantPartial bool
}{ }{

View File

@@ -7,7 +7,6 @@ import (
"math" "math"
"math/big" "math/big"
"reflect" "reflect"
"slices"
"strconv" "strconv"
"strings" "strings"
@@ -590,7 +589,7 @@ type ParseMeta struct {
AllVariables []*Variable AllVariables []*Variable
} }
func Parse(b hcl.Body, opt Opt, val any) (*ParseMeta, hcl.Diagnostics) { func Parse(b hcl.Body, opt Opt, val interface{}) (*ParseMeta, hcl.Diagnostics) {
reserved := map[string]struct{}{} reserved := map[string]struct{}{}
schema, _ := gohcl.ImpliedBodySchema(val) schema, _ := gohcl.ImpliedBodySchema(val)
@@ -764,7 +763,7 @@ func Parse(b hcl.Body, opt Opt, val any) (*ParseMeta, hcl.Diagnostics) {
types := map[string]field{} types := map[string]field{}
renamed := map[string]map[string][]string{} renamed := map[string]map[string][]string{}
vt := reflect.ValueOf(val).Elem().Type() vt := reflect.ValueOf(val).Elem().Type()
for i := range vt.NumField() { for i := 0; i < vt.NumField(); i++ {
tags := strings.Split(vt.Field(i).Tag.Get("hcl"), ",") tags := strings.Split(vt.Field(i).Tag.Get("hcl"), ",")
p.blockTypes[tags[0]] = vt.Field(i).Type.Elem().Elem() p.blockTypes[tags[0]] = vt.Field(i).Type.Elem().Elem()
@@ -832,7 +831,7 @@ func Parse(b hcl.Body, opt Opt, val any) (*ParseMeta, hcl.Diagnostics) {
oldValue, exists := t.values[lblName] oldValue, exists := t.values[lblName]
if !exists && lblExists { if !exists && lblExists {
if v.Elem().Field(t.idx).Type().Kind() == reflect.Slice { if v.Elem().Field(t.idx).Type().Kind() == reflect.Slice {
for i := range v.Elem().Field(t.idx).Len() { for i := 0; i < v.Elem().Field(t.idx).Len(); i++ {
if lblName == v.Elem().Field(t.idx).Index(i).Elem().Field(lblIndex).String() { if lblName == v.Elem().Field(t.idx).Index(i).Elem().Field(lblIndex).String() {
exists = true exists = true
oldValue = value{Value: v.Elem().Field(t.idx).Index(i), idx: i} oldValue = value{Value: v.Elem().Field(t.idx).Index(i), idx: i}
@@ -899,7 +898,7 @@ func wrapErrorDiagnostic(message string, err error, subject *hcl.Range, context
func setName(v reflect.Value, name string) { func setName(v reflect.Value, name string) {
numFields := v.Elem().Type().NumField() numFields := v.Elem().Type().NumField()
for i := range numFields { for i := 0; i < numFields; i++ {
parts := strings.Split(v.Elem().Type().Field(i).Tag.Get("hcl"), ",") parts := strings.Split(v.Elem().Type().Field(i).Tag.Get("hcl"), ",")
for _, t := range parts[1:] { for _, t := range parts[1:] {
if t == "label" { if t == "label" {
@@ -911,10 +910,12 @@ func setName(v reflect.Value, name string) {
func getName(v reflect.Value) (string, bool) { func getName(v reflect.Value) (string, bool) {
numFields := v.Elem().Type().NumField() numFields := v.Elem().Type().NumField()
for i := range numFields { for i := 0; i < numFields; i++ {
parts := strings.Split(v.Elem().Type().Field(i).Tag.Get("hcl"), ",") parts := strings.Split(v.Elem().Type().Field(i).Tag.Get("hcl"), ",")
if slices.Contains(parts[1:], "label") { for _, t := range parts[1:] {
return v.Elem().Field(i).String(), true if t == "label" {
return v.Elem().Field(i).String(), true
}
} }
} }
return "", false return "", false
@@ -922,10 +923,12 @@ func getName(v reflect.Value) (string, bool) {
func getNameIndex(v reflect.Value) (int, bool) { func getNameIndex(v reflect.Value) (int, bool) {
numFields := v.Elem().Type().NumField() numFields := v.Elem().Type().NumField()
for i := range numFields { for i := 0; i < numFields; i++ {
parts := strings.Split(v.Elem().Type().Field(i).Tag.Get("hcl"), ",") parts := strings.Split(v.Elem().Type().Field(i).Tag.Get("hcl"), ",")
if slices.Contains(parts[1:], "label") { for _, t := range parts[1:] {
return i, true if t == "label" {
return i, true
}
} }
} }
return 0, false return 0, false
@@ -985,7 +988,7 @@ func key(ks ...any) uint64 {
return hash.Sum64() return hash.Sum64()
} }
func decodeBody(body hcl.Body, ctx *hcl.EvalContext, val any) hcl.Diagnostics { func decodeBody(body hcl.Body, ctx *hcl.EvalContext, val interface{}) hcl.Diagnostics {
dec := gohcl.DecodeOptions{ImpliedType: ImpliedType} dec := gohcl.DecodeOptions{ImpliedType: ImpliedType}
return dec.DecodeBody(body, ctx, val) return dec.DecodeBody(body, ctx, val)
} }

View File

@@ -43,7 +43,7 @@ import (
// In particular, ImpliedType will never use capsule types in its returned // In particular, ImpliedType will never use capsule types in its returned
// type, because it cannot know the capsule types supported by the calling // type, because it cannot know the capsule types supported by the calling
// program. // program.
func ImpliedType(gv any) (cty.Type, error) { func ImpliedType(gv interface{}) (cty.Type, error) {
rt := reflect.TypeOf(gv) rt := reflect.TypeOf(gv)
var path cty.Path var path cty.Path
return impliedType(rt, path) return impliedType(rt, path)
@@ -148,7 +148,7 @@ func structTagIndices(st reflect.Type) map[string]int {
ct := st.NumField() ct := st.NumField()
ret := make(map[string]int, ct) ret := make(map[string]int, ct)
for i := range ct { for i := 0; i < ct; i++ {
field := st.Field(i) field := st.Field(i)
attrName := field.Tag.Get("cty") attrName := field.Tag.Get("cty")
if attrName != "" { if attrName != "" {

View File

@@ -539,7 +539,7 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opts map[
node := dp.Node().Driver node := dp.Node().Driver
if node.IsMobyDriver() { if node.IsMobyDriver() {
for _, e := range so.Exports { for _, e := range so.Exports {
if e.Type == "moby" && e.Attrs["push"] != "" && !node.Features(ctx)[driver.DirectPush] { if e.Type == "moby" && e.Attrs["push"] != "" {
if ok, _ := strconv.ParseBool(e.Attrs["push"]); ok { if ok, _ := strconv.ParseBool(e.Attrs["push"]); ok {
pushNames = e.Attrs["name"] pushNames = e.Attrs["name"]
if pushNames == "" { if pushNames == "" {
@@ -622,7 +622,7 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opts map[
// This is fallback for some very old buildkit versions. // This is fallback for some very old buildkit versions.
// Note that the mediatype isn't really correct as most of the time it is image manifest and // Note that the mediatype isn't really correct as most of the time it is image manifest and
// not manifest list but actually both are handled because for Docker mediatypes the // not manifest list but actually both are handled because for Docker mediatypes the
// mediatype value in the Accept header does not seem to matter. // mediatype value in the Accpet header does not seem to matter.
s, ok = r.ExporterResponse[exptypes.ExporterImageDigestKey] s, ok = r.ExporterResponse[exptypes.ExporterImageDigestKey]
if ok { if ok {
descs = append(descs, specs.Descriptor{ descs = append(descs, specs.Descriptor{

View File

@@ -4,7 +4,6 @@ import (
"context" "context"
stderrors "errors" stderrors "errors"
"net" "net"
"slices"
"github.com/containerd/platforms" "github.com/containerd/platforms"
"github.com/docker/buildx/builder" "github.com/docker/buildx/builder"
@@ -38,7 +37,15 @@ func Dial(ctx context.Context, nodes []builder.Node, pw progress.Writer, platfor
for _, ls := range resolved { for _, ls := range resolved {
for _, rn := range ls { for _, rn := range ls {
if platform != nil { if platform != nil {
if !slices.ContainsFunc(rn.platforms, platforms.Only(*platform).Match) { p := *platform
var found bool
for _, pp := range rn.platforms {
if platforms.Only(p).Match(pp) {
found = true
break
}
}
if !found {
continue continue
} }
} }

View File

@@ -3,7 +3,6 @@ package build
import ( import (
"context" "context"
"fmt" "fmt"
"slices"
"sync" "sync"
"github.com/containerd/platforms" "github.com/containerd/platforms"
@@ -222,7 +221,7 @@ func (r *nodeResolver) get(p specs.Platform, matcher matchMaker, additionalPlatf
for i, node := range r.nodes { for i, node := range r.nodes {
platforms := node.Platforms platforms := node.Platforms
if additionalPlatforms != nil { if additionalPlatforms != nil {
platforms = slices.Clone(platforms) platforms = append([]specs.Platform{}, platforms...)
platforms = append(platforms, additionalPlatforms(i, node)...) platforms = append(platforms, additionalPlatforms(i, node)...)
} }
for _, p2 := range platforms { for _, p2 := range platforms {

View File

@@ -28,11 +28,11 @@ func TestSyncMultiReaderParallel(t *testing.T) {
readers := make([]io.ReadCloser, numReaders) readers := make([]io.ReadCloser, numReaders)
for i := range numReaders { for i := 0; i < numReaders; i++ {
readers[i] = mr.NewReadCloser() readers[i] = mr.NewReadCloser()
} }
for i := range numReaders { for i := 0; i < numReaders; i++ {
wg.Add(1) wg.Add(1)
go func(readerId int) { go func(readerId int) {
defer wg.Done() defer wg.Done()

View File

@@ -5,7 +5,6 @@ import (
"encoding/json" "encoding/json"
"net/url" "net/url"
"os" "os"
"slices"
"sort" "sort"
"strings" "strings"
"sync" "sync"
@@ -657,7 +656,13 @@ func parseBuildkitdFlags(inp string, driver string, driverOpts map[string]string
flags.StringArrayVar(&allowInsecureEntitlements, "allow-insecure-entitlement", nil, "") flags.StringArrayVar(&allowInsecureEntitlements, "allow-insecure-entitlement", nil, "")
_ = flags.Parse(res) _ = flags.Parse(res)
hasNetworkHostEntitlement := slices.Contains(allowInsecureEntitlements, "network.host") var hasNetworkHostEntitlement bool
for _, e := range allowInsecureEntitlements {
if e == "network.host" {
hasNetworkHostEntitlement = true
break
}
}
var hasNetworkHostEntitlementInConf bool var hasNetworkHostEntitlementInConf bool
if buildkitdConfigFile != "" { if buildkitdConfigFile != "" {
@@ -666,8 +671,11 @@ func parseBuildkitdFlags(inp string, driver string, driverOpts map[string]string
return nil, err return nil, err
} else if btoml != nil { } else if btoml != nil {
if ies := btoml.GetArray("insecure-entitlements"); ies != nil { if ies := btoml.GetArray("insecure-entitlements"); ies != nil {
if slices.Contains(ies.([]string), "network.host") { for _, e := range ies.([]string) {
hasNetworkHostEntitlementInConf = true if e == "network.host" {
hasNetworkHostEntitlementInConf = true
break
}
} }
} }
} }

View File

@@ -169,7 +169,7 @@ func (b *Builder) LoadNodes(ctx context.Context, opts ...LoadNodesOption) (_ []N
// dynamic nodes are used in Kubernetes driver. // dynamic nodes are used in Kubernetes driver.
// Kubernetes' pods are dynamically mapped to BuildKit Nodes. // Kubernetes' pods are dynamically mapped to BuildKit Nodes.
if di.DriverInfo != nil && len(di.DriverInfo.DynamicNodes) > 0 { if di.DriverInfo != nil && len(di.DriverInfo.DynamicNodes) > 0 {
for i := range di.DriverInfo.DynamicNodes { for i := 0; i < len(di.DriverInfo.DynamicNodes); i++ {
diClone := di diClone := di
if pl := di.DriverInfo.DynamicNodes[i].Platforms; len(pl) > 0 { if pl := di.DriverInfo.DynamicNodes[i].Platforms; len(pl) > 0 {
diClone.Platforms = pl diClone.Platforms = pl

View File

@@ -305,7 +305,7 @@ func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in ba
desktop.PrintBuildDetails(os.Stderr, printer.BuildRefs(), term) desktop.PrintBuildDetails(os.Stderr, printer.BuildRefs(), term)
} }
if len(in.metadataFile) > 0 { if len(in.metadataFile) > 0 {
dt := make(map[string]any) dt := make(map[string]interface{})
for t, r := range resp { for t, r := range resp {
dt[t] = decodeExporterResponse(r.ExporterResponse) dt[t] = decodeExporterResponse(r.ExporterResponse)
} }

View File

@@ -11,7 +11,6 @@ import (
"io" "io"
"os" "os"
"path/filepath" "path/filepath"
"slices"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
@@ -157,7 +156,7 @@ func (o *buildOptions) toControllerOptions() (*controllerapi.BuildOptions, error
return nil, err return nil, err
} }
inAttests := slices.Clone(o.attests) inAttests := append([]string{}, o.attests...)
if o.provenance != "" { if o.provenance != "" {
inAttests = append(inAttests, buildflags.CanonicalizeAttest("provenance", o.provenance)) inAttests = append(inAttests, buildflags.CanonicalizeAttest("provenance", o.provenance))
} }
@@ -741,7 +740,7 @@ func checkWarnedFlags(f *pflag.Flag) {
} }
} }
func writeMetadataFile(filename string, dt any) error { func writeMetadataFile(filename string, dt interface{}) error {
b, err := json.MarshalIndent(dt, "", " ") b, err := json.MarshalIndent(dt, "", " ")
if err != nil { if err != nil {
return err return err
@@ -749,7 +748,7 @@ func writeMetadataFile(filename string, dt any) error {
return atomicwriter.WriteFile(filename, b, 0644) return atomicwriter.WriteFile(filename, b, 0644)
} }
func decodeExporterResponse(exporterResponse map[string]string) map[string]any { func decodeExporterResponse(exporterResponse map[string]string) map[string]interface{} {
decFunc := func(k, v string) ([]byte, error) { decFunc := func(k, v string) ([]byte, error) {
if k == "result.json" { if k == "result.json" {
// result.json is part of metadata response for subrequests which // result.json is part of metadata response for subrequests which
@@ -758,16 +757,16 @@ func decodeExporterResponse(exporterResponse map[string]string) map[string]any {
} }
return base64.StdEncoding.DecodeString(v) return base64.StdEncoding.DecodeString(v)
} }
out := make(map[string]any) out := make(map[string]interface{})
for k, v := range exporterResponse { for k, v := range exporterResponse {
dt, err := decFunc(k, v) dt, err := decFunc(k, v)
if err != nil { if err != nil {
out[k] = v out[k] = v
continue continue
} }
var raw map[string]any 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]any var rawList []map[string]interface{}
if err = json.Unmarshal(dt, &rawList); err != nil || len(rawList) == 0 { if err = json.Unmarshal(dt, &rawList); err != nil || len(rawList) == 0 {
out[k] = v out[k] = v
continue continue

View File

@@ -124,7 +124,7 @@ func duCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
return cmd return cmd
} }
func printKV(w io.Writer, k string, v any) { func printKV(w io.Writer, k string, v interface{}) {
fmt.Fprintf(w, "%s:\t%v\n", k, v) fmt.Fprintf(w, "%s:\t%v\n", k, v)
} }

View File

@@ -1,135 +0,0 @@
package history
import (
"context"
"encoding/json"
"fmt"
"io"
"net"
"net/http"
"os"
"strings"
remoteutil "github.com/docker/buildx/driver/remote/util"
"github.com/docker/buildx/util/cobrautil/completion"
"github.com/docker/buildx/util/desktop"
"github.com/docker/cli/cli/command"
"github.com/pkg/browser"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
type importOptions struct {
file []string
}
func runImport(ctx context.Context, dockerCli command.Cli, opts importOptions) error {
sock, err := desktop.BuildServerAddr()
if err != nil {
return err
}
tr := http.DefaultTransport.(*http.Transport).Clone()
tr.DialContext = func(ctx context.Context, _, _ string) (net.Conn, error) {
network, addr, ok := strings.Cut(sock, "://")
if !ok {
return nil, errors.Errorf("invalid endpoint address: %s", sock)
}
return remoteutil.DialContext(ctx, network, addr)
}
client := &http.Client{
Transport: tr,
}
var urls []string
if len(opts.file) == 0 {
u, err := importFrom(ctx, client, os.Stdin)
if err != nil {
return err
}
urls = append(urls, u...)
} else {
for _, fn := range opts.file {
var f *os.File
var rdr io.Reader = os.Stdin
if fn != "-" {
f, err = os.Open(fn)
if err != nil {
return errors.Wrapf(err, "failed to open file %s", fn)
}
rdr = f
}
u, err := importFrom(ctx, client, rdr)
if err != nil {
return err
}
urls = append(urls, u...)
if f != nil {
f.Close()
}
}
}
if len(urls) == 0 {
return errors.New("no build records found in the bundle")
}
for i, url := range urls {
fmt.Fprintln(dockerCli.Err(), url)
if i == 0 {
err = browser.OpenURL(url)
}
}
return err
}
func importFrom(ctx context.Context, c *http.Client, rdr io.Reader) ([]string, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodPost, "http://docker-desktop/upload", rdr)
if err != nil {
return nil, errors.Wrap(err, "failed to create request")
}
resp, err := c.Do(req)
if err != nil {
return nil, errors.Wrap(err, "failed to send request, check if Docker Desktop is running")
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
return nil, errors.Errorf("failed to import build: %s", string(body))
}
var refs []string
dec := json.NewDecoder(resp.Body)
if err := dec.Decode(&refs); err != nil {
return nil, errors.Wrap(err, "failed to decode response")
}
var urls []string
for _, ref := range refs {
urls = append(urls, desktop.BuildURL(fmt.Sprintf(".imported/_/%s", ref)))
}
return urls, err
}
func importCmd(dockerCli command.Cli, _ RootOptions) *cobra.Command {
var options importOptions
cmd := &cobra.Command{
Use: "import [OPTIONS] < bundle.dockerbuild",
Short: "Import a build into Docker Desktop",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
return runImport(cmd.Context(), dockerCli, options)
},
ValidArgsFunction: completion.Disable,
}
flags := cmd.Flags()
flags.StringArrayVarP(&options.file, "file", "f", nil, "Import from a file path")
return cmd
}

View File

@@ -173,7 +173,7 @@ func runInspect(ctx context.Context, dockerCli command.Cli, opts inspectOptions)
} }
} }
recs, err := queryRecords(ctx, opts.ref, nodes, nil) recs, err := queryRecords(ctx, opts.ref, nodes)
if err != nil { if err != nil {
return err return err
} }
@@ -185,7 +185,14 @@ func runInspect(ctx context.Context, dockerCli command.Cli, opts inspectOptions)
return errors.Errorf("no record found for ref %q", opts.ref) return errors.Errorf("no record found for ref %q", opts.ref)
} }
if opts.ref == "" {
slices.SortFunc(recs, func(a, b historyRecord) int {
return b.CreatedAt.AsTime().Compare(a.CreatedAt.AsTime())
})
}
rec := &recs[0] rec := &recs[0]
c, err := rec.node.Driver.Client(ctx) c, err := rec.node.Driver.Client(ctx)
if err != nil { if err != nil {
return err return err
@@ -346,7 +353,7 @@ workers0:
out.Error.Name = name out.Error.Name = name
out.Error.Logs = logs out.Error.Logs = logs
} }
out.Error.Stack = fmt.Appendf(nil, "%+v", stack.Formatter(retErr)) out.Error.Stack = []byte(fmt.Sprintf("%+v", stack.Formatter(retErr)))
} }
} }

View File

@@ -3,6 +3,7 @@ package history
import ( import (
"context" "context"
"io" "io"
"slices"
"github.com/containerd/containerd/v2/core/content/proxy" "github.com/containerd/containerd/v2/core/content/proxy"
"github.com/containerd/platforms" "github.com/containerd/platforms"
@@ -41,7 +42,7 @@ func runAttachment(ctx context.Context, dockerCli command.Cli, opts attachmentOp
} }
} }
recs, err := queryRecords(ctx, opts.ref, nodes, nil) recs, err := queryRecords(ctx, opts.ref, nodes)
if err != nil { if err != nil {
return err return err
} }
@@ -53,6 +54,12 @@ func runAttachment(ctx context.Context, dockerCli command.Cli, opts attachmentOp
return errors.Errorf("no record found for ref %q", opts.ref) return errors.Errorf("no record found for ref %q", opts.ref)
} }
if opts.ref == "" {
slices.SortFunc(recs, func(a, b historyRecord) int {
return b.CreatedAt.AsTime().Compare(a.CreatedAt.AsTime())
})
}
rec := &recs[0] rec := &recs[0]
c, err := rec.node.Driver.Client(ctx) c, err := rec.node.Driver.Client(ctx)

View File

@@ -4,6 +4,7 @@ import (
"context" "context"
"io" "io"
"os" "os"
"slices"
"github.com/docker/buildx/builder" "github.com/docker/buildx/builder"
"github.com/docker/buildx/util/cobrautil/completion" "github.com/docker/buildx/util/cobrautil/completion"
@@ -38,7 +39,7 @@ func runLogs(ctx context.Context, dockerCli command.Cli, opts logsOptions) error
} }
} }
recs, err := queryRecords(ctx, opts.ref, nodes, nil) recs, err := queryRecords(ctx, opts.ref, nodes)
if err != nil { if err != nil {
return err return err
} }
@@ -50,6 +51,12 @@ func runLogs(ctx context.Context, dockerCli command.Cli, opts logsOptions) error
return errors.Errorf("no record found for ref %q", opts.ref) return errors.Errorf("no record found for ref %q", opts.ref)
} }
if opts.ref == "" {
slices.SortFunc(recs, func(a, b historyRecord) int {
return b.CreatedAt.AsTime().Compare(a.CreatedAt.AsTime())
})
}
rec := &recs[0] rec := &recs[0]
c, err := rec.node.Driver.Client(ctx) c, err := rec.node.Driver.Client(ctx)
if err != nil { if err != nil {

View File

@@ -56,7 +56,7 @@ func runLs(ctx context.Context, dockerCli command.Cli, opts lsOptions) error {
} }
} }
out, err := queryRecords(ctx, "", nodes, nil) out, err := queryRecords(ctx, "", nodes)
if err != nil { if err != nil {
return err return err
} }
@@ -161,7 +161,7 @@ type lsContext struct {
} }
func (c *lsContext) MarshalJSON() ([]byte, error) { func (c *lsContext) MarshalJSON() ([]byte, error) {
m := map[string]any{ m := map[string]interface{}{
"ref": c.FullRef(), "ref": c.FullRef(),
"name": c.Name(), "name": c.Name(),
"status": c.Status(), "status": c.Status(),

View File

@@ -3,6 +3,7 @@ package history
import ( import (
"context" "context"
"fmt" "fmt"
"slices"
"github.com/docker/buildx/builder" "github.com/docker/buildx/builder"
"github.com/docker/buildx/util/cobrautil/completion" "github.com/docker/buildx/util/cobrautil/completion"
@@ -34,7 +35,7 @@ func runOpen(ctx context.Context, dockerCli command.Cli, opts openOptions) error
} }
} }
recs, err := queryRecords(ctx, opts.ref, nodes, nil) recs, err := queryRecords(ctx, opts.ref, nodes)
if err != nil { if err != nil {
return err return err
} }
@@ -46,6 +47,12 @@ func runOpen(ctx context.Context, dockerCli command.Cli, opts openOptions) error
return errors.Errorf("no record found for ref %q", opts.ref) return errors.Errorf("no record found for ref %q", opts.ref)
} }
if opts.ref == "" {
slices.SortFunc(recs, func(a, b historyRecord) int {
return b.CreatedAt.AsTime().Compare(a.CreatedAt.AsTime())
})
}
rec := &recs[0] rec := &recs[0]
url := desktop.BuildURL(fmt.Sprintf("%s/%s/%s", rec.node.Builder, rec.node.Name, rec.Ref)) url := desktop.BuildURL(fmt.Sprintf("%s/%s/%s", rec.node.Builder, rec.node.Name, rec.Ref))

View File

@@ -25,7 +25,6 @@ func RootCmd(rootcmd *cobra.Command, dockerCli command.Cli, opts RootOptions) *c
inspectCmd(dockerCli, opts), inspectCmd(dockerCli, opts),
openCmd(dockerCli, opts), openCmd(dockerCli, opts),
traceCmd(dockerCli, opts), traceCmd(dockerCli, opts),
importCmd(dockerCli, opts),
) )
return cmd return cmd

View File

@@ -8,6 +8,9 @@ import (
"io" "io"
"net" "net"
"os" "os"
"slices"
"strconv"
"strings"
"time" "time"
"github.com/containerd/console" "github.com/containerd/console"
@@ -34,20 +37,51 @@ type traceOptions struct {
} }
func loadTrace(ctx context.Context, ref string, nodes []builder.Node) (string, []byte, error) { func loadTrace(ctx context.Context, ref string, nodes []builder.Node) (string, []byte, error) {
recs, err := queryRecords(ctx, ref, nodes, &queryOptions{ var offset *int
CompletedOnly: true, if strings.HasPrefix(ref, "^") {
}) off, err := strconv.Atoi(ref[1:])
if err != nil {
return "", nil, errors.Wrapf(err, "invalid offset %q", ref)
}
offset = &off
ref = ""
}
recs, err := queryRecords(ctx, ref, nodes)
if err != nil { if err != nil {
return "", nil, err return "", nil, err
} }
if len(recs) == 0 { var rec *historyRecord
if ref == "" {
slices.SortFunc(recs, func(a, b historyRecord) int {
return b.CreatedAt.AsTime().Compare(a.CreatedAt.AsTime())
})
for _, r := range recs {
if r.CompletedAt != nil {
if offset != nil {
if *offset > 0 {
*offset--
continue
}
}
rec = &r
break
}
}
if offset != nil && *offset > 0 {
return "", nil, errors.Errorf("no completed build found with offset %d", *offset)
}
} else {
rec = &recs[0]
}
if rec == nil {
if ref == "" { if ref == "" {
return "", nil, errors.New("no records found") return "", nil, errors.New("no records found")
} }
return "", nil, errors.Errorf("no record found for ref %q", ref) return "", nil, errors.Errorf("no record found for ref %q", ref)
} }
rec := &recs[0]
if rec.CompletedAt == nil { if rec.CompletedAt == nil {
return "", nil, errors.Errorf("build %q is not completed, only completed builds can be traced", rec.Ref) return "", nil, errors.Errorf("build %q is not completed, only completed builds can be traced", rec.Ref)
@@ -69,9 +103,7 @@ func loadTrace(ctx context.Context, ref string, nodes []builder.Node) (string, [
return "", nil, err return "", nil, err
} }
recs, err := queryRecords(ctx, rec.Ref, []builder.Node{*rec.node}, &queryOptions{ recs, err := queryRecords(ctx, rec.Ref, []builder.Node{*rec.node})
CompletedOnly: true,
})
if err != nil { if err != nil {
return "", nil, err return "", nil, err
} }

View File

@@ -5,8 +5,6 @@ import (
"fmt" "fmt"
"io" "io"
"path/filepath" "path/filepath"
"slices"
"strconv"
"strings" "strings"
"sync" "sync"
"time" "time"
@@ -108,24 +106,10 @@ type historyRecord struct {
name string name string
} }
type queryOptions struct { func queryRecords(ctx context.Context, ref string, nodes []builder.Node) ([]historyRecord, error) {
CompletedOnly bool
}
func queryRecords(ctx context.Context, ref string, nodes []builder.Node, opts *queryOptions) ([]historyRecord, error) {
var mu sync.Mutex var mu sync.Mutex
var out []historyRecord var out []historyRecord
var offset *int
if strings.HasPrefix(ref, "^") {
off, err := strconv.Atoi(ref[1:])
if err != nil {
return nil, errors.Wrapf(err, "invalid offset %q", ref)
}
offset = &off
ref = ""
}
eg, ctx := errgroup.WithContext(ctx) eg, ctx := errgroup.WithContext(ctx)
for _, node := range nodes { for _, node := range nodes {
node := node node := node
@@ -169,10 +153,6 @@ func queryRecords(ctx context.Context, ref string, nodes []builder.Node, opts *q
if he.Type == controlapi.BuildHistoryEventType_DELETED || he.Record == nil { if he.Type == controlapi.BuildHistoryEventType_DELETED || he.Record == nil {
continue continue
} }
if opts != nil && opts.CompletedOnly && he.Type != controlapi.BuildHistoryEventType_COMPLETE {
continue
}
records = append(records, historyRecord{ records = append(records, historyRecord{
BuildHistoryRecord: he.Record, BuildHistoryRecord: he.Record,
currentTimestamp: ts, currentTimestamp: ts,
@@ -189,27 +169,6 @@ func queryRecords(ctx context.Context, ref string, nodes []builder.Node, opts *q
if err := eg.Wait(); err != nil { if err := eg.Wait(); err != nil {
return nil, err return nil, err
} }
slices.SortFunc(out, func(a, b historyRecord) int {
return b.CreatedAt.AsTime().Compare(a.CreatedAt.AsTime())
})
if offset != nil {
var filtered []historyRecord
for _, r := range out {
if *offset > 0 {
*offset--
continue
}
filtered = append(filtered, r)
break
}
if *offset > 0 {
return nil, errors.Errorf("no completed build found with offset %d", *offset)
}
out = filtered
}
return out, nil return out, nil
} }

View File

@@ -194,7 +194,7 @@ func runCreate(ctx context.Context, dockerCli command.Cli, in createOptions, arg
} }
s := s s := s
eg2.Go(func() error { eg2.Go(func() error {
sub.Log(1, fmt.Appendf(nil, "copying %s from %s to %s\n", s.Desc.Digest.String(), s.Ref.String(), t.String())) sub.Log(1, []byte(fmt.Sprintf("copying %s from %s to %s\n", s.Desc.Digest.String(), s.Ref.String(), t.String())))
return r.Copy(ctx, s, t) return r.Copy(ctx, s, t)
}) })
} }
@@ -202,7 +202,7 @@ func runCreate(ctx context.Context, dockerCli command.Cli, in createOptions, arg
if err := eg2.Wait(); err != nil { if err := eg2.Wait(); err != nil {
return err return err
} }
sub.Log(1, fmt.Appendf(nil, "pushing %s to %s\n", desc.Digest.String(), t.String())) sub.Log(1, []byte(fmt.Sprintf("pushing %s to %s\n", desc.Digest.String(), t.String())))
return r.Push(ctx, t, desc, dt) return r.Push(ctx, t, desc, dt)
}) })
}) })

View File

@@ -13,8 +13,8 @@ import (
type BuildxController interface { type BuildxController interface {
Build(ctx context.Context, options *controllerapi.BuildOptions, in io.ReadCloser, progress progress.Writer) (ref string, resp *client.SolveResponse, inputs *build.Inputs, err error) Build(ctx context.Context, options *controllerapi.BuildOptions, in io.ReadCloser, progress progress.Writer) (ref string, resp *client.SolveResponse, inputs *build.Inputs, err error)
// Invoke starts an IO session into the specified process. // Invoke starts an IO session into the specified process.
// If pid doesn't match to any running processes, it starts a new process with the specified config. // If pid doesn't matche to any running processes, it starts a new process with the specified config.
// If there is no container running or InvokeConfig.Rollback is specified, the process will start in a newly created container. // If there is no container running or InvokeConfig.Rollback is speicfied, the process will start in a newly created container.
// NOTE: If needed, in the future, we can split this API into three APIs (NewContainer, NewProcess and Attach). // NOTE: If needed, in the future, we can split this API into three APIs (NewContainer, NewProcess and Attach).
Invoke(ctx context.Context, ref, pid string, options *controllerapi.InvokeConfig, ioIn io.ReadCloser, ioOut io.WriteCloser, ioErr io.WriteCloser) error Invoke(ctx context.Context, ref, pid string, options *controllerapi.InvokeConfig, ioIn io.ReadCloser, ioOut io.WriteCloser, ioErr io.WriteCloser) error
Kill(ctx context.Context) error Kill(ctx context.Context) error

View File

@@ -24,11 +24,11 @@ func (w *writer) Write(status *client.SolveStatus) {
func (w *writer) WriteBuildRef(target string, ref string) {} func (w *writer) WriteBuildRef(target string, ref string) {}
func (w *writer) ValidateLogSource(digest.Digest, any) bool { func (w *writer) ValidateLogSource(digest.Digest, interface{}) bool {
return true return true
} }
func (w *writer) ClearLogSource(any) {} func (w *writer) ClearLogSource(interface{}) {}
func ToControlStatus(s *client.SolveStatus) *StatusResponse { func ToControlStatus(s *client.SolveStatus) *StatusResponse {
resp := StatusResponse{} resp := StatusResponse{}

View File

@@ -1,8 +1,6 @@
package pb package pb
import ( import (
"slices"
"github.com/moby/buildkit/session" "github.com/moby/buildkit/session"
"github.com/moby/buildkit/session/sshforward/sshprovider" "github.com/moby/buildkit/session/sshforward/sshprovider"
) )
@@ -12,7 +10,7 @@ func CreateSSH(ssh []*SSH) (session.Attachable, error) {
for _, ssh := range ssh { for _, ssh := range ssh {
cfg := sshprovider.AgentConfig{ cfg := sshprovider.AgentConfig{
ID: ssh.ID, ID: ssh.ID,
Paths: slices.Clone(ssh.Paths), Paths: append([]string{}, ssh.Paths...),
} }
configs = append(configs, cfg) configs = append(configs, cfg)
} }

View File

@@ -39,7 +39,7 @@ func (p *Process) Done() <-chan error {
return p.errCh return p.errCh
} }
// Manager manages a set of processes. // Manager manages a set of proceses.
type Manager struct { type Manager struct {
container atomic.Value container atomic.Value
processes sync.Map processes sync.Map

View File

@@ -140,7 +140,7 @@ func serveCmd(dockerCli command.Cli) *cobra.Command {
return err return err
} }
pidF := filepath.Join(root, defaultPIDFilename) pidF := filepath.Join(root, defaultPIDFilename)
if err := os.WriteFile(pidF, fmt.Appendf(nil, "%d", os.Getpid()), 0600); err != nil { if err := os.WriteFile(pidF, []byte(fmt.Sprintf("%d", os.Getpid())), 0600); err != nil {
return err return err
} }
defer func() { defer func() {

View File

@@ -48,8 +48,6 @@ target "lint" {
"linux/s390x", "linux/s390x",
"linux/ppc64le", "linux/ppc64le",
"linux/riscv64", "linux/riscv64",
"netbsd/amd64",
"netbsd/arm64",
"openbsd/amd64", "openbsd/amd64",
"openbsd/arm64", "openbsd/arm64",
"windows/amd64", "windows/amd64",
@@ -169,8 +167,6 @@ target "binaries-cross" {
"linux/ppc64le", "linux/ppc64le",
"linux/riscv64", "linux/riscv64",
"linux/s390x", "linux/s390x",
"netbsd/amd64",
"netbsd/arm64",
"openbsd/amd64", "openbsd/amd64",
"openbsd/arm64", "openbsd/arm64",
"windows/amd64", "windows/amd64",

View File

@@ -347,22 +347,18 @@ is defined in https://golang.org/pkg/path/#Match.
```console ```console
$ docker buildx bake --set target.args.mybuildarg=value $ docker buildx bake --set target.args.mybuildarg=value
$ docker buildx bake --set target.platform=linux/arm64 $ docker buildx bake --set target.platform=linux/arm64
$ docker buildx bake --set foo*.args.mybuildarg=value # overrides build arg for all targets starting with 'foo' $ docker buildx bake --set foo*.args.mybuildarg=value # overrides build arg for all targets starting with 'foo'
$ docker buildx bake --set *.platform=linux/arm64 # overrides platform for all targets $ docker buildx bake --set *.platform=linux/arm64 # overrides platform for all targets
$ docker buildx bake --set foo*.no-cache # bypass caching only for targets starting with 'foo' $ docker buildx bake --set foo*.no-cache # bypass caching only for targets starting with 'foo'
$ docker buildx bake --set target.platform+=linux/arm64 # appends 'linux/arm64' to the platform list
``` ```
You can override the following fields: You can override the following fields:
* `annotations`
* `attest`
* `args` * `args`
* `cache-from` * `cache-from`
* `cache-to` * `cache-to`
* `context` * `context`
* `dockerfile` * `dockerfile`
* `entitlements`
* `labels` * `labels`
* `load` * `load`
* `no-cache` * `no-cache`
@@ -375,20 +371,3 @@ You can override the following fields:
* `ssh` * `ssh`
* `tags` * `tags`
* `target` * `target`
You can append using `+=` operator for the following fields:
* `annotations
* `attest
* `cache-from`
* `cache-to`
* `entitlements
* `no-cache-filter`
* `output`
* `platform`
* `secrets`
* `ssh`
* `tags`
> [!NOTE]
> ¹ These fields already append by default.

View File

@@ -7,7 +7,6 @@ Commands to work on build records
| Name | Description | | Name | Description |
|:---------------------------------------|:-----------------------------------------------| |:---------------------------------------|:-----------------------------------------------|
| [`import`](buildx_history_import.md) | Import a build into Docker Desktop |
| [`inspect`](buildx_history_inspect.md) | Inspect a build | | [`inspect`](buildx_history_inspect.md) | Inspect a build |
| [`logs`](buildx_history_logs.md) | Print the logs of a build | | [`logs`](buildx_history_logs.md) | Print the logs of a build |
| [`ls`](buildx_history_ls.md) | List build records | | [`ls`](buildx_history_ls.md) | List build records |

View File

@@ -1,16 +0,0 @@
# docker buildx history import
<!---MARKER_GEN_START-->
Import a build into Docker Desktop
### Options
| Name | Type | Default | Description |
|:----------------|:--------------|:--------|:-----------------------------------------|
| `--builder` | `string` | | Override the configured builder instance |
| `-D`, `--debug` | `bool` | | Enable debug logging |
| `-f`, `--file` | `stringArray` | | Import from a file path |
<!---MARKER_GEN_END-->

View File

@@ -420,7 +420,6 @@ func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool {
driver.DockerExporter: true, driver.DockerExporter: true,
driver.CacheExport: true, driver.CacheExport: true,
driver.MultiPlatform: true, driver.MultiPlatform: true,
driver.DirectPush: true,
driver.DefaultLoad: d.defaultLoad, driver.DefaultLoad: d.defaultLoad,
} }
} }

View File

@@ -93,7 +93,6 @@ func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool {
driver.DockerExporter: useContainerdSnapshotter, driver.DockerExporter: useContainerdSnapshotter,
driver.CacheExport: useContainerdSnapshotter, driver.CacheExport: useContainerdSnapshotter,
driver.MultiPlatform: useContainerdSnapshotter, driver.MultiPlatform: useContainerdSnapshotter,
driver.DirectPush: useContainerdSnapshotter,
driver.DefaultLoad: true, driver.DefaultLoad: true,
} }
}) })

View File

@@ -7,6 +7,5 @@ const DockerExporter Feature = "Docker exporter"
const CacheExport Feature = "Cache export" const CacheExport Feature = "Cache export"
const MultiPlatform Feature = "Multi-platform build" const MultiPlatform Feature = "Multi-platform build"
const DirectPush Feature = "Direct push"
const DefaultLoad Feature = "Automatically load images to the Docker Engine image store" const DefaultLoad Feature = "Automatically load images to the Docker Engine image store"

View File

@@ -35,10 +35,10 @@ func testEndpoint(server, defaultNamespace string, ca, cert, key []byte, skipTLS
} }
var testStoreCfg = store.NewConfig( var testStoreCfg = store.NewConfig(
func() any { func() interface{} {
return &map[string]any{} return &map[string]interface{}{}
}, },
store.EndpointTypeGetter(KubernetesEndpoint, func() any { return &EndpointMeta{} }), store.EndpointTypeGetter(KubernetesEndpoint, func() interface{} { return &EndpointMeta{} }),
) )
func TestSaveLoadContexts(t *testing.T) { func TestSaveLoadContexts(t *testing.T) {
@@ -197,7 +197,7 @@ func checkClientConfig(t *testing.T, ep Endpoint, server, namespace string, ca,
func save(s store.Writer, ep Endpoint, name string) error { func save(s store.Writer, ep Endpoint, name string) error {
meta := store.Metadata{ meta := store.Metadata{
Endpoints: map[string]any{ Endpoints: map[string]interface{}{
KubernetesEndpoint: ep.EndpointMeta, KubernetesEndpoint: ep.EndpointMeta,
}, },
Name: name, Name: name,

View File

@@ -43,7 +43,7 @@ type Endpoint struct {
func init() { func init() {
command.RegisterDefaultStoreEndpoints( command.RegisterDefaultStoreEndpoints(
store.EndpointTypeGetter(KubernetesEndpoint, func() any { return &EndpointMeta{} }), store.EndpointTypeGetter(KubernetesEndpoint, func() interface{} { return &EndpointMeta{} }),
) )
} }
@@ -96,7 +96,7 @@ func (c *Endpoint) KubernetesConfig() clientcmd.ClientConfig {
// ResolveDefault returns endpoint metadata for the default Kubernetes // ResolveDefault returns endpoint metadata for the default Kubernetes
// endpoint, which is derived from the env-based kubeconfig. // endpoint, which is derived from the env-based kubeconfig.
func (c *EndpointMeta) ResolveDefault() (any, *store.EndpointTLSData, error) { func (c *EndpointMeta) ResolveDefault() (interface{}, *store.EndpointTLSData, error) {
kubeconfig := os.Getenv("KUBECONFIG") kubeconfig := os.Getenv("KUBECONFIG")
if kubeconfig == "" { if kubeconfig == "" {
kubeconfig = filepath.Join(homedir.Get(), ".kube/config") kubeconfig = filepath.Join(homedir.Get(), ".kube/config")

View File

@@ -238,7 +238,6 @@ func (d *Driver) Features(_ context.Context) map[driver.Feature]bool {
driver.DockerExporter: d.DockerAPI != nil, driver.DockerExporter: d.DockerAPI != nil,
driver.CacheExport: true, driver.CacheExport: true,
driver.MultiPlatform: true, // Untested (needs multiple Driver instances) driver.MultiPlatform: true, // Untested (needs multiple Driver instances)
driver.DirectPush: true,
driver.DefaultLoad: d.defaultLoad, driver.DefaultLoad: d.defaultLoad,
} }
} }

View File

@@ -90,7 +90,7 @@ func ListRunningPods(ctx context.Context, client clientcorev1.PodInterface, depl
for i := range podList.Items { for i := range podList.Items {
pod := &podList.Items[i] pod := &podList.Items[i]
if pod.Status.Phase == corev1.PodRunning { if pod.Status.Phase == corev1.PodRunning {
logrus.Debugf("pod running: %q", pod.Name) logrus.Debugf("pod runnning: %q", pod.Name)
runningPods = append(runningPods, pod) runningPods = append(runningPods, pod)
} }
} }

View File

@@ -25,7 +25,7 @@ func GenerateNodeName(builderName string, txn *store.Txn) (string, error) {
} }
var name string var name string
for range 6 { for i := 0; i < 6; i++ {
name, err = randomName() name, err = randomName()
if err != nil { if err != nil {
return "", err return "", err

View File

@@ -164,7 +164,6 @@ func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool {
driver.DockerExporter: true, driver.DockerExporter: true,
driver.CacheExport: true, driver.CacheExport: true,
driver.MultiPlatform: true, driver.MultiPlatform: true,
driver.DirectPush: true,
driver.DefaultLoad: d.defaultLoad, driver.DefaultLoad: d.defaultLoad,
} }
} }

10
go.mod
View File

@@ -6,9 +6,9 @@ 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.27.27 github.com/aws/aws-sdk-go-v2/config v1.27.27
github.com/compose-spec/compose-go/v2 v2.4.8 github.com/compose-spec/compose-go/v2 v2.4.7
github.com/containerd/console v1.0.4 github.com/containerd/console v1.0.4
github.com/containerd/containerd/v2 v2.0.3 github.com/containerd/containerd/v2 v2.0.2
github.com/containerd/continuity v0.4.5 github.com/containerd/continuity v0.4.5
github.com/containerd/errdefs v1.0.0 github.com/containerd/errdefs v1.0.0
github.com/containerd/log v0.1.0 github.com/containerd/log v0.1.0
@@ -17,9 +17,9 @@ require (
github.com/creack/pty v1.1.24 github.com/creack/pty v1.1.24
github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew v1.1.1
github.com/distribution/reference v0.6.0 github.com/distribution/reference v0.6.0
github.com/docker/cli v28.0.1+incompatible github.com/docker/cli v28.0.0-rc.2+incompatible
github.com/docker/cli-docs-tool v0.9.0 github.com/docker/cli-docs-tool v0.9.0
github.com/docker/docker v28.0.1+incompatible github.com/docker/docker v28.0.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
@@ -29,7 +29,7 @@ require (
github.com/hashicorp/hcl/v2 v2.23.0 github.com/hashicorp/hcl/v2 v2.23.0
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.20.1 github.com/moby/buildkit v0.20.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

30
go.sum
View File

@@ -77,16 +77,16 @@ github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004 h1:lkAMpLVBDaj17e
github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
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.8 h1:7Myl8wDRl/4mRz77S+eyDJymGGEHu0diQdGSSeyq90A= github.com/compose-spec/compose-go/v2 v2.4.7 h1:WNpz5bIbKG+G+w9pfu72B1ZXr+Og9jez8TMEo8ecXPk=
github.com/compose-spec/compose-go/v2 v2.4.8/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/compose-spec/compose-go/v2 v2.4.7/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc=
github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo= github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins= github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
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/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0= github.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0=
github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc=
github.com/containerd/containerd/v2 v2.0.3 h1:zBKgwgZsuu+LPCMzCLgA4sC4MiZzZ59ZT31XkmiISQM= github.com/containerd/containerd/v2 v2.0.2 h1:GmH/tRBlTvrXOLwSpWE2vNAm8+MqI6nmxKpKBNKY8Wc=
github.com/containerd/containerd/v2 v2.0.3/go.mod h1:5j9QUUaV/cy9ZeAx4S+8n9ffpf+iYnEj4jiExgcbuLY= github.com/containerd/containerd/v2 v2.0.2/go.mod h1:wIqEvQ/6cyPFUGJ5yMFanspPabMLor+bF865OHvNTTI=
github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4= github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
@@ -122,15 +122,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 v28.0.1+incompatible h1:g0h5NQNda3/CxIsaZfH4Tyf6vpxFth7PYl3hgCPOKzs= github.com/docker/cli v28.0.0-rc.2+incompatible h1:2N1dpr3qtlJwIQpqXm7oNwWNAUGzpKlsCeJ32ejvpTk=
github.com/docker/cli v28.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v28.0.0-rc.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli-docs-tool v0.9.0 h1:CVwQbE+ZziwlPqrJ7LRyUF6GvCA+6gj7MTCsayaK9t0= github.com/docker/cli-docs-tool v0.9.0 h1:CVwQbE+ZziwlPqrJ7LRyUF6GvCA+6gj7MTCsayaK9t0=
github.com/docker/cli-docs-tool v0.9.0/go.mod h1:ClrwlNW+UioiRyH9GiAOe1o3J/TsY3Tr1ipoypjAUtc= github.com/docker/cli-docs-tool v0.9.0/go.mod h1:ClrwlNW+UioiRyH9GiAOe1o3J/TsY3Tr1ipoypjAUtc=
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 v28.0.1+incompatible h1:FCHjSRdXhNRFjlHMTv4jUNlIBbTeRjrWfeFuJp7jpo0= github.com/docker/docker v28.0.0-rc.2+incompatible h1:p+Ri+C0mmbPkhYVD9Sxnp/TnNnZoQWEj/EwOC465Uq4=
github.com/docker/docker v28.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v28.0.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=
@@ -152,6 +152,8 @@ github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqFfzE= github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqFfzE=
github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
@@ -295,8 +297,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.20.1 h1:sT0ZXhhNo5rVbMcYfgttma3TdUHfO5JjFA0UAL8p9fY= github.com/moby/buildkit v0.20.0 h1:aF5RujjQ310Pn6SLL/wQYIrSsPXy0sQ5KvWifwq1h8Y=
github.com/moby/buildkit v0.20.1/go.mod h1:Rq9nB/fJImdk6QeM0niKtOHJqwKeYMrK847hTTDVuA4= github.com/moby/buildkit v0.20.0/go.mod h1:HYFUIK+iGDRxRgdphZ9Nv0y1Fz7mv0HrU7xZoXx217E=
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=
@@ -349,6 +351,8 @@ github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQ
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk= github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 h1:DmNGcqH3WDbV5k8OJ+esPWbqUOX5rMLR2PMvziDMJi0=
github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626/go.mod h1:BRHJJd0E+cx42OybVYSgUvZmU0B8P9gZuRXlZUP7TKI=
github.com/opencontainers/selinux v1.11.1 h1:nHFvthhM0qY8/m+vfhJylliSshm8G1jJ2jDMcgULaH8= github.com/opencontainers/selinux v1.11.1 h1:nHFvthhM0qY8/m+vfhJylliSshm8G1jJ2jDMcgULaH8=
github.com/opencontainers/selinux v1.11.1/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= github.com/opencontainers/selinux v1.11.1/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
@@ -433,6 +437,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4DzbAiAiEL3c= github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4DzbAiAiEL3c=
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=
@@ -626,3 +632,7 @@ sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+s
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
tags.cncf.io/container-device-interface v0.8.0 h1:8bCFo/g9WODjWx3m6EYl3GfUG31eKJbaggyBDxEldRc=
tags.cncf.io/container-device-interface v0.8.0/go.mod h1:Apb7N4VdILW0EVdEMRYXIDVRZfNJZ+kmEUss2kRRQ6Y=
tags.cncf.io/container-device-interface/specs-go v0.8.0 h1:QYGFzGxvYK/ZLMrjhvY0RjpUavIn4KcmRmVP/JjdBTA=
tags.cncf.io/container-device-interface/specs-go v0.8.0/go.mod h1:BhJIkjjPh4qpys+qm4DAYtUyryaTDg9zris+AczXyws=

View File

@@ -9,13 +9,10 @@ Vagrant.configure("2") do |config|
config.vm.provision "init", type: "shell", run: "once" do |sh| config.vm.provision "init", type: "shell", run: "once" do |sh|
sh.inline = <<~SHELL sh.inline = <<~SHELL
set -x
pkg bootstrap pkg bootstrap
pkg install -y git pkg install -y go123 git
ln -s /usr/local/bin/go123 /usr/local/bin/go
fetch https://go.dev/dl/go#{ENV['GO_VERSION']}.freebsd-amd64.tar.gz go install gotest.tools/gotestsum@#{ENV['GOTESTSUM_VERSION']}
tar -C /usr/local -xzf go#{ENV['GO_VERSION']}.freebsd-amd64.tar.gz
ln -s /usr/local/go/bin/go /usr/local/bin/go
SHELL SHELL
end end
end end

View File

@@ -1,32 +0,0 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.box = "generic/netbsd9"
config.vm.boot_timeout = 900
config.vm.synced_folder ".", "/vagrant", type: "rsync"
config.ssh.keep_alive = true
config.vm.provision "init", type: "shell", run: "once" do |sh|
sh.inline = <<~SHELL
set -x
mkdir -p /var/tmp
chmod 1777 /var/tmp
pkgin -y install git mozilla-rootcerts
mozilla-rootcerts install
ftp https://go.dev/dl/go#{ENV['GO_VERSION']}.netbsd-amd64.tar.gz
tar -C /var/tmp -xzf go#{ENV['GO_VERSION']}.netbsd-amd64.tar.gz
cat << 'EOF' > /usr/bin/go-wrapper
#!/bin/sh
export TMPDIR="/var/tmp"
exec /var/tmp/go/bin/go "$@"
EOF
chmod +x /usr/bin/go-wrapper
ln -s /usr/bin/go-wrapper /usr/bin/go
SHELL
end
end

View File

@@ -10,12 +10,12 @@ Vagrant.configure("2") do |config|
config.vm.provision "init", type: "shell", run: "once" do |sh| config.vm.provision "init", type: "shell", run: "once" do |sh|
sh.inline = <<~SHELL sh.inline = <<~SHELL
set -x
pkg_add -x git pkg_add -x git
ftp https://go.dev/dl/go#{ENV['GO_VERSION']}.openbsd-amd64.tar.gz ftp https://go.dev/dl/go1.23.3.openbsd-amd64.tar.gz
tar -C /usr/local -xzf go#{ENV['GO_VERSION']}.openbsd-amd64.tar.gz tar -C /usr/local -xzf go1.23.3.openbsd-amd64.tar.gz
ln -s /usr/local/go/bin/go /usr/local/bin/go ln -s /usr/local/go/bin/go /usr/local/bin/go
go install gotest.tools/gotestsum@#{ENV['GOTESTSUM_VERSION']}
SHELL SHELL
end end
end end

View File

@@ -5,10 +5,9 @@ ARG ALPINE_VERSION=3.21
ARG XX_VERSION=1.6.1 ARG XX_VERSION=1.6.1
ARG GOLANGCI_LINT_VERSION=1.62.0 ARG GOLANGCI_LINT_VERSION=1.62.0
# v0.31 requires go1.24 ARG GOPLS_VERSION=v0.26.0
ARG GOPLS_VERSION=v0.30.0
# disabled: deprecated unusedvariable simplifyrange # disabled: deprecated unusedvariable simplifyrange
ARG GOPLS_ANALYZERS="embeddirective fillreturns hostport infertypeargs modernize nonewvars noresultvalues simplifycompositelit simplifyslice unusedparams yield" ARG GOPLS_ANALYZERS="embeddirective fillreturns infertypeargs nonewvars 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

@@ -4,7 +4,6 @@ import (
"context" "context"
"fmt" "fmt"
"io" "io"
"slices"
"github.com/docker/buildx/monitor/types" "github.com/docker/buildx/monitor/types"
"github.com/pkg/errors" "github.com/pkg/errors"
@@ -51,7 +50,14 @@ func (cm *AttachCmd) Exec(ctx context.Context, args []string) error {
if err != nil { if err != nil {
return errors.Errorf("failed to get the list of sessions: %v", err) return errors.Errorf("failed to get the list of sessions: %v", err)
} }
if !slices.Contains(refs, ref) { found := false
for _, s := range refs {
if s == ref {
found = true
break
}
}
if !found {
return errors.Errorf("unknown ID: %q", ref) return errors.Errorf("unknown ID: %q", ref)
} }
cm.m.Detach() // Finish existing attach cm.m.Detach() // Finish existing attach

View File

@@ -2,7 +2,6 @@ package store
import ( import (
"fmt" "fmt"
"slices"
"time" "time"
"github.com/containerd/platforms" "github.com/containerd/platforms"
@@ -45,7 +44,7 @@ func (ng *NodeGroup) Leave(name string) error {
if len(ng.Nodes) == 1 { if len(ng.Nodes) == 1 {
return errors.Errorf("can not leave last node, do you want to rm instance instead?") return errors.Errorf("can not leave last node, do you want to rm instance instead?")
} }
ng.Nodes = slices.Delete(ng.Nodes, i, i+1) ng.Nodes = append(ng.Nodes[:i], ng.Nodes[i+1:]...)
return nil return nil
} }

View File

@@ -39,7 +39,7 @@ func ValidateName(s string) (string, error) {
func GenerateName(txn *Txn) (string, error) { func GenerateName(txn *Txn) (string, error) {
var name string var name string
for i := range 6 { for i := 0; i < 6; i++ {
name = namesgenerator.GetRandomName(i) name = namesgenerator.GetRandomName(i)
if _, err := txn.NodeGroupByName(name); err != nil { if _, err := txn.NodeGroupByName(name); err != nil {
if !os.IsNotExist(errors.Cause(err)) { if !os.IsNotExist(errors.Cause(err)) {

View File

@@ -1016,11 +1016,11 @@ FROM scratch
COPY foo /foo COPY foo /foo
`) `)
destDir := t.TempDir() destDir := t.TempDir()
bakefile := fmt.Appendf(nil, ` bakefile := []byte(fmt.Sprintf(`
target "default" { target "default" {
output = ["type=local,dest=%s/not/exists"] output = ["type=local,dest=%s/not/exists"]
} }
`, destDir) `, destDir))
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("docker-bake.hcl", bakefile, 0600), fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
@@ -1050,11 +1050,11 @@ FROM scratch
COPY foo /foo COPY foo /foo
`) `)
destDir := t.TempDir() destDir := t.TempDir()
bakefile := fmt.Appendf(nil, ` bakefile := []byte(fmt.Sprintf(`
target "default" { target "default" {
output = ["type=local,dest=%s"] output = ["type=local,dest=%s"]
} }
`, destDir) `, destDir))
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("docker-bake.hcl", bakefile, 0600), fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
@@ -1151,11 +1151,11 @@ COPY Dockerfile /foo
keyDir := t.TempDir() keyDir := t.TempDir()
err := writeTempPrivateKey(filepath.Join(keyDir, "id_rsa")) err := writeTempPrivateKey(filepath.Join(keyDir, "id_rsa"))
require.NoError(t, err) require.NoError(t, err)
bakefile := fmt.Appendf(nil, ` bakefile := []byte(fmt.Sprintf(`
target "default" { target "default" {
ssh = ["key=%s"] ssh = ["key=%s"]
} }
`, filepath.Join(keyDir, "id_rsa")) `, filepath.Join(keyDir, "id_rsa")))
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("docker-bake.hcl", bakefile, 0600), fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
@@ -1314,8 +1314,8 @@ target "default" {
type mdT struct { type mdT struct {
Default struct { Default struct {
BuildRef string `json:"buildx.build.ref"` BuildRef string `json:"buildx.build.ref"`
BuildProvenance map[string]any `json:"buildx.build.provenance"` BuildProvenance map[string]interface{} `json:"buildx.build.provenance"`
} `json:"default"` } `json:"default"`
} }
var md mdT var md mdT

View File

@@ -804,8 +804,8 @@ func buildMetadataProvenance(t *testing.T, sb integration.Sandbox, metadataMode
require.NoError(t, err) require.NoError(t, err)
type mdT struct { type mdT struct {
BuildRef string `json:"buildx.build.ref"` BuildRef string `json:"buildx.build.ref"`
BuildProvenance map[string]any `json:"buildx.build.provenance"` BuildProvenance map[string]interface{} `json:"buildx.build.provenance"`
} }
var md mdT var md mdT
err = json.Unmarshal(dt, &md) err = json.Unmarshal(dt, &md)

View File

@@ -50,7 +50,7 @@ func withDir(dir string) cmdOpt {
func buildxCmd(sb integration.Sandbox, opts ...cmdOpt) *exec.Cmd { func buildxCmd(sb integration.Sandbox, opts ...cmdOpt) *exec.Cmd {
cmd := exec.Command("buildx") cmd := exec.Command("buildx")
cmd.Env = os.Environ() cmd.Env = append([]string{}, os.Environ()...)
for _, opt := range opts { for _, opt := range opts {
opt(cmd) opt(cmd)
} }
@@ -77,7 +77,7 @@ func buildxCmd(sb integration.Sandbox, opts ...cmdOpt) *exec.Cmd {
func dockerCmd(sb integration.Sandbox, opts ...cmdOpt) *exec.Cmd { func dockerCmd(sb integration.Sandbox, opts ...cmdOpt) *exec.Cmd {
cmd := exec.Command("docker") cmd := exec.Command("docker")
cmd.Env = os.Environ() cmd.Env = append([]string{}, os.Environ()...)
for _, opt := range opts { for _, opt := range opts {
opt(cmd) opt(cmd)
} }
@@ -214,7 +214,7 @@ func skipNoCompatBuildKit(t *testing.T, sb integration.Sandbox, constraint strin
} }
} }
func ptrstr(s any) *string { func ptrstr(s interface{}) *string {
var n *string var n *string
if reflect.ValueOf(s).Kind() == reflect.String { if reflect.ValueOf(s).Kind() == reflect.String {
ss := s.(string) ss := s.(string)

View File

@@ -45,7 +45,7 @@ func testRmMulti(t *testing.T, sb integration.Sandbox) {
} }
var builderNames []string var builderNames []string
for range 3 { for i := 0; i < 3; i++ {
out, err := createCmd(sb, withArgs("--driver", "docker-container")) out, err := createCmd(sb, withArgs("--driver", "docker-container"))
require.NoError(t, err, out) require.NoError(t, err, out)
builderName := strings.TrimSpace(out) builderName := strings.TrimSpace(out)

View File

@@ -2,7 +2,6 @@ package workers
import ( import (
"os" "os"
"slices"
"strings" "strings"
"github.com/moby/buildkit/util/testutil/integration" "github.com/moby/buildkit/util/testutil/integration"
@@ -50,14 +49,23 @@ func (s *backend) ExtraEnv() []string {
func (s backend) Supports(feature string) bool { func (s backend) Supports(feature string) bool {
if enabledFeatures := os.Getenv("BUILDKIT_TEST_ENABLE_FEATURES"); enabledFeatures != "" { if enabledFeatures := os.Getenv("BUILDKIT_TEST_ENABLE_FEATURES"); enabledFeatures != "" {
if slices.Contains(strings.Split(enabledFeatures, ","), feature) { for _, enabledFeature := range strings.Split(enabledFeatures, ",") {
return true if feature == enabledFeature {
return true
}
} }
} }
if disabledFeatures := os.Getenv("BUILDKIT_TEST_DISABLE_FEATURES"); disabledFeatures != "" { if disabledFeatures := os.Getenv("BUILDKIT_TEST_DISABLE_FEATURES"); disabledFeatures != "" {
if slices.Contains(strings.Split(disabledFeatures, ","), feature) { for _, disabledFeature := range strings.Split(disabledFeatures, ",") {
if feature == disabledFeature {
return false
}
}
}
for _, unsupportedFeature := range s.unsupportedFeatures {
if feature == unsupportedFeature {
return false return false
} }
} }
return !slices.Contains(s.unsupportedFeatures, feature) return true
} }

View File

@@ -90,7 +90,7 @@ func (a *Attest) ToPB() *controllerapi.Attest {
} }
func (a *Attest) MarshalJSON() ([]byte, error) { func (a *Attest) MarshalJSON() ([]byte, error) {
m := make(map[string]any, len(a.Attrs)+2) m := make(map[string]interface{}, len(a.Attrs)+2)
for k, v := range a.Attrs { for k, v := range a.Attrs {
m[k] = v m[k] = v
} }
@@ -102,7 +102,7 @@ func (a *Attest) MarshalJSON() ([]byte, error) {
} }
func (a *Attest) UnmarshalJSON(data []byte) error { func (a *Attest) UnmarshalJSON(data []byte) error {
var m map[string]any var m map[string]interface{}
if err := json.Unmarshal(data, &m); err != nil { if err := json.Unmarshal(data, &m); err != nil {
return err return err
} }

View File

@@ -150,7 +150,7 @@ func (e *CacheOptionsEntry) UnmarshalText(text []byte) error {
return e.validate(text) return e.validate(text)
} }
func (e *CacheOptionsEntry) validate(gv any) error { func (e *CacheOptionsEntry) validate(gv interface{}) error {
if e.Type == "" { if e.Type == "" {
var text []byte var text []byte
switch gv := gv.(type) { switch gv := gv.(type) {

View File

@@ -27,7 +27,7 @@ func (s Secrets) Normalize() Secrets {
if len(s) == 0 { if len(s) == 0 {
return nil return nil
} }
return removeSecretDupes(s) return removeDupes(s)
} }
func (s Secrets) ToPB() []*controllerapi.Secret { func (s Secrets) ToPB() []*controllerapi.Secret {
@@ -155,17 +155,3 @@ func parseSecret(value string) (*controllerapi.Secret, error) {
} }
return s.ToPB(), nil return s.ToPB(), nil
} }
func removeSecretDupes(s []*Secret) []*Secret {
var res []*Secret
m := map[string]int{}
for _, sec := range s {
if i, ok := m[sec.ID]; ok {
res[i] = sec
} else {
m[sec.ID] = len(res)
res = append(res, sec)
}
}
return res
}

View File

@@ -81,17 +81,4 @@ func TestSecrets(t *testing.T) {
result := actual.Equals(expected) result := actual.Equals(expected)
require.True(t, result.True()) require.True(t, result.True())
}) })
t.Run("RemoveDupes", func(t *testing.T) {
secrets := Secrets{
{ID: "mysecret", Env: "FOO"},
{ID: "mysecret", Env: "BAR"},
{ID: "mysecret2", Env: "BAZ"},
}.Normalize()
expected := `[{"id":"mysecret","env":"BAR"},{"id":"mysecret2","env":"BAZ"}]`
actual, err := json.Marshal(secrets)
require.NoError(t, err)
require.JSONEq(t, expected, string(actual))
})
} }

View File

@@ -28,7 +28,7 @@ func (s SSHKeys) Normalize() SSHKeys {
if len(s) == 0 { if len(s) == 0 {
return nil return nil
} }
return removeSSHDupes(s) return removeDupes(s)
} }
func (s SSHKeys) ToPB() []*controllerapi.SSH { func (s SSHKeys) ToPB() []*controllerapi.SSH {
@@ -131,17 +131,3 @@ func IsGitSSH(repo string) bool {
} }
return url.Scheme == gitutil.SSHProtocol return url.Scheme == gitutil.SSHProtocol
} }
func removeSSHDupes(s []*SSH) []*SSH {
var res []*SSH
m := map[string]int{}
for _, ssh := range s {
if i, ok := m[ssh.ID]; ok {
res[i] = ssh
} else {
m[ssh.ID] = len(res)
res = append(res, ssh)
}
}
return res
}

View File

@@ -82,17 +82,4 @@ func TestSSHKeys(t *testing.T) {
result := actual.Equals(expected) result := actual.Equals(expected)
require.True(t, result.True()) require.True(t, result.True())
}) })
t.Run("RemoveDupes", func(t *testing.T) {
sshkeys := SSHKeys{
{ID: "default"},
{ID: "key", Paths: []string{"path/to/foo"}},
{ID: "key", Paths: []string{"path/to/bar"}},
}.Normalize()
expected := `[{"id":"default"},{"id":"key","paths":["path/to/bar"]}]`
actual, err := json.Marshal(sshkeys)
require.NoError(t, err)
require.JSONEq(t, expected, string(actual))
})
} }

View File

@@ -33,7 +33,7 @@ func removeDupes[E comparable[E]](s []E) []E {
return s return s
} }
func getAndDelete(m map[string]cty.Value, attr string, gv any) error { func getAndDelete(m map[string]cty.Value, attr string, gv interface{}) error {
if v, ok := m[attr]; ok && v.IsKnown() { if v, ok := m[attr]; ok && v.IsKnown() {
delete(m, attr) delete(m, attr)
return gocty.FromCtyValue(v, gv) return gocty.FromCtyValue(v, gv)

View File

@@ -1,21 +0,0 @@
package desktop
import (
"os"
"path/filepath"
"github.com/pkg/errors"
)
const (
socketName = "docker-desktop-build.sock"
socketPath = "Library/Containers/com.docker.docker/Data"
)
func BuildServerAddr() (string, error) {
dir, err := os.UserHomeDir()
if err != nil {
return "", errors.Wrap(err, "failed to get user home directory")
}
return "unix://" + filepath.Join(dir, socketPath, socketName), nil
}

View File

@@ -1,29 +0,0 @@
package desktop
import (
"os"
"path/filepath"
"github.com/pkg/errors"
)
const (
socketName = "docker-desktop-build.sock"
socketPath = ".docker/desktop"
wslSocketPath = "/mnt/wsl/docker-desktop/shared-sockets/host-services"
)
func BuildServerAddr() (string, error) {
if os.Getenv("WSL_DISTRO_NAME") != "" {
socket := filepath.Join(wslSocketPath, socketName)
if _, err := os.Stat(socket); os.IsNotExist(err) {
return "", errors.New("Docker Desktop Build backend is not yet supported on WSL. Please run this command on Windows host instead.") //nolint:revive
}
return "unix://" + socket, nil
}
dir, err := os.UserHomeDir()
if err != nil {
return "", errors.Wrap(err, "failed to get user home directory")
}
return "unix://" + filepath.Join(dir, socketPath, socketName), nil
}

View File

@@ -1,13 +0,0 @@
//go:build !windows && !darwin && !linux
package desktop
import (
"runtime"
"github.com/pkg/errors"
)
func BuildServerAddr() (string, error) {
return "", errors.Errorf("Docker Desktop unsupported on %s", runtime.GOOS)
}

View File

@@ -1,5 +0,0 @@
package desktop
func BuildServerAddr() (string, error) {
return "npipe:////./pipe/dockerDesktopBuildServer", nil
}

View File

@@ -156,7 +156,7 @@ func (r *Resolver) Combine(ctx context.Context, srcs []*Source, ann map[exptypes
case exptypes.AnnotationIndex: case exptypes.AnnotationIndex:
indexAnnotation[k.Key] = v indexAnnotation[k.Key] = v
case exptypes.AnnotationManifestDescriptor: case exptypes.AnnotationManifestDescriptor:
for i := range newDescs { for i := 0; i < len(newDescs); i++ {
if newDescs[i].Annotations == nil { if newDescs[i].Annotations == nil {
newDescs[i].Annotations = map[string]string{} newDescs[i].Annotations = map[string]string{}
} }
@@ -194,11 +194,8 @@ func (r *Resolver) Combine(ctx context.Context, srcs []*Source, ann map[exptypes
func (r *Resolver) Push(ctx context.Context, ref reference.Named, desc ocispec.Descriptor, dt []byte) error { func (r *Resolver) Push(ctx context.Context, ref reference.Named, desc ocispec.Descriptor, dt []byte) error {
ctx = remotes.WithMediaTypeKeyPrefix(ctx, "application/vnd.in-toto+json", "intoto") ctx = remotes.WithMediaTypeKeyPrefix(ctx, "application/vnd.in-toto+json", "intoto")
fullRef, err := reference.WithDigest(reference.TagNameOnly(ref), desc.Digest) ref = reference.TagNameOnly(ref)
if err != nil { p, err := r.resolver().Pusher(ctx, ref.String())
return errors.Wrapf(err, "failed to combine ref %s with digest %s", ref, desc.Digest)
}
p, err := r.resolver().Pusher(ctx, fullRef.String())
if err != nil { if err != nil {
return err return err
} }
@@ -220,8 +217,8 @@ func (r *Resolver) Push(ctx context.Context, ref reference.Named, desc ocispec.D
func (r *Resolver) Copy(ctx context.Context, src *Source, dest reference.Named) error { func (r *Resolver) Copy(ctx context.Context, src *Source, dest reference.Named) error {
ctx = remotes.WithMediaTypeKeyPrefix(ctx, "application/vnd.in-toto+json", "intoto") ctx = remotes.WithMediaTypeKeyPrefix(ctx, "application/vnd.in-toto+json", "intoto")
// push by digest dest = reference.TagNameOnly(dest)
p, err := r.resolver().Pusher(ctx, dest.Name()) p, err := r.resolver().Pusher(ctx, dest.String())
if err != nil { if err != nil {
return err return err
} }

View File

@@ -278,8 +278,8 @@ func (l *loader) scanConfig(ctx context.Context, fetcher remotes.Fetcher, desc o
} }
type sbomStub struct { type sbomStub struct {
SPDX any `json:",omitempty"` SPDX interface{} `json:",omitempty"`
AdditionalSPDXs []any `json:",omitempty"` AdditionalSPDXs []interface{} `json:",omitempty"`
} }
func (l *loader) scanSBOM(ctx context.Context, fetcher remotes.Fetcher, r *result, refs []digest.Digest, as *asset) error { func (l *loader) scanSBOM(ctx context.Context, fetcher remotes.Fetcher, r *result, refs []digest.Digest, as *asset) error {
@@ -309,7 +309,7 @@ func (l *loader) scanSBOM(ctx context.Context, fetcher remotes.Fetcher, r *resul
} }
var spdx struct { var spdx struct {
Predicate any `json:"predicate"` Predicate interface{} `json:"predicate"`
} }
if err := json.Unmarshal(dt, &spdx); err != nil { if err := json.Unmarshal(dt, &spdx); err != nil {
return nil, err return nil, err
@@ -330,7 +330,7 @@ func (l *loader) scanSBOM(ctx context.Context, fetcher remotes.Fetcher, r *resul
} }
type provenanceStub struct { type provenanceStub struct {
SLSA any `json:",omitempty"` SLSA interface{} `json:",omitempty"`
} }
func (l *loader) scanProvenance(ctx context.Context, fetcher remotes.Fetcher, r *result, refs []digest.Digest, as *asset) error { func (l *loader) scanProvenance(ctx context.Context, fetcher remotes.Fetcher, r *result, refs []digest.Digest, as *asset) error {
@@ -360,7 +360,7 @@ func (l *loader) scanProvenance(ctx context.Context, fetcher remotes.Fetcher, r
} }
var slsa struct { var slsa struct {
Predicate any `json:"predicate"` Predicate interface{} `json:"predicate"`
} }
if err := json.Unmarshal(dt, &slsa); err != nil { if err := json.Unmarshal(dt, &slsa); err != nil {
return nil, err return nil, err

View File

@@ -89,7 +89,7 @@ func (p *Printer) Print(raw bool, out io.Writer) error {
} }
tpl, err := template.New("").Funcs(template.FuncMap{ tpl, err := template.New("").Funcs(template.FuncMap{
"json": func(v any) string { "json": func(v interface{}) string {
b, _ := json.MarshalIndent(v, "", " ") b, _ := json.MarshalIndent(v, "", " ")
return string(b) return string(b)
}, },
@@ -101,7 +101,7 @@ func (p *Printer) Print(raw bool, out io.Writer) error {
imageconfigs := res.Configs() imageconfigs := res.Configs()
format := tpl.Root.String() format := tpl.Root.String()
var mfst any var mfst interface{}
switch p.manifest.MediaType { switch p.manifest.MediaType {
case images.MediaTypeDockerSchema2Manifest, ocispecs.MediaTypeImageManifest: case images.MediaTypeDockerSchema2Manifest, ocispecs.MediaTypeImageManifest:
mfst = p.manifest mfst = p.manifest
@@ -206,7 +206,7 @@ func (p *Printer) printManifestList(out io.Writer) error {
type tplInput struct { type tplInput struct {
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
Manifest any `json:"manifest,omitempty"` Manifest interface{} `json:"manifest,omitempty"`
Image *ocispecs.Image `json:"image,omitempty"` Image *ocispecs.Image `json:"image,omitempty"`
result *result result *result
@@ -236,7 +236,7 @@ func (inp tplInput) Provenance() (provenanceStub, error) {
type tplInputs struct { type tplInputs struct {
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
Manifest any `json:"manifest,omitempty"` Manifest interface{} `json:"manifest,omitempty"`
Image map[string]*ocispecs.Image `json:"image,omitempty"` Image map[string]*ocispecs.Image `json:"image,omitempty"`
result *result result *result

View File

@@ -126,7 +126,7 @@ func TestMuxIO(t *testing.T) {
if tt.outputsNum != len(tt.wants) { if tt.outputsNum != len(tt.wants) {
t.Fatalf("wants != outputsNum") t.Fatalf("wants != outputsNum")
} }
for i := range tt.outputsNum { for i := 0; i < tt.outputsNum; i++ {
outBuf, out := newTestOut(i) outBuf, out := newTestOut(i)
outBufs = append(outBufs, outBuf) outBufs = append(outBufs, outBuf)
outs = append(outs, MuxOut{out, nil, nil}) outs = append(outs, MuxOut{out, nil, nil})
@@ -304,7 +304,7 @@ func writeMasked(w io.Writer, s string) io.Writer {
return return
} }
var masked string var masked string
for range n { for i := 0; i < n; i++ {
masked += s masked += s
} }
if _, err := w.Write([]byte(masked)); err != nil { if _, err := w.Write([]byte(masked)); err != nil {

View File

@@ -83,9 +83,9 @@ type Log struct {
// KeyValue is a key-value pair with typed value. // KeyValue is a key-value pair with typed value.
type KeyValue struct { type KeyValue struct {
Key string `json:"key"` Key string `json:"key"`
Type ValueType `json:"type,omitempty"` Type ValueType `json:"type,omitempty"`
Value any `json:"value"` Value interface{} `json:"value"`
} }
// DependencyLink shows dependencies between services // DependencyLink shows dependencies between services

View File

@@ -149,7 +149,7 @@ type keyValue struct {
// value is a custom type used to unmarshal otel Value correctly. // value is a custom type used to unmarshal otel Value correctly.
type value struct { type value struct {
Type string Type string
Value any Value interface{}
} }
// UnmarshalJSON implements json.Unmarshaler for Span which allows correctly // UnmarshalJSON implements json.Unmarshaler for Span which allows correctly
@@ -318,7 +318,7 @@ func (kv *keyValue) asAttributeKeyValue() (attribute.KeyValue, error) {
switch sli := kv.Value.Value.(type) { switch sli := kv.Value.Value.(type) {
case []string: case []string:
strSli = sli strSli = sli
case []any: case []interface{}:
for i := range sli { for i := range sli {
var v string var v string
// best case we have a string, otherwise, cast it using // best case we have a string, otherwise, cast it using

View File

@@ -131,7 +131,7 @@ func TestAsAttributeKeyValue(t *testing.T) {
name: "stringslice (interface of string)", name: "stringslice (interface of string)",
args: args{ args: args{
Type: attribute.STRINGSLICE.String(), Type: attribute.STRINGSLICE.String(),
value: []any{"value1", "value2"}, value: []interface{}{"value1", "value2"},
}, },
want: attribute.StringSlice("key", []string{"value1", "value2"}), want: attribute.StringSlice("key", []string{"value1", "value2"}),
}, },
@@ -139,7 +139,7 @@ func TestAsAttributeKeyValue(t *testing.T) {
name: "stringslice (interface mixed)", name: "stringslice (interface mixed)",
args: args{ args: args{
Type: attribute.STRINGSLICE.String(), Type: attribute.STRINGSLICE.String(),
value: []any{"value1", 2}, value: []interface{}{"value1", 2},
}, },
want: attribute.StringSlice("key", []string{"value1", "2"}), want: attribute.StringSlice("key", []string{"value1", "2"}),
}, },

View File

@@ -27,7 +27,7 @@ type Printer struct {
err error err error
warnings []client.VertexWarning warnings []client.VertexWarning
logMu sync.Mutex logMu sync.Mutex
logSourceMap map[digest.Digest]any logSourceMap map[digest.Digest]interface{}
metrics *metricWriter metrics *metricWriter
// TODO: remove once we can use result context to pass build ref // TODO: remove once we can use result context to pass build ref
@@ -74,7 +74,7 @@ func (p *Printer) Warnings() []client.VertexWarning {
return dedupWarnings(p.warnings) return dedupWarnings(p.warnings)
} }
func (p *Printer) ValidateLogSource(dgst digest.Digest, v any) bool { func (p *Printer) ValidateLogSource(dgst digest.Digest, v interface{}) bool {
p.logMu.Lock() p.logMu.Lock()
defer p.logMu.Unlock() defer p.logMu.Unlock()
src, ok := p.logSourceMap[dgst] src, ok := p.logSourceMap[dgst]
@@ -89,7 +89,7 @@ func (p *Printer) ValidateLogSource(dgst digest.Digest, v any) bool {
return false return false
} }
func (p *Printer) ClearLogSource(v any) { func (p *Printer) ClearLogSource(v interface{}) {
p.logMu.Lock() p.logMu.Lock()
defer p.logMu.Unlock() defer p.logMu.Unlock()
for d := range p.logSourceMap { for d := range p.logSourceMap {
@@ -125,7 +125,7 @@ func NewPrinter(ctx context.Context, out console.File, mode progressui.DisplayMo
pw.closeOnce = sync.Once{} pw.closeOnce = sync.Once{}
pw.logMu.Lock() pw.logMu.Lock()
pw.logSourceMap = map[digest.Digest]any{} pw.logSourceMap = map[digest.Digest]interface{}{}
pw.logMu.Unlock() pw.logMu.Unlock()
resumeLogs := logutil.Pause(logrus.StandardLogger()) resumeLogs := logutil.Pause(logrus.StandardLogger())

View File

@@ -11,8 +11,8 @@ import (
type Writer interface { type Writer interface {
Write(*client.SolveStatus) Write(*client.SolveStatus)
WriteBuildRef(string, string) WriteBuildRef(string, string)
ValidateLogSource(digest.Digest, any) bool ValidateLogSource(digest.Digest, interface{}) bool
ClearLogSource(any) ClearLogSource(interface{})
} }
func Write(w Writer, name string, f func() error) error { func Write(w Writer, name string, f func() error) error {

View File

@@ -7,18 +7,18 @@ import (
type Map struct { type Map struct {
mu sync.RWMutex mu sync.RWMutex
m map[string]any m map[string]interface{}
ch map[string]chan struct{} ch map[string]chan struct{}
} }
func New() *Map { func New() *Map {
return &Map{ return &Map{
m: make(map[string]any), m: make(map[string]interface{}),
ch: make(map[string]chan struct{}), ch: make(map[string]chan struct{}),
} }
} }
func (m *Map) Set(key string, value any) { func (m *Map) Set(key string, value interface{}) {
m.mu.Lock() m.mu.Lock()
defer m.mu.Unlock() defer m.mu.Unlock()
@@ -32,13 +32,13 @@ func (m *Map) Set(key string, value any) {
m.ch[key] = nil m.ch[key] = nil
} }
func (m *Map) Get(ctx context.Context, keys ...string) (map[string]any, error) { func (m *Map) Get(ctx context.Context, keys ...string) (map[string]interface{}, error) {
if len(keys) == 0 { if len(keys) == 0 {
return map[string]any{}, nil return map[string]interface{}{}, nil
} }
if len(keys) > 1 { if len(keys) > 1 {
out := make(map[string]any) out := make(map[string]interface{})
for _, key := range keys { for _, key := range keys {
mm, err := m.Get(ctx, key) mm, err := m.Get(ctx, key)
if err != nil { if err != nil {
@@ -70,5 +70,5 @@ func (m *Map) Get(ctx context.Context, keys ...string) (map[string]any, error) {
res := m.m[key] res := m.m[key]
m.mu.Unlock() m.mu.Unlock()
return map[string]any{key: res}, nil return map[string]interface{}{key: res}, nil
} }

View File

@@ -26,7 +26,6 @@ import (
"strings" "strings"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
"github.com/compose-spec/compose-go/v2/consts" "github.com/compose-spec/compose-go/v2/consts"
"github.com/compose-spec/compose-go/v2/dotenv" "github.com/compose-spec/compose-go/v2/dotenv"
@@ -483,27 +482,8 @@ func (o *ProjectOptions) prepare(ctx context.Context) (*types.ConfigDetails, err
return configDetails, err return configDetails, err
} }
isNamed := false
if o.Name == "" {
type named struct {
Name string `yaml:"name,omitempty"`
}
// if any of the compose file is named, this is equivalent to user passing --project-name
for _, cfg := range configDetails.ConfigFiles {
var n named
err = yaml.Unmarshal(cfg.Content, &n)
if err != nil {
return nil, err
}
if n.Name != "" {
isNamed = true
break
}
}
}
o.loadOptions = append(o.loadOptions, o.loadOptions = append(o.loadOptions,
withNamePrecedenceLoad(defaultDir, isNamed, o), withNamePrecedenceLoad(defaultDir, o),
withConvertWindowsPaths(o), withConvertWindowsPaths(o),
withListeners(o)) withListeners(o))
@@ -516,13 +496,13 @@ func ProjectFromOptions(ctx context.Context, options *ProjectOptions) (*types.Pr
return options.LoadProject(ctx) return options.LoadProject(ctx)
} }
func withNamePrecedenceLoad(absWorkingDir string, namedInYaml bool, options *ProjectOptions) func(*loader.Options) { func withNamePrecedenceLoad(absWorkingDir string, options *ProjectOptions) func(*loader.Options) {
return func(opts *loader.Options) { return func(opts *loader.Options) {
if options.Name != "" { if options.Name != "" {
opts.SetProjectName(options.Name, true) opts.SetProjectName(options.Name, true)
} else if nameFromEnv, ok := options.Environment[consts.ComposeProjectName]; ok && nameFromEnv != "" { } else if nameFromEnv, ok := options.Environment[consts.ComposeProjectName]; ok && nameFromEnv != "" {
opts.SetProjectName(nameFromEnv, true) opts.SetProjectName(nameFromEnv, true)
} else if !namedInYaml { } else {
dirname := filepath.Base(absWorkingDir) dirname := filepath.Base(absWorkingDir)
symlink, err := filepath.EvalSymlinks(absWorkingDir) symlink, err := filepath.EvalSymlinks(absWorkingDir)
if err == nil && filepath.Base(symlink) != dirname { if err == nil && filepath.Base(symlink) != dirname {

View File

@@ -27,6 +27,10 @@ import (
"github.com/compose-spec/compose-go/v2/types" "github.com/compose-spec/compose-go/v2/types"
) )
// as we use another service definition by `extends`, we must exclude attributes which creates dependency to another service
// see https://github.com/compose-spec/compose-spec/blob/main/05-services.md#restrictions
var exclusions = []string{"depends_on", "volumes_from"}
func ApplyExtends(ctx context.Context, dict map[string]any, opts *Options, tracker *cycleTracker, post ...PostProcessor) error { func ApplyExtends(ctx context.Context, dict map[string]any, opts *Options, tracker *cycleTracker, post ...PostProcessor) error {
a, ok := dict["services"] a, ok := dict["services"]
if !ok { if !ok {
@@ -119,6 +123,9 @@ func applyServiceExtends(ctx context.Context, name string, services map[string]a
}, },
}) })
} }
for _, exclusion := range exclusions {
delete(source, exclusion)
}
merged, err := override.ExtendService(source, service) merged, err := override.ExtendService(source, service)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -64,7 +64,6 @@ var interpolateTypeCastMapping = map[tree.Path]interp.Cast{
iPath("networks", tree.PathMatchAll, "external"): toBoolean, iPath("networks", tree.PathMatchAll, "external"): toBoolean,
iPath("networks", tree.PathMatchAll, "internal"): toBoolean, iPath("networks", tree.PathMatchAll, "internal"): toBoolean,
iPath("networks", tree.PathMatchAll, "attachable"): toBoolean, iPath("networks", tree.PathMatchAll, "attachable"): toBoolean,
iPath("networks", tree.PathMatchAll, "enable_ipv4"): toBoolean,
iPath("networks", tree.PathMatchAll, "enable_ipv6"): toBoolean, iPath("networks", tree.PathMatchAll, "enable_ipv6"): toBoolean,
iPath("volumes", tree.PathMatchAll, "external"): toBoolean, iPath("volumes", tree.PathMatchAll, "external"): toBoolean,
iPath("secrets", tree.PathMatchAll, "external"): toBoolean, iPath("secrets", tree.PathMatchAll, "external"): toBoolean,

View File

@@ -28,7 +28,7 @@ import (
// checkConsistency validate a compose model is consistent // checkConsistency validate a compose model is consistent
func checkConsistency(project *types.Project) error { func checkConsistency(project *types.Project) error {
for name, s := range project.Services { for _, s := range project.Services {
if s.Build == nil && s.Image == "" { if s.Build == nil && s.Image == "" {
return fmt.Errorf("service %q has neither an image nor a build context specified: %w", s.Name, errdefs.ErrInvalid) return fmt.Errorf("service %q has neither an image nor a build context specified: %w", s.Name, errdefs.ErrInvalid)
} }
@@ -38,18 +38,6 @@ func checkConsistency(project *types.Project) error {
return fmt.Errorf("service %q declares mutualy exclusive dockerfile and dockerfile_inline: %w", s.Name, errdefs.ErrInvalid) return fmt.Errorf("service %q declares mutualy exclusive dockerfile and dockerfile_inline: %w", s.Name, errdefs.ErrInvalid)
} }
for add, c := range s.Build.AdditionalContexts {
if target, ok := strings.CutPrefix(c, types.ServicePrefix); ok {
t, err := project.GetService(target)
if err != nil {
return fmt.Errorf("service %q declares unknown service %q as additional contexts %s", name, target, add)
}
if t.Build == nil {
return fmt.Errorf("service %q declares non-buildable service %q as additional contexts %s", name, target, add)
}
}
}
if len(s.Build.Platforms) > 0 && s.Platform != "" { if len(s.Build.Platforms) > 0 && s.Platform != "" {
var found bool var found bool
for _, platform := range s.Build.Platforms { for _, platform := range s.Build.Platforms {

View File

@@ -16,20 +16,13 @@
package paths package paths
import ( import "strings"
"strings"
"github.com/compose-spec/compose-go/v2/types"
)
func (r *relativePathsResolver) absContextPath(value any) (any, error) { func (r *relativePathsResolver) absContextPath(value any) (any, error) {
v := value.(string) v := value.(string)
if strings.Contains(v, "://") { // `docker-image://` or any builder specific context type if strings.Contains(v, "://") { // `docker-image://` or any builder specific context type
return v, nil return v, nil
} }
if strings.HasPrefix(v, types.ServicePrefix) { // `docker-image://` or any builder specific context type
return v, nil
}
if isRemoteContext(v) { if isRemoteContext(v) {
return v, nil return v, nil
} }

View File

@@ -1,6 +1,6 @@
{ {
"$schema": "https://json-schema.org/draft-07/schema", "$schema": "https://json-schema.org/draft/2019-09/schema#",
"$id": "compose_spec.json", "id": "compose_spec.json",
"type": "object", "type": "object",
"title": "Compose Specification", "title": "Compose Specification",
"description": "The Compose file is a YAML file defining a multi-containers based application.", "description": "The Compose file is a YAML file defining a multi-containers based application.",
@@ -25,6 +25,7 @@
}, },
"services": { "services": {
"id": "#/properties/services",
"type": "object", "type": "object",
"patternProperties": { "patternProperties": {
"^[a-zA-Z0-9._-]+$": { "^[a-zA-Z0-9._-]+$": {
@@ -35,6 +36,7 @@
}, },
"networks": { "networks": {
"id": "#/properties/networks",
"type": "object", "type": "object",
"patternProperties": { "patternProperties": {
"^[a-zA-Z0-9._-]+$": { "^[a-zA-Z0-9._-]+$": {
@@ -44,6 +46,7 @@
}, },
"volumes": { "volumes": {
"id": "#/properties/volumes",
"type": "object", "type": "object",
"patternProperties": { "patternProperties": {
"^[a-zA-Z0-9._-]+$": { "^[a-zA-Z0-9._-]+$": {
@@ -54,6 +57,7 @@
}, },
"secrets": { "secrets": {
"id": "#/properties/secrets",
"type": "object", "type": "object",
"patternProperties": { "patternProperties": {
"^[a-zA-Z0-9._-]+$": { "^[a-zA-Z0-9._-]+$": {
@@ -64,6 +68,7 @@
}, },
"configs": { "configs": {
"id": "#/properties/configs",
"type": "object", "type": "object",
"patternProperties": { "patternProperties": {
"^[a-zA-Z0-9._-]+$": { "^[a-zA-Z0-9._-]+$": {
@@ -80,6 +85,7 @@
"definitions": { "definitions": {
"service": { "service": {
"id": "#/definitions/service",
"type": "object", "type": "object",
"properties": { "properties": {
@@ -240,7 +246,8 @@
"expose": { "expose": {
"type": "array", "type": "array",
"items": { "items": {
"type": ["string", "number"] "type": ["string", "number"],
"format": "expose"
}, },
"uniqueItems": true "uniqueItems": true
}, },
@@ -320,8 +327,7 @@
"^.+$": {"type": ["string", "number"]} "^.+$": {"type": ["string", "number"]}
} }
}, },
"priority": {"type": "number"}, "priority": {"type": "number"}
"gw_priority": {"type": "number"}
}, },
"additionalProperties": false, "additionalProperties": false,
"patternProperties": {"^x-": {}} "patternProperties": {"^x-": {}}
@@ -463,6 +469,7 @@
}, },
"healthcheck": { "healthcheck": {
"id": "#/definitions/healthcheck",
"type": "object", "type": "object",
"properties": { "properties": {
"disable": {"type": ["boolean", "string"]}, "disable": {"type": ["boolean", "string"]},
@@ -482,6 +489,7 @@
"patternProperties": {"^x-": {}} "patternProperties": {"^x-": {}}
}, },
"development": { "development": {
"id": "#/definitions/development",
"type": ["object", "null"], "type": ["object", "null"],
"properties": { "properties": {
"watch": { "watch": {
@@ -505,6 +513,7 @@
"patternProperties": {"^x-": {}} "patternProperties": {"^x-": {}}
}, },
"deployment": { "deployment": {
"id": "#/definitions/deployment",
"type": ["object", "null"], "type": ["object", "null"],
"properties": { "properties": {
"mode": {"type": "string"}, "mode": {"type": "string"},
@@ -606,6 +615,7 @@
}, },
"generic_resources": { "generic_resources": {
"id": "#/definitions/generic_resources",
"type": "array", "type": "array",
"items": { "items": {
"type": "object", "type": "object",
@@ -626,6 +636,7 @@
}, },
"devices": { "devices": {
"id": "#/definitions/devices",
"type": "array", "type": "array",
"items": { "items": {
"type": "object", "type": "object",
@@ -645,26 +656,24 @@
}, },
"gpus": { "gpus": {
"oneOf": [ "id": "#/definitions/gpus",
{"type": "string", "enum": ["all"]}, "type": "array",
{"type": "array", "items": {
"items": { "type": "object",
"type": "object", "properties": {
"properties": { "capabilities": {"$ref": "#/definitions/list_of_strings"},
"capabilities": {"$ref": "#/definitions/list_of_strings"}, "count": {"type": ["string", "integer"]},
"count": {"type": ["string", "integer"]}, "device_ids": {"$ref": "#/definitions/list_of_strings"},
"device_ids": {"$ref": "#/definitions/list_of_strings"}, "driver":{"type": "string"},
"driver":{"type": "string"}, "options":{"$ref": "#/definitions/list_or_dict"}
"options":{"$ref": "#/definitions/list_or_dict"} },
} "additionalProperties": false,
}, "patternProperties": {"^x-": {}}
"additionalProperties": false, }
"patternProperties": {"^x-": {}}
}
]
}, },
"include": { "include": {
"id": "#/definitions/include",
"oneOf": [ "oneOf": [
{"type": "string"}, {"type": "string"},
{ {
@@ -680,6 +689,7 @@
}, },
"network": { "network": {
"id": "#/definitions/network",
"type": ["object", "null"], "type": ["object", "null"],
"properties": { "properties": {
"name": {"type": "string"}, "name": {"type": "string"},
@@ -733,7 +743,6 @@
"patternProperties": {"^x-": {}} "patternProperties": {"^x-": {}}
}, },
"internal": {"type": ["boolean", "string"]}, "internal": {"type": ["boolean", "string"]},
"enable_ipv4": {"type": ["boolean", "string"]},
"enable_ipv6": {"type": ["boolean", "string"]}, "enable_ipv6": {"type": ["boolean", "string"]},
"attachable": {"type": ["boolean", "string"]}, "attachable": {"type": ["boolean", "string"]},
"labels": {"$ref": "#/definitions/list_or_dict"} "labels": {"$ref": "#/definitions/list_or_dict"}
@@ -743,6 +752,7 @@
}, },
"volume": { "volume": {
"id": "#/definitions/volume",
"type": ["object", "null"], "type": ["object", "null"],
"properties": { "properties": {
"name": {"type": "string"}, "name": {"type": "string"},
@@ -771,6 +781,7 @@
}, },
"secret": { "secret": {
"id": "#/definitions/secret",
"type": "object", "type": "object",
"properties": { "properties": {
"name": {"type": "string"}, "name": {"type": "string"},
@@ -797,6 +808,7 @@
}, },
"config": { "config": {
"id": "#/definitions/config",
"type": "object", "type": "object",
"properties": { "properties": {
"name": {"type": "string"}, "name": {"type": "string"},
@@ -828,6 +840,7 @@
}, },
"service_hook": { "service_hook": {
"id": "#/definitions/service_hook",
"type": "object", "type": "object",
"properties": { "properties": {
"command": {"$ref": "#/definitions/command"}, "command": {"$ref": "#/definitions/command"},
@@ -992,6 +1005,20 @@
] ]
} }
} }
},
"constraints": {
"service": {
"id": "#/definitions/constraints/service",
"anyOf": [
{"required": ["build"]},
{"required": ["image"]}
],
"properties": {
"build": {
"required": ["context"]
}
}
}
} }
} }
} }

View File

@@ -32,7 +32,6 @@ func init() {
transformers["services.*.env_file"] = transformEnvFile transformers["services.*.env_file"] = transformEnvFile
transformers["services.*.label_file"] = transformStringOrList transformers["services.*.label_file"] = transformStringOrList
transformers["services.*.extends"] = transformExtends transformers["services.*.extends"] = transformExtends
transformers["services.*.gpus"] = transformGpus
transformers["services.*.networks"] = transformServiceNetworks transformers["services.*.networks"] = transformServiceNetworks
transformers["services.*.volumes.*"] = transformVolumeMount transformers["services.*.volumes.*"] = transformVolumeMount
transformers["services.*.dns"] = transformStringOrList transformers["services.*.dns"] = transformStringOrList

View File

@@ -1,38 +0,0 @@
/*
Copyright 2020 The Compose Specification 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 transform
import (
"fmt"
"github.com/compose-spec/compose-go/v2/tree"
)
func transformGpus(data any, p tree.Path, ignoreParseError bool) (any, error) {
switch v := data.(type) {
case []any:
return transformSequence(v, p, ignoreParseError)
case string:
return []any{
map[string]any{
"count": "all",
},
}, nil
default:
return data, fmt.Errorf("%s: invalid type %T for gpus", p, v)
}
}

View File

@@ -1452,12 +1452,6 @@ func deriveDeepCopy_24(dst, src *NetworkConfig) {
} else { } else {
dst.CustomLabels = nil dst.CustomLabels = nil
} }
if src.EnableIPv4 == nil {
dst.EnableIPv4 = nil
} else {
dst.EnableIPv4 = new(bool)
*dst.EnableIPv4 = *src.EnableIPv4
}
if src.EnableIPv6 == nil { if src.EnableIPv6 == nil {
dst.EnableIPv6 = nil dst.EnableIPv6 = nil
} else { } else {

View File

@@ -438,14 +438,13 @@ type PlacementPreferences struct {
// ServiceNetworkConfig is the network configuration for a service // ServiceNetworkConfig is the network configuration for a service
type ServiceNetworkConfig struct { type ServiceNetworkConfig struct {
Priority int `yaml:"priority,omitempty" json:"priority,omitempty"` Priority int `yaml:"priority,omitempty" json:"priority,omitempty"`
GatewayPriority int `yaml:"gw_priority,omitempty" json:"gw_priority,omitempty"` Aliases []string `yaml:"aliases,omitempty" json:"aliases,omitempty"`
Aliases []string `yaml:"aliases,omitempty" json:"aliases,omitempty"` Ipv4Address string `yaml:"ipv4_address,omitempty" json:"ipv4_address,omitempty"`
Ipv4Address string `yaml:"ipv4_address,omitempty" json:"ipv4_address,omitempty"` Ipv6Address string `yaml:"ipv6_address,omitempty" json:"ipv6_address,omitempty"`
Ipv6Address string `yaml:"ipv6_address,omitempty" json:"ipv6_address,omitempty"` LinkLocalIPs []string `yaml:"link_local_ips,omitempty" json:"link_local_ips,omitempty"`
LinkLocalIPs []string `yaml:"link_local_ips,omitempty" json:"link_local_ips,omitempty"` MacAddress string `yaml:"mac_address,omitempty" json:"mac_address,omitempty"`
MacAddress string `yaml:"mac_address,omitempty" json:"mac_address,omitempty"` DriverOpts Options `yaml:"driver_opts,omitempty" json:"driver_opts,omitempty"`
DriverOpts Options `yaml:"driver_opts,omitempty" json:"driver_opts,omitempty"`
Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"` Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"`
} }
@@ -689,7 +688,6 @@ type NetworkConfig struct {
Attachable bool `yaml:"attachable,omitempty" json:"attachable,omitempty"` Attachable bool `yaml:"attachable,omitempty" json:"attachable,omitempty"`
Labels Labels `yaml:"labels,omitempty" json:"labels,omitempty"` Labels Labels `yaml:"labels,omitempty" json:"labels,omitempty"`
CustomLabels Labels `yaml:"-" json:"-"` CustomLabels Labels `yaml:"-" json:"-"`
EnableIPv4 *bool `yaml:"enable_ipv4,omitempty" json:"enable_ipv4,omitempty"`
EnableIPv6 *bool `yaml:"enable_ipv6,omitempty" json:"enable_ipv6,omitempty"` EnableIPv6 *bool `yaml:"enable_ipv6,omitempty" json:"enable_ipv6,omitempty"`
Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"` Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"`
} }

View File

@@ -26,7 +26,6 @@ import (
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
"github.com/containerd/containerd/v2/core/content" "github.com/containerd/containerd/v2/core/content"
"github.com/containerd/containerd/v2/defaults"
"github.com/containerd/containerd/v2/pkg/protobuf" "github.com/containerd/containerd/v2/pkg/protobuf"
) )
@@ -77,37 +76,27 @@ func (rw *remoteWriter) Digest() digest.Digest {
} }
func (rw *remoteWriter) Write(p []byte) (n int, err error) { func (rw *remoteWriter) Write(p []byte) (n int, err error) {
const maxBufferSize = defaults.DefaultMaxSendMsgSize >> 1 offset := rw.offset
for i := 0; i < len(p); i += maxBufferSize {
offset := rw.offset
end := i + maxBufferSize resp, err := rw.send(&contentapi.WriteContentRequest{
if end > len(p) { Action: contentapi.WriteAction_WRITE,
end = len(p) Offset: offset,
} Data: p,
data := p[i:end] })
if err != nil {
resp, err := rw.send(&contentapi.WriteContentRequest{ return 0, fmt.Errorf("failed to send write: %w", errgrpc.ToNative(err))
Action: contentapi.WriteAction_WRITE,
Offset: offset,
Data: data,
})
if err != nil {
return 0, fmt.Errorf("failed to send write: %w", errgrpc.ToNative(err))
}
written := int(resp.Offset - offset)
rw.offset += int64(written)
if resp.Digest != "" {
rw.digest = digest.Digest(resp.Digest)
}
n += written
if written < len(data) {
return n, io.ErrShortWrite
}
} }
return n, nil
n = int(resp.Offset - offset)
if n < len(p) {
err = io.ErrShortWrite
}
rw.offset += int64(n)
if resp.Digest != "" {
rw.digest = digest.Digest(resp.Digest)
}
return
} }
func (rw *remoteWriter) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) (err error) { func (rw *remoteWriter) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) (err error) {

View File

@@ -23,7 +23,7 @@ var (
Package = "github.com/containerd/containerd/v2" Package = "github.com/containerd/containerd/v2"
// Version holds the complete version number. Filled in at linking time. // Version holds the complete version number. Filled in at linking time.
Version = "2.0.3+unknown" Version = "2.0.2+unknown"
// Revision is filled with the VCS (e.g. git) revision being used to build // Revision is filled with the VCS (e.g. git) revision being used to build
// the program at linking time. // the program at linking time.

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