diff --git a/src/couchbeam.erl b/src/couchbeam.erl index 5317c4b8..daf4970c 100644 --- a/src/couchbeam.erl +++ b/src/couchbeam.erl @@ -16,6 +16,9 @@ server_info/1, get_uuid/1, get_uuids/2, replicate/2, replicate/3, replicate/4, + get_config/1, get_config/2, get_config/3, + set_config/4, set_config/5, + delete_config/3, delete_config/4, all_dbs/1, all_dbs/2, db_exists/2, create_db/2, create_db/3, create_db/4, open_db/2, open_db/3, @@ -222,6 +225,45 @@ replicate(Server, Source, Target, Options) -> ], replicate(Server, {RepProp}). +%% @doc retrieve all the configuration from a couchdb node. +get_config(Server) -> + get_config(Server, <<>>, <<>>). + +%% @doc retrieve all the configuration from a section in the couchdb +%% config. +get_config(Server, Section) -> + get_config(Server, Section, <<>>). + +%% @doc retrieve a key value from the couchdb config +get_config(#server{url=ServerUrl, options=Opts}, Section, Key) -> + PathParts = [<<"_config">>, + hackney_bstr:to_binary(Section), + hackney_bstr:to_binary(Key)], + PathParts1 = [P || P <- PathParts, P /= <<>>], + + Url = hackney_url:make_url(ServerUrl, PathParts1, []), + Resp = couchbeam_httpc:db_request(get, Url, [], <<>>, Opts, [200]), + case Resp of + {ok, _, _, Ref} -> + {ok, couchbeam_httpc:json_body(Ref)}; + Error -> + Error + end. + +%% @doc set a key, value in the couchdb config +set_config(Server, Section, Key, Value) -> + set_config(Server, Section, Key, Value, true). + +set_config(Server, Section, Key, Value, Persist) -> + update_config(Server, Section, Key, Value, Persist, put). + +%% @doc delete a key from the couchdb config +delete_config(Server, Section, Key) -> + delete_config(Server, Section, Key, true). + +delete_config(Server, Section, Key, Persist) -> + update_config(Server, Section, Key, <<>>, Persist, delete). + %% @doc get list of databases on a CouchDB node %% @spec all_dbs(server()) -> {ok, iolist()} all_dbs(#server{}=Server) -> all_dbs(Server, []). @@ -1019,6 +1061,29 @@ maybe_docid(Server, {DocProps}) -> {DocProps} end. +update_config(#server{url=ServerUrl, options=Opts}, Section, Key, Value, + Persist, Method) -> + PathParts = [<<"_config">>, + hackney_bstr:to_binary(Section), + hackney_bstr:to_binary(Key)], + Url = hackney_url:make_url(ServerUrl, PathParts, []), + Headers = [{<<"Content-Type">>, <<"application/json">>}, + {<<"X-Couch-Persist">>, atom_to_binary(Persist, latin1)}], + + Body = case Method of + delete -> <<>>; + put -> couchbeam_ejson:encode(Value) + end, + + Resp = couchbeam_httpc:db_request(Method, Url, Headers, Body, Opts, + [200]), + case Resp of + {ok, _, _, Ref} -> + {ok, couchbeam_httpc:json_body(Ref)}; + Error -> + Error + end. + -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). @@ -1292,6 +1357,22 @@ replicate_test() -> ?assert(is_binary(InstanceStartTime)), ok. +config_test() -> + Server = couchbeam:server_connection(), + {ok, {AllConfig}} = couchbeam:get_config(Server), + ?assert(proplists:is_defined(<<"httpd">>, AllConfig)), + {ok, {HttpdConfig}} = couchbeam:get_config(Server, <<"httpd">>), + ?assert(proplists:is_defined(<<"port">>, HttpdConfig)), + {ok, Port} = couchbeam:get_config(Server, <<"httpd">>, <<"port">>), + ?assertEqual(<<"5984">>, Port), + ?assertMatch({ok, <<>>}, couchbeam:set_config(Server, <<"couchbeam">>,<<"test">>, <<"1">>, false)), + ?assertEqual({ok, <<"1">>}, couchbeam:get_config(Server, <<"couchbeam">>,<<"test">>)), + ?assertEqual({ok, <<"1">>}, couchbeam:set_config(Server, <<"couchbeam">>,<<"test">>, <<"2">>, false)), + ?assertEqual({ok, <<"2">>}, couchbeam:get_config(Server, <<"couchbeam">>, <<"test">>)), + ?assertEqual({ok, <<"2">>}, couchbeam:delete_config(Server, <<"couchbeam">>, <<"test">>, false)), + ?assertEqual({error, not_found}, couchbeam:get_config(Server, <<"couchbeam">>, <<"test">>)), + ok. + collect_mp({doc, Doc, Next}, Acc) -> collect_mp(couchbeam:stream_doc(Next), [{doc, Doc} | Acc]); collect_mp({att, Name, Next}, Acc) ->