在consul-template中循环中覆盖一个变量。

huangapple go评论70阅读模式
英文:

Overriding a variable in a loop in consul-template

问题

我正在使用consul-template中的以下模板:

{{ range services }}
  {{ $server_name := .Name | replaceAll "_" "." }}
  {{ range .Tags }}
    {{ if . | regexMatch "server_name=" }}
      # 在 {{ . }} 中找到匹配的 server_name
      {{ $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 }}

生成的结果是

  # 在 server_name=geoserver.hello.org 中找到匹配的 server_name
  



    
  
  # 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

其中.Namegeoserver_dev_hello_org,并且有一个server_name=geoserver.hello.org的标签。我期望在.Tags循环结束时,$server_name的值应该是geoserver.hello.org,但它仍然保持原始值geoserver.dev.hello.org

如何使循环覆盖$server_name(并在找到值时退出循环)?

英文:

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)?

答案1

得分: 5

consul-template模板中,你可以使用scratch - 一个在模板生命周期内可用的临时键值存储。

你的代码应该如下所示:

{{ range services }}
  {{ $server_name := .Name | replaceAll "_" "." }}
  {{ scratch.Set "server_name" $server_name }}
  {{ range .Tags }}
    {{ if . | regexMatch "server_name=" }}
      # 在 {{ . }} 中找到匹配的 server_name
      {{ $server_name := . | regexReplaceAll ".*=" "" }}
      {{ scratch.Set "server_name" $server_name }}
    {{ end }}
  {{ end }}
  # server_name = {{ scratch.Get "server_name" }}
        acl host_{{ .Name }} hdr(host) -i {{ $server_name }}
        use_backend {{ .Name }}_backend if host_{{ .Name }}
{{ end }}
英文:

In a consul-template template, you can use the scratch - a temporary key-value store available throughout the lifetime of a template.

Your code would look like this:

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

答案2

得分: 2

内部的$server_name和外部的$server_name是不同的变量。在Go模板中,你不能设置外部作用域的变量:http://play.golang.org/p/0fuOmqXrSK。

你可以尝试重写你的模板,将acl等部分放在内部的if语句中,这样就可以正常工作,除非你需要执行那部分代码只一次。Go模板并不是为了处理复杂逻辑而设计的脚本语言,它是用来展示预先计算好的信息的工具,可以看作是增强版的fmt.Printf。所有的逻辑,包括搜索和替换,都应该在Go代码中完成,这样会更快、更安全,也更容易维护和调试。

英文:

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.

答案3

得分: 1

自从Go 1.11发布以来,可以通过模板中的赋值来修改变量。所以现在可以这样做:

  {{ $v := "init" }}
  {{ if true }}
    {{ $v = "changed" }}
  {{ end }}
  v: {{ $v }} {{/* "changed" */}}

这个版本是在v0.25.1发布的时候通过引入到Consul Template中的。

英文:

Since Go 1.11 release it's possible to modify variables via assignements within templates. So this is working now:

  {{ $v := "init" }}
  {{ if true }}
    {{ $v = "changed" }}
  {{ end }}
  v: {{ $v }} {{/* "changed" */}}

This version was introduced to Consul Template with the v0.25.1 release.

huangapple
  • 本文由 发表于 2016年1月13日 16:29:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/34761716.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定