mirror of
https://github.com/valitydev/epg_connector.git
synced 2024-11-06 00:05:21 +00:00
TD-929: add implementation
This commit is contained in:
parent
ab2168b35a
commit
78152d43d1
18
.gitignore
vendored
Normal file
18
.gitignore
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
# general
|
||||
log
|
||||
/_build/
|
||||
/_checkouts/
|
||||
*~
|
||||
erl_crash.dump
|
||||
rebar3.crashdump
|
||||
.tags*
|
||||
*.sublime-workspace
|
||||
.edts
|
||||
.DS_Store
|
||||
/.idea/
|
||||
*.beam
|
||||
/test/log/
|
||||
|
||||
tags
|
||||
.image.dev
|
||||
bin
|
@ -1,2 +1,2 @@
|
||||
# epg_connector
|
||||
Postgres connector fot Erlang
|
||||
Postgres connector for Erlang
|
||||
|
28
config/sys.config
Normal file
28
config/sys.config
Normal file
@ -0,0 +1,28 @@
|
||||
[
|
||||
{epg_connector, [
|
||||
{databases, #{
|
||||
default_db => #{
|
||||
host =>"127.0.0.1",
|
||||
port => 5432,
|
||||
database => "db_name",
|
||||
username => "postgres",
|
||||
password => "postgres"
|
||||
}
|
||||
}},
|
||||
{pools, #{
|
||||
default_pool => #{
|
||||
database => default_db,
|
||||
size => 10
|
||||
}
|
||||
}},
|
||||
%% Must specified for umbrella application
|
||||
{vault_token_path, "/var/run/secrets/kubernetes.io/serviceaccount/token"},
|
||||
{vault_role, "epg_connector"},
|
||||
{vault_key_pg_creds, "epg_connector/pg_creds"}
|
||||
]},
|
||||
|
||||
{canal, [
|
||||
{url, "http://vault:8200"},
|
||||
{engine, kvv2}
|
||||
]}
|
||||
].
|
13
rebar.config
Normal file
13
rebar.config
Normal file
@ -0,0 +1,13 @@
|
||||
{erl_opts, [debug_info]}.
|
||||
{deps, [
|
||||
jsx,
|
||||
{canal, {git, "https://github.com/valitydev/canal", {branch, master}}},
|
||||
{epgsql, {git, "https://github.com/epgsql/epgsql.git", {tag, "4.7.1"}}},
|
||||
{epgsql_pool, {git, "https://github.com/wgnet/epgsql_pool", {branch, "master"}}},
|
||||
{herd, {git, "https://github.com/wgnet/herd.git", {tag, "1.3.4"}}}
|
||||
]}.
|
||||
|
||||
{shell, [
|
||||
% {config, "config/sys.config"},
|
||||
{apps, [epg_connector]}
|
||||
]}.
|
18
src/epg_connector.app.src
Normal file
18
src/epg_connector.app.src
Normal file
@ -0,0 +1,18 @@
|
||||
{application, epg_connector,
|
||||
[{description, "An OTP application"},
|
||||
{vsn, "0.1.0"},
|
||||
{registered, []},
|
||||
{mod, {epg_connector_app, []}},
|
||||
{applications,
|
||||
[kernel,
|
||||
stdlib,
|
||||
canal,
|
||||
epgsql,
|
||||
epgsql_pool
|
||||
]},
|
||||
{env,[]},
|
||||
{modules, []},
|
||||
|
||||
{licenses, ["MIT"]},
|
||||
{links, []}
|
||||
]}.
|
101
src/epg_connector_app.erl
Normal file
101
src/epg_connector_app.erl
Normal file
@ -0,0 +1,101 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%% @doc epg_connector public API
|
||||
%% @end
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
-module(epg_connector_app).
|
||||
|
||||
-behaviour(application).
|
||||
|
||||
-define(VAULT_TOKEN_PATH, "/var/run/secrets/kubernetes.io/serviceaccount/token").
|
||||
-define(VAULT_ROLE, "api-key-mgmt-v2").
|
||||
-define(VAULT_KEY_PG_CREDS, "api-key-mgmt-v2/pg_creds").
|
||||
|
||||
-export([start/2, stop/1]).
|
||||
|
||||
start(_StartType, _StartArgs) ->
|
||||
Databases = application:get_env(epg_connector, databases, #{}),
|
||||
ok = maybe_set_secrets(Databases),
|
||||
Pools = application:get_env(epg_connector, pools, #{}),
|
||||
ok = start_pools(Pools, Databases),
|
||||
epg_connector_sup:start_link().
|
||||
|
||||
stop(_State) ->
|
||||
ok.
|
||||
|
||||
%% internal functions
|
||||
|
||||
start_pools(Pools, Databases) ->
|
||||
maps:fold(
|
||||
fun(PoolName, Opts, _Acc) ->
|
||||
#{
|
||||
database := DB,
|
||||
size := Size
|
||||
} = Opts,
|
||||
DbParams = maps:get(DB, Databases),
|
||||
{ok, _} = epgsql_pool:start(PoolName, Size, Size, DbParams),
|
||||
ok
|
||||
end,
|
||||
ok,
|
||||
Pools
|
||||
).
|
||||
|
||||
maybe_set_secrets(Databases) ->
|
||||
TokenPath = application:get_env(epg_connector, vault_token_path, ?VAULT_TOKEN_PATH),
|
||||
try vault_client_auth(TokenPath) of
|
||||
ok ->
|
||||
Key = unicode:characters_to_binary(
|
||||
application:get_env(epg_connector, vault_key_pg_creds, ?VAULT_KEY_PG_CREDS)
|
||||
),
|
||||
set_secrets(canal:read(Key), Databases);
|
||||
Error ->
|
||||
logger:error("can`t auth vault client with error: ~p", [Error]),
|
||||
skip
|
||||
catch
|
||||
_:_ ->
|
||||
logger:error("catch exception when auth vault client"),
|
||||
skip
|
||||
end,
|
||||
ok.
|
||||
|
||||
vault_client_auth(TokenPath) ->
|
||||
case read_maybe_linked_file(TokenPath) of
|
||||
{ok, Token} ->
|
||||
Role = unicode:characters_to_binary(application:get_env(epg_connector, vault_role, ?VAULT_ROLE)),
|
||||
canal:auth({kubernetes, Role, Token});
|
||||
Error ->
|
||||
Error
|
||||
end.
|
||||
|
||||
read_maybe_linked_file(MaybeLinkName) ->
|
||||
case file:read_link(MaybeLinkName) of
|
||||
{error, enoent} = Result ->
|
||||
Result;
|
||||
{error, einval} ->
|
||||
file:read_file(MaybeLinkName);
|
||||
{ok, Filename} ->
|
||||
file:read_file(maybe_expand_relative(MaybeLinkName, Filename))
|
||||
end.
|
||||
|
||||
maybe_expand_relative(BaseFilename, Filename) ->
|
||||
filename:absname_join(filename:dirname(BaseFilename), Filename).
|
||||
|
||||
set_secrets({ok, #{<<"pg_creds">> := #{<<"pg_user">> := PgUser, <<"pg_password">> := PgPassword}}}, Databases) ->
|
||||
logger:info("postgres credentials successfuly read from vault (as json)"),
|
||||
NewDbConfig = maps:fold(fun(DbName, ConnOpts, Acc) ->
|
||||
Acc#{
|
||||
DbName => ConnOpts#{
|
||||
username => unicode:characters_to_list(PgUser),
|
||||
password => unicode:characters_to_list(PgPassword)
|
||||
}
|
||||
}
|
||||
end, #{}, Databases),
|
||||
application:set_env(epg_connector, databases, NewDbConfig),
|
||||
ok;
|
||||
set_secrets({ok, #{<<"pg_creds">> := PgCreds}}, Databases) ->
|
||||
logger:info("postgres credentials successfuly read from vault (as string)"),
|
||||
set_secrets({ok, #{<<"pg_creds">> => jsx:decode(PgCreds, [return_maps])}}, Databases);
|
||||
set_secrets(Error, _Databases) ->
|
||||
logger:error("can`t read postgres credentials from vault with error: ~p", [Error]),
|
||||
skip.
|
||||
|
26
src/epg_connector_sup.erl
Normal file
26
src/epg_connector_sup.erl
Normal file
@ -0,0 +1,26 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%% @doc epg_connector top level supervisor.
|
||||
%% @end
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
-module(epg_connector_sup).
|
||||
|
||||
-behaviour(supervisor).
|
||||
|
||||
-export([start_link/0]).
|
||||
|
||||
-export([init/1]).
|
||||
|
||||
-define(SERVER, ?MODULE).
|
||||
|
||||
start_link() ->
|
||||
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
|
||||
|
||||
init([]) ->
|
||||
SupFlags = #{strategy => one_for_all,
|
||||
intensity => 0,
|
||||
period => 1},
|
||||
ChildSpecs = [],
|
||||
{ok, {SupFlags, ChildSpecs}}.
|
||||
|
||||
%% internal functions
|
Loading…
Reference in New Issue
Block a user