From 0f018ea5dd678d37668c819552328b3254c2f220 Mon Sep 17 00:00:00 2001 From: matt-winkler <75497565+matt-winkler@users.noreply.github.com> Date: Wed, 26 May 2021 10:18:16 -0600 Subject: [PATCH] Bugfix/issue 3350 snowflake non json response (#3365) * attempt at solving with while loop * added comment on loop * update changelog * modified per drew's suggestions * updates after linting --- CHANGELOG.md | 2 ++ .../dbt/adapters/snowflake/connections.py | 25 ++++++++++++++++--- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9cd3022872..d92f5232e62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ - Separate `compiled_path` from `build_path`, and print the former alongside node error messages ([#1985](https://github.com/fishtown-analytics/dbt/issues/1985), [#3327](https://github.com/fishtown-analytics/dbt/pull/3327)) - Fix exception caused when running `dbt debug` with BigQuery connections ([#3314](https://github.com/fishtown-analytics/dbt/issues/3314), [#3351](https://github.com/fishtown-analytics/dbt/pull/3351)) - Raise better error if snapshot is missing required configurations ([#3381](https://github.com/fishtown-analytics/dbt/issues/3381), [#3385](https://github.com/fishtown-analytics/dbt/pull/3385)) +- Fix `dbt run` errors caused from receiving non-JSON responses from Snowflake with Oauth ([#3350](https://github.com/fishtown-analytics/dbt/issues/3350) ### Under the hood - Added logic for registry requests to raise a timeout error after a response hangs out for 30 seconds and 5 attempts have been made to reach the endpoint ([#3177](https://github.com/fishtown-analytics/dbt/issues/3177), [#3275](https://github.com/fishtown-analytics/dbt/pull/3275)) @@ -32,6 +33,7 @@ Contributors: - [@jaypeedevlin](https://github.com/jaypeedevlin) ([#2999](https://github.com/fishtown-analytics/dbt/issues/2999)) - [@PJGaetan](https://github.com/PJGaetan) ([#3315](https://github.com/fishtown-analytics/dbt/pull/3376)) - [@jnatkins](https://github.com/jnatkins) ([#3385](https://github.com/fishtown-analytics/dbt/pull/3385)) +- [@matt-winkler](https://github.com/matt-winkler) ([#3365](https://github.com/fishtown-analytics/dbt/pull/3365)) ## dbt 0.20.0b1 (May 03, 2021) diff --git a/plugins/snowflake/dbt/adapters/snowflake/connections.py b/plugins/snowflake/dbt/adapters/snowflake/connections.py index 4821cdaad09..81aab29ac41 100644 --- a/plugins/snowflake/dbt/adapters/snowflake/connections.py +++ b/plugins/snowflake/dbt/adapters/snowflake/connections.py @@ -5,6 +5,7 @@ from contextlib import contextmanager from dataclasses import dataclass from io import StringIO +from time import sleep from typing import Optional from cryptography.hazmat.backends import default_backend @@ -106,6 +107,7 @@ def _get_access_token(self) -> str: 'need a client ID a client secret, and a refresh token to get ' 'an access token' ) + # should the full url be a config item? token_url = _TOKEN_REQUEST_URL.format(self.account) # I think this is only used to redirect on success, which we ignore @@ -125,10 +127,25 @@ def _get_access_token(self) -> str: 'Authorization': f'Basic {auth}', 'Content-type': 'application/x-www-form-urlencoded;charset=utf-8' } - result = requests.post(token_url, headers=headers, data=data) - result_json = result.json() - if 'access_token' not in result_json: - raise DatabaseException(f'Did not get a token: {result_json}') + + result_json = None + max_iter = 20 + # Attempt to obtain JSON for 1 second before throwing an error + for i in range(max_iter): + result = requests.post(token_url, headers=headers, data=data) + try: + result_json = result.json() + break + except ValueError as e: + message = result.text + logger.debug(f"Got a non-json response ({result.status_code}): \ + {e}, message: {message}") + sleep(0.05) + + if result_json is None: + raise DatabaseException(f"""Did not receive valid json with access_token. + Showing json response: {result_json}""") + return result_json['access_token'] def _get_private_key(self):