Skip to content

Commit

Permalink
Merge pull request #4192 from esl/user-friendly-errors-internal-dbs
Browse files Browse the repository at this point in the history
User friendly errors for internal databases
  • Loading branch information
arcusfelis authored Dec 28, 2023
2 parents 8775cb9 + 0ff0376 commit 18d0bd5
Show file tree
Hide file tree
Showing 12 changed files with 352 additions and 101 deletions.
57 changes: 48 additions & 9 deletions big_tests/tests/graphql_cets_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@
-import(distributed_helper, [mim/0, mim2/0, rpc/4]).
-import(domain_helper, [host_type/1]).
-import(mongooseimctl_helper, [rpc_call/3]).
-import(graphql_helper, [execute_command/4, get_unauthorized/1, get_ok_value/2]).
-import(graphql_helper, [execute_command/4, get_unauthorized/1, get_ok_value/2, get_not_loaded/1]).

all() ->
[{group, admin_cets_cli},
{group, admin_cets_http},
{group, domain_admin_cets}].
{group, domain_admin_cets},
{group, cets_not_configured}].

groups() ->
[{admin_cets_http, [parallel], admin_cets_tests()},
{admin_cets_cli, [parallel], admin_cets_tests()},
{domain_admin_cets, [], domain_admin_tests()}].
{domain_admin_cets, [], domain_admin_tests()},
{cets_not_configured, [parallel], cets_not_configured_test()}].

admin_cets_tests() ->
[has_sm_table_in_info,
Expand All @@ -37,6 +39,10 @@ domain_admin_tests() ->
[domain_admin_get_table_info_test,
domain_admin_get_system_info_test].

cets_not_configured_test() ->
[get_table_info_not_configured_test,
get_system_info_not_configured_test].

init_per_suite(Config) ->
case rpc_call(mongoose_config, get_opt, [[internal_databases, cets, backend], undefined]) of
rdbms ->
Expand All @@ -46,24 +52,49 @@ init_per_suite(Config) ->
ok = rpc_call(cets_discovery, wait_for_ready, [mongoose_cets_discovery, 5000]),
Config2 ++ distributed_helper:require_rpc_nodes([mim, mim2]);
_ ->
{skip, "CETS is not configured with RDBMS"}
Config
end.

end_per_suite(Config) ->
ensure_bad_node_unregistered(),
escalus:end_per_suite(Config).
case rpc_call(mongoose_config, lookup_opt, [[internal_databases, cets, backend]]) of
{ok, rdbms} ->
ensure_bad_node_unregistered(),
escalus:end_per_suite(Config);
_ ->
ok
end.

init_per_group(admin_cets_http, Config) ->
graphql_helper:init_admin_handler(Config);
Config1 = graphql_helper:init_admin_handler(Config),
skip_if_cets_not_configured(Config1);
init_per_group(admin_cets_cli, Config) ->
graphql_helper:init_admin_cli(Config);
Config1 = graphql_helper:init_admin_cli(Config),
skip_if_cets_not_configured(Config1);
init_per_group(domain_admin_cets, Config) ->
graphql_helper:init_domain_admin_handler(Config).
Config1 = graphql_helper:init_domain_admin_handler(Config),
skip_if_cets_not_configured(Config1);
init_per_group(cets_not_configured, Config) ->
case rpc_call(mongoose_config, lookup_opt, [[internal_databases, cets]]) of
{error, not_found} ->
graphql_helper:init_admin_handler(Config);
{ok, _} ->
{skip, "CETS is configured"}
end.

end_per_group(cets_not_configured, _Config) ->
graphql_helper:clean();
end_per_group(_, _Config) ->
graphql_helper:clean(),
escalus_fresh:clean().

skip_if_cets_not_configured(Config) ->
case rpc_call(mongoose_config, lookup_opt, [[internal_databases, cets, backend]]) of
{ok, rdbms} ->
Config;
_ ->
{skip, "CETS is not configured with RDBMS"}
end.

init_per_testcase(has_sm_table_in_info, Config) ->
case rpc_call(ejabberd_sm, sm_backend, []) of
ejabberd_sm_cets ->
Expand Down Expand Up @@ -186,6 +217,14 @@ domain_admin_get_table_info_test(Config) ->
domain_admin_get_system_info_test(Config) ->
get_unauthorized(get_system_info(Config)).

% CETS not configured tests

get_table_info_not_configured_test(Config) ->
get_not_loaded(get_table_info(Config)).

get_system_info_not_configured_test(Config) ->
get_not_loaded(get_system_info(Config)).

%--------------------------------------------------------------------------------------------------
% Helpers
%--------------------------------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion big_tests/tests/graphql_helper.erl
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ get_listener_opts(EpName) ->

get_not_loaded(Resp) ->
?assertEqual(<<"deps_not_loaded">>, get_err_code(Resp)),
?assertEqual(<<"Some of required modules or services are not loaded">>, get_err_msg(Resp)).
?assertNotEqual(nomatch, binary:match(get_err_msg(Resp), <<"Some of the required">>)).

get_err_code(Resp) ->
get_value([extensions, code], get_error(1, Resp)).
Expand Down
4 changes: 2 additions & 2 deletions big_tests/tests/graphql_http_upload_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ user_http_upload_not_configured(Config) ->
user_http_upload_not_configured(Config, Alice) ->
Result = user_get_url(<<"test">>, 123, <<"Test">>, 123, Alice, Config),
?assertEqual(<<"deps_not_loaded">>, get_err_code(Result)),
?assertEqual(<<"Some of required modules or services are not loaded">>, get_err_msg(Result)).
?assertEqual(<<"Some of the required modules are not loaded">>, get_err_msg(Result)).

% Admin test cases

Expand Down Expand Up @@ -268,7 +268,7 @@ admin_http_upload_not_configured(Config) ->
admin_http_upload_not_configured(Config, Domain) ->
Result = admin_get_url(Domain, <<"test">>, 123, <<"Test">>, 123, Config),
?assertEqual(<<"deps_not_loaded">>, get_err_code(Result)),
?assertEqual(<<"Some of required modules or services are not loaded">>, get_err_msg(Result)).
?assertEqual(<<"Some of the required modules are not loaded">>, get_err_msg(Result)).

domain_admin_get_url_no_permission(Config) ->
Result1 = admin_get_url(<<"AAAAA">>, <<"test">>, 123, <<"Test">>, 123, Config),
Expand Down
77 changes: 70 additions & 7 deletions big_tests/tests/graphql_mnesia_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,22 @@
-import(mongooseimctl_helper, [rpc_call/3]).
-import(graphql_helper, [execute_command/4, execute_user_command/5, user_to_bin/1,
get_ok_value/2, get_err_code/1, get_err_value/2, get_unauthorized/1,
get_coercion_err_msg/1]).
get_coercion_err_msg/1, get_not_loaded/1]).

