Bläddra i källkod

Merge pull request #37613 from tiborvass/buildkit-pull

builder: implement PullParent option with buildkit
Sebastiaan van Stijn 6 år sedan
förälder
incheckning
ba5c92f1bf
2 ändrade filer med 61 tillägg och 15 borttagningar
  1. 55 15
      builder/builder-next/adapters/containerimage/pull.go
  2. 6 0
      builder/builder-next/builder.go

+ 55 - 15
builder/builder-next/adapters/containerimage/pull.go

@@ -42,8 +42,6 @@ import (
 	"golang.org/x/time/rate"
 )
 
-const preferLocal = true // FIXME: make this optional from the op
-
 // SourceOpt is options for creating the image source
 type SourceOpt struct {
 	SessionManager  *session.Manager
@@ -114,32 +112,61 @@ func (is *imageSource) resolveLocal(refStr string) ([]byte, error) {
 	return img.RawJSON(), nil
 }
 
-func (is *imageSource) ResolveImageConfig(ctx context.Context, ref string, opt gw.ResolveImageConfigOpt) (digest.Digest, []byte, error) {
-	if preferLocal {
-		dt, err := is.resolveLocal(ref)
-		if err == nil {
-			return "", dt, nil
-		}
-	}
-
+func (is *imageSource) resolveRemote(ctx context.Context, ref string, platform *ocispec.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, is.getResolver(ctx), is.ContentStore, opt.Platform)
+		dgst, dt, err := imageutil.Config(ctx, ref, is.getResolver(ctx), is.ContentStore, platform)
 		if err != nil {
 			return nil, err
 		}
 		return &t{dgst: dgst, dt: dt}, nil
 	})
+	var typed *t
 	if err != nil {
 		return "", nil, err
 	}
-	typed := res.(*t)
+	typed = res.(*t)
 	return typed.dgst, typed.dt, nil
 }
 
+func (is *imageSource) ResolveImageConfig(ctx context.Context, ref string, opt gw.ResolveImageConfigOpt) (digest.Digest, []byte, error) {
+	resolveMode, err := source.ParseImageResolveMode(opt.ResolveMode)
+	if err != nil {
+		return "", nil, err
+	}
+	switch resolveMode {
+	case source.ResolveModeForcePull:
+		dgst, dt, err := is.resolveRemote(ctx, ref, opt.Platform)
+		// TODO: pull should fallback to local in case of failure to allow offline behavior
+		// the fallback doesn't work currently
+		return dgst, dt, err
+		/*
+			if err == nil {
+				return dgst, dt, err
+			}
+			// fallback to local
+			dt, err = is.resolveLocal(ref)
+			return "", dt, err
+		*/
+
+	case source.ResolveModeDefault:
+		// default == prefer local, but in the future could be smarter
+		fallthrough
+	case source.ResolveModePreferLocal:
+		dt, err := is.resolveLocal(ref)
+		if err == nil {
+			return "", dt, err
+		}
+		// fallback to remote
+		return is.resolveRemote(ctx, ref, opt.Platform)
+	}
+	// should never happen
+	return "", nil, fmt.Errorf("builder cannot resolve image %s: invalid mode %q", ref, opt.ResolveMode)
+}
+
 func (is *imageSource) Resolve(ctx context.Context, id source.Identifier) (source.SourceInstance, error) {
 	imageIdentifier, ok := id.(*source.ImageIdentifier)
 	if !ok {
@@ -213,7 +240,7 @@ func (p *puller) resolveLocal() {
 			}
 		}
 
-		if preferLocal {
+		if p.src.ResolveMode == source.ResolveModeDefault || p.src.ResolveMode == source.ResolveModePreferLocal {
 			dt, err := p.is.resolveLocal(p.src.Reference.String())
 			if err == nil {
 				p.config = dt
@@ -257,8 +284,7 @@ func (p *puller) resolve(ctx context.Context) error {
 				resolveProgressDone(err)
 				return
 			}
-
-			_, dt, err := p.is.ResolveImageConfig(ctx, ref.String(), gw.ResolveImageConfigOpt{Platform: &p.platform})
+			_, dt, err := p.is.ResolveImageConfig(ctx, ref.String(), gw.ResolveImageConfigOpt{Platform: &p.platform, ResolveMode: resolveModeToString(p.src.ResolveMode)})
 			if err != nil {
 				p.resolveErr = err
 				resolveProgressDone(err)
@@ -732,3 +758,17 @@ func cacheKeyFromConfig(dt []byte) digest.Digest {
 	}
 	return identity.ChainID(img.RootFS.DiffIDs)
 }
+
+// resolveModeToString is the equivalent of github.com/moby/buildkit/solver/llb.ResolveMode.String()
+// FIXME: add String method on source.ResolveMode
+func resolveModeToString(rm source.ResolveMode) string {
+	switch rm {
+	case source.ResolveModeDefault:
+		return "default"
+	case source.ResolveModeForcePull:
+		return "pull"
+	case source.ResolveModePreferLocal:
+		return "local"
+	}
+	return ""
+}

+ 6 - 0
builder/builder-next/builder.go

@@ -209,6 +209,12 @@ func (b *Builder) Build(ctx context.Context, opt backend.BuildConfig) (*builder.
 		frontendAttrs["no-cache"] = ""
 	}
 
+	if opt.Options.PullParent {
+		frontendAttrs["image-resolve-mode"] = "pull"
+	} else {
+		frontendAttrs["image-resolve-mode"] = "default"
+	}
+
 	if opt.Options.Platform != "" {
 		// same as in newBuilder in builder/dockerfile.builder.go
 		// TODO: remove once opt.Options.Platform is of type specs.Platform