Node.js, yarn, and the serverless framework.
yarn global add serverless
Lambda functions are spread through two project services: Subscriptions and Tokens, each with their own directory and its own serverless.yml configuration:
|
|-subscriptions-service
|-tokens-service
Each service directory in turn, occupy its own functions.
serverless can be used to work with its own aws credentials so it doesn't need to run with your own root user's API keys. This is a best practice and should be followed.
Configuring credentials for serverless:
$ sls config credentials --provider aws --key xxxxxxxxxxxxxx --secret xxxxxxxxxxxxxx --profile serverless-cli
This is nice, but it just adds an entry to the ~/.aws/credentials file. To actually let your .serveless project know which profile to use you need to specify it in the provider directive on serverless.yml or it will take the default.
Edit .serverless
and add an appropriate profile entry as follows:
service: new-service
provider:
name: aws
runtime: nodejs6.10
stage: dev
profile: serverless-cli
Each service in the project has it's own directory, and own functions configuration in a serverless.yml
file.
The functions in subscriptions-service
require the web push public/private key pairs available as environment variables WEB_PUSH_PUBKEY
and WEB_PUSH_PRVKEY
.
The serverless configuration deploys them to aws based on the JSON file contents in config.dev.json
which shouldn't be committed to git as it includes your web push secrets identity.
An example config.dev.json
file contents:
{
"vapidKeys": {
"publicKey": "xxxxxxxxxx",
"privateKey": "xxxxxxxxxx"
}
}
*The keys can be generated using the web-push
npm package: web-push generate-vapid-keys --json
to deploy an entire serverless configuration with all the setup cd into one of the functions and run the following:
$ cd tokens-service
$ sls deploy —verbose
To only deploy and update a specific function's implementation run the following:
$ cd subscriptions-service
$ sls deploy function --function saveSubscription
$ sls deploy function --function triggerSubscriptionByToken
Bazz uses a DynamoDB for persistency, so for any of the functions to work, it needs a database. This is accommodated using the localstack project.
Manual tests are run by invoking individual functions using the serverless framework.
localstack is used as an all-in-one project to simulate and mock many of AWS services in a local docker-based environment.
Python is required:
$ pip install localstack
We'll run the docker-based localstack version:
$ localstack start --docker
This will download an image with all the required software running inside it. We can test running it with some aws commands that point to the local aws infra:
$ aws --endpoint-url=http://localhost:4572 s3 ls
Once localstack is up and able to serve DynamoDB requests, its required to migrate the bazz schema to create tables and indexes:
$ cd subscriptions-service
$ sls dynamodb migrate
$ sls invoke local --function <function-name>
Provide the function with a data payload from a json file that is passed as the event
:
$ sls invoke local --function <function-name> --path <input.json>
where input.json
looks as follows: (https://serverless.com/framework/docs/providers/aws/cli-reference/invoke-local/)
{
"resource": "/",
"path": "/",
"httpMethod": "GET",
"body": "{\"subscription\":{\"endpoint\":\"http://www.example.com\",\"auth_keys\":\"123\"},\"token\":\"abc-def\"}"
}
or provide it with data input on the command line:
$ sls invoke local --function <function-name> —-data <data input>
$ sls invoke local --function functionName --context "hello world"
The sls
CLI implements a debug capability similar to NODE_DEBUG conventions.
To print out all debug information when sls
is invokved prefix every command execution with SLS_DEBUG=*
Invoke the createToken
function, without needing to pass any data or context:
$ cd subscriptions-service
$ sls invoke local --function createToken
Invoke the saveSubscription
function, which expects a valid subscription object in the request body, so we pass in a --path
argument for a json file that represents the event
object in the lambda:
$ cd subscriptions-service
$ SLS_DEBUG=* sls invoke local --function saveSubscription --path __tests__/__fixtures__/saveSubscriptionData.json
$ cd subscriptions-service
$ SLS_DEBUG=* sls invoke local --function triggerSubscriptionByToken --path __tests__/__fixtures__/triggerNotificationData.json
$ cd subscriptions-service
$ SLS_DEBUG=* sls invoke local --function getSubscriptions --path __tests__/__fixtures__/getSubscriptionsByToken.json
bazz-frontend - the frontend project
bazz - the Node.js CLI app
Liran Tal liran.tal@gmail.com