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