はじめに
Cloudfomationを普段から開発し何度もスタック作成を試行錯誤している人で
TeraformやCDKへの移行ができない人向け
特にスタックをポチポチマネジメントコンソールでやっていたり、aws cliから作成するにもコマンドを複数叩いて回るのがメンドクサイ人におすすめ
TL;DL
cfn-execを利用する
前提
aws cli実行環境
python3.7以上の実行環境
note: OS依存性はない
note: aws-vault環境の場合は以下のように実行する
aws-vault exec yourprofile-- cfn-exec -v
詳細
Command Line | Option | Description |
---|---|---|
-n, --stack-name | STACK_NAME | 任意のスタック名(max 64文字) |
-i, --input-path | INPUT_PATH | Cloudfomationファイルのローカル相対/絶対パス、またはS3バケットURL |
-p, --parameter-file | PARAM | Parameterファイルのローカル相対/絶対パス、またはパブリックなURLやS3バケットURL |
-s3, --s3-bucket-url-parameter-key-name *1 | S3_BUCKET_URL_PARAMETER_KEY_NAME | 指定するCloudfomationファイルのパスがローカルであり、かつそのCloudfomationファイルから別のCloudfomationファイルを参照するネスト構造を有する場合に、その参照先を指定するベースURLパスを定義するCloudfomationパラメータキー名 |
-dr, --disable-roleback | Stack作成に失敗したとき、ロールバックしない | |
-del, --delete-stack | Stack作成の成否に関わらず実行後に削除する | |
-csf, --change-set-force-deploy | Change set作成後にそのまま適用する |
*1: 説明が意味不明と思うので、2.実行例 2.3. ローカルにあるネスト構造を持つCloudfomationテンプレートからスタックを作成する を参考すること
パラメータファイルはyaml or jsonフォーマットに対応し、aws cliフォーマットとシンプルフォーマットに対応している
aws cli フォーマット
[
{
"ParameterKey": "BucketName",
"ParameterValue": "cfnexec-example-test-01234567890123456789"
}
]
---
- ParameterKey: BucketName
ParameterValue: cfnexec-example-test-01234567890123456789
シンプルフォーマット
{
"BucketName": "cfnexec-example-test-01234567890123456789"
}
---
BucketName: cfnexec-example-test-01234567890123456789
1. インストール
pip install cfnexec
cfn-exec -v
2. 実行例
2.1 実行例の対象となるファイル
単体で実行可能なCloudformationテンプレート s3.yml
---
AWSTemplateFormatVersion: "2010-09-09"
Description: s3.yml
Parameters:
BucketName:
Type: String
Default: "BucketName"
Resources:
S3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref BucketName
s3.ymlを呼び出すCloudfomationテンプレート main.yml
---
AWSTemplateFormatVersion: "2010-09-09"
Description: main.yml
Parameters:
TemplateS3BucketURL:
Description: Referenced S3 bucket URL
Type: String
Default: TemplateS3BucketURL
BucketName:
Type: String
Default: BucketName
Resources:
# Create S3 Bucket
S3:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: !Sub ${TemplateS3BucketURL}/components/s3.yml
Parameters:
BucketName: !Ref BucketName
s3.yml単体を実行するためのパラメータファイル
---
- ParameterKey: BucketName
ParameterValue: cfnexec-example-test-01234567890123456789
ネスト構造を持つmain.ymlを実行するためのパラメータファイル ローカルファイル版
---
TemplateS3BucketURL: TemplateS3BucketURL
BucketName: cfnexec-example-test-01234567890123456789
ネスト構造を持つmain.ymlを実行するためのパラメータファイル GithubURL版
{
"TemplateS3BucketURL": "https://raw.githubusercontent.com/Takenori-Kusaka/cfn-exec/main/example/input/",
"BucketName": "cfnexec-example-test-01234567890123456789"
}
なお、ローカルファイルの相対パス参照例はcfn-execをcloneし、そのルートディレクトリ上で実行したものである
git clone https://github.com/Takenori-Kusaka/cfn-exec.git
cd cfn-exec
2.2 ローカルにある単体実行可能なCloudfomationテンプレートからスタックを作成する
$ cfn-exec -n local-file1 -i ./example/input/components/s3.yml -p ./example/param_cfn.json
Found credentials in environment variables.
StackName: local-file1
CFn URL: https://s3-us-east-2.amazonaws.com/cfn-exec-us-east-2-9178840d-1214-43a4-9c8f-47fbd81d8f3c/s3.yml
Parameters:
Index ParameterKey ParameterValue
------- -------------- -----------------------------------------
0 BucketName cfnexec-example-test-01234567890123456789
Create a new local-file1.
Creating to stack... : local-file1
Index Timestamp ResourceStatus LogicalResourceId PhysicalResourceId ResourceStatusReason
------- -------------------------------- ---------------- ------------------- ----------------------------------------- ----------------------
0 2022-03-25 14:03:36.757000+00:00 CREATE_COMPLETE S3Bucket cfnexec-example-test-01234567890123456789
Creation to stack completed successfully!! : local-file1
2.3 ローカルにあるネスト構造を持つCloudfomationテンプレートからスタックを作成する
$ cfn-exec -n local-file2 -i ./example/input/main.yml -p ./example/param.yml -s3 TemplateS3BucketURL
Found credentials in environment variables.
StackName: local-file2
CFn URL: https://s3-us-east-2.amazonaws.com/cfn-exec-us-east-2-36e9fce4-388a-41d1-a11a-277026d25d9b/main.yml
Parameters:
Index ParameterKey ParameterValue
------- ------------------- --------------------------------------------------------------------------------
0 TemplateS3BucketURL https://cfn-exec-us-east-2-36e9fce4-388a-41d1-a11a-277026d25d9b.s3.amazonaws.com
1 BucketName cfnexec-example-test-01234567890123456789
Create a new local-file2.
Creating to stack... : local-file2
Index Timestamp ResourceStatus LogicalResourceId PhysicalResourceId ResourceStatusReason
------- -------------------------------- ---------------- ------------------- ----------------------------------------- ----------------------
0 2022-03-25 14:10:48.058000+00:00 CREATE_COMPLETE S3Bucket cfnexec-example-test-01234567890123456789
Creation to stack completed successfully!! : local-file2
note: スタック作成完了後テーブルにはネスト先を含めて実際のAWSリソースのみを表示する
動作フロー
ローカルファイルは一度S3へアップロードし、その上で対象のURLを指定する
このアップロード時に対象ファイルと同じフォルダ下にあるものを同時にアップロードすることでURLを解決する
以下のファイル構造を持ち、Cloudfomationテンプレートにmain.ymlを指定した場合のフローを説明する
./example
│ param.yml
│
└─input
│ main.yml
│
└─components
s3.yml
- 一時的なs3バケットを作成する(スタック名+リージョン+UUID)
- main.ymlの親ディレクトリ(./example/input)を取得する
- 2.のフォルダ以下にあるすべてのファイル(main.yml, components/s3.yml)をs3へアップロードする
- s3バケットのURLとアップロードした対象のCloudfomationテンプレートファイルのURLを取得する
- パラメータからs3バケットURLを指すキー(-s3オプションで指定した名前)を探し、その値を取得したs3バケットURLへ置換する
- 対象のCloudfomationテンプレートファイルのURLと置換済みパラメータを利用してスタックを作成する
- スタック作成完了後に一時的なs3バケットは削除する
3.の時点でS3バケット上のファイル構造は以下の通り
S3Bucket
│ main.yml
│
└─components
s3.yml
2.4 インターネット上にある単体実行可能なCloudfomationテンプレートからスタックを作成する
$ cfn-exec -n public-file1 -i https://cfn-exec-us-east-2-f0f165a5-f221-4b2f-9d69-34cb268d8c11.s3.us-east-2.amazonaws.com/input/components/s3.json -p https://cfn-exec-us-east-2-f0f165a5-f221-4b2f-9d69-34cb268d8c11.s3.us-east-2.amazonaws.com/param_cfn.json
Found credentials in environment variables.
StackName: public-file1
CFn URL: https://cfn-exec-us-east-2-f0f165a5-f221-4b2f-9d69-34cb268d8c11.s3.us-east-2.amazonaws.com/input/components/s3.json
Parameters:
Index ParameterKey ParameterValue
------- -------------- -----------------------------------------
0 BucketName cfnexec-example-test-01234567890123456789
Create a new public-file1.
Creating to stack... : public-file1
Index Timestamp ResourceStatus LogicalResourceId PhysicalResourceId ResourceStatusReason
------- -------------------------------- ---------------- ------------------- ----------------------------------------- ----------------------
0 2022-03-25 14:40:38.038000+00:00 CREATE_COMPLETE S3Bucket cfnexec-example-test-01234567890123456789
Creation to stack completed successfully!! : public-file1
2.5 インターネット上にあるネスト構造を持つCloudfomationテンプレートからスタックを作成する
$ cfn-exec -n public-file2 -i https://cfn-exec-us-east-2-f0f165a5-f221-4b2f-9d69-34cb268d8c11.s3.us-east-2.amazonaws.com/input/main.json -p https://cfn-exec-us-east-2-f0f165a5-f221-4b2f-9d69-34cb268d8c11.s3.us-east-2.amazonaws.com/param.json
Found credentials in environment variables.
StackName: public-file2
CFn URL: https://cfn-exec-us-east-2-f0f165a5-f221-4b2f-9d69-34cb268d8c11.s3.us-east-2.amazonaws.com/input/main.json
Parameters:
Index ParameterKey ParameterValue
------- ------------------- ------------------------------------------------------------------------------------------------
0 TemplateS3BucketURL https://cfn-exec-us-east-2-f0f165a5-f221-4b2f-9d69-34cb268d8c11.s3.us-east-2.amazonaws.com/input
1 BucketName cfnexec-example-test-01234567890123456789
Create a new public-file2.
Creating to stack... : public-file2
Index Timestamp ResourceStatus LogicalResourceId PhysicalResourceId ResourceStatusReason
------- -------------------------------- ---------------- ------------------- ----------------------------------------- ----------------------
0 2022-03-25 14:49:55.072000+00:00 CREATE_COMPLETE S3Bucket cfnexec-example-test-01234567890123456789
Creation to stack completed successfully!! : public-file2
2.6 実行可能な組み合わせパターン
テンプレートはS3バケット、パラメータはローカルファイル
$ cfn-exec -n public-file1 -i https://cfn-exec-us-east-2-f0f165a5-f221-4b2f-9d69-34cb268d8c11.s3.us-east-2.amazonaws.com/input/components/s3.json -p ./example/param.yml
テンプレートはローカルファイル、パラメータはs3バケットファイル
$ cfn-exec -n public-file2 -i ./example/input/main.yml -p https://cfn-exec-us-east-2-f0f165a5-f221-4b2f-9d69-34cb268d8c11.s3.us-east-2.amazonaws.com/param.json
テンプレートはローカルファイル、パラメータはGithubファイル
$ cfn-exec -n public-file2 -i ./example/input/main.yml -p https://raw.githubusercontent.com/Takenori-Kusaka/cfn-exec/main/example/param.json
上記の通り組み合わせパターンに依存性なし
2.7 スタック作成時にロールバックさせない
-drオプションを有効化する
$ cfn-exec -n local-file2 -i ./example/input/main.yml -p ./example/param.yml -dr
Found credentials in environment variables.
StackName: local-file2
CFn URL: https://s3-us-east-2.amazonaws.com/cfn-exec-us-east-2-ec4802c9-6c62-4868-af79-25a05289640c/main.yml
Parameters:
Index ParameterKey ParameterValue
------- ------------------- -----------------------------------------
0 TemplateS3BucketURL TemplateS3BucketURL
1 BucketName cfnexec-example-test-01234567890123456789
Create a new local-file2.
Creating to stack... : local-file2
Waiter StackCreateComplete failed: Waiter encountered a terminal failure state: For expression "Stacks[].StackStatus" we matched expected path: "CREATE_FAILED" at least once
Index Timestamp ResourceStatus LogicalResourceId PhysicalResourceId ResourceStatusReason
------- -------------------------------- ---------------- ------------------- -------------------- ------------------------------------
0 2022-03-25 15:02:44.266000+00:00 CREATE_FAILED S3 TemplateURL must be a supported URL.
Attempted to create but failed... : local-file2
"we matched expected path: "CREATE_FAILED" at least once"のCREATE_FAILEDが-drがないとき、ROLLBACK_COMPLETEになる
自動的にロールバックした場合上記例のように失敗理由を確認することができない
2.8 スタック検証目的として、作成後に削除する(成否関係なく)
-delオプションを有効化する
$ cfn-exec -n local-file2 -i ./example/input/main.yml -p ./example/param.yml -del
Found credentials in environment variables.
StackName: local-file2
CFn URL: https://s3-us-east-2.amazonaws.com/cfn-exec-us-east-2-5087db33-a8d9-4754-853a-5aa2de2cdf21/main.yml
Parameters:
Index ParameterKey ParameterValue
------- ------------------- -----------------------------------------
0 TemplateS3BucketURL TemplateS3BucketURL
1 BucketName cfnexec-example-test-01234567890123456789
Create a new local-file2.
Creating to stack... : local-file2
Waiter StackCreateComplete failed: Waiter encountered a terminal failure state: For expression "Stacks[].StackStatus" we matched expected path: "ROLLBACK_COMPLETE" at least once
Index Timestamp ResourceStatus LogicalResourceId PhysicalResourceId ResourceStatusReason
------- -------------------------------- ---------------- ------------------- -------------------- ----------------------
0 2022-03-25 15:06:01.605000+00:00 DELETE_COMPLETE S3
Attempted to create but failed... : local-file2
Deleting to stack... : local-file2
Deletion to stack completed. : local-file2
最後にDeleteしている
2.9 変更セットを作成する
2.実行例 2.3. ローカルにあるネスト構造を持つCloudfomationテンプレートからスタックを作成する を実行済みとし、すでにlocal-file2のスタックが存在する状態で実行する
ここでは参照するパラメータのバケット名を変更して実行した
$ cfn-exec -n local-file2 -i ./example/input/main.yml -p ./example/param.yml -s3 TemplateS3BucketURL
Found credentials in environment variables.
StackName: local-file2
CFn URL: https://s3-us-east-2.amazonaws.com/cfn-exec-us-east-2-c7d9d1bd-9788-4caf-82c1-12f8edfc9b4e/main.yml
Parameters:
Index ParameterKey ParameterValue
------- ------------------- --------------------------------------------------------------------------------
0 TemplateS3BucketURL https://cfn-exec-us-east-2-c7d9d1bd-9788-4caf-82c1-12f8edfc9b4e.s3.amazonaws.com
1 BucketName cfnexec-example2-test-01234567890123456789
Since local-file2 already exists, create new change set.
Creating to change set... : local-file2-9bb145aa-0f20-445b-9d53-2b4fca411c19
Creation to change set completed successfully!! : local-file2-9bb145aa-0f20-445b-9d53-2b4fca411c19
Creation to change set completed successfully!! : local-file2-9bb145aa-0f20-445b-9d53-2b4fca411c19
Index Type Action LogicalResourceId PhysicalResourceId ResourceType Replacement
------- -------- -------- ------------------- ----------------------------------------- --------------- -------------
0 Resource Modify S3Bucket cfnexec-example-test-01234567890123456789 AWS::S3::Bucket True
変更セットを作成したいスタック名、変更後のCloudfomationテンプレート、パラメータファイルを指定して実行する
そのため、スタック作成時と全く同じコマンドで実行可能であり、ファイルの変更だけで対応可能(CIへ組み込み容易)
テーブル出力から、変更差分を確認できる
2.10 変更セット作成後そのまま適用する
2.9同様に2.実行例 2.3. ローカルにあるネスト構造を持つCloudfomationテンプレートからスタックを作成する を実行済みとし、すでにlocal-file2のスタックが存在する状態で実行する
追加のオプションとして-csfを有効化する
$ cfn-exec -n local-file2 -i ./example/input/main.yml -p ./example/param.yml -s3 TemplateS3BucketURL -csf
Found credentials in environment variables.
StackName: local-file2
CFn URL: https://s3-us-east-2.amazonaws.com/cfn-exec-us-east-2-6c1dae89-1791-4acd-85ef-49fb48fe188f/main.yml
Parameters:
Index ParameterKey ParameterValue
------- ------------------- --------------------------------------------------------------------------------
0 TemplateS3BucketURL https://cfn-exec-us-east-2-6c1dae89-1791-4acd-85ef-49fb48fe188f.s3.amazonaws.com
1 BucketName cfnexec-example2-test-01234567890123456789
Since local-file2 already exists, create new change set.
Creating to change set... : local-file2-eb08e8bf-6760-4b0e-8d35-0d23d21e8412
Creation to change set completed successfully!! : local-file2-eb08e8bf-6760-4b0e-8d35-0d23d21e8412
Creation to change set completed successfully!! : local-file2-eb08e8bf-6760-4b0e-8d35-0d23d21e8412
Index Type Action LogicalResourceId PhysicalResourceId ResourceType Replacement
------- -------- -------- ------------------- ----------------------------------------- --------------- -------------
0 Resource Modify S3Bucket cfnexec-example-test-01234567890123456789 AWS::S3::Bucket True
Execute to change set: local-file2-eb08e8bf-6760-4b0e-8d35-0d23d21e8412
Executing change set...
Execution to change set completed successfully!! : local-file2-eb08e8bf-6760-4b0e-8d35-0d23d21e8412
最後にExecuteし適用している
2.11 (参考)変更セット作成失敗時の結果
$ cfn-exec -n local-file2 -i ./example/input/main.yml -p ./example/param.yml
Found credentials in environment variables.
StackName: local-file2
CFn URL: https://s3-us-east-2.amazonaws.com/cfn-exec-us-east-2-cfb30642-3946-4421-86cc-66b58fff76c9/main.yml
Parameters:
Index ParameterKey ParameterValue
------- ------------------- -----------------------------------------
0 TemplateS3BucketURL TemplateS3BucketURL
1 BucketName cfnexec-example-test-01234567890123456789
Since local-file2 already exists, create new change set.
Creating to change set... : local-file2-4dc75f4e-918c-4bd5-9606-32625c5107af
Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state: For expression "Status" we matched expected path: "FAILED"
Attempted to create but failed... : local-file2-4dc75f4e-918c-4bd5-9606-32625c5107af
Reason: TemplateURL must be a supported URL.
おわりに
おそらく似たようなツールは世の中と各会社内に山ほどあると思うが、検索能力がなく見つけられなかったので作った
誰かしらが助かることを祈って