Files
buildkit/solver/llbsolver/ops/exec_binfmt.go
Sebastiaan van Stijn 175973babc switch to github.com/containerd/platforms module
Switch to use github.com/containerd/platforms module, because containerd's
platforms package has moved to a separate module. This allows updating the
platforms parsing independent of the containerd module itself.

The package in containerd is deprecated, but kept as an alias to provide
compatibility between codebases.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-07-02 22:59:12 +02:00

129 lines
3.0 KiB
Go

package ops
import (
"context"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/containerd/containerd/mount"
"github.com/containerd/platforms"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/snapshot"
"github.com/moby/buildkit/solver/pb"
"github.com/moby/buildkit/util/archutil"
"github.com/moby/buildkit/util/bklog"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
copy "github.com/tonistiigi/fsutil/copy"
)
const qemuMountName = "/dev/.buildkit_qemu_emulator"
var qemuArchMap = map[string]string{
"arm64": "aarch64",
"amd64": "x86_64",
"riscv64": "riscv64",
"arm": "arm",
"s390x": "s390x",
"ppc64": "ppc64",
"ppc64le": "ppc64le",
"386": "i386",
}
type emulator struct {
path string
idmap *idtools.IdentityMapping
}
func (e *emulator) Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error) {
return &staticEmulatorMount{path: e.path, idmap: e.idmap}, nil
}
type staticEmulatorMount struct {
path string
idmap *idtools.IdentityMapping
}
func (m *staticEmulatorMount) Mount() ([]mount.Mount, func() error, error) {
tmpdir, err := os.MkdirTemp("", "buildkit-qemu-emulator")
if err != nil {
return nil, nil, err
}
var ret bool
defer func() {
if !ret {
os.RemoveAll(tmpdir)
}
}()
var uid, gid int
if m.idmap != nil {
root := m.idmap.RootPair()
uid = root.UID
gid = root.GID
}
if err := copy.Copy(context.TODO(), filepath.Dir(m.path), filepath.Base(m.path), tmpdir, qemuMountName, func(ci *copy.CopyInfo) {
m := 0555
ci.Mode = &m
}, copy.WithChown(uid, gid)); err != nil {
return nil, nil, err
}
ret = true
return []mount.Mount{{
Type: "bind",
Source: filepath.Join(tmpdir, qemuMountName),
Options: []string{"ro", "bind"},
}}, func() error {
return os.RemoveAll(tmpdir)
}, nil
}
func (m *staticEmulatorMount) IdentityMapping() *idtools.IdentityMapping {
return m.idmap
}
func getEmulator(ctx context.Context, p *pb.Platform) (*emulator, error) {
all := archutil.SupportedPlatforms(false)
pp := platforms.Normalize(ocispecs.Platform{
Architecture: p.Architecture,
OS: p.OS,
OSVersion: p.OSVersion,
OSFeatures: p.OSFeatures,
Variant: p.Variant,
})
for _, p := range all {
if platforms.Only(p).Match(pp) {
return nil, nil
}
}
if pp.Architecture == "amd64" {
if pp.Variant != "" && pp.Variant != "v2" {
var supported []string
for _, p := range all {
if p.Architecture == "amd64" {
supported = append(supported, platforms.Format(p))
}
}
return nil, errors.Errorf("no support for running processes with %s platform, supported: %s", platforms.Format(pp), strings.Join(supported, ", "))
}
}
a, ok := qemuArchMap[pp.Architecture]
if !ok {
a = pp.Architecture
}
fn, err := exec.LookPath("buildkit-qemu-" + a)
if err != nil {
bklog.G(ctx).Warn(err.Error()) // TODO: remove this with pull support
return nil, nil // no emulator available
}
return &emulator{path: fn}, nil
}