2

详解 Terraform 基础语法及常见函数

 1 year ago
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.
neoserver,ios ssh client

详解 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 支持以下类型的运算符:

  • 算术运算符:操作数和结果都为数字类型,包括:+,-(减法),*,/,%,-(负数)。
  • 关系运算符:操作数为任意类型,结果为布尔值,包括:==,!=。
  • 比较运算符:操作数为数字类型,结果为布尔值,包括:>,>=,<,<=。
  • 逻辑运算符:操作数和结果都为布尔类型,包括:||,&&,!。

在表达式中使用多个运算符时,将按照以下优先级进行求解:

  1. !, - (负数)
  2. *, /, %
  3. +, - (减法)
  4. >, >=, <, <=
  5. ==, !=

条件表达式

条件表达式采用布尔表达式的值进行二选一,其语法可以表示为:

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 替换成 str2replace("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 中的所有 keykeys({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

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK