В цьому пості трохи подивимось на типи даних, які можемо використовувати в Terraform, щоб простіше розібратись з наступним постом – Terraform: цикли count, for_each та for.
Документація – Type Constraints та Types and Values.
Маємо наступні типи поділені на групи:
- Primitive Types:
string: послідовність Unicode символів, простий текстnumber: числові значенняbool: true або false
- Complex Types:
- Collection Types:
list: список – тип структури для зберігання простої колекції значень одного типу, доступних по індексамmap: колекція key:value значень одного типуset: аналогічнаlist, але без індексів та сортування
- Structural Types:
object: для зберігання значені різних типів даних – набір іменованих атрибутів, кожен з власним типом данихtuple: послідовність елементів, кожен з власним типом даних, з індексами як уlist
- Collection Types:
Зміст
Primitive types
Найпростіший тип, в якому можемо зберігати тільки одне значення певного типу.
string
Приклад:
variable "var_string" {
type = string
default = "a string"
}
output "string" {
value = var.var_string
}
Результат очевидний:
... Outputs: string = "a string"
number
Аналогічно, але для integer значень:
variable "var_number" {
type = number
default = 1
}
output "number" {
value = var.var_number
}
Результат:
... Outputs: number = 1
bool
Використовується для Conditional Expressions:
variable "var_bool" {
type = bool
default = true
}
output "number" {
value = var.var_bool ? "True" : "False"
}
Результат:
... Outputs: number = "True"
Або створення ресурсу, якщо умова дійсна:
resource "local_file" "file" {
count = var.var_bool ? 1 : 0
filename = "file.txt"
content = var.var_string
}
Collection Types
list
Послідовність значень одного типу з індексами, починаючи з нуля.
При створенні list можна або не вказувати тип (default == any), або обмежити одним певним типом:
variable "var_list_any" {
type = list
default = ["a string", 10]
}
variable "var_list_string" {
type = list(string)
default = ["first string", "second string"]
}
resource "local_file" "file" {
filename = "file-${var.var_list_any[1]}.txt"
content = var.var_list_string[0]
}
output "list_any" {
value = var.var_list_any
}
output "list_string" {
value = var.var_list_string
}
Результат:
... Outputs: list_any = tolist([ "a string", "10", ]) list_string = tolist([ "first string", "second string", ])
І файл:
$ cat file-10.txt first string
В list можна використовувати інші типи даних – інші list, map тощо.
При цьому в одному list можуть бути різні типи примітивів (string, number, bool), але однаковий тип для інших типів, тобто:
variable "var_list_any" {
type = list
default = ["a", true, 1]
}
variable "var_list_lists" {
type = list
default = [
["a", "b"],
["c", "d"]
]
}
output "list_any" {
value = var.var_list_any
}
output "list_lists" {
value = var.var_list_lists
}
Результат:
...
Outputs:
list_any = tolist([
"a",
"true",
"1",
])
list_lists = tolist([
[
"a",
"b",
],
[
"c",
"d",
],
])
Зі списками можемо використовувати цикли, наприклад:
variable "var_list_any" {
type = list
default = ["a string", 10]
}
variable "var_list_string" {
type = list(string)
default = ["first string", "second string"]
}
resource "local_file" "file" {
for_each = toset(var.var_list_any)
filename = "file-${each.key}.txt"
content = each.value
}
output "list_string" {
value = [ for a in var.var_list_string : upper(a)]
}
Результат:
... Outputs: list_string = [ "FIRST STRING", "SECOND STRING", ]
Та файли:
$ ls -1 file-10.txt 'file-a string.txt' $ cat file-a\ string.txt a string
map
Значення у формі key:value з доступом до значення по імені ключа:
variable "var_map" {
type = map
default = {
"one" = "first",
"two" = "second"
}
}
output "map_one" {
value = var.var_map["one"]
}
output "map_two" {
value = var.var_map["two"]
}
Також в outputs можемо вивести атрибут, тобто value = var.var_map.one.
Результат:
... Outputs: map_one = "first" map_two = "second"
Також з map можемо використати lookup() для пошуку значення по ключу:
output "map_lookup" {
value = lookup(var.var_map, "one", "None")
}
Результат:
... Outputs: map_lookup = "first" map_one = "first" map_two = "second"
Або більш складний приклад – вибір кількості інстансів за ціною в залежності від типу:
variable "instance_cost" {
type = map
default = {
"t3.medium" = "0.04USD",
"t3.large" = "0.08USD",
}
}
variable "instance_number" {
type = map
default = {
"0.04USD" = 2,
"0.08USD" = 1,
}
}
output "instances_count" {
value = lookup(var.instance_number, var.instance_cost["t3.medium"], 0)
}
Результат:
... Outputs: instances_count = 2
map також може включати в себе list або інший map, але всі об’єкти мають бути одного типу (тобто, не можна мати map в якому будуть і list, і другий map):
variable "var_map_of_maps" {
type = map
default = {
"out-map-key-1" = {
"in-map-key-1" = "inner map 1 key one",
"in-map-key-2" = "inner map 1 inner key two",
},
"out-map-key-2" = {
"in-map-key-1" = "inner map 2 key one",
"in-map-key-2" = "inner map 2 key two",
},
}
}
output "map_of_maps" {
value = var.var_map_of_maps
}
Результат:
...
Outputs:
map_of_maps = tomap({
"out-map-key-1" = {
"in-map-key-1" = "inner map 1 key one"
"in-map-key-2" = "inner map 1 inner key two"
}
"out-map-key-2" = {
"in-map-key-1" = "inner map 2 key one"
"in-map-key-2" = "inner map 2 key two"
}
})
set
Послідовність значень одного або різних типів як в list, але без індексів та сортування:
variable "var_set_any" {
type = set(any)
default = ["string", 1]
}
variable "var_set_string" {
type = set(string)
default = ["string1", "string2"]
}
output "set_any" {
value = var.var_set_any
}
output "set_string" {
value = var.var_set_string
}
Результат:
... ... Outputs: set_any = toset([ "1", "string", ]) set_string = toset([ "string1", "string2", ])
Як і list або map, set може мати вкладені типи:
variable "var_set_lists" {
type = set(list(any))
default = [
["a", "b"],
["c", "d"]
]
}
output "set_any" {
value = var.var_set_lists
}
Результат:
...
set_any = toset([
tolist([
"a",
"b",
]),
tolist([
"c",
"d",
]),
])
Structural Types
object
На відміну від map та list, object є структурним типом, який може мати значення різних типів, в тому числі включати в себе типи list та map.
Схож на Struct в C або Golang:
variable "var_object" {
type = object({
name = string,
id = number,
data = list(string)
data_map = map(any)
})
default = {
name = "one",
id = 10,
data = ["first", "second"],
data_map = {
"one" = "first",
"two" = "second"
}
}
}
output "object" {
value = var.var_object
}
output "object_map" {
value = var.var_object.data_map
}
Результат:
...
Outputs:
object = {
"data" = tolist([
"first",
"second",
])
"data_map" = tomap({
"one" = "first"
"two" = "second"
})
"id" = 10
"name" = "one"
}
object_map = tomap({
"one" = "first"
"two" = "second"
})
tuple
Подібний до object, але з індексами замість імен ключів:
variable "var_tuple" {
type = tuple ([
string,
number,
list(string),
map(any)
] )
default = [
"one",
10,
["first", "second"],
{
"one" = "first",
"two" = "second"
}
]
}
output "tuple" {
value = var.var_tuple
}
output "tuple_map" {
value = var.var_tuple[3]
}
Результат:
Outputs:
tuple = [
"one",
10,
tolist([
"first",
"second",
]),
tomap({
"one" = "first"
"two" = "second"
}),
]
tuple_map = tomap({
"one" = "first"
"two" = "second"
})
В наступному пості подивимось на цикли.