ZeroSharp

Robert Anderson's ones and zeros

Serverless Framework - Part 4: Connecting the Parts

| Comments

This is part of an ongoing series about the Serverless framework: Part 1, part 2, part 3.

New version 0.3.1

Edit: since the original version of this post, a new version 0.3.1 of Serverless was released. I have updated the tutorial below to reflect the newer version. Also, TSD has been deprecated in favour of Typings so I’ve updated to use Typings instead. All parts have been updated for the latest version of the framework 0.3.1.

The Password of the Day Generator class

First up we need a class to generate and check the password of the day. For the moment, let’s pretend the password of the day is always the string “Password”. Put the following typescript class in nodejscomponent/src.

nodejscomponent/src/passwordOfTheDay.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
export function checkPotd(password : string) : boolean
{
    return new PasswordGenerator().check(password);
}

export class PasswordGenerator
{
  generate(date: Date) : string
  {
        // generate today's password
      return "Password";
  }    
  
  check(password : string) : boolean
  {
        // check the value matches today's password of the day
      return password == this.generate(new Date());
  }
}

Now add a mocha test for it.

nodejscomponent/src/test/passwordOfTheDayTest.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/// <reference path="../../typings/main.d.ts" />
import PasswordOfTheDay = require("../passwordOfTheDay");

describe("Generator", () => {
    var subject : PasswordOfTheDay.PasswordGenerator;

    beforeEach(function () {
        subject = new PasswordOfTheDay.PasswordGenerator();
    });

    describe("#generate", () => {
        it("should generate the password", () => {
            var result : string = subject.generate(new Date(2010, 6, 24));
            if (result !== "Password") {
                throw new Error("Expected 'Password' but was " + result);
            }
        });
    });

    describe("#check", () => {
        it("should return false when the password is incorrect", () => {
            var result : boolean = subject.check("garbage");
            if (result !== false) {
                throw new Error("Expected 'false' but was " + result);
            }
        });
    });

    describe("#check", () => {
        it("should return true when the password is correct", () => {
            var result : boolean = subject.check("Password");
            if (result !== true) {
                throw new Error("Expected 'true' but was " + result);
            }
        });
    });

});

Now compile everything.

$ cd nodejscomponent
$ tsc

You will now find that there is a corresponding javascript file in the lib folder

nodejscomponent/src/passwordOfTheDay.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function checkPotd(password) {
    return new PasswordGenerator().check(password);
}
exports.checkPotd = checkPotd;
var PasswordGenerator = (function () {
    function PasswordGenerator() {
    }
    PasswordGenerator.prototype.generate = function (date) {
        // generate today's password
        return "Password";
    };
    PasswordGenerator.prototype.check = function (password) {
        // check the value matches today's password of the day
        return password == this.generate(new Date());
    };
    return PasswordGenerator;
})();
exports.PasswordGenerator = PasswordGenerator;

And likewise for the mocha test in lib/test. Now to run those tests:

$ npm test

> @0.0.1 pretest /Users/ra/Projects/Coprocess/serverlessPotd/nodejscomponent
> tsc

> @0.0.1 test /Users/ra/Projects/Coprocess/serverlessPotd/nodejscomponent
> mocha ./lib/test

Generator
    #generate
    ✓ should generate the password
    #check
    ✓ should return false when the password is incorrect
    #check
    ✓ should return true when the password is correct

3 passing (10ms)

Nice. Next, modify the main entry point of the component index.js.

nodejscomponent/lib/index.js
1
2
3
4
5
6
7
8
9
10
11
12
// Dependencies
var PasswordOfTheDay = require('./passwordOfTheDay');

module.exports.respond = function(event, cb) {

  var result = PasswordOfTheDay.checkPotd(event.password);
  var response = {
    message: result
  };

  return cb(null, response);
};

Notice how we make use of event.password which is the parameter we configured in part 3 in the s_function.json file.

Let’s deploy!

$ serverless dash deploy
_______                             __
|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
|____   |_____|__|  \___/|_____|__| |__|_____|_____|_____|
|   |   |             The Serverless Application Framework
|       |                           serverless.com, v0.3.1
`-------'

Use the <up>, <down>, <pageup>, <pagedown>, <home>, and <end> keys to navigate.
Press <enter> to select/deselect, or <space> to select/deselect and move down.
Press <ctrl> + <enter> to immediately deploy selected.


Serverless: Select the assets you wish to deploy:
    nodejscomponent - potd - check
    function - nodejscomponent/potd/check
    endpoint - nodejscomponent/potd/check@potd/check~GET
    - - - - -
> Deploy

Serverless: Deploying functions in "dev" to the following regions: eu-west-1  
Serverless: ------------------------  
Serverless: Successfully deployed functions in "dev" to the following regions:   
Serverless: eu-west-1 ------------------------  
Serverless:   nodejscomponent/potd/check: arn:aws:lambda:eu-west-1:962613113552:function:serverlessPotd-nodejscomponent-potd-check:dev  

And lets visit that URI

https://rhnjv4ms2b.execute-api.eu-west-1.amazonaws.com/development/potd/check?password=nonsense
1
2
3
{
    message: false
}
https://rhnjv4ms2b.execute-api.eu-west-1.amazonaws.com/development/potd/check?password=Password
1
2
3
{
    message: true
}

Rock and roll. A working password checker running on Lambda in the Amazon cloud.

Next up - we’ll extend the PasswordGenerator class to pull in a node package and generate a better password.

The source code so far is on GitHub. Note the default .gitignore file skips the admin.env file which contains the (sensitive) AWS keys in it so don’t forget to add your own.

Comments