go text/template & Consul-template

weixin_34194087發表於2018-05-23

一、概覽

http://docscn.studygolang.com/pkg/text/template/

1. 資料結構

資料結構是UTF-8-encoded的文字。可以使用任意的format。

2. "Actions"

"Actions" 是 data evaluations or control structures , 使用 "{{" and "}}"分割;
actions外面的文字就是普通的輸出文字。
除了raw字串外,action不能span新的lines,就是必須在一行內寫完,雖然comments可以。

  • 使用 . 來訪問當前位置的上下文
  • 使用 $. 來引用當前模板根級的上下文
  • 使用 $var 來訪問建立的變數

3. pipeline

如何判斷pipeline是空的?
當pipeline的值等於如下值時,那麼這個pipeline被認為是空:

  • false
  • 0
  • nil指標或interface
  • 長度為0的array、slice、map、string

4. 基本函式

  • 只能使用函式+引數的用法
    例如: 不能使用類似於 $aa++$aa:=$aa+1 ,只能使用 add $aa 1
{{and .X .Y .Z}} 
{{or .X .Y .Z}} 
{{ not true }}

{{if eq true .Var1 .Var2}}{{end}} 
#eq支援多個引數,其他的ne、lt、le、gt、ge

{{call .Field.Func .Arg1 .Arg2}}
#返回1個值或2個值,第二個值作為error型別的錯誤,不等於nil的時候執行將終止
 
{{index .Maps "name"}}
#index 支援 map, slice, array, string,讀取指定型別對應下標的值

{{printf "The content length is %d" (.Content|len)}}  
# len 支援 map, slice, array, string, chan

# print/printf/println  %#v


二、Actions

1. 註釋

{{/* a comment */}}

註釋,可能包含多行,註釋不能巢狀,而且必須像上面這樣寫。

2. pipeline - if

如何判斷pipeline是空的?
當pipeline的值等於如下值時,那麼這個pipeline被認為是空:

  • false
  • 0
  • nil指標或interface
  • 長度為0的array、slice、map、string
{{pipeline}}
# 預設的文字表示。 
  
{{if pipeline}} T1 {{end}}

{{if pipeline}} T1 {{else}} T0 {{end}} 

{{if pipeline}} T1 {{else if pipeline}} T0 {{end}}

3. pipeline - range

dot的含義不受影響。

{{range pipeline}} T1 {{end}}

{{range pipeline}} T1 {{else}} T0 {{end}}

{{range $index,$elem := .Pages}}

pipeline的值必須是array、slice、map、或channel。
如果pipeline的length是0,就不輸出任何內容。
否則,dot被設定為 array、slice、map的連續的elements。並且T1被執行。

4. template

{{template "name"}}
{{template "name" pipeline}}
# 指定name的template被執行,使用nil data或給定的pipeline。 

5. pipeline - with

{{with pipeline}} T1 {{end}}

{{with $value :="My name is %s"}}{{printf . "slene"}}{{end}}

{{with pipeline}} T1 {{else}} T0 {{end}}

如果pipeline是empty,不生成任何輸出。

否則,dot被設定為pipeline的值,並且T1被執行。

例子:

