Terraform未宣言リソースの対処法
冒頭まとめ terraform planやterraform validateで次のエラーが出た場合、参照先のリソースが現在のモジュールに宣言されていません。 Error: Reference to undeclared resource A managed resource "aws_security_group" "main" has not been declared in the root module. 最初に、説明文の型名aws_security_groupとラベル名mainを確認してください。同じモジュール内にresource "aws_security_group" "main"という宣言があるかを探します。ラベルのタイプミス、data.の付け忘れ、別モジュールのリソースを直接参照していることが主な確認点です。 クラウド上やstateにリソースが存在していても、設定内の宣言の代わりにはなりません。参照している式と、その式から見える宣言を確認する必要があります。 エラーメッセージの意味 通常の管理対象リソースは<型名>.<ラベル名>.<属性名>で参照します。たとえばaws_security_group.main.idでは、aws_security_groupが型、mainがresourceブロックのラベル、idが属性です。 ラベルはTerraformの設定内で使う名前です。AWS側の名前を設定するname = "web-sg"などの値とは別なので、そこが一致していても参照は成立しません。 Terraformの参照の公式文書は、管理対象リソース、データソース、モジュール出力を別の形式として説明しています。 参照先 参照の形式 管理対象リソース aws_instance.web.id データソース data.aws_ami.ubuntu.id 子モジュールの出力 module.network.vpc_id 入力変数 var.instance_count ローカル値 local.common_tags 本体のevaluate_valid.goでは、参照しているモジュールの設定からリソース宣言を探し、見つからなければこの診断を作ります。stateに記録されているかを調べることで、未宣言の参照を有効にする処理ではありません。 最初に型名・ラベル名・読込範囲を確認する エラーに表示されたファイルと行は、問題の参照が書かれた場所です。そこから参照先の宣言を探してください。 resource "aws_security_group" "web"しかないのにaws_security_group.main.idを参照していれば、ラベル名が違っています。エディターの検索で、型名とラベル名をそれぞれ確認できます。 宣言が別ファイルにある場合は、そのファイルの場所も確認します。同じディレクトリの.tf・.tf.jsonは一つのモジュールとして読み込まれますが、サブディレクトリのファイルは自動では取り込まれません。この範囲は設定ファイルの公式文書に明記されています。 たとえば、main.tfと同じ場所のresources.tfへ宣言を移すだけなら同じモジュールです。modules/network/main.tfへ移した場合は別モジュールになるため、元の場所から同じ参照を続けることはできません。 CLIでは通常、コマンドを実行したディレクトリがルートモジュールです。ローカルとCIで結果が違う場合は、実行ディレクトリや-chdirの指定、対象ファイルがCIに含まれているかも確認してください。 タイプミスとdata.の付け忘れを直す タイプミスなら、参照側を実際の宣言に合わせます。次は組み込みリソースterraform_dataを使った説明用の例です。 resource "terraform_data" "web" { input = "example" } output "value" { # 誤り:mainというラベルの宣言がない value = terraform_data.main.output } 宣言をそのまま使う場合は、outputの参照を次のように直します。 ...