プラン作成の前に無効なインフラストラクチャ設定を拒否する

ShellBeginner
オンラインで実践に進む

はじめに

チームには、Terraform で管理しているレポート用ストレージがすでにあります。自動デプロイを導入する前に、書式が整っていない設定や構造的に無効な設定を、プラン作成に進む前に拒否するジョブが必要です。

2 つの静的チェックをゲートとして設定し、それぞれが実際にジョブを停止させることを観察してから、設定を修復します。Terraform の設定、プランと状態、Git の基礎、シェルの終了ステータスを理解していることを前提とします。準備済みの環境を使用するため、個人の AWS アカウントは不要です。

認定試験との関連

認定資格 試験のタスク 演習内容
DevOps Engineer – Professional (DOP-C02) Task 1.2 後続のデリバリーステージより前に自動の静的チェックを配置し、失敗の終了ステータスで処理を停止する基礎演習です。

品質ゲートの概要:設定は plan の前に fmt と validate を通過します。失敗すると後続のステージは停止し、既存のストレージと状態は変更されません。

プランの前にチェックを追加する

このステップでは、用意された順次実行ジョブに静的チェックを組み込みます。既存のバケットとレポートは、この実験を支えるインフラストラクチャです。データと Terraform の状態は変更せずに保持しなければなりません。

Terminal インターフェースを使用します。用意された Git リポジトリに移動し、ツールの環境設定を読み込みます。source は準備済みの変数を現在のシェルに適用するもので、インフラストラクチャをデプロイするものではありません。

cd /home/labex/project/report-delivery
source environment.sh

リソースの設定と、現在のジョブのステージを確認します。cat は各ファイルを表示するので、ジョブが何を管理し、何を実行するかを確認できます。

cat main.tf pipeline.json

バケットには Purpose タグがあります。現時点では、ジョブにあるのは plan ステージだけです。プランが成功しただけでは、その前に書式と構造のチェックが実行されたことにはなりません。

terraform fmt -check は、ファイルを書き換えずに、Terraform の標準的な書式に従っているかを確認します。terraform validate は、対応しているリソース属性などを含め、初期化済みの設定の内部整合性を確認します。どちらも設定が業務要件を満たすことを証明するものではありません。次の実験では、モジュールのアサーションを扱います。

用意された実行プログラムは、ステージ名を固定の Terraform コマンドに対応付け、最初のエラーで停止します。run-job.py は変更しないでください。課題は pipeline.json の設定であり、用意された実行プログラムの書き換えではありません。検証では、その動作を評価する前に、実際に使われるエントリーポイントが用意された原本と一致することを確認します。プラン作成より前に両方のチェックを追加してください。ヒアドキュメントは、区切り語の間にある JSON を pipeline.json に書き込みます。EOF を引用符で囲むことで、内容がそのまま保持されます。

cat > pipeline.json <<'EOF'
{"stages":["fmt","validate","plan"]}
EOF

Python の標準インタープリターでジョブを実行します。これは学習用のローカルランナーで、各ステージでは標準の Terraform コマンドを実行します。

python3 run-job.py

[fmt] native exit 0、[validate] native exit 0、[plan] native exit 0 と表示されるはずです。用意されたインフラストラクチャはすでに設定と一致しているため、プランには変更がないと表示されます。エラーがあると後続のステージは停止します。変更のあるプランでは Terraform 自体の終了コードが 2 になり、ランナーはこれを正常なプレビューとして扱います。適用の許可として扱うことはありません。

Git で変更を確認します。-- は、パスをコマンドのオプションから区切ります。

git diff -- pipeline.json

差分には、両方の新しいゲートが plan より前に表示されるはずです。このジョブには適用のステージはありません。

書式エラーで停止させる

このステップでは、標準的な空白の入れ方に従っていない有効な HCL 式を追加し、書式チェックのゲートがプラン作成の前にジョブを停止させることを確かめます。

小さな出力ブロックを追加します。>> は既存のファイルに追記します。空白を詰めた書き方は意図的なものであり、この出力が新しいリソースを管理することはありません。

cat >> main.tf <<'EOF'

output "format_probe" {value="spacing"}
EOF

