[TOC]
0x00 前言简述 Q: 什么是模板? 答: MVC 框架(Model View Controller): Model(模型,通常在服务端)用于处理数据、View(视图,客户端代码)用于展现结果、Controller(控制器)用于控制数据流,确保 M(模型改变) 和 V(视图) 的同步,即一旦 M 改变,V 也应该同步更新。
常常对于 View 端的处理,在很多动态语言中是通过在静态 HTML 代码中插入动态数据来实现的。由于最终展示给用户的信息大部分是静态不变的,只有少部分数据会根据用户的不同而动态生成, 所以将静态信息固化为模板可以复用代码,提高展示效率
; 例如:JSP 的 <%=....=%> 和 PHP 的 <?php.....?>
语法。
Go语言提供了简单灵活的模板支持,而基于 Go 开发的 Docker 继承了该强大能力,使其可以脱离 Shell 的相关操作,直接对结果进行格式化输出。 比如,对于 docker ls 的输出信息会根据附加参数的不同而不同,但其表头信息是固定的, 并且所有支持 –format 扩展的 Docker CLI 指令
以及kubectl查看相关命令
均支持该操作。
0x01 基础语法 描述: 下面列举出Go模板的常用用法并进行简单的演示;
1.注释
[TOC]
0x00 前言简述 Q: 什么是模板? 答: MVC 框架(Model View Controller): Model(模型,通常在服务端)用于处理数据、View(视图,客户端代码)用于展现结果、Controller(控制器)用于控制数据流,确保 M(模型改变) 和 V(视图) 的同步,即一旦 M 改变,V 也应该同步更新。
常常对于 View 端的处理,在很多动态语言中是通过在静态 HTML 代码中插入动态数据来实现的。由于最终展示给用户的信息大部分是静态不变的,只有少部分数据会根据用户的不同而动态生成, 所以将静态信息固化为模板可以复用代码,提高展示效率
; 例如:JSP 的 <%=....=%> 和 PHP 的 <?php.....?>
语法。
Go语言提供了简单灵活的模板支持,而基于 Go 开发的 Docker 继承了该强大能力,使其可以脱离 Shell 的相关操作,直接对结果进行格式化输出。 比如,对于 docker ls 的输出信息会根据附加参数的不同而不同,但其表头信息是固定的, 并且所有支持 –format 扩展的 Docker CLI 指令
以及kubectl查看相关命令
均支持该操作。
0x01 基础语法 描述: 下面列举出Go模板的常用用法并进行简单的演示;
1.注释
1 2 3 4 docker inspect --format='{{/*查看容器的默认网关*/}}' $INSTANCE_ID docker inspect --format='{{/*查看容器的默认网关*/}}{{.NetworkSettings.Networks.opt_default.Gateway}}' dc1
2.打印信息 描述: Go template 中利用 go 语言的 print 函数
对模板中的字符串进行输出, go中还包括两种相似println 和 printf等内置函数。
print: 将传入的对象转换为字符串并写入到标准输出中。如果后跟多个参数,输出结果之间会自动填充空格进行分隔。
println:功能和 print 类似,但会在结尾添加一个换行符。也可以直接使用
来换行。
printf: 与 shell 等环境一致,可配合占位符用于格式化输出。
基础示例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 docker inspect --format '{{.State.Pid}} {{.State.ExitCode}}' $INSTANCE_ID docker inspect --format '{{print .State.Pid .State.ExitCode}}' $INSTANCE_ID docker inspect --format '{{.State.Pid}}{{println}}{{/*println 表示换行*/}}{{.State.ExitCode}}' $INSTANCE_ID docker inspect --format '{{printf "Pid:%d ExitCode:%d" .State.Pid .State.ExitCode}}' $INSTANCE_ID
3.变量 系统变量 描述:通过下面的符号组合获取当前对象,因为点号表示当前对象及上下文,和 Java、C++ 中的 this 类似,另外如果返回结果也是一个 Struct 对象(Json 中以花括号/大括号包含)
,则可以直接通过点号级联调用,获取子对象的指定属性值。
注意: 如果需要获取的属性名称包含点号(比如下列示例数据)或者以数字开头,则不能直接通过级联调用获取信息。因为属性名称中的点号会被解析成级联信息,进而导致返回错误结果。即便使用引号将其包含也会提示语法格式错误。此时,需要通过 index 来读取指定属性信息。1 2 3 4 5 6 7 8 9 "Options" : { "com.docker.network.bridge.default_bridge" : "true" , "com.docker.network.bridge.enable_icc" : "true" , "com.docker.network.bridge.enable_ip_masquerade" : "true" , "com.docker.network.bridge.host_binding_ipv4" : "0.0.0.0" , "com.docker.network.bridge.name" : "docker0" , "com.docker.network.driver.mtu" : "1500" },
基础实例:1 2 3 4 5 6 7 8 9 10 11 12 docker inspect --format '{{/*读取容器状态*/}}{{.State.Status}}' $INSTANCE_ID docker inspect --format '{{.Options.com.docker.network.driver.mtu}}' bridge <no value> docker inspect --format '{{.Options."com.docker.network.driver.mtu"}}' bridge Template parsing error: template: :1: bad character U+0022 '"' docker inspect --format '{{/*读取网络在hosts上的名称*/}}{{index .Options "com.docker.network.bridge.name"}}' bridge docker0
自定义变量 描述:可以在处理过程中设置自定义变量,然后结合自定义变量做更复杂的处理。如果自定义变量的返回值是对象,则可以通过点号进一步级联访问其属性。比如 。
基础实例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 docker inspect --format '{{.NetworkSettings.Ports}}' dc1 docker inspect --format '{{/*通过变量组合展示容器绑定端口列表*/}}已绑定端口列表:{{println}}{{range $p,$conf := .NetworkSettings.Ports}}{{$p}} -> {{(index $conf 0).HostPort}}{{println}}{{end}}' dc1 已绑定端口列表: 80/tcp -> 32770 8081/tcp -> 8081
4.索引 描述:如果返回结果是一个 map, slice, array 或 string
,则可以使用 index 加索引序号(从零开始计数)来读取属性值。
基础示例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 ... "IPAM" : { "Driver" : "default" , "Options" : null, "Config" : [ { "Subnet" : "172.31.254.1/24" , "Gateway" : "172.31.254.1" } ] }, "Ports" : { "80/tcp" : [ { "HostIp" : "0.0.0.0" , "HostPort" : "8081" } ] }, ... docker inspect bridge --format '{{/*查看网络的默认网关*/}}{{(index .IPAM.Config 0).Gateway}}' docker inspect dc1 --format '{{/*查看主机映射端口*/}}{{(index .NetworkSettings.Ports "80/tcp" 0).HostPort}}' 8081
5.条件判断 描述: 与其他一些编程语言一样,利用基本判断和if .. else .. end
以及判断条件进行组合判断;
基础语法:1 2 3 4 5 6 7 8 9 {{if pipeline}}{{end}} {{if pipeline}}{{else }}{{if pipeline}}{{end}}{{end}} {{if pipeline}}{{else if pipeline}}{{else }}{{end}} {{if not .State.Restarting}}{{/*条件为真执行*/}}{{end}} {{or .State.Status .State.Restarting}} {{if 判断条件 .Var1 .Var2}}{{/*为真时候执行*/}}{{else }}{{/*为假时候执行*/}}{{end}}
基础判断说明:
基础示例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 docker inspect --format '{{if ne 0 .State.ExitCode}}非正常停止的容器:{{.Name}}{{end}}' $(docker ps -aq) docker inspect --format '{{if ne "exited" .State.Status}}{{.Name}} 运行中{{else}}{{.Name}} 已停止{{end}}' $(docker ps -aq) docker inspect --format '{{if not .State.Running}}{{.Name}}{{else if .}}该容器{{.Name}}还在运行{{end}}' $(docker ps -aq) docker inspect --format '{{if eq "exited" .State.Status}}{{.Name}}{{else if eq .State.Restarting true}}容器{{.Name}}配置了Restarting策略.{{else}}容器{{.Name}}正在运行,但是没有配置Restarting策略{{end}}' $(docker ps -aq)
6.遍历(循环) 描述:range 用于遍历结构内返回值的所有数据。支持的类型包括 array, slice, map 和 channel
。使用要点:
对应的值长度为 0 时 range 不会执行。
结构内部如要使用外部的变量,需要在前面加引用比如Var2。
range 也支持 else 操作。效果是当返回值为空或长度为 0 时执行 else 内的内容。
基础语法:1 2 {{range pipeline}}{{.}}{{end}} {{range pipeline}}{{.}}{{else }}{{.}}{{end}}
基础示例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 docker inspect dc1 --format='{{range .State.Health.Log}}{{.Start}}{{println}}{{end}}' 2020-07-07 16:25:51.354025918 +0800 CST 2020-07-07 16:26:51.423164721 +0800 CST 2020-07-07 16:27:51.56890628 +0800 CST 2020-07-07 16:28:51.635154369 +0800 CST 2020-07-07 16:29:51.70101931 +0800 CST docker inspect dc1 --format='{{ .NetworkSettings.Networks}}' map[opt_default:0xc0001e2f00] docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -q) 172.17.0.2 172.18.0.2
管道(Pipeline) 描述: 管道 即 pipeline 与 shell 中类似,可以是上下文的变量输出,也可以是函数通过管道传递的返回值。
简单示例:1 2 3 示例: {{.Con | markdown | addlinks}} {{.Name | printf "%s" }}
基础示例:1 2 3 4 5 6 7 docker inspect --format '{{.State.Status}}' $(docker ps -aq) docker inspect --format '{{.State.Status | len}}' $(docker ps -aq)
内置函数 len 函数 描述:返回相应对象的长度。 示例:1 docker inspect --format '{{len .Name}}' $INSTANCE_ID
0x02 扩展语法 描述:基于第三方进行增强模板及函数,例如Docker中基于go模板的基础上,构建了一些内置函数。
Docker 扩展
1.json: Docker 默认以字符串显示返回结果。而该函数可以将结果格式化为压缩后的 json 格式数据。
1 2 3 join docker inspect --format='{{json .Config}}' $INSTANCE_ID
2.join:用指定的字符串将返回结果连接后一起展示。操作对象必须是字符串数组。
1 2 docker inspect --format '{{join .Config.Entrypoint " , "}}' $INSTANCE_ID
3.lower: 将返回结果中的字母全部转换为小写。操作对象必须是字符串。
4.upper: 将返回结果中的字母全部转换为大写。操作对象必须是字符串。
1 2 docker inspect --format "{{lower .Name}}" $INSTANCE_ID docker inspect --format "{{upper .Name}}" $INSTANCE_ID
5.title: 将返回结果的首字母转换为大写。操作对象必须是字符串,而且不能是纯数字。
1 docker inspect --format "{{title .State.Status}}" $INSTANCE_ID
6.split: 使用指定分隔符将返回结果拆分为字符串列表。操作对象必须是字符串且不能是纯数字。同时字符串中必须包含相应的分隔符,否则会直接忽略操作。
1 2 docker inspect --format '{{split .HostsPath "/"}}' $INSTANCE_ID