[{"data":1,"prerenderedAt":1232},["ShallowReactive",2],{"content-\u002Fcontents\u002Fuse-aws-sam":3,"surroundPost-\u002Fcontents\u002Fuse-aws-sam":1223},{"id":4,"title":5,"body":6,"createdAt":1211,"description":1212,"draft":1213,"extension":1214,"meta":1215,"navigation":574,"path":1216,"seo":1217,"stem":1218,"tags":1219,"thumbnail":1221,"updatedAt":1211,"__hash__":1222},"contents\u002Fcontents\u002Fuse-aws-sam.md","AWS SAMの使い方｜ローカル開発からデプロイまで",{"type":7,"value":8,"toc":1200},"minimark",[9,13,16,19,22,33,36,39,47,52,62,72,75,93,96,99,103,112,115,118,122,126,135,138,160,163,166,169,291,306,309,321,328,331,346,349,352,355,372,387,395,398,431,434,445,448,452,455,458,461,479,485,1090,1093,1107,1111,1114,1121,1124,1176,1179,1185,1188,1193,1196],[10,11,12],"p",{},"本記事では、AWS SAM（Serverless Application Model）について解説します。",[10,14,15],{},"SAM は AWS 上でサーバレスアプリケーションを構築しようと思うとよくでてきます。SAM がどんなもので何ができるのかよくわかってなかったので勉強したいと思ってました。",[10,17,18],{},"また、サーバレスアプリケーションを構築する際に悩んだのがローカルの開発環境です。",[10,20,21],{},"Lambda 単体なら以前紹介した python-lambda-local や lambda-uploder を使った方法があります。",[23,24,25],"ul",{},[26,27,28],"li",{},[29,30,32],"a",{"href":31},"lambda_dev_env","【AWS】python-lambda-local と lambda-uploader を使ってみた",[10,34,35],{},"しかし、API Gateway などと組み合わせようと思うと少々無理があります。",[10,37,38],{},"そこで、サーバレスのおすすめローカル開発環境はなにか調べてみると AWS SAM に行き着きました。",[10,40,41,42,46],{},"調べた結果、Lambda 単体の場合でも sam が利用できたので sam が使えれば",[43,44,45],"code",{},"lambda-uploder","の方法はいらないかもです。",[48,49,51],"h2",{"id":50},"aws-sam-できること","AWS SAM できること",[10,53,54,55,61],{},"まずは",[29,56,60],{"href":57,"rel":58},"https:\u002F\u002Faws.amazon.com\u002Fjp\u002Fserverless\u002Fsam\u002F",[59],"nofollow","公式サイト","の説明を見てみましょう。",[63,64,65],"blockquote",{},[10,66,67,68],{},"迅速に記述可能な構文で関数、API、データベース、イベントソースマッピングを表現できます。リソースごとにわずか数行で、任意のアプリケーションを定義して YAML を使用してモデリングできます。デプロイ中、SAM が SAM 構文を AWS CloudFormation 構文に変換および拡張することで、サーバーレスアプリケーションの構築を高速化することができます。\n（中略）\nSAM CLI により Lambda に似た実行環境が提供され、SAM テンプレートで定義されたアプリケーションの構築、テスト、デバッグをローカルで実行できます。\n引用：",[29,69,71],{"href":57,"rel":70},[59],"AWS サーバーレスアプリケーションモデル",[10,73,74],{},"ここからわかるのは SAM でできることは以下の 3 点。",[76,77,80,81],"div",{"className":78},[79],"point-box","\n  ",[23,82,83,84,83,87,83,90,80],{},"\n    ",[26,85,86],{},"サーバレスアプリケーションをYAMLで定義",[26,88,89],{},"SAM構文で書かれたアプリケーションはCloudFormationに変換され、デプロイ可能",[26,91,92],{},"SAM CLIではローカルでテスト、デバックを行える",[10,94,95],{},"SAM では Infrastructure as Code（IaC）とローカルでの開発が可能になる。",[10,97,98],{},"やりたかったのはローカル開発環境構築なので使えそうです。",[48,100,102],{"id":101},"aws-sam-のインストールubuntu","AWS SAM のインストール（ubuntu）",[10,104,105,106,111],{},"インストール方法は",[29,107,110],{"href":108,"rel":109},"https:\u002F\u002Fdocs.aws.amazon.com\u002Fja_jp\u002Fserverless-application-model\u002Flatest\u002Fdeveloperguide\u002Fserverless-sam-cli-install-linux.html",[59],"公式","に丁寧に書いてあるので割愛します。",[10,113,114],{},"手順に従ってコマンドをコピペして実行すると問題なく sam コマンドが使えました。",[10,116,117],{},"Docker と Homebrew のインストールが必要になりますが、これもインストール方法に記載されています。",[48,119,121],{"id":120},"aws-sam-の使い方","AWS SAM の使い方",[123,124,125],"h3",{"id":125},"公式テンプレートで学ぶ",[10,127,128,129,134],{},"最初ということで、公式が提供している template の Hello Wolrd を試してみます。こちらについても",[29,130,133],{"href":131,"rel":132},"https:\u002F\u002Fdocs.aws.amazon.com\u002Fja_jp\u002Fserverless-application-model\u002Flatest\u002Fdeveloperguide\u002Fserverless-getting-started-hello-world.html",[59],"公式の解説","があります。この記事の内容は公式の解説を噛み砕いたものです。",[10,136,137],{},"以下のコマンドでアプリ名やランタイム、template の選択ができます。template の選択で 1 つめの Hello World の template を選択しました。ランタイムは python 3.7 です。",[139,140,145],"pre",{"className":141,"code":142,"language":143,"meta":144,"style":144},"language-bash shiki shiki-themes github-dark","sam init\n","bash","",[43,146,147],{"__ignoreMap":144},[148,149,152,156],"span",{"class":150,"line":151},"line",1,[148,153,155],{"class":154},"svObZ","sam",[148,157,159],{"class":158},"sU2Wk"," init\n",[10,161,162],{},"上記コマンドを実行するといろいろ選択肢が提示されます。書かれている内容に従って選択していけばうまくいきました。",[10,164,165],{},"実行後には作成したアプリ名のフォルダができあがっているはずなので、そこに移動します。",[10,167,168],{},"フォルダ内は以下のような構成になっています。",[139,170,172],{"className":141,"code":171,"language":143,"meta":144,"style":144},".\n├── README.md\n├── events\n│   └── event.json\n├── hello_world\n│   ├── __init__.py\n│   ├── app.py\n│   └── requirements.txt\n├── template.yaml\n└── tests\n    └── unit\n        ├── __init__.py\n        └── test_handler.py\n",[43,173,174,180,189,197,209,217,228,238,248,256,265,274,282],{"__ignoreMap":144},[148,175,176],{"class":150,"line":151},[148,177,179],{"class":178},"sDLfK",".\n",[148,181,183,186],{"class":150,"line":182},2,[148,184,185],{"class":154},"├──",[148,187,188],{"class":158}," README.md\n",[148,190,192,194],{"class":150,"line":191},3,[148,193,185],{"class":154},[148,195,196],{"class":158}," events\n",[148,198,200,203,206],{"class":150,"line":199},4,[148,201,202],{"class":154},"│",[148,204,205],{"class":158},"   └──",[148,207,208],{"class":158}," event.json\n",[148,210,212,214],{"class":150,"line":211},5,[148,213,185],{"class":154},[148,215,216],{"class":158}," hello_world\n",[148,218,220,222,225],{"class":150,"line":219},6,[148,221,202],{"class":154},[148,223,224],{"class":158},"   ├──",[148,226,227],{"class":158}," __init__.py\n",[148,229,231,233,235],{"class":150,"line":230},7,[148,232,202],{"class":154},[148,234,224],{"class":158},[148,236,237],{"class":158}," app.py\n",[148,239,241,243,245],{"class":150,"line":240},8,[148,242,202],{"class":154},[148,244,205],{"class":158},[148,246,247],{"class":158}," requirements.txt\n",[148,249,251,253],{"class":150,"line":250},9,[148,252,185],{"class":154},[148,254,255],{"class":158}," template.yaml\n",[148,257,259,262],{"class":150,"line":258},10,[148,260,261],{"class":154},"└──",[148,263,264],{"class":158}," tests\n",[148,266,268,271],{"class":150,"line":267},11,[148,269,270],{"class":154},"    └──",[148,272,273],{"class":158}," unit\n",[148,275,277,280],{"class":150,"line":276},12,[148,278,279],{"class":154},"        ├──",[148,281,227],{"class":158},[148,283,285,288],{"class":150,"line":284},13,[148,286,287],{"class":154},"        └──",[148,289,290],{"class":158}," test_handler.py\n",[10,292,293,294,297,298,301,302,305],{},"内容はけっこうシンプルです。",[43,295,296],{},"events","フォルダには Lambda の入力となるリクエスト情報が入ってました。",[43,299,300],{},"hello_world","フォルダは python で書かれた Lambda の実体があります。",[43,303,304],{},"tests","はそのままの内容で hello_workd 関数のテストが記述されたファイルがあります。",[10,307,308],{},"次にやることは、ビルドを行い、アップロード用のファイル群を生成します。ビルドには以下のコマンドを使用します。",[139,310,312],{"className":141,"code":311,"language":143,"meta":144,"style":144},"sam build\n",[43,313,314],{"__ignoreMap":144},[148,315,316,318],{"class":150,"line":151},[148,317,155],{"class":154},[148,319,320],{"class":158}," build\n",[10,322,323,324,327],{},"このコマンドを実行すると",[43,325,326],{},".aws_sam","フォルダが作成されます。",[10,329,330],{},"あとばデプロイするだけです。デプロイコマンドは以下です。",[139,332,334],{"className":141,"code":333,"language":143,"meta":144,"style":144},"sam deploy --guided\n",[43,335,336],{"__ignoreMap":144},[148,337,338,340,343],{"class":150,"line":151},[148,339,155],{"class":154},[148,341,342],{"class":158}," deploy",[148,344,345],{"class":178}," --guided\n",[10,347,348],{},"コマンドラインでいろいろ聞かれるので素直に答えていけばデプロイができます。**デプロイされるものはそれぞれのリソース単体ではなく、CloudFormation のスタックとしてまとめて作成されます。**また、s3 に sam-cli 用のバケットが作成されます。",[10,350,351],{},"途中で CloudFormation のスタック名を指定しますが、この時アンダースコアなど使えない文字があるので注意してください。",[10,353,354],{},"なので、HelloWorld のテンプレートを使った場合に作成されるものをまとめると以下になります。",[76,356,80,358],{"className":357},[79],[23,359,83,360,83,363,83,366,83,369,80],{},[26,361,362],{},"【s3】sam-cli用バケット",[26,364,365],{},"【CloudFormation】Lambda・API Gatewayを定義したリソースをまとめたスタック",[26,367,368],{},"【API Gateway】Lambdaを呼び出すGET",[26,370,371],{},"【Lambda】Pythonで書かれたhelloworld",[10,373,374,375,378,379,382,383,386],{},"これらの情報については",[43,376,377],{},"sam init","で作成したフォルダの",[43,380,381],{},"template.yaml","に記述されてます。また、",[43,384,385],{},"samconfig.toml","にスタック名、バケット名などの情報が記載されてます。",[10,388,389,390,394],{},"最後に私が気になっていた",[391,392,393],"strong",{},"ローカルでの開発方法","を試してみます。",[10,396,397],{},"今回のテンプレートでは以下の 2 つのコマンドが使えます。",[139,399,401],{"className":141,"code":400,"language":143,"meta":144,"style":144},"sam local start-api\nsam local invoke \"HelloWorldFunction\" -e events\u002Fevent.json\n",[43,402,403,413],{"__ignoreMap":144},[148,404,405,407,410],{"class":150,"line":151},[148,406,155],{"class":154},[148,408,409],{"class":158}," local",[148,411,412],{"class":158}," start-api\n",[148,414,415,417,419,422,425,428],{"class":150,"line":182},[148,416,155],{"class":154},[148,418,409],{"class":158},[148,420,421],{"class":158}," invoke",[148,423,424],{"class":158}," \"HelloWorldFunction\"",[148,426,427],{"class":178}," -e",[148,429,430],{"class":158}," events\u002Fevent.json\n",[10,432,433],{},"１つ目は Docker を使用して、API をホストするアプリケーションが起動します。実行するとアクセス先の URL が表示されるので、そこにリクエストを投げると API から Lambda が呼び出され実行することができます。",[10,435,436,437,440,441,444],{},"２つ目は単純にコマンド引数に指定した",[43,438,439],{},"event.json","を Lambda に渡して Lambda 単体を実行できます。こちらは以前行っていた",[43,442,443],{},"python-lambda-local","と同等のことができるので便利です。",[10,446,447],{},"最後に作成したリソースを削除する際は、CloudFormation で定義されているスタックを削除します。これでスタックで作成されたリソースをまるごと消せます。",[48,449,451],{"id":450},"sam-api-gateway-lambda-で-s3-のデータを-json-で取得する","SAM + API Gateway + Lambda で S3 のデータを JSON で取得する　",[10,453,454],{},"ざっくり使い方がわかったので、応用してみます。",[10,456,457],{},"やることは API の GET で Lambda を呼び出し、Lambda では S3 から取得したデータをまとめて json で返すようにします。\nほぼ Hello World の Lambda を変えるだけです。",[10,459,460],{},"手順は以下になります。今すぐ使うわけじゃないので、今回デプロイはしません。",[76,462,80,464],{"className":463},[79],[465,466,83,467,83,470,83,473,83,476,80],"ol",{},[26,468,469],{},"sam initで作業フォルダを作成",[26,471,472],{},"template.yamlに定義したい関数情報を記述",[26,474,475],{},"関数の記述",[26,477,478],{},"ローカルテスト",[10,480,481,482,484],{},"以下は",[43,483,377],{},"入力後の出力です。",[139,486,488],{"className":141,"code":487,"language":143,"meta":144,"style":144},"$ sam init\nWhich template source would you like to use?\n        1 - AWS Quick Start Templates\n        2 - Custom Template Location\nChoice: 1\n\nWhich runtime would you like to use?\n        1 - nodejs12.x\n        2 - python3.8\n        3 - ruby2.7\n        4 - go1.x\n        5 - java11\n        6 - dotnetcore3.1\n        7 - nodejs10.x\n        8 - python3.7\n        9 - python3.6\n        10 - python2.7\n        11 - ruby2.5\n        12 - java8\n        13 - dotnetcore2.1\n        14 - dotnetcore2.0\n        15 - dotnetcore1.0\nRuntime: 8\n\nProject name [sam-app]: sam-twitter-process\n\nCloning app templates from https:\u002F\u002Fgithub.com\u002Fawslabs\u002Faws-sam-cli-app-templates.git\n\nAWS quick start application templates:\n        1 - Hello World Example\n        2 - EventBridge Hello World\n        3 - EventBridge App from scratch (100+ Event Schemas)\nTemplate selection: 1\n\n-----------------------\ntitle: AWS SAMの使い方｜ローカル開発からデプロイまで\ncreatedAt: '2020-04-07'\nupdatedAt: '2020-04-07'\ntags: ['AWS', 'Python']\ndraft: false\ndescription:  '本記事では、AWS SAM（Serverless Application Model）について解説します。簡単なテンプレートが提供されているので、それを使って基本の使い方を把握した後、ちょっとした応用をします。内容はAPI Gateway + LambdaでLambdaがS3からデータを取得し、JSONをまとめて返します。'\nthumbnail: '\u002Fimg\u002Ftwitter-card.png'\n---\n# AWS SAMの使い方｜ローカル開発からデプロイまで\n--------------------\nName: sam-twitter-process\nRuntime: python3.7\nDependency Manager: pip\nApplication Template: hello-world\nOutput Directory: .\n\nNext steps can be found in the README file at .\u002Fsam-twitter-process\u002FREADME.md\n",[43,489,490,500,526,546,562,570,576,593,602,611,621,631,641,651,662,673,684,695,706,717,728,739,750,759,764,777,782,800,805,823,839,854,883,894,899,905,916,925,933,951,960,969,978,984,991,997,1006,1013,1025,1037,1049,1054],{"__ignoreMap":144},[148,491,492,495,498],{"class":150,"line":151},[148,493,494],{"class":154},"$",[148,496,497],{"class":158}," sam",[148,499,159],{"class":158},[148,501,502,505,508,511,514,517,520,523],{"class":150,"line":182},[148,503,504],{"class":154},"Which",[148,506,507],{"class":158}," template",[148,509,510],{"class":158}," source",[148,512,513],{"class":158}," would",[148,515,516],{"class":158}," you",[148,518,519],{"class":158}," like",[148,521,522],{"class":158}," to",[148,524,525],{"class":158}," use?\n",[148,527,528,531,534,537,540,543],{"class":150,"line":191},[148,529,530],{"class":154},"        1",[148,532,533],{"class":158}," -",[148,535,536],{"class":158}," AWS",[148,538,539],{"class":158}," Quick",[148,541,542],{"class":158}," Start",[148,544,545],{"class":158}," Templates\n",[148,547,548,551,553,556,559],{"class":150,"line":199},[148,549,550],{"class":154},"        2",[148,552,533],{"class":158},[148,554,555],{"class":158}," Custom",[148,557,558],{"class":158}," Template",[148,560,561],{"class":158}," Location\n",[148,563,564,567],{"class":150,"line":211},[148,565,566],{"class":154},"Choice:",[148,568,569],{"class":178}," 1\n",[148,571,572],{"class":150,"line":219},[148,573,575],{"emptyLinePlaceholder":574},true,"\n",[148,577,578,580,583,585,587,589,591],{"class":150,"line":230},[148,579,504],{"class":154},[148,581,582],{"class":158}," runtime",[148,584,513],{"class":158},[148,586,516],{"class":158},[148,588,519],{"class":158},[148,590,522],{"class":158},[148,592,525],{"class":158},[148,594,595,597,599],{"class":150,"line":240},[148,596,530],{"class":154},[148,598,533],{"class":158},[148,600,601],{"class":158}," nodejs12.x\n",[148,603,604,606,608],{"class":150,"line":250},[148,605,550],{"class":154},[148,607,533],{"class":158},[148,609,610],{"class":158}," python3.8\n",[148,612,613,616,618],{"class":150,"line":258},[148,614,615],{"class":154},"        3",[148,617,533],{"class":158},[148,619,620],{"class":158}," ruby2.7\n",[148,622,623,626,628],{"class":150,"line":267},[148,624,625],{"class":154},"        4",[148,627,533],{"class":158},[148,629,630],{"class":158}," go1.x\n",[148,632,633,636,638],{"class":150,"line":276},[148,634,635],{"class":154},"        5",[148,637,533],{"class":158},[148,639,640],{"class":158}," java11\n",[148,642,643,646,648],{"class":150,"line":284},[148,644,645],{"class":154},"        6",[148,647,533],{"class":158},[148,649,650],{"class":158}," dotnetcore3.1\n",[148,652,654,657,659],{"class":150,"line":653},14,[148,655,656],{"class":154},"        7",[148,658,533],{"class":158},[148,660,661],{"class":158}," nodejs10.x\n",[148,663,665,668,670],{"class":150,"line":664},15,[148,666,667],{"class":154},"        8",[148,669,533],{"class":158},[148,671,672],{"class":158}," python3.7\n",[148,674,676,679,681],{"class":150,"line":675},16,[148,677,678],{"class":154},"        9",[148,680,533],{"class":158},[148,682,683],{"class":158}," python3.6\n",[148,685,687,690,692],{"class":150,"line":686},17,[148,688,689],{"class":154},"        10",[148,691,533],{"class":158},[148,693,694],{"class":158}," python2.7\n",[148,696,698,701,703],{"class":150,"line":697},18,[148,699,700],{"class":154},"        11",[148,702,533],{"class":158},[148,704,705],{"class":158}," ruby2.5\n",[148,707,709,712,714],{"class":150,"line":708},19,[148,710,711],{"class":154},"        12",[148,713,533],{"class":158},[148,715,716],{"class":158}," java8\n",[148,718,720,723,725],{"class":150,"line":719},20,[148,721,722],{"class":154},"        13",[148,724,533],{"class":158},[148,726,727],{"class":158}," dotnetcore2.1\n",[148,729,731,734,736],{"class":150,"line":730},21,[148,732,733],{"class":154},"        14",[148,735,533],{"class":158},[148,737,738],{"class":158}," dotnetcore2.0\n",[148,740,742,745,747],{"class":150,"line":741},22,[148,743,744],{"class":154},"        15",[148,746,533],{"class":158},[148,748,749],{"class":158}," dotnetcore1.0\n",[148,751,753,756],{"class":150,"line":752},23,[148,754,755],{"class":154},"Runtime:",[148,757,758],{"class":178}," 8\n",[148,760,762],{"class":150,"line":761},24,[148,763,575],{"emptyLinePlaceholder":574},[148,765,767,770,773],{"class":150,"line":766},25,[148,768,769],{"class":154},"Project",[148,771,772],{"class":158}," name",[148,774,776],{"class":775},"s95oV"," [sam-app]: sam-twitter-process\n",[148,778,780],{"class":150,"line":779},26,[148,781,575],{"emptyLinePlaceholder":574},[148,783,785,788,791,794,797],{"class":150,"line":784},27,[148,786,787],{"class":154},"Cloning",[148,789,790],{"class":158}," app",[148,792,793],{"class":158}," templates",[148,795,796],{"class":158}," from",[148,798,799],{"class":158}," https:\u002F\u002Fgithub.com\u002Fawslabs\u002Faws-sam-cli-app-templates.git\n",[148,801,803],{"class":150,"line":802},28,[148,804,575],{"emptyLinePlaceholder":574},[148,806,808,811,814,817,820],{"class":150,"line":807},29,[148,809,810],{"class":154},"AWS",[148,812,813],{"class":158}," quick",[148,815,816],{"class":158}," start",[148,818,819],{"class":158}," application",[148,821,822],{"class":158}," templates:\n",[148,824,826,828,830,833,836],{"class":150,"line":825},30,[148,827,530],{"class":154},[148,829,533],{"class":158},[148,831,832],{"class":158}," Hello",[148,834,835],{"class":158}," World",[148,837,838],{"class":158}," Example\n",[148,840,842,844,846,849,851],{"class":150,"line":841},31,[148,843,550],{"class":154},[148,845,533],{"class":158},[148,847,848],{"class":158}," EventBridge",[148,850,832],{"class":158},[148,852,853],{"class":158}," World\n",[148,855,857,859,861,863,866,868,871,874,877,880],{"class":150,"line":856},32,[148,858,615],{"class":154},[148,860,533],{"class":158},[148,862,848],{"class":158},[148,864,865],{"class":158}," App",[148,867,796],{"class":158},[148,869,870],{"class":158}," scratch",[148,872,873],{"class":775}," (100+ ",[148,875,876],{"class":158},"Event",[148,878,879],{"class":158}," Schemas",[148,881,882],{"class":775},")\n",[148,884,886,889,892],{"class":150,"line":885},33,[148,887,888],{"class":154},"Template",[148,890,891],{"class":158}," selection:",[148,893,569],{"class":178},[148,895,897],{"class":150,"line":896},34,[148,898,575],{"emptyLinePlaceholder":574},[148,900,902],{"class":150,"line":901},35,[148,903,904],{"class":154},"-----------------------\n",[148,906,908,911,913],{"class":150,"line":907},36,[148,909,910],{"class":154},"title:",[148,912,536],{"class":158},[148,914,915],{"class":158}," SAMの使い方｜ローカル開発からデプロイまで\n",[148,917,919,922],{"class":150,"line":918},37,[148,920,921],{"class":154},"createdAt:",[148,923,924],{"class":158}," '2020-04-07'\n",[148,926,928,931],{"class":150,"line":927},38,[148,929,930],{"class":154},"updatedAt:",[148,932,924],{"class":158},[148,934,936,939,942,945,948],{"class":150,"line":935},39,[148,937,938],{"class":154},"tags:",[148,940,941],{"class":775}," [",[148,943,944],{"class":158},"'AWS'",[148,946,947],{"class":775},", ",[148,949,950],{"class":158},"'Python']\n",[148,952,954,957],{"class":150,"line":953},40,[148,955,956],{"class":154},"draft:",[148,958,959],{"class":178}," false\n",[148,961,963,966],{"class":150,"line":962},41,[148,964,965],{"class":154},"description:",[148,967,968],{"class":158},"  '本記事では、AWS SAM（Serverless Application Model）について解説します。簡単なテンプレートが提供されているので、それを使って基本の使い方を把握した後、ちょっとした応用をします。内容はAPI Gateway + LambdaでLambdaがS3からデータを取得し、JSONをまとめて返します。'\n",[148,970,972,975],{"class":150,"line":971},42,[148,973,974],{"class":154},"thumbnail:",[148,976,977],{"class":158}," '\u002Fimg\u002Ftwitter-card.png'\n",[148,979,981],{"class":150,"line":980},43,[148,982,983],{"class":154},"---\n",[148,985,987],{"class":150,"line":986},44,[148,988,990],{"class":989},"sAwPA","# AWS SAMの使い方｜ローカル開発からデプロイまで\n",[148,992,994],{"class":150,"line":993},45,[148,995,996],{"class":154},"--------------------\n",[148,998,1000,1003],{"class":150,"line":999},46,[148,1001,1002],{"class":154},"Name:",[148,1004,1005],{"class":158}," sam-twitter-process\n",[148,1007,1009,1011],{"class":150,"line":1008},47,[148,1010,755],{"class":154},[148,1012,672],{"class":158},[148,1014,1016,1019,1022],{"class":150,"line":1015},48,[148,1017,1018],{"class":154},"Dependency",[148,1020,1021],{"class":158}," Manager:",[148,1023,1024],{"class":158}," pip\n",[148,1026,1028,1031,1034],{"class":150,"line":1027},49,[148,1029,1030],{"class":154},"Application",[148,1032,1033],{"class":158}," Template:",[148,1035,1036],{"class":158}," hello-world\n",[148,1038,1040,1043,1046],{"class":150,"line":1039},50,[148,1041,1042],{"class":154},"Output",[148,1044,1045],{"class":158}," Directory:",[148,1047,1048],{"class":158}," .\n",[148,1050,1052],{"class":150,"line":1051},51,[148,1053,575],{"emptyLinePlaceholder":574},[148,1055,1057,1060,1063,1066,1069,1072,1075,1078,1081,1084,1087],{"class":150,"line":1056},52,[148,1058,1059],{"class":154},"Next",[148,1061,1062],{"class":158}," steps",[148,1064,1065],{"class":158}," can",[148,1067,1068],{"class":158}," be",[148,1070,1071],{"class":158}," found",[148,1073,1074],{"class":158}," in",[148,1076,1077],{"class":158}," the",[148,1079,1080],{"class":158}," README",[148,1082,1083],{"class":158}," file",[148,1085,1086],{"class":158}," at",[148,1088,1089],{"class":158}," .\u002Fsam-twitter-process\u002FREADME.md\n",[10,1091,1092],{},"次に template を書き換えます。といっても、パスやファイル名を変えるだけです。\nあとは、Lmabda で pandas を使うので、requirements.txt に書き加えておきます。",[10,1094,1095,1096,1099,1100,1103,1104,1106],{},"Lambda をテストするには",[43,1097,1098],{},"sam build","したのちに、",[43,1101,1102],{},"sam local start-api","を行い、ブラウザから指定されたアドレスにアクセスすればできます。注意点はコード変更後に",[43,1105,1098],{},"をしないと変更が反映されないです。",[123,1108,1110],{"id":1109},"get-で取得した-json-の日本語が文字化けする","GET で取得した JSON の日本語が文字化けする",[10,1112,1113],{},"Lambda の返り値の JSON がコマンドラインでは問題なく出力されていたが、ブラウザで取得した JSON をみると日本語が文字化けしていました。",[10,1115,1116,1117,1120],{},"対策は pandas で直接",[43,1118,1119],{},"df.to_json","とするのではなく、いったん index を振り直してから辞書を作成します。その後 json.dumps で json にします。",[10,1122,1123],{},"これで日本語の文字化けが直りました。",[139,1125,1129],{"className":1126,"code":1127,"language":1128,"meta":144,"style":144},"language-py shiki shiki-themes github-dark","df = df.reset_index(drop=True)\nres = df.to_dict(orient=\"recodes\")\nreturn {\n  \"statusCode\": 200,\n  \"headers\": {\n        'Content-type': 'application\u002Fjson;charset=UTF-8'\n  },\n  \"body\": json.dumps(res, ensure_ascii=False),\n}\n\n","py",[43,1130,1131,1136,1141,1146,1151,1156,1161,1166,1171],{"__ignoreMap":144},[148,1132,1133],{"class":150,"line":151},[148,1134,1135],{},"df = df.reset_index(drop=True)\n",[148,1137,1138],{"class":150,"line":182},[148,1139,1140],{},"res = df.to_dict(orient=\"recodes\")\n",[148,1142,1143],{"class":150,"line":191},[148,1144,1145],{},"return {\n",[148,1147,1148],{"class":150,"line":199},[148,1149,1150],{},"  \"statusCode\": 200,\n",[148,1152,1153],{"class":150,"line":211},[148,1154,1155],{},"  \"headers\": {\n",[148,1157,1158],{"class":150,"line":219},[148,1159,1160],{},"        'Content-type': 'application\u002Fjson;charset=UTF-8'\n",[148,1162,1163],{"class":150,"line":230},[148,1164,1165],{},"  },\n",[148,1167,1168],{"class":150,"line":240},[148,1169,1170],{},"  \"body\": json.dumps(res, ensure_ascii=False),\n",[148,1172,1173],{"class":150,"line":250},[148,1174,1175],{},"}\n",[48,1177,1178],{"id":1178},"まとめ",[10,1180,1181,1182,1184],{},"SAM をなんとなく、敬遠していましたが試してみると使いやすくてよかったです。公式ドキュメントがけっこう充実していたのが大きいです。",[43,1183,45],{},"はもう必要ないですね。template.yaml さえ書ければかなり便利に使えそうです。",[10,1186,1187],{},"少し残念だったのは、以下のように作成済みのバケットをイベントソースに指定できないことです。",[63,1189,1190],{},[10,1191,1192],{},"NOTE: To specify an S3 bucket as an event source for a Lambda function, both resources have to be declared in the same template. AWS SAM does not support specifying an existing bucket as an event source.",[10,1194,1195],{},"SAM を使う場合は、S3 のバケット作成も含めて全体を新しく作る必要がありそうです。",[1197,1198,1199],"style",{},"html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}",{"title":144,"searchDepth":182,"depth":182,"links":1201},[1202,1203,1204,1207,1210],{"id":50,"depth":182,"text":51},{"id":101,"depth":182,"text":102},{"id":120,"depth":182,"text":121,"children":1205},[1206],{"id":125,"depth":191,"text":125},{"id":450,"depth":182,"text":451,"children":1208},[1209],{"id":1109,"depth":191,"text":1110},{"id":1178,"depth":182,"text":1178},"2020-04-07","本記事では、AWS SAM（Serverless Application Model）について解説します。簡単なテンプレートが提供されているので、それを使って基本の使い方を把握した後、ちょっとした応用をします。内容はAPI Gateway + LambdaでLambdaがS3からデータを取得し、JSONをまとめて返します。",false,"md",{},"\u002Fcontents\u002Fuse-aws-sam",{"title":5,"description":1212},"contents\u002Fuse-aws-sam",[810,1220],"Python","\u002Fimg\u002Ftwitter-card.png","IYtOaCL7DgrGO47a30Unemo0dYaRuMOCtn1Q47ypX0I",[1224,1228],{"title":1225,"path":1226,"stem":1227,"children":-1},"Pythonのエラーハンドリング：try...exceptのベストプラクティスを考える","\u002Fcontents\u002Ftry_exept","contents\u002Ftry_exept",{"title":1229,"path":1230,"stem":1231,"children":-1},"VikingMem: A Memory Base Management System for Stateful LLM-based Applications","\u002Fcontents\u002Fvikingmem-memory-base","contents\u002Fvikingmem-memory-base",1784936718577]