diff --git a/apps/emqx_bridge_cassandra/src/emqx_bridge_cassandra_connector.erl b/apps/emqx_bridge_cassandra/src/emqx_bridge_cassandra_connector.erl index afea652ef..e29dc7931 100644 --- a/apps/emqx_bridge_cassandra/src/emqx_bridge_cassandra_connector.erl +++ b/apps/emqx_bridge_cassandra/src/emqx_bridge_cassandra_connector.erl @@ -70,7 +70,7 @@ cassandra_db_fields() -> {keyspace, fun keyspace/1}, {pool_size, fun emqx_connector_schema_lib:pool_size/1}, {username, fun emqx_connector_schema_lib:username/1}, - {password, fun emqx_connector_schema_lib:password/1}, + {password, emqx_connector_schema_lib:password_field()}, {auto_reconnect, fun emqx_connector_schema_lib:auto_reconnect/1} ]. @@ -111,14 +111,14 @@ on_start( emqx_schema:parse_servers(Servers0, ?DEFAULT_SERVER_OPTION) ), - Options = [ - {nodes, Servers}, - {keyspace, Keyspace}, - {auto_reconnect, ?AUTO_RECONNECT_INTERVAL}, - {pool_size, PoolSize} - ], - Options1 = maybe_add_opt(username, Config, Options), - Options2 = maybe_add_opt(password, Config, Options1, _IsSensitive = true), + Options = + maps:to_list(maps:with([username, password], Config)) ++ + [ + {nodes, Servers}, + {keyspace, Keyspace}, + {auto_reconnect, ?AUTO_RECONNECT_INTERVAL}, + {pool_size, PoolSize} + ], SslOpts = case maps:get(enable, SSL) of @@ -131,7 +131,7 @@ on_start( [] end, State = parse_prepare_cql(Config), - case emqx_resource_pool:start(InstId, ?MODULE, Options2 ++ SslOpts) of + case emqx_resource_pool:start(InstId, ?MODULE, Options ++ SslOpts) of ok -> {ok, init_prepare(State#{pool_name => InstId, prepare_statement => #{}})}; {error, Reason} -> @@ -387,6 +387,7 @@ conn_opts(Opts) -> conn_opts([], Acc) -> Acc; conn_opts([{password, Password} | Opts], Acc) -> + %% TODO: teach `ecql` to accept 0-arity closures as passwords. conn_opts(Opts, [{password, emqx_secret:unwrap(Password)} | Acc]); conn_opts([Opt | Opts], Acc) -> conn_opts(Opts, [Opt | Acc]). @@ -512,19 +513,3 @@ maybe_assign_type(V) when is_integer(V) -> maybe_assign_type(V) when is_float(V) -> {double, V}; maybe_assign_type(V) -> V. - -maybe_add_opt(Key, Conf, Opts) -> - maybe_add_opt(Key, Conf, Opts, _IsSensitive = false). - -maybe_add_opt(Key, Conf, Opts, IsSensitive) -> - case Conf of - #{Key := Val} -> - [{Key, maybe_wrap(IsSensitive, Val)} | Opts]; - _ -> - Opts - end. - -maybe_wrap(false = _IsSensitive, Val) -> - Val; -maybe_wrap(true, Val) -> - emqx_secret:wrap(Val). diff --git a/apps/emqx_bridge_cassandra/test/emqx_bridge_cassandra_connector_SUITE.erl b/apps/emqx_bridge_cassandra/test/emqx_bridge_cassandra_connector_SUITE.erl index fcd482b47..de306e3f0 100644 --- a/apps/emqx_bridge_cassandra/test/emqx_bridge_cassandra_connector_SUITE.erl +++ b/apps/emqx_bridge_cassandra/test/emqx_bridge_cassandra_connector_SUITE.erl @@ -40,10 +40,9 @@ all() -> ]. groups() -> - TCs = emqx_common_test_helpers:all(?MODULE), [ - {auth, TCs}, - {noauth, TCs} + {auth, [t_lifecycle, t_start_passfile]}, + {noauth, [t_lifecycle]} ]. cassandra_servers(CassandraHost) -> @@ -115,32 +114,37 @@ end_per_testcase(_, _Config) -> t_lifecycle(Config) -> perform_lifecycle_check( - <<"emqx_connector_cassandra_SUITE">>, + <>, cassandra_config(Config) ). -show(X) -> - erlang:display(X), - X. - -show(Label, What) -> - erlang:display({Label, What}), - What. +t_start_passfile(Config) -> + ResourceID = atom_to_binary(?FUNCTION_NAME), + PasswordFilename = filename:join(?config(priv_dir, Config), "passfile"), + ok = file:write_file(PasswordFilename, ?CASSA_PASSWORD), + InitialConfig = emqx_utils_maps:deep_merge( + cassandra_config(Config), + #{ + <<"config">> => #{ + password => iolist_to_binary(["file://", PasswordFilename]) + } + } + ), + ?assertMatch( + #{status := connected}, + create_local_resource(ResourceID, check_config(InitialConfig)) + ), + ?assertEqual( + ok, + emqx_resource:remove_local(ResourceID) + ). perform_lifecycle_check(ResourceId, InitialConfig) -> - {ok, #{config := CheckedConfig}} = - emqx_resource:check_config(?CASSANDRA_RESOURCE_MOD, InitialConfig), - {ok, #{ + CheckedConfig = check_config(InitialConfig), + #{ state := #{pool_name := PoolName} = State, status := InitialStatus - }} = - emqx_resource:create_local( - ResourceId, - ?CONNECTOR_RESOURCE_GROUP, - ?CASSANDRA_RESOURCE_MOD, - CheckedConfig, - #{} - ), + } = create_local_resource(ResourceId, CheckedConfig), ?assertEqual(InitialStatus, connected), % Instance should match the state and status of the just started resource {ok, ?CONNECTOR_RESOURCE_GROUP, #{ @@ -191,6 +195,21 @@ perform_lifecycle_check(ResourceId, InitialConfig) -> %% utils %%-------------------------------------------------------------------- +check_config(Config) -> + {ok, #{config := CheckedConfig}} = emqx_resource:check_config(?CASSANDRA_RESOURCE_MOD, Config), + CheckedConfig. + +create_local_resource(ResourceId, CheckedConfig) -> + {ok, Bridge} = + emqx_resource:create_local( + ResourceId, + ?CONNECTOR_RESOURCE_GROUP, + ?CASSANDRA_RESOURCE_MOD, + CheckedConfig, + #{} + ), + Bridge. + cassandra_config(Config) -> Host = ?config(cassa_host, Config), AuthOpts = maps:from_list(?config(cassa_auth_opts, Config)),