github.com/pdmccormick/importable-docker-buildx@v0.0.0-20240426161518-e47091289030/commands/inspect.go (about) 1 package commands 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "sort" 8 "strings" 9 "text/tabwriter" 10 "time" 11 12 "github.com/docker/buildx/builder" 13 "github.com/docker/buildx/driver" 14 "github.com/docker/buildx/util/cobrautil/completion" 15 "github.com/docker/buildx/util/platformutil" 16 "github.com/docker/cli/cli" 17 "github.com/docker/cli/cli/command" 18 "github.com/docker/cli/cli/debug" 19 "github.com/docker/go-units" 20 "github.com/spf13/cobra" 21 ) 22 23 type inspectOptions struct { 24 bootstrap bool 25 builder string 26 } 27 28 func runInspect(ctx context.Context, dockerCli command.Cli, in inspectOptions) error { 29 b, err := builder.New(dockerCli, 30 builder.WithName(in.builder), 31 builder.WithSkippedValidation(), 32 ) 33 if err != nil { 34 return err 35 } 36 37 timeoutCtx, cancel := context.WithTimeout(ctx, 20*time.Second) 38 defer cancel() 39 40 nodes, err := b.LoadNodes(timeoutCtx, builder.WithData()) 41 if in.bootstrap { 42 var ok bool 43 ok, err = b.Boot(ctx) 44 if err != nil { 45 return err 46 } 47 if ok { 48 nodes, err = b.LoadNodes(timeoutCtx, builder.WithData()) 49 } 50 } 51 52 w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) 53 fmt.Fprintf(w, "Name:\t%s\n", b.Name) 54 fmt.Fprintf(w, "Driver:\t%s\n", b.Driver) 55 if !b.NodeGroup.LastActivity.IsZero() { 56 fmt.Fprintf(w, "Last Activity:\t%v\n", b.NodeGroup.LastActivity) 57 } 58 59 if err != nil { 60 fmt.Fprintf(w, "Error:\t%s\n", err.Error()) 61 } else if b.Err() != nil { 62 fmt.Fprintf(w, "Error:\t%s\n", b.Err().Error()) 63 } 64 if err == nil { 65 fmt.Fprintln(w, "") 66 fmt.Fprintln(w, "Nodes:") 67 68 for i, n := range nodes { 69 if i != 0 { 70 fmt.Fprintln(w, "") 71 } 72 fmt.Fprintf(w, "Name:\t%s\n", n.Name) 73 fmt.Fprintf(w, "Endpoint:\t%s\n", n.Endpoint) 74 75 var driverOpts []string 76 for k, v := range n.DriverOpts { 77 driverOpts = append(driverOpts, fmt.Sprintf("%s=%q", k, v)) 78 } 79 if len(driverOpts) > 0 { 80 fmt.Fprintf(w, "Driver Options:\t%s\n", strings.Join(driverOpts, " ")) 81 } 82 83 if err := n.Err; err != nil { 84 fmt.Fprintf(w, "Error:\t%s\n", err.Error()) 85 } else { 86 fmt.Fprintf(w, "Status:\t%s\n", nodes[i].DriverInfo.Status) 87 if len(n.BuildkitdFlags) > 0 { 88 fmt.Fprintf(w, "BuildKit daemon flags:\t%s\n", strings.Join(n.BuildkitdFlags, " ")) 89 } 90 if nodes[i].Version != "" { 91 fmt.Fprintf(w, "BuildKit version:\t%s\n", nodes[i].Version) 92 } 93 platforms := platformutil.FormatInGroups(n.Node.Platforms, n.Platforms) 94 if len(platforms) > 0 { 95 fmt.Fprintf(w, "Platforms:\t%s\n", strings.Join(platforms, ", ")) 96 } 97 if debug.IsEnabled() { 98 fmt.Fprintf(w, "Features:\n") 99 features := nodes[i].Driver.Features(ctx) 100 featKeys := make([]string, 0, len(features)) 101 for k := range features { 102 featKeys = append(featKeys, string(k)) 103 } 104 sort.Strings(featKeys) 105 for _, k := range featKeys { 106 fmt.Fprintf(w, "\t%s:\t%t\n", k, features[driver.Feature(k)]) 107 } 108 } 109 if len(nodes[i].Labels) > 0 { 110 fmt.Fprintf(w, "Labels:\n") 111 for _, k := range sortedKeys(nodes[i].Labels) { 112 v := nodes[i].Labels[k] 113 fmt.Fprintf(w, "\t%s:\t%s\n", k, v) 114 } 115 } 116 for ri, rule := range nodes[i].GCPolicy { 117 fmt.Fprintf(w, "GC Policy rule#%d:\n", ri) 118 fmt.Fprintf(w, "\tAll:\t%v\n", rule.All) 119 if len(rule.Filter) > 0 { 120 fmt.Fprintf(w, "\tFilters:\t%s\n", strings.Join(rule.Filter, " ")) 121 } 122 if rule.KeepDuration > 0 { 123 fmt.Fprintf(w, "\tKeep Duration:\t%v\n", rule.KeepDuration.String()) 124 } 125 if rule.KeepBytes > 0 { 126 fmt.Fprintf(w, "\tKeep Bytes:\t%s\n", units.BytesSize(float64(rule.KeepBytes))) 127 } 128 } 129 } 130 } 131 } 132 133 w.Flush() 134 135 return nil 136 } 137 138 func inspectCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command { 139 var options inspectOptions 140 141 cmd := &cobra.Command{ 142 Use: "inspect [NAME]", 143 Short: "Inspect current builder instance", 144 Args: cli.RequiresMaxArgs(1), 145 RunE: func(cmd *cobra.Command, args []string) error { 146 options.builder = rootOpts.builder 147 if len(args) > 0 { 148 options.builder = args[0] 149 } 150 return runInspect(cmd.Context(), dockerCli, options) 151 }, 152 ValidArgsFunction: completion.BuilderNames(dockerCli), 153 } 154 155 flags := cmd.Flags() 156 flags.BoolVar(&options.bootstrap, "bootstrap", false, "Ensure builder has booted before inspecting") 157 158 return cmd 159 } 160 161 func sortedKeys(m map[string]string) []string { 162 s := make([]string, len(m)) 163 i := 0 164 for k := range m { 165 s[i] = k 166 i++ 167 } 168 sort.Strings(s) 169 return s 170 }