質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Terraform

Terraformは、インフラ構築のためのツールです。AWS/DigitalOcean/GoogleCloudといった様々なインフラに対応。インフラ構成のコード管理や変更の作業などの手間を自動化し、インフラ構築の効率化を図ることができます。

AWS(Amazon Web Services)

Amazon Web Services (AWS)は、仮想空間を機軸とした、クラスター状のコンピュータ・ネットワーク・データベース・ストーレッジ・サポートツールをAWSというインフラから提供する商用サービスです。

Q&A

1回答

5863閲覧

Terraform Moduleを使い別ディレクトリのリソースを参照させたい

Baloncesto

総合スコア7

Terraform

Terraformは、インフラ構築のためのツールです。AWS/DigitalOcean/GoogleCloudといった様々なインフラに対応。インフラ構成のコード管理や変更の作業などの手間を自動化し、インフラ構築の効率化を図ることができます。

AWS(Amazon Web Services)

Amazon Web Services (AWS)は、仮想空間を機軸とした、クラスター状のコンピュータ・ネットワーク・データベース・ストーレッジ・サポートツールをAWSというインフラから提供する商用サービスです。

0グッド

3クリップ

投稿2022/06/30 03:44

編集2022/06/30 05:24

表題の件で確認させてください。

現在以下フォルダ構成の環境でTerraform環境を構築しております。

├─tf-common │ │ output.tf │ │ provider.tf │ │ sns.tf │ │ terraform.tfvars │ └─tf-tenant │ .terraform.lock.hcl │ cloudwatch.tf │ provider.tf │ route53.tf │ Tenant-0041.tfvars │ └─.terraform │ terraform.tfstate

tf-tenantフォルダ配下でterraform planを実行すると以下のようにエラーとなりました。
sns_topicが参照できない旨のエラーとなるのですが、解決できず困っております。

│ Error: Reference to undeclared resource │ │ on cloudwatch.tf line 23, in resource "aws_cloudwatch_metric_alarm" "healthcheck": │ 23: alarm_actions = ["${aws_sns_topic.topic.arn}"] │ │ A managed resource "aws_sns_topic" "topic" has not been declared in the root module.

調べてみると、moduleを利用することで別フォルダのリリースを参照できるとのことなのですが、
今ひとつ使い方がわからず、困っております。

この環境の場合、どういったmoduleを利用することでsnsのリソースを参照させることができるのでしょうか?

念のためですが、cloudwatch.tfとsns.tfのコードは以下となります。
cloudwatch.tf

6 resource "aws_cloudwatch_metric_alarm" "healthcheck" { 7 count = length(aws_route53_health_check.HealthCheck) 8 provider = aws.virginia 9 alarm_name = var.targets[count.index].alarm_name 10 comparison_operator = "LessThanThreshold" 11 evaluation_periods = "1" 12 metric_name = "HealthCheckStatus" 13 namespace = "AWS/Route53" 14 period = "60" 15 statistic = "Minimum" 16 threshold = "1" 17 18 dimensions = { 19 HealthCheckId = aws_route53_health_check.HealthCheck[count.index].id 20 } 21 alarm_description = "Send an alarm if ${var.environment} is down" 22 actions_enabled = "true" 23 alarm_actions = ["${aws_sns_topic.topic.arn}"] }

sns.tf

resource "aws_sns_topic" "topic" { # name = var.sns_topic name = var.service_name provider = aws.virginia delivery_policy = jsonencode({ "http" : { "defaultHealthyRetryPolicy" : { "minDelayTarget" : 20, "maxDelayTarget" : 20, "numRetries" : 3, "numMaxDelayRetries" : 0, "numNoDelayRetries" : 0, "numMinDelayRetries" : 0, "backoffFunction" : "linear" }, "disableSubscriptionOverrides" : false, "defaultThrottlePolicy" : { "maxReceivesPerSecond" : 1 } } }) } resource "aws_sns_topic_subscription" "default" { topic_arn = aws_sns_topic.topic.arn provider = aws.virginia protocol = "lambda" endpoint = aws_lambda_function.default.arn }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

68user

2022/06/30 06:28

その前に、common:tenant が 1対多でいいんですかね。 そして全体を 1つの tfstate にするのはOK? どちらも yes であるなら、 module-common/ module-tenant/ main.tf という構成にして、main.tf は module "common" { source = "./module-common" } module "tenant1" { source = "./module-tenant" sns_topic = common.aws_sns_topic } module "tenant2" { source = "./module-tenant" sns_topic = common.aws_sns_topic } とかそういう感じです。 まずは tfstate を分けるかどうかを決めましょう。module 化はキレイに整理するための手段なのでどっちでも (module 化したほうがよいとは思いますが)。
68user

2022/06/30 06:31

> 調べてみると、moduleを利用することで別フォルダのリリースを参照できるとのことなのですが、 module でそういうのできましたっけ。 別 tfstate を見るなら terraform_remote_state だと思います。
guest

回答1

0

moduleを利用することで別フォルダのリリースを参照できる

今回はディレクトリが分かれていることではなくtfstateが分かれていることが問題です。
問題とは書きましたが、それが必ずしも悪いことではありません。
tf-commonというディレクトリは恐らく各tenantで使用する共通リソースを定義するためのディレクトリとしてtfstateを分けているんだと思うので、そのディレクトリをmoduleとして読み込むのは微妙だと思います。
※そもそものディレクトリ構成がどうであるべきかまではここで話し切るのは難しいので省略します。

今回であれば以下のいずれかで対応することになるかなと思います

  • Data Sourceで、別tfstateで管理しているSNS topicのARNを取得する
    • Data Sourceでtfstate管理外のリソースを検索して情報を取得できます。SNSトピックはトピック名でARNを取得できます。
    • 当然ながら、参照すべきリソースが既にないとエラーになってしまう可能性が高いです。
    • Data Source: aws_sns_topic
  • terraform_remote_stateを使う
  • ARNを直書きする
    • おすすめはしませんが、一応これでも解決はできます。

上記はtf-commonとtf-tenantが別tfstateであることを前提に書いていますが、同じtfstateにしてもいいということであれば話は変わってきます。


質問と関係ないですが

"${aws_sns_topic.topic.arn}"
このような表記は古い表記で、変数を単体で参照したいだけなら
aws_sns_topic.topic.arn
で十分です。
"Send an alarm if ${var.environment} is down"
の箇所は単体で参照しているのではなく別の文字列の中で変数を展開させていますが、このような場合は従来どおり囲ってあげる必要があります。

また、
count = length(aws_route53_health_check.HealthCheck)
のようにするよりも、for_eachを使ったループにしたほうが、リソース名のmapで各リソースが定義されるので該当のリソースを参照したいときに楽です。
countだとindexの数字から対象リソースを特定することが難しいです。

投稿2022/06/30 08:58

yu_1985

総合スコア7586

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問