Slide 1

Slide 1 text

LINKLET FUNCTIONS AS A SERVICE v3

Slide 2

Slide 2 text

FUNCTIONS AS A SERVICE Users Developers
 DevOps XYZ FaaS Container Linklet FaaS Container XYZ FaaS Container Linklet FaaS Container XYZ FaaS Container Linklet FaaS Container API Gateway Container Orchestration BIG PICTURE - FAAS ARCHITECTURE

Slide 3

Slide 3 text

FUNCTIONS AS A SERVICE API Gateway + Integration via Hypertext, Hypermedia or GraphQL API + Auth, SSL and Cache Layer + Rerouting, Mapping and Query Layer + Stateless and Scalable Container
 Orchestration + FaaS-Discovery and Dynamic DNS Registration + Logging, Monitoring and Traceability Layer + Rerouting/Proxy and Scaling Layer + Isolation and Provisioning on OS Level RUNTIME ENVIRONMENT COMPONENTS

Slide 4

Slide 4 text

FUNCTIONS AS A SERVICE Linklet FaaS + Expose simple HTTP Endpoints (Port 80) + Publish/Subscribe Events + Prefer a Stateless Approach + Location Transparent + Configure via Environment-Variables CLI Tooling + Scripting Automation + Templating + Simple and Self-Descriptive DEVELOPER/DEVOP COMPONENTS

Slide 5

Slide 5 text

FUNCTIONS AS A SERVICE Linklet FaaS PRINCIPLES SIMPLICITY PERFORMANCE LIGHTWEIGHT BUILD-IN EXPERIENCE Location Transparency
 Favors Isolated, Stateless, Testable & Configurable Fast and Easy Test-, Run-, Refactor-, Deployment-Cycles) Do one thing and do it good Async I/O and Async Execution Hassle-Free Creation, Maintenance and Deployment

Slide 6

Slide 6 text

FUNCTIONS AS A SERVICE DEVELOPMENT TIME npm install -g linklet linklet -V linklet help

Slide 7

Slide 7 text

FUNCTIONS AS A SERVICE CREATE FAAS linklet help create linklet create my-faas

Slide 8

Slide 8 text

FUNCTIONS AS A SERVICE DEVELOP & RUN LOCALLY cd my-faas npm run dev

Slide 9

Slide 9 text

FUNCTIONS AS A SERVICE DEVELOP cd my-faas vi index.js npm run dev

Slide 10

Slide 10 text

FUNCTIONS AS A SERVICE DEVELOP module.exports = async () => { return { msg: 'A simple FaaS with Linklet!', }; };

Slide 11

Slide 11 text

FUNCTIONS AS A SERVICE MOCHA INTEGRATION TESTS const assert = require('assert'); const fetch = require('node-fetch'); const linklet = require('linklet'); describe('Integration tests', () => { const sut = require('./index'); const server = linklet(sut); let instance = null; before(async () => { instance = await linklet.listen(server, {silent: true}); }); after(() => instance.close()); it('should fetch with status code 200 and JSON response', async () => { const response = await fetch(instance.url, { method: 'POST', body: JSON.stringify({msg: 'Hello World'}) }); assert.equal(response.status, 200); const actual = await response.json(); assert.deepEqual(actual, {msg: 'Hello World'}); }); });

Slide 12

Slide 12 text

FUNCTIONS AS A SERVICE 12 FACTOR APP READY module.exports = () => ({ msg: 'Hello World from Linklet!' }); module.exports.onStart = async () => { console.log('On start - do something async ...'); }; module.exports.onStop = async () => { const exitCode = 0; console.log(`Exit - return ${exitCode}`); return exitCode; }; npm run dev

Slide 13

Slide 13 text

FUNCTIONS AS A SERVICE DEPLOY TO DROPSTACK npm install -g dropstack-cli dropstack login dropstack deploy

Slide 14

Slide 14 text

FUNCTIONS AS A SERVICE DEPLOY AS PURE CONTAINER linklet create --docker my-faas docker build -t mikebild/my-faas:1.0.0 . docker run -it -p 8080:80 mikebild/my-faas:1.0.0 curl http://192.168.99.100:8080 docker push mikebild/my-faas:1.0.0

Slide 15

Slide 15 text

FUNCTIONS AS A SERVICE + Handle Web-Hooks + Implement simple RESTful-APIs + Implement Periodic Tasks + Implement Start Scheduled Tasks + Publish / Subscribe to EventStreams + Spawn/Exec „external“ applications + Perform Redirects + Handle Basic Auth, JWT or OAuth/OAuth2 SOME USE CASES LINKLET FAAS

Slide 16

Slide 16 text

FUNCTIONS AS A SERVICE LINKLET FAAS API module.exports = async () => { return { msg: 'Hello World from Linklet!', } } HANDLE JSON-RESPONSE curl http://localhost:3000

Slide 17

Slide 17 text

FUNCTIONS AS A SERVICE const { json } = require('linklet'); module.exports = async (req, res) => { const data = await json(req); console.log(data); return 'JSON body logged out to console!'; }; HANDLE JSON-REQUESTS curl -X POST http://localhost:3000 \ -H "content-type: application/json" \ -d '{"message": "Hello World"}' LINKLET FAAS API

Slide 18

Slide 18 text

