详解 Terraform 基础语法及常见函数
source link: https://www.fdevops.com/2023/01/18/terraform-31237
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
详解 Terraform 基础语法及常见函数
本文介绍一下 Terraform 配置代码的基础语法。
通过对本文的学习,能更快的、更高效的了解并使用 Terraform。
Terraform 配置语言主要基于 HCL 语法,具有配置简单,可读性强等特点,并且兼容 JSON 语法。
Terraform 配置语言主要由参数 (Argument),块 (Block),表达式 (Experssion) 和函数 (Functions) 组成。
参数 (Argument)
使用等号 (=) 将一个值或表达式赋值给指定的参数名称,参数名称可以使用字母、数字、 下划线 (_) 和连接符 (-) 表示,且首字母不能是数字,例如:
image_id = "ad091b52-742f-469e-8f3c-fd81cadf0743"
块 (Block)
块将多个参数聚合在一起,并支持嵌套。
块由块类型、块标签和块主体构成,格式如下:
resource "huaweicloud_compute_instance" "myinstance" {
name = "myinstance"
......
network {
uuid = "55534eaa-533a-419d-9b40-ec427ea7195a"
}
}
在使用块时必须先声明其对应的类型,样例中 resource 和 network 均为块类型,其中 resource 为顶层块类型,network 为嵌套块类型。
Terraform 支持的顶层块类型包括: provider,resource,data,variable,output,module,locals 等关键字。
块标签在块类型之后定义,且数量由块类型决定,样例中 resource 块类型包含两个标签:huaweicloud_compute_instance 和 myinstance,嵌套的 network 类型没有块标签。
块主体定义在块最后,由 { 和 } 字符进行封装,在块主体内可以嵌套其他类型以实现不同的层级结构。
更多详细信息,请参见 Terraform 的配置语法文档。
Terraform支持以下参数类型:
- string:字符串类型,由一个或多个 Unicode 字符组成,例如 "hello"。
- number:数字类型,可以表示整数和浮点数。
- bool:布尔类型,只能是 true 或 false。
Terraform 能够根据参数类型自动将 number 和 bool 类型转换为 string 类型。
如果一个字符串能够表示为一个数字或布尔类型的值,Terraform 也可以进行反向转换。
字符串、 数字和布尔类型的参数可以直接赋值,例如:
disk_type = "SSD"
disk_size = 40
enable = true
# 支持使用字符串表示数字和布尔类型
disk_size = "40"
enable = "true"
- map (...):映射类型,以键值对 (key-value pair) 的方式组合起来的数据元素集合,其中 key 为 string 类型,对应的值可以是 string,number,bool 等类型,且所有元素的值必须是同一类型。
- list (...):列表类型,具有同类型的数据元素集合,元素可以是基本类型和块类型,列表索引从 0 开始。
- set (...):集合类型,类似于列表类型,但是集合中的元素是没有任何辅助标识符或顺序,且元素具有唯一性。
映射类型使用 {} 封装,其表示形式非常灵活:键值对可以使用等号 "=" 或冒号 ":" 连接;如果 key 不以数字开头,可以不加双引号;对于多行映射,键值对之间可以使用换行符或者逗号进行分隔。
推荐使用等号 (=) 连接键值对并用换行符进行分隔,例如:
# 推荐格式
tags = {
foo = "bar"
key = "value"
}
# 其他格式
tags = {"foo" = "bar", "key" = "value"}
tags = {"foo" : "bar", "key" : "value"}
tags = {foo = "bar", key = "value"}
tags = {foo : "bar", key : "value"}
tags = {
foo : "bar"
key : "value"
}
列表类型和集合类型的表示方式相同,其中元素为基本类型的列表/集合使用 [] 封 装,元素为块类型的列表/集合使用重复块的形式表示,例如:
# 基本类型的列表
security_groups = ["default", "internal"]
# 块类型的列表
network {
uuid = "55534eaa-533a-419d-9b40-ec427ea7195a"
}
network {
uuid = "ad091b52-742f-469e-8f3c-fd81cadf0743"
}
- null:空类型,如果将一个参数设置为 null,表示这个参数未填写,Terraform 会自动忽略该参数,并使用默认值。null 在条件表达式中较为常见,如 var.test=="" ? null : var.test,表示当 var.test 的值为 "" 时,就将其忽略。
单行注释以 # 或 // 开头;
多行注释 /* 开始,以 */ 结束,不支持嵌套块注释。
Terraform 配置文件使用 UTF-8 编码,对于标识符、注释和字符串都支持非 ASCII 字符。
多行字符串在一行末尾以
<<EOF
开头,中间是字符串内容,最后以EOF
结尾。EOF
也可以替换为其他字符。例如:
resource "huaweicloud_obs_bucket" "web_bucket" {
...
website {
...
routing_rules = <<EOF
[{
"Condition": {
"KeyPrefixEquals": "docs/"
},
"Redirect": {
"ReplaceKeyPrefixWith": "documents/"
}
}]
EOF
}
}
Terraform 约定了一些惯用的风格样式,以确保不同团队编写的文件和模块的风格一致性。
建议用户遵循这些约定,推荐的样式约定如下:
对于每个嵌套级别,缩进两个空格。
当多个单行的参数在同一嵌套级别连续出现时,建议将等号对齐。
name = "myinstance" availability_zone = "cn-north-1a"
使用空行分隔块中的逻辑参数组。
当块主体同时包含参数和块时,建议将所有参数放在顶部,嵌套块放在参数的下方并使用空行隔开。
将元参数 (meta-arguments) 放在块主体的顶部,并使用空行与其它参数隔开;将元参数块 (meta-argument blocks) 放在块主体的最后,并用空行与其他块隔开。
resource "huaweicloud_obs_bucket" "demo" { count = 1 bucket = "bucket_demo" acl = "public-read" tags = { foo = "bar" env = "test" } lifecycle { create_before_destroy = true } }
顶层块之间使用空行将彼此隔开。
建议将相同类型的嵌套块放在一起,不同类型的嵌套块使用空行隔开。
https://www.terraform.io/docs/configuration/style.html
表达式用于引用或计算配置中的值,最简单的表达式是文字表达式,如 "hello world" 或 5。
Terraform 支持多种表达式,包括运算符、条件表达式以及丰富的内置函数。
通过 "terraform console" 命令可以打开一个交互式的控制台,我们可以使用该控制台进行表达式及内置函数的体验和测试。
运算符是执行特定的数学或逻辑操作的服务,Terraform 支持以下类型的运算符:
- 算术运算符:操作数和结果都为数字类型,包括:+,-(减法),*,/,%,-(负数)。
- 关系运算符:操作数为任意类型,结果为布尔值,包括:==,!=。
- 比较运算符:操作数为数字类型,结果为布尔值,包括:>,>=,<,<=。
- 逻辑运算符:操作数和结果都为布尔类型,包括:||,&&,!。
在表达式中使用多个运算符时,将按照以下优先级进行求解:
- !, - (负数)
- *, /, %
- +, - (减法)
- >, >=, <, <=
- ==, !=
条件表达式
条件表达式采用布尔表达式的值进行二选一,其语法可以表示为:
condition ? true_value : false_value
该语句表示:如果 condition 为true,结果为 true_value,否则为 false_value。条件表达式的结果可以是任意类型,但 true_value 和 false_value 的类型必须保持一致。
条件表达式的常见用法是使用默认值替换无效值,如下:
var.a != "" ? var.a : "default-a"
该语句表示:如果 var.a 的值不为空,则返回 var.a 的值,否则返回一个默认值。
for 表达式
for 表达式用于遍历集合类型 (map、list、set) 中的每个元素,并对元素进行处理,最 后将结果输出为一个新的集合类型。
for 表达式的输出结果取决于所使用的括号类型:
- 使用 '[' 和 ']' 将生成一个列表
- 使用 '{' 和 '}' 将生成一个映射/对象
假设列表 mylist 的值为 ["AA", "BBB", "CCCC"],我们可以使用for表达式对 mylist 中的每个字符串元素转换为小写,并输出一个列表:
> [for str in var.mylist : lower(str)]
[
"aa",
"bbb",
"cccc",
]
我们也可以将结果输出为一个映射,映射关系通过 "=>" 确定:
> {for str in var.mylist : str => lower(str)}
{
"AA" = "aa"
"BBB" = "bbb"
"CCCC" = "cccc"
}
映射类型也可以通过 for 表达式转换进行处理,假设 mymap 的值为 {element1="aaa", element2="bbb", element3="ccc"},我们可以将映射中的每个键值转换为大写:
> {for key, value in var.mymap : key => upper(value)}
{
"element1 = "AAA"
"element2 = "BBB"
"element3 = "CCC"
}
此外,for 表达式还可以使用 if 语句对元素进行过滤:
> [for str in var.list : upper(str) if length(str) >= 3]
[
"bbb",
"cccc",
]
https://www.terraform.io/docs/configuration/expressions.html
Terraform 支持丰富的内置函数,用于处理字符串、数值计算、加密,类型转换等操作,我们可以通过函数名称进行调用,其语法如下:
<函数名称>(<参数1>, <参数2> ...)
本文主要对 Terraform 中常见的函数进行总结并通过样例说明其用法。
通过 Terraform 官方文档可以查看完整的函数支持列表。
字符串函数
函数名称 | 函数描述 | 样例 | 运行结果 |
---|---|---|---|
format | 字符串格式化 | format("Hello, %s!", "Huaweicloud") | Hello, Huaweicloud! |
lower | 将字符串中的字母转换为小写 | lower("HELLO") | hello |
upper | 将字符串中的字母转换为大写 | upper("hello") | HELLO |
join | 使用自定义字符将列表拼接成字符串 | join(", ", ["One", "Two", "Three"]) | One, Two, Three |
split | 根据分隔符拆分字符串 | split(", ", "One, Two, Three") | ["One", "Two", "Three"] |
substr | 通过偏移量和长度从给定的字符串中提取一个子串 | substr("hello world!", 1, 4) | ello |
replace | 把字符串中的 str1 替换成 str2 | replace("hello, huaweicloud!", "h", "H") | Hello, Huaweicloud! |
数值计算函数
函数名称 | 函数描述 | 样例 | 运行结果 |
---|---|---|---|
abs | 计算绝对值 | abs(-12.4) | 12.4 |
max | 计算最大值 | max(12, 54, 6),max([12, 54, 6]...) | 54, 54 |
min | 计算最小值 | min(12, 54, 6),min([12, 54, 6]...) | 6, 6 |
log | 计算对数 | log(16, 2) | 4 |
power | 计算x的y次幂 | power(3, 2) | 9 |
函数名称 | 函数描述 | 样例 | 运行结果 |
---|---|---|---|
element | 通过下标从列表中检索对应元素值 | element(["One", "Two", "Three"], 1) | Two |
index | 返回给定值在列表中的索引,如果该值不存在将报错 | index(["a", "b", "c"], "b") | 1 |
lookup | 使用给定的键从映射表中检索对应的值。如果给定的键不存在,则返回默认值 | lookup({IT="A", CT="B"}, "IT", "G") ,lookup({IT="A", CT="B"}, "IE", "G") | A, G |
flatten | 展开列表中的嵌套元素 | flatten([["a", "b"], [], ["c"]] | ["a", "b", "c"] |
keys | 返回 map 中的所有 key | keys({a=1, b=2, c=3}) | ["a", "b", "c"] |
length | 获取列表、映射或是字符串的长度 | length(["One", "Two", "Three"]),length({IT="A", CT="B"}),length("Hello, Huaweicloud!") | 3, 2, 19 |
类型转化函数
函数名称 | 函数描述 | 样例 | 运行结果 |
---|---|---|---|
toset | 将列表类型转换为集合类型 | toset(["One", "Two", "One"]) | ["One", "Two"] |
tolist | 将集合类型转换为列表类型 | toset(["One", "Two", "Three"]) | ["One", "Two", "Three"] |
tonumber | 将字符串类型转换为数字类型 | tonumber("33") | 33 |
tostring | 将数字类型转换为字符串类型 | tostring(33) | "33" |
函数名称 | 函数描述 | 样例 | 运行结果 |
---|---|---|---|
base64en code | 将 UTF-8 字符串转换为 base64 编码 | base64encode("Hello, Huaweicloud!") | SGVsbG8sIEh1YXdlaWNsb3VkIQ== |
base64de code | 将 base64 编码解码为 UTF-8 字符串(结果非UTF-8格式会报错) | base64decode("SGVsbG8sIEh1YXdlaWNsb3VkIQ==") | Hello, Huaweicloud! |
base64gzi p | 将UTF-8字符串压缩 并转换为base64编码 | base64gzip("Hello, Huaweicloud!") | H4sIAAAAAAAA//JIzcnJ11HwKE0sT81MzskvTVEEAAAA//8BAAD//7SZqpwTAAAA |
哈希和加密函数
函数名称 | 函数描述 | 样例 | 运行结果 |
---|---|---|---|
sha256 | 计算字符串的 SHA256 值(16进 制) | sha256("Hello, Huaweicloud!") | bbb76b2eb48a6610c1c87c8828c9b22ee1a5f5ca4c5c91584be154def9404910 |
sha512 | 计算字符串的 SHA512 值(16进 制) | sha512("Hello, Huaweicloud!") | 61f1ce05848b7dd7b23ee6ed5f32d9ce7476066d1c4c7a2f6a8f9d51f8edabb569ab22af0c796d01b6291715eb844edaafb1da4d6b80ed343844 2016d42dac7b |
base64sha256 | 计算字符串的 SHA256 值,并转换为 base64 编码 | base64sha256("Hello, Huaweicloud!") | u7drLrSKZhDByHyIKMmyLuGl9cpMXJFYS+FU3vlASRA= |
base64sha512 | 计算字符串的 SHA512 值,并转换为 base64 编码 | base64sha512("Hello, Huaweicloud!") | YfH0BYSLfdeyPubtXzLZznR2Bm0cTHovao+dUfjtq7VpqyKvDHltAbYpFxXrhE7ar7HaTWuA7TQ4RCAW1C2sew== |
md5 | 计算 MD5 值 | md5("hello world") | 5eb63bbbe01eeed093cb22bb8f5acdc3 |
base64sha512("Hello, Huaweicloud!") 不等于 base64encode(sha512("Hello, Huaweicloud!")),因为 sha512 计算的十六进制值结果在 Terraform 中是 Unicode 编码格式,并没指定 UTF-8 实现。
文件操作函数
函数名称 | 函数描述 | 样例 | 运行结果 |
---|---|---|---|
abspath | 计算文件的绝对路径 | abspath("./hello.txt") | /home/demo/test/terraform/hello.txt |
dirname | 计算字符串中包含的路径 | dirname("foo/bar/baz.txt") | foo/bar |
basename | 计算字符串中的文件名 | basename("foo/bar/baz.txt") | baz.txt |
file | 读取文件并返回文件内容 | file("./hello.txt") | Hello, Huaweicloud! |
filebase64 | 读取文件并返回文件内容的base64编码 | filebase64("./hello.txt") | SGVsbG8sIEh1YXdlaWNsb3VkIQ== |
本文为转载文章,贵在分享,版权归原作者及原出处所有,如涉及版权等问题,请及时与我联系。
原文出处:huaweicloud
原文链接:https://support.huaweicloud.com/basics-terraform/basics-terraform.pdf
Recommend
-
1
Haskell 基本语法(四)高阶函数 发表于 2021-06-30 ...
-
8
《Terraform 101 从入门到实践》 第五章 HCL语法 《Terraform 101 从入门到实践》 第五章 HCL语法 ...
-
3
《Terraform 101 从入门到实践》这本书只将在南瓜慢说官方网站和GitHub两个地方同步更新,如果你在其它地方看到,那应该就是抄...
-
3
Jenkinsfile声明式语法详解原创 上篇文章对Jenkins pipeline入门做了简单介绍,简单见识了Jenkinsfile当中的几个常用的语法关键字,本文将针对声明式的语法进行详细解读,这种解读将会是手册性质的,会有讲解,必要的也会有简单实验演示,但是并...
-
12
shell脚本基本语法详解
-
2
C++的语法基础(六)⭐写在前面的话:本系列文章旨在短时间内回顾C/C++语法中的重点与易错点,巩固算法竞赛与写题过程中常用的语法知识,精准地解决学过但有遗忘的情况,为算法刷题打下坚实的基础。9.1函数基础一个典型的函...
-
1
🚩write in front🚩 🔎大家好,我是謓泽,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎 🏅2021年度博客之星物联网与嵌入式开发TOP5~2021博客之星Top100~阿里云专家博主 & 阿里云星级博主~掘金⇿InfoQ~51CTOP创...
-
5
javascript异步编程之generator(生成器函数)与asnyc/await语法糖 精选 原创 开水泡饭520...
-
4
《Terraform 101 从入门到实践》这本小册在南瓜慢说官方网站和GitHub两个地方同步更新,书中的示...
-
4
《Terraform 101 从入门到实践》这本小册在南瓜慢说官方网站和GitHub两个地方同步更新,书中的示...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK