From 1bfd38131e5cce61128a00ff610c8adfe342503b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Hedenstro=CC=88m?= <erik@hedenstroem.com> Date: Wed, 6 Apr 2016 20:29:02 +0200 Subject: [PATCH] Implemented regexp matching for service id and tags (fixes #10 and #11). --- README.md | 10 +++++ apps/consul_proxy/src/consul_proxy.app.src | 2 +- apps/consul_proxy/src/consul_proxy_router.erl | 40 +++++++++++++++---- rebar.config | 2 +- 4 files changed, 45 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 614b8e5..45e58e1 100644 --- a/README.md +++ b/README.md @@ -30,3 +30,13 @@ Todo ---- - Allow explicit setting of upstream/downstream headers + + +Domain descriptor +----------------- + +{ + "ServiceName" : "test", (String) + "ServiceID" : "fast", (Regexp) + "ServiceTags" : "fast" (Regexp) +} \ No newline at end of file diff --git a/apps/consul_proxy/src/consul_proxy.app.src b/apps/consul_proxy/src/consul_proxy.app.src index 7513d3a..418155c 100644 --- a/apps/consul_proxy/src/consul_proxy.app.src +++ b/apps/consul_proxy/src/consul_proxy.app.src @@ -1,6 +1,6 @@ {application, consul_proxy, [ {description, "Proxy for docker swarm using consul and vegur"}, - {vsn, "0.4.2"}, + {vsn, "0.4.3"}, {registered, []}, {mod, {consul_proxy_app, []}}, {applications, [ diff --git a/apps/consul_proxy/src/consul_proxy_router.erl b/apps/consul_proxy/src/consul_proxy_router.erl index ec3c8ca..fc373a6 100644 --- a/apps/consul_proxy/src/consul_proxy_router.erl +++ b/apps/consul_proxy/src/consul_proxy_router.erl @@ -94,9 +94,9 @@ lookup_services(Domain, Upstream, State) -> {Capture, Upstream1} = cowboyku_req:meta(host_capture, Upstream, []), InterpolatedProperties = consul_proxy_utils:string_interpolate(Properties, Capture, [<<"Rewrite">>]), ServiceName = proplists:get_value(<<"ServiceName">>, InterpolatedProperties), - ServiceID = proplists:get_value(<<"ServiceID">>, InterpolatedProperties), - ServiceTags = proplists:get_value(<<"ServiceTags">>, InterpolatedProperties, []), - case lookup_services(Domain, Upstream1, InterpolatedProperties, {ServiceName, ServiceID, ServiceTags}, true) of + ServiceIDRE = proplists:get_value(<<"ServiceID">>, InterpolatedProperties, <<".*">>), + ServiceTagsRE = proplists:get_value(<<"ServiceTags">>, InterpolatedProperties, <<".*">>), + case lookup_services(Domain, Upstream1, InterpolatedProperties, {ServiceName, ServiceIDRE, ServiceTagsRE}, true) of {ok, Services, true} -> consul_proxy_utils:cache_add(<<"services:", Domain/binary>>, {ok, Services}), {ok, Services, Upstream1, State}; @@ -112,17 +112,19 @@ lookup_services(Domain, Upstream, State) -> {ok, Services, Upstream, State} end. -lookup_services(Domain, Upstream, Properties, {undefined, _ServiceID, _ServiceTags}, CacheFlag) -> +lookup_services(Domain, Upstream, Properties, {undefined, _ServiceIDRE, _ServiceTagsRE}, CacheFlag) -> lookup_nodes(Domain, Upstream, Properties, proplists:get_value(<<"ServiceNodes">>, Properties), CacheFlag); -lookup_services(_Domain, _Upstream, _Properties, {ServiceName, _, _}, CacheFlag) -> +lookup_services(_Domain, _Upstream, _Properties, {ServiceName, ServiceIDRE, ServiceTagsRE}, CacheFlag) -> case consul_client:service(ServiceName) of {ok, Nodes} -> {ok, lists:foldr( fun(Node, Acc) -> ServiceID = proplists:get_value(<<"ServiceID">>, Node), - ServicePort = proplists:get_value(<<"ServicePort">>, Node, 80), + ServiceTags = proplists:get_value(<<"ServiceTags">>, Node), + ServiceMatches = matches(ServiceID, ServiceIDRE) and matches(ServiceTags, ServiceTagsRE), case get_ip_addresses(proplists:get_value(<<"ServiceAddress">>, Node)) of - [ServiceAddress] -> + [ServiceAddress] when ServiceMatches -> + ServicePort = proplists:get_value(<<"ServicePort">>, Node, 80), [{{service, ServiceName, ServiceID}, ServiceAddress, ServicePort} | Acc]; _ -> Acc @@ -190,3 +192,27 @@ get_ip_addresses(Host) -> lager:warning("Unable to lookup addresses for '~s': ~p", [Host, Reason]), [] end. + +matches(_Subject, <<".*">>) -> + true; +matches([], _RE) -> + false; +matches(undefined, _RE) -> + false; +matches([Subject | Subjects], RE) -> + case matches(Subject, RE) of + true -> + true; + false -> + matches(Subjects, RE) + end; +matches(Subject, RE) -> + case catch re:run(Subject, RE) of + {match, _} -> + true; + nomatch -> + false; + {'EXIT', Reason} -> + lager:warning("Regexp failed: ~p", [Reason]), + false + end. diff --git a/rebar.config b/rebar.config index 1ffb5ee..8a68d21 100644 --- a/rebar.config +++ b/rebar.config @@ -18,7 +18,7 @@ ]}. {relx, [ - {release, {consul_proxy, "0.4.2"}, [consul_proxy]}, {sys_config, "./config/sys.config"}, + {release, {consul_proxy, "0.4.3"}, [consul_proxy]}, {sys_config, "./config/sys.config"}, {vm_args, "./config/vm.args"}, {dev_mode, true}, {include_erts, false}, -- GitLab