Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Functions-as-a-Service with Linklet

Mike Bild
November 19, 2017

Functions-as-a-Service with Linklet

Mike Bild

November 19, 2017
Tweet

More Decks by Mike Bild

Other Decks in Programming

Transcript

  1. 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
  2. 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
  3. 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
  4. 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
  5. FUNCTIONS AS A SERVICE DEVELOP module.exports = async () =>

    { return { msg: 'A simple FaaS with Linklet!', }; };
  6. 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'}); }); });
  7. 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
  8. FUNCTIONS AS A SERVICE DEPLOY TO DROPSTACK npm install -g

    dropstack-cli dropstack login dropstack deploy
  9. 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
  10. 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
  11. FUNCTIONS AS A SERVICE LINKLET FAAS API module.exports = async

    () => { return { msg: 'Hello World from Linklet!', } } HANDLE JSON-RESPONSE curl http://localhost:3000
  12. 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
  13. 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
  14. 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
  15. 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 …
  16. 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
  17. 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
  18. 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
  19. 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 .
  20. FUNCTIONS AS A SERVICE THANK YOU! QUESTIONS SOFTWARE ENGINEER
 //

    FREELANCER // WORKSHOPS @MIKEBILD @MIKEBILD ASK ME ABOUT FAAS & LINKLET
  21. 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