MCPcopy
hub / github.com/hashicorp/consul-template

github.com/hashicorp/consul-template @v0.42.0 sqlite

repository ↗ · DeepWiki ↗ · release v0.42.0 ↗
1,253 symbols 5,906 edges 158 files 652 documented · 52%
README

Consul Template

build ci Go Documentation

This project provides a convenient way to populate values from [Consul][consul] into the file system using the consul-template daemon.

The daemon consul-template queries a [Consul][consul], [Vault][vault], or [Nomad][nomad] cluster and updates any number of specified templates on the file system. As an added bonus, it can optionally run arbitrary commands when the update process completes. Please see the [examples folder][examples] for some scenarios where this functionality might prove useful.


The documentation in this README corresponds to the main branch of Consul Template. It may contain unreleased features or different APIs than the most recently released version.

Please see the Git tag that corresponds to your version of Consul Template for the proper documentation.


Table of Contents

Community Support

If you have questions about how consul-template works, its capabilities or anything other than a bug or feature request (use github's issue tracker for those), please see our community support resources.

Community portal: https://discuss.hashicorp.com/tags/c/consul/29/consul-template

Other resources: https://www.consul.io/community.html

Additionally, for issues and pull requests, we'll be using the :+1: reactions as a rough voting system to help gauge community priorities. So please add :+1: to any issue or pull request you'd like to see worked on. Thanks.

Installation

  1. Download a pre-compiled, released version from the [Consul Template releases page][releases].

  2. Extract the binary using unzip or tar.

  3. Move the binary into $PATH.

To compile from source, please see the instructions in the contributing section.

Quick Example

This short example assumes Consul is installed locally.

  1. Start a Consul cluster in dev mode:

shell $ consul agent -dev

  1. Author a template in.tpl to query the kv store:

liquid {{ key "foo" }}

  1. Start Consul Template:

shell $ consul-template -template "in.tpl:out.txt" -once

  1. Write data to the key in Consul:

shell $ consul kv put foo bar

  1. Observe Consul Template has written the file out.txt:

shell $ cat out.txt bar

For more examples and use cases, please see the [examples folder][examples] in this repository.

Learn Guides

In addition to these [examples][examples], HashiCorp has published guides and official documentation to help walk through a few common use cases for Consul Template. * Consul KV * Consul Catalog * Vault Agent Templates * Vault Secrets * Nomad Native Service Discovery

Configuration

Configuration documentation has been moved to docs/configuration.md.

Reload Configuration and Templates

While there are multiple ways to run Consul Template, the most common pattern is to run Consul Template as a system service. When Consul Template first starts, it reads any configuration files and templates from disk and loads them into memory. From that point forward, changes to the files on disk do not propagate to running process without a reload.

The reason for this behavior is simple and aligns with other tools like haproxy. A user may want to perform pre-flight validation checks on the configuration or templates before loading them into the process. Additionally, a user may want to update configuration and templates simultaneously. Having Consul Template automatically watch and reload those files on changes is both operationally dangerous and against some of the paradigms of modern infrastructure. Instead, Consul Template listens for the SIGHUP syscall to trigger a configuration reload. If you update configuration or templates, simply send HUP to the running Consul Template process and Consul Template will reload all the configurations and templates from disk.

Templating Language

Templating Language documentation has been moved to docs/templating-language.md.

Caveats

Docker Image Use

The Alpine Docker image is configured to support an external volume to render shared templates to. If mounted you will need to make sure that the consul-template user in the docker image has write permissions to the directory. Also if you build your own image using these you need to be sure you have the permissions correct.

The consul-template user in docker has a UID of 100 and a GID of 1000.

This effects the in image directories /consul-template/config, used to add configuration when using this as a parent image, and /consul-template/data, exported as a VOLUME as a location to render shared results.

Previously the image initially ran as root in order to ensure the permissions allowed it. But this ran against docker best practices and security policies.

If you build your own image based on ours you can override these values with --build-arg parameters.

Dots in Service Names

Using dots . in service names will conflict with the use of dots for TAG delineation in the template. Dots already interfere with using DNS for service names, so we recommend avoiding dots wherever possible.

Termination on Error

By default Consul Template is highly fault-tolerant. If Consul is unreachable or a template changes, Consul Template will happily continue running. The only exception to this rule is if the optional command exits non-zero. In this case, Consul Template will also exit non-zero. The reason for this decision is so the user can easily configure something like Upstart or God to manage Consul Template as a service.

If you want Consul Template to continue watching for changes, even if the optional command argument fails, you can append || true to your command. Note that || is a "shell-ism", not a built-in function. You will also need to run your command under a shell:

$ consul-template \
  -template "in.ctmpl:out.file:/bin/bash -c 'service nginx restart || true'"

In this example, even if the Nginx restart command returns non-zero, the overall function will still return an OK exit code; Consul Template will continue to run as a service. Additionally, if you have complex logic for restarting your service, you can intelligently choose when you want Consul Template to exit and when you want it to continue to watch for changes. For these types of complex scripts, we recommend using a custom sh or bash script instead of putting the logic directly in the consul-template command or configuration file.

Commands

Environment

The current processes environment is used when executing commands with the following additional environment variables:

  • CONSUL_HTTP_ADDR
  • CONSUL_HTTP_TOKEN
  • CONSUL_HTTP_TOKEN_FILE
  • CONSUL_HTTP_AUTH
  • CONSUL_HTTP_SSL
  • CONSUL_HTTP_SSL_VERIFY
  • NOMAD_ADDR
  • NOMAD_NAMESPACE
  • NOMAD_TOKEN

These environment variables are exported with their current values when the command executes. Other Consul tooling reads these environment variables, providing smooth integration with other Consul tools (like consul maint or consul lock). Additionally, exposing these environment variables gives power users the ability to further customize their command script.

Multiple Commands

The command configured for running on template rendering must take one of two forms.

The first is as a list of the command and arguments split at spaces. The command can use an absolute path or be found on the execution environment's PATH and must be the first item in the list. This form allows for single or multi-word commands that can be executed directly with a system call. For example...

command = ["echo", "hello"] command = ["/opt/foo-package/bin/run-foo"] command = ["foo"]

Note that if you give a single command without the list denoting square brackets ([]) it is converted into a list with a single argument.

This: command = "foo" is equivalent to: command = ["foo"]

The second form is as a single quoted command using system shell features. This form requires a shell named sh be on the executable search path (eg. PATH on *nix). This is the standard on all *nix systems and should work out of the box on those systems. This won't work on, for example, Docker images with only the executable and without a minimal system like Alpine. Using this form you can join multiple commands with logical operators, && and ||, use pipelines with |, conditionals, etc. Note that the shell sh is normally /bin/sh on *nix systems and is either a POSIX shell or a shell run in POSIX compatible mode, so it is best to stick to POSIX shell syntax in this command. For example..

command = "/opt/foo && /opt/bar"

command = "if /opt/foo ; then /opt/bar ; fi"

Using this method you can run as many shell commands as you need with whatever logic you need. Though it is suggested that if it gets too long you might want to wrap it in a shell script, deploy and run that.

Shell Commands and Exec Mode

Using the system shell based command has one additional caveat when used for the Exec mode process (the managed, executed process to which it will propagate signals). That is to get signals to work correctly means not only does anything the shell runs need to handle signals, but the shell itself needs to handle them. This needs to be managed by you as shells will exit upon receiving most signals.

A common example of this would be wanting the SIGHUP signal to trigger a reload of the underlying process and to be ignored by the shell process. To get this you have 2 options, you can use trap to ignore the signal or you can use exec to replace the shell with another process.

To use trap to ignore the signal, you call trap to catch the signal in the shell with no action. For example if you had an underlying nginx process you wanted to run with a shell command and have the shell ignore it you'd do..

command = "trap '' HUP; /usr/sbin/nginx -c /etc/nginx/nginx.conf"

The trap '' HUP; bit is enough to get the shell to ignore the HUP signal. If you left off the trap command nginx would reload but the shell command would exit but leave the nginx still running, not unmanaged.

Alternatively using exec will replace the shell's process with a sub-process, keeping the same PID and process grouping (allowing the sub-process to be managed). This is simpler, but a bit less flexible than trap, and looks like..

command = "exec /usr/sbin/nginx -c /etc/nginx/nginx.conf"

Where the nginx process would replace the enclosing shell process to be managed by consul-template, receiving the Signals directly. Basically exec eliminates the shell from the equation.

See your shell's documentation on trap and/or exec for more details on this.

Multi-phase Execution

Consul Template does an n-pass evaluation of templates, accumulating dependencies on each pass. This is required due to nested dependencies, such as:

{{ range services }}
{{ range service .Name }}
  {{ .Address }}
{{ end }}{{ end }}

During the first pass, Consul Template does not know any of the services in Consul, so it has to perform a query. When those results are returned, the inner-loop is then evaluated with that result, potentially creating more queries and watches.

Because of this implementation, template functions need a default value that is an acceptable parameter to a range function (or similar), but does not actually execute the inner loop (which would cause a pani

Extension points exported contracts — how you extend this code

Dependency (Interface)
Dependency is an interface for a dependency that Consul Template is capable of watching. [32 implementers]
dependency/dependency.go
TransportDialer (Interface)
TransportDialer is an interface that allows passing a custom dialer function to an HTTP client's transport config [1 implementers]
dependency/client_set.go
ErrExitable (Interface)
ErrExitable is an interface that defines an integer ExitStatus() function. [1 implementers]
manager/errors.go
Reader (FuncType)
Reader is an interface that is implemented by os.OpenFile. The Config.ReaderFunc requires this interface so that applica
config/config.go
RetryFunc (FuncType)
RetryFunc is the signature of a function that supports retries.
config/retry.go
Renderer (FuncType)
(no doc)
renderer/renderer.go
RetryFunc (FuncType)
(no doc)
watch/watcher.go

Core symbols most depended-on inside this repo

String
called by 869
config/convert.go
Bool
called by 512
config/convert.go
Fatal
called by 490
test/helpers.go
TimeDuration
called by 489
config/convert.go
Errorf
called by 476
test/helpers.go
Run
called by 261
cli.go
AppendTenancyInfo
called by 237
test/tenancy_helper.go
Int
called by 166
config/convert.go

Shape

Function 610
Method 475
Struct 135
TypeAlias 19
FuncType 8
Interface 6

Languages

Go100%

Modules by API surface

template/funcs.go91 symbols
manager/runner.go37 symbols
watch/dependencies_test.go33 symbols
dependency/dependency_test.go26 symbols
config/convert.go26 symbols
child/child_test.go24 symbols
config/convert_test.go23 symbols
dependency/nomad_var_structs.go21 symbols
child/child.go20 symbols
test/helpers.go19 symbols
dependency/client_set.go19 symbols
dependency/dependency.go18 symbols

Used by 2 indexed graphs manifest dependencies, hub-wide

Dependencies from manifests, versioned

dario.cat/mergov1.0.2 · 1×
github.com/Masterminds/goutilsv1.1.1 · 1×
github.com/Masterminds/semver/v3v3.3.0 · 1×
github.com/armon/go-metricsv0.4.1 · 1×
github.com/davecgh/go-spewv1.1.2-0.20180830191 · 1×
github.com/go-jose/go-jose/v4v4.1.4 · 1×
github.com/go-viper/mapstructure/v2v2.5.0 · 1×

For agents

$ claude mcp add consul-template \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact