From cf7fdc8d5945b788eca362d11db645d0b4200ae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Hedenstro=CC=88m?= <erik@hedenstroem.com> Date: Thu, 7 Apr 2016 00:33:13 +0200 Subject: [PATCH] Initial working luerl resolver --- apps/consul_proxy/src/consul_proxy_router.erl | 30 +++++++++++--- apps/consul_proxy/src/consul_proxy_utils.erl | 41 +++++++++++++++---- test/defaults.consul | 6 ++- 3 files changed, 60 insertions(+), 17 deletions(-) diff --git a/apps/consul_proxy/src/consul_proxy_router.erl b/apps/consul_proxy/src/consul_proxy_router.erl index fc373a6..30e07e8 100644 --- a/apps/consul_proxy/src/consul_proxy_router.erl +++ b/apps/consul_proxy/src/consul_proxy_router.erl @@ -153,14 +153,14 @@ lookup_nodes(Domain, _Upstream, _Properties, Nodes, CacheFlag) -> lookup_resolver(_Domain, _Upstream, _Properties, undefined, _CacheFlag) -> {error, route_lookup_failed}; lookup_resolver(Domain, Upstream, Properties, ServiceResolver, _CacheFlag) -> - case consul_proxy_utils:eval_script(ServiceResolver, [{'Req', Upstream}]) of + case consul_proxy_utils:eval_script(ServiceResolver, build_script_vars(Upstream)) of {ok, ServiceName} when is_binary(ServiceName) -> - lookup_services(Domain, Upstream, Properties, {ServiceName, undefined, []}, false); + lookup_services(Domain, Upstream, Properties, {ServiceName, <<".*">>, <<".*">>}, false); + {ok, [ServiceName]} when is_binary(ServiceName) -> + lookup_services(Domain, Upstream, Properties, {ServiceName, <<".*">>, <<".*">>}, false); {ok, {ServiceName, ServiceID}} when is_binary(ServiceName), is_binary(ServiceID) -> - lookup_services(Domain, Upstream, Properties, {ServiceName, ServiceID, []}, false); - {ok, {ServiceName, ServiceTags}} when is_binary(ServiceName), is_list(ServiceTags) -> - lookup_services(Domain, Upstream, Properties, {ServiceName, undefined, ServiceTags}, false); - {ok, {ServiceName, ServiceID, ServiceTags}} when is_binary(ServiceName), is_binary(ServiceID), is_list(ServiceTags) -> + lookup_services(Domain, Upstream, Properties, {ServiceName, ServiceID, <<".*">>}, false); + {ok, {ServiceName, ServiceID, ServiceTags}} when is_binary(ServiceName), is_binary(ServiceID), is_binary(ServiceTags) -> lookup_services(Domain, Upstream, Properties, {ServiceName, ServiceID, ServiceTags}, false); {ok, {Host, Port}} when is_binary(Host), is_integer(Port) -> lookup_nodes(Domain, Upstream, Properties, [[{<<"ServiceHost">>, Host}, {<<"ServicePort">>, Port}]], false); @@ -216,3 +216,21 @@ matches(Subject, RE) -> lager:warning("Regexp failed: ~p", [Reason]), false end. + +build_script_vars(Req) -> + [ + {request, [ + {method, element(1, cowboyku_req:method(Req))}, + {domain, element(1, cowboyku_req:host(Req))}, + {port, element(1, cowboyku_req:port(Req))}, + {path, element(1, cowboyku_req:path(Req))}, + {query, element(1, cowboyku_req:qs_vals(Req))}, + {headers, element(1, cowboyku_req:headers(Req))}, + {cookies, element(1, cowboyku_req:cookies(Req))}, + {meta, [ + {request_id, element(1, cowboyku_req:meta(request_id, Req, nil))}, + {initial_host, element(1, cowboyku_req:meta(initial_host, Req, nil))}, + {host_capture, element(1, cowboyku_req:meta(host_capture, Req, []))} + ]} + ]} + ]. \ No newline at end of file diff --git a/apps/consul_proxy/src/consul_proxy_utils.erl b/apps/consul_proxy/src/consul_proxy_utils.erl index 6e80655..2faae06 100644 --- a/apps/consul_proxy/src/consul_proxy_utils.erl +++ b/apps/consul_proxy/src/consul_proxy_utils.erl @@ -158,8 +158,14 @@ detect_protocol(Req) -> end. -spec eval_script(Name :: binary(), Vars :: list()) -> {error, term()} | {ok, term()}. -eval_script(Name, Vars) -> - Key = <<"script:", Name/binary>>, +eval_script(Name, Vars) when byte_size(Name) > 4 -> + eval_script(Name, Vars, binary:part(Name, {byte_size(Name), -4})); +eval_script(Name, _Vars) -> + {error, {bad_script_name, Name}}. + +-spec eval_script(Name :: binary(), Vars :: list(), Type :: erl | lua) -> {error, term()} | {ok, term()}. +eval_script(Name, Vars, <<".erl">>) -> + Key = <<"erl_script:", Name/binary>>, Parsed = case cache_get(Key) of undefined -> case consul_client:get(<<"consul_proxy/scripts/", Name/binary>>) of @@ -187,12 +193,7 @@ eval_script(Name, Vars) -> {error, Reason1} -> {error, Reason1}; {ok, ExprList1} -> - Bindings = lists:foldl( - fun({K, V}, AccIn) -> - erl_eval:add_binding(K, V, AccIn); - (_, AccIn) -> - AccIn - end, erl_eval:new_bindings(), Vars), + Bindings = erl_eval:add_binding('Props', Vars, erl_eval:new_bindings()), try {value, Value, _} = erl_eval:exprs(ExprList1, Bindings), {ok, Value} @@ -202,7 +203,29 @@ eval_script(Name, Vars) -> lager:error("Eval of script '~s' failed~nStacktrace:~s", [Name, Stacktrace]), {error, {Class, ExceptionReason}} end - end. + end; +eval_script(Name, Vars, <<".lua">>) -> + case consul_client:get(<<"consul_proxy/scripts/", Name/binary>>) of + {error, Reason} -> + {error, Reason}; + {ok, Binary} -> + State = lists:foldl( + fun({Path, Value}, AccIn) -> + luerl:set_table(Path, Value, AccIn) + end, luerl:init(), vars_to_table([props], Vars)), + luerl:eval(Binary, State) + end; +eval_script(Name, _Vars, _Suffix) -> + {error, {unknown_language, Name}}. + +vars_to_table([], []) -> + []; +vars_to_table(Path, [{Key, Value} | Vars]) -> + vars_to_table(Path, Vars) ++ vars_to_table([Key | Path], Value); +vars_to_table(Path, Value) -> + [{lists:reverse(Path), Value}]. + + -spec normalize(jsx:json_term()) -> jsx:json_term(). normalize([{Key, Value} | Tuples]) -> [{normalize_key(Key), normalize(Value)} | normalize(Tuples)]; diff --git a/test/defaults.consul b/test/defaults.consul index b1c5dd1..e1eb12a 100644 --- a/test/defaults.consul +++ b/test/defaults.consul @@ -1,9 +1,11 @@ consul_proxy/domains/test.service.docker:ewogICJTZXJ2aWNlTmFtZSIgOiAidGVzdCIKfQ== consul_proxy/domains/consul.service.docker:ewogICJTZXJ2aWNlTmFtZSIgOiAiY29uc3VsIgp9 consul_proxy/domains/rewrite-example:ewogICJTZXJ2aWNlTmFtZSIgOiAiJDxzZXJ2aWNlPiIsCiAgIkFsaWFzZXMiIDogWwogICAgIig/PHNlcnZpY2U+LiopLXJld3JpdGVbLl1zZXJ2aWNlWy5dZG9ja2VyIgogIF0sCiAgIlJld3JpdGUiIDogWwogICAgWyJeL2FwaS8oLiopJCIsIi9pbmZvLnBocD9hcGk9JDEiXQogIF0KfQ== -consul_proxy/domains/resolver-example:ewogICJTZXJ2aWNlUmVzb2x2ZXIiIDogInJlc29sdmVyLWV4YW1wbGUuZXJsIiwKICAiQWxpYXNlcyIgOiBbCiAgICAiKD88c2VydmljZT4uKiktcmVzb2x2ZXJbLl1zZXJ2aWNlWy5dZG9ja2VyIgogIF0KfQ== -consul_proxy/scripts/resolver-example.erl:e0NhcHR1cmUsX30gPSBjb3dib3lrdV9yZXE6bWV0YShob3N0X2NhcHR1cmUsIFJlcSksCnByb3BsaXN0czpnZXRfdmFsdWUoPDwic2VydmljZSI+PiwgQ2FwdHVyZSku +consul_proxy/scripts/resolver-example.erl:UmVxdWVzdCA9IHByb3BsaXN0czpnZXRfdmFsdWUocmVxdWVzdCwgUHJvcHMsIFtdKSwKTWV0YSA9IHByb3BsaXN0czpnZXRfdmFsdWUobWV0YSwgUmVxdWVzdCwgW10pLApDYXB0dXJlID0gcHJvcGxpc3RzOmdldF92YWx1ZShob3N0X2NhcHR1cmUsIE1ldGEsIFtdKSwKcHJvcGxpc3RzOmdldF92YWx1ZSg8PCJzZXJ2aWNlIj4+LCBDYXB0dXJlKS4= consul_proxy/watchers/nodes:WwogICAgImh0dHBzOi8vdGVzdC5zZXJ2aWNlLmRvY2tlci9pbmZvLnBocCIKXQ== consul_proxy/watchers/services:WwogICAgImh0dHBzOi8vdGVzdC5zZXJ2aWNlLmRvY2tlci9pbmZvLnBocCIKXQ== consul_proxy/watchers/kv:WwogICAgImh0dHBzOi8vdGVzdC5zZXJ2aWNlLmRvY2tlci9pbmZvLnBocCIKXQ== consul_proxy/hijackers:WwogIHsKICAgICJ1c2VybmFtZSIgOiAiaGlqYWNrZXIiLAogICAgInBhc3N3b3JkIiA6ICIwdEhWdFNhOThrSGkyZStkVHVWdHo3S3lYWTgzVys3cGZ6eEZYd2VKWUtualcxOXRSeHBVbFFSV1lYbGI4V21YIiwKICAgICJkb21haW5zIiA6IFsKICAgICAgIi4qIgogICAgXQogIH0KXQ== +consul_proxy/domains/resolver-example-erl:ewogICJTZXJ2aWNlUmVzb2x2ZXIiIDogInJlc29sdmVyLWV4YW1wbGUuZXJsIiwKICAiQWxpYXNlcyIgOiBbCiAgICAiKD88c2VydmljZT4uKiktcmVzb2x2ZXItZXJsWy5dc2VydmljZVsuXWRvY2tlciIKICBdCn0= +consul_proxy/domains/resolver-example-lua:ewogICJTZXJ2aWNlUmVzb2x2ZXIiIDogInJlc29sdmVyLWV4YW1wbGUubHVhIiwKICAiQWxpYXNlcyIgOiBbCiAgICAiKD88c2VydmljZT4uKiktcmVzb2x2ZXItbHVhWy5dc2VydmljZVsuXWRvY2tlciIKICBdCn0= +consul_proxy/scripts/resolver-example.lua:cmV0dXJuIHByb3BzLnJlcXVlc3QubWV0YS5ob3N0X2NhcHR1cmUuc2VydmljZTs= -- GitLab