Friday, March 9, 2018

How to run Jenkins behind Caddy ?

https://caddyserver.com/ : Caddy is the HTTP/2 web server with automatic HTTPS

https://jenkins.io/ : The leading open source automation server, Jenkins provides hundreds of plugins to support building, deploying and automating any project.

I have installed Jenkins in Ubuntu.
If you want to install in Ubuntu please follow the tutorial below.
http://www.fullstacktechnos.com/2018/03/how-to-install-jenkins-in-ubuntu.html

Install Caddy

1)
praja@ip-****:~/jenkins$ wget https://github.com/mholt/caddy/releases/download/v0.10.10/caddy_v0.10.10_linux_amd64.tar.gz
Saving to: ‘caddy_v0.10.10_linux_amd64.tar.gz’
caddy_v0.10.10_linux_amd64.tar.gz    100%[===================================================================>]   5.36M  1.95MB/s    in 2.7s    
2017-12-28 09:01:36 (1.95 MB/s) - ‘caddy_v0.10.10_linux_amd64.tar.gz’ saved [5617625/5617625]


2)
sudo cp caddy /usr/local/bin/

praja@ip-****:~/jenkins$ ls -lart /usr/local/bin/
total 17168
drwxr-xr-x 10 root root     4096 Nov 21 10:30 ..
drwxr-xr-x  2 root root     4096 Dec 28 09:07 .
-rwxr-xr-x  1 root root 17568553 Dec 28 09:07 caddy

3)
Once the installation is complete, please add the cap_net_bind_service capability to the Caddy binary. This capability will allow the Caddy executable to bind to a port less than 1024.

praja@ip-****:~/jenkins$ sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/caddy

4)
Create the directories where you will store the Caddy configuration file Caddyfile and SSL certificates.
The term “Caddyfile” is a plaintext configuration file used to configure how Caddy works.
This configuration file is very similar in purpose to httpd.conf in Apache or nginx.conf in Nginx.

Run the following commands:

sudo mkdir /etc/caddy
sudo chown -R root:www-data /etc/caddy
sudo mkdir /etc/ssl/caddy
sudo chown -R www-data:root /etc/ssl/caddy
sudo chmod 0770 /etc/ssl/caddy
sudo touch /etc/caddy/Caddyfile
sudo mkdir /var/www
sudo chown www-data: /var/www

5)
caddy file

This will proxy all of the root traffic from port 80 to port 8080 where our Jenkins application is running – while passing the host information that most backend applications would expect when we specify transparent.

praja@ip-****:/etc/caddy$ cat Caddyfile 
jenkins.fullstacktechnos.com {
  gzip
  proxy / :8080 {
    transparent
  }
}

sudo chown www-data:www-data Caddyfile
sudo chmod 444 Caddyfile

praja@ip-****:/etc/caddy$ ls -lart Caddyfile 
-r--r--r-- 1 www-data www-data 72 Dec 28 09:31 Caddyfile

** Change the hostname as per your hosting domain or use localhost if you are testing locally.

6)
Caddy Service File

Run the following commands:

praja@ip-****:~/jenkins/init/linux-systemd$ pwd
/home/praja/jenkins/init/linux-systemd

praja@ip-****:~/jenkins/init/linux-systemd$ ls
caddy.service  README.md

praja@ip-****:~/jenkins/init/linux-systemd$ sudo cp caddy.service /etc/systemd/system/

praja@ip-****:~/jenkins/init/linux-systemd$ sudo chown root:root /etc/systemd/system/caddy.service

praja@ip-****:~/jenkins/init/linux-systemd$ sudo chmod 744 /etc/systemd/system/caddy.service

praja@ip-****:~/jenkins/init/linux-systemd$ sudo systemctl daemon-reload

praja@ip-****:/etc/systemd/system$ sudo systemctl enable caddy.service
Created symlink from /etc/systemd/system/multi-user.target.wants/caddy.service to /etc/systemd/system/caddy.service.


