Skip to content

Commit ea285af

Browse files
committed
Properly pass through target platform
This makes sure that the requested target platform is propagated everywhere it needs to be. There are some room for improvements here. For example, source packages really should not depend on the target platform and we could get away with using the native platform there. These kinds of improvements will require some code restructuring which is out of scope for this change. Signed-off-by: Brian Goff <[email protected]>
1 parent dc9de3c commit ea285af

25 files changed

+254
-99
lines changed

frontend/build.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,12 @@ func BuildWithPlatformFromUIClient(ctx context.Context, client gwclient.Client,
167167
// image in the build context matching the image ref.
168168
//
169169
// This follows the behavior of of the dockerfile frontend.
170-
func GetBaseImage(sOpt dalec.SourceOpts, ref string) llb.State {
170+
func GetBaseImage(sOpt dalec.SourceOpts, ref string, opts ...llb.ConstraintsOpt) llb.State {
171171
return llb.Scratch().Async(func(ctx context.Context, _ llb.State, c *llb.Constraints) (llb.State, error) {
172+
for _, o := range opts {
173+
o.SetConstraintsOption(c)
174+
}
175+
172176
fromClient, err := sOpt.GetContext(ref, dalec.WithConstraint(c))
173177
if err != nil {
174178
return llb.Scratch(), err
@@ -177,7 +181,8 @@ func GetBaseImage(sOpt dalec.SourceOpts, ref string) llb.State {
177181
if fromClient != nil {
178182
return *fromClient, nil
179183
}
180-
return llb.Image(ref, llb.WithMetaResolver(sOpt.Resolver), dalec.WithConstraint(c)), nil
184+
185+
return llb.Image(ref, dalec.WithConstraint(c), llb.WithMetaResolver(sOpt.Resolver)), nil
181186
})
182187
}
183188

frontend/debug/handle_gomod.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const keyGomodWorker = "context:gomod-worker"
1616
// Gomods outputs all the gomodule dependencies for the spec
1717
func Gomods(ctx context.Context, client gwclient.Client) (*client.Result, error) {
1818
return frontend.BuildWithPlatform(ctx, client, func(ctx context.Context, client gwclient.Client, platform *ocispecs.Platform, spec *dalec.Spec, targetKey string) (gwclient.Reference, *dalec.DockerImageSpec, error) {
19-
sOpt, err := frontend.SourceOptFromClient(ctx, client)
19+
sOpt, err := frontend.SourceOptFromClient(ctx, client, platform)
2020
if err != nil {
2121
return nil, nil, err
2222
}
@@ -34,7 +34,7 @@ func Gomods(ctx context.Context, client gwclient.Client) (*client.Result, error)
3434
Run(llb.Shlex("apk add --no-cache go git ca-certificates patch")).Root()
3535
}
3636

37-
st, err := spec.GomodDeps(sOpt, worker)
37+
st, err := spec.GomodDeps(sOpt, worker, dalec.Platform(platform))
3838
if err != nil {
3939
return nil, nil, err
4040
}

frontend/debug/handle_sources.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
// Sources is a handler that outputs all the sources.
1515
func Sources(ctx context.Context, client gwclient.Client) (*client.Result, error) {
1616
return frontend.BuildWithPlatform(ctx, client, func(ctx context.Context, client gwclient.Client, platform *ocispecs.Platform, spec *dalec.Spec, targetKey string) (gwclient.Reference, *dalec.DockerImageSpec, error) {
17-
sOpt, err := frontend.SourceOptFromClient(ctx, client)
17+
sOpt, err := frontend.SourceOptFromClient(ctx, client, platform)
1818
if err != nil {
1919
return nil, nil, err
2020
}
@@ -53,7 +53,7 @@ func Sources(ctx context.Context, client gwclient.Client) (*client.Result, error
5353
func PatchedSources(ctx context.Context, client gwclient.Client) (*client.Result, error) {
5454
return frontend.BuildWithPlatform(ctx, client, func(ctx context.Context, client gwclient.Client, platform *ocispecs.Platform, spec *dalec.Spec, targetKey string) (gwclient.Reference, *dalec.DockerImageSpec, error) {
5555
const keyPatchedSourcesWorker = "context:patched-sources-worker"
56-
sOpt, err := frontend.SourceOptFromClient(ctx, client)
56+
sOpt, err := frontend.SourceOptFromClient(ctx, client, platform)
5757
if err != nil {
5858
return nil, nil, err
5959
}
@@ -69,12 +69,13 @@ func PatchedSources(ctx context.Context, client gwclient.Client) (*client.Result
6969
Run(llb.Shlex("apk add --no-cache go git ca-certificates patch")).Root()
7070
}
7171

72-
sources, err := dalec.Sources(spec, sOpt)
72+
pc := dalec.Platform(platform)
73+
sources, err := dalec.Sources(spec, sOpt, pc)
7374
if err != nil {
7475
return nil, nil, err
7576
}
7677

77-
sources = dalec.PatchSources(worker, spec, sources)
78+
sources = dalec.PatchSources(worker, spec, sources, pc)
7879
if err != nil {
7980
return nil, nil, err
8081
}

frontend/gateway.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/moby/buildkit/solver/pb"
1414
"github.com/moby/buildkit/util/bklog"
1515
"github.com/opencontainers/go-digest"
16+
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
1617
"github.com/pkg/errors"
1718
)
1819

@@ -55,12 +56,12 @@ func getDockerfile(ctx context.Context, client gwclient.Client, build *dalec.Sou
5556
// ForwarderFromClient creates a [dalec.ForwarderFunc] from a gateway client.
5657
// This is used for forwarding builds to other frontends in [dalec.Source2LLBGetter]
5758
func ForwarderFromClient(ctx context.Context, client gwclient.Client) dalec.ForwarderFunc {
58-
return func(st llb.State, spec *dalec.SourceBuild) (llb.State, error) {
59+
return func(st llb.State, spec *dalec.SourceBuild, opts ...llb.ConstraintsOpt) (llb.State, error) {
5960
if spec == nil {
6061
spec = &dalec.SourceBuild{}
6162
}
6263

63-
def, err := st.Marshal(ctx)
64+
def, err := st.Marshal(ctx, opts...)
6465
if err != nil {
6566
return llb.Scratch(), err
6667
}
@@ -101,10 +102,11 @@ func GetBuildArg(client gwclient.Client, k string) (string, bool) {
101102
return "", false
102103
}
103104

104-
func SourceOptFromUIClient(ctx context.Context, c gwclient.Client, dc *dockerui.Client) dalec.SourceOpts {
105+
func SourceOptFromUIClient(ctx context.Context, c gwclient.Client, dc *dockerui.Client, platform *ocispecs.Platform) dalec.SourceOpts {
105106
return dalec.SourceOpts{
106-
Resolver: c,
107-
Forward: ForwarderFromClient(ctx, c),
107+
TargetPlatform: platform,
108+
Resolver: c,
109+
Forward: ForwarderFromClient(ctx, c),
108110
GetContext: func(ref string, opts ...llb.LocalOption) (*llb.State, error) {
109111
if ref == dockerui.DefaultLocalNameContext {
110112
return dc.MainContext(ctx, opts...)
@@ -114,6 +116,7 @@ func SourceOptFromUIClient(ctx context.Context, c gwclient.Client, dc *dockerui.
114116
AsyncLocalOpts: func() []llb.LocalOption {
115117
return opts
116118
},
119+
Platform: platform,
117120
})
118121
if err != nil {
119122
return nil, err
@@ -127,12 +130,12 @@ func SourceOptFromUIClient(ctx context.Context, c gwclient.Client, dc *dockerui.
127130
}
128131
}
129132

130-
func SourceOptFromClient(ctx context.Context, c gwclient.Client) (dalec.SourceOpts, error) {
133+
func SourceOptFromClient(ctx context.Context, c gwclient.Client, platform *ocispecs.Platform) (dalec.SourceOpts, error) {
131134
dc, err := dockerui.NewClient(c)
132135
if err != nil {
133136
return dalec.SourceOpts{}, err
134137
}
135-
return SourceOptFromUIClient(ctx, c, dc), nil
138+
return SourceOptFromUIClient(ctx, c, dc, platform), nil
136139
}
137140

138141
var (

frontend/test_runner.go

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/moby/buildkit/client/llb"
1515
gwclient "github.com/moby/buildkit/frontend/gateway/client"
1616
"github.com/moby/buildkit/identity"
17+
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
1718
"github.com/pkg/errors"
1819
)
1920

@@ -31,7 +32,7 @@ const (
3132
)
3233

3334
// Run tests runs the tests defined in the spec against the given target container.
34-
func RunTests(ctx context.Context, client gwclient.Client, spec *dalec.Spec, ref gwclient.Reference, withTestDeps llb.StateOption, target string) error {
35+
func RunTests(ctx context.Context, client gwclient.Client, spec *dalec.Spec, ref gwclient.Reference, withTestDeps llb.StateOption, target string, platform *ocispecs.Platform) error {
3536
if skipVar := client.BuildOpts().Opts["build-arg:"+"DALEC_SKIP_TESTS"]; skipVar != "" {
3637
skip, err := strconv.ParseBool(skipVar)
3738
if err != nil {
@@ -67,7 +68,7 @@ func RunTests(ctx context.Context, client gwclient.Client, spec *dalec.Spec, ref
6768
return err
6869
}
6970

70-
sOpt, err := SourceOptFromClient(ctx, client)
71+
sOpt, err := SourceOptFromClient(ctx, client, platform)
7172
if err != nil {
7273
return err
7374
}
@@ -76,6 +77,7 @@ func RunTests(ctx context.Context, client gwclient.Client, spec *dalec.Spec, ref
7677
st llb.State
7778
t *dalec.TestSpec
7879
stdios map[int]llb.State
80+
opts []llb.ConstraintsOpt
7981
}
8082

8183
ctrWithDeps := ctr.With(withTestDeps)
@@ -93,7 +95,7 @@ func RunTests(ctx context.Context, client gwclient.Client, spec *dalec.Spec, ref
9395
pg := llb.ProgressGroup(identity.NewID(), "Test: "+path.Join(target, test.Name), false)
9496

9597
for _, sm := range test.Mounts {
96-
st, err := sm.Spec.AsMount(internalMountSourceName, sOpt, pg)
98+
st, err := sm.Spec.AsMount(internalMountSourceName, sOpt, pg, dalec.Platform(platform))
9799
if err != nil {
98100
return err
99101
}
@@ -119,18 +121,18 @@ func RunTests(ctx context.Context, client gwclient.Client, spec *dalec.Spec, ref
119121
if step.Stdin != "" {
120122
needsStdioMount = true
121123
stepOpts = append(stepOpts, llb.AddEnv("STDIN_FILE", filepath.Join("/tmp", id, "stdin")))
122-
ioSt = ioSt.File(llb.Mkfile("stdin", 0444, []byte(step.Stdin)))
124+
ioSt = ioSt.File(llb.Mkfile("stdin", 0444, []byte(step.Stdin)), pg)
123125
}
124126
if !step.Stdout.IsEmpty() {
125127
needsStdioMount = true
126128
stepOpts = append(stepOpts, llb.AddEnv("STDOUT_FILE", path.Join("/tmp", id, "stdout")))
127-
ioSt = ioSt.File(llb.Mkfile("stdout", 0664, nil))
129+
ioSt = ioSt.File(llb.Mkfile("stdout", 0664, nil), pg)
128130
}
129131

130132
if !step.Stderr.IsEmpty() {
131133
needsStdioMount = true
132134
stepOpts = append(stepOpts, llb.AddEnv("STDERR_FILE", path.Join("/tmp", id, "stderr")))
133-
ioSt = ioSt.File(llb.Mkfile("stderr", 0664, nil))
135+
ioSt = ioSt.File(llb.Mkfile("stderr", 0664, nil), pg)
134136
}
135137

136138
cmd, err := shlex.Split(step.Command)
@@ -165,9 +167,9 @@ func RunTests(ctx context.Context, client gwclient.Client, spec *dalec.Spec, ref
165167
worker = est.Root()
166168
}
167169

168-
runs = append(runs, testPair{st: worker, t: test, stdios: ios})
170+
runs = append(runs, testPair{st: worker, t: test, stdios: ios, opts: []llb.ConstraintsOpt{pg, dalec.Platform(platform)}})
169171
} else {
170-
runs = append(runs, testPair{st: base, t: test})
172+
runs = append(runs, testPair{st: base, t: test, opts: []llb.ConstraintsOpt{pg, dalec.Platform(platform)}})
171173
}
172174
}
173175

@@ -177,7 +179,7 @@ func RunTests(ctx context.Context, client gwclient.Client, spec *dalec.Spec, ref
177179
pair := pair
178180
wg.Add(1)
179181
go func() {
180-
if err := runTest(ctx, pair.t, pair.st, pair.stdios, client); err != nil {
182+
if err := runTest(ctx, pair.t, pair.st, pair.stdios, client, pair.opts...); err != nil {
181183
errs.Append(errors.Wrap(err, "FAILED: "+path.Join(target, pair.t.Name)))
182184
}
183185
wg.Done()
@@ -193,8 +195,8 @@ type frontendClient interface {
193195
CurrentFrontend() (*llb.State, error)
194196
}
195197

196-
func runTest(ctx context.Context, t *dalec.TestSpec, st llb.State, ios map[int]llb.State, client gwclient.Client) error {
197-
def, err := st.Marshal(ctx)
198+
func runTest(ctx context.Context, t *dalec.TestSpec, st llb.State, ios map[int]llb.State, client gwclient.Client, opts ...llb.ConstraintsOpt) error {
199+
def, err := st.Marshal(ctx, opts...)
198200
if err != nil {
199201
return err
200202
}
@@ -245,7 +247,7 @@ func runTest(ctx context.Context, t *dalec.TestSpec, st llb.State, ios map[int]l
245247
}
246248

247249
for i, st := range ios {
248-
def, err := st.Marshal(ctx)
250+
def, err := st.Marshal(ctx, opts...)
249251
if err != nil {
250252
outErr = stderrors.Join(errors.Wrap(err, "failed to marshal stdio state"))
251253
continue

helpers.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,3 +634,12 @@ func BaseImageConfig(platform *ocispecs.Platform) *DockerImageSpec {
634634

635635
return img
636636
}
637+
638+
// Platform returns a [llb.ConstraintsOpt] that sets the platform to the provided platform
639+
// If the platform is nil, the [llb.ConstraintOpt] is a no-op.
640+
func Platform(platform *ocispecs.Platform) llb.ConstraintsOpt {
641+
if platform == nil {
642+
return constraintsOptFunc(func(c *llb.Constraints) {})
643+
}
644+
return llb.Platform(*platform)
645+
}

source.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/moby/buildkit/frontend/dockerui"
1616
"github.com/moby/buildkit/identity"
1717
"github.com/moby/buildkit/util/gitutil"
18+
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
1819
"github.com/pkg/errors"
1920
)
2021

@@ -225,12 +226,13 @@ var (
225226

226227
type LLBGetter func(sOpts SourceOpts, opts ...llb.ConstraintsOpt) (llb.State, error)
227228

228-
type ForwarderFunc func(llb.State, *SourceBuild) (llb.State, error)
229+
type ForwarderFunc func(llb.State, *SourceBuild, ...llb.ConstraintsOpt) (llb.State, error)
229230

230231
type SourceOpts struct {
231-
Resolver llb.ImageMetaResolver
232-
Forward ForwarderFunc
233-
GetContext func(string, ...llb.LocalOption) (*llb.State, error)
232+
Resolver llb.ImageMetaResolver
233+
Forward ForwarderFunc
234+
GetContext func(string, ...llb.LocalOption) (*llb.State, error)
235+
TargetPlatform *ocispecs.Platform
234236
}
235237

236238
func (s *Source) asState(name string, forMount bool, sOpt SourceOpts, opts ...llb.ConstraintsOpt) (llb.State, error) {

source_build.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func (src *SourceBuild) AsState(name string, sOpt SourceOpts, opts ...llb.Constr
6161
st = llb.Scratch()
6262
}
6363

64-
st, err = sOpt.Forward(st, src)
64+
st, err = sOpt.Forward(st, src, opts...)
6565
if err != nil {
6666
return llb.Scratch(), err
6767
}

source_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,7 @@ func getSourceOp(ctx context.Context, t *testing.T, src Source) []*pb.Op {
837837
if src.Build.Source.Inline == nil || src.Build.Source.Inline.File == nil {
838838
t.Fatal("Cannot test from a Dockerfile without inline content")
839839
}
840-
sOpt.Forward = func(_ llb.State, build *SourceBuild) (llb.State, error) {
840+
sOpt.Forward = func(_ llb.State, build *SourceBuild, _ ...llb.ConstraintsOpt) (llb.State, error) {
841841
// Note, we can't really test anything other than inline here because we don't have access to the actual buildkit client,
842842
// so we can't extract extract the dockerfile from the input state (nor do we have any input state)
843843
src := []byte(src.Build.Source.Inline.File.Contents)

targets/linux/deb/distro/pkg.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,20 +170,21 @@ func (cfg *Config) RunTests(ctx context.Context, client gwclient.Client, _ llb.S
170170
}
171171

172172
withTestDeps := cfg.InstallTestDeps(sOpt, targetKey, spec, opts...)
173-
err = frontend.RunTests(ctx, client, spec, ref, withTestDeps, targetKey)
173+
err = frontend.RunTests(ctx, client, spec, ref, withTestDeps, targetKey, sOpt.TargetPlatform)
174174
return ref, err
175175
}
176176

177177
func (cfg *Config) HandleSourcePkg(ctx context.Context, client gwclient.Client) (*gwclient.Result, error) {
178178
return frontend.BuildWithPlatform(ctx, client, func(ctx context.Context, client gwclient.Client, platform *ocispecs.Platform, spec *dalec.Spec, targetKey string) (gwclient.Reference, *dalec.DockerImageSpec, error) {
179-
sOpt, err := frontend.SourceOptFromClient(ctx, client)
179+
sOpt, err := frontend.SourceOptFromClient(ctx, client, platform)
180180
if err != nil {
181181
return nil, nil, err
182182
}
183183

184184
pg := dalec.ProgressGroup(spec.Name)
185+
pc := dalec.Platform(platform)
185186

186-
worker, err := cfg.Worker(sOpt, pg)
187+
worker, err := cfg.Worker(sOpt, pg, pc)
187188
if err != nil {
188189
return nil, nil, err
189190
}
@@ -201,7 +202,7 @@ func (cfg *Config) HandleSourcePkg(ctx context.Context, client gwclient.Client)
201202
return nil, nil, err
202203
}
203204

204-
st, err := deb.SourcePackage(ctx, sOpt, worker.With(extraPaths), spec, targetKey, versionID, cfg, pg)
205+
st, err := deb.SourcePackage(ctx, sOpt, worker.With(extraPaths), spec, targetKey, versionID, cfg, pg, pc)
205206
if err != nil {
206207
return nil, nil, errors.Wrap(err, "error building source package")
207208
}

0 commit comments

Comments
 (0)