Skip to content

Commit

Permalink
new chapter WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
azat-co committed Dec 24, 2017
1 parent 66d14ac commit 5129bb6
Show file tree
Hide file tree
Showing 52 changed files with 1,599 additions and 1 deletion.
815 changes: 815 additions & 0 deletions chapter15/chapter15.md

Large diffs are not rendered by default.

Binary file added chapter15/media/WhatIsDocker_2_VMs_0-2_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/WhatIsDocker_3_Containers_2_0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/aws-ec2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/aws-ecs-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/aws-ecs-10-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/aws-ecs-10.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/aws-ecs-11.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/aws-ecs-12.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/aws-ecs-13.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/aws-ecs-14.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/aws-ecs-15.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/aws-ecs-16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/aws-ecs-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/aws-ecs-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/aws-ecs-4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/aws-ecs-5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/aws-ecs-6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/aws-ecs-7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/aws-ecs-8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/aws-ecs-9.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/aws-ecs-console-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/aws-ecs-console-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/aws-ecs-console-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/aws-ecs-console-4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/docker-ee.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter15/media/docker-engine-mac.png
Binary file added chapter15/media/docker-images.png
Binary file added chapter15/media/docker-running.png
Binary file added chapter15/media/hello-world.png
Binary file added chapter15/media/node-npm.png
513 changes: 513 additions & 0 deletions chapter16/chapter16.md

Large diffs are not rendered by default.

Binary file added chapter16/media/serverless-1.png
Binary file added chapter16/media/serverless-db.png
Binary file added chapter16/media/serverless-postman.png
Binary file added chapter16/media/serverless-web-console-1.gif
Binary file added chapter16/media/serverless-web-console-2.gif
43 changes: 43 additions & 0 deletions code/ch15/banking-api/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
FROM node:6-alpine


# Some image metadata
LABEL version="1.0"
LABEL description="This is an example of a Node API server with connection to MongoDB. \
More details at https://github.com/azat-co/node-in-production and https://node.university"
#ARG mongodb_container_name
#ARG app_env

# Environment variables
# Add/change/overwrite with docker run --env key=value
# ENV NODE_ENV=$app_env
ENV PORT=3000
# ENV DB_URI="mongodb://${mongodb_container_name}:27017/db-${app_env}"
# agr->env->npm start->pm2-dev or pm2-docker
# User
#USER app
# Mount Volume in docker run command

RUN npm i -g pm2@2.4.6

# Create api directory
RUN mkdir -p /usr/src/api
# From now one we are working in /usr/src/api
WORKDIR /usr/src/api

# Install api dependencies
COPY ./api/package.json .
# Run build if necessary with devDependencies then clean them up
RUN npm i --production

# Copy keys from a secret URL, e.g., S3 bucket or GitHub Gist
# Example adds an image from a remote URL
ADD "https://process.filestackapi.com/ADNupMnWyR7kCWRvm76Laz/resize=height:60/https://www.filepicker.io/api/file/WYqKiG0xQQ65DBnss8nD" ./public/node-university-logo.png

# Copy API source code
COPY ./api/ .

EXPOSE 3000

# The following command will use NODE_ENV to run pm2-docker or pm2-dev
CMD ["npm", "start"]
1 change: 1 addition & 0 deletions code/ch15/banking-api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
see labs/1-dockerized-node.md
20 changes: 20 additions & 0 deletions code/ch15/banking-api/api/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "banking-api",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "sh ./test.sh",
"start": "if [[ ${NODE_ENV} = production ]]; then ./node_modules/.bin/pm2-docker start -i 0 server.js; else ./node_modules/.bin/pm2-dev server.js; fi"
},
"keywords": [],
"author": "Azat Mardan",
"license": "MIT",
"dependencies": {
"errorhandler": "1.5.0",
"express": "4.15.2",
"globalog": "1.0.0",
"monk": "4.0.0",
"pm2": "2.4.6"
}
}
36 changes: 36 additions & 0 deletions code/ch15/banking-api/api/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
require('globalog')
const http = require('http')
const express = require('express')
const errorhandler = require('errorhandler')
const app = express()
const monk = require('monk')