praja@ip-****:/etc/systemd/system$ sudo systemctl status caddy.service
● caddy.service - Caddy HTTP/2 web server
   Loaded: loaded (/etc/systemd/system/caddy.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2017-12-28 09:50:04 UTC; 8s ago
     Docs: https://caddyserver.com/docs
 Main PID: 18390 (caddy)
    Tasks: 7
   Memory: 9.5M
      CPU: 163ms
   CGroup: /system.slice/caddy.service
           └─18390 /usr/local/bin/caddy -log stdout -agree=true -conf=/etc/caddy/Caddyfile -root=/var/tmp

Dec 28 09:50:04 ip-**** caddy[18390]: Your sites will be served over HTTPS automatically using Let's Encrypt.
...

** Now visit jenkins.<your-domain>.com. Jenkins will be served over https.

Caddy is the HTTP/2 web server with automatic HTTPS

How to install Jenkins in Ubuntu ?

https://jenkins.io/ : The leading open source automation server, Jenkins provides hundreds of plugins to support building, deploying and automating any project.

Inside Your Ubuntu box :


root@ip-****:~# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.3 LTS
Release: 16.04

Codename: xenial

Setup: =>

You need to have a JDK and JRE installed.
openjdk-7-jre and openjdk-7-jdk are suggested.

Install Java 8 in Ubuntu:

1)
praja@ip-****:/etc/apt/sources.list.d$ sudo add-apt-repository ppa:webupd8team/java
 Oracle Java (JDK) Installer (automatically downloads and installs Oracle JDK7 / JDK8 / JDK9). There are no actual Java files in this PPA.
Ubuntu 16.10 Yakkety Yak is no longer supported by Canonical (and thus, Launchpad and this PPA). The PPA supports Ubuntu 17.10, 17.04, 16.04, 14.04 and 12.04.
Oracle JDK 9 is now considered stable. There are currently only 64bit builds (no other builds are available for download: http://www.oracle.com/technetwork/java/javase/downloads/index.html )
 More info: https://launchpad.net/~webupd8team/+archive/ubuntu/java
Press [ENTER] to continue or ctrl-c to cancel adding it

OK

praja@ip-****:/etc/apt/sources.list.d$ ls
webupd8team-ubuntu-java-xenial.list
praja@ip-172-31-17-211:/etc/apt/sources.list.d$ cat webupd8team-ubuntu-java-xenial.list 
deb http://ppa.launchpad.net/webupd8team/java/ubuntu xenial main
# deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu xenial main


2)
praja@ip-****:~/jenkins$ sudo apt-get update
Get:1 http://ppa.launchpad.net/webupd8team/java/ubuntu xenial InRelease [17.5 kB]
Hit:2 http://ap-south-1.ec2.archive.ubuntu.com/ubuntu xenial InRelease          
Get:3 http://ap-south-1.ec2.archive.ubuntu.com/ubuntu xenial-updates InRelease [102 kB]                   
Hit:4 http://security.ubuntu.com/ubuntu xenial-security InRelease                   
Get:5 http://ppa.launchpad.net/webupd8team/java/ubuntu xenial/main amd64 Packages [2,912 B]                   
Get:6 http://ppa.launchpad.net/webupd8team/java/ubuntu xenial/main Translation-en [1,260 B]                
Get:7 http://ap-south-1.ec2.archive.ubuntu.com/ubuntu xenial-backports InRelease [102 kB]
Fetched 226 kB in 0s (239 kB/s)
Reading package lists... Done

3)

praja@ip-****:~/jenkins$ sudo apt-get install oracle-java8-installer
Reading package lists... Done
Building dependency tree       

Reading state information... Done 

4)


praja@ip-****:~/jenkins$ javac -version
javac 1.8.0_151


Oracle JDK 8 installed

Optional:

set JAVA_HOME

praja@ip-****:/usr/lib$ sudo update-alternatives --config java
There is 1 choice for the alternative java (providing /usr/bin/java).

  Selection    Path                                     Priority   Status
------------------------------------------------------------
  0            /usr/lib/jvm/java-8-oracle/jre/bin/java   1081      auto mode
* 1            /usr/lib/jvm/java-8-oracle/jre/bin/java   1081      manual mode

Open => <sudo nano /etc/environment>
Update java home path.

PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"
JAVA_HOME="/usr/lib/jvm/java-8-oracle"

praja@ip-****:/usr/lib$ source /etc/environment
praja@ip-****:/usr/lib$ echo $JAVA_HOME

/usr/lib/jvm/java-8-oracle


Install Jenkins :


1)
praja@****:~/jenkins$ wget -q -O - https://pkg.jenkins.io/debian/jenkins-ci.org.key | sudo apt-key add -

OK

2)
praja@ip-****:~/jenkins$ sudo sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'


3)
praja@ip-****:~/jenkins$ sudo apt-get update
Hit:1 http://ppa.launchpad.net/webupd8team/java/ubuntu xenial InRelease
Hit:2 http://security.ubuntu.com/ubuntu xenial-security InRelease        
Hit:3 http://ap-south-1.ec2.archive.ubuntu.com/ubuntu xenial InRelease            
Get:4 http://ap-south-1.ec2.archive.ubuntu.com/ubuntu xenial-updates InRelease [102 kB]           
Ign:5 http://pkg.jenkins.io/debian-stable binary/ InRelease                                                 
Get:6 http://pkg.jenkins.io/debian-stable binary/ Release [2,042 B]               
Get:7 http://ap-south-1.ec2.archive.ubuntu.com/ubuntu xenial-backports InRelease [102 kB]
Get:8 http://pkg.jenkins.io/debian-stable binary/ Release.gpg [181 B]
Get:9 http://pkg.jenkins.io/debian-stable binary/ Packages [12.5 kB]
Fetched 219 kB in 1s (181 kB/s)
Reading package lists... Done


4)
praja@ip-****:~/jenkins$ sudo apt-get install jenkins
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Processing triggers for ureadahead (0.100.0-19) ...



Check Service -

praja@ip-****:~/jenkins$ sudo /etc/init.d/jenkins status
● jenkins.service - LSB: Start Jenkins at boot time
   Loaded: loaded (/etc/init.d/jenkins; bad; vendor preset: enabled)
   Active: active (exited) since Thu 2017-12-28 06:48:39 UTC; 3min 14s ago
     Docs: man:systemd-sysv-generator(8)
    Tasks: 0
   Memory: 0B
      CPU: 0

Dec 28 06:48:38 ip-172-31-17-211 systemd[1]: Starting LSB: Start Jenkins at boot time...
Dec 28 06:48:38 ip-172-31-17-211 jenkins[17388]:  * Starting Jenkins Automation Server jenkins
Dec 28 06:48:38 ip-172-31-17-211 su[17409]: Successful su for jenkins by root
Dec 28 06:48:38 ip-172-31-17-211 su[17409]: + ??? root:jenkins
Dec 28 06:48:38 ip-172-31-17-211 su[17409]: pam_unix(su:session): session opened for user jenkins by (uid=0)
Dec 28 06:48:39 ip-172-31-17-211 jenkins[17388]:    ...done.

Dec 28 06:48:39 ip-172-31-17-211 systemd[1]: Started LSB: Start Jenkins at boot time.

** jenkins user is created to run the service


praja@ip-****:~/jenkins$ id jenkins
uid=112(jenkins) gid=116(jenkins) groups=116(jenkins)

Log file location -

praja@ip-172-31-17-211:~/jenkins$ tail /var/log/jenkins/jenkins.log 
Dec 28, 2017 6:48:59 AM hudson.model.DownloadService$Downloadable load
INFO: Obtained the updated data file for hudson.tasks.Maven.MavenInstaller


Config file -

praja@ip-172-31-17-211:~/jenkins$ cat /etc/default/jenkins


For More Info:

Wednesday, December 6, 2017

Express app using firebase HTTP Trigger

if you want to know about firebase and firebase cloud functions before jumping into this article, please visit the following links.

1) Firebase RealTime Database
2) Firebase Authentication Service
3) Why we need cloud functions
4) Introduction to cloud functions

HTTP Trigger:
It will be invoked based on the rest call from the client. You can perform the pre validation of data before writing into db, connect to third party services like git, slack etc.

Express App using HTTP Trigger:

