mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-10-31 16:13:45 +08:00 
			
		
		
		
	imagetools: implement inspect for manifest list
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
		
							
								
								
									
										92
									
								
								util/imagetools/inspect.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								util/imagetools/inspect.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| package imagetools | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"io" | ||||
| 	"net/http" | ||||
|  | ||||
| 	"github.com/containerd/containerd/remotes" | ||||
| 	"github.com/containerd/containerd/remotes/docker" | ||||
| 	clitypes "github.com/docker/cli/cli/config/types" | ||||
| 	"github.com/docker/distribution/reference" | ||||
| 	ocispec "github.com/opencontainers/image-spec/specs-go/v1" | ||||
| ) | ||||
|  | ||||
| type Auth interface { | ||||
| 	GetAuthConfig(registryHostname string) (clitypes.AuthConfig, error) | ||||
| } | ||||
|  | ||||
| type Opt struct { | ||||
| 	Auth Auth | ||||
| } | ||||
|  | ||||
| type Resolver struct { | ||||
| 	r remotes.Resolver | ||||
| } | ||||
|  | ||||
| func New(opt Opt) *Resolver { | ||||
| 	resolver := docker.NewResolver(docker.ResolverOptions{ | ||||
| 		Client:      http.DefaultClient, | ||||
| 		Credentials: toCredentialsFunc(opt.Auth), | ||||
| 	}) | ||||
| 	return &Resolver{ | ||||
| 		r: resolver, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (r *Resolver) Get(ctx context.Context, in string) ([]byte, ocispec.Descriptor, error) { | ||||
| 	ref, err := parseRef(in) | ||||
| 	if err != nil { | ||||
| 		return nil, ocispec.Descriptor{}, err | ||||
| 	} | ||||
|  | ||||
| 	in, desc, err := r.r.Resolve(ctx, ref.String()) | ||||
| 	if err != nil { | ||||
| 		return nil, ocispec.Descriptor{}, err | ||||
| 	} | ||||
|  | ||||
| 	fetcher, err := r.r.Fetcher(ctx, in) | ||||
| 	if err != nil { | ||||
| 		return nil, ocispec.Descriptor{}, err | ||||
| 	} | ||||
|  | ||||
| 	rc, err := fetcher.Fetch(ctx, desc) | ||||
| 	if err != nil { | ||||
| 		return nil, ocispec.Descriptor{}, err | ||||
| 	} | ||||
|  | ||||
| 	buf := &bytes.Buffer{} | ||||
| 	_, err = io.Copy(buf, rc) | ||||
| 	rc.Close() | ||||
| 	if err != nil { | ||||
| 		return nil, ocispec.Descriptor{}, err | ||||
| 	} | ||||
|  | ||||
| 	return buf.Bytes(), desc, nil | ||||
| } | ||||
|  | ||||
| func parseRef(s string) (reference.Named, error) { | ||||
| 	ref, err := reference.ParseNormalizedNamed(s) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	ref = reference.TagNameOnly(ref) | ||||
| 	return ref, nil | ||||
| } | ||||
|  | ||||
| func toCredentialsFunc(a Auth) func(string) (string, string, error) { | ||||
| 	return func(host string) (string, string, error) { | ||||
| 		if host == "registry-1.docker.io" { | ||||
| 			host = "https://index.docker.io/v1/" | ||||
| 		} | ||||
| 		ac, err := a.GetAuthConfig(host) | ||||
| 		if err != nil { | ||||
| 			return "", "", err | ||||
| 		} | ||||
| 		if ac.IdentityToken != "" { | ||||
| 			return "", ac.IdentityToken, nil | ||||
| 		} | ||||
| 		return ac.Username, ac.Password, nil | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										74
									
								
								util/imagetools/printers.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								util/imagetools/printers.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| package imagetools | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"text/tabwriter" | ||||
|  | ||||
| 	"github.com/containerd/containerd/platforms" | ||||
| 	"github.com/docker/distribution/reference" | ||||
| 	ocispec "github.com/opencontainers/image-spec/specs-go/v1" | ||||
| ) | ||||
|  | ||||
| func PrintManifestList(dt []byte, desc ocispec.Descriptor, refstr string, out io.Writer) error { | ||||
| 	ref, err := parseRef(refstr) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	var mfst ocispec.Index | ||||
| 	if err := json.Unmarshal(dt, &mfst); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	w := tabwriter.NewWriter(out, 0, 0, 1, ' ', 0) | ||||
|  | ||||
| 	fmt.Fprintf(w, "Name:\t%s\n", ref.String()) | ||||
| 	fmt.Fprintf(w, "MediaType:\t%s\n", desc.MediaType) | ||||
| 	fmt.Fprintf(w, "Digest:\t%s\n", desc.Digest) | ||||
| 	fmt.Fprintf(w, "\t\n") | ||||
|  | ||||
| 	fmt.Fprintf(w, "Manifests:\t\n") | ||||
| 	w.Flush() | ||||
|  | ||||
| 	pfx := "  " | ||||
|  | ||||
| 	w = tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) | ||||
| 	for i, m := range mfst.Manifests { | ||||
| 		if i != 0 { | ||||
| 			fmt.Fprintf(w, "\t\n") | ||||
| 		} | ||||
| 		cr, err := reference.WithDigest(ref, m.Digest) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		fmt.Fprintf(w, "%sName:\t%s\n", pfx, cr.String()) | ||||
| 		fmt.Fprintf(w, "%sMediaType:\t%s\n", pfx, m.MediaType) | ||||
| 		if p := m.Platform; p != nil { | ||||
| 			fmt.Fprintf(w, "%sPlatform:\t%s\n", pfx, platforms.Format(*p)) | ||||
| 			if p.OSVersion != "" { | ||||
| 				fmt.Fprintf(w, "%sOSVersion:\t%s\n", pfx, p.OSVersion) | ||||
| 			} | ||||
| 			if len(p.OSFeatures) > 0 { | ||||
| 				fmt.Fprintf(w, "%sOSFeatures:\t%s\n", pfx, strings.Join(p.OSFeatures, ", ")) | ||||
| 			} | ||||
| 			if len(m.URLs) > 0 { | ||||
| 				fmt.Fprintf(w, "%sURLs:\t%s\n", pfx, strings.Join(m.URLs, ", ")) | ||||
| 			} | ||||
| 			if len(m.Annotations) > 0 { | ||||
| 				w.Flush() | ||||
| 				w2 := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) | ||||
| 				pfx2 := pfx + "  " | ||||
| 				for k, v := range m.Annotations { | ||||
| 					fmt.Fprintf(w2, "%s%s:\t%s\n", pfx2, k, v) | ||||
| 				} | ||||
| 				w2.Flush() | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return w.Flush() | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Tonis Tiigi
					Tonis Tiigi