Merge pull request #5192 from blockscout/vb-db-config-parser
Fix DATABASE_URL config parserpull/5191/head
commit
776fa44251
@ -0,0 +1,47 @@ |
||||
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 postgrex enviroment vars < DATABASE_URL components, with values being overwritted by higher priority. |
||||
""" |
||||
|
||||
# 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) |
||||
|
||||
@postgrex_env_vars |
||||
|> get_env_vars(env_function) |
||||
|> Keyword.merge(extract_parameters(url)) |
||||
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) |
||||
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,71 @@ |
||||
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" |
||||
assert 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" |
||||
assert result[:password] == "" |
||||
assert result[:hostname] == "cooltesthost" |
||||
assert result[:port] == "7777" |
||||
assert result[:database] == "test_database" |
||||
end |
||||
|
||||
test "overwrite postgrex vars param with database url" 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] == "test_username" |
||||
assert result[:password] == "" |
||||
assert result[:hostname] == "127.8.8.1" |
||||
assert result[:port] == "7777" |
||||
assert result[:database] == "test_database" |
||||
end |
||||
|
||||
test "overwrite database password param with empty DATABASE_URL password" 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] == "test_username" |
||||
assert result[: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