An open API service indexing awesome lists of open source software.

https://github.com/ccfontes/faas-bb

An OpenFaaS template for writing Functions in Babashka.
https://github.com/ccfontes/faas-bb

babashka bb clojure openfaas

Last synced: about 2 months ago
JSON representation

An OpenFaaS template for writing Functions in Babashka.

Awesome Lists containing this project

README

          

:url-proj: https://github.com/ccfontes/faas-bb
:img-ci-tests-status: {url-proj}/actions/workflows/faas_fn_build_invoke.yml/badge.svg
:img-ci-hadolint-status: {url-proj}/actions/workflows/hadolint.yml/badge.svg
:img-ci-clj-kondo-status: {url-proj}/actions/workflows/clj-kondo.yml/badge.svg
:url-ci-status-tests: "{url-proj}/actions/workflows/faas_fn_build_invoke.yml"
:url-ci-status-hadolint: "{url-proj}/actions/workflows/hadolint.yml"
:url-ci-status-clj-kondo: "{url-proj}/actions/workflows/clj-kondo.yml"
:img-license: https://img.shields.io/badge/license-MIT-black.svg

= faas-bb image:{img-ci-tests-status}[link={url-ci-status-tests}] image:{img-ci-hadolint-status}[link={url-ci-status-hadolint}] image:{img-ci-clj-kondo-status}[link={url-ci-status-clj-kondo}] image:{img-license}[link=LICENSE]

An https://github.com/openfaas[OpenFaaS] template for writing Functions in https://babashka.org[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

* https://docs.openfaas.com/cli/install/[OpenFaaS CLI]: makes the `faas-cli` command available.

*Optional for REPL support*

* https://github.com/babashka/babashka#installation[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*:
[source, bash]
----
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:
[source, bash]
----
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:
[source, clojure]
----
(defn handler [{:keys [headers body context] :as event}]
...)
----
`event` is a map containing `:headers`, `:body` and `:context` keys.

`:headers` contains headers, as such:
[source, clojure]
----
{: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`:
[source, 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:
[source, yml]
----
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:
[source, clojure]
----
{: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:
[source, yml]
----
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 }`, with `` parsed as a Clojure data structure other than a map.

Following up from the definition of `my-function` above, we define the following secrets:
[source, bash]
----
echo 'bar' | faas-cli secret create foo
echo '{:spam "eggs"}' | faas-cli secret create baz
----
becomes this in the `:context` map:
[source, clojure]
----
{: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`:
[source, yml]
----
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 https://github.com/babashka/babashka#installation[Babashka installed] in your local.

In the root directory of your Function run:
[source, bash]
----
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:

[source, bash]
----
rlwrap bb -cp .
----

== link:examples[Function examples]

See the link:examples[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 link:.github/workflows/faas_fn_build_invoke.yml[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 https://github.com/babashka/babashka#installation[installed].

[source, bash]
----
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

- https://www.mailbriefly.com[MailBriefly.com] is using `faas-bb` on all its microservices (with joy).

== 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 https://github.com/ring-clojure/ring-defaults/blob/master/src/ring/middleware/defaults.clj[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 https://github.com/ring-clojure[ring] to work with Babashka, originally authored by James Reeves and contributors, and used under the MIT license: link:template/bb/lib/ring/middleware/json.clj[ring.middleware.json], link:template/bb/lib/ring/util/io.clj[ring.util.io], link:template/bb/lib/ring/util/mime_type.clj[ring.util.mime-type], link:template/bb/lib/ring/util/parsing.clj[ring.util.parsing], link:template/bb/lib/ring/util/response.clj[ring.util.response], link:template/bb/lib/ring/util/time.clj[ring.util.time].

== link:LICENSE[License]

Copyright (c) 2023 Carlos da Cunha Fontes.

This project is licensed under the MIT License. See link:LICENSE[LICENSE] for details.