Lambda をいろいろな用途で使い出すと function の登録や更新が面倒なので、自分が使い回している gulpfile の雛形を晒しておきます。
機能
lambda.yml
という設定ファイルに環境毎の lambda の設定情報を記載しておきます。
gulp build --env={production|development}
で、コードの build、zip化、function 登録・更新までを自動で行います。
必要なもの
package.json の devDependencies には、
- del
- gulp
- gulp-awslambda
- gulp-install
- gulp-load-plugins
- gulp-rename
- gulp-zip
- js-yaml
- run-sequence
- yargs
が必要です。
dependencies にある場合は、省略可。
雛形
const gulp = require('gulp')
const $ = require('gulp-load-plugins')()
const argv = require('yargs').argv
const env = argv.env || 'development'
gulp.task('build', () =>
require('run-sequence')('clean', 'lambda')
)
gulp.task('clean', (done) =>
require('del')(['build/*', '!build/node_modules', 'dist/*'], done)
)
gulp.task('prepareCode', () =>
gulp.src('src/**/*.js')
.pipe(gulp.dest('build'))
)
gulp.task('prepareConfig', () =>
gulp.src(`config/${env}.yml`)
.pipe($.rename('default.yml'))
.pipe(gulp.dest('build/config'))
)
gulp.task('preparePackages', () =>
gulp.src('./package.json')
.pipe(gulp.dest('build'))
.pipe($.install({production: true}))
)
gulp.task('lambda', ['prepareCode', 'prepareConfig', 'preparePackages'], () => {
const lambdaConfig = require('js-yaml').safeLoad(require('fs').readFileSync('lambda.yml', 'utf8'))[env]
return gulp.src(['build/**', '!build/package.json'])
.pipe($.zip('lambda.zip'))
.pipe($.awslambda(lambdaConfig.lambda, lambdaConfig.config))
.pipe(gulp.dest('dist'))
})
default:
config: &config
region: ap-northeast-1
lambda: &default
Handler: lambda.handler
Runtime: nodejs4.3
MemorySize: 128
Timeout: 60
production:
config:
<<: *config
profile: production
lambda:
<<: *default
FunctionName: {FUNCTION_NAME}
Description: {DESCRIPTION}
Role: {ROLE_ARN}
development:
config: *config
lambda:
<<: *default
FunctionName: {FUNCTION_NAME}-dev
Description: {DESCRIPTION}
Role: {ROLE_ARN}
やってること
- clean
build 用フォルダの削除。
- prepareCode
ソースファイル(src/*/.js)を build 以下にコピーする。
- prepareConfig
環境用設定ファイル(config/*.yml)を選択し、build/config/default.yml としてコピーする。
- preparePackages
lambda 実行に必要な node_modules を build フォルダにインストールする。
native build が必要なパッケージには非対応。
- gulp task: lambda
build フォルダ以下を lambda.zip として固めて lambda に登録。
function がない場合は新規に作成、ある場合はコードを反映。登録情報に変更がある場合は更新後にコード反映。
- gulp task: build
clean 後に lambda 実行。
補足
lambda function 用の設定ファイルが必要
node-config(+ js-yaml)で環境毎の設定ファイルをロードし利用する手法を採用しています。
違うやり方が好きな人は、gulpfile の prepareConfig
の部分を適宜修正してください。
lambda.yml の AWS Credential について
config
項に config.region
以外何も指定していない場合、認証情報として awscli の default profile の利用を試みます。
違う profile を指定する場合は、config.profile
に profile 名 を指定してください。
Node の AWS SDK は現時点で role_arn に対応していないため、assume-role は自前で行っておく必要があります。
AssumeRole が面倒な人向け簡易 shell script
lambda.yml の Role について
lambda 実行用の IAM Role は事前に awscli もしくは管理コンソールで作成しておき、その ARN を指定します。
IAM Role を作るには、
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
上記 AssumeRolePolicy.json を用意して
$ aws iam create-role \
--role-name {LAMBDA_ROLE_NAME} \
--assume-role-policy-document file://AssumeRolePolicy.json
で role 作成。
$ aws iam attach-role-policy \
--role-name {LAMBDA_ROLE_NAME} \
--policy-arn arn:aws:iam::aws:policy/AWSLambdaExecute
で作成した role に管理ポリシーの AWSLambdaExecute を付与。
追加でインラインポリシーを指定したい場合は、
{
"Version": "2012-10-17",
"Statement": [
{
"Effect":"Allow",
"Action":"sdb:*",
"Resource":"arn:aws:sdb:*"
}
]
}
のような InlinePolicy.json を用意(追加で付与したい権限を設定)して、
$ aws iam put-role-policy \
--role-name {LAMBDA_ROLE_NAME} \
--policy-name {POLICY_NAME} \
--policy-document file://InlinePolicy.json
で追加付与。
Role ARN は、
$ aws iam get-role \
--role-name {LAMBDA_ROLE_NAME} \
--query Role.Arn \
--output text
で確認できます。