Skip to content

Instantly share code, notes, and snippets.

@rnewson
Last active August 29, 2015 14:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rnewson/8042d395d784d099a28f to your computer and use it in GitHub Desktop.
Save rnewson/8042d395d784d099a28f to your computer and use it in GitHub Desktop.
commit 52161b7b5cbf24bce42e82b28dc8a7f284e951ac
Author: Robert Newson <rnewson@apache.org>
Date: Wed Jun 17 14:41:50 2015 +0100
Add _node_config, an endpoint to configure specific nodes from any node
diff --git a/src/chttpd.erl b/src/chttpd.erl
index 5d1f4ee..19d01ed 100644
--- a/src/chttpd.erl
+++ b/src/chttpd.erl
@@ -366,7 +366,7 @@ url_handler("favicon.ico") -> fun chttpd_misc:handle_favicon_req/1;
url_handler("_utils") -> fun chttpd_misc:handle_utils_dir_req/1;
url_handler("_all_dbs") -> fun chttpd_misc:handle_all_dbs_req/1;
url_handler("_active_tasks") -> fun chttpd_misc:handle_task_status_req/1;
-url_handler("_config") -> fun chttpd_misc:handle_config_req/1;
+url_handler("_node_config") -> fun chttpd_misc:handle_node_config_req/1;
url_handler("_reload_query_servers") -> fun chttpd_misc:handle_reload_query_servers_req/1;
url_handler("_replicate") -> fun chttpd_misc:handle_replicate_req/1;
url_handler("_uuids") -> fun chttpd_misc:handle_uuids_req/1;
diff --git a/src/chttpd_misc.erl b/src/chttpd_misc.erl
index 3afa30c..65ddba6 100644
--- a/src/chttpd_misc.erl
+++ b/src/chttpd_misc.erl
@@ -14,7 +14,7 @@
-export([
handle_all_dbs_req/1,
- handle_config_req/1,
+ handle_node_config_req/1,
handle_favicon_req/1,
handle_favicon_req/2,
handle_replicate_req/1,
@@ -230,7 +230,7 @@ handle_uuids_req(Req) ->
% GET /_config/
% GET /_config
-handle_config_req(#httpd{method='GET', path_parts=[_]}=Req) ->
+handle_node_config_req(#httpd{method='GET', path_parts=[_, Node]}=Req) ->
Grouped = lists:foldl(fun({{Section, Key}, Value}, Acc) ->
case dict:is_key(Section, Acc) of
true ->
@@ -238,45 +238,60 @@ handle_config_req(#httpd{method='GET', path_parts=[_]}=Req) ->
false ->
dict:store(Section, [{list_to_binary(Key), list_to_binary(Value)}], Acc)
end
- end, dict:new(), config:all()),
+ end, dict:new(), rpc_config(Node, all, [])),
KVs = dict:fold(fun(Section, Values, Acc) ->
[{list_to_binary(Section), {Values}} | Acc]
end, [], Grouped),
send_json(Req, 200, {KVs});
% GET /_config/Section
-handle_config_req(#httpd{method='GET', path_parts=[_,Section]}=Req) ->
+handle_node_config_req(#httpd{method='GET', path_parts=[_, Node, Section]}=Req) ->
KVs = [{list_to_binary(Key), list_to_binary(Value)}
- || {Key, Value} <- config:get(Section)],
+ || {Key, Value} <- rpc_config(Node, get, [Section])],
send_json(Req, 200, {KVs});
% PUT /_config/Section/Key
% "value"
-handle_config_req(#httpd{method='PUT', path_parts=[_, Section, Key]}=Req) ->
+handle_node_config_req(#httpd{method='PUT', path_parts=[_, Node, Section, Key]}=Req) ->
Value = chttpd:json_body(Req),
Persist = chttpd:header_value(Req, "X-Couch-Persist") /= "false",
- OldValue = config:get(Section, Key, ""),
- ok = config:set(Section, Key, ?b2l(Value), Persist),
+ OldValue = rpc_config(Node, get, [Section, Key, ""]),
+ ok = rpc_config(Node, set, [Section, Key, ?b2l(Value), Persist]),
send_json(Req, 200, list_to_binary(OldValue));
% GET /_config/Section/Key
-handle_config_req(#httpd{method='GET', path_parts=[_, Section, Key]}=Req) ->
- case config:get(Section, Key, undefined) of
+handle_node_config_req(#httpd{method='GET', path_parts=[_, Node, Section, Key]}=Req) ->
+ case rpc_config(Node, get, [Section, Key, undefined]) of
undefined ->
throw({not_found, unknown_config_value});
Value ->
send_json(Req, 200, list_to_binary(Value))
end;
% DELETE /_config/Section/Key
-handle_config_req(#httpd{method='DELETE',path_parts=[_,Section,Key]}=Req) ->
+handle_node_config_req(#httpd{method='DELETE',path_parts=[_, Node, Section, Key]}=Req) ->
Persist = chttpd:header_value(Req, "X-Couch-Persist") /= "false",
- case config:get(Section, Key, undefined) of
+ case rpc_config(Node, get, [Section, Key, undefined]) of
undefined ->
throw({not_found, unknown_config_value});
OldValue ->
- config:delete(Section, Key, Persist),
+ rpc_config(Node, delete, [Section, Key, Persist]),
send_json(Req, 200, list_to_binary(OldValue))
end;
-handle_config_req(Req) ->
+handle_node_config_req(Req) ->
send_method_not_allowed(Req, "GET,PUT,DELETE").
+rpc_config(Node, Fun, Args) when is_binary(Node) ->
+ try
+ rpc_config(list_to_existing_atom(?b2l(Node)), Fun, Args)
+ catch
+ error:badarg ->
+ throw({no_such_node, Node})
+ end;
+rpc_config(Node, Fun, Args) when is_atom(Node) ->
+ case rpc:call(Node, config, Fun,Args) of
+ {badrpc, Reason} ->
+ throw(Reason);
+ Else ->
+ Else
+ end.
+
% Note: this resource is exposed on the backdoor interface, but it's in chttpd
% because it's not couch trunk
handle_system_req(Req) ->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment