pipenv + aws-sam-cli + python-dotenv でチーム開発

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

1. はじめに

クラウドインテグレーション部の千葉です。

Python が好きなので、Lambda を使った開発の際は Serverless Frameworkaws-python3 のテンプレートを当てて使っています。
ただ、Serverless Framework 自体が Node.js で動いているので、ちょっとしたタスクをやらせるダケなのにファイルや README.md の内容が増えちゃってウンザリしちゃうんです。

そんなワケで『基本は Serverless Framework』としつつ『定期的にSalesforceのレコード検索して結果をSlackに投稿する』的な、ちょっとしたモノは Python のみでサクっと作っちゃいたい。と思い、 aws / serverless-application-model(以下、SAM) をつかった開発の流れを整理しておくことにしました。

例として、2人のチームで 毎週金曜日の 10:00(JST) に OpenWeatherMap で任意の場所の天気を Lambda のログに出力する って処理を実装するイメージで解説していきます。
Salesforceのレコード検索して結果をSlackに投稿 だと、コードの説明が長くなっちゃいそうなので簡易的なものにしました)

以下、2人の参加者を便宜的にリーダー / メンバーと表現します。

2. リーダーの作業

2-1. Python 3.8.6 環境に pipenv / aws-sam-cli をインストール

$ pyenv install 3.8.6
$ cd /tmp
$ pyenv local 3.8.6
$ pyenv install pipenv
$ pyenv install aws-sam-cli

2-2. SAM プロジェクトの作成・移動

$ sam init --runtime python3.8 --app-template hello-world --output-dir ~/Developments --name owm-example
$ cd ~/Developments/owm-example

2-3. pipenv 仮想環境の構築

$ pyenv local 3.8.6
$ pipenv --python 3.8.6
$ pipenv shell

2-4. パッケージのインストール

次のコマンドで --dev オプションが付いているものは、開発環境にのみ必要なものとなります。

$ pipenv install aws-sam-cli --dev
$ pipenv install flake8 --dev
$ pipenv install python-dotenv --dev
$ pipenv install pyowm

2-5. ディレクトリ構造、ファイル名の変更

SAM の hello-world テンプレートの状態から、ディレクトリ構造・ファイル名の変更を実施します。

