Skip to content

Latest commit

 

History

History
217 lines (160 loc) · 8.44 KB

README.adoc

File metadata and controls

217 lines (160 loc) · 8.44 KB

faas-bb badge badge badge license MIT black

An OpenFaaS template for writing Functions in Babashka (v1.3.187 SNAPSHOT).

Why

The ergonomics of Babashka, combined with the simplicity of Clojure, make it a great choice for writing Functions in OpenFaaS, from single purpose Functions, to frontend facing REST APIs, to serving hiccup backed HTML pages - delivered with a back-to-back joyful development experience.

Babashka is designed for minimal memory usage, allowing you to scale up your narrow-purposed Functions with comparable RAM consumption.

Babashka scripts run immediately, ensuring:

  • that Function cold start times are kept to a minimum.

  • a rapid development feedback loop.

  • a simple REPL workflow - just start everything all over again, it’s fast.

Prerequisites

Optional for REPL support

  • Babashka: makes the bb command available.

  • rlwrap: readline support, here for Babashka REPL.

Usage

Pull OpenFaaS template

To create Babashka Functions with this template, use the following command once:

faas-cli template pull https://github.com/ccfontes/faas-bb

If you ever need to update the template, simply run the command above with the --overwrite flag.

Create a Babashka Function

Create Babashka Functions as with the following command example:

faas-cli new --lang bb my-bb-function

A new project is created for a function defined as my-bb-function. It will contain:

  • a handler namespace that is required for the template to work properly. This namespace needs to have a top-level handler function with 0 or 1 arguments.

  • a bb.edn file where ship dependencies can be added. Remove this file if you don’t need to add any dependencies or run a REPL without passing the classpath explicitly.

  • a test directory containing:

    • run_tests.clj with the namespace that will be used to run the tests. You can use any test library and test runner you like.

    • a bb.edn file where test dependencies can be added. Remove this file if you don’t need to add any dependencies.

Defining Function handler

In bb language:

(defn handler [{:keys [headers body context] :as event}]
  ...)

event is a map containing :headers, :body and :context keys.

:headers contains headers, as such:

{:content-type "application/json"}

:body is the payload body. When passing a JSON object payload and using bb language, the payload will be automatically parsed as a Clojure map with keyword keys. There are cases where it’s preferable to have string keys in the payload body, and it’s possible to support them by setting keywords: false in the Function in stack.yml:

my-function:
  lang: bb
  handler: ./anything/my-function
  image: ${DOCKER_REGISTRY_IMG_ORG_PATH}/my-function
  environment:
    keywords: false

:context contains environment variables. Additional environment variables can be defined in the stack.yml file, as such:

my-function:
  lang: bb
  handler: ./anything/my-function
  image: ${DOCKER_REGISTRY_IMG_ORG_PATH}/my-function
  environment:
    MY_ENV1: foo
    MY_ENV2: 2

:context will contain:

 {:my-env1 "foo"
  :my-env2 2}

If you declare secrets in the stack.yml file, these will be available in :context map as well. Let’s start with an example:

my-function:
  lang: bb
  handler: ./anything/my-function
  image: ${DOCKER_REGISTRY_IMG_ORG_PATH}/my-function
  secrets:
    - foo
    - baz

A secret value that is an EDN string, when internally parsed as a Clojure map, will have its content spliced into the :context map. Otherwise, the secret will be available in the :context map as {:secret-name <secret-value>}, with <secret-value> parsed as a Clojure data structure other than a map.

Following up from the definition of my-function above, we define the following secrets:

echo 'bar' | faas-cli secret create foo
echo '{:spam "eggs"}' | faas-cli secret create baz

becomes this in the :context map:

{:foo "bar" :spam "eggs"}

Function tests

Tests for your Function run when you build the Function image (faas-cli build).

A test directory in the Function’s top-level directory is provided, containing:

  • run_tests.clj, with the namespace that will be used to run the tests. You can use any test library and test runner you like.

  • a bb.edn file where test dependencies can be added. Remove this file if you don’t need to add any dependencies.

To disable running existing tests, set the TEST build time argument to false:

my-function:
  lang: bb
  handler: ./anything/my-function
  image: ${DOCKER_REGISTRY_IMG_ORG_PATH}/my-function
   build_args:
      TEST: false

If you don’t plan on testing, you can remove the test directory altogether.

Existing test files are removed from the final Docker image used to run the Function in OpenFaaS.

Spin up a REPL

Spin up a REPL in the context of your Function project.

Note
You’ll need to have Babashka installed in your local.

In the root directory of your Function run:

rlwrap bb

Spins up a REPL with readline support.

If you remove bb.edn with just {:paths ["."]} in it, the Function will still work, but then you will need to explicitly pass the classpath when spinning up a REPL:

rlwrap bb -cp .

See the examples directory to find a fully working set of OpenFaaS Functions written in Babashka.

faas-bb tests

CI tests

All tests run in CI with Github Actions. Some commands can be found in a Github Actions workflow to help you with testing your changes before pushing them to a topic branch.

Unit tests

Run locally the unit tests for the bb template.

The requirement is that babashka (bb) is installed.

cd template/bb
bb --config tests.edn tests.clj

tests.clj is included with the template so you can test any changes you make to the template before using it.

Projects using faas-bb

Contributing

Contributions are welcome! If you find a bug or have an idea for a new feature, please open an issue or submit a pull request.

The template may benefit from some common middleware functions, such as those offered in the ring-defaults library. Users are welcome to recommend integrating any middleware they think would be useful for handling common web application needs.

Third party code

The following files are derived from ring to work with Babashka, originally authored by James Reeves and contributors, and used under the MIT license: ring.middleware.json, ring.util.io, ring.util.mime-type, ring.util.parsing, ring.util.response, ring.util.time.

Copyright (c) 2023 Carlos da Cunha Fontes.

This project is licensed under the MIT License. See LICENSE for details.