よく変数の定義でmap(object())となっているのを見るので、どういうことなのかを調べた結果を共有。
結論
Object型で構造化した変数を、mapでコレクションとして扱っている。このようにすることで変数の管理がしやすくなり、少ない記述でたくさんのリソースを一気にプロビジョニングできる。
前提
oci_core_instance(https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_instance)
の一部で説明。
Objectを用いないとどうなるか
Objectを用いず変数を羅列すると、variables.tfは以下のようになる。
variable "availability_domain" {
type = string
}
variable "display_name" {
type = string
}
variable "shape" {
type = string
}
variable "source_details_source_type" {
type = string
}
variable "source_details_source_id" {
type = string
}
variable "create_vnic_details_assign_public_ip" {
type = bool
}
variable "create_vnic_details_subnet_id" {
type = string
}
variable "shape_config_baseline_ocpu_utilization" {
type = string
}
variable "shape_config_memory_in_gbs" {
type = string
}
variable "shape_config_ocpus" {
type = string
}
variable "metadata_ssh_authorized_keys" {
type = string
}
variable "metadata_user_data" {
type = string
}
たくさんの変数が羅列されており、どの変数とどの変数が関連するものかがぱっと見でわかりにくく、管理が難しくなる。
Objectを用いると...
上記のような変数たちを、Objectを用いて書き直すと以下のようにできる。
variable "instances" {
type = object({
availability_domain = string
display_name = string
shape = string
source_details = object({
source_id = string
})
create_vnic_details = object({
assign_public_ip = bool
subnet_id = string
})
shape_config = object({
baseline_ocpu_utilization = string
memory_in_gbs = string
ocpus = string
})
metadata = object({
ssh_authorized_keys = string
user_data = string
})
})
}
これで、各変数がどういった値なのかがぱっと見でわかるようになった。
mapを用いないとどうなるか
ではこの状態でインスタンスを二つプロビジョニングすることを考えてみる。すると、下記のようにvariables.tfを書く必要がある。
variable "instance1" {
type = object({
availability_domain = string
display_name = string
shape = string
source_details = object({
source_id = string
})
create_vnic_details = object({
assign_public_ip = bool
subnet_id = string
})
shape_config = object({
baseline_ocpu_utilization = string
memory_in_gbs = string
ocpus = string
})
metadata = object({
ssh_authorized_keys = string
user_data = string
})
})
}
variable "instance2" {
type = object({
availability_domain = string
display_name = string
shape = string
source_details = object({
source_id = string
})
create_vnic_details = object({
assign_public_ip = bool
subnet_id = string
})
shape_config = object({
baseline_ocpu_utilization = string
memory_in_gbs = string
ocpus = string
})
metadata = object({
ssh_authorized_keys = string
user_data = string
})
})
}
これでは明らかに冗長になっている。
mapを用いると...
上記の冗長な変数を、mapを用いてきれいに書き直してみる。
variable "instances" {
type = map(object({
availability_domain = string
display_name = string
shape = string
source_details = object({
source_id = string
})
create_vnic_details = object({
assign_public_ip = bool
subnet_id = string
})
shape_config = object({
baseline_ocpu_utilization = string
memory_in_gbs = string
ocpus = string
})
metadata = object({
ssh_authorized_keys = string
user_data = string
})
}))
}
変数の定義はObject型の定義にmap()を追加するだけでOK。変数の中身を設定するときは、以下のように設定できる。
instances = {
instance01 = {
availability_domain = ....
display_name = ....
shape = ....
source_details = {
source_id = ....
source_type = ....
}
shape_config = {
baseline_ocpu_utilization = ....
memory_in_gbs = ....
ocpus = ....
}
metadat = {
ssh_authorized_keys = ....
user_data = ....
}
}
instance02 = {
#同様に記述
}
}
このようにすることで、モジュールを呼び出すときは、以下のように呼び出せる。
module "instance" {
source = #モジュールの場所
compartment_id = #各モジュール共通の変数は切り出す
instances = var.instances
}
このように、モジュール呼び出しの部分が非常にシンプルに記述できる。