github.com/DaoCloud/dao@v0.0.0-20161212064103-c3dbfd13ee36/api/client/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/client"
    10  	"github.com/docker/docker/api/client/inspect"
    11  	"github.com/docker/docker/cli"
    12  	"github.com/docker/docker/pkg/ioutils"
    13  	"github.com/docker/engine-api/types/swarm"
    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 *client.DockerCli) *cobra.Command {
    26  	var opts inspectOptions
    27  
    28  	cmd := &cobra.Command{
    29  		Use:   "inspect [OPTIONS] self|NODE [NODE...]",
    30  		Short: "显示Swarm集群中一个或多个节点的详细信息",
    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", "", "使用指定的Go语言模板格式化命令输出内容。")
    40  	flags.BoolVar(&opts.pretty, "pretty", false, "通过人工可读的格式输出命令信息。")
    41  	return cmd
    42  }
    43  
    44  func runInspect(dockerCli *client.DockerCli, opts inspectOptions) error {
    45  	client := dockerCli.Client()
    46  	ctx := context.Background()
    47  	getRef := func(ref string) (interface{}, []byte, error) {
    48  		nodeRef, err := Reference(client, ctx, 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, "名称:\t\t\t%s\n", node.Spec.Name)
    85  	if node.Spec.Labels != nil {
    86  		fmt.Fprintln(out, "标签:")
    87  		for k, v := range node.Spec.Labels {
    88  			fmt.Fprintf(out, " - %s = %s\n", k, v)
    89  		}
    90  	}
    91  
    92  	ioutils.FprintfIfNotEmpty(out, "主机名:\t\t%s\n", node.Description.Hostname)
    93  	fmt.Fprintf(out, "加入集群时间:\t\t%s\n", client.PrettyPrint(node.CreatedAt))
    94  	fmt.Fprintln(out, "状态:")
    95  	fmt.Fprintf(out, " 状态:\t\t\t%s\n", client.PrettyPrint(node.Status.State))
    96  	ioutils.FprintfIfNotEmpty(out, " 状态消息:\t\t%s\n", client.PrettyPrint(node.Status.Message))
    97  	fmt.Fprintf(out, " 可达状态:\t\t%s\n", client.PrettyPrint(node.Spec.Availability))
    98  
    99  	if node.ManagerStatus != nil {
   100  		fmt.Fprintln(out, "管理角色状态:")
   101  		fmt.Fprintf(out, " 监听地址:\t\t%s\n", node.ManagerStatus.Addr)
   102  		fmt.Fprintf(out, " Raft一致性状态:\t\t%s\n", client.PrettyPrint(node.ManagerStatus.Reachability))
   103  		leader := "No"
   104  		if node.ManagerStatus.Leader {
   105  			leader = "Yes"
   106  		}
   107  		fmt.Fprintf(out, " 领导者:\t\t%s\n", leader)
   108  	}
   109  
   110  	fmt.Fprintln(out, "平台信息:")
   111  	fmt.Fprintf(out, " 操作系统:\t%s\n", node.Description.Platform.OS)
   112  	fmt.Fprintf(out, " 机器架构:\t\t%s\n", node.Description.Platform.Architecture)
   113  
   114  	fmt.Fprintln(out, "机器资源:")
   115  	fmt.Fprintf(out, " CPU总数量:\t\t\t%d\n", node.Description.Resources.NanoCPUs/1e9)
   116  	fmt.Fprintf(out, " 总内存:\t\t%s\n", units.BytesSize(float64(node.Description.Resources.MemoryBytes)))
   117  
   118  	var pluginTypes []string
   119  	pluginNamesByType := map[string][]string{}
   120  	for _, p := range node.Description.Engine.Plugins {
   121  		// append to pluginTypes only if not done previously
   122  		if _, ok := pluginNamesByType[p.Type]; !ok {
   123  			pluginTypes = append(pluginTypes, p.Type)
   124  		}
   125  		pluginNamesByType[p.Type] = append(pluginNamesByType[p.Type], p.Name)
   126  	}
   127  
   128  	if len(pluginTypes) > 0 {
   129  		fmt.Fprintln(out, "插件:")
   130  		sort.Strings(pluginTypes) // ensure stable output
   131  		for _, pluginType := range pluginTypes {
   132  			fmt.Fprintf(out, "  %s:\t\t%s\n", pluginType, strings.Join(pluginNamesByType[pluginType], ", "))
   133  		}
   134  	}
   135  	fmt.Fprintf(out, "Docker引擎版本:\t\t%s\n", node.Description.Engine.EngineVersion)
   136  
   137  	if len(node.Description.Engine.Labels) != 0 {
   138  		fmt.Fprintln(out, "Docker引擎标签:")
   139  		for k, v := range node.Description.Engine.Labels {
   140  			fmt.Fprintf(out, " - %s = %s\n", k, v)
   141  		}
   142  	}
   143  }