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