In-process gateway forwarder drops NewContainer platform
Contributing guidelines and issue reporting guide
- I've read the contributing guidelines and wholeheartedly agree. I've also read the issue reporting guide.
Well-formed report checklist
- I have found a bug that the documentation does not mention anything about my problem
- I have found a bug that there are no open or closed issues that are related to my problem
- I have provided version/information about my environment and done my best to provide a reproducer
Description of bug
Bug description
frontend/gateway/forwarder.BridgeClient.NewContainer does not copy client.NewContainerRequest.Platform to container.NewContainerRequest. The container then uses the runtime.GOOS and runtime.GOARCH values in the daemon. The protobuf/gRPC gateway path copies the requested platform.
This only affects BuildKit applications that register an in-process frontend using forwarder.NewGatewayForwarder, so the built-in Dockerfile frontend (which does not call NewContainer) is unaffected. The defect can affect a BuildKit application that registers an in-process frontend with forwarder.NewGatewayForwarder.
I would expect each NewContainer implementation to preserve the requested platform.
Reproduction
Create frontend/gateway/forwarder/newcontainer_platform_test.go:
Reproducerpackage forwarder_test
import (
"context"
"reflect"
"runtime"
"testing"
"github.com/moby/buildkit/cache"
bkclient "github.com/moby/buildkit/client"
gwclient "github.com/moby/buildkit/frontend/gateway/client"
"github.com/moby/buildkit/frontend/gateway/forwarder"
"github.com/moby/buildkit/solver/pb"
)
type workers struct{}
func (workers) DefaultCacheManager() (cache.Manager, error) { return nil, nil }
func (workers) WorkerInfos() []bkclient.WorkerInfo { return nil }
func TestNewContainerForwardsPlatform(t *testing.T) {
ctx := context.Background()
c, err := forwarder.LLBBridgeToGatewayClient(
ctx, nil, nil, nil, nil, workers{}, "", nil,
)
if err != nil {
t.Fatal(err)
}
targetOS := "windows"
if runtime.GOOS == targetOS {
targetOS = "linux"
}
targetArch := "amd64"
if runtime.GOARCH == targetArch {
targetArch = "arm64"
}
want := &pb.Platform{
OS: targetOS,
Architecture: targetArch,
}
ctr, err := c.NewContainer(ctx, gwclient.NewContainerRequest{
Platform: want,
})
if err != nil {
t.Fatal(err)
}
defer ctr.Release(ctx)
stored := reflect.ValueOf(ctr).Elem().FieldByName("platform").Elem()
gotOS := stored.FieldByName("OS").String()
gotArch := stored.FieldByName("Architecture").String()
if gotOS != want.OS || gotArch != want.Architecture {
t.Fatalf(
"stored platform = %s/%s; want %s/%s",
gotOS, gotArch, want.OS, want.Architecture,
)
}
}Then run:
go test ./frontend/gateway/forwarder -run '^TestNewContainerForwardsPlatform$' -count=1 -vResult:
=== RUN TestNewContainerForwardsPlatform
newcontainer_platform_test.go:59: stored platform = darwin/arm64; want windows/amd64
--- FAIL: TestNewContainerForwardsPlatform (0.00s)
FAILVersion information
BuildKit version: v0.32.2
BuildKit commit: 991535e0973488b6a429096d21fa13f81f2d89d8
Daemon platform: linux/arm64
Requested platform: windows/amd64
Source: moby/buildkit