Please checkout the following projects from github if you want to play around.

Web Client:
1) https://github.com/fullstacktechnos/firebase-frontend

Firebase Functions:
2) https://github.com/fullstacktechnos/firebase-functions


* Following code sends a message from the web app using http post.

firebase.auth().currentUser.getToken().then(function(token) {
                    let restEndPoint = 'https://us-central1-testapp.cloudfunctions.net/app/writemsg';
                    console.log('Sending request to', restEndPoint, 'with ID token in Authorization header.');
                    var req = new XMLHttpRequest();
                    req.onload = function() {
                        console.log(req.responseText);
                    }.bind(this);
                    req.onerror = function() {
                        console.log('There was an error');
                    }.bind(this);
                    req.open('POST', restEndPoint, true);
                    req.setRequestHeader('Authorization', 'Bearer ' + token);
                    req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
                    req.send("message="+content);
                }.bind(this))
                .catch(function(err) { console.log('No token found')});


- In the above code we are passing a message using http post request to the rest endpoint 'writemsg'.
- User is sending the message after he/she login. So we can pass the token in Authorization header for verification in backend.
- https://us-central1-testapp.cloudfunctions.net/app/ is the rest api base url. You can find it in firebase project under Functions or in the console at the time of deployment.


* Following cloud function code

- creates an express app
- invoke the http trigger when the rest api is called
- validate the user token
- go to the http post handler
- validate the input data and write into the realtime database.


const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

//http trigger
const express = require('express');
const cookieParser = require('cookie-parser')();
const cors = require('cors')({ origin: true });
const app = express();

const validateFirebaseIdToken = (req, res, next) => {
  console.log('Check if request is authorized with Firebase ID token');

  if ((!req.headers.authorization || !req.headers.authorization.startsWith('Bearer ')) &&
    !req.cookies.__session) {
    console.error('No Firebase ID token was passed as a Bearer token');
    res.status(403).send('Unauthorized');
    return;
  }

  let idToken;
  if (req.headers.authorization && req.headers.authorization.startsWith('Bearer ')) {
    console.log('Found "Authorization" header');
    // Read the ID Token from the Authorization header.
    idToken = req.headers.authorization.split('Bearer ')[1];
  } else {
    console.log('Found "__session" cookie');
    // Read the ID Token from cookie.
    idToken = req.cookies.__session;
  }

  admin.auth().verifyIdToken(idToken).then(decodedIdToken => {
    console.log('ID Token correctly decoded', decodedIdToken);
    req.user = decodedIdToken;
    next();
  }).catch(error => {
    console.error('Error while verifying Firebase ID token:', error);
    res.status(403).send('Unauthorized');
  });
};

app.use(cors);
app.use(cookieParser);
app.use(validateFirebaseIdToken);

app.post('/writemsg', (req, res) => {
  if (req.body.message === undefined) {
    res.status(400).send('No message defined!');
  } else {
    console.log('input data :: ' + req.body.message);
    
    //Insert message to Realtime Database node "messages"
    admin.database().ref('messages').push({
      type: 'Rest',
      description: req.body.message
    })
    .then(() => res.status(200).send('Msg updated Successfully'))
    .catch( error => res.status(401).send('Not able to update the msg'))
  }
});

exports.app = functions.https.onRequest(app);

* Note:
To know more please visit the following link.
https://firebase.google.com/docs/functions/http-events

Useful Reads:
http://www.fullstacktechnos.com/2017/12/firebase-realtime-database-trigger.html
http://www.fullstacktechnos.com/2017/12/firebase-authentication-trigger.html

Firebase Realtime Database Trigger

if you want to know about firebase and firebase cloud functions before jumping into this article, please visit the following links.

1) Firebase RealTime Database
2) Firebase Authentication Service
3) Why we need cloud functions
4) Introduction to cloud functions

Realtime Database Trigger :

We can invoke realtime db trigger in response to any database events from the client.
From your web or mobile app when ever there is a database event, cloud realtime db trigger can be invoked. It is a post db operation.

For ex: User sends a msg called "stupid message" from the app to write into message node. If a db trigger is attached to the message node, it can listen to the onWrite() event, read the incoming msg, change to "Wonderful message" and stores back.

