github.1git.de/docker/cli@v26.1.3+incompatible/cli-plugins/hooks/template.go (about) 1 package hooks 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "strconv" 8 "strings" 9 "text/template" 10 11 "github.com/spf13/cobra" 12 ) 13 14 type HookType int 15 16 const ( 17 NextSteps = iota 18 ) 19 20 // HookMessage represents a plugin hook response. Plugins 21 // declaring support for CLI hooks need to print a json 22 // representation of this type when their hook subcommand 23 // is invoked. 24 type HookMessage struct { 25 Type HookType 26 Template string 27 } 28 29 // TemplateReplaceSubcommandName returns a hook template string 30 // that will be replaced by the CLI subcommand being executed 31 // 32 // Example: 33 // 34 // "you ran the subcommand: " + TemplateReplaceSubcommandName() 35 // 36 // when being executed after the command: 37 // `docker run --name "my-container" alpine` 38 // will result in the message: 39 // `you ran the subcommand: run` 40 func TemplateReplaceSubcommandName() string { 41 return hookTemplateCommandName 42 } 43 44 // TemplateReplaceFlagValue returns a hook template string 45 // that will be replaced by the flags value. 46 // 47 // Example: 48 // 49 // "you ran a container named: " + TemplateReplaceFlagValue("name") 50 // 51 // when being executed after the command: 52 // `docker run --name "my-container" alpine` 53 // will result in the message: 54 // `you ran a container named: my-container` 55 func TemplateReplaceFlagValue(flag string) string { 56 return fmt.Sprintf(hookTemplateFlagValue, flag) 57 } 58 59 // TemplateReplaceArg takes an index i and returns a hook 60 // template string that the CLI will replace the template with 61 // the ith argument, after processing the passed flags. 62 // 63 // Example: 64 // 65 // "run this image with `docker run " + TemplateReplaceArg(0) + "`" 66 // 67 // when being executed after the command: 68 // `docker pull alpine` 69 // will result in the message: 70 // "Run this image with `docker run alpine`" 71 func TemplateReplaceArg(i int) string { 72 return fmt.Sprintf(hookTemplateArg, strconv.Itoa(i)) 73 } 74 75 func ParseTemplate(hookTemplate string, cmd *cobra.Command) ([]string, error) { 76 tmpl := template.New("").Funcs(commandFunctions) 77 tmpl, err := tmpl.Parse(hookTemplate) 78 if err != nil { 79 return nil, err 80 } 81 b := bytes.Buffer{} 82 err = tmpl.Execute(&b, cmd) 83 if err != nil { 84 return nil, err 85 } 86 return strings.Split(b.String(), "\n"), nil 87 } 88 89 var ErrHookTemplateParse = errors.New("failed to parse hook template") 90 91 const ( 92 hookTemplateCommandName = "{{.Name}}" 93 hookTemplateFlagValue = `{{flag . "%s"}}` 94 hookTemplateArg = "{{arg . %s}}" 95 ) 96 97 var commandFunctions = template.FuncMap{ 98 "flag": getFlagValue, 99 "arg": getArgValue, 100 } 101 102 func getFlagValue(cmd *cobra.Command, flag string) (string, error) { 103 cmdFlag := cmd.Flag(flag) 104 if cmdFlag == nil { 105 return "", ErrHookTemplateParse 106 } 107 return cmdFlag.Value.String(), nil 108 } 109 110 func getArgValue(cmd *cobra.Command, i int) (string, error) { 111 flags := cmd.Flags() 112 if flags == nil { 113 return "", ErrHookTemplateParse 114 } 115 return flags.Arg(i), nil 116 }