MSPF-396: update to erlang 21 (#13)

* MSPF-396: update to erlang 21 (#12)

* Setup to run on local machine

* Migrated to new erlang/cowboy with dependencies

* Updated dependecies & fixed wrong error handling

* Removed redundant dependecy and hid generated apps

* Removed extra cors module, added Options to handler

* Fixed middleware misplacement, and properly implemented handler behaviour

* cleaned up

* returned to url instead of http in private repos

* Returned to using cowboy_cors as CORS app, fixed typing, added epic branches rules for Jenkins

* added missing dependency, divided net_opts option

* Updated cors policy, added cors tests

* Reverted unnessesary Jenkinsfile changes

* Suppresed jesse warnings

* Updated build image tag

* Switched to using new jesse and parse_trans

* Bumped utils and image tags, updated registry

* bumped base image

* bumped build_utils, removed registry redefinition

* Refreshed outdated config (#14)

* bumped erlang-health, fixed lager crash

* Upgraded lager, restored redirection, refreshed config

* Refreshed deprecated ranch opts passing

* Switched to master branches

* Bumped build image
This commit is contained in:
Toporkov Igor 2019-04-03 17:20:56 +03:00 committed by GitHub
parent ba71536ebc
commit 1b31deb9f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 178 additions and 115 deletions

4
Jenkinsfile vendored
View File

@ -33,7 +33,7 @@ build('url-shortener', 'docker-host', finalHook) {
sh 'make wc_xref' sh 'make wc_xref'
} }
runStage('dialyze') { runStage('dialyze') {
withWsCache("_build/default/rebar3_19.1_plt") { withWsCache("_build/default/rebar3_21.1.1_plt") {
sh 'make wc_dialyze' sh 'make wc_dialyze'
} }
} }
@ -62,4 +62,4 @@ build('url-shortener', 'docker-host', finalHook) {
} }
} }
} }
} }

View File

@ -13,11 +13,11 @@ SERVICE_IMAGE_TAG ?= $(shell git rev-parse HEAD)
SERVICE_IMAGE_PUSH_TAG ?= $(SERVICE_IMAGE_TAG) SERVICE_IMAGE_PUSH_TAG ?= $(SERVICE_IMAGE_TAG)
# Base image for the service # Base image for the service
BASE_IMAGE_NAME := service_erlang BASE_IMAGE_NAME := service-erlang
BASE_IMAGE_TAG := 16e2b3ef17e5fdefac8554ced9c2c74e5c6e9e11 BASE_IMAGE_TAG := bdb3e60ddc70044bae1aa581d260d3a9803a2477
# Build image tag to be used # Build image tag to be used
BUILD_IMAGE_TAG := eee42f2ca018c313190bc350fe47d4dea70b6d27 BUILD_IMAGE_TAG := a166721af4f3454345d443bc681b91962d259d40
CALL_ANYWHERE := all submodules rebar-update compile xref lint dialyze start devrel release clean distclean CALL_ANYWHERE := all submodules rebar-update compile xref lint dialyze start devrel release clean distclean

View File

