This commit is contained in:
Thomas
2023-06-20 13:57:01 +02:00
committed by GitHub
46 changed files with 13077 additions and 310 deletions

View File

@@ -0,0 +1,199 @@
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
// }

View File

@@ -2,66 +2,79 @@ package commands
import (
"github.com/docker/buildx/builder"
"github.com/docker/buildx/util/cobrautil/completion"
"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"
"github.com/pkg/errors"
"github.com/docker/cli/cli/command/formatter"
cliflags "github.com/docker/cli/cli/flags"
"github.com/spf13/cobra"
)
type inspectOptions struct {
builder string
format string
raw bool
builderName string
format string
refs []string
}
func runInspect(dockerCli command.Cli, in inspectOptions, name string) error {
ctx := appcontext.Context()
func inspectCmd(dockerCLI command.Cli, rootOpts RootOptions) *cobra.Command {
var opts inspectOptions
if in.format != "" && in.raw {
return errors.Errorf("format and raw cannot be used together")
cmd := &cobra.Command{
Use: "inspect [OPTIONS] IMAGE [IMAGE...]",
Short: "Show detailed information on one or more images in the registry",
Args: cli.RequiresMinArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
opts.builderName = *rootOpts.Builder
opts.refs = args
return runInspect(dockerCLI, opts, args[0])
},
}
b, err := builder.New(dockerCli, builder.WithName(in.builder))
flags := cmd.Flags()
flags.StringVarP(&opts.format, "format", "f", "", cliflags.InspectFormatHelp)
return cmd
}
func runInspect(dockerCli command.Cli, opts inspectOptions, name string) error {
b, err := builder.New(dockerCli, builder.WithName(opts.builderName))
if err != nil {
return err
}
imageopt, err := b.ImageOpt()
if err != nil {
return err
}
p, err := imagetools.NewPrinter(ctx, imageopt, name, in.format)
if err != nil {
return err
}
return p.Print(in.raw, dockerCli.Out())
return inspectFormatWrite(formatter.Context{
Output: dockerCli.Out(),
Format: makeFormat(opts.format),
}, name, imageopt)
}
func inspectCmd(dockerCli command.Cli, rootOpts RootOptions) *cobra.Command {
var options inspectOptions
// func runInspect(dockerCLI command.Cli, opts inspectOptions, name string) error {
// b, err := builder.New(dockerCLI, builder.WithName(opts.builderName))
// if err != nil {
// return fmt.Errorf("new builder: %w", err)
// }
cmd := &cobra.Command{
Use: "inspect [OPTIONS] NAME",
Short: "Show details of an image in the registry",
Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
options.builder = *rootOpts.Builder
return runInspect(dockerCli, options, args[0])
},
ValidArgsFunction: completion.Disable,
}
// imgopt, err := b.ImageOpt()
// if err != nil {
// return fmt.Errorf("image opt: %w", err)
// }
flags := cmd.Flags()
// resolver := imagetools.New(imgopt)
// ctx := appcontext.Context()
// return inspect.Inspect(dockerCLI.Out(), opts.refs, opts.format, func(ref string) (interface{}, []byte, error) {
// newref, err := imagetools.ParseRef(ref)
// if err != nil {
// return nil, nil, err
// }
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
}
// dt, mfst, err := resolver.Get(ctx, newref.String())
// if err != nil {
// return nil, nil, err
// }
// return mfst, dt, err
// })
// }