はじめに
世の中にはとても便利なものがありふれており...
今回は CircleCI
と AWS CloudFormation (以下 CFn)
をメインにタイトルのようなことをしていくやつです。
みんな大好き CircleCI
troposhpere っていうのは CFn のテンプレートを Python を使って生成するツールです。
テンプレートを自分でゴリゴリ書けるぜ!!Foooooo!!な方は別に troposphere 使わんでもいいと思うし自分で書けばいいと思う。
環境
- Python 3.7.4
- pip==19.3
- poetry==0.12.17
- troposphere = "^2.5"
- boto3 = "^1.9"
- awscli = "^1.16"
- awacs = "^0.9.6"
- poetry==0.12.17
- CircleCI 2.0
- Amazon Web Services
準備
AWS のアカウントは持っている前提です。また IAM
CFn
S3
へのアクセス権限が必要になります。ここでは詳細な権限は省略します。
CircleCI からアクセスするユーザを作る
ここは、ぶっちゃけパパっと Web から作ってもいいと思うんですけどどうせなら CFn
で作りましょうよということで。
from awacs.aws import Action, Allow, PolicyDocument, Statement from troposphere import Ref, Template from troposphere.iam import PolicyType, User from troposphere.validators import iam_user_name circleci_user = User( 'CircleCIUser', UserName=iam_user_name('circleci') ) circleci_user_policy = PolicyType( 'CircleCIUserPolicy', PolicyName='CircleCIUserPolicy', Users=[Ref(circleci_user)], PolicyDocument=PolicyDocument( Statement=[ Statement( Effect=Allow, Action=[ Action(prefix='s3', action='Get*'), Action(prefix='s3', action='PutObject'), Action(prefix='s3', action='DeleteObject'), Action(prefix='s3', action='ListBucket'), ], Resource=[ 'arn:aws:s3:::{{ YOUR_BUCKET }}', 'arn:aws:s3:::{{ YOUR_BUCKET }}/*', ] ), Statement( Effect=Allow, Action=[ Action(prefix='cloudformation', action='Describe*'), Action(prefix='cloudformation', action='EstimateTemplateCost'), Action(prefix='cloudformation', action='Get*'), Action(prefix='cloudformation', action='List*'), Action(prefix='cloudformation', action='ValidateTemplate'), Action(prefix='cloudformation', action='DetectStackDrift'), Action(prefix='cloudformation', action='DetectStackResourceDrift'), ], Resource=['*'] ) ] ) ) t = Template() t.add_resource(circleci_user) t.add_resource(circleci_user_policy) print(t.to_yaml(cleanup=True))
という感じで。
{{ YOUR_BUCKET }}
は使用する S3 のバケットです。
ファイルに書き出す際は、1番上に
AWSTemplateFormatVersion: 2010-09-09
を入れておくといいでしょう。
本当はこれ自体をはじめから CFn の検証に当てたいんですけどまぁ別にそんな大したことないしとりあえず、 CFn のスタック生成に当てて作っちゃいましょう!
続いて circleci
ユーザのアクセスキーを生成して IAM から取得してメモしておきましょう!
CircleCI の設定
Web から Git の WebHook 等の設定をしています。
先程メモした、 circleci
ユーザのアクセスキー等を CircleCI のプロジェクトの設定画面の Environment Variables
に設定しておきましょう!
.circleci/config.yml
はこんな感じです。
version: 2 jobs: build: docker: - image: circleci/python:3.7.4 working_directory: ~/repo steps: - checkout - restore_cache: keys: - v1-dependencies-{{ checksum "poetry.lock" }} - run: name: Install dependencies command: | pip install -U pip==19.3 pip install poetry poetry install - save_cache: paths: - /home/circleci/.cache/pypoetry/virtualenvs/project-py3.7 key: v1-dependencies-{{ checksum "poetry.lock" }} - run: name: Export all configurations command: | poetry run python all_export.py -e # ここですべての設定を書き出しています - run: name: Create aws credentials & config command: | mkdir -p ~/.aws echo "[default]" > ~/.aws/credentials echo "aws_access_key_id = ${AWS_ACCESS_KEY_ID}" >> ~/.aws/credentials echo "aws_secret_access_key = ${AWS_SECRET_ACCESS_KEY}" >> ~/.aws/credentials cat >> ~/.aws/config << EOF [profile default] region = ap-northeast-1 output = json EOF - run: name: Upload to S3 & Validate outputs command: | poetry run aws s3 sync outputs/ s3://{{ YOUR_BUCKET }}/ --exclude "*" --include "*.yml" --cache-control "max-age=0" poetry run aws cloudformation validate-template --template-url https://{{ YOUR_BUCKET }}.s3-{{ YOUR_REGION }}.amazonaws.com/{{ FILE_1 }}.yml poetry run aws cloudformation validate-template --template-url https://{{ YOUR_BUCKET }}.s3-{{ YOUR_REGION }}.amazonaws.com/{{ FILE_2 }}.yml poetry run aws cloudformation validate-template --template-url https://{{ YOUR_BUCKET }}.s3-{{ YOUR_REGION }}.amazonaws.com/{{ FILE_3 }}.yml - store_artifacts: path: outputs
途中で、 ~/.aws/credentials
と ~/.aws/config
を作っているのですが、もしかしたら環境変数を設定していたら必要ないかも🤔
なぜここでこんな面倒臭いことをしてるかというと、 CircleCI のプロジェクト設定画面にある AWS Permissions
に設定をするとどうやらジョブ(or Workflow ここは検証してない)に付き、1回しか反映されないっていう仕様らしいので生成した。
outputs/
に検証したいファイルを一旦書き出しを行って、 awscli
によって *.yml
に一致するものを同期するようにした。あとは CFn の検証にかけるだけ。おわおわり。
最後に
今、お仕事で 3,000 行近くの CFn テンプレートを生成していて、私にはそんなことをできる力はないのでググってたら troposphere
というツールを発見した。
なので検証も同時にできると嬉しいなって思って CircleCI を使ってテストという感じで実装をしてみた。
ちなみに CFn の検証に失敗するとしっかりと終了コードが 0
以外になってくれるので CircleCI 上でもテスト失敗という感じで返してくれる。
今度もしかしたら書くかもしれないけど CloudFront
+ S3
+ AWS Lambda
+ Route53
による CFn のテンプレート生成のときに循環依存などの検証で今回の CircleCI
での運用がありがたい感じに作用してくれた。
おまけ
私は、 Python を使ったのプロジェクトの開発は PyCharm
を使う人間なのだが、 Run/Debug Configurations
に export
upload
validate
という Configurations をそれぞれ作って PyCharm でも一応テストできるようにはしてある。
主に Python を書いている iOS アプリエンジニアでした。