• HashiCorp Developer

  • HashiCorp Cloud Platform
  • Terraform
  • Packer
  • Consul
  • Vault
  • Boundary
  • Nomad
  • Waypoint
  • Vagrant
Nomad
  • Install
  • Intro
  • Tutorials
  • Documentation
  • API
  • Tools
  • Plugins
  • Sign up
Templates

Skip to main content
4 tutorials
  • Learn Go Template Syntax
  • Format Nomad Command Output with Templates
  • DRY Nomad Job Specs with Levant
  • Make Abstract Job Specs with Levant

  • Resources

  • Tutorial Library
  • Community Forum
    (opens in new tab)
  • Support
    (opens in new tab)
  • GitHub
    (opens in new tab)
  1. Developer
  2. Nomad
  3. Tutorials
  4. Templates
  5. Format Nomad Command Output with Templates

Format Nomad Command Output with Templates

  • 8min

  • NomadNomad

When using Nomad at an intermediate to advanced level, you'll need to interface with other systems or customize output generated by Nomad. The -t flag is a powerful way to pass a template in Go's text/template format to several of the Nomad commands that generate output based on the API. This allows you to filter and customize the output to meet your specific needs.

The commands that allow for the -t flag are:

  • nomad acl policy list
  • nomad acl token list
  • nomad alloc status
  • nomad deployment list
  • nomad deployment status
  • nomad eval status
  • nomad job deployments
  • nomad job history
  • nomad job inspect
  • nomad namespace list
  • nomad node status
  • nomad plugin status
  • nomad quota list
  • nomad volume status

This tutorial will teach you how to explore the objects that are returned to the template engine and how to use template syntax to format the output into a custom form.

Prerequisites

This guide assumes the following:

  • Familiarity with Go's text/template syntax. You can learn more about it in the Learn Go Template Syntax tutorial

  • That you are running these commands against a Nomad cluster with an active workload. You can create a minimal environment using a dev agent, started with nomad agent -dev, then running at least one Nomad job. You can use nomad init -short to create a sample Docker job or provide your own Nomad job.

Note the shell-specific syntax

When using the -t flag, you need to correctly handle string literals based on your shell environment. In a POSIX shell, you can run the following with a single quote:

$ nomad node status  -t '{{printf "%#+v" .}}'

In a Windows shell (for example, PowerShell), use single quotes but escape the double quotes inside the parameter as follows:

PS> nomad node status  -t '{{printf \"%#+v\" .}}'

In this tutorial, you can select examples with the proper escaping using the tabs above the snippets.

Start discovering objects

The printf function and the "%#+v" format string are critical tools for you in exploring an unfamiliar template context.

Run the following command to output the context being passed to the template in Go object format.

$ nomad node status -t '{{printf "%#+v" .}}'
PS> nomad node status -t '{{printf \"%#+v\" .}}'
[]*api.NodeListStub{(*api.NodeListStub)(0xc0003fa160), (*api.NodeListStub)(0xc0003fa0b0), (*api.NodeListStub)(0xc0003fa000)}

The output indicates that the context consists of a list ([]) of pointers (*) to api.NodeListStub objects. The list will also show one NodeListStub object per client node in your cluster's server state.

You can explore these api.NodeListStub object by using the range control over the list.

