TerraformでAmazon WorkSpacesを簡単インポート:importブロックとfor_eachの活用法
はじめに
こんにちは、Shunです。
今回は、Amazon WorkSpacesをTerraformへ簡単にインポートする方法をご紹介します。
Terraform 1.7以降で利用可能となったimportブロック内のfor_each構文を活用して、複数のAmazon WorkSpacesを一括でインポートします。
参考: Terraform 1.7 adds test mocking and config-driven remove
importブロックの使い方については、本記事で解説をしないので、importブロックの使用方法から知りたい方は、以下の記事を先に読むことをおすすめします。
想定読者
- Terraformを使用して多数のリソースをインポートする方法に関心がある方
- Terraformのimportブロックおよびfor_each構文の使い方に興味がある方
- Amazon WorkSpacesの運用効率化に興味がある方
importブロック内でのfor_each構文の書き方
importブロック内でfor_each構文を使用することは、一般的なTerraformでのfor_eachの使用と大きな違いはありません。また、一般的なimportコマンドとの記述方法との違いもfor_eachの行が追加される程度です。
importブロック内でfor_each構文を利用する際の重要な点は、インポートするリソースのresourceブロックを同時に記述することです。
以下にfor_eachを用いたリソースの定義と、それに対応するインポートコマンドの生成例を示します。
locals { buckets = { "staging" = "bucket1" "uat" = "bucket2" "prod" = "bucket3" } } import { for_each = local.buckets to = aws_s3_bucket.this[each.key] id = each.value } # ここがポイント resource "aws_s3_bucket" "this" { for_each = local.buckets }
引用: Import multiple instances with for_each
resourceブロックを同時に記述する必要があるのは、importブロック内でfor_each構文を使用する際に、以下のようなコードの自動生成ができないためです。
$ terraform plan -generate-config-out=generated.tf
実施すること
前提
以下を前提としています。
- Terraform環境は構築済み
- AWS CLI環境は構築済み
- Python環境は構築済み
- Amazon WorkSpacesが既に運用されている
ゴール
本記事の目的は、以下のステップを通じて、運用中のAmazon WorkSpacesをTerraformにインポートすることです。
- AWS CLIを使用して、運用中のAmazon WorkSpacesの一覧を取得
- 取得したAmazon WorkSpaces一覧を整形
- 整形されたAmazon WorkSpacesの一覧をTerraformへ記述し、インポートを実施
最終的なインポートを実施するためのTerraformコードは、以下の通りです。
terraform { required_version = "~> 1.7.0" backend "s3" { bucket = "[s3_bucket_name]" key = "[s3_key_name]" dynamodb_table = "[dynamodb_table_name]" region = "ap-northeast-1" } required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } } provider "aws" { region = "ap-northeast-1" } locals { workspaces = { "[User_Name1]" = { DirectoryId = "[DirectoryId1]" BundleId = "[BundleId1]" WorkspaceId = "[WorkspaceId1]" } "[User_Name2]" = { DirectoryId = "[DirectoryId2]" BundleId = "[BundleId2]" WorkspaceId = "[WorkspaceId2]" } "[User_Name3]" = { DirectoryId = "[DirectoryId3]" BundleId = "[BundleId3]" WorkspaceId = "[WorkspaceId3]" } ... } } import { for_each = local.workspaces to = aws_workspaces_workspace.main[each.key] id = each.value.WorkspaceId } resource "aws_workspaces_workspace" "main" { for_each = local.workspaces user_name = each.key directory_id = each.value.DirectoryId bundle_id = each.value.BundleId id = each.value.WorkspaceId }
手順
1. AWS CLIを使用して、運用中のAmazon WorkSpacesの一覧を取得
まず、Amazon WorkSpacesをTerraformへインポートするため、以下の必要情報をAWS CLIから取得します。
- UserName
- DirectoryId
- BundleId
- WorkspaceId
次のコマンドを実行して、output.json
へAmazon WorkSpacesの情報を出力します。
aws workspaces describe-workspaces --query "Workspaces[].[UserName,DirectoryId,BundleId,WorkspaceId]" > output.json
output.json
は、以下のようになります。
[ [ "[UserName1]", "[DirectoryId1]", "[BundleId1]", "[WorkspaceId1]" ], [ "[UserName2]", "[DirectoryId2]", "[BundleId2]", "[WorkspaceId2]" ], [ "[UserName3]", "[DirectoryId3]", "[BundleId3]", "[WorkspaceId3]" ], ... ]
2. 取得したAmazon WorkSpaces一覧を整形
(今回は、Pythonを用いて整形してみます。)
Terraformのlocals
で指定可能なmap型へ値を整形するために、Pythonを使用します。
今回は、識別がしやすいUser_Name
を基にmapを作成します。
formatted.py
という名前のPythonファイルを作成します。
import json # output.jsonを読み込む with open('output.json', 'r') as file: data = json.load(file) formatted_data = "" # 各レコードをmap型に変換 for record in data: formatted_data += f'"{record[0]}" = {{\n' formatted_data += f'\tDirectoryId = "{record[1]}"\n' formatted_data += f'\tBundleId = "{record[2]}"\n' formatted_data += f'\tWorkspaceId = "{record[3]}"\n' formatted_data += '}\n' print(formatted_data)
権限を付与し、実行します。
$ chmod 755 formatted.py $ python3 formatted.py > formatted_output.json
formatted_output.json
は以下のようになります。
"[User_Name1]" = { DirectoryId = "[DirectoryId1]" BundleId = "[BundleId1]" WorkspaceId = "[WorkspaceId1]" } "[User_Name2]" = { DirectoryId = "[DirectoryId2]" BundleId = "[BundleId2]" WorkspaceId = "[WorkspaceId2]" } "[User_Name3]" = { DirectoryId = "[DirectoryId3]" BundleId = "[BundleId3]" WorkspaceId = "[WorkspaceId3]" } ...
3. 整形されたAmazon WorkSpacesの一覧をTerraformへ記述し、インポートを実施
2.で出力した内容をlocals
のworkspaces
へ入れ、それを基にimportを行います。
terraform { required_version = "~> 1.7.0" backend "s3" { bucket = "[s3_bucket_name]" key = "[s3_key_name]" dynamodb_table = "[dynamodb_table_name]" region = "ap-northeast-1" } required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } } provider "aws" { region = "ap-northeast-1" } locals { workspaces = { # ここにpythonで整形したファイルの中身を入れます "[User_Name1]" = { DirectoryId = "[DirectoryId1]" BundleId = "[BundleId1]" WorkspaceId = "[WorkspaceId1]" } "[User_Name2]" = { DirectoryId = "[DirectoryId2]" BundleId = "[BundleId2]" WorkspaceId = "[WorkspaceId2]" } "[User_Name3]" = { DirectoryId = "[DirectoryId3]" BundleId = "[BundleId3]" WorkspaceId = "[WorkspaceId3]" } ... } } import { for_each = local.workspaces to = aws_workspaces_workspace.main[each.key] id = each.value.WorkspaceId } resource "aws_workspaces_workspace" "main" { for_each = local.workspaces user_name = each.key directory_id = each.value.DirectoryId bundle_id = each.value.BundleId id = each.value.WorkspaceId }
terraform plan
を実行すると、以下のようなエラーが発生しますが、これは機能が実験段階であるためであり、問題ありません。
$ terraform plan ~中略~ Plan: x to import, 0 to add, 0 to change, 0 to destroy. ╷ │ Warning: Config generation is experimental │ │ Generating configuration during import is currently experimental, and the generated
このエラーは無視してterraform apply
を実行します。
$ terraform apply ~中略~ Apply complete! Resources: x imported, 0 added, 0 changed, 0 destroyed.
これでインポートは完了です。
$ terraform state list aws_workspaces_workspace.main["User_Name1"] aws_workspaces_workspace.main["User_Name2"] aws_workspaces_workspace.main["User_Name3"] ...
まとめ
Terraform 1.7では、新たにimportブロック内でfor_each構文が使用できるようになりました。
この新機能のおかげで、importブロックにリソースを一つずつ記述する必要がなくなりました。これにより、コード化のプロセスがより効率的になります。
しかし、冒頭の関連記事で紹介されている、従来のimportコマンドで利用できたコード生成機能はこの新機能ではサポートされていません。
そのため、インポート自体は効率的になっても、Terraformの管理自体は煩雑になる可能性があります。
Amazon WorkSpacesの運用を考えると、以下のようなコード化が望ましい場合があります。
$ cat import.tf import { to = aws_workspaces_workspace.User_Name1 id = each.value.WorkspaceId } $ terraform plan -generate-config-out=generated.tf $ cat generated.tf resource "aws_workspaces_workspace" "User_Name1" { bundle_id = "BundleId1" directory_id = "DirectoryId1" root_volume_encryption_enabled = false tags = {} tags_all = {} user_name = "User_Name1" user_volume_encryption_enabled = false volume_encryption_key = null workspace_properties { compute_type_name = "" root_volume_size_gib = running_mode = "" running_mode_auto_stop_timeout_in_minutes = user_volume_size_gib = } }
今後、様々な検証を行いながら、この新しい機能の適切な使用方法を模索していく必要があります。
最後まで読んでいただき、ありがとうございました!
テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!
Follow @twitterGoogle Cloud11冠、2024 AWS All Cert、ビール検定1冠
Recommends
こちらもおすすめ
-
Terraform で Amazon EC2 を複数台作成する
2022.4.7
-
AWSサービスをTerraformでコード化する:AWS Chatbot編
2024.3.11
Special Topics
注目記事はこちら
データ分析入門
これから始めるBigQuery基礎知識
2024.02.28
AWSの料金が 10 %割引になる!
『AWSの請求代行リセールサービス』
2024.07.16