FUNCTIONS AS A SERVICE const { interval } = require('linklet'); let count = 0; console.log(`Executes a function every 5s. Wait ...`); module.exports = interval({ period: 5000 })(() => console.log(`${++count}x executed!`) ); PERIODIC SCHEDULED FUNCTION LINKLET FAAS API

Slide 19

Slide 19 text

FUNCTIONS AS A SERVICE + Composable & Reusable Functions [f(g(z()))] + Pipes & Filters (Middleware) Request/Response Handler + Includes some default Handler-Enhancements: COMPOSE TO HIGHER-ORDER-HANDLER LINKLET FAAS compose // Compose/Pipe functions together withCORS // Enhance with CORS Headers withTime // Enhance with X-Response-Time Header withLog // Enhance with Request/Response StdOut Logging (Text/JSON) withQuery // Enhance with Request-Query Parser withParams // Enhance with URL-Parameter (RegEx-Route) Parser withRedirect // Enhance with Redirect from path (RegEx) to target path withTextBody // Enhance with JSON-Body Parser withJsonBody // Enhance with JSON-Body Parser withInterval // Enhance with periodic time scheduler

Slide 20

Slide 20 text

FUNCTIONS AS A SERVICE + https://github.com/CodeCommission/linklet-higher-handlers + Includes more Handler-Enhancements: MORE HIGHER-ORDER-HANDLER LINKLET FAAS withRoute // Enhance with Request-Method functions withBasicAuth // Enhance with a Basic-Auth Handler withJWTAuth // Enhance with a Basic-Auth Handler withOAuth2 // Enhance with a OAuth2 Handler SOONISH …

Slide 21

Slide 21 text

FUNCTIONS AS A SERVICE const { compose, withLog, withQuery, withParams, withJsonBody } = require('linklet'); module.exports = compose( withLog({ json: true }), withQuery(), withParams({ path: '/items/:id?' }), withJsonBody() )(handler); async function handler(req) { return { body: req.body, params: req.params, hasParamMatch: req.hasParamMatch }; } HANDLER ENHANCEMENTS LINKLET FAAS API curl http://localhost:3000/items/1

Slide 22

Slide 22 text

FUNCTIONS AS A SERVICE const { compose, withQuery, withJsonBody } = require('linklet'); const { withRoute } = require('linklet-higher-handlers'); module.exports = compose( withQuery(), withJsonBody(), withRoute({ path: '/items/:id?', GET: async (req, res) => req.params.id ? { ...req.params, ...req.query } : [{ ...req.query, ...req.params, id: 1 }] }), withRoute({ path: '/rows/:id?', GET: async (req, res) => req.params.id ? { ...req.params, ...req.query } : [{ ...req.query, ...req.params, id: 'one' }] }) )(); MORE HANDLER ENHANCEMENTS LINKLET FAAS API curl http://localhost:3000/items?foo=bar

Slide 23

Slide 23 text

FUNCTIONS AS A SERVICE const {compose, withLog} = require('linklet'); const urlEncodedParse = require('urlencoded-body-parser'); module.exports = compose( withLog({json: true}), withURLEncodedBody() )(handler); async function handler(req) { return { body: req.body }; } function withURLEncodedBody() { return handler => async (req, res) => { req.body = await urlEncodedParse(req); return handler(req, res); }; } CUSTOM ENHANCEMENTS LINKLET FAAS API curl -s -XPOST --data-urlencode "msg=hello world" http://localhost:3000

Slide 24

Slide 24 text

FUNCTIONS AS A SERVICE const {compose, withLog, handle} = require('linklet'); module.exports = compose( withLog({json: true}), withBasicAuth({validate: ({username, password}) => password === 'mypassword' ? {role: 'users'} : null}) )(handler); async function handler(req) { return { user: req.user, body: req.body }; } function withBasicAuth({validate = () => ({})}) { return handler => async (req, res) => { const authHeader = req.headers.authorization; if (!authHeader.includes('Basic')) return handler(req, res); const asString = Buffer.from(authHeader.replace('Basic ', ''), 'base64').toString('ascii'); const [username, password] = asString.split(':'); const validationResult = await validate({username, password}); if (!validationResult) return handle(req, res, null, { statusCode: 401, status: 'Unauthorized', message: 'Unauthorized' }); req.user = {...validationResult, username}; return handler(req, res); }; } CUSTOM ENHANCEMENTS LINKLET FAAS API curl -s -u myusername:mypassword http://localhost:3000 | jq .

Slide 25

Slide 25 text

FUNCTIONS AS A SERVICE THANK YOU! QUESTIONS SOFTWARE ENGINEER
 // FREELANCER // WORKSHOPS @MIKEBILD @MIKEBILD ASK ME ABOUT FAAS & LINKLET

Slide 26

Slide 26 text

FUNCTIONS AS A SERVICE RESOURCES ▸ 12 Factor Apps https://12factor.net ▸ Zero to FaaS Tutorial https://github.com/CodeCommission/linklet/blob/master/docs/zero-to-faas.md ▸ On SpeakerDeck https://speakerdeck.com/mikebild/functions-as-a-service-with-linklet ▸ Linklet News on Twitter https://twitter.com/linklet_run ▸ Linklet Code and Issues on GitHub https://github.com/CodeCommission/linklet