Kungfuig

Intro
Live config supporting many different backends.
Kungfuig (pronounced: [ˌkʌŋˈfig]) provides an easy way to plug live configuration into everything.
It provides backends for env and system and supports custom backends.
Installation
def deps do
[
{:kungfuig, "~> 0.1"}
]
endUsing
Kungfuig is the easy way to read the external configuration from sources that are not controlled by the application using it, such as Redis, or Database.
Here is the example of backend implementation for the config read from external MySQL.
defmodule MyApp.Kungfuig.MySQL do
@moduledoc false
use Kungfuig.Backend
@impl Kungfuig.Backend
def get(_meta) do
with {:ok, host} <- System.fetch_env("MYSQL_HOST"),
{:ok, db} <- System.fetch_env("MYSQL_DB"),
{:ok, user} <- System.fetch_env("MYSQL_USER"),
{:ok, pass} <- System.fetch_env("MYSQL_PASS"),
{:ok, pid} when is_pid(pid) <-
MyXQL.start_link(hostname: host, database: db, username: user, password: pass),
result <- MyXQL.query!(pid, "SELECT * FROM some_table") do
GenServer.stop(pid)
result =
result.rows
|> Flow.from_enumerable()
|> Flow.map(fn [_, field1, field2, _, _] -> {field1, field2} end)
|> Flow.partition(key: &elem(&1, 0))
|> Flow.reduce(fn -> %{} end, fn {field1, field2}, acc ->
Map.update(
acc,
String.to_existing_atom(field1),
[field2],
&[field2 | &1]
)
end)
Logger.info("Loaded #{Enum.count(result)} values from " <> host)
{:ok, result}
else
:error ->
Logger.warn("Skipped reconfig, one of MYSQL_{HOST,DB,USER,PASS} is missing")
:ok
error ->
Logger.error("Reconfiguring failed. Error: " <> inspect(error))
{:error, error}
end
end
endTesting
Simply implement a stub returning an expected config and you are all set.
defmodule MyApp.Kungfuig.Stub do
@moduledoc false
use Kungfuig.Backend
@impl Kungfuig.Backend
def get(_meta), do: %{foo: :bar, baz: [42]}
endChangelog
0.4.1— allowimminent: trueoption toKungfuig.Backend0.4.0— allow namedKungfuig.Supervisor(thanks @vbroskas)0.3.0— allow validation throughNimbleOptions(per backend and global)0.2.0— scaffold for backends + several callbacks (and the automatic one forBlender)