Automatically set target platform based on client architecture

Set the default platform based on the client's OS and architecture. This
function is the same one that buildkit uses (https://github.com/moby/buildkit/blob/master/frontend/dockerfile/builder/build.go#L100-L102) to set the default build target platform

Signed-off-by: Marcos Lilljedahl <marcosnils@gmail.com>
This commit is contained in:
Marcos Lilljedahl 2022-04-05 12:28:53 -03:00
parent cc79934c18
commit 34c7a2ff12
4 changed files with 46 additions and 17 deletions

View File

@ -7,12 +7,15 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/containerd/containerd/platforms"
"github.com/google/uuid" "github.com/google/uuid"
"go.opentelemetry.io/otel/trace" "go.opentelemetry.io/otel/trace"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
specs "github.com/opencontainers/image-spec/specs-go/v1"
// Cue // Cue
// buildkit // buildkit
@ -78,6 +81,15 @@ func (c *Client) Do(ctx context.Context, pctx *plancontext.Context, fn DoFunc) e
lg := log.Ctx(ctx) lg := log.Ctx(ctx)
eg, gctx := errgroup.WithContext(ctx) eg, gctx := errgroup.WithContext(ctx)
// if platform is set through plan config, skip detection.
if !pctx.Platform.IsSet() {
p, err := c.detectPlatform(ctx)
if err != nil {
return err
}
pctx.Platform.Set(*p)
}
// Spawn print function // Spawn print function
events := make(chan *bk.SolveStatus) events := make(chan *bk.SolveStatus)
eg.Go(func() error { eg.Go(func() error {
@ -95,6 +107,26 @@ func (c *Client) Do(ctx context.Context, pctx *plancontext.Context, fn DoFunc) e
return eg.Wait() return eg.Wait()
} }
// detectPlatform will try to automatically Buildkit's target platform.
// If not possible, default platform will be used.
func (c *Client) detectPlatform(ctx context.Context) (*specs.Platform, error) {
w, err := c.c.ListWorkers(ctx)
if err != nil {
return nil, fmt.Errorf("error detecting platform %w", err)
}
lg := log.Ctx(ctx)
if len(w) > 0 && len(w[0].Platforms) > 0 {
dPlatform := w[0].Platforms[0]
lg.Debug().
Str("platform", fmt.Sprintf("%s", dPlatform)).
Msg("platform detected automatically")
return &dPlatform, nil
}
defaultPlatform := platforms.DefaultSpec()
return &defaultPlatform, nil
}
func convertCacheOptionEntries(ims []bk.CacheOptionsEntry) []bkgw.CacheOptionsEntry { func convertCacheOptionEntries(ims []bk.CacheOptionsEntry) []bkgw.CacheOptionsEntry {
convertIms := []bkgw.CacheOptionsEntry{} convertIms := []bkgw.CacheOptionsEntry{}

View File

@ -123,7 +123,7 @@ func (p *Plan) configPlatform() error {
} }
// Set platform to context // Set platform to context
err = p.context.Platform.Set(platform) err = p.context.Platform.SetString(platform)
if err != nil { if err != nil {
return err return err
} }

View File

@ -17,9 +17,7 @@ type Context struct {
func New() *Context { func New() *Context {
return &Context{ return &Context{
Platform: &platformContext{ Platform: &platformContext{},
platform: defaultPlatform,
},
FS: &fsContext{ FS: &fsContext{
store: make(map[string]*FS), store: make(map[string]*FS),
}, },

View File

@ -5,28 +5,27 @@ import (
specs "github.com/opencontainers/image-spec/specs-go/v1" specs "github.com/opencontainers/image-spec/specs-go/v1"
) )
var (
// Default platform.
// FIXME: This should be auto detected using buildkit
defaultPlatform = specs.Platform{
OS: "linux",
Architecture: "amd64",
}
)
type platformContext struct { type platformContext struct {
platform specs.Platform platform *specs.Platform
} }
func (c *platformContext) Get() specs.Platform { func (c *platformContext) Get() specs.Platform {
return c.platform return *c.platform
} }
func (c *platformContext) Set(platform string) error { func (c *platformContext) SetString(platform string) error {
p, err := platforms.Parse(platform) p, err := platforms.Parse(platform)
if err != nil { if err != nil {
return err return err
} }
c.platform = p c.platform = &p
return nil return nil
} }
func (c *platformContext) Set(p specs.Platform) {
c.platform = &p
}
func (c *platformContext) IsSet() bool {
return c.platform != nil
}