From 3f0462299ea779a703ffdd7a45919ef1e3e1e406 Mon Sep 17 00:00:00 2001 From: Carlos Fontes Date: Tue, 19 Dec 2023 16:16:19 +0900 Subject: [PATCH] Add secrets to :context map --- README.adoc | 31 +++++++++++++++++++++++++++++-- template/bb/index.clj | 21 ++++++++++++++++++++- template/bb/tests.clj | 5 +++++ 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/README.adoc b/README.adoc index e563e79..b9f99c8 100644 --- a/README.adoc +++ b/README.adoc @@ -19,7 +19,7 @@ Why Babashka for OpenFaaS instead of Clojure proper?: ** 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. -* Babashka is designed for minimal memory usage, allowing you to scale up your single-purpose functions with comparable RAM consumption. +* Babashka is designed for minimal memory usage, allowing you to scale up your single-purpose Functions with comparable RAM consumption. == Prerequisites @@ -103,6 +103,31 @@ my-function: :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"} +---- + In `bb-streaming` language: [source, clojure] ---- @@ -113,7 +138,9 @@ The `event` is extracted from the HTTP payload body, and the function return is === Function tests -To test the code of a Function, a `test` directory in the Function's top-level directory is provided, containing: +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. diff --git a/template/bb/index.clj b/template/bb/index.clj index 3976428..2663fb7 100755 --- a/template/bb/index.clj +++ b/template/bb/index.clj @@ -9,9 +9,27 @@ [ring.middleware.text :refer [wrap-text-body]] [ring.middleware.headers :refer [wrap-lowercase-headers wrap-friendly-headers]] [ring.util.walk :as ring-walk] + [ring.util.string :as ring-string] [compojure.response :as response] + [babashka.fs :as fs] + [clojure.edn :as edn] [handler :as function])) +(defn ->secret [filepath secret-raw] + (let [secret (edn/read-string secret-raw)] + (if (map? secret) + secret + (let [secret-key (-> filepath fs/file-name keyword)] + {secret-key (ring-string/read-string secret-raw)})))) + +(defn ->secrets [] + (when (fs/exists? "/var/openfaas/secrets") + (->> (fs/list-dir "/var/openfaas/secrets") + (map #(let [filepath (-> % str) + secret-raw (slurp filepath)] + (->secret filepath secret-raw))) + (apply merge)))) + (def keywords? #(if (nil? %) true %)) (def fn-arg-cnt #(some-> % meta :arglists first count)) @@ -36,7 +54,8 @@ (defn -main [] (let [env (ring-walk/format-context (System/getenv)) + context (merge env (->secrets)) faas-fn (wrap-arg #'function/handler)] - (run-server (->app faas-fn env) + (run-server (->app faas-fn context) {:port 8082}) @(promise))) diff --git a/template/bb/tests.clj b/template/bb/tests.clj index ef6c159..0689873 100644 --- a/template/bb/tests.clj +++ b/template/bb/tests.clj @@ -33,6 +33,11 @@ "asd" => "asd" :qwer => "qwer") +(eg index/->secret + [_ "{:foo \"bar\"}"] => {:foo "bar"} + ["foo" "bar"] => {:foo "bar"} + ["foo" "[1 \"baz\"]"] => {:foo [1 "baz"]}) + (eg index/keywords? true => true false => false