github.com/containerd/nerdctl@v1.7.7/cmd/nerdctl/inspect.go (about) 1 /* 2 Copyright The containerd Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package main 18 19 import ( 20 "context" 21 "fmt" 22 23 "github.com/containerd/nerdctl/pkg/api/types" 24 "github.com/containerd/nerdctl/pkg/clientutil" 25 "github.com/containerd/nerdctl/pkg/cmd/container" 26 "github.com/containerd/nerdctl/pkg/cmd/image" 27 "github.com/containerd/nerdctl/pkg/idutil/containerwalker" 28 "github.com/containerd/nerdctl/pkg/idutil/imagewalker" 29 30 "github.com/spf13/cobra" 31 ) 32 33 func newInspectCommand() *cobra.Command { 34 var inspectCommand = &cobra.Command{ 35 Use: "inspect", 36 Short: "Return low-level information on objects.", 37 Args: cobra.MinimumNArgs(1), 38 RunE: inspectAction, 39 ValidArgsFunction: inspectShellComplete, 40 SilenceUsage: true, 41 SilenceErrors: true, 42 } 43 44 addInspectFlags(inspectCommand) 45 46 return inspectCommand 47 } 48 49 var validInspectType = map[string]bool{ 50 "container": true, 51 "image": true, 52 } 53 54 func addInspectFlags(cmd *cobra.Command) { 55 cmd.Flags().StringP("format", "f", "", "Format the output using the given Go template, e.g, '{{json .}}'") 56 cmd.RegisterFlagCompletionFunc("format", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { 57 return []string{"json"}, cobra.ShellCompDirectiveNoFileComp 58 }) 59 cmd.Flags().String("type", "", "Return JSON for specified type") 60 cmd.RegisterFlagCompletionFunc("type", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { 61 return []string{"image", "container", ""}, cobra.ShellCompDirectiveNoFileComp 62 }) 63 cmd.Flags().String("mode", "dockercompat", `Inspect mode, "dockercompat" for Docker-compatible output, "native" for containerd-native output`) 64 cmd.RegisterFlagCompletionFunc("mode", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { 65 return []string{"dockercompat", "native"}, cobra.ShellCompDirectiveNoFileComp 66 }) 67 } 68 69 func inspectAction(cmd *cobra.Command, args []string) error { 70 globalOptions, err := processRootCmdFlags(cmd) 71 if err != nil { 72 return err 73 } 74 namespace := globalOptions.Namespace 75 address := globalOptions.Address 76 inspectType, err := cmd.Flags().GetString("type") 77 if err != nil { 78 return err 79 } 80 81 if len(inspectType) > 0 && !validInspectType[inspectType] { 82 return fmt.Errorf("%q is not a valid value for --type", inspectType) 83 } 84 85 // container and image inspect can share the same client, since no `platform` 86 // flag will be passed for image inspect. 87 client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), namespace, address) 88 if err != nil { 89 return err 90 } 91 defer cancel() 92 93 imagewalker := &imagewalker.ImageWalker{ 94 Client: client, 95 OnFound: func(ctx context.Context, found imagewalker.Found) error { 96 return nil 97 }, 98 } 99 100 containerwalker := &containerwalker.ContainerWalker{ 101 Client: client, 102 OnFound: func(ctx context.Context, found containerwalker.Found) error { 103 return nil 104 }, 105 } 106 107 inspectImage := len(inspectType) == 0 || inspectType == "image" 108 inspectContainer := len(inspectType) == 0 || inspectType == "container" 109 110 var imageInspectOptions types.ImageInspectOptions 111 var containerInspectOptions types.ContainerInspectOptions 112 if inspectImage { 113 platform := "" 114 imageInspectOptions, err = processImageInspectOptions(cmd, &platform) 115 if err != nil { 116 return err 117 } 118 } 119 if inspectContainer { 120 containerInspectOptions, err = processContainerInspectOptions(cmd) 121 if err != nil { 122 return err 123 } 124 } 125 126 var errs []error 127 for _, req := range args { 128 var ni int 129 var nc int 130 131 if inspectImage { 132 ni, err = imagewalker.Walk(ctx, req) 133 if err != nil { 134 return err 135 } 136 } 137 if inspectContainer { 138 nc, err = containerwalker.Walk(ctx, req) 139 if err != nil { 140 return err 141 } 142 } 143 144 if ni == 0 && nc == 0 { 145 errs = append(errs, fmt.Errorf("no such object %s", req)) 146 } else if ni > 0 { 147 if err := image.Inspect(ctx, client, []string{req}, imageInspectOptions); err != nil { 148 errs = append(errs, err) 149 } 150 } else if nc > 0 { 151 if err := container.Inspect(ctx, client, []string{req}, containerInspectOptions); err != nil { 152 errs = append(errs, err) 153 } 154 } 155 } 156 157 if len(errs) > 0 { 158 return fmt.Errorf("%d errors: %v", len(errs), errs) 159 } 160 161 return nil 162 } 163 164 func inspectShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { 165 // show container names 166 containers, _ := shellCompleteContainerNames(cmd, nil) 167 // show image names 168 images, _ := shellCompleteImageNames(cmd) 169 return append(containers, images...), cobra.ShellCompDirectiveNoFileComp 170 }