package hooks import ( "bytes" "errors" "fmt" "strconv" "strings" "text/template" "github.com/spf13/cobra" ) type HookType int const ( NextSteps = iota ) // HookMessage represents a plugin hook response. Plugins // declaring support for CLI hooks need to print a json // representation of this type when their hook subcommand // is invoked. type HookMessage struct { Type HookType Template string } // TemplateReplaceSubcommandName returns a hook template string // that will be replaced by the CLI subcommand being executed // // Example: // // "you ran the subcommand: " + TemplateReplaceSubcommandName() // // when being executed after the command: // `docker run --name "my-container" alpine` // will result in the message: // `you ran the subcommand: run` func TemplateReplaceSubcommandName() string { return hookTemplateCommandName } // TemplateReplaceFlagValue returns a hook template string // that will be replaced by the flags value. // // Example: // // "you ran a container named: " + TemplateReplaceFlagValue("name") // // when being executed after the command: // `docker run --name "my-container" alpine` // will result in the message: // `you ran a container named: my-container` func TemplateReplaceFlagValue(flag string) string { return fmt.Sprintf(hookTemplateFlagValue, flag) } // TemplateReplaceArg takes an index i and returns a hook // template string that the CLI will replace the template with // the ith argument, after processing the passed flags. // // Example: // // "run this image with `docker run " + TemplateReplaceArg(0) + "`" // // when being executed after the command: // `docker pull alpine` // will result in the message: // "Run this image with `docker run alpine`" func TemplateReplaceArg(i int) string { return fmt.Sprintf(hookTemplateArg, strconv.Itoa(i)) } func ParseTemplate(hookTemplate string, cmd *cobra.Command) ([]string, error) { tmpl := template.New("").Funcs(commandFunctions) tmpl, err := tmpl.Parse(hookTemplate) if err != nil { return nil, err } b := bytes.Buffer{} err = tmpl.Execute(&b, cmd) if err != nil { return nil, err } return strings.Split(b.String(), "\n"), nil } var ErrHookTemplateParse = errors.New("failed to parse hook template") const ( hookTemplateCommandName = "{{.Name}}" hookTemplateFlagValue = `{{flag . "%s"}}` hookTemplateArg = "{{arg . %s}}" ) var commandFunctions = template.FuncMap{ "flag": getFlagValue, "arg": getArgValue, } func getFlagValue(cmd *cobra.Command, flag string) (string, error) { cmdFlag := cmd.Flag(flag) if cmdFlag == nil { return "", ErrHookTemplateParse } return cmdFlag.Value.String(), nil } func getArgValue(cmd *cobra.Command, i int) (string, error) { flags := cmd.Flags() if flags == nil { return "", ErrHookTemplateParse } return flags.Arg(i), nil }