AWS CloudFormationテンプレートからparameter-overridesのJSONファイルを生成する

記事タイトルとURLをコピーする

この記事について

AWS CloudFormation(以下、CloudFormation)テンプレートファイルを渡すと、Parametersセクションを読み取り、AWS CLIでデプロイする際に使えるパラメーター(parameter-overrides)のJSONを生成するPythonスクリプトの紹介です。(ファイル名はparameters.json固定)

動作環境

Poetry表記で書いておきます。

[tool.poetry.dependencies]
python = "^3.12"
pyyaml = "^6.0.1"

なぜ作ったのか?

デプロイのたびに毎回パラメーターを手動で指定するのは非効率ですしミスを誘発します。
たとえば1つのテンプレートで本番環境、ステージング環境と使い分けたいとき、パラメーターファイルだけ別れていると管理がシンプルです。

とはいえ、パラメーターファイルを手動で作るのは面倒だなと思ったのでPythonスクリプトで実装しました。

ちなみにChatGPTがほとんどを作ってくれました。私が対応したのは一部のエラー対処です。

コード

今回はコードの作成をChatGPTに任せましたが、唯一追加したのがyaml.SafeLoader.add_multi_constructor('!', lambda loader, suffix, node: None)です。
これがないと!Refなど、!を含む記述でエラーになります。

medium.com

import json
import yaml
import argparse

def load_template(file_path):
    """テンプレートファイルを読み込む"""
    with open(file_path, 'r') as file:
        if file_path.endswith('.yaml') or file_path.endswith('.yml'):
            # 何も処置しないと!Refや!Subなどがエラーになるので、無視するようにする
            yaml.SafeLoader.add_multi_constructor('!', lambda loader, suffix, node: None)
            return yaml.safe_load(file)
        elif file_path.endswith('.json'):
            return json.load(file)
        else:
            raise ValueError("ファイル形式はJSONまたはYAMLである必要があります。")

def generate_parameters_json(template):
    """ParametersセクションからJSONファイルを生成する"""
    parameters = template.get('Parameters', {})
    params_for_cli = []

    for param, details in parameters.items():
        default = details.get('Default')
        if default is not None:
            params_for_cli.append({
                "ParameterKey": param,
                "ParameterValue": default
            })
        else:
            params_for_cli.append({
                "ParameterKey": param,
                "ParameterValue": "手動で値を入力してください"
            })

    return json.dumps(params_for_cli, indent=4, ensure_ascii=False)

def main():
    """メイン関数"""
    parser = argparse.ArgumentParser(description='CloudFormationテンプレートのParametersを解析して、CLI用のJSONファイルを生成します。')
    parser.add_argument('template_file', type=str, help='CloudFormationテンプレートファイルのパス')
    args = parser.parse_args()

    try:
        template = load_template(args.template_file)
        params_json = generate_parameters_json(template)
        output_file_path = 'parameters.json'
        with open(output_file_path, 'w', encoding='utf-8') as file:
            file.write(params_json)
        print(f"生成されたパラメータファイルは '{output_file_path}' に保存されました。")
    except Exception as e:
        print(f"エラーが発生しました: {e}")

if __name__ == "__main__":
    main()

使い方

使い方は以下の通りです。

  1. PyYAMLをインストールしておく(例:pip install pyyaml
  2. サンプルコードをDLして名前を付けておく(例:script.py
  3. 実行するpython script.py ./aurora-mysql.yml
  4. 実行場所にparameters.jsonが作られる
  5. デプロイなどで活用する
    (例:aws cloudformation deploy --template-file /path_to_template/template.json --stack-name my-new-stack --parameter-overrides file://path_to_parameters/parameters.json

おわりに

CloudFormationテンプレートには必ずパラメーターJSONを作る運用にしておけば、デプロイもラッパースクリプトなどで環境を切り替えるなど、色々できるかもしれないですね。

最後までお読みいただき、ありがとうございました。

水本 正敏(執筆記事の一覧)

エンタープライズクラウド部 ソリューションアーキテクト1課

国内ITベンダーのカスタマーエンジニアからAWSに魅了されサーバーワークスへ。