Please checkout the following projects from github if you want to play around.

Web Client:
1) https://github.com/fullstacktechnos/firebase-frontend

Firebase Functions:
2) https://github.com/fullstacktechnos/firebase-functions


** Following function from the web client will write a message to firebase realtime database having node "messages"

var ref = firebase.database().ref('messages');
                var data = {
                    type: 'Generic',
                    description: 'Stupid msg'
                }
                ref.push(data);



** Following cloud function in firebase will be invoked, sanitized the data and save it back.

//db trigger
function sanitize(msgDescription) {
  var sanitisedContent = msgDescription;
  sanitisedContent = sanitisedContent.replace(/\bstupid\b/ig, "wonderful");
  return sanitisedContent;
}
exports.sanitizeMessage = functions.database.ref('/messages/{mid}').onWrite(event => {
  const msg = event.data.val();

  //prevent calling same trigger again.
  if (msg.sanitized) {
    return;
  }
  console.log("Sanitizing new message : " + event.params.mid);
  console.log(msg);
  msg.sanitized = true;

  msg.description = sanitize(msg.description);
  return event.data.ref.set(msg);
})

*Please check the github project mention above for the working copy.

- The above db trigger (sanitizeMessage) will be invoked every time there is a new message write.
- It reads the incoming message after the message written into the db(as db triggers are post operation trigger), check the word "stupid" in it, if present change it to "wonderful" and writes back.

- If we write back to the same node again the same db trigger will be invoked which will continue for infinite loop. So to avoid the infinite looping we are checking at the beginning if the message is sanitized. If it is then we don't need to proceed.

- Its always better to return a promise from the trigger as mentioned in the last line of "sanitizeMessage" function. This way google function won't be killed until the promise is either resolved or rejected. So we can wait for the db operation to complete.

Event Handlers:
onWrite(), which triggers when data is created, destroyed, or changed in the Realtime Database.
onCreate(), which triggers when new data is created in the Realtime Database.
onUpdate(), which triggers when data is updated in the Realtime Database.
onDelete(), which triggers when data is deleted from the Realtime Database.

**Note:
For more information please visit:
https://firebase.google.com/docs/functions/database-events

Firebase Authentication Trigger

If you want to familiar with what is firebase and firebase cloud functions before jumping into this article please visit the following links.

1) Firebase RealTime Database
2) Firebase Authentication Service
3) Why we need cloud functions
4) Introduction to cloud functions

We can trigger auth cloud functions that can run in response to user creation or deletion.

For ex: From your web or mobile app when ever there is a user signup you can invoke your auth trigger in the backend, which is a firebase cloud function, that will send a welcome email to the user. You don't need to duplicate sending welcome email code in your web and mobile apps. Common business logic can move to the server side.

Please checkout the following projects from github if you want to play around.

Web Client:
1) https://github.com/fullstacktechnos/firebase-frontend

Firebase Functions:
2) https://github.com/fullstacktechnos/firebase-functions

First one is a frontend web app using which you can send request to your firebase backend.
Second one is your firebase cloud functions which will be triggered in specific conditions.

If you have issues setting up cloud function project please check the link Introduction to cloud functions above


** Following function from the web client will send a user registration request to firebase:


firebase.auth().signInWithEmailAndPassword(email, password)
                .then(function(result) {
                    console.log(result);
                })
                .catch(function(error) {
                    console.log('signIn error', error);
                })



** Following cloud function in firebase will be invoked and performed few extra work and save it.


//Auth trigger
exports.createUserAccount = functions.auth.user().onCreate(event => {
  const uid = event.data.uid;
  const email = event.data.email;
  const photoUrl = event.data.photoUrl || 'http://lorempixel.com/400/200/';
  const newUserRef = ref.child(`/users/${uid}`);

  return newUserRef.set({
    photoUrl: photoUrl,
    email: email
  })
})


