github.com/kunnos/engine@v1.13.1/cli/command/node/inspect.go (about)

     1  package node
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"sort"
     7  	"strings"
     8  
     9  	"github.com/docker/docker/api/types/swarm"
    10  	"github.com/docker/docker/cli"
    11  	"github.com/docker/docker/cli/command"
    12  	"github.com/docker/docker/cli/command/inspect"
    13  	"github.com/docker/docker/pkg/ioutils"
    14  	"github.com/docker/go-units"
    15  	"github.com/spf13/cobra"
    16  	"golang.org/x/net/context"
    17  )
    18  
    19  type inspectOptions struct {
    20  	nodeIds []string
    21  	format  string
    22  	pretty  bool
    23  }
    24  
    25  func newInspectCommand(dockerCli *command.DockerCli) *cobra.Command {
    26  	var opts inspectOptions
    27  
    28  	cmd := &cobra.Command{
    29  		Use:   "inspect [OPTIONS] self|NODE [NODE...]",
    30  		Short: "Display detailed information on one or more nodes",
    31  		Args:  cli.RequiresMinArgs(1),
    32  		RunE: func(cmd *cobra.Command, args []string) error {
    33  			opts.nodeIds = 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.BoolVar(&opts.pretty, "pretty", false, "Print the information in a human friendly format.")
    41  	return cmd
    42  }
    43  
    44  func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error {
    45  	client := dockerCli.Client()
    46  	ctx := context.Background()
    47  	getRef := func(ref string) (interface{}, []byte, error) {
    48  		nodeRef, err := Reference(ctx, client, ref)
    49  		if err != nil {
    50  			return nil, nil, err
    51  		}
    52  		node, _, err := client.NodeInspectWithRaw(ctx, nodeRef)
    53  		return node, nil, err
    54  	}
    55  
    56  	if !opts.pretty {
    57  		return inspect.Inspect(dockerCli.Out(), opts.nodeIds, opts.format, getRef)
    58  	}
    59  	return printHumanFriendly(dockerCli.Out(), opts.nodeIds, getRef)
    60  }
    61  
    62  func printHumanFriendly(out io.Writer, refs []string, getRef inspect.GetRefFunc) error {
    63  	for idx, ref := range refs {
    64  		obj, _, err := getRef(ref)
    65  		if err != nil {
    66  			return err
    67  		}
    68  		printNode(out, obj.(swarm.Node))
    69  
    70  		// TODO: better way to do this?
    71  		// print extra space between objects, but not after the last one
    72  		if idx+1 != len(refs) {
    73  			fmt.Fprintf(out, "\n\n")
    74  		} else {
    75  			fmt.Fprintf(out, "\n")
    76  		}
    77  	}
    78  	return nil
    79  }
    80  
    81  // TODO: use a template
    82  func printNode(out io.Writer, node swarm.Node) {
    83  	fmt.Fprintf(out, "ID:\t\t\t%s\n", node.ID)
    84  	ioutils.FprintfIfNotEmpty(out, "Name:\t\t\t%s\n", node.Spec.Name)
    85  	if node.Spec.Labels != nil {
    86  		fmt.Fprintln(out, "Labels:")
    87  		for k, v := range node.Spec.Labels {
    88  			fmt.Fprintf(out, " - %s = %s\n", k, v)
    89  		}
    90  	}
    91  
    92  	ioutils.FprintfIfNotEmpty(out, "Hostname:\t\t%s\n", node.Description.Hostname)
    93  	fmt.Fprintf(out, "Joined at:\t\t%s\n", command.PrettyPrint(node.CreatedAt))
    94  	fmt.Fprintln(out, "Status:")
    95  	fmt.Fprintf(out, " State:\t\t\t%s\n", command.PrettyPrint(node.Status.State))
    96  	ioutils.FprintfIfNotEmpty(out, " Message:\t\t%s\n", command.PrettyPrint(node.Status.Message))
    97  	fmt.Fprintf(out, " Availability:\t\t%s\n", command.PrettyPrint(node.Spec.Availability))
    98  	ioutils.FprintfIfNotEmpty(out, " Address:\t\t%s\n", command.PrettyPrint(node.Status.Addr))
    99  
   100  	if node.ManagerStatus != nil {
   101  		fmt.Fprintln(out, "Manager Status:")
   102  		fmt.Fprintf(out, " Address:\t\t%s\n", node.ManagerStatus.Addr)
   103  		fmt.Fprintf(out, " Raft Status:\t\t%s\n", command.PrettyPrint(node.ManagerStatus.Reachability))
   104  		leader := "No"
   105  		if node.ManagerStatus.Leader {
   106  			leader = "Yes"
   107  		}
   108  		fmt.Fprintf(out, " Leader:\t\t%s\n", leader)
   109  	}
   110  
   111  	fmt.Fprintln(out, "Platform:")
   112  	fmt.Fprintf(out, " Operating System:\t%s\n", node.Description.Platform.OS)
   113  	fmt.Fprintf(out, " Architecture:\t\t%s\n", node.Description.Platform.Architecture)
   114  
   115  	fmt.Fprintln(out, "Resources:")
   116  	fmt.Fprintf(out, " CPUs:\t\t\t%d\n", node.Description.Resources.NanoCPUs/1e9)
   117  	fmt.Fprintf(out, " Memory:\t\t%s\n", units.BytesSize(float64(node.Description.Resources.MemoryBytes)))
   118  
   119  	var pluginTypes []string
   120  	pluginNamesByType := map[string][]string{}
   121  	for _, p := range node.Description.Engine.Plugins {
   122  		// append to pluginTypes only if not done previously
   123  		if _, ok := pluginNamesByType[p.Type]; !ok {
   124  			pluginTypes = append(pluginTypes, p.Type)
   125  		}
   126  		pluginNamesByType[p.Type] = append(pluginNamesByType[p.Type], p.Name)
   127  	}
   128  
   129  	if len(pluginTypes) > 0 {
   130  		fmt.Fprintln(out, "Plugins:")
   131  		sort.Strings(pluginTypes) // ensure stable output
   132  		for _, pluginType := range pluginTypes {
   133  			fmt.Fprintf(out, "  %s:\t\t%s\n", pluginType, strings.Join(pluginNamesByType[pluginType], ", "))
   134  		}
   135  	}
   136  	fmt.Fprintf(out, "Engine Version:\t\t%s\n", node.Description.Engine.EngineVersion)
   137  
   138  	if len(node.Description.Engine.Labels) != 0 {
   139  		fmt.Fprintln(out, "Engine Labels:")
   140  		for k, v := range node.Description.Engine.Labels {
   141  			fmt.Fprintf(out, " - %s = %s\n", k, v)
   142  		}
   143  	}
   144  }