const db = monk(process.env.DB_URI, (err)=>{
if (err) {
error(err)
process.exit(1)
}
})

const accounts = db.get('accounts')

app.use(express.static('public'))
app.use(errorhandler())

app.get('/accounts', (req, res, next)=>{
accounts.find({ }, (err, docs) =>{
if (err) return next(err)
return res.send(docs)
})
})

app.get('/accounts/:accountId/transactions', (req, res)=>{
accounts.findOne({_id: req.params.accountId}, (err, doc) =>{
if (err) return next(err)
return res.send(doc.transactions)
})
})

http.createServer(app).listen(process.env.PORT, ()=>{
log(`Listening on port ${process.env.PORT}`)
})
3 changes: 3 additions & 0 deletions code/ch15/banking-api/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
curl localhost:3000
curl localhost:3000/accounts
curl localhost:3000/accounts/10/transactions
6 changes: 6 additions & 0 deletions code/ch15/docker-node-hello/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FROM node:6-alpine
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY server.js /usr/src/app
EXPOSE 3000
CMD [ "node", "server.js" ]
9 changes: 9 additions & 0 deletions code/ch15/docker-node-hello/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const port = 3000
require('http')
.createServer((req, res) => {
console.log('url:', req.url)
res.end('hello world')
})
.listen(port, (error)=>{
console.log(`server is running on ${port}`)
})
52 changes: 52 additions & 0 deletions code/ch16/serverless/create-api.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
APINAME=api-for-db-api
REGION=us-west-1
NAME=db-api # function name
API_PATH=db-api
# Create an API
aws apigateway create-rest-api --name "${APINAME}" --description "Api for ${NAME}" --region ${REGION}
APIID=$(aws apigateway get-rest-apis --query "items[?name==\`${APINAME}\`].id" --output text --region ${REGION})
echo "API ID: ${APIID}"
PARENTRESOURCEID=$(aws apigateway get-resources --rest-api-id ${APIID} --query "items[?path=='/'].id" --output text --region ${REGION})
echo "Parent resource ID: ${PARENTRESOURCEI}"
# Create a resource as a path, our function will handle many tables (resources) but you can be more specific
aws apigateway create-resource --rest-api-id ${APIID} --parent-id ${PARENTRESOURCEID} --path-part ${API_PATH} --region ${REGION}
RESOURCEID=$(aws apigateway get-resources --rest-api-id ${APIID} --query "items[?path=='/db-api'].id" --output text --region ${REGION})
echo "Resource ID for path ${API_PATH}: ${APIID}"
# Add a method like GET, POST, PUT, etc.; for CRUD we need all methods so just put ANY. Here you can set up auth as well
aws apigateway put-method --rest-api-id ${APIID} --resource-id ${RESOURCEID} --http-method ANY --authorization-type NONE --no-api-key-required --region ${REGION}
LAMBDAARN=$(aws lambda list-functions --query "Functions[?FunctionName==\`${NAME}\`].FunctionArn" --output text --region ${REGION})
echo "Lambda Arn: ${LAMBDAARN}"
# Create integration
# http-method: proxy any http method, but could be only GET, POST, PUT, etc.
# type: proxy everything, other possible options: HTTP and AWS
# integration-http-method: must be POST for method to lambda integration to inkove lambda
aws apigateway put-integration --rest-api-id ${APIID} \
--resource-id ${RESOURCEID} \
--http-method ANY \
--type AWS_PROXY \
--integration-http-method POST \
--uri arn:aws:apigateway:${REGION}:lambda:path/2015-03-31/functions/${LAMBDAARN}/invocations
aws apigateway create-deployment --rest-api-id ${APIID} --stage-name prod --region ${REGION}
APIARN=$(echo ${LAMBDAARN} | sed -e 's/lambda/execute-api/' -e "s/function:${NAME}/${APIID}/")
echo "APIARN: $APIARN"
UUID=$(uuidgen)
# Add permissions to invoke function
# use uuid to make sure we don't get already exists error
# in source-arn, change to prod/GET or prod/POST where pattern is stage/http-method
aws lambda add-permission \
--function-name ${NAME} \
--statement-id apigateway-db-api-any-proxy-${UUID} \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn "${APIARN}/*/*/db-api"
# This is where you can control responses
aws apigateway put-method-response \
--rest-api-id ${APIID} \
--resource-id ${RESOURCEID} \
--http-method ANY \
--status-code 200 \
--response-models "{}" \
--region ${REGION}
echo "Resource URL is https://${APIID}.execute-api.${REGION}.amazonaws.com/prod/db-api/?TableName=messages"
echo "Testing..."
curl "https://${APIID}.execute-api.${REGION}.amazonaws.com/prod/db-api/?TableName=messages"
14 changes: 14 additions & 0 deletions code/ch16/serverless/db-api-test-post.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"httpMethod": "POST",
"queryStringParameters": {
"TableName": "messages"
},
"body": {
"TableName": "messages",
"Item":{
"id":"1",
"author": "Neil Armstrong",
"text": "That is one small step for (a) man, one giant leap for mankind"
}
}
}
6 changes: 6 additions & 0 deletions code/ch16/serverless/db-api-test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"httpMethod": "GET",
"queryStringParameters": {
"TableName": "messages"
}
}
40 changes: 40 additions & 0 deletions code/ch16/serverless/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
'use strict'