- The above auth trigger will be invoked every time there is a new user creation in firebase.
- In the above function you can see that its checking for photo url which should come as a input from client, if it is not present then trigger is adding a default photo url.
- Once the data is ready trigger is writing to the child node(/users/useruid/) of user pointing to user id.
- Firebase stores User data in its own place which we cant change but we can store our own data into Real time database.

**Note:
For more information please visit:
https://firebase.google.com/docs/functions/auth-events

Useful Read :
http://www.fullstacktechnos.com/2017/12/firebase-realtime-database-trigger.html
http://www.fullstacktechnos.com/2017/12/express-app-using-firebase-http-trigger.html

Monday, November 20, 2017

Rest API using AWS Lamda, Serverless and Nodejs

Prerequisite

1) AWS Lamda - If you are not aware of lamda function, please visit the following link.

http://www.fullstacktechnos.com/2017/11/what-is-aws-lamda.html

2) Serverless Framework - I am using serverless to deploy my aws infrastructure. Please visit the following article to setup the serverless in your local box.
You don't need to create any project though.

http://www.fullstacktechnos.com/2017/11/create-your-first-nodejs-lamda-function.html

Setup

If you have configured serverless for aws successfully then verify the installations by typing the command in the terminal. Your version number may not match mine.

$node -v
v6.11.3
$sls -v
1.18.1
$aws --version
aws-cli/1.11.127 Python/3.6.2 Darwin/17.2.0 botocore/1.5.90
$cat ~/.aws/credentials 
[default]
aws_access_key_id=*******************
aws_secret_access_key=*****************


I have already created the sample nodejs lamda project with serverless. Please find the following  github link.


https://github.com/fullstacktechnos/serverless-lamda-test


Checkout the code.


git clone https://github.com/fullstacktechnos/serverless-lamda-test.git


handler.js : (lamda code goes here)

'use strict';

module.exports.helloWorld = (event, context, callback) => {
  const response = {
    statusCode: 200,
    headers: {
      'Access-Control-Allow-Origin': '*', // Required for CORS support to work
    },
    body: JSON.stringify({
      message: 'Go Serverless v1.0! Your function executed successfully!',
      input: event,
    }),
  };

  callback(null, response);
};


serverless.yml:


# Welcome to serverless. Read the docs
# https://serverless.com/framework/docs/

# Serverless.yml is the configuration the CLI
# uses to deploy your code to your provider of choice

# The `service` block is the name of the service
service: serverless-hello-world

# The `provider` block defines where your service will be deployed
provider:
  name: aws
  runtime: nodejs6.10

# The `functions` block defines what code to deploy
functions:
  helloWorld:
    handler: handler.helloWorld
    # The `events` block defines how to trigger the handler.helloWorld code
    events:
      - http:
          path: hello-world
          method: get
          cors: true


To define a rest endpoint we have to mention the method (get or post) and path inside events -> http.
cors: true will enable the cross.

To know more about it please visit the serverless.com (https://serverless.com/framework/docs/providers/aws/guide/events/)


If you want to push the same code to your aws environment then run the following command.


$sls deploy

Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip file to S3 (967 B)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
..............
Serverless: Stack update finished...
Service Information
service: serverless-hello-world
stage: dev
region: us-east-1
api keys:
  None
endpoints:
  GET - https://l2krwp3ete.execute-api.us-east-1.amazonaws.com/dev/hello-world
functions:
  helloWorld: serverless-hello-world-dev-helloWorld


- Go to the browser and enter the GET endpoint URL. Your's will be different than mine. Mine is for testing purpose. It wont be available for you.

- You can see the event object that lamda return as a response in the browser.


* For more information please visit the following link.
https://aws.amazon.com/lambda/details/
https://serverless.com/framework/docs/providers/aws/guide/quick-start/


Create your first nodejs lamda function using serverless framework

AWS Lamda :

If you are not aware of lamda function, please visit the following link to know about it.

http://www.fullstacktechnos.com/2017/11/what-is-aws-lamda.html


Serverless Framework :

https://serverless.com/

Serverless framework is the toolkit for deploying and operating serverless architectures. The framework can manage deploying infrastructure and code to AWS, Google Cloud Platofrm, Microsoft Azure and IBM Openwhisk.
If you want to launch your first lamda function to cloud then this framework will definitely help you.

Serverless Setup for Lamda

1) Install nodejs: (Node.js v6.5.0 or later is required)


