...

Source file src/github.com/docker/cli/cli-plugins/manager/cobra.go

Documentation: github.com/docker/cli/cli-plugins/manager

     1  package manager
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"sync"
     7  
     8  	"github.com/docker/cli/cli/command"
     9  	"github.com/spf13/cobra"
    10  )
    11  
    12  const (
    13  	// CommandAnnotationPlugin is added to every stub command added by
    14  	// AddPluginCommandStubs with the value "true" and so can be
    15  	// used to distinguish plugin stubs from regular commands.
    16  	CommandAnnotationPlugin = "com.docker.cli.plugin"
    17  
    18  	// CommandAnnotationPluginVendor is added to every stub command
    19  	// added by AddPluginCommandStubs and contains the vendor of
    20  	// that plugin.
    21  	CommandAnnotationPluginVendor = "com.docker.cli.plugin.vendor"
    22  
    23  	// CommandAnnotationPluginVersion is added to every stub command
    24  	// added by AddPluginCommandStubs and contains the version of
    25  	// that plugin.
    26  	CommandAnnotationPluginVersion = "com.docker.cli.plugin.version"
    27  
    28  	// CommandAnnotationPluginInvalid is added to any stub command
    29  	// added by AddPluginCommandStubs for an invalid command (that
    30  	// is, one which failed it's candidate test) and contains the
    31  	// reason for the failure.
    32  	CommandAnnotationPluginInvalid = "com.docker.cli.plugin-invalid"
    33  )
    34  
    35  var pluginCommandStubsOnce sync.Once
    36  
    37  // AddPluginCommandStubs adds a stub cobra.Commands for each valid and invalid
    38  // plugin. The command stubs will have several annotations added, see
    39  // `CommandAnnotationPlugin*`.
    40  func AddPluginCommandStubs(dockerCli command.Cli, rootCmd *cobra.Command) (err error) {
    41  	pluginCommandStubsOnce.Do(func() {
    42  		var plugins []Plugin
    43  		plugins, err = ListPlugins(dockerCli, rootCmd)
    44  		if err != nil {
    45  			return
    46  		}
    47  		for _, p := range plugins {
    48  			p := p
    49  			vendor := p.Vendor
    50  			if vendor == "" {
    51  				vendor = "unknown"
    52  			}
    53  			annotations := map[string]string{
    54  				CommandAnnotationPlugin:        "true",
    55  				CommandAnnotationPluginVendor:  vendor,
    56  				CommandAnnotationPluginVersion: p.Version,
    57  			}
    58  			if p.Err != nil {
    59  				annotations[CommandAnnotationPluginInvalid] = p.Err.Error()
    60  			}
    61  			rootCmd.AddCommand(&cobra.Command{
    62  				Use:                p.Name,
    63  				Short:              p.ShortDescription,
    64  				Run:                func(_ *cobra.Command, _ []string) {},
    65  				Annotations:        annotations,
    66  				DisableFlagParsing: true,
    67  				RunE: func(cmd *cobra.Command, args []string) error {
    68  					flags := rootCmd.PersistentFlags()
    69  					flags.SetOutput(nil)
    70  					perr := flags.Parse(args)
    71  					if perr != nil {
    72  						return err
    73  					}
    74  					if flags.Changed("help") {
    75  						cmd.HelpFunc()(rootCmd, args)
    76  						return nil
    77  					}
    78  					return fmt.Errorf("docker: '%s' is not a docker command.\nSee 'docker --help'", cmd.Name())
    79  				},
    80  				ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
    81  					// Delegate completion to plugin
    82  					cargs := []string{p.Path, cobra.ShellCompRequestCmd, p.Name}
    83  					cargs = append(cargs, args...)
    84  					cargs = append(cargs, toComplete)
    85  					os.Args = cargs
    86  					runCommand, runErr := PluginRunCommand(dockerCli, p.Name, cmd)
    87  					if runErr != nil {
    88  						return nil, cobra.ShellCompDirectiveError
    89  					}
    90  					runErr = runCommand.Run()
    91  					if runErr == nil {
    92  						os.Exit(0) // plugin already rendered complete data
    93  					}
    94  					return nil, cobra.ShellCompDirectiveError
    95  				},
    96  			})
    97  		}
    98  	})
    99  	return err
   100  }
   101  

View as plain text