@ -51,11 +51,12 @@ get_processor_childspecs(Opts, HealthCheckers) ->
[woody_server:child_spec( [woody_server:child_spec(
?MODULE, ?MODULE,
#{ #{
ip => IP, ip => IP,
port => maps:get(port, Opts, 8022), port => maps:get(port, Opts, 8022),
net_opts => maps:get(net_opts, Opts, []), protocol_opts => maps:get(protocol_opts, Opts, #{}),
event_handler => scoper_woody_event_handler, transport_opts => maps:get(transport_opts, Opts, #{}),
handlers => [ event_handler => scoper_woody_event_handler,
handlers => [
{"/v1/stateproc", { {"/v1/stateproc", {
{mg_proto_state_processing_thrift, 'Processor'}, {mg_proto_state_processing_thrift, 'Processor'},
shortener_slug shortener_slug

View File

@ -144,7 +144,7 @@ derive_kid_from_public_key_pem_entry(JWK) ->
}. }.
-spec store_key(keyname(), {pem_file, file:filename()}, store_opts()) -> -spec store_key(keyname(), {pem_file, file:filename()}, store_opts()) ->
ok | {error, file:posix() | {unknown_key, _}}. {ok, keyinfo()} | {error, file:posix() | {unknown_key, _}}.
store_key(Keyname, {pem_file, Filename}, Opts) -> store_key(Keyname, {pem_file, Filename}, Opts) ->
case jose_jwk:from_pem_file(Filename) of case jose_jwk:from_pem_file(Filename) of

View File

@ -11,25 +11,24 @@
policy_init(Req) -> policy_init(Req) ->
{ok, Req, undefined}. {ok, Req, undefined}.
-spec allowed_origins(cowboy_req:req(), any()) -> {'*', cowboy_req:req(), any()}. -spec allowed_origins(cowboy_req:req(), any()) -> {'*', any()}.
allowed_origins(Req, State) -> allowed_origins(_, State) ->
{'*', Req, State}. {'*', State}.
-spec allowed_headers(cowboy_req:req(), any()) -> {[binary()], cowboy_req:req(), any()}. -spec allowed_headers(cowboy_req:req(), any()) -> {[binary()], any()}.
allowed_headers(Req, State) -> allowed_headers(_, State) ->
{[ {[
<<"accept">>, <<"accept">>,
<<"access-control-allow-headers">>, <<"access-control-allow-headers">>,
<<"authorization">>, <<"authorization">>,
<<"content-type">>, <<"content-type">>,
<<"origin">>,
<<"x-request-id">>, <<"x-request-id">>,
<<"x-requested-with">> <<"x-requested-with">>
], Req, State}. ], State}.
-spec allowed_methods(cowboy_req:req(), any()) -> {[binary()], cowboy_req:req(), any()}. -spec allowed_methods(cowboy_req:req(), any()) -> {[binary()], any()}.
allowed_methods(Req, State) -> allowed_methods(_, State) ->
{[<<"GET">>, <<"POST">>, <<"PUT">>, <<"DELETE">>, <<"OPTIONS">>], Req, State}. {[<<"GET">>, <<"POST">>, <<"PUT">>, <<"DELETE">>, <<"OPTIONS">>], State}.

View File

@ -3,14 +3,13 @@
%% Swagger handler %% Swagger handler
-behaviour(swag_server_logic_handler). -behaviour(swag_server_logic_handler).
-export([authorize_api_key/2]). -export([authorize_api_key/3]).
-export([handle_request/3]). -export([handle_request/4]).
%% Cowboy http handler %% Cowboy http handler
-behaviour(cowboy_http_handler). -behaviour(cowboy_handler).
-export([init/3]). -export([init/2]).
-export([handle/2]).
-export([terminate/3]). -export([terminate/3]).
%% %%
@ -23,17 +22,17 @@
-type request_data() :: #{atom() | binary() => term()}. -type request_data() :: #{atom() | binary() => term()}.
-type subject_id() :: woody_user_identity:id(). -type subject_id() :: woody_user_identity:id().
-spec authorize_api_key(operation_id(), swag_server:api_key()) -> -spec authorize_api_key(operation_id(), swag_server:api_key(), swag_server:handler_opts(_)) ->
Result :: false | {true, shortener_auth:context()}. Result :: false | {true, shortener_auth:context()}.
authorize_api_key(OperationID, ApiKey) -> authorize_api_key(OperationID, ApiKey, _Opts) ->
ok = scoper:add_scope('swag.server', #{operation => OperationID}), ok = scoper:add_scope('swag.server', #{operation => OperationID}),
shortener_auth:authorize_api_key(OperationID, ApiKey). shortener_auth:authorize_api_key(OperationID, ApiKey).
-spec handle_request(operation_id(), request_data(), request_ctx()) -> -spec handle_request(operation_id(), request_data(), request_ctx(), any()) ->
{ok | error, swag_server_logic_handler:response()}. {ok | error, swag_server:response()}.
handle_request(OperationID, Req, Context) -> handle_request(OperationID, Req, Context, _Opts) ->
try try
AuthContext = get_auth_context(Context), AuthContext = get_auth_context(Context),
WoodyCtx = create_woody_ctx(Req, AuthContext), WoodyCtx = create_woody_ctx(Req, AuthContext),
@ -43,7 +42,7 @@ handle_request(OperationID, Req, Context) ->
SubjectID = get_subject_id(AuthContext), SubjectID = get_subject_id(AuthContext),
process_request(OperationID, Req, Slug, SubjectID, WoodyCtx); process_request(OperationID, Req, Slug, SubjectID, WoodyCtx);
{error, forbidden} -> {error, forbidden} ->
{ok, {403, [], undefined}} {ok, {403, #{}, undefined}}
end end
catch catch
error:{woody_error, {Source, Class, Details}} -> error:{woody_error, {Source, Class, Details}} ->
@ -87,16 +86,16 @@ get_auth_context(#{auth_context := AuthContext}) ->
AuthContext. AuthContext.
handle_woody_error(_Source, result_unexpected, _Details) -> handle_woody_error(_Source, result_unexpected, _Details) ->
{500, [], <<>>}; {500, #{}, <<>>};
handle_woody_error(_Source, resource_unavailable, _Details) -> handle_woody_error(_Source, resource_unavailable, _Details) ->
{503, [], <<>>}; {503, #{}, <<>>};
handle_woody_error(_Source, result_unknown, _Details) -> handle_woody_error(_Source, result_unknown, _Details) ->
{504, [], <<>>}. {504, #{}, <<>>}.
%% %%
-spec process_request(operation_id(), request_data(), shortener_slug:slug(), subject_id(), woody_context:ctx()) -> -spec process_request(operation_id(), request_data(), shortener_slug:slug(), subject_id(), woody_context:ctx()) ->
{ok | error, swag_server_logic_handler:response()}. {ok | error, swag_server:response()}.
process_request( process_request(
'ShortenUrl', 'ShortenUrl',
@ -111,9 +110,9 @@ process_request(
case validate_source_url(SourceUrl) of case validate_source_url(SourceUrl) of
true -> true ->
Slug = shortener_slug:create(SourceUrl, parse_timestamp(ExpiresAt), SubjectID, WoodyCtx), Slug = shortener_slug:create(SourceUrl, parse_timestamp(ExpiresAt), SubjectID, WoodyCtx),
{ok, {201, [], construct_shortened_url(Slug)}}; {ok, {201, #{}, construct_shortened_url(Slug)}};
false -> false ->
{ok, {400, [], #{ {ok, {400, #{}, #{
<<"code">> => <<"forbidden_source_url">>, <<"code">> => <<"forbidden_source_url">>,
<<"message">> => <<"Source URL is forbidden">> <<"message">> => <<"Source URL is forbidden">>
}}} }}}
@ -126,7 +125,7 @@ process_request(
_SubjectID, _SubjectID,
_WoodyCtx _WoodyCtx
) -> ) ->
{error, {404, [], undefined}}; {error, {404, #{}, undefined}};
process_request( process_request(
'GetShortenedUrl', 'GetShortenedUrl',
_Req, _Req,
@ -134,7 +133,7 @@ process_request(
_SubjectID, _SubjectID,
_WoodyCtx _WoodyCtx
) -> ) ->
{ok, {200, [], construct_shortened_url(Slug)}}; {ok, {200, #{}, construct_shortened_url(Slug)}};
process_request( process_request(
'DeleteShortenedUrl', 'DeleteShortenedUrl',
@ -145,9 +144,9 @@ process_request(
) -> ) ->
case shortener_slug:remove(ID, WoodyCtx) of case shortener_slug:remove(ID, WoodyCtx) of
ok -> ok ->
{ok, {204, [], undefined}}; {ok, {204, #{}, undefined}};
{error, notfound} -> {error, notfound} ->
{error, {404, [], undefined}} {error, {404, #{}, undefined}}
end. end.
validate_source_url(SourceUrl) -> validate_source_url(SourceUrl) ->
@ -214,30 +213,24 @@ get_source_url_whitelist() ->
-type request() :: cowboy_req:req(). -type request() :: cowboy_req:req().
-type terminate_reason() :: {normal, shutdown} | {error, atom()}. -type terminate_reason() :: {normal, shutdown} | {error, atom()}.
-spec init({atom(), http}, request(), _) -> -spec init(request(), _) ->
{ok, request(), state()}. {ok, request(), state()}.
init({_, http}, Req, _Opts) -> init(Req, Opts) ->
{ok, Req, undefined}. ID = cowboy_req:binding('shortenedUrlID', Req),
Req1 = case shortener_slug:get(ID, woody_context:new()) of
-spec handle(request(), state()) ->
{ok, request(), state()}.
handle(Req1, St) ->
{ID, Req2} = cowboy_req:binding('shortenedUrlID', Req1),
{ok, Req3} = case shortener_slug:get(ID, woody_context:new()) of
{ok, #{source := Source, expires_at := ExpiresAt}} -> {ok, #{source := Source, expires_at := ExpiresAt}} ->
{ok, {Date, Time, _, _UndefinedButDialyzerDisagrees}} = rfc3339:parse(ExpiresAt), {ok, {Date, Time, _, _UndefinedButDialyzerDisagrees}} = rfc3339:parse(ExpiresAt),
Headers = [ Headers = #{
{<<"location">> , Source}, <<"location">> => Source,
{<<"expires">> , cowboy_clock:rfc1123({Date, Time})}, <<"expires">> => cowboy_clock:rfc1123({Date, Time}),
{<<"cache-control">> , <<"must-revalidate">>} <<"cache-control">> => <<"must-revalidate">>
], },
cowboy_req:reply(301, Headers, Req2); cowboy_req:reply(301, Headers, Req);
{error, notfound} -> {error, notfound} ->
cowboy_req:reply(404, Req2) cowboy_req:reply(404, Req)
end, end,
{ok, Req3, St}. {ok, Req1, Opts}.
-spec terminate(terminate_reason(), request(), state()) -> -spec terminate(terminate_reason(), request(), state()) ->
ok. ok.

View File

@ -16,7 +16,7 @@ child_spec(LogicHandler, Opts, AdditionalRoutes) ->
?MODULE, ?MODULE,
Transport, Transport,
TransportOpts, TransportOpts,
cowboy_protocol, cowboy_clear,
CowboyOpts CowboyOpts
). ).
@ -24,7 +24,7 @@ get_socket_transport(Opts) ->
{ok, IP} = inet:parse_address(maps:get(ip, Opts, ?DEFAULT_IP_ADDR)), {ok, IP} = inet:parse_address(maps:get(ip, Opts, ?DEFAULT_IP_ADDR)),
Port = maps:get(port, Opts, ?DEFAULT_PORT), Port = maps:get(port, Opts, ?DEFAULT_PORT),
Acceptors = maps:get(acceptors, Opts, ?DEFAULT_ACCEPTORS_POOLSIZE), Acceptors = maps:get(acceptors, Opts, ?DEFAULT_ACCEPTORS_POOLSIZE),
{ranch_tcp, [{ip, IP}, {port, Port}, {num_acceptors, Acceptors}]}. {ranch_tcp, #{socket_opts => [{ip, IP}, {port, Port}], num_acceptors => Acceptors}}.
get_cowboy_config(LogicHandler, AdditionalRoutes, Opts) -> get_cowboy_config(LogicHandler, AdditionalRoutes, Opts) ->
ShortUrlTemplate = maps:get(short_url_template, Opts), ShortUrlTemplate = maps:get(short_url_template, Opts),
@ -34,19 +34,19 @@ get_cowboy_config(LogicHandler, AdditionalRoutes, Opts) ->
swag_server_router:get_paths(LogicHandler) ++ swag_server_router:get_paths(LogicHandler) ++
[{'_', [{genlib:to_list(ShortUrlPath) ++ ":shortenedUrlID", shortener_handler, #{}}]}] [{'_', [{genlib:to_list(ShortUrlPath) ++ ":shortenedUrlID", shortener_handler, #{}}]}]
), ),
[ #{
{env, [ env => #{
{dispatch, cowboy_router:compile(Routes)}, dispatch => cowboy_router:compile(Routes),
{cors_policy, shortener_cors_policy} cors_policy => shortener_cors_policy
]}, },
{middlewares, [ middlewares => [
cowboy_router, cowboy_router,
cowboy_cors, cowboy_cors,
cowboy_handler cowboy_handler
]}, ],
{onrequest, cowboy_access_log:get_request_hook()}, stream_handlers => [cowboy_stream_h, cowboy_access_log_h],
{onresponse, cowboy_access_log:get_response_hook(shortener_access_lager_event)} sink => shortener_access_lager_event
]. }.
squash_routes(Routes) -> squash_routes(Routes) ->
orddict:to_list(lists:foldl( orddict:to_list(lists:foldl(

View File

@ -22,6 +22,11 @@
-export([woody_timeout_test/1]). -export([woody_timeout_test/1]).
-export([unsupported_cors_method/1]).
-export([supported_cors_method/1]).
-export([unsupported_cors_header/1]).
-export([supported_cors_header/1]).
%% tests descriptions %% tests descriptions
-type config() :: [{atom(), term()}]. -type config() :: [{atom(), term()}].
@ -33,7 +38,7 @@
all() -> all() ->
[ [
{group, general}, {group, general},
{group, cors},
woody_timeout_test woody_timeout_test
]. ].
@ -53,6 +58,12 @@ groups() ->
fordidden_source_url, fordidden_source_url,
url_expired, url_expired,
always_unique_url always_unique_url
]},
{cors, [], [
unsupported_cors_method,
supported_cors_method,
unsupported_cors_header,
supported_cors_header
]} ]}
]. ].
@ -87,7 +98,7 @@ init_per_suite(C) ->
-spec init_per_group(atom(), config()) -> config(). -spec init_per_group(atom(), config()) -> config().
init_per_group(general, C) -> init_per_group(_Group, C) ->
ShortenerApp = ShortenerApp =
genlib_app:start_application_with(shortener, get_app_config( genlib_app:start_application_with(shortener, get_app_config(
?config(port, C), ?config(port, C),
@ -101,7 +112,7 @@ init_per_group(general, C) ->
-spec end_per_group(atom(), config()) -> _. -spec end_per_group(atom(), config()) -> _.
end_per_group(general, C) -> end_per_group(_Group, C) ->
genlib_app:stop_unload_applications(?config(shortener_app, C)). genlib_app:stop_unload_applications(?config(shortener_app, C)).
get_keysource(Key, C) -> get_keysource(Key, C) ->
@ -220,6 +231,57 @@ always_unique_url(C) ->
N = length(lists:usort(IDs)), N = length(lists:usort(IDs)),
N = length(lists:usort(ShortUrls)). N = length(lists:usort(ShortUrls)).
%% cors
-spec unsupported_cors_method(config()) -> _.
-spec supported_cors_method(config()) -> _.
-spec unsupported_cors_header(config()) -> _.
-spec supported_cors_header(config()) -> _.
unsupported_cors_method(C) ->
SourceUrl = <<"https://oops.io/">>,
Params = construct_params(SourceUrl),
C1 = set_api_auth_token(unsupported_cors_method, [read, write], C),
{ok, 201, _, #{<<"shortenedUrl">> := ShortUrl}} = shorten_url(Params, C1),
ReqHeaders = [{<<"origin">>, <<"localhost">>}, {<<"access-control-request-method">>, <<"PATCH">>}],
{ok, 200, Headers, _} = hackney:request(options, ShortUrl, ReqHeaders),
false = lists:member(<<"access-control-allow-methods">>, Headers).
supported_cors_method(C) ->
SourceUrl = <<"https://oops.io/">>,
Params = construct_params(SourceUrl),
C1 = set_api_auth_token(supported_cors_method, [read, write], C),
{ok, 201, _, #{<<"shortenedUrl">> := ShortUrl}} = shorten_url(Params, C1),
ReqHeaders = [{<<"origin">>, <<"localhost">>}, {<<"access-control-request-method">>, <<"GET">>}],
{ok, 200, Headers, _} = hackney:request(options, ShortUrl, ReqHeaders),
{Allowed, _} = shortener_cors_policy:allowed_methods(undefined, undefined),
{_, Returned} = lists:keyfind(<<"access-control-allow-methods">>, 1, Headers),
Allowed = binary:split(Returned, <<",">>, [global]).
supported_cors_header(C) ->
SourceUrl = <<"https://oops.io/">>,
Params = construct_params(SourceUrl),
C1 = set_api_auth_token(supported_cors_header, [read, write], C),
{ok, 201, _, #{<<"shortenedUrl">> := ShortUrl}} = shorten_url(Params, C1),
ReqHeaders = [{<<"origin">>, <<"localhost">>}, {<<"access-control-request-method">>, <<"GET">>}, {<<"access-control-request-headers">>, <<"content-type,authorization">>}],
{ok, 200, Headers, _} = hackney:request(options, ShortUrl, ReqHeaders),
{Allowed, _} = shortener_cors_policy:allowed_headers(undefined, undefined),
{_, Returned} = lists:keyfind(<<"access-control-allow-headers">>, 1, Headers),
[_ | Allowed] = binary:split(Returned, <<",">>, [global]). % truncate origin
unsupported_cors_header(C) ->
SourceUrl = <<"https://oops.io/">>,
Params = construct_params(SourceUrl),
C1 = set_api_auth_token(unsupported_cors_header, [read, write], C),
{ok, 201, _, #{<<"shortenedUrl">> := ShortUrl}} = shorten_url(Params, C1),
ReqHeaders = [{<<"origin">>, <<"localhost">>}, {<<"access-control-request-method">>, <<"GET">>}, {<<"access-control-request-headers">>, <<"content-type,42">>}],
{ok, 200, Headers, _} = hackney:request(options, ShortUrl, ReqHeaders),
false = lists:member(<<"access-control-allow-headers">>, Headers),
false = lists:member(<<"access-control-allow-credentials">>, Headers),
false = lists:member(<<"access-control-allow-methods">>, Headers),
false = lists:member(<<"access-control-allow-origin">>, Headers).
construct_params(SourceUrl) -> construct_params(SourceUrl) ->
construct_params(SourceUrl, 3600). construct_params(SourceUrl, 3600).

@ -1 +1 @@
Subproject commit 8dd1d30e97e4db20c9da98a5ddb261b199402bc0 Subproject commit 870b70a63af18fc7a02c9ff26b06132d2b1993cb

View File

@ -4,7 +4,7 @@
{error_logger_hwm, 600}, {error_logger_hwm, 600},
{log_root, "/var/log/shortener"}, {log_root, "/var/log/shortener"},
{handlers, [ {handlers, [
{lager_console_backend, debug}, {lager_console_backend, [{level, debug}]},
{lager_file_backend, [ {lager_file_backend, [
{file, "console.json"}, {file, "console.json"},
{level, debug}, {level, debug},
@ -51,9 +51,9 @@
{processor, #{ {processor, #{
ip => "::", ip => "::",
port => 8022, port => 8022,
net_opts => [ protocol_opts => #{
{timeout , 60000} request_timeout => 60000
] }
}}, }},
{service_clients, #{ {service_clients, #{
automaton => #{ automaton => #{

View File

@ -28,9 +28,9 @@
% Common project dependencies. % Common project dependencies.
{deps, [ {deps, [
{cowboy, "1.0.4"}, {lager, "3.6.4"},
{cowboy, "2.5.0"},
{jose, "1.7.9"}, {jose, "1.7.9"},
{lager, "3.5.2"},
{genlib, {genlib,
{git, "https://github.com/rbkmoney/genlib.git", {git, "https://github.com/rbkmoney/genlib.git",
{branch, "master"} {branch, "master"}
@ -46,11 +46,6 @@
{branch, "master"} {branch, "master"}
} }
}, },
{cowboy_cors,
{git, "https://github.com/danielwhite/cowboy_cors.git",
{branch, "master"}
}
},
{woody, {woody,
{git, "git@github.com:rbkmoney/woody_erlang.git", {git, "git@github.com:rbkmoney/woody_erlang.git",
{branch, "master"} {branch, "master"}
@ -73,7 +68,12 @@
}, },
{erl_health, {erl_health,
{git, "https://github.com/rbkmoney/erlang-health.git", {git, "https://github.com/rbkmoney/erlang-health.git",
{branch, master} {branch, "master"}
}
},
{cowboy_cors,
{git, "https://github.com/rbkmoney/cowboy_cors.git",
{branch, "master"}
} }
} }
]}. ]}.

View File

@ -1,38 +1,44 @@
{"1.1.0", {"1.1.0",
[{<<"base64url">>,{pkg,<<"base64url">>,<<"0.0.1">>},1}, [{<<"base64url">>,{pkg,<<"base64url">>,<<"0.0.1">>},1},
{<<"certifi">>,{pkg,<<"certifi">>,<<"0.7.0">>},1}, {<<"cache">>,{pkg,<<"cache">>,<<"2.2.0">>},1},
{<<"certifi">>,{pkg,<<"certifi">>,<<"2.3.1">>},1},
{<<"cg_mon">>, {<<"cg_mon">>,
{git,"https://github.com/rbkmoney/cg_mon.git", {git,"https://github.com/rbkmoney/cg_mon.git",
{ref,"5a87a37694e42b6592d3b4164ae54e0e87e24e18"}}, {ref,"5a87a37694e42b6592d3b4164ae54e0e87e24e18"}},
1}, 1},
{<<"cowboy">>,{pkg,<<"cowboy">>,<<"1.0.4">>},0}, {<<"cowboy">>,{pkg,<<"cowboy">>,<<"2.5.0">>},0},
{<<"cowboy_access_log">>, {<<"cowboy_access_log">>,
{git,"git@github.com:rbkmoney/cowboy_access_log.git", {git,"git@github.com:rbkmoney/cowboy_access_log.git",
{ref,"c91ae2316f3daf5465ec12e9fdd0ae37082885c0"}}, {ref,"b6e9f5cdd0990c756ace0267983226abaf137bd0"}},
0}, 0},
{<<"cowboy_cors">>, {<<"cowboy_cors">>,
{git,"https://github.com/danielwhite/cowboy_cors.git", {git,"https://github.com/rbkmoney/cowboy_cors.git",
{ref,"392f5804b63fff2bd0fda67671d5b2fbe0badd37"}}, {ref,"4cac7528845a8610d471b6fbb92321f79d93f0b8"}},
0}, 0},
{<<"cowlib">>,{pkg,<<"cowlib">>,<<"1.0.2">>},1}, {<<"cowlib">>,{pkg,<<"cowlib">>,<<"2.6.0">>},1},
{<<"erl_health">>, {<<"erl_health">>,
{git,"https://github.com/rbkmoney/erlang-health.git", {git,"https://github.com/rbkmoney/erlang-health.git",
{ref,"ab3ca1ccab6e77905810aa270eb936dbe70e02f8"}}, {ref,"2575c7b63d82a92de54d2d27e504413675e64811"}},
0}, 0},
{<<"genlib">>, {<<"genlib">>,
{git,"https://github.com/rbkmoney/genlib.git", {git,"https://github.com/rbkmoney/genlib.git",
{ref,"7fc1ca1a57dbe2b8b837951095e314c32afd6c9a"}}, {ref,"7fc1ca1a57dbe2b8b837951095e314c32afd6c9a"}},
0}, 0},
{<<"goldrush">>,{pkg,<<"goldrush">>,<<"0.1.9">>},1}, {<<"goldrush">>,{pkg,<<"goldrush">>,<<"0.1.9">>},1},
{<<"hackney">>,{pkg,<<"hackney">>,<<"1.6.2">>},0}, {<<"gproc">>,{pkg,<<"gproc">>,<<"0.8.0">>},1},
{<<"idna">>,{pkg,<<"idna">>,<<"1.2.0">>},1}, {<<"gun">>,
{git,"https://github.com/ninenines/gun.git",
{ref,"e7dd9f227e46979d8073e71c683395a809b78cb4"}},
1},
{<<"hackney">>,{pkg,<<"hackney">>,<<"1.15.0">>},0},
{<<"idna">>,{pkg,<<"idna">>,<<"5.1.2">>},1},
{<<"jesse">>, {<<"jesse">>,
{git,"https://github.com/rbkmoney/jesse.git", {git,"https://github.com/rbkmoney/jesse.git",
{ref,"39105922d1ce5834383d8e8aa877c60319b9834a"}}, {ref,"723e835708a022bbce9e57807ecf220b00fb771a"}},
0}, 0},
{<<"jose">>,{pkg,<<"jose">>,<<"1.7.9">>},0}, {<<"jose">>,{pkg,<<"jose">>,<<"1.7.9">>},0},
{<<"jsx">>,{pkg,<<"jsx">>,<<"2.8.2">>},0}, {<<"jsx">>,{pkg,<<"jsx">>,<<"2.8.2">>},0},
{<<"lager">>,{pkg,<<"lager">>,<<"3.5.2">>},0}, {<<"lager">>,{pkg,<<"lager">>,<<"3.6.4">>},0},
{<<"lager_logstash_formatter">>, {<<"lager_logstash_formatter">>,
{git,"git@github.com:rbkmoney/lager_logstash_formatter.git", {git,"git@github.com:rbkmoney/lager_logstash_formatter.git",
{ref,"24527c15c47749866f2d427b333fa1333a46b8af"}}, {ref,"24527c15c47749866f2d427b333fa1333a46b8af"}},
@ -44,15 +50,14 @@
0}, 0},
{<<"mimerl">>,{pkg,<<"mimerl">>,<<"1.0.2">>},1}, {<<"mimerl">>,{pkg,<<"mimerl">>,<<"1.0.2">>},1},
{<<"parse_trans">>, {<<"parse_trans">>,
{git,"https://github.com/rbkmoney/parse_trans.git", {git,"https://github.com/uwiger/parse_trans.git",
{ref,"5ee45f5bfa6c04329bea3281977b774f04c89f11"}}, {ref,"76abb347c3c1d00fb0ccf9e4b43e22b3d2288484"}},
0}, 0},
{<<"pooler">>,{pkg,<<"pooler">>,<<"1.5.0">>},0}, {<<"ranch">>,{pkg,<<"ranch">>,<<"1.6.2">>},1},
{<<"ranch">>,{pkg,<<"ranch">>,<<"1.4.0">>},1},
{<<"rfc3339">>,{pkg,<<"rfc3339">>,<<"0.2.2">>},0}, {<<"rfc3339">>,{pkg,<<"rfc3339">>,<<"0.2.2">>},0},
{<<"scoper">>, {<<"scoper">>,
{git,"git@github.com:rbkmoney/scoper.git", {git,"git@github.com:rbkmoney/scoper.git",
{ref,"802057089bac258f45e35263eb2223961618468d"}}, {ref,"206f76e006207f75828c1df3dde0deaa8554f332"}},
0}, 0},
{<<"snowflake">>, {<<"snowflake">>,
{git,"https://github.com/rbkmoney/snowflake.git", {git,"https://github.com/rbkmoney/snowflake.git",
@ -63,30 +68,33 @@
{git,"https://github.com/rbkmoney/thrift_erlang.git", {git,"https://github.com/rbkmoney/thrift_erlang.git",
{ref,"240bbc842f6e9b90d01bd07838778cf48752b510"}}, {ref,"240bbc842f6e9b90d01bd07838778cf48752b510"}},
1}, 1},
{<<"unicode_util_compat">>,{pkg,<<"unicode_util_compat">>,<<"0.3.1">>},2},
{<<"woody">>, {<<"woody">>,
{git,"git@github.com:rbkmoney/woody_erlang.git", {git,"git@github.com:rbkmoney/woody_erlang.git",
{ref,"354ac7664529ddecc07376bdaf4408cd8022fb61"}}, {ref,"c396f927b5149d1b5589262773a9e6a39cb68d33"}},
0}, 0},
{<<"woody_user_identity">>, {<<"woody_user_identity">>,
{git,"git@github.com:rbkmoney/woody_erlang_user_identity.git", {git,"git@github.com:rbkmoney/woody_erlang_user_identity.git",
{ref,"9c7ad2b8beac9c88c54594b264743dec7b9cf696"}}, {ref,"fe973ab27fee9fc1cc39281e88816c7b6dce84c6"}},
0}]}. 0}]}.
[ [
{pkg_hash,[ {pkg_hash,[
{<<"base64url">>, <<"36A90125F5948E3AFD7BE97662A1504B934DD5DAC78451CA6E9ABF85A10286BE">>}, {<<"base64url">>, <<"36A90125F5948E3AFD7BE97662A1504B934DD5DAC78451CA6E9ABF85A10286BE">>},
{<<"certifi">>, <<"861A57F3808F7EB0C2D1802AFEAAE0FA5DE813B0DF0979153CBAFCD853ABABAF">>}, {<<"cache">>, <<"3C11DBF4CD8FCD5787C95A5FB2A04038E3729CFCA0386016EEA8C953AB48A5AB">>},
{<<"cowboy">>, <<"A324A8DF9F2316C833A470D918AAF73AE894278B8AA6226CE7A9BF699388F878">>}, {<<"certifi">>, <<"D0F424232390BF47D82DA8478022301C561CF6445B5B5FB6A84D49A9E76D2639">>},
{<<"cowlib">>, <<"9D769A1D062C9C3AC753096F868CA121E2730B9A377DE23DEC0F7E08B1DF84EE">>}, {<<"cowboy">>, <<"4EF3AE066EE10FE01EA3272EDC8F024347A0D3EB95F6FBB9AED556DACBFC1337">>},
{<<"cowlib">>, <<"8AA629F81A0FC189F261DC98A42243FA842625FEEA3C7EC56C48F4CCDB55490F">>},
{<<"goldrush">>, <<"F06E5D5F1277DA5C413E84D5A2924174182FB108DABB39D5EC548B27424CD106">>}, {<<"goldrush">>, <<"F06E5D5F1277DA5C413E84D5A2924174182FB108DABB39D5EC548B27424CD106">>},
{<<"hackney">>, <<"96A0A5E7E65B7ACAD8031D231965718CC70A9B4131A8B033B7543BBD673B8210">>}, {<<"gproc">>, <<"CEA02C578589C61E5341FCE149EA36CCEF236CC2ECAC8691FBA408E7EA77EC2F">>},
{<<"idna">>, <<"AC62EE99DA068F43C50DC69ACF700E03A62A348360126260E87F2B54ECED86B2">>}, {<<"hackney">>, <<"287A5D2304D516F63E56C469511C42B016423BCB167E61B611F6BAD47E3CA60E">>},
{<<"idna">>, <<"E21CB58A09F0228A9E0B95EAA1217F1BCFC31A1AAA6E1FDF2F53A33F7DBD9494">>},
{<<"jose">>, <<"9DC5A14AB62DB4E41677FCC97993752562FB57AD0B8BA062589682EDD3ACB91F">>}, {<<"jose">>, <<"9DC5A14AB62DB4E41677FCC97993752562FB57AD0B8BA062589682EDD3ACB91F">>},
{<<"jsx">>, <<"7ACC7D785B5ABE8A6E9ADBDE926A24E481F29956DD8B4DF49E3E4E7BCC92A018">>}, {<<"jsx">>, <<"7ACC7D785B5ABE8A6E9ADBDE926A24E481F29956DD8B4DF49E3E4E7BCC92A018">>},
{<<"lager">>, <<"614A8C8F67BF99B69EB264EA22121AD25511C055AAEC09B086773D5108C6767F">>}, {<<"lager">>, <<"CED6E98070FB4E58EE93174D006D46479C79844DF7FC17FA4FEFC1049A320D88">>},
{<<"metrics">>, <<"25F094DEA2CDA98213CECC3AEFF09E940299D950904393B2A29D191C346A8486">>}, {<<"metrics">>, <<"25F094DEA2CDA98213CECC3AEFF09E940299D950904393B2A29D191C346A8486">>},
{<<"mimerl">>, <<"993F9B0E084083405ED8252B99460C4F0563E41729AB42D9074FD5E52439BE88">>}, {<<"mimerl">>, <<"993F9B0E084083405ED8252B99460C4F0563E41729AB42D9074FD5E52439BE88">>},
{<<"pooler">>, <<"0FD4BE5D2976E6A2E9A1617623031758C26F200C1FCA89E4A3C542747BEC6371">>}, {<<"ranch">>, <<"6DB93C78F411EE033DBB18BA8234C5574883ACB9A75AF0FB90A9B82EA46AFA00">>},
{<<"ranch">>, <<"10272F95DA79340FA7E8774BA7930B901713D272905D0012B06CA6D994F8826B">>},
{<<"rfc3339">>, <<"1552DF616ACA368D982E9F085A0E933B6688A3F4938A671798978EC2C0C58730">>}, {<<"rfc3339">>, <<"1552DF616ACA368D982E9F085A0E933B6688A3F4938A671798978EC2C0C58730">>},
{<<"ssl_verify_fun">>, <<"28A4D65B7F59893BC2C7DE786DEC1E1555BD742D336043FE644AE956C3497FBE">>}]} {<<"ssl_verify_fun">>, <<"28A4D65B7F59893BC2C7DE786DEC1E1555BD742D336043FE644AE956C3497FBE">>},
{<<"unicode_util_compat">>, <<"A1F612A7B512638634A603C8F401892AFBF99B8CE93A45041F8AACA99CADB85E">>}]}
]. ].