github.com/kaisenlinux/docker@v0.0.0-20230510090727-ea55db55fac7/swarmkit/cmd/swarmctl/node/inspect.go (about) 1 package node 2 3 import ( 4 "errors" 5 "fmt" 6 "os" 7 "sort" 8 "text/tabwriter" 9 10 "github.com/docker/swarmkit/api" 11 "github.com/docker/swarmkit/api/genericresource" 12 "github.com/docker/swarmkit/cmd/swarmctl/common" 13 "github.com/docker/swarmkit/cmd/swarmctl/task" 14 "github.com/dustin/go-humanize" 15 "github.com/spf13/cobra" 16 ) 17 18 func printNodeSummary(node *api.Node) { 19 w := tabwriter.NewWriter(os.Stdout, 8, 8, 8, ' ', 0) 20 defer func() { 21 // Ignore flushing errors - there's nothing we can do. 22 _ = w.Flush() 23 }() 24 spec := &node.Spec 25 desc := node.Description 26 if desc == nil { 27 desc = &api.NodeDescription{} 28 } 29 common.FprintfIfNotEmpty(w, "ID\t: %s\n", node.ID) 30 if node.Description != nil { 31 common.FprintfIfNotEmpty(w, "Hostname\t: %s\n", node.Description.Hostname) 32 } 33 if len(spec.Annotations.Labels) != 0 { 34 fmt.Fprint(w, "Node Labels\t:") 35 // sort label output for readability 36 var keys []string 37 for k := range spec.Annotations.Labels { 38 keys = append(keys, k) 39 } 40 sort.Strings(keys) 41 for _, k := range keys { 42 fmt.Fprintf(w, " %s=%s", k, spec.Annotations.Labels[k]) 43 } 44 fmt.Fprintln(w) 45 } 46 fmt.Fprintln(w, "Status:\t") 47 common.FprintfIfNotEmpty(w, " State\t: %s\n", node.Status.State.String()) 48 common.FprintfIfNotEmpty(w, " Message\t: %s\n", node.Status.Message) 49 common.FprintfIfNotEmpty(w, " Availability\t: %s\n", spec.Availability.String()) 50 common.FprintfIfNotEmpty(w, " Address\t: %s\n", node.Status.Addr) 51 52 if node.ManagerStatus != nil { 53 fmt.Fprintln(w, "Manager status:\t") 54 common.FprintfIfNotEmpty(w, " Address\t: %s\n", node.ManagerStatus.Addr) 55 common.FprintfIfNotEmpty(w, " Raft status\t: %s\n", node.ManagerStatus.Reachability.String()) 56 leader := "no" 57 if node.ManagerStatus.Leader { 58 leader = "yes" 59 } 60 common.FprintfIfNotEmpty(w, " Leader\t: %s\n", leader) 61 } 62 63 if desc.Platform != nil { 64 fmt.Fprintln(w, "Platform:\t") 65 common.FprintfIfNotEmpty(w, " Operating System\t: %s\n", desc.Platform.OS) 66 common.FprintfIfNotEmpty(w, " Architecture\t: %s\n", desc.Platform.Architecture) 67 } 68 69 if desc.Resources != nil { 70 fmt.Fprintln(w, "Resources:\t") 71 fmt.Fprintf(w, " CPUs\t: %d\n", desc.Resources.NanoCPUs/1e9) 72 fmt.Fprintf(w, " Memory\t: %s\n", humanize.IBytes(uint64(desc.Resources.MemoryBytes))) 73 fmt.Fprintln(w, " Generic Resources:\t") 74 for _, r := range desc.Resources.Generic { 75 k := genericresource.Kind(r) 76 v := genericresource.Value(r) 77 fmt.Fprintf(w, " %s\t: %s\n", k, v) 78 } 79 } 80 81 if desc.Engine != nil { 82 fmt.Fprintln(w, "Plugins:\t") 83 var pluginTypes []string 84 pluginNamesByType := map[string][]string{} 85 for _, p := range desc.Engine.Plugins { 86 // append to pluginTypes only if not done previously 87 if _, ok := pluginNamesByType[p.Type]; !ok { 88 pluginTypes = append(pluginTypes, p.Type) 89 } 90 pluginNamesByType[p.Type] = append(pluginNamesByType[p.Type], p.Name) 91 } 92 93 sort.Strings(pluginTypes) // ensure stable output 94 for _, pluginType := range pluginTypes { 95 fmt.Fprintf(w, " %s\t: %v\n", pluginType, pluginNamesByType[pluginType]) 96 } 97 } 98 99 if desc.Engine != nil { 100 common.FprintfIfNotEmpty(w, "Engine Version\t: %s\n", desc.Engine.EngineVersion) 101 102 if len(desc.Engine.Labels) != 0 { 103 fmt.Fprint(w, "Engine Labels\t:") 104 var keys []string 105 for k := range desc.Engine.Labels { 106 keys = append(keys, k) 107 } 108 sort.Strings(keys) 109 for _, k := range keys { 110 fmt.Fprintf(w, " %s=%s", k, desc.Engine.Labels[k]) 111 } 112 fmt.Fprintln(w) 113 } 114 } 115 } 116 117 var ( 118 inspectCmd = &cobra.Command{ 119 Use: "inspect <node ID>", 120 Short: "Inspect a node", 121 RunE: func(cmd *cobra.Command, args []string) error { 122 if len(args) == 0 { 123 return errors.New("node ID missing") 124 } 125 126 if len(args) > 1 { 127 return errors.New("inspect command takes exactly 1 argument") 128 } 129 130 flags := cmd.Flags() 131 132 all, err := flags.GetBool("all") 133 if err != nil { 134 return err 135 } 136 137 c, err := common.Dial(cmd) 138 if err != nil { 139 return err 140 } 141 142 node, err := getNode(common.Context(cmd), c, args[0]) 143 if err != nil { 144 return err 145 } 146 147 r, err := c.ListTasks(common.Context(cmd), 148 &api.ListTasksRequest{ 149 Filters: &api.ListTasksRequest_Filters{ 150 NodeIDs: []string{node.ID}, 151 }, 152 }) 153 if err != nil { 154 return err 155 } 156 157 printNodeSummary(node) 158 if len(r.Tasks) > 0 { 159 fmt.Println() 160 task.Print(r.Tasks, all, common.NewResolver(cmd, c)) 161 } 162 163 return nil 164 }, 165 } 166 ) 167 168 func init() { 169 inspectCmd.Flags().BoolP("all", "a", false, "Show all tasks (default shows just running)") 170 }