github.com/xeptore/docker-cli@v20.10.14+incompatible/cli/command/system/inspect.go (about) 1 package system 2 3 import ( 4 "context" 5 "fmt" 6 "strings" 7 8 "github.com/docker/cli/cli" 9 "github.com/docker/cli/cli/command" 10 "github.com/docker/cli/cli/command/inspect" 11 "github.com/docker/docker/api/types" 12 apiclient "github.com/docker/docker/client" 13 "github.com/pkg/errors" 14 "github.com/spf13/cobra" 15 ) 16 17 type inspectOptions struct { 18 format string 19 inspectType string 20 size bool 21 ids []string 22 } 23 24 // NewInspectCommand creates a new cobra.Command for `docker inspect` 25 func NewInspectCommand(dockerCli command.Cli) *cobra.Command { 26 var opts inspectOptions 27 28 cmd := &cobra.Command{ 29 Use: "inspect [OPTIONS] NAME|ID [NAME|ID...]", 30 Short: "Return low-level information on Docker objects", 31 Args: cli.RequiresMinArgs(1), 32 RunE: func(cmd *cobra.Command, args []string) error { 33 opts.ids = args 34 return runInspect(dockerCli, opts) 35 }, 36 } 37 38 flags := cmd.Flags() 39 flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template") 40 flags.StringVar(&opts.inspectType, "type", "", "Return JSON for specified type") 41 flags.BoolVarP(&opts.size, "size", "s", false, "Display total file sizes if the type is container") 42 43 return cmd 44 } 45 46 func runInspect(dockerCli command.Cli, opts inspectOptions) error { 47 var elementSearcher inspect.GetRefFunc 48 switch opts.inspectType { 49 case "", "container", "image", "node", "network", "service", "volume", "task", "plugin", "secret": 50 elementSearcher = inspectAll(context.Background(), dockerCli, opts.size, opts.inspectType) 51 default: 52 return errors.Errorf("%q is not a valid value for --type", opts.inspectType) 53 } 54 return inspect.Inspect(dockerCli.Out(), opts.ids, opts.format, elementSearcher) 55 } 56 57 func inspectContainers(ctx context.Context, dockerCli command.Cli, getSize bool) inspect.GetRefFunc { 58 return func(ref string) (interface{}, []byte, error) { 59 return dockerCli.Client().ContainerInspectWithRaw(ctx, ref, getSize) 60 } 61 } 62 63 func inspectImages(ctx context.Context, dockerCli command.Cli) inspect.GetRefFunc { 64 return func(ref string) (interface{}, []byte, error) { 65 return dockerCli.Client().ImageInspectWithRaw(ctx, ref) 66 } 67 } 68 69 func inspectNetwork(ctx context.Context, dockerCli command.Cli) inspect.GetRefFunc { 70 return func(ref string) (interface{}, []byte, error) { 71 return dockerCli.Client().NetworkInspectWithRaw(ctx, ref, types.NetworkInspectOptions{}) 72 } 73 } 74 75 func inspectNode(ctx context.Context, dockerCli command.Cli) inspect.GetRefFunc { 76 return func(ref string) (interface{}, []byte, error) { 77 return dockerCli.Client().NodeInspectWithRaw(ctx, ref) 78 } 79 } 80 81 func inspectService(ctx context.Context, dockerCli command.Cli) inspect.GetRefFunc { 82 return func(ref string) (interface{}, []byte, error) { 83 // Service inspect shows defaults values in empty fields. 84 return dockerCli.Client().ServiceInspectWithRaw(ctx, ref, types.ServiceInspectOptions{InsertDefaults: true}) 85 } 86 } 87 88 func inspectTasks(ctx context.Context, dockerCli command.Cli) inspect.GetRefFunc { 89 return func(ref string) (interface{}, []byte, error) { 90 return dockerCli.Client().TaskInspectWithRaw(ctx, ref) 91 } 92 } 93 94 func inspectVolume(ctx context.Context, dockerCli command.Cli) inspect.GetRefFunc { 95 return func(ref string) (interface{}, []byte, error) { 96 return dockerCli.Client().VolumeInspectWithRaw(ctx, ref) 97 } 98 } 99 100 func inspectPlugin(ctx context.Context, dockerCli command.Cli) inspect.GetRefFunc { 101 return func(ref string) (interface{}, []byte, error) { 102 return dockerCli.Client().PluginInspectWithRaw(ctx, ref) 103 } 104 } 105 106 func inspectSecret(ctx context.Context, dockerCli command.Cli) inspect.GetRefFunc { 107 return func(ref string) (interface{}, []byte, error) { 108 return dockerCli.Client().SecretInspectWithRaw(ctx, ref) 109 } 110 } 111 112 func inspectAll(ctx context.Context, dockerCli command.Cli, getSize bool, typeConstraint string) inspect.GetRefFunc { 113 var inspectAutodetect = []struct { 114 objectType string 115 isSizeSupported bool 116 isSwarmObject bool 117 objectInspector func(string) (interface{}, []byte, error) 118 }{ 119 { 120 objectType: "container", 121 isSizeSupported: true, 122 objectInspector: inspectContainers(ctx, dockerCli, getSize), 123 }, 124 { 125 objectType: "image", 126 objectInspector: inspectImages(ctx, dockerCli), 127 }, 128 { 129 objectType: "network", 130 objectInspector: inspectNetwork(ctx, dockerCli), 131 }, 132 { 133 objectType: "volume", 134 objectInspector: inspectVolume(ctx, dockerCli), 135 }, 136 { 137 objectType: "service", 138 isSwarmObject: true, 139 objectInspector: inspectService(ctx, dockerCli), 140 }, 141 { 142 objectType: "task", 143 isSwarmObject: true, 144 objectInspector: inspectTasks(ctx, dockerCli), 145 }, 146 { 147 objectType: "node", 148 isSwarmObject: true, 149 objectInspector: inspectNode(ctx, dockerCli), 150 }, 151 { 152 objectType: "plugin", 153 objectInspector: inspectPlugin(ctx, dockerCli), 154 }, 155 { 156 objectType: "secret", 157 isSwarmObject: true, 158 objectInspector: inspectSecret(ctx, dockerCli), 159 }, 160 } 161 162 // isSwarmManager does an Info API call to verify that the daemon is 163 // a swarm manager. 164 isSwarmManager := func() bool { 165 info, err := dockerCli.Client().Info(ctx) 166 if err != nil { 167 fmt.Fprintln(dockerCli.Err(), err) 168 return false 169 } 170 return info.Swarm.ControlAvailable 171 } 172 173 return func(ref string) (interface{}, []byte, error) { 174 const ( 175 swarmSupportUnknown = iota 176 swarmSupported 177 swarmUnsupported 178 ) 179 180 isSwarmSupported := swarmSupportUnknown 181 182 for _, inspectData := range inspectAutodetect { 183 if typeConstraint != "" && inspectData.objectType != typeConstraint { 184 continue 185 } 186 if typeConstraint == "" && inspectData.isSwarmObject { 187 if isSwarmSupported == swarmSupportUnknown { 188 if isSwarmManager() { 189 isSwarmSupported = swarmSupported 190 } else { 191 isSwarmSupported = swarmUnsupported 192 } 193 } 194 if isSwarmSupported == swarmUnsupported { 195 continue 196 } 197 } 198 v, raw, err := inspectData.objectInspector(ref) 199 if err != nil { 200 if typeConstraint == "" && isErrSkippable(err) { 201 continue 202 } 203 return v, raw, err 204 } 205 if getSize && !inspectData.isSizeSupported { 206 fmt.Fprintf(dockerCli.Err(), "WARNING: --size ignored for %s\n", inspectData.objectType) 207 } 208 return v, raw, err 209 } 210 return nil, nil, errors.Errorf("Error: No such object: %s", ref) 211 } 212 } 213 214 func isErrSkippable(err error) bool { 215 return apiclient.IsErrNotFound(err) || 216 strings.Contains(err.Error(), "not supported") || 217 strings.Contains(err.Error(), "invalid reference format") 218 }