ツナワタリマイライフ

日常ネタから技術ネタ、音楽ネタまで何でも書きます。

Terraform importの実装

はじめに

PRを出した。(mergeまではしばらく時間がかかりそうな雰囲気)

github.com

Autoscaling groupのlifecycle hookのimportをsupportするというニッチ(?)なissueを解決するためのもの。

そもそも先日行った Source Code Readingのオフ会をきっかけに、次のmeetup(8/1を予定)までに何か1つPRだすぞーといって出したもの。準備からコード読み含めて連休の結構な時間を使った。

terraform-jp.connpass.com

このissue自体もcontributorのkterada0509 さんが教えてくれて、参考の実装まで教えてくれて手取り足取りどころではない感じで圧倒的感謝です。

結果的にほぼ参考実装の丸コピにはなったものの、理解するために手を動かしていい経験になった。

Terraform import

そもそもimportとは何かというと、既存のリソースをTerraformの管理下におくこと(=stste fileにとりこむこと)である。

tffileは生成してくれないので、実際はimportしたあとplanの差分を埋めるべくtffileを書く必要がある。

コマンドはこんな感じになる。

$ terraform import <resource type>.<resource name> <resource id>
# terraform import aws_autoscaling_group.chaspy_test_asg test-asg

こんな感じになる。

で、インポートする時点では中身は空でいいのでtffileに以下のような定義をおいておく必要がある。

resource "aws_autoscaling_group" "chaspy_test_asg" {
}

test-asgというのが実際にAWS上にあるAutoscaling Groupの名前である。

コードを読む / ストレートにImportする

さて、ではこのAutoscaling Groupのリソースファイルを見てみよう。

https://github.com/terraform-providers/terraform-provider-aws/blob/v2.19.0/aws/resource_aws_autoscaling_group.go#L28:titie

ポイントしてるように、Importを可能にするにはこのようなImporterを実装する必要がある。

     Importer: &schema.ResourceImporter{
            State: schema.ImportStatePassthrough,
        },

ImportStatePassthrough が何を意味しているかというと、cliの第2引数で受け取ったidが、そのままresource idとして使える場合、そのまま実際のリソースの情報を resourceAwsAutoscalingGroupRead functionで読み取り、その内容をstateファイルにつっこむことになる。

もしこのようにストレートにインポートできる場合で、importがsupportされていなければ、この部分を追加するだけでimportできるようになる。

Importがストレートにいかない場合

では今回のPRのように、 ImportStatePassthrough ではうまくいかないパターンはどんなパターンか。

参考にした AutoscalingPolicyと同じく、そのリソースのidだけではresourceのgetができないような場合はimportを工夫する必要がある。

参考にした実装のAutoscalingPolicyのドキュメントを見てみよう。

www.terraform.io

$ terraform import aws_autoscaling_policy.test-policy asg-name/policy-name

なぜこうしているかというと、policy-nameだけではリソースが一意に定まらないからである。

cliを見てもわかるが、autoscaling policyはautoscaling groupが必須である。(そりゃそうだ)

docs.aws.amazon.com

で、import実行時にはasg nameとpolicy-nameを/区切りで入力させることにしている。

ではこの実装を見てみよう。

terraform-provider-aws/resource_aws_autoscaling_policy.go at v2.19.0 · terraform-providers/terraform-provider-aws · GitHub

passthroughするわけにはいかないので、オリジナルのimport用functionを実装している。

     Importer: &schema.ResourceImporter{
            State: resourceAwsAutoscalingPolicyImport,
        },

terraform-provider-aws/resource_aws_autoscaling_policy.go at v2.19.0 · terraform-providers/terraform-provider-aws · GitHub

期待している <asg-name>/<policy-name> がきた場合、スラッシュ区切りで分けて、そのリソースのpropertyにsetするとともに、SetIdでidを付与している。

逆に言えばpassthroughの場合、このd.idがそのままそのリソースにSetIdされることになるのだろう。

今回取り組んだ Autoscaling Lifecycle Hookも同じような構造であったため、ほぼそのままの実装でいけた。

おわりに

これまで使われている、使っているOSSへのContributionができていなかったので、今回挑戦できて本当によかった。

8/1のmeetupのLTで話す内容だが、このPRを送るための事前準備、debug方法、テスト方法などなどもまとめてブログに書く予定。

はやくマージされないかなー


追記:7/16 Mergeされました!

github.com