$node -v
v6.11.3


2) Install serverless framework CLI.


npm install -g serverless

$serverless -v
1.18.1


3) Install AWS-CLI.


$aws --version
aws-cli/1.11.127 Python/3.6.2 Darwin/17.2.0 botocore/1.5.90

If you need any help to install AWS-CLI please refer the following article.
http://www.fullstacktechnos.com/2017/07/how-to-install-aws-cli-in-mac.html


3) Create AWS Admin user and get the keys.

To manage the aws resource serverless needs AWS account credentials which has the required roles and permissions to manage the aws infrastructure. If you don't have a AWS account create a free one.

- Create an user having administrator access (which i think easy to test) and get the access key and secret key for that user.

Note:
Please follow the following article to know how to create aws user and how to add specific roles.

http://www.fullstacktechnos.com/2017/07/how-to-push-local-file-to-s3-using-aws.html

Don't worry about the name of the article. It gives you the information about how to add an aws user,  specific role and how to access the keys.


4) Configure credentials using aws-cli.

Go to the console and type


$ aws configure
AWS Access Key ID [****************]:
AWS Secret Access Key [****************]:
Default region name [None]:
Default output format [None]:


5) Create a nodejs project using npm

Go to the console, create folder called test-lamda, go inside and type "npm init". Follow the instructions.


6) Create a lamda function using serverless

Go to console, Inside your nodejs project folder type



$serverless create --template aws-nodejs

Serverless: Generating boilerplate...
 _______                             __
|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
|____   |_____|__|  \___/|_____|__| |__|_____|_____|_____|
|   |   |             The Serverless Application Framework
|       |                           serverless.com, v1.18.1
 -------'

Serverless: Successfully generated boilerplate for template: "aws-nodejs"

Serverless: NOTE: Please update the "service" property in serverless.yml with your service name



Please check the handler.js and serverless.yml file.


handler.js :

It has a single lamda function called "hello" which has 3 input parameters i)event ii) context iii)callback

event contains the req object that has information about path, httpMethod, headers etc.
This basic lamda function when invoked will create a response object and send it back.


serverless.yml:

This file has all the aws infrastructure details that serverless needs to configure when enabled. You can see only service and provider is enabled. You can enable any other features as per requirement



7) Deploy your lamda function to AWS

Go to console, Inside your nodejs project folder type.


$serverless deploy

Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
.....
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip file to S3 (1.29 KB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
...............
Serverless: Stack update finished...
Service Information
service: test-lamda-serverless
stage: dev
region: us-east-1
stack: test-lamda-serverless-dev
api keys:
  None
endpoints:
  None
functions:
  hello: test-lamda-serverless-dev-hello



8) Invoke your lamda function


$sls invoke --function hello
{
    "statusCode": 200,
    "body": "{\"message\":\"Go Serverless v1.0! Your function executed successfully!\",\"input\":{}}"

}

* sls is short form of serverless


9) Check the logs.


$sls logs -f hello -t

START RequestId: 3cc05fc9-cee9-11e8-a9ca-f960d9ae7ppp Version: $LATEST
END RequestId: 3cc05fc9-cee9-11e8-a9ca-f960d9ae7ppp

REPORT RequestId: 3cc05fc9-cee9-11e8-a9ca-f960d9ae7ppp  Duration: 0.83 ms       Billed Duration: 100 ms         Memory Size: 1024 MB    Max Memory Used: 20 MB

* f is short form of function, hello is the function name

Summary:

1) nodejs v6.5.0 or later
2) npm install -g serverless
3) aws configure <Configure aws admin account access key and secret>
4) npm init
5) serverless create --template aws-nodejs
6) serverless deploy
7) sls invoke --function hello


* For more details on serverless framework for aws please visit following links:

https://serverless.com/framework/docs/providers/aws/guide/quick-start/
https://serverless.com/framework/docs/providers/aws/guide/credentials/
https://serverless.com/framework/docs/providers/aws/examples/hello-world/node/