AWS SAMテンプレートのWeb Backendを試す。
はじめに
サーバレスアプリケーショ作ることになり、SAM使おうと思い色々調べていたのですが、 大体がHello Worldであり、DBまでできるものを見たかったので、 同じくSAMのテンプレートで選べるWeb Backendを作ってみました。
SAMの環境構築
基本的にはAWSのガイドを見て進めれば出来ると思います。
Mac
macOS への AWS SAM CLI のインストール - AWS サーバーレスアプリケーションモデル
Win
Windows での AWS SAM CLI のインストール - AWS サーバーレスアプリケーションモデル
- AWS アカウントの作成
- IAM アクセス許可の設定
- Docker をインストールします。注意 Dockerは、アプリケーションをローカルでテストするための前提条件です。
- Homebrew をインストールします。
- AWS SAM CLI のインストール
1〜4は割愛します。
ステップ 5. AWS SAM CLI のインストール
インストール
$ brew tap aws/tap $ brew install aws-sam-cli
インストールできたか確認
$ sam --version SAM CLI, version 1.1.0
初回確認は意外と待ちました。(5秒位)
今回の流れでは不要ですが、アップグレードする場合
$ brew upgrade aws-sam-cli
Web Backendの作成
Hello Worldですが全体の流れは大体同じです。
チュートリアル Hello World アプリケーションの導入 - AWS サーバーレスアプリケーションモデル
ステップ 1. サンプルのダウンロード AWS SAM アプリケーション
sam init *途中入力を求められます。 Which template source would you like to use? 1 - AWS Quick Start Templates 2 - Custom Template Location Choice: 1 *1を選択 Which runtime would you like to use? 1 - nodejs12.x 2 - python3.8 3 - ruby2.7 4 - go1.x 5 - java11 6 - dotnetcore3.1 7 - nodejs10.x 8 - python3.7 9 - python3.6 10 - python2.7 11 - ruby2.5 12 - java8.al2 13 - java8 14 - dotnetcore2.1 Runtime: 1 * 1 - nodejs12.xを選択 Project name [sam-app]: ただエンターを押せばsam-appでディレクトリが作られます。 Cloning app templates from https://github.com/awslabs/aws-sam-cli-app-templates.git AWS quick start application templates: 1 - Hello World Example 2 - Step Functions Sample App (Stock Trader) 3 - Quick Start: From Scratch 4 - Quick Start: Scheduled Events 5 - Quick Start: S3 6 - Quick Start: SNS 7 - Quick Start: SQS 8 - Quick Start: Web Backend Template selection: 8 *Web Backendなので8を選択します。 ----------------------- Generating application: ----------------------- Name: sam-app Runtime: nodejs12.x Dependency Manager: npm Application Template: web-backend Output Directory: . Next steps can be found in the README file at ./sam-app/README.md
ステップ 2. アプリケーションの構築
$ cd sam-app $ sam build Building function 'getAllItemsFunction' Running NodejsNpmBuilder:NpmPack Running NodejsNpmBuilder:CopyNpmrc Running NodejsNpmBuilder:CopySource Running NodejsNpmBuilder:NpmInstall Running NodejsNpmBuilder:CleanUpNpmrc Building function 'getByIdFunction' Running NodejsNpmBuilder:NpmPack Running NodejsNpmBuilder:CopyNpmrc Running NodejsNpmBuilder:CopySource Running NodejsNpmBuilder:NpmInstall Running NodejsNpmBuilder:CleanUpNpmrc Building function 'putItemFunction' Running NodejsNpmBuilder:NpmPack Running NodejsNpmBuilder:CopyNpmrc Running NodejsNpmBuilder:CopySource Running NodejsNpmBuilder:NpmInstall Running NodejsNpmBuilder:CleanUpNpmrc 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
ステップ 3. アプリケーションをAWSクラウドにデプロイする
sam deploy --guided
デプロイするためには色々と権限が必要です。
awsのcredentialによっては権限不足でエラーになるので適宜必要な権限を付与してあげてください。
私の場合は下記の権限を追加してデプロイ出来るようになりました。
ローカル実行時に「profileを指定することで」任意のcredentialを利用可能です。
使っているcredentialを変えたくない場合は、
~/.aws/credentialsに定義した上でsamのコマンドを実行しましょう。
下記はローカルで動作させるためのコマンド
sam local start-api --env-vars env.json --profile default --debug
IAM
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "iam:GetRole", "iam:PassRole", "iam:DetachRolePolicy", "iam:TagRole", "iam:CreateRole", "iam:DeleteRole", "iam:AttachRolePolicy", "iam:UpdateRole", "iam:PutRolePolicy" ], "Resource": "*" } ] }
Cloudformation
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "cloudformation:DescribeStackEvents", "cloudformation:DescribeStackSet", "cloudformation:CreateChangeSet", "cloudformation:DescribeChangeSet", "cloudformation:ExecuteChangeSet", "cloudformation:DeleteChangeSet", "cloudformation:DescribeStacks" ], "Resource": "*" } ] }
API_Gateway
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "apigateway:DELETE", "apigateway:SetWebACL", "apigateway:PUT", "apigateway:PATCH", "apigateway:POST", "apigateway:GET" ], "Resource": "*" } ] }
Lambda
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "lambda:CreateFunction", "lambda:AddPermission", "lambda:GetFunction", "lambda:GetFunctionConfiguration", "lambda:DeleteFunction", "lambda:RemovePermission" ], "Resource": "*" } ] }
S3
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:PutBucketTagging", "s3:PutBucketPolicy", "s3:CreateBucket", "s3:DeleteBucketPolicy", "s3:DeleteBucket", "s3:PutBucketVersioning" ], "Resource": "*" } ] }
DynamoDB
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "dynamodb:CreateTable", "dynamodb:DescribeTable" ], "Resource": "*" } ] }
クリーンアップ
このチュートリアルを実行して作成した AWS リソースが不要になった場合は、
デプロイした AWS CloudFormation スタックを削除することでリソースを削除できます。
コンソールかコマンド実行のいずれか。
・AWSコンソールからCloudformationのページへ行き、スタックよりsam-appを削除
- AWS マネジメントコンソール にサインインして、https://console.aws.amazon.com/cloudformation で AWS CloudFormation コンソールを開きます。
- 左のナビゲーションペインで [スタック] を選択します。
- スタックのリストで、[sam-app] (または作成したスタックの名前) を選択します。
- [削除] を選択します。
・コマンド実行
aws cloudformation delete-stack --stack-name sam-app --region ap-northeast-1
※スタックの削除を行うには下記権限が別途必要
cloudformation:DeleteStack
SAMでデプロイしたcredentialで出来上がったアプリケーションの確認をしようとすると色々権限なくて止まる。
ちゃんとやるならSAM作成とアプリ開発でポリシー分けるのがよさげです。
全部かちょっと怪しいですが、途中で追加した権限
"iam:PutRolePolicy", "iam:GetRolePolicy" "dynamodb:GetItem", "dynamodb:Scan", "dynamodb:DeleteTable" "s3:DeleteBucket", "s3:PutBucketVersioning"
Laravelバージョンアップした件(5.5 → 6.0)その2
ようやく落ち着いたので続きを書きます。
前回の振り返り
見出しだけ
- configureMonologUsingのエラー
- 'str'、'array'の修正
- AbstractRequestのメソッド可視化レベル変更
- proxy headerの修正
- codeseptionの修正(バージョンアップ)
- laravel-moduleのmigrate
Loggerの修正
configureMonologUsingが使えなくなり、logger.phpでログ周りの設定を管理するようになったため、
ログ周りの共通クラスで使用していたLog::getMonolog();でエラーに。
$monolog = Log::getMonolog(); // 変更前 $monolog = Log::getLogger(); // 変更後
共通化しているロガーが厄介で、呼び出し側のパラメータでログファイル名が動的に変わるようにな作りで、
ログハンドラーを消したり設定したりをしており、単純にlogger.phpに定義できず。
上記のようなloggerの設定を変更している処理だったので、
下記サイトを参考にStreamHandlerを宣言して、ファイル名なんかを設定し直すようにして現行どおりのログにできました。感謝
【Laravel】monologでカスタムログ出力先を変更する方法メモ | SAGA.TXT
// ロガー
$log = new Logger('name'); // ログ名を引数にいれます。(ログが出力された時、)
// ハンドラー(メイン処理)に入れる引数を用意する。
$log_path = storage_path() .'/logs/login.log'; //ファイルパス
$log_level = config('app.log_level'); // ログレベル
$bubble = true; // 以降のハンドラに処理を続行させるかどうかのフラグ、デフォルトは、true
$filePermission = 0777; //ログファイルのパーミッションを変更できるので、必要な場合は入れておく
// ★ロガーにハンドラーをpush
$log->pushHandler(new StreamHandler($log_path, $log_level , $bubble, $filePermission));
画面を開くとFaker\Factoryのエラー
ローカルでは発生しなかったが、STGデプロイしたら発生
テストデータなどで使うfakerをどこかしらで使っているようでした。
具体的な解決策はほとんど見つけられず、単純に対応できそうな下記の対応としました。
composer.jsonではrequire-devに定義されていたので、これをrequireに移動
"fzaninotto/faker": "~1.4"
色々と見つかるので、各バージョンのアップグレードガイドを見直して影響ないか確認することに。
全部見きれないので、影響度が高いものと中程度を中心に確認。
6.X
Carbon 1.xのサポート停止
https://carbon.nesbot.com/docs/#api-carbon-2
- ::create()のmonth、day未指定の場合、1固定となった。Carbon1の場合、カレントの値。
マイクロ秒まで精度向上
日付イコールがイコールにならない可能性。$date->jsonSerialize() and json_encode($date 配列で返していたものを文字列に変化
- setToStringFormatのクロージャの書き方が変わった。
- setWeekStartsAt、 setWeekEndsAt非推奨 範囲外の値を指定した場合、例外をスローしなくなった
- isSameMonth、isCurrentMonth 異なる年の比較においてfalseを返すようになった。 isSameMonthの2番目のパラメーターまたはisCurrentMonthの最初のパラメーターとしてfalseを渡して、年を無視して比較できます。
- ::compareYearWithMonth()、 ::compareYearWithMonth() 削除
- ミックスイン時、$selfは不要、代わりに$thisを使用
ミックスインって何って思ったらtraitみたいな仕組みのよう。
理解するのに一苦労しましたが、mixinを使う際のクロージャの引数に$selfを用いて呼び出し元の変数を参照できていたのが、
$selfを書かなくても良くなり、$thisで参照できるようになったよ。ってことだと思う。
carbonのgithubのテストコードか何かに書いてあったソースを見てようやく理解。
私が見た実装には該当箇所がなかったので、検証はしていません。
Carbonのマクロ使用時におけるクロージャの引数のことだと思われます。
バージョン1では引数に$selfを必要としてたのが、引数が不要となり、$thisで同等の操作が可能になった。
下記Carbonのバージョン違いのテストコードから判断。
https://github.com/briannesbitt/Carbon/blob/version-1.next/tests/Carbon/Fixtures/Mixin.php
https://github.com/briannesbitt/Carbon/blob/master/tests/Carbon/Fixtures/Mixin.php
- useMicrosecondsFallback、isMicrosecondsFallbackEnabled 削除
- CarbonIntervalの不明なメソッドの呼び出しの振る舞い null → Exception
- dayOfYearの開始値 0から → 1から
Redisデフォルトクライアント
現状影響はないが、現バージョンのpredisは7系で廃止となる予定とのこと。
可能であればphpredisへ切り替える。設定変更のみであれば対応したい。
データベースのCapsule::tableメソッド
illuminate/databaseの使用箇所がないため、影響なしと判断
EloquentのArrayableとtoArray
ArrayableとtoArrayで検索。Eloquentとは関係なさそうなため、影響なしと判断
EloquentのBelongsTo::updateメソッド
使用箇所がないと思われるため影響なしと判断。
belogToの実装はあったが、そのメソッドを呼び出している箇所がない。
Eloquentの主キータイプ
主キーがint型でないテーブルが影響
password_resets系が該当。
Laravelのauthにより生成されるテーブルのため問題なしと判断。
他のEloquentについてもprimarykey変数設定がされていたので、こちらも問題なし。
多言語化のLang::trans and Lang::transChoiceメソッド
Langの使用箇所がないため、影響なしと判断
多言語化のLang::getFromJsonメソッド
Langの使用箇所がないため、影響なしと判断
キュー再試行制限
artisanコマンドなのでひとまず影響なし。
環境によってはデプロイツールなどで仕様されている場合もあるかもですね。
メール確認再送信Route
resendの使用箇所がないため、影響なしと判断
メール確認ルートの変更
email/verifyの使用箇所がないため、影響なしと判断
Inputファサード
該当あり。
Input::get → Request::inputに変更
Input::flash(); → $request->flashに変更
5.8
キャッシュ持続時間が秒指定に
要修正
キャッシュロックの安全性向上
Cache::lock()->release()について使用箇所がないため、影響なしと判断
環境変数のパース
.envには#が含まれていると#の後ろが切れてしまう。クオートで囲っていれば問題なし。
使用箇所がないため、影響なし
Markdownファイルのディレクトリ変更
こういった使われ方はしていない。Markdownを用いたメールは未使用なので影響なし
Nexmo/Slack通知チャンネル
未使用であるため影響なし
新しいデフォルトパスワード長
システムでは最低6文字なのでで影響あるかと思いきや自前でバリデーションしているからか特に影響なし。
コンテナジェネレーターとタグ付けサービス
使用箇所がないため、影響なしと判断
SQLiteバージョン制約
使用箇所がないため、影響なしと判断
ヘルパから文字列と配列クラスへ
6.0の対応にて済み
遅延サービスプロバイダ
未使用と思われるため、影響なしと判断
PSR-16準拠
Illuminate\Cache\Repositoryを使用している箇所がないため、影響なしと判断
Illuminate\Support\Facades\Cacheがファサードのためこちらも調査
使用箇所が1箇所あり。
「キャッシュ持続時間が秒指定」の対応箇所と同じため、その確認で影響なしと判断。
不規則変化する複数形のモデル名
ルールに沿った命名であるか、$tableの指定があるため、影響なしと判断
IDが増加するカスタムピボットモデル
カスタムピボットモデルを使用しているかは不明。多対多リレーションは用いていないのでOKか?
Pivotでgrep。該当なしのため、影響なしと判断
カスタム中間テーブルモデルの定義を参考
LaravelのPivotモデルを使い中間テーブルから関係を取得する - Qiita
Pheanstalk4.0
使用箇所がないため、影響なしと判断
5.7
svgディレクトリの追加
使用しているかは不明だが、コピーして持ってこようかと思いましたが、 特にガイドには記載がなかったが、5.8時点で削除されており、6.0にも存在していないので特に対応しないでおく。
or操作子
bladeのorが使えなくなり、??に変更
単純に置き換えて終了
Cache
アップグレードガイドに従って、各プロジェクトで実行
とわいえ、Cacheは基本redisを用いていることからディレクトリは使われておらず影響はなさそうですが、
バージョンに合わせてディレクトリ構成を変更。
mkdir -p storage/framework/cache/data cp storage/framework/cache/.gitignore storage/framework/cache/data/.gitignore
storage/framework/cache/.gitignoreの内容を下記に修正
* !data/ !.gitignore
Route::redirectメソッド
httpステータスが302で問題なかったので対応不要。
SQLite外部キー
使用箇所がないため、影響なしと判断
テンプレートテーマ
使用箇所がないため、影響なしと判断
ネストしたバリデーションデータ
ネストしてそうだったので動作しない可能性ある箇所を発見。
テストコードを作り確認。
すべてのバリデーションルールが実施できたため問題なし。
テスト
artisanでテストは行っていないので、影響なしと判断
5.6
artisan optimizeの廃止
未使用なので問題なし。
HTMLエンティティエンコーディング
変更前:Blade(およびeヘルパ)は、HTMLエンティティをダブルエンコードしませんでした。
変更後:ダブルエンコードするように。htmlspecialchars関数のデフォルト動作と同じ挙動になった。
以前と同様の振る舞いをするには、Blade::withoutDoubleEncodingを用いる。
e(を用いているbladeを対象に、調査。
該当箇所あり、画面で直接確認。
エンコード前情報が出力されていたため、修正。
レートリミッターのtooManyAttemptsメソッド
未使用のため、影響なしと判断
morphsカラムのインデックス順
未使用のため、影響なしと判断
新しい設定ファイル
configureMonologUsingメソッド
こちらも上記のログ対応で済み
ログWriterクラス
Writer指定箇所がないため影響なし
withSwiftMessageコールバック
実装箇所あり。カスタマイズ性の向上でありそうなので、影響なしと判断
ペジネーション Bootstrap4
ページネーションを確認する。見た目上変化なしのため問題なし
カスタマイズしていると引っかかる可能性あるかも。
新しく生成されたモデルの返却
200を限定して見ている処理はなさそう。 テストコードの一部にステータス200を見ているものがあるのでそこがエラーとなる可能性あり。 codeceptionのacceptanceのテストが該当箇所がありましたが、これらはバージョンアップ前からテスト動作しないため、確認できず、放置w
ValidatesWhenResolvedインターフェイス
未使用のため、影響なしと判断
リードオンリーenvヘルパ
https://readouble.com/laravel/5.8/ja/upgrade.html#deferred-service-providers 地味に影響あったのがこれ
テストコード内の共通処理でputenvでDB接続先を変えてたりしていたものが効かなくなっていることが判明。 configヘルパで代用。