diff options
author | Nick Vatamaniuc <vatamane@apache.org> | 2019-04-23 18:36:35 -0400 |
---|---|---|
committer | Nick Vatamaniuc <nickva@users.noreply.github.com> | 2019-04-23 19:31:20 -0400 |
commit | 3a54280670704c96f8628eb7cfe926f6f2e414e0 (patch) | |
tree | 07c637db7777526ff35b37123be4ec1a5890078d | |
parent | b1f65df8b1b0b425563e9b33c84bb8228de21578 (diff) | |
download | couchdb-3a54280670704c96f8628eb7cfe926f6f2e414e0.tar.gz |
Allow restricting resharding parameters
To avoid inadvertently splitting all the shards in all the ranges due to user
error, introduce an option enforce the presence of node and range job creation
parameters.
-rw-r--r-- | src/mem3/src/mem3_reshard_api.erl | 22 | ||||
-rw-r--r-- | src/mem3/test/mem3_reshard_api_test.erl | 29 |
2 files changed, 51 insertions, 0 deletions
diff --git a/src/mem3/src/mem3_reshard_api.erl b/src/mem3/src/mem3_reshard_api.erl index f39df4cbb..0d3377db7 100644 --- a/src/mem3/src/mem3_reshard_api.erl +++ b/src/mem3/src/mem3_reshard_api.erl @@ -166,13 +166,17 @@ get_reason(StateProps) when is_list(StateProps) -> pick_shards(undefined, undefined, Db, undefined) when is_binary(Db) -> + check_node_required(), + check_range_required(), mem3:shards(Db); pick_shards(Node, undefined, Db, undefined) when is_atom(Node), is_binary(Db) -> + check_range_required(), [S || S <- mem3:shards(Db), mem3:node(S) == Node]; pick_shards(undefined, undefined, Db, [_B, _E] = Range) when is_binary(Db) -> + check_node_required(), [S || S <- mem3:shards(Db), mem3:range(S) == Range]; pick_shards(Node, undefined, Db, [_B, _E] = Range) when is_atom(Node), @@ -180,6 +184,7 @@ pick_shards(Node, undefined, Db, [_B, _E] = Range) when is_atom(Node), [S || S <- mem3:shards(Db), mem3:node(S) == Node, mem3:range(S) == Range]; pick_shards(undefined, Shard, undefined, undefined) when is_binary(Shard) -> + check_node_required(), Db = mem3:dbname(Shard), [S || S <- mem3:shards(Db), mem3:name(S) == Shard]; @@ -193,3 +198,20 @@ pick_shards(_, undefined, undefined, _) -> pick_shards(_, Db, Shard, _) when is_binary(Db), is_binary(Shard) -> throw({bad_request, <<"`db` and `shard` are mutually exclusive">>}). + + +check_node_required() -> + case config:get_boolean("reshard", "require_node_param", false) of + true -> + throw({bad_request, <<"`node` prameter is required">>}); + false -> + ok + end. + +check_range_required() -> + case config:get_boolean("reshard", "require_range_param", false) of + true -> + throw({bad_request, <<"`range` prameter is required">>}); + false -> + ok + end. diff --git a/src/mem3/test/mem3_reshard_api_test.erl b/src/mem3/test/mem3_reshard_api_test.erl index c8be28591..982fed173 100644 --- a/src/mem3/test/mem3_reshard_api_test.erl +++ b/src/mem3/test/mem3_reshard_api_test.erl @@ -49,6 +49,8 @@ teardown({Url, {Db1, Db2, Db3}}) -> delete_db(Url, Db2), delete_db(Url, Db3), ok = config:delete("reshard", "max_jobs", _Persist=false), + ok = config:delete("reshard", "require_node_param", _Persist=false), + ok = config:delete("reshard", "require_range_param", _Persist=false), ok = config:delete("admins", ?USER, _Persist=false), meck:unload(). @@ -99,6 +101,7 @@ mem3_reshard_api_test_() -> fun recover_in_topoff3/1, fun recover_in_source_delete/1, fun check_max_jobs/1, + fun check_node_and_range_required_params/1, fun cleanup_completed_jobs/1 ] } @@ -678,6 +681,32 @@ check_max_jobs({Top, {Db1, Db2, _}}) -> end). +check_node_and_range_required_params({Top, {Db1, _, _}}) -> + ?_test(begin + Jobs = Top ++ ?JOBS, + + Node = atom_to_binary(node(), utf8), + Range = <<"00000000-ffffffff">>, + + config:set("reshard", "require_node_param", "true", _Persist=false), + {C1, R1} = req(post, Jobs, #{type => split, db => Db1}), + NodeRequiredErr = <<"`node` prameter is required">>, + ?assertEqual({400, #{<<"error">> => <<"bad_request">>, + <<"reason">> => NodeRequiredErr}}, {C1, R1}), + + config:set("reshard", "require_range_param", "true", _Persist=false), + {C2, R2} = req(post, Jobs, #{type => split, db => Db1, node => Node}), + RangeRequiredErr = <<"`range` prameter is required">>, + ?assertEqual({400, #{<<"error">> => <<"bad_request">>, + <<"reason">> => RangeRequiredErr}}, {C2, R2}), + + Body = #{type => split, db => Db1, range => Range, node => Node}, + {C3, R3} = req(post, Jobs, Body), + ?assertMatch({201, [#{?OK := true}]}, {C3, R3}), + wait_to_complete_then_cleanup(Top, R3) + end). + + cleanup_completed_jobs({Top, {Db1, _, _}}) -> ?_test(begin Body = #{type => split, db => Db1}, |