# 変更前の状態
.
|-- Pipfile
|-- Pipfile.lock
|-- README.md
|-- __init__.py -------------> 削除
|-- events ------------------> ディレクトリごと削除
|   `-- event.json
|-- hello_world -------------> src に変更
|   |-- __init__.py ---------> 削除
|   |-- app.py --------------> handler.py に変更
|   `-- requirements.txt
|-- template.yaml
`-- tests -------------------> ディレクトリごと削除
    |-- __init__.py
    `-- unit
        |-- __init__.py
        `-- test_handler.py

# コマンドの実行
$ rm -rf events
$ rm -rf tests
$ mv hello_world src
$ mv src/app.py src/handler.py
$ rm __init__.py
$ rm src/__init__.py

2-6. template.yaml の編集

SAM の hello-world テンプレート用の状態から、以下の内容に書き換えます。

2-7. コード解析ツールの設定ファイルを作成

flake8 の設定ファイル (.flake8)を以下の内容で作成します。

  • 1行の長さが79文字以下の制限を無効
  • .aws-sam 以下を解析対象から除外

2-8. サンプル環境変数ファイル、開発用の環境変数ファイルの作成

開発時に必要になる環境変数のサンプルファイルを、以下の内容で作成します。

作成した sample.env を元に開発環境用の環境変数ファイルを作成します。

$ cp sample.env .env
$ vim .env

OpenWeatherMap の自アカウントの API Key と、自分は住んでいるエリアに書き換えます。

2-9. バージョン管理除外ファイルの追記

Git リポジトリで管理したくないファイルを .gitignore に追記します。

$ echo ".env" >> .gitignore
$ echo ".aws-sam/" >> .gitignore
$ echo "src/requirements.txt" >> .gitignore
$ echo "samconfig.toml" >> .gitignore

2-10. メインのコード実装

src/handler.py を、以下の内容で書き換えます。

ローカル環境での動作確認

$ python src/handler.py
Yokohama,Jp - Current Weather: Clouds

2-11. ビルド、Docker環境での動作確認

以下のとおり、ビルドコマンドを実行して Build Succeeded が返ってくることを確認してください。

$ pipenv lock -r > src/requirements.txt; sam build

Building codeuri: src/ runtime: python3.8 metadata: {} functions: ['WeeklyTask']
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided

Docker環境での動作確認

$ sam local invoke --parameter-overrides ApiKey=#{開発用のAPI Key} Place=Yokohama,Jp

2-12. 自分のAWS環境へのデプロイ

デプロイの実行(コマンド実行後のガイダンスに答えるかたちで進みます)
ApiKey と Place の値には、開発環境用の値を指定してください。

$ sam deploy --guided --parameter-overrides ApiKey=#{開発用のAPI Key} Place=Yokohama,Jp --stack-name WeeklyTaskDev

2-13. Git リポジトリへ Push

コード解析の実行

$ flake8

特にヘンなコードも無いようなので、GitHub や CodeCommit 等の適当な場所にリポジトリを作成して master ブランチに Push します。

$ git init
$ git remote add origin ssh://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/owm-example
$ git add .
$ git commit -m "first commit" 
$ git push origin master

2-14. 本番AWS環境へのデプロイ

デプロイの実行(コマンド実行後のガイダンスに答えるかたちで進みます)
ApiKeyPlace の値には、本番環境用の値を指定してください。

$ sam deploy --guided --parameter-overrides ApiKey=#{本番用のAPI Key} Place=Tokyo,Jp --stack-name WeeklyTaskProd --profile prod

3. メンバーの作業

3-1. Git リポジトリのクローン、移動

$ git clone ssh://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/owm-example ~/Developments/owm-example
$ cd ~/Developments/owm-example

3-2. Python 3.8.6 の仮想環境構築、パッケージのインストール

$ pyenv install 3.8.6
$ pyenv local 3.8.6
$ pip install pipenv
$ pipenv --python 3.8.6
$ pipenv shell
$ pipenv sync --dev

3-3. 開発環境用の環境変数ファイルの作成

sample.env を元に開発環境用の環境変数ファイルを作成します。

$ cp sample.env .env
$ vim .env

OpenWeatherMap の自アカウントの API Key と、自分は住んでいるエリアに書き換えます。

3-4. コードの改修

フィーチャーブランチの作成

$ git branch feature/add-datetime
$ git checkout feature/add-datetime

src/handler.py を編集して、現在のシステム日時を出力するようにしました。

ローカル環境での動作確認(末尾に日時が出力されるようになりました)

$ python src/handler.py
Chiba,Jp - Current Weather: Clouds (2020-12-16 23:13:00.868971)

3-5. ビルド、Docker環境での動作確認

以下のとおり、ビルドコマンドを実行して Build Succeeded が返ってくることを確認してください。

$ pipenv lock -r > src/requirements.txt; sam build

Building codeuri: src/ runtime: python3.8 metadata: {} functions: ['WeeklyTask']
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided

Docker環境での動作確認

$ sam local invoke --parameter-overrides ApiKey=#{開発用のAPI Key} Place=Chiba,Jp

3-6. Commit、Push、PullRequest の作成

コード解析の実行

$ flake8

特にヘンなコードも無いようなので、リモートリポジトリに Push します。

$ git add src/handler.py
$ git commit -m "システム日時を出力するようにしました"
$ git push origin feature/add-datetime

feature/add-datetime ブランチ → master ブランチへの PullRequest を作成。(GitHub Flow を想定)

3-7. 自分のAWS環境へのデプロイ

デプロイの実行(コマンド実行後のガイダンスに答えるかたちで進みます)
ApiKey と Place の値には、開発環境用の値を指定してください。

$ sam deploy --guided --parameter-overrides ApiKey=#{開発用のAPI Key} Place=Chiba,Jp --stack-name WeeklyTaskDev

3-8. 本番AWS環境へのデプロイ

デプロイの実行(コマンド実行後のガイダンスに答えるかたちで進みます)
ApiKeyPlace の値には、本番環境用の値を指定してください。

$ git checkout master
$ git pull origin
$ sam deploy --guided --parameter-overrides ApiKey=#{本番用のAPI Key} Place=Tokyo,Jp --stack-name WeeklyTaskProd --profile prod

4. まとめ

なんだか長くなっちゃいましたが、ちょっとしたモノを Python のみでサクっと作りたいときの手順を整理してみました。
最終的なファイル構成は以下のとおりです。

.
|-- .env --------------------> Git リポジトリ管理外
|-- .flake8
|-- .gitignore
|-- Pipfile
|-- Pipfile.lock
|-- README.md
|-- samconfig.toml ----------> Git リポジトリ管理外
|-- sample.env
|-- src
|   |-- handler.py
|   `-- requirements.txt ----> Git リポジトリ管理外
`-- template.yaml

以上、おつかれさまでした。

千葉 哲也 (執筆記事の一覧)

クラウドインテグレーション部

コーヒーゼリーが好きです。