背景
- Terraforming (http://terraforming.dtan4.net) を使うと、既存のResourceをTerraformにImportできるのでとても便利!
-
terraform import
は、 tf ファイルのimportには対応してないので、既存のを載せるには、やはり TerraformingがよいThe current implementation of Terraform import can only import resources into the state. It does not generate configuration. A future version of Terraform will also generate configuration.
問題
Terraforming で iam role をImportするとDescriptionがimport出来ずdiffが出てしまう
解決方法
https://github.com/dtan4/terraforming/pull/474 すでにPRが出ている。が、 2019/06/25に出たPRがマージされてない…
おまけ
せっかくなのでhttps://github.com/dtan4/terraforming をちゃんと理解してみた。
Terraformingの歴史
Commit logで振り返った。ざっくり見ると以下の感じ
- Initial commitは2015年3月25日! ←自分がTerraformのTの字も知らない頃…
- 最初のリソースはRDS、そしてS3
-
もともとのコマンドの使い方は、以下のような形
aws rds describe-db-instances | ./terraforming-rds aws s3 ls | ./terraforming-s3
ELB, VPC, Security Groupが追加
lib/terraforming/resource/
にクラスが移されるerb
テンプレートが導入される別れていたコマンドが
terraforming
へ統合されるいろいろツール導入とテスト修正
それまでは aws cli + terraformingをパイプで渡していたのから、
aws-sdk
を利用するように変更になるThorを使ったcliになる
残りは細かい修正とResourceの追加が繰り返される
構成
.
├── bin
│ └── terraforming # cliとして呼ばれる
...
├── lib
│ ├── terraforming
│ │ ├── cli.rb # cliの定義
│ │ ├── resource # AWSのResourceのClassを定義したファイルがここに入ってる (ここにaws-sdkからresource情報をとりtf/tfstate生成する)
│ │ ├── template # tf生成するときに使われるerbのテンプレート
│ │ ├── util.rb # 共通のメソッド
│ │ └── version.rb # バージョン
│ └── terraforming.rb # terraforming/以下で定義されたものをrequireしている
├── script
│ ├── console
│ ├── generate # 新しいResourceを追加するとき用のscript
│ └── setup
├── spec # rspecファルダ
│ ├── fixtures
│ │ └── terraform.tfstate
│ ├── lib
│ │ ├── terraforming
│ │ └── terraforming_spec.rb
│ └── spec_helper.rb
├── templates # テンプレート
│ ├── resource.erb.erb
│ ├── resource.rb.erb
│ └── resource_spec.rb.erb
├── terraforming.gemspec
自分でもgem作ってみよう! 目標:「iam_roleのdescriptionを追加したのを動かす」
Gemとかほとんどつくったことないから適当にGoogleって my_rubygemとか作ってみた (割愛)
https://github.com/nakamasato/practice_terraforming 真似て作ったやつ。
Gemを作る
-
gem作成
bundle gem practice_terraforming
gemspecの編集
iam_roleだけ動くもの作る
以下のものをコピってくる
-
lib/practice_terraforming/resource/iam_role.rb
aws-sdk
を使ってresource情報を取ってきてtfstateを作るロジックが書いてある. tfファイルは、templateに読み込んだ変数からerbで生成するようになっている -
lib/practice_terraforming/template/tf/iam_role.erb
tfファイル作るようのテンプレート spec/lib/practice_terraforming/resource/iam_role_spec.rb
-
bin/practice_terraforming
cliでexecuteする部分 -
lib/practice_terraforming.rb
dependenciesの読み込み -
lib/practice_terraforming/cli.rb
Thorを使ったcliの実装 -
lib/practice_terraforming/util.rb
いろいろ使える道具が入ってる
いろいろ動かして https://github.com/nakamasato/practice_terraforming/commit/93dbdc8f01485c022ffee51e9641d4d6e903f953 (コミット名がクソすぎるが) このコミットでとりあえず iam_roleが動くようになった。 (s3はbackendに使ってるせいかなんか必要そうだったから入れといた、iam_policy_attachmentも入れてしまった)
動かすには、
gem build practice_terraforming.gemspec
gem install practice_terraforming-0.1.0.gem
とすると、practice_terrafroming
が使えるようになる
practice_terraforming
Commands:
practice_terraforming help [COMMAND] # Describe available commands or one specific command
practice_terraforming iampa # Iam Policy Attachment
practice_terraforming iamr # Iam Role
practice_terraforming s3 # S3
Options:
[--merge=MERGE] # tfstate file to merge
[--overwrite], [--no-overwrite] # Overwrite existing tfstate
[--tfstate], [--no-tfstate] # Generate tfstate
[--profile=PROFILE] # AWS credentials profile
[--region=REGION] # AWS region
[--assume=ASSUME] # Role ARN to assume
[--use-bundled-cert], [--no-use-bundled-cert] # Use the bundled CA certificate from AWS SDK
iam_roleにdescriptionを足す (変更の仕方を勉強)
上記に貼ったPRと同じような変更だが、自分でやってみる https://github.com/nakamasato/practice_terraforming/commit/d5e97ebc56f2811a33ec61b01e8d376d605f5cae
以下の2つを対応させるロジックを lib/practice_terraforming/resource/iam_role.rb
に書くだけである。
-
aws-sdk
で帰ってくる値を https://docs.aws.amazon.com/sdkforruby/api/Aws/ClientStubs.html で確認 - TerraformのResourceをhttps://www.terraform.io/docs/providers/aws/r/iam_role.html で確認
今回の場合は、description追加のみ
ついでだから gemもリリース
bundle exec rake build
practice_terraforming 0.1.3 built to pkg/practice_terraforming-0.1.3.gem.
bundle exec rake release
practice_terraforming 0.1.3 built to pkg/practice_terraforming-0.1.3.gem.
Tagged v0.1.3.
Pushed git commits and tags.
Pushing gem to https://rubygems.org...
Successfully registered gem: practice_terraforming (0.1.3)
Pushed practice_terraforming 0.1.3 to rubygems.org
https://rubygems.org/gems/practice_terraforming ができた。
おまけ2
問題2
実はもう一つ問題があった。 Terraformingにiam_policy_attachmentは実装されてるが、これは、公式ドキュメントで以下のように書いてある。
WARNING: The aws_iam_policy_attachment resource creates exclusive attachments of IAM policies. Across the entire AWS account, all of the users/roles/groups to which a single policy is attached must be declared by a single aws_iam_policy_attachment resource. This means that even any users/roles/groups that have the attached policy via any other mechanism (including other Terraform resources) will have that attached policy revoked by this resource. Consider aws_iam_role_policy_attachment, aws_iam_user_policy_attachment, or aws_iam_group_policy_attachment instead. These resources do not enforce exclusive attachment of an IAM policy.
要するに、iam_policy_attachmentで管理してて変更すると、それ以外で管理してたやつが完全に外されるから気をつけてねって話。 aws_iam_role_policy_attachment
とかaws_iam_user_policy_attachment
とかaws_iam_group_policy_attachment
を使えばそういうことは起きないということ。
関連のGithubとかqiitaもある
- #133 provider/aws : IAM policy attachment/detach bug ?n
- terraform の aws_iam_policy_attachment は使わないほうが無難
iam_role_policy_attachment
のリソースも追加してPRもだした
iam_role_policy_attachment
と aws_iam_user_policy_attachment
とaws_iam_group_policy_attachment
それぞれでimportできればいいわけだからそれを作ることにした。今回はとりあえずiam_role_policy_attachment
だけ。
あんまりアクティブじゃなさそうだから、マージされるかわからないけど、 https://github.com/dtan4/terraforming/pull/489 を出した。 practice_terraforming
で練習してからこのPR出したから、 practice_terraforming
の方では実装済み。
あとは、 iam_user_policy_attachment
と iam_group_policy_attachment
も同じように書いておこう。
まとめ
- terraformingは便利
- terraformingのリソース変更は、
lib/terraforming/resource/<resource>.rb
とlib/terraforming/template/tf/<resource>.erb
をaws-sdk
と Terraformのresourceドキュメントを見て変更すれば良い (テストも) - リソースの追加は、 terraformingのdocsにあるように
script/generate <resource>
を使ってgenerateしたあとに、aws-sdkとterraformのresourceの間を埋めるロジックを追加する (テストも)