こんにちは、高知からリモートインターンしている森田ドラゴンです。最近はCentOSをPCに入れて色々触りたいなと思ってます。Linuxを入れた暁には、マウスを破壊してコマンドラインしか使えない体にしようと思ってます(箸の持ち方を矯正される子供みたいで面白いですね)。
前回、Pythonのテストコードが書き終わったので、残っているタスクは以下になります。
・SwaggerなしでSAMの作成
・SwaggerをimportしてSAMを作成
・アップロードしてjs, awsリソースのテスト
Swaggerは、APIの構造を効率的に定義できるドキュメントだと勘違いしていましたが、本当の使い方はCloudFormationのように、YAMLで設計図を書くことにあるみたいです。
SwaggerなしでSAMの作成
SAMの作成といっても、ほとんど触ることはありません。AWS::Serverlss::Functionを設定してあげればそれで終了です。
ApiFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
Role: !GetAtt OtenkiIamRole.Arn
CodeUri: weather_api/
Handler: app.lambda_handler
Runtime: python3.7
Events:
HelloWorld:
Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
Path: /
Method: post
AWS::Serverlss::FunctionはLambdaを設定するためのものですが、API GWも作ってくれます。「ではAPI GWは作らなくていいのか?」という疑問が湧きましたが、正解は公式ドキュメントに書いてありました。
we recommend that you create APIs by specifying this resource type as an event source of your AWS::Serverless::Function
resource.
このAPI GWのリソースはServerlss::Functionのイベントソースとして返してあげたほうがいいですよ〜
久しぶりにバッチりと、しかも公式で答えが見つかったのでスッキリしました。
curlが通らない
SAMの雛形はできたので、さっそくローカルリソースを curlで叩いてテストしました。
curl http://127.0.0.1:3000/ -d \"{\id\:\"4000040\", \"date\": \"0\"}\" -H "Content-Type:application/jsonただ、
すると、そんなデータはないぞとエラーが発生しました。evenをprintして確認して見ましたが、データは遅れているみたいです。自分の知らないPythonの仕様か、API GWからLambdaに送られる際に特殊なルールがあるのか、色々考えましたが、結局コマンドをミスしていただけでした。
curl http://127.0.0.1:3000/ -d "{\"id\":\"400040\", \"date\": 0}" -H "Content-Type:application/json"
-dオプションのあとを見てください。 -d オプションの後に、postしたいデータを送るのですが、データは" ダブルクォーテーションでくくる必要があります。 最初に打ったコマンドでは、タブルクォーテーションをエスケープしてしまっていたので、データを受け付けてもらえませんでした。
ちなみにシングルクォーテーションで、内部のjsonを定義するとエラーが起きます。Python的にはシングルクォーテーションとダブルクォーテーションを区別しませんが、API GWからのeventのjsonがシングルクォーテーションで定義されているため、データの区切りがおかしくなりエラーが起きます。
SwaggerをSAMにimport
SwaggerをSAMにimportしてあげるには、API GWに以下の記述を追加します
DefinitionBody:
'Fn::Transform':
Name: 'AWS::Include'
Parameters:
Location: ~swaggerが置いてある場所のurl~
そしてSwaggerの方には、以下を追加します。
x-amazon-apigateway-integration:
httpMethod: post
type: aws_proxy
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ApiFunction.Arn}/invocations
x-amazon-apigateway-integrationはドキュメントにあるように、OpenAPI Operation オブジェクトの拡張プロパティだそうです。SwaggerでFn::Subが使えたりと、色々よしなにやってくれるみたいですが、動作を完全に理解していないので、また調べ直して見たいと思います。
Invalid permissions on Lambda function
SAMがデプロイできたので、テストしてみると上のエラーが。Permissionエラーなので、「IAMロールを調整すればいいだろう」と思っていましたが、何故かRoleが付与されません。
AWSコンソールから付与しても、反映された様子がない。
ドキュメント
の通りにコマンドを打っても、同じ結果だったので、SAMの記述をもう少し調べてみようと思います。
感想
SAMとSwaggerを連携させる部分で、どこでエラーが発生しているのか特定するのが大変でした。単純に文法をミスしている可能性もあるので、その場合はエラー文の指示通りに記述したり、検索をかけても解決しない場合が多いです。
SAMのあたりはもう少しサンプルを作って見たいです。