templatesgoconsulconsul-template

Overriding a variable in a loop in consul-template


I'm using the following template in consul-template:

{{ range services }}
  {{ $server_name := .Name | replaceAll "_" "." }}
  {{ range .Tags }}
    {{ if . | regexMatch "server_name=" }}
      # found matching server_name in {{ . }}
      {{ $server_name := . | regexReplaceAll ".*=" "" }}
    {{ end }}
  {{ end }}
  # server_name = {{ $server_name }}
        acl host_{{ .Name }} hdr(host) -i {{ $server_name }}
        use_backend {{ .Name }}_backend if host_{{ .Name }}
{{ end }}

which produces

  # found matching server_name in server_name=geoserver.hello.org






  # server_name = geoserver.dev.hello.org
        acl host_geoserver_dev_hello_org hdr(host) -i geoserver.dev.hello.org
        use_backend geoserver_dev_hello_org_backend if host_geoserver_dev_hello_org

where .Name is geoserver_dev_hello_org and there is a server_name=geoserver.hello.org tag. I expect that by the end of the .Tags range loop, $server_name should have value geoserver.hello.org, but it still has its original value of geoserver.dev.hello.org.

How can I make it so that the loop overrides $server_name (and exit the loop when the value is found)?


Solution

  • Inner $server_name and outer $server_name are different variables. You can't set a variable from outer scope in Go templates: http://play.golang.org/p/0fuOmqXrSK.

    You could try and rewrite your template to print the acl etc. part inside the inner if which would work unless you need to execute that part just once. Go templates are not designed as a scripting language for complex logic, it's a tool for showing pre-computed information. A fmt.Printf on steroids if you will. All logic including search and replacement should be in Go, it'll be faster, safer, easier to maintain and debug.