Repository: dbt-labs/dbt-redshift
Pull request #496 (2023-06-15 16:21:19)

[Backport 1.5.latest] Pass `region` param on to redshift conn as is
Backport cbb45ca585a61b1bb250b48aac69c410f8ef4efb from #485.


Patch:
diff --git a/.changes/unreleased/Fixes-20230612-114853.yaml b/.changes/unreleased/Fixes-20230612-114853.yaml
new file mode 100644
index 00000000..1650c570
--- /dev/null
+++ b/.changes/unreleased/Fixes-20230612-114853.yaml
@@ -0,0 +1,6 @@
+kind: Fixes
+body: remove requirement for region param
+time: 2023-06-12T11:48:53.980327-07:00
+custom:
+  Author: colin-rogers-dbt
+  Issue: "484"
diff --git a/dbt/adapters/redshift/connections.py b/dbt/adapters/redshift/connections.py
index c29f3ab0..93bc798a 100644
--- a/dbt/adapters/redshift/connections.py
+++ b/dbt/adapters/redshift/connections.py
@@ -7,8 +7,6 @@ from dataclasses import dataclass, field
 import agate
 import sqlparse
 import redshift_connector
-import urllib.request
-import json
 from redshift_connector.utils.oids import get_datatype_name
 
 from dbt.adapters.sql import SQLConnectionManager
@@ -48,23 +46,6 @@ class IAMDurationEncoder(FieldEncoder):
 dbtClassMixin.register_field_encoders({IAMDuration: IAMDurationEncoder()})
 
 
-def _get_aws_regions():
-    # Extract the prefixes from the AWS IP ranges JSON to determine the available regions
-    url = "https://ip-ranges.amazonaws.com/ip-ranges.json"
-    response = urllib.request.urlopen(url)
-    data = json.loads(response.read().decode())
-    regions = set()
-
-    for prefix in data["prefixes"]:
-        if prefix["service"] == "AMAZON":
-            regions.add(prefix["region"])
-
-    return regions
-
-
-_AVAILABLE_AWS_REGIONS = _get_aws_regions()
-
-
 class RedshiftConnectionMethod(StrEnum):
     DATABASE = "database"
     IAM = "iam"
@@ -149,7 +130,7 @@ class RedshiftCredentials(Credentials):
     role: Optional[str] = None
     sslmode: Optional[UserSSLMode] = field(default_factory=UserSSLMode.default)
     retries: int = 1
-    region: Optional[str] = None  # if not provided, will be determined from host
+    region: Optional[str] = None
     # opt-in by default per team deliberation on https://peps.python.org/pep-0249/#autocommit
     autocommit: Optional[bool] = True
 
@@ -178,13 +159,6 @@ class RedshiftCredentials(Credentials):
         return self.host
 
 
-def _is_valid_region(region):
-    if region is None or len(region) == 0:
-        logger.warning("Couldn't determine AWS regions. Skipping validation to avoid blocking.")
-        return True
-    return region in _AVAILABLE_AWS_REGIONS
-
-
 class RedshiftConnectMethodFactory:
     credentials: RedshiftCredentials
 
@@ -202,23 +176,6 @@ class RedshiftConnectMethodFactory:
             "region": self.credentials.region,
             "timeout": self.credentials.connect_timeout,
         }
-        if kwargs["region"] is None:
-            logger.debug("No region provided, attempting to determine from host.")
-            try:
-                region_value = self.credentials.host.split(".")[2]
-            except IndexError:
-                raise dbt.exceptions.FailedToConnectError(
-                    "No region provided and unable to determine region from host: "
-                    "{}".format(self.credentials.host)
-                )
-
-            kwargs["region"] = region_value
-
-        # Validate the set region
-        if not _is_valid_region(kwargs["region"]):
-            raise dbt.exceptions.FailedToConnectError(
-                "Invalid region provided: {}".format(kwargs["region"])
-            )
 
         redshift_ssl_config = RedshiftSSLConfig.parse(self.credentials.sslmode)
         kwargs.update(redshift_ssl_config.to_dict())


Test patch:
diff --git a/tests/unit/test_redshift_adapter.py b/tests/unit/test_redshift_adapter.py
index d2f7e6cf..46f80b5e 100644
--- a/tests/unit/test_redshift_adapter.py
+++ b/tests/unit/test_redshift_adapter.py
@@ -64,24 +64,7 @@ class TestRedshiftAdapter(unittest.TestCase):
         return self._adapter
 
     @mock.patch("redshift_connector.connect", Mock())
-    def test_implicit_database_conn(self):
-        connection = self.adapter.acquire_connection("dummy")
-        connection.handle
-        redshift_connector.connect.assert_called_once_with(
-            host="thishostshouldnotexist.test.us-east-1",
-            database="redshift",
-            user="root",
-            password="password",
-            port=5439,
-            auto_create=False,
-            db_groups=[],
-            timeout=None,
-            region="us-east-1",
-            **DEFAULT_SSL_CONFIG,
-        )
-
-    @mock.patch("redshift_connector.connect", Mock())
-    def test_explicit_database_conn(self):
+    def test_explicit_region_with_database_conn(self):
         self.config.method = "database"
 
         connection = self.adapter.acquire_connection("dummy")
@@ -94,7 +77,7 @@ class TestRedshiftAdapter(unittest.TestCase):
             port=5439,
             auto_create=False,
             db_groups=[],
