github.1git.de/docker/cli@v26.1.3+incompatible/cli/command/manifest/inspect.go (about) 1 package manifest 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/json" 7 "fmt" 8 9 "github.com/distribution/reference" 10 "github.com/docker/cli/cli" 11 "github.com/docker/cli/cli/command" 12 "github.com/docker/cli/cli/manifest/types" 13 "github.com/docker/distribution/manifest/manifestlist" 14 "github.com/docker/docker/registry" 15 "github.com/pkg/errors" 16 "github.com/spf13/cobra" 17 ) 18 19 type inspectOptions struct { 20 ref string 21 list string 22 verbose bool 23 insecure bool 24 } 25 26 // NewInspectCommand creates a new `docker manifest inspect` command 27 func newInspectCommand(dockerCli command.Cli) *cobra.Command { 28 var opts inspectOptions 29 30 cmd := &cobra.Command{ 31 Use: "inspect [OPTIONS] [MANIFEST_LIST] MANIFEST", 32 Short: "Display an image manifest, or manifest list", 33 Args: cli.RequiresRangeArgs(1, 2), 34 RunE: func(cmd *cobra.Command, args []string) error { 35 switch len(args) { 36 case 1: 37 opts.ref = args[0] 38 case 2: 39 opts.list = args[0] 40 opts.ref = args[1] 41 } 42 return runInspect(cmd.Context(), dockerCli, opts) 43 }, 44 } 45 46 flags := cmd.Flags() 47 flags.BoolVar(&opts.insecure, "insecure", false, "Allow communication with an insecure registry") 48 flags.BoolVarP(&opts.verbose, "verbose", "v", false, "Output additional info including layers and platform") 49 return cmd 50 } 51 52 func runInspect(ctx context.Context, dockerCli command.Cli, opts inspectOptions) error { 53 namedRef, err := normalizeReference(opts.ref) 54 if err != nil { 55 return err 56 } 57 58 // If list reference is provided, display the local manifest in a list 59 if opts.list != "" { 60 listRef, err := normalizeReference(opts.list) 61 if err != nil { 62 return err 63 } 64 65 imageManifest, err := dockerCli.ManifestStore().Get(listRef, namedRef) 66 if err != nil { 67 return err 68 } 69 return printManifest(dockerCli, imageManifest, opts) 70 } 71 72 // Try a local manifest list first 73 localManifestList, err := dockerCli.ManifestStore().GetList(namedRef) 74 if err == nil { 75 return printManifestList(dockerCli, namedRef, localManifestList, opts) 76 } 77 78 // Next try a remote manifest 79 registryClient := dockerCli.RegistryClient(opts.insecure) 80 imageManifest, err := registryClient.GetManifest(ctx, namedRef) 81 if err == nil { 82 return printManifest(dockerCli, imageManifest, opts) 83 } 84 85 // Finally try a remote manifest list 86 manifestList, err := registryClient.GetManifestList(ctx, namedRef) 87 if err != nil { 88 return err 89 } 90 return printManifestList(dockerCli, namedRef, manifestList, opts) 91 } 92 93 func printManifest(dockerCli command.Cli, manifest types.ImageManifest, opts inspectOptions) error { 94 buffer := new(bytes.Buffer) 95 if !opts.verbose { 96 _, raw, err := manifest.Payload() 97 if err != nil { 98 return err 99 } 100 if err := json.Indent(buffer, raw, "", "\t"); err != nil { 101 return err 102 } 103 fmt.Fprintln(dockerCli.Out(), buffer.String()) 104 return nil 105 } 106 jsonBytes, err := json.MarshalIndent(manifest, "", "\t") 107 if err != nil { 108 return err 109 } 110 dockerCli.Out().Write(append(jsonBytes, '\n')) 111 return nil 112 } 113 114 func printManifestList(dockerCli command.Cli, namedRef reference.Named, list []types.ImageManifest, opts inspectOptions) error { 115 if !opts.verbose { 116 targetRepo, err := registry.ParseRepositoryInfo(namedRef) 117 if err != nil { 118 return err 119 } 120 121 manifests := []manifestlist.ManifestDescriptor{} 122 // More than one response. This is a manifest list. 123 for _, img := range list { 124 mfd, err := buildManifestDescriptor(targetRepo, img) 125 if err != nil { 126 return errors.Wrap(err, "failed to assemble ManifestDescriptor") 127 } 128 manifests = append(manifests, mfd) 129 } 130 deserializedML, err := manifestlist.FromDescriptors(manifests) 131 if err != nil { 132 return err 133 } 134 jsonBytes, err := deserializedML.MarshalJSON() 135 if err != nil { 136 return err 137 } 138 fmt.Fprintln(dockerCli.Out(), string(jsonBytes)) 139 return nil 140 } 141 jsonBytes, err := json.MarshalIndent(list, "", "\t") 142 if err != nil { 143 return err 144 } 145 dockerCli.Out().Write(append(jsonBytes, '\n')) 146 return nil 147 }