Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vendor: github.com/moby/buildkit v0.13.0-rc2 #47364

Merged
merged 14 commits into from Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
11 changes: 11 additions & 0 deletions .github/workflows/buildkit.yml
Expand Up @@ -50,6 +50,9 @@ jobs:
timeout-minutes: 120
needs:
- build
env:
TEST_IMAGE_BUILD: "0"
TEST_IMAGE_ID: "buildkit-tests"
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -115,6 +118,14 @@ jobs:
sudo service docker restart
docker version
docker info
-
name: Build test image
uses: docker/bake-action@v4
with:
workdir: ./buildkit
targets: integration-tests
set: |
*.output=type=docker,name=${{ env.TEST_IMAGE_ID }}
-
name: Test
run: |
Expand Down
139 changes: 106 additions & 33 deletions builder/builder-next/adapters/containerimage/pull.go
Expand Up @@ -9,6 +9,7 @@ import (
"fmt"
"io"
"path"
"strconv"
"strings"
"sync"
"time"
Expand All @@ -34,14 +35,15 @@ import (
pkgprogress "github.com/docker/docker/pkg/progress"
"github.com/docker/docker/reference"
"github.com/moby/buildkit/cache"
"github.com/moby/buildkit/client/llb"
"github.com/moby/buildkit/client"
"github.com/moby/buildkit/client/llb/sourceresolver"
"github.com/moby/buildkit/session"
"github.com/moby/buildkit/solver"
"github.com/moby/buildkit/solver/pb"
"github.com/moby/buildkit/source"
"github.com/moby/buildkit/source/containerimage"
srctypes "github.com/moby/buildkit/source/types"
"github.com/moby/buildkit/sourcepolicy"
policy "github.com/moby/buildkit/sourcepolicy/pb"
spb "github.com/moby/buildkit/sourcepolicy/pb"
"github.com/moby/buildkit/util/flightcontrol"
"github.com/moby/buildkit/util/imageutil"
Expand Down Expand Up @@ -80,9 +82,77 @@ func NewSource(opt SourceOpt) (*Source, error) {
return &Source{SourceOpt: opt}, nil
}

// ID returns image scheme identifier
func (is *Source) ID() string {
return srctypes.DockerImageScheme
// Schemes returns a list of SourceOp identifier schemes that this source
// should match.
func (is *Source) Schemes() []string {
return []string{srctypes.DockerImageScheme}
}

// Identifier constructs an Identifier from the given scheme, ref, and attrs,
// all of which come from a SourceOp.
func (is *Source) Identifier(scheme, ref string, attrs map[string]string, platform *pb.Platform) (source.Identifier, error) {
return is.registryIdentifier(ref, attrs, platform)
}

// Copied from github.com/moby/buildkit/source/containerimage/source.go
func (is *Source) registryIdentifier(ref string, attrs map[string]string, platform *pb.Platform) (source.Identifier, error) {
id, err := containerimage.NewImageIdentifier(ref)
if err != nil {
return nil, err
}

if platform != nil {
id.Platform = &ocispec.Platform{
OS: platform.OS,
Architecture: platform.Architecture,
Variant: platform.Variant,
OSVersion: platform.OSVersion,
}
if platform.OSFeatures != nil {
id.Platform.OSFeatures = append([]string{}, platform.OSFeatures...)
}
}

for k, v := range attrs {
switch k {
case pb.AttrImageResolveMode:
rm, err := resolver.ParseImageResolveMode(v)
if err != nil {
return nil, err
}
id.ResolveMode = rm
case pb.AttrImageRecordType:
rt, err := parseImageRecordType(v)
if err != nil {
return nil, err
}
id.RecordType = rt
case pb.AttrImageLayerLimit:
l, err := strconv.Atoi(v)
if err != nil {
return nil, errors.Wrapf(err, "invalid layer limit %s", v)
}
if l <= 0 {
return nil, errors.Errorf("invalid layer limit %s", v)
}
id.LayerLimit = &l
}
}

return id, nil
}

func parseImageRecordType(v string) (client.UsageRecordType, error) {
switch client.UsageRecordType(v) {
case "", client.UsageRecordTypeRegular:
return client.UsageRecordTypeRegular, nil
case client.UsageRecordTypeInternal:
return client.UsageRecordTypeInternal, nil
case client.UsageRecordTypeFrontend:
return client.UsageRecordTypeFrontend, nil
default:
return "", errors.Errorf("invalid record type %s", v)
}
}

func (is *Source) resolveLocal(refStr string) (*image.Image, error) {
Expand All @@ -107,7 +177,7 @@ type resolveRemoteResult struct {
dt []byte
}

func (is *Source) resolveRemote(ctx context.Context, ref string, platform *ocispec.Platform, sm *session.Manager, g session.Group) (string, digest.Digest, []byte, error) {
func (is *Source) resolveRemote(ctx context.Context, ref string, platform *ocispec.Platform, sm *session.Manager, g session.Group) (digest.Digest, []byte, error) {
p := platforms.DefaultSpec()
if platform != nil {
p = *platform
Expand All @@ -116,34 +186,36 @@ func (is *Source) resolveRemote(ctx context.Context, ref string, platform *ocisp
key := "getconfig::" + ref + "::" + platforms.Format(p)
res, err := is.g.Do(ctx, key, func(ctx context.Context) (*resolveRemoteResult, error) {
res := resolver.DefaultPool.GetResolver(is.RegistryHosts, ref, "pull", sm, g)
ref, dgst, dt, err := imageutil.Config(ctx, ref, res, is.ContentStore, is.LeaseManager, platform, []*policy.Policy{})
dgst, dt, err := imageutil.Config(ctx, ref, res, is.ContentStore, is.LeaseManager, platform)
if err != nil {
return nil, err
}
return &resolveRemoteResult{ref: ref, dgst: dgst, dt: dt}, nil
})
if err != nil {
return ref, "", nil, err
return "", nil, err
}
return res.ref, res.dgst, res.dt, nil
return res.dgst, res.dt, nil
}

// ResolveImageConfig returns image config for an image
func (is *Source) ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt, sm *session.Manager, g session.Group) (string, digest.Digest, []byte, error) {
func (is *Source) ResolveImageConfig(ctx context.Context, ref string, opt sourceresolver.Opt, sm *session.Manager, g session.Group) (digest.Digest, []byte, error) {
if opt.ImageOpt == nil {
return "", nil, fmt.Errorf("can only resolve an image: %v, opt: %v", ref, opt)
}
ref, err := applySourcePolicies(ctx, ref, opt.SourcePolicies)
if err != nil {
return "", "", nil, err
return "", nil, err
}
resolveMode, err := source.ParseImageResolveMode(opt.ResolveMode)
resolveMode, err := resolver.ParseImageResolveMode(opt.ImageOpt.ResolveMode)
if err != nil {
return ref, "", nil, err
return "", nil, err
}
switch resolveMode {
case source.ResolveModeForcePull:
ref, dgst, dt, err := is.resolveRemote(ctx, ref, opt.Platform, sm, g)
case resolver.ResolveModeForcePull:
return is.resolveRemote(ctx, ref, opt.Platform, sm, g)
// TODO: pull should fallback to local in case of failure to allow offline behavior
// the fallback doesn't work currently
return ref, dgst, dt, err
/*
if err == nil {
return dgst, dt, err
Expand All @@ -153,10 +225,10 @@ func (is *Source) ResolveImageConfig(ctx context.Context, ref string, opt llb.Re
return "", dt, err
*/

case source.ResolveModeDefault:
case resolver.ResolveModeDefault:
// default == prefer local, but in the future could be smarter
fallthrough
case source.ResolveModePreferLocal:
case resolver.ResolveModePreferLocal:
img, err := is.resolveLocal(ref)
if err == nil {
if opt.Platform != nil && !platformMatches(img, opt.Platform) {
Expand All @@ -165,19 +237,19 @@ func (is *Source) ResolveImageConfig(ctx context.Context, ref string, opt llb.Re
path.Join(img.OS, img.Architecture, img.Variant),
)
} else {
return ref, "", img.RawJSON(), err
return "", img.RawJSON(), err
}
}
// fallback to remote
return is.resolveRemote(ctx, ref, opt.Platform, sm, g)
}
// should never happen
return ref, "", nil, fmt.Errorf("builder cannot resolve image %s: invalid mode %q", ref, opt.ResolveMode)
return "", nil, fmt.Errorf("builder cannot resolve image %s: invalid mode %q", ref, opt.ImageOpt.ResolveMode)
}

// Resolve returns access to pulling for an identifier
func (is *Source) Resolve(ctx context.Context, id source.Identifier, sm *session.Manager, vtx solver.Vertex) (source.SourceInstance, error) {
imageIdentifier, ok := id.(*source.ImageIdentifier)
imageIdentifier, ok := id.(*containerimage.ImageIdentifier)
if !ok {
return nil, errors.Errorf("invalid image identifier %v", id)
}
Expand All @@ -201,7 +273,7 @@ type puller struct {
is *Source
resolveLocalOnce sync.Once
g flightcontrol.Group[struct{}]
src *source.ImageIdentifier
src *containerimage.ImageIdentifier
desc ocispec.Descriptor
ref string
config []byte
Expand Down Expand Up @@ -253,7 +325,7 @@ func (p *puller) resolveLocal() {
}
}

if p.src.ResolveMode == source.ResolveModeDefault || p.src.ResolveMode == source.ResolveModePreferLocal {
if p.src.ResolveMode == resolver.ResolveModeDefault || p.src.ResolveMode == resolver.ResolveModePreferLocal {
ref := p.src.Reference.String()
img, err := p.is.resolveLocal(ref)
if err == nil {
Expand Down Expand Up @@ -302,12 +374,17 @@ func (p *puller) resolve(ctx context.Context, g session.Group) error {
if err != nil {
return struct{}{}, err
}
newRef, _, dt, err := p.is.ResolveImageConfig(ctx, ref.String(), llb.ResolveImageConfigOpt{Platform: &p.platform, ResolveMode: p.src.ResolveMode.String()}, p.sm, g)
_, dt, err := p.is.ResolveImageConfig(ctx, ref.String(), sourceresolver.Opt{
Platform: &p.platform,
ImageOpt: &sourceresolver.ResolveImageOpt{
ResolveMode: p.src.ResolveMode.String(),
},
}, p.sm, g)
if err != nil {
return struct{}{}, err
}

p.ref = newRef
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, good catch!

Yeah it looks like this shouldn't be deleted.
I restored it as:
p.ref = ref.String()

because ResolveImageConfig no longer returns a reference.
Looking at the old implementation, it didn't really change the ref that was passed as an argument.
The only place where it returned a different ref is where it went to the (remotes.Resolver) Resolve(), but it doesn't seem to change it either (at least the docker remote).

p.ref = ref.String()
p.config = dt
}
return struct{}{}, nil
Expand Down Expand Up @@ -866,12 +943,8 @@ func applySourcePolicies(ctx context.Context, str string, spls []*spb.Policy) (s
if err != nil {
return "", errors.WithStack(err)
}
op := &pb.Op{
Op: &pb.Op_Source{
Source: &pb.SourceOp{
Identifier: srctypes.DockerImageScheme + "://" + ref.String(),
},
},
op := &pb.SourceOp{
Identifier: srctypes.DockerImageScheme + "://" + ref.String(),
}

mut, err := sourcepolicy.NewEngine(spls).Evaluate(ctx, op)
vvoland marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -884,9 +957,9 @@ func applySourcePolicies(ctx context.Context, str string, spls []*spb.Policy) (s
t string
ok bool
)
t, newRef, ok := strings.Cut(op.GetSource().GetIdentifier(), "://")
t, newRef, ok := strings.Cut(op.GetIdentifier(), "://")
if !ok {
return "", errors.Errorf("could not parse ref: %s", op.GetSource().GetIdentifier())
return "", errors.Errorf("could not parse ref: %s", op.GetIdentifier())
}
if ok && t != srctypes.DockerImageScheme {
return "", &imageutil.ResolveToNonImageError{Ref: str, Updated: newRef}
Expand Down
7 changes: 4 additions & 3 deletions builder/builder-next/builder.go
Expand Up @@ -389,9 +389,10 @@ func (b *Builder) Build(ctx context.Context, opt backend.BuildConfig) (*builder.
}

req := &controlapi.SolveRequest{
Ref: id,
Exporter: exporterName,
ExporterAttrs: exporterAttrs,
Ref: id,
Exporters: []*controlapi.Exporter{
&controlapi.Exporter{Type: exporterName, Attrs: exporterAttrs},
},
Frontend: "dockerfile.v0",
FrontendAttrs: frontendAttrs,
Session: opt.Options.SessionID,
Expand Down
15 changes: 9 additions & 6 deletions builder/builder-next/controller.go
Expand Up @@ -67,11 +67,11 @@ func newController(ctx context.Context, rt http.RoundTripper, opt Opt) (*control
}

func getTraceExporter(ctx context.Context) trace.SpanExporter {
exp, err := detect.Exporter()
span, _, err := detect.Exporter()
if err != nil {
log.G(ctx).WithError(err).Error("Failed to detect trace exporter for buildkit controller")
}
return exp
return span
}

func newSnapshotterController(ctx context.Context, rt http.RoundTripper, opt Opt) (*control.Controller, error) {
Expand Down Expand Up @@ -105,7 +105,8 @@ func newSnapshotterController(ctx context.Context, rt http.RoundTripper, opt Opt
wo, err := containerd.NewWorkerOpt(opt.Root, opt.ContainerdAddress, opt.Snapshotter, opt.ContainerdNamespace,
opt.Rootless, map[string]string{
label.Snapshotter: opt.Snapshotter,
}, dns, nc, opt.ApparmorProfile, false, nil, "", ctd.WithTimeout(60*time.Second))
}, dns, nc, opt.ApparmorProfile, false, nil, "", nil, ctd.WithTimeout(60*time.Second),
)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -302,9 +303,11 @@ func newGraphDriverController(ctx context.Context, rt http.RoundTripper, opt Opt
}

exp, err := mobyexporter.New(mobyexporter.Opt{
ImageStore: dist.ImageStore,
Differ: differ,
ImageTagger: opt.ImageTagger,
ImageStore: dist.ImageStore,
ContentStore: store,
Differ: differ,
ImageTagger: opt.ImageTagger,
LeaseManager: lm,
})
if err != nil {
return nil, err
Expand Down