You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
200 lines
4.7 KiB
Go
200 lines
4.7 KiB
Go
package commands
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"github.com/docker/buildx/util/imagetools"
|
|
"github.com/docker/cli/cli/command/formatter"
|
|
"github.com/docker/distribution/reference"
|
|
"github.com/moby/buildkit/util/appcontext"
|
|
"github.com/opencontainers/go-digest"
|
|
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
|
|
)
|
|
|
|
const (
|
|
tableFormat = "table {{ .Name }}\t{{ .MediaType }}\t{{ .Digest }}"
|
|
prettyTemplate = `{{- if .Name }}
|
|
Name: {{ .Name }}
|
|
{{- end }}
|
|
{{- if .MediaType }}
|
|
MediaType: {{ .MediaType }}
|
|
{{- end }}
|
|
{{- if .Digest }}
|
|
Digest: {{ .Digest }}
|
|
{{- end }}
|
|
{{- if .Manifests }}
|
|
Manifests:
|
|
{{- range $manifest := .Manifests }}
|
|
{{ if $manifest.Name }}
|
|
Name: {{ $manifest.Name }}
|
|
{{- end }}
|
|
{{- if $manifest.MediaType }}
|
|
MediaType: {{ $manifest.MediaType }}
|
|
{{- end }}
|
|
{{- if $manifest.Platform }}
|
|
Platform: {{ $manifest.Platform }}
|
|
{{- end }}
|
|
{{- if $manifest.OSVersion }}
|
|
OSVersion: {{ $manifest.OSVersion }}
|
|
{{- end }}
|
|
{{- if $manifest.OSFeatures }}
|
|
OSFeatures: {{ $manifest.OSFeatures }}
|
|
{{- end }}
|
|
{{- if $manifest.URLs }}
|
|
URLs: {{ $manifest.URLs }}
|
|
{{- end }}
|
|
{{- if $manifest.Annotations }}
|
|
{{ range $key, $value := $manifest.Annotations }}
|
|
{{ $key }}: {{ $value }}
|
|
{{- end }}
|
|
{{- end }}
|
|
{{- end }}
|
|
{{- end }}`
|
|
)
|
|
|
|
func makeFormat(source string) formatter.Format {
|
|
switch source {
|
|
case formatter.PrettyFormatKey:
|
|
return prettyTemplate
|
|
case formatter.TableFormatKey:
|
|
return tableFormat
|
|
case formatter.RawFormatKey:
|
|
return formatter.JSONFormat
|
|
}
|
|
return formatter.Format(source)
|
|
}
|
|
|
|
func inspectFormatWrite(ctx formatter.Context, name string, opt imagetools.Opt) error {
|
|
resolver := imagetools.New(opt)
|
|
return ctx.Write(&inspectContext{
|
|
HeaderContext: formatter.HeaderContext{
|
|
Header: formatter.SubHeaderContext{
|
|
"Name": "NAME",
|
|
"MediaType": "MEDIA TYPE",
|
|
"Digest": "DIGEST",
|
|
},
|
|
},
|
|
}, func(format func(formatter.SubContext) error) error {
|
|
ref, err := imagetools.ParseRef(name)
|
|
if err != nil {
|
|
return fmt.Errorf("parse ref: %w", err)
|
|
}
|
|
|
|
dt, mfst, err := resolver.Get(appcontext.Context(), ref.String())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var index ocispecs.Index
|
|
if err := json.Unmarshal(dt, &index); err != nil {
|
|
return err
|
|
}
|
|
|
|
return format(&inspectContext{
|
|
ref: ref,
|
|
index: index,
|
|
descriptor: mfst,
|
|
resolver: resolver,
|
|
})
|
|
})
|
|
}
|
|
|
|
type inspectContext struct {
|
|
formatter.HeaderContext
|
|
ref reference.Named
|
|
index ocispecs.Index
|
|
descriptor ocispecs.Descriptor
|
|
resolver *imagetools.Resolver
|
|
}
|
|
|
|
func (ctx *inspectContext) MarshalJSON() ([]byte, error) {
|
|
return formatter.MarshalJSON(ctx)
|
|
}
|
|
|
|
func (ctx *inspectContext) Name() string {
|
|
return ctx.ref.String()
|
|
}
|
|
|
|
func (ctx *inspectContext) Manifest() manifestList {
|
|
return manifestList{
|
|
SchemaVersion: ctx.index.Versioned.SchemaVersion,
|
|
MediaType: ctx.index.MediaType,
|
|
Digest: ctx.descriptor.Digest,
|
|
Size: ctx.descriptor.Size,
|
|
Manifests: ctx.index.Manifests,
|
|
Annotations: ctx.descriptor.Annotations,
|
|
}
|
|
}
|
|
|
|
func (ctx *inspectContext) Image() (*ocispecs.Image, error) {
|
|
res, err := imagetools.
|
|
NewLoader(ctx.resolver.Resolver()).
|
|
Load(appcontext.Context(), ctx.ref.String())
|
|
if err != nil {
|
|
return nil, fmt.Errorf("load: %w", err)
|
|
}
|
|
var img *ocispecs.Image
|
|
for _, v := range res.Configs() {
|
|
img = v
|
|
break
|
|
}
|
|
return img, nil
|
|
}
|
|
|
|
type manifestList struct {
|
|
SchemaVersion int
|
|
MediaType string
|
|
Digest digest.Digest
|
|
Size int64
|
|
Manifests []ocispecs.Descriptor
|
|
Annotations map[string]string
|
|
}
|
|
|
|
// type inspectManifestContext struct {
|
|
// ref reference.Named
|
|
// descriptor ocispecs.Descriptor
|
|
// }
|
|
|
|
// func (ctx *inspectManifestContext) MarshalJSON() ([]byte, error) {
|
|
// return formatter.MarshalJSON(ctx)
|
|
// }
|
|
|
|
// func (ctx *inspectManifestContext) Name() (string, error) {
|
|
// cc, err := reference.WithDigest(ctx.ref, ctx.descriptor.Digest)
|
|
// if err != nil {
|
|
// return "", fmt.Errorf("with digest: %w", err)
|
|
// }
|
|
// return cc.String(), nil
|
|
// }
|
|
|
|
// func (ctx *inspectManifestContext) MediaType() string {
|
|
// return ctx.descriptor.MediaType
|
|
// }
|
|
|
|
// func (ctx *inspectManifestContext) Platform() *string {
|
|
// if ctx.descriptor.Platform != nil {
|
|
// s := platforms.Format(*ctx.descriptor.Platform)
|
|
// return &s
|
|
// }
|
|
// return nil
|
|
// }
|
|
|
|
// func (ctx *inspectManifestContext) OSVersion() string {
|
|
// if ctx.descriptor.Platform != nil {
|
|
// return ctx.descriptor.Platform.OSVersion
|
|
// }
|
|
// return ""
|
|
// }
|
|
|
|
// func (ctx *inspectManifestContext) OSFeatures() []string {
|
|
// if ctx.descriptor.Platform != nil {
|
|
// return ctx.descriptor.Platform.OSFeatures
|
|
// }
|
|
// return nil
|
|
// }
|
|
|
|
// func (ctx *inspectManifestContext) URLs() []string {
|
|
// return ctx.descriptor.URLs
|
|
// }
|