github.1git.de/docker/cli@v26.1.3+incompatible/cli/command/context/list.go (about) 1 package context 2 3 import ( 4 "fmt" 5 "os" 6 "sort" 7 8 "github.com/docker/cli/cli" 9 "github.com/docker/cli/cli/command" 10 "github.com/docker/cli/cli/command/completion" 11 "github.com/docker/cli/cli/command/formatter" 12 "github.com/docker/cli/cli/context/docker" 13 flagsHelper "github.com/docker/cli/cli/flags" 14 "github.com/docker/docker/client" 15 "github.com/fvbommel/sortorder" 16 "github.com/spf13/cobra" 17 ) 18 19 type listOptions struct { 20 format string 21 quiet bool 22 } 23 24 func newListCommand(dockerCli command.Cli) *cobra.Command { 25 opts := &listOptions{} 26 cmd := &cobra.Command{ 27 Use: "ls [OPTIONS]", 28 Aliases: []string{"list"}, 29 Short: "List contexts", 30 Args: cli.NoArgs, 31 RunE: func(cmd *cobra.Command, args []string) error { 32 return runList(dockerCli, opts) 33 }, 34 ValidArgsFunction: completion.NoComplete, 35 } 36 37 flags := cmd.Flags() 38 flags.StringVar(&opts.format, "format", "", flagsHelper.FormatHelp) 39 flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only show context names") 40 return cmd 41 } 42 43 func runList(dockerCli command.Cli, opts *listOptions) error { 44 if opts.format == "" { 45 opts.format = formatter.TableFormatKey 46 } 47 contextMap, err := dockerCli.ContextStore().List() 48 if err != nil { 49 return err 50 } 51 var ( 52 curContext = dockerCli.CurrentContext() 53 curFound bool 54 contexts = make([]*formatter.ClientContext, 0, len(contextMap)) 55 ) 56 for _, rawMeta := range contextMap { 57 isCurrent := rawMeta.Name == curContext 58 if isCurrent { 59 curFound = true 60 } 61 meta, err := command.GetDockerContext(rawMeta) 62 if err != nil { 63 // Add a stub-entry to the list, including the error-message 64 // indicating that the context couldn't be loaded. 65 contexts = append(contexts, &formatter.ClientContext{ 66 Name: rawMeta.Name, 67 Current: isCurrent, 68 Error: err.Error(), 69 }) 70 continue 71 } 72 var errMsg string 73 dockerEndpoint, err := docker.EndpointFromContext(rawMeta) 74 if err != nil { 75 errMsg = err.Error() 76 } 77 desc := formatter.ClientContext{ 78 Name: rawMeta.Name, 79 Current: isCurrent, 80 Description: meta.Description, 81 DockerEndpoint: dockerEndpoint.Host, 82 Error: errMsg, 83 } 84 contexts = append(contexts, &desc) 85 } 86 if !curFound { 87 // The currently specified context wasn't found. We add a stub-entry 88 // to the list, including the error-message indicating that the context 89 // wasn't found. 90 var errMsg string 91 _, err := dockerCli.ContextStore().GetMetadata(curContext) 92 if err != nil { 93 errMsg = err.Error() 94 } 95 contexts = append(contexts, &formatter.ClientContext{ 96 Name: curContext, 97 Current: true, 98 Error: errMsg, 99 }) 100 } 101 sort.Slice(contexts, func(i, j int) bool { 102 return sortorder.NaturalLess(contexts[i].Name, contexts[j].Name) 103 }) 104 if err := format(dockerCli, opts, contexts); err != nil { 105 return err 106 } 107 if os.Getenv(client.EnvOverrideHost) != "" { 108 _, _ = fmt.Fprintf(dockerCli.Err(), "Warning: %[1]s environment variable overrides the active context. "+ 109 "To use a context, either set the global --context flag, or unset %[1]s environment variable.\n", client.EnvOverrideHost) 110 } 111 return nil 112 } 113 114 func format(dockerCli command.Cli, opts *listOptions, contexts []*formatter.ClientContext) error { 115 contextCtx := formatter.Context{ 116 Output: dockerCli.Out(), 117 Format: formatter.NewClientContextFormat(opts.format, opts.quiet), 118 } 119 return formatter.ClientContextWrite(contextCtx, contexts) 120 }