tl;dr
- この記事はterraform Advent Calendar 2020の4日目です
- 先日同僚のコードをレビューした時に merge の使いどころについて解説したんだけどちょっと整理しようかなって
- merge の順序だけでも意図があるんだよって
- ぶっちゃけカレンダーに穴を開けないようにしたいだけw
元のコード
aws関係の自作モジュールで tags を渡すところが微妙だった。
a.tf
module a {
source = "../modules/hoge"
(省略)
tags = {
Project = "X"
Env = "prod"
Make = "terraform"
}
}
module/hoge/
variable "tags" {
description = "tags"
type = map
default = {
Project = ""
Make = "terraform"
Env = ""
}
}
resource aws_hoge {
(省略)
tags = var.tags
}
もちろん動くけれども。
なにがダメか
- tags の default 部分は呼び出し側の値をバリデートしていないので値が自由になる(バリデーションは今回の用向きには必要ないので対象外)
- Make = "terraform" って、呼び出し側が書いてたら意味ない
- それはつまり Make タグの値を他の値にしてしまうことも可能になる(Make:Ansible とかねw)
- この module を使ったらタグに Make:terraform が付くんだよ、という意図を持たせたかったはずなんだけど。。。
ダメな直し
module/hoge/
locals {
tags = {
Make = "terraform"
}
}
variable "tags" {
description = "tags"
type = map
default = {}
}
resource aws_hoge {
(省略)
tags = merge(local.tags, var.tags)
}
惜しい。けど、merge() は後勝ちなので、呼び出し側で Make = "ansible" って書いたら結局それになっちゃう。
あえて意図をつけるなら、Make ってタグを渡さなくても自動で terraform が付くよ。書き換えてもいいよ。になってしまう。
たぶん違うタグで違う用途ならアリかもしれないが、今回には当てはまらない。
少なくてもロジックとして考えた場合、好きな値に出来てしまうなら最初からデフォルト値なんか持たせる必要がなかった。つまりただの考慮漏れに見えてしまう。
Make:terraform を死守するための直し
tags = merge(var.tags, local.tags)
これなら Make:terraform を死守できる。
意図しているところは、このモジュールを使うと Make:terraform というタグが付く。違う値にはさせない。消すこともさせない。になる。
(そしてこの意図は他のタグやアトリビュートでも同じように使える大事なことだ)
(おまけ)そこまで考える必要ある?
- 自作モジュールだし、動けばいいんだよって意見はごもっとも。一緒には仕事したくないけどw
- 別の値にしたい奴には好きにやらせればいいじゃんって意見には、まぁ好きにすればと。インターネット老人会またはPerlユーザならそう考えるのもわかる。
- 意図とかコメントしておけばいいんじゃんって意見には、まぁ反対はする。コードが読めないメンバーを慮って説明をコメントするのはリーダブルコード的にも美しくない。
- スケジュールとか手間とかって意見には、仕事のQEDを勉強しなおしてきてねって。話はそれからだ。
- 異論は認めるw
(おまけ2)たとえば
- 例えば PowerdBy とか、BaseCode とか、モジュールを使っていることを明示的にタグで残す、のはリソース管理の観点からもお勧め
- 例えば Name タグを後ろに書いてあるモジュールは多い(Nameの値をソレにする意図がある)
- 例えば aws vpc module とかを見て、意図を考えるのとても勉強になる
最後に
神は細部に宿るって言うし、ちょっとでもいいコードをしゅっと書けるようになりたい。