diff --git a/commands/imagetools/inspect.go b/commands/imagetools/inspect.go
index 70867431..7efc648c 100644
--- a/commands/imagetools/inspect.go
+++ b/commands/imagetools/inspect.go
@@ -4,6 +4,7 @@ import (
"github.com/docker/buildx/store"
"github.com/docker/buildx/store/storeutil"
"github.com/docker/buildx/util/imagetools"
+ "github.com/docker/cli-docs-tool/annotation"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/moby/buildkit/util/appcontext"
@@ -71,7 +72,10 @@ func inspectCmd(dockerCli command.Cli, rootOpts RootOptions) *cobra.Command {
}
flags := cmd.Flags()
- flags.StringVar(&options.format, "format", "{{.Manifest}}", "Format the output using the given Go template")
+
+ flags.StringVar(&options.format, "format", "", "Format the output using the given Go template")
+ flags.SetAnnotation("format", annotation.DefaultValue, []string{`"{{.Manifest}}"`})
+
flags.BoolVar(&options.raw, "raw", false, "Show original, unformatted JSON manifest")
return cmd
diff --git a/docs/reference/buildx_imagetools_inspect.md b/docs/reference/buildx_imagetools_inspect.md
index da48341e..30a96b5e 100644
--- a/docs/reference/buildx_imagetools_inspect.md
+++ b/docs/reference/buildx_imagetools_inspect.md
@@ -12,7 +12,8 @@ Show details of an image in the registry
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| [`--builder`](#builder) | `string` | | Override the configured builder instance |
-| [`--raw`](#raw) | | | Show original JSON manifest |
+| [`--format`](#format) | `string` | `{{.Manifest}}` | Format the output using the given Go template |
+| [`--raw`](#raw) | | | Show original, unformatted JSON manifest |
@@ -21,6 +22,42 @@ Show details of an image in the registry
Show details of an image in the registry.
+```console
+$ docker buildx imagetools inspect alpine
+Name: docker.io/library/alpine:latest
+MediaType: application/vnd.docker.distribution.manifest.list.v2+json
+Digest: sha256:21a3deaa0d32a8057914f36584b5288d2e5ecc984380bc0118285c70fa8c9300
+
+Manifests:
+ Name: docker.io/library/alpine:latest@sha256:e7d88de73db3d3fd9b2d63aa7f447a10fd0220b7cbf39803c803f2af9ba256b3
+ MediaType: application/vnd.docker.distribution.manifest.v2+json
+ Platform: linux/amd64
+
+ Name: docker.io/library/alpine:latest@sha256:e047bc2af17934d38c5a7fa9f46d443f1de3a7675546402592ef805cfa929f9d
+ MediaType: application/vnd.docker.distribution.manifest.v2+json
+ Platform: linux/arm/v6
+
+ Name: docker.io/library/alpine:latest@sha256:8483ecd016885d8dba70426fda133c30466f661bb041490d525658f1aac73822
+ MediaType: application/vnd.docker.distribution.manifest.v2+json
+ Platform: linux/arm/v7
+
+ Name: docker.io/library/alpine:latest@sha256:c74f1b1166784193ea6c8f9440263b9be6cae07dfe35e32a5df7a31358ac2060
+ MediaType: application/vnd.docker.distribution.manifest.v2+json
+ Platform: linux/arm64/v8
+
+ Name: docker.io/library/alpine:latest@sha256:2689e157117d2da668ad4699549e55eba1ceb79cb7862368b30919f0488213f4
+ MediaType: application/vnd.docker.distribution.manifest.v2+json
+ Platform: linux/386
+
+ Name: docker.io/library/alpine:latest@sha256:2042a492bcdd847a01cd7f119cd48caa180da696ed2aedd085001a78664407d6
+ MediaType: application/vnd.docker.distribution.manifest.v2+json
+ Platform: linux/ppc64le
+
+ Name: docker.io/library/alpine:latest@sha256:49e322ab6690e73a4909f787bcbdb873631264ff4a108cddfd9f9c249ba1d58e
+ MediaType: application/vnd.docker.distribution.manifest.v2+json
+ Platform: linux/s390x
+```
+
## Examples
### Override the configured builder instance (--builder)
@@ -29,12 +66,12 @@ Same as [`buildx --builder`](buildx.md#builder).
### Format the output (--format)
-Format the output using the given Go template. At the moment the following
-fields are available:
+Format the output using the given Go template. Defaults to `{{.Manifest}}` if
+unset. Following fields are available:
* `.Name`: provides the reference of the image
-* `.Manifest`: provides manifest or manifest list
-* `.Config`: provides the image config as `application/vnd.oci.image.config.v1+json` mediatype
+* `.Manifest`: provides the manifest or manifest list
+* `.Image`: provides the image config
* `.BuildInfo`: provides [build info from image config](https://github.com/moby/buildkit/blob/master/docs/build-repro.md#image-config)
#### `.Name`
@@ -57,30 +94,30 @@ Digest: sha256:08602e7340970e92bde5e0a2e887c1fde4d9ae753d1e05efb4c8ef3b609f97
$ docker buildx imagetools inspect moby/buildkit:master --format "{{.Manifest}}"
Name: docker.io/moby/buildkit:master
MediaType: application/vnd.docker.distribution.manifest.list.v2+json
-Digest: sha256:4e078bb87be98cc2a0fcdac4a05ac934055d563bd3d23e4d714eb03a3f62b49e
+Digest: sha256:3183f7ce54d1efb44c34b84f428ae10aaf141e553c6b52a7ff44cc7083a05a66
Manifests:
- Name: docker.io/moby/buildkit:master@sha256:bd1e78f06de26610fadf4eb9d04b1a45a545799d6342701726e952cc0c11c912
+ Name: docker.io/moby/buildkit:master@sha256:667d28c9fb33820ce686887a717a148e89fa77f9097f9352996bbcce99d352b1
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/amd64
- Name: docker.io/moby/buildkit:master@sha256:d37dcced63ec0965824fca644f0ac9efad8569434ec15b4c83adfcb3dcfc743b
+ Name: docker.io/moby/buildkit:master@sha256:71789527b64ab3d7b3de01d364b449cd7f7a3da758218fbf73b9c9aae05a6775
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/arm/v7
- Name: docker.io/moby/buildkit:master@sha256:ce142eb2255e6af46f2809e159fd03081697c7605a3de03b9cbe9a52ddb244bf
+ Name: docker.io/moby/buildkit:master@sha256:fb64667e1ce6ab0d05478f3a8402af07b27737598dcf9a510fb1d792b13a66be
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/arm64
- Name: docker.io/moby/buildkit:master@sha256:f59bfb5062fff76ce464bfa4e25ebaaaac887d6818238e119d68613c456d360c
+ Name: docker.io/moby/buildkit:master@sha256:1c3ddf95a0788e23f72f25800c05abc4458946685e2b66788c3d978cde6da92b
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/s390x
- Name: docker.io/moby/buildkit:master@sha256:cc96426e0c50a78105d5637d31356db5dd6ec594f21b24276e534a32da09645c
+ Name: docker.io/moby/buildkit:master@sha256:05bcde6d460a284e5bc88026cd070277e8380355de3126cbc8fe8a452708c6b1
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/ppc64le
- Name: docker.io/moby/buildkit:master@sha256:39f9c1e2878e6c333acb23187d6b205ce82ed934c60da326cb2c698192631478
+ Name: docker.io/moby/buildkit:master@sha256:c04c57765304ab84f4f9807fff3e11605c3a60e16435c734b02c723680f6bd6e
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/riscv64
```
@@ -92,21 +129,21 @@ $ docker buildx imagetools inspect crazymax/buildx:buildinfo --format "{{.BuildI
Name: docker.io/crazymax/buildx:buildinfo
Frontend: dockerfile.v0
Attrs:
+ filename: Dockerfile
+ source: docker/dockerfile-upstream:master-labs
build-arg:bar: foo
build-arg:foo: bar
- filename: Dockerfile
- source: crazymax/dockerfile:buildattrs
Sources:
Type: docker-image
Ref: docker.io/docker/buildx-bin:0.6.1@sha256:a652ced4a4141977c7daaed0a074dcd9844a78d7d2615465b12f433ae6dd29f0
Pin: sha256:a652ced4a4141977c7daaed0a074dcd9844a78d7d2615465b12f433ae6dd29f0
Type: docker-image
- Ref: docker.io/library/alpine:3.13@sha256:026f721af4cf2843e07bba648e158fb35ecc876d822130633cc49f707f0fc88c
+ Ref: docker.io/library/alpine:3.13
Pin: sha256:026f721af4cf2843e07bba648e158fb35ecc876d822130633cc49f707f0fc88c
Type: docker-image
- Ref: docker.io/moby/buildkit:v0.9.0@sha256:8dc668e7f66db1c044aadbed306020743516a94848793e0f81f94a087ee78cab
+ Ref: docker.io/moby/buildkit:v0.9.0
Pin: sha256:8dc668e7f66db1c044aadbed306020743516a94848793e0f81f94a087ee78cab
Type: docker-image
@@ -251,10 +288,10 @@ $ docker buildx imagetools inspect crazymax/buildx:buildinfo --format "{{json .}
"name": "crazymax/buildx:buildinfo",
"manifest": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
- "digest": "sha256:ac98300a6580fa30d9350a868de2a09f5a0190f4ba94e6c0ead8cc892150977c",
+ "digest": "sha256:899d2c7acbc124d406820857bb51d9089717bbe4e22b97eb4bc5789e99f09f83",
"size": 2628
},
- "config": {
+ "image": {
"created": "2022-02-24T12:27:43.627154558Z",
"architecture": "amd64",
"os": "linux",
@@ -379,7 +416,7 @@ $ docker buildx imagetools inspect crazymax/buildx:buildinfo --format "{{json .}
"build-arg:bar": "foo",
"build-arg:foo": "bar",
"filename": "Dockerfile",
- "source": "crazymax/dockerfile:buildattrs"
+ "source": "docker/dockerfile-upstream:master-labs"
},
"sources": [
{
@@ -389,12 +426,12 @@ $ docker buildx imagetools inspect crazymax/buildx:buildinfo --format "{{json .}
},
{
"type": "docker-image",
- "ref": "docker.io/library/alpine:3.13@sha256:026f721af4cf2843e07bba648e158fb35ecc876d822130633cc49f707f0fc88c",
+ "ref": "docker.io/library/alpine:3.13",
"pin": "sha256:026f721af4cf2843e07bba648e158fb35ecc876d822130633cc49f707f0fc88c"
},
{
"type": "docker-image",
- "ref": "docker.io/moby/buildkit:v0.9.0@sha256:8dc668e7f66db1c044aadbed306020743516a94848793e0f81f94a087ee78cab",
+ "ref": "docker.io/moby/buildkit:v0.9.0",
"pin": "sha256:8dc668e7f66db1c044aadbed306020743516a94848793e0f81f94a087ee78cab"
},
{
@@ -412,6 +449,81 @@ $ docker buildx imagetools inspect crazymax/buildx:buildinfo --format "{{json .}
}
```
+#### Multi-platform
+
+Multi-platform images are supported for `.Image` and `.BuildInfo` fields. If
+you want to pick up a specific platform, you can specify it using the `index`
+go template function:
+
+```console
+$ docker buildx imagetools inspect --format '{{json (index .Image "linux/s390x")}}' moby/buildkit:master
+```
+```json
+{
+ "created": "2022-02-25T17:13:27.89891722Z",
+ "architecture": "s390x",
+ "os": "linux",
+ "config": {
+ "Env": [
+ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+ ],
+ "Entrypoint": [
+ "buildkitd"
+ ],
+ "Volumes": {
+ "/var/lib/buildkit": {}
+ }
+ },
+ "rootfs": {
+ "type": "layers",
+ "diff_ids": [
+ "sha256:41048e32d0684349141cf05f629c5fc3c5915d1f3426b66dbb8953a540e01e1e",
+ "sha256:2651209b9208fff6c053bc3c17353cb07874e50f1a9bc96d6afd03aef63de76a",
+ "sha256:6741ed7e73039d853fa8902246a4c7e8bf9dd09652fd1b08251bc5f9e8876a7f",
+ "sha256:92ac046adeeb65c86ae3f0b458dee04ad4a462e417661c04d77642c66494f69b"
+ ]
+ },
+ "history": [
+ {
+ "created": "2021-11-24T20:41:23.709681315Z",
+ "created_by": "/bin/sh -c #(nop) ADD file:cd24c711a2ef431b3ff94f9a02bfc42f159bc60de1d0eceecafea4e8af02441d in / "
+ },
+ {
+ "created": "2021-11-24T20:41:23.94211262Z",
+ "created_by": "/bin/sh -c #(nop) CMD [\"/bin/sh\"]",
+ "empty_layer": true
+ },
+ {
+ "created": "2022-01-26T18:15:21.449825391Z",
+ "created_by": "RUN /bin/sh -c apk add --no-cache fuse3 git openssh pigz xz \u0026\u0026 ln -s fusermount3 /usr/bin/fusermount # buildkit",
+ "comment": "buildkit.dockerfile.v0"
+ },
+ {
+ "created": "2022-02-24T00:34:00.924540012Z",
+ "created_by": "COPY examples/buildctl-daemonless/buildctl-daemonless.sh /usr/bin/ # buildkit",
+ "comment": "buildkit.dockerfile.v0"
+ },
+ {
+ "created": "2022-02-25T17:13:27.89891722Z",
+ "created_by": "VOLUME [/var/lib/buildkit]",
+ "comment": "buildkit.dockerfile.v0",
+ "empty_layer": true
+ },
+ {
+ "created": "2022-02-25T17:13:27.89891722Z",
+ "created_by": "COPY / /usr/bin/ # buildkit",
+ "comment": "buildkit.dockerfile.v0"
+ },
+ {
+ "created": "2022-02-25T17:13:27.89891722Z",
+ "created_by": "ENTRYPOINT [\"buildkitd\"]",
+ "comment": "buildkit.dockerfile.v0",
+ "empty_layer": true
+ }
+ ]
+}
+```
+
### Show original, unformatted JSON manifest (--raw)
Use the `--raw` option to print the unformatted JSON manifest bytes.
@@ -460,7 +572,7 @@ $ docker buildx imagetools inspect --raw moby/buildkit:master | jq
"manifests": [
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
- "digest": "sha256:905307ef07e366e5977163218b9f01e9553fe2c15fe5e4a529328f91b510351d",
+ "digest": "sha256:667d28c9fb33820ce686887a717a148e89fa77f9097f9352996bbcce99d352b1",
"size": 1158,
"platform": {
"architecture": "amd64",
@@ -469,7 +581,7 @@ $ docker buildx imagetools inspect --raw moby/buildkit:master | jq
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
- "digest": "sha256:250a6dd96c377a1084cf8ea766916ae643f2fdf0f2e68728b3fda0a4d4669a2e",
+ "digest": "sha256:71789527b64ab3d7b3de01d364b449cd7f7a3da758218fbf73b9c9aae05a6775",
"size": 1158,
"platform": {
"architecture": "arm",
@@ -479,7 +591,7 @@ $ docker buildx imagetools inspect --raw moby/buildkit:master | jq
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
- "digest": "sha256:7ee37cac4b2b8b54d28127a10aa783260430a145bafab169cec88b8a20462678",
+ "digest": "sha256:fb64667e1ce6ab0d05478f3a8402af07b27737598dcf9a510fb1d792b13a66be",
"size": 1158,
"platform": {
"architecture": "arm64",
@@ -488,7 +600,7 @@ $ docker buildx imagetools inspect --raw moby/buildkit:master | jq
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
- "digest": "sha256:0ba8d091f6b346a5c45b06dcb534b6b6945a681fcdf40c195e1d6619115dffd2",
+ "digest": "sha256:1c3ddf95a0788e23f72f25800c05abc4458946685e2b66788c3d978cde6da92b",
"size": 1158,
"platform": {
"architecture": "s390x",
@@ -497,7 +609,7 @@ $ docker buildx imagetools inspect --raw moby/buildkit:master | jq
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
- "digest": "sha256:964d4b79d1be97ce22e6fe0c29be1d6cc63da10e5b8a21505851014c9846268a",
+ "digest": "sha256:05bcde6d460a284e5bc88026cd070277e8380355de3126cbc8fe8a452708c6b1",
"size": 1159,
"platform": {
"architecture": "ppc64le",
@@ -506,7 +618,7 @@ $ docker buildx imagetools inspect --raw moby/buildkit:master | jq
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
- "digest": "sha256:44d8de2c5f813b48d649a3a6cc348b57387cc22355897a14c7447cbfa03d079c",
+ "digest": "sha256:c04c57765304ab84f4f9807fff3e11605c3a60e16435c734b02c723680f6bd6e",
"size": 1158,
"platform": {
"architecture": "riscv64",
diff --git a/util/imagetools/inspect.go b/util/imagetools/inspect.go
index 059f25e7..88e96788 100644
--- a/util/imagetools/inspect.go
+++ b/util/imagetools/inspect.go
@@ -163,10 +163,10 @@ func RegistryAuthForRef(ref string, a Auth) (string, error) {
return base64.URLEncoding.EncodeToString(buf), nil
}
-func (r *Resolver) ImageConfig(ctx context.Context, in string) (digest.Digest, []byte, error) {
+func (r *Resolver) ImageConfig(ctx context.Context, in string, platform *ocispec.Platform) (digest.Digest, []byte, error) {
in, _, err := r.Resolve(ctx, in)
if err != nil {
return "", nil, err
}
- return imageutil.Config(ctx, in, r.resolver(), r.buffer, nil, nil)
+ return imageutil.Config(ctx, in, r.resolver(), r.buffer, nil, platform)
}
diff --git a/util/imagetools/printers.go b/util/imagetools/printers.go
index 900027b7..20118eb0 100644
--- a/util/imagetools/printers.go
+++ b/util/imagetools/printers.go
@@ -28,12 +28,11 @@ type Printer struct {
name string
format string
- raw []byte
- ref reference.Named
- manifest ocispecs.Descriptor
- index ocispecs.Index
- image ocispecs.Image
- binfo binfotypes.BuildInfo
+ raw []byte
+ ref reference.Named
+ manifest ocispecs.Descriptor
+ index ocispecs.Index
+ platforms []ocispecs.Platform
}
func NewPrinter(ctx context.Context, opt Opt, name string, format string) (*Printer, error) {
@@ -54,44 +53,26 @@ func NewPrinter(ctx context.Context, opt Opt, name string, format string) (*Prin
return nil, err
}
- _, dtcic, err := resolver.ImageConfig(ctx, name)
- if err != nil {
- return nil, err
- }
-
- var image ocispecs.Image
- if err = json.Unmarshal(dtcic, &image); err != nil {
- return nil, err
- }
-
- var binfo binfotypes.BuildInfo
- if len(dtcic) > 0 {
- var biconfig binfotypes.ImageConfig
- if err := json.Unmarshal(dtcic, &biconfig); err != nil {
- return nil, errors.Wrap(err, "failed to unmarshal image config")
- }
- if len(biconfig.BuildInfo) > 0 {
- bidec, err := base64.StdEncoding.DecodeString(biconfig.BuildInfo)
- if err != nil {
- return nil, errors.Wrap(err, "failed to decode build info")
- }
- if err = json.Unmarshal(bidec, &binfo); err != nil {
- return nil, errors.Wrap(err, "failed to unmarshal build info")
- }
+ var pforms []ocispecs.Platform
+ switch manifest.MediaType {
+ case images.MediaTypeDockerSchema2ManifestList, ocispecs.MediaTypeImageIndex:
+ for _, m := range index.Manifests {
+ pforms = append(pforms, *m.Platform)
}
+ default:
+ pforms = append(pforms, platforms.DefaultSpec())
}
return &Printer{
- ctx: ctx,
- resolver: resolver,
- name: name,
- format: format,
- raw: dt,
- ref: ref,
- manifest: manifest,
- index: index,
- image: image,
- binfo: binfo,
+ ctx: ctx,
+ resolver: resolver,
+ name: name,
+ format: format,
+ raw: dt,
+ ref: ref,
+ manifest: manifest,
+ index: index,
+ platforms: pforms,
}, nil
}
@@ -101,6 +82,21 @@ func (p *Printer) Print(raw bool, out io.Writer) error {
return err
}
+ if p.format == "" {
+ w := tabwriter.NewWriter(out, 0, 0, 1, ' ', 0)
+ _, _ = fmt.Fprintf(w, "Name:\t%s\n", p.ref.String())
+ _, _ = fmt.Fprintf(w, "MediaType:\t%s\n", p.manifest.MediaType)
+ _, _ = fmt.Fprintf(w, "Digest:\t%s\n", p.manifest.Digest)
+ _ = w.Flush()
+ switch p.manifest.MediaType {
+ case images.MediaTypeDockerSchema2ManifestList, ocispecs.MediaTypeImageIndex:
+ if err := p.printManifestList(out); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+
tpl, err := template.New("").Funcs(template.FuncMap{
"json": func(v interface{}) string {
b, _ := json.MarshalIndent(v, "", " ")
@@ -111,6 +107,22 @@ func (p *Printer) Print(raw bool, out io.Writer) error {
return err
}
+ imageconfigs := make(map[string]*ocispecs.Image)
+ buildinfos := make(map[string]*binfotypes.BuildInfo)
+ for _, pform := range p.platforms {
+ img, dtic, err := p.getImageConfig(&pform)
+ if err != nil {
+ return err
+ } else if img != nil {
+ imageconfigs[platforms.Format(pform)] = img
+ }
+ if bi, err := p.getBuildInfo(dtic); err != nil {
+ return err
+ } else if bi != nil {
+ buildinfos[platforms.Format(pform)] = bi
+ }
+ }
+
format := tpl.Root.String()
var manifest interface{}
@@ -120,23 +132,12 @@ func (p *Printer) Print(raw bool, out io.Writer) error {
case images.MediaTypeDockerSchema2ManifestList, ocispecs.MediaTypeImageIndex:
manifest = p.index
}
- v := struct {
- Name string `json:"name,omitempty"`
- Manifest interface{} `json:"manifest,omitempty"`
- Config ocispecs.Image `json:"config,omitempty"`
- BuildInfo binfotypes.BuildInfo `json:"buildinfo,omitempty"`
- }{
- Name: p.name,
- Manifest: manifest,
- Config: p.image,
- BuildInfo: p.binfo,
- }
switch {
- case strings.HasPrefix(format, "{{.Manifest"), strings.HasPrefix(format, "{{.Config"), strings.HasPrefix(format, "{{.BuildInfo"):
+ // TODO: print formatted config
+ case strings.HasPrefix(format, "{{.Manifest"), strings.HasPrefix(format, "{{.BuildInfo"):
w := tabwriter.NewWriter(out, 0, 0, 1, ' ', 0)
_, _ = fmt.Fprintf(w, "Name:\t%s\n", p.ref.String())
- _ = w.Flush()
if strings.HasPrefix(format, "{{.Manifest") {
_, _ = fmt.Fprintf(w, "MediaType:\t%s\n", p.manifest.MediaType)
_, _ = fmt.Fprintf(w, "Digest:\t%s\n", p.manifest.Digest)
@@ -145,13 +146,43 @@ func (p *Printer) Print(raw bool, out io.Writer) error {
case images.MediaTypeDockerSchema2ManifestList, ocispecs.MediaTypeImageIndex:
_ = p.printManifestList(out)
}
- } else if strings.HasPrefix(format, "{{.Config") {
- // TODO: print formatted config
} else if strings.HasPrefix(format, "{{.BuildInfo") {
- _ = p.printBuildInfo(p.binfo, "", out)
+ _ = w.Flush()
+ _ = p.printBuildInfos(buildinfos, out)
}
default:
- return tpl.Execute(out, v)
+ if len(p.platforms) > 1 {
+ return tpl.Execute(out, struct {
+ Name string `json:"name,omitempty"`
+ Manifest interface{} `json:"manifest,omitempty"`
+ Image map[string]*ocispecs.Image `json:"image,omitempty"`
+ BuildInfo map[string]*binfotypes.BuildInfo `json:"buildinfo,omitempty"`
+ }{
+ Name: p.name,
+ Manifest: manifest,
+ Image: imageconfigs,
+ BuildInfo: buildinfos,
+ })
+ }
+ var imageconfig *ocispecs.Image
+ for _, ic := range imageconfigs {
+ imageconfig = ic
+ }
+ var buildinfo *binfotypes.BuildInfo
+ for _, bi := range buildinfos {
+ buildinfo = bi
+ }
+ return tpl.Execute(out, struct {
+ Name string `json:"name,omitempty"`
+ Manifest interface{} `json:"manifest,omitempty"`
+ Image *ocispecs.Image `json:"image,omitempty"`
+ BuildInfo *binfotypes.BuildInfo `json:"buildinfo,omitempty"`
+ }{
+ Name: p.name,
+ Manifest: manifest,
+ Image: imageconfig,
+ BuildInfo: buildinfo,
+ })
}
return nil
@@ -198,7 +229,24 @@ func (p *Printer) printManifestList(out io.Writer) error {
return w.Flush()
}
-func (p *Printer) printBuildInfo(bi binfotypes.BuildInfo, pfx string, out io.Writer) error {
+func (p *Printer) printBuildInfos(bis map[string]*binfotypes.BuildInfo, out io.Writer) error {
+ if len(bis) == 1 {
+ for _, bi := range bis {
+ return p.printBuildInfo(bi, "", out)
+ }
+ }
+ for pform, bi := range bis {
+ w := tabwriter.NewWriter(out, 0, 0, 1, ' ', 0)
+ _, _ = fmt.Fprintf(w, "\t\nPlatform:\t%s\t\n", pform)
+ _ = w.Flush()
+ if err := p.printBuildInfo(bi, "", out); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (p *Printer) printBuildInfo(bi *binfotypes.BuildInfo, pfx string, out io.Writer) error {
w := tabwriter.NewWriter(out, 0, 0, 1, ' ', 0)
_, _ = fmt.Fprintf(w, "%sFrontend:\t%s\n", pfx, bi.Frontend)
@@ -233,10 +281,42 @@ func (p *Printer) printBuildInfo(bi binfotypes.BuildInfo, pfx string, out io.Wri
}
_, _ = fmt.Fprintf(w, "%sName:\t%s\n", pfx+defaultPfx, k)
_ = w.Flush()
- _ = p.printBuildInfo(v, pfx+defaultPfx, out)
+ _ = p.printBuildInfo(&v, pfx+defaultPfx, out)
firstPass = false
}
}
return w.Flush()
}
+
+func (p *Printer) getImageConfig(platform *ocispecs.Platform) (*ocispecs.Image, []byte, error) {
+ _, dtic, err := p.resolver.ImageConfig(p.ctx, p.name, platform)
+ if err != nil {
+ return nil, nil, err
+ }
+ var img *ocispecs.Image
+ if err = json.Unmarshal(dtic, &img); err != nil {
+ return nil, nil, err
+ }
+ return img, dtic, nil
+}
+
+func (p *Printer) getBuildInfo(dtic []byte) (*binfotypes.BuildInfo, error) {
+ var binfo *binfotypes.BuildInfo
+ if len(dtic) > 0 {
+ var biconfig binfotypes.ImageConfig
+ if err := json.Unmarshal(dtic, &biconfig); err != nil {
+ return nil, errors.Wrap(err, "failed to unmarshal image config")
+ }
+ if len(biconfig.BuildInfo) > 0 {
+ dtbi, err := base64.StdEncoding.DecodeString(biconfig.BuildInfo)
+ if err != nil {
+ return nil, errors.Wrap(err, "failed to decode build info")
+ }
+ if err = json.Unmarshal(dtbi, &binfo); err != nil {
+ return nil, errors.Wrap(err, "failed to unmarshal build info")
+ }
+ }
+ }
+ return binfo, nil
+}