Consul Template parses files authored in the Go Template format. If you are not familiar with the syntax, please read Go's documentation and examples. In addition to the Go-provided template functions, Consul Template provides the following functions:
- API Functions
- Scratch
- Helper Functions
- base64Decode
- base64Encode
- base64URLDecode
- base64URLEncode
- byKey
- byTag
- byMeta
- contains
- containsAll
- containsAny
- containsNone
- containsNotAll
- env
- envOrDefault
- executeTemplate
- explode
- explodeMap
- indent
- in
- loop
- join
- mergeMap
- mergeMapWithOverride
- trimSpace
- parseBool
- parseFloat
- parseInt
- parseJSON
- parseUint
- parseYAML
- plugin
- regexMatch
- regexReplaceAll
- replaceAll
- sha256Hex
- md5sum
- split
- timestamp
- toJSON
- toJSONPretty
- toUnescapedJSON
- toUnescapedJSONPretty
- toLower
- toTitle
- toTOML
- toUpper
- toYAML
- sockaddr
- writeToFile
- Math Functions
- Debugging Functions
API functions interact with remote API calls, communicating with external services like Consul and Vault.
Query Consul for the leaf certificate representing a single service.
{{ caLeaf "<NAME>" }}
For example:
{{ with caLeaf "proxy" }}{{ .CertPEM }}{{ end }}
renders
-----BEGIN CERTIFICATE-----
MIICizCCAjGgAwIBAgIBCDAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtDb25zdWwg
...
lXcQzfKlIYeFWvcAv4cA4W258gTtqaFRDRJ2i720eQ==
-----END CERTIFICATE-----
The two most useful fields are .CertPEM
and .PrivateKeyPEM
. For a complete
list of available fields, see consul's documentation on
LeafCert.
Query Consul for all connect trusted certificate authority (CA) root certificates.
{{ caRoots }}
For example:
{{ range caRoots }}{{ .RootCertPEM }}{{ end }}
renders
-----BEGIN CERTIFICATE-----
MIICWDCCAf+gAwIBAgIBBzAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtDb25zdWwg
...
bcA+Su3r8qSRppTlc6D0UOYOWc1ykQKQOK7mIg==
-----END CERTIFICATE-----
The most useful field is .RootCertPEM
. For a complete list of available
fields, see consul's documentation on
CARootList.
Query Consul for connect-capable services based on their health.
{{ connect "<TAG>.<NAME>@<DATACENTER>~<NEAR>|<FILTER>" }}
Syntax is exactly the same as for the service function below.
{{ range connect "web" }}
server {{ .Name }} {{ .Address }}:{{ .Port }}{{ end }}
renders the IP addresses of all healthy nodes with a logical connect-capable service named "web":
server web01 10.5.2.45:21000
server web02 10.2.6.61:21000
Query Consul for all datacenters in its catalog.
{{ datacenters }}
For example:
{{ range datacenters }}
{{ . }}{{ end }}
renders
dc1
dc2
An optional boolean can be specified which instructs Consul Template to ignore datacenters which are inaccessible or do not have a current leader. Enabling this option requires an O(N+1) operation and therefore is not recommended in environments where performance is a factor.
// Ignores datacenters which are inaccessible
{{ datacenters true }}
Read and output the contents of a local file on disk. If the file cannot be read, an error will occur. When the file changes, Consul Template will pick up the change and re-render the template.
{{ file "<PATH>" }}
For example:
{{ file "/path/to/my/file" }}
renders
file contents
This does not process nested templates. See
executeTemplate
for a way to render nested templates.
Query Consul for the value at the given key path. If the key does not
exist, Consul Template will block rendering until the key is present. To avoid
blocking, use keyOrDefault
or keyExists
.
{{ key "<PATH>@<DATACENTER>" }}
The <DATACENTER>
attribute is optional; if omitted, the local datacenter is
used.
For example:
{{ key "service/redis/maxconns" }}
renders
15
Query Consul for the value at the given key path. If the key exists,
this will return true, false otherwise. Unlike key
, this function will not
block if the key does not exist. This is useful for controlling flow.
{{ keyExists "<PATH>@<DATACENTER>" }}
The <DATACENTER>
attribute is optional; if omitted, the local datacenter is
used.
For example:
{{ if keyExists "app/beta_active" }}
# ...
{{ else }}
# ...
{{ end }}
Query Consul for the value at the given key path. If the key does not
exist, the default value will be used instead. Unlike key
, this function will
not block if the key does not exist.
{{ keyOrDefault "<PATH>@<DATACENTER>" "<DEFAULT>" }}
The <DATACENTER>
attribute is optional; if omitted, the local datacenter is
used.
For example:
{{ keyOrDefault "service/redis/maxconns" "5" }}
renders
5
Note that Consul Template uses a multi-phase
execution. During the first phase of evaluation, Consul
Template will have no data from Consul and thus will always fall back to the
default value. Subsequent reads from Consul will pull in the real value from
Consul (if the key exists) on the next template pass. This is important because
it means that Consul Template will never "block" the rendering of a template due
to a missing key from a keyOrDefault
. Even if the key exists,
if Consul has not yet returned data for the key, the default value will be used
instead.
Query Consul for all top-level kv pairs at the given key path.
{{ ls "<PATH>@<DATACENTER>" }}
The <DATACENTER>
attribute is optional; if omitted, the local datacenter is
used.
For example:
{{ range ls "service/redis" }}
{{ .Key }}:{{ .Value }}{{ end }}
renders
maxconns:15
minconns:5
Same as ls
, but refuse to render template, if the KV prefix query return blank/empty data.
This is especially useful, for rendering mission critical files, that are being populated by consul-template.
For example:
/root/.ssh/authorized_keys
/etc/sysconfig/iptables
Using safeLs
on empty prefixes will result in template output not being rendered at all.
To learn how safeLs
was born see CT-1131 C-3975 and CR-82.
Query Consul for a node in the catalog.
{{node "<NAME>@<DATACENTER>"}}
The <NAME>
attribute is optional; if omitted, the local agent node is used.
The <DATACENTER>
attribute is optional; if omitted, the local datacenter is
used.
For example:
{{ with node }}
{{ .Node.Address }}{{ end }}
renders
10.5.2.6
To query a different node:
{{ with node "node1@dc2" }}
{{ .Node.Address }}{{ end }}
renders
10.4.2.6
To access map data such as TaggedAddresses
or Meta
, use
Go's text/template map indexing.
Query Consul for all nodes in the catalog.
{{ nodes "@<DATACENTER>~<NEAR>" }}
The <DATACENTER>
attribute is optional; if omitted, the local datacenter is
used.
The <NEAR>
attribute is optional; if omitted, results are specified in lexical
order. If provided a node name, results are ordered by shortest round-trip time
to the provided node. If provided _agent
, results are ordered by shortest
round-trip time to the local agent.
For example:
{{ range nodes }}
{{ .Address }}{{ end }}
renders
10.4.2.13
10.46.2.5
To query a different data center and order by shortest trip time to ourselves:
{{ range nodes "@dc2~_agent" }}
{{ .Address }}{{ end }}
To access map data such as TaggedAddresses
or Meta
, use
Go's text/template map indexing.
Query Vault for the secret at the given path.
{{ secret "<PATH>" "<DATA>" }}
The <DATA>
attribute is optional; if omitted, the request will be a vault read
(HTTP GET) request. If provided, the request will be a vault write
(HTTP
PUT/POST) request.
For example:
{{ with secret "secret/passwords" }}
{{ .Data.wifi }}{{ end }}
renders
FORWARDSoneword
To access a versioned secret value (for the K/V version 2 backend):
{{ with secret "secret/passwords?version=1" }}
{{ .Data.data.wifi }}{{ end }}
When omitting the ?version
parameter, the latest version of the secret will be
fetched. Note the nested .Data.data
syntax when referencing the secret value.
For more information about using the K/V v2 backend, see the
Vault Documentation.
When using Vault versions 0.10.0/0.10.1, the secret path will have to be prefixed
with "data", i.e. secret/data/passwords
for the example above. This is not
necessary for Vault versions after 0.10.1, as consul-template will detect the KV
backend version being used. The version 2 KV backend did not exist prior to 0.10.0,
so these are the only affected versions.
An example using write to generate PKI certificates:
{{ with secret "pki/issue/my-domain-dot-com" "common_name=foo.example.com" }}
{{ .Data.certificate }}{{ end }}
An example of adding (writing) a derived Vault token while reading it back out for use in a configuration file.
{{with secret "/auth/token/create" "policies=policy_1" "no_default_policy=true"}}
{{.Auth.ClientToken}}{{ end }}
The parameters must be key=value
pairs, and each pair must be its own argument
to the function:
Please always consider the security implications of having the contents of a secret in plain-text on disk. If an attacker is able to get access to the file, they will have access to plain-text secrets.
Please note that Vault does not support blocking queries. As a result, Consul Template will not immediately reload in the event a secret is changed as it does with Consul's key-value store. Consul Template will renew the secret with Vault's Renewer API. The Renew API tries to use most of the time the secret is good, renewing at around 90% of the lease time (as set by Vault).
Also consider enabling error_on_missing_key
when working with templates that
will interact with Vault. By default, Consul Template uses Go's templating
language. When accessing a struct field or map key that does not exist, it
defaults to printing <no value>
. This may not be the desired behavior,
especially when working with passwords or other data. As such, it is recommended
you set:
template {
error_on_missing_key = true
}
You can also guard against empty values using if
or with
blocks.
{{ with secret "secret/foo"}}
{{ if .Data.password }}
password = "{{ .Data.password }}"
{{ end }}
{{ end }}
Query Vault for the list of secrets at the given path. Not all endpoints support listing.
{{ secrets "<PATH>" }}
For example:
{{ range secrets "secret/" }}
{{ . }}{{ end }}
renders
bar
foo
zip
To iterate and list over every secret in the generic secret backend in Vault:
{{ range secrets "secret/" }}
{{ with secret (printf "secret/%s" .) }}{{ range $k, $v := .Data }}
{{ $k }}: {{ $v }}
{{ end }}{{ end }}{{ end }}
.Data
should be replaced with .Data.data
for KV-V2 secrets engines.
You should probably never do this.
Please also note that Vault does not support
blocking queries. To understand the implications, please read the note at the
end of the secret
function.
Query Consul for services based on their health.
{{ service "<TAG>.<NAME>@<DATACENTER>~<NEAR>|<FILTER>" }}
The <TAG>
attribute is optional; if omitted, all nodes will be queried.
The <DATACENTER>
attribute is optional; if omitted, the local datacenter is
used.
The <NEAR>
attribute is optional; if omitted, results are specified in lexical
order. If provided a node name, results are ordered by shortest round-trip time
to the provided node. If provided _agent
, results are ordered by shortest
round-trip time to the local agent.
The <FILTER>
attribute is optional; if omitted, only healthy services are
returned. Providing a filter allows for client-side filtering of services.
For example:
{{ range service tag1.web@east-aws }}
server {{ .Name }} {{ .Address }}:{{ .Port }}{{ end }}
The example above is querying Consul for healthy "web" services, in the "east-aws" data center. The tag and data center attributes are optional. To query all nodes of the "web" service (regardless of tag) for the current data center:
{{ range service "web" }}
server {{ .Name }} {{ .Address }}:{{ .Port }}{{ end }}
renders the IP addresses of all healthy nodes with a logical service named "web":
server web01 10.5.2.45:2492
server web02 10.2.6.61:2904
To access map data such as NodeTaggedAddresses
, ServiceTaggedAddresses
or
NodeMeta
, use Go's text/template map indexing.
{{ range service "web" }}
{{ with .ServiceTaggedAddresses.wan }}
http://{{ .Address }}:{{ .Port }}
{{ end }}
{{ end }}
By default only healthy services are returned. To list all services, pass the "any" filter:
{{ service "web|any" }}
This will return all services registered to the agent, regardless of their status.
To filter services by a specific set of healths, specify a comma-separated list of health statuses:
{{ service "web|passing,warning" }}
This will returns services which are deemed "passing" or "warning" according to their node and service-level checks defined in Consul. Please note that the comma implies an "or", not an "and".
Note: Due to the use of dot .
to delimit TAG, the service
command will
not recognize service names containing dots.
Note: There is an architectural difference between the following:
{{ service "web" }}
{{ service "web|passing" }}
The former will return all services which Consul considers "healthy" and passing. The latter will return all services registered with the Consul agent and perform client-side filtering. As a general rule, do not use the "passing" argument alone if you want only healthy services - simply omit the second argument instead.
Query Consul for all services in the catalog.
{{ services "@<DATACENTER>" }}
The <DATACENTER>
attribute is optional; if omitted, the local datacenter is
used.
For example:
{{ range services }}
{{ .Name }}: {{ .Tags | join "," }}{{ end }}
renders
node01 tag1,tag2,tag3
Query Consul for all kv pairs at the given key path.
{{ tree "<PATH>@<DATACENTER>" }}
The <DATACENTER>
attribute is optional; if omitted, the local datacenter is
used.
For example:
{{ range tree "service/redis" }}
{{ .Key }}:{{ .Value }}{{ end }}
renders
minconns 2
maxconns 12
nested/config/value "value"
Unlike ls
, tree
returns all keys under the prefix, just like the Unix
tree
command.
Same as tree
, but refuse to render template, if the KV prefix query return blank/empty data.
This is especially useful, for rendering mission critical files, that are being populated by consul-template.
For example:
/root/.ssh/authorized_keys
/etc/sysconfig/iptables
Using safeTree
on empty prefixes will result in template output not being rendered at all.
To learn how safeTree
was born see CT-1131 C-3975 and CR-82.
The scratchpad (or "scratch" for short) is available within the context of a template to store temporary data or computations. Scratch data is not shared between templates and is not cached between invocations.
Returns a boolean if data exists in the scratchpad at the named key. Even if the
data at that key is nil
, this still returns true.
{{ scratch.Key "foo" }}
Returns the value in the scratchpad at the named key. If the data does not
exist, this will return nil
.
{{ scratch.Get "foo" }}
Saves the given value at the given key. If data already exists at that key, it is overwritten.
{{ scratch.Set "foo" "bar" }}
This behaves exactly the same as Set
, but does not overwrite if the value
already exists.
{{ scratch.SetX "foo" "bar" }}
Saves a value in a named key in the map. If data already exists at that key, it is overwritten.
{{ scratch.MapSet "vars" "foo" "bar" }}
This behaves exactly the same as MapSet
, but does not overwrite if the value
already exists.
{{ scratch.MapSetX "vars" "foo" "bar" }}
Returns a sorted list (by key) of all values in the named map.
{{ scratch.MapValues "vars" }}
Unlike API functions, helper functions do not query remote services. These functions are useful for parsing data, formatting data, performing math, etc.
Accepts a base64-encoded string and returns the decoded result, or an error if the given string is not a valid base64 string.
{{ base64Decode "aGVsbG8=" }}
renders
hello
Accepts a string and returns a base64-encoded string.
{{ base64Encode "hello" }}
renders
aGVsbG8=
Accepts a base64-encoded URL-safe string and returns the decoded result, or an error if the given string is not a valid base64 URL-safe string.
{{ base64URLDecode "aGVsbG8=" }}
renders
hello
Accepts a string and returns a base-64 encoded URL-safe string.
{{ base64Encode "hello" }}
renders
aGVsbG8=
Accepts a list of pairs returned from a tree
call and creates a map that groups pairs by their top-level directory.
For example:
groups/elasticsearch/es1
groups/elasticsearch/es2
groups/elasticsearch/es3
services/elasticsearch/check_elasticsearch
services/elasticsearch/check_indexes
with the following template
{{ range $key, $pairs := tree "groups" | byKey }}{{ $key }}:
{{ range $pair := $pairs }} {{ .Key }}={{ .Value }}
{{ end }}{{ end }}
renders
elasticsearch:
es1=1
es2=1
es3=1
Note that the top-most key is stripped from the Key value. Keys that have no prefix after stripping are removed from the list.
The resulting pairs are keyed as a map, so it is possible to look up a single value by key:
{{ $weights := tree "weights" }}
{{ range service "release.web" }}
{{ $weight := or (index $weights .Node) 100 }}
server {{ .Node }} {{ .Address }}:{{ .Port }} weight {{ $weight }}{{ end }}
Takes the list of services returned by the service
or
services
function and creates a map that groups services by tag.
{{ range $tag, $services := service "web" | byTag }}{{ $tag }}
{{ range $services }} server {{ .Name }} {{ .Address }}:{{ .Port }}
{{ end }}{{ end }}
Takes a list of services returned by service
and returns a map
that groups services by ServiceMeta values. Multiple service meta keys can be
passed as a comma separated string. |int
can be added to a meta key to
convert numbers from service meta values to padded numbers in printf "%05d" % value
format (useful for sorting as Go Template sorts maps by keys).
Example:
If we have the following services registered in Consul:
{
"Services": [
{
"ID": "redis-dev-1",
"Name": "redis",
"ServiceMeta": {
"environment": "dev",
"shard_number": "1"
},
...
},
{
"ID": "redis-prod-1",
"Name": "redis",
"ServiceMeta": {
"environment": "prod",
"shard_number": "1"
},
...
},
{
"ID": "redis-prod-2",
"Name": "redis",
"ServiceMeta": {
"environment": "prod",
"shard_number": "2"
},
...
}
]
}
{{ service "redis|any" | byMeta "environment,shard_number|int" | toJSON }}
The code above will produce a map of services grouped by meta:
{
"dev_00001": [
{
"ID": "redis-dev-1",
...
}
],
"prod_00001": [
{
"ID": "redis-prod-1",
...
}
],
"prod_00002": [
{
"ID": "redis-prod-2",
...
}
]
}
Determines if a needle is within an iterable element.
{{ if .Tags | contains "production" }}
# ...
{{ end }}
Returns true
if all needles are within an iterable element, or false
otherwise. Returns true
if the list of needles is empty.
{{ if containsAll $requiredTags .Tags }}
# ...
{{ end }}
Returns true
if any needle is within an iterable element, or false
otherwise. Returns false
if the list of needles is empty.
{{ if containsAny $acceptableTags .Tags }}
# ...
{{ end }}
Returns true
if no needles are within an iterable element, or false
otherwise. Returns true
if the list of needles is empty.
{{ if containsNone $forbiddenTags .Tags }}
# ...
{{ end }}
Returns true
if some needle is not within an iterable element, or false
otherwise. Returns false
if the list of needles is empty.
{{ if containsNotAll $excludingTags .Tags }}
# ...
{{ end }}
Reads the given environment variable accessible to the current process.
{{ env "CLUSTER_ID" }}
This function can be chained to manipulate the output:
{{ env "CLUSTER_ID" | toLower }}
Reads the given environment variable and if it does not exist or is blank use a default value, ex 12345
.
{{ or (env "CLUSTER_ID") "12345" }}
Reads the given environment variable accessible to the current process. If the environment variable is found, the value of that variable will be used. This includes empty values. Otherwise, the default will be used instead.
{{ envOrDefault "CLUSTER_NAME" "Default_Cluster" }}
This function can be chained to manipulate the output:
{{ envOrDefault "CLUSTER_NAME" "Default_Cluster" | toLower }}
If you need the semantics of using the default when the environment has the value but it's empty, you can use normal env
with or
. This leverages the fact that go templates interpret the empty string ("") as false.
{{ or (env "TIMEOUT_CONNECT") "5s" }}
Executes and returns a defined template.
{{ define "custom" }}my custom template{{ end }}
This is my other template:
{{ executeTemplate "custom" }}
And I can call it multiple times:
{{ executeTemplate "custom" }}
Even with a new context:
{{ executeTemplate "custom" 42 }}
Or save it to a variable:
{{ $var := executeTemplate "custom" }}
Takes the result from a tree
or ls
call and converts it into a deeply-nested
map for parsing/traversing.
{{ tree "config" | explode }}
Note: You will lose any metadata about the key-pair after it has been exploded. You can also access deeply nested values:
{{ with tree "config" | explode }}
{{ .a.b.c }}{{ end }}
You will need to have a reasonable format about your data in Consul. Please see Go's text/template package for more information.
Takes the value of a map and converts it into a deeply-nested map for parsing/traversing,
using the same logic as explode
.
{{ scratch.MapSet "example", "foo/bar", "a" }}
{{ scratch.MapSet "example", "foo/baz", "b" }}
{{ scratch.Get "example" | explodeMap | toYAML }}
Indents a block of text by prefixing N number of spaces per line.
{{ tree "foo" | explode | toYAML | indent 4 }}
Determines if a needle is within an iterable element.
{{ if in .Tags "production" }}
# ...
{{ end }}
Accepts varying parameters and differs its behavior based on those parameters.
If loop
is given one integer, it will return a goroutine that begins at zero
and loops up to but not including the given integer:
{{ range loop 5 }}
# Comment{{end}}
If given two integers, this function will return a goroutine that begins at the first integer and loops up to but not including the second integer:
{{ range $i := loop 5 8 }}
stanza-{{ $i }}{{ end }}
which would render:
stanza-5
stanza-6
stanza-7
Note: It is not possible to get the index and the element since the function returns a goroutine, not a slice. In other words, the following is not valid:
# Will NOT work!
{{ range $i, $e := loop 5 8 }}
# ...{{ end }}
Takes the given list of strings as a pipe and joins them on the provided string:
{{ $items | join "," }}
Takes the result from explode
and an exploded argument then merges it both maps. The argument's source will not be overridden by piped map.
{{ $base := tree "base" | explode }}
{{ $overrides := tree "overrides" | explode | mergeMap $base}}
{{ with $overrides }}
{{ .a.b.c }}{{ end }}
Takes the result from explode
and an exploded argument then merges it both maps. The argument's source will be overridden by piped map.
{{ $base := tree "base" | explode }}
{{ $overrides := tree "overrides" | explode | mergeMapWithOverride $base}}
{{ with $overrides }}
{{ .a.b.c }}{{ end }}
Takes the provided input and trims all whitespace, tabs and newlines:
{{ file "/etc/ec2_version" | trimSpace }}
Takes the given string and parses it as a boolean:
{{ "true" | parseBool }}
This can be combined with a key and a conditional check, for example:
{{ if key "feature/enabled" | parseBool }}{{ end }}
Takes the given string and parses it as a base-10 float64:
{{ "1.2" | parseFloat }}
Takes the given string and parses it as a base-10 int64:
{{ "1" | parseInt }}
This can be combined with other helpers, for example:
{{ range $i := loop key "config/pool_size" | parseInt }}
# ...{{ end }}
Takes the given input (usually the value from a key) and parses the result as JSON:
{{ with $d := key "user/info" | parseJSON }}{{ $d.name }}{{ end }}
Note: Consul Template evaluates the template multiple times, and on the first evaluation the value of the key will be empty (because no data has been loaded yet). This means that templates must guard against empty responses.
Takes the given string and parses it as a base-10 int64:
{{ "1" | parseUint }}
Takes the given input (usually the value from a key) and parses the result as YAML:
{{ with $d := key "user/info" | parseYAML }}{{ $d.name }}{{ end }}
Note: The same caveats that apply to parseJSON
apply to parseYAML
.
Takes the name of a plugin and optional payload and executes a Consul Template plugin.
{{ plugin "my-plugin" }}
The plugin can take an arbitrary number of string arguments, and can be the target of a pipeline that produces strings as well. This is most commonly combined with a JSON filter for customization:
{{ tree "foo" | explode | toJSON | plugin "my-plugin" }}
Please see the plugins section for more information about plugins.
Takes the argument as a regular expression and will return true
if it matches
on the given string, or false
otherwise.
{{ if "foo.bar" | regexMatch "foo([.a-z]+)" }}
# ...
{{ else }}
# ...
{{ end }}
Takes the argument as a regular expression and replaces all occurrences of the regex with the given string. As in go, you can use variables like $1 to refer to subexpressions in the replacement string.
{{ "foo.bar" | regexReplaceAll "foo([.a-z]+)" "$1" }}
Takes the argument as a string and replaces all occurrences of the given string with the given string.
{{ "foo.bar" | replaceAll "." "_" }}
This function can be chained with other functions as well:
{{ service "web" }}{{ .Name | replaceAll ":" "_" }}{{ end }}
Takes the argument as a string and compute the sha256_hex value
{{ "bladibla" | sha256Hex }}
Takes a string input as an argument, and returns the hex-encoded md5 hash of the input.
{{ "myString" | md5 }}
Splits the given string on the provided separator:
{{ "foo\nbar\n" | split "\n" }}
This can be combined with chained and piped with other functions:
{{ key "foo" | toUpper | split "\n" | join "," }}
Returns the current timestamp as a string (UTC). If no arguments are given, the result is the current RFC3339 timestamp:
{{ timestamp }} // e.g. 1970-01-01T00:00:00Z
If the optional parameter is given, it is used to format the timestamp. The magic reference date Mon Jan 2 15:04:05 -0700 MST 2006 can be used to format the date as required:
{{ timestamp "2006-01-02" }} // e.g. 1970-01-01
See Go's time.Format
for more
information.
As a special case, if the optional parameter is "unix"
, the unix timestamp in
seconds is returned as a string.
{{ timestamp "unix" }} // e.g. 0
Takes the result from a tree
or ls
call and converts it into a JSON object.
{{ tree "config" | explode | toJSON }}
renders
{"admin":{"port":"1234"},"maxconns":"5","minconns":"2"}
Note: Consul stores all KV data as strings. Thus true is "true", 1 is "1", etc.
Takes the result from a tree
or ls
call and converts it into a
pretty-printed JSON object, indented by two spaces.
{{ tree "config" | explode | toJSONPretty }}
renders
{
"admin": {
"port": "1234"
},
"maxconns": "5",
"minconns": "2"
}
Note: Consul stores all KV data as strings. Thus true is "true", 1 is "1", etc.
Takes the result from a tree
or ls
call and converts it into a JSON object without HTML escaping. This function comes in handy when working with db connection strings or URIs containing query parameters.
{{ tree "config" | explode | toUnescapedJSON }}
renders
{"admin":{"port":"1234"},"maxconns":"5","minconns":"2", "queryparams": "a?b=c&d=e"}
Takes the result from a tree
or ls
call and converts it into a
pretty-printed JSON object without HTML escaping, indented by two spaces.
{{ tree "config" | explode | toUnescapedJSONPretty }}
renders
{
"admin": {
"port": "1234"
},
"maxconns": "5",
"minconns": "2",
"queryparams": "a?b=c&d=e"
}
Takes the argument as a string and converts it to lowercase.
{{ key "user/name" | toLower }}
See Go's strings.ToLower
for more
information.
Takes the argument as a string and converts it to titlecase.
{{ key "user/name" | toTitle }}
See Go's strings.Title
for more
information.
Takes the result from a tree
or ls
call and converts it into a TOML object.
{{ tree "config" | explode | toTOML }}
renders
maxconns = "5"
minconns = "2"
[admin]
port = "1134"
Note: Consul stores all KV data as strings. Thus true is "true"
, 1 is "1"
, etc.
Takes the argument as a string and converts it to uppercase.
{{ key "user/name" | toUpper }}
See Go's strings.ToUpper
for more
information.
Takes the result from a tree
or ls
call and converts it into a
pretty-printed YAML object, indented by two spaces.
{{ tree "config" | explode | toYAML }}
renders
admin:
port: "1234"
maxconns: "5"
minconns: "2"
Note: Consul stores all KV data as strings. Thus true is "true"
, 1 is "1"
, etc.
Takes a quote-escaped template string as an argument and passes it on to hashicorp/go-sockaddr templating engine.
{{ sockaddr "GetPrivateIP" }}
See hashicorp/go-sockaddr documentation for more information.
Writes the content to a file with username, group name, permissions. There are optional flags to select appending mode or add a newline.
For example:
{{ key "my/key/path" | writeToFile "/my/file/path.txt" "my-user" "my-group" "0644" }}
{{ key "my/key/path" | writeToFile "/my/file/path.txt" "my-user" "my-group" "0644" "append" }}
{{ key "my/key/path" | writeToFile "/my/file/path.txt" "my-user" "my-group" "0644" "append,newline" }}
The following functions are available on floats and integer values.
Returns the sum of the two values.
{{ add 1 2 }} // 3
This can also be used with a pipe function.
{{ 1 | add 2 }} // 3
Returns the difference of the second value from the first.
{{ subtract 2 5 }} // 3
This can also be used with a pipe function.
{{ 5 | subtract 2 }} // 3
Please take careful note of the order of arguments.
Returns the product of the two values.
{{ multiply 2 2 }} // 4
This can also be used with a pipe function.
{{ 2 | multiply 2 }} // 4
Returns the division of the second value from the first.
{{ divide 2 10 }} // 5
This can also be used with a pipe function.
{{ 10 | divide 2 }} // 5
Please take careful note of the order or arguments.
Returns the modulo of the second value from the first.
{{ modulo 2 5 }} // 1
This can also be used with a pipe function.
{{ 5 | modulo 2 }} // 1
Please take careful note of the order of arguments.
Returns the minimum of the two values.
{{ minimum 2 5 }} // 2
This can also be used with a pipe function.
{{ 5 | minimum 2 }} // 2
Returns the maximum of the two values.
{{ maximum 2 5 }} // 2
This can also be used with a pipe function.
{{ 5 | maximum 2 }} // 2
Debugging functions help template developers understand the current context of a template block. These
are provided by the spew library.
See the spew
GoDoc documentation for more information.
Outputs the value with full newlines, indentation, type, and pointer
information to stdout (instead of rendered in the template) by calling spew.Dump
on it. Returns an empty string
or an error.
{{- $JSON := `{ "foo": { "bar":true, "baz":"string", "theAnswer":42} }` -}}
{{- $OBJ := parseJSON $JSON -}}
{{- spew_dump $OBJ -}}
renders
>
(map[string]interface {}) (len=1) {
(string) (len=3) "foo": (map[string]interface {}) (len=3) {
(string) (len=3) "bar": (bool) true,
(string) (len=3) "baz": (string) (len=6) "string",
(string) (len=9) "theAnswer": (float64) 42
}
}
Creates a string containing the values with full newlines, indentation, type, and pointer information by calling spew.Sdump
on them. Returns an error or the string. The return value can be captured as a variable, used as input to a pipeline, or written to the template in place.
{{- $JSON := `{ "foo": { "bar":true, "baz":"string", "theAnswer":42} }` -}}
{{- $OBJ := parseJSON $JSON -}}
{{- spew_dump $OBJ -}}
renders
>
(map[string]interface {}) (len=1) {
(string) (len=3) "foo": (map[string]interface {}) (len=3) {
(string) (len=3) "bar": (bool) true,
(string) (len=3) "baz": (string) (len=6) "string",
(string) (len=9) "theAnswer": (float64) 42
}
}
Formats output according to the provided format string and then writes the generated information to stdout. You can use format strings to produce a compacted inline printing style by your choice:
%v
: most compact%+v
: adds pointer addresses%#v
: adds types%#+v
: adds types and pointer addresses
spew_printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
spew_printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
Examples
Given this template fragment,
{{- $JSON := `{ "foo": { "bar":true, "baz":"string", "theAnswer":42} }` -}}
{{- $OBJ := parseJSON $JSON -}}
{{- spew_printf "%v\n" $OBJ }}
outputs
map[foo:map[bar:true baz:string theAnswer:42]]
{{ spew_printf "%+v\n" $OBJ }}
outputs
map[foo:map[bar:true baz:string theAnswer:42]]
{{ spew_printf "%v\n" $OBJ }}
outputs
map[foo:map[bar:true baz:string theAnswer:42]]
{{ spew_printf "%#v\n" $OBJ }}
outputs
(map[string]interface {})map[foo:(map[string]interface {})map[bar:(bool)true baz:(string)string theAnswer:(float64)42]]
{{ spew_printf "%#+v\n" $OBJ }}
outputs
(map[string]interface {})map[foo:(map[string]interface {})map[theAnswer:(float64)42 bar:(bool)true baz:(string)string]]
If you would prefer to use format strings with a compacted inline printing style, use the convenience wrappers for spew.Printf
, spew.Sprintf
, etc with:
%v
: most compact%+v
: adds pointer addresses%#v
: adds types%#+v
: adds types and pointer addresses