Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 7 additions & 12 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1773,11 +1773,11 @@ func testOCILayoutSource(t *testing.T, sb integration.Sandbox) {
require.NoError(t, err)

// reference the OCI Layout in a build
// note that the key does not need to be the directory name, just something unique.
// since we are doing just one build with one remote here, we can give it any old ID,
// even something really imaginative, like "one"
csID := "one"
st = llb.OCILayout(csID, digest)
// note that the key does not need to be the directory name, just something
// unique. since we are doing just one build with one remote here, we can
// give it any ID
csID := "my-content-store"
st = llb.OCILayout(fmt.Sprintf("not/real@%s", digest), llb.OCIStore("", csID))

def, err = st.Marshal(context.TODO())
require.NoError(t, err)
Expand Down Expand Up @@ -1902,12 +1902,7 @@ func testOCILayoutPlatformSource(t *testing.T, sb integration.Sandbox) {

store, err := local.NewStore(dir)
require.NoError(t, err)

// reference the OCI Layout in a build
// note that the key does not need to be the directory name, just something unique.
// since we are doing just one build with one remote here, we can give it any old ID,
// even something really imaginative, like "one"
csID := "one"
csID := "my-content-store"

destDir := t.TempDir()

Expand All @@ -1917,7 +1912,7 @@ func testOCILayoutPlatformSource(t *testing.T, sb integration.Sandbox) {
Platforms: make([]exptypes.Platform, len(platformsToTest)),
}
for i, platform := range platformsToTest {
st := llb.OCILayout(csID, digest)
st := llb.OCILayout(fmt.Sprintf("not/real@%s", digest), llb.OCIStore("", csID))

def, err := st.Marshal(ctx, llb.Platform(platforms.MustParse(platform)))
if err != nil {
Expand Down
17 changes: 12 additions & 5 deletions client/llb/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,16 @@ const (
)

type ResolveImageConfigOpt struct {
Platform *ocispecs.Platform
ResolveMode string
LogName string
ResolverType // default is ResolverTypeRegistry
SessionID string
ResolverType

Platform *ocispecs.Platform
ResolveMode string
LogName string

Store ResolveImageConfigOptStore
}

type ResolveImageConfigOptStore struct {
SessionID string
StoreID string
}
21 changes: 11 additions & 10 deletions client/llb/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
_ "crypto/sha256" // for opencontainers/go-digest
"encoding/json"
"fmt"
"os"
"strconv"
"strings"
Expand Down Expand Up @@ -455,7 +454,7 @@ func Differ(t DiffType, required bool) LocalOption {
})
}

func OCILayout(store string, digest digest.Digest, opts ...OCILayoutOption) State {
func OCILayout(ref string, opts ...OCILayoutOption) State {
gi := &OCILayoutInfo{}

for _, o := range opts {
Expand All @@ -464,17 +463,17 @@ func OCILayout(store string, digest digest.Digest, opts ...OCILayoutOption) Stat
attrs := map[string]string{}
if gi.sessionID != "" {
attrs[pb.AttrOCILayoutSessionID] = gi.sessionID
addCap(&gi.Constraints, pb.CapSourceOCILayoutSessionID)
}

if ll := gi.layerLimit; ll != nil {
attrs[pb.AttrOCILayoutLayerLimit] = strconv.FormatInt(int64(*ll), 10)
addCap(&gi.Constraints, pb.CapSourceOCILayoutLayerLimit)
if gi.storeID != "" {
attrs[pb.AttrOCILayoutStoreID] = gi.storeID
}
if gi.layerLimit != nil {
attrs[pb.AttrOCILayoutLayerLimit] = strconv.FormatInt(int64(*gi.layerLimit), 10)
}

addCap(&gi.Constraints, pb.CapSourceOCILayout)

source := NewSource(fmt.Sprintf("oci-layout://%s@%s", store, digest), attrs, gi.Constraints)
source := NewSource("oci-layout://"+ref, attrs, gi.Constraints)
return NewState(source.Output())
}

Expand All @@ -488,9 +487,10 @@ func (fn ociLayoutOptionFunc) SetOCILayoutOption(li *OCILayoutInfo) {
fn(li)
}

func OCISessionID(id string) OCILayoutOption {
func OCIStore(sessionID string, storeID string) OCILayoutOption {
return ociLayoutOptionFunc(func(oi *OCILayoutInfo) {
oi.sessionID = id
oi.sessionID = sessionID
oi.storeID = storeID
})
}

Expand All @@ -503,6 +503,7 @@ func OCILayerLimit(limit int) OCILayoutOption {
type OCILayoutInfo struct {
constraintsWrapper
sessionID string
storeID string
layerLimit *int
}

Expand Down
70 changes: 37 additions & 33 deletions frontend/dockerfile/builder/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -873,29 +873,29 @@ func contextByNameFunc(c client.Client, sessionID string) func(context.Context,
p = &pp
}
if p != nil {
name := name + "::" + platforms.Format(platforms.Normalize(*p))
st, img, err := contextByName(ctx, c, sessionID, name, p, resolveMode)
pname := name + "::" + platforms.Format(platforms.Normalize(*p))
st, img, err := contextByName(ctx, c, sessionID, name, pname, p, resolveMode)
if err != nil {
return nil, nil, err
}
if st != nil {
return st, img, nil
}
}
return contextByName(ctx, c, sessionID, name, p, resolveMode)
return contextByName(ctx, c, sessionID, name, name, p, resolveMode)
}
}

func contextByName(ctx context.Context, c client.Client, sessionID, name string, platform *ocispecs.Platform, resolveMode string) (*llb.State, *dockerfile2llb.Image, error) {
func contextByName(ctx context.Context, c client.Client, sessionID, name string, pname string, platform *ocispecs.Platform, resolveMode string) (*llb.State, *dockerfile2llb.Image, error) {
opts := c.BuildOpts().Opts
v, ok := opts[contextPrefix+name]
v, ok := opts[contextPrefix+pname]
if !ok {
return nil, nil, nil
}

vv := strings.SplitN(v, ":", 2)
if len(vv) != 2 {
return nil, nil, errors.Errorf("invalid context specifier %s for %s", v, name)
return nil, nil, errors.Errorf("invalid context specifier %s for %s", v, pname)
}
// allow git@ without protocol for SSH URLs for backwards compatibility
if strings.HasPrefix(vv[0], "git@") {
Expand All @@ -910,7 +910,7 @@ func contextByName(ctx context.Context, c client.Client, sessionID, name string,
}

imgOpt := []llb.ImageOption{
llb.WithCustomName("[context " + name + "] " + ref),
llb.WithCustomName("[context " + pname + "] " + ref),
}
if platform != nil {
imgOpt = append(imgOpt, llb.Platform(*platform))
Expand All @@ -926,9 +926,8 @@ func contextByName(ctx context.Context, c client.Client, sessionID, name string,
_, data, err := c.ResolveImageConfig(ctx, named.String(), llb.ResolveImageConfigOpt{
Platform: platform,
ResolveMode: resolveMode,
LogName: fmt.Sprintf("[context %s] load metadata for %s", name, ref),
LogName: fmt.Sprintf("[context %s] load metadata for %s", pname, ref),
ResolverType: llb.ResolverTypeRegistry,
SessionID: sessionID,
})
if err != nil {
return nil, nil, err
Expand All @@ -955,7 +954,7 @@ func contextByName(ctx context.Context, c client.Client, sessionID, name string,
case "http", "https":
st, ok := detectGitContext(v, true)
if !ok {
httpst := llb.HTTP(v, llb.WithCustomName("[context "+name+"] "+v))
httpst := llb.HTTP(v, llb.WithCustomName("[context "+pname+"] "+v))
st = &httpst
}
return st, nil, nil
Expand All @@ -969,25 +968,31 @@ func contextByName(ctx context.Context, c client.Client, sessionID, name string,
if !ok {
return nil, nil, errors.Errorf("oci-layout reference %q has no name", ref.String())
}
if reference.Domain(named) != "" {
return nil, nil, errors.Errorf("oci-layout reference %q has domain", ref.String())
dgstd, ok := named.(reference.Digested)
if !ok {
return nil, nil, errors.Errorf("oci-layout reference %q has no digest", named.String())
}
if strings.Contains(reference.Path(named), "/") {
return nil, nil, errors.Errorf("oci-layout reference %q name is multi-part", ref.String())

// for the dummy ref primarily used in log messages, we can use the
// original name, since the store key may not be significant
dummyRef, err := reference.ParseNormalizedNamed(name)
if err != nil {
return nil, nil, errors.Wrapf(err, "could not parse oci-layout reference %q", name)
}
digested, ok := ref.(reference.Digested)
if !ok {
return nil, nil, errors.Errorf("oci-layout reference %q does not have digest", ref.String())
dummyRef, err = reference.WithDigest(dummyRef, dgstd.Digest())
if err != nil {
return nil, nil, errors.Wrapf(err, "could not wrap %q with digest", name)
}

// We use store id as the host here, the image name will be ignored
// (since image lookup is not currently supported)
id := fmt.Sprintf("%s/image@%s", named.Name(), digested.Digest())
_, data, err := c.ResolveImageConfig(ctx, id, llb.ResolveImageConfigOpt{
_, data, err := c.ResolveImageConfig(ctx, dummyRef.String(), llb.ResolveImageConfigOpt{
Platform: platform,
ResolveMode: resolveMode,
LogName: fmt.Sprintf("[context %s] load metadata for %s", name, ref),
LogName: fmt.Sprintf("[context %s] load metadata for %s", pname, dummyRef.String()),
ResolverType: llb.ResolverTypeOCILayout,
Store: llb.ResolveImageConfigOptStore{
SessionID: sessionID,
StoreID: named.Name(),
},
})
if err != nil {
return nil, nil, err
Expand All @@ -999,15 +1004,14 @@ func contextByName(ctx context.Context, c client.Client, sessionID, name string,
}

ociOpt := []llb.OCILayoutOption{
llb.WithCustomName("[context " + name + "] OCI load from client"),
llb.OCISessionID(c.BuildOpts().SessionID),
llb.WithCustomName("[context " + pname + "] OCI load from client"),
llb.OCIStore(c.BuildOpts().SessionID, named.Name()),
}
if platform != nil {
ociOpt = append(ociOpt, llb.Platform(*platform))
}
st := llb.OCILayout(
named.Name(),
digested.Digest(),
dummyRef.String(),
ociOpt...,
)
st, err = st.WithImageConfig(data)
Expand All @@ -1019,8 +1023,8 @@ func contextByName(ctx context.Context, c client.Client, sessionID, name string,
st := llb.Local(vv[1],
llb.SessionID(c.BuildOpts().SessionID),
llb.FollowPaths([]string{dockerignoreFilename}),
llb.SharedKeyHint("context:"+name+"-"+dockerignoreFilename),
llb.WithCustomName("[context "+name+"] load "+dockerignoreFilename),
llb.SharedKeyHint("context:"+pname+"-"+dockerignoreFilename),
llb.WithCustomName("[context "+pname+"] load "+dockerignoreFilename),
llb.Differ(llb.DiffNone, false),
)
def, err := st.Marshal(ctx)
Expand Down Expand Up @@ -1049,9 +1053,9 @@ func contextByName(ctx context.Context, c client.Client, sessionID, name string,
}
}
st = llb.Local(vv[1],
llb.WithCustomName("[context "+name+"] load from client"),
llb.WithCustomName("[context "+pname+"] load from client"),
llb.SessionID(c.BuildOpts().SessionID),
llb.SharedKeyHint("context:"+name),
llb.SharedKeyHint("context:"+pname),
llb.ExcludePatterns(excludes),
)
return &st, nil, nil
Expand All @@ -1062,7 +1066,7 @@ func contextByName(ctx context.Context, c client.Client, sessionID, name string,
}
st, ok := inputs[vv[1]]
if !ok {
return nil, nil, errors.Errorf("invalid input %s for %s", vv[1], name)
return nil, nil, errors.Errorf("invalid input %s for %s", vv[1], pname)
}
md, ok := opts[inputMetadataPrefix+vv[1]]
if ok {
Expand All @@ -1077,14 +1081,14 @@ func contextByName(ctx context.Context, c client.Client, sessionID, name string,
return nil, nil, err
}
if err := json.Unmarshal(dtic, &img); err != nil {
return nil, nil, errors.Wrapf(err, "failed to parse image config for %s", name)
return nil, nil, errors.Wrapf(err, "failed to parse image config for %s", pname)
}
}
return &st, img, nil
}
return &st, nil, nil
default:
return nil, nil, errors.Errorf("unsupported context source %s for %s", vv[0], name)
return nil, nil, errors.Errorf("unsupported context source %s for %s", vv[0], pname)
}
}

Expand Down
6 changes: 5 additions & 1 deletion frontend/gateway/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -541,10 +541,14 @@ func (lbf *llbBridgeForwarder) ResolveImageConfig(ctx context.Context, req *pb.R
}
}
dgst, dt, err := lbf.llbBridge.ResolveImageConfig(ctx, req.Ref, llb.ResolveImageConfigOpt{
ResolverType: llb.ResolverType(req.ResolverType),
Platform: platform,
ResolveMode: req.ResolveMode,
LogName: req.LogName,
ResolverType: llb.ResolverType(req.ResolverType),
Store: llb.ResolveImageConfigOptStore{
SessionID: req.SessionID,
StoreID: req.StoreID,
},
})
if err != nil {
return nil, err
Expand Down
10 changes: 9 additions & 1 deletion frontend/gateway/grpcclient/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,15 @@ func (c *grpcClient) ResolveImageConfig(ctx context.Context, ref string, opt llb
OSFeatures: platform.OSFeatures,
}
}
resp, err := c.client.ResolveImageConfig(ctx, &pb.ResolveImageConfigRequest{Ref: ref, Platform: p, ResolveMode: opt.ResolveMode, LogName: opt.LogName, ResolverType: int32(opt.ResolverType), SessionID: opt.SessionID})
resp, err := c.client.ResolveImageConfig(ctx, &pb.ResolveImageConfigRequest{
ResolverType: int32(opt.ResolverType),
Ref: ref,
Platform: p,
ResolveMode: opt.ResolveMode,
LogName: opt.LogName,
SessionID: opt.Store.SessionID,
StoreID: opt.Store.StoreID,
})
if err != nil {
return "", nil, err
}
Expand Down
Loading