はじめに
こんにちは。Wano株式会社エンジニアのnariと申します。
7月からある新規のプロジェクトでterraform職人デビューしました。
絶賛IaCにハマり、tfファイルと格闘する毎日を過ごしております。
moduleといえば、Terraform module Registryは実装の参考にはなるけれど、moduleとしてusecaseが狭かったり、外部に依存したくなかったりで、結局ローカルにprivate moduleを作ることが多いと思います。
その際痛感したのが、
汎用的なmodule作るのって、難しい。。。
あまり凝りすぎて可読性が落ちたり使いづらくならない範囲で、用途の広いmoduleが欲しい。。
そこで自分がmoduleを作るときに、便利だなと思って使用しているtipsを3つ紹介したいと思います。
想定読者
- 最近terraformerになった人
-
Pragmatic Terraform on AWSを読了し、実際のmodule作りに励んでいる方
-> terraformerになりたい方は「Pragmatic Terraform on AWS」が神本だったので紹介するをまず読んでください! - terraform 0.12.0にupgradeしようとされている方
TL;DR
-
汎用的なmodule作りには
- optionalなfield -> variableのdefault値 null
- optionalなargument -> dynamic block+三項演算子
- optionalなresource -> count+三項演算子
実行環境
terraform 0.12.0
汎用的なmoduleの特徴
- requiredが少ない
- optionalが多く、様々な用途に対応できる
汎用的moduleを作るためのtips3選
1.variableのdefault値でnullを使用し、optionalなfieldを設定
module example
/* codebuild */
resource "aws_codebuild_project" "default" {
...
source {
type = var.source_type
location = var.source_location
buildspec = var.buildspec
}
...
}
/* optional source_typeがs3の場合required*/
variable "source_location" {
default = null
}
説明
- valiableのdefault値でnullを使用することで、設定しない限りそのfieldは無いものとして扱われる
- null値の導入は0.12.0から
- ある条件下でのみ設定したいfieldに使用する(今回で言えばsource_type=s3)
2.dynamic blockと三項演算子を使用し、optionalなargumentを設定
module example
/* ecs sercie */
resource "aws_ecs_service" "default" {
...
dynamic load_balancer {
//is_load_balancer_modeがfalseならこのargument設定されない
for_each = var.has_load_balancer ? {dummy:"hoge"} : {}
content {
target_group_arn = var.target_group_arn
container_name = var.container_name
container_port = var.container_port
}
}
...
}
/* optional*/
variable "has_load_balancer" {
description = "もしload_balancer argumentを設定したいなら、trueを入れる"
default = false
}
/* has_load_balancerがtrueなら requierd */
variable "target_group_arn" {
default = null
}
variable "container_name" {
default = null
}
variable "container_port" {
default = null
}
説明
- has_load_balancerのflagを設定し、dynamic blockと三項演算子を使用することで、load_balancerを設定する場合もしない場合も対応可能なecs sercviceのmoduleが作れる
- 三項演算子とは? -> 三項演算子
- dynamic blockとは? -> Expressions
- dynamic blockの導入は0.12.0から
- has_load_balancer=falseの場合は、空のmapを設定することで、argumentが設定されない
- has_load_balancer=trueの場合はkey valueが1組のmapを設定することで、argumentが1つ設定される(コードが汚いのでなんとかならないかな、、要検討)
3.countと三項演算子を使用し、optionalなresourceを設定
module example
resource "aws_iam_user_login_profile" "default" {
count = var.has_login_profile ? 1 : 0
user = aws_iam_user.default.name
pgp_key = var.pgp_key
}
/*if you want to login as this user, required*/
variable "has_login_profile" {
default = false
}
説明
- 例えば、コンソールログインできるuserもできないuserも作れるmoduleにしたい、という場合resource丸々がoptionalとして扱いたくなる
- そこで、has_login_profileのようなフラグを用意して、trueならcount=1でlogin_profileを生成する,falseならcount=0でlogin_profileを生成しないとしてやる
終わりに
0.12.0で追加された話としては、object型が便利だなぁとか色々あると思いますが、今日はこの辺で。
今回紹介したサンプルなど、awsのresource系のmoduleはこちらのリンクに掲載してますので、ご参考にしてください。
terraformerとしてスーパービギナーですので至らぬところたくさんあると思いますのでご指摘お待ちしております。
最近全然記事書けてなかったので、今日明日で溜まってたトピックでいっぱい記事書こうと思います