はじめに
前回、Terraformを使ってTROCCOのチームを作ったところ既存のものと重複してしまいました。
今更ですが、既存環境の設定をインポートして既存の設定を含めてTerraformで管理できるようにしていこうと思います。
やりたいこと
- TROCCOに登録済みのユーザーをTerraformで管理できるようにする
- TROCCOに登録済みのチームをTerraformで管理できるようにする
Terraformのimportの使い方を調べる
詳しく知りたい方は弊社Dさんの公開している下記を参考ください
上記は私には難しかったので、もっと基礎の下記の記事を参考にしました
まとめると下記の設定をすればインポートできそうです。
- importブロックを設定する
- インポートするユーザーやチームのリソースを作成する
TROCCOに登録済みのユーザーをインポートする
まず、importブロック を設定します。
ややこしくなりそうなので新しい.tfファイルを作成しました。
import {
to = trocco_user.import # trocco_user.import はインポートするユーザーのリソースと名前です
id = XXXX # インポートしたいユーザーのidを指定します
}
# リソースの名前は既存と重複しないものを設定する必要があります
resource "trocco_user" "import" {
# 必須項目のみ記載しています
email = "import_user@example.com"
role = "member"
}
importブロックで使用したidはTROCCO APIで取得しました
https://documents.trocco.io/apidocs/get-users
terraform plan するとこのようにimportが1件発生するのがわかります
指定していない値はTROCCOの現在の値に合わせて設定されました。
>terraform plan
trocco_user.import: Preparing import... [id=XXXX]
trocco_user.import: Refreshing state...
Terraform will perform the following actions:
# trocco_user.import will be imported
resource "trocco_user" "import" {
can_use_audit_log = true
email = "import_user@example.com"
id = XXXX
is_restricted_connection_modify = false
password = (sensitive value)
role = "admin"
}
Plan: 1 to import, 0 to add, 0 to change, 0 to destroy.
terraform apply を実行して反映すると、.tfstateにインポートしたユーザーが反映されました!
{
"mode": "managed",
"type": "trocco_user",
"name": "import",
"provider": "provider[\"registry.terraform.io/trocco-io/trocco\"]",
"instances": [
{
"schema_version": 0,
"attributes": {
"can_use_audit_log": true,
"email": "import_user@example.com",
"id": XXXX,
"is_restricted_connection_modify": false,
"password": "",
"role": "admin"
},
"sensitive_attributes": [
[
{
"type": "get_attr",
"value": "password"
}
]
]
}
]
},
この時点では、インポートしたユーザーはTerraform上で管理している部署に紐づけられていないいないのでそのあたりも設定しておきます。
まず、部署は var.department で指定しているのでインポートしたユーザーを追記します。
variable "departments" {
type = map(list(string))
default = {
"sales" = [
"sales01",
"sales02",
"import_user"
]
~~~
]
}
}
この時点でterraform plan をしてみると、既存の設定(trocco_user.users)に引っかかり import_user が新しいユーザーとして作成されそうになります。
>terraform plan
# trocco_user.users["import_user@example.com"] will be created
+ resource "trocco_user" "users" {
+ can_use_audit_log = true
+ email = "import_user@example.com"
+ id = (known after apply)
+ is_restricted_connection_modify = false
+ password = (sensitive value)
+ role = "admin"
}
Plan: 1 to add, 0 to change, 0 to destroy.
既存でどんな設定をしているかは下記をご参考ください
https://qiita.com/khpkymgc/items/011880d16186129560b7
別のリソースで作成すると同アドレスのユーザーが存在していても認識できないようです
既存のリソースに対して除外条件を設定することも考えましたが、管理が手間になるので他の方法を探します
import_userの所属するリソースを変更する
調べたところ、.tfstateを書き換えて import_user を trocco_user.usersリソース 配下へ移し替え、 trocco_user.importリソースを削除すれば良いようです。
trocco_user.usersリソースを見ると、trocco_user.importリソースにはなかった "index_key" が存在したので、これを追加してtrocco_user.usersリソース配下に書き換えます。
{
"mode": "managed",
"type": "trocco_user",
"name": "users",
"provider": "provider[\"registry.terraform.io/trocco-io/trocco\"]",
"instances": [
{
~~~~~~~~~
{
"index_key": "import_user@example.com", # 手入力で追加しました
"schema_version": 0,
"attributes": {
"can_use_audit_log": true,
"email": "import_user@example.com",
"id": XXXX,
"is_restricted_connection_modify": false,
"password": "",
"role": "admin"
},
"sensitive_attributes": [
[
{
"type": "get_attr",
"value": "password"
}
]
]
}
]
},
trocco_user.importリソースを削除(importブロックも削除しました)して terraform plan を実行すると、うまくいったようです!
TROCCOに登録済みのチームをTerraformで管理できるようにする
ユーザーのインポートができたので、チームもインポートしていきます。
同じように、importブロックと作成したいリソースを記載します
import {
to = trocco_team.import_sample
id = XXXX
}
# サンプルチーム
resource "trocco_team" "import_sample" {
name = "サンプル"
description = "チームの例"
members = flatten([
for department, members in var.departments : [
for member in members : {
user_id = local.user_email_ids[local.local_part_to_email[member]],
role = lower(department) == "test" ? "team_member" : "team_admin"
}
if lower(department) == "admin" || lower(department) == "test"
]
])
}
チームのidを取得するAPIはこちら
https://documents.trocco.io/apidocs/get-teams
terraform plan を実行すると問題なくインポートされそうです
>terraform plan
Plan: 1 to import, 0 to add, 0 to change, 0 to destroy.
terraform apply を実行し、インポートが完了しました!
>terraform apply
Apply complete! Resources: 1 imported, 0 added, 0 changed, 0 destroyed.
チームでは、リソースの移動が不要なのでimportブロックの削除などは行わなくても問題ありません。
ただ、もう使わない&管理上スッキリさせたいので削除しても問題ありません
インポート完了後、terraform planを行うと何故かchangeが発生する
チームのインポートが完了した後、設定を変更せずterraform planを実行してみました。
すると、何故かchangeが発生してしまいました
# trocco_team.import_sample will be updated in-place
~ resource "trocco_team" "import_sample" {
id = XXXX
~ members = [
~ {
~ user_id = ○○○○ -> △△△△
# (1 unchanged attribute hidden)
},
~ {
~ user_id = △△△△ -> ○○○○
# (1 unchanged attribute hidden)
},
]
name = "サンプル"
# (1 unchanged attribute hidden)
}
チームに所属するユーザーの登録順が変わることでchangeが発生するようです
確認したところ、Terraform Provider for TROCCOの古いバージョンで発生していた不具合のようです。
Providerのバージョンを0.3.0から最新の0.7.0へアップデートしてみます。
下記のサイトを参考に、.tfファイルへバージョン情報を追記し、terraform init -upgarade
を実行しました。
再度terraform planを行うと、No changeとなり問題ないことが確認できました
>terraform plan
No changes. Your infrastructure matches the configuration.
お疲れ様でした!
おわりに
今回はインポートするリソースが少なかったので、APIで手動で情報を取得してimportブロックを手入力してと人力作業でどうにかなりましたが、数が多いと大変そうだなと感じました。
冒頭で紹介したDさんの記事ではそのあたりをPythonを使ってうまいこと実施されていたので実運用を考えるとTerraform以外の言語の知識も勉強しないといけないなと思いました。
また、記事の最後に書いた インポート完了後、terraform planを行うとchangeが発生する 問題について、最初自分で調べたところ「flattenを使うと処理順は考慮されない(毎回バラバラの順番になる)」という情報があり、ここまで試してきた内容が全部駄目になるかとすごく焦りました。
Providerのバージョンアップで済んで本当に良かったです。
やりたいことに対して、実装方法の選択肢をいくつか持っておいて対応できるようにすることって重要だなとひしひしと感じました。
terraform importが無事に使えたことでTerraformの基本的な内容は一旦履修できた気でいますが、これからも色々試して良いやり方を学んでいきたいと思います!