回鍋沒多久就踩到 Terraform 雷到不行的茶包,最近在設計 terraform-aws-web 這個模組的 aws_security_group_rule 時候有參考官方 terraform-aws-security-group 的寫法,在 count 的地方利用 length 去算 variable input 進來有幾個 list 進而產生多個 rule。
module 像是這樣判斷:
resource "aws_security_group_rule" "ingress_with_source_security_group_id" { count = "${length(var.web_ingress_source_security_group_id)}" ... }
然後使用模組的時候可以這樣丟進來:
web_ingress_source_security_group_id = [ { rule = "http-80-tcp" source_security_group_id = "${var.alb_sg_id}" }, { rule = "https-443-tcp" source_security_group_id = "${var.alb_sg_id}" } ]
這樣看起來是可以彈性的建立 resource 沒錯 … 但好景不常,小弟習慣把自己建起來的整包 terraform destroy 後再 apply … 來驗證拿到另一個環境真的能動,結果 destroy 後就壞了
aws_security_group_rule.ingress_with_source_security_group_id: value of ‘count’ cannot be computed
count 的值不能被計算 ?
這個錯誤訊息很不合理,因為在 apply 的時候可以使用 length 計算出 count 的數量,但反覆驗證後發現只有在 destroy 才發生 count 無法計算的錯誤?
這個問題其實在「terraform modules value of count cannot be computed#12570」討論的沸沸揚揚,從 2017/03 就出現的問題留到現在 …
其原因是 count 只能計算已知的數值,對於不存在的數值會有問題 … 所以 destroy 就壞了
The current constraint is that count may only use values that can be known at plan time.
然後官方建議是不要使用有任何 dependency 的 variable,或者是用 -target 例外處理這個 resource
文中還有人提到用 locals 來處理 length 計算後再丟到 count,不過不曉得為什麼我用起來不能動 …
所以我參考 terraform-aws-security-group 的作法,額外加一個 static variable 給 count (單純覺得用 -target 會忘記),所以 module 會變這樣:
variable "web_number_of_ingress_source_security_group_id" { description = "The Security Group ingress number other security group source id of Web." default = "0" } resource "aws_security_group_rule" "ingress_with_source_security_group_id" { count = "${var.web_number_of_ingress_source_security_group_id}" ... }
使用 module 會麻煩一點 …
web_ingress_source_security_group_id = [ { rule = "http-80-tcp" source_security_group_id = "${var.alb_sg_id}" }, { rule = "https-443-tcp" source_security_group_id = "${var.alb_sg_id}" } ] web_number_of_ingress_source_security_group_id = 2
如果 destroy 就會用 module 預設的 0,解法有好幾種,但都不是很好用,只能等官方解。