API Gateway+Lambda+Serverless+TravisでAPI開発のCI/CDパイプラインを構築する

概要

スクリーンショット 2017-02-21 10.15.16.png

API GatewayとLambdaを使ったAPI開発時のCI/CDについての記事です。
僕がnode.jsを普段から使用しているため、解説はnodeがベースになっています。

https://github.com/horike37/serverless-api-integration-test-sample
ソースはすべてGitHubに上がってますのでそちらもご確認ください。

CIで実施する内容

以下の内容をCIとして行うことを考えます。

  • ESLintによる構文チェック
  • Mocha, Chaiを使用したユニットテスト
  • APIをAWSへデプロイしてテストを行うインテグレーションテスト

CDで実施する内容

以下のようなルールでデプロイのサイクルを回します。

  • Gitのdevelopmentブランチへのpushをテスト環境へのデプロイと想定。

    • 構文チェックとユニットテストを実施。
    • ビルドが通れば、ServerlessのdevelopmentステージにAPIをデプロイ。
  • Gitのmasterを最新ソースの集約場所として想定して、pushを実施。
    • 構文チェックとユニットテストとインテグレーションテストを実施。
    • ビルドが通ってもデプロイは実施しない。
  • Gitのtagへのpushを本番環境へのデプロイと想定。
    • 構文チェックとユニットテストとインテグレーションテストを実施。
    • ビルドが通れば、ServerlessのproductionステージにAPIをデプロイ。

Continuous Integration

ESLintによる構文チェック

http://eslint.org/
JavaScript界隈ではもっともメジャーな構文チェックツールだと思います。
構文ルールを定義して、構文エラーや記法を統一させることでソースの可読性や品質を向上させます。

https://github.com/horike37/serverless-api-integration-test-sample/blob/master/.eslintrc.js#L2
今回はルールとしてArbnbを採用しました。どの構文ルールを採用するかはチームの好みで決めれば良いと思います。

Mocha, Chaiを使用したユニットテスト

単体テストを実施します。メソッドや関数毎に入力値と出力値をチェックして関数単位での品質チェックを行います。

https://github.com/horike37/serverless-api-integration-test-sample/tree/master/lib
このようにLambdaがメインで実行する部分から、ビジネスロジックをclassに切り出してあげるとテストが書きやすくなるのでそうすることが多いです。

APIをAWSへデプロイしたテストを行うインテグレーションテスト

インテグレーションテストはサーバレスアーキテクチャの特徴とも言えるテストです。

サーバレスアーキテクチャは複数のサービスで構成されているケースが多く、ユニットテストだけではアーキテクチャ全体のテストを網羅できません。実際のクラウド環境へリソースをデプロイして結合テストを行い、すべて成功すれば、それを破棄します。

このデプロイ管理にはServerlessを使用しています。

https://github.com/horike37/serverless-api-integration-test-sample/blob/master/integration-test/test.js#L18
https://github.com/horike37/serverless-api-integration-test-sample/blob/master/integration-test/test.js#L41
テストの最初と最後にアーキテクチャのデプロイと削除を行っています。このメソッドの実体は、sls deploysls removeです。

it('should return correct values from all apis', () => {
     const testEndpoint = `${endpoint}/hello`;

     return fetch(testEndpoint, { method: 'GET' })
       .then(response => response.json())
       .then((json) => expect(json.message).to.equal('Go Serverless v1.0! Your function executed successfully!'));
  });

https://github.com/horike37/serverless-api-integration-test-sample/blob/master/integration-test/test.js#L35-L37
そしてここがテストのメインの部分です。デプロイされたAPIへリクエストを送り、その返り値をchaiでチェックを行います。
こうすることで何本APIを作ったとしても自動テストが可能になるというメリットがあります。

Continuous Delivery

デプロイスクリプト

以下の様なスクリプトでデプロイを実施します。Gitのtagにpushされた際にproduction環境へ。Gitのdevelopmentブランチにpushされた際にdeployment環境へ。それぞれビルドが正しく通ればデプロイされるようになっています。

bin/deploy.sh
#!/bin/bash
set -e
BRANCH=${TRAVIS_BRANCH:-$(git rev-parse --abbrev-ref HEAD)}
if [[ $TRAVIS_TAG ]]; then
  STAGE="production"
