Skip to content

Commit

Permalink
dockerfile: use target name as the dummy reference
Browse files Browse the repository at this point in the history
Now that the reference is not significant to image resolution, with only
the digest being used to determine what to lookup, the only effect of
the dummy reference is to provide reasonable error messages.

Since the name of the store is likely not significant, using that as the
basis for the reference may be deceiving. We can use the original name
of the image as the dummy reference, except with the targeted digest. We
can't easily require that clients should expose the name of the store,
since that may be a leak of the local path to the store, which may be
private.

Signed-off-by: Justin Chadwell <[email protected]>
  • Loading branch information
jedevc committed Dec 7, 2022
1 parent 13c4057 commit 7e10a01
Showing 1 changed file with 32 additions and 28 deletions.
60 changes: 32 additions & 28 deletions frontend/dockerfile/builder/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -868,29 +868,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 @@ -905,7 +905,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 @@ -921,7 +921,7 @@ 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,
})
if err != nil {
Expand Down Expand Up @@ -949,7 +949,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 @@ -963,22 +963,26 @@ 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)
}

id := fmt.Sprintf("foo/bar@%s", 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,
Expand All @@ -995,8 +999,8 @@ func contextByName(ctx context.Context, c client.Client, sessionID, name string,
}

st := llb.OCILayout(
id,
llb.WithCustomName("[context "+name+"] OCI load from client"),
dummyRef.String(),
llb.WithCustomName("[context "+pname+"] OCI load from client"),
llb.OCIStore(c.BuildOpts().SessionID, named.Name()),
)
st, err = st.WithImageConfig(data)
Expand All @@ -1008,8 +1012,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 @@ -1038,9 +1042,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 @@ -1051,7 +1055,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 @@ -1066,14 +1070,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

0 comments on commit 7e10a01

Please sign in to comment.