《Terraform 101 从入门到实践》这本小册在南瓜慢说官方网站和GitHub两个地方同步更新,书中的示例代码也是放在GitHub上,方便大家参考查看。
Terraform的函数
Terraform为了让大家在表达式上可以更加灵活方便地进行计算,提供了大量的内置函数(Function)。目前并不支持自定义函数,只能使用Terraform自带的。使用函数的格式也很简单,直接写函数名+参数即可。如下面的函数为取最大值:
> max(34, 45, 232, 25) 232
这里把函数单独列成一章不是因为它很难理解,而因为它很常用,值得把这些函数梳理一下,以便查询使用吧。
数值计算函数
绝对值abs:
> abs(5) 5 > abs(-3.1415926) 3.1415926 > abs(0) 0
返回大于等于该数值的最小整数:
> ceil(3) 3 > ceil(3.1) 4 > ceil(2.9) 3
小于等于该数值的最大整数:
> floor(6) 6 > floor(6.9) 6 > floor(5.34) 5
对数函数:
> log(16, 2) 4 > log(9, 3) 2.0000000000000004
指数函数:
> pow(6, 2) 36 > pow(6, 1) 6 > pow(6, 0) 1
最大值、最小值:
> max(2, 98, 75, 4) 98 > min(2, 98, 75, 4) 2
字符串转换成整数,第二个参数为进制:
> parseint("16", 10) 16 > parseint("16", 16) 22 > parseint("FF", 16) 255 > parseint("1010", 2) 10
信号量函数:
> signum(6) 1 > signum(-6) -1 > signum(0) 0
字符串函数
删去换行,在从文件中读取文本时非常有用:
> chomp("www.pkslow.com") "www.pkslow.com" > chomp("www.pkslow.comn") "www.pkslow.com" > chomp("www.pkslow.comnn") "www.pkslow.com" > chomp("www.pkslow.comnnr") "www.pkslow.com" > chomp("www.pkslow.comnnra") <<EOT www.pkslow.com a EOT
格式化输出:
> format("Hi, %s!", "Larry") "Hi, Larry!" > format("My name is %s, I'm %d", "Larry", 18) "My name is Larry, I'm 18" > format("The reuslt is %.2f", 3) "The reuslt is 3.00" > format("The reuslt is %.2f", 3.1415) "The reuslt is 3.14" > format("The reuslt is %8.2f", 3.1415) "The reuslt is 3.14"
遍历格式化列表:
> formatlist("My name is %s, I'm %d %s.", ["Larry", "Jeremy", "Tailor"], [18, 28, 33], "in 2022") tolist([ "My name is Larry, I'm 18 in 2022.", "My name is Jeremy, I'm 28 in 2022.", "My name is Tailor, I'm 33 in 2022.", ])
参数可以是List,还可以是单个变量。
字符串连接:
> join(".", ["www", "pkslow", "com"]) "www.pkslow.com" > join(", ", ["Larry", "Pkslow", "JJ"]) "Larry, Pkslow, JJ"
大小写字母转换:
> lower("Larry Nanhua DENG") "larry nanhua deng" > upper("Larry Nanhua DENG") "LARRY NANHUA DENG"
首字母大写:
> title("larry") "Larry"
替换:
> replace("www.larrydpk.com", "larrydpk", "pkslow") "www.pkslow.com" > replace("hello larry", "/la.*y/", "pkslow") "hello pkslow"
分割:
> split(".", "www.pklow.com") tolist([ "www", "pklow", "com", ])
反转:
> strrev("pkslow") "wolskp"
截取:
> substr("Larry Deng", 0, 5) "Larry" > substr("Larry Deng", -4, -1) "Deng"
去除头尾某些特定字符,注意这里只要有对应字符就会删除:
> trim("?!what?!!!!!", "?!") "what" > trim("abaaaaabbLarry Dengaab", "ab") "Larry Deng"
去除头尾特定字符串,注意与上面的区别:
> trimsuffix("?!what?!!!!!", "!!!") "?!what?!!" > trimprefix("?!what?!!!!!", "?!") "what?!!!!!"
去除头尾的空格、换行等空串:
> trimspace(" Larry Deng nr") "Larry Deng"
正则匹配,下面的例子是匹配第一个和匹配所有:
> regex("[a-z\.]+", "2021www.pkslow.com2022larry deng 31415926") "www.pkslow.com" > regexall("[a-z\.]+", "2021www.pkslow.com2022larry deng 31415926") tolist([ "www.pkslow.com", "larry", "deng", ])
更多正则匹配语法可参考:https://www.terraform.io/language/functions/regex
集合类函数
alltrue:判断列表是否全为真,空列表直接返回true。只能是bool类型或者对应的字符串。
> alltrue([true, "true"]) true > alltrue([true, "true", false]) false > alltrue([]) true > alltrue([1]) ╷ │ Error: Invalid function argument │ │ on <console-input> line 1: │ (source code not available) │ │ Invalid value for "list" parameter: element 0: bool required.
anytrue:判断列表是否有真,只要有一个为真就返回true。空列表为false。
> anytrue([true]) true > anytrue([true, false]) true > anytrue([false, false]) false > anytrue([]) false
chunklist分片:根据分片数来对列表进行切分。
> chunklist(["www", "pkslow", "com", "Larry", "Deng"], 3) tolist([ tolist([ "www", "pkslow", "com", ]), tolist([ "Larry", "Deng", ]), ])
coalesce返回第一个非空元素:
> coalesce("", "a", "b") "a" > coalesce("", "", "b") "b"
coalescelist返回第一个非空列表:
> coalescelist([], ["pkslow"]) [ "pkslow", ]
从字符串列表里把空的去掉:
> compact(["", "www", "", "pkslow", "com"]) tolist([ "www", "pkslow", "com", ])
concat连接多个列表:
> concat([1, 2, 3], [4, 5, 6]) [ 1, 2, 3, 4, 5, 6, ]
contains判断是否存在某个元素:
> contains(["www", "pkslow", "com"], "pkslow") true > contains(["www", "pkslow", "com"], "Larry") false
distinct去除重复元素:
> distinct([1, 2, 2, 1, 3, 8, 1, 10]) tolist([ 1, 2, 3, 8, 10, ])
element获取列表的某个元素:
> element(["a", "b", "c"], 1) "b" > element(["a", "b", "c"], 2) "c" > element(["a", "b", "c"], 3) "a" > element(["a", "b", "c"], 4) "b"
flatten把内嵌的列表都展开成一个列表:
> flatten([1, 2, 3, [1], [[6]]]) [ 1, 2, 3, 1, 6, ]
index获取列表中的元素的索引值:
> index(["www", "pkslow", "com"], "pkslow") 1
keys获取map的所有key值:
> keys({name="Larry", age=18, webSite="www.pkslow.com"}) [ "age", "name", "webSite", ]
values获取map的value值:
> values({name="Larry", age=18, webSite="www.pkslow.com"}) [ 18, "Larry", "www.pkslow.com", ]
length获取字符串、列表、Map等的长度:
> length([]) 0 > length(["pkslow"]) 1 > length(["pkslow", "com"]) 2 > length({pkslow = "com"}) 1 > length("pkslow") 6
lookup(map, key, default)根据key值在map中找到对应的value值,如果没有则返回默认值:
> lookup({name = "Larry", age = 18}, "age", 1) 18 > lookup({name = "Larry", age = 18}, "myAge", 1) 1
matchkeys(valueslist, keyslist, searchset)对key值进行匹配。匹配到key值后,返回对应的Value值。
> matchkeys(["a", "b", "c", "d"], [1, 2, 3, 4], [2, 4]) tolist([ "b", "d", ])
merge合并Map,key相同的会被最后的覆盖:
> merge({name = "Larry", webSite = "pkslow.com"}, {age = 18}) { "age" = 18 "name" = "Larry" "webSite" = "pkslow.com" } > merge({name = "Larry", webSite = "pkslow.com"}, {age = 18}, {age = 13}) { "age" = 13 "name" = "Larry" "webSite" = "pkslow.com" }
one取集合的一个元素,如果为空则返回null;如果只有一个元素,则返回该元素;如果多个元素,则报错:
> one([]) null > one(["pkslow"]) "pkslow" > one(["pkslow", "com"]) ╷ │ Error: Invalid function argument │ │ on <console-input> line 1: │ (source code not available) │ │ Invalid value for "list" parameter: must be a list, set, or tuple value with either zero or one elements. ╵
range生成顺序列表:
range(max) range(start, limit) range(start, limit, step) > range(3) tolist([ 0, 1, 2, ]) > range(1, 6) tolist([ 1, 2, 3, 4, 5, ]) > range(1, 6, 2) tolist([ 1, 3, 5, ])
reverse反转列表:
> reverse([1, 2, 3, 4]) [ 4, 3, 2, 1, ]
setintersection对set求交集:
> setintersection([1, 2, 3], [2, 3, 4], [2, 3, 6]) toset([ 2, 3, ])
setproduct列出所有组合可能:
> setproduct(["Larry", "Harry"], ["Deng", "Potter"]) tolist([ [ "Larry", "Deng", ], [ "Larry", "Potter", ], [ "Harry", "Deng", ], [ "Harry", "Potter", ], ])
setsubtract:set的减法
> setsubtract([1, 2, 3], [3, 4]) toset([ 1, 2, ]) # 求不同 > setunion(setsubtract(["a", "b", "c"], ["a", "c", "d"]), setsubtract(["a", "c", "d"], ["a", "b", "c"])) [ "b", "d", ]
setunion:set的加法
> setunion([1, 2, 3], [3, 4]) toset([ 1, 2, 3, 4, ])
slice(list, startindex, endindex)截取列表部分,包括startindex,但不包括endindex:
> slice(["a", "b", "c", "d", "e"], 1, 4) [ "b", "c", "d", ]
sort对列表中的字符串进行排序,要注意如果输入的是数字,会先转化为字符串再排序:
> sort(["larry", "pkslow", "com", "deng"]) tolist([ "com", "deng", "larry", "pkslow", ]) > sort([3, 6, 1, 9, 12, 79, 22]) tolist([ "1", "12", "22", "3", "6", "79", "9", ])
sum求和:
> sum([3, 1.2, 9, 17.3, 2.2]) 32.7
transpose对Map的key和value进行换位:
> transpose({"a" = ["1", "2"], "b" = ["2", "3"]}) tomap({ "1" = tolist([ "a", ]) "2" = tolist([ "a", "b", ]) "3" = tolist([ "b", ]) })
zipmap根据key和value的列表按一对一关系生成Map:
> zipmap(["age", "name"], [18, "Larry Deng"]) { "age" = 18 "name" = "Larry Deng" }
加密解密
Base64:
> base64encode("pkslow") "cGtzbG93" > base64decode("cGtzbG93") "pkslow" > textencodebase64("pkslow", "UTF-8") "cGtzbG93" > textdecodebase64("cGtzbG93", "UTF-8") "pkslow"
csv文本解析:
> csvdecode("seq,name,agen1,larry,18n2,pkslow,3n3,Jeremy,29") tolist([ { "age" = "18" "name" = "larry" "seq" = "1" }, { "age" = "3" "name" = "pkslow" "seq" = "2" }, { "age" = "29" "name" = "Jeremy" "seq" = "3" }, ])
Json解析:
> jsonencode({"name"="Larry", "age"=18}) "{"age":18,"name":"Larry"}" > jsondecode("{"age":18,"name":"Larry"}") { "age" = 18 "name" = "Larry" }
URL:
> urlencode("Larry Deng/a/:/./@") "Larry+Deng%2Fa%2F%3A%2F.%2F%40"
YAML:
> yamlencode({"a":"b", "c":"d"}) "a": "b" "c": "d" > yamlencode({"foo":[1, 2, 3], "bar": "baz"}) "bar": "baz" "foo": - 1 - 2 - 3 > yamlencode({"foo":[1, {"a":"b","c":"d"}, 3], "bar": "baz"}) "bar": "baz" "foo": - 1 - "a": "b" "c": "d" - 3 > yamldecode("hello: world") { "hello" = "world" } > yamldecode("true") true > yamldecode("{a: &foo [1, 2, 3], b: *foo}") { "a" = [ 1, 2, 3, ] "b" = [ 1, 2, 3, ] }
文件处理:
获取绝对路径:
> abspath(path.root) "/Users/larry"
获取路径中的目录,或者是文件名:
> dirname("/home/larry/soft/terraform") "/home/larry/soft" > dirname("/home/larry/soft/terraform/") "/home/larry/soft/terraform" > basename("/home/larry/soft/terraform") "terraform" > basename("/home/larry/soft/terraform/") "terraform"
判断文件是否存在,并获取文件内容:
> fileexists("/Users/larry/.bash_profile") true > file("/Users/larry/.bash_profile") > filebase64("/Users/larry/.bash_profile")
根据模式匹配所有文件:
> fileset("/Users/larry", "*.bash*") toset([ ".bash_history", ".bash_profile", ".bash_profile.backup", ])
templatefile(path, vars)模板化文件:指定文件和变量,把变量值替换掉模板中的变量。
时间函数
获取当前时间,并格式化显示,格式请参考:https://www.terraform.io/language/functions/formatdate
> formatdate("YYYY-MM-DD hh:mm:ss / D MMMM YYYY", timestamp()) "2022-03-05 08:25:48 / 5 March 2022" > formatdate("EEEE, DD-MMM-YY hh:mm:ss ZZZ", "2018-01-02T23:12:01Z") "Tuesday, 02-Jan-18 23:12:01 UTC"
时间加减:
> timeadd(timestamp(), "24h") "2022-03-06T08:28:52Z" > timeadd(timestamp(), "-24h10m") "2022-03-04T08:19:08Z"
支持的单位有:"ns", "us" (or "µs"), "ms", "s", "m", and "h".
其它
加密:
> md5("www.pkslow.com") "97e164b60faf4d7875c2a8a5bc3f2245"
UUID:
> uuid() "049bf418-15d1-e034-28db-92945067dcf6"
IP:
> cidrsubnet("172.16.0.0/12", 4, 2) "172.18.0.0/16"
更多请参考官网。