{{ "\"output\""}} 或 {{ \`"output"\`}} #字串常量,雙引號escape

{{ printf "%q" pipeline }} #列印物件的值,也要看到函式呼叫的方式

{{ pipeline | printf "%#v" }}


三、Consul-template:

https://github.com/hashicorp/consul-template

1、快速的例子:

consul-template -consul-addr 10.0.209.149:8500 \
  -consul-token xxx \
  -once \
  -template "in.tpl:out.txt:somecommand" 

# 檢視幫助
consul-template -h

  • 可以指定多個 -template
  • command執行的條件是輸出檔案是否發生變化,跟模版監控的內容是否發生變化無關!
  • 當consul-template啟動時就會根據模版生成文字到輸出檔案,如果生成的內容和輸出檔案原有的內容不一致就會觸發command執行。
  • 如果任意一個 -template 指定的command的退出狀態碼不是0,即不是正常返回,consul-template命令將結束!可以使用 xxx || true 作為命令來保證其正常返回。

Exec mode介紹: 當template首次完全被render之後,consul-template spawns一個子程式並管理其生命週期。當任意的輸出檔案發生變化時,consul-template會傳送一個reload訊號(這個訊號可以配置)給子程式。另外,consul-template會proxy它收到的任何訊號給子程式。
有一定經常造成困擾的是 命令字串的執行行為和在shell中不一樣。當你在shell中執行 foo | bar 或 foo > bar 時,實際上它是作為shell的子程式執行的。當consul-template spawn出一個子程式時,它是執行於shell之外的,所以其行為和在consul-template命令列中使用如下方式指定的命令執行方式是不一樣的
其他具體的請自行參看官網,這裡不做過多贅述

2、配置檔案

格式:

   consul {
     auth {
       enabled = true
     }
     address = "127.0.0.1:8500"
   }
   reload_signal = "SIGHUP"
   dump_signal = "SIGQUIT"
   kill_signal = "SIGINT"

   env {
     #...
   }
  • 使用配置檔案,可以多次指定單個檔案,也可以指定資料夾
  • 優先順序: CLI指定的引數 > 最後指定的配置檔案
  • 資料夾內的配置檔案按照 lexical order(字典排序)順序排序生效
consul-template -config "my/config.hcl"


四 、 Consul-template API

1、datacenters

Query Consul for all datacenters in its catalog.

{{ range datacenters }}{{ . }}{{ end }}

2、file

讀取本地檔案,如果讀取錯誤,會發生錯誤。
檔案內容更改時,會re-render template。

{{ file "/path/to/my/file" }}

3、key

查詢consul的給定key的value,如果key不存在,consul-teplate會阻塞直到key存在了為止。

為了避免阻塞,可以使用keyOrDefault或keyExists。

<DATACENTER>預設是local datacenter。

{{ key "<PATH>@<DATACENTER>" }}
{{ if keyExists "<PATH>@<DATACENTER>" }}
{{ keyOrDefault "<PATH>@<DATACENTER>" "<DEFAULT>" }}

4、ls

查詢給定路徑的所有鍵值對,必須是資料夾的路徑,如果路徑指向一個key,請使用key API

{{ range ls "service/redis" }} {{ .Key }}:{{ .Value }}{{ end }}

4.1 tree

查詢給定路徑的所有的 kv pair , 和 ls 的區別是 ls 沒有遞迴效果,也就是說不顯示子資料夾及其之內的key-value,而tree會遞迴。

{{ range tree "service/redis" }} {{ .Key }}:{{ .Value }}{{ end }}

5、node

查詢 catalog中的某個node,如果node不存在那命令會一直提示該node不存在,並且卡住

{{node "<NAME>@<DATACENTER>"}} 

NAME預設是local agent node

{{ with node }}{{ .Node.Address }}{{ end }}  #實測報錯

如何遍歷該map?

6、nodes

查詢catalog中的所有nodes:

{{ nodes "@<DATACENTER>~<NEAR>" }}

DATACENTER預設是local datacenter

NEAR或_agent是排序方式,預設是按字典順序排序

{{ range nodes }} {{ .Address }}{{ end }}

7、service

查詢某些服務

{{ service "<TAG>.<NAME>@<DATACENTER>~<NEAR>|<FILTER>" }}
{{ range service "web" }} server {{ .Name }}{{ .Address }}:{{ .Port }}{{ end }}
{{ service "web|any" }}
{{ service "web" "passing,warning" }} 或者    {{ service "web|passing,warning" }}(經實測後者不行)

8、services

返回所有服務

{{ range services }} {{ .Name }}: {{ .Tags | join "," }}{{ end }}

9、sratch

抓取,用於儲存臨時值,不能在不同的template之間共享,也不能在不同的呼叫之間cache。

{{ scratch.Key "foo" }}  #判斷key是否存在
{{ scratch.Get "foo" }}
{{ scratch.Set "foo" "bar" }} #設定或覆蓋
{{ scratch.SetX "foo" "bar" }}  #設定或不覆蓋
{{ scratch.MapSet "vars" "foo" "bar" }}  #設定map中的某個key的值,覆蓋
{{ scratch.MapSetX "vars" "foo" "bar" }}  #不覆蓋
{{ scratch.MapValues "vars" }}  #返回一個按key排序的所有values的list

10. 幫助函式

下面是一些幫助函式

 {{ base64Decode "aGVsbG8=" }}
 {{ base64Encode "hello" }}
 {{ base64URLDecode "aGVsbG8=" }}
 {{ base64Encode "hello" }}

10.1 byKey

byKey 接收tree返回的list,然後建立一個map,把相同的top-level的作為key,其他部分組成一個list作為value。

    {{ range $key, $pairs := tree "groups" | byKey }}{{ $key }}:
      {{ range $pair := $pairs }}  {{ .Key }}={{ .Value }}
    {{ end }}{{ end }}

10.2 explode :

explode 接收tree或ls的結果,並將其轉換為一個深度nested map。

  {{ with tree "config" | explode }} {{ .a.b.c }}{{ end }}

10.3 byTag

    {{ range $tag, $services := service "web" | byTag }}{{ $tag }}
      {{ range $services }} server {{ .Name }} {{ .Address }}:{{ .Port }}
    {{ end }}{{ end }}

10.4 contains

   {{ if .Tags | contains "production" }}
      # ...
   {{ end }}

10.5 in

類似於contains

  {{ if in .Tags "production" }}
  # ...
  {{ end }}

10.5 集合判斷

containsAll containsAny containsNone containsNotAll

  {{ if containsAny $acceptableTags .Tags }}
  # ...
  {{ end }}

10.6 env

讀取當前程式可訪問的環境變數

  {{ env "CLUSTER_ID" | toLower }}

10.7 loop

第一個數字可以省略,預設是0

  {{ range $i := loop 5 8 }}
  stanza-{{ $i }}{{ end }}

10.8 join/split

把陣列元素連線起來

  {{ $items | join "," }}

10.9 trimSpace

trim首尾的 空白字元、tabs、newlines

  {{ file "/etc/ec2_version" | trimSpace }}

10.10 parseBool parseFloat parseInt parseJson parseUint

  {{ "true" | parseBool }}

10.11 plugin

 {{ plugin "my-plugin" }}

10.12 regexMatch regexReplaceAll replaceAll

    {{ if "foo.bar" | regexMatch "foo([.a-z]+)" }}

10.13 timestamp

10.14 toJSON

10.15 toJSONPretty

帶縮排格式的JSON

10.16 toLower toTitle toTOML toUpper toYAML

10.17 add

{{ add 1 2 }} 
# 或者
{{ 1 | add 2 }}

10.18 subtract multiply divide modulo(模)

{{ modulo 2 5 }} // 1

相關文章