🎃

rainとMakefileを使って効率的にCloudFormationを管理する

2025/01/20に公開

はじめに

AWSのCloudFormationを効率的に扱うためのユーティリティとしてrainコマンドがあります。本記事では、rain.mkというMakefileでrainを使用し、中小規模のCloudFormationテンプレート管理をシンプルにする方法を紹介します。

rainとは?

rainは、CloudFormationテンプレートを扱うための便利なCLIツールです。フォーマット整形、リソースの差分確認、テンプレートのデプロイや削除など、多機能なCLIツールとして、AWSリソース管理を効率化します。詳しくは、下記のURLを参照してください。

私の環境は?

  • Lubuntu24.04
  • rain v1.21.0
  • aws-cli v2.22.33
  • cfn-lint v1.22.4
  • envsubst v0.23
  • GNU Make v4.3

rain.mkのコード解説

rainコマンドの使用方法を共通化して再利用できるように、rain.mkを用意します。
makefileの内容は以下のとおり。

rain.mkのコード全体
rain.mk
############################################################################
#
# rain command utilities
#
# [required commands]
#  - rain
#  - aws-cli
#  - cfn-lint
#  - envsubst
#  - make
#
# [parameters]
#  - required
#    - RAIN_STACK_NAME: name of the stack
#    - RAIN_CFN_YML   : name of the CFN template file
#    - RAIN_PROFILE   : aws profile
#  - options
#    - RAIN_CONFIG    : name of the rain config file (cfn parameters, tags)
#    - RAINOPT        : rain additional options (except for pkg)
#    - RAINPKGOPT     : rain pkg options
#
############################################################################

# variables ---------------------------------------------------------------

RAIN_CFN_DIR            := $(shell basename $(shell dirname $(PWD)))/$(shell basename $(PWD))
RAIN_CONFIG_DEFAULT_TAG := ../rain_conf_default_tags.yml
RAIN_TEMPLATE_TMP       := $(RAIN_STACK_NAME).tmpl.raintmp.yml
RAIN_CONFIG_TMP         := $(RAIN_STACK_NAME).conf.raintmp.yml

# defines -----------------------------------------------------------------