$ nomad node status -t '{{range .}}{{printf "%#+v" .}}{{end}}'
PS> nomad node status -t '{{range .}}{{printf \"%#+v\" .}}{{end}}'
&api.NodeListStub{Address:"10.0.2.52", ID:"4f60bc83-71a2-7790-b120-4e55d0e6ed34", Datacenter:"dc1", Name:"nomad-client-2.node.consul", NodeClass:"", Version:"0.12.0", Drain:false, SchedulingEligibility:"eligible", Status:"ready", ...

If you have a lot of client nodes in your cluster state, this output will be unwieldy. In that case, you can use with and the index function to get the first list item.

$ nomad node status -t '{{with index . 0}}{{printf "%#+v" .}}{{end}}'
PS> nomad node status -t '{{with index . 0}}{{printf \"%#+v\" .}}{{end}}'
&api.NodeListStub{Address:"10.0.2.52", ID:"4f60bc83-71a2-7790-b120-4e55d0e6ed34", Datacenter:"dc1", Name:"nomad-client-2.node.consul", NodeClass:"", Version:"0.12.0", Drain:false, SchedulingEligibility:"eligible", Status:"ready", ...
&api.NodeListStub{Address:"10.0.2.52", ID:"4f60bc83-71a2-7790-b120-4e55d0e6ed34", Datacenter:"dc1", Name:"nomad-client-2.node.consul", NodeClass:"", Version:"0.12.0", Drain:false, SchedulingEligibility:"eligible", Status:"ready", ...

Finally, output Name and Version for each client in the cluster.

$ nomad node status -t '{{range .}}{{printf "%s: %s\n" .Name .Version}}{{end}}'
PS> nomad node status -t '{{range .}}{{printf \"%s: %s\n\" .Name .Version}}{{end}}'
nomad-client-2.node.consul: 0.12.0
nomad-client-3.node.consul: 0.12.0
nomad-client-1.node.consul: 0.12.0

Make quiet output

Suppose you want to create a reduced version of the nomad job status output to show just the running job IDs in your cluster and nothing else.

$ nomad job inspect -t '{{range .}}{{if eq .Status "running"}}{{ println .Name}}{{end}}{{end}}'
PS> nomad job inspect -t '{{range .}}{{if eq .Status \"running\"}}{{ println .Name}}{{end}}{{end}}'

Nomad will output the job IDs for every running job in your cluster. For example:

fabio
sockshop-carts
sockshop-catalogue
sockshop-frontend
sockshop-infra
sockshop-orders
sockshop-payment
sockshop-shipping
sockshop-user

Challenge yourself

Allocations have a slightly different shape. How might you create similar output from the nomad alloc status command? Make sure that your Nomad cluster has at least one allocation running and then use the printf technique from earlier to explore the values sent into the template.

Print the context that you are passed from the command using the printf command.

$ nomad alloc status -t '{{printf "%#+v" . }}'
PS> nomad alloc status -t '{{printf \"%#+v\" . }}'
[]*api.AllocationListStub ...

Note that the first thing that you receive is a list ([]) of pointers (*) to AllocationListStub objects.

Use range to traverse each item in the list.

$ nomad alloc status -t '{{range .}}{{printf "%#+v" . }}{{end}}'
PS> nomad alloc status -t '{{range .}}{{printf \"%#+v\" . }}{{end}}'
&api.AllocationListStub{ID:"30663b68-4d8a-aada-4ad2-011b1acae3a1", EvalID:"c5eda90b-f675-048e-b2f7-9ced30e4916b", Name:"sockshop-user.userdb[0]", Namespace:"default", NodeID:"3be35c12-70aa-8816-195e-a4630a457727", NodeName:"nomad-client-3.node.consul", JobID:"sockshop-user", JobType:"service", JobVersion:0x0, ...

If you have a lot of allocations running, this could get unwieldy. In that case, you can use with and the index function to get the first list item.

$ nomad alloc status -t '{{with index . 0}}{{printf "%#+v" . }}{{end}}'
PS> nomad alloc status -t '{{with index . 0}}{{printf \"%#+v\" . }}{{end}}'
&api.AllocationListStub{ID:"30663b68-4d8a-aada-4ad2-011b1acae3a1", EvalID:"c5eda90b-f675-048e-b2f7-9ced30e4916b", Name:"sockshop-user.userdb[0]", Namespace:"default", NodeID:"3be35c12-70aa-8816-195e-a4630a457727", NodeName:"nomad-client-3.node.consul", JobID:"sockshop-user", JobType:"service", JobVersion:0x0, ...

The fields on the AllocationListStub object that give insight into the running state of an allocation are DesiredStatus and ClientStatus.

Did you know? The definition of an AllocationListStub object and valid values for the DesiredStatus and ClientStatus are located in Nomad's api package. Take a moment to look at it and see what other information you might be interested in displaying with templates.

Update your template to show items with a DesiredStatus of "run" and a client status of "running" or "pending."

$ nomad alloc status -t '{{range .}}{{if and (eq .DesiredStatus "run") (or (eq .ClientStatus "running") (eq .ClientStatus "pending"))}}{{println .ID}}{{end}}{{end}}'
PS> nomad alloc status -t '{{range .}}{{if and (eq .DesiredStatus \"run\") (or (eq .ClientStatus \"running\") (eq .ClientStatus \"pending\"))}}{{println .ID}}{{end}}{{end}}'
30663b68-4d8a-aada-4ad2-011b1acae3a1
11b916da-d679-1718-26f3-f6cd499bfdb8
68bcb157-359f-9293-d091-5a8ef71475ad
...

You now have a list of the IDs for all of the allocations running in your Nomad cluster.

Retrieve a template from file

Using the command line to write templates becomes challenging as the template becomes more complex.

By writing a template in its own file, you can use comments, span multiple lines, and indent conditionals in order to make them more readable to you and to other operators.

Consider using some of these techniques to include the template data into the command.

Create a file named running_jobs.tmpl with the following content.

{{- /*
  Get Running Jobs
  Run with `nomad job inspect -t "$(cat running_jobs.tmpl)"`
*/ -}}
{{- range . -}}
  {{- if eq .Status "running" -}}
    {{- println .Name -}}
  {{- end -}}
{{- end -}}

Now, use a subshell to read the file into a variable

$ nomad job inspect -t "$(cat running_jobs.tmpl)"

Create a file named running_jobs.tmpl with the following content.

{{- /*
  Get Running Jobs
  Run with:
    $content=Get-Content running_jobs.tmpl -Raw; nomad job inspect -t $content
*/ -}}
{{- range . -}}
  {{- if eq .Status \"running\" -}}
    {{- println .Name -}}
  {{- end -}}
{{- end -}}

Now, use a subshell to read the file into a variable

PS> $content=Get-Content running_jobs.tmpl -Raw; nomad job inspect -t $content

Learn more

In this tutorial, you learned how to:

  • Customize the output of several Nomad commands using Go's text/template syntax.

  • Use the printf function to discover what is available in the template's context.

  • Use a template definition contained in a file as part of the command.

Learn more about templating in other tutorials in the Nomad Templating Collection.

 Previous
 Next

On this page

  1. Format Nomad Command Output with Templates
  2. Prerequisites
  3. Note the shell-specific syntax
  4. Start discovering objects
  5. Make quiet output
  6. Retrieve a template from file
  7. Learn more
Give Feedback(opens in new tab)
  • Certifications
  • System Status
  • Terms of Use
  • Security
  • Privacy
  • Trademark Policy
  • Trade Controls
  • Give Feedback(opens in new tab)