Make and Deploy a Serverless Application Into AWS lambda
Tags: serverless, lamda, aws, node
Published: 2019-09-24 09:13:37

At my job we needed a solution for writing, maintaining and deploying aws lambdas. The serverless framework is a nodejs framework used for making and deploying serverless applications such as AWS Lambdas.

So we selected the serverless application as our choice for these sole reasons:

- Easy to manage configuration environment via enviromental viariables.
- Easy to keep a record of the lambda settings and change history via git, so we can kill the person who did a mistake. (ok ok just kidding, no human has been killed ;) ... yet )
- Because it also is node.js framework we can use the normal variety of the frameworks used for unit and integration testing.
- Also for the reason above we also could manage and deploy dependencies as well using combination of nodejs tools and the ones provided from the  serverless framework.
- Ce can have a single, easy to maintain, codebase with more than one aws lambdas without the need for duplicate code.

# Install serverless

```
sudo -H npm i -g serverless
```
(For windows ommit the `sudo -H` part)

# Our first lambda

If not we need to create our project folder and initialize an node.js project:
```
mkdir myFirstLambda
cd myFirstLambda
npm init
git add .
git commit -m "Our first project"
```
Then install `serverless` as dev-dependency, we need that because on colaborative projects it will install all the required tools to deploy and run the project:

```
npm install --save-dev serverless

```

And then run the following command to bootstrap our first lambda function:
```
serverless create --template aws-nodejs
```
With that command 2 files have been generated:

* `handler.js` Where contains our aws lambda handlers.
* `serverless.yml` where it contains all the deployment and running settings.

Then on `handler.js` change the function `module.exports.hello` with a respective name representing the functionality. For our purpoce we will keep it as is. We can run the lambda function locally via the command:

```
 sls invoke local --stage=dev --function hello
```

Which it will show the returning value of the function hello on `handler.js`. Also it is a good idea to place the command above as a `start` script into `package.json` at `scripts` section.

# Deploy aws lambda

First of all we need to specify the lambda name. So we need to modify the `serverless.yml` accorditly in order to be able to specify the AWS lambda name. So we change the `functions` sections from:

```
functions:
  hello:
    handler: handler.hello
```

Into:

```
functions:
  hello:
    handler: handler.hello
    name: MyLambda
    description: "My First Lambda"
    timeout: 10
    memorySize: 512
```

With that we can list the deployed lambda as `MyLambda` as aws console, also as seen above we can specify and share lambda settings.

Furthermore is good idea to specify enviromental variables via at the `environment:` section with the following setting:

```
  environment: ${file(./.env.${self:provider.stage}.yml)}
```
With that we can use the `stage` for each deployment environment and each setting will be provided from .env files. Also upon deployment the `.env` files will be used in order to be able to specify the **deployed** lambda environmental variables as well.

Also is good idea to ship a template .env file named `.env.yml.dist` so each developer will need to do:

```
cp .env.yml.dist .env.dev.yml
```

And fill the appropriate settings. Also for production you need to do:

```
cp .env.yml.dist .env.prod.yml
```

Then exclude these files to be deployed except the on offered by the stage parameter (will seen bellow):

```
package:
  include:
    - .env.${self:provider.stage}.yml
  exclude:
    - .env.*.yml.dist
    - .env.*.yml
```

Then deploy with the command:

```
sls deploy --stage ^environment_type^ --region ^aws_region^
```

As seen the pattern followed is the: `.env.^environment_type^.yml` where the `^environment_type^` is the value provided from the `--stage` parameter at both `sls invoke` and `sls deploy` commands.


Also we could specify depending the environment the lambda name using these settings as well:

```
functions:
  hello:
    handler: handler.hello
    name: MyLambda-${self:provider.stage}
    description: "My First Lambda"
    timeout: 10
    memorySize: 512
```

Where the `${self:provider.stage}` takes its value from the `--stage` parameter. Than applies where the `${self:provider.stage}` is met at the `serverless.yml` file.