{:deps {com.wagoe/wagoe-config {:mvn/version "1.1.0-rc-1"}}}
Loads resources/conf/<env>/config.edn through Aero and exposes the settings
libraries need. Assembling an Integrant system from those settings is your
application’s job, not this library’s.
{:deps {com.wagoe/wagoe-config {:mvn/version "1.1.0-rc-1"}}}
| Namespace | Purpose |
|---|---|
|
|
| The |
(require '[wagoe.config :as config])
(def cfg (config/load-config)) ; reads conf/<WAG_ENV>/config.edn
(config/db-spec cfg) ; => {:adapter :sqlite :database-path "app.db" ...}
(config/http-config cfg)
(config/logging-config cfg)
load-config resolves the profile from WAG_ENV, accepting both the long and
short spellings — production and prod name the same directory.
| Function | Reads |
|---|---|
| The active database: the first of |
| Port, host and server settings. |
| Application identity and the development tenant. |
| Password and profile rules for the |
| Observability adapters. Each defaults rather than throwing — an absent optional section is normal. |
#secret reads a value through a secret source instead of straight from the
environment:
{:password #secret "DB_PASSWORD" ; the default source, :env
:api-key #secret [:file "stripe-key"] ; /run/secrets/stripe-key, trimmed
:token #secret {:name "API_TOKEN" :default "dev-token"}} ; a default for dev
Two sources are built in. :env reads an environment variable. :file reads
a file in /run/secrets, where Docker and Kubernetes mount secrets; set
WAGOE_SECRETS_DIR to read another directory. Leading and trailing whitespace
is trimmed.
A secret that no source has, or that is blank, fails load-config with a
:configuration-error naming the secret and its source. The value never
appears in an error. The map form takes :name, and optionally :source and
:default; the default is used when the secret is missing. #or does not
supply one: a missing #secret inside it fails like any other.
bb doctor reports every #secret without a default that the :env or
:file source does not have, by name. It cannot ask other sources.
Pass :default-secret-source to make bare names read another source:
(config/load-config {:default-secret-source :file})
Every value a #secret resolved to is redacted by value, whatever key it sits
under: (wagoe.config.secrets/redact x) replaces it with
<secret source:name>. The devtools config page and the REPL (config :section)
helper show placeholders, and Apply on the config page writes the real value
back.
A source is anything implementing ISecretSource. fetch-secret returns the
value, or nil when the source does not have it. Throw when the source cannot
be reached, so boot fails instead of running without the secret. Wagoe ships
no Vault, SOPS or cloud adapter; a Vault one is a few lines:
(ns my.app.vault
(:require [wagoe.config.secrets :as secrets]))
(defrecord VaultSource [client mount]
secrets/ISecretSource
(fetch-secret [_ secret-name]
;; my-vault stands in for your Vault client
(get-in (my-vault/read-secret client (str mount "/" secret-name)) [:data :value])))
(defn source []
(->VaultSource (my-vault/client (System/getenv "VAULT_ADDR")) "secret/my-app"))
Declare it at the top level of config.edn and name it with
#secret [:vault "db-password"]:
{:secret-sources {:vault my.app.vault/source}
:active {:wagoe/postgresql {:password #secret [:vault "db-password"]}}}
The symbol names an ISecretSource, or a function of no arguments that
returns one. The map is read before the rest of the file, so it must be
literal: not inside #profile, and not in an included file. Because the file
declares it, every reader of the config sees it, including the migration and
database CLIs, which run no application code first. A bare aero/read-config
does not: read through config/load-config or config/read-config-resource.
A source under :env or :file replaces the built-in one.
Sources passed to load-config under :secret-sources win over declared ones:
(config/load-config {:secret-sources {:vault (->VaultSource client "secret/my-app")}})
Four published libraries read configuration. Until it was extracted (#412) they did it with
requiring-resolve against a wagoe.config namespace that the monorepo and
wagoe new both happened to generate — a convention nothing declared and
nothing checked, resting in one case on a private var. Anyone assembling a
Wagoe application by hand had no such namespace at all.
Can you improve this documentation? These fine people already did:
thijscreemers & Thijs CreemersEdit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |