AWS APIGateway/Lambda Python用ServerlessFramework!

こんにちは。

2016/7/12にAWSからpython用のServerlessFlameWorkが発表されました。
こちら→ Preview the Python Serverless Microframework for AWS

まだproductionでの利用は推奨されておらず、devでご利用くださいとのことですが、 せっかくなのでとりあえず動かしてみようと思います。

github.com

まずはReadme通りに

[unicorn ~]# chalice new-project iryond_demo && cd iry*
[unicorn iryond_demo]# ll
total 4
-rw-r--r-- 1 root root 784 Jul 16 15:01 app.py
-rw-r--r-- 1 root root   0 Jul 16 15:01 requirements.txt
[unicorn iryond_demo]# cat app.py
from chalice import Chalice

app = Chalice(app_name='iryond_demo')


@app.route('/')
def index():
    return {'hello': 'world'}

[unicorn iryond_demo]# chalice deploy
Initial creation of lambda function.
Creating role
Creating deployment package.
Lambda deploy done.
Initiating first time deployment...
Deploying to: dev
https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/
[unicorn iryond_demo]# curl -X GET https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/
{"hello": "world"}

おーすごい。
何も考えずに動かして、簡単にAPIGatewayとLambdaができちゃいました。
もちろんブラウザからもアクセス可能です。

実行した後の、それぞれの構成は下記のとおりです。
■構成図 f:id:iryond:20160716155647p:plain

ただ一個だけハマったところがあって、
サンプルのとおり、helloworld でnew-projectすると、
よくわからないエラー(※1)が出て正常に動作しません。

注意点:new-projectは被らなそうな名前を使いましょう。

(※1) こんなエラーが出ましたが、解析の仕方がわからず、、とりあえず名前変更で対処。

# chalice deploy
Initial creation of lambda function.
Updating IAM policy.
Traceback (most recent call last):
  File "/usr/local/bin/chalice", line 9, in <module>
    load_entry_point('chalice==0.0.1', 'console_scripts', 'chalice')()
  File "/usr/local/lib/python2.7/site-packages/chalice/cli/__init__.py", line 203, in main
    return cli(obj={})
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 716, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 696, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 1060, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 889, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 534, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/chalice/cli/__init__.py", line 123, in deploy
    d.deploy(ctx.obj)
  File "/usr/local/lib/python2.7/site-packages/chalice/deployer.py", line 203, in deploy
    self._deploy_lambda(config)
  File "/usr/local/lib/python2.7/site-packages/chalice/deployer.py", line 218, in _deploy_lambda
    function_arn = self._first_time_lambda_create(config)
  File "/usr/local/lib/python2.7/site-packages/chalice/deployer.py", line 259, in _first_time_lambda_create
    role_arn = self._get_or_create_lambda_role_arn(config)
  File "/usr/local/lib/python2.7/site-packages/chalice/deployer.py", line 304, in _get_or_create_lambda_role_arn
    self._update_role_with_latest_policy(app_name, config)
  File "/usr/local/lib/python2.7/site-packages/chalice/deployer.py", line 315, in _update_role_with_latest_policy
    diff = policy.diff_policies(previous, app_policy)
  File "/usr/local/lib/python2.7/site-packages/chalice/policy.py", line 38, in diff_policies
    old = _create_simple_format(old)
  File "/usr/local/lib/python2.7/site-packages/chalice/policy.py", line 53, in _create_simple_format
    for statement in policy['Statement']:
KeyError: 'Statement'

API機能を持たせてみる

冒頭の記事のとおり、入力した名前を含めてレスポンスするAPIとしたいと思います。
ソースをちょちょっと書き換えて~~

[unicorn iryond_demo]# cat app.py
from chalice import Chalice

app = Chalice(app_name='iryond_demo')


@app.route('/')
def index():
    return {'hello': 'world'}

@app.route('/hello/{name}')
def hello(name):
    return {'hello': name}

[unicorn iryond_demo]# chalice deploy
Updating IAM policy.
Updating lambda function...
Regen deployment package...
Sending changes to lambda.
Lambda deploy done.
API Gateway rest API already found.
Deleting root resource id
Done deleting existing resources.
Deploying to: dev
https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/
[unicorn iryond_demo]# curl https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/hello/iryond
{"hello": "iryond"}

最後のリクエストで、ちゃんと入力値を含めたレスポンスを返してますね~。

また、この場合のそれぞれの構成は下記のとおりです。
■構成図 f:id:iryond:20160716155700p:plain

うん、面白い。

隠しフォルダをのぞいてみる

プロジェクトフォルダ直下に、.chaliceフォルダがあったので、のぞいてみました。

[unicorn iryond_demo]# ll -a
total 16
drwxr-xr-x 3 root root 4096 Jul 16 15:48 .
dr-xr-x--- 7 root root 4096 Jul 16 15:50 ..
-rw-r--r-- 1 root root  202 Jul 16 15:48 app.py
drwxr-xr-x 4 root root 4096 Jul 16 15:01 .chalice
-rw-r--r-- 1 root root    0 Jul 16 15:01 requirements.txt
[unicorn iryond_demo]# cd .chalice/
[unicorn .chalice]# ll
total 16
-rw-r--r-- 1 root root  134 Jul 16 15:01 config.json
drwxr-xr-x 2 root root 4096 Jul 16 15:48 deployments
-rw-r--r-- 1 root root  250 Jul 16 15:48 policy.json
drwxr-xr-x 7 root root 4096 Jul 16 15:01 venv
[unicorn .chalice]# cat config.json
{
  "lambda_arn": "arn:aws:lambda:ap-northeast-1:xxxxxxxx:function:iryond_demo",
  "app_name": "iryond_demo",
  "stage": "dev"
}[unicorn .chalice]# ll deployments/
total 2948
-rw-r--r-- 1 root root 3015411 Jul 16 15:48 xxxxxxxxxxxxxxxxxxxxxx.zip
[unicorn .chalice]# ll venv/
total 20
drwxr-xr-x 2 root root 4096 Jul 16 15:01 bin
drwxr-xr-x 2 root root 4096 Jul 16 15:01 include
drwxr-xr-x 3 root root 4096 Jul 16 15:01 lib
drwxr-xr-x 3 root root 4096 Jul 16 15:01 lib64
drwxr-xr-x 2 root root 4096 Jul 16 15:01 local

APIGatewayの環境を管理しているのはconfig.jsonで、
deploymentsの中にLambdaにアップロードするファイルがあるようです。
なんかあったときはこの辺見るといい感じなのかも?

やってみたいこと

  • 認証連携
  • DB連携
  • その他いろいろ

まとめ(?)

chalicepythonのflaskをもとに作られているようで、
これでWebアプリケーションとか全然作れちゃえそうな感じですね。

Webプログラミングの経験が全然ないので、
この機会にちょっといろいろやってみようと思います。

それでは。