elif [[ $BRANCH == 'development' ]]; then
  STAGE="development"
fi

if [ -z ${STAGE+x} ]; then
  echo "Not deploying changes";
  exit 0;
fi

echo "Deploying from branch $BRANCH to stage $STAGE"
npm prune --production  #remove devDependencies
sls deploy --stage $STAGE --region $AWS_REGION

ServerlessのIAM権限

TravisにてServerlessが動作するように専用のユーザを発行します。今回は最低限で以下の様なIAMポリシーを与えています。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt543534534",
            "Effect": "Allow",
            "Action": [
                "iam:GetRole",
                "iam:CreateRole",
                "iam:DeleteRole",
                "iam:PutRolePolicy",
                "iam:DeleteRolePolicy",
                "iam:PassRole",
                "logs:*",
                "s3:*",
                "lambda:*",
                "cloudformation:*",
                "apigateway:*"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

そして、TravisからAWSリソースへアクセスするためにcredentialをTravisへ設定します。
もちろん生のcredentialを.travis.ymlへ追記することはご法度です。

Travisのコマンドにより暗号化し、credentialがTravisの環境上でしか使えないようにします。

$ travis encrypt AWS_ACCESS_KEY_ID=xxxxxxxxxxx --add
$ travis encrypt AWS_SECRET_ACCESS_KEY=xxxxxxxxxxx --add

このコマンドにより。.travis.ymlに暗号化した状態でcredentialが設定されます。
これはTravis上でビルドを実行した際に環境変数として設定されます。

Travisの設定ファイル

最終的にはこんな感じに.travis.ymlが仕上がりました。

travis.yml
language: node_js
node_js:
  - '4.3'
env:
  global:
    - AWS_REGION=us-east-1
    - SLS_DEBUG=true
    - secure: lSxO7tZ0c/FA8VL72042dqQZ+tRjsS93iVYxMr1ghP/0tBxdmrhhYdAD9UrSv/Kk+Y1jRlkpQ2uaARHoy+6ZqmhchX32HpIYBQVJ/ntMSgv37gFbrNTOfSFoATMTRy6RT2UKaIWAa4xnmDxaQNFPx4X5l9Y25RdivoR+WXrEPd4eCCTVL/23bABSIySSTs+VGqQIppE4Jw5ibbcSoTLsuj00nK+VrmYHNlTSiEuKIxgFC1Ix0hqayJ/kely0DqYW/CY/vCCf0V4yazJo9fG1EFfrHsSIAKKeGRY7WMnLPJ7hJGwRiVV1/atMx/5kRPKOADcRTfoh3noXS3/sd1hbGjTwnJVRVrYiUocHwuNbo1TpW1On85jXEdvnKY9JYelFEnXnWn6A2bRMhgL/zul/WuSPCGq7HpsGMRhXrEiEYJ9YhnVNiUTaV2amoOClMOpHFnStMfTJVg7NJ8mBF4XOzODvhAzyPFDWdJ94Ejl1LAnGOAp/wBQVbFswKPdwdosFU6LyirQkA4k0q7C4zXYywyQtrY7H9w7FtKo+U4596GQAQtvzQz6GS42c1WBX0fIrMu1VXc+KmwCUBEVmvBxLS7c0DJUI61atDFGq7788K7IMWw83lIFjJULdwv1qU4uBi3MvPm2OHCdRAzBGEYIC87zfcYI/gi41rh3bj/C0wiI=
    - secure: LIh0lkl/t72EbMd47WgEXqnoG3REp+oPhIfDR5Cs8SMO4sacvo2j4pRkRKIwwpdKozxdgLEMl1rwDoHyYPH77FzvDnwiufpaYgQs278wmi+6ZvoC9nhgdn2sT7cFnYuYAO8dC7G/NHzXogAVmiObf3I+hzNLjDqWwWVjqPm41p4P4c2EJUVo0nVlcaUOf8elS1j6zp+ZL1EQo4Fm4IumDgNpZUP4bSq8CcVPvF0ynMlslI8XNMnBOiYmG+644qILScyPK1Q2SPdMLqL5YXHuYfE0aCpFcWOcNZIalBmaxPqFNW+QHQvaYiwoENx/i91KS3U2mqfcNYY4o9viih47PFsaddvtBeB83Wfls7GIZ/XmvBKREuS5Gwhz930DbAvUNQT1ylS9Y6TTIIWIbe3Qmv6ngd9TrDHlnbVhQYgar9ur+TgvLyhs5YLAeLn85c3Z3GYN5JUuCq5bclzh4I+myagaWJPoujS1nT+vKLUW8hu5MkxApn+uFUo/OIW1WG4qho/ddh7RoJbI9oTebWjpXhLwd1pSET1yBVSEetORluh0pW7r5A425Rm80B58Mg/x0NNmM1x6DBrCZ5R8d+Bam6C7P4WxxrRex7vFcqRWeKlJNINO+rtPW3Uuo/s9yC9980uQ00eY0kqhouR8ol6xs/4Xye1AHovPR2unzEe37fM=
before_install:
  - chmod +x ./bin/deploy.sh
  - npm i -g serverless@1.6.1
install:
  - travis_retry npm install
script:
  - npm run lint
  - npm run test
  - if [[ $TRAVIS_BRANCH == "master" ]] || [[ $TRAVIS_TAG ]]; then npm run integration-test; fi
after_success:
  - cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage
  - ./bin/deploy.sh

実行結果

developmentブランチへのpush

https://travis-ci.org/horike37/serverless-api-integration-test-sample/builds/203491545
ESLintとユニットテストのビルドが成功し、developmentステージへデプロイされています。

masterブランチへのpush

https://travis-ci.org/horike37/serverless-api-integration-test-sample/builds/203489525
ESLintとユニットテストとインテグレーションテストが成功しましたが、デプロイはされていません。

tagへのpush

https://travis-ci.org/horike37/serverless-api-integration-test-sample/builds/203484838

0.1というタグにpushをしています。
ESLintとユニットテストとインテグレーションテストが成功し、puroductionステージにデプロイされています。

如何でしたでしょうか。こんな感じでCI/CDパイプラインを構築することですべてが自動化され品質も担保されるようになりました。よろしければ是非参考にしてみてください!

では、良いパイプラインライフを!

参考文献

CodePipelineでServerless Frameworkのデプロイを管理する

続きを読む

CircleCIからServerless Frameworkのデプロイを実行する

経緯

「APIはServerless FWでデプロイするでー」
「フロントエンドはS3なー」
「devDependenciesのパッケージ増えたから、デプロイ前に消しといてなー」
「間違えて本番にデプロイしないようにステージの確認しっかりね」

_人人人人人人_
> めんどい <
 ̄Y^Y^Y^Y^Y ̄

計画

  • 手でコマンドうつから事故る
  • 開発環境へのデプロイくらい自動化したい
  • CircleCIからsls deployすればええやん

想定

clientディレクトリにS3へアップするファイルが、srcディレクトリ内にServerless FW用のスクリプトが配置されている。

├── serverless.yml
├── ci
│   └── deploy_dev.sh
├── circle.yml
├── client
│   ├── css
│   ├── img
│   ├── index.html
│   └── js
├── src
│   └── api1.js
└── tests

結果

circleci.yml
---
machine:
  node:
    version: 4.3

dependencies:
  override:
    - npm install

test:
  override:
    - npm test
    - npm run lint

deployment:
  dev:
    branch: dev
    commands:
      - ./ci/deploy_dev.sh
ci/deploy_dev.sh
#!/bin/bash
npm install -g serverless
cd ~/${CIRCLE_PROJECT_REPONAME}
npm prune --production
serverless deploy --stage dev --region us-east-1
cd client
aws s3 sync ./ s3://YOUR_BACKET_NAME_HERE --delete --exclude '*.DS_Store'

ハマったところ

Serverless Frameworkはグローバルインストール

devDependenciesでServerless Frameworkを入れてるので、npm prune --productionしてしまうと./node_modules/serverless/bin/serverlessは動かない。
かといってLambdaに同梱する必要もないものなので、npm install -g serverlessで対応しています。

必要に応じてバージョン指定とかもすればいいかなと。

serverless.ymlのあるディレクトリに移動する

cd ~/${CIRCLE_PROJECT_REPONAME}でリポジトリ内のディレクトリに移動しないと以下のようなエラーでCIがコケます。

 Serverless Error ---------------------------------------

     This command can only be run inside a service directory

slsコマンドはリージョンを指定する

CircleCIだとAWS Permissionsでクレデンシャル情報を設定していると思いますが、これだけだとリージョンが指定されてないのでやっぱりデプロイがコケます。

--region us-east-1をつけてやってください。

CircleCIに設定しているIAMロールに要注意

CircleCIに設定しているIAMロールに権限が足りないと、これもまたデプロイ失敗します。
できるだけきっちり設定しておいたほうがいいと思いますが、とりあえずIAMユーザー部分だけ最低限にしたバージョンは以下。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt9999999998000",
            "Effect": "Allow",
            "Action": [
                "iam:GetRole",
                "iam:CreateRole",
                "iam:DeleteRole",
                "iam:PutRolePolicy",
                "iam:DeleteRolePolicy",
                "iam:PassRole"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Sid": "Stmt9999999999000",
            "Effect": "Allow",
            "Action": [
                "s3:*",
                "lambda:*",
                "cloudformation:*",
                "apigateway:*"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

終わりに

master or releaseブランチあたりに対しても同様のことを行うことで、本番デプロイの自動化も可能とは思います。
「目視確認後にリリースしたい」とか「リリースのタイミングはこちらで決めたい」という場合は、AWS CodePipelineの手動承認機能とCode Buildで設定してみてください。

参考:https://aws.amazon.com/jp/about-aws/whats-new/2016/07/aws-codepipeline-adds-manual-approval-actions/

続きを読む

CircleCIでRailsアプリをAmazon ECRにpushする

概要

railsアプリのテストとECRへのプッシュが目的。

サンプルコード

circle.yml
machine:
  services:
    - docker
  timezone:
    Asia/Tokyo
  environment:
    CIRCLE_ENV: test
dependencies:
  pre:
    - if [[ -e ~/docker/ruby.tar ]]; then docker load --input ~/docker/ruby.tar; fi
    - if [[ -e ~/docker/awesome-app-$CIRCLE_BRANCH.tar ]]; then docker load --input ~/docker/awesome-app-$CIRCLE_BRANCH.tar; fi
    - bundle --path=vendor/bundle
    - bundle exec rake assets:precompile
  cache_directories:
    - "~/docker"
    - "vendor/bundle"
    - "public/assets"
  override:
    - docker info
    - docker build -t $DOCKER_REPOS/awesome-app:$CIRCLE_BRANCH .
    - mkdir -p ~/docker
    - docker save -o ~/docker/ruby.tar ruby
    - docker save -o ~/docker/awesome-app-$CIRCLE_BRANCH.tar $DOCKER_REPOS/awesome-app:$CIRCLE_BRANCH
database:
  override:
    - bundle exec rake db:create db:schema:load db:migrate rake db:seed_fu
test:
  override:
    - bundle exec rubocop
    - bundle exec rspec
deployment:
  hub:
    branch: /^(master|staging)$/
    commands:
      - $(aws ecr get-login --region $AWS_REGION)
      - docker push $DOCKER_REPOS/awesome-app:$CIRCLE_BRANCH

dependencies

CircleCIだと、dockerイメージのキャッシュがされないので、
docker save & loadするっていうハックが一般的みたい。
~/dockerに逃してるが、将来docker imageがキャッシュされたら再検討。

bundleも忘れずにキャッシュされるようにしておく。

deployment

deploymentのセクションに関して、
master、stagingブランチの時だけECRにpushしたいという意図がある。
CIRCLE_BRANCHには、pushされたブランチ名が入るので、正規表現で切り分ける。

ENV

事前にCircleCI側にENVを設定する必要あり。
画面遷移: Setting->BUILD SETTINGS->Environment Variables

  • AWS_ACCESS_KEY_ID
  • AWS_ACCOUNT_ID
  • AWS_REGION
  • AWS_SECRET_ACCESS_KEY
  • DOCKER_REPOS
  • SECRET_KEY_BASE

続きを読む

OpsWorks管理下のAmazon LinuxをCLIでアップグレードする

はじめに

何かにつけ、GUIが苦手です。WEBブラウザを開くと、トンデモなバナーをクリックしてしまうし、そもそもトンデモなバナーが出来てきてしまうネットワーク広告が怖い。
OpsWorks(AWSマネジメントコンソール)では、広告は表示されないのですが、いつか広告モデルになるかもしれない…
そんな不安から日々のオペレーションは、awscliを用いたCLIで完結したいというのがモチベーションです。
今回は、OpsWorksで唯一GUIなオペレーション(awscliにサブコマンドが用意されていない)となるUpgrade Operating SystemをCLIで実施するコネタを紹介します。

バージョン

動作を確認している環境とそのバージョンは、以下の通りです。

  • OpsWorks(リモート環境)

    • Cehf 11.10
    • Berkshelf 3.2.0
    • Amazon Linux 2016.03 → 2016.09
  • Mac(ローカル環境)
    • aws-cli 1.11.28 Python/2.7.10 Darwin/15.6.0 botocore/1.4.85

Custom JSONの準備

下ごしらえとして、OpsWorksに渡すattributeをCustom JSONとしてJSONフォーマットのファイルにまとめておきます。
OpsWorksのビルドインcookbookであるdependenciesのattributeを上書きします。詳細は、後述します。

$ mkdir ./aws/opsworks && vi $_/upgrade-amazonlinux.json

{
  "dependencies": {
    "os_release_version": "2016.09",
    "allow_reboot": false,
    "upgrade_debs": true
  }
}

コマンド

CLIでAmazon Linuxをアップグレードしていきます。

幸せなchefになるために、独自の味付けをしない、つまり可能な限りビルドインのcookbookを利用するべきです。
Upgrade Operating Systemで実施しているのは、update_dependenciesというdeployになり、dependencies::updateレシピを実行しています。該当のレシピを一読すると、yum -y updateコマンドを実行していました。前述のCustom JSONは、yum -y updateするために必要なattributeとなります。

  • os_release_versionは、アップグレードしたいAmazon Linuxのバージョンを指定します。
  • allow_reboot は、パッケージのアップデートの後に再起動するか指定します。今回は、インスタンスの停止を明示的に実施しますので、falseとしておきます。
  • upgrade_debsは、一見Debianぽいですがパッケージをアップデートするか否かのフラグとして実装されてます。今回は、アップデートするのでtrueとしておきます。

Upgrade Operating Systemの正体を把握できたので、awscliで以下のような一連コマンドを実行していきます。

# 1. Stackのリビジョンを指定
$ aws opsworks --region us-east-1 update-stack --stack-id STACK_ID --custom-cookbooks-source "{"Revision":"UgradeAmazonLinux"}"

# 2. Stackで管理している全EC2インスタンスに対して、update_custom_cookbooksの実行(最新版cookbookを配置)
$ aws opsworks --region us-east-1 create-deployment --stack-id STACK_ID --command "{"Name":"update_custom_cookbooks"}"

# 3. opsworks agentのバージョンアップ(最新版を利用する)
$ aws opsworks --region us-east-1 update-stack --stack-id STACK_ID --agent-version LATEST

# 4. Custom JSONとレシピを指定して、全パッケージをアップデート
$ aws opsworks --region us-east-1 create-deployment --stack-id STACK_ID --instance-ids INSTANCE_ID01 INSTANCE_ID02 --command "{"Name":"execute_recipes","Args":{"recipes":["dependencies::update"]}}" --custom-json file://./aws/opsworks/upgrade-amazonlinux.json

# 5. EC2インスタンスの停止
$ aws opsworks --region us-east-1 stop-instance --instance-id INSTANCE_ID01
$ aws opsworks --region us-east-1 stop-instance --instance-id INSTANCE_ID02

# 6. OpsWorksで保持しているOSのバージョン情報を更新
$ aws opsworks --region us-east-1 update-instance --instance-id INSTANCE_ID01 --os "Amazon Linux 2016.09"

# 7. EC2インスタンスの起動
$ aws opsworks --region us-east-1 start-instance --instance-id INSTANCE_ID01
$ aws opsworks --region us-east-1 start-instance --instance-id INSTANCE_ID02

4でビルドインのcookbookにCustom JSONでattributeを渡し、全パッケージのアップデートを実施します。
5でEC2インスタンスを停止するのは、以下の2つの理由があります。

  • OpsWorksが保持しているEC2インスタンスの情報を更新するためには、該当のEC2インスタンスを停止する必要がある
  • OSアップグレード後は、setupライフサイクルイベントを実施することを推奨されている

setup ライフサイクルイベントは、7の起動時に実行されます。

おわりに

AWSが広告モデルになったら嫌ですね。
Enjoy CLI!

参考

続きを読む

【AWS Lambda】Amazon Linux の Docker イメージを使ってデプロイパッケージを作成する

AWS Lambda の実行環境に無いライブラリを利用する場合には、ローカル環境でライブラリのソース群をダウンロードしておいてそれをデプロイパッケージに含めて Lambda にアップロードする必要があります。

Python の例だとデプロイパッケージを作る際に例えば下記のような手順を踏みます。

$ virtualenv -p python2.7 venv
$ source venv/bin/activate
$ pip install -r requirements.txt
$ zip deploy_package.zip lambda_function.py # 実行スクリプトを zip にする
$ cd venv/lib/python2.7/site-packages
$ zip -r ../../../../deploy_package.zip * # pip でインストールしたライブラリを zip に追加

利用したいライブラリが純粋な Python コードであればこのパッケージは問題無く Lambda 上でも動作するのですが、OS の機能に依存しているようなライブラリの場合、ローカル環境でビルド・インストールされたものを Lambda 上にアップロードしても動きません。
上記の例で言うと pip install は Lambda の実行環境と同じ環境で行う必要があります。

失敗例

pycrypto というライブラリを使う Lambda Function を作って実行します。

requirements.txt
pycrypto==2.6.1
lambda_function.py
from Crypto.PublicKey import RSA


def lambda_handler(event, context):
    return {"messagge": "success"}

上記のファイルを用意してローカルの OS X 環境でデプロイパッケージを作成します。

$ virtualenv -p python2.7 venv
$ source venv/bin/activate
$ pip install -r requirements.txt
$ zip deploy_package.zip lambda_function.py
$ cd venv/lib/python2.7/site-packages
$ zip -r ../../../../deploy_package.zip *

作成した deploy_package.zip を AWS Lambda にアップロードして実行すると次のようなエラーが出ます。
Unable to import module 'lambda_function'

Unable to import module 'lambda_function'

エラーログ全文を見ると Unable to import module 'lambda_function': /var/task/Crypto/Util/_counter.so: invalid ELF header とあります。pycrypto が参照するファイルのヘッダ情報が不正であるようです。原因は pycrypto をインストールした環境が Lambda の実行環境と異なるところにあります。

対策

Amazon Linux の Docker イメージを用いてライブラリのインストールを行うことでこの問題を回避することができます。

先述のファイルと同じ階層にこのような Dockerfile を用意して

Dockerfile
FROM amazonlinux:latest

RUN yum -y update && yum -y install gcc python27-devel
RUN cd /tmp && 
    curl https://bootstrap.pypa.io/get-pip.py | python2.7 - && 
    pip install virtualenv
WORKDIR /app
CMD virtualenv -p python2.7 venv-for-deployment && 
    source venv-for-deployment/bin/activate && 
    pip install -r requirements.txt

このようにコマンドを実行すると venv-for-deployment という名前で、Amazon Linux でビルドされた Python ライブラリコードが作成されます。

$ docker build . -t packager
$ docker run --rm -it -v $(PWD):/app packager

その後は下記のようにデプロイパッケージの zip を作成して AWS Lambda にアップロードします。

$ zip deploy_package.zip lambda_function.py
$ cd venv-for-deployment/lib/python2.7/site-packages
$ zip -r ../../../../deploy_package.zip * .* # dotfile が含まれる場合は ".*" も

実行するとライブラリが import 出来て無事 "success" が表示されます。

success

自動化

ちょっと叩くコマンド量が多いのでこのような Makefile を作っておくと make だけで zip が生成されて便利です。

Makefile
package:
    docker build . -t packager
    docker run --rm -it -v $(PWD):/app packager
    zip deploy_package.zip lambda_function.py
    cd venv-for-deployment/lib/python2.7/site-packages && zip -r ../../../../deploy_package.zip * .*
    echo "Completed. Please upload deploy_package.zip to AWS Lambda"

サンプル

今回用いた Lambda Function のサンプルはこちらのリポジトリに置いています。
https://github.com/morishin/python-lambda-function-test

所感

AWS Lambda 便利なのですがちょっと凝ったことをしようとすると泣きそうになりますね。

続きを読む