-record(mnesia_table_test, {key :: integer(), name :: binary()}).
-record(vcard, {us, vcard}).

all() ->
[{group, admin_mnesia_cli},
{group, admin_mnesia_http},
{group, domain_admin_mnesia}].
{group, domain_admin_mnesia},
{group, mnesia_not_configured}].

groups() ->
[{admin_mnesia_http, [sequence], admin_mnesia_tests()},
{admin_mnesia_cli, [sequence], admin_mnesia_tests()},
{domain_admin_mnesia, [], domain_admin_tests()}].
{domain_admin_mnesia, [], domain_admin_tests()},
{mnesia_not_configured, [parallel], mnesia_not_configured_tests()}].

admin_mnesia_tests() ->
[dump_mnesia_table_test,
Expand Down Expand Up @@ -64,6 +66,18 @@ domain_admin_tests() ->
domain_admin_set_master_test,
domain_admin_get_info_test].

mnesia_not_configured_tests() ->
[backup_not_configured_test,
change_nodename_not_configured_test,
dump_not_configured_test,
dump_table_not_configured_test,
install_fallback_not_configured_test,
load_not_configured_test,
restore_not_configured_test,
set_master_not_configured_test,
system_info_not_configured_test
].

init_per_suite(Config) ->
application:ensure_all_started(jid),
ok = mnesia:create_schema([node()]),
Expand All @@ -76,16 +90,33 @@ end_per_suite(_C) ->
mnesia:delete_schema([node()]).

init_per_group(admin_mnesia_http, Config) ->
graphql_helper:init_admin_handler(Config);
Config1 = graphql_helper:init_admin_handler(Config),
skip_if_mnesia_not_configured(Config1);
init_per_group(admin_mnesia_cli, Config) ->
graphql_helper:init_admin_cli(Config);
Config1 = graphql_helper:init_admin_cli(Config),
skip_if_mnesia_not_configured(Config1);
init_per_group(domain_admin_mnesia, Config) ->
graphql_helper:init_domain_admin_handler(Config).

Config1 = graphql_helper:init_domain_admin_handler(Config),
skip_if_mnesia_not_configured(Config1);
init_per_group(mnesia_not_configured, Config) ->
case rpc_call(mongoose_config, lookup_opt, [[internal_databases, mnesia]]) of
{error, not_found} ->
graphql_helper:init_admin_handler(Config);
{ok, _} ->
{skip, "Mnesia is configured"}
end.
end_per_group(_, _Config) ->
graphql_helper:clean(),
escalus_fresh:clean().

skip_if_mnesia_not_configured(Config) ->
case rpc_call(mongoose_config, lookup_opt, [[internal_databases, mnesia]]) of
{error, not_found} ->
{skip, "Mnesia is not configured"};
{ok, _} ->
Config
end.

% Admin tests

dump_mnesia_table_test(Config) ->
Expand Down Expand Up @@ -313,6 +344,38 @@ domain_admin_set_master_test(Config) ->
domain_admin_get_info_test(Config) ->
get_unauthorized(get_info([<<"running_db_nodes">>], Config)).

