Extract database parameters from DATABASE_URL. (#305)
* Extract database parameters from DATABASE_URL.pull/5192/head
parent
d093b94913
commit
941c4dac31
@ -0,0 +1,62 @@ |
||||
defmodule Explorer.Repo.ConfigHelper do |
||||
@moduledoc """ |
||||
Extracts values from environment and adds them to application config. |
||||
|
||||
Notably, this module processes the DATABASE_URL environment variable and extracts discrete parameters. |
||||
|
||||
The priority of vars is DATABASE_URL components < postgrex enviroment vars < application config vars, with values being overwritted by higher priority. |
||||
""" |
||||
|
||||
# set in apps/*/config/*.exs |
||||
@app_env_vars [ |
||||
username: "DATABASE_USER", |
||||
password: "DATABASE_PASSWORD", |
||||
host: "DATABASE_HOST", |
||||
port: "DATABASE_PORT", |
||||
database: "DATABASE_DB" |
||||
] |
||||
|
||||
# https://hexdocs.pm/postgrex/Postgrex.html#start_link/1-options |
||||
@postgrex_env_vars [ |
||||
username: "PGUSER", |
||||
password: "PGPASSWORD", |
||||
host: "PGHOST", |
||||
port: "PGPORT", |
||||
database: "PGDATABASE" |
||||
] |
||||
|
||||
def get_db_config(opts) do |
||||
url = opts[:url] || System.get_env("DATABASE_URL") |
||||
env_function = opts[:env_func] || (&System.get_env/1) |
||||
|
||||
url |
||||
|> extract_parameters() |
||||
|> Keyword.merge(get_env_vars(@postgrex_env_vars, env_function)) |
||||
|> Keyword.merge(get_env_vars(@app_env_vars, env_function)) |
||||
end |
||||
|
||||
defp extract_parameters(empty) when empty == nil or empty == "", do: [] |
||||
|
||||
# sobelow_skip ["DOS.StringToAtom"] |
||||
defp extract_parameters(database_url) do |
||||
~r/\w*:\/\/(?<username>\w+):(?<password>\w*)?@(?<hostname>[a-zA-Z\d\.]+):(?<port>\d+)\/(?<database>\w+)/ |
||||
|> Regex.named_captures(database_url) |
||||
|> Keyword.new(fn {k, v} -> {String.to_atom(k), v} end) |
||||
|> Keyword.put(:url, database_url) |
||||
|> Enum.filter(fn |
||||
# don't include keys with empty values |
||||
{_, ""} -> false |
||||
_ -> true |
||||
end) |
||||
end |
||||
|
||||
defp get_env_vars(vars, env_function) do |
||||
Enum.reduce(vars, [], fn {name, var}, opts -> |
||||
case env_function.(var) do |
||||
nil -> opts |
||||
"" -> opts |
||||
env_value -> Keyword.put(opts, name, env_value) |
||||
end |
||||
end) |
||||
end |
||||
end |
@ -0,0 +1,72 @@ |
||||
defmodule Explorer.Repo.ConfigHelperTest do |
||||
use Explorer.DataCase |
||||
|
||||
alias Explorer.Repo.ConfigHelper |
||||
|
||||
describe "get_db_config/1" do |
||||
test "parse params from database url" do |
||||
database_url = "postgresql://test_username:test_password@127.8.8.1:7777/test_database" |
||||
|
||||
result = ConfigHelper.get_db_config(%{url: database_url, env_func: fn _ -> nil end}) |
||||
|
||||
assert result[:username] == "test_username" |
||||
assert result[:password] == "test_password" |
||||
assert result[:hostname] == "127.8.8.1" |
||||
assert result[:port] == "7777" |
||||
assert result[:database] == "test_database" |
||||
end |
||||
|
||||
test "get username without password" do |
||||
database_url = "postgresql://test_username:@127.8.8.1:7777/test_database" |
||||
|
||||
result = ConfigHelper.get_db_config(%{url: database_url, env_func: fn _ -> nil end}) |
||||
|
||||
assert result[:username] == "test_username" |
||||
refute result[:password] |
||||
assert result[:hostname] == "127.8.8.1" |
||||
assert result[:port] == "7777" |
||||
assert result[:database] == "test_database" |
||||
end |
||||
|
||||
test "get hostname instead of ip" do |
||||
database_url = "postgresql://test_username:@cooltesthost:7777/test_database" |
||||
|
||||
result = ConfigHelper.get_db_config(%{url: database_url, env_func: fn _ -> nil end}) |
||||
|
||||
assert result[:username] == "test_username" |
||||
refute result[:password] |
||||
assert result[:hostname] == "cooltesthost" |
||||
assert result[:port] == "7777" |
||||
assert result[:database] == "test_database" |
||||
end |
||||
|
||||
test "overwrite database url param with postgrex vars" do |
||||
database_url = "postgresql://test_username:@127.8.8.1:7777/test_database" |
||||
|
||||
vars = %{"PGUSER" => "postgrex_user", "PGPASSWORD" => "postgrex_password"} |
||||
func = fn v -> vars[v] end |
||||
result = ConfigHelper.get_db_config(%{url: database_url, env_func: func}) |
||||
|
||||
assert result[:username] == "postgrex_user" |
||||
assert result[:password] == "postgrex_password" |
||||
assert result[:hostname] == "127.8.8.1" |
||||
assert result[:port] == "7777" |
||||
assert result[:database] == "test_database" |
||||
end |
||||
|
||||
test "overwrite database url param and postgrex with app env" do |
||||
database_url = "postgresql://test_username:@127.8.8.1:7777/test_database" |
||||
|
||||
vars = %{"PGUSER" => "postgrex_user", "PGPASSWORD" => "postgrex_password", "DATABASE_USER" => "app_db_user"} |
||||
func = fn v -> vars[v] end |
||||
|
||||
result = ConfigHelper.get_db_config(%{url: database_url, env_func: func}) |
||||
|
||||
assert result[:username] == "app_db_user" |
||||
assert result[:password] == "postgrex_password" |
||||
assert result[:hostname] == "127.8.8.1" |
||||
assert result[:port] == "7777" |
||||
assert result[:database] == "test_database" |
||||
end |
||||
end |
||||
end |
Loading…
Reference in new issue