1

I'm trying to get a simple index that I can append to output of a Go template snippet using consul-template. Looked around a bit and couldn't figure out the simple solution. Basically, given this input

backend web_back
    balance roundrobin
    {{range service "web-busybox" "passing"}}
        server  {{ .Name }} {{ .Address }}:80 check
    {{ end }}

I would like to see web-busybox-n 10.1.1.1:80 check

Where n is the current index in the range loop. Is this possible with range and maps?

icza
  • 389,944
  • 63
  • 907
  • 827
4m1r
  • 12,234
  • 9
  • 46
  • 58

2 Answers2

0

There is no iteration number when ranging over maps (only a value and an optional key). You can achieve what you want with custom functions.

One possible solution that uses an inc() function to increment an index variable in each iteration:

func main() {
    t := template.Must(template.New("").Funcs(template.FuncMap{
        "inc": func(i int) int { return i + 1 },
    }).Parse(src))

    m := map[string]string{
        "one":   "first",
        "two":   "second",
        "three": "third",
    }

    fmt.Println(t.Execute(os.Stdout, m))
}

const src = `{{$idx := 0}}
{{range $key, $value := .}}
    index: {{$idx}} key: {{ $key }} value: {{ $value }}
    {{$idx = (inc $idx)}}
{{end}}`

This outputs (try it on the Go Payground) (compacted output):

index: 0 key: one value: first
index: 1 key: three value: third
index: 2 key: two value: second

See similar / related questions:

Go template remove the last comma in range loop

Join range block in go template

Golang code to repeat an html code n times

icza
  • 389,944
  • 63
  • 907
  • 827
  • Thanks @icza this is pretty hard to understand as a Go newbie. Any way we can simplify or use something native to the templating language? I wonder if we could convert the map into an array and then get a range index? – 4m1r Apr 18 '19 at 15:30
  • @4m1r If you are allowed to convert your map to a slice, then there is no issue: ranging over a slice you have the index too. – icza Apr 18 '19 at 21:56
0

The example below looks for all servers providing the pmm service, but will only create the command to register with the first pmm server found (when $index == 0)

{{- range $index, $service := service "pmm" -}}
    {{- if eq $index 0 -}}
sudo pmm-admin config --server {{ $service.Address }}
    {{- end -}}
{{- end -}}
Wandering Zombie
  • 1,101
  • 13
  • 14