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