console.log('Loading function')
const doc = require('dynamodb-doc')
const dynamo = new doc.DynamoDB()

// All the request info in event
// "handler" is defined on the function creation
exports.handler = (event, context, callback) => {
// Callback to finish response
const done = (err, res) => callback(null, {
statusCode: err ? '400' : '200',
body: err ? err.message : JSON.stringify(res),
headers: {
'Content-Type': 'application/json'
}
})
// To support mock testing, accept object not just strings
if (typeof event.body === 'string') { event.body = JSON.parse(event.body) }
switch (event.httpMethod) {
// Table name and key are in payload
case 'DELETE':
dynamo.deleteItem(event.body, done)
break
// No payload, just a query string param
case 'GET':
dynamo.scan({ TableName: event.queryStringParameters.TableName }, done)
break
// Table name and key are in payload
case 'POST':
dynamo.putItem(event.body, done)
break
// Table name and key are in payload
case 'PUT':
dynamo.updateItem(event.body, done)
break
default:
done(new Error(`Unsupported method "${event.httpMethod}"`))
}
}
15 changes: 15 additions & 0 deletions code/ch16/serverless/lambda-trust-policy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": [
"lambda.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
24 changes: 24 additions & 0 deletions code/ch16/serverless/my-first-fn.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: >-
A simple backend (read/write to DynamoDB) with a RESTful API endpoint using
Amazon API Gateway.
Resources:
myfirstfn:
Type: 'AWS::Serverless::Function'
Properties:
Handler: index.handler
Runtime: nodejs6.10
CodeUri: .
Description: >-
A simple backend (read/write to DynamoDB) with a RESTful API endpoint
using Amazon API Gateway.
MemorySize: 512
Timeout: 10
Role: 'arn:aws:iam::161599702702:role/service-role/my-role-for-fn'
Events:
Api1:
Type: Api
Properties:
Path: /my-first-fn
Method: ANY
1 change: 1 addition & 0 deletions code/ch16/serverless/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"statusCode":"200","body":"{\"Items\":[{\"id\":\"1\",\"text\":\"That is one small step for (a) man, one giant leap for mankind\",\"author\":\"Neil Armstrong\"}],\"Count\":1,\"ScannedCount\":1}","headers":{"Content-Type":"application/json"}}
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ If you'd like to contribute financially towards the effort (or any of my other o
13. [Node HTTP/2 Servers](https://github.com/azat-co/practicalnode/blob/master/chapter13/chapter13.md) [2nd Edition] <-- NEEDS REVIEW! 👀
14. [Asynchronous Code in Node](https://github.com/azat-co/practicalnode/blob/master/chapter14/chapter14.md) [WIP]
15. Node Microservices with Docker and AWS ECS [WIP]
16. Serverless with AWS Lambda [WIP]
16. Serverless Node with AWS Lambda [WIP]

Note: It's work in progress (1st -> 2nd Edition) and the draft will be completed in the end of 2017. See for [2nd Edition] for newer updated content.

Expand Down

0 comments on commit 5129bb6

Please sign in to comment.