consul-template解析以Go Template格式编写的文件,如果您不熟悉语法,请阅读Go的文档和示例。除Go提供的模板功能外,Consul Template还提供以下功能。
1. API函数
API函数与远程API调用交互,与Consul和Vault等外部服务进行通信。
datacenters
查询Consul其中所有数据中心。
1 |
{{ datacenter }} |
例如:
1 |
{{ range datacenters }} |
结果:
dc1 |
可以指定一个可选的布尔值,指示Consul Template忽略无法访问或没有当前leader的数据中心。启用此选项需要执行O(N + 1)操作,因此不建议在性能较高的环境中使用。
1 |
// Ignores datacenters which are inaccessible |
file
读取并输出磁盘上本地文件的内容。如果无法读取文件,则会发生错误。当文件更改时,Consul Template将获取更改并重新渲染模板。
1 |
{{ file " |
例如:
1 |
{{ file "/path/to/my/file" }} |
结果:
file contents |
这不会处理嵌套模板。有关呈现嵌套模板的方法,请参阅executeTemplate。
key
查询Consul获取给定键路径的值。如果密钥不存在,Consul Template将停止渲染,直到键值存在。要避免阻塞,请使用keyOrDefault
或keyExists
。
1 |
{{ key " |
例如:
1 |
{{ key "service/redis/maxconns" }} |
结果:
15 |
keyExists
查询Consul获取给定键路径的值。如果密钥存在,则返回true,否则返回false。与key不同,如果key不存在,则此功能不会阻塞。这对于控制流程很有用。
1 |
{{ keyExists " |
属性是可选的;如果省略,则使用本地数据中心(后面其他参数若无特殊说明,则同理)。
例如:
1 |
{{ if keyExists "app/beta_active" }} |
keyOrDefault
查询Consul获取给定键路径的值。如果key不存在,则将使用默认值。与key不同,如果键值不存在,则此功能不会阻塞流程。
1 |
{{ keyOrDefault " |
例如:
1 |
{{ keyOrDefault "service/redis/maxconns" "5" }} |
结果:
5 |
请注意,Consul Template使用多阶段执行。在评估的第一阶段,Consul Template将没有来自Consul的数据,因此将始终回退到默认值。从Consul的后续读取将在下一个模板传递中从Consul(如果key存在)中提取实际值。这很重要,因为这意味着由于keyOrDefault
中缺少键值,Consul Template永远不会“阻塞”模板的渲染。即使key存在,如果Consul尚未返回key的数据,也将使用默认值。
ls
查询给定键路径上所有顶级键值对
1 |
{{ ls " |
例如:
1 |
{{ range ls "service/redis" }} |
maxconns:15 |
node
查询consul节点
1 |
{{node " |
属性是可选的;如果省略,则使用本地agent节点。
例如:
1 |
{{ with node }} |
结果:
10.5.2.6 |
查询一个同的节点
1 |
{{ with node "node1@dc2" }} |
结果:
10.4.2.6 |
要访问TaggedAddresses
或Meta
等地图数据,请使用Go’s text/template 地图索引。
nodes
查询所有consul节点
1 |
{{ nodes "@ |
属性是可选的;如果省略,则以词法顺序指定结果。如果提供了节点名称,则结果按照提供的节点的最短往返时间排序。如果提供_agent
,则结果按照到本地代理的最短往返时间排序。
例如:
1 |
{{ range nodes }} |
结果:
10.4.2.13 |
要按最短的响应时间查询获取不同的数据中心:
1 |
{{ range nodes "@dc2~_agent" }} |
secret
查询给定路径上的密码。
1 |
{{ secret " |
属性是可选的;如果省略,请求将是一个密码
vault read
(HTTP GET)请求。如果提供,请求将是vault write
(HTTP PUT / POST)请求。
例如:
1 |
{{ with secret "secret/passwords" }} |
结果:
FORWARDSoneword |
要访问版本化的密码值(对于K / V版本2后端):
1 |
{{ with secret "secret/passwords?version=1" }} |
省略?version
参数时,将获取最新版本的密码。引用密码值时请注意嵌套的.Data.data语法。有关使用K/V v2后端的详细信息,请参阅Vault文档。
使用Vault版本0.10.0 / 0.10.1时,密码路径必须以“data”为前缀,即上述示例的secret/data/passwords
。对于0.10.1之后的Vault版本,这不是必需的,因为consul-template将检测正在使用的KV后端版本。版本2 KV后端在0.10.0之前不存在,因此这些是唯一受影响的版本。
使用write生成PKI证书的示例:
1 |
{{ with secret "pki/issue/my-domain-dot-com" "common_name=foo.example.com" }} |
参数必须是key = value对,并且每对必须是函数的自己的参数:
请始终考虑在磁盘上以纯文本形式保密的内容的安全隐患。如果***者能够访问该文件,他们将可以访问纯文本机密。
请注意,Vault不支持阻塞查询。因此,如果密码被更改,Consul Template将不会立即重新加载,就像Consul的键值存储一样。 Consul Template将在原始密码的租约期限的一半时间内获取新密码。例如,Vault的通用密码后端中的大多数项目都有默认的30天租约。这意味着Consul Template将每15天更新一次密码。因此,建议在生成初始密钥时使用较小的租约期限,以迫使Consul Template更频繁地续订。
在使用将与Vault交互的模板时,还要考虑启用error_on_missing_key
。默认情况下,Consul Template使用Go的模板语言。访问不存在的结构字段或映射键时,默认为打印""。这可能不是理想的行为,尤其是在处理密码或其他数据时。因此,建议您设置:
template { |
您还可以使用if
或with block
来防止空值。
1 |
{{ with secret "secret/foo"}} |
secrets
查询Vault以获取给定路径上的密码列表。并非所有节点都支持列表。
1 |
{{ secrets " |
例如:
1 |
{{ range secrets "secret/" }} |
结果:
bar |
要迭代并列出Vault中通用密码后端中的每个密码:
1 |
{{ range secrets "secret/" }} |
你可能永远不会这样做。
另请注意,Vault不支持阻塞查询。要了解其含义,请阅读secret
末尾的注释。
service
根据健康状况查询服务
1 |
{{ service " |
属性是可选的;如果省略,将查询所有节点。
属性是可选的;如果省略,则仅返回健康服务。提供过滤器允许客户端过滤服务。
上面的示例是在“east-aws”数据中心查询Consul的健康“web”服务。tag和datacenter属性是可选的。要查询当前数据中心的“Web”服务的所有节点(无论标签如何):
1 |
{{ range service "web" }} |
结果,使用名为“web”的逻辑服务呈现所有健康节点的IP地址::
server web01 10.5.2.45:2492 |
默认情况下,仅返回健康服务。要列出所有服务,请传递“any”过滤器,这将返回注册到代理的所有服务,无论其状态如何。:
1 |
{{ service "web|any" }} |
要按特定的运行状况集过滤服务,请指定以逗号分隔的运行状况列表:
1 |
{{ service "web|passing,warning" }} |
这将根据Consul中定义的节点和服务级别检查返回被视为“通过”或“警告”的服务。请注意,逗号表示“或”,而不是“和”。
注意
:以下内容存在架构差异:
1 |
{{ service "web" }} |
前者将返回Consul认为“健康”的所有服务并通过。后者将返回在Consul代理注册的所有服务并执行客户端的过滤。作为一般规则,如果您只想要健康的服务,请不要单独使用passing
参数,只需要省略第二个参数即可。
services
查询所有的服务
1 |
{{ services "@ |
例如:
1 |
{{ range services }} |
结果:
node01 tag1,tag2,tag3 |
tree
查询指定路径键值对
1 |
{{ tree " |
例如:
1 |
{{ range tree "service/redis" }} |
结果:
minconns 2 |
不像ls
,tree
返回带前缀的所有键值,就像Unix的tree命令。
2. Scratch暂存器
暂存器在模板的上下文中可用于存储临时数据或计算。 Scratch数据不在模板之间共享,也不在调用之间缓存。
scratch.Key
如果数据存在于命名键的暂存器中,则返回布尔值。即使该键的数据为“nil”,仍然会返回true。
1 |
{{ scratch.Key "foo" }} |
scratch.Get
返回指定键的暂存器中的值。如果数据不存在,则返回“nil”。
1 |
{{ scratch.Get "foo" }} |
scratch.Set
将给定值保存在给定键上。如果该值已存在,则会被覆盖。
1 |
{{ scratch.Set "foo" "bar" }} |
scratch.SetX
此行为与Set
完全相同,但如果值已存在则不会覆盖。
1 |
{{ scratch.SetX "foo" "bar" }} |
scratch.MapSet
将值保存在映射的命名键中。如果该值已存在,则会被覆盖。
1 |
{{ scratch.MapSet "vars" "foo" "bar" }} |
scratch.MapSetX
此行为与MapSet
完全相同,但如果值已存在则不会覆盖。
1 |
{{ scratch.MapSetX "vars" "foo" "bar" }} |
scratch.MapValues
返回指定映射中所有值的排序列表(按键)。
1 |
{{ scratch.MapValues "vars" }} |
3. Helper Functions辅助函数
与API函数不同,辅助函数不查询远程服务。这些函数对于解析数据,格式化数据,执行数学等非常有用。
base64Decode
接受base64编码的字符串并返回解码的结果,如果给定的字符串不是有效的base64字符串,则返回错误。
1 |
{{ base64Decode "aGVsbG8=" }} |
结果:
hello |
base64Encode
接受一个字符串并返回一个base64编码的字符串。
1 |
{{ base64Encode "hello" }} |
结果:
aGVsbG8= |
base64URLDecode
接受base64编码的URL安全字符串并返回解码结果,如果给定字符串不是有效的base64 URL安全字符串,则返回错误。
1 |
{{ base64URLDecode "aGVsbG8=" }} |
结果:
hello |
base64URLEncode
接受一个字符串并返回base-64编码的URL安全字符串。
1 |
{{ base64Encode "hello" }} |
结果:
aGVsbG8= |
byKey
接受tree
调用返回的对的列表,并创建一个按顶级目录对进行分组的映射。
例如此目录列表:
groups/elasticsearch/es1 |
使用以下模板
1 |
{{ range $key, $pairs := tree "groups" | byKey }}{{ $key }}: |
结果:
elasticsearch: |
请注意,最顶层的键是从Key值中删除的。剥离后没有前缀的键将从列表中删除。
结果键值对被键控为一个映射,因此可以按键查找单个值:
1 |
{{ $weights := tree "weights" }} |
byTag
获取service
或services
函数返回的服务列表,并创建一个按标签对服务进行分组的映射
1 |
{{ range $tag, $services := service "web" | byTag }}{{ $tag }} |
contains
确定是否在可迭代元素内。
1 |
{{ if .Tags | contains "production" }} |
containsAll
如果所有值都在可迭代元素内,则返回true,否则返回false。如果值列表为空,则返回true。
1 |
{{ if containsAll $requiredTags .Tags }} |
containsAny
如果任意一个值在可迭代元素内,则返回true,否则返回false。如果值列表为空,则返回false。
1 |
{{ if containsAny $acceptableTags .Tags }} |
containsNone
如果没有值在可迭代元素内,则返回true,否则返回false。如果值列表为空,则返回true。
1 |
{{ if containsNone $forbiddenTags .Tags }} |
containsNotAll
如果某些值不在可迭代元素内,则返回true,否则返回false。如果值列表为空,则返回false。
1 |
{{ if containsNotAll $excludingTags .Tags }} |
env
读取当前进程可访问的给定环境变量。
1 |
{{ env "CLUSTER_ID" }} |
可以链接此函数来操作输出:
1 |
{{ env "CLUSTER_ID" | toLower }} |
例如,读取给定的环境变量,如果它不存在或为空,则使用默认值12345:
1 |
{{ or (env "CLUSTER_ID") "12345" }} |
executeTemplate
执行并返回已定义的模板。
1 |
{{ define "custom" }}my custom template{{ end }} |
explode
从tree
或ls
调用获取结果并将其转换为深度嵌套的映射以进行解析/遍历。
1 |
{{ tree "config" | explode }} |
注意:在失败后,您将丢失有关键值对的所有元数据。但还可以访问深层嵌套值:
1 |
{{ with tree "config" | explode }} |
indent
通过在每行前面添加N个空格来缩进文本块。
1 |
{{ tree "foo" | explode | toYAML | indent 4 }} |
in
确定针是否在可迭代元素内。
1 |
{{ if in .Tags "production" }} |
loop
接受不同的参数,并根据这些参数区分其行为。
如果给出一个整数的循环,它将返回一个从0开始并循环到但不包括给定整数的goroutine:
1 |
{{ range loop 5 }} |
如果给定两个整数,则此函数将返回从第一个整数开始并循环到但不包括第二个整数的goroutine:
例如:
1 |
{{ range $i := loop 5 8 }} |
结果:
stanza-5 |
注意:由于函数返回goroutine而不是切片,因此无法获取索引和元素。换句话说,以下内容无效
:
1 |
# Will NOT work! |
join
字符串连接:
1 |
{{ $items | join "," }} |
trimSpace
获取给定的字符串并将其解析为布尔值:
{{ "true" | parseBool }} |
这可以与键和条件检查结合使用,例如:
1 |
{{ if key "feature/enabled" | parseBool }}{{ end }} |
parseFloat
获取给定的字符串并将其解析为基数为10的float64:
1 |
{{ "1.2" | parseFloat }} |
parseInt
获取给定的字符串并将其解析为base-10 int64:
{{ "1" | parseInt }} |
这可以与其他助手结合使用,例如:
1 |
{{ range $i := loop key "config/pool_size" | parseInt }} |
parseJSON
获取给定的输入(通常是键中的值)并将结果解析为JSON:
1 |
{{ with $d := key "user/info" | parseJSON }}{{ $d.name }}{{ end }} |
注意
:Consul Template会多次评估模板,并且在第一次评估时,键的值将为空(因为尚未加载任何数据)。这意味着模板必须防止空响应。
parseUint
获取给定的字符串并将其解析为base-10 int64:
1 |
{{ "1" | parseUint }} |
plugin
获取插件和可选有效加载的名称并执行Consul Template插件。
1 |
{{ plugin "my-plugin" }} |
该插件可以采用任意数量的字符串参数,也可以是生成字符串的管道的目标。这通常与用于自定义的JSON过滤器结合使用:
有关插件的更多信息,请参阅插件部分
1 |
{{ tree "foo" | explode | toJSON | plugin "my-plugin" }} |
regexMatch
将参数作为正则表达式,如果在给定字符串上匹配则返回true
,否则返回false
。
1 |
{{ if "foo.bar" | regexMatch "foo([.a-z]+)" }} |
regexReplaceAll
将参数作为正则表达式,并将所有出现的正则表达式替换为给定的字符串。与go一样,您可以使用$1
之类的变量来引用替换字符串中的子表达式。
1 |
{{ "foo.bar" | regexReplaceAll "foo([.a-z]+)" "$1" }} |
replaceAll
将参数作为字符串取代,并用给定的字符串替换给定字符串的所有匹配项。
1 |
{{ "foo.bar" | replaceAll "." "_" }} |
此功能也可以与其他功能链接:
1 |
{{ service "web" }}{{ .Name | replaceAll ":" "_" }}{{ end }} |
split
在提供的分隔符上拆分给定的字符串:
1 |
{{ "foo\nbar\n" | split "\n" }} |
这可以与链接和管道与其他功能结合使用:
1 |
{{ key "foo" | toUpper | split "\n" | join "," }} |
timestamp
以字符串(UTC)形式返回当前时间戳。如果没有给出参数,则结果是当前的RFC3339时间戳:
1 |
{{ timestamp }} // e.g. 1970-01-01T00:00:00Z |
如果给出了可选参数,则它用于格式化时间戳。参考日期Mon Jan 2 15:04:05 -0700 MST 2006可用于根据需要格式化日期:
1 |
{{ timestamp "2006-01-02" }} // e.g. 1970-01-01 |
有关更多信息,请参阅Go’s time.Format
作为一种特殊情况,如果可选参数是“unix”,则以秒为单位的unix时间戳将作为字符串返回。
1 |
{{ timestamp "unix" }} // e.g. 0 |
toJSON
从tree
或ls
调用获取结果并将其转换为JSON对象。
1 |
{{ tree "config" | explode | toJSON }} |
结果:
1 |
{"admin":{"port":"1234"},"maxconns":"5","minconns":"2"} |
注意
:Consul将所有KV数据存储为字符串。因此,true为“true”,1为“1”,等等。
toJSONPretty
从tree
或ls
调用获取结果并将其转换为漂亮打印的JSON对象,缩进两个空格。
1 |
{{ tree "config" | explode | toJSONPretty }} |
结果:
1 |
{ |
toLower
将参数作为字符串并将其转换为小写。
1 |
{{ key "user/name" | toLower }} |
参见Go’s strings.ToLower
toTitle
将参数作为字符串并将其转换为标题。
1 |
{{ key "user/name" | toTitle }} |
参见Go’s strings.Title
toTOML
从tree
或ls
调用获取结果并将其转换为TOML对象。
1 |
{{ tree "config" | explode | toTOML }} |
结果:
1 |
maxconns = "5" |
toUpper
将参数作为字符串并将其转换为大写。
1 |
{{ key "user/name" | toUpper }} |
参见Go’s strings.ToUpper
toYAML
从tree
或ls
调用获取结果并将其转换为漂亮打印的YAML对象,缩进两个空格。
1 |
{{ tree "config" | explode | toYAML }} |
结果:
1 |
admin: |
4. Math Functions数学函数
方便浮点数和整数值数学计算的函数
add
返回两个值的总和。
1 |
{{ add 1 2 }} // 3 |
这也可以与管道功能一起使用(下同)。
1 |
{{ 1 | add 2 }} // 3 |
subtract
返回第一个值与第二个值的差值。
1 |
{{ subtract 2 5 }} // 3 |
1 |
{{ 5 | subtract 2 }} // 3 |
请仔细注意参数的顺序(下同)。
multiply
返回两个值的乘积。
1 |
{{ multiply 2 2 }} // 4 |
1 |
{{ 2 | multiply 2 }} // 4 |
divide
返回第一个值的第二个值的除法。
1 |
{{ divide 2 10 }} // 5 |
1 |
{{ 10 | divide 2 }} // 5 |
modulo
返回第一个值的第二个模的模数。
1 |
{{ modulo 2 5 }} // 1 |
1 |
{{ 5 | modulo 2 }} // 1 |