go text/template & Consul-template
一、概覽
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
相關文章
- go template使用Go
- 基於Docker + Consul + Nginx + Consul-template的服務負載均衡實現DockerNginx負載
- Go標準庫:Go template用法詳解Go
- Go HTML/template 模板使用方法GoHTML
- go 模板(template)的常用基本語法Go
- 採用docker-compose和consul-template實現nginx自動發現自動註冊-微服務治理DockerNginx微服務
- kubectl技巧之通過go-template擷取屬性Go
- html templateHTML
- ES 筆記十四:Index Template 和 Dynamic Template筆記Index
- c++ 模板模板引數("Template Template Parameters")C++
- Using the Template Collection to Add a Template Column in WebDataGridWeb
- BaiDu TemplateAI
- Django模板templateDjango
- Js template engineJS
- artTemplate js templateJS
- C_template
- Mendix Page Template
- ansible template
- 等不及 go 泛型釋出,我先實現了(類似 C++ 的 template)Go泛型C++
- 模板方法模式(Template)模式
- Vue template To JSXVueJS
- elasticsearch之search templateElasticsearch
- Oracle ASM Template DirectoryOracleASM
- Abstract Factory + Template = BuilderUI
- 關於Template模式模式
- ASM Disk Group TemplateASM
- [Javascript] template literal tagJavaScript
- C++之templateC++
- 探究 Text Kit 和 Core Text 的前世今生 (Text Kit 篇)
- Python:Template模板字串Python字串
- ansible之template模組
- ASP.NET MVC TemplateASP.NETMVC
- Python Template 錯誤Python
- oracle controlfile template;Oracle
- 標準庫之template
- c++11-17 模板核心知識(十四)—— 解析模板之依賴型模板名稱 Dependent Names of Templates(.template/->template/::template)C++
- text/html和text/plain的區別HTMLAI
- template might not exist or might not be accessible by any of the configured Template Resolvers