概要
Terraformのplanやapplyコマンドをオプション未設定の状態で実行したときに、.tfファイル内で宣言しているvariableに対して値を代入していない場合、デフォルトの挙動としてインタラクティブに値を代入することを求められます。
しかし、この挙動が適さないユースケースが存在します。
本記事ではインタラクティブに値を入力することが適するまたは適さないユースケースを確認し、値が代入されていないvariableに対してインタラクティブな値の代入を回避する方法を紹介します。
ユースケース
値が代入されていないvariableに対してインタラクティブな入力を求められることが適する場合と適さないユースケースとして、ローカル環境での利用とCI/CD環境での利用が挙げられます。
ローカル環境での利用
ローカル環境でTerraformを実行する際には、variableに値をインタラクティブに入力することが便利な場合があります。例えば、テストや小規模なデプロイを行う場合、インタラクティブに値を入力することで迅速に設定を変更できます。
CI/CD環境での利用
一方、CI/CDパイプラインでは、インタラクティブな入力を回避したい場合が多いです。自動化されたパイプラインでは、すべてのvariableの値が事前に設定されている必要があり、値が設定されていないvariableがあれば即時にエラーを返す必要があるためです。パイプライン処理中にインタラクティブに値の入力を求められると最悪の場合、ユーザーからの入力を求められていることに気づかず、パイプラインの処理が入力待ちにより止まってしまいます。
値の入力を求められる原因
terraform planやterraform apply実行時にオプションとして指定可能な-inputの値をセットしないことが原因です。
実際に-inputオプションに関する説明を見てみると下記の通り示されています。
Ask for input for variables if not directly set.
このオプションを使用しない場合は、値の入力を求められます。
回避策
値を代入していないを代入していないvariableに対してインタラクティブな値入力を回避する方法を2つ紹介します。
① -inputにfalseを渡す
terraform plan -input=false
or
terraform apply -input=false
上記のように`plan`や`apply`コマンド実行時に`-input=false`をセットすると、値を代入していないvariableに対してインタラクティブな値渡しをすることなく、variableに値が代入されていない場合は即座位にエラーが返されます。
② 環境変数にTF_INPUTをセットする
export TF_INPUT=false
terraform plan
or
terraform apply
上記のように環境変数にTF_INPUT=falseをセットすると、値を代入していないvariableに対してインタラクティブな値渡しをすることなく、variableに値が代入されていない場合は即座位にエラーが返されます。
TF_INPUTとは
公式ドキュメントでは下記の通りの述べられています。
If set to "false" or "0", causes terraform commands to behave as if the -input=false flag was specified. This is used when you want to disable prompts for variables that haven't had their values specified.
-inputオプションのように動作する、値が指定されていなvariableに対して入力を求めることを無効にするフラグのようです。
まとめ
Terraformでplanやapplyコマンドを実行する際にインタラクティブに値の入力を求められることを回避する方法とこれを使用したいユースケースを紹介しました。
自動化されたCI/CDパイプラインでコマンドを実行する際には値の入力を求められないようにしておくことが得策ですね。
おまけ1:TF_INPUTの隠れたFalse値
ドキュメントに記載されているTF_INPUTの値をFalseとして扱うための値として下記のようなものが挙げられます。
- False
- FALSE
- f
- F
これはTerraformの内部実装でTF_INPUTが処理されるソースコードを確認して気づきました。
ソースコードは下記の通りです。
軽く説明すると343~349行目の処理で0が返ると、値が代入されていないvariableに対して値を入力することが求められません。
ここで注目したい箇所は344行目です。ここではTF_INPUTにセットされていた値がevnVar変数に代入されている状態で、この値を入力としてstrconvのParseBoolを実行しています。ということはstrconvのParseBoolがfalseを返すような入力値であれば、値が代入されていないvariableに対して値を入力することが求められなくなるということですね。これは実際にコードを確認しないとわからない気づきでした。特にfやFがFalse値として有効かは実際のコードを確認しないとわからないですよね。
実際に環境変数に`TF_INPUT=f`をセットした状態で実行した結果、値を代入していないvariableに対してインタラクティブな値の入力は求めらず、即座にエラーが返されました。
ただし、実用性の観点では意図的にTF_INPUT=fのような一目で理解しにくい値を入れる必要はないと思いますが...興味深い発見でした。
おまけ2:TF_INPUT vs -input
TF_INPUTと-inputにセットした値では、どちらの値が優先されるのでしょうか?
実際に確認してみたところ、優先されるTF_INPUTでも-inputでもなく、falseの値が優先されることが確認できました。どちらか一方でもFalseを指定していれば、その値が優先されると言うことですね。下記の通り、TF_INPUTと-inputでTrue or Flaseをセットした場合に、値の入力が求められるかの対応を表にまとめてみました。
TF_INPUT | -input | 値の入力を求められるか |
True | True | Yes |
True | False | No |
False | True | No |
False | False | No |