-            region="us-east-1",
+            region=None,
             timeout=None,
             **DEFAULT_SSL_CONFIG,
         )
@@ -116,7 +99,7 @@ class TestRedshiftAdapter(unittest.TestCase):
             password="",
             user="",
             cluster_identifier="my_redshift",
-            region="us-east-1",
+            region=None,
             timeout=None,
             auto_create=False,
             db_groups=[],
@@ -138,7 +121,7 @@ class TestRedshiftAdapter(unittest.TestCase):
             port=5439,
             auto_create=False,
             db_groups=[],
-            region="us-east-1",
+            region=None,
             timeout=30,
             **DEFAULT_SSL_CONFIG,
         )
@@ -160,7 +143,7 @@ class TestRedshiftAdapter(unittest.TestCase):
             host="thishostshouldnotexist.test.us-east-1",
             database="redshift",
             cluster_identifier="my_redshift",
-            region="us-east-1",
+            region=None,
             auto_create=False,
             db_groups=[],
             db_user="root",
@@ -187,7 +170,7 @@ class TestRedshiftAdapter(unittest.TestCase):
             host="doesnotexist.1233.us-east-2.redshift-serverless.amazonaws.com",
             database="redshift",
             cluster_identifier=None,
-            region="us-east-2",
+            region=None,
             auto_create=False,
             db_groups=[],
             db_user="root",
@@ -228,66 +211,6 @@ class TestRedshiftAdapter(unittest.TestCase):
             **DEFAULT_SSL_CONFIG,
         )
 
-    @mock.patch("redshift_connector.connect", Mock())
-    @mock.patch("boto3.Session", Mock())
-    def test_explicit_region_failure(self):
-        # Failure test with no region
-        self.config.credentials = self.config.credentials.replace(
-            method="iam",
-            iam_profile="test",
-            host="doesnotexist.1233_no_region",
-            region=None,
-        )
-
-        with self.assertRaises(dbt.exceptions.FailedToConnectError):
-            connection = self.adapter.acquire_connection("dummy")
-            connection.handle
-            redshift_connector.connect.assert_called_once_with(
-                iam=True,
-                host="doesnotexist.1233_no_region",
-                database="redshift",
-                cluster_identifier=None,
-                auto_create=False,
-                db_groups=[],
-                db_user="root",
-                password="",
-                user="",
-                profile="test",
-                timeout=None,
-                port=5439,
-                **DEFAULT_SSL_CONFIG,
-            )
-
-    @mock.patch("redshift_connector.connect", Mock())
-    @mock.patch("boto3.Session", Mock())
-    def test_explicit_invalid_region(self):
-        # Invalid region test
-        self.config.credentials = self.config.credentials.replace(
-            method="iam",
-            iam_profile="test",
-            host="doesnotexist.1233_no_region.us-not-a-region-1",
-            region=None,
-        )
-
-        with self.assertRaises(dbt.exceptions.FailedToConnectError):
-            connection = self.adapter.acquire_connection("dummy")
-            connection.handle
-            redshift_connector.connect.assert_called_once_with(
-                iam=True,
-                host="doesnotexist.1233_no_region",
-                database="redshift",
-                cluster_identifier=None,
-                auto_create=False,
-                db_groups=[],
-                db_user="root",
-                password="",
-                user="",
-                profile="test",
-                timeout=None,
-                port=5439,
-                **DEFAULT_SSL_CONFIG,
-            )
-
     @mock.patch("redshift_connector.connect", Mock())
     def test_sslmode_disable(self):
         self.config.credentials.sslmode = "disable"
@@ -301,7 +224,7 @@ class TestRedshiftAdapter(unittest.TestCase):
             port=5439,
             auto_create=False,
             db_groups=[],
-            region="us-east-1",
+            region=None,
             timeout=None,
             ssl=False,
             sslmode=None,
@@ -320,7 +243,7 @@ class TestRedshiftAdapter(unittest.TestCase):
             port=5439,
             auto_create=False,
             db_groups=[],
-            region="us-east-1",
+            region=None,
             timeout=None,
             ssl=True,
             sslmode="verify-ca",
@@ -339,7 +262,7 @@ class TestRedshiftAdapter(unittest.TestCase):
             port=5439,
             auto_create=False,
             db_groups=[],
-            region="us-east-1",
+            region=None,
             timeout=None,
             ssl=True,
             sslmode="verify-full",
@@ -358,7 +281,7 @@ class TestRedshiftAdapter(unittest.TestCase):
             port=5439,
             auto_create=False,
             db_groups=[],
-            region="us-east-1",
+            region=None,
             timeout=None,
             ssl=True,
             sslmode="verify-ca",
@@ -377,7 +300,7 @@ class TestRedshiftAdapter(unittest.TestCase):
             port=5439,
             auto_create=False,
             db_groups=[],
-            region="us-east-1",
+            region=None,
             timeout=None,
             ssl=True,
             sslmode="verify-ca",
@@ -399,7 +322,7 @@ class TestRedshiftAdapter(unittest.TestCase):
                 host="doesnotexist.1233.us-east-2.redshift-srvrlss.amazonaws.com",
                 database="redshift",
                 cluster_identifier=None,
-                region="us-east-2",
+                region=None,
                 auto_create=False,
                 db_groups=[],
                 db_user="root",