templates
text with values filled in (!tpl)
A template is text in which winch fills in the values of each host.
Syntax
The !tpl tag marks a template, a Go text/template. It builds text, such as a path or a line. The template files of a recipe use the same language.
Data
A template reads these names with a leading dot:
| .vars | the variables of the host, with the vars of the recipe step |
| .facts | the facts of the host; run winch doc facts |
| .host | name, short, address, groups, and vars of the host; address is the name when the host has no address |
| .item | the current element in a step with loop |
Inside range, "." is the element. $.vars reads the variables.
Where templates go
Any module argument can be a template or an expression, and so can then.
Functions and actions
A function takes its arguments after its name, separated by spaces: {{ join .vars.names ", " }}. Templates also have the actions of Go's text/template: if, else, range, with, define, template, block, break, and continue, and the variables $x := value.
Missing values
A template that reads a missing map key fails. Use get for a map key that may be missing. A variable needs a value or a default; get does not read the host's own .vars. A template that prints a null value fails.
Quoting
A value goes into a command as it is. Quote a value that must stay one word with quote. Quote a YAML value that starts with a quote, [, {, &, *, or !, or that contains ": " or " #". A template that starts with {{ needs quotes.
Other hosts
Templates have no match(). To list other hosts, give a recipe step a variable with an !expr that uses match(), and range over it in a template of the recipe.
When they run
winch evaluates templates on the machine that runs winch, during the plan. They cannot read the result of a step. winch checks each one when it loads the project: an unknown name or a syntax error is an error. An error while winch evaluates one for a host fails that host. The other hosts go on.
Functions
| Function | Meaning |
|---|---|
and | and x y: the first empty argument, or the last argument. |
call | call f args: the result of the function f. |
eq | eq a b: true when a equals b. |
ge | ge a b: true when a >= b. |
get | get m key: the value of key in the map m, or nothing when m has no such key. |
gt | gt a b: true when a > b. |
has | has list v: true when list contains v. |
html | html s: s with the special characters of HTML escaped. |
index | index x k: the element of the map or the list x at the key or the index k. |
join | join list sep: the elements of list as text, joined with sep. |
js | js s: s escaped for a JavaScript string. |
json | json v: v as JSON on one line. |
le | le a b: true when a <= b. |
len | len x: the length of a string, a list, or a map. |
lt | lt a b: true when a < b. |
ne | ne a b: true when a does not equal b. |
not | not x: true when x is empty or false. |
or | or x y: the first argument that is not empty, or the last argument. |
print | print args: the arguments as text, as Go's fmt.Sprint gives them. |
printf | printf format args: the arguments formatted as Go's fmt.Sprintf does: {{ printf "%05d" .vars.uid }}. |
println | println args: the arguments as text, with spaces between them and a newline at the end. |
quote | quote s: s in single quotes for sh, each ' as '\''. |
slice | slice x i j: the part of the string or the list x from the index i up to j. |
sqlquote | sqlquote s: s as a string literal for MariaDB, or for PostgreSQL with E before it: in single quotes, each ' as '', each \ as \\. |
title | title s: s with the first letter of each word in upper case. |
urlquery | urlquery s: s escaped for the query of a URL. |
templates.and
and x y: the first empty argument, or the last argument. In an expression, and is an operator.
templates.call
call f args: the result of the function f. Project data holds no functions.
templates.eq
eq a b: true when a equals b. With more arguments, true when a equals any of them. In an expression, use ==.
templates.ge
ge a b: true when a >= b.
templates.get
get m key: the value of key in the map m, or nothing when m has no such key. It reads a key that a map may leave out: {{ with get . "endpoint" }}Endpoint = {{ . }}{{ end }}. It does not read the host's own .vars: a variable that may have no value needs a default.
templates.gt
gt a b: true when a > b.
templates.has
has list v: true when list contains v. In an expression, use v in list.
templates.html
html s: s with the special characters of HTML escaped.
templates.index
index x k: the element of the map or the list x at the key or the index k. More keys read deeper. A missing map key is an error. Use get for a key that may be missing.
templates.join
join list sep: the elements of list as text, joined with sep.
templates.js
js s: s escaped for a JavaScript string.
templates.json
json v: v as JSON on one line. Map keys are in sorted order, and non-ASCII characters stay UTF-8. The output is also a valid YAML value, so it writes a string into a JSON or a YAML file: "data-root": {{ json .vars.docker_root }}.
templates.le
le a b: true when a <= b.
templates.len
len x: the length of a string, a list, or a map.
templates.lt
lt a b: true when a < b.
templates.ne
ne a b: true when a does not equal b.
templates.not
not x: true when x is empty or false. In an expression, not and ! are operators.
templates.or
or x y: the first argument that is not empty, or the last argument. In an expression, or is an operator.
templates.print
print args: the arguments as text, as Go's fmt.Sprint gives them.
templates.printf
printf format args: the arguments formatted as Go's fmt.Sprintf does: {{ printf "%05d" .vars.uid }}.
templates.println
println args: the arguments as text, with spaces between them and a newline at the end.
templates.quote
quote s: s in single quotes for sh, each ' as '\''. A value goes into a command as it is. Quote a value that must stay one word: then: !tpl "postmap {{ quote .vars.map }}".
templates.slice
slice x i j: the part of the string or the list x from the index i up to j. In an expression, use x[i:j].
templates.sqlquote
sqlquote s: s as a string literal for MariaDB, or for PostgreSQL with E before it: in single quotes, each ' as '', each \ as \\. It assumes the default SQL mode, without NO_BACKSLASH_ESCAPES, and a UTF-8 client.
templates.title
title s: s with the first letter of each word in upper case.
templates.urlquery
urlquery s: s escaped for the query of a URL.
Example
# winch.yaml
name: demo
hosts:
web1.acme.com: {}
web2.acme.com: {}
vars:
sites: [blog, shop]
admins: [ann, bob]
steps:
- name: Write the sites
file:
path: !tpl /etc/nginx/sites-enabled/{{ .item }}.conf
content: !tpl "server_name {{ .item }}.{{ .host.short }};\n"
loop: !expr vars.sites
- name: List the admins
file:
path: /etc/app/admins.conf
content: !tpl "admins ={{ range .vars.admins }} {{ . }}{{ end }}\n"
- name: List the other hosts
recipe: peers
vars:
peers_hosts: !expr filter(match("all"), .name != host.name)
recipes:
peers:
steps:
- file:
path: /etc/peers
content: !tpl "{{ range .vars.peers_hosts }}{{ .name }} {{ .address }}\n{{ end }}"