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  }