Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(bigquery): Custom message when Service Account doesnt have the correct Roles and Permissions #21838

Merged
merged 5 commits into from
Oct 26, 2022

Conversation

Antonio-RiveroMartnez
Copy link
Member

SUMMARY

BigQuery is now returning the project name twice in the error message when connecting, which breaks the Regex in the custom_errors dictionary, so we need to adjust it in order to stop displaying the general connection failed message. Also, we are updating the message displayed to users and the tests.

Additionally, in order to actually being able to catch the right error, we are raising the exceptions with their original message instead of the default one, otherwise the exception handler will ignore it and display the default message.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

Before:
error

After:
test

TESTING INSTRUCTIONS

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags:
  • Changes UI
  • Includes DB Migration (follow approval process in SIP-59)
    • Migration is atomic, supports rollback & is backwards-compatible
    • Confirm DB migration upgrade and downgrade tested
    • Runtime estimates and downtime expectations provided
  • Introduces new feature or API
  • Removes existing feature or API

@Antonio-RiveroMartnez Antonio-RiveroMartnez changed the title chore(bigquery): Custom message when Service Account doesnt have the correct Roles and Permissions feat(bigquery): Custom message when Service Account doesnt have the correct Roles and Permissions Oct 17, 2022
@codecov
Copy link

codecov bot commented Oct 17, 2022

Codecov Report

Merging #21838 (5a11829) into master (fa67315) will decrease coverage by 11.35%.
The diff coverage is 35.71%.

@@             Coverage Diff             @@
##           master   #21838       +/-   ##
===========================================
- Coverage   66.95%   55.59%   -11.36%     
===========================================
  Files        1807     1807               
  Lines       69182    69212       +30     
  Branches     7402     7402               
===========================================
- Hits        46319    38479     -7840     
- Misses      20952    28822     +7870     
  Partials     1911     1911               
Flag Coverage Δ
hive 52.91% <28.57%> (-0.02%) ⬇️
mysql ?
postgres ?
presto 52.81% <28.57%> (-0.02%) ⬇️
python 57.96% <35.71%> (-23.54%) ⬇️
sqlite ?
unit 51.09% <35.71%> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
superset/db_engine_specs/bigquery.py 54.35% <ø> (-27.70%) ⬇️
superset/databases/commands/create.py 67.92% <25.00%> (-23.92%) ⬇️
superset/databases/commands/test_connection.py 64.00% <33.33%> (-34.64%) ⬇️
superset/databases/api.py 53.29% <50.00%> (-42.24%) ⬇️
superset/utils/dashboard_import_export.py 0.00% <0.00%> (-100.00%) ⬇️
superset/tags/core.py 4.54% <0.00%> (-95.46%) ⬇️
superset/key_value/commands/update.py 0.00% <0.00%> (-90.91%) ⬇️
superset/key_value/commands/delete.py 0.00% <0.00%> (-87.88%) ⬇️
superset/key_value/commands/delete_expired.py 0.00% <0.00%> (-84.00%) ⬇️
superset/dashboards/commands/importers/v0.py 15.62% <0.00%> (-76.25%) ⬇️
... and 287 more

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

# so we try to return the message from the errors instead of using the
# default message
error_list: List[SupersetError] = ex.errors
for error in error_list:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of doing a loop can we just do set check?

if SupersetErrorType.CONNECTION_DATABASE_PERMISSIONS_ERROR in error_list

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm error_list contains a list of SupersetError, while SupersetErrorType.CONNECTION_DATABASE_PERMISSIONS_ERROR is just a enum, that comparison won't work. Reducing error_list would also require iterating over the list, so, let me see if there's a more "Pythonic" way of checking without looping. But right now, I don't see how to get to the error_type for each item in the list without somehow looping over the list.

error.error_type
== SupersetErrorType.CONNECTION_DATABASE_PERMISSIONS_ERROR
):
raise DatabaseConnectionFailedError(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we just raise the original DatabaseTestConnectionFailedError

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated. I am catching the new exception type in the API now along with sending back to the user a dict with the error messages instead of just raw strings.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you show me the diff between the payload coming back from the API when you send DatabaseConnectionFailedError vs the original exception?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before I was raising DatabaseConnectionFailedError which only has one error in it, so the API response would look like:
{message: '<message_here>'} while now I'm just throwing the original exception (DatabaseTestConnectionFailed) which has a list of errors, so the API would respond with a dict like: {[error_type]: [error_message], [error_type_2]: [error_message_2], ...} which is already a known pattern to the DatabaseModal for error displaying.

So basically after the change based on the input you gave me, I'm doing the latter.

For example:

Before when throwing a DatabaseConnectionFailedError the API would respond:

422
{ 
message: 'Unable to connect. Verify that the following roles are set on the service account: "BigQuery Data Viewer", "BigQuery Metadata Viewer", "BigQuery Job User" and the following permissions are set "bigquery.readsessions.create", "bigquery.readsessions.getData"' 
}

And now throwing the original DatabaseTestConnectionFailed it looks like:

422
{ 
CONNECTION_DATABASE_PERMISSIONS_ERROR: 'Unable to connect. Verify that the following roles are set on the service account: "BigQuery Data Viewer", "BigQuery Metadata Viewer", "BigQuery Job User" and the following permissions are set "bigquery.readsessions.create", "bigquery.readsessions.getData"',
...
<other_errors_here>
}

Copy link
Member

@jinghua-qa jinghua-qa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Able to see the custom msg for error msg. LGTM

    - Start sending the message from test connection exceptions instead of a generic exception with no message in it
    - Update the regex CONNECTION_DATABASE_PERMISSIONS_REGEX because google is sending the project name twice now
    - Update tests
- Add the original message ONLY for CONNECTION_DATABASE_PERMISSIONS_ERROR error types so we can keep using the default message for other cases used in other places like tests
- Raise the original DatabaseTestConnectionFailedError exception instead of a new one.
- Adding normalized_messages method in SupersetErrorsException since the to_dict is not useful for getting the right message to users
- Raise the original DatabaseConnectionFailedError from the test command with the right message when necessary
- Remove the unnecessary code changes to handle multiple errors or DatabaseTestConnectionFailedError exceptions
engine=self._properties.get("sqlalchemy_uri", "").split(":")[0],
)
# So we can show the original message
raise ex
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Original message -> Custom message after extracting the error.
Otherwise the DatabaseConnectionFailedError would have the default Connection failed ... message caught from below.

@hughhhh hughhhh self-requested a review October 26, 2022 17:31
        - Send a SupersetErrorsException instead of Test one since in the future we will be raising just superset exceptions
        - Update testsq
@@ -145,7 +152,7 @@ def ping(engine: Engine) -> bool:
)
# check for custom errors (wrong username, wrong password, etc)
errors = database.db_engine_spec.extract_errors(ex, context)
raise DatabaseTestConnectionFailedError(errors) from ex
raise SupersetErrorsException(errors) from ex
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Antonio-RiveroMartnez I'm looking into some 500 errors for test connections, and I saw this change. What would happen if I were to change this back to raise the DatabaseTestConnectionFailedError which is a 422? Would it break anything from this PR? I checked through the implementation and it looks like it should still catch the SupersetErrorsExceptions because it is the base class, but I wanted to see if I might be missing anything here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @eschutho, the problem of doing that is that we would lost the original message and instead the message from DatabaseTestConnectionFailedError would be used (Connection failed, please check your connection settings) and not the custom message with roles after parsing the original message.

@mistercrunch mistercrunch added 🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels 🚢 2.1.0 and removed 🚢 2.1.3 labels Mar 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels size/L 🚢 2.1.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants