mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-05-18 00:47:48 +08:00
imagetools: refactor combining repository logic
This patch modifies the existing combining code in imagetools create to provide better support for multiple repositories down the road. Specifically, the code should no longer rely on a single repository being used for all sources and tags, and should resolve descriptors in their relevant repositories. Signed-off-by: Justin Chadwell <me@jedevc.com>
This commit is contained in:
parent
07992e66e0
commit
d3412f1039
@ -925,7 +925,21 @@ func BuildWithResultHandler(ctx context.Context, drivers []DriverInfo, opt map[s
|
||||
|
||||
itpull := imagetools.New(imageopt)
|
||||
|
||||
dt, desc, err := itpull.Combine(ctx, names[0], descs)
|
||||
ref, err := reference.ParseNormalizedNamed(names[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ref = reference.TagNameOnly(ref)
|
||||
|
||||
srcs := make([]*imagetools.Source, len(descs))
|
||||
for i, desc := range descs {
|
||||
srcs[i] = &imagetools.Source{
|
||||
Desc: desc,
|
||||
Ref: ref,
|
||||
}
|
||||
}
|
||||
|
||||
dt, desc, err := itpull.Combine(ctx, srcs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -82,14 +82,20 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error {
|
||||
return errors.Errorf("multiple repositories currently not supported, found %v", repos)
|
||||
}
|
||||
|
||||
var repo string
|
||||
for r := range repos {
|
||||
repo = r
|
||||
var defaultRepo *string
|
||||
if len(repos) == 1 {
|
||||
for repo := range repos {
|
||||
defaultRepo = &repo
|
||||
}
|
||||
}
|
||||
|
||||
for i, s := range srcs {
|
||||
if s.Ref == nil && s.Desc.MediaType == "" && s.Desc.Digest != "" {
|
||||
n, err := reference.ParseNormalizedNamed(repo)
|
||||
if defaultRepo == nil {
|
||||
return errors.Errorf("multiple repositories specified, cannot determine default from %v", repos)
|
||||
}
|
||||
|
||||
n, err := reference.ParseNormalizedNamed(*defaultRepo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -143,7 +149,6 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srcs[i].Ref = nil
|
||||
if srcs[i].Desc.Digest == "" {
|
||||
srcs[i].Desc = desc
|
||||
} else {
|
||||
@ -162,12 +167,7 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error {
|
||||
}
|
||||
}
|
||||
|
||||
descs := make([]ocispec.Descriptor, len(srcs))
|
||||
for i := range descs {
|
||||
descs[i] = srcs[i].Desc
|
||||
}
|
||||
|
||||
dt, desc, err := r.Combine(ctx, repo, descs)
|
||||
dt, desc, err := r.Combine(ctx, srcs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -190,13 +190,8 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type src struct {
|
||||
Desc ocispec.Descriptor
|
||||
Ref reference.Named
|
||||
}
|
||||
|
||||
func parseSources(in []string) ([]*src, error) {
|
||||
out := make([]*src, len(in))
|
||||
func parseSources(in []string) ([]*imagetools.Source, error) {
|
||||
out := make([]*imagetools.Source, len(in))
|
||||
for i, in := range in {
|
||||
s, err := parseSource(in)
|
||||
if err != nil {
|
||||
@ -219,11 +214,11 @@ func parseRefs(in []string) ([]reference.Named, error) {
|
||||
return refs, nil
|
||||
}
|
||||
|
||||
func parseSource(in string) (*src, error) {
|
||||
func parseSource(in string) (*imagetools.Source, error) {
|
||||
// source can be a digest, reference or a descriptor JSON
|
||||
dgst, err := digest.Parse(in)
|
||||
if err == nil {
|
||||
return &src{
|
||||
return &imagetools.Source{
|
||||
Desc: ocispec.Descriptor{
|
||||
Digest: dgst,
|
||||
},
|
||||
@ -234,14 +229,14 @@ func parseSource(in string) (*src, error) {
|
||||
|
||||
ref, err := reference.ParseNormalizedNamed(in)
|
||||
if err == nil {
|
||||
return &src{
|
||||
return &imagetools.Source{
|
||||
Ref: ref,
|
||||
}, nil
|
||||
} else if !strings.HasPrefix(in, "{") {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var s src
|
||||
var s imagetools.Source
|
||||
if err := json.Unmarshal([]byte(in), &s.Desc); err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
@ -17,46 +17,46 @@ import (
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
func (r *Resolver) Combine(ctx context.Context, in string, descs []ocispec.Descriptor) ([]byte, ocispec.Descriptor, error) {
|
||||
ref, err := parseRef(in)
|
||||
if err != nil {
|
||||
return nil, ocispec.Descriptor{}, err
|
||||
}
|
||||
type Source struct {
|
||||
Desc ocispec.Descriptor
|
||||
Ref reference.Named
|
||||
}
|
||||
|
||||
func (r *Resolver) Combine(ctx context.Context, srcs []*Source) ([]byte, ocispec.Descriptor, error) {
|
||||
eg, ctx := errgroup.WithContext(ctx)
|
||||
|
||||
dts := make([][]byte, len(descs))
|
||||
dts := make([][]byte, len(srcs))
|
||||
for i := range dts {
|
||||
func(i int) {
|
||||
eg.Go(func() error {
|
||||
dt, err := r.GetDescriptor(ctx, ref.String(), descs[i])
|
||||
dt, err := r.GetDescriptor(ctx, srcs[i].Ref.String(), srcs[i].Desc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dts[i] = dt
|
||||
|
||||
if descs[i].MediaType == "" {
|
||||
if srcs[i].Desc.MediaType == "" {
|
||||
mt, err := detectMediaType(dt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
descs[i].MediaType = mt
|
||||
srcs[i].Desc.MediaType = mt
|
||||
}
|
||||
|
||||
mt := descs[i].MediaType
|
||||
mt := srcs[i].Desc.MediaType
|
||||
|
||||
switch mt {
|
||||
case images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest:
|
||||
p := descs[i].Platform
|
||||
if descs[i].Platform == nil {
|
||||
p := srcs[i].Desc.Platform
|
||||
if srcs[i].Desc.Platform == nil {
|
||||
p = &ocispec.Platform{}
|
||||
}
|
||||
if p.OS == "" || p.Architecture == "" {
|
||||
if err := r.loadPlatform(ctx, p, in, dt); err != nil {
|
||||
if err := r.loadPlatform(ctx, p, srcs[i].Ref.String(), dt); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
descs[i].Platform = p
|
||||
srcs[i].Desc.Platform = p
|
||||
case images.MediaTypeDockerSchema1Manifest:
|
||||
return errors.Errorf("schema1 manifests are not allowed in manifest lists")
|
||||
}
|
||||
@ -71,14 +71,14 @@ func (r *Resolver) Combine(ctx context.Context, in string, descs []ocispec.Descr
|
||||
}
|
||||
|
||||
// on single source, return original bytes
|
||||
if len(descs) == 1 {
|
||||
if mt := descs[0].MediaType; mt == images.MediaTypeDockerSchema2ManifestList || mt == ocispec.MediaTypeImageIndex {
|
||||
return dts[0], descs[0], nil
|
||||
if len(srcs) == 1 {
|
||||
if mt := srcs[0].Desc.MediaType; mt == images.MediaTypeDockerSchema2ManifestList || mt == ocispec.MediaTypeImageIndex {
|
||||
return dts[0], srcs[0].Desc, nil
|
||||
}
|
||||
}
|
||||
|
||||
m := map[digest.Digest]int{}
|
||||
newDescs := make([]ocispec.Descriptor, 0, len(descs))
|
||||
newDescs := make([]ocispec.Descriptor, 0, len(srcs))
|
||||
|
||||
addDesc := func(d ocispec.Descriptor) {
|
||||
idx, ok := m[d.Digest]
|
||||
@ -103,8 +103,8 @@ func (r *Resolver) Combine(ctx context.Context, in string, descs []ocispec.Descr
|
||||
}
|
||||
}
|
||||
|
||||
for i, desc := range descs {
|
||||
switch desc.MediaType {
|
||||
for i, src := range srcs {
|
||||
switch src.Desc.MediaType {
|
||||
case images.MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex:
|
||||
var mfst ocispec.Index
|
||||
if err := json.Unmarshal(dts[i], &mfst); err != nil {
|
||||
@ -114,7 +114,7 @@ func (r *Resolver) Combine(ctx context.Context, in string, descs []ocispec.Descr
|
||||
addDesc(d)
|
||||
}
|
||||
default:
|
||||
addDesc(desc)
|
||||
addDesc(src.Desc)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user