Просмотр исходного кода

test(snowflake): fix tests after changes to health check

Recently, we started to try to check the provided credentials at creation time.  This
broke the tests against real snowflake.
Thales Macedo Garitezi 1 год назад
Родитель
Сommit
e6f4c3e53c

+ 39 - 0
apps/emqx_bridge_snowflake/docs/dev-quick-ref.md

@@ -116,6 +116,45 @@ alter user snowpipeuser set default_role = snowpipe;
 -- not required, but helps gather JWT failure reasons like skewed time
 grant monitor on account to role snowpipe;
 
+
+-- Create a role for the Snowpipe privileges, but missing write permissions to
+-- stage, so health check can happen but staging can't.
+
+CREATE USER IF NOT EXISTS snowpipe_ro_user
+    PASSWORD = 'TestUser99'
+    MUST_CHANGE_PASSWORD = FALSE;
+
+-- Set the RSA public key for 'testuser'
+-- Note: Remove the '-----BEGIN PUBLIC KEY-----' and '-----END PUBLIC KEY-----' lines from your PEM file,
+-- and include the remaining content below, preserving line breaks.
+
+ALTER USER snowpipe_ro_user SET RSA_PUBLIC_KEY = '
+<YOUR_PUBLIC_KEY_CONTENTS_LINE_1>
+<YOUR_PUBLIC_KEY_CONTENTS_LINE_2>
+<YOUR_PUBLIC_KEY_CONTENTS_LINE_3>
+<YOUR_PUBLIC_KEY_CONTENTS_LINE_4>
+';
+
+
+create or replace role snowpipe_ro;
+-- Grant the USAGE privilege on the database and schema that contain the pipe object.
+grant usage on database testdatabase to role snowpipe_ro;
+grant usage on schema testdatabase.public to role snowpipe_ro;
+-- Grant the SELECT privileges on the target table.
+grant  select on testdatabase.public.test0 to role snowpipe_ro;
+-- Grant the READ privilege on the internal stage.
+grant read on stage testdatabase.public.teststage0 to role snowpipe_ro;
+-- Grant the MONITOR privileges on the pipe object.
+grant monitor on pipe testdatabase.public.testpipe0 to role snowpipe_ro;
+-- Grant the role to a user
+grant role snowpipe_ro to user snowpipe_ro_user;
+-- Set the role as the default role for the user
+alter user snowpipe_ro_user set default_role = snowpipe_ro;
+
+---- OPTIONAL
+-- not required, but helps gather JWT failure reasons like skewed time
+grant monitor on account to role snowpipe_ro;
+
 ```
 
 ## Basic helper functions

+ 28 - 14
apps/emqx_bridge_snowflake/test/emqx_bridge_snowflake_SUITE.erl

@@ -33,6 +33,7 @@
 -define(WAREHOUSE, <<"testwarehouse">>).
 -define(PIPE, <<"testpipe0">>).
 -define(PIPE_USER, <<"snowpipeuser">>).
+-define(PIPE_USER_RO, <<"snowpipe_ro_user">>).
 
 -define(CONF_COLUMN_ORDER, ?CONF_COLUMN_ORDER([])).
 -define(CONF_COLUMN_ORDER(T), [
@@ -147,7 +148,7 @@ end_per_testcase(_Testcase, Config) ->
 timetrap(Config) ->
     case ?config(mock, Config) of
         true ->
-            {seconds, 10};
+            {seconds, 20};
         false ->
             {seconds, 150}
     end.
@@ -1050,28 +1051,42 @@ t_aggreg_invalid_column_values(Config0) ->
     ),
     ok.
 
-t_aggreg_inexistent_database(init, Config) when is_list(Config) ->
-    t_aggreg_inexistent_database(init, maps:from_list(Config));
-t_aggreg_inexistent_database(init, #{mock := true} = Config) ->
+%% Checks that we enqueue aggregated buffer errors if the delivery fails, and that
+%% reflects on the action status.
+t_aggreg_failed_delivery(init, Config) when is_list(Config) ->
+    t_aggreg_failed_delivery(init, maps:from_list(Config));
+t_aggreg_failed_delivery(init, #{mock := true} = Config) ->
     Mod = ?CONN_MOD,
-    meck:expect(Mod, do_stage_file, fun(
-        _ConnPid, _Filename, _Database, _Schema, _Stage, _ActionName
+    meck:expect(Mod, do_insert_files_request, fun(
+        _HTTPPool, _Req, _RequestTTL, _MaxRetries
     ) ->
-        Msg =
-            "SQL compilation error:, Database 'INEXISTENT' does not"
-            " exist or not authorized. SQLSTATE IS: 02000",
-        {error, Msg}
+        Headers = [
+            {<<"content-type">>, <<"application/json">>},
+            {<<"date">>, <<"Wed, 09 Oct 2024 13:12:55 GMT">>},
+            {<<"strict-transport-security">>, <<"max-age=31536000">>},
+            {<<"x-content-type-options">>, <<"nosniff">>},
+            {<<"x-frame-options">>, <<"deny">>},
+            {<<"content-length">>, <<"175">>},
+            {<<"connection">>, <<"keep-alive">>}
+        ],
+        Body = <<
+            "{\n  \"data\" : null,\n  \"code\" : \"390403\",\n  "
+            "\"message\" : \"Not authorized to manage the specified object. "
+            "Pipe access permission denied\",\n  \"success\" : false,\n  "
+            "\"headers\" : null\n}"
+        >>,
+        {ok, 403, Headers, Body}
     end),
     maps:to_list(Config);
-t_aggreg_inexistent_database(init, #{} = Config) ->
+t_aggreg_failed_delivery(init, #{} = Config) ->
     maps:to_list(Config).
-t_aggreg_inexistent_database(Config) ->
+t_aggreg_failed_delivery(Config) ->
     ?check_trace(
         emqx_bridge_v2_testlib:snk_timetrap(),
         begin
             {ok, _} = emqx_bridge_v2_testlib:create_bridge_api(
                 Config,
-                #{<<"parameters">> => #{<<"database">> => <<"inexistent">>}}
+                #{<<"parameters">> => #{<<"pipe_user">> => ?PIPE_USER_RO}}
             ),
             ActionResId = emqx_bridge_v2_testlib:bridge_id(Config),
             %% BeginMark = get_begin_mark(Config, ActionResId),
@@ -1186,4 +1201,3 @@ t_wrong_snowpipe_user(Config) ->
 %%       + Not supported when using pipes: `ABORT_STATEMENT'
 %%    - Missing data for a required column
 %% * Transient failure when staging file
-%% * Transient failure when calling `insertFiles'

+ 6 - 1
apps/emqx_connector_aggregator/src/emqx_connector_aggregator.erl

@@ -428,7 +428,12 @@ enqueue_status_error({upload_failed, Error}, St = #st{errors = QErrors}) ->
     %% TODO
     %% This code feels too specific, errors probably need classification.
     St#st{errors = queue:in(Error, QErrors)};
-enqueue_status_error(_AnotherError, St) ->
+enqueue_status_error(_AnotherError, St = #st{name = Name}) ->
+    ?SLOG(debug, #{
+        msg => "aggregated_buffer_error_not_enqueued",
+        error => _AnotherError,
+        action => Name
+    }),
     St.
 
 handle_take_error(St = #st{errors = QErrors0}) ->