source: image source platform support

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
docker-18.09
Tonis Tiigi 2018-06-23 22:52:19 -07:00
parent 19612b901f
commit f9383c48a3
19 changed files with 240 additions and 123 deletions

View File

@ -12,6 +12,7 @@ import (
"github.com/moby/buildkit/util/contentutil"
"github.com/moby/buildkit/util/imageutil"
digest "github.com/opencontainers/go-digest"
specs "github.com/opencontainers/image-spec/specs-go/v1"
)
var defaultImageMetaResolver llb.ImageMetaResolver
@ -22,12 +23,12 @@ var WithDefault = llb.ImageOptionFunc(func(ii *llb.ImageInfo) {
})
type imageMetaResolverOpts struct {
platform string
platform *specs.Platform
}
type ImageMetaResolverOpt func(o *imageMetaResolverOpts)
func WithPlatform(p string) ImageMetaResolverOpt {
func WithDefaultPlatform(p *specs.Platform) ImageMetaResolverOpt {
return func(o *imageMetaResolverOpts) {
o.platform = p
}
@ -59,7 +60,7 @@ func Default() llb.ImageMetaResolver {
type imageMetaResolver struct {
resolver remotes.Resolver
buffer contentutil.Buffer
platform string
platform *specs.Platform
locker *locker.Locker
cache map[string]resolveResult
}
@ -69,7 +70,7 @@ type resolveResult struct {
dgst digest.Digest
}
func (imr *imageMetaResolver) ResolveImageConfig(ctx context.Context, ref string) (digest.Digest, []byte, error) {
func (imr *imageMetaResolver) ResolveImageConfig(ctx context.Context, ref string, platform *specs.Platform) (digest.Digest, []byte, error) {
imr.locker.Lock(ref)
defer imr.locker.Unlock(ref)
@ -77,7 +78,11 @@ func (imr *imageMetaResolver) ResolveImageConfig(ctx context.Context, ref string
return res.dgst, res.config, nil
}
dgst, config, err := imageutil.Config(ctx, ref, imr.resolver, imr.buffer, imr.platform)
if platform == nil {
platform = imr.platform
}
dgst, config, err := imageutil.Config(ctx, ref, imr.resolver, imr.buffer, platform)
if err != nil {
return "", nil, err
}

View File

@ -4,6 +4,7 @@ import (
"context"
digest "github.com/opencontainers/go-digest"
specs "github.com/opencontainers/image-spec/specs-go/v1"
)
func WithMetaResolver(mr ImageMetaResolver) ImageOption {
@ -13,5 +14,5 @@ func WithMetaResolver(mr ImageMetaResolver) ImageOption {
}
type ImageMetaResolver interface {
ResolveImageConfig(ctx context.Context, ref string) (digest.Digest, []byte, error)
ResolveImageConfig(ctx context.Context, ref string, platform *specs.Platform) (digest.Digest, []byte, error)
}

View File

@ -87,7 +87,7 @@ func Image(ref string, opts ...ImageOption) State {
src.err = err
}
if info.metaResolver != nil {
_, dt, err := info.metaResolver.ResolveImageConfig(context.TODO(), ref)
_, dt, err := info.metaResolver.ResolveImageConfig(context.TODO(), ref, info.Constraints.Platform)
if err != nil {
src.err = err
} else {

View File

@ -162,8 +162,8 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State,
d.stage.BaseName = reference.TagNameOnly(ref).String()
var isScratch bool
if metaResolver != nil && reachable {
dgst, dt, err := metaResolver.ResolveImageConfig(ctx, d.stage.BaseName)
if err == nil { // handle the error while builder is actually running
dgst, dt, err := metaResolver.ResolveImageConfig(ctx, d.stage.BaseName, nil) // TODO: platform
if err == nil { // handle the error while builder is actually running
var img Image
if err := json.Unmarshal(dt, &img); err != nil {
return err

View File

@ -9,6 +9,7 @@ import (
"github.com/moby/buildkit/solver"
"github.com/moby/buildkit/solver/pb"
digest "github.com/opencontainers/go-digest"
specs "github.com/opencontainers/image-spec/specs-go/v1"
)
type Frontend interface {
@ -17,7 +18,7 @@ type Frontend interface {
type FrontendLLBBridge interface {
Solve(ctx context.Context, req SolveRequest) (solver.CachedResult, map[string][]byte, error)
ResolveImageConfig(ctx context.Context, ref string) (digest.Digest, []byte, error)
ResolveImageConfig(ctx context.Context, ref string, platform *specs.Platform) (digest.Digest, []byte, error)
Exec(ctx context.Context, meta executor.Meta, rootfs cache.ImmutableRef, stdin io.ReadCloser, stdout, stderr io.WriteCloser) error
}

View File

@ -5,12 +5,13 @@ import (
"github.com/moby/buildkit/solver/pb"
digest "github.com/opencontainers/go-digest"
specs "github.com/opencontainers/image-spec/specs-go/v1"
)
// TODO: make this take same options as LLBBridge. Add Return()
type Client interface {
Solve(ctx context.Context, req SolveRequest, exporterAttr map[string][]byte, final bool) (Reference, error)
ResolveImageConfig(ctx context.Context, ref string) (digest.Digest, []byte, error)
ResolveImageConfig(ctx context.Context, ref string, platform *specs.Platform) (digest.Digest, []byte, error)
Opts() map[string]string
SessionID() string
}

View File

@ -22,7 +22,7 @@ import (
"github.com/moby/buildkit/solver"
"github.com/moby/buildkit/util/tracing"
"github.com/moby/buildkit/worker"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/net/http2"
@ -63,7 +63,7 @@ func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.Fronten
sid := session.FromContext(ctx)
_, isDevel := opts[keyDevel]
var img ocispec.Image
var img specs.Image
var rootFS cache.ImmutableRef
var readonly bool // TODO: try to switch to read-only by default.
@ -95,7 +95,7 @@ func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.Fronten
return nil, nil, err
}
dgst, config, err := llbBridge.ResolveImageConfig(ctx, reference.TagNameOnly(sourceRef).String())
dgst, config, err := llbBridge.ResolveImageConfig(ctx, reference.TagNameOnly(sourceRef).String(), nil) // TODO:
if err != nil {
return nil, nil, err
}
@ -262,7 +262,17 @@ type llbBridgeForwarder struct {
func (lbf *llbBridgeForwarder) ResolveImageConfig(ctx context.Context, req *pb.ResolveImageConfigRequest) (*pb.ResolveImageConfigResponse, error) {
ctx = tracing.ContextWithSpanFromContext(ctx, lbf.callCtx)
dgst, dt, err := lbf.llbBridge.ResolveImageConfig(ctx, req.Ref)
var platform *specs.Platform
if p := req.Platform; p != nil {
platform = &specs.Platform{
OS: p.OS,
Architecture: p.Architecture,
Variant: p.Variant,
OSVersion: p.OSVersion,
OSFeatures: p.OSFeatures,
}
}
dgst, dt, err := lbf.llbBridge.ResolveImageConfig(ctx, req.Ref, platform)
if err != nil {
return nil, err
}

View File

@ -11,7 +11,9 @@ import (
"github.com/moby/buildkit/frontend/gateway/client"
pb "github.com/moby/buildkit/frontend/gateway/pb"
opspb "github.com/moby/buildkit/solver/pb"
digest "github.com/opencontainers/go-digest"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"google.golang.org/grpc"
)
@ -63,8 +65,18 @@ func (c *grpcClient) Solve(ctx context.Context, creq client.SolveRequest, export
return &reference{id: resp.Ref, c: c}, nil
}
func (c *grpcClient) ResolveImageConfig(ctx context.Context, ref string) (digest.Digest, []byte, error) {
resp, err := c.client.ResolveImageConfig(ctx, &pb.ResolveImageConfigRequest{Ref: ref})
func (c *grpcClient) ResolveImageConfig(ctx context.Context, ref string, platform *specs.Platform) (digest.Digest, []byte, error) {
var p *opspb.Platform
if platform != nil {
p = &opspb.Platform{
OS: platform.OS,
Architecture: platform.Architecture,
Variant: platform.Variant,
OSVersion: platform.OSVersion,
OSFeatures: platform.OSFeatures,
}
}
resp, err := c.client.ResolveImageConfig(ctx, &pb.ResolveImageConfigRequest{Ref: ref, Platform: p})
if err != nil {
return "", nil, err
}

View File

@ -45,7 +45,8 @@ var _ = math.Inf
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
type ResolveImageConfigRequest struct {
Ref string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"`
Ref string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"`
Platform *pb.Platform `protobuf:"bytes,2,opt,name=Platform" json:"Platform,omitempty"`
}
func (m *ResolveImageConfigRequest) Reset() { *m = ResolveImageConfigRequest{} }
@ -60,6 +61,13 @@ func (m *ResolveImageConfigRequest) GetRef() string {
return ""
}
func (m *ResolveImageConfigRequest) GetPlatform() *pb.Platform {
if m != nil {
return m.Platform
}
return nil
}
type ResolveImageConfigResponse struct {
Digest github_com_opencontainers_go_digest.Digest `protobuf:"bytes,1,opt,name=Digest,proto3,customtype=github.com/opencontainers/go-digest.Digest" json:"Digest"`
Config []byte `protobuf:"bytes,2,opt,name=Config,proto3" json:"Config,omitempty"`
@ -451,6 +459,16 @@ func (m *ResolveImageConfigRequest) MarshalTo(dAtA []byte) (int, error) {
i = encodeVarintGateway(dAtA, i, uint64(len(m.Ref)))
i += copy(dAtA[i:], m.Ref)
}
if m.Platform != nil {
dAtA[i] = 0x12
i++
i = encodeVarintGateway(dAtA, i, uint64(m.Platform.Size()))
n1, err := m.Platform.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n1
}
return i, nil
}
@ -503,11 +521,11 @@ func (m *SolveRequest) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0xa
i++
i = encodeVarintGateway(dAtA, i, uint64(m.Definition.Size()))
n1, err := m.Definition.MarshalTo(dAtA[i:])
n2, err := m.Definition.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n1
i += n2
}
if len(m.Frontend) > 0 {
dAtA[i] = 0x12
@ -627,11 +645,11 @@ func (m *ReadFileRequest) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0x1a
i++
i = encodeVarintGateway(dAtA, i, uint64(m.Range.Size()))
n2, err := m.Range.MarshalTo(dAtA[i:])
n3, err := m.Range.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n2
i += n3
}
return i, nil
}
@ -740,6 +758,10 @@ func (m *ResolveImageConfigRequest) Size() (n int) {
if l > 0 {
n += 1 + l + sovGateway(uint64(l))
}
if m.Platform != nil {
l = m.Platform.Size()
n += 1 + l + sovGateway(uint64(l))
}
return n
}
@ -929,6 +951,39 @@ func (m *ResolveImageConfigRequest) Unmarshal(dAtA []byte) error {
}
m.Ref = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Platform", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGateway
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGateway
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.Platform == nil {
m.Platform = &pb.Platform{}
}
if err := m.Platform.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipGateway(dAtA[iNdEx:])
@ -1998,45 +2053,46 @@ var (
func init() { proto.RegisterFile("gateway.proto", fileDescriptorGateway) }
var fileDescriptorGateway = []byte{
// 629 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0x4d, 0x4f, 0xdb, 0x40,
0x10, 0xad, 0x63, 0x40, 0x64, 0x12, 0x3e, 0xb4, 0xaa, 0x2a, 0xe3, 0x03, 0x44, 0x56, 0x45, 0x2d,
0x5a, 0x6c, 0x35, 0x6d, 0x25, 0x44, 0xa5, 0x4a, 0x0d, 0x1f, 0x12, 0x15, 0x12, 0x68, 0x7b, 0xa8,
0xc4, 0xcd, 0x4e, 0xc6, 0x66, 0x45, 0xb2, 0xeb, 0xda, 0x1b, 0xda, 0xa8, 0x97, 0xf6, 0xe7, 0xf4,
0x9f, 0x70, 0xec, 0x99, 0x03, 0xaa, 0xf8, 0x25, 0x95, 0xd7, 0xeb, 0x60, 0x48, 0x49, 0xe9, 0x6d,
0xdf, 0x78, 0xe6, 0xed, 0x9b, 0x79, 0xb3, 0x86, 0x85, 0x38, 0x90, 0xf8, 0x25, 0x18, 0x79, 0x49,
0x2a, 0xa4, 0x20, 0x2b, 0x03, 0x11, 0x8e, 0xbc, 0x70, 0xc8, 0xfa, 0xbd, 0x33, 0x26, 0xbd, 0xf3,
0x97, 0x5e, 0x94, 0x0a, 0x2e, 0x91, 0xf7, 0xec, 0xcd, 0x98, 0xc9, 0xd3, 0x61, 0xe8, 0x75, 0xc5,
0xc0, 0x8f, 0x45, 0x2c, 0x7c, 0x55, 0x11, 0x0e, 0x23, 0x85, 0x14, 0x50, 0xa7, 0x82, 0xc9, 0x7e,
0x51, 0x49, 0xcf, 0x49, 0xfd, 0x92, 0xd4, 0xcf, 0x44, 0xff, 0x1c, 0x53, 0x3f, 0x09, 0x7d, 0x91,
0x64, 0x45, 0xb6, 0xb3, 0x09, 0x2b, 0x14, 0xd5, 0x87, 0x83, 0x41, 0x10, 0xe3, 0x8e, 0xe0, 0x11,
0x8b, 0x29, 0x7e, 0x1e, 0x62, 0x26, 0xc9, 0x32, 0x98, 0x14, 0x23, 0xcb, 0x68, 0x19, 0x6e, 0x9d,
0xe6, 0x47, 0xe7, 0xbb, 0x01, 0xf6, 0xdf, 0xf2, 0xb3, 0x44, 0xf0, 0x0c, 0xc9, 0x07, 0x98, 0xdb,
0x65, 0x31, 0x66, 0xb2, 0xa8, 0xe9, 0xb4, 0x2f, 0xae, 0xd6, 0x1e, 0x5d, 0x5e, 0xad, 0x6d, 0x54,
0x34, 0x89, 0x04, 0x79, 0x57, 0x70, 0x19, 0x30, 0x8e, 0x69, 0xe6, 0xc7, 0x62, 0xb3, 0xa7, 0x4a,
0xbc, 0xa2, 0x92, 0x6a, 0x06, 0xf2, 0x04, 0xe6, 0x0a, 0x76, 0xab, 0xd6, 0x32, 0xdc, 0x26, 0xd5,
0xc8, 0xb9, 0xac, 0x41, 0xf3, 0x63, 0x2e, 0xa0, 0x54, 0xe9, 0x01, 0xec, 0x62, 0xc4, 0x38, 0x93,
0x4c, 0x70, 0x75, 0x71, 0xa3, 0xbd, 0xe8, 0x25, 0xa1, 0x77, 0x13, 0xa5, 0x95, 0x0c, 0x62, 0xc3,
0xfc, 0xbe, 0x9e, 0xad, 0xa2, 0xae, 0xd3, 0x31, 0x26, 0x27, 0xd0, 0x28, 0xcf, 0x47, 0x89, 0xb4,
0xcc, 0x96, 0xe9, 0x36, 0xda, 0x5b, 0xde, 0xbd, 0xe6, 0x78, 0x55, 0x25, 0x5e, 0xa5, 0x74, 0x8f,
0xcb, 0x74, 0x44, 0xab, 0x64, 0xc4, 0x85, 0xa5, 0x83, 0x41, 0x22, 0x52, 0xb9, 0x13, 0x74, 0x4f,
0x91, 0x62, 0x94, 0x59, 0x33, 0x2d, 0xd3, 0xad, 0xd3, 0xbb, 0x61, 0xf2, 0x18, 0x66, 0xf7, 0x19,
0x0f, 0xfa, 0x16, 0xb4, 0x0c, 0x77, 0x9e, 0x16, 0x80, 0x38, 0xd0, 0xdc, 0xfb, 0x9a, 0x27, 0x62,
0xfa, 0x5e, 0xca, 0xd4, 0x6a, 0xa8, 0xb1, 0xdc, 0x8a, 0xd9, 0xef, 0x60, 0xf9, 0xae, 0x88, 0xdc,
0xc5, 0x33, 0x1c, 0x95, 0x2e, 0x9e, 0xe1, 0x28, 0xe7, 0x3f, 0x0f, 0xfa, 0x43, 0xd4, 0xed, 0x17,
0x60, 0xbb, 0xb6, 0x65, 0x38, 0x7b, 0xb0, 0xa0, 0x3b, 0xd2, 0x8e, 0x4e, 0xac, 0xc0, 0x84, 0x8c,
0xda, 0xa4, 0x0c, 0xe7, 0x1b, 0x2c, 0x51, 0x0c, 0x7a, 0xfb, 0xac, 0x8f, 0xf7, 0xee, 0x92, 0xf2,
0x81, 0xf5, 0xf1, 0x38, 0x90, 0xa7, 0x63, 0x1f, 0x34, 0x26, 0xdb, 0x30, 0x4b, 0x03, 0x1e, 0xa3,
0x65, 0x2a, 0x3b, 0x9f, 0x4e, 0x71, 0x40, 0x5d, 0x92, 0xe7, 0xd2, 0xa2, 0xc4, 0x79, 0x0b, 0xf5,
0x71, 0x2c, 0xdf, 0xa2, 0xa3, 0x28, 0xca, 0xb0, 0xd8, 0x48, 0x93, 0x6a, 0x94, 0xc7, 0x0f, 0x91,
0xc7, 0xfa, 0x6a, 0x93, 0x6a, 0xe4, 0xac, 0xc3, 0xf2, 0x8d, 0x72, 0x3d, 0x03, 0x02, 0x33, 0xbb,
0x81, 0x0c, 0x14, 0x43, 0x93, 0xaa, 0xb3, 0xb3, 0x00, 0x8d, 0x63, 0xc6, 0xcb, 0x97, 0xe2, 0x2c,
0x42, 0xf3, 0x58, 0xf0, 0xf1, 0x43, 0x68, 0xff, 0x34, 0xa1, 0x7e, 0x78, 0xd8, 0xe9, 0xa4, 0xac,
0x17, 0x23, 0xf9, 0x61, 0x00, 0x99, 0x7c, 0x35, 0xe4, 0xf5, 0x94, 0xae, 0xee, 0x7d, 0x94, 0xf6,
0x9b, 0xff, 0xac, 0xd2, 0x4d, 0x9c, 0xc0, 0xac, 0x72, 0x96, 0x3c, 0x7b, 0xe0, 0x36, 0xdb, 0xee,
0xbf, 0x13, 0x35, 0x77, 0x17, 0xe6, 0xcb, 0xa1, 0x91, 0x8d, 0xa9, 0xf2, 0x6e, 0xed, 0x84, 0xfd,
0xfc, 0x41, 0xb9, 0xfa, 0x92, 0x4f, 0x30, 0x93, 0x4f, 0x9c, 0xac, 0x4f, 0x29, 0xaa, 0x58, 0x62,
0x4f, 0xeb, 0xb3, 0xea, 0x55, 0xa7, 0x79, 0x71, 0xbd, 0x6a, 0xfc, 0xba, 0x5e, 0x35, 0x7e, 0x5f,
0xaf, 0x1a, 0xe1, 0x9c, 0xfa, 0x2f, 0xbe, 0xfa, 0x13, 0x00, 0x00, 0xff, 0xff, 0xd8, 0x21, 0xd1,
0x98, 0xa0, 0x05, 0x00, 0x00,
// 652 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0x4d, 0x4f, 0xdb, 0x4a,
0x14, 0x7d, 0x8e, 0x01, 0x25, 0x37, 0xe6, 0x43, 0xa3, 0xa7, 0x27, 0xe3, 0x05, 0x44, 0xd6, 0x13,
0xcf, 0xe2, 0x15, 0x5b, 0x4d, 0x5b, 0x09, 0x51, 0xa9, 0x52, 0xc3, 0x87, 0x44, 0x85, 0x44, 0x34,
0x5d, 0x20, 0xb1, 0x1b, 0x27, 0x63, 0x33, 0xc2, 0x99, 0x71, 0xed, 0x09, 0x6d, 0xd4, 0x4d, 0xfb,
0x73, 0xfa, 0x4f, 0x58, 0x76, 0xcd, 0x02, 0x55, 0xfc, 0x92, 0xca, 0xe3, 0x71, 0x30, 0x50, 0x52,
0xba, 0x9b, 0x73, 0x7d, 0xef, 0x99, 0x73, 0xe7, 0xdc, 0x6b, 0x58, 0x8c, 0x89, 0xa4, 0x1f, 0xc9,
0xc4, 0x4f, 0x33, 0x21, 0x05, 0x5a, 0x1d, 0x89, 0x70, 0xe2, 0x87, 0x63, 0x96, 0x0c, 0xcf, 0x99,
0xf4, 0x2f, 0x9e, 0xfb, 0x51, 0x26, 0xb8, 0xa4, 0x7c, 0xe8, 0x6c, 0xc5, 0x4c, 0x9e, 0x8d, 0x43,
0x7f, 0x20, 0x46, 0x41, 0x2c, 0x62, 0x11, 0xa8, 0x8a, 0x70, 0x1c, 0x29, 0xa4, 0x80, 0x3a, 0x95,
0x4c, 0xce, 0xb3, 0x5a, 0x7a, 0x41, 0x1a, 0x54, 0xa4, 0x41, 0x2e, 0x92, 0x0b, 0x9a, 0x05, 0x69,
0x18, 0x88, 0x34, 0x2f, 0xb3, 0xdd, 0x13, 0x58, 0xc5, 0x54, 0x7d, 0x38, 0x1c, 0x91, 0x98, 0xee,
0x0a, 0x1e, 0xb1, 0x18, 0xd3, 0x0f, 0x63, 0x9a, 0x4b, 0xb4, 0x02, 0x26, 0xa6, 0x91, 0x6d, 0x74,
0x0c, 0xaf, 0x85, 0x8b, 0x23, 0xf2, 0xa0, 0xd9, 0x4f, 0x88, 0x8c, 0x44, 0x36, 0xb2, 0x1b, 0x1d,
0xc3, 0x6b, 0x77, 0x2d, 0x3f, 0x0d, 0xfd, 0x2a, 0x86, 0xa7, 0x5f, 0xdd, 0x2f, 0x06, 0x38, 0xbf,
0x62, 0xce, 0x53, 0xc1, 0x73, 0x8a, 0xde, 0xc1, 0xc2, 0x1e, 0x8b, 0x69, 0x2e, 0x4b, 0xf6, 0x5e,
0xf7, 0xf2, 0x7a, 0xfd, 0xaf, 0xab, 0xeb, 0xf5, 0xcd, 0x9a, 0x7a, 0x91, 0x52, 0x3e, 0x10, 0x5c,
0x12, 0xc6, 0x69, 0x96, 0x07, 0xb1, 0xd8, 0x1a, 0xaa, 0x12, 0xbf, 0xac, 0xc4, 0x9a, 0x01, 0xfd,
0x03, 0x0b, 0x25, 0xbb, 0x92, 0x64, 0x61, 0x8d, 0xdc, 0xab, 0x06, 0x58, 0xef, 0x0b, 0x01, 0x55,
0x3f, 0x3e, 0xc0, 0x1e, 0x8d, 0x18, 0x67, 0x92, 0x09, 0xae, 0x2e, 0x6e, 0x77, 0x97, 0x0a, 0xfd,
0xb7, 0x51, 0x5c, 0xcb, 0x40, 0x0e, 0x34, 0x0f, 0xb4, 0x0b, 0x8a, 0xba, 0x85, 0xa7, 0x18, 0x9d,
0x42, 0xbb, 0x3a, 0x1f, 0xa7, 0xd2, 0x36, 0x3b, 0xa6, 0xd7, 0xee, 0x6e, 0xfb, 0x8f, 0xda, 0xe8,
0xd7, 0x95, 0xf8, 0xb5, 0xd2, 0x7d, 0x2e, 0xb3, 0x09, 0xae, 0x93, 0x21, 0x0f, 0x96, 0x0f, 0x47,
0xa9, 0xc8, 0xe4, 0x2e, 0x19, 0x9c, 0x51, 0x4c, 0xa3, 0xdc, 0x9e, 0xeb, 0x98, 0x5e, 0x0b, 0xdf,
0x0f, 0xa3, 0xbf, 0x61, 0xfe, 0x80, 0x71, 0x92, 0xd8, 0xd0, 0x31, 0xbc, 0x26, 0x2e, 0x01, 0x72,
0xc1, 0xda, 0xff, 0x54, 0x24, 0xd2, 0xec, 0xad, 0x94, 0x99, 0xdd, 0x56, 0xcf, 0x72, 0x27, 0xe6,
0xbc, 0x81, 0x95, 0xfb, 0x22, 0x0a, 0xbf, 0xcf, 0xe9, 0xa4, 0xf2, 0xfb, 0x9c, 0x4e, 0x0a, 0xfe,
0x0b, 0x92, 0x8c, 0xa9, 0x6e, 0xbf, 0x04, 0x3b, 0x8d, 0x6d, 0xc3, 0xdd, 0x87, 0x45, 0xdd, 0x91,
0x76, 0xf4, 0xe1, 0xb0, 0xdc, 0x97, 0xd1, 0x78, 0x28, 0xc3, 0xfd, 0x0c, 0xcb, 0x98, 0x92, 0xe1,
0x01, 0x4b, 0xe8, 0xe3, 0x53, 0x57, 0xf8, 0xc0, 0x12, 0xda, 0x27, 0xf2, 0x6c, 0xea, 0x83, 0xc6,
0x68, 0x07, 0xe6, 0x31, 0xe1, 0x31, 0xb5, 0x4d, 0x65, 0xe7, 0xbf, 0x33, 0x1c, 0x50, 0x97, 0x14,
0xb9, 0xb8, 0x2c, 0x71, 0x5f, 0x43, 0x6b, 0x1a, 0x2b, 0xa6, 0xe8, 0x38, 0x8a, 0x72, 0x5a, 0x4e,
0xa4, 0x89, 0x35, 0x2a, 0xe2, 0x47, 0x94, 0xc7, 0xfa, 0x6a, 0x13, 0x6b, 0xe4, 0x6e, 0xc0, 0xca,
0xad, 0x72, 0xfd, 0x06, 0x08, 0xe6, 0xf6, 0x88, 0x24, 0x8a, 0xc1, 0xc2, 0xea, 0xec, 0x2e, 0x42,
0xbb, 0xcf, 0x78, 0xb5, 0x53, 0xee, 0x12, 0x58, 0x7d, 0xc1, 0xa7, 0x8b, 0xd0, 0xfd, 0x66, 0x42,
0xeb, 0xe8, 0xa8, 0xd7, 0xcb, 0xd8, 0x30, 0xa6, 0xe8, 0xab, 0x01, 0xe8, 0xe1, 0xd6, 0xa0, 0x97,
0x33, 0xba, 0x7a, 0x74, 0x7d, 0x9d, 0x57, 0x7f, 0x58, 0xa5, 0x9b, 0x38, 0x85, 0x79, 0xe5, 0x2c,
0xfa, 0xef, 0x89, 0xd3, 0xec, 0x78, 0xbf, 0x4f, 0xd4, 0xdc, 0x03, 0x68, 0x56, 0x8f, 0x86, 0x36,
0x67, 0xca, 0xbb, 0x33, 0x13, 0xce, 0xff, 0x4f, 0xca, 0xd5, 0x97, 0x9c, 0xc0, 0x5c, 0xf1, 0xe2,
0x68, 0x63, 0x46, 0x51, 0xcd, 0x12, 0x67, 0x56, 0x9f, 0x75, 0xaf, 0x7a, 0xd6, 0xe5, 0xcd, 0x9a,
0xf1, 0xfd, 0x66, 0xcd, 0xf8, 0x71, 0xb3, 0x66, 0x84, 0x0b, 0xea, 0x0f, 0xfa, 0xe2, 0x67, 0x00,
0x00, 0x00, 0xff, 0xff, 0xbc, 0x68, 0x1b, 0xf0, 0xca, 0x05, 0x00, 0x00,
}

View File

@ -18,6 +18,7 @@ service LLBBridge {
message ResolveImageConfigRequest {
string Ref = 1;
pb.Platform Platform = 2;
}
message ResolveImageConfigResponse {

View File

@ -108,12 +108,12 @@ func (s *llbBridge) Exec(ctx context.Context, meta executor.Meta, root cache.Imm
return err
}
func (s *llbBridge) ResolveImageConfig(ctx context.Context, ref string) (digest.Digest, []byte, error) {
func (s *llbBridge) ResolveImageConfig(ctx context.Context, ref string, platform *specs.Platform) (digest.Digest, []byte, error) {
w, err := s.resolveWorker()
if err != nil {
return "", nil, err
}
return w.ResolveImageConfig(ctx, ref)
return w.ResolveImageConfig(ctx, ref, platform)
}
type lazyCacheManager struct {

View File

@ -14,18 +14,20 @@ import (
const sourceCacheType = "buildkit.source.v0"
type sourceOp struct {
mu sync.Mutex
op *pb.Op_Source
sm *source.Manager
src source.SourceInstance
w worker.Worker
mu sync.Mutex
op *pb.Op_Source
platform *pb.Platform
sm *source.Manager
src source.SourceInstance
w worker.Worker
}
func NewSourceOp(_ solver.Vertex, op *pb.Op_Source, sm *source.Manager, w worker.Worker) (solver.Op, error) {
func NewSourceOp(_ solver.Vertex, op *pb.Op_Source, platform *pb.Platform, sm *source.Manager, w worker.Worker) (solver.Op, error) {
return &sourceOp{
op: op,
sm: sm,
w: w,
op: op,
sm: sm,
w: w,
platform: platform,
}, nil
}
@ -35,7 +37,7 @@ func (s *sourceOp) instance(ctx context.Context) (source.SourceInstance, error)
if s.src != nil {
return s.src, nil
}
id, err := source.FromLLB(s.op)
id, err := source.FromLLB(s.op, s.platform)
if err != nil {
return nil, err
}

View File

@ -129,7 +129,7 @@ func loadLLB(def *pb.Definition, fn func(digest.Digest, *pb.Op, func(digest.Dige
func llbOpName(op *pb.Op) string {
switch op := op.Op.(type) {
case *pb.Op_Source:
if id, err := source.FromLLB(op); err == nil {
if id, err := source.FromLLB(op, nil); err == nil {
if id, ok := id.(*source.LocalIdentifier); ok {
if len(id.IncludePatterns) == 1 {
return op.Source.Identifier + " (" + id.IncludePatterns[0] + ")"

View File

@ -4,11 +4,11 @@ import (
"context"
"encoding/json"
"fmt"
"runtime"
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/diff"
"github.com/containerd/containerd/images"
"github.com/containerd/containerd/platforms"
"github.com/docker/distribution/reference"
"github.com/moby/buildkit/cache"
"github.com/moby/buildkit/session"
@ -19,7 +19,7 @@ import (
"github.com/moby/buildkit/util/pull"
digest "github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/identity"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)
@ -52,13 +52,13 @@ func (is *imageSource) ID() string {
return source.DockerImageScheme
}
func (is *imageSource) ResolveImageConfig(ctx context.Context, ref string) (digest.Digest, []byte, error) {
func (is *imageSource) ResolveImageConfig(ctx context.Context, ref string, platform *specs.Platform) (digest.Digest, []byte, error) {
type t struct {
dgst digest.Digest
dt []byte
}
res, err := is.g.Do(ctx, ref, func(ctx context.Context) (interface{}, error) {
dgst, dt, err := imageutil.Config(ctx, ref, pull.NewResolver(ctx, is.SessionManager, is.ImageStore), is.ContentStore, "")
dgst, dt, err := imageutil.Config(ctx, ref, pull.NewResolver(ctx, is.SessionManager, is.ImageStore), is.ContentStore, platform)
if err != nil {
return nil, err
}
@ -77,34 +77,44 @@ func (is *imageSource) Resolve(ctx context.Context, id source.Identifier) (sourc
return nil, errors.Errorf("invalid image identifier %v", id)
}
platform := platforms.DefaultSpec()
if imageIdentifier.Platform != nil {
platform = *imageIdentifier.Platform
}
pullerUtil := &pull.Puller{
Snapshotter: is.Snapshotter,
ContentStore: is.ContentStore,
Applier: is.Applier,
Src: imageIdentifier.Reference,
Resolver: pull.NewResolver(ctx, is.SessionManager, is.ImageStore),
Platform: &platform,
}
p := &puller{
CacheAccessor: is.CacheAccessor,
Puller: pullerUtil,
Platform: platform,
}
return p, nil
}
type puller struct {
CacheAccessor cache.Accessor
Platform specs.Platform
*pull.Puller
}
func mainManifestKey(ctx context.Context, desc ocispec.Descriptor) (digest.Digest, error) {
func mainManifestKey(ctx context.Context, desc specs.Descriptor, platform specs.Platform) (digest.Digest, error) {
dt, err := json.Marshal(struct {
Digest digest.Digest
OS string
Arch string
Digest digest.Digest
OS string
Arch string
Variant string `json:",omitempty"`
}{
Digest: desc.Digest,
OS: runtime.GOOS,
Arch: runtime.GOARCH,
Digest: desc.Digest,
OS: platform.OS,
Arch: platform.Architecture,
Variant: platform.Variant,
})
if err != nil {
return "", err
@ -118,7 +128,7 @@ func (p *puller) CacheKey(ctx context.Context, index int) (string, bool, error)
return "", false, err
}
if index == 0 || desc.Digest == "" {
k, err := mainManifestKey(ctx, desc)
k, err := mainManifestKey(ctx, desc, p.Platform)
if err != nil {
return "", false, err
}
@ -132,10 +142,10 @@ func (p *puller) CacheKey(ctx context.Context, index int) (string, bool, error)
if err != nil {
return "", false, nil
}
_, dt, err := imageutil.Config(ctx, ref.String(), p.Resolver, p.ContentStore, "")
_, dt, err := imageutil.Config(ctx, ref.String(), p.Resolver, p.ContentStore, nil) // TODO
if err != nil {
// this happens on schema1 images
k, err := mainManifestKey(ctx, desc)
k, err := mainManifestKey(ctx, desc, p.Platform)
if err != nil {
return "", false, err
}
@ -158,7 +168,7 @@ func (p *puller) Snapshot(ctx context.Context) (cache.ImmutableRef, error) {
// cacheKeyFromConfig returns a stable digest from image config. If image config
// is a known oci image we will use chainID of layers.
func cacheKeyFromConfig(dt []byte) digest.Digest {
var img ocispec.Image
var img specs.Image
err := json.Unmarshal(dt, &img)
if err != nil {
return digest.FromBytes(dt)

View File

@ -8,6 +8,7 @@ import (
"github.com/containerd/containerd/reference"
"github.com/moby/buildkit/solver/pb"
digest "github.com/opencontainers/go-digest"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)
@ -50,11 +51,20 @@ func FromString(s string) (Identifier, error) {
return nil, errors.Wrapf(errNotFound, "unknown schema %s", parts[0])
}
}
func FromLLB(op *pb.Op_Source) (Identifier, error) {
func FromLLB(op *pb.Op_Source, platform *pb.Platform) (Identifier, error) {
id, err := FromString(op.Source.Identifier)
if err != nil {
return nil, err
}
if id, ok := id.(*ImageIdentifier); ok && platform != nil {
id.Platform = &specs.Platform{
OS: platform.OS,
Architecture: platform.Architecture,
Variant: platform.Variant,
OSVersion: platform.OSVersion,
OSFeatures: platform.OSFeatures,
}
}
if id, ok := id.(*GitIdentifier); ok {
for k, v := range op.Source.Attrs {
switch k {
@ -136,6 +146,7 @@ func FromLLB(op *pb.Op_Source) (Identifier, error) {
type ImageIdentifier struct {
Reference reference.Spec
Platform *specs.Platform
}
func NewImageIdentifier(str string) (*ImageIdentifier, error) {

View File

@ -10,7 +10,7 @@ import (
"github.com/containerd/containerd/reference"
"github.com/containerd/containerd/remotes"
digest "github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)
@ -19,16 +19,18 @@ type IngesterProvider interface {
content.Provider
}
func Config(ctx context.Context, str string, resolver remotes.Resolver, ingester IngesterProvider, platform string) (digest.Digest, []byte, error) {
if platform == "" {
platform = platforms.Default()
func Config(ctx context.Context, str string, resolver remotes.Resolver, ingester IngesterProvider, platform *specs.Platform) (digest.Digest, []byte, error) {
// TODO: fix containerd to take struct instead of string
platformStr := platforms.Default()
if platform != nil {
platformStr = platforms.Format(*platform)
}
ref, err := reference.Parse(str)
if err != nil {
return "", nil, errors.WithStack(err)
}
desc := ocispec.Descriptor{
desc := specs.Descriptor{
Digest: ref.Digest(),
}
if desc.Digest != "" {
@ -56,12 +58,12 @@ func Config(ctx context.Context, str string, resolver remotes.Resolver, ingester
handlers := []images.Handler{
remotes.FetchHandler(ingester, fetcher),
childrenConfigHandler(ingester, platform),
childrenConfigHandler(ingester, platformStr),
}
if err := images.Dispatch(ctx, images.Handlers(handlers...), desc); err != nil {
return "", nil, err
}
config, err := images.Config(ctx, ingester, desc, platform)
config, err := images.Config(ctx, ingester, desc, platformStr)
if err != nil {
return "", nil, err
}
@ -75,10 +77,10 @@ func Config(ctx context.Context, str string, resolver remotes.Resolver, ingester
}
func childrenConfigHandler(provider content.Provider, platform string) images.HandlerFunc {
return func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
var descs []ocispec.Descriptor
return func(ctx context.Context, desc specs.Descriptor) ([]specs.Descriptor, error) {
var descs []specs.Descriptor
switch desc.MediaType {
case images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest:
case images.MediaTypeDockerSchema2Manifest, specs.MediaTypeImageManifest:
p, err := content.ReadBlob(ctx, provider, desc)
if err != nil {
return nil, err
@ -86,19 +88,19 @@ func childrenConfigHandler(provider content.Provider, platform string) images.Ha
// TODO(stevvooe): We just assume oci manifest, for now. There may be
// subtle differences from the docker version.
var manifest ocispec.Manifest
var manifest specs.Manifest
if err := json.Unmarshal(p, &manifest); err != nil {
return nil, err
}
descs = append(descs, manifest.Config)
case images.MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex:
case images.MediaTypeDockerSchema2ManifestList, specs.MediaTypeImageIndex:
p, err := content.ReadBlob(ctx, provider, desc)
if err != nil {
return nil, err
}
var index ocispec.Index
var index specs.Index
if err := json.Unmarshal(p, &index); err != nil {
return nil, err
}
@ -118,7 +120,7 @@ func childrenConfigHandler(provider content.Provider, platform string) images.Ha
} else {
descs = append(descs, index.Manifests...)
}
case images.MediaTypeDockerSchema2Config, ocispec.MediaTypeImageConfig:
case images.MediaTypeDockerSchema2Config, specs.MediaTypeImageConfig:
// childless data types.
return nil, nil
default:
@ -129,7 +131,7 @@ func childrenConfigHandler(provider content.Provider, platform string) images.Ha
}
}
// ocispec.MediaTypeImageManifest, // TODO: detect schema1/manifest-list
// specs.MediaTypeImageManifest, // TODO: detect schema1/manifest-list
func DetectManifestMediaType(ra content.ReaderAt) (string, error) {
// TODO: schema1

View File

@ -29,6 +29,7 @@ type Puller struct {
ContentStore content.Store
Applier diff.Applier
Src reference.Spec
Platform *ocispec.Platform
// See NewResolver()
Resolver remotes.Resolver
resolveOnce sync.Once
@ -86,6 +87,11 @@ func (p *Puller) Pull(ctx context.Context) (*Pulled, error) {
return nil, err
}
platformStr := platforms.Default()
if p.Platform != nil {
platformStr = platforms.Format(*p.Platform)
}
ongoing := newJobs(p.ref)
pctx, stopProgress := context.WithCancel(ctx)
@ -117,7 +123,7 @@ func (p *Puller) Pull(ctx context.Context) (*Pulled, error) {
// Set any children labels for that content
childrenHandler = images.SetChildrenLabels(p.ContentStore, childrenHandler)
// Filter the childen by the platform
childrenHandler = images.FilterPlatforms(childrenHandler, platforms.Default())
childrenHandler = images.FilterPlatforms(childrenHandler, platformStr)
handlers = append(handlers,
remotes.FetchHandler(p.ContentStore, fetcher),
@ -155,7 +161,7 @@ func (p *Puller) Pull(ctx context.Context) (*Pulled, error) {
delete(allBlobs, desc.Digest)
return nil, nil
}),
images.FilterPlatforms(images.ChildrenHandler(p.ContentStore), platforms.Default()),
images.FilterPlatforms(images.ChildrenHandler(p.ContentStore), platformStr),
}
if err := images.Dispatch(ctx, images.Handlers(handlers...), p.desc); err != nil {
@ -209,7 +215,7 @@ func (p *Puller) Pull(ctx context.Context) (*Pulled, error) {
defer release()
unpackProgressDone := oneOffProgress(ctx, "unpacking "+p.Src.String())
chainid, err := unpack(ctx, p.desc, p.ContentStore, csh, p.Snapshotter, p.Applier)
chainid, err := unpack(ctx, p.desc, p.ContentStore, csh, p.Snapshotter, p.Applier, platformStr)
if err != nil {
return nil, unpackProgressDone(err)
}
@ -222,8 +228,8 @@ func (p *Puller) Pull(ctx context.Context) (*Pulled, error) {
}, nil
}
func unpack(ctx context.Context, desc ocispec.Descriptor, cs content.Store, csh ctdsnapshot.Snapshotter, s snapshot.Snapshotter, applier diff.Applier) (digest.Digest, error) {
layers, err := getLayers(ctx, cs, desc)
func unpack(ctx context.Context, desc ocispec.Descriptor, cs content.Store, csh ctdsnapshot.Snapshotter, s snapshot.Snapshotter, applier diff.Applier, platform string) (digest.Digest, error) {
layers, err := getLayers(ctx, cs, desc, platform)
if err != nil {
return "", err
}
@ -263,13 +269,13 @@ func fillBlobMapping(ctx context.Context, s snapshot.Snapshotter, layers []rootf
return nil
}
func getLayers(ctx context.Context, provider content.Provider, desc ocispec.Descriptor) ([]rootfs.Layer, error) {
manifest, err := images.Manifest(ctx, provider, desc, platforms.Default())
func getLayers(ctx context.Context, provider content.Provider, desc ocispec.Descriptor, platform string) ([]rootfs.Layer, error) {
manifest, err := images.Manifest(ctx, provider, desc, platform)
if err != nil {
return nil, errors.WithStack(err)
}
image := images.Image{Target: desc}
diffIDs, err := image.RootFS(ctx, provider, platforms.Default())
diffIDs, err := image.RootFS(ctx, provider, platform)
if err != nil {
return nil, errors.Wrap(err, "failed to resolve rootfs")
}

View File

@ -211,11 +211,10 @@ func (w *Worker) LoadRef(id string) (cache.ImmutableRef, error) {
}
func (w *Worker) ResolveOp(v solver.Vertex, s frontend.FrontendLLBBridge) (solver.Op, error) {
// TODO: update this to send full op
if op, ok := v.Sys().(*pb.Op); ok {
switch op := op.Op.(type) {
if baseOp, ok := v.Sys().(*pb.Op); ok {
switch op := baseOp.Op.(type) {
case *pb.Op_Source:
return ops.NewSourceOp(v, op, w.SourceManager, w)
return ops.NewSourceOp(v, op, baseOp.Platform, w.SourceManager, w)
case *pb.Op_Exec:
return ops.NewExecOp(v, op, w.CacheManager, w.MetadataStore, w.Executor, w)
case *pb.Op_Build:
@ -225,17 +224,17 @@ func (w *Worker) ResolveOp(v solver.Vertex, s frontend.FrontendLLBBridge) (solve
return nil, errors.Errorf("could not resolve %v", v)
}
func (w *Worker) ResolveImageConfig(ctx context.Context, ref string) (digest.Digest, []byte, error) {
func (w *Worker) ResolveImageConfig(ctx context.Context, ref string, platform *specs.Platform) (digest.Digest, []byte, error) {
// ImageSource is typically source/containerimage
resolveImageConfig, ok := w.ImageSource.(resolveImageConfig)
if !ok {
return "", nil, errors.Errorf("worker %q does not implement ResolveImageConfig", w.ID())
}
return resolveImageConfig.ResolveImageConfig(ctx, ref)
return resolveImageConfig.ResolveImageConfig(ctx, ref, platform)
}
type resolveImageConfig interface {
ResolveImageConfig(ctx context.Context, ref string) (digest.Digest, []byte, error)
ResolveImageConfig(ctx context.Context, ref string, platform *specs.Platform) (digest.Digest, []byte, error)
}
func (w *Worker) Exec(ctx context.Context, meta executor.Meta, rootFS cache.ImmutableRef, stdin io.ReadCloser, stdout, stderr io.WriteCloser) error {

View File

@ -22,7 +22,7 @@ type Worker interface {
LoadRef(id string) (cache.ImmutableRef, error)
// ResolveOp resolves Vertex.Sys() to Op implementation.
ResolveOp(v solver.Vertex, s frontend.FrontendLLBBridge) (solver.Op, error)
ResolveImageConfig(ctx context.Context, ref string) (digest.Digest, []byte, error)
ResolveImageConfig(ctx context.Context, ref string, platform *specs.Platform) (digest.Digest, []byte, error)
// Exec is similar to executor.Exec but without []mount.Mount
Exec(ctx context.Context, meta executor.Meta, rootFS cache.ImmutableRef, stdin io.ReadCloser, stdout, stderr io.WriteCloser) error
DiskUsage(ctx context.Context, opt client.DiskUsageInfo) ([]*client.UsageInfo, error)