backup_not_configured_test(Config) ->
Filename = <<"backup_not_configured_test">>,
get_not_loaded(backup_mnesia(Filename, Config)).

change_nodename_not_configured_test(Config) ->
Filename1 = <<"change_nodename_not_configured_test">>,
Filename2 = <<"change_nodename2_not_configured_test">>,
ChangeFrom = <<"mongooseim@localhost">>,
ChangeTo = <<"change_nodename_not_configured_test@localhost">>,
get_not_loaded(change_nodename(ChangeFrom, ChangeTo, Filename1, Filename2, Config)).

dump_not_configured_test(Config) ->
get_not_loaded(dump_mnesia(<<"File">>, Config)).

dump_table_not_configured_test(Config) ->
get_not_loaded(dump_mnesia_table(<<"File">>, <<"mnesia_table_test">>, Config)).

install_fallback_not_configured_test(Config) ->
get_not_loaded(install_fallback(<<"Path">>, Config)).

load_not_configured_test(Config) ->
get_not_loaded(load_mnesia(<<"Path">>, Config)).

restore_not_configured_test(Config) ->
get_not_loaded(restore_mnesia(<<"Path">>, Config)).

set_master_not_configured_test(Config) ->
get_not_loaded(set_master(mim(), Config)).

system_info_not_configured_test(Config) ->
get_not_loaded(get_info([<<"running_db_nodes">>], Config)).

%--------------------------------------------------------------------------------------------------
% Helpers
%--------------------------------------------------------------------------------------------------
Expand Down
6 changes: 3 additions & 3 deletions priv/graphql/schemas/admin/cets.gql
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
"Allow admin to get information about CETS status"
type CETSAdminQuery @protected{
type CETSAdminQuery @use(internal_databases: ["cets"]) @protected{
"Get a list of tables from the local node"
tableInfo: [CETSTableInfo]
@protected(type: GLOBAL)
@protected(type: GLOBAL) @use
"Get status of CETS"
systemInfo: CETSSystemInfo
@protected(type: GLOBAL)
@protected(type: GLOBAL) @use
}

type CETSTableInfo {
Expand Down
22 changes: 11 additions & 11 deletions priv/graphql/schemas/admin/mnesia.gql
Original file line number Diff line number Diff line change
@@ -1,44 +1,44 @@
"""
Allow admin to acquire information about mnesia database
"""
type MnesiaAdminQuery @protected{
type MnesiaAdminQuery @use(internal_databases: ["mnesia"]) @protected{
"""
Get the information about appropriate mnesia property for a specified key,
if no keys are provided all the available properties will be returned
"""
systemInfo(keys: [String!]): [MnesiaInfo]
@protected(type: GLOBAL)
@protected(type: GLOBAL) @use
}

"""
Allow admin to backup, dump, load, restore and modify mnesia database
"""
type MnesiaAdminMutation @protected{
type MnesiaAdminMutation @use(internal_databases: ["mnesia"]) @protected{
"Set mnesia's master node"
setMaster(node: NodeName!): String
@protected(type: GLOBAL)
@protected(type: GLOBAL) @use
"Change nodename from 'fromString' to 'toString' in 'source' backup file and create new 'target' backup file"
changeNodename(fromString: NodeName!, toString: NodeName!,
source: String!, target: String!): String
@protected(type: GLOBAL)
@protected(type: GLOBAL) @use
"Save mnesia backup to file 'path'"
backup(path: String!): String
@protected(type: GLOBAL)
@protected(type: GLOBAL) @use
"Restore mnesia backup from file 'path'"
restore(path: String!): String
@protected(type: GLOBAL)
@protected(type: GLOBAL) @use
"Dump mnesia to file 'path'"
dump(path: String!): String
@protected(type: GLOBAL)
@protected(type: GLOBAL) @use
"Dump mnesia table 'table' to file 'path'"
dumpTable(path: String!, table: String!): String
@protected(type: GLOBAL)
@protected(type: GLOBAL) @use
"Load mnesia from file 'path' that was previously dumped"
load(path: String!): String
@protected(type: GLOBAL)
@protected(type: GLOBAL) @use
"Install mnesia fallback"
installFallback(path: String!): String
@protected(type: GLOBAL)
@protected(type: GLOBAL) @use
}

union MnesiaInfo = MnesiaStringResponse | MnesiaListResponse | MnesiaIntResponse
Expand Down
2 changes: 2 additions & 0 deletions priv/graphql/schemas/global/use_dir.gql
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ directive @use(
modules: [String!] = [],
"The list of services used by the category or command"
services: [String!] = [],
"The list of internal databases used by the category or command"
internal_databases: [String!] = [],
"The name of argument that contains domain or host type"
arg: String) on FIELD_DEFINITION | OBJECT
Loading

0 comments on commit 18d0bd5

Please sign in to comment.