英文:
how do I pass a command status to Postrun in cobra cli
问题
Cobra CLI支持在命令执行后调用PostRun。
https://github.com/spf13/cobra#prerun-and-postrun-hooks
我如何将命令状态传递给PostRun调用?
我需要在命令执行后将其状态发送到服务器。
英文:
Cobra CLI has support for PostRun to invoke after execution of a command.
https://github.com/spf13/cobra#prerun-and-postrun-hooks
How do I pass on the command status to PostRun call?
I have requirement of posting the command status after its execution to a server
答案1
得分: 2
更清晰的方法是利用cobra命令中提供的注释。
package main
import (
"fmt"
"github.com/spf13/cobra"
)
func main() {
var rootCmd = &cobra.Command{
Use: "root [sub]",
Short: "My root command",
Run: func(cmd *cobra.Command, args []string) {
// 在这里进行处理
// 设置命令的注释
cmd.Annotations = make(map[string]string)
cmd.Annotations["status"] = "status_goes_here"
cmd.Annotations["error"] = "error_goes_here"
},
PostRun: func(cmd *cobra.Command, args []string) {
// 检索注释
fmt.Println(cmd.Annotations["status"])
fmt.Println(cmd.Annotations["error"])
},
}
rootCmd.SetArgs([]string{"sub", "arg1", "arg2"})
rootCmd.Execute()
}
我真的很喜欢@Bracken在这里采取的方法,尽管有一些调整可以使其工作。
package main
import (
"fmt"
"errors"
"github.com/spf13/cobra"
)
type wrapper struct {
err error
}
// RunE在出现错误的情况下无法继续执行,从而不执行PostRun操作
func (w *wrapper) Run(f func(cmd *cobra.Command, args []string) error) func(cmd *cobra.Command, args []string) {
return func(cmd *cobra.Command, args []string) {
err := f(cmd, args)
w.err = err
}
}
func (w *wrapper) PostRun(f func(cmd *cobra.Command, args []string, cmdErr error)) func(cmd *cobra.Command, args []string) {
return func(cmd *cobra.Command, args []string) {
f(cmd, args, w.err)
}
}
func main() {
cmdWrap := wrapper{}
var rootCmd = &cobra.Command{
Use: "root [sub]",
Short: "My root command",
Run: cmdWrap.Run(func(cmd *cobra.Command, args []string) error {
return errors.New("i'm not in the book, you know")
}),
PostRun: cmdWrap.PostRun(func(cmd *cobra.Command, args []string, cmdErr error) {
fmt.Printf("error was %v\n", cmdErr)
}),
}
rootCmd.SetArgs([]string{"sub", "arg1", "arg2"})
rootCmd.Execute()
}
----- 旧回答 -----
如果我理解正确,需要将一些状态从cmd.Execute传递到PostRun。
您可以使用ExecuteContext(ctx context.Context)
方法而不是Execute()
,并在上下文中设置所需的键值对。
ctx := context.WithValue(context.Background(), "status", "statusValue")
rootCmd.ExecuteContext(ctx)
在PostRun中可以使用cmd.Context()
检索相同的值。
PostRun: func(cmd *cobra.Command, args []string) {
ctx := cmd.Context()
status := ctx.Value("status")
}
英文:
Cleaner approach would be to leverage the Annotations provided in cobra command
package main
import (
"fmt"
"github.com/spf13/cobra"
)
func main() {
var rootCmd = &cobra.Command{
Use: "root [sub]",
Short: "My root command",
Run: func(cmd *cobra.Command, args []string) {
// Do your processing here
// Set the command annotations
cmd.Annotations = make(map[string]string)
cmd.Annotations["status"] = "status_goes_here"
cmd.Annotations["error"] = "error_goes_here"
},
PostRun: func(cmd *cobra.Command, args []string) {
// Retrieve the annotations
fmt.Println(cmd.Annotations["status"])
fmt.Println(cmd.Annotations["error"])
},
}
rootCmd.SetArgs([]string{"sub", "arg1", "arg2"})
rootCmd.Execute()
}
Really liked the approach @Bracken has taken here, Although there are some tweaks that will make it work
package main
import (
"fmt"
"errors"
"github.com/spf13/cobra"
)
type wrapper struct {
err error
}
// RunE fails to proceed further in case of error resulting in not executing PostRun actions
func (w *wrapper) Run(f func(cmd *cobra.Command, args []string) error) func(cmd *cobra.Command, args []string) {
return func(cmd *cobra.Command, args []string) {
err := f(cmd, args)
w.err = err
}
}
func (w *wrapper) PostRun(f func(cmd *cobra.Command, args []string, cmdErr error)) func(cmd *cobra.Command, args []string) {
return func(cmd *cobra.Command, args []string) {
f(cmd, args, w.err)
}
}
func main() {
cmdWrap := wrapper{}
var rootCmd = &cobra.Command{
Use: "root [sub]",
Short: "My root command",
Run: cmdWrap.Run(func(cmd *cobra.Command, args []string) error {
return errors.New("i'm not in the book, you know")
}),
PostRun: cmdWrap.PostRun(func(cmd *cobra.Command, args []string, cmdErr error) {
fmt.Printf("error was %v\n", cmdErr)
}),
}
rootCmd.SetArgs([]string{"sub", "arg1", "arg2"})
rootCmd.Execute()
}
----- Old Answer -----
If I understand it right, There is some status that needs to be passed from cmd.Execute to PostRun.
You can use ExecuteContext(ctx context.Context)
method instead of Execute()
and set whatever key-value needs to be set in context.
ctx := context.WithValue(context.Background(), "status", "statusValue")
rootCmd.ExecuteContext(ctx)
Same values can be Retrieved inside PostRun using cmd.Context()
PostRun: func(cmd *cobra.Command, args []string) {
ctx := cmd.Context()
status := ctx.Value("status")
}
答案2
得分: 0
我会使用高阶函数来包装你的Run
(或RunE
)函数和PostRun
函数,以捕获错误或恐慌,并将它们传递给你的PostRun
函数:
package main
import (
"fmt"
"github.com/spf13/cobra"
)
type wrapper struct {
err error
}
func (w *wrapper) RunE(f func(cmd *cobra.Command, args []string) error) func(cmd *cobra.Command, args []string) error {
return func(cmd *cobra.Command, args []string) (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic: %v", r)
w.err = err
}
}()
err = f(cmd, args)
w.err = err
return
}
}
func (w *wrapper) PostRun(f func(cmd *cobra.Command, args []string, cmdErr error)) func(cmd *cobra.Command, args []string) {
return func(cmd *cobra.Command, args []string) {
f(cmd, args, w.err)
}
}
func main() {
cmdWrap := wrapper{}
var cmdFail = &cobra.Command{
Use: "fail",
Short: "Doesn't work",
RunE: cmdWrap.RunE(func(cmd *cobra.Command, args []string) error {
panic("i'm not in the book, you know")
}),
PostRun: cmdWrap.PostRun(func(cmd *cobra.Command, args []string, cmdErr error) {
fmt.Printf("error was %v\n", cmdErr)
}),
}
var rootCmd = &cobra.Command{}
rootCmd.AddCommand(cmdFail)
rootCmd.Execute()
}
英文:
I would wrap your Run
(or RunE
) function and your PostRun
function using high order functions to catch errors or panics and then pass them into your PostRun
:
package main
import (
"fmt"
"github.com/spf13/cobra"
)
type wrapper struct {
err error
}
func (w *wrapper) RunE(f func(cmd *cobra.Command, args []string) error) func(cmd *cobra.Command, args []string) error {
return func(cmd *cobra.Command, args []string) (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic: %v", r)
w.err = err
}
}()
err = f(cmd, args)
w.err = err
return
}
}
func (w *wrapper) PostRun(f func(cmd *cobra.Command, args []string, cmdErr error)) func(cmd *cobra.Command, args []string) {
return func(cmd *cobra.Command, args []string) {
f(cmd, args, w.err)
}
}
func main() {
cmdWrap := wrapper{}
var cmdFail = &cobra.Command{
Use: "fail",
Short: "Doesn't work",
RunE: cmdWrap.RunE(func(cmd *cobra.Command, args []string) error {
panic("i'm not in the book, you know")
}),
PostRun: cmdWrap.PostRun(func(cmd *cobra.Command, args []string, cmdErr error) {
fmt.Printf("error was %v\n", cmdErr)
}),
}
var rootCmd = &cobra.Command{}
rootCmd.AddCommand(cmdFail)
rootCmd.Execute()
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论