起きたこと
利用しているAWS WAFv2の社内モジュールでは、変数に応じてマネージドルール or IPset or regexルールをACLに登録する仕組みにしています。 ipsetやregexのルールはまた別のモジュールで指定しているので、WAFモジュール側でどのルールを渡されたかlookup()を用いて判定しようとしています。
# ipruleモジュール resource "wafv2_iprule" { ... output = { name = this.name arn = this.arn } } # WAFv2モジュール resource "wafv2_webacl" { for_each = lookup(var.iprule, "arn", false) == false ? [] : [""] .... for_each = lookup(var.regex, "arn", false) == false ? [] : [""] ....
こんな感じで使っています
module "huga"{ source = "hogehoge" ... iprule = { # ここをregexとかmanagedに変更すると指定ルールに応じた実装になる rule_arn = "" } }
この実装だと、managedruleのようなarnがあらかじめ定まっている場合を除き、うまく動作しません。 ipruleとregexどちらも存在するかのように判定してしまい、変数のobject構造がmoduleの期待とズレてしまいます。
原因
lookup()は引数の対象オブジェクト内にある変数の解決を待たずに動作する(undefind状態のまま評価してしまう)ので、lookup(var.regex, "arn", false)
がエラーを返しており、デフォルト値であるfalseを返さないことが原因です。
map内部の変数は全部解決してから評価してほしいのに…
解決策
lookup()ではなくmoduleで変数の存在確認をするにはtry()を使いましょう。
モジュールをいじれない場合はruleのモジュールを先にapplyすると、tfstateからarnを引っ張ってきて式を評価するのでワークアラウンドとしては -target
を使ってapplyするのも一つの手です。