ジョブをもう一度実行します。このコマンドは失敗することを想定しています。ここでは、その失敗こそが確認したい結果です。

python3 run-job.py

最初のステージは Terraform 自体の終了コード 3 を報告し、main.tf を表示します。ジョブは Job stopped; later stages did not run. と表示します。[validate] 行も [plan] 行も表示されないはずです。書式は AWS に接続せずに修正できます。

提案される書式の変更を具体的に確認します。-diff が変更内容を表示し、-check によってファイルは変更されずに残ります。

terraform fmt -check -diff

このコマンドも意図的にゼロ以外の終了ステータスを返します。このステップのチェックのために、書式の不備はそのまま残してください。次のステップで修復します。

書式と妥当性を区別する

このステップでは、書式を修復してから、構造の検証でしか検出できない別のエラーを追加します。

まず、Terraform にファイル内の空白を直接修正させます。-check を付けずに fmt を実行すると、書式の変更が行われます。

terraform fmt

出力には main.tf が表示されます。修復した設定がジョブを通過することを確認します。

python3 run-job.py

すべてのステージが実行されるはずです。追加した出力によって、プランで Terraform 自体の終了コードが 2 になる場合があります。これは出力の変更を提案するもので、適用は行いません。

次に、S3 バケットリソースが公開していない属性への参照を追加します。このブロックは標準的な書式に従っているので、最初のゲートは通過できます。

cat >> main.tf <<'EOF'

output "missing" {
  value = aws_s3_bucket.reports.missing_attribute
}
EOF

まず、書式だけを確認します。

terraform fmt -check

何も表示せず、終了コード 0 を返します。その後、ジョブ全体を実行します。

python3 run-job.py

書式チェックのゲートは通過し、続いて validate で Terraform 自体の終了コード 1 と Unsupported attribute の診断が表示されるはずです。プランのステージの行は表示されないはずです。この式は書式こそ正しいものの、対応していない属性を参照しています。ステップのチェックのため、このエラーを残してください。

設定を修復して環境を保持する

このステップでは、有効であることが分かっているリソース設定に戻し、ゲート付きのジョブを再実行して、レポート用ストレージが変更されていないことを確認します。

git restore -- main.tf は、リポジトリの開始時のコミットから、このファイルだけを復元します。実験用に追加した両方の出力を削除し、別ファイルの pipeline.json に加えた変更は保持します。

git restore -- main.tf

ジョブ全体をもう一度実行します。

python3 run-job.py

3 つすべてのステージで Terraform 自体の終了コードが 0 になるはずです。プランには変更がないと表示されるはずです。静的チェックを通過するとプラン作成に進めますが、デプロイの承認や適用は行われません。

ストレージからレポートを直接読み取ります。- は、別のローカルコピーを保存する代わりに、内容を標準出力に送ります。

aws s3   cp s3://delivery-gates-reports/report.csv -

想定される結果:

quarter,total
Q1,320

この演習で保持しなければならない、隣接するバケットのレポートを確認します。

aws s3   cp s3://delivery-gates-neighbor/keep.txt -

引き続き preserve neighboring report と表示されるはずです。最後に Git の差分を確認し、残した変更がパイプライン設定であることを確認します。

git diff -- main.tf pipeline.json

準備済みのバケットは、どちらも削除しないでください。チームが所有する既存のインフラストラクチャです。このジョブにはデプロイやプラン保存のステージがないため、クリーンアップが必要な新しいクラウドリソースやプラン成果物は残りません。試しに追加した一時的な出力は、main.tf を復元した際に削除されています。最後のチェックのために品質ゲートは保持してください。

まとめ

プラン作成の前に書式チェックと構造の検証を行う、順次実行の Terraform ジョブを構築しました。書式の不備と、それとは別の未対応属性のエラーが後続のステージを停止させることを観察し、その後で設定を修復して、レポートデータと状態を保持しました。

静的な妥当性は、品質を確かめる層の 1 つです。次の実験では、実行可能なモジュールのアサーションを使い、有効な設定が意図した動作をもたらすかを確認します。今回使用したチェックについては、公式の fmt リファレンスと validate リファレンスを参照してください。