Templating

Warewulf uses the text/template engine to convert dynamic content into static content and auto-populate files with the appropriate data on demand.

In Warewulf, you can find templates both for the provisioning services (e.g. /etc/warewulf/ipxe/, /etc/warewulf/dhcp/, and /etc/warewulf/hosts.tmpl) as well as within the runtime and system overlays.

(more documentation coming soon)

Examples

Comment

{{  /* This comment won't show up in file, but an empty line /* }}
{{  /* No empty line, line break removed at end of this line /* -}}
{{-  /* No empty line, line break removed at front of this line /* }}

Range

iterate over elements of an array

{{ range $devname, $netdev := .NetDevs }}
    # netdev = {{ $netdev.Hwaddr }}
{{ end }}

Increment Variable In Loop

iterate over elements of an array and increment i each loop cycle

{{ $i := 0 }}
{{ range $devname, $netdev := .NetDevs }}
    # netdev{{$i}} = {{ $netdev.Hwaddr }}
    {{ $i = inc $i }}
{{ end }}

Decrement

iterate over elements of an array and decrement i each loop cycle

{{ $i := 10 }}
{{ range $devname, $netdev := .NetDevs }}
    # netdev{{$i}} = {{ $netdev.Hwaddr }}
    {{ $i = dec $i }}
{{ end }}

Access Tag

Acces the value of an individual tag foo

foo: {{ index .Tags "foo" }}
{{ if eq (index .Tags "foo") "baar" -}}
foo: {{ index .Tags "foo" }}
{{ end -}}

Create Multiple Files

The following template will create a file called ifcfg-NETWORKNAME.xml for every network present on the node

{{- $host := .BuildHost }}
{{- $time := .BuildTime }}
{{- $source := .BuildSource }}
{{range $devname, $netdev := .NetDevs -}}
{{- $filename := print "ifcfg-" $devname ".xml" }}
{{- file $filename }}
<!--
This file is autogenerated by warewulf
Host:   {{ $host }}
Time:   {{ $time }}
Source: {{ $source }}
-->
<interface origin="static generated warewulf config">
  <name>{{$netdev.Device}}</name>
  {{ if $netdev.Type -}}
  <link-type>{{ $netdev.Type }}</link-type>
  {{ end -}}
  <control>
    <mode>boot</mode>
  </control>
  <firewall/>
  <link/>
  <ipv4>
    <enabled>true</enabled>
    <arp-verify>true</arp-verify>
  </ipv4>
  <ipv4:static>
    <address>
      <local>{{$netdev.IpCIDR}}</local>
    </address>
{{ if $netdev.Gateway -}}
    <route>
      <nexthop>
        <gateway>{{$netdev.Gateway}}</gateway>
      </nexthop>
    </route>
{{ end -}}
  </ipv4:static>
  <ipv6>
    <enabled>true</enabled>
    <privacy>prefer-public</privacy>
    <accept-redirects>false</accept-redirects>
  </ipv6>
{{ if $netdev.Ipaddr6 -}}
  <ipv6:static>
    <address>
      <local>{{ $netdev.Ipaddr6 }}</local>
    </address>
  </ipv6:static>
{{ end -}}
</interface>
{{ end -}}

Special Commands

Include

A file from the host can be include with following template

{{ Include file }}

IncludeFrom

With following snippet a file from a given container can be included

{{ IncludeFrom container file }}

IncludeBlock

Includes a file up to the line where a abort string is found. This is useful, e.g., for the hosts file, which can have local modifications which are not controlled by warewulf. For this example the abort string is “# Do not edit after this line”

{{ IncludeBlock "/etc/hosts" "# Do not edit after this line" }}
# This block is autogenerated by warewulf
# Host:   {{.BuildHost}}
# Time:   {{.BuildTime}}
# Source: {{.BuildSource}}


# Warewulf Server
{{$.Ipaddr}} warewulf {{$.BuildHost}}

{{- range $node := $.AllNodes}}                  {{/* for each node */}}
# Entry for {{$node.Id.Get}}
{{- range $devname, $netdev := $node.NetDevs}} {{/* for each network device on the node */}}
{{- if $netdev.Ipaddr.Defined}}                {{/* if we have an ip address on this network device */}}
{{- /* emit the node name as hostname if this is the primary */}}
{{$netdev.Ipaddr.Get}} {{$node.Id.Get}}-{{$devname}}
{{- if $netdev.Device.Defined}} {{$node.Id.Get}}-{{$netdev.Device.Get}}{{end}}
{{- if $netdev.Primary.GetB}} {{$node.Id.Get}}{{end}}
{{- end}} {{/* end if ip */}}
{{- end}} {{/* end for each network device */}}
{{- end}} {{/* end for each node */}}

Abort

If {{ abort }} is found in a template, the resulting file isn’t written.

Nobackup

If a file exists on the target, a backup file is written with the suffix .wwbackup. This only happens for the host overlay, as e.g. the /etc/hosts exists on the host. If this is not the intended behavior, the {{ nobackup }} flag can be added to a template.

Split

A given string can be split into substrings.

{{ $x := "a:b:c" -}}
{{ $y := (split $x ":") -}}
{{ range $y }} {{.}} {{ end }}

Node specific files

Sometimes there is the need to have specific files for every node which can’t be generated by a template. You can include these files with following template:

{{- $filename := print "/root/" .Id "-payload" }}
{{ Include $filename }}