summaryrefslogtreecommitdiff
path: root/plugins.go
diff options
context:
space:
mode:
authorDave Henderson <dhenderson@gmail.com>2022-05-28 12:51:53 -0400
committerDave Henderson <dhenderson@gmail.com>2022-05-28 13:15:01 -0400
commit4a5d32b4fbf89388e687bdf8758fbeae81267679 (patch)
treedb931a656ce0435a5ac2d8661d7a7aef78066104 /plugins.go
parentaac83f2f276e113ce46d6c0ff66d6d71ef2d70f8 (diff)
PluginFunc to create custom template functions
Signed-off-by: Dave Henderson <dhenderson@gmail.com>
Diffstat (limited to 'plugins.go')
-rw-r--r--plugins.go77
1 files changed, 59 insertions, 18 deletions
diff --git a/plugins.go b/plugins.go
index 3e6e1f04..b7349567 100644
--- a/plugins.go
+++ b/plugins.go
@@ -17,40 +17,81 @@ import (
"github.com/hairyhenderson/gomplate/v3/internal/config"
)
+// bindPlugins creates custom plugin functions for each plugin specified by
+// the config, and adds them to the given funcMap. Uses the configuration's
+// PluginTimeout as the default plugin Timeout. Errors if a function name is
+// duplicated.
func bindPlugins(ctx context.Context, cfg *config.Config, funcMap template.FuncMap) error {
for k, v := range cfg.Plugins {
+ if _, ok := funcMap[k]; ok {
+ return fmt.Errorf("function %q is already bound, and can not be overridden", k)
+ }
+
+ // default the timeout to the one in the config
timeout := cfg.PluginTimeout
if v.Timeout != 0 {
timeout = v.Timeout
}
- plugin := &plugin{
- ctx: ctx,
- name: k,
- path: v.Cmd,
- timeout: timeout,
- pipe: v.Pipe,
- stderr: cfg.Stderr,
- }
- if _, ok := funcMap[plugin.name]; ok {
- return fmt.Errorf("function %q is already bound, and can not be overridden", plugin.name)
- }
- funcMap[plugin.name] = plugin.run
+ funcMap[k] = PluginFunc(ctx, v.Cmd, PluginOpts{
+ Timeout: timeout,
+ Pipe: v.Pipe,
+ Stderr: cfg.Stderr,
+ })
}
+
return nil
}
+// PluginOpts are options for controlling plugin function execution
+type PluginOpts struct {
+ // Stderr can be set to redirect the plugin's stderr to a custom writer.
+ // Defaults to os.Stderr.
+ Stderr io.Writer
+
+ // Timeout is the maximum amount of time to wait for the plugin to complete.
+ // Defaults to 5 seconds.
+ Timeout time.Duration
+
+ // Pipe indicates whether the last argument should be piped to the plugin's
+ // stdin (true) or processed as a commandline argument (false)
+ Pipe bool
+}
+
+// PluginFunc creates a template function that runs an external process - either
+// a shell script or commandline executable.
+func PluginFunc(ctx context.Context, cmd string, opts PluginOpts) func(...interface{}) (interface{}, error) {
+ timeout := opts.Timeout
+ if timeout == 0 {
+ timeout = 5 * time.Second
+ }
+
+ stderr := opts.Stderr
+ if stderr == nil {
+ stderr = os.Stderr
+ }
+
+ plugin := &plugin{
+ ctx: ctx,
+ path: cmd,
+ timeout: timeout,
+ pipe: opts.Pipe,
+ stderr: stderr,
+ }
+
+ return plugin.run
+}
+
// plugin represents a custom function that binds to an external process to be executed
type plugin struct {
- ctx context.Context
- stderr io.Writer
- name, path string
- timeout time.Duration
- pipe bool
+ ctx context.Context
+ stderr io.Writer
+ path string
+ timeout time.Duration
+ pipe bool
}
// builds a command that's appropriate for running scripts
-// nolint: gosec
func (p *plugin) buildCommand(a []string) (name string, args []string) {
switch filepath.Ext(p.path) {
case ".ps1":