Consul
Execute custom scripts with Consul Template plugins
For some use cases, it may be necessary to write a plugin that offloads work to another system. This is especially useful for things that may not fit in the "standard library" of Consul Template, but still need to be shared across multiple instances.
Consul Template plugins must have the following API:
$ NAME [INPUT...]
- NAME- the name of the plugin - this is also the name of the binary, either a full path or just the program name. It will be executed in a shell with the inherited- PATHso e.g. the plugin- catwill run the first executable- catthat is found on the- PATH.
- INPUT- input from the template. There will be one INPUT for every argument passed to the- pluginfunction. If the arguments contain whitespace, that whitespace will be passed as if the argument were quoted by the shell.
Important notes
- Plugins execute user-provided scripts and pass in potentially sensitive data from Consul or Vault. Nothing is validated or protected by Consul Template, so all necessary precautions and considerations should be made by template authors 
- Plugin output must be returned as a string on - stdout. Only- stdoutwill be parsed for output. Be sure to log all errors and debugging messages onto- stderrto avoid errors when Consul Template returns the value. Note that output to- stderrwill only be output if the plugin returns a non-zero exit code.
- Always - exit 0or Consul Template will assume the plugin failed to execute.
- Ensure the empty input case is handled correctly (see Multi-phase execution) 
- Data piped into the plugin is appended after any parameters given explicitly. For example, {{ "sample-data" | plugin "my-plugin" "some-parameter"}} - will callmy-plugin some-parameter sample-data`.
Examples
The following example plugin removes any JSON keys that start with an underscore and returns the JSON string:
func main() {
  arg := []byte(os.Args[1])
  var parsed map[string]interface{}
  if err := json.Unmarshal(arg, &parsed); err != nil {
    fmt.Fprintln(os.Stderr, fmt.Sprintf("err: %s", err))
    os.Exit(1)
  }
  for k, _ := range parsed {
    if string(k[0]) == "_" {
      delete(parsed, k)
    }
  }
  result, err := json.Marshal(parsed)
  if err != nil {
    fmt.Fprintln(os.Stderr, fmt.Sprintf("err: %s", err))
    os.Exit(1)
  }
  fmt.Fprintln(os.Stdout, fmt.Sprintf("%s", result))
  os.Exit(0)
}