《Terraform 101 從入門到實踐》 Functions函式

南瓜慢說發表於2023-02-18
《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.com\n")
"www.pkslow.com"
> chomp("www.pkslow.com\n\n")
"www.pkslow.com"
> chomp("www.pkslow.com\n\n\r")
"www.pkslow.com"
> chomp("www.pkslow.com\n\n\ra")
<<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 \n\r")
"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/lang...

集合類函式

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,age\n1,larry,18\n2,pkslow,3\n3,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/lang...

> 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"

更多請參考官網。

相關文章