RAIN_I_COL1 := \033[32m
RAIN_I_ICON := *🌂* rain.mk *
RAIN_I_COL2 := \033[0m
define rain_msg_info
	@echo -e "$(RAIN_I_COL1)$(RAIN_I_ICON) $1$(RAIN_I_COL2)"
endef

RAIN_E_COL1 := \033[31m
RAIN_E_ICON := *☔* rain.mk *
RAIN_E_COL2 := \033[0m
define rain_msg_err
	echo -e "$(RAIN_E_COL1)$(RAIN_E_ICON) Error: $1$(RAIN_E_COL2)"
endef

define rain_create_tmp
	@if [ -e "$(RAIN_TEMPLATE_TMP)" ]; then \
	  $(call rain_msg_err,"$(RAIN_TEMPLATE_TMP) already exists. run 'make rain_clean'."); \
	  exit 1; \
	fi
	@if [ -e "$(RAIN_CONFIG_TMP)" ]; then \
	  $(call rain_msg_err,"$(RAIN_CONFIG_TMP) already exists. run 'make rain_clean'."); \
	  exit 1; \
	fi
	$(call rain_msg_info,"run rain pkg.")
	@if ! rain pkg $(RAIN_CFN_YML) --no-analytics -o $(RAIN_TEMPLATE_TMP) $(RAINPKGOPT); then \
	  $(call rain_msg_err,"rain pkg failed."); \
	  exit 1; \
	fi
	$(call rain_msg_info,"run cfn-lint.")
	@if ! cfn-lint $(RAIN_TEMPLATE_TMP); then \
	  $(call rain_msg_err,"cfn-lint failed."); \
	  exit 1; \
	fi
	@if ! envsubst < $(RAIN_CONFIG_DEFAULT_TAG) > $(RAIN_CONFIG_TMP); then \
	  $(call rain_msg_err,"envsubst failed. $(RAIN_CONFIG_DEFAULT_TAG)"); \
	  exit 1; \
	fi
	@if [ ! -z "$(RAIN_CONFIG)" ]; then \
	  if ! envsubst < "$(RAIN_CONFIG)" >> $(RAIN_CONFIG_TMP); then \
	    $(call rain_msg_err,"envsubst failed. $(RAIN_CONFIG)"); \
	    exit 1; \
	  fi \
	fi
	$(call rain_msg_info,"print rain config.")
	@cat $(RAIN_CONFIG_TMP)
endef

# targets -----------------------------------------------------------------

all:
	$(eval SHELL := /bin/bash)
	$(call rain_msg_info,"Available targets:")
	$(call rain_msg_info,"  rain_lint       - Lint the CloudFormation template")
	$(call rain_msg_info,"  rain_forecast   - Show the forecast of stack changes")
	$(call rain_msg_info,"  rain_deploy     - Deploy the stack")
	$(call rain_msg_info,"  rain_rm         - Remove the stack")
	$(call rain_msg_info,"  rain_diff       - Compare local and deployed stack")
	$(call rain_msg_info,"  rain_ls         - Show stack information")
	$(call rain_msg_info,"  rain_logs       - Show stack logs")
	$(call rain_msg_info,"  rain_tree       - Show stack resource tree")
	$(call rain_msg_info,"  rain_info       - Display the AWS account and region.")
	$(call rain_msg_info,"  rain_clean      - Clean temporary files")

rain_lint:
	$(eval SHELL := /bin/bash)
	$(call rain_msg_info,"Lint the CloudFormation template.")
	$(call rain_msg_info,"print stack name.")
	@echo "$(RAIN_STACK_NAME)"
	$(call rain_create_tmp)
	$(call rain_msg_info,"run rain.")
	-rain fmt $(RAIN_TEMPLATE_TMP) $(RAINOPT)
	@make rain_clean

rain_forecast:
	$(eval SHELL := /bin/bash)
	$(call rain_msg_info,"Show the forecast of stack changes.")
	$(call rain_msg_info,"print stack name.")
	@echo "$(RAIN_STACK_NAME)"
	$(call rain_create_tmp)
	$(call rain_msg_info,"run rain.")
	-rain forecast $(RAIN_TEMPLATE_TMP) $(RAIN_STACK_NAME) $(RAINOPT) \
	--experimental \
	--profile $(RAIN_PROFILE) \
	--config $(RAIN_CONFIG_TMP)
	@make rain_clean

rain_deploy:
	$(eval SHELL := /bin/bash)
	$(call rain_msg_info,"Deploy the stack.")
	$(call rain_msg_info,"print stack name.")
	@echo "$(RAIN_STACK_NAME)"
	$(call rain_create_tmp)
	$(call rain_msg_info,"run rain.")
	-rain deploy $(RAIN_TEMPLATE_TMP) $(RAIN_STACK_NAME) $(RAINOPT) \
	--profile $(RAIN_PROFILE) \
	--config $(RAIN_CONFIG_TMP)
	@make rain_clean

rain_rm:
	$(eval SHELL := /bin/bash)
	$(call rain_msg_info,"Remove the stack.")
	$(call rain_msg_info,"print stack name.")
	@echo "$(RAIN_STACK_NAME)"
	$(call rain_msg_info,"run rain.")
	rain rm $(RAIN_STACK_NAME) $(RAINOPT) \
	--profile $(RAIN_PROFILE)

rain_diff:
	$(eval SHELL := /bin/bash)
	$(call rain_msg_info,"Compare local and deployed stack.")
	$(call rain_msg_info,"print stack name.")
	@echo "$(RAIN_STACK_NAME)"
	$(call rain_create_tmp)
	$(call rain_msg_info,"run rain.")
	-rain diff <(rain cat $(RAIN_STACK_NAME) --profile $(RAIN_PROFILE) $(RAINOPT)) \
	$(RAIN_TEMPLATE_TMP)
	@make rain_clean

rain_ls:
	$(eval SHELL := /bin/bash)
	$(call rain_msg_info,"Show stack information.")
	$(call rain_msg_info,"print stack name.")
	@echo "$(RAIN_STACK_NAME)"
	$(call rain_msg_info,"run rain.")
	rain ls $(RAIN_STACK_NAME) $(RAINOPT) \
	--profile $(RAIN_PROFILE)

rain_logs:
	$(eval SHELL := /bin/bash)
	$(call rain_msg_info,"Show stack logs.")
	$(call rain_msg_info,"print stack name.")
	@echo "$(RAIN_STACK_NAME)"
	$(call rain_msg_info,"run rain.")
	rain logs $(RAIN_STACK_NAME) $(RAINOPT) \
	--all \
	--profile $(RAIN_PROFILE)

rain_tree:
	$(eval SHELL := /bin/bash)
	$(call rain_msg_info,"Show stack resource tree.")
	$(call rain_msg_info,"print stack name.")
	@echo "$(RAIN_STACK_NAME)"
	$(call rain_create_tmp)
	$(call rain_msg_info,"run rain.")
	-rain tree $(RAIN_TEMPLATE_TMP) $(RAINOPT)
	@make rain_clean

rain_info:
	$(eval SHELL := /bin/bash)
	$(call rain_msg_info,"Display the AWS account and region.")
	$(call rain_msg_info,"print stack name.")
	@echo "$(RAIN_STACK_NAME)"
	$(call rain_msg_info,"run rain.")
	rain info $(RAINOPT) \
	--profile $(RAIN_PROFILE)

rain_clean:
	@rm -f *.raintmp.yml > /dev/null 2>&1

############################################################################
.PHONY: all rain_lint rain_forecast rain_deploy rain_rm rain_diff rain_ls rain_logs rain_tree rain_info rain_clean

必要なコマンドとパラメータ

必須コマンド

rain.mkには下記のコマンドが必要です。インストールしておいてください。

  • rain: CloudFormationを操作するツール。
  • aws-cli: AWSのサービスをコマンドラインから操作できるツール。
  • cfn-lint: CloudFormationテンプレートの検証ツール。
  • envsubst: 環境変数の置換に使用。
  • make: Makefileの実行に使用。

必須パラメータ

rain.mkを使用する場合、下記の環境変数は、必ず設定してください。

  • RAIN_STACK_NAME: デプロイするスタック名。
  • RAIN_CFN_YML: CloudFormationテンプレートファイル名。
  • RAIN_PROFILE: 使用するAWSプロファイル。

オプションパラメータ

rain.mkを使用する場合、下記の環境変数は、必要な場合に設定してください。

  • RAIN_CONFIG: rainの設定ファイル(CloudFormationパラメータやタグを含む)。
  • RAINOPT: rainコマンドに渡す追加オプション。(pkg除く)
  • RAINPKGOPT: rain pkgに渡す追加オプション。

主なターゲットの説明

rain_lint

CloudFormationテンプレートを検証し、フォーマットしたテンプレートと一緒にパラメータとタグも表示します。

  • CloudFormationテンプレートの再生成: rain pkgを使用。!RAIN::Includeなどのrain特有の機能を処理してCloudFormationテンプレートを生成。
  • テンプレートの検証: cfn-lintを使用。
  • rainのフォーマットを適用して表示: rain fmtを使用。
make rain_lint

rain_forecast

変更がAWSリソースに与える影響を事前に予測・可視化します。

make rain_forecast

rain_deploy

CloudFormationテンプレートを適用してスタックを作成または更新します。

make rain_deploy

rain_rm

スタックを削除します。

make rain_rm

rain_diff

ローカルテンプレートと現在のデプロイ済みスタックの差分を確認します。

make rain_diff

rain.mkの使用方法

rain.mkは、単独では使用しません。Makefileにincludeして使用します。

ディレクトリ構造例

以下は、ディレクトリ構造の例です。プロジェクト単位またはサービス単位などに分けてディレクトリを作成し、複数のスタックを管理する想定です。

├── projectA/
│   ├── Makefile
│   ├── cfn_iam_role.yml
│   ├── cfn_sg.yml
│   └── rain_sg.yml
├── rain.mk
├── rain_conf_default_tags.yml
└── rain_inc_map_vpc.yml

Makefileの内容解説

Makefileではrain.mkをincludeして簡潔にCloudFormationを操作します。exportは必須です。

Makefileのコード全体
Makefile
#
# CloudFormation sample
#

include ../rain.mk
export

# parameters of rain.mk (required)
RAIN_PROFILE := sandbox

# parameters of rain.mk (optional)
#RAINOPT :=

# parameters of RAIN_CONFIG (sample)
# SECRET := $(shell aws secretsmanager get-secret-value --secret-id password --query SecretString --output text --profile $(RAIN_PROFILE))

# target of rain.mk
RAINCMD := rain_lint

# stack of Security Group
sg:
	$(eval RAIN_STACK_NAME := sample-sg)
	$(eval RAIN_CFN_YML    := cfn_sg.yml)
	$(eval RAIN_CONFIG     := rain_sg.yml)
	$(eval SG_NAME         := sample)
	make $(RAINCMD)

# stack of IAM Role
role:
	$(eval RAIN_STACK_NAME := sample-role)
	$(eval RAIN_CFN_YML    := cfn_iam_role.yml)
	make $(RAINCMD)

# .PHONY targets are used to declare targets that are not associated with real files.
.PHONY: sg role

ターゲットの定義

sgおよびroleは、異なるスタックを操作するためのターゲットです。

  • sg:
    • スタック名: sample-sg
    • テンプレート: cfn_sg.yml
    • 設定ファイル: rain_sg.yml
  • role:
    • スタック名: sample-role
    • テンプレート: cfn_iam_role.yml

RAINCMDの設定

RAINCMDに目的の操作を設定します。デフォルトは、rain_lintとし、make実行時にRAINCMDを変更します。これにより、RAINCMDを打ち間違うと、rain_lintが実行されます。

RAINCMD := rain_lint

目的の操作を切り替えたいときは、makeコマンド実行時に以下のようにします。

make sg RAINCMD=rain_deploy

RAIN_PROFILEの設定

RAIN_PROFILEにはCloudFormation対象のAWS環境を設定します。
設定値は、awscliに定義したprofileです。MakefileにはデフォルトのAWS環境(開発環境など)を記述します。

RAIN_PROFILE := sandbox

処理対象の環境を切り替えるときは、makeコマンド実行時に以下のようにします。

make sg RAINCMD=rain_deploy RAIN_PROFILE=production

localstackでCloudFormationのテストをしたい場合は、以下のように実行します。
下記例の192.168.10.10は、PCのIPアドレスです。localhostはNGです。

make sg RAINCMD=rain_deploy RAIN_PROFILE=localstack AWS_ENDPOINT_URL=http://192.168.10.10:4566

rain_config_default_tags.yml

全スタックに必須のタグを定義します。

rain_config_default_tags.yml
Tags:
  author: sre
  cfn_location: ${RAIN_CFN_DIR}/${RAIN_CFN_YML}
  orchestrator: rain.mk

rain_sg.yml

cfn_sg.ymlに入力するパラメータを定義します。この設定により、実行時にパラメータを手動で入力する必要を無くし、誰でも簡単に実行できるようにしています。

rain_sg.yml
Parameters:
  SgName: ${SG_NAME}

固有のタグ(ex. コストタグ)を設定したい場合は以下のようにします。

rain_sg.yml
  CostGroup: projectA
Parameters:
  RoleName: ${SG_NAME}

固有のタグ(ex. コストタグ)だけ設定したい場合は以下のようにします。

rain_sg.yml
  CostGroup: projectA

環境変数は、envsubstコマンドによって置換されるため、以下のようなメリットがあります。

  1. 一貫性のある設定管理
    環境変数を使用することで、異なる環境(開発、テスト、本番など)に対して一貫した設定を適用できます。これにより、環境ごとに異なる設定ファイルを用意する手間が省けます。

  2. 簡単なメンテナンス
    環境変数を変更するだけで設定を更新できるため、設定ファイルのメンテナンスが容易になります。特に、複数のプロジェクトやスタックを管理する場合に便利です。

  3. セキュリティの向上
    環境変数を使用することで、機密情報(例: APIキーやパスワード)をコードベースに直接記述することを避けられます。これにより、セキュリティリスクを低減できます。
    例として、Makefileには環境変数(SECRET)を定義するコメントがあります。

  4. 柔軟性の向上
    環境変数を使うことで、同じテンプレートを異なる用途や条件で再利用しやすくなります。これにより、コードの再利用性が向上します。

rain_inc_map_vpc.yml

以下は、他のスタックと共有するMappingsの定義です。rainの機能を利用してテンプレートにインクルードして使用します。
私は、CFNテンプレートのMappingsをよく使うのですが、複数のテンプレートで共有したいMappingsがある場合に、この方法を利用しています。

rain_inc_map_vpc.yml
AccountToVpcParams:
  "012345678901":
    VpcId: vpc-1234
    VpcCidr: 10.0.0.0/16
    PrivateSubnetId1: subnet-2345
    PrivateSubnetId2: subnet-6789

cfn_sg.yml

CloudFormationのテンプレートを定義します。!RAIN::Includeのようなrainのプロパティも使用できます。

cfn_sg.ymlのコード全体
cfn_sg.yml
AWSTemplateFormatVersion: "2010-09-09"
Description: sg

Parameters:
  SgName:
    Type: String

Rain:
  Constants:
    Test1: sample
    Test2: !Sub ${Rain::Test1}-comment

Mappings:
  !Rain::Include ../rain_inc_map_vpc.yml

Resources:

  SecurityGroup1:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !FindInMap [ AccountToVpcParams, !Ref "AWS::AccountId", "VpcId" ]
      GroupName: !Sub "${SgName}-1"
      GroupDescription: !Rain::Constant Test1
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: !FindInMap [ AccountToVpcParams, !Ref "AWS::AccountId", "VpcCidr" ]

  SecurityGroup2:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !FindInMap [ AccountToVpcParams, !Ref "AWS::AccountId", "VpcId" ]
      GroupName: !Sub "${SgName}-2"
      GroupDescription: !Rain::Constant Test2
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: !FindInMap [ AccountToVpcParams, !Ref "AWS::AccountId", "VpcCidr" ]

CloudFormation操作の例

以下に、実際にMakefileを使ってCloudFormationスタックを操作する例を記します。

テンプレートの検証

sgのCFNテンプレートを検証するには以下のコマンドを実行します。RAINCMDのデフォルト値をrain_lintにしているので、RAINCMDは省略できます。
なお、!Rain::Includeなどは、処理された状態でcfn-lintが実行されます。

make sg

lintエラーの場合は、以下のように表示されます。カレントにワークファイル(下記の例だとsample-sg.tmpl.raintmp.yml)があるので、それでエラー内容を確認できます。
このワークファイルは、rain pkgを実行して、!Rain::Includeのようなrainのプロパティを処理したものです。スタック名.tmpl.raintmp.ymlの命名規則でワークファイルが作成されます。
再度、make sgする前に、make rain_cleanを実行してこのワークファイルを削除してください。

実行例(lintエラー)
$ make sg
make rain_lint
*🌂* rain.mk * Lint the CloudFormation template.
*🌂* rain.mk * print stack name.
sample-sg
*🌂* rain.mk * run rain pkg.
*🌂* rain.mk * run cfn-lint.
E1001 'Resources' is a required property
sample-sg.tmpl.raintmp.yml:1:1

E1001 Additional properties are not allowed ('Resources:' was unexpected. Did you mean 'Resources'?)
sample-sg.tmpl.raintmp.yml:19:1

*☔* rain.mk * Error: cfn-lint failed.
make[1]: *** [../rain.mk:101: rain_lint] エラー 1
make: *** [Makefile:23: sg] エラー 2

lintに成功した場合は、以下のようにフォーマットしたテンプレートとタグ、パラメータを表示します。
表示されるテンプレートは、rain pkgで生成したものです。ここで表示されたテンプレートを使用してスタックが作成(または更新)されます。

実行例(lint success)
$ make sg
make rain_lint
*🌂* rain.mk * Lint the CloudFormation template.
*🌂* rain.mk * print stack name.
sample-sg
*🌂* rain.mk * run rain pkg.
*🌂* rain.mk * run cfn-lint.
*🌂* rain.mk * print rain config.
Tags:
  author: sre
  cfn_location: rain_mk/projectA/cfn_sg.yml
  orchestrator: rain.mk
Parameters:
  SgName: sample
*🌂* rain.mk * run rain.
rain fmt sample-sg.tmpl.raintmp.yml
AWSTemplateFormatVersion: "2010-09-09"

Description: sg

Parameters:
  SgName:
    Type: String

Mappings:
  AccountToVpcParams:
    "012345678901":
      VpcId: vpc-1234
      VpcCidr: 10.0.0.0/16
      PrivateSubnetId1: subnet-2345
      PrivateSubnetId2: subnet-6789

Resources:
  SecurityGroup1:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !FindInMap
        - AccountToVpcParams
        - !Ref AWS::AccountId
        - VpcId
      GroupName: !Sub ${SgName}-1
      GroupDescription: sample
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: !FindInMap
            - AccountToVpcParams
            - !Ref AWS::AccountId
            - VpcCidr

  SecurityGroup2:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !FindInMap
        - AccountToVpcParams
        - !Ref AWS::AccountId
        - VpcId
      GroupName: !Sub ${SgName}-2
      GroupDescription: sample-comment
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: !FindInMap
            - AccountToVpcParams
            - !Ref AWS::AccountId
            - VpcCidr

rain pkgには、--no-analyticsをつけています。このオプションをつけないと、以下のようなMETADATAが追加されてdeploy時にエラーになります。(昔は、なかったのに。。。)

Metadata:
  AWSToolsMetrics:
    Rain: '{"Version":"v1.21.0","Experimental":false,"HasModules":false,"HasRainSection":false}'

スタックのデプロイ

sgのスタックをデプロイするには以下のコマンドを実行します。

make sg RAINCMD=rain_deploy

これにより、ChangeSetが作成され表示されます。内容を確認して問題なければ、"Y"を入力してデプロイを続行します。

実行例(ChangeSet confirm)
$ make sg RAINCMD=rain_deploy
make rain_deploy
*🌂* rain.mk * Deploy the stack.
*🌂* rain.mk * print stack name.
sample-sg
*🌂* rain.mk * run rain pkg.
*🌂* rain.mk * run cfn-lint.
*🌂* rain.mk * print rain config.
Tags:
  author: sre
  cfn_location: rain_mk/projectA/cfn_sg.yml
  orchestrator: rain.mk
Parameters:
  SgName: sample
*🌂* rain.mk * run rain.
rain deploy sample-sg.tmpl.raintmp.yml sample-sg  \
--profile sandbox \
--config sample-sg.conf.raintmp.yml
CloudFormation will make the following changes:
Stack sample-sg:
  + AWS::EC2::SecurityGroup SecurityGroup1
  + AWS::EC2::SecurityGroup SecurityGroup2
Do you wish to continue? (Y/n)

続行した場合は、sample-sgスタックが作成されます。

実行例(deploy success)
$ make sg RAINCMD=rain_deploy
make rain_deploy
*🌂* rain.mk * Deploy the stack.
*🌂* rain.mk * print stack name.
sample-sg
*🌂* rain.mk * run rain pkg.
*🌂* rain.mk * run cfn-lint.
*🌂* rain.mk * print rain config.
Tags:
  author: sre
  cfn_location: rain_mk/projectA/cfn_sg.yml
  orchestrator: rain.mk
Parameters:
  SgName: sample
*🌂* rain.mk * run rain.
rain deploy sample-sg.tmpl.raintmp.yml sample-sg  \
--profile sandbox \
--config sample-sg.conf.raintmp.yml
CloudFormation will make the following changes:
Stack sample-sg:
  + AWS::EC2::SecurityGroup SecurityGroup1
  + AWS::EC2::SecurityGroup SecurityGroup2
Do you wish to continue? (Y/n) Y
Deploying template 'sample-sg.tmpl.raintmp.yml' as stack 'sample-sg' in us-east-1.
Stack sample-sg: CREATE_COMPLETE
Successfully deployed sample-sg

差分確認

sgのテンプレートを修正後、デプロイ前に変更点を確認するには以下を実行します。

make sg RAINCMD=rain_diff

これにより、ローカルのテンプレートとデプロイ済みのスタックの内容が比較され、違いが表示されます。

実行例(compare)
$ make sg RAINCMD=rain_diff
make rain_diff
*🌂* rain.mk * Compare local and deployed stack.
*🌂* rain.mk * print stack name.
sample-sg
*🌂* rain.mk * run rain pkg.
*🌂* rain.mk * run cfn-lint.
*🌂* rain.mk * print rain config.
Tags:
  author: sre
  cfn_location: rain_mk/projectA/cfn_sg.yml
  orchestrator: rain.mk
Parameters:
  SgName: sample
*🌂* rain.mk * run rain.
rain diff <(rain cat sample-sg --profile sandbox ) \
sample-sg.tmpl.raintmp.yml
(|) Resources:
(|)   SecurityGroup1:
(|)     Properties:
(>)       GroupDescription: sample2
(|)   SecurityGroup2:
(|)     Properties:
(>)       GroupDescription: sample2-comment

スタックの削除

sgが不要になり、スタックを削除する場合は以下を実行します。

make sg RAINCMD=rain_rm

これにより、スタックを削除するか確認されます。問題なければ、"y"を入力して削除を続行します。

実行例(remove confirm)
$ make sg RAINCMD=rain_rm
make rain_rm
*🌂* rain.mk * Remove the stack.
*🌂* rain.mk * print stack name.
sample-sg
*🌂* rain.mk * run rain.
rain rm sample-sg  \
--profile sandbox
Stack sample-sg: CREATE_COMPLETE
Are you sure you want to delete this stack? (y/N)

続行した場合は、sample-sgスタックが削除されます。

実行例(remove success)
$ make sg RAINCMD=rain_rm
make rain_rm
*🌂* rain.mk * Remove the stack.
*🌂* rain.mk * print stack name.
sample-sg
*🌂* rain.mk * run rain.
rain rm sample-sg  \
--profile sandbox
Stack sample-sg: CREATE_COMPLETE
Are you sure you want to delete this stack? (y/N) y
Successfully deleted stack 'sample-sg'

まとめ

rain.mkとMakefileを使用することで、CloudFormationスタックの操作を効率化できます。テンプレートの検証からスタックのデプロイ、削除、差分確認まで、誰もが簡潔に行えるのがポイントです。

Discussion