Consul-template: scratch.MapValues and range

Created on 15 Mar 2017  路  2Comments  路  Source: hashicorp/consul-template

It seems like scratch.MapValues doesn't work with range, not sure if I'm using it wrong or if this is a bug...

Consul Template version

consul-template v0.18.1 (9c62737)

Configuration

{{ scratch.MapSet "test" "a" 1 }}
{{ scratch.MapSet "test" "b" 2 }}
{{ scratch.MapSet "test" "c" 3 }}

{{ range scratch.MapValues "test" }}
{{ .Key }}: {{ .Value }}
{{ end }}

Command

consul-template -template test.tpl -once -dry

Expected behavior

a: 1
b: 2
c: 3

Actual behavior

Consul Template returned errors:
test.tpl: execute: template: :6:3: executing "" at <.Key>: can't evaluate field Key in type interface {}

Steps to reproduce

  1. Create test.tpl with above content
  2. Run consul-template -template test.tpl -once -dry

Most helpful comment

In case anyone else stumbles here trying to work out how to loop over a scratch map and get its keys as well as values you can use:

{{ scratch.MapSet "test" "a" 1 }}
{{ scratch.MapSet "test" "b" 2 }}
{{ scratch.MapSet "test" "c" 3 }}

{{ range $key, $val := scratch.Get "test" }}
{{ $key }}: {{ $val }}{{ end }}

prints

a: 1
b: 2
c: 3

From the documentation it wasn't obvious you could use scratch.Get as a getter for Maps as maps have their own unique setter, it just reads like MapValues was the only getter for them.

All 2 comments

Hi there,

Thank you for opening an issue. I think your syntax is incorrect. There are no .Key and .Value methods when ranging over a map. You can read more in Go's text/template documentation, but to iterate over a map:

{{  range $k, $v := myMap }}

Now, the function MapValues does not return a map; it returns the sorted _values_ of the map in a slice. For example:

{{ range $i, $e := scratch.MapValues "test" }}
{{ $i }}: {{ $e }}{{ end }}

prints

0: 1
1: 2
2: 3

Notice that "$i" is the index in the slice, not the key in the map. Maps are not ordered, so there is no deterministic way to "iterate" over a map in a template; it would be different each time.

In case anyone else stumbles here trying to work out how to loop over a scratch map and get its keys as well as values you can use:

{{ scratch.MapSet "test" "a" 1 }}
{{ scratch.MapSet "test" "b" 2 }}
{{ scratch.MapSet "test" "c" 3 }}

{{ range $key, $val := scratch.Get "test" }}
{{ $key }}: {{ $val }}{{ end }}

prints

a: 1
b: 2
c: 3

From the documentation it wasn't obvious you could use scratch.Get as a getter for Maps as maps have their own unique setter, it just reads like MapValues was the only getter for them.

Was this page helpful?
0 / 5 - 0 ratings