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:

.varsthe variables of the host, with the vars of the recipe step
.factsthe facts of the host; run winch doc facts
.hostname, short, address, groups, and vars of the host; address is the name when the host has no address
.itemthe 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

FunctionMeaning
andand x y: the first empty argument, or the last argument.
callcall f args: the result of the function f.
eqeq a b: true when a equals b.
gege a b: true when a >= b.
getget m key: the value of key in the map m, or nothing when m has no such key.
gtgt a b: true when a > b.
hashas list v: true when list contains v.
htmlhtml s: s with the special characters of HTML escaped.
indexindex x k: the element of the map or the list x at the key or the index k.
joinjoin list sep: the elements of list as text, joined with sep.
jsjs s: s escaped for a JavaScript string.
jsonjson v: v as JSON on one line.
lele a b: true when a <= b.
lenlen x: the length of a string, a list, or a map.
ltlt a b: true when a < b.
nene a b: true when a does not equal b.
notnot x: true when x is empty or false.
oror x y: the first argument that is not empty, or the last argument.
printprint args: the arguments as text, as Go's fmt.Sprint gives them.
printfprintf format args: the arguments formatted as Go's fmt.Sprintf does: {{ printf "%05d" .vars.uid }}.
printlnprintln args: the arguments as text, with spaces between them and a newline at the end.
quotequote s: s in single quotes for sh, each ' as '\''.
sliceslice x i j: the part of the string or the list x from the index i up to j.
sqlquotesqlquote s: s as a string literal for MariaDB, or for PostgreSQL with E before it: in single quotes, each ' as '', each \ as \\.
titletitle s: s with the first letter of each word in upper case.
urlqueryurlquery 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 }}"